11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org> 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2000 Mark Lord <mlord@pobox.com> 45fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * Copyright (C) 2007 Bartlomiej Zolnierkiewicz 55fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * May be copied or modified under the terms of the GNU General Public License 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Development of this chipset driver was funded 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by the nice folks at National Semiconductor. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Documentation: 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * CS5530 documentation available from National Semiconductor. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ide.h> 2178829dd9224b62e2092a681afaee1bda4d0cb93bBartlomiej Zolnierkiewicz 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz#define DRV_NAME "cs5530" 25ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Here are the standard PIO mode 0-4 timings for each "format". 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Format-0 uses fast data reg timings, with slower command reg timings. 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Format-1 uses fast timings for all registers, but won't work with all drives. 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int cs5530_pio_timings[2][5] = { 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010} 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * After chip reset, the PIO timings are set to 0x0000e132, which is not valid. 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132) 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20)) 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 4388b2b32babd46cd54d2de4d17eb869aea3383e11Bartlomiej Zolnierkiewicz * cs5530_set_pio_mode - set host controller for PIO mode 44e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewicz * @hwif: port 4526bcb879c03254545a19c6700fe5bcef6f21e7b1Bartlomiej Zolnierkiewicz * @drive: drive 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4788b2b32babd46cd54d2de4d17eb869aea3383e11Bartlomiej Zolnierkiewicz * Handles setting of PIO mode for the chipset. 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4926bcb879c03254545a19c6700fe5bcef6f21e7b1Bartlomiej Zolnierkiewicz * The init_hwif_cs5530() routine guarantees that all drives 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will have valid default PIO timings set up before we get here. 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 53e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewiczstatic void cs5530_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 55e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewicz unsigned long basereg = CS5530_BASEREG(hwif); 5688b2b32babd46cd54d2de4d17eb869aea3383e11Bartlomiej Zolnierkiewicz unsigned int format = (inl(basereg + 4) >> 31) & 1; 57e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewicz const u8 pio = drive->pio_mode - XFER_PIO_0; 5888b2b32babd46cd54d2de4d17eb869aea3383e11Bartlomiej Zolnierkiewicz 5988b2b32babd46cd54d2de4d17eb869aea3383e11Bartlomiej Zolnierkiewicz outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3)); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 635fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * cs5530_udma_filter - UDMA filter 645fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * @drive: drive 655fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * 665fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * cs5530_udma_filter() does UDMA mask filtering for the given drive 675fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * taking into the consideration capabilities of the mate device. 685fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * 695fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * The CS5530 specifies that two drives sharing a cable cannot mix 705fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * UDMA/MDMA. It has to be one or the other, for the pair, though 715fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * different timings can still be chosen for each drive. We could 725fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * set the appropriate timing bits on the fly, but that might be 735fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * a bit confusing. So, for now we statically handle this requirement 745fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * by looking at our mate drive to see what it is capable of, before 755fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * choosing a mode for our own drive. 765fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * 775fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * Note: This relies on the fact we never fail from UDMA to MWDMA2 785fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * but instead drop to PIO. 795fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz */ 805fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz 815fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewiczstatic u8 cs5530_udma_filter(ide_drive_t *drive) 825fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz{ 835fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz ide_hwif_t *hwif = drive->hwif; 847e59ea21aab1a91ca31bc64c7d3035ebdbd336d1Bartlomiej Zolnierkiewicz ide_drive_t *mate = ide_get_pair_dev(drive); 859ecab6e5bf87f96dc2fa89cc9e8d5576fbde4325Julia Lawall u16 *mateid; 865fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz u8 mask = hwif->ultra_mask; 875fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz 887e59ea21aab1a91ca31bc64c7d3035ebdbd336d1Bartlomiej Zolnierkiewicz if (mate == NULL) 895fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz goto out; 909ecab6e5bf87f96dc2fa89cc9e8d5576fbde4325Julia Lawall mateid = mate->id; 915fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz 9248fb2688aa67baba373531cc4ed2d9e695983c3fBartlomiej Zolnierkiewicz if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) { 934dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz if ((mateid[ATA_ID_FIELD_VALID] & 4) && 944dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz (mateid[ATA_ID_UDMA_MODES] & 7)) 955fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz goto out; 968d64fcd9357798ad0d61f8877de13d5e1b1ab510Sergei Shtylyov if (mateid[ATA_ID_MWDMA_MODES] & 7) 975fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz mask = 0; 985fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz } 995fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewiczout: 1005fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz return mask; 1015fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz} 1025fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz 1038776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewiczstatic void cs5530_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) 1043c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz{ 1055fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz unsigned long basereg; 1063c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz unsigned int reg, timings = 0; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1088776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewicz switch (drive->dma_mode) { 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_UDMA_0: timings = 0x00921250; break; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_UDMA_1: timings = 0x00911140; break; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_UDMA_2: timings = 0x00911030; break; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_MW_DMA_0: timings = 0x00077771; break; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_MW_DMA_1: timings = 0x00012121; break; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case XFER_MW_DMA_2: timings = 0x00002020; break; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1168776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewicz basereg = CS5530_BASEREG(hwif); 1170ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz reg = inl(basereg + 4); /* get drive0 config register */ 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timings |= reg & 0x80000000; /* preserve PIO format bit */ 1193c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz if ((drive-> dn & 1) == 0) { /* are we configuring drive0? */ 1200ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz outl(timings, basereg + 4); /* write drive0 config register */ 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (timings & 0x00100000) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= 0x00100000; /* enable UDMA timings for both drives */ 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg &= ~0x00100000; /* disable UDMA timings for both drives */ 1260ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz outl(reg, basereg + 4); /* write drive0 config register */ 1270ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz outl(timings, basereg + 12); /* write drive1 config register */ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * init_chipset_5530 - set up 5530 bridge 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: PCI device 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize the cs5530 bridge for reliable IDE DMA operation. 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1382ed0ef543ae3f3ea4f8bd0433fb1fed22625a309Bartlomiej Zolnierkiewiczstatic int init_chipset_cs5530(struct pci_dev *dev) 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 142f7b0d2df2f6fd9abdf47b4a1965dcaa2870e35dfBartlomiej Zolnierkiewicz if (pci_resource_start(dev, 4) == 0) 143f7b0d2df2f6fd9abdf47b4a1965dcaa2870e35dfBartlomiej Zolnierkiewicz return -EFAULT; 144f7b0d2df2f6fd9abdf47b4a1965dcaa2870e35dfBartlomiej Zolnierkiewicz 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = NULL; 146652aa16291095911640137155063a5c6ea9bad74Alan Cox while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) { 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (dev->device) { 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCI_DEVICE_ID_CYRIX_PCI_MASTER: 149652aa16291095911640137155063a5c6ea9bad74Alan Cox master_0 = pci_dev_get(dev); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PCI_DEVICE_ID_CYRIX_5530_LEGACY: 152652aa16291095911640137155063a5c6ea9bad74Alan Cox cs5530_0 = pci_dev_get(dev); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!master_0) { 157a326b02b0c576001353dbc489154959b0889c6bfBartlomiej Zolnierkiewicz printk(KERN_ERR DRV_NAME ": unable to locate PCI MASTER function\n"); 158652aa16291095911640137155063a5c6ea9bad74Alan Cox goto out; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!cs5530_0) { 161a326b02b0c576001353dbc489154959b0889c6bfBartlomiej Zolnierkiewicz printk(KERN_ERR DRV_NAME ": unable to locate CS5530 LEGACY function\n"); 162652aa16291095911640137155063a5c6ea9bad74Alan Cox goto out; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530: 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * --> OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_master(cs5530_0); 171694625c0b322905d6892fad873029f764cd4823fRandy Dunlap pci_try_set_mwi(cs5530_0); 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set PCI CacheLineSize to 16-bytes: 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Disable trapping of UDMA register accesses (Win98 hack): 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_word(cs5530_0, 0xd0, 0x5006); 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus: 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The other settings are what is necessary to get the register 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * into a sane state for IDE DMA operation. 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_byte(master_0, 0x40, 0x1e); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set max PCI burst size (16-bytes seems to work best): 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16bytes: set bit-1 at 0x41 (reg value of 0x16) 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * all others: clear bit-1 at 0x41, and do: 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 128bytes: OR 0x00 at 0x41 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 256bytes: OR 0x04 at 0x41 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 512bytes: OR 0x08 at 0x41 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1024bytes: OR 0x0c at 0x41 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_byte(master_0, 0x41, 0x14); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These settings are necessary to get the chip 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * into a sane state for IDE DMA operation. 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_byte(master_0, 0x42, 0x00); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_byte(master_0, 0x43, 0xc1); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 215652aa16291095911640137155063a5c6ea9bad74Alan Coxout: 216652aa16291095911640137155063a5c6ea9bad74Alan Cox pci_dev_put(master_0); 217652aa16291095911640137155063a5c6ea9bad74Alan Cox pci_dev_put(cs5530_0); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * init_hwif_cs5530 - initialise an IDE channel 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @hwif: IDE to initialize 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This gets invoked by the IDE driver once for each channel. It 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * performs channel-specific pre-initialization before drive probing. 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 229fe31edc8a3b6081f3580c9ae4c5c61103f3412a5Greg Kroah-Hartmanstatic void init_hwif_cs5530 (ide_hwif_t *hwif) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long basereg; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 d0_timings; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds basereg = CS5530_BASEREG(hwif); 2350ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz d0_timings = inl(basereg + 0); 23693104654c4cb64b1fc56f3d021dbc8bc7ea142fcBartlomiej Zolnierkiewicz if (CS5530_BAD_PIO(d0_timings)) 2370ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 0); 23893104654c4cb64b1fc56f3d021dbc8bc7ea142fcBartlomiej Zolnierkiewicz if (CS5530_BAD_PIO(inl(basereg + 8))) 2390ecdca26e556eae9668ce6de9554757dddb942efBartlomiej Zolnierkiewicz outl(cs5530_pio_timings[(d0_timings >> 31) & 1][0], basereg + 8); 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 242ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewiczstatic const struct ide_port_ops cs5530_port_ops = { 243ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .set_pio_mode = cs5530_set_pio_mode, 244ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .set_dma_mode = cs5530_set_dma_mode, 245ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .udma_filter = cs5530_udma_filter, 246ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz}; 247ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz 248fe31edc8a3b6081f3580c9ae4c5c61103f3412a5Greg Kroah-Hartmanstatic const struct ide_port_info cs5530_chipset = { 249ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz .name = DRV_NAME, 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .init_chipset = init_chipset_cs5530, 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .init_hwif = init_hwif_cs5530, 252ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .port_ops = &cs5530_port_ops, 2531c51361a9867021dd7444b56d87834003d4ca67dBartlomiej Zolnierkiewicz .host_flags = IDE_HFLAG_SERIALIZE | 2545e71d9c5a50b92b33d35061d42ac39166db9578eBartlomiej Zolnierkiewicz IDE_HFLAG_POST_SET_MODE, 2554099d14322149c7a467e4997b87be4ba8eb78697Bartlomiej Zolnierkiewicz .pio_mask = ATA_PIO4, 2565f8b6c34854a966fe5eb7241fde0419d47d5d408Bartlomiej Zolnierkiewicz .mwdma_mask = ATA_MWDMA2, 2575f8b6c34854a966fe5eb7241fde0419d47d5d408Bartlomiej Zolnierkiewicz .udma_mask = ATA_UDMA2, 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 260fe31edc8a3b6081f3580c9ae4c5c61103f3412a5Greg Kroah-Hartmanstatic int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2626cdf6eb357c2681596b7b1672b92396ba82333d4Bartlomiej Zolnierkiewicz return ide_pci_init_one(dev, &cs5530_chipset, NULL); 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2659cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewiczstatic const struct pci_device_id cs5530_pci_tbl[] = { 2669cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewicz { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), 0 }, 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0, }, 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, cs5530_pci_tbl); 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewiczstatic struct pci_driver cs5530_pci_driver = { 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "CS5530 IDE", 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = cs5530_pci_tbl, 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = cs5530_init_one, 275d16492a9789982955e627a7ffdcd1c3b945f7e85Bartlomiej Zolnierkiewicz .remove = ide_pci_remove, 276feb22b7f8e62b1b987a3a1dbad95af767a1df832Bartlomiej Zolnierkiewicz .suspend = ide_pci_suspend, 277feb22b7f8e62b1b987a3a1dbad95af767a1df832Bartlomiej Zolnierkiewicz .resume = ide_pci_resume, 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28082ab1eeceba6705cd5a8815c48eb03af1dada744Bartlomiej Zolnierkiewiczstatic int __init cs5530_ide_init(void) 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 282a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewicz return ide_pci_register_driver(&cs5530_pci_driver); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 285d16492a9789982955e627a7ffdcd1c3b945f7e85Bartlomiej Zolnierkiewiczstatic void __exit cs5530_ide_exit(void) 286d16492a9789982955e627a7ffdcd1c3b945f7e85Bartlomiej Zolnierkiewicz{ 287a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewicz pci_unregister_driver(&cs5530_pci_driver); 288d16492a9789982955e627a7ffdcd1c3b945f7e85Bartlomiej Zolnierkiewicz} 289d16492a9789982955e627a7ffdcd1c3b945f7e85Bartlomiej Zolnierkiewicz 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(cs5530_ide_init); 291d16492a9789982955e627a7ffdcd1c3b945f7e85Bartlomiej Zolnierkiewiczmodule_exit(cs5530_ide_exit); 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Mark Lord"); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("PCI driver module for Cyrix/NS 5530 IDE"); 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 296