1c6fd2807SJeff Garzik /* 2c6fd2807SJeff Garzik * sata_sil.c - Silicon Image SATA 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 2003-2005 Red Hat, Inc. 9c6fd2807SJeff Garzik * Copyright 2003 Benjamin Herrenschmidt 10c6fd2807SJeff Garzik * 11c6fd2807SJeff Garzik * 12c6fd2807SJeff Garzik * This program is free software; you can redistribute it and/or modify 13c6fd2807SJeff Garzik * it under the terms of the GNU General Public License as published by 14c6fd2807SJeff Garzik * the Free Software Foundation; either version 2, or (at your option) 15c6fd2807SJeff Garzik * any later version. 16c6fd2807SJeff Garzik * 17c6fd2807SJeff Garzik * This program is distributed in the hope that it will be useful, 18c6fd2807SJeff Garzik * but WITHOUT ANY WARRANTY; without even the implied warranty of 19c6fd2807SJeff Garzik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20c6fd2807SJeff Garzik * GNU General Public License for more details. 21c6fd2807SJeff Garzik * 22c6fd2807SJeff Garzik * You should have received a copy of the GNU General Public License 23c6fd2807SJeff Garzik * along with this program; see the file COPYING. If not, write to 24c6fd2807SJeff Garzik * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 25c6fd2807SJeff Garzik * 26c6fd2807SJeff Garzik * 27c6fd2807SJeff Garzik * libata documentation is available via 'make {ps|pdf}docs', 28c6fd2807SJeff Garzik * as Documentation/DocBook/libata.* 29c6fd2807SJeff Garzik * 30c6fd2807SJeff Garzik * Documentation for SiI 3112: 31c6fd2807SJeff Garzik * http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2 32c6fd2807SJeff Garzik * 33c6fd2807SJeff Garzik * Other errata and documentation available under NDA. 34c6fd2807SJeff Garzik * 35c6fd2807SJeff Garzik */ 36c6fd2807SJeff Garzik 37c6fd2807SJeff Garzik #include <linux/kernel.h> 38c6fd2807SJeff Garzik #include <linux/module.h> 39c6fd2807SJeff Garzik #include <linux/pci.h> 40c6fd2807SJeff Garzik #include <linux/init.h> 41c6fd2807SJeff Garzik #include <linux/blkdev.h> 42c6fd2807SJeff Garzik #include <linux/delay.h> 43c6fd2807SJeff Garzik #include <linux/interrupt.h> 44c6fd2807SJeff Garzik #include <linux/device.h> 45c6fd2807SJeff Garzik #include <scsi/scsi_host.h> 46c6fd2807SJeff Garzik #include <linux/libata.h> 471737ef75SAlexander Beregalov #include <linux/dmi.h> 48c6fd2807SJeff Garzik 49c6fd2807SJeff Garzik #define DRV_NAME "sata_sil" 50c7e324f1SRobert Hancock #define DRV_VERSION "2.4" 51c7e324f1SRobert Hancock 52c7e324f1SRobert Hancock #define SIL_DMA_BOUNDARY 0x7fffffffUL 53c6fd2807SJeff Garzik 54c6fd2807SJeff Garzik enum { 550d5ff566STejun Heo SIL_MMIO_BAR = 5, 560d5ff566STejun Heo 57c6fd2807SJeff Garzik /* 58c6fd2807SJeff Garzik * host flags 59c6fd2807SJeff Garzik */ 60c6fd2807SJeff Garzik SIL_FLAG_NO_SATA_IRQ = (1 << 28), 61c6fd2807SJeff Garzik SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29), 62c6fd2807SJeff Garzik SIL_FLAG_MOD15WRITE = (1 << 30), 63c6fd2807SJeff Garzik 649cbe056fSSergei Shtylyov SIL_DFL_PORT_FLAGS = ATA_FLAG_SATA, 65c6fd2807SJeff Garzik 66c6fd2807SJeff Garzik /* 67c6fd2807SJeff Garzik * Controller IDs 68c6fd2807SJeff Garzik */ 69c6fd2807SJeff Garzik sil_3112 = 0, 70c6fd2807SJeff Garzik sil_3112_no_sata_irq = 1, 71c6fd2807SJeff Garzik sil_3512 = 2, 72c6fd2807SJeff Garzik sil_3114 = 3, 73c6fd2807SJeff Garzik 74c6fd2807SJeff Garzik /* 75c6fd2807SJeff Garzik * Register offsets 76c6fd2807SJeff Garzik */ 77c6fd2807SJeff Garzik SIL_SYSCFG = 0x48, 78c6fd2807SJeff Garzik 79c6fd2807SJeff Garzik /* 80c6fd2807SJeff Garzik * Register bits 81c6fd2807SJeff Garzik */ 82c6fd2807SJeff Garzik /* SYSCFG */ 83c6fd2807SJeff Garzik SIL_MASK_IDE0_INT = (1 << 22), 84c6fd2807SJeff Garzik SIL_MASK_IDE1_INT = (1 << 23), 85c6fd2807SJeff Garzik SIL_MASK_IDE2_INT = (1 << 24), 86c6fd2807SJeff Garzik SIL_MASK_IDE3_INT = (1 << 25), 87c6fd2807SJeff Garzik SIL_MASK_2PORT = SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT, 88c6fd2807SJeff Garzik SIL_MASK_4PORT = SIL_MASK_2PORT | 89c6fd2807SJeff Garzik SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT, 90c6fd2807SJeff Garzik 91c6fd2807SJeff Garzik /* BMDMA/BMDMA2 */ 92c6fd2807SJeff Garzik SIL_INTR_STEERING = (1 << 1), 93c6fd2807SJeff Garzik 94c6fd2807SJeff Garzik SIL_DMA_ENABLE = (1 << 0), /* DMA run switch */ 95c6fd2807SJeff Garzik SIL_DMA_RDWR = (1 << 3), /* DMA Rd-Wr */ 96c6fd2807SJeff Garzik SIL_DMA_SATA_IRQ = (1 << 4), /* OR of all SATA IRQs */ 97c6fd2807SJeff Garzik SIL_DMA_ACTIVE = (1 << 16), /* DMA running */ 98c6fd2807SJeff Garzik SIL_DMA_ERROR = (1 << 17), /* PCI bus error */ 99c6fd2807SJeff Garzik SIL_DMA_COMPLETE = (1 << 18), /* cmd complete / IRQ pending */ 100c6fd2807SJeff Garzik SIL_DMA_N_SATA_IRQ = (1 << 6), /* SATA_IRQ for the next channel */ 101c6fd2807SJeff Garzik SIL_DMA_N_ACTIVE = (1 << 24), /* ACTIVE for the next channel */ 102c6fd2807SJeff Garzik SIL_DMA_N_ERROR = (1 << 25), /* ERROR for the next channel */ 103c6fd2807SJeff Garzik SIL_DMA_N_COMPLETE = (1 << 26), /* COMPLETE for the next channel */ 104c6fd2807SJeff Garzik 105c6fd2807SJeff Garzik /* SIEN */ 106c6fd2807SJeff Garzik SIL_SIEN_N = (1 << 16), /* triggered by SError.N */ 107c6fd2807SJeff Garzik 108c6fd2807SJeff Garzik /* 109c6fd2807SJeff Garzik * Others 110c6fd2807SJeff Garzik */ 111c6fd2807SJeff Garzik SIL_QUIRK_MOD15WRITE = (1 << 0), 112c6fd2807SJeff Garzik SIL_QUIRK_UDMA5MAX = (1 << 1), 113c6fd2807SJeff Garzik }; 114c6fd2807SJeff Garzik 115c6fd2807SJeff Garzik static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 116281d426cSAlexey Dobriyan #ifdef CONFIG_PM 117c6fd2807SJeff Garzik static int sil_pci_device_resume(struct pci_dev *pdev); 118281d426cSAlexey Dobriyan #endif 119cd0d3bbcSAlan static void sil_dev_config(struct ata_device *dev); 12082ef04fbSTejun Heo static int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); 12182ef04fbSTejun Heo static int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); 1220260731fSTejun Heo static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed); 123c7e324f1SRobert Hancock static void sil_qc_prep(struct ata_queued_cmd *qc); 124c7e324f1SRobert Hancock static void sil_bmdma_setup(struct ata_queued_cmd *qc); 125c7e324f1SRobert Hancock static void sil_bmdma_start(struct ata_queued_cmd *qc); 126c7e324f1SRobert Hancock static void sil_bmdma_stop(struct ata_queued_cmd *qc); 127c6fd2807SJeff Garzik static void sil_freeze(struct ata_port *ap); 128c6fd2807SJeff Garzik static void sil_thaw(struct ata_port *ap); 129c6fd2807SJeff Garzik 130c6fd2807SJeff Garzik 131c6fd2807SJeff Garzik static const struct pci_device_id sil_pci_tbl[] = { 13254bb3a94SJeff Garzik { PCI_VDEVICE(CMD, 0x3112), sil_3112 }, 13354bb3a94SJeff Garzik { PCI_VDEVICE(CMD, 0x0240), sil_3112 }, 13454bb3a94SJeff Garzik { PCI_VDEVICE(CMD, 0x3512), sil_3512 }, 13554bb3a94SJeff Garzik { PCI_VDEVICE(CMD, 0x3114), sil_3114 }, 13654bb3a94SJeff Garzik { PCI_VDEVICE(ATI, 0x436e), sil_3112 }, 13754bb3a94SJeff Garzik { PCI_VDEVICE(ATI, 0x4379), sil_3112_no_sata_irq }, 13854bb3a94SJeff Garzik { PCI_VDEVICE(ATI, 0x437a), sil_3112_no_sata_irq }, 13954bb3a94SJeff Garzik 140c6fd2807SJeff Garzik { } /* terminate list */ 141c6fd2807SJeff Garzik }; 142c6fd2807SJeff Garzik 143c6fd2807SJeff Garzik 144c6fd2807SJeff Garzik /* TODO firmware versions should be added - eric */ 145c6fd2807SJeff Garzik static const struct sil_drivelist { 146c6fd2807SJeff Garzik const char *product; 147c6fd2807SJeff Garzik unsigned int quirk; 148c6fd2807SJeff Garzik } sil_blacklist [] = { 149c6fd2807SJeff Garzik { "ST320012AS", SIL_QUIRK_MOD15WRITE }, 150c6fd2807SJeff Garzik { "ST330013AS", SIL_QUIRK_MOD15WRITE }, 151c6fd2807SJeff Garzik { "ST340017AS", SIL_QUIRK_MOD15WRITE }, 152c6fd2807SJeff Garzik { "ST360015AS", SIL_QUIRK_MOD15WRITE }, 153c6fd2807SJeff Garzik { "ST380023AS", SIL_QUIRK_MOD15WRITE }, 154c6fd2807SJeff Garzik { "ST3120023AS", SIL_QUIRK_MOD15WRITE }, 155c6fd2807SJeff Garzik { "ST340014ASL", SIL_QUIRK_MOD15WRITE }, 156c6fd2807SJeff Garzik { "ST360014ASL", SIL_QUIRK_MOD15WRITE }, 157c6fd2807SJeff Garzik { "ST380011ASL", SIL_QUIRK_MOD15WRITE }, 158c6fd2807SJeff Garzik { "ST3120022ASL", SIL_QUIRK_MOD15WRITE }, 159c6fd2807SJeff Garzik { "ST3160021ASL", SIL_QUIRK_MOD15WRITE }, 160c6fd2807SJeff Garzik { "Maxtor 4D060H3", SIL_QUIRK_UDMA5MAX }, 161c6fd2807SJeff Garzik { } 162c6fd2807SJeff Garzik }; 163c6fd2807SJeff Garzik 164c6fd2807SJeff Garzik static struct pci_driver sil_pci_driver = { 165c6fd2807SJeff Garzik .name = DRV_NAME, 166c6fd2807SJeff Garzik .id_table = sil_pci_tbl, 167c6fd2807SJeff Garzik .probe = sil_init_one, 168c6fd2807SJeff Garzik .remove = ata_pci_remove_one, 169281d426cSAlexey Dobriyan #ifdef CONFIG_PM 170c6fd2807SJeff Garzik .suspend = ata_pci_device_suspend, 171c6fd2807SJeff Garzik .resume = sil_pci_device_resume, 172281d426cSAlexey Dobriyan #endif 173c6fd2807SJeff Garzik }; 174c6fd2807SJeff Garzik 175c6fd2807SJeff Garzik static struct scsi_host_template sil_sht = { 176c7e324f1SRobert Hancock ATA_BASE_SHT(DRV_NAME), 177c7e324f1SRobert Hancock /** These controllers support Large Block Transfer which allows 178c7e324f1SRobert Hancock transfer chunks up to 2GB and which cross 64KB boundaries, 179c7e324f1SRobert Hancock therefore the DMA limits are more relaxed than standard ATA SFF. */ 180c7e324f1SRobert Hancock .dma_boundary = SIL_DMA_BOUNDARY, 181c7e324f1SRobert Hancock .sg_tablesize = ATA_MAX_PRD 182c6fd2807SJeff Garzik }; 183c6fd2807SJeff Garzik 184029cfd6bSTejun Heo static struct ata_port_operations sil_ops = { 18531f80112SRobert Hancock .inherits = &ata_bmdma32_port_ops, 186c6fd2807SJeff Garzik .dev_config = sil_dev_config, 1879d2c7c75SAlan Cox .set_mode = sil_set_mode, 188c7e324f1SRobert Hancock .bmdma_setup = sil_bmdma_setup, 189c7e324f1SRobert Hancock .bmdma_start = sil_bmdma_start, 190c7e324f1SRobert Hancock .bmdma_stop = sil_bmdma_stop, 191c7e324f1SRobert Hancock .qc_prep = sil_qc_prep, 192c6fd2807SJeff Garzik .freeze = sil_freeze, 193c6fd2807SJeff Garzik .thaw = sil_thaw, 194c6fd2807SJeff Garzik .scr_read = sil_scr_read, 195c6fd2807SJeff Garzik .scr_write = sil_scr_write, 196c6fd2807SJeff Garzik }; 197c6fd2807SJeff Garzik 198c6fd2807SJeff Garzik static const struct ata_port_info sil_port_info[] = { 199c6fd2807SJeff Garzik /* sil_3112 */ 200c6fd2807SJeff Garzik { 201cca3974eSJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE, 20214bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 20314bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 204bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5, 205c6fd2807SJeff Garzik .port_ops = &sil_ops, 206c6fd2807SJeff Garzik }, 207c6fd2807SJeff Garzik /* sil_3112_no_sata_irq */ 208c6fd2807SJeff Garzik { 209cca3974eSJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE | 210c6fd2807SJeff Garzik SIL_FLAG_NO_SATA_IRQ, 21114bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 21214bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 213bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5, 214c6fd2807SJeff Garzik .port_ops = &sil_ops, 215c6fd2807SJeff Garzik }, 216c6fd2807SJeff Garzik /* sil_3512 */ 217c6fd2807SJeff Garzik { 218cca3974eSJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, 21914bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 22014bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 221bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5, 222c6fd2807SJeff Garzik .port_ops = &sil_ops, 223c6fd2807SJeff Garzik }, 224c6fd2807SJeff Garzik /* sil_3114 */ 225c6fd2807SJeff Garzik { 226cca3974eSJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, 22714bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 22814bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 229bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5, 230c6fd2807SJeff Garzik .port_ops = &sil_ops, 231c6fd2807SJeff Garzik }, 232c6fd2807SJeff Garzik }; 233c6fd2807SJeff Garzik 234c6fd2807SJeff Garzik /* per-port register offsets */ 235c6fd2807SJeff Garzik /* TODO: we can probably calculate rather than use a table */ 236c6fd2807SJeff Garzik static const struct { 237c6fd2807SJeff Garzik unsigned long tf; /* ATA taskfile register block */ 238c6fd2807SJeff Garzik unsigned long ctl; /* ATA control/altstatus register block */ 239c6fd2807SJeff Garzik unsigned long bmdma; /* DMA register block */ 240c6fd2807SJeff Garzik unsigned long bmdma2; /* DMA register block #2 */ 241c6fd2807SJeff Garzik unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */ 242c6fd2807SJeff Garzik unsigned long scr; /* SATA control register block */ 243c6fd2807SJeff Garzik unsigned long sien; /* SATA Interrupt Enable register */ 244c6fd2807SJeff Garzik unsigned long xfer_mode;/* data transfer mode register */ 245c6fd2807SJeff Garzik unsigned long sfis_cfg; /* SATA FIS reception config register */ 246c6fd2807SJeff Garzik } sil_port[] = { 247c6fd2807SJeff Garzik /* port 0 ... */ 2485bcd7a00SJeff Garzik /* tf ctl bmdma bmdma2 fifo scr sien mode sfis */ 2495bcd7a00SJeff Garzik { 0x80, 0x8A, 0x0, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c }, 2505bcd7a00SJeff Garzik { 0xC0, 0xCA, 0x8, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc }, 251c6fd2807SJeff Garzik { 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c }, 252c6fd2807SJeff Garzik { 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc }, 253c6fd2807SJeff Garzik /* ... port 3 */ 254c6fd2807SJeff Garzik }; 255c6fd2807SJeff Garzik 256c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 257c6fd2807SJeff Garzik MODULE_DESCRIPTION("low-level driver for Silicon Image SATA controller"); 258c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 259c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, sil_pci_tbl); 260c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 261c6fd2807SJeff Garzik 2625796d1c4SJeff Garzik static int slow_down; 263c6fd2807SJeff Garzik module_param(slow_down, int, 0444); 264c6fd2807SJeff Garzik MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)"); 265c6fd2807SJeff Garzik 266c6fd2807SJeff Garzik 267c7e324f1SRobert Hancock static void sil_bmdma_stop(struct ata_queued_cmd *qc) 268c7e324f1SRobert Hancock { 269c7e324f1SRobert Hancock struct ata_port *ap = qc->ap; 270c7e324f1SRobert Hancock void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 271c7e324f1SRobert Hancock void __iomem *bmdma2 = mmio_base + sil_port[ap->port_no].bmdma2; 272c7e324f1SRobert Hancock 273c7e324f1SRobert Hancock /* clear start/stop bit - can safely always write 0 */ 274c7e324f1SRobert Hancock iowrite8(0, bmdma2); 275c7e324f1SRobert Hancock 276c7e324f1SRobert Hancock /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ 277c7e324f1SRobert Hancock ata_sff_dma_pause(ap); 278c7e324f1SRobert Hancock } 279c7e324f1SRobert Hancock 280c7e324f1SRobert Hancock static void sil_bmdma_setup(struct ata_queued_cmd *qc) 281c7e324f1SRobert Hancock { 282c7e324f1SRobert Hancock struct ata_port *ap = qc->ap; 283c7e324f1SRobert Hancock void __iomem *bmdma = ap->ioaddr.bmdma_addr; 284c7e324f1SRobert Hancock 285c7e324f1SRobert Hancock /* load PRD table addr. */ 286f60d7011STejun Heo iowrite32(ap->bmdma_prd_dma, bmdma + ATA_DMA_TABLE_OFS); 287c7e324f1SRobert Hancock 288c7e324f1SRobert Hancock /* issue r/w command */ 289c7e324f1SRobert Hancock ap->ops->sff_exec_command(ap, &qc->tf); 290c7e324f1SRobert Hancock } 291c7e324f1SRobert Hancock 292c7e324f1SRobert Hancock static void sil_bmdma_start(struct ata_queued_cmd *qc) 293c7e324f1SRobert Hancock { 294c7e324f1SRobert Hancock unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); 295c7e324f1SRobert Hancock struct ata_port *ap = qc->ap; 296c7e324f1SRobert Hancock void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 297c7e324f1SRobert Hancock void __iomem *bmdma2 = mmio_base + sil_port[ap->port_no].bmdma2; 298c7e324f1SRobert Hancock u8 dmactl = ATA_DMA_START; 299c7e324f1SRobert Hancock 300c7e324f1SRobert Hancock /* set transfer direction, start host DMA transaction 301c7e324f1SRobert Hancock Note: For Large Block Transfer to work, the DMA must be started 302c7e324f1SRobert Hancock using the bmdma2 register. */ 303c7e324f1SRobert Hancock if (!rw) 304c7e324f1SRobert Hancock dmactl |= ATA_DMA_WR; 305c7e324f1SRobert Hancock iowrite8(dmactl, bmdma2); 306c7e324f1SRobert Hancock } 307c7e324f1SRobert Hancock 308c7e324f1SRobert Hancock /* The way God intended PCI IDE scatter/gather lists to look and behave... */ 309c7e324f1SRobert Hancock static void sil_fill_sg(struct ata_queued_cmd *qc) 310c7e324f1SRobert Hancock { 311c7e324f1SRobert Hancock struct scatterlist *sg; 312c7e324f1SRobert Hancock struct ata_port *ap = qc->ap; 313f60d7011STejun Heo struct ata_bmdma_prd *prd, *last_prd = NULL; 314c7e324f1SRobert Hancock unsigned int si; 315c7e324f1SRobert Hancock 316f60d7011STejun Heo prd = &ap->bmdma_prd[0]; 317c7e324f1SRobert Hancock for_each_sg(qc->sg, sg, qc->n_elem, si) { 318c7e324f1SRobert Hancock /* Note h/w doesn't support 64-bit, so we unconditionally 319c7e324f1SRobert Hancock * truncate dma_addr_t to u32. 320c7e324f1SRobert Hancock */ 321c7e324f1SRobert Hancock u32 addr = (u32) sg_dma_address(sg); 322c7e324f1SRobert Hancock u32 sg_len = sg_dma_len(sg); 323c7e324f1SRobert Hancock 324c7e324f1SRobert Hancock prd->addr = cpu_to_le32(addr); 325c7e324f1SRobert Hancock prd->flags_len = cpu_to_le32(sg_len); 32641137aa6SPasi Kärkkäinen VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", si, addr, sg_len); 327c7e324f1SRobert Hancock 328c7e324f1SRobert Hancock last_prd = prd; 329c7e324f1SRobert Hancock prd++; 330c7e324f1SRobert Hancock } 331c7e324f1SRobert Hancock 332c7e324f1SRobert Hancock if (likely(last_prd)) 333c7e324f1SRobert Hancock last_prd->flags_len |= cpu_to_le32(ATA_PRD_EOT); 334c7e324f1SRobert Hancock } 335c7e324f1SRobert Hancock 336c7e324f1SRobert Hancock static void sil_qc_prep(struct ata_queued_cmd *qc) 337c7e324f1SRobert Hancock { 338c7e324f1SRobert Hancock if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 339c7e324f1SRobert Hancock return; 340c7e324f1SRobert Hancock 341c7e324f1SRobert Hancock sil_fill_sg(qc); 342c7e324f1SRobert Hancock } 343c7e324f1SRobert Hancock 344c6fd2807SJeff Garzik static unsigned char sil_get_device_cache_line(struct pci_dev *pdev) 345c6fd2807SJeff Garzik { 346c6fd2807SJeff Garzik u8 cache_line = 0; 347c6fd2807SJeff Garzik pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line); 348c6fd2807SJeff Garzik return cache_line; 349c6fd2807SJeff Garzik } 350c6fd2807SJeff Garzik 3519d2c7c75SAlan Cox /** 3529d2c7c75SAlan Cox * sil_set_mode - wrap set_mode functions 3530260731fSTejun Heo * @link: link to set up 3549d2c7c75SAlan Cox * @r_failed: returned device when we fail 3559d2c7c75SAlan Cox * 3569d2c7c75SAlan Cox * Wrap the libata method for device setup as after the setup we need 3579d2c7c75SAlan Cox * to inspect the results and do some configuration work 3589d2c7c75SAlan Cox */ 3599d2c7c75SAlan Cox 3600260731fSTejun Heo static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed) 361c6fd2807SJeff Garzik { 3620260731fSTejun Heo struct ata_port *ap = link->ap; 3630260731fSTejun Heo void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 3640d5ff566STejun Heo void __iomem *addr = mmio_base + sil_port[ap->port_no].xfer_mode; 3650260731fSTejun Heo struct ata_device *dev; 366f58229f8STejun Heo u32 tmp, dev_mode[2] = { }; 3679d2c7c75SAlan Cox int rc; 3689d2c7c75SAlan Cox 3690260731fSTejun Heo rc = ata_do_set_mode(link, r_failed); 3709d2c7c75SAlan Cox if (rc) 3719d2c7c75SAlan Cox return rc; 372c6fd2807SJeff Garzik 3731eca4365STejun Heo ata_for_each_dev(dev, link, ALL) { 374c6fd2807SJeff Garzik if (!ata_dev_enabled(dev)) 375f58229f8STejun Heo dev_mode[dev->devno] = 0; /* PIO0/1/2 */ 376c6fd2807SJeff Garzik else if (dev->flags & ATA_DFLAG_PIO) 377f58229f8STejun Heo dev_mode[dev->devno] = 1; /* PIO3/4 */ 378c6fd2807SJeff Garzik else 379f58229f8STejun Heo dev_mode[dev->devno] = 3; /* UDMA */ 380c6fd2807SJeff Garzik /* value 2 indicates MDMA */ 381c6fd2807SJeff Garzik } 382c6fd2807SJeff Garzik 383c6fd2807SJeff Garzik tmp = readl(addr); 384c6fd2807SJeff Garzik tmp &= ~((1<<5) | (1<<4) | (1<<1) | (1<<0)); 385c6fd2807SJeff Garzik tmp |= dev_mode[0]; 386c6fd2807SJeff Garzik tmp |= (dev_mode[1] << 4); 387c6fd2807SJeff Garzik writel(tmp, addr); 388c6fd2807SJeff Garzik readl(addr); /* flush */ 3899d2c7c75SAlan Cox return 0; 390c6fd2807SJeff Garzik } 391c6fd2807SJeff Garzik 3925796d1c4SJeff Garzik static inline void __iomem *sil_scr_addr(struct ata_port *ap, 3935796d1c4SJeff Garzik unsigned int sc_reg) 394c6fd2807SJeff Garzik { 3950d5ff566STejun Heo void __iomem *offset = ap->ioaddr.scr_addr; 396c6fd2807SJeff Garzik 397c6fd2807SJeff Garzik switch (sc_reg) { 398c6fd2807SJeff Garzik case SCR_STATUS: 399c6fd2807SJeff Garzik return offset + 4; 400c6fd2807SJeff Garzik case SCR_ERROR: 401c6fd2807SJeff Garzik return offset + 8; 402c6fd2807SJeff Garzik case SCR_CONTROL: 403c6fd2807SJeff Garzik return offset; 404c6fd2807SJeff Garzik default: 405c6fd2807SJeff Garzik /* do nothing */ 406c6fd2807SJeff Garzik break; 407c6fd2807SJeff Garzik } 408c6fd2807SJeff Garzik 4098d9db2d2SRandy Dunlap return NULL; 410c6fd2807SJeff Garzik } 411c6fd2807SJeff Garzik 41282ef04fbSTejun Heo static int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) 413c6fd2807SJeff Garzik { 41482ef04fbSTejun Heo void __iomem *mmio = sil_scr_addr(link->ap, sc_reg); 415da3dbb17STejun Heo 416da3dbb17STejun Heo if (mmio) { 417da3dbb17STejun Heo *val = readl(mmio); 418da3dbb17STejun Heo return 0; 419da3dbb17STejun Heo } 420da3dbb17STejun Heo return -EINVAL; 421c6fd2807SJeff Garzik } 422c6fd2807SJeff Garzik 42382ef04fbSTejun Heo static int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) 424c6fd2807SJeff Garzik { 42582ef04fbSTejun Heo void __iomem *mmio = sil_scr_addr(link->ap, sc_reg); 426da3dbb17STejun Heo 427da3dbb17STejun Heo if (mmio) { 428c6fd2807SJeff Garzik writel(val, mmio); 429da3dbb17STejun Heo return 0; 430da3dbb17STejun Heo } 431da3dbb17STejun Heo return -EINVAL; 432c6fd2807SJeff Garzik } 433c6fd2807SJeff Garzik 434c6fd2807SJeff Garzik static void sil_host_intr(struct ata_port *ap, u32 bmdma2) 435c6fd2807SJeff Garzik { 4369af5c9c9STejun Heo struct ata_eh_info *ehi = &ap->link.eh_info; 4379af5c9c9STejun Heo struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag); 438c6fd2807SJeff Garzik u8 status; 439c6fd2807SJeff Garzik 440c6fd2807SJeff Garzik if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) { 441ebd1699eSJeff Garzik u32 serror = 0xffffffff; 442c6fd2807SJeff Garzik 443c6fd2807SJeff Garzik /* SIEN doesn't mask SATA IRQs on some 3112s. Those 444c6fd2807SJeff Garzik * controllers continue to assert IRQ as long as 445c6fd2807SJeff Garzik * SError bits are pending. Clear SError immediately. 446c6fd2807SJeff Garzik */ 44782ef04fbSTejun Heo sil_scr_read(&ap->link, SCR_ERROR, &serror); 44882ef04fbSTejun Heo sil_scr_write(&ap->link, SCR_ERROR, serror); 449c6fd2807SJeff Garzik 4508cf32ac6STejun Heo /* Sometimes spurious interrupts occur, double check 4518cf32ac6STejun Heo * it's PHYRDY CHG. 4528cf32ac6STejun Heo */ 4538cf32ac6STejun Heo if (serror & SERR_PHYRDY_CHG) { 4549af5c9c9STejun Heo ap->link.eh_info.serror |= serror; 455c6fd2807SJeff Garzik goto freeze; 456c6fd2807SJeff Garzik } 457c6fd2807SJeff Garzik 4588cf32ac6STejun Heo if (!(bmdma2 & SIL_DMA_COMPLETE)) 4598cf32ac6STejun Heo return; 4608cf32ac6STejun Heo } 461c6fd2807SJeff Garzik 4628cf32ac6STejun Heo if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { 463e2f8fb72STejun Heo /* this sometimes happens, just clear IRQ */ 4645682ed33STejun Heo ap->ops->sff_check_status(ap); 465e2f8fb72STejun Heo return; 466e2f8fb72STejun Heo } 467e2f8fb72STejun Heo 468c6fd2807SJeff Garzik /* Check whether we are expecting interrupt in this state */ 469c6fd2807SJeff Garzik switch (ap->hsm_task_state) { 470c6fd2807SJeff Garzik case HSM_ST_FIRST: 471c6fd2807SJeff Garzik /* Some pre-ATAPI-4 devices assert INTRQ 472c6fd2807SJeff Garzik * at this state when ready to receive CDB. 473c6fd2807SJeff Garzik */ 474c6fd2807SJeff Garzik 475c6fd2807SJeff Garzik /* Check the ATA_DFLAG_CDB_INTR flag is enough here. 476405e66b3STejun Heo * The flag was turned on only for atapi devices. No 477405e66b3STejun Heo * need to check ata_is_atapi(qc->tf.protocol) again. 478c6fd2807SJeff Garzik */ 479c6fd2807SJeff Garzik if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) 480c6fd2807SJeff Garzik goto err_hsm; 481c6fd2807SJeff Garzik break; 482c6fd2807SJeff Garzik case HSM_ST_LAST: 483405e66b3STejun Heo if (ata_is_dma(qc->tf.protocol)) { 484c6fd2807SJeff Garzik /* clear DMA-Start bit */ 485c6fd2807SJeff Garzik ap->ops->bmdma_stop(qc); 486c6fd2807SJeff Garzik 487c6fd2807SJeff Garzik if (bmdma2 & SIL_DMA_ERROR) { 488c6fd2807SJeff Garzik qc->err_mask |= AC_ERR_HOST_BUS; 489c6fd2807SJeff Garzik ap->hsm_task_state = HSM_ST_ERR; 490c6fd2807SJeff Garzik } 491c6fd2807SJeff Garzik } 492c6fd2807SJeff Garzik break; 493c6fd2807SJeff Garzik case HSM_ST: 494c6fd2807SJeff Garzik break; 495c6fd2807SJeff Garzik default: 496c6fd2807SJeff Garzik goto err_hsm; 497c6fd2807SJeff Garzik } 498c6fd2807SJeff Garzik 499c6fd2807SJeff Garzik /* check main status, clearing INTRQ */ 5005682ed33STejun Heo status = ap->ops->sff_check_status(ap); 501c6fd2807SJeff Garzik if (unlikely(status & ATA_BUSY)) 502c6fd2807SJeff Garzik goto err_hsm; 503c6fd2807SJeff Garzik 504c6fd2807SJeff Garzik /* ack bmdma irq events */ 50537f65b8bSTejun Heo ata_bmdma_irq_clear(ap); 506c6fd2807SJeff Garzik 507c6fd2807SJeff Garzik /* kick HSM in the ass */ 5089363c382STejun Heo ata_sff_hsm_move(ap, qc, status, 0); 509c6fd2807SJeff Garzik 510405e66b3STejun Heo if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol)) 511ea54763fSTejun Heo ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2); 512ea54763fSTejun Heo 513c6fd2807SJeff Garzik return; 514c6fd2807SJeff Garzik 515c6fd2807SJeff Garzik err_hsm: 516c6fd2807SJeff Garzik qc->err_mask |= AC_ERR_HSM; 517c6fd2807SJeff Garzik freeze: 518c6fd2807SJeff Garzik ata_port_freeze(ap); 519c6fd2807SJeff Garzik } 520c6fd2807SJeff Garzik 5217d12e780SDavid Howells static irqreturn_t sil_interrupt(int irq, void *dev_instance) 522c6fd2807SJeff Garzik { 523cca3974eSJeff Garzik struct ata_host *host = dev_instance; 5240d5ff566STejun Heo void __iomem *mmio_base = host->iomap[SIL_MMIO_BAR]; 525c6fd2807SJeff Garzik int handled = 0; 526c6fd2807SJeff Garzik int i; 527c6fd2807SJeff Garzik 528cca3974eSJeff Garzik spin_lock(&host->lock); 529c6fd2807SJeff Garzik 530cca3974eSJeff Garzik for (i = 0; i < host->n_ports; i++) { 531cca3974eSJeff Garzik struct ata_port *ap = host->ports[i]; 532c6fd2807SJeff Garzik u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2); 533c6fd2807SJeff Garzik 534c6fd2807SJeff Garzik /* turn off SATA_IRQ if not supported */ 535c6fd2807SJeff Garzik if (ap->flags & SIL_FLAG_NO_SATA_IRQ) 536c6fd2807SJeff Garzik bmdma2 &= ~SIL_DMA_SATA_IRQ; 537c6fd2807SJeff Garzik 538c6fd2807SJeff Garzik if (bmdma2 == 0xffffffff || 539c6fd2807SJeff Garzik !(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ))) 540c6fd2807SJeff Garzik continue; 541c6fd2807SJeff Garzik 542c6fd2807SJeff Garzik sil_host_intr(ap, bmdma2); 543c6fd2807SJeff Garzik handled = 1; 544c6fd2807SJeff Garzik } 545c6fd2807SJeff Garzik 546cca3974eSJeff Garzik spin_unlock(&host->lock); 547c6fd2807SJeff Garzik 548c6fd2807SJeff Garzik return IRQ_RETVAL(handled); 549c6fd2807SJeff Garzik } 550c6fd2807SJeff Garzik 551c6fd2807SJeff Garzik static void sil_freeze(struct ata_port *ap) 552c6fd2807SJeff Garzik { 5530d5ff566STejun Heo void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 554c6fd2807SJeff Garzik u32 tmp; 555c6fd2807SJeff Garzik 556c6fd2807SJeff Garzik /* global IRQ mask doesn't block SATA IRQ, turn off explicitly */ 557c6fd2807SJeff Garzik writel(0, mmio_base + sil_port[ap->port_no].sien); 558c6fd2807SJeff Garzik 559c6fd2807SJeff Garzik /* plug IRQ */ 560c6fd2807SJeff Garzik tmp = readl(mmio_base + SIL_SYSCFG); 561c6fd2807SJeff Garzik tmp |= SIL_MASK_IDE0_INT << ap->port_no; 562c6fd2807SJeff Garzik writel(tmp, mmio_base + SIL_SYSCFG); 563c6fd2807SJeff Garzik readl(mmio_base + SIL_SYSCFG); /* flush */ 5642fc37adbSJeff Garzik 5652fc37adbSJeff Garzik /* Ensure DMA_ENABLE is off. 5662fc37adbSJeff Garzik * 5672fc37adbSJeff Garzik * This is because the controller will not give us access to the 5682fc37adbSJeff Garzik * taskfile registers while a DMA is in progress 5692fc37adbSJeff Garzik */ 5702fc37adbSJeff Garzik iowrite8(ioread8(ap->ioaddr.bmdma_addr) & ~SIL_DMA_ENABLE, 5712fc37adbSJeff Garzik ap->ioaddr.bmdma_addr); 5722fc37adbSJeff Garzik 5732fc37adbSJeff Garzik /* According to ata_bmdma_stop, an HDMA transition requires 5742fc37adbSJeff Garzik * on PIO cycle. But we can't read a taskfile register. 5752fc37adbSJeff Garzik */ 5762fc37adbSJeff Garzik ioread8(ap->ioaddr.bmdma_addr); 577c6fd2807SJeff Garzik } 578c6fd2807SJeff Garzik 579c6fd2807SJeff Garzik static void sil_thaw(struct ata_port *ap) 580c6fd2807SJeff Garzik { 5810d5ff566STejun Heo void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 582c6fd2807SJeff Garzik u32 tmp; 583c6fd2807SJeff Garzik 584c6fd2807SJeff Garzik /* clear IRQ */ 5855682ed33STejun Heo ap->ops->sff_check_status(ap); 58637f65b8bSTejun Heo ata_bmdma_irq_clear(ap); 587c6fd2807SJeff Garzik 588c6fd2807SJeff Garzik /* turn on SATA IRQ if supported */ 589c6fd2807SJeff Garzik if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ)) 590c6fd2807SJeff Garzik writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien); 591c6fd2807SJeff Garzik 592c6fd2807SJeff Garzik /* turn on IRQ */ 593c6fd2807SJeff Garzik tmp = readl(mmio_base + SIL_SYSCFG); 594c6fd2807SJeff Garzik tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no); 595c6fd2807SJeff Garzik writel(tmp, mmio_base + SIL_SYSCFG); 596c6fd2807SJeff Garzik } 597c6fd2807SJeff Garzik 598c6fd2807SJeff Garzik /** 599c6fd2807SJeff Garzik * sil_dev_config - Apply device/host-specific errata fixups 600c6fd2807SJeff Garzik * @dev: Device to be examined 601c6fd2807SJeff Garzik * 602c6fd2807SJeff Garzik * After the IDENTIFY [PACKET] DEVICE step is complete, and a 603c6fd2807SJeff Garzik * device is known to be present, this function is called. 604c6fd2807SJeff Garzik * We apply two errata fixups which are specific to Silicon Image, 605c6fd2807SJeff Garzik * a Seagate and a Maxtor fixup. 606c6fd2807SJeff Garzik * 607c6fd2807SJeff Garzik * For certain Seagate devices, we must limit the maximum sectors 608c6fd2807SJeff Garzik * to under 8K. 609c6fd2807SJeff Garzik * 610c6fd2807SJeff Garzik * For certain Maxtor devices, we must not program the drive 611c6fd2807SJeff Garzik * beyond udma5. 612c6fd2807SJeff Garzik * 613c6fd2807SJeff Garzik * Both fixups are unfairly pessimistic. As soon as I get more 614c6fd2807SJeff Garzik * information on these errata, I will create a more exhaustive 615c6fd2807SJeff Garzik * list, and apply the fixups to only the specific 616c6fd2807SJeff Garzik * devices/hosts/firmwares that need it. 617c6fd2807SJeff Garzik * 618c6fd2807SJeff Garzik * 20040111 - Seagate drives affected by the Mod15Write bug are blacklisted 619c6fd2807SJeff Garzik * The Maxtor quirk is in the blacklist, but I'm keeping the original 620c6fd2807SJeff Garzik * pessimistic fix for the following reasons... 621c6fd2807SJeff Garzik * - There seems to be less info on it, only one device gleaned off the 622c6fd2807SJeff Garzik * Windows driver, maybe only one is affected. More info would be greatly 623c6fd2807SJeff Garzik * appreciated. 624c6fd2807SJeff Garzik * - But then again UDMA5 is hardly anything to complain about 625c6fd2807SJeff Garzik */ 626cd0d3bbcSAlan static void sil_dev_config(struct ata_device *dev) 627c6fd2807SJeff Garzik { 6289af5c9c9STejun Heo struct ata_port *ap = dev->link->ap; 6299af5c9c9STejun Heo int print_info = ap->link.eh_context.i.flags & ATA_EHI_PRINTINFO; 630c6fd2807SJeff Garzik unsigned int n, quirks = 0; 631a0cf733bSTejun Heo unsigned char model_num[ATA_ID_PROD_LEN + 1]; 632c6fd2807SJeff Garzik 633a0cf733bSTejun Heo ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); 634c6fd2807SJeff Garzik 635c6fd2807SJeff Garzik for (n = 0; sil_blacklist[n].product; n++) 636c6fd2807SJeff Garzik if (!strcmp(sil_blacklist[n].product, model_num)) { 637c6fd2807SJeff Garzik quirks = sil_blacklist[n].quirk; 638c6fd2807SJeff Garzik break; 639c6fd2807SJeff Garzik } 640c6fd2807SJeff Garzik 641c6fd2807SJeff Garzik /* limit requests to 15 sectors */ 642c6fd2807SJeff Garzik if (slow_down || 643c6fd2807SJeff Garzik ((ap->flags & SIL_FLAG_MOD15WRITE) && 644c6fd2807SJeff Garzik (quirks & SIL_QUIRK_MOD15WRITE))) { 645efdaedc4STejun Heo if (print_info) 646a9a79dfeSJoe Perches ata_dev_info(dev, 647a9a79dfeSJoe Perches "applying Seagate errata fix (mod15write workaround)\n"); 648c6fd2807SJeff Garzik dev->max_sectors = 15; 649c6fd2807SJeff Garzik return; 650c6fd2807SJeff Garzik } 651c6fd2807SJeff Garzik 652c6fd2807SJeff Garzik /* limit to udma5 */ 653c6fd2807SJeff Garzik if (quirks & SIL_QUIRK_UDMA5MAX) { 654efdaedc4STejun Heo if (print_info) 655a9a79dfeSJoe Perches ata_dev_info(dev, "applying Maxtor errata fix %s\n", 656a9a79dfeSJoe Perches model_num); 657c6fd2807SJeff Garzik dev->udma_mask &= ATA_UDMA5; 658c6fd2807SJeff Garzik return; 659c6fd2807SJeff Garzik } 660c6fd2807SJeff Garzik } 661c6fd2807SJeff Garzik 6624447d351STejun Heo static void sil_init_controller(struct ata_host *host) 663c6fd2807SJeff Garzik { 6644447d351STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 6654447d351STejun Heo void __iomem *mmio_base = host->iomap[SIL_MMIO_BAR]; 666c6fd2807SJeff Garzik u8 cls; 667c6fd2807SJeff Garzik u32 tmp; 668c6fd2807SJeff Garzik int i; 669c6fd2807SJeff Garzik 670c6fd2807SJeff Garzik /* Initialize FIFO PCI bus arbitration */ 671c6fd2807SJeff Garzik cls = sil_get_device_cache_line(pdev); 672c6fd2807SJeff Garzik if (cls) { 673c6fd2807SJeff Garzik cls >>= 3; 674c6fd2807SJeff Garzik cls++; /* cls = (line_size/8)+1 */ 6754447d351STejun Heo for (i = 0; i < host->n_ports; i++) 676c6fd2807SJeff Garzik writew(cls << 8 | cls, 677c6fd2807SJeff Garzik mmio_base + sil_port[i].fifo_cfg); 678c6fd2807SJeff Garzik } else 679a44fec1fSJoe Perches dev_warn(&pdev->dev, 680c6fd2807SJeff Garzik "cache line size not set. Driver may not function\n"); 681c6fd2807SJeff Garzik 682c6fd2807SJeff Garzik /* Apply R_ERR on DMA activate FIS errata workaround */ 6834447d351STejun Heo if (host->ports[0]->flags & SIL_FLAG_RERR_ON_DMA_ACT) { 684c6fd2807SJeff Garzik int cnt; 685c6fd2807SJeff Garzik 6864447d351STejun Heo for (i = 0, cnt = 0; i < host->n_ports; i++) { 687c6fd2807SJeff Garzik tmp = readl(mmio_base + sil_port[i].sfis_cfg); 688c6fd2807SJeff Garzik if ((tmp & 0x3) != 0x01) 689c6fd2807SJeff Garzik continue; 690c6fd2807SJeff Garzik if (!cnt) 691a44fec1fSJoe Perches dev_info(&pdev->dev, 692a44fec1fSJoe Perches "Applying R_ERR on DMA activate FIS errata fix\n"); 693c6fd2807SJeff Garzik writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg); 694c6fd2807SJeff Garzik cnt++; 695c6fd2807SJeff Garzik } 696c6fd2807SJeff Garzik } 697c6fd2807SJeff Garzik 6984447d351STejun Heo if (host->n_ports == 4) { 699c6fd2807SJeff Garzik /* flip the magic "make 4 ports work" bit */ 700c6fd2807SJeff Garzik tmp = readl(mmio_base + sil_port[2].bmdma); 701c6fd2807SJeff Garzik if ((tmp & SIL_INTR_STEERING) == 0) 702c6fd2807SJeff Garzik writel(tmp | SIL_INTR_STEERING, 703c6fd2807SJeff Garzik mmio_base + sil_port[2].bmdma); 704c6fd2807SJeff Garzik } 705c6fd2807SJeff Garzik } 706c6fd2807SJeff Garzik 707e57db7bdSRafael J. Wysocki static bool sil_broken_system_poweroff(struct pci_dev *pdev) 708e57db7bdSRafael J. Wysocki { 709e57db7bdSRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 710e57db7bdSRafael J. Wysocki { 711e57db7bdSRafael J. Wysocki .ident = "HP Compaq nx6325", 712e57db7bdSRafael J. Wysocki .matches = { 713e57db7bdSRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 714e57db7bdSRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"), 715e57db7bdSRafael J. Wysocki }, 716e57db7bdSRafael J. Wysocki /* PCI slot number of the controller */ 717e57db7bdSRafael J. Wysocki .driver_data = (void *)0x12UL, 718e57db7bdSRafael J. Wysocki }, 719e57db7bdSRafael J. Wysocki 720e57db7bdSRafael J. Wysocki { } /* terminate list */ 721e57db7bdSRafael J. Wysocki }; 722e57db7bdSRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 723e57db7bdSRafael J. Wysocki 724e57db7bdSRafael J. Wysocki if (dmi) { 725e57db7bdSRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 726e57db7bdSRafael J. Wysocki /* apply the quirk only to on-board controllers */ 727e57db7bdSRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 728e57db7bdSRafael J. Wysocki } 729e57db7bdSRafael J. Wysocki 730e57db7bdSRafael J. Wysocki return false; 731e57db7bdSRafael J. Wysocki } 732e57db7bdSRafael J. Wysocki 733c6fd2807SJeff Garzik static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 734c6fd2807SJeff Garzik { 7354447d351STejun Heo int board_id = ent->driver_data; 736e57db7bdSRafael J. Wysocki struct ata_port_info pi = sil_port_info[board_id]; 737e57db7bdSRafael J. Wysocki const struct ata_port_info *ppi[] = { &pi, NULL }; 7384447d351STejun Heo struct ata_host *host; 739c6fd2807SJeff Garzik void __iomem *mmio_base; 7404447d351STejun Heo int n_ports, rc; 741c6fd2807SJeff Garzik unsigned int i; 742c6fd2807SJeff Garzik 74306296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 744c6fd2807SJeff Garzik 7454447d351STejun Heo /* allocate host */ 7464447d351STejun Heo n_ports = 2; 7474447d351STejun Heo if (board_id == sil_3114) 7484447d351STejun Heo n_ports = 4; 7494447d351STejun Heo 750e57db7bdSRafael J. Wysocki if (sil_broken_system_poweroff(pdev)) { 751e57db7bdSRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN | 752e57db7bdSRafael J. Wysocki ATA_FLAG_NO_HIBERNATE_SPINDOWN; 753e57db7bdSRafael J. Wysocki dev_info(&pdev->dev, "quirky BIOS, skipping spindown " 754e57db7bdSRafael J. Wysocki "on poweroff and hibernation\n"); 755e57db7bdSRafael J. Wysocki } 756e57db7bdSRafael J. Wysocki 7574447d351STejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 7584447d351STejun Heo if (!host) 7594447d351STejun Heo return -ENOMEM; 7604447d351STejun Heo 7614447d351STejun Heo /* acquire resources and fill host */ 76224dc5f33STejun Heo rc = pcim_enable_device(pdev); 763c6fd2807SJeff Garzik if (rc) 764c6fd2807SJeff Garzik return rc; 765c6fd2807SJeff Garzik 7660d5ff566STejun Heo rc = pcim_iomap_regions(pdev, 1 << SIL_MMIO_BAR, DRV_NAME); 7670d5ff566STejun Heo if (rc == -EBUSY) 76824dc5f33STejun Heo pcim_pin_device(pdev); 7690d5ff566STejun Heo if (rc) 77024dc5f33STejun Heo return rc; 7714447d351STejun Heo host->iomap = pcim_iomap_table(pdev); 772c6fd2807SJeff Garzik 773c6fd2807SJeff Garzik rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); 774c6fd2807SJeff Garzik if (rc) 77524dc5f33STejun Heo return rc; 776c6fd2807SJeff Garzik rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); 777c6fd2807SJeff Garzik if (rc) 77824dc5f33STejun Heo return rc; 779c6fd2807SJeff Garzik 7804447d351STejun Heo mmio_base = host->iomap[SIL_MMIO_BAR]; 781c6fd2807SJeff Garzik 7824447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 783cbcdd875STejun Heo struct ata_port *ap = host->ports[i]; 784cbcdd875STejun Heo struct ata_ioports *ioaddr = &ap->ioaddr; 785c6fd2807SJeff Garzik 7864447d351STejun Heo ioaddr->cmd_addr = mmio_base + sil_port[i].tf; 7874447d351STejun Heo ioaddr->altstatus_addr = 7884447d351STejun Heo ioaddr->ctl_addr = mmio_base + sil_port[i].ctl; 7894447d351STejun Heo ioaddr->bmdma_addr = mmio_base + sil_port[i].bmdma; 7904447d351STejun Heo ioaddr->scr_addr = mmio_base + sil_port[i].scr; 7919363c382STejun Heo ata_sff_std_ports(ioaddr); 792cbcdd875STejun Heo 793cbcdd875STejun Heo ata_port_pbar_desc(ap, SIL_MMIO_BAR, -1, "mmio"); 794cbcdd875STejun Heo ata_port_pbar_desc(ap, SIL_MMIO_BAR, sil_port[i].tf, "tf"); 795c6fd2807SJeff Garzik } 796c6fd2807SJeff Garzik 7974447d351STejun Heo /* initialize and activate */ 7984447d351STejun Heo sil_init_controller(host); 799c6fd2807SJeff Garzik 800c6fd2807SJeff Garzik pci_set_master(pdev); 8014447d351STejun Heo return ata_host_activate(host, pdev->irq, sil_interrupt, IRQF_SHARED, 8024447d351STejun Heo &sil_sht); 803c6fd2807SJeff Garzik } 804c6fd2807SJeff Garzik 805281d426cSAlexey Dobriyan #ifdef CONFIG_PM 806c6fd2807SJeff Garzik static int sil_pci_device_resume(struct pci_dev *pdev) 807c6fd2807SJeff Garzik { 808cca3974eSJeff Garzik struct ata_host *host = dev_get_drvdata(&pdev->dev); 809553c4aa6STejun Heo int rc; 810c6fd2807SJeff Garzik 811553c4aa6STejun Heo rc = ata_pci_device_do_resume(pdev); 812553c4aa6STejun Heo if (rc) 813553c4aa6STejun Heo return rc; 814553c4aa6STejun Heo 8154447d351STejun Heo sil_init_controller(host); 816cca3974eSJeff Garzik ata_host_resume(host); 817c6fd2807SJeff Garzik 818c6fd2807SJeff Garzik return 0; 819c6fd2807SJeff Garzik } 820281d426cSAlexey Dobriyan #endif 821c6fd2807SJeff Garzik 8222fc75da0SAxel Lin module_pci_driver(sil_pci_driver); 823