/*
 * drivers/ide/pci/tc86c001.c	Version 1.01	Sep 5, 2007
 *
 * Copyright (C) 2002 Toshiba Corporation
 * Copyright (C) 2005-2006 MontaVista Software, Inc. <source@mvista.com>
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#include <linux/types.h>
#include <linux/pci.h>
#include <linux/ide.h>

static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
{
	ide_hwif_t *hwif	= HWIF(drive);
	unsigned long scr_port	= hwif->config_data + (drive->dn ? 0x02 : 0x00);
	u16 mode, scr		= inw(scr_port);

	switch (speed) {
		case XFER_UDMA_4:	mode = 0x00c0; break;
		case XFER_UDMA_3:	mode = 0x00b0; break;
		case XFER_UDMA_2:	mode = 0x00a0; break;
		case XFER_UDMA_1:	mode = 0x0090; break;
		case XFER_UDMA_0:	mode = 0x0080; break;
		case XFER_MW_DMA_2:	mode = 0x0070; break;
		case XFER_MW_DMA_1:	mode = 0x0060; break;
		case XFER_MW_DMA_0:	mode = 0x0050; break;
		case XFER_PIO_4:	mode = 0x0400; break;
		case XFER_PIO_3:	mode = 0x0300; break;
		case XFER_PIO_2:	mode = 0x0200; break;
		case XFER_PIO_1:	mode = 0x0100; break;
		case XFER_PIO_0:
		default:		mode = 0x0000; break;
	}

	scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
	scr |= mode;
	outw(scr, scr_port);
}

static void tc86c001_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
	tc86c001_set_mode(drive, XFER_PIO_0 + pio);
}

/*
 * HACKITY HACK
 *
 * This is a workaround for the limitation 5 of the TC86C001 IDE controller:
 * if a DMA transfer terminates prematurely, the controller leaves the device's
 * interrupt request (INTRQ) pending and does not generate a PCI interrupt (or
 * set the interrupt bit in the DMA status register), thus no PCI interrupt
 * will occur until a DMA transfer has been successfully completed.
 *
 * We work around this by initiating dummy, zero-length DMA transfer on
 * a DMA timeout expiration. I found no better way to do this with the current
 * IDE core than to temporarily replace a higher level driver's timer expiry
 * handler with our own backing up to that handler in case our recovery fails.
 */
