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