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, &reg);
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