static int tc86c001_timer_expiry(ide_drive_t *drive)
{
	ide_hwif_t *hwif	= HWIF(drive);
	ide_expiry_t *expiry	= ide_get_hwifdata(hwif);
	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
	u8 dma_stat		= inb(hwif->dma_status);

	/* Restore a higher level driver's expiry handler first. */
	hwgroup->expiry	= expiry;

	if ((dma_stat & 5) == 1) {	/* DMA active and no interrupt */
		unsigned long sc_base	= hwif->config_data;
		unsigned long twcr_port	= sc_base + (drive->dn ? 0x06 : 0x04);
		u8 dma_cmd		= inb(hwif->dma_command);

		printk(KERN_WARNING "%s: DMA interrupt possibly stuck, "
		       "attempting recovery...\n", drive->name);

		/* Stop DMA */
		outb(dma_cmd & ~0x01, hwif->dma_command);

		/* Setup the dummy DMA transfer */
		outw(0, sc_base + 0x0a);	/* Sector Count */
		outw(0, twcr_port);	/* Transfer Word Count 1 or 2 */

		/* Start the dummy DMA transfer */
		outb(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */
		outb(0x01, hwif->dma_command); /* set START_STOPBM */

		/*
		 * If an interrupt was pending, it should come thru shortly.
		 * If not, a higher level driver's expiry handler should
		 * eventually cause some kind of recovery from the DMA stall.
		 */
		return WAIT_MIN_SLEEP;
	}

	/* Chain to the restored expiry handler if DMA wasn't active. */
	if (likely(expiry != NULL))
		return expiry(drive);

	/* If there was no handler, "emulate" that for ide_timer_expiry()... */
	return -1;
}

static void tc86c001_dma_start(ide_drive_t *drive)
{
	ide_hwif_t *hwif	= HWIF(drive);
	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
	unsigned long sc_base	= hwif->config_data;
	unsigned long twcr_port	= sc_base + (drive->dn ? 0x06 : 0x04);
	unsigned long nsectors	= hwgroup->rq->nr_sectors;

	/*
	 * We have to manually load the sector count and size into
	 * the appropriate system control registers for DMA to work
	 * with LBA48 and ATAPI devices...
	 */
	outw(nsectors, sc_base + 0x0a);	/* Sector Count */
	outw(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */

	/* Install our timeout expiry hook, saving the current handler... */
	ide_set_hwifdata(hwif, hwgroup->expiry);
	hwgroup->expiry = &tc86c001_timer_expiry;

	ide_dma_start(drive);
}

static int tc86c001_busproc(ide_drive_t *drive, int state)
{
	ide_hwif_t *hwif	= HWIF(drive);
	unsigned long sc_base	= hwif->config_data;
	u16 scr1;

	/* System Control 1 Register bit 11 (ATA Hard Reset) read */
	scr1 = inw(sc_base + 0x00);

	switch (state) {
		case BUSSTATE_ON:
			if (!(scr1 & 0x0800))
				return 0;
			scr1 &= ~0x0800;

			hwif->drives[0].failures = hwif->drives[1].failures = 0;
			break;
		case BUSSTATE_OFF:
			if (scr1 & 0x0800)
				return 0;
			scr1 |= 0x0800;

			hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
			hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
			break;
		default:
			return -EINVAL;
	}

	/* System Control 1 Register bit 11 (ATA Hard Reset) write */
	outw(scr1, sc_base + 0x00);
	return 0;
}

static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
{
	unsigned long sc_base	= pci_resource_start(hwif->pci_dev, 5);
	u16 scr1		= inw(sc_base + 0x00);

	/* System Control 1 Register bit 15 (Soft Reset) set */
	outw(scr1 |  0x8000, sc_base + 0x00);

	/* System Control 1 Register bit 14 (FIFO Reset) set */
	outw(scr1 |  0x4000, sc_base + 0x00);

	/* System Control 1 Register: reset clear */
	outw(scr1 & ~0xc000, sc_base + 0x00);

	/* Store the system control register base for convenience... */
	hwif->config_data = sc_base;

	hwif->set_pio_mode = &tc86c001_set_pio_mode;
	hwif->set_dma_mode = &tc86c001_set_mode;

	hwif->busproc	= &tc86c001_busproc;

	if (!hwif->dma_base)
		return;

	/*
	 * Sector Count Control Register bits 0 and 1 set:
	 * software sets Sector Count Register for master and slave device
	 */
	outw(0x0003, sc_base + 0x0c);

	/* Sector Count Register limit */
	hwif->rqsize	 = 0xffff;

	hwif->dma_start 	= &tc86c001_dma_start;

	if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
		/*
		 * System Control  1 Register bit 13 (PDIAGN):
		 * 0=80-pin cable, 1=40-pin cable
		 */
		scr1 = inw(sc_base + 0x00);
		hwif->cbl = (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
	}
}

static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
							const char *name)
{
	int err = pci_request_region(dev, 5, name);

	if (err)
		printk(KERN_ERR "%s: system control regs already in use", name);
	return err;
}

static ide_pci_device_t tc86c001_chipset __devinitdata = {
	.name		= "TC86C001",
	.init_chipset	= init_chipset_tc86c001,
	.init_hwif	= init_hwif_tc86c001,
	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
	.pio_mask	= ATA_PIO4,
	.mwdma_mask	= ATA_MWDMA2,
	.udma_mask	= ATA_UDMA4,
};

static int __devinit tc86c001_init_one(struct pci_dev *dev,
				       const struct pci_device_id *id)
{
	return ide_setup_pci_device(dev, &tc86c001_chipset);
}

static const struct pci_device_id tc86c001_pci_tbl[] = {
	{ PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE), 0 },
	{ 0, }
};
MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl);

static struct pci_driver driver = {
	.name		= "TC86C001",
	.id_table	= tc86c001_pci_tbl,
	.probe		= tc86c001_init_one
};

static int __init tc86c001_ide_init(void)
{
	return ide_pci_register_driver(&driver);
}
module_init(tc86c001_ide_init);

MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
MODULE_DESCRIPTION("PCI driver module for TC86C001 IDE");
MODULE_LICENSE("GPL");
