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