1c6fd2807SJeff Garzik /* 2c6fd2807SJeff Garzik * ahci.c - AHCI SATA support 3c6fd2807SJeff Garzik * 4c6fd2807SJeff Garzik * Maintained by: Jeff Garzik <jgarzik@pobox.com> 5c6fd2807SJeff Garzik * Please ALWAYS copy linux-ide@vger.kernel.org 6c6fd2807SJeff Garzik * on emails. 7c6fd2807SJeff Garzik * 8c6fd2807SJeff Garzik * Copyright 2004-2005 Red Hat, Inc. 9c6fd2807SJeff Garzik * 10c6fd2807SJeff Garzik * 11c6fd2807SJeff Garzik * This program is free software; you can redistribute it and/or modify 12c6fd2807SJeff Garzik * it under the terms of the GNU General Public License as published by 13c6fd2807SJeff Garzik * the Free Software Foundation; either version 2, or (at your option) 14c6fd2807SJeff Garzik * any later version. 15c6fd2807SJeff Garzik * 16c6fd2807SJeff Garzik * This program is distributed in the hope that it will be useful, 17c6fd2807SJeff Garzik * but WITHOUT ANY WARRANTY; without even the implied warranty of 18c6fd2807SJeff Garzik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19c6fd2807SJeff Garzik * GNU General Public License for more details. 20c6fd2807SJeff Garzik * 21c6fd2807SJeff Garzik * You should have received a copy of the GNU General Public License 22c6fd2807SJeff Garzik * along with this program; see the file COPYING. If not, write to 23c6fd2807SJeff Garzik * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 24c6fd2807SJeff Garzik * 25c6fd2807SJeff Garzik * 26c6fd2807SJeff Garzik * libata documentation is available via 'make {ps|pdf}docs', 27c6fd2807SJeff Garzik * as Documentation/DocBook/libata.* 28c6fd2807SJeff Garzik * 29c6fd2807SJeff Garzik * AHCI hardware documentation: 30c6fd2807SJeff Garzik * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf 31c6fd2807SJeff Garzik * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf 32c6fd2807SJeff Garzik * 33c6fd2807SJeff Garzik */ 34c6fd2807SJeff Garzik 35c6fd2807SJeff Garzik #include <linux/kernel.h> 36c6fd2807SJeff Garzik #include <linux/module.h> 37c6fd2807SJeff Garzik #include <linux/pci.h> 38c6fd2807SJeff Garzik #include <linux/init.h> 39c6fd2807SJeff Garzik #include <linux/blkdev.h> 40c6fd2807SJeff Garzik #include <linux/delay.h> 41c6fd2807SJeff Garzik #include <linux/interrupt.h> 42c6fd2807SJeff Garzik #include <linux/sched.h> 43c6fd2807SJeff Garzik #include <linux/dma-mapping.h> 44c6fd2807SJeff Garzik #include <linux/device.h> 45c6fd2807SJeff Garzik #include <scsi/scsi_host.h> 46c6fd2807SJeff Garzik #include <scsi/scsi_cmnd.h> 47c6fd2807SJeff Garzik #include <linux/libata.h> 48c6fd2807SJeff Garzik #include <asm/io.h> 49c6fd2807SJeff Garzik 50c6fd2807SJeff Garzik #define DRV_NAME "ahci" 51c6fd2807SJeff Garzik #define DRV_VERSION "2.0" 52c6fd2807SJeff Garzik 53c6fd2807SJeff Garzik 54c6fd2807SJeff Garzik enum { 55c6fd2807SJeff Garzik AHCI_PCI_BAR = 5, 56c6fd2807SJeff Garzik AHCI_MAX_SG = 168, /* hardware max is 64K */ 57c6fd2807SJeff Garzik AHCI_DMA_BOUNDARY = 0xffffffff, 58c6fd2807SJeff Garzik AHCI_USE_CLUSTERING = 0, 59c6fd2807SJeff Garzik AHCI_MAX_CMDS = 32, 60c6fd2807SJeff Garzik AHCI_CMD_SZ = 32, 61c6fd2807SJeff Garzik AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ, 62c6fd2807SJeff Garzik AHCI_RX_FIS_SZ = 256, 63c6fd2807SJeff Garzik AHCI_CMD_TBL_CDB = 0x40, 64c6fd2807SJeff Garzik AHCI_CMD_TBL_HDR_SZ = 0x80, 65c6fd2807SJeff Garzik AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16), 66c6fd2807SJeff Garzik AHCI_CMD_TBL_AR_SZ = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS, 67c6fd2807SJeff Garzik AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + 68c6fd2807SJeff Garzik AHCI_RX_FIS_SZ, 69c6fd2807SJeff Garzik AHCI_IRQ_ON_SG = (1 << 31), 70c6fd2807SJeff Garzik AHCI_CMD_ATAPI = (1 << 5), 71c6fd2807SJeff Garzik AHCI_CMD_WRITE = (1 << 6), 72c6fd2807SJeff Garzik AHCI_CMD_PREFETCH = (1 << 7), 73c6fd2807SJeff Garzik AHCI_CMD_RESET = (1 << 8), 74c6fd2807SJeff Garzik AHCI_CMD_CLR_BUSY = (1 << 10), 75c6fd2807SJeff Garzik 76c6fd2807SJeff Garzik RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ 77c6fd2807SJeff Garzik RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ 78c6fd2807SJeff Garzik 79c6fd2807SJeff Garzik board_ahci = 0, 80c6fd2807SJeff Garzik board_ahci_vt8251 = 1, 81*41669553STejun Heo board_ahci_ign_iferr = 2, 82c6fd2807SJeff Garzik 83c6fd2807SJeff Garzik /* global controller registers */ 84c6fd2807SJeff Garzik HOST_CAP = 0x00, /* host capabilities */ 85c6fd2807SJeff Garzik HOST_CTL = 0x04, /* global host control */ 86c6fd2807SJeff Garzik HOST_IRQ_STAT = 0x08, /* interrupt status */ 87c6fd2807SJeff Garzik HOST_PORTS_IMPL = 0x0c, /* bitmap of implemented ports */ 88c6fd2807SJeff Garzik HOST_VERSION = 0x10, /* AHCI spec. version compliancy */ 89c6fd2807SJeff Garzik 90c6fd2807SJeff Garzik /* HOST_CTL bits */ 91c6fd2807SJeff Garzik HOST_RESET = (1 << 0), /* reset controller; self-clear */ 92c6fd2807SJeff Garzik HOST_IRQ_EN = (1 << 1), /* global IRQ enable */ 93c6fd2807SJeff Garzik HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ 94c6fd2807SJeff Garzik 95c6fd2807SJeff Garzik /* HOST_CAP bits */ 96c6fd2807SJeff Garzik HOST_CAP_SSC = (1 << 14), /* Slumber capable */ 97c6fd2807SJeff Garzik HOST_CAP_CLO = (1 << 24), /* Command List Override support */ 98c6fd2807SJeff Garzik HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ 99c6fd2807SJeff Garzik HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ 100c6fd2807SJeff Garzik HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ 101c6fd2807SJeff Garzik 102c6fd2807SJeff Garzik /* registers for each SATA port */ 103c6fd2807SJeff Garzik PORT_LST_ADDR = 0x00, /* command list DMA addr */ 104c6fd2807SJeff Garzik PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */ 105c6fd2807SJeff Garzik PORT_FIS_ADDR = 0x08, /* FIS rx buf addr */ 106c6fd2807SJeff Garzik PORT_FIS_ADDR_HI = 0x0c, /* FIS rx buf addr hi */ 107c6fd2807SJeff Garzik PORT_IRQ_STAT = 0x10, /* interrupt status */ 108c6fd2807SJeff Garzik PORT_IRQ_MASK = 0x14, /* interrupt enable/disable mask */ 109c6fd2807SJeff Garzik PORT_CMD = 0x18, /* port command */ 110c6fd2807SJeff Garzik PORT_TFDATA = 0x20, /* taskfile data */ 111c6fd2807SJeff Garzik PORT_SIG = 0x24, /* device TF signature */ 112c6fd2807SJeff Garzik PORT_CMD_ISSUE = 0x38, /* command issue */ 113c6fd2807SJeff Garzik PORT_SCR = 0x28, /* SATA phy register block */ 114c6fd2807SJeff Garzik PORT_SCR_STAT = 0x28, /* SATA phy register: SStatus */ 115c6fd2807SJeff Garzik PORT_SCR_CTL = 0x2c, /* SATA phy register: SControl */ 116c6fd2807SJeff Garzik PORT_SCR_ERR = 0x30, /* SATA phy register: SError */ 117c6fd2807SJeff Garzik PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */ 118c6fd2807SJeff Garzik 119c6fd2807SJeff Garzik /* PORT_IRQ_{STAT,MASK} bits */ 120c6fd2807SJeff Garzik PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */ 121c6fd2807SJeff Garzik PORT_IRQ_TF_ERR = (1 << 30), /* task file error */ 122c6fd2807SJeff Garzik PORT_IRQ_HBUS_ERR = (1 << 29), /* host bus fatal error */ 123c6fd2807SJeff Garzik PORT_IRQ_HBUS_DATA_ERR = (1 << 28), /* host bus data error */ 124c6fd2807SJeff Garzik PORT_IRQ_IF_ERR = (1 << 27), /* interface fatal error */ 125c6fd2807SJeff Garzik PORT_IRQ_IF_NONFATAL = (1 << 26), /* interface non-fatal error */ 126c6fd2807SJeff Garzik PORT_IRQ_OVERFLOW = (1 << 24), /* xfer exhausted available S/G */ 127c6fd2807SJeff Garzik PORT_IRQ_BAD_PMP = (1 << 23), /* incorrect port multiplier */ 128c6fd2807SJeff Garzik 129c6fd2807SJeff Garzik PORT_IRQ_PHYRDY = (1 << 22), /* PhyRdy changed */ 130c6fd2807SJeff Garzik PORT_IRQ_DEV_ILCK = (1 << 7), /* device interlock */ 131c6fd2807SJeff Garzik PORT_IRQ_CONNECT = (1 << 6), /* port connect change status */ 132c6fd2807SJeff Garzik PORT_IRQ_SG_DONE = (1 << 5), /* descriptor processed */ 133c6fd2807SJeff Garzik PORT_IRQ_UNK_FIS = (1 << 4), /* unknown FIS rx'd */ 134c6fd2807SJeff Garzik PORT_IRQ_SDB_FIS = (1 << 3), /* Set Device Bits FIS rx'd */ 135c6fd2807SJeff Garzik PORT_IRQ_DMAS_FIS = (1 << 2), /* DMA Setup FIS rx'd */ 136c6fd2807SJeff Garzik PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */ 137c6fd2807SJeff Garzik PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */ 138c6fd2807SJeff Garzik 139c6fd2807SJeff Garzik PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR | 140c6fd2807SJeff Garzik PORT_IRQ_IF_ERR | 141c6fd2807SJeff Garzik PORT_IRQ_CONNECT | 142c6fd2807SJeff Garzik PORT_IRQ_PHYRDY | 143c6fd2807SJeff Garzik PORT_IRQ_UNK_FIS, 144c6fd2807SJeff Garzik PORT_IRQ_ERROR = PORT_IRQ_FREEZE | 145c6fd2807SJeff Garzik PORT_IRQ_TF_ERR | 146c6fd2807SJeff Garzik PORT_IRQ_HBUS_DATA_ERR, 147c6fd2807SJeff Garzik DEF_PORT_IRQ = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | 148c6fd2807SJeff Garzik PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | 149c6fd2807SJeff Garzik PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS, 150c6fd2807SJeff Garzik 151c6fd2807SJeff Garzik /* PORT_CMD bits */ 152c6fd2807SJeff Garzik PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ 153c6fd2807SJeff Garzik PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ 154c6fd2807SJeff Garzik PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ 155c6fd2807SJeff Garzik PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */ 156c6fd2807SJeff Garzik PORT_CMD_CLO = (1 << 3), /* Command list override */ 157c6fd2807SJeff Garzik PORT_CMD_POWER_ON = (1 << 2), /* Power up device */ 158c6fd2807SJeff Garzik PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */ 159c6fd2807SJeff Garzik PORT_CMD_START = (1 << 0), /* Enable port DMA engine */ 160c6fd2807SJeff Garzik 161c6fd2807SJeff Garzik PORT_CMD_ICC_MASK = (0xf << 28), /* i/f ICC state mask */ 162c6fd2807SJeff Garzik PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */ 163c6fd2807SJeff Garzik PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */ 164c6fd2807SJeff Garzik PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */ 165c6fd2807SJeff Garzik 166c6fd2807SJeff Garzik /* hpriv->flags bits */ 167c6fd2807SJeff Garzik AHCI_FLAG_MSI = (1 << 0), 168c6fd2807SJeff Garzik 169c6fd2807SJeff Garzik /* ap->flags bits */ 170c6fd2807SJeff Garzik AHCI_FLAG_RESET_NEEDS_CLO = (1 << 24), 171c6fd2807SJeff Garzik AHCI_FLAG_NO_NCQ = (1 << 25), 172*41669553STejun Heo AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 26), /* ignore IRQ_IF_ERR */ 173c6fd2807SJeff Garzik }; 174c6fd2807SJeff Garzik 175c6fd2807SJeff Garzik struct ahci_cmd_hdr { 176c6fd2807SJeff Garzik u32 opts; 177c6fd2807SJeff Garzik u32 status; 178c6fd2807SJeff Garzik u32 tbl_addr; 179c6fd2807SJeff Garzik u32 tbl_addr_hi; 180c6fd2807SJeff Garzik u32 reserved[4]; 181c6fd2807SJeff Garzik }; 182c6fd2807SJeff Garzik 183c6fd2807SJeff Garzik struct ahci_sg { 184c6fd2807SJeff Garzik u32 addr; 185c6fd2807SJeff Garzik u32 addr_hi; 186c6fd2807SJeff Garzik u32 reserved; 187c6fd2807SJeff Garzik u32 flags_size; 188c6fd2807SJeff Garzik }; 189c6fd2807SJeff Garzik 190c6fd2807SJeff Garzik struct ahci_host_priv { 191c6fd2807SJeff Garzik unsigned long flags; 192c6fd2807SJeff Garzik u32 cap; /* cache of HOST_CAP register */ 193c6fd2807SJeff Garzik u32 port_map; /* cache of HOST_PORTS_IMPL reg */ 194c6fd2807SJeff Garzik }; 195c6fd2807SJeff Garzik 196c6fd2807SJeff Garzik struct ahci_port_priv { 197c6fd2807SJeff Garzik struct ahci_cmd_hdr *cmd_slot; 198c6fd2807SJeff Garzik dma_addr_t cmd_slot_dma; 199c6fd2807SJeff Garzik void *cmd_tbl; 200c6fd2807SJeff Garzik dma_addr_t cmd_tbl_dma; 201c6fd2807SJeff Garzik void *rx_fis; 202c6fd2807SJeff Garzik dma_addr_t rx_fis_dma; 203c6fd2807SJeff Garzik }; 204c6fd2807SJeff Garzik 205c6fd2807SJeff Garzik static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg); 206c6fd2807SJeff Garzik static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); 207c6fd2807SJeff Garzik static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); 208c6fd2807SJeff Garzik static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); 2097d12e780SDavid Howells static irqreturn_t ahci_interrupt (int irq, void *dev_instance); 210c6fd2807SJeff Garzik static void ahci_irq_clear(struct ata_port *ap); 211c6fd2807SJeff Garzik static int ahci_port_start(struct ata_port *ap); 212c6fd2807SJeff Garzik static void ahci_port_stop(struct ata_port *ap); 213c6fd2807SJeff Garzik static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf); 214c6fd2807SJeff Garzik static void ahci_qc_prep(struct ata_queued_cmd *qc); 215c6fd2807SJeff Garzik static u8 ahci_check_status(struct ata_port *ap); 216c6fd2807SJeff Garzik static void ahci_freeze(struct ata_port *ap); 217c6fd2807SJeff Garzik static void ahci_thaw(struct ata_port *ap); 218c6fd2807SJeff Garzik static void ahci_error_handler(struct ata_port *ap); 219c6fd2807SJeff Garzik static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); 220c6fd2807SJeff Garzik static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg); 221c6fd2807SJeff Garzik static int ahci_port_resume(struct ata_port *ap); 222c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); 223c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev); 224c6fd2807SJeff Garzik static void ahci_remove_one (struct pci_dev *pdev); 225c6fd2807SJeff Garzik 226c6fd2807SJeff Garzik static struct scsi_host_template ahci_sht = { 227c6fd2807SJeff Garzik .module = THIS_MODULE, 228c6fd2807SJeff Garzik .name = DRV_NAME, 229c6fd2807SJeff Garzik .ioctl = ata_scsi_ioctl, 230c6fd2807SJeff Garzik .queuecommand = ata_scsi_queuecmd, 231c6fd2807SJeff Garzik .change_queue_depth = ata_scsi_change_queue_depth, 232c6fd2807SJeff Garzik .can_queue = AHCI_MAX_CMDS - 1, 233c6fd2807SJeff Garzik .this_id = ATA_SHT_THIS_ID, 234c6fd2807SJeff Garzik .sg_tablesize = AHCI_MAX_SG, 235c6fd2807SJeff Garzik .cmd_per_lun = ATA_SHT_CMD_PER_LUN, 236c6fd2807SJeff Garzik .emulated = ATA_SHT_EMULATED, 237c6fd2807SJeff Garzik .use_clustering = AHCI_USE_CLUSTERING, 238c6fd2807SJeff Garzik .proc_name = DRV_NAME, 239c6fd2807SJeff Garzik .dma_boundary = AHCI_DMA_BOUNDARY, 240c6fd2807SJeff Garzik .slave_configure = ata_scsi_slave_config, 241c6fd2807SJeff Garzik .slave_destroy = ata_scsi_slave_destroy, 242c6fd2807SJeff Garzik .bios_param = ata_std_bios_param, 243c6fd2807SJeff Garzik .suspend = ata_scsi_device_suspend, 244c6fd2807SJeff Garzik .resume = ata_scsi_device_resume, 245c6fd2807SJeff Garzik }; 246c6fd2807SJeff Garzik 247c6fd2807SJeff Garzik static const struct ata_port_operations ahci_ops = { 248c6fd2807SJeff Garzik .port_disable = ata_port_disable, 249c6fd2807SJeff Garzik 250c6fd2807SJeff Garzik .check_status = ahci_check_status, 251c6fd2807SJeff Garzik .check_altstatus = ahci_check_status, 252c6fd2807SJeff Garzik .dev_select = ata_noop_dev_select, 253c6fd2807SJeff Garzik 254c6fd2807SJeff Garzik .tf_read = ahci_tf_read, 255c6fd2807SJeff Garzik 256c6fd2807SJeff Garzik .qc_prep = ahci_qc_prep, 257c6fd2807SJeff Garzik .qc_issue = ahci_qc_issue, 258c6fd2807SJeff Garzik 259c6fd2807SJeff Garzik .irq_handler = ahci_interrupt, 260c6fd2807SJeff Garzik .irq_clear = ahci_irq_clear, 261c6fd2807SJeff Garzik 262c6fd2807SJeff Garzik .scr_read = ahci_scr_read, 263c6fd2807SJeff Garzik .scr_write = ahci_scr_write, 264c6fd2807SJeff Garzik 265c6fd2807SJeff Garzik .freeze = ahci_freeze, 266c6fd2807SJeff Garzik .thaw = ahci_thaw, 267c6fd2807SJeff Garzik 268c6fd2807SJeff Garzik .error_handler = ahci_error_handler, 269c6fd2807SJeff Garzik .post_internal_cmd = ahci_post_internal_cmd, 270c6fd2807SJeff Garzik 271c6fd2807SJeff Garzik .port_suspend = ahci_port_suspend, 272c6fd2807SJeff Garzik .port_resume = ahci_port_resume, 273c6fd2807SJeff Garzik 274c6fd2807SJeff Garzik .port_start = ahci_port_start, 275c6fd2807SJeff Garzik .port_stop = ahci_port_stop, 276c6fd2807SJeff Garzik }; 277c6fd2807SJeff Garzik 278c6fd2807SJeff Garzik static const struct ata_port_info ahci_port_info[] = { 279c6fd2807SJeff Garzik /* board_ahci */ 280c6fd2807SJeff Garzik { 281c6fd2807SJeff Garzik .sht = &ahci_sht, 282cca3974eSJeff Garzik .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 283c6fd2807SJeff Garzik ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | 284c6fd2807SJeff Garzik ATA_FLAG_SKIP_D2H_BSY, 285c6fd2807SJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 286c6fd2807SJeff Garzik .udma_mask = 0x7f, /* udma0-6 ; FIXME */ 287c6fd2807SJeff Garzik .port_ops = &ahci_ops, 288c6fd2807SJeff Garzik }, 289c6fd2807SJeff Garzik /* board_ahci_vt8251 */ 290c6fd2807SJeff Garzik { 291c6fd2807SJeff Garzik .sht = &ahci_sht, 292cca3974eSJeff Garzik .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 293c6fd2807SJeff Garzik ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | 294c6fd2807SJeff Garzik ATA_FLAG_SKIP_D2H_BSY | 295c6fd2807SJeff Garzik AHCI_FLAG_RESET_NEEDS_CLO | AHCI_FLAG_NO_NCQ, 296c6fd2807SJeff Garzik .pio_mask = 0x1f, /* pio0-4 */ 297c6fd2807SJeff Garzik .udma_mask = 0x7f, /* udma0-6 ; FIXME */ 298c6fd2807SJeff Garzik .port_ops = &ahci_ops, 299c6fd2807SJeff Garzik }, 300*41669553STejun Heo /* board_ahci_ign_iferr */ 301*41669553STejun Heo { 302*41669553STejun Heo .sht = &ahci_sht, 303*41669553STejun Heo .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 304*41669553STejun Heo ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | 305*41669553STejun Heo ATA_FLAG_SKIP_D2H_BSY | 306*41669553STejun Heo AHCI_FLAG_IGN_IRQ_IF_ERR, 307*41669553STejun Heo .pio_mask = 0x1f, /* pio0-4 */ 308*41669553STejun Heo .udma_mask = 0x7f, /* udma0-6 ; FIXME */ 309*41669553STejun Heo .port_ops = &ahci_ops, 310*41669553STejun Heo }, 311c6fd2807SJeff Garzik }; 312c6fd2807SJeff Garzik 313c6fd2807SJeff Garzik static const struct pci_device_id ahci_pci_tbl[] = { 314c6fd2807SJeff Garzik /* Intel */ 31554bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */ 31654bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */ 31754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ 31854bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ 31954bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ 32054bb3a94SJeff Garzik { PCI_VDEVICE(AL, 0x5288), board_ahci }, /* ULi M5288 */ 32154bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ 32254bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ 32354bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ 32454bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ 32554bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */ 32654bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */ 32754bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ 32854bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ 32954bb3a94SJeff Garzik { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ 330f33d625fSJason Gaston { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ 331f33d625fSJason Gaston { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ 332f33d625fSJason Gaston { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ 333f33d625fSJason Gaston { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ 334f33d625fSJason Gaston { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ 335f33d625fSJason Gaston { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */ 336f33d625fSJason Gaston { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */ 337f33d625fSJason Gaston { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */ 338f33d625fSJason Gaston { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */ 339f33d625fSJason Gaston { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ 340f33d625fSJason Gaston { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ 341c6fd2807SJeff Garzik 342c6fd2807SJeff Garzik /* JMicron */ 343*41669553STejun Heo { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */ 344*41669553STejun Heo { PCI_VDEVICE(JMICRON, 0x2361), board_ahci_ign_iferr }, /* JMB361 */ 345*41669553STejun Heo { PCI_VDEVICE(JMICRON, 0x2363), board_ahci_ign_iferr }, /* JMB363 */ 346*41669553STejun Heo { PCI_VDEVICE(JMICRON, 0x2365), board_ahci_ign_iferr }, /* JMB365 */ 347*41669553STejun Heo { PCI_VDEVICE(JMICRON, 0x2366), board_ahci_ign_iferr }, /* JMB366 */ 348c6fd2807SJeff Garzik 349c6fd2807SJeff Garzik /* ATI */ 35054bb3a94SJeff Garzik { PCI_VDEVICE(ATI, 0x4380), board_ahci }, /* ATI SB600 non-raid */ 35154bb3a94SJeff Garzik { PCI_VDEVICE(ATI, 0x4381), board_ahci }, /* ATI SB600 raid */ 352c6fd2807SJeff Garzik 353c6fd2807SJeff Garzik /* VIA */ 35454bb3a94SJeff Garzik { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ 355c6fd2807SJeff Garzik 356c6fd2807SJeff Garzik /* NVIDIA */ 35754bb3a94SJeff Garzik { PCI_VDEVICE(NVIDIA, 0x044c), board_ahci }, /* MCP65 */ 35854bb3a94SJeff Garzik { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci }, /* MCP65 */ 35954bb3a94SJeff Garzik { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci }, /* MCP65 */ 36054bb3a94SJeff Garzik { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci }, /* MCP65 */ 361895663cdSPeer Chen { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci }, /* MCP67 */ 362895663cdSPeer Chen { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci }, /* MCP67 */ 363895663cdSPeer Chen { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci }, /* MCP67 */ 364895663cdSPeer Chen { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci }, /* MCP67 */ 365895663cdSPeer Chen { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci }, /* MCP67 */ 366895663cdSPeer Chen { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci }, /* MCP67 */ 367895663cdSPeer Chen { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci }, /* MCP67 */ 368895663cdSPeer Chen { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci }, /* MCP67 */ 369c6fd2807SJeff Garzik 370c6fd2807SJeff Garzik /* SiS */ 37154bb3a94SJeff Garzik { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ 37254bb3a94SJeff Garzik { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */ 37354bb3a94SJeff Garzik { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ 374c6fd2807SJeff Garzik 375c6fd2807SJeff Garzik { } /* terminate list */ 376c6fd2807SJeff Garzik }; 377c6fd2807SJeff Garzik 378c6fd2807SJeff Garzik 379c6fd2807SJeff Garzik static struct pci_driver ahci_pci_driver = { 380c6fd2807SJeff Garzik .name = DRV_NAME, 381c6fd2807SJeff Garzik .id_table = ahci_pci_tbl, 382c6fd2807SJeff Garzik .probe = ahci_init_one, 383c6fd2807SJeff Garzik .suspend = ahci_pci_device_suspend, 384c6fd2807SJeff Garzik .resume = ahci_pci_device_resume, 385c6fd2807SJeff Garzik .remove = ahci_remove_one, 386c6fd2807SJeff Garzik }; 387c6fd2807SJeff Garzik 388c6fd2807SJeff Garzik 389c6fd2807SJeff Garzik static inline unsigned long ahci_port_base_ul (unsigned long base, unsigned int port) 390c6fd2807SJeff Garzik { 391c6fd2807SJeff Garzik return base + 0x100 + (port * 0x80); 392c6fd2807SJeff Garzik } 393c6fd2807SJeff Garzik 394c6fd2807SJeff Garzik static inline void __iomem *ahci_port_base (void __iomem *base, unsigned int port) 395c6fd2807SJeff Garzik { 396c6fd2807SJeff Garzik return (void __iomem *) ahci_port_base_ul((unsigned long)base, port); 397c6fd2807SJeff Garzik } 398c6fd2807SJeff Garzik 399c6fd2807SJeff Garzik static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in) 400c6fd2807SJeff Garzik { 401c6fd2807SJeff Garzik unsigned int sc_reg; 402c6fd2807SJeff Garzik 403c6fd2807SJeff Garzik switch (sc_reg_in) { 404c6fd2807SJeff Garzik case SCR_STATUS: sc_reg = 0; break; 405c6fd2807SJeff Garzik case SCR_CONTROL: sc_reg = 1; break; 406c6fd2807SJeff Garzik case SCR_ERROR: sc_reg = 2; break; 407c6fd2807SJeff Garzik case SCR_ACTIVE: sc_reg = 3; break; 408c6fd2807SJeff Garzik default: 409c6fd2807SJeff Garzik return 0xffffffffU; 410c6fd2807SJeff Garzik } 411c6fd2807SJeff Garzik 412c6fd2807SJeff Garzik return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); 413c6fd2807SJeff Garzik } 414c6fd2807SJeff Garzik 415c6fd2807SJeff Garzik 416c6fd2807SJeff Garzik static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in, 417c6fd2807SJeff Garzik u32 val) 418c6fd2807SJeff Garzik { 419c6fd2807SJeff Garzik unsigned int sc_reg; 420c6fd2807SJeff Garzik 421c6fd2807SJeff Garzik switch (sc_reg_in) { 422c6fd2807SJeff Garzik case SCR_STATUS: sc_reg = 0; break; 423c6fd2807SJeff Garzik case SCR_CONTROL: sc_reg = 1; break; 424c6fd2807SJeff Garzik case SCR_ERROR: sc_reg = 2; break; 425c6fd2807SJeff Garzik case SCR_ACTIVE: sc_reg = 3; break; 426c6fd2807SJeff Garzik default: 427c6fd2807SJeff Garzik return; 428c6fd2807SJeff Garzik } 429c6fd2807SJeff Garzik 430c6fd2807SJeff Garzik writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); 431c6fd2807SJeff Garzik } 432c6fd2807SJeff Garzik 433c6fd2807SJeff Garzik static void ahci_start_engine(void __iomem *port_mmio) 434c6fd2807SJeff Garzik { 435c6fd2807SJeff Garzik u32 tmp; 436c6fd2807SJeff Garzik 437c6fd2807SJeff Garzik /* start DMA */ 438c6fd2807SJeff Garzik tmp = readl(port_mmio + PORT_CMD); 439c6fd2807SJeff Garzik tmp |= PORT_CMD_START; 440c6fd2807SJeff Garzik writel(tmp, port_mmio + PORT_CMD); 441c6fd2807SJeff Garzik readl(port_mmio + PORT_CMD); /* flush */ 442c6fd2807SJeff Garzik } 443c6fd2807SJeff Garzik 444c6fd2807SJeff Garzik static int ahci_stop_engine(void __iomem *port_mmio) 445c6fd2807SJeff Garzik { 446c6fd2807SJeff Garzik u32 tmp; 447c6fd2807SJeff Garzik 448c6fd2807SJeff Garzik tmp = readl(port_mmio + PORT_CMD); 449c6fd2807SJeff Garzik 450c6fd2807SJeff Garzik /* check if the HBA is idle */ 451c6fd2807SJeff Garzik if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0) 452c6fd2807SJeff Garzik return 0; 453c6fd2807SJeff Garzik 454c6fd2807SJeff Garzik /* setting HBA to idle */ 455c6fd2807SJeff Garzik tmp &= ~PORT_CMD_START; 456c6fd2807SJeff Garzik writel(tmp, port_mmio + PORT_CMD); 457c6fd2807SJeff Garzik 458c6fd2807SJeff Garzik /* wait for engine to stop. This could be as long as 500 msec */ 459c6fd2807SJeff Garzik tmp = ata_wait_register(port_mmio + PORT_CMD, 460c6fd2807SJeff Garzik PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500); 461c6fd2807SJeff Garzik if (tmp & PORT_CMD_LIST_ON) 462c6fd2807SJeff Garzik return -EIO; 463c6fd2807SJeff Garzik 464c6fd2807SJeff Garzik return 0; 465c6fd2807SJeff Garzik } 466c6fd2807SJeff Garzik 467c6fd2807SJeff Garzik static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap, 468c6fd2807SJeff Garzik dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma) 469c6fd2807SJeff Garzik { 470c6fd2807SJeff Garzik u32 tmp; 471c6fd2807SJeff Garzik 472c6fd2807SJeff Garzik /* set FIS registers */ 473c6fd2807SJeff Garzik if (cap & HOST_CAP_64) 474c6fd2807SJeff Garzik writel((cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI); 475c6fd2807SJeff Garzik writel(cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR); 476c6fd2807SJeff Garzik 477c6fd2807SJeff Garzik if (cap & HOST_CAP_64) 478c6fd2807SJeff Garzik writel((rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI); 479c6fd2807SJeff Garzik writel(rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR); 480c6fd2807SJeff Garzik 481c6fd2807SJeff Garzik /* enable FIS reception */ 482c6fd2807SJeff Garzik tmp = readl(port_mmio + PORT_CMD); 483c6fd2807SJeff Garzik tmp |= PORT_CMD_FIS_RX; 484c6fd2807SJeff Garzik writel(tmp, port_mmio + PORT_CMD); 485c6fd2807SJeff Garzik 486c6fd2807SJeff Garzik /* flush */ 487c6fd2807SJeff Garzik readl(port_mmio + PORT_CMD); 488c6fd2807SJeff Garzik } 489c6fd2807SJeff Garzik 490c6fd2807SJeff Garzik static int ahci_stop_fis_rx(void __iomem *port_mmio) 491c6fd2807SJeff Garzik { 492c6fd2807SJeff Garzik u32 tmp; 493c6fd2807SJeff Garzik 494c6fd2807SJeff Garzik /* disable FIS reception */ 495c6fd2807SJeff Garzik tmp = readl(port_mmio + PORT_CMD); 496c6fd2807SJeff Garzik tmp &= ~PORT_CMD_FIS_RX; 497c6fd2807SJeff Garzik writel(tmp, port_mmio + PORT_CMD); 498c6fd2807SJeff Garzik 499c6fd2807SJeff Garzik /* wait for completion, spec says 500ms, give it 1000 */ 500c6fd2807SJeff Garzik tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON, 501c6fd2807SJeff Garzik PORT_CMD_FIS_ON, 10, 1000); 502c6fd2807SJeff Garzik if (tmp & PORT_CMD_FIS_ON) 503c6fd2807SJeff Garzik return -EBUSY; 504c6fd2807SJeff Garzik 505c6fd2807SJeff Garzik return 0; 506c6fd2807SJeff Garzik } 507c6fd2807SJeff Garzik 508c6fd2807SJeff Garzik static void ahci_power_up(void __iomem *port_mmio, u32 cap) 509c6fd2807SJeff Garzik { 510c6fd2807SJeff Garzik u32 cmd; 511c6fd2807SJeff Garzik 512c6fd2807SJeff Garzik cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK; 513c6fd2807SJeff Garzik 514c6fd2807SJeff Garzik /* spin up device */ 515c6fd2807SJeff Garzik if (cap & HOST_CAP_SSS) { 516c6fd2807SJeff Garzik cmd |= PORT_CMD_SPIN_UP; 517c6fd2807SJeff Garzik writel(cmd, port_mmio + PORT_CMD); 518c6fd2807SJeff Garzik } 519c6fd2807SJeff Garzik 520c6fd2807SJeff Garzik /* wake up link */ 521c6fd2807SJeff Garzik writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD); 522c6fd2807SJeff Garzik } 523c6fd2807SJeff Garzik 524c6fd2807SJeff Garzik static void ahci_power_down(void __iomem *port_mmio, u32 cap) 525c6fd2807SJeff Garzik { 526c6fd2807SJeff Garzik u32 cmd, scontrol; 527c6fd2807SJeff Garzik 528c6fd2807SJeff Garzik cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK; 529c6fd2807SJeff Garzik 530c6fd2807SJeff Garzik if (cap & HOST_CAP_SSC) { 531c6fd2807SJeff Garzik /* enable transitions to slumber mode */ 532c6fd2807SJeff Garzik scontrol = readl(port_mmio + PORT_SCR_CTL); 533c6fd2807SJeff Garzik if ((scontrol & 0x0f00) > 0x100) { 534c6fd2807SJeff Garzik scontrol &= ~0xf00; 535c6fd2807SJeff Garzik writel(scontrol, port_mmio + PORT_SCR_CTL); 536c6fd2807SJeff Garzik } 537c6fd2807SJeff Garzik 538c6fd2807SJeff Garzik /* put device into slumber mode */ 539c6fd2807SJeff Garzik writel(cmd | PORT_CMD_ICC_SLUMBER, port_mmio + PORT_CMD); 540c6fd2807SJeff Garzik 541c6fd2807SJeff Garzik /* wait for the transition to complete */ 542c6fd2807SJeff Garzik ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_ICC_SLUMBER, 543c6fd2807SJeff Garzik PORT_CMD_ICC_SLUMBER, 1, 50); 544c6fd2807SJeff Garzik } 545c6fd2807SJeff Garzik 546c6fd2807SJeff Garzik /* put device into listen mode */ 547c6fd2807SJeff Garzik if (cap & HOST_CAP_SSS) { 548c6fd2807SJeff Garzik /* first set PxSCTL.DET to 0 */ 549c6fd2807SJeff Garzik scontrol = readl(port_mmio + PORT_SCR_CTL); 550c6fd2807SJeff Garzik scontrol &= ~0xf; 551c6fd2807SJeff Garzik writel(scontrol, port_mmio + PORT_SCR_CTL); 552c6fd2807SJeff Garzik 553c6fd2807SJeff Garzik /* then set PxCMD.SUD to 0 */ 554c6fd2807SJeff Garzik cmd &= ~PORT_CMD_SPIN_UP; 555c6fd2807SJeff Garzik writel(cmd, port_mmio + PORT_CMD); 556c6fd2807SJeff Garzik } 557c6fd2807SJeff Garzik } 558c6fd2807SJeff Garzik 559c6fd2807SJeff Garzik static void ahci_init_port(void __iomem *port_mmio, u32 cap, 560c6fd2807SJeff Garzik dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma) 561c6fd2807SJeff Garzik { 562c6fd2807SJeff Garzik /* power up */ 563c6fd2807SJeff Garzik ahci_power_up(port_mmio, cap); 564c6fd2807SJeff Garzik 565c6fd2807SJeff Garzik /* enable FIS reception */ 566c6fd2807SJeff Garzik ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma); 567c6fd2807SJeff Garzik 568c6fd2807SJeff Garzik /* enable DMA */ 569c6fd2807SJeff Garzik ahci_start_engine(port_mmio); 570c6fd2807SJeff Garzik } 571c6fd2807SJeff Garzik 572c6fd2807SJeff Garzik static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg) 573c6fd2807SJeff Garzik { 574c6fd2807SJeff Garzik int rc; 575c6fd2807SJeff Garzik 576c6fd2807SJeff Garzik /* disable DMA */ 577c6fd2807SJeff Garzik rc = ahci_stop_engine(port_mmio); 578c6fd2807SJeff Garzik if (rc) { 579c6fd2807SJeff Garzik *emsg = "failed to stop engine"; 580c6fd2807SJeff Garzik return rc; 581c6fd2807SJeff Garzik } 582c6fd2807SJeff Garzik 583c6fd2807SJeff Garzik /* disable FIS reception */ 584c6fd2807SJeff Garzik rc = ahci_stop_fis_rx(port_mmio); 585c6fd2807SJeff Garzik if (rc) { 586c6fd2807SJeff Garzik *emsg = "failed stop FIS RX"; 587c6fd2807SJeff Garzik return rc; 588c6fd2807SJeff Garzik } 589c6fd2807SJeff Garzik 590c6fd2807SJeff Garzik /* put device into slumber mode */ 591c6fd2807SJeff Garzik ahci_power_down(port_mmio, cap); 592c6fd2807SJeff Garzik 593c6fd2807SJeff Garzik return 0; 594c6fd2807SJeff Garzik } 595c6fd2807SJeff Garzik 596c6fd2807SJeff Garzik static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) 597c6fd2807SJeff Garzik { 598c6fd2807SJeff Garzik u32 cap_save, tmp; 599c6fd2807SJeff Garzik 600c6fd2807SJeff Garzik cap_save = readl(mmio + HOST_CAP); 601c6fd2807SJeff Garzik cap_save &= ( (1<<28) | (1<<17) ); 602c6fd2807SJeff Garzik cap_save |= (1 << 27); 603c6fd2807SJeff Garzik 604c6fd2807SJeff Garzik /* global controller reset */ 605c6fd2807SJeff Garzik tmp = readl(mmio + HOST_CTL); 606c6fd2807SJeff Garzik if ((tmp & HOST_RESET) == 0) { 607c6fd2807SJeff Garzik writel(tmp | HOST_RESET, mmio + HOST_CTL); 608c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 609c6fd2807SJeff Garzik } 610c6fd2807SJeff Garzik 611c6fd2807SJeff Garzik /* reset must complete within 1 second, or 612c6fd2807SJeff Garzik * the hardware should be considered fried. 613c6fd2807SJeff Garzik */ 614c6fd2807SJeff Garzik ssleep(1); 615c6fd2807SJeff Garzik 616c6fd2807SJeff Garzik tmp = readl(mmio + HOST_CTL); 617c6fd2807SJeff Garzik if (tmp & HOST_RESET) { 618c6fd2807SJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 619c6fd2807SJeff Garzik "controller reset failed (0x%x)\n", tmp); 620c6fd2807SJeff Garzik return -EIO; 621c6fd2807SJeff Garzik } 622c6fd2807SJeff Garzik 623c6fd2807SJeff Garzik writel(HOST_AHCI_EN, mmio + HOST_CTL); 624c6fd2807SJeff Garzik (void) readl(mmio + HOST_CTL); /* flush */ 625c6fd2807SJeff Garzik writel(cap_save, mmio + HOST_CAP); 626c6fd2807SJeff Garzik writel(0xf, mmio + HOST_PORTS_IMPL); 627c6fd2807SJeff Garzik (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ 628c6fd2807SJeff Garzik 629c6fd2807SJeff Garzik if (pdev->vendor == PCI_VENDOR_ID_INTEL) { 630c6fd2807SJeff Garzik u16 tmp16; 631c6fd2807SJeff Garzik 632c6fd2807SJeff Garzik /* configure PCS */ 633c6fd2807SJeff Garzik pci_read_config_word(pdev, 0x92, &tmp16); 634c6fd2807SJeff Garzik tmp16 |= 0xf; 635c6fd2807SJeff Garzik pci_write_config_word(pdev, 0x92, tmp16); 636c6fd2807SJeff Garzik } 637c6fd2807SJeff Garzik 638c6fd2807SJeff Garzik return 0; 639c6fd2807SJeff Garzik } 640c6fd2807SJeff Garzik 641c6fd2807SJeff Garzik static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev, 642c6fd2807SJeff Garzik int n_ports, u32 cap) 643c6fd2807SJeff Garzik { 644c6fd2807SJeff Garzik int i, rc; 645c6fd2807SJeff Garzik u32 tmp; 646c6fd2807SJeff Garzik 647c6fd2807SJeff Garzik for (i = 0; i < n_ports; i++) { 648c6fd2807SJeff Garzik void __iomem *port_mmio = ahci_port_base(mmio, i); 649c6fd2807SJeff Garzik const char *emsg = NULL; 650c6fd2807SJeff Garzik 651c6fd2807SJeff Garzik #if 0 /* BIOSen initialize this incorrectly */ 652c6fd2807SJeff Garzik if (!(hpriv->port_map & (1 << i))) 653c6fd2807SJeff Garzik continue; 654c6fd2807SJeff Garzik #endif 655c6fd2807SJeff Garzik 656c6fd2807SJeff Garzik /* make sure port is not active */ 657c6fd2807SJeff Garzik rc = ahci_deinit_port(port_mmio, cap, &emsg); 658c6fd2807SJeff Garzik if (rc) 659c6fd2807SJeff Garzik dev_printk(KERN_WARNING, &pdev->dev, 660c6fd2807SJeff Garzik "%s (%d)\n", emsg, rc); 661c6fd2807SJeff Garzik 662c6fd2807SJeff Garzik /* clear SError */ 663c6fd2807SJeff Garzik tmp = readl(port_mmio + PORT_SCR_ERR); 664c6fd2807SJeff Garzik VPRINTK("PORT_SCR_ERR 0x%x\n", tmp); 665c6fd2807SJeff Garzik writel(tmp, port_mmio + PORT_SCR_ERR); 666c6fd2807SJeff Garzik 667c6fd2807SJeff Garzik /* clear port IRQ */ 668c6fd2807SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 669c6fd2807SJeff Garzik VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); 670c6fd2807SJeff Garzik if (tmp) 671c6fd2807SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 672c6fd2807SJeff Garzik 673c6fd2807SJeff Garzik writel(1 << i, mmio + HOST_IRQ_STAT); 674c6fd2807SJeff Garzik } 675c6fd2807SJeff Garzik 676c6fd2807SJeff Garzik tmp = readl(mmio + HOST_CTL); 677c6fd2807SJeff Garzik VPRINTK("HOST_CTL 0x%x\n", tmp); 678c6fd2807SJeff Garzik writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL); 679c6fd2807SJeff Garzik tmp = readl(mmio + HOST_CTL); 680c6fd2807SJeff Garzik VPRINTK("HOST_CTL 0x%x\n", tmp); 681c6fd2807SJeff Garzik } 682c6fd2807SJeff Garzik 683c6fd2807SJeff Garzik static unsigned int ahci_dev_classify(struct ata_port *ap) 684c6fd2807SJeff Garzik { 685c6fd2807SJeff Garzik void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; 686c6fd2807SJeff Garzik struct ata_taskfile tf; 687c6fd2807SJeff Garzik u32 tmp; 688c6fd2807SJeff Garzik 689c6fd2807SJeff Garzik tmp = readl(port_mmio + PORT_SIG); 690c6fd2807SJeff Garzik tf.lbah = (tmp >> 24) & 0xff; 691c6fd2807SJeff Garzik tf.lbam = (tmp >> 16) & 0xff; 692c6fd2807SJeff Garzik tf.lbal = (tmp >> 8) & 0xff; 693c6fd2807SJeff Garzik tf.nsect = (tmp) & 0xff; 694c6fd2807SJeff Garzik 695c6fd2807SJeff Garzik return ata_dev_classify(&tf); 696c6fd2807SJeff Garzik } 697c6fd2807SJeff Garzik 698c6fd2807SJeff Garzik static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, 699c6fd2807SJeff Garzik u32 opts) 700c6fd2807SJeff Garzik { 701c6fd2807SJeff Garzik dma_addr_t cmd_tbl_dma; 702c6fd2807SJeff Garzik 703c6fd2807SJeff Garzik cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ; 704c6fd2807SJeff Garzik 705c6fd2807SJeff Garzik pp->cmd_slot[tag].opts = cpu_to_le32(opts); 706c6fd2807SJeff Garzik pp->cmd_slot[tag].status = 0; 707c6fd2807SJeff Garzik pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff); 708c6fd2807SJeff Garzik pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16); 709c6fd2807SJeff Garzik } 710c6fd2807SJeff Garzik 711c6fd2807SJeff Garzik static int ahci_clo(struct ata_port *ap) 712c6fd2807SJeff Garzik { 713c6fd2807SJeff Garzik void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; 714cca3974eSJeff Garzik struct ahci_host_priv *hpriv = ap->host->private_data; 715c6fd2807SJeff Garzik u32 tmp; 716c6fd2807SJeff Garzik 717c6fd2807SJeff Garzik if (!(hpriv->cap & HOST_CAP_CLO)) 718c6fd2807SJeff Garzik return -EOPNOTSUPP; 719c6fd2807SJeff Garzik 720c6fd2807SJeff Garzik tmp = readl(port_mmio + PORT_CMD); 721c6fd2807SJeff Garzik tmp |= PORT_CMD_CLO; 722c6fd2807SJeff Garzik writel(tmp, port_mmio + PORT_CMD); 723c6fd2807SJeff Garzik 724c6fd2807SJeff Garzik tmp = ata_wait_register(port_mmio + PORT_CMD, 725c6fd2807SJeff Garzik PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); 726c6fd2807SJeff Garzik if (tmp & PORT_CMD_CLO) 727c6fd2807SJeff Garzik return -EIO; 728c6fd2807SJeff Garzik 729c6fd2807SJeff Garzik return 0; 730c6fd2807SJeff Garzik } 731c6fd2807SJeff Garzik 732c6fd2807SJeff Garzik static int ahci_prereset(struct ata_port *ap) 733c6fd2807SJeff Garzik { 734c6fd2807SJeff Garzik if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) && 735c6fd2807SJeff Garzik (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) { 736c6fd2807SJeff Garzik /* ATA_BUSY hasn't cleared, so send a CLO */ 737c6fd2807SJeff Garzik ahci_clo(ap); 738c6fd2807SJeff Garzik } 739c6fd2807SJeff Garzik 740c6fd2807SJeff Garzik return ata_std_prereset(ap); 741c6fd2807SJeff Garzik } 742c6fd2807SJeff Garzik 743c6fd2807SJeff Garzik static int ahci_softreset(struct ata_port *ap, unsigned int *class) 744c6fd2807SJeff Garzik { 745c6fd2807SJeff Garzik struct ahci_port_priv *pp = ap->private_data; 746cca3974eSJeff Garzik void __iomem *mmio = ap->host->mmio_base; 747c6fd2807SJeff Garzik void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 748c6fd2807SJeff Garzik const u32 cmd_fis_len = 5; /* five dwords */ 749c6fd2807SJeff Garzik const char *reason = NULL; 750c6fd2807SJeff Garzik struct ata_taskfile tf; 751c6fd2807SJeff Garzik u32 tmp; 752c6fd2807SJeff Garzik u8 *fis; 753c6fd2807SJeff Garzik int rc; 754c6fd2807SJeff Garzik 755c6fd2807SJeff Garzik DPRINTK("ENTER\n"); 756c6fd2807SJeff Garzik 757c6fd2807SJeff Garzik if (ata_port_offline(ap)) { 758c6fd2807SJeff Garzik DPRINTK("PHY reports no device\n"); 759c6fd2807SJeff Garzik *class = ATA_DEV_NONE; 760c6fd2807SJeff Garzik return 0; 761c6fd2807SJeff Garzik } 762c6fd2807SJeff Garzik 763c6fd2807SJeff Garzik /* prepare for SRST (AHCI-1.1 10.4.1) */ 764c6fd2807SJeff Garzik rc = ahci_stop_engine(port_mmio); 765c6fd2807SJeff Garzik if (rc) { 766c6fd2807SJeff Garzik reason = "failed to stop engine"; 767c6fd2807SJeff Garzik goto fail_restart; 768c6fd2807SJeff Garzik } 769c6fd2807SJeff Garzik 770c6fd2807SJeff Garzik /* check BUSY/DRQ, perform Command List Override if necessary */ 7711244a19cSTejun Heo if (ahci_check_status(ap) & (ATA_BUSY | ATA_DRQ)) { 772c6fd2807SJeff Garzik rc = ahci_clo(ap); 773c6fd2807SJeff Garzik 774c6fd2807SJeff Garzik if (rc == -EOPNOTSUPP) { 775c6fd2807SJeff Garzik reason = "port busy but CLO unavailable"; 776c6fd2807SJeff Garzik goto fail_restart; 777c6fd2807SJeff Garzik } else if (rc) { 778c6fd2807SJeff Garzik reason = "port busy but CLO failed"; 779c6fd2807SJeff Garzik goto fail_restart; 780c6fd2807SJeff Garzik } 781c6fd2807SJeff Garzik } 782c6fd2807SJeff Garzik 783c6fd2807SJeff Garzik /* restart engine */ 784c6fd2807SJeff Garzik ahci_start_engine(port_mmio); 785c6fd2807SJeff Garzik 786c6fd2807SJeff Garzik ata_tf_init(ap->device, &tf); 787c6fd2807SJeff Garzik fis = pp->cmd_tbl; 788c6fd2807SJeff Garzik 789c6fd2807SJeff Garzik /* issue the first D2H Register FIS */ 790c6fd2807SJeff Garzik ahci_fill_cmd_slot(pp, 0, 791c6fd2807SJeff Garzik cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY); 792c6fd2807SJeff Garzik 793c6fd2807SJeff Garzik tf.ctl |= ATA_SRST; 794c6fd2807SJeff Garzik ata_tf_to_fis(&tf, fis, 0); 795c6fd2807SJeff Garzik fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ 796c6fd2807SJeff Garzik 797c6fd2807SJeff Garzik writel(1, port_mmio + PORT_CMD_ISSUE); 798c6fd2807SJeff Garzik 799c6fd2807SJeff Garzik tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, 1, 500); 800c6fd2807SJeff Garzik if (tmp & 0x1) { 801c6fd2807SJeff Garzik rc = -EIO; 802c6fd2807SJeff Garzik reason = "1st FIS failed"; 803c6fd2807SJeff Garzik goto fail; 804c6fd2807SJeff Garzik } 805c6fd2807SJeff Garzik 806c6fd2807SJeff Garzik /* spec says at least 5us, but be generous and sleep for 1ms */ 807c6fd2807SJeff Garzik msleep(1); 808c6fd2807SJeff Garzik 809c6fd2807SJeff Garzik /* issue the second D2H Register FIS */ 810c6fd2807SJeff Garzik ahci_fill_cmd_slot(pp, 0, cmd_fis_len); 811c6fd2807SJeff Garzik 812c6fd2807SJeff Garzik tf.ctl &= ~ATA_SRST; 813c6fd2807SJeff Garzik ata_tf_to_fis(&tf, fis, 0); 814c6fd2807SJeff Garzik fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ 815c6fd2807SJeff Garzik 816c6fd2807SJeff Garzik writel(1, port_mmio + PORT_CMD_ISSUE); 817c6fd2807SJeff Garzik readl(port_mmio + PORT_CMD_ISSUE); /* flush */ 818c6fd2807SJeff Garzik 819c6fd2807SJeff Garzik /* spec mandates ">= 2ms" before checking status. 820c6fd2807SJeff Garzik * We wait 150ms, because that was the magic delay used for 821c6fd2807SJeff Garzik * ATAPI devices in Hale Landis's ATADRVR, for the period of time 822c6fd2807SJeff Garzik * between when the ATA command register is written, and then 823c6fd2807SJeff Garzik * status is checked. Because waiting for "a while" before 824c6fd2807SJeff Garzik * checking status is fine, post SRST, we perform this magic 825c6fd2807SJeff Garzik * delay here as well. 826c6fd2807SJeff Garzik */ 827c6fd2807SJeff Garzik msleep(150); 828c6fd2807SJeff Garzik 829c6fd2807SJeff Garzik *class = ATA_DEV_NONE; 830c6fd2807SJeff Garzik if (ata_port_online(ap)) { 831c6fd2807SJeff Garzik if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { 832c6fd2807SJeff Garzik rc = -EIO; 833c6fd2807SJeff Garzik reason = "device not ready"; 834c6fd2807SJeff Garzik goto fail; 835c6fd2807SJeff Garzik } 836c6fd2807SJeff Garzik *class = ahci_dev_classify(ap); 837c6fd2807SJeff Garzik } 838c6fd2807SJeff Garzik 839c6fd2807SJeff Garzik DPRINTK("EXIT, class=%u\n", *class); 840c6fd2807SJeff Garzik return 0; 841c6fd2807SJeff Garzik 842c6fd2807SJeff Garzik fail_restart: 843c6fd2807SJeff Garzik ahci_start_engine(port_mmio); 844c6fd2807SJeff Garzik fail: 845c6fd2807SJeff Garzik ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); 846c6fd2807SJeff Garzik return rc; 847c6fd2807SJeff Garzik } 848c6fd2807SJeff Garzik 849c6fd2807SJeff Garzik static int ahci_hardreset(struct ata_port *ap, unsigned int *class) 850c6fd2807SJeff Garzik { 851c6fd2807SJeff Garzik struct ahci_port_priv *pp = ap->private_data; 852c6fd2807SJeff Garzik u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 853c6fd2807SJeff Garzik struct ata_taskfile tf; 854cca3974eSJeff Garzik void __iomem *mmio = ap->host->mmio_base; 855c6fd2807SJeff Garzik void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 856c6fd2807SJeff Garzik int rc; 857c6fd2807SJeff Garzik 858c6fd2807SJeff Garzik DPRINTK("ENTER\n"); 859c6fd2807SJeff Garzik 860c6fd2807SJeff Garzik ahci_stop_engine(port_mmio); 861c6fd2807SJeff Garzik 862c6fd2807SJeff Garzik /* clear D2H reception area to properly wait for D2H FIS */ 863c6fd2807SJeff Garzik ata_tf_init(ap->device, &tf); 864c6fd2807SJeff Garzik tf.command = 0xff; 865c6fd2807SJeff Garzik ata_tf_to_fis(&tf, d2h_fis, 0); 866c6fd2807SJeff Garzik 867c6fd2807SJeff Garzik rc = sata_std_hardreset(ap, class); 868c6fd2807SJeff Garzik 869c6fd2807SJeff Garzik ahci_start_engine(port_mmio); 870c6fd2807SJeff Garzik 871c6fd2807SJeff Garzik if (rc == 0 && ata_port_online(ap)) 872c6fd2807SJeff Garzik *class = ahci_dev_classify(ap); 873c6fd2807SJeff Garzik if (*class == ATA_DEV_UNKNOWN) 874c6fd2807SJeff Garzik *class = ATA_DEV_NONE; 875c6fd2807SJeff Garzik 876c6fd2807SJeff Garzik DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); 877c6fd2807SJeff Garzik return rc; 878c6fd2807SJeff Garzik } 879c6fd2807SJeff Garzik 880c6fd2807SJeff Garzik static void ahci_postreset(struct ata_port *ap, unsigned int *class) 881c6fd2807SJeff Garzik { 882c6fd2807SJeff Garzik void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; 883c6fd2807SJeff Garzik u32 new_tmp, tmp; 884c6fd2807SJeff Garzik 885c6fd2807SJeff Garzik ata_std_postreset(ap, class); 886c6fd2807SJeff Garzik 887c6fd2807SJeff Garzik /* Make sure port's ATAPI bit is set appropriately */ 888c6fd2807SJeff Garzik new_tmp = tmp = readl(port_mmio + PORT_CMD); 889c6fd2807SJeff Garzik if (*class == ATA_DEV_ATAPI) 890c6fd2807SJeff Garzik new_tmp |= PORT_CMD_ATAPI; 891c6fd2807SJeff Garzik else 892c6fd2807SJeff Garzik new_tmp &= ~PORT_CMD_ATAPI; 893c6fd2807SJeff Garzik if (new_tmp != tmp) { 894c6fd2807SJeff Garzik writel(new_tmp, port_mmio + PORT_CMD); 895c6fd2807SJeff Garzik readl(port_mmio + PORT_CMD); /* flush */ 896c6fd2807SJeff Garzik } 897c6fd2807SJeff Garzik } 898c6fd2807SJeff Garzik 899c6fd2807SJeff Garzik static u8 ahci_check_status(struct ata_port *ap) 900c6fd2807SJeff Garzik { 901c6fd2807SJeff Garzik void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; 902c6fd2807SJeff Garzik 903c6fd2807SJeff Garzik return readl(mmio + PORT_TFDATA) & 0xFF; 904c6fd2807SJeff Garzik } 905c6fd2807SJeff Garzik 906c6fd2807SJeff Garzik static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf) 907c6fd2807SJeff Garzik { 908c6fd2807SJeff Garzik struct ahci_port_priv *pp = ap->private_data; 909c6fd2807SJeff Garzik u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 910c6fd2807SJeff Garzik 911c6fd2807SJeff Garzik ata_tf_from_fis(d2h_fis, tf); 912c6fd2807SJeff Garzik } 913c6fd2807SJeff Garzik 914c6fd2807SJeff Garzik static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl) 915c6fd2807SJeff Garzik { 916c6fd2807SJeff Garzik struct scatterlist *sg; 917c6fd2807SJeff Garzik struct ahci_sg *ahci_sg; 918c6fd2807SJeff Garzik unsigned int n_sg = 0; 919c6fd2807SJeff Garzik 920c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 921c6fd2807SJeff Garzik 922c6fd2807SJeff Garzik /* 923c6fd2807SJeff Garzik * Next, the S/G list. 924c6fd2807SJeff Garzik */ 925c6fd2807SJeff Garzik ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ; 926c6fd2807SJeff Garzik ata_for_each_sg(sg, qc) { 927c6fd2807SJeff Garzik dma_addr_t addr = sg_dma_address(sg); 928c6fd2807SJeff Garzik u32 sg_len = sg_dma_len(sg); 929c6fd2807SJeff Garzik 930c6fd2807SJeff Garzik ahci_sg->addr = cpu_to_le32(addr & 0xffffffff); 931c6fd2807SJeff Garzik ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); 932c6fd2807SJeff Garzik ahci_sg->flags_size = cpu_to_le32(sg_len - 1); 933c6fd2807SJeff Garzik 934c6fd2807SJeff Garzik ahci_sg++; 935c6fd2807SJeff Garzik n_sg++; 936c6fd2807SJeff Garzik } 937c6fd2807SJeff Garzik 938c6fd2807SJeff Garzik return n_sg; 939c6fd2807SJeff Garzik } 940c6fd2807SJeff Garzik 941c6fd2807SJeff Garzik static void ahci_qc_prep(struct ata_queued_cmd *qc) 942c6fd2807SJeff Garzik { 943c6fd2807SJeff Garzik struct ata_port *ap = qc->ap; 944c6fd2807SJeff Garzik struct ahci_port_priv *pp = ap->private_data; 945c6fd2807SJeff Garzik int is_atapi = is_atapi_taskfile(&qc->tf); 946c6fd2807SJeff Garzik void *cmd_tbl; 947c6fd2807SJeff Garzik u32 opts; 948c6fd2807SJeff Garzik const u32 cmd_fis_len = 5; /* five dwords */ 949c6fd2807SJeff Garzik unsigned int n_elem; 950c6fd2807SJeff Garzik 951c6fd2807SJeff Garzik /* 952c6fd2807SJeff Garzik * Fill in command table information. First, the header, 953c6fd2807SJeff Garzik * a SATA Register - Host to Device command FIS. 954c6fd2807SJeff Garzik */ 955c6fd2807SJeff Garzik cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ; 956c6fd2807SJeff Garzik 957c6fd2807SJeff Garzik ata_tf_to_fis(&qc->tf, cmd_tbl, 0); 958c6fd2807SJeff Garzik if (is_atapi) { 959c6fd2807SJeff Garzik memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); 960c6fd2807SJeff Garzik memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len); 961c6fd2807SJeff Garzik } 962c6fd2807SJeff Garzik 963c6fd2807SJeff Garzik n_elem = 0; 964c6fd2807SJeff Garzik if (qc->flags & ATA_QCFLAG_DMAMAP) 965c6fd2807SJeff Garzik n_elem = ahci_fill_sg(qc, cmd_tbl); 966c6fd2807SJeff Garzik 967c6fd2807SJeff Garzik /* 968c6fd2807SJeff Garzik * Fill in command slot information. 969c6fd2807SJeff Garzik */ 970c6fd2807SJeff Garzik opts = cmd_fis_len | n_elem << 16; 971c6fd2807SJeff Garzik if (qc->tf.flags & ATA_TFLAG_WRITE) 972c6fd2807SJeff Garzik opts |= AHCI_CMD_WRITE; 973c6fd2807SJeff Garzik if (is_atapi) 974c6fd2807SJeff Garzik opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH; 975c6fd2807SJeff Garzik 976c6fd2807SJeff Garzik ahci_fill_cmd_slot(pp, qc->tag, opts); 977c6fd2807SJeff Garzik } 978c6fd2807SJeff Garzik 979c6fd2807SJeff Garzik static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) 980c6fd2807SJeff Garzik { 981c6fd2807SJeff Garzik struct ahci_port_priv *pp = ap->private_data; 982c6fd2807SJeff Garzik struct ata_eh_info *ehi = &ap->eh_info; 983c6fd2807SJeff Garzik unsigned int err_mask = 0, action = 0; 984c6fd2807SJeff Garzik struct ata_queued_cmd *qc; 985c6fd2807SJeff Garzik u32 serror; 986c6fd2807SJeff Garzik 987c6fd2807SJeff Garzik ata_ehi_clear_desc(ehi); 988c6fd2807SJeff Garzik 989c6fd2807SJeff Garzik /* AHCI needs SError cleared; otherwise, it might lock up */ 990c6fd2807SJeff Garzik serror = ahci_scr_read(ap, SCR_ERROR); 991c6fd2807SJeff Garzik ahci_scr_write(ap, SCR_ERROR, serror); 992c6fd2807SJeff Garzik 993c6fd2807SJeff Garzik /* analyze @irq_stat */ 994c6fd2807SJeff Garzik ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); 995c6fd2807SJeff Garzik 996*41669553STejun Heo /* some controllers set IRQ_IF_ERR on device errors, ignore it */ 997*41669553STejun Heo if (ap->flags & AHCI_FLAG_IGN_IRQ_IF_ERR) 998*41669553STejun Heo irq_stat &= ~PORT_IRQ_IF_ERR; 999*41669553STejun Heo 1000c6fd2807SJeff Garzik if (irq_stat & PORT_IRQ_TF_ERR) 1001c6fd2807SJeff Garzik err_mask |= AC_ERR_DEV; 1002c6fd2807SJeff Garzik 1003c6fd2807SJeff Garzik if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) { 1004c6fd2807SJeff Garzik err_mask |= AC_ERR_HOST_BUS; 1005c6fd2807SJeff Garzik action |= ATA_EH_SOFTRESET; 1006c6fd2807SJeff Garzik } 1007c6fd2807SJeff Garzik 1008c6fd2807SJeff Garzik if (irq_stat & PORT_IRQ_IF_ERR) { 1009c6fd2807SJeff Garzik err_mask |= AC_ERR_ATA_BUS; 1010c6fd2807SJeff Garzik action |= ATA_EH_SOFTRESET; 1011c6fd2807SJeff Garzik ata_ehi_push_desc(ehi, ", interface fatal error"); 1012c6fd2807SJeff Garzik } 1013c6fd2807SJeff Garzik 1014c6fd2807SJeff Garzik if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) { 1015c6fd2807SJeff Garzik ata_ehi_hotplugged(ehi); 1016c6fd2807SJeff Garzik ata_ehi_push_desc(ehi, ", %s", irq_stat & PORT_IRQ_CONNECT ? 1017c6fd2807SJeff Garzik "connection status changed" : "PHY RDY changed"); 1018c6fd2807SJeff Garzik } 1019c6fd2807SJeff Garzik 1020c6fd2807SJeff Garzik if (irq_stat & PORT_IRQ_UNK_FIS) { 1021c6fd2807SJeff Garzik u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK); 1022c6fd2807SJeff Garzik 1023c6fd2807SJeff Garzik err_mask |= AC_ERR_HSM; 1024c6fd2807SJeff Garzik action |= ATA_EH_SOFTRESET; 1025c6fd2807SJeff Garzik ata_ehi_push_desc(ehi, ", unknown FIS %08x %08x %08x %08x", 1026c6fd2807SJeff Garzik unk[0], unk[1], unk[2], unk[3]); 1027c6fd2807SJeff Garzik } 1028c6fd2807SJeff Garzik 1029c6fd2807SJeff Garzik /* okay, let's hand over to EH */ 1030c6fd2807SJeff Garzik ehi->serror |= serror; 1031c6fd2807SJeff Garzik ehi->action |= action; 1032c6fd2807SJeff Garzik 1033c6fd2807SJeff Garzik qc = ata_qc_from_tag(ap, ap->active_tag); 1034c6fd2807SJeff Garzik if (qc) 1035c6fd2807SJeff Garzik qc->err_mask |= err_mask; 1036c6fd2807SJeff Garzik else 1037c6fd2807SJeff Garzik ehi->err_mask |= err_mask; 1038c6fd2807SJeff Garzik 1039c6fd2807SJeff Garzik if (irq_stat & PORT_IRQ_FREEZE) 1040c6fd2807SJeff Garzik ata_port_freeze(ap); 1041c6fd2807SJeff Garzik else 1042c6fd2807SJeff Garzik ata_port_abort(ap); 1043c6fd2807SJeff Garzik } 1044c6fd2807SJeff Garzik 1045c6fd2807SJeff Garzik static void ahci_host_intr(struct ata_port *ap) 1046c6fd2807SJeff Garzik { 1047cca3974eSJeff Garzik void __iomem *mmio = ap->host->mmio_base; 1048c6fd2807SJeff Garzik void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 1049c6fd2807SJeff Garzik struct ata_eh_info *ehi = &ap->eh_info; 1050c6fd2807SJeff Garzik u32 status, qc_active; 1051c6fd2807SJeff Garzik int rc; 1052c6fd2807SJeff Garzik 1053c6fd2807SJeff Garzik status = readl(port_mmio + PORT_IRQ_STAT); 1054c6fd2807SJeff Garzik writel(status, port_mmio + PORT_IRQ_STAT); 1055c6fd2807SJeff Garzik 1056c6fd2807SJeff Garzik if (unlikely(status & PORT_IRQ_ERROR)) { 1057c6fd2807SJeff Garzik ahci_error_intr(ap, status); 1058c6fd2807SJeff Garzik return; 1059c6fd2807SJeff Garzik } 1060c6fd2807SJeff Garzik 1061c6fd2807SJeff Garzik if (ap->sactive) 1062c6fd2807SJeff Garzik qc_active = readl(port_mmio + PORT_SCR_ACT); 1063c6fd2807SJeff Garzik else 1064c6fd2807SJeff Garzik qc_active = readl(port_mmio + PORT_CMD_ISSUE); 1065c6fd2807SJeff Garzik 1066c6fd2807SJeff Garzik rc = ata_qc_complete_multiple(ap, qc_active, NULL); 1067c6fd2807SJeff Garzik if (rc > 0) 1068c6fd2807SJeff Garzik return; 1069c6fd2807SJeff Garzik if (rc < 0) { 1070c6fd2807SJeff Garzik ehi->err_mask |= AC_ERR_HSM; 1071c6fd2807SJeff Garzik ehi->action |= ATA_EH_SOFTRESET; 1072c6fd2807SJeff Garzik ata_port_freeze(ap); 1073c6fd2807SJeff Garzik return; 1074c6fd2807SJeff Garzik } 1075c6fd2807SJeff Garzik 1076c6fd2807SJeff Garzik /* hmmm... a spurious interupt */ 1077c6fd2807SJeff Garzik 1078c6fd2807SJeff Garzik /* some devices send D2H reg with I bit set during NCQ command phase */ 107912a87d36SAlan Cox if (ap->sactive && (status & PORT_IRQ_D2H_REG_FIS)) 1080c6fd2807SJeff Garzik return; 1081c6fd2807SJeff Garzik 1082c6fd2807SJeff Garzik /* ignore interim PIO setup fis interrupts */ 1083c6fd2807SJeff Garzik if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS)) 1084c6fd2807SJeff Garzik return; 1085c6fd2807SJeff Garzik 1086c6fd2807SJeff Garzik if (ata_ratelimit()) 1087c6fd2807SJeff Garzik ata_port_printk(ap, KERN_INFO, "spurious interrupt " 1088c6fd2807SJeff Garzik "(irq_stat 0x%x active_tag %d sactive 0x%x)\n", 1089c6fd2807SJeff Garzik status, ap->active_tag, ap->sactive); 1090c6fd2807SJeff Garzik } 1091c6fd2807SJeff Garzik 1092c6fd2807SJeff Garzik static void ahci_irq_clear(struct ata_port *ap) 1093c6fd2807SJeff Garzik { 1094c6fd2807SJeff Garzik /* TODO */ 1095c6fd2807SJeff Garzik } 1096c6fd2807SJeff Garzik 10977d12e780SDavid Howells static irqreturn_t ahci_interrupt(int irq, void *dev_instance) 1098c6fd2807SJeff Garzik { 1099cca3974eSJeff Garzik struct ata_host *host = dev_instance; 1100c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 1101c6fd2807SJeff Garzik unsigned int i, handled = 0; 1102c6fd2807SJeff Garzik void __iomem *mmio; 1103c6fd2807SJeff Garzik u32 irq_stat, irq_ack = 0; 1104c6fd2807SJeff Garzik 1105c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 1106c6fd2807SJeff Garzik 1107cca3974eSJeff Garzik hpriv = host->private_data; 1108cca3974eSJeff Garzik mmio = host->mmio_base; 1109c6fd2807SJeff Garzik 1110c6fd2807SJeff Garzik /* sigh. 0xffffffff is a valid return from h/w */ 1111c6fd2807SJeff Garzik irq_stat = readl(mmio + HOST_IRQ_STAT); 1112c6fd2807SJeff Garzik irq_stat &= hpriv->port_map; 1113c6fd2807SJeff Garzik if (!irq_stat) 1114c6fd2807SJeff Garzik return IRQ_NONE; 1115c6fd2807SJeff Garzik 1116cca3974eSJeff Garzik spin_lock(&host->lock); 1117c6fd2807SJeff Garzik 1118cca3974eSJeff Garzik for (i = 0; i < host->n_ports; i++) { 1119c6fd2807SJeff Garzik struct ata_port *ap; 1120c6fd2807SJeff Garzik 1121c6fd2807SJeff Garzik if (!(irq_stat & (1 << i))) 1122c6fd2807SJeff Garzik continue; 1123c6fd2807SJeff Garzik 1124cca3974eSJeff Garzik ap = host->ports[i]; 1125c6fd2807SJeff Garzik if (ap) { 1126c6fd2807SJeff Garzik ahci_host_intr(ap); 1127c6fd2807SJeff Garzik VPRINTK("port %u\n", i); 1128c6fd2807SJeff Garzik } else { 1129c6fd2807SJeff Garzik VPRINTK("port %u (no irq)\n", i); 1130c6fd2807SJeff Garzik if (ata_ratelimit()) 1131cca3974eSJeff Garzik dev_printk(KERN_WARNING, host->dev, 1132c6fd2807SJeff Garzik "interrupt on disabled port %u\n", i); 1133c6fd2807SJeff Garzik } 1134c6fd2807SJeff Garzik 1135c6fd2807SJeff Garzik irq_ack |= (1 << i); 1136c6fd2807SJeff Garzik } 1137c6fd2807SJeff Garzik 1138c6fd2807SJeff Garzik if (irq_ack) { 1139c6fd2807SJeff Garzik writel(irq_ack, mmio + HOST_IRQ_STAT); 1140c6fd2807SJeff Garzik handled = 1; 1141c6fd2807SJeff Garzik } 1142c6fd2807SJeff Garzik 1143cca3974eSJeff Garzik spin_unlock(&host->lock); 1144c6fd2807SJeff Garzik 1145c6fd2807SJeff Garzik VPRINTK("EXIT\n"); 1146c6fd2807SJeff Garzik 1147c6fd2807SJeff Garzik return IRQ_RETVAL(handled); 1148c6fd2807SJeff Garzik } 1149c6fd2807SJeff Garzik 1150c6fd2807SJeff Garzik static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) 1151c6fd2807SJeff Garzik { 1152c6fd2807SJeff Garzik struct ata_port *ap = qc->ap; 1153c6fd2807SJeff Garzik void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; 1154c6fd2807SJeff Garzik 1155c6fd2807SJeff Garzik if (qc->tf.protocol == ATA_PROT_NCQ) 1156c6fd2807SJeff Garzik writel(1 << qc->tag, port_mmio + PORT_SCR_ACT); 1157c6fd2807SJeff Garzik writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE); 1158c6fd2807SJeff Garzik readl(port_mmio + PORT_CMD_ISSUE); /* flush */ 1159c6fd2807SJeff Garzik 1160c6fd2807SJeff Garzik return 0; 1161c6fd2807SJeff Garzik } 1162c6fd2807SJeff Garzik 1163c6fd2807SJeff Garzik static void ahci_freeze(struct ata_port *ap) 1164c6fd2807SJeff Garzik { 1165cca3974eSJeff Garzik void __iomem *mmio = ap->host->mmio_base; 1166c6fd2807SJeff Garzik void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 1167c6fd2807SJeff Garzik 1168c6fd2807SJeff Garzik /* turn IRQ off */ 1169c6fd2807SJeff Garzik writel(0, port_mmio + PORT_IRQ_MASK); 1170c6fd2807SJeff Garzik } 1171c6fd2807SJeff Garzik 1172c6fd2807SJeff Garzik static void ahci_thaw(struct ata_port *ap) 1173c6fd2807SJeff Garzik { 1174cca3974eSJeff Garzik void __iomem *mmio = ap->host->mmio_base; 1175c6fd2807SJeff Garzik void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 1176c6fd2807SJeff Garzik u32 tmp; 1177c6fd2807SJeff Garzik 1178c6fd2807SJeff Garzik /* clear IRQ */ 1179c6fd2807SJeff Garzik tmp = readl(port_mmio + PORT_IRQ_STAT); 1180c6fd2807SJeff Garzik writel(tmp, port_mmio + PORT_IRQ_STAT); 1181c6fd2807SJeff Garzik writel(1 << ap->id, mmio + HOST_IRQ_STAT); 1182c6fd2807SJeff Garzik 1183c6fd2807SJeff Garzik /* turn IRQ back on */ 1184c6fd2807SJeff Garzik writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); 1185c6fd2807SJeff Garzik } 1186c6fd2807SJeff Garzik 1187c6fd2807SJeff Garzik static void ahci_error_handler(struct ata_port *ap) 1188c6fd2807SJeff Garzik { 1189cca3974eSJeff Garzik void __iomem *mmio = ap->host->mmio_base; 1190c6fd2807SJeff Garzik void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 1191c6fd2807SJeff Garzik 1192c6fd2807SJeff Garzik if (!(ap->pflags & ATA_PFLAG_FROZEN)) { 1193c6fd2807SJeff Garzik /* restart engine */ 1194c6fd2807SJeff Garzik ahci_stop_engine(port_mmio); 1195c6fd2807SJeff Garzik ahci_start_engine(port_mmio); 1196c6fd2807SJeff Garzik } 1197c6fd2807SJeff Garzik 1198c6fd2807SJeff Garzik /* perform recovery */ 1199c6fd2807SJeff Garzik ata_do_eh(ap, ahci_prereset, ahci_softreset, ahci_hardreset, 1200c6fd2807SJeff Garzik ahci_postreset); 1201c6fd2807SJeff Garzik } 1202c6fd2807SJeff Garzik 1203c6fd2807SJeff Garzik static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) 1204c6fd2807SJeff Garzik { 1205c6fd2807SJeff Garzik struct ata_port *ap = qc->ap; 1206cca3974eSJeff Garzik void __iomem *mmio = ap->host->mmio_base; 1207c6fd2807SJeff Garzik void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 1208c6fd2807SJeff Garzik 1209c6fd2807SJeff Garzik if (qc->flags & ATA_QCFLAG_FAILED) 1210c6fd2807SJeff Garzik qc->err_mask |= AC_ERR_OTHER; 1211c6fd2807SJeff Garzik 1212c6fd2807SJeff Garzik if (qc->err_mask) { 1213c6fd2807SJeff Garzik /* make DMA engine forget about the failed command */ 1214c6fd2807SJeff Garzik ahci_stop_engine(port_mmio); 1215c6fd2807SJeff Garzik ahci_start_engine(port_mmio); 1216c6fd2807SJeff Garzik } 1217c6fd2807SJeff Garzik } 1218c6fd2807SJeff Garzik 1219c6fd2807SJeff Garzik static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) 1220c6fd2807SJeff Garzik { 1221cca3974eSJeff Garzik struct ahci_host_priv *hpriv = ap->host->private_data; 1222c6fd2807SJeff Garzik struct ahci_port_priv *pp = ap->private_data; 1223cca3974eSJeff Garzik void __iomem *mmio = ap->host->mmio_base; 1224c6fd2807SJeff Garzik void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 1225c6fd2807SJeff Garzik const char *emsg = NULL; 1226c6fd2807SJeff Garzik int rc; 1227c6fd2807SJeff Garzik 1228c6fd2807SJeff Garzik rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg); 1229c6fd2807SJeff Garzik if (rc) { 1230c6fd2807SJeff Garzik ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc); 1231c6fd2807SJeff Garzik ahci_init_port(port_mmio, hpriv->cap, 1232c6fd2807SJeff Garzik pp->cmd_slot_dma, pp->rx_fis_dma); 1233c6fd2807SJeff Garzik } 1234c6fd2807SJeff Garzik 1235c6fd2807SJeff Garzik return rc; 1236c6fd2807SJeff Garzik } 1237c6fd2807SJeff Garzik 1238c6fd2807SJeff Garzik static int ahci_port_resume(struct ata_port *ap) 1239c6fd2807SJeff Garzik { 1240c6fd2807SJeff Garzik struct ahci_port_priv *pp = ap->private_data; 1241cca3974eSJeff Garzik struct ahci_host_priv *hpriv = ap->host->private_data; 1242cca3974eSJeff Garzik void __iomem *mmio = ap->host->mmio_base; 1243c6fd2807SJeff Garzik void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 1244c6fd2807SJeff Garzik 1245c6fd2807SJeff Garzik ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma); 1246c6fd2807SJeff Garzik 1247c6fd2807SJeff Garzik return 0; 1248c6fd2807SJeff Garzik } 1249c6fd2807SJeff Garzik 1250c6fd2807SJeff Garzik static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) 1251c6fd2807SJeff Garzik { 1252cca3974eSJeff Garzik struct ata_host *host = dev_get_drvdata(&pdev->dev); 1253cca3974eSJeff Garzik void __iomem *mmio = host->mmio_base; 1254c6fd2807SJeff Garzik u32 ctl; 1255c6fd2807SJeff Garzik 1256c6fd2807SJeff Garzik if (mesg.event == PM_EVENT_SUSPEND) { 1257c6fd2807SJeff Garzik /* AHCI spec rev1.1 section 8.3.3: 1258c6fd2807SJeff Garzik * Software must disable interrupts prior to requesting a 1259c6fd2807SJeff Garzik * transition of the HBA to D3 state. 1260c6fd2807SJeff Garzik */ 1261c6fd2807SJeff Garzik ctl = readl(mmio + HOST_CTL); 1262c6fd2807SJeff Garzik ctl &= ~HOST_IRQ_EN; 1263c6fd2807SJeff Garzik writel(ctl, mmio + HOST_CTL); 1264c6fd2807SJeff Garzik readl(mmio + HOST_CTL); /* flush */ 1265c6fd2807SJeff Garzik } 1266c6fd2807SJeff Garzik 1267c6fd2807SJeff Garzik return ata_pci_device_suspend(pdev, mesg); 1268c6fd2807SJeff Garzik } 1269c6fd2807SJeff Garzik 1270c6fd2807SJeff Garzik static int ahci_pci_device_resume(struct pci_dev *pdev) 1271c6fd2807SJeff Garzik { 1272cca3974eSJeff Garzik struct ata_host *host = dev_get_drvdata(&pdev->dev); 1273cca3974eSJeff Garzik struct ahci_host_priv *hpriv = host->private_data; 1274cca3974eSJeff Garzik void __iomem *mmio = host->mmio_base; 1275c6fd2807SJeff Garzik int rc; 1276c6fd2807SJeff Garzik 1277c6fd2807SJeff Garzik ata_pci_device_do_resume(pdev); 1278c6fd2807SJeff Garzik 1279c6fd2807SJeff Garzik if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 1280c6fd2807SJeff Garzik rc = ahci_reset_controller(mmio, pdev); 1281c6fd2807SJeff Garzik if (rc) 1282c6fd2807SJeff Garzik return rc; 1283c6fd2807SJeff Garzik 1284cca3974eSJeff Garzik ahci_init_controller(mmio, pdev, host->n_ports, hpriv->cap); 1285c6fd2807SJeff Garzik } 1286c6fd2807SJeff Garzik 1287cca3974eSJeff Garzik ata_host_resume(host); 1288c6fd2807SJeff Garzik 1289c6fd2807SJeff Garzik return 0; 1290c6fd2807SJeff Garzik } 1291c6fd2807SJeff Garzik 1292c6fd2807SJeff Garzik static int ahci_port_start(struct ata_port *ap) 1293c6fd2807SJeff Garzik { 1294cca3974eSJeff Garzik struct device *dev = ap->host->dev; 1295cca3974eSJeff Garzik struct ahci_host_priv *hpriv = ap->host->private_data; 1296c6fd2807SJeff Garzik struct ahci_port_priv *pp; 1297cca3974eSJeff Garzik void __iomem *mmio = ap->host->mmio_base; 1298c6fd2807SJeff Garzik void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 1299c6fd2807SJeff Garzik void *mem; 1300c6fd2807SJeff Garzik dma_addr_t mem_dma; 1301c6fd2807SJeff Garzik int rc; 1302c6fd2807SJeff Garzik 1303c6fd2807SJeff Garzik pp = kmalloc(sizeof(*pp), GFP_KERNEL); 1304c6fd2807SJeff Garzik if (!pp) 1305c6fd2807SJeff Garzik return -ENOMEM; 1306c6fd2807SJeff Garzik memset(pp, 0, sizeof(*pp)); 1307c6fd2807SJeff Garzik 1308c6fd2807SJeff Garzik rc = ata_pad_alloc(ap, dev); 1309c6fd2807SJeff Garzik if (rc) { 1310c6fd2807SJeff Garzik kfree(pp); 1311c6fd2807SJeff Garzik return rc; 1312c6fd2807SJeff Garzik } 1313c6fd2807SJeff Garzik 1314c6fd2807SJeff Garzik mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); 1315c6fd2807SJeff Garzik if (!mem) { 1316c6fd2807SJeff Garzik ata_pad_free(ap, dev); 1317c6fd2807SJeff Garzik kfree(pp); 1318c6fd2807SJeff Garzik return -ENOMEM; 1319c6fd2807SJeff Garzik } 1320c6fd2807SJeff Garzik memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ); 1321c6fd2807SJeff Garzik 1322c6fd2807SJeff Garzik /* 1323c6fd2807SJeff Garzik * First item in chunk of DMA memory: 32-slot command table, 1324c6fd2807SJeff Garzik * 32 bytes each in size 1325c6fd2807SJeff Garzik */ 1326c6fd2807SJeff Garzik pp->cmd_slot = mem; 1327c6fd2807SJeff Garzik pp->cmd_slot_dma = mem_dma; 1328c6fd2807SJeff Garzik 1329c6fd2807SJeff Garzik mem += AHCI_CMD_SLOT_SZ; 1330c6fd2807SJeff Garzik mem_dma += AHCI_CMD_SLOT_SZ; 1331c6fd2807SJeff Garzik 1332c6fd2807SJeff Garzik /* 1333c6fd2807SJeff Garzik * Second item: Received-FIS area 1334c6fd2807SJeff Garzik */ 1335c6fd2807SJeff Garzik pp->rx_fis = mem; 1336c6fd2807SJeff Garzik pp->rx_fis_dma = mem_dma; 1337c6fd2807SJeff Garzik 1338c6fd2807SJeff Garzik mem += AHCI_RX_FIS_SZ; 1339c6fd2807SJeff Garzik mem_dma += AHCI_RX_FIS_SZ; 1340c6fd2807SJeff Garzik 1341c6fd2807SJeff Garzik /* 1342c6fd2807SJeff Garzik * Third item: data area for storing a single command 1343c6fd2807SJeff Garzik * and its scatter-gather table 1344c6fd2807SJeff Garzik */ 1345c6fd2807SJeff Garzik pp->cmd_tbl = mem; 1346c6fd2807SJeff Garzik pp->cmd_tbl_dma = mem_dma; 1347c6fd2807SJeff Garzik 1348c6fd2807SJeff Garzik ap->private_data = pp; 1349c6fd2807SJeff Garzik 1350c6fd2807SJeff Garzik /* initialize port */ 1351c6fd2807SJeff Garzik ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma); 1352c6fd2807SJeff Garzik 1353c6fd2807SJeff Garzik return 0; 1354c6fd2807SJeff Garzik } 1355c6fd2807SJeff Garzik 1356c6fd2807SJeff Garzik static void ahci_port_stop(struct ata_port *ap) 1357c6fd2807SJeff Garzik { 1358cca3974eSJeff Garzik struct device *dev = ap->host->dev; 1359cca3974eSJeff Garzik struct ahci_host_priv *hpriv = ap->host->private_data; 1360c6fd2807SJeff Garzik struct ahci_port_priv *pp = ap->private_data; 1361cca3974eSJeff Garzik void __iomem *mmio = ap->host->mmio_base; 1362c6fd2807SJeff Garzik void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 1363c6fd2807SJeff Garzik const char *emsg = NULL; 1364c6fd2807SJeff Garzik int rc; 1365c6fd2807SJeff Garzik 1366c6fd2807SJeff Garzik /* de-initialize port */ 1367c6fd2807SJeff Garzik rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg); 1368c6fd2807SJeff Garzik if (rc) 1369c6fd2807SJeff Garzik ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc); 1370c6fd2807SJeff Garzik 1371c6fd2807SJeff Garzik ap->private_data = NULL; 1372c6fd2807SJeff Garzik dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, 1373c6fd2807SJeff Garzik pp->cmd_slot, pp->cmd_slot_dma); 1374c6fd2807SJeff Garzik ata_pad_free(ap, dev); 1375c6fd2807SJeff Garzik kfree(pp); 1376c6fd2807SJeff Garzik } 1377c6fd2807SJeff Garzik 1378c6fd2807SJeff Garzik static void ahci_setup_port(struct ata_ioports *port, unsigned long base, 1379c6fd2807SJeff Garzik unsigned int port_idx) 1380c6fd2807SJeff Garzik { 1381c6fd2807SJeff Garzik VPRINTK("ENTER, base==0x%lx, port_idx %u\n", base, port_idx); 1382c6fd2807SJeff Garzik base = ahci_port_base_ul(base, port_idx); 1383c6fd2807SJeff Garzik VPRINTK("base now==0x%lx\n", base); 1384c6fd2807SJeff Garzik 1385c6fd2807SJeff Garzik port->cmd_addr = base; 1386c6fd2807SJeff Garzik port->scr_addr = base + PORT_SCR; 1387c6fd2807SJeff Garzik 1388c6fd2807SJeff Garzik VPRINTK("EXIT\n"); 1389c6fd2807SJeff Garzik } 1390c6fd2807SJeff Garzik 1391c6fd2807SJeff Garzik static int ahci_host_init(struct ata_probe_ent *probe_ent) 1392c6fd2807SJeff Garzik { 1393c6fd2807SJeff Garzik struct ahci_host_priv *hpriv = probe_ent->private_data; 1394c6fd2807SJeff Garzik struct pci_dev *pdev = to_pci_dev(probe_ent->dev); 1395c6fd2807SJeff Garzik void __iomem *mmio = probe_ent->mmio_base; 1396c6fd2807SJeff Garzik unsigned int i, using_dac; 1397c6fd2807SJeff Garzik int rc; 1398c6fd2807SJeff Garzik 1399c6fd2807SJeff Garzik rc = ahci_reset_controller(mmio, pdev); 1400c6fd2807SJeff Garzik if (rc) 1401c6fd2807SJeff Garzik return rc; 1402c6fd2807SJeff Garzik 1403c6fd2807SJeff Garzik hpriv->cap = readl(mmio + HOST_CAP); 1404c6fd2807SJeff Garzik hpriv->port_map = readl(mmio + HOST_PORTS_IMPL); 1405c6fd2807SJeff Garzik probe_ent->n_ports = (hpriv->cap & 0x1f) + 1; 1406c6fd2807SJeff Garzik 1407c6fd2807SJeff Garzik VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n", 1408c6fd2807SJeff Garzik hpriv->cap, hpriv->port_map, probe_ent->n_ports); 1409c6fd2807SJeff Garzik 1410c6fd2807SJeff Garzik using_dac = hpriv->cap & HOST_CAP_64; 1411c6fd2807SJeff Garzik if (using_dac && 1412c6fd2807SJeff Garzik !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { 1413c6fd2807SJeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); 1414c6fd2807SJeff Garzik if (rc) { 1415c6fd2807SJeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 1416c6fd2807SJeff Garzik if (rc) { 1417c6fd2807SJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 1418c6fd2807SJeff Garzik "64-bit DMA enable failed\n"); 1419c6fd2807SJeff Garzik return rc; 1420c6fd2807SJeff Garzik } 1421c6fd2807SJeff Garzik } 1422c6fd2807SJeff Garzik } else { 1423c6fd2807SJeff Garzik rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); 1424c6fd2807SJeff Garzik if (rc) { 1425c6fd2807SJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 1426c6fd2807SJeff Garzik "32-bit DMA enable failed\n"); 1427c6fd2807SJeff Garzik return rc; 1428c6fd2807SJeff Garzik } 1429c6fd2807SJeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 1430c6fd2807SJeff Garzik if (rc) { 1431c6fd2807SJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 1432c6fd2807SJeff Garzik "32-bit consistent DMA enable failed\n"); 1433c6fd2807SJeff Garzik return rc; 1434c6fd2807SJeff Garzik } 1435c6fd2807SJeff Garzik } 1436c6fd2807SJeff Garzik 1437c6fd2807SJeff Garzik for (i = 0; i < probe_ent->n_ports; i++) 1438c6fd2807SJeff Garzik ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i); 1439c6fd2807SJeff Garzik 1440c6fd2807SJeff Garzik ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap); 1441c6fd2807SJeff Garzik 1442c6fd2807SJeff Garzik pci_set_master(pdev); 1443c6fd2807SJeff Garzik 1444c6fd2807SJeff Garzik return 0; 1445c6fd2807SJeff Garzik } 1446c6fd2807SJeff Garzik 1447c6fd2807SJeff Garzik static void ahci_print_info(struct ata_probe_ent *probe_ent) 1448c6fd2807SJeff Garzik { 1449c6fd2807SJeff Garzik struct ahci_host_priv *hpriv = probe_ent->private_data; 1450c6fd2807SJeff Garzik struct pci_dev *pdev = to_pci_dev(probe_ent->dev); 1451c6fd2807SJeff Garzik void __iomem *mmio = probe_ent->mmio_base; 1452c6fd2807SJeff Garzik u32 vers, cap, impl, speed; 1453c6fd2807SJeff Garzik const char *speed_s; 1454c6fd2807SJeff Garzik u16 cc; 1455c6fd2807SJeff Garzik const char *scc_s; 1456c6fd2807SJeff Garzik 1457c6fd2807SJeff Garzik vers = readl(mmio + HOST_VERSION); 1458c6fd2807SJeff Garzik cap = hpriv->cap; 1459c6fd2807SJeff Garzik impl = hpriv->port_map; 1460c6fd2807SJeff Garzik 1461c6fd2807SJeff Garzik speed = (cap >> 20) & 0xf; 1462c6fd2807SJeff Garzik if (speed == 1) 1463c6fd2807SJeff Garzik speed_s = "1.5"; 1464c6fd2807SJeff Garzik else if (speed == 2) 1465c6fd2807SJeff Garzik speed_s = "3"; 1466c6fd2807SJeff Garzik else 1467c6fd2807SJeff Garzik speed_s = "?"; 1468c6fd2807SJeff Garzik 1469c6fd2807SJeff Garzik pci_read_config_word(pdev, 0x0a, &cc); 1470c6fd2807SJeff Garzik if (cc == 0x0101) 1471c6fd2807SJeff Garzik scc_s = "IDE"; 1472c6fd2807SJeff Garzik else if (cc == 0x0106) 1473c6fd2807SJeff Garzik scc_s = "SATA"; 1474c6fd2807SJeff Garzik else if (cc == 0x0104) 1475c6fd2807SJeff Garzik scc_s = "RAID"; 1476c6fd2807SJeff Garzik else 1477c6fd2807SJeff Garzik scc_s = "unknown"; 1478c6fd2807SJeff Garzik 1479c6fd2807SJeff Garzik dev_printk(KERN_INFO, &pdev->dev, 1480c6fd2807SJeff Garzik "AHCI %02x%02x.%02x%02x " 1481c6fd2807SJeff Garzik "%u slots %u ports %s Gbps 0x%x impl %s mode\n" 1482c6fd2807SJeff Garzik , 1483c6fd2807SJeff Garzik 1484c6fd2807SJeff Garzik (vers >> 24) & 0xff, 1485c6fd2807SJeff Garzik (vers >> 16) & 0xff, 1486c6fd2807SJeff Garzik (vers >> 8) & 0xff, 1487c6fd2807SJeff Garzik vers & 0xff, 1488c6fd2807SJeff Garzik 1489c6fd2807SJeff Garzik ((cap >> 8) & 0x1f) + 1, 1490c6fd2807SJeff Garzik (cap & 0x1f) + 1, 1491c6fd2807SJeff Garzik speed_s, 1492c6fd2807SJeff Garzik impl, 1493c6fd2807SJeff Garzik scc_s); 1494c6fd2807SJeff Garzik 1495c6fd2807SJeff Garzik dev_printk(KERN_INFO, &pdev->dev, 1496c6fd2807SJeff Garzik "flags: " 1497c6fd2807SJeff Garzik "%s%s%s%s%s%s" 1498c6fd2807SJeff Garzik "%s%s%s%s%s%s%s\n" 1499c6fd2807SJeff Garzik , 1500c6fd2807SJeff Garzik 1501c6fd2807SJeff Garzik cap & (1 << 31) ? "64bit " : "", 1502c6fd2807SJeff Garzik cap & (1 << 30) ? "ncq " : "", 1503c6fd2807SJeff Garzik cap & (1 << 28) ? "ilck " : "", 1504c6fd2807SJeff Garzik cap & (1 << 27) ? "stag " : "", 1505c6fd2807SJeff Garzik cap & (1 << 26) ? "pm " : "", 1506c6fd2807SJeff Garzik cap & (1 << 25) ? "led " : "", 1507c6fd2807SJeff Garzik 1508c6fd2807SJeff Garzik cap & (1 << 24) ? "clo " : "", 1509c6fd2807SJeff Garzik cap & (1 << 19) ? "nz " : "", 1510c6fd2807SJeff Garzik cap & (1 << 18) ? "only " : "", 1511c6fd2807SJeff Garzik cap & (1 << 17) ? "pmp " : "", 1512c6fd2807SJeff Garzik cap & (1 << 15) ? "pio " : "", 1513c6fd2807SJeff Garzik cap & (1 << 14) ? "slum " : "", 1514c6fd2807SJeff Garzik cap & (1 << 13) ? "part " : "" 1515c6fd2807SJeff Garzik ); 1516c6fd2807SJeff Garzik } 1517c6fd2807SJeff Garzik 1518c6fd2807SJeff Garzik static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) 1519c6fd2807SJeff Garzik { 1520c6fd2807SJeff Garzik static int printed_version; 1521c6fd2807SJeff Garzik struct ata_probe_ent *probe_ent = NULL; 1522c6fd2807SJeff Garzik struct ahci_host_priv *hpriv; 1523c6fd2807SJeff Garzik unsigned long base; 1524c6fd2807SJeff Garzik void __iomem *mmio_base; 1525c6fd2807SJeff Garzik unsigned int board_idx = (unsigned int) ent->driver_data; 1526c6fd2807SJeff Garzik int have_msi, pci_dev_busy = 0; 1527c6fd2807SJeff Garzik int rc; 1528c6fd2807SJeff Garzik 1529c6fd2807SJeff Garzik VPRINTK("ENTER\n"); 1530c6fd2807SJeff Garzik 1531c6fd2807SJeff Garzik WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS); 1532c6fd2807SJeff Garzik 1533c6fd2807SJeff Garzik if (!printed_version++) 1534c6fd2807SJeff Garzik dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); 1535c6fd2807SJeff Garzik 1536c6fd2807SJeff Garzik /* JMicron-specific fixup: make sure we're in AHCI mode */ 1537c6fd2807SJeff Garzik /* This is protected from races with ata_jmicron by the pci probe 1538c6fd2807SJeff Garzik locking */ 1539c6fd2807SJeff Garzik if (pdev->vendor == PCI_VENDOR_ID_JMICRON) { 1540c6fd2807SJeff Garzik /* AHCI enable, AHCI on function 0 */ 1541c6fd2807SJeff Garzik pci_write_config_byte(pdev, 0x41, 0xa1); 1542c6fd2807SJeff Garzik /* Function 1 is the PATA controller */ 1543c6fd2807SJeff Garzik if (PCI_FUNC(pdev->devfn)) 1544c6fd2807SJeff Garzik return -ENODEV; 1545c6fd2807SJeff Garzik } 1546c6fd2807SJeff Garzik 1547c6fd2807SJeff Garzik rc = pci_enable_device(pdev); 1548c6fd2807SJeff Garzik if (rc) 1549c6fd2807SJeff Garzik return rc; 1550c6fd2807SJeff Garzik 1551c6fd2807SJeff Garzik rc = pci_request_regions(pdev, DRV_NAME); 1552c6fd2807SJeff Garzik if (rc) { 1553c6fd2807SJeff Garzik pci_dev_busy = 1; 1554c6fd2807SJeff Garzik goto err_out; 1555c6fd2807SJeff Garzik } 1556c6fd2807SJeff Garzik 1557c6fd2807SJeff Garzik if (pci_enable_msi(pdev) == 0) 1558c6fd2807SJeff Garzik have_msi = 1; 1559c6fd2807SJeff Garzik else { 1560c6fd2807SJeff Garzik pci_intx(pdev, 1); 1561c6fd2807SJeff Garzik have_msi = 0; 1562c6fd2807SJeff Garzik } 1563c6fd2807SJeff Garzik 1564c6fd2807SJeff Garzik probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); 1565c6fd2807SJeff Garzik if (probe_ent == NULL) { 1566c6fd2807SJeff Garzik rc = -ENOMEM; 1567c6fd2807SJeff Garzik goto err_out_msi; 1568c6fd2807SJeff Garzik } 1569c6fd2807SJeff Garzik 1570c6fd2807SJeff Garzik memset(probe_ent, 0, sizeof(*probe_ent)); 1571c6fd2807SJeff Garzik probe_ent->dev = pci_dev_to_dev(pdev); 1572c6fd2807SJeff Garzik INIT_LIST_HEAD(&probe_ent->node); 1573c6fd2807SJeff Garzik 1574c6fd2807SJeff Garzik mmio_base = pci_iomap(pdev, AHCI_PCI_BAR, 0); 1575c6fd2807SJeff Garzik if (mmio_base == NULL) { 1576c6fd2807SJeff Garzik rc = -ENOMEM; 1577c6fd2807SJeff Garzik goto err_out_free_ent; 1578c6fd2807SJeff Garzik } 1579c6fd2807SJeff Garzik base = (unsigned long) mmio_base; 1580c6fd2807SJeff Garzik 1581c6fd2807SJeff Garzik hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL); 1582c6fd2807SJeff Garzik if (!hpriv) { 1583c6fd2807SJeff Garzik rc = -ENOMEM; 1584c6fd2807SJeff Garzik goto err_out_iounmap; 1585c6fd2807SJeff Garzik } 1586c6fd2807SJeff Garzik memset(hpriv, 0, sizeof(*hpriv)); 1587c6fd2807SJeff Garzik 1588c6fd2807SJeff Garzik probe_ent->sht = ahci_port_info[board_idx].sht; 1589cca3974eSJeff Garzik probe_ent->port_flags = ahci_port_info[board_idx].flags; 1590c6fd2807SJeff Garzik probe_ent->pio_mask = ahci_port_info[board_idx].pio_mask; 1591c6fd2807SJeff Garzik probe_ent->udma_mask = ahci_port_info[board_idx].udma_mask; 1592c6fd2807SJeff Garzik probe_ent->port_ops = ahci_port_info[board_idx].port_ops; 1593c6fd2807SJeff Garzik 1594c6fd2807SJeff Garzik probe_ent->irq = pdev->irq; 1595c6fd2807SJeff Garzik probe_ent->irq_flags = IRQF_SHARED; 1596c6fd2807SJeff Garzik probe_ent->mmio_base = mmio_base; 1597c6fd2807SJeff Garzik probe_ent->private_data = hpriv; 1598c6fd2807SJeff Garzik 1599c6fd2807SJeff Garzik if (have_msi) 1600c6fd2807SJeff Garzik hpriv->flags |= AHCI_FLAG_MSI; 1601c6fd2807SJeff Garzik 1602c6fd2807SJeff Garzik /* initialize adapter */ 1603c6fd2807SJeff Garzik rc = ahci_host_init(probe_ent); 1604c6fd2807SJeff Garzik if (rc) 1605c6fd2807SJeff Garzik goto err_out_hpriv; 1606c6fd2807SJeff Garzik 1607cca3974eSJeff Garzik if (!(probe_ent->port_flags & AHCI_FLAG_NO_NCQ) && 1608c6fd2807SJeff Garzik (hpriv->cap & HOST_CAP_NCQ)) 1609cca3974eSJeff Garzik probe_ent->port_flags |= ATA_FLAG_NCQ; 1610c6fd2807SJeff Garzik 1611c6fd2807SJeff Garzik ahci_print_info(probe_ent); 1612c6fd2807SJeff Garzik 1613c6fd2807SJeff Garzik /* FIXME: check ata_device_add return value */ 1614c6fd2807SJeff Garzik ata_device_add(probe_ent); 1615c6fd2807SJeff Garzik kfree(probe_ent); 1616c6fd2807SJeff Garzik 1617c6fd2807SJeff Garzik return 0; 1618c6fd2807SJeff Garzik 1619c6fd2807SJeff Garzik err_out_hpriv: 1620c6fd2807SJeff Garzik kfree(hpriv); 1621c6fd2807SJeff Garzik err_out_iounmap: 1622c6fd2807SJeff Garzik pci_iounmap(pdev, mmio_base); 1623c6fd2807SJeff Garzik err_out_free_ent: 1624c6fd2807SJeff Garzik kfree(probe_ent); 1625c6fd2807SJeff Garzik err_out_msi: 1626c6fd2807SJeff Garzik if (have_msi) 1627c6fd2807SJeff Garzik pci_disable_msi(pdev); 1628c6fd2807SJeff Garzik else 1629c6fd2807SJeff Garzik pci_intx(pdev, 0); 1630c6fd2807SJeff Garzik pci_release_regions(pdev); 1631c6fd2807SJeff Garzik err_out: 1632c6fd2807SJeff Garzik if (!pci_dev_busy) 1633c6fd2807SJeff Garzik pci_disable_device(pdev); 1634c6fd2807SJeff Garzik return rc; 1635c6fd2807SJeff Garzik } 1636c6fd2807SJeff Garzik 1637c6fd2807SJeff Garzik static void ahci_remove_one (struct pci_dev *pdev) 1638c6fd2807SJeff Garzik { 1639c6fd2807SJeff Garzik struct device *dev = pci_dev_to_dev(pdev); 1640cca3974eSJeff Garzik struct ata_host *host = dev_get_drvdata(dev); 1641cca3974eSJeff Garzik struct ahci_host_priv *hpriv = host->private_data; 1642c6fd2807SJeff Garzik unsigned int i; 1643c6fd2807SJeff Garzik int have_msi; 1644c6fd2807SJeff Garzik 1645cca3974eSJeff Garzik for (i = 0; i < host->n_ports; i++) 1646cca3974eSJeff Garzik ata_port_detach(host->ports[i]); 1647c6fd2807SJeff Garzik 1648c6fd2807SJeff Garzik have_msi = hpriv->flags & AHCI_FLAG_MSI; 1649cca3974eSJeff Garzik free_irq(host->irq, host); 1650c6fd2807SJeff Garzik 1651cca3974eSJeff Garzik for (i = 0; i < host->n_ports; i++) { 1652cca3974eSJeff Garzik struct ata_port *ap = host->ports[i]; 1653c6fd2807SJeff Garzik 1654cca3974eSJeff Garzik ata_scsi_release(ap->scsi_host); 1655cca3974eSJeff Garzik scsi_host_put(ap->scsi_host); 1656c6fd2807SJeff Garzik } 1657c6fd2807SJeff Garzik 1658c6fd2807SJeff Garzik kfree(hpriv); 1659cca3974eSJeff Garzik pci_iounmap(pdev, host->mmio_base); 1660cca3974eSJeff Garzik kfree(host); 1661c6fd2807SJeff Garzik 1662c6fd2807SJeff Garzik if (have_msi) 1663c6fd2807SJeff Garzik pci_disable_msi(pdev); 1664c6fd2807SJeff Garzik else 1665c6fd2807SJeff Garzik pci_intx(pdev, 0); 1666c6fd2807SJeff Garzik pci_release_regions(pdev); 1667c6fd2807SJeff Garzik pci_disable_device(pdev); 1668c6fd2807SJeff Garzik dev_set_drvdata(dev, NULL); 1669c6fd2807SJeff Garzik } 1670c6fd2807SJeff Garzik 1671c6fd2807SJeff Garzik static int __init ahci_init(void) 1672c6fd2807SJeff Garzik { 1673c6fd2807SJeff Garzik return pci_register_driver(&ahci_pci_driver); 1674c6fd2807SJeff Garzik } 1675c6fd2807SJeff Garzik 1676c6fd2807SJeff Garzik static void __exit ahci_exit(void) 1677c6fd2807SJeff Garzik { 1678c6fd2807SJeff Garzik pci_unregister_driver(&ahci_pci_driver); 1679c6fd2807SJeff Garzik } 1680c6fd2807SJeff Garzik 1681c6fd2807SJeff Garzik 1682c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 1683c6fd2807SJeff Garzik MODULE_DESCRIPTION("AHCI SATA low-level driver"); 1684c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 1685c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, ahci_pci_tbl); 1686c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 1687c6fd2807SJeff Garzik 1688c6fd2807SJeff Garzik module_init(ahci_init); 1689c6fd2807SJeff Garzik module_exit(ahci_exit); 1690