1c82ee6d3SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2c6fd2807SJeff Garzik /* 3c6fd2807SJeff Garzik * sata_sil.c - Silicon Image SATA 4c6fd2807SJeff Garzik * 58c3d3d4bSTejun Heo * Maintained by: Tejun Heo <tj@kernel.org> 6c6fd2807SJeff Garzik * Please ALWAYS copy linux-ide@vger.kernel.org 7c6fd2807SJeff Garzik * on emails. 8c6fd2807SJeff Garzik * 9c6fd2807SJeff Garzik * Copyright 2003-2005 Red Hat, Inc. 10c6fd2807SJeff Garzik * Copyright 2003 Benjamin Herrenschmidt 11c6fd2807SJeff Garzik * 12c6fd2807SJeff Garzik * libata documentation is available via 'make {ps|pdf}docs', 1319285f3cSMauro Carvalho Chehab * as Documentation/driver-api/libata.rst 14c6fd2807SJeff Garzik * 15c6fd2807SJeff Garzik * Documentation for SiI 3112: 16c6fd2807SJeff Garzik * http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2 17c6fd2807SJeff Garzik * 18c6fd2807SJeff Garzik * Other errata and documentation available under NDA. 19c6fd2807SJeff Garzik */ 20c6fd2807SJeff Garzik 21c6fd2807SJeff Garzik #include <linux/kernel.h> 22c6fd2807SJeff Garzik #include <linux/module.h> 23c6fd2807SJeff Garzik #include <linux/pci.h> 24c6fd2807SJeff Garzik #include <linux/blkdev.h> 25c6fd2807SJeff Garzik #include <linux/delay.h> 26c6fd2807SJeff Garzik #include <linux/interrupt.h> 27c6fd2807SJeff Garzik #include <linux/device.h> 28c6fd2807SJeff Garzik #include <scsi/scsi_host.h> 29c6fd2807SJeff Garzik #include <linux/libata.h> 301737ef75SAlexander Beregalov #include <linux/dmi.h> 31c6fd2807SJeff Garzik 32c6fd2807SJeff Garzik #define DRV_NAME "sata_sil" 33c7e324f1SRobert Hancock #define DRV_VERSION "2.4" 34c7e324f1SRobert Hancock 35c7e324f1SRobert Hancock #define SIL_DMA_BOUNDARY 0x7fffffffUL 36c6fd2807SJeff Garzik 37c6fd2807SJeff Garzik enum { 380d5ff566STejun Heo SIL_MMIO_BAR = 5, 390d5ff566STejun Heo 40c6fd2807SJeff Garzik /* 41c6fd2807SJeff Garzik * host flags 42c6fd2807SJeff Garzik */ 43c6fd2807SJeff Garzik SIL_FLAG_NO_SATA_IRQ = (1 << 28), 44c6fd2807SJeff Garzik SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29), 45c6fd2807SJeff Garzik SIL_FLAG_MOD15WRITE = (1 << 30), 46c6fd2807SJeff Garzik 479cbe056fSSergei Shtylyov SIL_DFL_PORT_FLAGS = ATA_FLAG_SATA, 48c6fd2807SJeff Garzik 49c6fd2807SJeff Garzik /* 50c6fd2807SJeff Garzik * Controller IDs 51c6fd2807SJeff Garzik */ 52c6fd2807SJeff Garzik sil_3112 = 0, 53c6fd2807SJeff Garzik sil_3112_no_sata_irq = 1, 54c6fd2807SJeff Garzik sil_3512 = 2, 55c6fd2807SJeff Garzik sil_3114 = 3, 56c6fd2807SJeff Garzik 57c6fd2807SJeff Garzik /* 58c6fd2807SJeff Garzik * Register offsets 59c6fd2807SJeff Garzik */ 60c6fd2807SJeff Garzik SIL_SYSCFG = 0x48, 61c6fd2807SJeff Garzik 62c6fd2807SJeff Garzik /* 63c6fd2807SJeff Garzik * Register bits 64c6fd2807SJeff Garzik */ 65c6fd2807SJeff Garzik /* SYSCFG */ 66c6fd2807SJeff Garzik SIL_MASK_IDE0_INT = (1 << 22), 67c6fd2807SJeff Garzik SIL_MASK_IDE1_INT = (1 << 23), 68c6fd2807SJeff Garzik SIL_MASK_IDE2_INT = (1 << 24), 69c6fd2807SJeff Garzik SIL_MASK_IDE3_INT = (1 << 25), 70c6fd2807SJeff Garzik SIL_MASK_2PORT = SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT, 71c6fd2807SJeff Garzik SIL_MASK_4PORT = SIL_MASK_2PORT | 72c6fd2807SJeff Garzik SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT, 73c6fd2807SJeff Garzik 74c6fd2807SJeff Garzik /* BMDMA/BMDMA2 */ 75c6fd2807SJeff Garzik SIL_INTR_STEERING = (1 << 1), 76c6fd2807SJeff Garzik 77c6fd2807SJeff Garzik SIL_DMA_ENABLE = (1 << 0), /* DMA run switch */ 78c6fd2807SJeff Garzik SIL_DMA_RDWR = (1 << 3), /* DMA Rd-Wr */ 79c6fd2807SJeff Garzik SIL_DMA_SATA_IRQ = (1 << 4), /* OR of all SATA IRQs */ 80c6fd2807SJeff Garzik SIL_DMA_ACTIVE = (1 << 16), /* DMA running */ 81c6fd2807SJeff Garzik SIL_DMA_ERROR = (1 << 17), /* PCI bus error */ 82c6fd2807SJeff Garzik SIL_DMA_COMPLETE = (1 << 18), /* cmd complete / IRQ pending */ 83c6fd2807SJeff Garzik SIL_DMA_N_SATA_IRQ = (1 << 6), /* SATA_IRQ for the next channel */ 84c6fd2807SJeff Garzik SIL_DMA_N_ACTIVE = (1 << 24), /* ACTIVE for the next channel */ 85c6fd2807SJeff Garzik SIL_DMA_N_ERROR = (1 << 25), /* ERROR for the next channel */ 86c6fd2807SJeff Garzik SIL_DMA_N_COMPLETE = (1 << 26), /* COMPLETE for the next channel */ 87c6fd2807SJeff Garzik 88c6fd2807SJeff Garzik /* SIEN */ 89c6fd2807SJeff Garzik SIL_SIEN_N = (1 << 16), /* triggered by SError.N */ 90c6fd2807SJeff Garzik 91c6fd2807SJeff Garzik /* 92c6fd2807SJeff Garzik * Others 93c6fd2807SJeff Garzik */ 94c6fd2807SJeff Garzik SIL_QUIRK_MOD15WRITE = (1 << 0), 95c6fd2807SJeff Garzik SIL_QUIRK_UDMA5MAX = (1 << 1), 96c6fd2807SJeff Garzik }; 97c6fd2807SJeff Garzik 98c6fd2807SJeff Garzik static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 9958eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP 100c6fd2807SJeff Garzik static int sil_pci_device_resume(struct pci_dev *pdev); 101281d426cSAlexey Dobriyan #endif 102cd0d3bbcSAlan static void sil_dev_config(struct ata_device *dev); 10382ef04fbSTejun Heo static int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); 10482ef04fbSTejun Heo static int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); 1050260731fSTejun Heo static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed); 106c7e324f1SRobert Hancock static void sil_qc_prep(struct ata_queued_cmd *qc); 107c7e324f1SRobert Hancock static void sil_bmdma_setup(struct ata_queued_cmd *qc); 108c7e324f1SRobert Hancock static void sil_bmdma_start(struct ata_queued_cmd *qc); 109c7e324f1SRobert Hancock static void sil_bmdma_stop(struct ata_queued_cmd *qc); 110c6fd2807SJeff Garzik static void sil_freeze(struct ata_port *ap); 111c6fd2807SJeff Garzik static void sil_thaw(struct ata_port *ap); 112c6fd2807SJeff Garzik 113c6fd2807SJeff Garzik 114c6fd2807SJeff Garzik static const struct pci_device_id sil_pci_tbl[] = { 11554bb3a94SJeff Garzik { PCI_VDEVICE(CMD, 0x3112), sil_3112 }, 11654bb3a94SJeff Garzik { PCI_VDEVICE(CMD, 0x0240), sil_3112 }, 11754bb3a94SJeff Garzik { PCI_VDEVICE(CMD, 0x3512), sil_3512 }, 11854bb3a94SJeff Garzik { PCI_VDEVICE(CMD, 0x3114), sil_3114 }, 11954bb3a94SJeff Garzik { PCI_VDEVICE(ATI, 0x436e), sil_3112 }, 12054bb3a94SJeff Garzik { PCI_VDEVICE(ATI, 0x4379), sil_3112_no_sata_irq }, 12154bb3a94SJeff Garzik { PCI_VDEVICE(ATI, 0x437a), sil_3112_no_sata_irq }, 12254bb3a94SJeff Garzik 123c6fd2807SJeff Garzik { } /* terminate list */ 124c6fd2807SJeff Garzik }; 125c6fd2807SJeff Garzik 126c6fd2807SJeff Garzik 127c6fd2807SJeff Garzik /* TODO firmware versions should be added - eric */ 128c6fd2807SJeff Garzik static const struct sil_drivelist { 129c6fd2807SJeff Garzik const char *product; 130c6fd2807SJeff Garzik unsigned int quirk; 131c6fd2807SJeff Garzik } sil_blacklist [] = { 132c6fd2807SJeff Garzik { "ST320012AS", SIL_QUIRK_MOD15WRITE }, 133c6fd2807SJeff Garzik { "ST330013AS", SIL_QUIRK_MOD15WRITE }, 134c6fd2807SJeff Garzik { "ST340017AS", SIL_QUIRK_MOD15WRITE }, 135c6fd2807SJeff Garzik { "ST360015AS", SIL_QUIRK_MOD15WRITE }, 136c6fd2807SJeff Garzik { "ST380023AS", SIL_QUIRK_MOD15WRITE }, 137c6fd2807SJeff Garzik { "ST3120023AS", SIL_QUIRK_MOD15WRITE }, 138c6fd2807SJeff Garzik { "ST340014ASL", SIL_QUIRK_MOD15WRITE }, 139c6fd2807SJeff Garzik { "ST360014ASL", SIL_QUIRK_MOD15WRITE }, 140c6fd2807SJeff Garzik { "ST380011ASL", SIL_QUIRK_MOD15WRITE }, 141c6fd2807SJeff Garzik { "ST3120022ASL", SIL_QUIRK_MOD15WRITE }, 142c6fd2807SJeff Garzik { "ST3160021ASL", SIL_QUIRK_MOD15WRITE }, 1439f9c47f0STejun Heo { "TOSHIBA MK2561GSYN", SIL_QUIRK_MOD15WRITE }, 144c6fd2807SJeff Garzik { "Maxtor 4D060H3", SIL_QUIRK_UDMA5MAX }, 145c6fd2807SJeff Garzik { } 146c6fd2807SJeff Garzik }; 147c6fd2807SJeff Garzik 148c6fd2807SJeff Garzik static struct pci_driver sil_pci_driver = { 149c6fd2807SJeff Garzik .name = DRV_NAME, 150c6fd2807SJeff Garzik .id_table = sil_pci_tbl, 151c6fd2807SJeff Garzik .probe = sil_init_one, 152c6fd2807SJeff Garzik .remove = ata_pci_remove_one, 15358eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP 154c6fd2807SJeff Garzik .suspend = ata_pci_device_suspend, 155c6fd2807SJeff Garzik .resume = sil_pci_device_resume, 156281d426cSAlexey Dobriyan #endif 157c6fd2807SJeff Garzik }; 158c6fd2807SJeff Garzik 159c6fd2807SJeff Garzik static struct scsi_host_template sil_sht = { 160c7e324f1SRobert Hancock ATA_BASE_SHT(DRV_NAME), 161c7e324f1SRobert Hancock /** These controllers support Large Block Transfer which allows 162c7e324f1SRobert Hancock transfer chunks up to 2GB and which cross 64KB boundaries, 163c7e324f1SRobert Hancock therefore the DMA limits are more relaxed than standard ATA SFF. */ 164c7e324f1SRobert Hancock .dma_boundary = SIL_DMA_BOUNDARY, 165c7e324f1SRobert Hancock .sg_tablesize = ATA_MAX_PRD 166c6fd2807SJeff Garzik }; 167c6fd2807SJeff Garzik 168029cfd6bSTejun Heo static struct ata_port_operations sil_ops = { 16931f80112SRobert Hancock .inherits = &ata_bmdma32_port_ops, 170c6fd2807SJeff Garzik .dev_config = sil_dev_config, 1719d2c7c75SAlan Cox .set_mode = sil_set_mode, 172c7e324f1SRobert Hancock .bmdma_setup = sil_bmdma_setup, 173c7e324f1SRobert Hancock .bmdma_start = sil_bmdma_start, 174c7e324f1SRobert Hancock .bmdma_stop = sil_bmdma_stop, 175c7e324f1SRobert Hancock .qc_prep = sil_qc_prep, 176c6fd2807SJeff Garzik .freeze = sil_freeze, 177c6fd2807SJeff Garzik .thaw = sil_thaw, 178c6fd2807SJeff Garzik .scr_read = sil_scr_read, 179c6fd2807SJeff Garzik .scr_write = sil_scr_write, 180c6fd2807SJeff Garzik }; 181c6fd2807SJeff Garzik 182c6fd2807SJeff Garzik static const struct ata_port_info sil_port_info[] = { 183c6fd2807SJeff Garzik /* sil_3112 */ 184c6fd2807SJeff Garzik { 185cca3974eSJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE, 18614bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 18714bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 188bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5, 189c6fd2807SJeff Garzik .port_ops = &sil_ops, 190c6fd2807SJeff Garzik }, 191c6fd2807SJeff Garzik /* sil_3112_no_sata_irq */ 192c6fd2807SJeff Garzik { 193cca3974eSJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE | 194c6fd2807SJeff Garzik SIL_FLAG_NO_SATA_IRQ, 19514bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 19614bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 197bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5, 198c6fd2807SJeff Garzik .port_ops = &sil_ops, 199c6fd2807SJeff Garzik }, 200c6fd2807SJeff Garzik /* sil_3512 */ 201c6fd2807SJeff Garzik { 202cca3974eSJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, 20314bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4, 20414bdef98SErik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 205bf6263a8SJeff Garzik .udma_mask = ATA_UDMA5, 206c6fd2807SJeff Garzik .port_ops = &sil_ops, 207c6fd2807SJeff Garzik }, 208c6fd2807SJeff Garzik /* sil_3114 */ 209c6fd2807SJeff Garzik { 210cca3974eSJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, 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 }; 217c6fd2807SJeff Garzik 218c6fd2807SJeff Garzik /* per-port register offsets */ 219c6fd2807SJeff Garzik /* TODO: we can probably calculate rather than use a table */ 220c6fd2807SJeff Garzik static const struct { 221c6fd2807SJeff Garzik unsigned long tf; /* ATA taskfile register block */ 222c6fd2807SJeff Garzik unsigned long ctl; /* ATA control/altstatus register block */ 223c6fd2807SJeff Garzik unsigned long bmdma; /* DMA register block */ 224c6fd2807SJeff Garzik unsigned long bmdma2; /* DMA register block #2 */ 225c6fd2807SJeff Garzik unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */ 226c6fd2807SJeff Garzik unsigned long scr; /* SATA control register block */ 227c6fd2807SJeff Garzik unsigned long sien; /* SATA Interrupt Enable register */ 228c6fd2807SJeff Garzik unsigned long xfer_mode;/* data transfer mode register */ 229c6fd2807SJeff Garzik unsigned long sfis_cfg; /* SATA FIS reception config register */ 230c6fd2807SJeff Garzik } sil_port[] = { 231c6fd2807SJeff Garzik /* port 0 ... */ 2325bcd7a00SJeff Garzik /* tf ctl bmdma bmdma2 fifo scr sien mode sfis */ 2335bcd7a00SJeff Garzik { 0x80, 0x8A, 0x0, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c }, 2345bcd7a00SJeff Garzik { 0xC0, 0xCA, 0x8, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc }, 235c6fd2807SJeff Garzik { 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c }, 236c6fd2807SJeff Garzik { 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc }, 237c6fd2807SJeff Garzik /* ... port 3 */ 238c6fd2807SJeff Garzik }; 239c6fd2807SJeff Garzik 240c6fd2807SJeff Garzik MODULE_AUTHOR("Jeff Garzik"); 241c6fd2807SJeff Garzik MODULE_DESCRIPTION("low-level driver for Silicon Image SATA controller"); 242c6fd2807SJeff Garzik MODULE_LICENSE("GPL"); 243c6fd2807SJeff Garzik MODULE_DEVICE_TABLE(pci, sil_pci_tbl); 244c6fd2807SJeff Garzik MODULE_VERSION(DRV_VERSION); 245c6fd2807SJeff Garzik 2465796d1c4SJeff Garzik static int slow_down; 247c6fd2807SJeff Garzik module_param(slow_down, int, 0444); 248c6fd2807SJeff Garzik MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)"); 249c6fd2807SJeff Garzik 250c6fd2807SJeff Garzik 251c7e324f1SRobert Hancock static void sil_bmdma_stop(struct ata_queued_cmd *qc) 252c7e324f1SRobert Hancock { 253c7e324f1SRobert Hancock struct ata_port *ap = qc->ap; 254c7e324f1SRobert Hancock void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 255c7e324f1SRobert Hancock void __iomem *bmdma2 = mmio_base + sil_port[ap->port_no].bmdma2; 256c7e324f1SRobert Hancock 257c7e324f1SRobert Hancock /* clear start/stop bit - can safely always write 0 */ 258c7e324f1SRobert Hancock iowrite8(0, bmdma2); 259c7e324f1SRobert Hancock 260c7e324f1SRobert Hancock /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ 261c7e324f1SRobert Hancock ata_sff_dma_pause(ap); 262c7e324f1SRobert Hancock } 263c7e324f1SRobert Hancock 264c7e324f1SRobert Hancock static void sil_bmdma_setup(struct ata_queued_cmd *qc) 265c7e324f1SRobert Hancock { 266c7e324f1SRobert Hancock struct ata_port *ap = qc->ap; 267c7e324f1SRobert Hancock void __iomem *bmdma = ap->ioaddr.bmdma_addr; 268c7e324f1SRobert Hancock 269c7e324f1SRobert Hancock /* load PRD table addr. */ 270f60d7011STejun Heo iowrite32(ap->bmdma_prd_dma, bmdma + ATA_DMA_TABLE_OFS); 271c7e324f1SRobert Hancock 272c7e324f1SRobert Hancock /* issue r/w command */ 273c7e324f1SRobert Hancock ap->ops->sff_exec_command(ap, &qc->tf); 274c7e324f1SRobert Hancock } 275c7e324f1SRobert Hancock 276c7e324f1SRobert Hancock static void sil_bmdma_start(struct ata_queued_cmd *qc) 277c7e324f1SRobert Hancock { 278c7e324f1SRobert Hancock unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); 279c7e324f1SRobert Hancock struct ata_port *ap = qc->ap; 280c7e324f1SRobert Hancock void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 281c7e324f1SRobert Hancock void __iomem *bmdma2 = mmio_base + sil_port[ap->port_no].bmdma2; 282c7e324f1SRobert Hancock u8 dmactl = ATA_DMA_START; 283c7e324f1SRobert Hancock 284c7e324f1SRobert Hancock /* set transfer direction, start host DMA transaction 285c7e324f1SRobert Hancock Note: For Large Block Transfer to work, the DMA must be started 286c7e324f1SRobert Hancock using the bmdma2 register. */ 287c7e324f1SRobert Hancock if (!rw) 288c7e324f1SRobert Hancock dmactl |= ATA_DMA_WR; 289c7e324f1SRobert Hancock iowrite8(dmactl, bmdma2); 290c7e324f1SRobert Hancock } 291c7e324f1SRobert Hancock 292c7e324f1SRobert Hancock /* The way God intended PCI IDE scatter/gather lists to look and behave... */ 293c7e324f1SRobert Hancock static void sil_fill_sg(struct ata_queued_cmd *qc) 294c7e324f1SRobert Hancock { 295c7e324f1SRobert Hancock struct scatterlist *sg; 296c7e324f1SRobert Hancock struct ata_port *ap = qc->ap; 297f60d7011STejun Heo struct ata_bmdma_prd *prd, *last_prd = NULL; 298c7e324f1SRobert Hancock unsigned int si; 299c7e324f1SRobert Hancock 300f60d7011STejun Heo prd = &ap->bmdma_prd[0]; 301c7e324f1SRobert Hancock for_each_sg(qc->sg, sg, qc->n_elem, si) { 302c7e324f1SRobert Hancock /* Note h/w doesn't support 64-bit, so we unconditionally 303c7e324f1SRobert Hancock * truncate dma_addr_t to u32. 304c7e324f1SRobert Hancock */ 305c7e324f1SRobert Hancock u32 addr = (u32) sg_dma_address(sg); 306c7e324f1SRobert Hancock u32 sg_len = sg_dma_len(sg); 307c7e324f1SRobert Hancock 308c7e324f1SRobert Hancock prd->addr = cpu_to_le32(addr); 309c7e324f1SRobert Hancock prd->flags_len = cpu_to_le32(sg_len); 31041137aa6SPasi Kärkkäinen VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", si, addr, sg_len); 311c7e324f1SRobert Hancock 312c7e324f1SRobert Hancock last_prd = prd; 313c7e324f1SRobert Hancock prd++; 314c7e324f1SRobert Hancock } 315c7e324f1SRobert Hancock 316c7e324f1SRobert Hancock if (likely(last_prd)) 317c7e324f1SRobert Hancock last_prd->flags_len |= cpu_to_le32(ATA_PRD_EOT); 318c7e324f1SRobert Hancock } 319c7e324f1SRobert Hancock 320c7e324f1SRobert Hancock static void sil_qc_prep(struct ata_queued_cmd *qc) 321c7e324f1SRobert Hancock { 322c7e324f1SRobert Hancock if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 323c7e324f1SRobert Hancock return; 324c7e324f1SRobert Hancock 325c7e324f1SRobert Hancock sil_fill_sg(qc); 326c7e324f1SRobert Hancock } 327c7e324f1SRobert Hancock 328c6fd2807SJeff Garzik static unsigned char sil_get_device_cache_line(struct pci_dev *pdev) 329c6fd2807SJeff Garzik { 330c6fd2807SJeff Garzik u8 cache_line = 0; 331c6fd2807SJeff Garzik pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line); 332c6fd2807SJeff Garzik return cache_line; 333c6fd2807SJeff Garzik } 334c6fd2807SJeff Garzik 3359d2c7c75SAlan Cox /** 3369d2c7c75SAlan Cox * sil_set_mode - wrap set_mode functions 3370260731fSTejun Heo * @link: link to set up 3389d2c7c75SAlan Cox * @r_failed: returned device when we fail 3399d2c7c75SAlan Cox * 3409d2c7c75SAlan Cox * Wrap the libata method for device setup as after the setup we need 3419d2c7c75SAlan Cox * to inspect the results and do some configuration work 3429d2c7c75SAlan Cox */ 3439d2c7c75SAlan Cox 3440260731fSTejun Heo static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed) 345c6fd2807SJeff Garzik { 3460260731fSTejun Heo struct ata_port *ap = link->ap; 3470260731fSTejun Heo void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 3480d5ff566STejun Heo void __iomem *addr = mmio_base + sil_port[ap->port_no].xfer_mode; 3490260731fSTejun Heo struct ata_device *dev; 350f58229f8STejun Heo u32 tmp, dev_mode[2] = { }; 3519d2c7c75SAlan Cox int rc; 3529d2c7c75SAlan Cox 3530260731fSTejun Heo rc = ata_do_set_mode(link, r_failed); 3549d2c7c75SAlan Cox if (rc) 3559d2c7c75SAlan Cox return rc; 356c6fd2807SJeff Garzik 3571eca4365STejun Heo ata_for_each_dev(dev, link, ALL) { 358c6fd2807SJeff Garzik if (!ata_dev_enabled(dev)) 359f58229f8STejun Heo dev_mode[dev->devno] = 0; /* PIO0/1/2 */ 360c6fd2807SJeff Garzik else if (dev->flags & ATA_DFLAG_PIO) 361f58229f8STejun Heo dev_mode[dev->devno] = 1; /* PIO3/4 */ 362c6fd2807SJeff Garzik else 363f58229f8STejun Heo dev_mode[dev->devno] = 3; /* UDMA */ 364c6fd2807SJeff Garzik /* value 2 indicates MDMA */ 365c6fd2807SJeff Garzik } 366c6fd2807SJeff Garzik 367c6fd2807SJeff Garzik tmp = readl(addr); 368c6fd2807SJeff Garzik tmp &= ~((1<<5) | (1<<4) | (1<<1) | (1<<0)); 369c6fd2807SJeff Garzik tmp |= dev_mode[0]; 370c6fd2807SJeff Garzik tmp |= (dev_mode[1] << 4); 371c6fd2807SJeff Garzik writel(tmp, addr); 372c6fd2807SJeff Garzik readl(addr); /* flush */ 3739d2c7c75SAlan Cox return 0; 374c6fd2807SJeff Garzik } 375c6fd2807SJeff Garzik 3765796d1c4SJeff Garzik static inline void __iomem *sil_scr_addr(struct ata_port *ap, 3775796d1c4SJeff Garzik unsigned int sc_reg) 378c6fd2807SJeff Garzik { 3790d5ff566STejun Heo void __iomem *offset = ap->ioaddr.scr_addr; 380c6fd2807SJeff Garzik 381c6fd2807SJeff Garzik switch (sc_reg) { 382c6fd2807SJeff Garzik case SCR_STATUS: 383c6fd2807SJeff Garzik return offset + 4; 384c6fd2807SJeff Garzik case SCR_ERROR: 385c6fd2807SJeff Garzik return offset + 8; 386c6fd2807SJeff Garzik case SCR_CONTROL: 387c6fd2807SJeff Garzik return offset; 388c6fd2807SJeff Garzik default: 389c6fd2807SJeff Garzik /* do nothing */ 390c6fd2807SJeff Garzik break; 391c6fd2807SJeff Garzik } 392c6fd2807SJeff Garzik 3938d9db2d2SRandy Dunlap return NULL; 394c6fd2807SJeff Garzik } 395c6fd2807SJeff Garzik 39682ef04fbSTejun Heo static int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) 397c6fd2807SJeff Garzik { 39882ef04fbSTejun Heo void __iomem *mmio = sil_scr_addr(link->ap, sc_reg); 399da3dbb17STejun Heo 400da3dbb17STejun Heo if (mmio) { 401da3dbb17STejun Heo *val = readl(mmio); 402da3dbb17STejun Heo return 0; 403da3dbb17STejun Heo } 404da3dbb17STejun Heo return -EINVAL; 405c6fd2807SJeff Garzik } 406c6fd2807SJeff Garzik 40782ef04fbSTejun Heo static int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) 408c6fd2807SJeff Garzik { 40982ef04fbSTejun Heo void __iomem *mmio = sil_scr_addr(link->ap, sc_reg); 410da3dbb17STejun Heo 411da3dbb17STejun Heo if (mmio) { 412c6fd2807SJeff Garzik writel(val, mmio); 413da3dbb17STejun Heo return 0; 414da3dbb17STejun Heo } 415da3dbb17STejun Heo return -EINVAL; 416c6fd2807SJeff Garzik } 417c6fd2807SJeff Garzik 418c6fd2807SJeff Garzik static void sil_host_intr(struct ata_port *ap, u32 bmdma2) 419c6fd2807SJeff Garzik { 4209af5c9c9STejun Heo struct ata_eh_info *ehi = &ap->link.eh_info; 4219af5c9c9STejun Heo struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag); 422c6fd2807SJeff Garzik u8 status; 423c6fd2807SJeff Garzik 424c6fd2807SJeff Garzik if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) { 425ebd1699eSJeff Garzik u32 serror = 0xffffffff; 426c6fd2807SJeff Garzik 427c6fd2807SJeff Garzik /* SIEN doesn't mask SATA IRQs on some 3112s. Those 428c6fd2807SJeff Garzik * controllers continue to assert IRQ as long as 429c6fd2807SJeff Garzik * SError bits are pending. Clear SError immediately. 430c6fd2807SJeff Garzik */ 43182ef04fbSTejun Heo sil_scr_read(&ap->link, SCR_ERROR, &serror); 43282ef04fbSTejun Heo sil_scr_write(&ap->link, SCR_ERROR, serror); 433c6fd2807SJeff Garzik 4348cf32ac6STejun Heo /* Sometimes spurious interrupts occur, double check 4358cf32ac6STejun Heo * it's PHYRDY CHG. 4368cf32ac6STejun Heo */ 4378cf32ac6STejun Heo if (serror & SERR_PHYRDY_CHG) { 4389af5c9c9STejun Heo ap->link.eh_info.serror |= serror; 439c6fd2807SJeff Garzik goto freeze; 440c6fd2807SJeff Garzik } 441c6fd2807SJeff Garzik 4428cf32ac6STejun Heo if (!(bmdma2 & SIL_DMA_COMPLETE)) 4438cf32ac6STejun Heo return; 4448cf32ac6STejun Heo } 445c6fd2807SJeff Garzik 4468cf32ac6STejun Heo if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { 447e2f8fb72STejun Heo /* this sometimes happens, just clear IRQ */ 4485682ed33STejun Heo ap->ops->sff_check_status(ap); 449e2f8fb72STejun Heo return; 450e2f8fb72STejun Heo } 451e2f8fb72STejun Heo 452c6fd2807SJeff Garzik /* Check whether we are expecting interrupt in this state */ 453c6fd2807SJeff Garzik switch (ap->hsm_task_state) { 454c6fd2807SJeff Garzik case HSM_ST_FIRST: 455c6fd2807SJeff Garzik /* Some pre-ATAPI-4 devices assert INTRQ 456c6fd2807SJeff Garzik * at this state when ready to receive CDB. 457c6fd2807SJeff Garzik */ 458c6fd2807SJeff Garzik 459c6fd2807SJeff Garzik /* Check the ATA_DFLAG_CDB_INTR flag is enough here. 460405e66b3STejun Heo * The flag was turned on only for atapi devices. No 461405e66b3STejun Heo * need to check ata_is_atapi(qc->tf.protocol) again. 462c6fd2807SJeff Garzik */ 463c6fd2807SJeff Garzik if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) 464c6fd2807SJeff Garzik goto err_hsm; 465c6fd2807SJeff Garzik break; 466c6fd2807SJeff Garzik case HSM_ST_LAST: 467405e66b3STejun Heo if (ata_is_dma(qc->tf.protocol)) { 468c6fd2807SJeff Garzik /* clear DMA-Start bit */ 469c6fd2807SJeff Garzik ap->ops->bmdma_stop(qc); 470c6fd2807SJeff Garzik 471c6fd2807SJeff Garzik if (bmdma2 & SIL_DMA_ERROR) { 472c6fd2807SJeff Garzik qc->err_mask |= AC_ERR_HOST_BUS; 473c6fd2807SJeff Garzik ap->hsm_task_state = HSM_ST_ERR; 474c6fd2807SJeff Garzik } 475c6fd2807SJeff Garzik } 476c6fd2807SJeff Garzik break; 477c6fd2807SJeff Garzik case HSM_ST: 478c6fd2807SJeff Garzik break; 479c6fd2807SJeff Garzik default: 480c6fd2807SJeff Garzik goto err_hsm; 481c6fd2807SJeff Garzik } 482c6fd2807SJeff Garzik 483c6fd2807SJeff Garzik /* check main status, clearing INTRQ */ 4845682ed33STejun Heo status = ap->ops->sff_check_status(ap); 485c6fd2807SJeff Garzik if (unlikely(status & ATA_BUSY)) 486c6fd2807SJeff Garzik goto err_hsm; 487c6fd2807SJeff Garzik 488c6fd2807SJeff Garzik /* ack bmdma irq events */ 48937f65b8bSTejun Heo ata_bmdma_irq_clear(ap); 490c6fd2807SJeff Garzik 491c6fd2807SJeff Garzik /* kick HSM in the ass */ 4929363c382STejun Heo ata_sff_hsm_move(ap, qc, status, 0); 493c6fd2807SJeff Garzik 494405e66b3STejun Heo if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol)) 495ea54763fSTejun Heo ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2); 496ea54763fSTejun Heo 497c6fd2807SJeff Garzik return; 498c6fd2807SJeff Garzik 499c6fd2807SJeff Garzik err_hsm: 500c6fd2807SJeff Garzik qc->err_mask |= AC_ERR_HSM; 501c6fd2807SJeff Garzik freeze: 502c6fd2807SJeff Garzik ata_port_freeze(ap); 503c6fd2807SJeff Garzik } 504c6fd2807SJeff Garzik 5057d12e780SDavid Howells static irqreturn_t sil_interrupt(int irq, void *dev_instance) 506c6fd2807SJeff Garzik { 507cca3974eSJeff Garzik struct ata_host *host = dev_instance; 5080d5ff566STejun Heo void __iomem *mmio_base = host->iomap[SIL_MMIO_BAR]; 509c6fd2807SJeff Garzik int handled = 0; 510c6fd2807SJeff Garzik int i; 511c6fd2807SJeff Garzik 512cca3974eSJeff Garzik spin_lock(&host->lock); 513c6fd2807SJeff Garzik 514cca3974eSJeff Garzik for (i = 0; i < host->n_ports; i++) { 515cca3974eSJeff Garzik struct ata_port *ap = host->ports[i]; 516c6fd2807SJeff Garzik u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2); 517c6fd2807SJeff Garzik 518c6fd2807SJeff Garzik /* turn off SATA_IRQ if not supported */ 519c6fd2807SJeff Garzik if (ap->flags & SIL_FLAG_NO_SATA_IRQ) 520c6fd2807SJeff Garzik bmdma2 &= ~SIL_DMA_SATA_IRQ; 521c6fd2807SJeff Garzik 522c6fd2807SJeff Garzik if (bmdma2 == 0xffffffff || 523c6fd2807SJeff Garzik !(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ))) 524c6fd2807SJeff Garzik continue; 525c6fd2807SJeff Garzik 526c6fd2807SJeff Garzik sil_host_intr(ap, bmdma2); 527c6fd2807SJeff Garzik handled = 1; 528c6fd2807SJeff Garzik } 529c6fd2807SJeff Garzik 530cca3974eSJeff Garzik spin_unlock(&host->lock); 531c6fd2807SJeff Garzik 532c6fd2807SJeff Garzik return IRQ_RETVAL(handled); 533c6fd2807SJeff Garzik } 534c6fd2807SJeff Garzik 535c6fd2807SJeff Garzik static void sil_freeze(struct ata_port *ap) 536c6fd2807SJeff Garzik { 5370d5ff566STejun Heo void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 538c6fd2807SJeff Garzik u32 tmp; 539c6fd2807SJeff Garzik 540c6fd2807SJeff Garzik /* global IRQ mask doesn't block SATA IRQ, turn off explicitly */ 541c6fd2807SJeff Garzik writel(0, mmio_base + sil_port[ap->port_no].sien); 542c6fd2807SJeff Garzik 543c6fd2807SJeff Garzik /* plug IRQ */ 544c6fd2807SJeff Garzik tmp = readl(mmio_base + SIL_SYSCFG); 545c6fd2807SJeff Garzik tmp |= SIL_MASK_IDE0_INT << ap->port_no; 546c6fd2807SJeff Garzik writel(tmp, mmio_base + SIL_SYSCFG); 547c6fd2807SJeff Garzik readl(mmio_base + SIL_SYSCFG); /* flush */ 5482fc37adbSJeff Garzik 5492fc37adbSJeff Garzik /* Ensure DMA_ENABLE is off. 5502fc37adbSJeff Garzik * 5512fc37adbSJeff Garzik * This is because the controller will not give us access to the 5522fc37adbSJeff Garzik * taskfile registers while a DMA is in progress 5532fc37adbSJeff Garzik */ 5542fc37adbSJeff Garzik iowrite8(ioread8(ap->ioaddr.bmdma_addr) & ~SIL_DMA_ENABLE, 5552fc37adbSJeff Garzik ap->ioaddr.bmdma_addr); 5562fc37adbSJeff Garzik 5572fc37adbSJeff Garzik /* According to ata_bmdma_stop, an HDMA transition requires 5582fc37adbSJeff Garzik * on PIO cycle. But we can't read a taskfile register. 5592fc37adbSJeff Garzik */ 5602fc37adbSJeff Garzik ioread8(ap->ioaddr.bmdma_addr); 561c6fd2807SJeff Garzik } 562c6fd2807SJeff Garzik 563c6fd2807SJeff Garzik static void sil_thaw(struct ata_port *ap) 564c6fd2807SJeff Garzik { 5650d5ff566STejun Heo void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 566c6fd2807SJeff Garzik u32 tmp; 567c6fd2807SJeff Garzik 568c6fd2807SJeff Garzik /* clear IRQ */ 5695682ed33STejun Heo ap->ops->sff_check_status(ap); 57037f65b8bSTejun Heo ata_bmdma_irq_clear(ap); 571c6fd2807SJeff Garzik 572c6fd2807SJeff Garzik /* turn on SATA IRQ if supported */ 573c6fd2807SJeff Garzik if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ)) 574c6fd2807SJeff Garzik writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien); 575c6fd2807SJeff Garzik 576c6fd2807SJeff Garzik /* turn on IRQ */ 577c6fd2807SJeff Garzik tmp = readl(mmio_base + SIL_SYSCFG); 578c6fd2807SJeff Garzik tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no); 579c6fd2807SJeff Garzik writel(tmp, mmio_base + SIL_SYSCFG); 580c6fd2807SJeff Garzik } 581c6fd2807SJeff Garzik 582c6fd2807SJeff Garzik /** 583c6fd2807SJeff Garzik * sil_dev_config - Apply device/host-specific errata fixups 584c6fd2807SJeff Garzik * @dev: Device to be examined 585c6fd2807SJeff Garzik * 586c6fd2807SJeff Garzik * After the IDENTIFY [PACKET] DEVICE step is complete, and a 587c6fd2807SJeff Garzik * device is known to be present, this function is called. 588c6fd2807SJeff Garzik * We apply two errata fixups which are specific to Silicon Image, 589c6fd2807SJeff Garzik * a Seagate and a Maxtor fixup. 590c6fd2807SJeff Garzik * 591c6fd2807SJeff Garzik * For certain Seagate devices, we must limit the maximum sectors 592c6fd2807SJeff Garzik * to under 8K. 593c6fd2807SJeff Garzik * 594c6fd2807SJeff Garzik * For certain Maxtor devices, we must not program the drive 595c6fd2807SJeff Garzik * beyond udma5. 596c6fd2807SJeff Garzik * 597c6fd2807SJeff Garzik * Both fixups are unfairly pessimistic. As soon as I get more 598c6fd2807SJeff Garzik * information on these errata, I will create a more exhaustive 599c6fd2807SJeff Garzik * list, and apply the fixups to only the specific 600c6fd2807SJeff Garzik * devices/hosts/firmwares that need it. 601c6fd2807SJeff Garzik * 602c6fd2807SJeff Garzik * 20040111 - Seagate drives affected by the Mod15Write bug are blacklisted 603c6fd2807SJeff Garzik * The Maxtor quirk is in the blacklist, but I'm keeping the original 604c6fd2807SJeff Garzik * pessimistic fix for the following reasons... 605c6fd2807SJeff Garzik * - There seems to be less info on it, only one device gleaned off the 606c6fd2807SJeff Garzik * Windows driver, maybe only one is affected. More info would be greatly 607c6fd2807SJeff Garzik * appreciated. 608c6fd2807SJeff Garzik * - But then again UDMA5 is hardly anything to complain about 609c6fd2807SJeff Garzik */ 610cd0d3bbcSAlan static void sil_dev_config(struct ata_device *dev) 611c6fd2807SJeff Garzik { 6129af5c9c9STejun Heo struct ata_port *ap = dev->link->ap; 6139af5c9c9STejun Heo int print_info = ap->link.eh_context.i.flags & ATA_EHI_PRINTINFO; 614c6fd2807SJeff Garzik unsigned int n, quirks = 0; 615a0cf733bSTejun Heo unsigned char model_num[ATA_ID_PROD_LEN + 1]; 616c6fd2807SJeff Garzik 617d98f1cd0SMikulas Patocka /* This controller doesn't support trim */ 618d98f1cd0SMikulas Patocka dev->horkage |= ATA_HORKAGE_NOTRIM; 619d98f1cd0SMikulas Patocka 620a0cf733bSTejun Heo ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); 621c6fd2807SJeff Garzik 622c6fd2807SJeff Garzik for (n = 0; sil_blacklist[n].product; n++) 623c6fd2807SJeff Garzik if (!strcmp(sil_blacklist[n].product, model_num)) { 624c6fd2807SJeff Garzik quirks = sil_blacklist[n].quirk; 625c6fd2807SJeff Garzik break; 626c6fd2807SJeff Garzik } 627c6fd2807SJeff Garzik 628c6fd2807SJeff Garzik /* limit requests to 15 sectors */ 629c6fd2807SJeff Garzik if (slow_down || 630c6fd2807SJeff Garzik ((ap->flags & SIL_FLAG_MOD15WRITE) && 631c6fd2807SJeff Garzik (quirks & SIL_QUIRK_MOD15WRITE))) { 632efdaedc4STejun Heo if (print_info) 633a9a79dfeSJoe Perches ata_dev_info(dev, 634a9a79dfeSJoe Perches "applying Seagate errata fix (mod15write workaround)\n"); 635c6fd2807SJeff Garzik dev->max_sectors = 15; 636c6fd2807SJeff Garzik return; 637c6fd2807SJeff Garzik } 638c6fd2807SJeff Garzik 639c6fd2807SJeff Garzik /* limit to udma5 */ 640c6fd2807SJeff Garzik if (quirks & SIL_QUIRK_UDMA5MAX) { 641efdaedc4STejun Heo if (print_info) 642a9a79dfeSJoe Perches ata_dev_info(dev, "applying Maxtor errata fix %s\n", 643a9a79dfeSJoe Perches model_num); 644c6fd2807SJeff Garzik dev->udma_mask &= ATA_UDMA5; 645c6fd2807SJeff Garzik return; 646c6fd2807SJeff Garzik } 647c6fd2807SJeff Garzik } 648c6fd2807SJeff Garzik 6494447d351STejun Heo static void sil_init_controller(struct ata_host *host) 650c6fd2807SJeff Garzik { 6514447d351STejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 6524447d351STejun Heo void __iomem *mmio_base = host->iomap[SIL_MMIO_BAR]; 653c6fd2807SJeff Garzik u8 cls; 654c6fd2807SJeff Garzik u32 tmp; 655c6fd2807SJeff Garzik int i; 656c6fd2807SJeff Garzik 657c6fd2807SJeff Garzik /* Initialize FIFO PCI bus arbitration */ 658c6fd2807SJeff Garzik cls = sil_get_device_cache_line(pdev); 659c6fd2807SJeff Garzik if (cls) { 660c6fd2807SJeff Garzik cls >>= 3; 661c6fd2807SJeff Garzik cls++; /* cls = (line_size/8)+1 */ 6624447d351STejun Heo for (i = 0; i < host->n_ports; i++) 663c6fd2807SJeff Garzik writew(cls << 8 | cls, 664c6fd2807SJeff Garzik mmio_base + sil_port[i].fifo_cfg); 665c6fd2807SJeff Garzik } else 666a44fec1fSJoe Perches dev_warn(&pdev->dev, 667c6fd2807SJeff Garzik "cache line size not set. Driver may not function\n"); 668c6fd2807SJeff Garzik 669c6fd2807SJeff Garzik /* Apply R_ERR on DMA activate FIS errata workaround */ 6704447d351STejun Heo if (host->ports[0]->flags & SIL_FLAG_RERR_ON_DMA_ACT) { 671c6fd2807SJeff Garzik int cnt; 672c6fd2807SJeff Garzik 6734447d351STejun Heo for (i = 0, cnt = 0; i < host->n_ports; i++) { 674c6fd2807SJeff Garzik tmp = readl(mmio_base + sil_port[i].sfis_cfg); 675c6fd2807SJeff Garzik if ((tmp & 0x3) != 0x01) 676c6fd2807SJeff Garzik continue; 677c6fd2807SJeff Garzik if (!cnt) 678a44fec1fSJoe Perches dev_info(&pdev->dev, 679a44fec1fSJoe Perches "Applying R_ERR on DMA activate FIS errata fix\n"); 680c6fd2807SJeff Garzik writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg); 681c6fd2807SJeff Garzik cnt++; 682c6fd2807SJeff Garzik } 683c6fd2807SJeff Garzik } 684c6fd2807SJeff Garzik 6854447d351STejun Heo if (host->n_ports == 4) { 686c6fd2807SJeff Garzik /* flip the magic "make 4 ports work" bit */ 687c6fd2807SJeff Garzik tmp = readl(mmio_base + sil_port[2].bmdma); 688c6fd2807SJeff Garzik if ((tmp & SIL_INTR_STEERING) == 0) 689c6fd2807SJeff Garzik writel(tmp | SIL_INTR_STEERING, 690c6fd2807SJeff Garzik mmio_base + sil_port[2].bmdma); 691c6fd2807SJeff Garzik } 692c6fd2807SJeff Garzik } 693c6fd2807SJeff Garzik 694e57db7bdSRafael J. Wysocki static bool sil_broken_system_poweroff(struct pci_dev *pdev) 695e57db7bdSRafael J. Wysocki { 696e57db7bdSRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 697e57db7bdSRafael J. Wysocki { 698e57db7bdSRafael J. Wysocki .ident = "HP Compaq nx6325", 699e57db7bdSRafael J. Wysocki .matches = { 700e57db7bdSRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 701e57db7bdSRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"), 702e57db7bdSRafael J. Wysocki }, 703e57db7bdSRafael J. Wysocki /* PCI slot number of the controller */ 704e57db7bdSRafael J. Wysocki .driver_data = (void *)0x12UL, 705e57db7bdSRafael J. Wysocki }, 706e57db7bdSRafael J. Wysocki 707e57db7bdSRafael J. Wysocki { } /* terminate list */ 708e57db7bdSRafael J. Wysocki }; 709e57db7bdSRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 710e57db7bdSRafael J. Wysocki 711e57db7bdSRafael J. Wysocki if (dmi) { 712e57db7bdSRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 713e57db7bdSRafael J. Wysocki /* apply the quirk only to on-board controllers */ 714e57db7bdSRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 715e57db7bdSRafael J. Wysocki } 716e57db7bdSRafael J. Wysocki 717e57db7bdSRafael J. Wysocki return false; 718e57db7bdSRafael J. Wysocki } 719e57db7bdSRafael J. Wysocki 720c6fd2807SJeff Garzik static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 721c6fd2807SJeff Garzik { 7224447d351STejun Heo int board_id = ent->driver_data; 723e57db7bdSRafael J. Wysocki struct ata_port_info pi = sil_port_info[board_id]; 724e57db7bdSRafael J. Wysocki const struct ata_port_info *ppi[] = { &pi, NULL }; 7254447d351STejun Heo struct ata_host *host; 726c6fd2807SJeff Garzik void __iomem *mmio_base; 7274447d351STejun Heo int n_ports, rc; 728c6fd2807SJeff Garzik unsigned int i; 729c6fd2807SJeff Garzik 73006296a1eSJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 731c6fd2807SJeff Garzik 7324447d351STejun Heo /* allocate host */ 7334447d351STejun Heo n_ports = 2; 7344447d351STejun Heo if (board_id == sil_3114) 7354447d351STejun Heo n_ports = 4; 7364447d351STejun Heo 737e57db7bdSRafael J. Wysocki if (sil_broken_system_poweroff(pdev)) { 738e57db7bdSRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN | 739e57db7bdSRafael J. Wysocki ATA_FLAG_NO_HIBERNATE_SPINDOWN; 740e57db7bdSRafael J. Wysocki dev_info(&pdev->dev, "quirky BIOS, skipping spindown " 741e57db7bdSRafael J. Wysocki "on poweroff and hibernation\n"); 742e57db7bdSRafael J. Wysocki } 743e57db7bdSRafael J. Wysocki 7444447d351STejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 7454447d351STejun Heo if (!host) 7464447d351STejun Heo return -ENOMEM; 7474447d351STejun Heo 7484447d351STejun Heo /* acquire resources and fill host */ 74924dc5f33STejun Heo rc = pcim_enable_device(pdev); 750c6fd2807SJeff Garzik if (rc) 751c6fd2807SJeff Garzik return rc; 752c6fd2807SJeff Garzik 7530d5ff566STejun Heo rc = pcim_iomap_regions(pdev, 1 << SIL_MMIO_BAR, DRV_NAME); 7540d5ff566STejun Heo if (rc == -EBUSY) 75524dc5f33STejun Heo pcim_pin_device(pdev); 7560d5ff566STejun Heo if (rc) 75724dc5f33STejun Heo return rc; 7584447d351STejun Heo host->iomap = pcim_iomap_table(pdev); 759c6fd2807SJeff Garzik 760b5e55556SChristoph Hellwig rc = dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); 761c6fd2807SJeff Garzik if (rc) 76224dc5f33STejun Heo return rc; 763c6fd2807SJeff Garzik 7644447d351STejun Heo mmio_base = host->iomap[SIL_MMIO_BAR]; 765c6fd2807SJeff Garzik 7664447d351STejun Heo for (i = 0; i < host->n_ports; i++) { 767cbcdd875STejun Heo struct ata_port *ap = host->ports[i]; 768cbcdd875STejun Heo struct ata_ioports *ioaddr = &ap->ioaddr; 769c6fd2807SJeff Garzik 7704447d351STejun Heo ioaddr->cmd_addr = mmio_base + sil_port[i].tf; 7714447d351STejun Heo ioaddr->altstatus_addr = 7724447d351STejun Heo ioaddr->ctl_addr = mmio_base + sil_port[i].ctl; 7734447d351STejun Heo ioaddr->bmdma_addr = mmio_base + sil_port[i].bmdma; 7744447d351STejun Heo ioaddr->scr_addr = mmio_base + sil_port[i].scr; 7759363c382STejun Heo ata_sff_std_ports(ioaddr); 776cbcdd875STejun Heo 777cbcdd875STejun Heo ata_port_pbar_desc(ap, SIL_MMIO_BAR, -1, "mmio"); 778cbcdd875STejun Heo ata_port_pbar_desc(ap, SIL_MMIO_BAR, sil_port[i].tf, "tf"); 779c6fd2807SJeff Garzik } 780c6fd2807SJeff Garzik 7814447d351STejun Heo /* initialize and activate */ 7824447d351STejun Heo sil_init_controller(host); 783c6fd2807SJeff Garzik 784c6fd2807SJeff Garzik pci_set_master(pdev); 7854447d351STejun Heo return ata_host_activate(host, pdev->irq, sil_interrupt, IRQF_SHARED, 7864447d351STejun Heo &sil_sht); 787c6fd2807SJeff Garzik } 788c6fd2807SJeff Garzik 78958eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP 790c6fd2807SJeff Garzik static int sil_pci_device_resume(struct pci_dev *pdev) 791c6fd2807SJeff Garzik { 7920a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 793553c4aa6STejun Heo int rc; 794c6fd2807SJeff Garzik 795553c4aa6STejun Heo rc = ata_pci_device_do_resume(pdev); 796553c4aa6STejun Heo if (rc) 797553c4aa6STejun Heo return rc; 798553c4aa6STejun Heo 7994447d351STejun Heo sil_init_controller(host); 800cca3974eSJeff Garzik ata_host_resume(host); 801c6fd2807SJeff Garzik 802c6fd2807SJeff Garzik return 0; 803c6fd2807SJeff Garzik } 804281d426cSAlexey Dobriyan #endif 805c6fd2807SJeff Garzik 8062fc75da0SAxel Lin module_pci_driver(sil_pci_driver); 807