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