13957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen/*
23957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * pata_cs5536.c	- CS5536 PATA for new ATA layer
33957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *			  (C) 2007 Martin K. Petersen <mkp@mkp.net>
4d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz *			  (C) 2011 Bartlomiej Zolnierkiewicz
53957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *
63957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * This program is free software; you can redistribute it and/or modify
73957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * it under the terms of the GNU General Public License version 2 as
83957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * published by the Free Software Foundation.
93957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *
103957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * This program is distributed in the hope that it will be useful,
113957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * but WITHOUT ANY WARRANTY; without even the implied warranty of
123957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
133957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * GNU General Public License for more details.
143957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *
153957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * You should have received a copy of the GNU General Public License
163957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * along with this program; if not, write to the Free Software
173957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
183957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *
193957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * Documentation:
203957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *	Available from AMD web site.
213957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *
223957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * The IDE timing registers for the CS5536 live in the Geode Machine
233957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * Specific Register file and not PCI config space.  Most BIOSes
243957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * virtualize the PCI registers so the chip looks like a standard IDE
253957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * controller.	Unfortunately not all implementations get this right.
263957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * In particular some have problems with unaligned accesses to the
273957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * virtualized PCI registers.  This driver always does full dword
283957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * writes to work around the issue.  Also, in case of a bad BIOS this
293957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * driver can be loaded with the "msr=1" parameter which forces using
303957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen * the Machine Specific Registers to configure the device.
313957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen */
323957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
333957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen#include <linux/kernel.h>
343957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen#include <linux/module.h>
353957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen#include <linux/pci.h>
363957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen#include <linux/init.h>
373957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen#include <linux/blkdev.h>
383957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen#include <linux/delay.h>
393957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen#include <linux/libata.h>
403957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen#include <scsi/scsi_host.h>
419272dcc232b84ccb027d6861077934055d42764dWu Zhangjin
429272dcc232b84ccb027d6861077934055d42764dWu Zhangjin#ifdef CONFIG_X86_32
433957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen#include <asm/msr.h>
449272dcc232b84ccb027d6861077934055d42764dWu Zhangjinstatic int use_msr;
459272dcc232b84ccb027d6861077934055d42764dWu Zhangjinmodule_param_named(msr, use_msr, int, 0644);
469272dcc232b84ccb027d6861077934055d42764dWu ZhangjinMODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");
479272dcc232b84ccb027d6861077934055d42764dWu Zhangjin#else
48ff5dd32b997a5a5ce3f4256257991133d694da0bJeff Garzik#undef rdmsr	/* avoid accidental MSR usage on, e.g. x86-64 */
49ff5dd32b997a5a5ce3f4256257991133d694da0bJeff Garzik#undef wrmsr
509272dcc232b84ccb027d6861077934055d42764dWu Zhangjin#define rdmsr(x, y, z) do { } while (0)
519272dcc232b84ccb027d6861077934055d42764dWu Zhangjin#define wrmsr(x, y, z) do { } while (0)
529272dcc232b84ccb027d6861077934055d42764dWu Zhangjin#define use_msr 0
539272dcc232b84ccb027d6861077934055d42764dWu Zhangjin#endif
543957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
553957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen#define DRV_NAME	"pata_cs5536"
569272dcc232b84ccb027d6861077934055d42764dWu Zhangjin#define DRV_VERSION	"0.0.8"
573957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
583957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersenenum {
59d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	MSR_IDE_CFG		= 0x51300010,
603957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	PCI_IDE_CFG		= 0x40,
613957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
62d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	CFG			= 0,
63d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	DTC			= 2,
64d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	CAST			= 3,
65d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	ETC			= 4,
66d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz
67d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	IDE_CFG_CHANEN		= (1 << 1),
68d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	IDE_CFG_CABLE		= (1 << 17) | (1 << 16),
693957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
703957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	IDE_D0_SHIFT		= 24,
713957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	IDE_D1_SHIFT		= 16,
723957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	IDE_DRV_MASK		= 0xff,
733957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
743957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	IDE_CAST_D0_SHIFT	= 6,
753957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	IDE_CAST_D1_SHIFT	= 4,
763957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	IDE_CAST_DRV_MASK	= 0x3,
773957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	IDE_CAST_CMD_MASK	= 0xff,
783957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	IDE_CAST_CMD_SHIFT	= 24,
793957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
80d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	IDE_ETC_UDMA_MASK	= 0xc0,
813957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen};
823957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
83d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewiczstatic int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)
843957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen{
853957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	if (unlikely(use_msr)) {
869272dcc232b84ccb027d6861077934055d42764dWu Zhangjin		u32 dummy __maybe_unused;
873957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
88d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz		rdmsr(MSR_IDE_CFG + reg, *val, dummy);
893957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		return 0;
903957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	}
913957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
92d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	return pci_read_config_dword(pdev, PCI_IDE_CFG + reg * 4, val);
933957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen}
943957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
95d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewiczstatic int cs5536_write(struct pci_dev *pdev, int reg, int val)
963957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen{
973957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	if (unlikely(use_msr)) {
98d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz		wrmsr(MSR_IDE_CFG + reg, val, 0);
993957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		return 0;
1003957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	}
1013957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
102d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	return pci_write_config_dword(pdev, PCI_IDE_CFG + reg * 4, val);
103d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz}
104d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz
105d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewiczstatic void cs5536_program_dtc(struct ata_device *adev, u8 tim)
106d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz{
107d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	struct pci_dev *pdev = to_pci_dev(adev->link->ap->host->dev);
108d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT;
109d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	u32 dtc;
110d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz
111d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	cs5536_read(pdev, DTC, &dtc);
112d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	dtc &= ~(IDE_DRV_MASK << dshift);
113d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	dtc |= tim << dshift;
114d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	cs5536_write(pdev, DTC, dtc);
1153957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen}
1163957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1173957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen/**
1183957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *	cs5536_cable_detect	-	detect cable type
1193957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *	@ap: Port to detect on
1203957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *
121d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz *	Perform cable detection for ATA66 capable cable.
122d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz *
123d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz *	Returns a cable type.
1243957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen */
1253957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1263957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersenstatic int cs5536_cable_detect(struct ata_port *ap)
1273957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen{
1283957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
1293957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	u32 cfg;
1303957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1313957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	cs5536_read(pdev, CFG, &cfg);
1323957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
133d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	if (cfg & IDE_CFG_CABLE)
1343957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		return ATA_CBL_PATA80;
1353957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	else
1363957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		return ATA_CBL_PATA40;
1373957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen}
1383957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1393957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen/**
1403957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *	cs5536_set_piomode		-	PIO setup
1413957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *	@ap: ATA interface
1423957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *	@adev: device on the interface
1433957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen */
1443957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1453957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersenstatic void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev)
1463957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen{
1473957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	static const u8 drv_timings[5] = {
1483957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		0x98, 0x55, 0x32, 0x21, 0x20,
1493957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	};
1503957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1513957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	static const u8 addr_timings[5] = {
1523957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		0x2, 0x1, 0x0, 0x0, 0x0,
1533957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	};
1543957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1553957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	static const u8 cmd_timings[5] = {
1563957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		0x99, 0x92, 0x90, 0x22, 0x20,
1573957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	};
1583957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1593957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
1603957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	struct ata_device *pair = ata_dev_pair(adev);
1613957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	int mode = adev->pio_mode - XFER_PIO_0;
1623957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	int cmdmode = mode;
163b6966a61a8b5df2987856c81f39a8fd014d32a80Martin K. Petersen	int cshift = adev->devno ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT;
164d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	u32 cast;
1653957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1663957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	if (pair)
1673957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		cmdmode = min(mode, pair->pio_mode - XFER_PIO_0);
1683957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
169d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	cs5536_program_dtc(adev, drv_timings[mode]);
1703957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
171d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	cs5536_read(pdev, CAST, &cast);
1723957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1733957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	cast &= ~(IDE_CAST_DRV_MASK << cshift);
1743957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	cast |= addr_timings[mode] << cshift;
1753957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1763957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT);
1773957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT;
1783957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1793957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	cs5536_write(pdev, CAST, cast);
1803957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen}
1813957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1823957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen/**
1833957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *	cs5536_set_dmamode		-	DMA timing setup
1843957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *	@ap: ATA interface
1853957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *	@adev: Device being configured
1863957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *
1873957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen */
1883957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1893957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersenstatic void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev)
1903957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen{
1913957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	static const u8 udma_timings[6] = {
1923957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6,
1933957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	};
1943957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1953957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	static const u8 mwdma_timings[3] = {
1963957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		0x67, 0x21, 0x20,
1973957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	};
1983957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
1993957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
200d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	u32 etc;
2013957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	int mode = adev->dma_mode;
202b6966a61a8b5df2987856c81f39a8fd014d32a80Martin K. Petersen	int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT;
2033957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
204d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	cs5536_read(pdev, ETC, &etc);
2053957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
206d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	if (mode >= XFER_UDMA_0) {
2073957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		etc &= ~(IDE_DRV_MASK << dshift);
2083957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		etc |= udma_timings[mode - XFER_UDMA_0] << dshift;
2093957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	} else { /* MWDMA */
210d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz		etc &= ~(IDE_ETC_UDMA_MASK << dshift);
211d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz		cs5536_program_dtc(adev, mwdma_timings[mode - XFER_MW_DMA_0]);
2123957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	}
213d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz
214d63e94a442df14c4e7b02763c3230374218b41f1Bartlomiej Zolnierkiewicz	cs5536_write(pdev, ETC, etc);
2153957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen}
2163957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2173957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersenstatic struct scsi_host_template cs5536_sht = {
21868d1d07b510bb57a504588adc2bd2758adea0965Tejun Heo	ATA_BMDMA_SHT(DRV_NAME),
2193957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen};
2203957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2213957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersenstatic struct ata_port_operations cs5536_port_ops = {
222ba3a221ce2ec0b636a15e12c23c97af68b9b1114Krzysztof Halasa	.inherits		= &ata_bmdma32_port_ops,
223029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo	.cable_detect		= cs5536_cable_detect,
2243957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	.set_piomode		= cs5536_set_piomode,
2253957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	.set_dmamode		= cs5536_set_dmamode,
2263957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen};
2273957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2283957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen/**
2293957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *	cs5536_init_one
2303957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *	@dev: PCI device
2313957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *	@id: Entry in match table
2323957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen *
2333957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen */
2343957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2353957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersenstatic int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
2363957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen{
2373957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	static const struct ata_port_info info = {
2383957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		.flags = ATA_FLAG_SLAVE_POSS,
23914bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø		.pio_mask = ATA_PIO4,
24014bdef982caeda19afe34010482867c18217c641Erik Inge Bolsø		.mwdma_mask = ATA_MWDMA2,
2413957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		.udma_mask = ATA_UDMA5,
2423957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		.port_ops = &cs5536_port_ops,
2433957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	};
2443957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2453957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
2463957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	u32 cfg;
2473957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2483957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	if (use_msr)
2493957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		printk(KERN_ERR DRV_NAME ": Using MSR regs instead of PCI\n");
2503957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2513957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	cs5536_read(dev, CFG, &cfg);
2523957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2533957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	if ((cfg & IDE_CFG_CHANEN) == 0) {
2543957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		printk(KERN_ERR DRV_NAME ": disabled by BIOS\n");
2553957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen		return -ENODEV;
2563957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	}
2573957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2581c5afdf7a629d2e77de8dd043b97a33dcd7e6dfaTejun Heo	return ata_pci_bmdma_init_one(dev, ppi, &cs5536_sht, NULL, 0);
2593957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen}
2603957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2613957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersenstatic const struct pci_device_id cs5536[] = {
2623957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	{ PCI_VDEVICE(AMD,	PCI_DEVICE_ID_AMD_CS5536_IDE), },
2633957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	{ },
2643957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen};
2653957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2663957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersenstatic struct pci_driver cs5536_pci_driver = {
2673957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	.name		= DRV_NAME,
2683957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	.id_table	= cs5536,
2693957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	.probe		= cs5536_init_one,
2703957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	.remove		= ata_pci_remove_one,
2713957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen#ifdef CONFIG_PM
2723957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	.suspend	= ata_pci_device_suspend,
2733957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	.resume		= ata_pci_device_resume,
2743957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen#endif
2753957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen};
2763957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2773957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersenstatic int __init cs5536_init(void)
2783957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen{
2793957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	return pci_register_driver(&cs5536_pci_driver);
2803957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen}
2813957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2823957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersenstatic void __exit cs5536_exit(void)
2833957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen{
2843957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen	pci_unregister_driver(&cs5536_pci_driver);
2853957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen}
2863957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2873957df6160c90955979229b230cb5202e6a5ee2bMartin K. PetersenMODULE_AUTHOR("Martin K. Petersen");
2883957df6160c90955979229b230cb5202e6a5ee2bMartin K. PetersenMODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller");
2893957df6160c90955979229b230cb5202e6a5ee2bMartin K. PetersenMODULE_LICENSE("GPL");
2903957df6160c90955979229b230cb5202e6a5ee2bMartin K. PetersenMODULE_DEVICE_TABLE(pci, cs5536);
2913957df6160c90955979229b230cb5202e6a5ee2bMartin K. PetersenMODULE_VERSION(DRV_VERSION);
2923957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersen
2933957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersenmodule_init(cs5536_init);
2943957df6160c90955979229b230cb5202e6a5ee2bMartin K. Petersenmodule_exit(cs5536_exit);
295