Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * Copyright (C) 2002 Toshiba Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (C) 2005-2006 MontaVista Software, Inc. <source@mvista.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * License version 2.  This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/ide.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #define DRV_NAME "tc86c001"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) static void tc86c001_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	unsigned long scr_port	= hwif->config_data + (drive->dn ? 0x02 : 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	u16 mode, scr		= inw(scr_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	const u8 speed		= drive->dma_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	switch (speed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	case XFER_UDMA_4:	mode = 0x00c0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	case XFER_UDMA_3:	mode = 0x00b0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	case XFER_UDMA_2:	mode = 0x00a0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	case XFER_UDMA_1:	mode = 0x0090; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	case XFER_UDMA_0:	mode = 0x0080; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	case XFER_MW_DMA_2:	mode = 0x0070; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	case XFER_MW_DMA_1:	mode = 0x0060; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	case XFER_MW_DMA_0:	mode = 0x0050; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	case XFER_PIO_4:	mode = 0x0400; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	case XFER_PIO_3:	mode = 0x0300; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	case XFER_PIO_2:	mode = 0x0200; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	case XFER_PIO_1:	mode = 0x0100; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	case XFER_PIO_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	default:		mode = 0x0000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	scr |= mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	outw(scr, scr_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) static void tc86c001_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	drive->dma_mode = drive->pio_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	tc86c001_set_mode(hwif, drive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  * HACKITY HACK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * This is a workaround for the limitation 5 of the TC86C001 IDE controller:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * if a DMA transfer terminates prematurely, the controller leaves the device's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * interrupt request (INTRQ) pending and does not generate a PCI interrupt (or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * set the interrupt bit in the DMA status register), thus no PCI interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * will occur until a DMA transfer has been successfully completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  * We work around this by initiating dummy, zero-length DMA transfer on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * a DMA timeout expiration. I found no better way to do this with the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * IDE core than to temporarily replace a higher level driver's timer expiry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  * handler with our own backing up to that handler in case our recovery fails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) static int tc86c001_timer_expiry(ide_drive_t *drive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	ide_hwif_t *hwif	= drive->hwif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	ide_expiry_t *expiry	= ide_get_hwifdata(hwif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	u8 dma_stat		= inb(hwif->dma_base + ATA_DMA_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	/* Restore a higher level driver's expiry handler first. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	hwif->expiry = expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	if ((dma_stat & 5) == 1) {	/* DMA active and no interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		unsigned long sc_base	= hwif->config_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		unsigned long twcr_port	= sc_base + (drive->dn ? 0x06 : 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		u8 dma_cmd		= inb(hwif->dma_base + ATA_DMA_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		printk(KERN_WARNING "%s: DMA interrupt possibly stuck, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		       "attempting recovery...\n", drive->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		/* Stop DMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		outb(dma_cmd & ~0x01, hwif->dma_base + ATA_DMA_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		/* Setup the dummy DMA transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		outw(0, sc_base + 0x0a);	/* Sector Count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		outw(0, twcr_port);	/* Transfer Word Count 1 or 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		/* Start the dummy DMA transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		/* clear R_OR_WCTR for write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		outb(0x00, hwif->dma_base + ATA_DMA_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		/* set START_STOPBM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		outb(0x01, hwif->dma_base + ATA_DMA_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		 * If an interrupt was pending, it should come thru shortly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		 * If not, a higher level driver's expiry handler should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		 * eventually cause some kind of recovery from the DMA stall.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		return WAIT_MIN_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	/* Chain to the restored expiry handler if DMA wasn't active. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	if (likely(expiry != NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		return expiry(drive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	/* If there was no handler, "emulate" that for ide_timer_expiry()... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static void tc86c001_dma_start(ide_drive_t *drive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	ide_hwif_t *hwif	= drive->hwif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	unsigned long sc_base	= hwif->config_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	unsigned long twcr_port	= sc_base + (drive->dn ? 0x06 : 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	unsigned long nsectors	= blk_rq_sectors(hwif->rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	 * We have to manually load the sector count and size into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	 * the appropriate system control registers for DMA to work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	 * with LBA48 and ATAPI devices...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	outw(nsectors, sc_base + 0x0a);	/* Sector Count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	outw(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	/* Install our timeout expiry hook, saving the current handler... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	ide_set_hwifdata(hwif, hwif->expiry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	hwif->expiry = &tc86c001_timer_expiry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	ide_dma_start(drive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static u8 tc86c001_cable_detect(ide_hwif_t *hwif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	struct pci_dev *dev = to_pci_dev(hwif->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	unsigned long sc_base = pci_resource_start(dev, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	u16 scr1 = inw(sc_base + 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	 * System Control  1 Register bit 13 (PDIAGN):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	 * 0=80-pin cable, 1=40-pin cable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	return (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static void init_hwif_tc86c001(ide_hwif_t *hwif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	unsigned long sc_base	= pci_resource_start(dev, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	u16 scr1		= inw(sc_base + 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	/* System Control 1 Register bit 15 (Soft Reset) set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	outw(scr1 |  0x8000, sc_base + 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	/* System Control 1 Register bit 14 (FIFO Reset) set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	outw(scr1 |  0x4000, sc_base + 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	/* System Control 1 Register: reset clear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	outw(scr1 & ~0xc000, sc_base + 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	/* Store the system control register base for convenience... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	hwif->config_data = sc_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	if (!hwif->dma_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	 * Sector Count Control Register bits 0 and 1 set:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	 * software sets Sector Count Register for master and slave device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	outw(0x0003, sc_base + 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	/* Sector Count Register limit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	hwif->rqsize	 = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static const struct ide_port_ops tc86c001_port_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	.set_pio_mode		= tc86c001_set_pio_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	.set_dma_mode		= tc86c001_set_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	.cable_detect		= tc86c001_cable_detect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static const struct ide_dma_ops tc86c001_dma_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	.dma_host_set		= ide_dma_host_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	.dma_setup		= ide_dma_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	.dma_start		= tc86c001_dma_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	.dma_end		= ide_dma_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	.dma_test_irq		= ide_dma_test_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	.dma_lost_irq		= ide_dma_lost_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	.dma_sff_read_status	= ide_dma_sff_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static const struct ide_port_info tc86c001_chipset = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	.name		= DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	.init_hwif	= init_hwif_tc86c001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	.port_ops	= &tc86c001_port_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	.dma_ops	= &tc86c001_dma_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	.pio_mask	= ATA_PIO4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	.mwdma_mask	= ATA_MWDMA2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	.udma_mask	= ATA_UDMA4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static int tc86c001_init_one(struct pci_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 			     const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	rc = pci_enable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	rc = pci_request_region(dev, 5, DRV_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		printk(KERN_ERR DRV_NAME ": system control regs already in use");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		goto out_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	rc = ide_pci_init_one(dev, &tc86c001_chipset, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		goto out_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) out_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	pci_release_region(dev, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) out_disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	pci_disable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static void tc86c001_remove(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	ide_pci_remove(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	pci_release_region(dev, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	pci_disable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static const struct pci_device_id tc86c001_pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	{ PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE), 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	{ 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static struct pci_driver tc86c001_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	.name		= "TC86C001",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	.id_table	= tc86c001_pci_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	.probe		= tc86c001_init_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	.remove		= tc86c001_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static int __init tc86c001_ide_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	return ide_pci_register_driver(&tc86c001_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static void __exit tc86c001_ide_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	pci_unregister_driver(&tc86c001_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) module_init(tc86c001_ide_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) module_exit(tc86c001_ide_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) MODULE_DESCRIPTION("PCI driver module for TC86C001 IDE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) MODULE_LICENSE("GPL");