11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com> 35fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * Copyright (C) 2007 Bartlomiej Zolnierkiewicz 45fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * May be copied or modified under the terms of the GNU General Public License 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Development of this chipset driver was funded 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by the nice folks at National Semiconductor. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Documentation: 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Available from National Semiconductor 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 175a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ide.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pm.h> 2278829dd9224b62e2092a681afaee1bda4d0cb93bBartlomiej Zolnierkiewicz 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz#define DRV_NAME "sc1200" 26ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SC1200_REV_A 0x00 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SC1200_REV_B1 0x01 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SC1200_REV_B3 0x02 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SC1200_REV_C1 0x03 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SC1200_REV_D1 0x04 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCI_CLK_33 0x00 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCI_CLK_48 0x01 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCI_CLK_66 0x02 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCI_CLK_33A 0x03 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short sc1200_get_pci_clock (void) 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char chip_id, silicon_revision; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int pci_clock; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check the silicon revision, as not all versions of the chip 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * have the register with the fast PCI bus timings. 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chip_id = inb (0x903c); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds silicon_revision = inb (0x903d); 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Read the fast pci clock frequency 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip_id == 0x04 && silicon_revision < SC1200_REV_B1) { 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_clock = PCI_CLK_33; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // check clock generator configuration (cfcc) 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // the clock is in bits 8 and 9 of this word 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_clock = inw (0x901e); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_clock >>= 8; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_clock &= 0x03; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pci_clock == PCI_CLK_33A) 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_clock = PCI_CLK_33; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pci_clock; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Here are the standard PIO mode 0-4 timings for each "format". 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Format-0 uses fast data reg timings, with slower command reg timings. 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Format-1 uses fast timings for all registers, but won't work with all drives. 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const unsigned int sc1200_pio_timings[4][5] = 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, // format0 33Mhz 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}, // format1, 33Mhz 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021}, // format1, 48Mhz 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131}}; // format1, 66Mhz 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * After chip reset, the PIO timings are set to 0x00009172, which is not valid. 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172) 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 813c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewiczstatic void sc1200_tunepio(ide_drive_t *drive, u8 pio) 823c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz{ 833c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz ide_hwif_t *hwif = drive->hwif; 8436501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz struct pci_dev *pdev = to_pci_dev(hwif->dev); 853c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0; 863c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz 873c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz pci_read_config_dword(pdev, basereg + 4, &format); 883c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz format = (format >> 31) & 1; 893c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz if (format) 903c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz format += sc1200_get_pci_clock(); 913c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz pci_write_config_dword(pdev, basereg + ((drive->dn & 1) << 3), 923c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz sc1200_pio_timings[format][pio]); 933c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz} 943c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809fBartlomiej Zolnierkiewicz 955fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz/* 965fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * The SC1200 specifies that two drives sharing a cable cannot mix 975fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * UDMA/MDMA. It has to be one or the other, for the pair, though 985fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * different timings can still be chosen for each drive. We could 995fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * set the appropriate timing bits on the fly, but that might be 1005fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * a bit confusing. So, for now we statically handle this requirement 1015fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * by looking at our mate drive to see what it is capable of, before 1025fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz * choosing a mode for our own drive. 1035fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz */ 1045fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewiczstatic u8 sc1200_udma_filter(ide_drive_t *drive) 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1065fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz ide_hwif_t *hwif = drive->hwif; 1077e59ea21aab1a91ca31bc64c7d3035ebdbd336d1Bartlomiej Zolnierkiewicz ide_drive_t *mate = ide_get_pair_dev(drive); 1089ecab6e5bf87f96dc2fa89cc9e8d5576fbde4325Julia Lawall u16 *mateid; 1095fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz u8 mask = hwif->ultra_mask; 1105fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz 1117e59ea21aab1a91ca31bc64c7d3035ebdbd336d1Bartlomiej Zolnierkiewicz if (mate == NULL) 1125fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz goto out; 1139ecab6e5bf87f96dc2fa89cc9e8d5576fbde4325Julia Lawall mateid = mate->id; 1145fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz 11548fb2688aa67baba373531cc4ed2d9e695983c3fBartlomiej Zolnierkiewicz if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) { 1164dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz if ((mateid[ATA_ID_FIELD_VALID] & 4) && 1174dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz (mateid[ATA_ID_UDMA_MODES] & 7)) 1185fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz goto out; 1198d64fcd9357798ad0d61f8877de13d5e1b1ab510Sergei Shtylyov if (mateid[ATA_ID_MWDMA_MODES] & 7) 1205fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz mask = 0; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1225fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewiczout: 1235fd216bbb277b645109a889c489e13a7aafbc304Bartlomiej Zolnierkiewicz return mask; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1268776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewiczstatic void sc1200_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12836501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz struct pci_dev *dev = to_pci_dev(hwif->dev); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int reg, timings; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short pci_clock; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int basereg = hwif->channel ? 0x50 : 0x40; 1328776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewicz const u8 mode = drive->dma_mode; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1344eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz static const u32 udma_timing[3][3] = { 1354eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz { 0x00921250, 0x00911140, 0x00911030 }, 1364eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz { 0x00932470, 0x00922260, 0x00922140 }, 1374eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz { 0x009436a1, 0x00933481, 0x00923261 }, 1384eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz }; 1394eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz 1404eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz static const u32 mwdma_timing[3][3] = { 1414eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz { 0x00077771, 0x00012121, 0x00002020 }, 1424eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz { 0x000bbbb2, 0x00024241, 0x00013131 }, 1434eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz { 0x000ffff3, 0x00035352, 0x00015151 }, 1444eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz }; 1454eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_clock = sc1200_get_pci_clock(); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that each DMA mode has several timings associated with it. 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The correct timing depends on the fast PCI clock freq. 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1524eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz 1534eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz if (mode >= XFER_UDMA_0) 1544eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz timings = udma_timing[pci_clock][mode - XFER_UDMA_0]; 1554eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz else 1564eed504d140319d6c1c7e0a5b7a9bf41dabf7ceaBartlomiej Zolnierkiewicz timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0]; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 158123995b97136cb41fa282f0ed2385f2c8066df96Bartlomiej Zolnierkiewicz if ((drive->dn & 1) == 0) { 15936501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz pci_read_config_dword(dev, basereg + 4, ®); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timings |= reg & 0x80000000; /* preserve PIO format bit */ 16136501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz pci_write_config_dword(dev, basereg + 4, timings); 16236501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz } else 16336501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz pci_write_config_dword(dev, basereg + 12, timings); 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Replacement for the standard ide_dma_end action in 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dma_proc. 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns 1 on error, 0 otherwise 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1715e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewiczstatic int sc1200_dma_end(ide_drive_t *drive) 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 173898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz ide_hwif_t *hwif = drive->hwif; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long dma_base = hwif->dma_base; 1759892ec5497af1ec38c46974b5a370ba11c636b19Bartlomiej Zolnierkiewicz u8 dma_stat; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_stat = inb(dma_base+2); /* get DMA status */ 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(dma_stat & 4)) 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" ide_dma_end dma_stat=%0x err=%x newerr=%x\n", 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_stat, ((dma_stat&7)!=4), ((dma_stat&2)==2)); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(dma_stat|0x1b, dma_base+2); /* clear the INTR & ERROR bits */ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(inb(dma_base)&~1, dma_base); /* !! DO THIS HERE !! stop DMA */ 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (dma_stat & 7) != 4; /* verify good DMA status */ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 19026bcb879c03254545a19c6700fe5bcef6f21e7b1Bartlomiej Zolnierkiewicz * sc1200_set_pio_mode() handles setting of PIO modes 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for both the chipset and drive. 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All existing BIOSs for this chipset guarantee that all drives 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will have valid default PIO timings set up before we get here. 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 19626bcb879c03254545a19c6700fe5bcef6f21e7b1Bartlomiej Zolnierkiewicz 197e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewiczstatic void sc1200_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mode = -1; 200e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewicz const u8 pio = drive->pio_mode - XFER_PIO_0; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 202a01ba4011aa745be44d0290c5da5cb2dfb4e37ceBartlomiej Zolnierkiewicz /* 20326bcb879c03254545a19c6700fe5bcef6f21e7b1Bartlomiej Zolnierkiewicz * bad abuse of ->set_pio_mode interface 204a01ba4011aa745be44d0290c5da5cb2dfb4e37ceBartlomiej Zolnierkiewicz */ 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (pio) { 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 200: mode = XFER_UDMA_0; break; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 201: mode = XFER_UDMA_1; break; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 202: mode = XFER_UDMA_2; break; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 100: mode = XFER_MW_DMA_0; break; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 101: mode = XFER_MW_DMA_1; break; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 102: mode = XFER_MW_DMA_2; break; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mode != -1) { 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("SC1200: %s: changing (U)DMA mode\n", drive->name); 2154a546e046d562bcd389149591fa5a534c8f832caBartlomiej Zolnierkiewicz ide_dma_off_quietly(drive); 21697100fc816badbbc162644cfde7ad39ae9211fb4Bartlomiej Zolnierkiewicz if (ide_set_dma_mode(drive, mode) == 0 && 21797100fc816badbbc162644cfde7ad39ae9211fb4Bartlomiej Zolnierkiewicz (drive->dev_flags & IDE_DFLAG_USING_DMA)) 2185e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz hwif->dma_ops->dma_host_set(drive, 1); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22288b2b32babd46cd54d2de4d17eb869aea3383e11Bartlomiej Zolnierkiewicz sc1200_tunepio(drive, pio); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 225b86cc29dc42203588264d917e88134bdd500b0d7Alexey Dobriyan#ifdef CONFIG_PM 2267c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewiczstruct sc1200_saved_state { 2277c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz u32 regs[8]; 2287c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz}; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2303bfffd97ef913045080861d1898286ac8975c22aPavel Machekstatic int sc1200_suspend (struct pci_dev *dev, pm_message_t state) 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 232ca078bae813dd46c0f9b102fdfb4a3384641ff48Pavel Machek printk("SC1200: suspend(%u)\n", state.event); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2347c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz /* 2357c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz * we only save state when going from full power to less 2367c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz */ 237ca078bae813dd46c0f9b102fdfb4a3384641ff48Pavel Machek if (state.event == PM_EVENT_ON) { 23896776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz struct ide_host *host = pci_get_drvdata(dev); 23996776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz struct sc1200_saved_state *ss = host->host_priv; 2407c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz unsigned int r; 2417c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz 2427c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz /* 2437c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz * save timing registers 2447c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz * (this may be unnecessary if BIOS also does it) 2457c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz */ 2467c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz for (r = 0; r < 8; r++) 2477c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz pci_read_config_dword(dev, 0x40 + r * 4, &ss->regs[r]); 2487c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz } 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_disable_device(dev); 251ca078bae813dd46c0f9b102fdfb4a3384641ff48Pavel Machek pci_set_power_state(dev, pci_choose_state(dev, state)); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sc1200_resume (struct pci_dev *dev) 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25796776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz struct ide_host *host = pci_get_drvdata(dev); 25896776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz struct sc1200_saved_state *ss = host->host_priv; 2597c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz unsigned int r; 2607c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz int i; 2619d434813641abb5d619224e165f391bf352b202bJeff Garzik 2629d434813641abb5d619224e165f391bf352b202bJeff Garzik i = pci_enable_device(dev); 2639d434813641abb5d619224e165f391bf352b202bJeff Garzik if (i) 2649d434813641abb5d619224e165f391bf352b202bJeff Garzik return i; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2667c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz /* 2677c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz * restore timing registers 2687c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz * (this may be unnecessary if BIOS also does it) 2697c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz */ 27096776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz for (r = 0; r < 8; r++) 27196776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]); 2727c0e26661dd104aaeb1391063cc986ddc0ac4aa4Bartlomiej Zolnierkiewicz 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 275b86cc29dc42203588264d917e88134bdd500b0d7Alexey Dobriyan#endif 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 277ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewiczstatic const struct ide_port_ops sc1200_port_ops = { 278ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .set_pio_mode = sc1200_set_pio_mode, 279ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .set_dma_mode = sc1200_set_dma_mode, 280ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .udma_filter = sc1200_udma_filter, 281ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz}; 282ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz 283f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewiczstatic const struct ide_dma_ops sc1200_dma_ops = { 284f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz .dma_host_set = ide_dma_host_set, 285f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz .dma_setup = ide_dma_setup, 286f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz .dma_start = ide_dma_start, 2875e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz .dma_end = sc1200_dma_end, 288f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz .dma_test_irq = ide_dma_test_irq, 289f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz .dma_lost_irq = ide_dma_lost_irq, 29022117d6eaac50d366d9013c88318a869ea4d8739Bartlomiej Zolnierkiewicz .dma_timer_expiry = ide_dma_sff_timer_expiry, 291592b5315219881c6c0af4785f96456ad2043193aSergei Shtylyov .dma_sff_read_status = ide_dma_sff_read_status, 2925e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz}; 2935e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz 2948562043606430185cad26d085d46adcc7ad67fd1Bartlomiej Zolnierkiewiczstatic const struct ide_port_info sc1200_chipset __devinitdata = { 295ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz .name = DRV_NAME, 296ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz .port_ops = &sc1200_port_ops, 2975e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz .dma_ops = &sc1200_dma_ops, 2981c51361a9867021dd7444b56d87834003d4ca67dBartlomiej Zolnierkiewicz .host_flags = IDE_HFLAG_SERIALIZE | 2991c51361a9867021dd7444b56d87834003d4ca67dBartlomiej Zolnierkiewicz IDE_HFLAG_POST_SET_MODE | 3005e71d9c5a50b92b33d35061d42ac39166db9578eBartlomiej Zolnierkiewicz IDE_HFLAG_ABUSE_DMA_MODES, 3014099d14322149c7a467e4997b87be4ba8eb78697Bartlomiej Zolnierkiewicz .pio_mask = ATA_PIO4, 3025f8b6c34854a966fe5eb7241fde0419d47d5d408Bartlomiej Zolnierkiewicz .mwdma_mask = ATA_MWDMA2, 3035f8b6c34854a966fe5eb7241fde0419d47d5d408Bartlomiej Zolnierkiewicz .udma_mask = ATA_UDMA2, 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 30896776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz struct sc1200_saved_state *ss = NULL; 30996776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz int rc; 31096776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz 31196776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz#ifdef CONFIG_PM 31296776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz ss = kmalloc(sizeof(*ss), GFP_KERNEL); 31396776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz if (ss == NULL) 31496776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz return -ENOMEM; 31596776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz#endif 31696776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz rc = ide_pci_init_one(dev, &sc1200_chipset, ss); 31796776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz if (rc) 31896776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz kfree(ss); 31996776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz 32096776f3b57eb7beb889a4368937cc9d74082a47eBartlomiej Zolnierkiewicz return rc; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3239cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewiczstatic const struct pci_device_id sc1200_pci_tbl[] = { 3249cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewicz { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_SCx200_IDE), 0}, 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0, }, 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, sc1200_pci_tbl); 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 329a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewiczstatic struct pci_driver sc1200_pci_driver = { 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "SC1200_IDE", 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = sc1200_pci_tbl, 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = sc1200_init_one, 333991f5e69c512b284aaec81432dff0440b2a2f418Bartlomiej Zolnierkiewicz .remove = ide_pci_remove, 334b86cc29dc42203588264d917e88134bdd500b0d7Alexey Dobriyan#ifdef CONFIG_PM 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = sc1200_suspend, 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = sc1200_resume, 337b86cc29dc42203588264d917e88134bdd500b0d7Alexey Dobriyan#endif 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34082ab1eeceba6705cd5a8815c48eb03af1dada744Bartlomiej Zolnierkiewiczstatic int __init sc1200_ide_init(void) 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 342a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewicz return ide_pci_register_driver(&sc1200_pci_driver); 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 345991f5e69c512b284aaec81432dff0440b2a2f418Bartlomiej Zolnierkiewiczstatic void __exit sc1200_ide_exit(void) 346991f5e69c512b284aaec81432dff0440b2a2f418Bartlomiej Zolnierkiewicz{ 347a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewicz pci_unregister_driver(&sc1200_pci_driver); 348991f5e69c512b284aaec81432dff0440b2a2f418Bartlomiej Zolnierkiewicz} 349991f5e69c512b284aaec81432dff0440b2a2f418Bartlomiej Zolnierkiewicz 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sc1200_ide_init); 351991f5e69c512b284aaec81432dff0440b2a2f418Bartlomiej Zolnierkiewiczmodule_exit(sc1200_ide_exit); 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Mark Lord"); 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("PCI driver module for NS SC1200 IDE"); 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 356