11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sata_sil.c - Silicon Image SATA 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Maintained by: Jeff Garzik <jgarzik@pobox.com> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Please ALWAYS copy linux-ide@vger.kernel.org 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * on emails. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * Copyright 2003-2005 Red Hat, Inc. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2003 Benjamin Herrenschmidt 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * 12af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * This program is free software; you can redistribute it and/or modify 13af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * it under the terms of the GNU General Public License as published by 14af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * the Free Software Foundation; either version 2, or (at your option) 15af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * any later version. 16af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * 17af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * This program is distributed in the hope that it will be useful, 18af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * but WITHOUT ANY WARRANTY; without even the implied warranty of 19af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * GNU General Public License for more details. 21af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * 22af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * You should have received a copy of the GNU General Public License 23af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * along with this program; see the file COPYING. If not, write to 24af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 25af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * 26af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * 27af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * libata documentation is available via 'make {ps|pdf}docs', 28af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * as Documentation/DocBook/libata.* 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 30953d1137fc4aba16deace262e93974913596dcfeJeff Garzik * Documentation for SiI 3112: 31953d1137fc4aba16deace262e93974913596dcfeJeff Garzik * http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2 32953d1137fc4aba16deace262e93974913596dcfeJeff Garzik * 33953d1137fc4aba16deace262e93974913596dcfeJeff Garzik * Other errata and documentation available under NDA. 34953d1137fc4aba16deace262e93974913596dcfeJeff Garzik * 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 44a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik#include <linux/device.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_host.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/libata.h> 471737ef7598d3515fdc11cb9ba7e054f334404e04Alexander Beregalov#include <linux/dmi.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRV_NAME "sata_sil" 50c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock#define DRV_VERSION "2.4" 51c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 52c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock#define SIL_DMA_BOUNDARY 0x7fffffffUL 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { 550d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo SIL_MMIO_BAR = 5, 560d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo 57e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* 58e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo * host flags 59e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo */ 60201ce85946504ea0e6bd9a365de26684b437121eTejun Heo SIL_FLAG_NO_SATA_IRQ = (1 << 28), 61e4e10e3e7995f5bd481d2720bf30d3a661d110caTejun Heo SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29), 62e4deec6304cbd5fd08bf573eccc68787945071c2Tejun Heo SIL_FLAG_MOD15WRITE = (1 << 30), 6320888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo 649cbe056f6c467e7395d5aec39aceec47812eb98eSergei Shtylyov SIL_DFL_PORT_FLAGS = ATA_FLAG_SATA, 65e4deec6304cbd5fd08bf573eccc68787945071c2Tejun Heo 66e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* 67e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo * Controller IDs 68e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo */ 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sil_3112 = 0, 70201ce85946504ea0e6bd9a365de26684b437121eTejun Heo sil_3112_no_sata_irq = 1, 71201ce85946504ea0e6bd9a365de26684b437121eTejun Heo sil_3512 = 2, 72201ce85946504ea0e6bd9a365de26684b437121eTejun Heo sil_3114 = 3, 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 74e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* 75e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo * Register offsets 76e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo */ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_SYSCFG = 0x48, 78e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo 79e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* 80e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo * Register bits 81e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo */ 82e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* SYSCFG */ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_IDE0_INT = (1 << 22), 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_IDE1_INT = (1 << 23), 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_IDE2_INT = (1 << 24), 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_IDE3_INT = (1 << 25), 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_2PORT = SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT, 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_4PORT = SIL_MASK_2PORT | 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT, 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* BMDMA/BMDMA2 */ 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_INTR_STEERING = (1 << 1), 93e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo 9420888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_ENABLE = (1 << 0), /* DMA run switch */ 9520888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_RDWR = (1 << 3), /* DMA Rd-Wr */ 9620888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_SATA_IRQ = (1 << 4), /* OR of all SATA IRQs */ 9720888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_ACTIVE = (1 << 16), /* DMA running */ 9820888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_ERROR = (1 << 17), /* PCI bus error */ 9920888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_COMPLETE = (1 << 18), /* cmd complete / IRQ pending */ 10020888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_N_SATA_IRQ = (1 << 6), /* SATA_IRQ for the next channel */ 10120888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_N_ACTIVE = (1 << 24), /* ACTIVE for the next channel */ 10220888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_N_ERROR = (1 << 25), /* ERROR for the next channel */ 10320888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_N_COMPLETE = (1 << 26), /* COMPLETE for the next channel */ 10420888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo 10520888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo /* SIEN */ 10620888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_SIEN_N = (1 << 16), /* triggered by SError.N */ 10720888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo 108e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* 109e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo * Others 110e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo */ 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_QUIRK_MOD15WRITE = (1 << 0), 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_QUIRK_UDMA5MAX = (1 << 1), 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1155796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 116281d426c7e64286f433645e27862e7744b1e9310Alexey Dobriyan#ifdef CONFIG_PM 117afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heostatic int sil_pci_device_resume(struct pci_dev *pdev); 118281d426c7e64286f433645e27862e7744b1e9310Alexey Dobriyan#endif 119cd0d3bbcdd650651b7ccfaf55d107e3fc237d95aAlan Coxstatic void sil_dev_config(struct ata_device *dev); 12082ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heostatic int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); 12182ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heostatic int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); 1220260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heostatic int sil_set_mode(struct ata_link *link, struct ata_device **r_failed); 123c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_qc_prep(struct ata_queued_cmd *qc); 124c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_bmdma_setup(struct ata_queued_cmd *qc); 125c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_bmdma_start(struct ata_queued_cmd *qc); 126c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_bmdma_stop(struct ata_queued_cmd *qc); 127f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heostatic void sil_freeze(struct ata_port *ap); 128f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heostatic void sil_thaw(struct ata_port *ap); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 130374b1873571bf80dc0c1fcceaaad067980f3b9deJeff Garzik 1313b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzikstatic const struct pci_device_id sil_pci_tbl[] = { 13254bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(CMD, 0x3112), sil_3112 }, 13354bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(CMD, 0x0240), sil_3112 }, 13454bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(CMD, 0x3512), sil_3512 }, 13554bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(CMD, 0x3114), sil_3114 }, 13654bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(ATI, 0x436e), sil_3112 }, 13754bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(ATI, 0x4379), sil_3112_no_sata_irq }, 13854bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(ATI, 0x437a), sil_3112_no_sata_irq }, 13954bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } /* terminate list */ 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TODO firmware versions should be added - eric */ 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const struct sil_drivelist { 1465796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik const char *product; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int quirk; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} sil_blacklist [] = { 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST320012AS", SIL_QUIRK_MOD15WRITE }, 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST330013AS", SIL_QUIRK_MOD15WRITE }, 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST340017AS", SIL_QUIRK_MOD15WRITE }, 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST360015AS", SIL_QUIRK_MOD15WRITE }, 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST380023AS", SIL_QUIRK_MOD15WRITE }, 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST3120023AS", SIL_QUIRK_MOD15WRITE }, 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST340014ASL", SIL_QUIRK_MOD15WRITE }, 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST360014ASL", SIL_QUIRK_MOD15WRITE }, 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST380011ASL", SIL_QUIRK_MOD15WRITE }, 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST3120022ASL", SIL_QUIRK_MOD15WRITE }, 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST3160021ASL", SIL_QUIRK_MOD15WRITE }, 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "Maxtor 4D060H3", SIL_QUIRK_UDMA5MAX }, 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver sil_pci_driver = { 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = DRV_NAME, 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = sil_pci_tbl, 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = sil_init_one, 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .remove = ata_pci_remove_one, 169281d426c7e64286f433645e27862e7744b1e9310Alexey Dobriyan#ifdef CONFIG_PM 170afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo .suspend = ata_pci_device_suspend, 171afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo .resume = sil_pci_device_resume, 172281d426c7e64286f433645e27862e7744b1e9310Alexey Dobriyan#endif 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 175193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzikstatic struct scsi_host_template sil_sht = { 176c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock ATA_BASE_SHT(DRV_NAME), 177c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /** These controllers support Large Block Transfer which allows 178c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock transfer chunks up to 2GB and which cross 64KB boundaries, 179c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock therefore the DMA limits are more relaxed than standard ATA SFF. */ 180c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock .dma_boundary = SIL_DMA_BOUNDARY, 181c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock .sg_tablesize = ATA_MAX_PRD 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 184029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heostatic struct ata_port_operations sil_ops = { 18531f80112cc7e7ea4c220d6f62b0a7052754befb3Robert Hancock .inherits = &ata_bmdma32_port_ops, 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .dev_config = sil_dev_config, 1879d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox .set_mode = sil_set_mode, 188c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock .bmdma_setup = sil_bmdma_setup, 189c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock .bmdma_start = sil_bmdma_start, 190c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock .bmdma_stop = sil_bmdma_stop, 191c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock .qc_prep = sil_qc_prep, 192f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo .freeze = sil_freeze, 193f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo .thaw = sil_thaw, 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .scr_read = sil_scr_read, 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .scr_write = sil_scr_write, 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19898ac62defe529d04a192688f40d801a2d8fbcf98Arjan van de Venstatic const struct ata_port_info sil_port_info[] = { 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* sil_3112 */ 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 201cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE, 20214bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø .pio_mask = ATA_PIO4, 20314bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 204bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA5, 205e4deec6304cbd5fd08bf573eccc68787945071c2Tejun Heo .port_ops = &sil_ops, 2060ee304d5802dc62746f13f12d4cb4ec4ed285f66Tejun Heo }, 207201ce85946504ea0e6bd9a365de26684b437121eTejun Heo /* sil_3112_no_sata_irq */ 208201ce85946504ea0e6bd9a365de26684b437121eTejun Heo { 209cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE | 210201ce85946504ea0e6bd9a365de26684b437121eTejun Heo SIL_FLAG_NO_SATA_IRQ, 21114bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø .pio_mask = ATA_PIO4, 21214bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 213bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA5, 214201ce85946504ea0e6bd9a365de26684b437121eTejun Heo .port_ops = &sil_ops, 215201ce85946504ea0e6bd9a365de26684b437121eTejun Heo }, 2160ee304d5802dc62746f13f12d4cb4ec4ed285f66Tejun Heo /* sil_3512 */ 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 218cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, 21914bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø .pio_mask = ATA_PIO4, 22014bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 221bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA5, 2220ee304d5802dc62746f13f12d4cb4ec4ed285f66Tejun Heo .port_ops = &sil_ops, 2230ee304d5802dc62746f13f12d4cb4ec4ed285f66Tejun Heo }, 2240ee304d5802dc62746f13f12d4cb4ec4ed285f66Tejun Heo /* sil_3114 */ 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 226cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, 22714bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø .pio_mask = ATA_PIO4, 22814bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø .mwdma_mask = ATA_MWDMA2, 229bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA5, 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .port_ops = &sil_ops, 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* per-port register offsets */ 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TODO: we can probably calculate rather than use a table */ 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const struct { 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long tf; /* ATA taskfile register block */ 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long ctl; /* ATA control/altstatus register block */ 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long bmdma; /* DMA register block */ 24020888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo unsigned long bmdma2; /* DMA register block #2 */ 24148d4ef2a1df9867c67b515d66732ba028a73735dTejun Heo unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */ 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long scr; /* SATA control register block */ 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long sien; /* SATA Interrupt Enable register */ 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long xfer_mode;/* data transfer mode register */ 245e4e10e3e7995f5bd481d2720bf30d3a661d110caTejun Heo unsigned long sfis_cfg; /* SATA FIS reception config register */ 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} sil_port[] = { 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* port 0 ... */ 2485bcd7a00a464fd81b4b68847b9b811a635a15b61Jeff Garzik /* tf ctl bmdma bmdma2 fifo scr sien mode sfis */ 2495bcd7a00a464fd81b4b68847b9b811a635a15b61Jeff Garzik { 0x80, 0x8A, 0x0, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c }, 2505bcd7a00a464fd81b4b68847b9b811a635a15b61Jeff Garzik { 0xC0, 0xCA, 0x8, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc }, 25120888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo { 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c }, 25220888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo { 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc }, 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ... port 3 */ 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Jeff Garzik"); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("low-level driver for Silicon Image SATA controller"); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, sil_pci_tbl); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_VERSION(DRV_VERSION); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2625796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic int slow_down; 26351e9f2ff83df6b1c81c5c44f4486c68ed87aa20eJeff Garzikmodule_param(slow_down, int, 0444); 26451e9f2ff83df6b1c81c5c44f4486c68ed87aa20eJeff GarzikMODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)"); 26551e9f2ff83df6b1c81c5c44f4486c68ed87aa20eJeff Garzik 266374b1873571bf80dc0c1fcceaaad067980f3b9deJeff Garzik 267c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_bmdma_stop(struct ata_queued_cmd *qc) 268c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock{ 269c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock struct ata_port *ap = qc->ap; 270c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 271c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock void __iomem *bmdma2 = mmio_base + sil_port[ap->port_no].bmdma2; 272c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 273c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /* clear start/stop bit - can safely always write 0 */ 274c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock iowrite8(0, bmdma2); 275c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 276c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ 277c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock ata_sff_dma_pause(ap); 278c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock} 279c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 280c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_bmdma_setup(struct ata_queued_cmd *qc) 281c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock{ 282c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock struct ata_port *ap = qc->ap; 283c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock void __iomem *bmdma = ap->ioaddr.bmdma_addr; 284c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 285c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /* load PRD table addr. */ 286f60d70113fa04e32aee2dedbf304a48469c9c45cTejun Heo iowrite32(ap->bmdma_prd_dma, bmdma + ATA_DMA_TABLE_OFS); 287c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 288c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /* issue r/w command */ 289c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock ap->ops->sff_exec_command(ap, &qc->tf); 290c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock} 291c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 292c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_bmdma_start(struct ata_queued_cmd *qc) 293c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock{ 294c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); 295c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock struct ata_port *ap = qc->ap; 296c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 297c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock void __iomem *bmdma2 = mmio_base + sil_port[ap->port_no].bmdma2; 298c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock u8 dmactl = ATA_DMA_START; 299c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 300c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /* set transfer direction, start host DMA transaction 301c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock Note: For Large Block Transfer to work, the DMA must be started 302c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock using the bmdma2 register. */ 303c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock if (!rw) 304c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock dmactl |= ATA_DMA_WR; 305c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock iowrite8(dmactl, bmdma2); 306c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock} 307c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 308c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock/* The way God intended PCI IDE scatter/gather lists to look and behave... */ 309c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_fill_sg(struct ata_queued_cmd *qc) 310c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock{ 311c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock struct scatterlist *sg; 312c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock struct ata_port *ap = qc->ap; 313f60d70113fa04e32aee2dedbf304a48469c9c45cTejun Heo struct ata_bmdma_prd *prd, *last_prd = NULL; 314c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock unsigned int si; 315c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 316f60d70113fa04e32aee2dedbf304a48469c9c45cTejun Heo prd = &ap->bmdma_prd[0]; 317c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock for_each_sg(qc->sg, sg, qc->n_elem, si) { 318c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /* Note h/w doesn't support 64-bit, so we unconditionally 319c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock * truncate dma_addr_t to u32. 320c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock */ 321c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock u32 addr = (u32) sg_dma_address(sg); 322c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock u32 sg_len = sg_dma_len(sg); 323c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 324c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock prd->addr = cpu_to_le32(addr); 325c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock prd->flags_len = cpu_to_le32(sg_len); 32641137aa61c1ccb7cd06981807113b7e2d0ad89edPasi Kärkkäinen VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", si, addr, sg_len); 327c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 328c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock last_prd = prd; 329c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock prd++; 330c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock } 331c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 332c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock if (likely(last_prd)) 333c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock last_prd->flags_len |= cpu_to_le32(ATA_PRD_EOT); 334c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock} 335c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 336c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_qc_prep(struct ata_queued_cmd *qc) 337c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock{ 338c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 339c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock return; 340c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 341c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock sil_fill_sg(qc); 342c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock} 343c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char sil_get_device_cache_line(struct pci_dev *pdev) 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 cache_line = 0; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line); 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return cache_line; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3519d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox/** 3529d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox * sil_set_mode - wrap set_mode functions 3530260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heo * @link: link to set up 3549d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox * @r_failed: returned device when we fail 3559d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox * 3569d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox * Wrap the libata method for device setup as after the setup we need 3579d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox * to inspect the results and do some configuration work 3589d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox */ 3599d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox 3600260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heostatic int sil_set_mode(struct ata_link *link, struct ata_device **r_failed) 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3620260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heo struct ata_port *ap = link->ap; 3630260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heo void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 3640d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *addr = mmio_base + sil_port[ap->port_no].xfer_mode; 3650260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heo struct ata_device *dev; 366f58229f8060055b08b34008ea08f31de1e2f003cTejun Heo u32 tmp, dev_mode[2] = { }; 3679d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox int rc; 368a617c09f6d646b60f31efc8afd9f81b752bf21b7Jeff Garzik 3690260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heo rc = ata_do_set_mode(link, r_failed); 3709d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox if (rc) 3719d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox return rc; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3731eca4365be25c540650693e941bc06a66cf38f94Tejun Heo ata_for_each_dev(dev, link, ALL) { 374e1211e3fa7fd05ff0d4f597fd37e40de8acc6784Tejun Heo if (!ata_dev_enabled(dev)) 375f58229f8060055b08b34008ea08f31de1e2f003cTejun Heo dev_mode[dev->devno] = 0; /* PIO0/1/2 */ 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (dev->flags & ATA_DFLAG_PIO) 377f58229f8060055b08b34008ea08f31de1e2f003cTejun Heo dev_mode[dev->devno] = 1; /* PIO3/4 */ 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 379f58229f8060055b08b34008ea08f31de1e2f003cTejun Heo dev_mode[dev->devno] = 3; /* UDMA */ 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* value 2 indicates MDMA */ 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = readl(addr); 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp &= ~((1<<5) | (1<<4) | (1<<1) | (1<<0)); 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp |= dev_mode[0]; 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp |= (dev_mode[1] << 4); 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(tmp, addr); 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds readl(addr); /* flush */ 3899d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox return 0; 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3925796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic inline void __iomem *sil_scr_addr(struct ata_port *ap, 3935796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik unsigned int sc_reg) 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3950d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *offset = ap->ioaddr.scr_addr; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (sc_reg) { 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SCR_STATUS: 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return offset + 4; 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SCR_ERROR: 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return offset + 8; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SCR_CONTROL: 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return offset; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* do nothing */ 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4098d9db2d2fbae9e05022825c32f86e00c8e342860Randy Dunlap return NULL; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41282ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heostatic int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 41482ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heo void __iomem *mmio = sil_scr_addr(link->ap, sc_reg); 415da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo 416da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo if (mmio) { 417da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo *val = readl(mmio); 418da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return 0; 419da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } 420da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return -EINVAL; 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42382ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heostatic int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 42582ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heo void __iomem *mmio = sil_scr_addr(link->ap, sc_reg); 426da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo 427da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo if (mmio) { 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(val, mmio); 429da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return 0; 430da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } 431da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return -EINVAL; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 434cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heostatic void sil_host_intr(struct ata_port *ap, u32 bmdma2) 435cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo{ 4369af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo struct ata_eh_info *ehi = &ap->link.eh_info; 4379af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag); 438cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo u8 status; 439cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 440e573890b00426189e1e223967a2c46fb758bf06eTejun Heo if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) { 441ebd1699ec5f1a6f1f2df6b48fa54bc6ff790143cJeff Garzik u32 serror = 0xffffffff; 442d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo 443d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo /* SIEN doesn't mask SATA IRQs on some 3112s. Those 444d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo * controllers continue to assert IRQ as long as 445d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo * SError bits are pending. Clear SError immediately. 446d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo */ 44782ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heo sil_scr_read(&ap->link, SCR_ERROR, &serror); 44882ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heo sil_scr_write(&ap->link, SCR_ERROR, serror); 449d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo 4508cf32ac6578a70025be1103466da9d1d6141429eTejun Heo /* Sometimes spurious interrupts occur, double check 4518cf32ac6578a70025be1103466da9d1d6141429eTejun Heo * it's PHYRDY CHG. 452d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo */ 4538cf32ac6578a70025be1103466da9d1d6141429eTejun Heo if (serror & SERR_PHYRDY_CHG) { 454f7fe7ad4bcaba17f05d5cbf1119772c645783b08Tejun Heo ap->link.eh_info.serror |= serror; 4558cf32ac6578a70025be1103466da9d1d6141429eTejun Heo goto freeze; 456d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo } 457d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo 4588cf32ac6578a70025be1103466da9d1d6141429eTejun Heo if (!(bmdma2 & SIL_DMA_COMPLETE)) 4598cf32ac6578a70025be1103466da9d1d6141429eTejun Heo return; 460e573890b00426189e1e223967a2c46fb758bf06eTejun Heo } 461e573890b00426189e1e223967a2c46fb758bf06eTejun Heo 4628cf32ac6578a70025be1103466da9d1d6141429eTejun Heo if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { 463e2f8fb72144a9f38d44ccf3f939e939392eda659Tejun Heo /* this sometimes happens, just clear IRQ */ 4645682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo ap->ops->sff_check_status(ap); 465e2f8fb72144a9f38d44ccf3f939e939392eda659Tejun Heo return; 466e2f8fb72144a9f38d44ccf3f939e939392eda659Tejun Heo } 467e2f8fb72144a9f38d44ccf3f939e939392eda659Tejun Heo 468cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* Check whether we are expecting interrupt in this state */ 469cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo switch (ap->hsm_task_state) { 470cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo case HSM_ST_FIRST: 471cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* Some pre-ATAPI-4 devices assert INTRQ 472cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo * at this state when ready to receive CDB. 473cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo */ 474cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 475cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* Check the ATA_DFLAG_CDB_INTR flag is enough here. 476405e66b38797875e80669eaf72d313dbb76533c3Tejun Heo * The flag was turned on only for atapi devices. No 477405e66b38797875e80669eaf72d313dbb76533c3Tejun Heo * need to check ata_is_atapi(qc->tf.protocol) again. 478cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo */ 479cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) 480cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo goto err_hsm; 481cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo break; 482cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo case HSM_ST_LAST: 483405e66b38797875e80669eaf72d313dbb76533c3Tejun Heo if (ata_is_dma(qc->tf.protocol)) { 484cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* clear DMA-Start bit */ 485cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo ap->ops->bmdma_stop(qc); 486cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 487cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo if (bmdma2 & SIL_DMA_ERROR) { 488cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo qc->err_mask |= AC_ERR_HOST_BUS; 489cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo ap->hsm_task_state = HSM_ST_ERR; 490cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo } 491cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo } 492cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo break; 493cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo case HSM_ST: 494cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo break; 495cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo default: 496cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo goto err_hsm; 497cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo } 498cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 499cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* check main status, clearing INTRQ */ 5005682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo status = ap->ops->sff_check_status(ap); 501cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo if (unlikely(status & ATA_BUSY)) 502cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo goto err_hsm; 503cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 504cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* ack bmdma irq events */ 50537f65b8bc262a5ae4c8e58be92fe3032f0aaaf04Tejun Heo ata_bmdma_irq_clear(ap); 506cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 507cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* kick HSM in the ass */ 5089363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo ata_sff_hsm_move(ap, qc, status, 0); 509cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 510405e66b38797875e80669eaf72d313dbb76533c3Tejun Heo if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol)) 511ea54763f8a7c51b9f8fcb14431812ae63fcbaf96Tejun Heo ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2); 512ea54763f8a7c51b9f8fcb14431812ae63fcbaf96Tejun Heo 513cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo return; 514cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 515cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo err_hsm: 516cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo qc->err_mask |= AC_ERR_HSM; 517cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo freeze: 518cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo ata_port_freeze(ap); 519cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo} 520cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 5217d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t sil_interrupt(int irq, void *dev_instance) 522cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo{ 523cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct ata_host *host = dev_instance; 5240d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio_base = host->iomap[SIL_MMIO_BAR]; 525cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo int handled = 0; 526cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo int i; 527cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 528cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik spin_lock(&host->lock); 529cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 530cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik for (i = 0; i < host->n_ports; i++) { 531cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct ata_port *ap = host->ports[i]; 532cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2); 533cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 534201ce85946504ea0e6bd9a365de26684b437121eTejun Heo /* turn off SATA_IRQ if not supported */ 535201ce85946504ea0e6bd9a365de26684b437121eTejun Heo if (ap->flags & SIL_FLAG_NO_SATA_IRQ) 536201ce85946504ea0e6bd9a365de26684b437121eTejun Heo bmdma2 &= ~SIL_DMA_SATA_IRQ; 537201ce85946504ea0e6bd9a365de26684b437121eTejun Heo 53823fa9618094975f803ed0c6a44604b16747b9637Tejun Heo if (bmdma2 == 0xffffffff || 53923fa9618094975f803ed0c6a44604b16747b9637Tejun Heo !(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ))) 540cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo continue; 541cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 542cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo sil_host_intr(ap, bmdma2); 543cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo handled = 1; 544cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo } 545cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 546cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik spin_unlock(&host->lock); 547cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 548cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo return IRQ_RETVAL(handled); 549cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo} 550cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 551f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heostatic void sil_freeze(struct ata_port *ap) 552f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo{ 5530d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 554f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo u32 tmp; 555f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo 556e573890b00426189e1e223967a2c46fb758bf06eTejun Heo /* global IRQ mask doesn't block SATA IRQ, turn off explicitly */ 557e573890b00426189e1e223967a2c46fb758bf06eTejun Heo writel(0, mmio_base + sil_port[ap->port_no].sien); 558e573890b00426189e1e223967a2c46fb758bf06eTejun Heo 559f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo /* plug IRQ */ 560f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo tmp = readl(mmio_base + SIL_SYSCFG); 561f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo tmp |= SIL_MASK_IDE0_INT << ap->port_no; 562f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo writel(tmp, mmio_base + SIL_SYSCFG); 563f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo readl(mmio_base + SIL_SYSCFG); /* flush */ 5642fc37adba0fb05760b8635c6706773af828ccf3cJeff Garzik 5652fc37adba0fb05760b8635c6706773af828ccf3cJeff Garzik /* Ensure DMA_ENABLE is off. 5662fc37adba0fb05760b8635c6706773af828ccf3cJeff Garzik * 5672fc37adba0fb05760b8635c6706773af828ccf3cJeff Garzik * This is because the controller will not give us access to the 5682fc37adba0fb05760b8635c6706773af828ccf3cJeff Garzik * taskfile registers while a DMA is in progress 5692fc37adba0fb05760b8635c6706773af828ccf3cJeff Garzik */ 5702fc37adba0fb05760b8635c6706773af828ccf3cJeff Garzik iowrite8(ioread8(ap->ioaddr.bmdma_addr) & ~SIL_DMA_ENABLE, 5712fc37adba0fb05760b8635c6706773af828ccf3cJeff Garzik ap->ioaddr.bmdma_addr); 5722fc37adba0fb05760b8635c6706773af828ccf3cJeff Garzik 5732fc37adba0fb05760b8635c6706773af828ccf3cJeff Garzik /* According to ata_bmdma_stop, an HDMA transition requires 5742fc37adba0fb05760b8635c6706773af828ccf3cJeff Garzik * on PIO cycle. But we can't read a taskfile register. 5752fc37adba0fb05760b8635c6706773af828ccf3cJeff Garzik */ 5762fc37adba0fb05760b8635c6706773af828ccf3cJeff Garzik ioread8(ap->ioaddr.bmdma_addr); 577f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo} 578f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo 579f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heostatic void sil_thaw(struct ata_port *ap) 580f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo{ 5810d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 582f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo u32 tmp; 583f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo 584f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo /* clear IRQ */ 5855682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo ap->ops->sff_check_status(ap); 58637f65b8bc262a5ae4c8e58be92fe3032f0aaaf04Tejun Heo ata_bmdma_irq_clear(ap); 587f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo 588201ce85946504ea0e6bd9a365de26684b437121eTejun Heo /* turn on SATA IRQ if supported */ 589201ce85946504ea0e6bd9a365de26684b437121eTejun Heo if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ)) 590201ce85946504ea0e6bd9a365de26684b437121eTejun Heo writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien); 591e573890b00426189e1e223967a2c46fb758bf06eTejun Heo 592f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo /* turn on IRQ */ 593f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo tmp = readl(mmio_base + SIL_SYSCFG); 594f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no); 595f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo writel(tmp, mmio_base + SIL_SYSCFG); 596f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo} 597f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sil_dev_config - Apply device/host-specific errata fixups 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: Device to be examined 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * After the IDENTIFY [PACKET] DEVICE step is complete, and a 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * device is known to be present, this function is called. 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We apply two errata fixups which are specific to Silicon Image, 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a Seagate and a Maxtor fixup. 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For certain Seagate devices, we must limit the maximum sectors 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to under 8K. 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For certain Maxtor devices, we must not program the drive 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * beyond udma5. 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Both fixups are unfairly pessimistic. As soon as I get more 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * information on these errata, I will create a more exhaustive 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * list, and apply the fixups to only the specific 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * devices/hosts/firmwares that need it. 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20040111 - Seagate drives affected by the Mod15Write bug are blacklisted 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The Maxtor quirk is in the blacklist, but I'm keeping the original 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pessimistic fix for the following reasons... 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - There seems to be less info on it, only one device gleaned off the 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Windows driver, maybe only one is affected. More info would be greatly 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * appreciated. 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - But then again UDMA5 is hardly anything to complain about 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 626cd0d3bbcdd650651b7ccfaf55d107e3fc237d95aAlan Coxstatic void sil_dev_config(struct ata_device *dev) 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6289af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo struct ata_port *ap = dev->link->ap; 6299af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo int print_info = ap->link.eh_context.i.flags & ATA_EHI_PRINTINFO; 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int n, quirks = 0; 631a0cf733b333eeeafb7324e2897448006c693c26cTejun Heo unsigned char model_num[ATA_ID_PROD_LEN + 1]; 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 633a0cf733b333eeeafb7324e2897448006c693c26cTejun Heo ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6358a60a07129fad60bba779a2a4038c7518b167fc7Jeff Garzik for (n = 0; sil_blacklist[n].product; n++) 6362e02671daa2cd69d93c828c40579bbe953f17210Tejun Heo if (!strcmp(sil_blacklist[n].product, model_num)) { 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds quirks = sil_blacklist[n].quirk; 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6408a60a07129fad60bba779a2a4038c7518b167fc7Jeff Garzik 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* limit requests to 15 sectors */ 64251e9f2ff83df6b1c81c5c44f4486c68ed87aa20eJeff Garzik if (slow_down || 64351e9f2ff83df6b1c81c5c44f4486c68ed87aa20eJeff Garzik ((ap->flags & SIL_FLAG_MOD15WRITE) && 64451e9f2ff83df6b1c81c5c44f4486c68ed87aa20eJeff Garzik (quirks & SIL_QUIRK_MOD15WRITE))) { 645efdaedc443e935eda82e9e78a6e65d1f993d242fTejun Heo if (print_info) 646a9a79dfec239568bdbf778242f8fcd10bcc5b9e2Joe Perches ata_dev_info(dev, 647a9a79dfec239568bdbf778242f8fcd10bcc5b9e2Joe Perches "applying Seagate errata fix (mod15write workaround)\n"); 648b00eec1d58ee71131375bfeb86e64bceec3f5618Tejun Heo dev->max_sectors = 15; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* limit to udma5 */ 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (quirks & SIL_QUIRK_UDMA5MAX) { 654efdaedc443e935eda82e9e78a6e65d1f993d242fTejun Heo if (print_info) 655a9a79dfec239568bdbf778242f8fcd10bcc5b9e2Joe Perches ata_dev_info(dev, "applying Maxtor errata fix %s\n", 656a9a79dfec239568bdbf778242f8fcd10bcc5b9e2Joe Perches model_num); 6575a529139554f12cb265715117a2153c936286294Tejun Heo dev->udma_mask &= ATA_UDMA5; 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6624447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic void sil_init_controller(struct ata_host *host) 6633d8ec91352099b32a400f1952112dc076da28106Tejun Heo{ 6644447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 6654447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo void __iomem *mmio_base = host->iomap[SIL_MMIO_BAR]; 6663d8ec91352099b32a400f1952112dc076da28106Tejun Heo u8 cls; 6673d8ec91352099b32a400f1952112dc076da28106Tejun Heo u32 tmp; 6683d8ec91352099b32a400f1952112dc076da28106Tejun Heo int i; 6693d8ec91352099b32a400f1952112dc076da28106Tejun Heo 6703d8ec91352099b32a400f1952112dc076da28106Tejun Heo /* Initialize FIFO PCI bus arbitration */ 6713d8ec91352099b32a400f1952112dc076da28106Tejun Heo cls = sil_get_device_cache_line(pdev); 6723d8ec91352099b32a400f1952112dc076da28106Tejun Heo if (cls) { 6733d8ec91352099b32a400f1952112dc076da28106Tejun Heo cls >>= 3; 6743d8ec91352099b32a400f1952112dc076da28106Tejun Heo cls++; /* cls = (line_size/8)+1 */ 6754447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (i = 0; i < host->n_ports; i++) 6763d8ec91352099b32a400f1952112dc076da28106Tejun Heo writew(cls << 8 | cls, 6773d8ec91352099b32a400f1952112dc076da28106Tejun Heo mmio_base + sil_port[i].fifo_cfg); 6783d8ec91352099b32a400f1952112dc076da28106Tejun Heo } else 679a44fec1fce5d5d14cc3ac4545b8da346394de666Joe Perches dev_warn(&pdev->dev, 680a44fec1fce5d5d14cc3ac4545b8da346394de666Joe Perches "cache line size not set. Driver may not function\n"); 6813d8ec91352099b32a400f1952112dc076da28106Tejun Heo 6823d8ec91352099b32a400f1952112dc076da28106Tejun Heo /* Apply R_ERR on DMA activate FIS errata workaround */ 6834447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo if (host->ports[0]->flags & SIL_FLAG_RERR_ON_DMA_ACT) { 6843d8ec91352099b32a400f1952112dc076da28106Tejun Heo int cnt; 6853d8ec91352099b32a400f1952112dc076da28106Tejun Heo 6864447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (i = 0, cnt = 0; i < host->n_ports; i++) { 6873d8ec91352099b32a400f1952112dc076da28106Tejun Heo tmp = readl(mmio_base + sil_port[i].sfis_cfg); 6883d8ec91352099b32a400f1952112dc076da28106Tejun Heo if ((tmp & 0x3) != 0x01) 6893d8ec91352099b32a400f1952112dc076da28106Tejun Heo continue; 6903d8ec91352099b32a400f1952112dc076da28106Tejun Heo if (!cnt) 691a44fec1fce5d5d14cc3ac4545b8da346394de666Joe Perches dev_info(&pdev->dev, 692a44fec1fce5d5d14cc3ac4545b8da346394de666Joe Perches "Applying R_ERR on DMA activate FIS errata fix\n"); 6933d8ec91352099b32a400f1952112dc076da28106Tejun Heo writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg); 6943d8ec91352099b32a400f1952112dc076da28106Tejun Heo cnt++; 6953d8ec91352099b32a400f1952112dc076da28106Tejun Heo } 6963d8ec91352099b32a400f1952112dc076da28106Tejun Heo } 6973d8ec91352099b32a400f1952112dc076da28106Tejun Heo 6984447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo if (host->n_ports == 4) { 6993d8ec91352099b32a400f1952112dc076da28106Tejun Heo /* flip the magic "make 4 ports work" bit */ 7003d8ec91352099b32a400f1952112dc076da28106Tejun Heo tmp = readl(mmio_base + sil_port[2].bmdma); 7013d8ec91352099b32a400f1952112dc076da28106Tejun Heo if ((tmp & SIL_INTR_STEERING) == 0) 7023d8ec91352099b32a400f1952112dc076da28106Tejun Heo writel(tmp | SIL_INTR_STEERING, 7033d8ec91352099b32a400f1952112dc076da28106Tejun Heo mmio_base + sil_port[2].bmdma); 7043d8ec91352099b32a400f1952112dc076da28106Tejun Heo } 7053d8ec91352099b32a400f1952112dc076da28106Tejun Heo} 7063d8ec91352099b32a400f1952112dc076da28106Tejun Heo 707e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysockistatic bool sil_broken_system_poweroff(struct pci_dev *pdev) 708e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki{ 709e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 710e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki { 711e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki .ident = "HP Compaq nx6325", 712e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki .matches = { 713e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 714e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"), 715e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki }, 716e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki /* PCI slot number of the controller */ 717e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki .driver_data = (void *)0x12UL, 718e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki }, 719e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki 720e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki { } /* terminate list */ 721e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki }; 722e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 723e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki 724e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki if (dmi) { 725e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 726e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki /* apply the quirk only to on-board controllers */ 727e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 728e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki } 729e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki 730e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki return false; 731e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki} 732e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki 7335796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7354447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo int board_id = ent->driver_data; 736e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki struct ata_port_info pi = sil_port_info[board_id]; 737e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki const struct ata_port_info *ppi[] = { &pi, NULL }; 7384447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct ata_host *host; 739ea6ba10bbb88e106f9e2db7dc253993bb3bbbe3bJeff Garzik void __iomem *mmio_base; 7404447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo int n_ports, rc; 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int i; 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 74306296a1e684bcd40b9a28d5d8030809e4295528bJoe Perches ata_print_version_once(&pdev->dev, DRV_VERSION); 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7454447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo /* allocate host */ 7464447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo n_ports = 2; 7474447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo if (board_id == sil_3114) 7484447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo n_ports = 4; 7494447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo 750e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki if (sil_broken_system_poweroff(pdev)) { 751e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN | 752e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki ATA_FLAG_NO_HIBERNATE_SPINDOWN; 753e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki dev_info(&pdev->dev, "quirky BIOS, skipping spindown " 754e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki "on poweroff and hibernation\n"); 755e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki } 756e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki 7574447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 7584447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo if (!host) 7594447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo return -ENOMEM; 7604447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo 7614447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo /* acquire resources and fill host */ 76224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo rc = pcim_enable_device(pdev); 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7660d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo rc = pcim_iomap_regions(pdev, 1 << SIL_MMIO_BAR, DRV_NAME); 7670d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo if (rc == -EBUSY) 76824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo pcim_pin_device(pdev); 7690d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo if (rc) 77024dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 7714447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo host->iomap = pcim_iomap_table(pdev); 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 77524dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 77824dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7804447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo mmio_base = host->iomap[SIL_MMIO_BAR]; 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7824447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (i = 0; i < host->n_ports; i++) { 783cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo struct ata_port *ap = host->ports[i]; 784cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo struct ata_ioports *ioaddr = &ap->ioaddr; 7854447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo 7864447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo ioaddr->cmd_addr = mmio_base + sil_port[i].tf; 7874447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo ioaddr->altstatus_addr = 7884447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo ioaddr->ctl_addr = mmio_base + sil_port[i].ctl; 7894447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo ioaddr->bmdma_addr = mmio_base + sil_port[i].bmdma; 7904447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo ioaddr->scr_addr = mmio_base + sil_port[i].scr; 7919363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo ata_sff_std_ports(ioaddr); 792cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo 793cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo ata_port_pbar_desc(ap, SIL_MMIO_BAR, -1, "mmio"); 794cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo ata_port_pbar_desc(ap, SIL_MMIO_BAR, sil_port[i].tf, "tf"); 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7974447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo /* initialize and activate */ 7984447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo sil_init_controller(host); 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_master(pdev); 8014447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo return ata_host_activate(host, pdev->irq, sil_interrupt, IRQF_SHARED, 8024447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo &sil_sht); 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 805281d426c7e64286f433645e27862e7744b1e9310Alexey Dobriyan#ifdef CONFIG_PM 806afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heostatic int sil_pci_device_resume(struct pci_dev *pdev) 807afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo{ 808cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct ata_host *host = dev_get_drvdata(&pdev->dev); 809553c4aa630af7bc885e056d0436e4eb7f238579bTejun Heo int rc; 810553c4aa630af7bc885e056d0436e4eb7f238579bTejun Heo 811553c4aa630af7bc885e056d0436e4eb7f238579bTejun Heo rc = ata_pci_device_do_resume(pdev); 812553c4aa630af7bc885e056d0436e4eb7f238579bTejun Heo if (rc) 813553c4aa630af7bc885e056d0436e4eb7f238579bTejun Heo return rc; 814afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo 8154447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo sil_init_controller(host); 816cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik ata_host_resume(host); 817afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo 818afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo return 0; 819afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo} 820281d426c7e64286f433645e27862e7744b1e9310Alexey Dobriyan#endif 821afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sil_init(void) 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 824b7887196e38da54ff893897b80875d632d1a1114Pavel Roskin return pci_register_driver(&sil_pci_driver); 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit sil_exit(void) 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unregister_driver(&sil_pci_driver); 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sil_init); 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sil_exit); 835