pata_cs5520.c revision 284901a90a9e0b812ca3f5f852cbbfb60d10249d
1669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
2669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	IDE tuning and bus mastering support for the CS5510/CS5520
3669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	chipsets
4669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
5669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	The CS5510/CS5520 are slightly unusual devices. Unlike the
6669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	typical IDE controllers they do bus mastering with the drive in
7669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	PIO mode and smarter silicon.
8669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
9669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	The practical upshot of this is that we must always tune the
10669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	drive for the right PIO mode. We must also ignore all the blacklists
11669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	and the drive bus mastering DMA information. Also to confuse matters
12669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	further we can do DMA on PIO only drives.
13669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
14669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	DMA on the 5510 also requires we disable_hlt() during DMA on early
15669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	revisions.
16669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
17669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	*** This driver is strictly experimental ***
18669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
19669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	(c) Copyright Red Hat Inc 2002
20669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
21669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * This program is free software; you can redistribute it and/or modify it
22669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * under the terms of the GNU General Public License as published by the
23669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Free Software Foundation; either version 2, or (at your option) any
24669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * later version.
25669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
26669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * This program is distributed in the hope that it will be useful, but
27669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * WITHOUT ANY WARRANTY; without even the implied warranty of
28669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * General Public License for more details.
30669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
31669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Documentation:
32669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Not publically available.
33669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
34669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/kernel.h>
35669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/module.h>
36669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/pci.h>
37669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/init.h>
38669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/blkdev.h>
39669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/delay.h>
40669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <scsi/scsi_host.h>
41669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/libata.h>
42669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
43669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#define DRV_NAME	"pata_cs5520"
442a3103ce4357a09c2289405f969acec0edf4398fJeff Garzik#define DRV_VERSION	"0.6.6"
45669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
46669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstruct pio_clocks
47669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
48669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int address;
49669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int assert;
50669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int recovery;
51669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
52669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
53669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic const struct pio_clocks cs5520_pio_clocks[]={
54669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{3, 6, 11},
55669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{2, 5, 6},
56669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{1, 4, 3},
57669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{1, 3, 2},
58669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{1, 2, 1}
59669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
60669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
61669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
62669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	cs5520_set_timings	-	program PIO timings
63669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@ap: ATA port
64669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: ATA device
65669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
66669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Program the PIO mode timings for the controller according to the pio
67669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	clocking table.
68669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
69669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
70669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void cs5520_set_timings(struct ata_port *ap, struct ata_device *adev, int pio)
71669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
72669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
73669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int slave = adev->devno;
74669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
75669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pio -= XFER_PIO_0;
76669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
77669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Channel command timing */
78669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_write_config_byte(pdev, 0x62 + ap->port_no,
79669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				(cs5520_pio_clocks[pio].recovery << 4) |
80669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				(cs5520_pio_clocks[pio].assert));
81669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* FIXME: should these use address ? */
82669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Read command timing */
83669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_write_config_byte(pdev, 0x64 +  4*ap->port_no + slave,
84669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				(cs5520_pio_clocks[pio].recovery << 4) |
85669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				(cs5520_pio_clocks[pio].assert));
86669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Write command timing */
87669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_write_config_byte(pdev, 0x66 +  4*ap->port_no + slave,
88669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				(cs5520_pio_clocks[pio].recovery << 4) |
89669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				(cs5520_pio_clocks[pio].assert));
90669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
91669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
92669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
93669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	cs5520_enable_dma	-	turn on DMA bits
94669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
95669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Turn on the DMA bits for this disk. Needed because the BIOS probably
96669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	has not done the work for us. Belongs in the core SATA code.
97669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
98669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
99669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void cs5520_enable_dma(struct ata_port *ap, struct ata_device *adev)
100669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
101669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Set the DMA enable/disable flag */
1020d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	u8 reg = ioread8(ap->ioaddr.bmdma_addr + 0x02);
103669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	reg |= 1<<(adev->devno + 5);
1040d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	iowrite8(reg, ap->ioaddr.bmdma_addr + 0x02);
105669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
106669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
107669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
108669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	cs5520_set_dmamode	-	program DMA timings
109669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@ap: ATA port
110669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: ATA device
111669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
112669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Program the DMA mode timings for the controller according to the pio
113669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	clocking table. Note that this device sets the DMA timings to PIO
114669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	mode values. This may seem bizarre but the 5520 architecture talks
115669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	PIO mode to the disk and DMA mode to the controller so the underlying
116669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	transfers are PIO timed.
117669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
118669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
119669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void cs5520_set_dmamode(struct ata_port *ap, struct ata_device *adev)
120669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
121669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	static const int dma_xlate[3] = { XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 };
122669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	cs5520_set_timings(ap, adev, dma_xlate[adev->dma_mode]);
123669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	cs5520_enable_dma(ap, adev);
124669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
125669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
126669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
127669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	cs5520_set_piomode	-	program PIO timings
128669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@ap: ATA port
129669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: ATA device
130669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
131669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Program the PIO mode timings for the controller according to the pio
132669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	clocking table. We know pio_mode will equal dma_mode because of the
133669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	CS5520 architecture. At least once we turned DMA on and wrote a
134669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	mode setter.
135669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
136669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
137669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void cs5520_set_piomode(struct ata_port *ap, struct ata_device *adev)
138669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
139669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	cs5520_set_timings(ap, adev, adev->pio_mode);
140669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
141669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
142669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct scsi_host_template cs5520_sht = {
14368d1d07b510bb57a504588adc2bd2758adea0965Tejun Heo	ATA_BMDMA_SHT(DRV_NAME),
144d26fc9551a15fdad0d5de8376a78816b8af44f00Alan Cox	.sg_tablesize		= LIBATA_DUMB_MAX_PRD,
145669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
146669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
147669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations cs5520_port_ops = {
148029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.inherits		= &ata_bmdma_port_ops,
1499363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo	.qc_prep		= ata_sff_dumb_qc_prep,
150029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.cable_detect		= ata_cable_40wire,
151669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.set_piomode		= cs5520_set_piomode,
152669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.set_dmamode		= cs5520_set_dmamode,
153669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
154669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1555d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heostatic int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
156669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
157cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo	static const unsigned int cmd_port[] = { 0x1F0, 0x170 };
158cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo	static const unsigned int ctl_port[] = { 0x3F6, 0x376 };
1595d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	struct ata_port_info pi = {
1605d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo		.flags		= ATA_FLAG_SLAVE_POSS,
16114bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø		.pio_mask	= ATA_PIO4,
1625d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo		.port_ops	= &cs5520_port_ops,
1635d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	};
1645d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	const struct ata_port_info *ppi[2];
165669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 pcicfg;
1664ca4e439640cd1d3659cbcf60e7a73c2ae0450b3Al Viro	void __iomem *iomap[5];
1675d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	struct ata_host *host;
1685d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	struct ata_ioports *ioaddr;
1695d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	int i, rc;
170669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
171f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	rc = pcim_enable_device(pdev);
172f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	if (rc)
173f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo		return rc;
174f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo
175669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* IDE port enable bits */
1765d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	pci_read_config_byte(pdev, 0x60, &pcicfg);
177669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
178669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Check if the ATA ports are enabled */
179669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if ((pcicfg & 3) == 0)
180669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		return -ENODEV;
181669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1825d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ppi[0] = ppi[1] = &ata_dummy_port_info;
1835d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	if (pcicfg & 1)
1845d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo		ppi[0] = &pi;
1855d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	if (pcicfg & 2)
1865d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo		ppi[1] = &pi;
1875d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo
188669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if ((pcicfg & 0x40) == 0) {
1895d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo		dev_printk(KERN_WARNING, &pdev->dev,
1905d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo			   "DMA mode disabled. Enabling.\n");
1915d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo		pci_write_config_byte(pdev, 0x60, pcicfg | 0x40);
192669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
193669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1945d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	pi.mwdma_mask = id->driver_data;
1955d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo
1965d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
1975d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	if (!host)
1985d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo		return -ENOMEM;
1995d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo
200669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Perform set up for DMA */
2010948391641918b95d8d96c15089eb5ac156850b3Benjamin Herrenschmidt	if (pci_enable_device_io(pdev)) {
202669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		printk(KERN_ERR DRV_NAME ": unable to configure BAR2.\n");
203669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		return -ENODEV;
204669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
2055d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo
206284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
207669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		printk(KERN_ERR DRV_NAME ": unable to configure DMA mask.\n");
208669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		return -ENODEV;
209669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
210284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang	if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
211669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		printk(KERN_ERR DRV_NAME ": unable to configure consistent DMA mask.\n");
212669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		return -ENODEV;
213669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
214669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
2155d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	/* Map IO ports and initialize host accordingly */
216cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo	iomap[0] = devm_ioport_map(&pdev->dev, cmd_port[0], 8);
217cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo	iomap[1] = devm_ioport_map(&pdev->dev, ctl_port[0], 1);
218cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo	iomap[2] = devm_ioport_map(&pdev->dev, cmd_port[1], 8);
219cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo	iomap[3] = devm_ioport_map(&pdev->dev, ctl_port[1], 1);
2205d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	iomap[4] = pcim_iomap(pdev, 2, 0);
2210d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo
2220d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	if (!iomap[0] || !iomap[1] || !iomap[2] || !iomap[3] || !iomap[4])
2230d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		return -ENOMEM;
2240d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo
2255d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ioaddr = &host->ports[0]->ioaddr;
2265d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ioaddr->cmd_addr = iomap[0];
2275d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ioaddr->ctl_addr = iomap[1];
2285d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ioaddr->altstatus_addr = iomap[1];
2295d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ioaddr->bmdma_addr = iomap[4];
2309363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo	ata_sff_std_ports(ioaddr);
2315d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo
232cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo	ata_port_desc(host->ports[0],
233cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		      "cmd 0x%x ctl 0x%x", cmd_port[0], ctl_port[0]);
234cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo	ata_port_pbar_desc(host->ports[0], 4, 0, "bmdma");
235cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo
2365d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ioaddr = &host->ports[1]->ioaddr;
2375d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ioaddr->cmd_addr = iomap[2];
2385d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ioaddr->ctl_addr = iomap[3];
2395d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ioaddr->altstatus_addr = iomap[3];
2405d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	ioaddr->bmdma_addr = iomap[4] + 8;
2419363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo	ata_sff_std_ports(ioaddr);
2425d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo
243cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo	ata_port_desc(host->ports[1],
244cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		      "cmd 0x%x ctl 0x%x", cmd_port[1], ctl_port[1]);
245cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo	ata_port_pbar_desc(host->ports[1], 4, 8, "bmdma");
246cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo
2475d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	/* activate the host */
2485d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	pci_set_master(pdev);
2495d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	rc = ata_host_start(host);
2505d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	if (rc)
2515d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo		return rc;
2525d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo
2535d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	for (i = 0; i < 2; i++) {
2545d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo		static const int irq[] = { 14, 15 };
2558c6b065b792061c2e471d530127f2348fd9d243dAlan Cox		struct ata_port *ap = host->ports[i];
2565d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo
2575d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo		if (ata_port_is_dummy(ap))
2585d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo			continue;
2595d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo
2605d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo		rc = devm_request_irq(&pdev->dev, irq[ap->port_no],
2619363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo				      ata_sff_interrupt, 0, DRV_NAME, host);
2625d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo		if (rc)
2635d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo			return rc;
2644031826b3ca40982880f6b9f2282c7d7fad60d77Tejun Heo
265cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo		ata_port_desc(ap, "irq %d", irq[i]);
2665d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	}
2675d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo
2685d728824efeda61d304153bfcf1378a3c18b7d70Tejun Heo	return ata_host_register(host, &cs5520_sht);
269669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
270669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
271438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#ifdef CONFIG_PM
2728501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox/**
2738501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox *	cs5520_reinit_one	-	device resume
2748501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox *	@pdev: PCI device
2758501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox *
2768501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox *	Do any reconfiguration work needed by a resume from RAM. We need
2778501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox *	to restore DMA mode support on BIOSen which disabled it
2788501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox */
279f20b16ff7c19d1c369ee07470952aca093551ed0Jeff Garzik
2808501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Coxstatic int cs5520_reinit_one(struct pci_dev *pdev)
2818501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox{
282f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	struct ata_host *host = dev_get_drvdata(&pdev->dev);
2838501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox	u8 pcicfg;
284f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	int rc;
285f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo
286f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	rc = ata_pci_device_do_resume(pdev);
287f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	if (rc)
288f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo		return rc;
289f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo
2908501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox	pci_read_config_byte(pdev, 0x60, &pcicfg);
2918501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox	if ((pcicfg & 0x40) == 0)
2928501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox		pci_write_config_byte(pdev, 0x60, pcicfg | 0x40);
293f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo
294f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	ata_host_resume(host);
295f08048e94564d009b19038cfbdd800aa83e79c7fTejun Heo	return 0;
2968501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox}
297aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox
298aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox/**
299aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox *	cs5520_pci_device_suspend	-	device suspend
300aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox *	@pdev: PCI device
301aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox *
302aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox *	We have to cut and waste bits from the standard method because
303aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox *	the 5520 is a bit odd and not just a pure ATA device. As a result
304aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox *	we must not disable it. The needed code is short and this avoids
305aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox *	chip specific mess in the core code.
306aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox */
307aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox
308aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Coxstatic int cs5520_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
309aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox{
310aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox	struct ata_host *host = dev_get_drvdata(&pdev->dev);
311aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox	int rc = 0;
312aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox
313aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox	rc = ata_host_suspend(host, mesg);
314aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox	if (rc)
315aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox		return rc;
316aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox
317aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox	pci_save_state(pdev);
318aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox	return 0;
319aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox}
320438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#endif /* CONFIG_PM */
321a84471fe269c38ea3725345c43ad64e5f489bea2Jeff Garzik
322669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/* For now keep DMA off. We can set it for all but A rev CS5510 once the
323669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik   core ATA code can handle it */
324669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
3252d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzikstatic const struct pci_device_id pata_cs5520[] = {
3262d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), },
3272d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5520), },
3282d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
3292d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ },
330669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
331669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
332669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct pci_driver cs5520_pci_driver = {
333669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.name 		= DRV_NAME,
334669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.id_table	= pata_cs5520,
335669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.probe 		= cs5520_init_one,
3362855568b1ee4f58ef2c0a13ddfceb4b0b216b7edJeff Garzik	.remove		= ata_pci_remove_one,
337438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#ifdef CONFIG_PM
338aa6de4942c25f05cb7f4aa8efa20c5ec0884d8f1Alan Cox	.suspend	= cs5520_pci_device_suspend,
3398501120f1df1aa6abe38b51ab91df08ccaa1b971Alan Cox	.resume		= cs5520_reinit_one,
340438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#endif
341669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
342669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
343669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic int __init cs5520_init(void)
344669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
345669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	return pci_register_driver(&cs5520_pci_driver);
346669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
347669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
348669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void __exit cs5520_exit(void)
349669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
350669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_unregister_driver(&cs5520_pci_driver);
351669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
352669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
353669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_AUTHOR("Alan Cox");
354669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_DESCRIPTION("low-level driver for Cyrix CS5510/5520");
355669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_LICENSE("GPL");
356669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_DEVICE_TABLE(pci, pata_cs5520);
357669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_VERSION(DRV_VERSION);
358669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
359669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_init(cs5520_init);
360669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikmodule_exit(cs5520_exit);
361669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
362