sata_mv.c revision 8c0aeb4a483334613336ef895f34cecc0ecbbfa6
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); 45220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 45320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 4542a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 4552a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port); 45647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); 45747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, 45847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik void __iomem *mmio); 459c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 460c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc); 461522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); 462522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio); 46347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 4642a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 4652a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port); 46647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); 46747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, 46847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik void __iomem *mmio); 469c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 470c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc); 471522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); 472522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio); 473c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, 474c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int port_no); 475721091685f853ba4e6c49f26f989db0b1a811250Mark Lordstatic void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv, 476721091685f853ba4e6c49f26f989db0b1a811250Mark Lord void __iomem *port_mmio, int want_ncq); 477721091685f853ba4e6c49f26f989db0b1a811250Mark Lordstatic int __mv_stop_dma(struct ata_port *ap); 47847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 479c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv5_sht = { 480c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .module = THIS_MODULE, 481c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .name = DRV_NAME, 482c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .ioctl = ata_scsi_ioctl, 483c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .queuecommand = ata_scsi_queuecmd, 484c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .can_queue = ATA_DEF_QUEUE, 485c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .this_id = ATA_SHT_THIS_ID, 486baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik .sg_tablesize = MV_MAX_SG_CT / 2, 487c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .cmd_per_lun = ATA_SHT_CMD_PER_LUN, 488c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .emulated = ATA_SHT_EMULATED, 489c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .use_clustering = 1, 490c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .proc_name = DRV_NAME, 491c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .dma_boundary = MV_DMA_BOUNDARY, 4923be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik .slave_configure = ata_scsi_slave_config, 493c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .slave_destroy = ata_scsi_slave_destroy, 494c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .bios_param = ata_std_bios_param, 495c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik}; 496c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 497c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic struct scsi_host_template mv6_sht = { 49820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .module = THIS_MODULE, 49920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .name = DRV_NAME, 50020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .ioctl = ata_scsi_ioctl, 50120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .queuecommand = ata_scsi_queuecmd, 502c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .can_queue = ATA_DEF_QUEUE, 50320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .this_id = ATA_SHT_THIS_ID, 504baf14aa14efcfdb5a74d5cf804691086c6bec743Jeff Garzik .sg_tablesize = MV_MAX_SG_CT / 2, 50520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, 50620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .emulated = ATA_SHT_EMULATED, 507d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik .use_clustering = 1, 50820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .proc_name = DRV_NAME, 50920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .dma_boundary = MV_DMA_BOUNDARY, 5103be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik .slave_configure = ata_scsi_slave_config, 511ccf68c3405fca11386004674377d951b9b18e756Tejun Heo .slave_destroy = ata_scsi_slave_destroy, 51220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .bios_param = ata_std_bios_param, 51320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 51420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 515c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv5_ops = { 516c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .tf_load = ata_tf_load, 517c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .tf_read = ata_tf_read, 518c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .check_status = ata_check_status, 519c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .exec_command = ata_exec_command, 520c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .dev_select = ata_std_dev_select, 521c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 522cffacd85bcf6fc652292001873119333555fe260Jeff Garzik .cable_detect = ata_cable_sata, 523c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 524c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .qc_prep = mv_qc_prep, 525c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .qc_issue = mv_qc_issue, 5260d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo .data_xfer = ata_data_xfer, 527c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 528c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .irq_clear = mv_irq_clear, 529246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi .irq_on = ata_irq_on, 530c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 531bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .error_handler = mv_error_handler, 532bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .post_internal_cmd = mv_post_int_cmd, 533bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .freeze = mv_eh_freeze, 534bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .thaw = mv_eh_thaw, 535bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 536c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .scr_read = mv5_scr_read, 537c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .scr_write = mv5_scr_write, 538c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 539c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_start = mv_port_start, 540c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_stop = mv_port_stop, 541c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik}; 542c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 543c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic const struct ata_port_operations mv6_ops = { 54420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .tf_load = ata_tf_load, 54520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .tf_read = ata_tf_read, 54620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .check_status = ata_check_status, 54720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .exec_command = ata_exec_command, 54820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .dev_select = ata_std_dev_select, 54920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 550cffacd85bcf6fc652292001873119333555fe260Jeff Garzik .cable_detect = ata_cable_sata, 55120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 55231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .qc_prep = mv_qc_prep, 55331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .qc_issue = mv_qc_issue, 5540d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo .data_xfer = ata_data_xfer, 55520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 55620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .irq_clear = mv_irq_clear, 557246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi .irq_on = ata_irq_on, 55820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 559bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .error_handler = mv_error_handler, 560bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .post_internal_cmd = mv_post_int_cmd, 561bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .freeze = mv_eh_freeze, 562bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .thaw = mv_eh_thaw, 563bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 56420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .scr_read = mv_scr_read, 56520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .scr_write = mv_scr_write, 56620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 56731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .port_start = mv_port_start, 56831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .port_stop = mv_port_stop, 56920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 57020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 571e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic const struct ata_port_operations mv_iie_ops = { 572e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .tf_load = ata_tf_load, 573e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .tf_read = ata_tf_read, 574e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .check_status = ata_check_status, 575e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .exec_command = ata_exec_command, 576e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .dev_select = ata_std_dev_select, 577e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 578cffacd85bcf6fc652292001873119333555fe260Jeff Garzik .cable_detect = ata_cable_sata, 579e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 580e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .qc_prep = mv_qc_prep_iie, 581e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .qc_issue = mv_qc_issue, 5820d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo .data_xfer = ata_data_xfer, 583e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 584e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .irq_clear = mv_irq_clear, 585246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi .irq_on = ata_irq_on, 586e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 587bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .error_handler = mv_error_handler, 588bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .post_internal_cmd = mv_post_int_cmd, 589bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .freeze = mv_eh_freeze, 590bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik .thaw = mv_eh_thaw, 591bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 592e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .scr_read = mv_scr_read, 593e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .scr_write = mv_scr_write, 594e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 595e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .port_start = mv_port_start, 596e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .port_stop = mv_port_stop, 597e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik}; 598e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 59998ac62defe529d04a192688f40d801a2d8fbcf98Arjan van de Venstatic const struct ata_port_info mv_port_info[] = { 60020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { /* chip_504x */ 601cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = MV_COMMON_FLAGS, 60231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 603bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 604c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv5_ops, 60520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, 60620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { /* chip_508x */ 607c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC, 60831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 609bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 610c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv5_ops, 61120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, 61247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik { /* chip_5080 */ 613c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC, 61447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 615bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 616c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv5_ops, 61747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik }, 61820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { /* chip_604x */ 619c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS, 62031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 621bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 622c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv6_ops, 62320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, 62420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { /* chip_608x */ 625c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS | 626c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik MV_FLAG_DUAL_HC, 62731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 628bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 629c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik .port_ops = &mv6_ops, 63020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, 631e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik { /* chip_6042 */ 632c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS, 633e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 634bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 635e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .port_ops = &mv_iie_ops, 636e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik }, 637e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik { /* chip_7042 */ 638c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS, 639e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 640bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA6, 641e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik .port_ops = &mv_iie_ops, 642e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik }, 64320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 64420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 6453b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzikstatic const struct pci_device_id mv_pci_tbl[] = { 6462d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x5040), chip_504x }, 6472d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x5041), chip_504x }, 6482d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x5080), chip_5080 }, 6492d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x5081), chip_508x }, 650cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox /* RocketRAID 1740/174x have different identifiers */ 651cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox { PCI_VDEVICE(TTI, 0x1740), chip_508x }, 652cfbf723eb7928879292ee71fa0d118fc4e37b8c9Alan Cox { PCI_VDEVICE(TTI, 0x1742), chip_508x }, 6532d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik 6542d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6040), chip_604x }, 6552d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6041), chip_604x }, 6562d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6042), chip_6042 }, 6572d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6080), chip_608x }, 6582d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(MARVELL, 0x6081), chip_608x }, 6592d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik 6602d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x }, 6612d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik 662d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger /* Adaptec 1430SA */ 663d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger { PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 }, 664d9f9c6bc91c14f53ffa782ffcd42259ecae1d38cFlorian Attenberger 66502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord /* Marvell 7042 support */ 6666a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom { PCI_VDEVICE(MARVELL, 0x7042), chip_7042 }, 6676a3d586d8e8a50e4cfd7f8c36d82a53c5614e05bMorrison, Tom 66802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord /* Highpoint RocketRAID PCIe series */ 66902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord { PCI_VDEVICE(TTI, 0x2300), chip_7042 }, 67002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord { PCI_VDEVICE(TTI, 0x2310), chip_7042 }, 67102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord 6722d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik { } /* terminate list */ 67320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 67420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 67520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic struct pci_driver mv_pci_driver = { 67620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .name = DRV_NAME, 67720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .id_table = mv_pci_tbl, 67820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .probe = mv_init_one, 67920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .remove = ata_pci_remove_one, 68020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 68120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 68247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv5xxx_ops = { 68347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .phy_errata = mv5_phy_errata, 68447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .enable_leds = mv5_enable_leds, 68547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .read_preamp = mv5_read_preamp, 68647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .reset_hc = mv5_reset_hc, 687522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik .reset_flash = mv5_reset_flash, 688522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik .reset_bus = mv5_reset_bus, 68947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}; 69047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 69147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic const struct mv_hw_ops mv6xxx_ops = { 69247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .phy_errata = mv6_phy_errata, 69347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .enable_leds = mv6_enable_leds, 69447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .read_preamp = mv6_read_preamp, 69547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik .reset_hc = mv6_reset_hc, 696522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik .reset_flash = mv6_reset_flash, 697522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik .reset_bus = mv_reset_pci_bus, 69847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik}; 69947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 70020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/* 701ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik * module options 702ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik */ 703ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikstatic int msi; /* Use PCI msi; either zero (off, default) or non-zero */ 704ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik 705ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik 706d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik/* move to PCI layer or libata core? */ 707d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzikstatic int pci_go_64(struct pci_dev *pdev) 708d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik{ 709d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik int rc; 710d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik 711d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { 712d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); 713d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) { 714d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 715d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) { 716d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik dev_printk(KERN_ERR, &pdev->dev, 717d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik "64-bit DMA enable failed\n"); 718d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 719d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 720d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 721d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } else { 722d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); 723d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) { 724d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik dev_printk(KERN_ERR, &pdev->dev, 725d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik "32-bit DMA enable failed\n"); 726d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 727d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 728d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 729d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) { 730d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik dev_printk(KERN_ERR, &pdev->dev, 731d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik "32-bit consistent DMA enable failed\n"); 732d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 733d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 734d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik } 735d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik 736d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 737d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik} 738d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik 739ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik/* 74020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Functions 74120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */ 74220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 74320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void writelfl(unsigned long data, void __iomem *addr) 74420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 74520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writel(data, addr); 74620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ (void) readl(addr); /* flush to avoid PCI posted write */ 74720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 74820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 74920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc) 75020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 75120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ)); 75220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 75320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 754c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hc_from_port(unsigned int port) 755c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 756c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return port >> MV_PORT_HC_SHIFT; 757c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 758c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 759c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline unsigned int mv_hardport_from_port(unsigned int port) 760c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 761c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return port & MV_PORT_MASK; 762c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 763c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 764c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic inline void __iomem *mv_hc_base_from_port(void __iomem *base, 765c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int port) 766c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 767c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return mv_hc_base(base, mv_hc_from_port(port)); 768c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 769c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 77020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_port_base(void __iomem *base, unsigned int port) 77120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 772c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return mv_hc_base_from_port(base, port) + 7738b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik MV_SATAHC_ARBTR_REG_SZ + 774c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik (mv_hardport_from_port(port) * MV_PORT_REG_SZ); 77520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 77620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 77720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic inline void __iomem *mv_ap_base(struct ata_port *ap) 77820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 7790d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no); 78020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 78120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 782cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic inline int mv_get_hc_count(unsigned long port_flags) 78331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 784cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1); 78531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 78631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 78731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_irq_clear(struct ata_port *ap) 78820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 78920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 79020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 791c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzikstatic void mv_set_edma_ptrs(void __iomem *port_mmio, 792c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik struct mv_host_priv *hpriv, 793c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik struct mv_port_priv *pp) 794c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik{ 795bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 index; 796bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 797c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik /* 798c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik * initialize request queue 799c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik */ 800bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT; 801bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 802c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik WARN_ON(pp->crqb_dma & 0x3ff); 803c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS); 804bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index, 805c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik port_mmio + EDMA_REQ_Q_IN_PTR_OFS); 806c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 807c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) 808bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl((pp->crqb_dma & 0xffffffff) | index, 809c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); 810c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik else 811bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); 812c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 813c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik /* 814c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik * initialize response queue 815c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik */ 816bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT; 817bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 818c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik WARN_ON(pp->crpb_dma & 0xff); 819c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS); 820c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 821c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0) 822bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl((pp->crpb_dma & 0xffffffff) | index, 823c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik port_mmio + EDMA_RSP_Q_IN_PTR_OFS); 824c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik else 825bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS); 826c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 827bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index, 828c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); 829c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik} 830c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 83105b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 83205b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_start_dma - Enable eDMA engine 83305b308e1df6d9d673daedb517969241f41278b52Brett Russ * @base: port base address 83405b308e1df6d9d673daedb517969241f41278b52Brett Russ * @pp: port private data 83505b308e1df6d9d673daedb517969241f41278b52Brett Russ * 836beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo * Verify the local cache of the eDMA state is accurate with a 837beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo * WARN_ON. 83805b308e1df6d9d673daedb517969241f41278b52Brett Russ * 83905b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 84005b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 84105b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 8420c58912e192fc3a4835d772aafa40b72552b819fMark Lordstatic void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio, 843721091685f853ba4e6c49f26f989db0b1a811250Mark Lord struct mv_port_priv *pp, u8 protocol) 84420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 845721091685f853ba4e6c49f26f989db0b1a811250Mark Lord int want_ncq = (protocol == ATA_PROT_NCQ); 846721091685f853ba4e6c49f26f989db0b1a811250Mark Lord 847721091685f853ba4e6c49f26f989db0b1a811250Mark Lord if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { 848721091685f853ba4e6c49f26f989db0b1a811250Mark Lord int using_ncq = ((pp->pp_flags & MV_PP_FLAG_NCQ_EN) != 0); 849721091685f853ba4e6c49f26f989db0b1a811250Mark Lord if (want_ncq != using_ncq) 850721091685f853ba4e6c49f26f989db0b1a811250Mark Lord __mv_stop_dma(ap); 851721091685f853ba4e6c49f26f989db0b1a811250Mark Lord } 852c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) { 8530c58912e192fc3a4835d772aafa40b72552b819fMark Lord struct mv_host_priv *hpriv = ap->host->private_data; 8540c58912e192fc3a4835d772aafa40b72552b819fMark Lord int hard_port = mv_hardport_from_port(ap->port_no); 8550c58912e192fc3a4835d772aafa40b72552b819fMark Lord void __iomem *hc_mmio = mv_hc_base_from_port( 8560c58912e192fc3a4835d772aafa40b72552b819fMark Lord ap->host->iomap[MV_PRIMARY_BAR], hard_port); 8570c58912e192fc3a4835d772aafa40b72552b819fMark Lord u32 hc_irq_cause, ipending; 8580c58912e192fc3a4835d772aafa40b72552b819fMark Lord 859bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* clear EDMA event indicators, if any */ 860f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 861bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 8620c58912e192fc3a4835d772aafa40b72552b819fMark Lord /* clear EDMA interrupt indicator, if any */ 8630c58912e192fc3a4835d772aafa40b72552b819fMark Lord hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS); 8640c58912e192fc3a4835d772aafa40b72552b819fMark Lord ipending = (DEV_IRQ << hard_port) | 8650c58912e192fc3a4835d772aafa40b72552b819fMark Lord (CRPB_DMA_DONE << hard_port); 8660c58912e192fc3a4835d772aafa40b72552b819fMark Lord if (hc_irq_cause & ipending) { 8670c58912e192fc3a4835d772aafa40b72552b819fMark Lord writelfl(hc_irq_cause & ~ipending, 8680c58912e192fc3a4835d772aafa40b72552b819fMark Lord hc_mmio + HC_IRQ_CAUSE_OFS); 8690c58912e192fc3a4835d772aafa40b72552b819fMark Lord } 8700c58912e192fc3a4835d772aafa40b72552b819fMark Lord 871721091685f853ba4e6c49f26f989db0b1a811250Mark Lord mv_edma_cfg(pp, hpriv, port_mmio, want_ncq); 8720c58912e192fc3a4835d772aafa40b72552b819fMark Lord 8730c58912e192fc3a4835d772aafa40b72552b819fMark Lord /* clear FIS IRQ Cause */ 8740c58912e192fc3a4835d772aafa40b72552b819fMark Lord writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS); 8750c58912e192fc3a4835d772aafa40b72552b819fMark Lord 876f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord mv_set_edma_ptrs(port_mmio, hpriv, pp); 877bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 878f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS); 879afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ pp->pp_flags |= MV_PP_FLAG_EDMA_EN; 880afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ } 881f630d562829fcd8160a118f98c1e5b9cdb4e703eMark Lord WARN_ON(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS))); 88220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 88320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 88405b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 8850ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik * __mv_stop_dma - Disable eDMA engine 88605b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 88705b308e1df6d9d673daedb517969241f41278b52Brett Russ * 888beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo * Verify the local cache of the eDMA state is accurate with a 889beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo * WARN_ON. 89005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 89105b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 89205b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 89305b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 8940ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzikstatic int __mv_stop_dma(struct ata_port *ap) 89520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 89631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_mmio = mv_ap_base(ap); 89731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp = ap->private_data; 89831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u32 reg; 899c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik int i, err = 0; 90031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 9014537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { 902afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ /* Disable EDMA if active. The disable bit auto clears. 90331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 90431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS); 90531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 906afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ } else { 907beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)); 9082dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik } 9098b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik 91031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* now properly wait for the eDMA to stop */ 91131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (i = 1000; i > 0; i--) { 91231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ reg = readl(port_mmio + EDMA_CMD_OFS); 9134537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik if (!(reg & EDMA_EN)) 91431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 9154537deb5e90b717a725b3d74b58b4bb1d28443d0Jeff Garzik 91631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ udelay(100); 91731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 91831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 919c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik if (reg & EDMA_EN) { 920f15a1dafed22d5037e0feea7528e1eeb28a1a7a3Tejun Heo ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n"); 921c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik err = -EIO; 92231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 923c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik 924c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik return err; 92520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 92620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 9270ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzikstatic int mv_stop_dma(struct ata_port *ap) 9280ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik{ 9290ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik unsigned long flags; 9300ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik int rc; 9310ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik 9320ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik spin_lock_irqsave(&ap->host->lock, flags); 9330ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik rc = __mv_stop_dma(ap); 9340ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik spin_unlock_irqrestore(&ap->host->lock, flags); 9350ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik 9360ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik return rc; 9370ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik} 9380ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik 9398a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#ifdef ATA_DEBUG 94031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_mem(void __iomem *start, unsigned bytes) 94120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 94231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ int b, w; 94331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (b = 0; b < bytes; ) { 94431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("%p: ", start + b); 94531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (w = 0; b < bytes && w < 4; w++) { 9462dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik printk("%08x ", readl(start + b)); 94731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ b += sizeof(u32); 94831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 94931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ printk("\n"); 95031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 95131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 9528a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik#endif 9538a70f8dc08dd40b7f8ac77280eaa99a8c6bc46f4Jeff Garzik 95431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes) 95531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 95631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG 95731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ int b, w; 95831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u32 dw; 95931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (b = 0; b < bytes; ) { 96031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("%02x: ", b); 96131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (w = 0; b < bytes && w < 4; w++) { 9622dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik (void) pci_read_config_dword(pdev, b, &dw); 9632dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik printk("%08x ", dw); 96431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ b += sizeof(u32); 96531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 96631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ printk("\n"); 96731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 96831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif 96931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 97031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_dump_all_regs(void __iomem *mmio_base, int port, 97131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct pci_dev *pdev) 97231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 97331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef ATA_DEBUG 9748b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik void __iomem *hc_base = mv_hc_base(mmio_base, 97531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port >> MV_PORT_HC_SHIFT); 97631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_base; 97731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ int start_port, num_ports, p, start_hc, num_hcs, hc; 97831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 97931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (0 > port) { 98031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ start_hc = start_port = 0; 98131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ num_ports = 8; /* shld be benign for 4 port devs */ 98231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ num_hcs = 2; 98331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } else { 98431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ start_hc = port >> MV_PORT_HC_SHIFT; 98531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ start_port = port; 98631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ num_ports = num_hcs = 1; 98731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 9888b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik DPRINTK("All registers for port(s) %u-%u:\n", start_port, 98931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ num_ports > 1 ? num_ports - 1 : start_port); 99031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 99131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (NULL != pdev) { 99231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("PCI config space regs:\n"); 99331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_pci_cfg(pdev, 0x68); 99431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 99531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("PCI regs:\n"); 99631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(mmio_base+0xc00, 0x3c); 99731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(mmio_base+0xd00, 0x34); 99831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(mmio_base+0xf00, 0x4); 99931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(mmio_base+0x1d00, 0x6c); 100031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (hc = start_hc; hc < start_hc + num_hcs; hc++) { 1001d220c37e0a3c9a47ae00e87e044d963b3ea040bcDan Aloni hc_base = mv_hc_base(mmio_base, hc); 100231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ DPRINTK("HC regs (HC %i):\n", hc); 100331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(hc_base, 0x1c); 100431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 100531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ for (p = start_port; p < start_port + num_ports; p++) { 100631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port_base = mv_port_base(mmio_base, p); 10072dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik DPRINTK("EDMA regs (port %i):\n", p); 100831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(port_base, 0x54); 10092dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik DPRINTK("SATA regs (port %i):\n", p); 101031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_mem(port_base+0x300, 0x60); 101131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 101231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif 101320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 101420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 101520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic unsigned int mv_scr_offset(unsigned int sc_reg_in) 101620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 101720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int ofs; 101820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 101920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ switch (sc_reg_in) { 102020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ case SCR_STATUS: 102120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ case SCR_CONTROL: 102220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ case SCR_ERROR: 102320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ofs = SATA_STATUS_OFS + (sc_reg_in * sizeof(u32)); 102420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ break; 102520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ case SCR_ACTIVE: 102620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ofs = SATA_ACTIVE_OFS; /* active is not with the others */ 102720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ break; 102820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ default: 102920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ofs = 0xffffffffU; 103020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ break; 103120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 103220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return ofs; 103320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 103420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1035da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val) 103620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 103720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int ofs = mv_scr_offset(sc_reg_in); 103820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1039da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo if (ofs != 0xffffffffU) { 1040da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo *val = readl(mv_ap_base(ap) + ofs); 1041da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return 0; 1042da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } else 1043da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return -EINVAL; 104420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 104520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1046da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) 104720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 104820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int ofs = mv_scr_offset(sc_reg_in); 104920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1050da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo if (ofs != 0xffffffffU) { 105120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writelfl(val, mv_ap_base(ap) + ofs); 1052da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return 0; 1053da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } else 1054da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return -EINVAL; 105520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 105620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1057721091685f853ba4e6c49f26f989db0b1a811250Mark Lordstatic void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv, 1058721091685f853ba4e6c49f26f989db0b1a811250Mark Lord void __iomem *port_mmio, int want_ncq) 1059e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{ 10600c58912e192fc3a4835d772aafa40b72552b819fMark Lord u32 cfg; 1061e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1062e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik /* set up non-NCQ EDMA configuration */ 10630c58912e192fc3a4835d772aafa40b72552b819fMark Lord cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */ 1064e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 10650c58912e192fc3a4835d772aafa40b72552b819fMark Lord if (IS_GEN_I(hpriv)) 1066e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik cfg |= (1 << 8); /* enab config burst size mask */ 1067e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 10680c58912e192fc3a4835d772aafa40b72552b819fMark Lord else if (IS_GEN_II(hpriv)) 1069e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN; 1070e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1071e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik else if (IS_GEN_IIE(hpriv)) { 1072e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */ 1073e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg |= (1 << 22); /* enab 4-entry host queue cache */ 1074e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik cfg |= (1 << 18); /* enab early completion */ 1075e728eabea110da90e69c05855e3a11174edb77efJeff Garzik cfg |= (1 << 17); /* enab cut-through (dis stor&forwrd) */ 1076e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik } 1077e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1078721091685f853ba4e6c49f26f989db0b1a811250Mark Lord if (want_ncq) { 1079721091685f853ba4e6c49f26f989db0b1a811250Mark Lord cfg |= EDMA_CFG_NCQ; 1080721091685f853ba4e6c49f26f989db0b1a811250Mark Lord pp->pp_flags |= MV_PP_FLAG_NCQ_EN; 1081721091685f853ba4e6c49f26f989db0b1a811250Mark Lord } else 1082721091685f853ba4e6c49f26f989db0b1a811250Mark Lord pp->pp_flags &= ~MV_PP_FLAG_NCQ_EN; 1083721091685f853ba4e6c49f26f989db0b1a811250Mark Lord 1084e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik writelfl(cfg, port_mmio + EDMA_CFG_OFS); 1085e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik} 1086e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 108705b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 108805b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_port_start - Port specific init/start routine. 108905b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 109005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 109105b308e1df6d9d673daedb517969241f41278b52Brett Russ * Allocate and point to DMA memory, init port private memory, 109205b308e1df6d9d673daedb517969241f41278b52Brett Russ * zero indices. 109305b308e1df6d9d673daedb517969241f41278b52Brett Russ * 109405b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 109505b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 109605b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 109731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int mv_port_start(struct ata_port *ap) 109831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 1099cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct device *dev = ap->host->dev; 1100cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 110131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp; 110231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_mmio = mv_ap_base(ap); 110331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void *mem; 110431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ dma_addr_t mem_dma; 11050ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik unsigned long flags; 110624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo int rc; 110731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 110824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); 11096037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik if (!pp) 111024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return -ENOMEM; 111131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 111224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma, 111324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo GFP_KERNEL); 11146037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik if (!mem) 111524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return -ENOMEM; 111631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ memset(mem, 0, MV_PORT_PRIV_DMA_SZ); 111731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 11186037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik rc = ata_pad_alloc(ap, dev); 11196037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik if (rc) 112024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 11216037d6bbdff65eb5a84fe35e140f4da4f7cc103aJeff Garzik 11228b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik /* First item in chunk of DMA memory: 112331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * 32-slot command request table (CRQB), 32 bytes each in size 112431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 112531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->crqb = mem; 112631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->crqb_dma = mem_dma; 112731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mem += MV_CRQB_Q_SZ; 112831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mem_dma += MV_CRQB_Q_SZ; 112931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 11308b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik /* Second item: 113131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * 32-slot command response table (CRPB), 8 bytes each in size 113231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 113331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->crpb = mem; 113431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->crpb_dma = mem_dma; 113531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mem += MV_CRPB_Q_SZ; 113631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mem_dma += MV_CRPB_Q_SZ; 113731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 113831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Third item: 113931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * Table of scatter-gather descriptors (ePRD), 16 bytes each 114031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 114131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->sg_tbl = mem; 114231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pp->sg_tbl_dma = mem_dma; 114331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 11440ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik spin_lock_irqsave(&ap->host->lock, flags); 11450ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik 1146721091685f853ba4e6c49f26f989db0b1a811250Mark Lord mv_edma_cfg(pp, hpriv, port_mmio, 0); 1147e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1148c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik mv_set_edma_ptrs(port_mmio, hpriv, pp); 114931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 11500ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik spin_unlock_irqrestore(&ap->host->lock, flags); 11510ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik 115231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Don't turn on EDMA here...do it before DMA commands only. Else 115331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * we'll be unable to send non-data, PIO, etc due to restricted access 115431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * to shadow regs. 115531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 115631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ ap->private_data = pp; 115731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return 0; 115831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 115931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 116005b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 116105b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_port_stop - Port specific cleanup/stop routine. 116205b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 116305b308e1df6d9d673daedb517969241f41278b52Brett Russ * 116405b308e1df6d9d673daedb517969241f41278b52Brett Russ * Stop DMA, cleanup port memory. 116505b308e1df6d9d673daedb517969241f41278b52Brett Russ * 116605b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 1167cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik * This routine uses the host lock to protect the DMA stop. 116805b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 116931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_stop(struct ata_port *ap) 117031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 117131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_stop_dma(ap); 117231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 117331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 117405b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 117505b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_fill_sg - Fill out the Marvell ePRD (scatter gather) entries 117605b308e1df6d9d673daedb517969241f41278b52Brett Russ * @qc: queued command whose SG list to source from 117705b308e1df6d9d673daedb517969241f41278b52Brett Russ * 117805b308e1df6d9d673daedb517969241f41278b52Brett Russ * Populate the SG list and mark the last entry. 117905b308e1df6d9d673daedb517969241f41278b52Brett Russ * 118005b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 118105b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 118205b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 11836c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzikstatic void mv_fill_sg(struct ata_queued_cmd *qc) 118431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 118531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp = qc->ap->private_data; 1186972c26bdd6b58e7534473c4f7928584578cf43f4Jeff Garzik struct scatterlist *sg; 11873be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik struct mv_sg *mv_sg, *last_sg = NULL; 1188ff2aeb1eb64c8a4770a6304f9addbae9f9828646Tejun Heo unsigned int si; 118931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1190d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik mv_sg = pp->sg_tbl; 1191ff2aeb1eb64c8a4770a6304f9addbae9f9828646Tejun Heo for_each_sg(qc->sg, sg, qc->n_elem, si) { 1192d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik dma_addr_t addr = sg_dma_address(sg); 1193d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik u32 sg_len = sg_dma_len(sg); 119422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 11954007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson while (sg_len) { 11964007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson u32 offset = addr & 0xffff; 11974007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson u32 len = sg_len; 119822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 11994007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson if ((offset + sg_len > 0x10000)) 12004007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson len = 0x10000 - offset; 12014007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson 12024007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson mv_sg->addr = cpu_to_le32(addr & 0xffffffff); 12034007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); 12046c08772e49622e90d39903e7ff0be1a0f463ac86Jeff Garzik mv_sg->flags_size = cpu_to_le32(len & 0xffff); 12054007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson 12064007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson sg_len -= len; 12074007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson addr += len; 12084007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson 12093be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik last_sg = mv_sg; 12104007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson mv_sg++; 12114007b493ee6e4a52c2b618ab8361847fba5bf116Olof Johansson } 121231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 12133be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik 12143be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik if (likely(last_sg)) 12153be6cbd73f74b4a3da82cc7d6e1688a4ae595fc7Jeff Garzik last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); 121631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 121731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 12185796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) 121931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 1220559eedad7f7764dacca33980127b4615011230e4Mark Lord u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS | 122131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ (last ? CRQB_CMD_LAST : 0); 1222559eedad7f7764dacca33980127b4615011230e4Mark Lord *cmdw = cpu_to_le16(tmp); 122331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 122431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 122505b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 122605b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_qc_prep - Host specific command preparation. 122705b308e1df6d9d673daedb517969241f41278b52Brett Russ * @qc: queued command to prepare 122805b308e1df6d9d673daedb517969241f41278b52Brett Russ * 122905b308e1df6d9d673daedb517969241f41278b52Brett Russ * This routine simply redirects to the general purpose routine 123005b308e1df6d9d673daedb517969241f41278b52Brett Russ * if command is not DMA. Else, it handles prep of the CRQB 123105b308e1df6d9d673daedb517969241f41278b52Brett Russ * (command request block), does some sanity checking, and calls 123205b308e1df6d9d673daedb517969241f41278b52Brett Russ * the SG load routine. 123305b308e1df6d9d673daedb517969241f41278b52Brett Russ * 123405b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 123505b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 123605b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 123731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_qc_prep(struct ata_queued_cmd *qc) 123831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 123931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct ata_port *ap = qc->ap; 124031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct mv_port_priv *pp = ap->private_data; 1241e14698745dd0de1ddbf5cd0cca4313a90f8c1cc1Mark Lord __le16 *cw; 124231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct ata_taskfile *tf; 124331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u16 flags = 0; 1244a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord unsigned in_index; 124531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 12462dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik if (qc->tf.protocol != ATA_PROT_DMA) 124731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return; 124820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 124931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Fill in command request block 125031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 1251e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (!(qc->tf.flags & ATA_TFLAG_WRITE)) 125231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ flags |= CRQB_FLAG_READ; 1253beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo WARN_ON(MV_MAX_Q_DEPTH <= qc->tag); 125431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ flags |= qc->tag << CRQB_TAG_SHIFT; 125531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1256bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* get current queue index from software */ 1257bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK; 1258a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord 1259a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord pp->crqb[in_index].sg_addr = 126031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); 1261a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord pp->crqb[in_index].sg_addr_hi = 126231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); 1263a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags); 126431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1265a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord cw = &pp->crqb[in_index].ata_cmd[0]; 126631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ tf = &qc->tf; 126731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 126831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Sadly, the CRQB cannot accomodate all registers--there are 126931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * only 11 bytes...so we must pick and choose required 127031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * registers based on the command. So, we drop feature and 127131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * hob_feature for [RW] DMA commands, but they are needed for 127231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * NCQ. NCQ will drop hob_nsect. 127320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */ 127431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ switch (tf->command) { 127531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_READ: 127631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_READ_EXT: 127731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_WRITE: 127831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_WRITE_EXT: 1279c15d85c8f3f73b5f20aae7928e25b6996f16b328Jens Axboe case ATA_CMD_WRITE_FUA_EXT: 128031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0); 128131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 128231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#ifdef LIBATA_NCQ /* FIXME: remove this line when NCQ added */ 128331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_FPDMA_READ: 128431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ case ATA_CMD_FPDMA_WRITE: 12858b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0); 128631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0); 128731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 128831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ#endif /* FIXME: remove this line when NCQ added */ 128931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ default: 129031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* The only other commands EDMA supports in non-queued and 129131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none 129231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * of which are defined/used by Linux. If we get here, this 129331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * driver needs work. 129431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * 129531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * FIXME: modify libata to give qc_prep a return value and 129631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * return error here. 129731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 129831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ BUG_ON(tf->command); 129931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 130031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 130131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0); 130231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0); 130331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0); 130431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0); 130531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0); 130631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0); 130731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0); 130831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0); 130931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1); /* last */ 131031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1311e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 1312e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik return; 1313e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik mv_fill_sg(qc); 1314e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik} 1315e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1316e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik/** 1317e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * mv_qc_prep_iie - Host specific command preparation. 1318e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * @qc: queued command to prepare 1319e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * 1320e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * This routine simply redirects to the general purpose routine 1321e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * if command is not DMA. Else, it handles prep of the CRQB 1322e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * (command request block), does some sanity checking, and calls 1323e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * the SG load routine. 1324e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * 1325e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * LOCKING: 1326e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik * Inherited from caller. 1327e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */ 1328e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzikstatic void mv_qc_prep_iie(struct ata_queued_cmd *qc) 1329e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik{ 1330e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik struct ata_port *ap = qc->ap; 1331e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik struct mv_port_priv *pp = ap->private_data; 1332e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik struct mv_crqb_iie *crqb; 1333e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik struct ata_taskfile *tf; 1334a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord unsigned in_index; 1335e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik u32 flags = 0; 1336e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 13372dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik if (qc->tf.protocol != ATA_PROT_DMA) 1338e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik return; 1339e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1340e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik /* Fill in Gen IIE command request block 1341e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik */ 1342e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (!(qc->tf.flags & ATA_TFLAG_WRITE)) 1343e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik flags |= CRQB_FLAG_READ; 1344e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1345beec7dbc6ff003bbc94de62b3323519c878fb2acTejun Heo WARN_ON(MV_MAX_Q_DEPTH <= qc->tag); 1346e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik flags |= qc->tag << CRQB_TAG_SHIFT; 13478c0aeb4a483334613336ef895f34cecc0ecbbfa6Mark Lord flags |= qc->tag << CRQB_HOSTQ_SHIFT; 1348e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1349bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* get current queue index from software */ 1350bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK; 1351a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord 1352a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord crqb = (struct mv_crqb_iie *) &pp->crqb[in_index]; 1353e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); 1354e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); 1355e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->flags = cpu_to_le32(flags); 1356e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1357e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik tf = &qc->tf; 1358e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->ata_cmd[0] = cpu_to_le32( 1359e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->command << 16) | 1360e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->feature << 24) 1361e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik ); 1362e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->ata_cmd[1] = cpu_to_le32( 1363e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->lbal << 0) | 1364e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->lbam << 8) | 1365e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->lbah << 16) | 1366e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->device << 24) 1367e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik ); 1368e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->ata_cmd[2] = cpu_to_le32( 1369e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_lbal << 0) | 1370e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_lbam << 8) | 1371e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_lbah << 16) | 1372e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_feature << 24) 1373e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik ); 1374e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik crqb->ata_cmd[3] = cpu_to_le32( 1375e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->nsect << 0) | 1376e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik (tf->hob_nsect << 8) 1377e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik ); 1378e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 1379e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 138031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return; 138131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_fill_sg(qc); 138231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 138331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 138405b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 138505b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_qc_issue - Initiate a command to the host 138605b308e1df6d9d673daedb517969241f41278b52Brett Russ * @qc: queued command to start 138705b308e1df6d9d673daedb517969241f41278b52Brett Russ * 138805b308e1df6d9d673daedb517969241f41278b52Brett Russ * This routine simply redirects to the general purpose routine 138905b308e1df6d9d673daedb517969241f41278b52Brett Russ * if command is not DMA. Else, it sanity checks our local 139005b308e1df6d9d673daedb517969241f41278b52Brett Russ * caches of the request producer/consumer indices then enables 139105b308e1df6d9d673daedb517969241f41278b52Brett Russ * DMA and bumps the request producer index. 139205b308e1df6d9d673daedb517969241f41278b52Brett Russ * 139305b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 139405b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 139505b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 13969a3d9eb0177eb10500d49cd283b35576082a522dTejun Heostatic unsigned int mv_qc_issue(struct ata_queued_cmd *qc) 139731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 1398c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik struct ata_port *ap = qc->ap; 1399c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik void __iomem *port_mmio = mv_ap_base(ap); 1400c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik struct mv_port_priv *pp = ap->private_data; 1401bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 in_index; 140231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1403c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik if (qc->tf.protocol != ATA_PROT_DMA) { 140431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* We're about to send a non-EDMA capable command to the 140531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * port. Turn off EDMA so there won't be problems accessing 140631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * shadow block, etc registers. 140731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 14080ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik __mv_stop_dma(ap); 140931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return ata_qc_issue_prot(qc); 141031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 141131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1412721091685f853ba4e6c49f26f989db0b1a811250Mark Lord mv_start_dma(ap, port_mmio, pp, qc->tf.protocol); 1413bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1414bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK; 141531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 141631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* until we do queuing, the queue should be empty at this point */ 1417a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) 1418a6432436c5e14b416f27c8f87c5bf0bc36771f49Mark Lord >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); 141931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1420bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik pp->req_idx++; 142131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 1422bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT; 142331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 142431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* and write the request in pointer to kick the EDMA to life */ 1425bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index, 1426bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik port_mmio + EDMA_REQ_Q_IN_PTR_OFS); 142731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 142831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return 0; 142931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 143031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 143105b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 143205b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_err_intr - Handle error interrupts on the port 143305b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 14349b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord * @reset_allowed: bool: 0 == don't trigger from reset here 143505b308e1df6d9d673daedb517969241f41278b52Brett Russ * 143605b308e1df6d9d673daedb517969241f41278b52Brett Russ * In most cases, just clear the interrupt and move on. However, 143705b308e1df6d9d673daedb517969241f41278b52Brett Russ * some cases require an eDMA reset, which is done right before 143805b308e1df6d9d673daedb517969241f41278b52Brett Russ * the COMRESET in mv_phy_reset(). The SERR case requires a 143905b308e1df6d9d673daedb517969241f41278b52Brett Russ * clear of pending errors in the SATA SERROR register. Finally, 144005b308e1df6d9d673daedb517969241f41278b52Brett Russ * if the port disabled DMA, update our cached copy to match. 144105b308e1df6d9d673daedb517969241f41278b52Brett Russ * 144205b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 144305b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 144405b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 1445bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc) 144631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 144731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *port_mmio = mv_ap_base(ap); 1448bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 edma_err_cause, eh_freeze_mask, serr = 0; 1449bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_port_priv *pp = ap->private_data; 1450bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 1451bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN); 1452bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int action = 0, err_mask = 0; 14539af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo struct ata_eh_info *ehi = &ap->link.eh_info; 145420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1455bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_ehi_clear_desc(ehi); 145620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1457bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (!edma_enabled) { 1458bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* just a guess: do we need to do this? should we 1459bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * expand this, and do it in all cases? 1460bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik */ 1461936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_read(&ap->link, SCR_ERROR, &serr); 1462936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_write_flush(&ap->link, SCR_ERROR, serr); 146320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 1464bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1465bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 1466bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1467bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause); 1468bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1469bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* 1470bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * all generations share these EDMA error cause bits 1471bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik */ 1472bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1473bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & EDMA_ERR_DEV) 1474bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik err_mask |= AC_ERR_DEV; 1475bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR | 14766c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik EDMA_ERR_CRQB_PAR | EDMA_ERR_CRPB_PAR | 1477bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik EDMA_ERR_INTRL_PAR)) { 1478bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik err_mask |= AC_ERR_ATA_BUS; 1479bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik action |= ATA_EH_HARDRESET; 1480b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo ata_ehi_push_desc(ehi, "parity error"); 1481bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1482bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) { 1483bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_ehi_hotplugged(ehi); 1484bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ? 1485b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo "dev disconnect" : "dev connect"); 14863606a380692cf958355a40fc1aa336800c17baf1Mark Lord action |= ATA_EH_HARDRESET; 1487bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1488bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1489ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik if (IS_GEN_I(hpriv)) { 1490bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik eh_freeze_mask = EDMA_EH_FREEZE_5; 1491bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1492bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & EDMA_ERR_SELF_DIS_5) { 1493bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_port_priv *pp = ap->private_data; 1494bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 1495b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo ata_ehi_push_desc(ehi, "EDMA self-disable"); 1496bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1497bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } else { 1498bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik eh_freeze_mask = EDMA_EH_FREEZE; 1499bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1500bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & EDMA_ERR_SELF_DIS) { 1501bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_port_priv *pp = ap->private_data; 1502bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 1503b64bbc39f2122a2276578e40144af69ef01decd4Tejun Heo ata_ehi_push_desc(ehi, "EDMA self-disable"); 1504bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1505bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1506bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & EDMA_ERR_SERR) { 1507936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_read(&ap->link, SCR_ERROR, &serr); 1508936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_write_flush(&ap->link, SCR_ERROR, serr); 1509bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik err_mask = AC_ERR_ATA_BUS; 1510bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik action |= ATA_EH_HARDRESET; 1511bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1512afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ } 151320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 151420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* Clear EDMA now that SERR cleanup done */ 15153606a380692cf958355a40fc1aa336800c17baf1Mark Lord writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 151620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1517bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (!err_mask) { 1518bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik err_mask = AC_ERR_OTHER; 1519bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik action |= ATA_EH_HARDRESET; 1520bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1521bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1522bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehi->serror |= serr; 1523bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehi->action |= action; 1524bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1525bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (qc) 1526bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik qc->err_mask |= err_mask; 1527bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik else 1528bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehi->err_mask |= err_mask; 1529bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1530bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (edma_err_cause & eh_freeze_mask) 1531bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_port_freeze(ap); 1532bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik else 1533bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_port_abort(ap); 1534bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 1535bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1536bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_pio(struct ata_port *ap) 1537bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 1538bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct ata_queued_cmd *qc; 1539bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u8 ata_status; 1540bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1541bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* ignore spurious intr if drive still BUSY */ 1542bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_status = readb(ap->ioaddr.status_addr); 1543bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (unlikely(ata_status & ATA_BUSY)) 1544bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return; 1545bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1546bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* get active ATA command */ 15479af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo qc = ata_qc_from_tag(ap, ap->link.active_tag); 1548bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (unlikely(!qc)) /* no active tag */ 1549bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return; 1550bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (qc->tf.flags & ATA_TFLAG_POLLING) /* polling; we don't own qc */ 1551bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return; 1552bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1553bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* and finally, complete the ATA command */ 1554bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik qc->err_mask |= ac_err_mask(ata_status); 1555bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_qc_complete(qc); 1556bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 1557bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1558bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_intr_edma(struct ata_port *ap) 1559bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 1560bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik void __iomem *port_mmio = mv_ap_base(ap); 1561bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 1562bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_port_priv *pp = ap->private_data; 1563bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct ata_queued_cmd *qc; 1564bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 out_index, in_index; 1565bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik bool work_done = false; 1566bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1567bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* get h/w response queue pointer */ 1568bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik in_index = (readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) 1569bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; 1570bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1571bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik while (1) { 1572bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u16 status; 15736c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik unsigned int tag; 1574bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1575bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* get s/w response queue last-read pointer, and compare */ 1576bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik out_index = pp->resp_idx & MV_MAX_Q_DEPTH_MASK; 1577bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (in_index == out_index) 1578bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik break; 1579bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1580bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* 50xx: get active ATA command */ 15810ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik if (IS_GEN_I(hpriv)) 15829af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo tag = ap->link.active_tag; 1583bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 15846c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik /* Gen II/IIE: get active ATA command via tag, to enable 15856c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik * support for queueing. this works transparently for 15866c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik * queued and non-queued modes. 1587bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik */ 15888c0aeb4a483334613336ef895f34cecc0ecbbfa6Mark Lord else 15898c0aeb4a483334613336ef895f34cecc0ecbbfa6Mark Lord tag = le16_to_cpu(pp->crpb[out_index].id) & 0x1f; 1590bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 15916c1153e00af8de755ec278d873a97c9ce2a72d10Jeff Garzik qc = ata_qc_from_tag(ap, tag); 1592bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1593bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* lower 8 bits of status are EDMA_ERR_IRQ_CAUSE_OFS 1594bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * bits (WARNING: might not necessarily be associated 1595bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * with this command), which -should- be clear 1596bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * if all is well 1597bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik */ 1598bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik status = le16_to_cpu(pp->crpb[out_index].flags); 1599bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (unlikely(status & 0xff)) { 1600bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_err_intr(ap, qc); 1601bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return; 1602bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1603bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1604bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* and finally, complete the ATA command */ 1605bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (qc) { 1606bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik qc->err_mask |= 1607bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ac_err_mask(status >> CRPB_FLAG_STATUS_SHIFT); 1608bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_qc_complete(qc); 1609bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1610bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 16110ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik /* advance software response queue pointer, to 1612bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * indicate (after the loop completes) to hardware 1613bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * that we have consumed a response queue entry. 1614bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik */ 1615bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik work_done = true; 1616bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik pp->resp_idx++; 1617bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1618bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1619bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (work_done) 1620bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | 1621bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik (out_index << EDMA_RSP_Q_PTR_SHIFT), 1622bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); 162320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 162420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 162505b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 162605b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_host_intr - Handle all interrupts on the given host controller 1627cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik * @host: host specific structure 162805b308e1df6d9d673daedb517969241f41278b52Brett Russ * @relevant: port error bits relevant to this host controller 162905b308e1df6d9d673daedb517969241f41278b52Brett Russ * @hc: which host controller we're to look at 163005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 163105b308e1df6d9d673daedb517969241f41278b52Brett Russ * Read then write clear the HC interrupt status then walk each 163205b308e1df6d9d673daedb517969241f41278b52Brett Russ * port connected to the HC and see if it needs servicing. Port 163305b308e1df6d9d673daedb517969241f41278b52Brett Russ * success ints are reported in the HC interrupt status reg, the 163405b308e1df6d9d673daedb517969241f41278b52Brett Russ * port error ints are reported in the higher level main 163505b308e1df6d9d673daedb517969241f41278b52Brett Russ * interrupt status register and thus are passed in via the 163605b308e1df6d9d673daedb517969241f41278b52Brett Russ * 'relevant' argument. 163705b308e1df6d9d673daedb517969241f41278b52Brett Russ * 163805b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 163905b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 164005b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 1641cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzikstatic void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc) 164220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 16430d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; 164420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ void __iomem *hc_mmio = mv_hc_base(mmio, hc); 164520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ u32 hc_irq_cause; 1646c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik int port, port0; 164720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1648351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik if (hc == 0) 164920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ port0 = 0; 1650351772658a4d1acc0221a6e30676bb0594e74812Jeff Garzik else 165120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ port0 = MV_PORTS_PER_HC; 165220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 165320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* we'll need the HC success int register in most cases */ 165420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS); 1655bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (!hc_irq_cause) 1656bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return; 1657bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1658bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); 165920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 166020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n", 16612dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik hc, relevant, hc_irq_cause); 166220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 166320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) { 1664cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct ata_port *ap = host->ports[port]; 166563af2a5c5990d95f1e7d8795f1425fb976ea2b4bMark Lord struct mv_port_priv *pp = ap->private_data; 1666bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik int have_err_bits, hard_port, shift; 166755d8ca4f8094246da6e71889a4e04bfafaa78b10Jeff Garzik 1668bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if ((!ap) || (ap->flags & ATA_FLAG_DISABLED)) 1669a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik continue; 1670a2c91a8819e315e9fd1aef3ff57badb6c1be3f80Jeff Garzik 167131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ shift = port << 1; /* (port * 2) */ 167220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (port >= MV_PORTS_PER_HC) { 167320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ shift++; /* skip bit 8 in the HC Main IRQ reg */ 167420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 1675bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik have_err_bits = ((PORT0_ERR << shift) & relevant); 1676bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1677bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (unlikely(have_err_bits)) { 1678bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct ata_queued_cmd *qc; 16798b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik 16809af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo qc = ata_qc_from_tag(ap, ap->link.active_tag); 1681bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (qc && (qc->tf.flags & ATA_TFLAG_POLLING)) 1682bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik continue; 1683bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1684bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_err_intr(ap, qc); 1685bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik continue; 1686bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1687bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1688bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik hard_port = mv_hardport_from_port(port); /* range 0..3 */ 1689bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1690bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { 1691bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) 1692bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_intr_edma(ap); 1693bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } else { 1694bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if ((DEV_IRQ << hard_port) & hc_irq_cause) 1695bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_intr_pio(ap); 169620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 169720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 169820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("EXIT\n"); 169920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 170020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1701bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_pci_error(struct ata_host *host, void __iomem *mmio) 1702bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 170302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord struct mv_host_priv *hpriv = host->private_data; 1704bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct ata_port *ap; 1705bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct ata_queued_cmd *qc; 1706bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct ata_eh_info *ehi; 1707bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int i, err_mask, printed = 0; 1708bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 err_cause; 1709bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 171002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord err_cause = readl(mmio + hpriv->irq_cause_ofs); 1711bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1712bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n", 1713bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik err_cause); 1714bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1715bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik DPRINTK("All regs @ PCI error\n"); 1716bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev)); 1717bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 171802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord writelfl(0, mmio + hpriv->irq_cause_ofs); 1719bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1720bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik for (i = 0; i < host->n_ports; i++) { 1721bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ap = host->ports[i]; 1722936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo if (!ata_link_offline(&ap->link)) { 17239af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo ehi = &ap->link.eh_info; 1724bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_ehi_clear_desc(ehi); 1725bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (!printed++) 1726bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_ehi_push_desc(ehi, 1727bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik "PCI err cause 0x%08x", err_cause); 1728bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik err_mask = AC_ERR_HOST_BUS; 1729bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehi->action = ATA_EH_HARDRESET; 17309af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo qc = ata_qc_from_tag(ap, ap->link.active_tag); 1731bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (qc) 1732bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik qc->err_mask |= err_mask; 1733bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik else 1734bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehi->err_mask |= err_mask; 1735bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 1736bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_port_freeze(ap); 1737bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1738bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1739bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 1740bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 174105b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 1742c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik * mv_interrupt - Main interrupt event handler 174305b308e1df6d9d673daedb517969241f41278b52Brett Russ * @irq: unused 174405b308e1df6d9d673daedb517969241f41278b52Brett Russ * @dev_instance: private data; in this case the host structure 174505b308e1df6d9d673daedb517969241f41278b52Brett Russ * 174605b308e1df6d9d673daedb517969241f41278b52Brett Russ * Read the read only register to determine if any host 174705b308e1df6d9d673daedb517969241f41278b52Brett Russ * controllers have pending interrupts. If so, call lower level 174805b308e1df6d9d673daedb517969241f41278b52Brett Russ * routine to handle. Also check for PCI errors which are only 174905b308e1df6d9d673daedb517969241f41278b52Brett Russ * reported here. 175005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 17518b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik * LOCKING: 1752cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik * This routine holds the host lock while processing pending 175305b308e1df6d9d673daedb517969241f41278b52Brett Russ * interrupts. 175405b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 17557d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mv_interrupt(int irq, void *dev_instance) 175620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 1757cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct ata_host *host = dev_instance; 175820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int hc, handled = 0, n_hcs; 17590d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; 1760646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord u32 irq_stat, irq_mask; 176120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1762646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord spin_lock(&host->lock); 176320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS); 1764646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord irq_mask = readl(mmio + HC_MAIN_IRQ_MASK_OFS); 176520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 176620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* check the cases where we either have nothing pending or have read 176720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * a bogus register value which can indicate HW removal or PCI fault 176820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */ 1769646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord if (!(irq_stat & irq_mask) || (0xffffffffU == irq_stat)) 1770646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord goto out_unlock; 177120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1772cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik n_hcs = mv_get_hc_count(host->ports[0]->flags); 177320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1774bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (unlikely(irq_stat & PCI_ERR)) { 1775bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_pci_error(host, mmio); 1776bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik handled = 1; 1777bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik goto out_unlock; /* skip all other HC irq handling */ 1778bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 1779bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 178020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ for (hc = 0; hc < n_hcs; hc++) { 178120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT)); 178220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (relevant) { 1783cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik mv_host_intr(host, relevant, hc); 1784bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik handled = 1; 178520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 178620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 1787615ab95342f6245026d8974b9724f7ea57d9a184Mark Lord 1788bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikout_unlock: 1789cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik spin_unlock(&host->lock); 179020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 179120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return IRQ_RETVAL(handled); 179220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 179320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1794c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port) 1795c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1796c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port); 1797c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL; 1798c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1799c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return hc_mmio + ofs; 1800c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1801c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1802c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic unsigned int mv5_scr_offset(unsigned int sc_reg_in) 1803c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1804c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int ofs; 1805c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1806c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik switch (sc_reg_in) { 1807c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik case SCR_STATUS: 1808c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik case SCR_ERROR: 1809c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik case SCR_CONTROL: 1810c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ofs = sc_reg_in * sizeof(u32); 1811c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik break; 1812c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik default: 1813c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ofs = 0xffffffffU; 1814c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik break; 1815c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik } 1816c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return ofs; 1817c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1818c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1819da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val) 1820c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 18210d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 18220d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *addr = mv5_phy_base(mmio, ap->port_no); 1823c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int ofs = mv5_scr_offset(sc_reg_in); 1824c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1825da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo if (ofs != 0xffffffffU) { 1826da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo *val = readl(addr + ofs); 1827da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return 0; 1828da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } else 1829da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return -EINVAL; 1830c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1831c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1832da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heostatic int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) 1833c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 18340d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 18350d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *addr = mv5_phy_base(mmio, ap->port_no); 1836c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int ofs = mv5_scr_offset(sc_reg_in); 1837c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1838da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo if (ofs != 0xffffffffU) { 18390d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo writelfl(val, addr + ofs); 1840da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return 0; 1841da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } else 1842da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return -EINVAL; 1843c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1844c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1845522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio) 1846522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{ 1847522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik int early_5080; 1848522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 184944c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0); 1850522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1851522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik if (!early_5080) { 1852522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL); 1853522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik tmp |= (1 << 0); 1854522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL); 1855522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik } 1856522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1857522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik mv_reset_pci_bus(pdev, mmio); 1858522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik} 1859522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1860522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzikstatic void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) 1861522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik{ 1862522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik writel(0x0fcfffff, mmio + MV_FLASH_CTL); 1863522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik} 1864522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 186547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, 1866ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik void __iomem *mmio) 1867ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{ 1868c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *phy_mmio = mv5_phy_base(mmio, idx); 1869c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik u32 tmp; 1870c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1871c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(phy_mmio + MV5_PHY_MODE); 1872c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1873c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik hpriv->signal[idx].pre = tmp & 0x1800; /* bits 12:11 */ 1874c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik hpriv->signal[idx].amps = tmp & 0xe0; /* bits 7:5 */ 1875ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik} 1876ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 187747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) 1878ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{ 1879522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik u32 tmp; 1880522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1881522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik writel(0, mmio + MV_GPIO_PORT_CTL); 1882522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1883522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik /* FIXME: handle MV_HP_ERRATA_50XXB2 errata */ 1884522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik 1885522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL); 1886522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik tmp |= ~(1 << 0); 1887522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL); 1888ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik} 1889ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 18902a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzikstatic void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 18912a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port) 1892bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{ 1893c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *phy_mmio = mv5_phy_base(mmio, port); 1894c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5); 1895c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik u32 tmp; 1896c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0); 1897c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1898c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik if (fix_apm_sq) { 1899c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(phy_mmio + MV5_LT_MODE); 1900c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= (1 << 19); 1901c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(tmp, phy_mmio + MV5_LT_MODE); 1902c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1903c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(phy_mmio + MV5_PHY_CTL); 1904c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp &= ~0x3; 1905c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= 0x1; 1906c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(tmp, phy_mmio + MV5_PHY_CTL); 1907c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik } 1908c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1909c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(phy_mmio + MV5_PHY_MODE); 1910c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp &= ~mask; 1911c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= hpriv->signal[port].pre; 1912c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= hpriv->signal[port].amps; 1913c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(tmp, phy_mmio + MV5_PHY_MODE); 1914bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik} 1915bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 1916c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1917c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO 1918c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, port_mmio + (reg)) 1919c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio, 1920c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int port) 1921c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1922c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 1923c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1924c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS); 1925c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1926c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mv_channel_reset(hpriv, mmio, port); 1927c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1928c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x028); /* command */ 1929c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(0x11f, port_mmio + EDMA_CFG_OFS); 1930c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x004); /* timer */ 1931c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x008); /* irq err cause */ 1932c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x00c); /* irq err mask */ 1933c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x010); /* rq bah */ 1934c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x014); /* rq inp */ 1935c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x018); /* rq outp */ 1936c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x01c); /* respq bah */ 1937c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x024); /* respq outp */ 1938c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x020); /* respq inp */ 1939c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x02c); /* test control */ 1940c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(0xbc, port_mmio + EDMA_IORDY_TMOUT); 1941c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1942c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO 1943c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1944c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#define ZERO(reg) writel(0, hc_mmio + (reg)) 1945c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 1946c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int hc) 194747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik{ 1948c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *hc_mmio = mv_hc_base(mmio, hc); 1949c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik u32 tmp; 1950c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1951c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x00c); 1952c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x010); 1953c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x014); 1954c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik ZERO(0x018); 1955c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1956c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp = readl(hc_mmio + 0x20); 1957c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp &= 0x1c1c1c1c; 1958c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik tmp |= 0x03030303; 1959c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writel(tmp, hc_mmio + 0x20); 1960c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 1961c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik#undef ZERO 1962c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1963c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 1964c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc) 1965c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 1966c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int hc, port; 1967c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1968c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik for (hc = 0; hc < n_hc; hc++) { 1969c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik for (port = 0; port < MV_PORTS_PER_HC; port++) 1970c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mv5_reset_hc_port(hpriv, mmio, 1971c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik (hc * MV_PORTS_PER_HC) + port); 1972c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1973c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mv5_reset_one_hc(hpriv, mmio, hc); 1974c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik } 1975c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 1976c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik return 0; 197747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik} 197847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 1979101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO 1980101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#define ZERO(reg) writel(0, mmio + (reg)) 1981101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio) 1982101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{ 198302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord struct ata_host *host = dev_get_drvdata(&pdev->dev); 198402a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord struct mv_host_priv *hpriv = host->private_data; 1985101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik u32 tmp; 1986101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1987101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp = readl(mmio + MV_PCI_MODE); 1988101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp &= 0xff00ffff; 1989101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(tmp, mmio + MV_PCI_MODE); 1990101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 1991101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_DISC_TIMER); 1992101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_MSI_TRIGGER); 1993101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT); 1994101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(HC_MAIN_IRQ_MASK_OFS); 1995101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_SERR_MASK); 199602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord ZERO(hpriv->irq_cause_ofs); 199702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord ZERO(hpriv->irq_mask_ofs); 1998101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_ERR_LOW_ADDRESS); 1999101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_ERR_HIGH_ADDRESS); 2000101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_ERR_ATTRIBUTE); 2001101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik ZERO(MV_PCI_ERR_COMMAND); 2002101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik} 2003101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik#undef ZERO 2004101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2005101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikstatic void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) 2006101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{ 2007101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik u32 tmp; 2008101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2009101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik mv5_reset_flash(hpriv, mmio); 2010101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2011101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp = readl(mmio + MV_GPIO_PORT_CTL); 2012101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp &= 0x3; 2013101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik tmp |= (1 << 5) | (1 << 6); 2014101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(tmp, mmio + MV_GPIO_PORT_CTL); 2015101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik} 2016101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2017101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik/** 2018101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * mv6_reset_hc - Perform the 6xxx global soft reset 2019101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * @mmio: base address of the HBA 2020101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * 2021101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * This routine only applies to 6xxx parts. 2022101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * 2023101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * LOCKING: 2024101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * Inherited from caller. 2025101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */ 2026c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, 2027c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int n_hc) 2028101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik{ 2029101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS; 2030101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik int i, rc = 0; 2031101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik u32 t; 2032101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2033101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik /* Following procedure defined in PCI "main command and status 2034101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik * register" table. 2035101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik */ 2036101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik t = readl(reg); 2037101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(t | STOP_PCI_MASTER, reg); 2038101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2039101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik for (i = 0; i < 1000; i++) { 2040101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik udelay(1); 2041101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik t = readl(reg); 20422dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik if (PCI_MASTER_EMPTY & t) 2043101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik break; 2044101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } 2045101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik if (!(PCI_MASTER_EMPTY & t)) { 2046101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik printk(KERN_ERR DRV_NAME ": PCI master won't flush\n"); 2047101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik rc = 1; 2048101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik goto done; 2049101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } 2050101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2051101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik /* set reset */ 2052101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik i = 5; 2053101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik do { 2054101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(t | GLOB_SFT_RST, reg); 2055101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik t = readl(reg); 2056101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik udelay(1); 2057101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } while (!(GLOB_SFT_RST & t) && (i-- > 0)); 2058101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2059101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik if (!(GLOB_SFT_RST & t)) { 2060101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik printk(KERN_ERR DRV_NAME ": can't set global reset\n"); 2061101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik rc = 1; 2062101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik goto done; 2063101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } 2064101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2065101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik /* clear reset and *reenable the PCI master* (not mentioned in spec) */ 2066101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik i = 5; 2067101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik do { 2068101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg); 2069101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik t = readl(reg); 2070101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik udelay(1); 2071101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } while ((GLOB_SFT_RST & t) && (i-- > 0)); 2072101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 2073101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik if (GLOB_SFT_RST & t) { 2074101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik printk(KERN_ERR DRV_NAME ": can't clear global reset\n"); 2075101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik rc = 1; 2076101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik } 2077101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzikdone: 2078101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik return rc; 2079101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik} 2080101ffae26c23ea928fce6d31a8b4901327d91a15Jeff Garzik 208147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, 2082ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik void __iomem *mmio) 2083ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{ 2084ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik void __iomem *port_mmio; 2085ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik u32 tmp; 2086ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 2087ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik tmp = readl(mmio + MV_RESET_CFG); 2088ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik if ((tmp & (1 << 0)) == 0) { 208947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->signal[idx].amps = 0x7 << 8; 2090ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik hpriv->signal[idx].pre = 0x1 << 5; 2091ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik return; 2092ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik } 2093ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 2094ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik port_mmio = mv_port_base(mmio, idx); 2095ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik tmp = readl(port_mmio + PHY_MODE2); 2096ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 2097ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik hpriv->signal[idx].amps = tmp & 0x700; /* bits 10:8 */ 2098ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik hpriv->signal[idx].pre = tmp & 0xe0; /* bits 7:5 */ 2099ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik} 2100ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 210147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzikstatic void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) 2102ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik{ 210347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(0x00000060, mmio + MV_GPIO_PORT_CTL); 2104ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik} 2105ba3fe8fb6a469390a14379519915f3c39a973d99Jeff Garzik 2106c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, 21072a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik unsigned int port) 2108bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{ 2109c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 2110c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2111bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik u32 hp_flags = hpriv->hp_flags; 211247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik int fix_phy_mode2 = 211347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); 2114bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik int fix_phy_mode4 = 211547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); 211647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik u32 m2, tmp; 211747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 211847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (fix_phy_mode2) { 211947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 = readl(port_mmio + PHY_MODE2); 212047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 &= ~(1 << 16); 212147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 |= (1 << 31); 212247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(m2, port_mmio + PHY_MODE2); 212347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 212447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik udelay(200); 212547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 212647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 = readl(port_mmio + PHY_MODE2); 212747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 &= ~((1 << 16) | (1 << 31)); 212847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(m2, port_mmio + PHY_MODE2); 212947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 213047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik udelay(200); 213147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik } 213247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 213347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik /* who knows what this magic does */ 213447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik tmp = readl(port_mmio + PHY_MODE3); 213547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik tmp &= ~0x7F800000; 213647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik tmp |= 0x2A800000; 213747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(tmp, port_mmio + PHY_MODE3); 2138bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2139bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik if (fix_phy_mode4) { 214047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik u32 m4; 2141bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2142bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik m4 = readl(port_mmio + PHY_MODE4); 214347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 214447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (hp_flags & MV_HP_ERRATA_60X1B2) 214547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik tmp = readl(port_mmio + 0x310); 2146bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2147bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik m4 = (m4 & ~(1 << 1)) | (1 << 0); 2148bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2149bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik writel(m4, port_mmio + PHY_MODE4); 215047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 215147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (hp_flags & MV_HP_ERRATA_60X1B2) 215247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(tmp, port_mmio + 0x310); 2153bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik } 2154bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2155bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik /* Revert values of pre-emphasis and signal amps to the saved ones */ 2156bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik m2 = readl(port_mmio + PHY_MODE2); 2157bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2158bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik m2 &= ~MV_M2_PREAMP_MASK; 21592a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik m2 |= hpriv->signal[port].amps; 21602a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik m2 |= hpriv->signal[port].pre; 216147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik m2 &= ~(1 << 16); 2162bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2163e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik /* according to mvSata 3.6.1, some IIE values are fixed */ 2164e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik if (IS_GEN_IIE(hpriv)) { 2165e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik m2 &= ~0xC30FF01F; 2166e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik m2 |= 0x0000900F; 2167e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik } 2168e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 2169bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik writel(m2, port_mmio + PHY_MODE2); 2170bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik} 2171bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2172c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzikstatic void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, 2173c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik unsigned int port_no) 2174c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik{ 2175c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port_no); 2176c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2177c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS); 2178c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2179ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik if (IS_GEN_II(hpriv)) { 2180c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); 2181eb46d684600ac145501805a294c94675e82eab2eMark Lord ifctl |= (1 << 7); /* enable gen2i speed */ 2182eb46d684600ac145501805a294c94675e82eab2eMark Lord ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */ 2183c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); 2184c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik } 2185c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2186c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik udelay(25); /* allow reset propagation */ 2187c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2188c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik /* Spec never mentions clearing the bit. Marvell's driver does 2189c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik * clear the bit, however. 2190c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik */ 2191c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik writelfl(0, port_mmio + EDMA_CMD_OFS); 2192c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2193c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik hpriv->ops->phy_errata(hpriv, mmio, port_no); 2194c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 2195ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik if (IS_GEN_I(hpriv)) 2196c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik mdelay(1); 2197c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik} 2198c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 219905b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 2200bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * mv_phy_reset - Perform eDMA reset followed by COMRESET 220105b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ap: ATA channel to manipulate 220205b308e1df6d9d673daedb517969241f41278b52Brett Russ * 220305b308e1df6d9d673daedb517969241f41278b52Brett Russ * Part of this is taken from __sata_phy_reset and modified to 220405b308e1df6d9d673daedb517969241f41278b52Brett Russ * not sleep since this routine gets called from interrupt level. 220505b308e1df6d9d673daedb517969241f41278b52Brett Russ * 220605b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 220705b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. This is coded to safe to call at 220805b308e1df6d9d673daedb517969241f41278b52Brett Russ * interrupt level, i.e. it does not sleep. 220931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 2210bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_phy_reset(struct ata_port *ap, unsigned int *class, 2211bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned long deadline) 221220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 2213095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik struct mv_port_priv *pp = ap->private_data; 2214cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 221520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ void __iomem *port_mmio = mv_ap_base(ap); 221622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik int retry = 5; 221722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik u32 sstatus; 221820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 221920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio); 222020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2221da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#ifdef DEBUG 2222da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo { 2223da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo u32 sstatus, serror, scontrol; 2224da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo 2225da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo mv_scr_read(ap, SCR_STATUS, &sstatus); 2226da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo mv_scr_read(ap, SCR_ERROR, &serror); 2227da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo mv_scr_read(ap, SCR_CONTROL, &scontrol); 2228da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x " 22292d79ab8fd7a7bf3a45d0e948ae27b3dd95ce95eaSaeed Bishara "SCtrl 0x%08x\n", sstatus, serror, scontrol); 2230da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } 2231da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#endif 223220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 223322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik /* Issue COMRESET via SControl */ 223422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzikcomreset_retry: 2235936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x301); 2236bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik msleep(1); 223722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 2238936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x300); 2239bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik msleep(20); 224022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 224131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ do { 2242936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo sata_scr_read(&ap->link, SCR_STATUS, &sstatus); 224362f1d0e6de138b91d55fbd7d579c837ed62e9e31Andres Salomon if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0)) 224431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ break; 224522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 2246bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik msleep(1); 2247c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik } while (time_before(jiffies, deadline)); 224820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 224922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik /* work around errata */ 2250ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik if (IS_GEN_II(hpriv) && 225122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) && 225222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik (retry-- > 0)) 225322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik goto comreset_retry; 2254095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 2255da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#ifdef DEBUG 2256da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo { 2257da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo u32 sstatus, serror, scontrol; 2258da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo 2259da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo mv_scr_read(ap, SCR_STATUS, &sstatus); 2260da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo mv_scr_read(ap, SCR_ERROR, &serror); 2261da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo mv_scr_read(ap, SCR_CONTROL, &scontrol); 2262da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x " 2263da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo "SCtrl 0x%08x\n", sstatus, serror, scontrol); 2264da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } 2265da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo#endif 226631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2267936fd7328657884d5a69a55666c74a55aa83ca27Tejun Heo if (ata_link_offline(&ap->link)) { 2268bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik *class = ATA_DEV_NONE; 226920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return; 227020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 227120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 227222374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik /* even after SStatus reflects that device is ready, 227322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik * it seems to take a while for link to be fully 227422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik * established (and thus Status no longer 0x80/0x7F), 227522374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik * so we poll a bit for that, here. 227622374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik */ 227722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik retry = 20; 227822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik while (1) { 227922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik u8 drv_stat = ata_check_status(ap); 228022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik if ((drv_stat != 0x80) && (drv_stat != 0x7f)) 228122374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik break; 2282bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik msleep(500); 228322374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik if (retry-- <= 0) 228422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik break; 2285bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (time_after(jiffies, deadline)) 2286bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik break; 228722374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik } 228822374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 2289bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* FIXME: if we passed the deadline, the following 2290bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik * code probably produces an invalid result 2291bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik */ 229220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2293bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* finally, read device signature from TF registers */ 22943f19859ee95a38c066a0420eb8a30c76ecd67a42Tejun Heo *class = ata_dev_try_classify(ap->link.device, 1, NULL); 2295095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 2296095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 2297095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 2298bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN); 2299095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 2300bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik VPRINTK("EXIT\n"); 230120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 230220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2303cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic int mv_prereset(struct ata_link *link, unsigned long deadline) 230422374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik{ 2305cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo struct ata_port *ap = link->ap; 2306bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_port_priv *pp = ap->private_data; 2307cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo struct ata_eh_context *ehc = &link->eh_context; 2308bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik int rc; 23090ea9e179f436f153fc19fdaef7abbc1e0da20762Jeff Garzik 2310bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik rc = mv_stop_dma(ap); 2311bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (rc) 2312bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehc->i.action |= ATA_EH_HARDRESET; 2313bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2314bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) { 2315bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET; 2316bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ehc->i.action |= ATA_EH_HARDRESET; 2317bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 2318bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2319bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* if we're about to do hardreset, nothing more to do */ 2320bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (ehc->i.action & ATA_EH_HARDRESET) 2321bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return 0; 2322bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2323cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo if (ata_link_online(link)) 2324bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik rc = ata_wait_ready(ap, deadline); 2325bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik else 2326bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik rc = -ENODEV; 2327bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2328bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return rc; 232922374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik} 233022374677d18c5eeefd3a283431d312b8c44fef02Jeff Garzik 2331cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic int mv_hardreset(struct ata_link *link, unsigned int *class, 2332bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned long deadline) 233331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 2334cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo struct ata_port *ap = link->ap; 2335bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik struct mv_host_priv *hpriv = ap->host->private_data; 23360d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 233731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2338bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_stop_dma(ap); 233931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2340bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_channel_reset(hpriv, mmio, ap->port_no); 234131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2342bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_phy_reset(ap, class, deadline); 2343bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2344bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return 0; 2345bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 2346bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2347cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heostatic void mv_postreset(struct ata_link *link, unsigned int *classes) 2348bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 2349cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo struct ata_port *ap = link->ap; 2350bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 serr; 2351bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2352bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* print link status */ 2353cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo sata_print_link_status(link); 235431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2355bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* clear SError */ 2356cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo sata_scr_read(link, SCR_ERROR, &serr); 2357cc0680a580b5be81a1ca321b58f8e9b80b5c1052Tejun Heo sata_scr_write_flush(link, SCR_ERROR, serr); 2358bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2359bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* bail out if no device is present */ 2360bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) { 2361bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik DPRINTK("EXIT, no device\n"); 2362bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik return; 23639b358e305c1d783c8a4ebf00344e95deb9e38f3dMark Lord } 2364bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2365bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* set up device control */ 2366bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik iowrite8(ap->ctl, ap->ioaddr.ctl_addr); 2367bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 2368bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2369bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_error_handler(struct ata_port *ap) 2370bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 2371bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik ata_do_eh(ap, mv_prereset, ata_std_softreset, 2372bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_hardreset, mv_postreset); 2373bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 2374bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2375bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_post_int_cmd(struct ata_queued_cmd *qc) 2376bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 2377bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mv_stop_dma(qc->ap); 2378bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 2379bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2380bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_freeze(struct ata_port *ap) 2381bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 2382bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 2383bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int hc = (ap->port_no > 3) ? 1 : 0; 2384bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 tmp, mask; 2385bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int shift; 2386bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2387bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* FIXME: handle coalescing completion events properly */ 2388bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2389bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik shift = ap->port_no * 2; 2390bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (hc > 0) 2391bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik shift++; 2392bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2393bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mask = 0x3 << shift; 2394bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2395bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* disable assertion of portN err, done events */ 2396bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS); 2397bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl(tmp & ~mask, mmio + HC_MAIN_IRQ_MASK_OFS); 2398bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik} 2399bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2400bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzikstatic void mv_eh_thaw(struct ata_port *ap) 2401bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik{ 2402bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; 2403bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int hc = (ap->port_no > 3) ? 1 : 0; 2404bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik void __iomem *hc_mmio = mv_hc_base(mmio, hc); 2405bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik void __iomem *port_mmio = mv_ap_base(ap); 2406bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik u32 tmp, mask, hc_irq_cause; 2407bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik unsigned int shift, hc_port_no = ap->port_no; 2408bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2409bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* FIXME: handle coalescing completion events properly */ 2410bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2411bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik shift = ap->port_no * 2; 2412bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik if (hc > 0) { 2413bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik shift++; 2414bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik hc_port_no -= 4; 2415bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik } 2416bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2417bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik mask = 0x3 << shift; 2418bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2419bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* clear EDMA errors on this port */ 2420bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 2421bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2422bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* clear pending irq events */ 2423bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS); 2424bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik hc_irq_cause &= ~(1 << hc_port_no); /* clear CRPB-done */ 2425bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik hc_irq_cause &= ~(1 << (hc_port_no + 8)); /* clear Device int */ 2426bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); 2427bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik 2428bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik /* enable assertion of portN err, done events */ 2429bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS); 2430bdd4dddee325a7dce3e84cf48201a06aa8508aa4Jeff Garzik writelfl(tmp | mask, mmio + HC_MAIN_IRQ_MASK_OFS); 243131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 243231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 243305b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 243405b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_port_init - Perform some early initialization on a single port. 243505b308e1df6d9d673daedb517969241f41278b52Brett Russ * @port: libata data structure storing shadow register addresses 243605b308e1df6d9d673daedb517969241f41278b52Brett Russ * @port_mmio: base address of the port 243705b308e1df6d9d673daedb517969241f41278b52Brett Russ * 243805b308e1df6d9d673daedb517969241f41278b52Brett Russ * Initialize shadow register mmio addresses, clear outstanding 243905b308e1df6d9d673daedb517969241f41278b52Brett Russ * interrupts on the port, and unmask interrupts for the future 244005b308e1df6d9d673daedb517969241f41278b52Brett Russ * start of the port. 244105b308e1df6d9d673daedb517969241f41278b52Brett Russ * 244205b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 244305b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 244405b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 244531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio) 244620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 24470d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *shd_base = port_mmio + SHD_BLK_OFS; 244831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ unsigned serr_ofs; 244931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 24508b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik /* PIO related setup 245131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 245231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA); 24538b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik port->error_addr = 245431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR); 245531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT); 245631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL); 245731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM); 245831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH); 245931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE); 24608b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik port->status_addr = 246131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS); 246231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* special case: control/altstatus doesn't have ATA_REG_ address */ 246331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS; 246431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 246531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* unused: */ 24668d9db2d2fbae9e05022825c32f86e00c8e342860Randy Dunlap port->cmd_addr = port->bmdma_addr = port->scr_addr = NULL; 246720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 246831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Clear any currently outstanding port interrupt conditions */ 246931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ serr_ofs = mv_scr_offset(SCR_ERROR); 247031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs); 247131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 247231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2473646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord /* unmask all non-transient EDMA error interrupts */ 2474646a4da514f2555298481cb00dc5b3eb02b21b72Mark Lord writelfl(~EDMA_ERR_IRQ_TRANSIENT, port_mmio + EDMA_ERR_IRQ_MASK_OFS); 247520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 24768b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n", 247731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(port_mmio + EDMA_CFG_OFS), 247831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS), 247931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS)); 248020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 248120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 24824447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_chip_id(struct ata_host *host, unsigned int board_idx) 2483bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{ 24844447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 24854447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct mv_host_priv *hpriv = host->private_data; 2486bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik u32 hp_flags = hpriv->hp_flags; 2487bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 24885796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik switch (board_idx) { 248947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case chip_5080: 249047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops = &mv5xxx_ops; 2491ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik hp_flags |= MV_HP_GEN_I; 249247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 249344c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok switch (pdev->revision) { 249447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x1: 249547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB0; 249647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 249747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x3: 249847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 249947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 250047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik default: 250147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 250247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik "Applying 50XXB2 workarounds to unknown rev\n"); 250347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 250447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 250547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik } 250647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 250747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 2508bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case chip_504x: 2509bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case chip_508x: 251047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops = &mv5xxx_ops; 2511ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik hp_flags |= MV_HP_GEN_I; 2512bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 251344c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok switch (pdev->revision) { 251447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x0: 251547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB0; 251647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 251747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x3: 251847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 251947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 252047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik default: 252147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 252247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik "Applying B2 workarounds to unknown rev\n"); 252347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_50XXB2; 252447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 2525bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik } 2526bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik break; 2527bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2528bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case chip_604x: 2529bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case chip_608x: 253047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops = &mv6xxx_ops; 2531ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik hp_flags |= MV_HP_GEN_II; 253247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 253344c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok switch (pdev->revision) { 253447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x7: 253547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_60X1B2; 253647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 253747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case 0x9: 253847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_60X1C0; 2539bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik break; 2540bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik default: 2541bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 254247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik "Applying B2 workarounds to unknown rev\n"); 254347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hp_flags |= MV_HP_ERRATA_60X1B2; 2544bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik break; 2545bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik } 2546bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik break; 2547bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2548e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik case chip_7042: 254902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hp_flags |= MV_HP_PCIE; 2550306b30f74d37f289033c696285e07ce0158a5d7bMark Lord if (pdev->vendor == PCI_VENDOR_ID_TTI && 2551306b30f74d37f289033c696285e07ce0158a5d7bMark Lord (pdev->device == 0x2300 || pdev->device == 0x2310)) 2552306b30f74d37f289033c696285e07ce0158a5d7bMark Lord { 25534e5200334e03e5620aa19d538300c13db270a063Mark Lord /* 25544e5200334e03e5620aa19d538300c13db270a063Mark Lord * Highpoint RocketRAID PCIe 23xx series cards: 25554e5200334e03e5620aa19d538300c13db270a063Mark Lord * 25564e5200334e03e5620aa19d538300c13db270a063Mark Lord * Unconfigured drives are treated as "Legacy" 25574e5200334e03e5620aa19d538300c13db270a063Mark Lord * by the BIOS, and it overwrites sector 8 with 25584e5200334e03e5620aa19d538300c13db270a063Mark Lord * a "Lgcy" metadata block prior to Linux boot. 25594e5200334e03e5620aa19d538300c13db270a063Mark Lord * 25604e5200334e03e5620aa19d538300c13db270a063Mark Lord * Configured drives (RAID or JBOD) leave sector 8 25614e5200334e03e5620aa19d538300c13db270a063Mark Lord * alone, but instead overwrite a high numbered 25624e5200334e03e5620aa19d538300c13db270a063Mark Lord * sector for the RAID metadata. This sector can 25634e5200334e03e5620aa19d538300c13db270a063Mark Lord * be determined exactly, by truncating the physical 25644e5200334e03e5620aa19d538300c13db270a063Mark Lord * drive capacity to a nice even GB value. 25654e5200334e03e5620aa19d538300c13db270a063Mark Lord * 25664e5200334e03e5620aa19d538300c13db270a063Mark Lord * RAID metadata is at: (dev->n_sectors & ~0xfffff) 25674e5200334e03e5620aa19d538300c13db270a063Mark Lord * 25684e5200334e03e5620aa19d538300c13db270a063Mark Lord * Warn the user, lest they think we're just buggy. 25694e5200334e03e5620aa19d538300c13db270a063Mark Lord */ 25704e5200334e03e5620aa19d538300c13db270a063Mark Lord printk(KERN_WARNING DRV_NAME ": Highpoint RocketRAID" 25714e5200334e03e5620aa19d538300c13db270a063Mark Lord " BIOS CORRUPTS DATA on all attached drives," 25724e5200334e03e5620aa19d538300c13db270a063Mark Lord " regardless of if/how they are configured." 25734e5200334e03e5620aa19d538300c13db270a063Mark Lord " BEWARE!\n"); 25744e5200334e03e5620aa19d538300c13db270a063Mark Lord printk(KERN_WARNING DRV_NAME ": For data safety, do not" 25754e5200334e03e5620aa19d538300c13db270a063Mark Lord " use sectors 8-9 on \"Legacy\" drives," 25764e5200334e03e5620aa19d538300c13db270a063Mark Lord " and avoid the final two gigabytes on" 25774e5200334e03e5620aa19d538300c13db270a063Mark Lord " all RocketRAID BIOS initialized drives.\n"); 2578306b30f74d37f289033c696285e07ce0158a5d7bMark Lord } 2579e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik case chip_6042: 2580e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hpriv->ops = &mv6xxx_ops; 2581e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hp_flags |= MV_HP_GEN_IIE; 2582e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 258344c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok switch (pdev->revision) { 2584e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik case 0x0: 2585e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hp_flags |= MV_HP_ERRATA_XX42A0; 2586e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik break; 2587e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik case 0x1: 2588e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hp_flags |= MV_HP_ERRATA_60X1C0; 2589e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik break; 2590e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik default: 2591e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 2592e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik "Applying 60X1C0 workarounds to unknown rev\n"); 2593e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik hp_flags |= MV_HP_ERRATA_60X1C0; 2594e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik break; 2595e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik } 2596e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik break; 2597e4e7b89280d1d666e2c09e5ad36cf071796c4c7eJeff Garzik 2598bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik default: 25995796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik dev_printk(KERN_ERR, &pdev->dev, 26005796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik "BUG: invalid board index %u\n", board_idx); 2601bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik return 1; 2602bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik } 2603bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2604bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik hpriv->hp_flags = hp_flags; 260502a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord if (hp_flags & MV_HP_PCIE) { 260602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hpriv->irq_cause_ofs = PCIE_IRQ_CAUSE_OFS; 260702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hpriv->irq_mask_ofs = PCIE_IRQ_MASK_OFS; 260802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hpriv->unmask_all_irqs = PCIE_UNMASK_ALL_IRQS; 260902a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord } else { 261002a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hpriv->irq_cause_ofs = PCI_IRQ_CAUSE_OFS; 261102a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hpriv->irq_mask_ofs = PCI_IRQ_MASK_OFS; 261202a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord hpriv->unmask_all_irqs = PCI_UNMASK_ALL_IRQS; 261302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord } 2614bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 2615bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik return 0; 2616bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik} 2617bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 261805b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 261947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * mv_init_host - Perform some early initialization of the host. 26204447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo * @host: ATA host to initialize 26214447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo * @board_idx: controller index 262205b308e1df6d9d673daedb517969241f41278b52Brett Russ * 262305b308e1df6d9d673daedb517969241f41278b52Brett Russ * If possible, do an early global reset of the host. Then do 262405b308e1df6d9d673daedb517969241f41278b52Brett Russ * our port init and clear/unmask all/relevant host interrupts. 262505b308e1df6d9d673daedb517969241f41278b52Brett Russ * 262605b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 262705b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 262805b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 26294447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic int mv_init_host(struct ata_host *host, unsigned int board_idx) 263020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 263120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ int rc = 0, n_hc, port, hc; 26324447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 26334447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; 26344447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct mv_host_priv *hpriv = host->private_data; 2635bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 263647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik /* global interrupt mask */ 263747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik writel(0, mmio + HC_MAIN_IRQ_MASK_OFS); 263847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 26394447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo rc = mv_chip_id(host, board_idx); 2640bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik if (rc) 2641bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik goto done; 2642bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 26434447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo n_hc = mv_get_hc_count(host->ports[0]->flags); 2644bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 26454447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (port = 0; port < host->n_ports; port++) 264647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops->read_preamp(hpriv, port, mmio); 264720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2648c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc); 264947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (rc) 265020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ goto done; 265120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2652522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik hpriv->ops->reset_flash(hpriv, mmio); 2653522479fb98c6667f081e75f87e298e413c0b1db8Jeff Garzik hpriv->ops->reset_bus(pdev, mmio); 265447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik hpriv->ops->enable_leds(hpriv, mmio); 265520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 26564447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (port = 0; port < host->n_ports; port++) { 2657ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik if (IS_GEN_II(hpriv)) { 2658c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 2659c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik 26602a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); 2661eb46d684600ac145501805a294c94675e82eab2eMark Lord ifctl |= (1 << 7); /* enable gen2i speed */ 2662eb46d684600ac145501805a294c94675e82eab2eMark Lord ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */ 26632a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); 26642a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik } 26652a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik 2666c9d39130123238ac18478a42e25cb7996eacfcc0Jeff Garzik hpriv->ops->phy_errata(hpriv, mmio, port); 26672a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik } 26682a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik 26694447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (port = 0; port < host->n_ports; port++) { 2670cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo struct ata_port *ap = host->ports[port]; 26712a47ce06d534692f9bd2bf4e90a20fc9b1054c39Jeff Garzik void __iomem *port_mmio = mv_port_base(mmio, port); 2672cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo unsigned int offset = port_mmio - mmio; 2673cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo 2674cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo mv_port_init(&ap->ioaddr, port_mmio); 2675cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo 2676cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio"); 2677cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port"); 267820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 267920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 268020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ for (hc = 0; hc < n_hc; hc++) { 268131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *hc_mmio = mv_hc_base(mmio, hc); 268231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 268331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ VPRINTK("HC%i: HC config=0x%08x HC IRQ cause " 268431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ "(before clear)=0x%08x\n", hc, 268531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(hc_mmio + HC_CFG_OFS), 268631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(hc_mmio + HC_IRQ_CAUSE_OFS)); 268731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 268831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Clear any currently outstanding hc interrupt conditions */ 268931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS); 269020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 269120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 269231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Clear any currently outstanding host interrupt conditions */ 269302a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord writelfl(0, mmio + hpriv->irq_cause_ofs); 269431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 269531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* and unmask interrupt generation for host regs */ 269602a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs); 2697fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik 2698ee9ccdf70163ca6408f6965e0fbc65baeac7312cJeff Garzik if (IS_GEN_I(hpriv)) 2699fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS); 2700fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik else 2701fb621e2fde735abab854586d52c96c5624bcb5b8Jeff Garzik writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS); 270220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 270320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x " 27048b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik "PCI int cause/mask=0x%08x/0x%08x\n", 270520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ readl(mmio + HC_MAIN_IRQ_CAUSE_OFS), 270620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ readl(mmio + HC_MAIN_IRQ_MASK_OFS), 270702a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord readl(mmio + hpriv->irq_cause_ofs), 270802a121da5a53d415b6596bc19cc6999d295d32a4Mark Lord readl(mmio + hpriv->irq_mask_ofs)); 2709bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 271031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russdone: 271120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return rc; 271220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 271320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 271405b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 271505b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_print_info - Dump key info to kernel log for perusal. 27164447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo * @host: ATA host to print info about 271705b308e1df6d9d673daedb517969241f41278b52Brett Russ * 271805b308e1df6d9d673daedb517969241f41278b52Brett Russ * FIXME: complete this. 271905b308e1df6d9d673daedb517969241f41278b52Brett Russ * 272005b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 272105b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 272205b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 27234447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic void mv_print_info(struct ata_host *host) 272431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 27254447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 27264447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct mv_host_priv *hpriv = host->private_data; 272744c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok u8 scc; 2728c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik const char *scc_s, *gen; 272931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 273031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Use this to determine the HW stepping of the chip so we know 273131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * what errata to workaround 273231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 273331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc); 273431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (scc == 0) 273531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ scc_s = "SCSI"; 273631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ else if (scc == 0x01) 273731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ scc_s = "RAID"; 273831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ else 2739c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik scc_s = "?"; 2740c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik 2741c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik if (IS_GEN_I(hpriv)) 2742c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen = "I"; 2743c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik else if (IS_GEN_II(hpriv)) 2744c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen = "II"; 2745c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik else if (IS_GEN_IIE(hpriv)) 2746c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen = "IIE"; 2747c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik else 2748c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen = "?"; 274931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 2750a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik dev_printk(KERN_INFO, &pdev->dev, 2751c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik "Gen-%s %u slots %u ports %s mode IRQ via %s\n", 2752c1e4fe711a410a139095e6b3e3ce3f07f466063cJeff Garzik gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports, 275331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx"); 275431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 275531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 275605b308e1df6d9d673daedb517969241f41278b52Brett Russ/** 275705b308e1df6d9d673daedb517969241f41278b52Brett Russ * mv_init_one - handle a positive probe of a Marvell host 275805b308e1df6d9d673daedb517969241f41278b52Brett Russ * @pdev: PCI device found 275905b308e1df6d9d673daedb517969241f41278b52Brett Russ * @ent: PCI device ID entry for the matched host 276005b308e1df6d9d673daedb517969241f41278b52Brett Russ * 276105b308e1df6d9d673daedb517969241f41278b52Brett Russ * LOCKING: 276205b308e1df6d9d673daedb517969241f41278b52Brett Russ * Inherited from caller. 276305b308e1df6d9d673daedb517969241f41278b52Brett Russ */ 276420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 276520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 27662dcb407e61458ded17503d6bd12b8c064965368bJeff Garzik static int printed_version; 276720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int board_idx = (unsigned int)ent->driver_data; 27684447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL }; 27694447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct ata_host *host; 27704447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct mv_host_priv *hpriv; 27714447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo int n_ports, rc; 277220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2773a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik if (!printed_version++) 2774a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); 277520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 27764447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo /* allocate host */ 27774447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC; 27784447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo 27794447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 27804447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL); 27814447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo if (!host || !hpriv) 27824447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo return -ENOMEM; 27834447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo host->private_data = hpriv; 27844447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo 27854447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo /* acquire resources */ 278624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo rc = pcim_enable_device(pdev); 278724dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo if (rc) 278820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return rc; 278920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 27900d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo rc = pcim_iomap_regions(pdev, 1 << MV_PRIMARY_BAR, DRV_NAME); 27910d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo if (rc == -EBUSY) 279224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo pcim_pin_device(pdev); 27930d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo if (rc) 279424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 27954447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo host->iomap = pcim_iomap_table(pdev); 279620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2797d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik rc = pci_go_64(pdev); 2798d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik if (rc) 2799d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik return rc; 2800d88184fb2348a50f7c34f5d49a901c875b2e0114Jeff Garzik 280120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* initialize adapter */ 28024447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo rc = mv_init_host(host, board_idx); 280324dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo if (rc) 280424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 280520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 280631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* Enable interrupts */ 28076a59dcf8678cbc4106a8a6e158d7408a87691358Tejun Heo if (msi && pci_enable_msi(pdev)) 280831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pci_intx(pdev, 1); 280920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 281031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mv_dump_pci_cfg(pdev, 0x68); 28114447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo mv_print_info(host); 281220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 28134447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo pci_set_master(pdev); 2814ea8b4db97aa41a66c05daa4055a1974692ccd52dJeff Garzik pci_try_set_mwi(pdev); 28154447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED, 2816c5d3e45a2200a0905dc45b72714726b7aac3aaf1Jeff Garzik IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht); 281720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 281820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 281920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int __init mv_init(void) 282020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 2821b7887196e38da54ff893897b80875d632d1a1114Pavel Roskin return pci_register_driver(&mv_pci_driver); 282220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 282320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 282420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void __exit mv_exit(void) 282520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 282620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ pci_unregister_driver(&mv_pci_driver); 282720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 282820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 282920f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_AUTHOR("Brett Russ"); 283020f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers"); 283120f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_LICENSE("GPL"); 283220f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_DEVICE_TABLE(pci, mv_pci_tbl); 283320f733e7d75a16bffc34842b7682c9247dd5f954Brett RussMODULE_VERSION(DRV_VERSION); 283420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 2835ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzikmodule_param(msi, int, 0444); 2836ddef9bb367b19383df627e388cb4c01c86ddba6cJeff GarzikMODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); 2837ddef9bb367b19383df627e388cb4c01c86ddba6cJeff Garzik 283820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_init(mv_init); 283920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russmodule_exit(mv_exit); 2840