162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  pata_rdc		-	Driver for later RDC PATA controllers
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  This is actually a driver for hardware meeting
662306a36Sopenharmony_ci *  INCITS 370-2004 (1510D): ATA Host Adapter Standards
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *  Based on ata_piix.
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/kernel.h>
1262306a36Sopenharmony_ci#include <linux/module.h>
1362306a36Sopenharmony_ci#include <linux/pci.h>
1462306a36Sopenharmony_ci#include <linux/blkdev.h>
1562306a36Sopenharmony_ci#include <linux/delay.h>
1662306a36Sopenharmony_ci#include <linux/device.h>
1762306a36Sopenharmony_ci#include <linux/gfp.h>
1862306a36Sopenharmony_ci#include <scsi/scsi_host.h>
1962306a36Sopenharmony_ci#include <linux/libata.h>
2062306a36Sopenharmony_ci#include <linux/dmi.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define DRV_NAME	"pata_rdc"
2362306a36Sopenharmony_ci#define DRV_VERSION	"0.01"
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistruct rdc_host_priv {
2662306a36Sopenharmony_ci	u32 saved_iocfg;
2762306a36Sopenharmony_ci};
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/**
3062306a36Sopenharmony_ci *	rdc_pata_cable_detect - Probe host controller cable detect info
3162306a36Sopenharmony_ci *	@ap: Port for which cable detect info is desired
3262306a36Sopenharmony_ci *
3362306a36Sopenharmony_ci *	Read 80c cable indicator from ATA PCI device's PCI config
3462306a36Sopenharmony_ci *	register.  This register is normally set by firmware (BIOS).
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci *	LOCKING:
3762306a36Sopenharmony_ci *	None (inherited from caller).
3862306a36Sopenharmony_ci */
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistatic int rdc_pata_cable_detect(struct ata_port *ap)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	struct rdc_host_priv *hpriv = ap->host->private_data;
4362306a36Sopenharmony_ci	u8 mask;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	/* check BIOS cable detect results */
4662306a36Sopenharmony_ci	mask = 0x30 << (2 * ap->port_no);
4762306a36Sopenharmony_ci	if ((hpriv->saved_iocfg & mask) == 0)
4862306a36Sopenharmony_ci		return ATA_CBL_PATA40;
4962306a36Sopenharmony_ci	return ATA_CBL_PATA80;
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/**
5362306a36Sopenharmony_ci *	rdc_pata_prereset - prereset for PATA host controller
5462306a36Sopenharmony_ci *	@link: Target link
5562306a36Sopenharmony_ci *	@deadline: deadline jiffies for the operation
5662306a36Sopenharmony_ci *
5762306a36Sopenharmony_ci *	LOCKING:
5862306a36Sopenharmony_ci *	None (inherited from caller).
5962306a36Sopenharmony_ci */
6062306a36Sopenharmony_cistatic int rdc_pata_prereset(struct ata_link *link, unsigned long deadline)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	struct ata_port *ap = link->ap;
6362306a36Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	static const struct pci_bits rdc_enable_bits[] = {
6662306a36Sopenharmony_ci		{ 0x41U, 1U, 0x80UL, 0x80UL },	/* port 0 */
6762306a36Sopenharmony_ci		{ 0x43U, 1U, 0x80UL, 0x80UL },	/* port 1 */
6862306a36Sopenharmony_ci	};
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	if (!pci_test_config_bits(pdev, &rdc_enable_bits[ap->port_no]))
7162306a36Sopenharmony_ci		return -ENOENT;
7262306a36Sopenharmony_ci	return ata_sff_prereset(link, deadline);
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic DEFINE_SPINLOCK(rdc_lock);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/**
7862306a36Sopenharmony_ci *	rdc_set_piomode - Initialize host controller PATA PIO timings
7962306a36Sopenharmony_ci *	@ap: Port whose timings we are configuring
8062306a36Sopenharmony_ci *	@adev: um
8162306a36Sopenharmony_ci *
8262306a36Sopenharmony_ci *	Set PIO mode for device, in host controller PCI config space.
8362306a36Sopenharmony_ci *
8462306a36Sopenharmony_ci *	LOCKING:
8562306a36Sopenharmony_ci *	None (inherited from caller).
8662306a36Sopenharmony_ci */
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic void rdc_set_piomode(struct ata_port *ap, struct ata_device *adev)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
9162306a36Sopenharmony_ci	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
9262306a36Sopenharmony_ci	unsigned long flags;
9362306a36Sopenharmony_ci	unsigned int is_slave	= (adev->devno != 0);
9462306a36Sopenharmony_ci	unsigned int master_port= ap->port_no ? 0x42 : 0x40;
9562306a36Sopenharmony_ci	unsigned int slave_port	= 0x44;
9662306a36Sopenharmony_ci	u16 master_data;
9762306a36Sopenharmony_ci	u8 slave_data;
9862306a36Sopenharmony_ci	u8 udma_enable;
9962306a36Sopenharmony_ci	int control = 0;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	static const	 /* ISP  RTC */
10262306a36Sopenharmony_ci	u8 timings[][2]	= { { 0, 0 },
10362306a36Sopenharmony_ci			    { 0, 0 },
10462306a36Sopenharmony_ci			    { 1, 0 },
10562306a36Sopenharmony_ci			    { 2, 1 },
10662306a36Sopenharmony_ci			    { 2, 3 }, };
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	if (pio >= 2)
10962306a36Sopenharmony_ci		control |= 1;	/* TIME1 enable */
11062306a36Sopenharmony_ci	if (ata_pio_need_iordy(adev))
11162306a36Sopenharmony_ci		control |= 2;	/* IE enable */
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	if (adev->class == ATA_DEV_ATA)
11462306a36Sopenharmony_ci		control |= 4;	/* PPE enable */
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	spin_lock_irqsave(&rdc_lock, flags);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	/* PIO configuration clears DTE unconditionally.  It will be
11962306a36Sopenharmony_ci	 * programmed in set_dmamode which is guaranteed to be called
12062306a36Sopenharmony_ci	 * after set_piomode if any DMA mode is available.
12162306a36Sopenharmony_ci	 */
12262306a36Sopenharmony_ci	pci_read_config_word(dev, master_port, &master_data);
12362306a36Sopenharmony_ci	if (is_slave) {
12462306a36Sopenharmony_ci		/* clear TIME1|IE1|PPE1|DTE1 */
12562306a36Sopenharmony_ci		master_data &= 0xff0f;
12662306a36Sopenharmony_ci		/* Enable SITRE (separate slave timing register) */
12762306a36Sopenharmony_ci		master_data |= 0x4000;
12862306a36Sopenharmony_ci		/* enable PPE1, IE1 and TIME1 as needed */
12962306a36Sopenharmony_ci		master_data |= (control << 4);
13062306a36Sopenharmony_ci		pci_read_config_byte(dev, slave_port, &slave_data);
13162306a36Sopenharmony_ci		slave_data &= (ap->port_no ? 0x0f : 0xf0);
13262306a36Sopenharmony_ci		/* Load the timing nibble for this slave */
13362306a36Sopenharmony_ci		slave_data |= ((timings[pio][0] << 2) | timings[pio][1])
13462306a36Sopenharmony_ci						<< (ap->port_no ? 4 : 0);
13562306a36Sopenharmony_ci	} else {
13662306a36Sopenharmony_ci		/* clear ISP|RCT|TIME0|IE0|PPE0|DTE0 */
13762306a36Sopenharmony_ci		master_data &= 0xccf0;
13862306a36Sopenharmony_ci		/* Enable PPE, IE and TIME as appropriate */
13962306a36Sopenharmony_ci		master_data |= control;
14062306a36Sopenharmony_ci		/* load ISP and RCT */
14162306a36Sopenharmony_ci		master_data |=
14262306a36Sopenharmony_ci			(timings[pio][0] << 12) |
14362306a36Sopenharmony_ci			(timings[pio][1] << 8);
14462306a36Sopenharmony_ci	}
14562306a36Sopenharmony_ci	pci_write_config_word(dev, master_port, master_data);
14662306a36Sopenharmony_ci	if (is_slave)
14762306a36Sopenharmony_ci		pci_write_config_byte(dev, slave_port, slave_data);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	/* Ensure the UDMA bit is off - it will be turned back on if
15062306a36Sopenharmony_ci	   UDMA is selected */
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	pci_read_config_byte(dev, 0x48, &udma_enable);
15362306a36Sopenharmony_ci	udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
15462306a36Sopenharmony_ci	pci_write_config_byte(dev, 0x48, udma_enable);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	spin_unlock_irqrestore(&rdc_lock, flags);
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci/**
16062306a36Sopenharmony_ci *	rdc_set_dmamode - Initialize host controller PATA PIO timings
16162306a36Sopenharmony_ci *	@ap: Port whose timings we are configuring
16262306a36Sopenharmony_ci *	@adev: Drive in question
16362306a36Sopenharmony_ci *
16462306a36Sopenharmony_ci *	Set UDMA mode for device, in host controller PCI config space.
16562306a36Sopenharmony_ci *
16662306a36Sopenharmony_ci *	LOCKING:
16762306a36Sopenharmony_ci *	None (inherited from caller).
16862306a36Sopenharmony_ci */
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic void rdc_set_dmamode(struct ata_port *ap, struct ata_device *adev)
17162306a36Sopenharmony_ci{
17262306a36Sopenharmony_ci	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
17362306a36Sopenharmony_ci	unsigned long flags;
17462306a36Sopenharmony_ci	u8 master_port		= ap->port_no ? 0x42 : 0x40;
17562306a36Sopenharmony_ci	u16 master_data;
17662306a36Sopenharmony_ci	u8 speed		= adev->dma_mode;
17762306a36Sopenharmony_ci	int devid		= adev->devno + 2 * ap->port_no;
17862306a36Sopenharmony_ci	u8 udma_enable		= 0;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	static const	 /* ISP  RTC */
18162306a36Sopenharmony_ci	u8 timings[][2]	= { { 0, 0 },
18262306a36Sopenharmony_ci			    { 0, 0 },
18362306a36Sopenharmony_ci			    { 1, 0 },
18462306a36Sopenharmony_ci			    { 2, 1 },
18562306a36Sopenharmony_ci			    { 2, 3 }, };
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	spin_lock_irqsave(&rdc_lock, flags);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	pci_read_config_word(dev, master_port, &master_data);
19062306a36Sopenharmony_ci	pci_read_config_byte(dev, 0x48, &udma_enable);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	if (speed >= XFER_UDMA_0) {
19362306a36Sopenharmony_ci		unsigned int udma = adev->dma_mode - XFER_UDMA_0;
19462306a36Sopenharmony_ci		u16 udma_timing;
19562306a36Sopenharmony_ci		u16 ideconf;
19662306a36Sopenharmony_ci		int u_clock, u_speed;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci		/*
19962306a36Sopenharmony_ci		 * UDMA is handled by a combination of clock switching and
20062306a36Sopenharmony_ci		 * selection of dividers
20162306a36Sopenharmony_ci		 *
20262306a36Sopenharmony_ci		 * Handy rule: Odd modes are UDMATIMx 01, even are 02
20362306a36Sopenharmony_ci		 *	       except UDMA0 which is 00
20462306a36Sopenharmony_ci		 */
20562306a36Sopenharmony_ci		u_speed = min(2 - (udma & 1), udma);
20662306a36Sopenharmony_ci		if (udma == 5)
20762306a36Sopenharmony_ci			u_clock = 0x1000;	/* 100Mhz */
20862306a36Sopenharmony_ci		else if (udma > 2)
20962306a36Sopenharmony_ci			u_clock = 1;		/* 66Mhz */
21062306a36Sopenharmony_ci		else
21162306a36Sopenharmony_ci			u_clock = 0;		/* 33Mhz */
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci		udma_enable |= (1 << devid);
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci		/* Load the CT/RP selection */
21662306a36Sopenharmony_ci		pci_read_config_word(dev, 0x4A, &udma_timing);
21762306a36Sopenharmony_ci		udma_timing &= ~(3 << (4 * devid));
21862306a36Sopenharmony_ci		udma_timing |= u_speed << (4 * devid);
21962306a36Sopenharmony_ci		pci_write_config_word(dev, 0x4A, udma_timing);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci		/* Select a 33/66/100Mhz clock */
22262306a36Sopenharmony_ci		pci_read_config_word(dev, 0x54, &ideconf);
22362306a36Sopenharmony_ci		ideconf &= ~(0x1001 << devid);
22462306a36Sopenharmony_ci		ideconf |= u_clock << devid;
22562306a36Sopenharmony_ci		pci_write_config_word(dev, 0x54, ideconf);
22662306a36Sopenharmony_ci	} else {
22762306a36Sopenharmony_ci		/*
22862306a36Sopenharmony_ci		 * MWDMA is driven by the PIO timings. We must also enable
22962306a36Sopenharmony_ci		 * IORDY unconditionally along with TIME1. PPE has already
23062306a36Sopenharmony_ci		 * been set when the PIO timing was set.
23162306a36Sopenharmony_ci		 */
23262306a36Sopenharmony_ci		unsigned int mwdma	= adev->dma_mode - XFER_MW_DMA_0;
23362306a36Sopenharmony_ci		unsigned int control;
23462306a36Sopenharmony_ci		u8 slave_data;
23562306a36Sopenharmony_ci		const unsigned int needed_pio[3] = {
23662306a36Sopenharmony_ci			XFER_PIO_0, XFER_PIO_3, XFER_PIO_4
23762306a36Sopenharmony_ci		};
23862306a36Sopenharmony_ci		int pio = needed_pio[mwdma] - XFER_PIO_0;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci		control = 3;	/* IORDY|TIME1 */
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci		/* If the drive MWDMA is faster than it can do PIO then
24362306a36Sopenharmony_ci		   we must force PIO into PIO0 */
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci		if (adev->pio_mode < needed_pio[mwdma])
24662306a36Sopenharmony_ci			/* Enable DMA timing only */
24762306a36Sopenharmony_ci			control |= 8;	/* PIO cycles in PIO0 */
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci		if (adev->devno) {	/* Slave */
25062306a36Sopenharmony_ci			master_data &= 0xFF4F;  /* Mask out IORDY|TIME1|DMAONLY */
25162306a36Sopenharmony_ci			master_data |= control << 4;
25262306a36Sopenharmony_ci			pci_read_config_byte(dev, 0x44, &slave_data);
25362306a36Sopenharmony_ci			slave_data &= (ap->port_no ? 0x0f : 0xf0);
25462306a36Sopenharmony_ci			/* Load the matching timing */
25562306a36Sopenharmony_ci			slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
25662306a36Sopenharmony_ci			pci_write_config_byte(dev, 0x44, slave_data);
25762306a36Sopenharmony_ci		} else { 	/* Master */
25862306a36Sopenharmony_ci			master_data &= 0xCCF4;	/* Mask out IORDY|TIME1|DMAONLY
25962306a36Sopenharmony_ci						   and master timing bits */
26062306a36Sopenharmony_ci			master_data |= control;
26162306a36Sopenharmony_ci			master_data |=
26262306a36Sopenharmony_ci				(timings[pio][0] << 12) |
26362306a36Sopenharmony_ci				(timings[pio][1] << 8);
26462306a36Sopenharmony_ci		}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci		udma_enable &= ~(1 << devid);
26762306a36Sopenharmony_ci		pci_write_config_word(dev, master_port, master_data);
26862306a36Sopenharmony_ci	}
26962306a36Sopenharmony_ci	pci_write_config_byte(dev, 0x48, udma_enable);
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	spin_unlock_irqrestore(&rdc_lock, flags);
27262306a36Sopenharmony_ci}
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_cistatic struct ata_port_operations rdc_pata_ops = {
27562306a36Sopenharmony_ci	.inherits		= &ata_bmdma32_port_ops,
27662306a36Sopenharmony_ci	.cable_detect		= rdc_pata_cable_detect,
27762306a36Sopenharmony_ci	.set_piomode		= rdc_set_piomode,
27862306a36Sopenharmony_ci	.set_dmamode		= rdc_set_dmamode,
27962306a36Sopenharmony_ci	.prereset		= rdc_pata_prereset,
28062306a36Sopenharmony_ci};
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_cistatic const struct ata_port_info rdc_port_info = {
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	.flags		= ATA_FLAG_SLAVE_POSS,
28562306a36Sopenharmony_ci	.pio_mask	= ATA_PIO4,
28662306a36Sopenharmony_ci	.mwdma_mask	= ATA_MWDMA12_ONLY,
28762306a36Sopenharmony_ci	.udma_mask	= ATA_UDMA5,
28862306a36Sopenharmony_ci	.port_ops	= &rdc_pata_ops,
28962306a36Sopenharmony_ci};
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_cistatic const struct scsi_host_template rdc_sht = {
29262306a36Sopenharmony_ci	ATA_BMDMA_SHT(DRV_NAME),
29362306a36Sopenharmony_ci};
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci/**
29662306a36Sopenharmony_ci *	rdc_init_one - Register PIIX ATA PCI device with kernel services
29762306a36Sopenharmony_ci *	@pdev: PCI device to register
29862306a36Sopenharmony_ci *	@ent: Entry in rdc_pci_tbl matching with @pdev
29962306a36Sopenharmony_ci *
30062306a36Sopenharmony_ci *	Called from kernel PCI layer.  We probe for combined mode (sigh),
30162306a36Sopenharmony_ci *	and then hand over control to libata, for it to do the rest.
30262306a36Sopenharmony_ci *
30362306a36Sopenharmony_ci *	LOCKING:
30462306a36Sopenharmony_ci *	Inherited from PCI layer (may sleep).
30562306a36Sopenharmony_ci *
30662306a36Sopenharmony_ci *	RETURNS:
30762306a36Sopenharmony_ci *	Zero on success, or -ERRNO value.
30862306a36Sopenharmony_ci */
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_cistatic int rdc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
31362306a36Sopenharmony_ci	struct ata_port_info port_info[2];
31462306a36Sopenharmony_ci	const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
31562306a36Sopenharmony_ci	struct ata_host *host;
31662306a36Sopenharmony_ci	struct rdc_host_priv *hpriv;
31762306a36Sopenharmony_ci	int rc;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	ata_print_version_once(&pdev->dev, DRV_VERSION);
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	port_info[0] = rdc_port_info;
32262306a36Sopenharmony_ci	port_info[1] = rdc_port_info;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	/* enable device and prepare host */
32562306a36Sopenharmony_ci	rc = pcim_enable_device(pdev);
32662306a36Sopenharmony_ci	if (rc)
32762306a36Sopenharmony_ci		return rc;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
33062306a36Sopenharmony_ci	if (!hpriv)
33162306a36Sopenharmony_ci		return -ENOMEM;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	/* Save IOCFG, this will be used for cable detection, quirk
33462306a36Sopenharmony_ci	 * detection and restoration on detach.
33562306a36Sopenharmony_ci	 */
33662306a36Sopenharmony_ci	pci_read_config_dword(pdev, 0x54, &hpriv->saved_iocfg);
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
33962306a36Sopenharmony_ci	if (rc)
34062306a36Sopenharmony_ci		return rc;
34162306a36Sopenharmony_ci	host->private_data = hpriv;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	pci_intx(pdev, 1);
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	host->flags |= ATA_HOST_PARALLEL_SCAN;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	pci_set_master(pdev);
34862306a36Sopenharmony_ci	return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, &rdc_sht);
34962306a36Sopenharmony_ci}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_cistatic void rdc_remove_one(struct pci_dev *pdev)
35262306a36Sopenharmony_ci{
35362306a36Sopenharmony_ci	struct ata_host *host = pci_get_drvdata(pdev);
35462306a36Sopenharmony_ci	struct rdc_host_priv *hpriv = host->private_data;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	pci_write_config_dword(pdev, 0x54, hpriv->saved_iocfg);
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	ata_pci_remove_one(pdev);
35962306a36Sopenharmony_ci}
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_cistatic const struct pci_device_id rdc_pci_tbl[] = {
36262306a36Sopenharmony_ci	{ PCI_DEVICE(0x17F3, 0x1011), },
36362306a36Sopenharmony_ci	{ PCI_DEVICE(0x17F3, 0x1012), },
36462306a36Sopenharmony_ci	{ }	/* terminate list */
36562306a36Sopenharmony_ci};
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic struct pci_driver rdc_pci_driver = {
36862306a36Sopenharmony_ci	.name			= DRV_NAME,
36962306a36Sopenharmony_ci	.id_table		= rdc_pci_tbl,
37062306a36Sopenharmony_ci	.probe			= rdc_init_one,
37162306a36Sopenharmony_ci	.remove			= rdc_remove_one,
37262306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
37362306a36Sopenharmony_ci	.suspend		= ata_pci_device_suspend,
37462306a36Sopenharmony_ci	.resume			= ata_pci_device_resume,
37562306a36Sopenharmony_ci#endif
37662306a36Sopenharmony_ci};
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_cimodule_pci_driver(rdc_pci_driver);
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ciMODULE_AUTHOR("Alan Cox (based on ata_piix)");
38262306a36Sopenharmony_ciMODULE_DESCRIPTION("SCSI low-level driver for RDC PATA controllers");
38362306a36Sopenharmony_ciMODULE_LICENSE("GPL");
38462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, rdc_pci_tbl);
38562306a36Sopenharmony_ciMODULE_VERSION(DRV_VERSION);
386