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