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;
131*29d2d5edSDamien Le Moal } sil_quirks[] = {
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
15925df73d9SBart 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 *
603*29d2d5edSDamien Le Moal * 20040111 - Seagate drives affected by the Mod15Write bug are quirked
604*29d2d5edSDamien Le Moal * The Maxtor quirk is in sil_quirks, 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
623*29d2d5edSDamien Le Moal for (n = 0; sil_quirks[n].product; n++)
624*29d2d5edSDamien Le Moal if (!strcmp(sil_quirks[n].product, model_num)) {
625*29d2d5edSDamien Le Moal quirks = sil_quirks[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