All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

it8213.c 5.59 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * ITE 8213 IDE driver
 *
 * Copyright (C) 2006 Jack Lee
 * Copyright (C) 2006 Alan Cox
 * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
 */

Jack Lee's avatar
Jack Lee committed
9 10 11 12 13 14 15 16
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>

17 18 19 20
/**
 *	it8213_set_pio_mode	-	set host controller for PIO mode
 *	@drive: drive
 *	@pio: PIO mode number
Jack Lee's avatar
Jack Lee committed
21
 *
22
 *	Set the interface PIO mode.
Jack Lee's avatar
Jack Lee committed
23 24
 */

25
static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
Jack Lee's avatar
Jack Lee committed
26 27
{
	ide_hwif_t *hwif	= HWIF(drive);
28
	struct pci_dev *dev	= to_pci_dev(hwif->dev);
29
	int is_slave		= drive->dn & 1;
Jack Lee's avatar
Jack Lee committed
30 31 32 33 34
	int master_port		= 0x40;
	int slave_port		= 0x44;
	unsigned long flags;
	u16 master_data;
	u8 slave_data;
35 36
	static DEFINE_SPINLOCK(tune_lock);
	int control = 0;
Jack Lee's avatar
Jack Lee committed
37

38 39 40 41 42 43
	static const u8 timings[][2]= {
					{ 0, 0 },
					{ 0, 0 },
					{ 1, 0 },
					{ 2, 1 },
					{ 2, 3 }, };
Jack Lee's avatar
Jack Lee committed
44 45 46

	spin_lock_irqsave(&tune_lock, flags);
	pci_read_config_word(dev, master_port, &master_data);
47 48 49 50 51 52 53

	if (pio > 1)
		control |= 1;	/* Programmable timing on */
	if (drive->media != ide_disk)
		control |= 4;	/* ATAPI */
	if (pio > 2)
		control |= 2;	/* IORDY */
Jack Lee's avatar
Jack Lee committed
54
	if (is_slave) {
55 56
		master_data |=  0x4000;
		master_data &= ~0x0070;
Jack Lee's avatar
Jack Lee committed
57
		if (pio > 1)
58
			master_data = master_data | (control << 4);
Jack Lee's avatar
Jack Lee committed
59 60
		pci_read_config_byte(dev, slave_port, &slave_data);
		slave_data = slave_data & 0xf0;
61
		slave_data = slave_data | (timings[pio][0] << 2) | timings[pio][1];
Jack Lee's avatar
Jack Lee committed
62
	} else {
63
		master_data &= ~0x3307;
Jack Lee's avatar
Jack Lee committed
64
		if (pio > 1)
65
			master_data = master_data | control;
Jack Lee's avatar
Jack Lee committed
66 67 68 69 70 71 72 73 74
		master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8);
	}
	pci_write_config_word(dev, master_port, master_data);
	if (is_slave)
		pci_write_config_byte(dev, slave_port, slave_data);
	spin_unlock_irqrestore(&tune_lock, flags);
}

/**
75 76 77
 *	it8213_set_dma_mode	-	set host controller for DMA mode
 *	@drive: drive
 *	@speed: DMA mode
Jack Lee's avatar
Jack Lee committed
78
 *
79
 *	Tune the ITE chipset for the DMA mode.
Jack Lee's avatar
Jack Lee committed
80 81
 */

82
static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
Jack Lee's avatar
Jack Lee committed
83 84
{
	ide_hwif_t *hwif	= HWIF(drive);
85
	struct pci_dev *dev	= to_pci_dev(hwif->dev);
Jack Lee's avatar
Jack Lee committed
86 87 88 89 90 91 92
	u8 maslave		= 0x40;
	int a_speed		= 3 << (drive->dn * 4);
	int u_flag		= 1 << drive->dn;
	int v_flag		= 0x01 << drive->dn;
	int w_flag		= 0x10 << drive->dn;
	int u_speed		= 0;
	u16			reg4042, reg4a;
93
	u8			reg48, reg54, reg55;
Jack Lee's avatar
Jack Lee committed
94 95 96 97 98 99 100

	pci_read_config_word(dev, maslave, &reg4042);
	pci_read_config_byte(dev, 0x48, &reg48);
	pci_read_config_word(dev, 0x4a, &reg4a);
	pci_read_config_byte(dev, 0x54, &reg54);
	pci_read_config_byte(dev, 0x55, &reg55);

101
	if (speed >= XFER_UDMA_0) {
102 103 104 105
		u8 udma = speed - XFER_UDMA_0;

		u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);

Jack Lee's avatar
Jack Lee committed
106 107 108 109 110 111 112 113 114 115
		if (!(reg48 & u_flag))
			pci_write_config_byte(dev, 0x48, reg48 | u_flag);
		if (speed >= XFER_UDMA_5) {
			pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
		} else {
			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
		}

		if ((reg4a & a_speed) != u_speed)
			pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
116
		if (speed > XFER_UDMA_2) {
Jack Lee's avatar
Jack Lee committed
117 118 119 120
			if (!(reg54 & v_flag))
				pci_write_config_byte(dev, 0x54, reg54 | v_flag);
		} else
			pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
121
	} else {
122
		const u8 mwdma_to_pio[] = { 0, 3, 4 };
123
		u8 pio;
124

Jack Lee's avatar
Jack Lee committed
125 126 127 128 129 130 131 132
		if (reg48 & u_flag)
			pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
		if (reg4a & a_speed)
			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
		if (reg54 & v_flag)
			pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
		if (reg55 & w_flag)
			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
133 134 135 136 137

		if (speed >= XFER_MW_DMA_0)
			pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
		else
			pio = 2; /* only SWDMA2 is allowed */
138

139 140
		it8213_set_pio_mode(drive, pio);
	}
