pata_pdc202xx_old.c revision 81ad1837b590775336f68eafcae8dab13a975b3a
1669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/*
2669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * pata_pdc202xx_old.c 	- Promise PDC202xx PATA for new ATA layer
3669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *			  (C) 2005 Red Hat Inc
4669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *			  Alan Cox <alan@redhat.com>
563ed71019c4437caef65fca1f83c990ae729024fBartlomiej Zolnierkiewicz *			  (C) 2007 Bartlomiej Zolnierkiewicz
6669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
7669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * Based in part on linux/drivers/ide/pci/pdc202xx_old.c
8669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
9669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * First cut with LBA48/ATAPI
10669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
11669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik * TODO:
1263ed71019c4437caef65fca1f83c990ae729024fBartlomiej Zolnierkiewicz *	Channel interlock/reset on both required
13669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
1485cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
15669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/kernel.h>
16669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/module.h>
17669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/pci.h>
18669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/init.h>
19669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/blkdev.h>
20669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/delay.h>
21669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <scsi/scsi_host.h>
22669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#include <linux/libata.h>
23669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
24669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik#define DRV_NAME "pata_pdc202xx_old"
25a0fcdc0259e98d1c16d96baea9ba8a8603e41791Jeff Garzik#define DRV_VERSION "0.4.2"
26669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
27a0fcdc0259e98d1c16d96baea9ba8a8603e41791Jeff Garzikstatic int pdc2026x_cable_detect(struct ata_port *ap)
28669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
29669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
30669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u16 cis;
3185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
32669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_read_config_word(pdev, 0x50, &cis);
33669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (cis & (1 << (10 + ap->port_no)))
34a0ac38f16045f90dbbcd265b638cd7254c53aa65Alan Cox		return ATA_CBL_PATA40;
35a0ac38f16045f90dbbcd265b638cd7254c53aa65Alan Cox	return ATA_CBL_PATA80;
36669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
37669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
38669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
39ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox *	pdc202xx_configure_piomode	-	set chip PIO timing
40669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@ap: ATA interface
41669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: ATA device
42669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@pio: PIO mode
43669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
44669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Called to do the PIO mode setup. Our timing registers are shared
45669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	so a configure_dmamode call will undo any work we do here and vice
46669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	versa
47669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
4885cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
49ada406c8246b0792afe4d7f8ae7606093052de87Alan Coxstatic void pdc202xx_configure_piomode(struct ata_port *ap, struct ata_device *adev, int pio)
50669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
51669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
5263ed71019c4437caef65fca1f83c990ae729024fBartlomiej Zolnierkiewicz	int port = 0x60 + 8 * ap->port_no + 4 * adev->devno;
53669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	static u16 pio_timing[5] = {
54669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		0x0913, 0x050C , 0x0308, 0x0206, 0x0104
55669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	};
56669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 r_ap, r_bp;
57669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
58669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_read_config_byte(pdev, port, &r_ap);
59669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_read_config_byte(pdev, port + 1, &r_bp);
60669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	r_ap &= ~0x3F;	/* Preserve ERRDY_EN, SYNC_IN */
6163ed71019c4437caef65fca1f83c990ae729024fBartlomiej Zolnierkiewicz	r_bp &= ~0x1F;
62669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	r_ap |= (pio_timing[pio] >> 8);
63669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	r_bp |= (pio_timing[pio] & 0xFF);
6485cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
65669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (ata_pio_need_iordy(adev))
66669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		r_ap |= 0x20;	/* IORDY enable */
67669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (adev->class == ATA_DEV_ATA)
68669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		r_ap |= 0x10;	/* FIFO enable */
69669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_write_config_byte(pdev, port, r_ap);
70669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_write_config_byte(pdev, port + 1, r_bp);
71669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
72669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
73669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
74ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox *	pdc202xx_set_piomode	-	set initial PIO mode data
75669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@ap: ATA interface
76669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: ATA device
77669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
78669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Called to do the PIO mode setup. Our timing registers are shared
79669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	but we want to set the PIO timing by default.
80669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
8185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
82ada406c8246b0792afe4d7f8ae7606093052de87Alan Coxstatic void pdc202xx_set_piomode(struct ata_port *ap, struct ata_device *adev)
83669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
84ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox	pdc202xx_configure_piomode(ap, adev, adev->pio_mode - XFER_PIO_0);
85669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
86669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
87669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
88ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox *	pdc202xx_configure_dmamode	-	set DMA mode in chip
89669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@ap: ATA interface
90669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: ATA device
91669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
92669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Load DMA cycle times into the chip ready for a DMA transfer
93669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	to occur.
94669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
9585cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
96ada406c8246b0792afe4d7f8ae7606093052de87Alan Coxstatic void pdc202xx_set_dmamode(struct ata_port *ap, struct ata_device *adev)
97669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
98669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
9963ed71019c4437caef65fca1f83c990ae729024fBartlomiej Zolnierkiewicz	int port = 0x60 + 8 * ap->port_no + 4 * adev->devno;
100669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	static u8 udma_timing[6][2] = {
101669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		{ 0x60, 0x03 },	/* 33 Mhz Clock */
102669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		{ 0x40, 0x02 },
103669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		{ 0x20, 0x01 },
104669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		{ 0x40, 0x02 },	/* 66 Mhz Clock */
105669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		{ 0x20, 0x01 },
10685cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik		{ 0x20, 0x01 }
107669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	};
10863ed71019c4437caef65fca1f83c990ae729024fBartlomiej Zolnierkiewicz	static u8 mdma_timing[3][2] = {
10963ed71019c4437caef65fca1f83c990ae729024fBartlomiej Zolnierkiewicz		{ 0x60, 0x03 },
11063ed71019c4437caef65fca1f83c990ae729024fBartlomiej Zolnierkiewicz		{ 0x60, 0x04 },
11163ed71019c4437caef65fca1f83c990ae729024fBartlomiej Zolnierkiewicz		{ 0xe0, 0x0f },
11263ed71019c4437caef65fca1f83c990ae729024fBartlomiej Zolnierkiewicz	};
113669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u8 r_bp, r_cp;
11485cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
115669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_read_config_byte(pdev, port + 1, &r_bp);
116669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_read_config_byte(pdev, port + 2, &r_cp);
11785cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
11863ed71019c4437caef65fca1f83c990ae729024fBartlomiej Zolnierkiewicz	r_bp &= ~0xE0;
119669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	r_cp &= ~0x0F;
12085cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
121669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (adev->dma_mode >= XFER_UDMA_0) {
122669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		int speed = adev->dma_mode - XFER_UDMA_0;
123669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		r_bp |= udma_timing[speed][0];
124669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		r_cp |= udma_timing[speed][1];
12585cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
126669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	} else {
127669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		int speed = adev->dma_mode - XFER_MW_DMA_0;
12863ed71019c4437caef65fca1f83c990ae729024fBartlomiej Zolnierkiewicz		r_bp |= mdma_timing[speed][0];
12963ed71019c4437caef65fca1f83c990ae729024fBartlomiej Zolnierkiewicz		r_cp |= mdma_timing[speed][1];
130669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
131669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_write_config_byte(pdev, port + 1, r_bp);
132669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	pci_write_config_byte(pdev, port + 2, r_cp);
13385cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
134669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
135669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
136669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
137669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	pdc2026x_bmdma_start		-	DMA engine begin
138669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@qc: ATA command
139669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
140669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	In UDMA3 or higher we have to clock switch for the duration of the
141669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	DMA transfer sequence.
142669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
14385cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
144669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void pdc2026x_bmdma_start(struct ata_queued_cmd *qc)
145669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
146669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_port *ap = qc->ap;
147669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_device *adev = qc->dev;
148669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_taskfile *tf = &qc->tf;
149669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int sel66 = ap->port_no ? 0x08: 0x02;
150669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
1510d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *master = ap->host->ports[0]->ioaddr.bmdma_addr;
1520d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *clock = master + 0x11;
1530d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *atapi_reg = master + 0x20 + (4 * ap->port_no);
15485cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
155669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	u32 len;
15685cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
157669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Check we keep host level locking here */
158669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (adev->dma_mode >= XFER_UDMA_2)
1590d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		iowrite8(ioread8(clock) | sel66, clock);
160669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	else
1610d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		iowrite8(ioread8(clock) & ~sel66, clock);
162669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
16385cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik	/* The DMA clocks may have been trashed by a reset. FIXME: make conditional
164669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	   and move to qc_issue ? */
165ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox	pdc202xx_set_dmamode(ap, qc->dev);
166669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
167669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Cases the state machine will not complete correctly without help */
168669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if ((tf->flags & ATA_TFLAG_LBA48) ||  tf->protocol == ATA_PROT_ATAPI_DMA)
169669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	{
1705e5188108bcf9ab2e6f87b4b54924354040b0aa7Alan Cox		len = qc->nbytes / 2;
17185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
172669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (tf->flags & ATA_TFLAG_WRITE)
173669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			len |= 0x06000000;
174669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		else
175669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			len |= 0x05000000;
17685cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
1770d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		iowrite32(len, atapi_reg);
178669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
17985cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
18085cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik	/* Activate DMA */
181669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	ata_bmdma_start(qc);
182669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
183669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
184669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
185669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	pdc2026x_bmdma_end		-	DMA engine stop
186669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@qc: ATA command
187669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
188669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	After a DMA completes we need to put the clock back to 33MHz for
189669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	PIO timings.
190669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
19185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
192669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc)
193669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
194669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_port *ap = qc->ap;
195669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_device *adev = qc->dev;
196669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	struct ata_taskfile *tf = &qc->tf;
19785cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
198669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	int sel66 = ap->port_no ? 0x08: 0x02;
199669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* The clock bits are in the same register for both channels */
2000d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *master = ap->host->ports[0]->ioaddr.bmdma_addr;
2010d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *clock = master + 0x11;
2020d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	void __iomem *atapi_reg = master + 0x20 + (4 * ap->port_no);
20385cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
204669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Cases the state machine will not complete correctly */
205669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (tf->protocol == ATA_PROT_ATAPI_DMA || ( tf->flags & ATA_TFLAG_LBA48)) {
2060d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		iowrite32(0, atapi_reg);
2070d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		iowrite8(ioread8(clock) & ~sel66, clock);
208669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
209669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Check we keep host level locking here */
210669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	/* Flip back to 33Mhz for PIO */
211669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (adev->dma_mode >= XFER_UDMA_2)
2120d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo		iowrite8(ioread8(clock) & ~sel66, clock);
213669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
214669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	ata_bmdma_stop(qc);
215669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
216669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
217669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik/**
218669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	pdc2026x_dev_config	-	device setup hook
219669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	@adev: newly found device
220669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *
221669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	Perform chip specific early setup. We need to lock the transfer
222669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	sizes to 8bit to avoid making the state engine on the 2026x cards
223669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik *	barf.
224669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik */
22585cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
226cd0d3bbcdd650651b7ccfaf55d107e3fc237d95aAlan Coxstatic void pdc2026x_dev_config(struct ata_device *adev)
227669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
228669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	adev->max_sectors = 256;
229669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
230669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
231ada406c8246b0792afe4d7f8ae7606093052de87Alan Coxstatic struct scsi_host_template pdc202xx_sht = {
232669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.module			= THIS_MODULE,
233669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.name			= DRV_NAME,
234669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.ioctl			= ata_scsi_ioctl,
235669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.queuecommand		= ata_scsi_queuecmd,
236669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.can_queue		= ATA_DEF_QUEUE,
237669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.this_id		= ATA_SHT_THIS_ID,
238669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.sg_tablesize		= LIBATA_MAX_PRD,
239669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
240669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.emulated		= ATA_SHT_EMULATED,
241669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.use_clustering		= ATA_SHT_USE_CLUSTERING,
242669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.proc_name		= DRV_NAME,
243669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.dma_boundary		= ATA_DMA_BOUNDARY,
244669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.slave_configure	= ata_scsi_slave_config,
245afdfe899e6420eac6c5eb3bc8c89456dff38d40eTejun Heo	.slave_destroy		= ata_scsi_slave_destroy,
246669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bios_param		= ata_std_bios_param,
247669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
248669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
249669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations pdc2024x_port_ops = {
250ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox	.set_piomode	= pdc202xx_set_piomode,
251ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox	.set_dmamode	= pdc202xx_set_dmamode,
252669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.mode_filter	= ata_pci_default_filter,
253669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.tf_load	= ata_tf_load,
254669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.tf_read	= ata_tf_read,
255669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.check_status 	= ata_check_status,
256669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.exec_command	= ata_exec_command,
257669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.dev_select 	= ata_std_dev_select,
258669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
259669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.freeze		= ata_bmdma_freeze,
260669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.thaw		= ata_bmdma_thaw,
261a0fcdc0259e98d1c16d96baea9ba8a8603e41791Jeff Garzik	.error_handler	= ata_bmdma_error_handler,
262669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.post_internal_cmd = ata_bmdma_post_internal_cmd,
263a0fcdc0259e98d1c16d96baea9ba8a8603e41791Jeff Garzik	.cable_detect	= ata_cable_40wire,
264669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
265669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bmdma_setup 	= ata_bmdma_setup,
266669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bmdma_start 	= ata_bmdma_start,
267669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bmdma_stop	= ata_bmdma_stop,
268669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bmdma_status 	= ata_bmdma_status,
269669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
270669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.qc_prep 	= ata_qc_prep,
271669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.qc_issue	= ata_qc_issue_prot,
2720d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer	= ata_data_xfer,
273669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
274669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.irq_handler	= ata_interrupt,
275669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.irq_clear	= ata_bmdma_irq_clear,
276246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on		= ata_irq_on,
27785cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
27881ad1837b590775336f68eafcae8dab13a975b3aAlan Cox	.port_start	= ata_sff_port_start,
27985cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik};
280669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
281669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzikstatic struct ata_port_operations pdc2026x_port_ops = {
282ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox	.set_piomode	= pdc202xx_set_piomode,
283ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox	.set_dmamode	= pdc202xx_set_dmamode,
284669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.mode_filter	= ata_pci_default_filter,
285669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.tf_load	= ata_tf_load,
286669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.tf_read	= ata_tf_read,
287669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.check_status 	= ata_check_status,
288669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.exec_command	= ata_exec_command,
289669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.dev_select 	= ata_std_dev_select,
290669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.dev_config	= pdc2026x_dev_config,
291669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
292669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.freeze		= ata_bmdma_freeze,
293669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.thaw		= ata_bmdma_thaw,
294a0fcdc0259e98d1c16d96baea9ba8a8603e41791Jeff Garzik	.error_handler	= ata_bmdma_error_handler,
295669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.post_internal_cmd = ata_bmdma_post_internal_cmd,
296a0fcdc0259e98d1c16d96baea9ba8a8603e41791Jeff Garzik	.cable_detect	= pdc2026x_cable_detect,
297669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
298669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bmdma_setup 	= ata_bmdma_setup,
299669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bmdma_start 	= pdc2026x_bmdma_start,
300669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bmdma_stop	= pdc2026x_bmdma_stop,
301669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.bmdma_status 	= ata_bmdma_status,
302669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
303669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.qc_prep 	= ata_qc_prep,
304669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.qc_issue	= ata_qc_issue_prot,
3050d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo	.data_xfer	= ata_data_xfer,
306669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
307669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.irq_handler	= ata_interrupt,
308669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	.irq_clear	= ata_bmdma_irq_clear,
309246ce3b675843e0369643cceb4faeb6cf6d19a30Akira Iguchi	.irq_on		= ata_irq_on,
31085cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
31181ad1837b590775336f68eafcae8dab13a975b3aAlan Cox	.port_start	= ata_sff_port_start,
31285cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik};
313669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
314ada406c8246b0792afe4d7f8ae7606093052de87Alan Coxstatic int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
315669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
3161626aeb881236c8cb022b5e4ca594146a951d669Tejun Heo	static const struct ata_port_info info[3] = {
317669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		{
318ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox			.sht = &pdc202xx_sht,
3191d2808fd3d2d5d2c0483796a0f443d1cb3f11367Jeff Garzik			.flags = ATA_FLAG_SLAVE_POSS,
320669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			.pio_mask = 0x1f,
321669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			.mwdma_mask = 0x07,
322669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			.udma_mask = ATA_UDMA2,
323669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			.port_ops = &pdc2024x_port_ops
32485cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik		},
325669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		{
326ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox			.sht = &pdc202xx_sht,
3271d2808fd3d2d5d2c0483796a0f443d1cb3f11367Jeff Garzik			.flags = ATA_FLAG_SLAVE_POSS,
328669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			.pio_mask = 0x1f,
329669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			.mwdma_mask = 0x07,
330669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			.udma_mask = ATA_UDMA4,
331669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			.port_ops = &pdc2026x_port_ops
332669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		},
333669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		{
334ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox			.sht = &pdc202xx_sht,
3351d2808fd3d2d5d2c0483796a0f443d1cb3f11367Jeff Garzik			.flags = ATA_FLAG_SLAVE_POSS,
336669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			.pio_mask = 0x1f,
337669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			.mwdma_mask = 0x07,
338669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			.udma_mask = ATA_UDMA5,
339669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			.port_ops = &pdc2026x_port_ops
340669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		}
34185cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
342669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	};
3431626aeb881236c8cb022b5e4ca594146a951d669Tejun Heo	const struct ata_port_info *ppi[] = { &info[id->driver_data], NULL };
34485cd7251b9112e3dabeac9fd3b175601ca607241Jeff Garzik
345669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	if (dev->device == PCI_DEVICE_ID_PROMISE_20265) {
346669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		struct pci_dev *bridge = dev->bus->self;
347669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		/* Don't grab anything behind a Promise I2O RAID */
348669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		if (bridge && bridge->vendor == PCI_VENDOR_ID_INTEL) {
349669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			if( bridge->device == PCI_DEVICE_ID_INTEL_I960)
350669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				return -ENODEV;
351669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik			if( bridge->device == PCI_DEVICE_ID_INTEL_I960RM)
352669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik				return -ENODEV;
353669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik		}
354669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik	}
3551626aeb881236c8cb022b5e4ca594146a951d669Tejun Heo	return ata_pci_init_one(dev, ppi);
356669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
357669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
358ada406c8246b0792afe4d7f8ae7606093052de87Alan Coxstatic const struct pci_device_id pdc202xx[] = {
3592d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20246), 0 },
3602d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20262), 1 },
3612d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20263), 1 },
3622d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20265), 2 },
3632d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ PCI_VDEVICE(PROMISE, PCI_DEVICE_ID_PROMISE_20267), 2 },
3642d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik
3652d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	{ },
366669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
367669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
368ada406c8246b0792afe4d7f8ae7606093052de87Alan Coxstatic struct pci_driver pdc202xx_pci_driver = {
3692d2744fc8be620a2dc469cf48349e3e704119f1bJeff Garzik	.name 		= DRV_NAME,
370ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox	.id_table	= pdc202xx,
371ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox	.probe 		= pdc202xx_init_one,
37262d64ae0ec76360736c9dc4ca2067ae8de0ba9f2Alan Cox	.remove		= ata_pci_remove_one,
373438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#ifdef CONFIG_PM
37462d64ae0ec76360736c9dc4ca2067ae8de0ba9f2Alan Cox	.suspend	= ata_pci_device_suspend,
37562d64ae0ec76360736c9dc4ca2067ae8de0ba9f2Alan Cox	.resume		= ata_pci_device_resume,
376438ac6d5e3f8106a6bd1a5682c508d660294a85dTejun Heo#endif
377669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik};
378669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
379ada406c8246b0792afe4d7f8ae7606093052de87Alan Coxstatic int __init pdc202xx_init(void)
380669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
381ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox	return pci_register_driver(&pdc202xx_pci_driver);
382669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
383669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
384ada406c8246b0792afe4d7f8ae7606093052de87Alan Coxstatic void __exit pdc202xx_exit(void)
385669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik{
386ada406c8246b0792afe4d7f8ae7606093052de87Alan Cox	pci_unregister_driver(&pdc202xx_pci_driver);
387669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik}
388669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
389669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_AUTHOR("Alan Cox");
390669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_DESCRIPTION("low-level driver for Promise 2024x and 20262-20267");
391669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_LICENSE("GPL");
392ada406c8246b0792afe4d7f8ae7606093052de87Alan CoxMODULE_DEVICE_TABLE(pci, pdc202xx);
393669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff GarzikMODULE_VERSION(DRV_VERSION);
394669a5db411d85a14f86cd92bc16bf7ab5b8aa235Jeff Garzik
395ada406c8246b0792afe4d7f8ae7606093052de87Alan Coxmodule_init(pdc202xx_init);
396ada406c8246b0792afe4d7f8ae7606093052de87Alan Coxmodule_exit(pdc202xx_exit);
397