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