141
}
Jack Lee's avatar
Jack Lee committed
142

143 144 145 146 147 148 149 150 151 152
static u8 __devinit it8213_cable_detect(ide_hwif_t *hwif)
{
	struct pci_dev *dev = to_pci_dev(hwif->dev);
	u8 reg42h = 0;

	pci_read_config_byte(dev, 0x42, &reg42h);

	return (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}

Jack Lee's avatar
Jack Lee committed
153 154 155 156
/**
 *	init_hwif_it8213	-	set up hwif structs
 *	@hwif: interface to set up
 *
157
 *	We do the basic set up of the interface structure.
Jack Lee's avatar
Jack Lee committed
158 159 160 161
 */

static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
{
162
	hwif->set_dma_mode = &it8213_set_dma_mode;
163
	hwif->set_pio_mode = &it8213_set_pio_mode;
Jack Lee's avatar
Jack Lee committed
164

165
	hwif->cable_detect = it8213_cable_detect;
Jack Lee's avatar
Jack Lee committed
166 167 168 169 170 171 172 173
}


#define DECLARE_ITE_DEV(name_str)			\
	{						\
		.name		= name_str,		\
		.init_hwif	= init_hwif_it8213,	\
		.enablebits	= {{0x41,0x80,0x80}}, \
174 175
		.host_flags	= IDE_HFLAG_SINGLE |	\
				  IDE_HFLAG_BOOTABLE,	\
Bartlomiej Zolnierkiewicz's avatar
Bartlomiej Zolnierkiewicz committed
176
		.pio_mask	= ATA_PIO4,		\
177 178 179
		.swdma_mask	= ATA_SWDMA2_ONLY,	\
		.mwdma_mask	= ATA_MWDMA12_ONLY,	\
		.udma_mask	= ATA_UDMA6,		\
Jack Lee's avatar
Jack Lee committed
180 181
	}

182
static const struct ide_port_info it8213_chipsets[] __devinitdata = {
Jack Lee's avatar
Jack Lee committed
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
	/* 0 */ DECLARE_ITE_DEV("IT8213"),
};


/**
 *	it8213_init_one	-	pci layer discovery entry
 *	@dev: PCI device
 *	@id: ident table entry
 *
 *	Called by the PCI code when it finds an ITE8213 controller. As
 *	this device follows the standard interfaces we can use the
 *	standard helper functions to do almost all the work for us.
 */

static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
	ide_setup_pci_device(dev, &it8213_chipsets[id->driver_data]);
	return 0;
}

203 204
static const struct pci_device_id it8213_pci_tbl[] = {
	{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8213), 0 },
Jack Lee's avatar
Jack Lee committed
205 206 207 208 209 210 211 212 213 214 215 216 217
	{ 0, },
};

MODULE_DEVICE_TABLE(pci, it8213_pci_tbl);

static struct pci_driver driver = {
	.name		= "ITE8213_IDE",
	.id_table	= it8213_pci_tbl,
	.probe		= it8213_init_one,
};

static int __init it8213_ide_init(void)
{
218 219
	return ide_pci_register_driver(&driver);
}
Jack Lee's avatar
Jack Lee committed
220 221 222

module_init(it8213_ide_init);

223
MODULE_AUTHOR("Jack Lee, Alan Cox");
Jack Lee's avatar
Jack Lee committed
224 225
MODULE_DESCRIPTION("PCI driver module for the ITE 8213");
MODULE_LICENSE("GPL");