it8213.c 7.74 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 17 18 19 20 21 22 23
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>

#include <asm/io.h>

/**
 *	it8213_dma_2_pio		-	return the PIO mode matching DMA
 *	@xfer_rate: transfer speed
 *
24
 *	Returns the nearest equivalent PIO timing for the DMA
Jack Lee's avatar
Jack Lee committed
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
 *	mode requested by the controller.
 */

static u8 it8213_dma_2_pio (u8 xfer_rate) {
	switch(xfer_rate) {
		case XFER_UDMA_6:
		case XFER_UDMA_5:
		case XFER_UDMA_4:
		case XFER_UDMA_3:
		case XFER_UDMA_2:
		case XFER_UDMA_1:
		case XFER_UDMA_0:
		case XFER_MW_DMA_2:
			return 4;
		case XFER_MW_DMA_1:
			return 3;
		case XFER_SW_DMA_2:
			return 2;
		case XFER_MW_DMA_0:
		case XFER_SW_DMA_1:
		case XFER_SW_DMA_0:
		default:
			return 0;
	}
}

/*
52
 *	it8213_tune_pio	-	tune a drive
Jack Lee's avatar
Jack Lee committed
53
 *	@drive: drive to tune
54
 *	@pio: desired PIO mode
Jack Lee's avatar
Jack Lee committed
55
 *
56
 *	Set the interface PIO mode.
Jack Lee's avatar
Jack Lee committed
57 58
 */

59
static void it8213_tune_pio(ide_drive_t *drive, const u8 pio)
Jack Lee's avatar
Jack Lee committed
60 61 62
{
	ide_hwif_t *hwif	= HWIF(drive);
	struct pci_dev *dev	= hwif->pci_dev;
63
	int is_slave		= drive->dn & 1;
Jack Lee's avatar
Jack Lee committed
64 65 66 67 68
	int master_port		= 0x40;
	int slave_port		= 0x44;
	unsigned long flags;
	u16 master_data;
	u8 slave_data;
69 70
	static DEFINE_SPINLOCK(tune_lock);
	int control = 0;
Jack Lee's avatar
Jack Lee committed
71

72 73 74 75 76 77
	static const u8 timings[][2]= {
					{ 0, 0 },
					{ 0, 0 },
					{ 1, 0 },
					{ 2, 1 },
					{ 2, 3 }, };
Jack Lee's avatar
Jack Lee committed
78 79 80

	spin_lock_irqsave(&tune_lock, flags);
	pci_read_config_word(dev, master_port, &master_data);
81 82 83 84 85 86 87

	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
88
	if (is_slave) {
89 90
		master_data |=  0x4000;
		master_data &= ~0x0070;
Jack Lee's avatar
Jack Lee committed
91
		if (pio > 1)
92
			master_data = master_data | (control << 4);
Jack Lee's avatar
Jack Lee committed
93 94
		pci_read_config_byte(dev, slave_port, &slave_data);
		slave_data = slave_data & 0xf0;
95
		slave_data = slave_data | (timings[pio][0] << 2) | timings[pio][1];
Jack Lee's avatar
Jack Lee committed
96
	} else {
97
		master_data &= ~0x3307;
Jack Lee's avatar
Jack Lee committed
98
		if (pio > 1)
99
			master_data = master_data | control;
Jack Lee's avatar
Jack Lee committed
100 101 102 103 104 105 106 107
		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);
}

108 109 110 111 112 113 114
static void it8213_tuneproc(ide_drive_t *drive, u8 pio)
{
	pio = ide_get_best_pio_mode(drive, pio, 4);
	it8213_tune_pio(drive, pio);
	ide_config_drive_speed(drive, XFER_PIO_0 + pio);
}

Jack Lee's avatar
Jack Lee committed
115 116 117 118 119 120 121 122 123 124
/**
 *	it8213_tune_chipset	-	set controller timings
 *	@drive: Drive to set up
 *	@xferspeed: speed we want to achieve
 *
 *	Tune the ITE chipset for the desired mode. If we can't achieve
 *	the desired mode then tune for a lower one, but ultimately
 *	make the thing work.
 */

125
static int it8213_tune_chipset (ide_drive_t *drive, u8 xferspeed)
Jack Lee's avatar
Jack Lee committed
126 127 128 129 130
{

	ide_hwif_t *hwif	= HWIF(drive);
	struct pci_dev *dev	= hwif->pci_dev;
	u8 maslave		= 0x40;
131
	u8 speed		= ide_rate_filter(drive, xferspeed);
Jack Lee's avatar
Jack Lee committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
	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;
	u8			reg48, reg54, reg55;

	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);

	switch(speed) {
		case XFER_UDMA_6:
		case XFER_UDMA_4:
149
		case XFER_UDMA_2:	u_speed = 2 << (drive->dn * 4); break;
Jack Lee's avatar
Jack Lee committed
150 151
		case XFER_UDMA_5:
		case XFER_UDMA_3:
152 153
		case XFER_UDMA_1:	u_speed = 1 << (drive->dn * 4); break;
		case XFER_UDMA_0:	u_speed = 0 << (drive->dn * 4); break;
Jack Lee's avatar
Jack Lee committed
154 155 156
			break;
		case XFER_MW_DMA_2:
		case XFER_MW_DMA_1:
157
		case XFER_SW_DMA_2:
Jack Lee's avatar
Jack Lee committed
158 159 160 161 162 163 164 165 166 167 168
			break;
		case XFER_PIO_4:
		case XFER_PIO_3:
		case XFER_PIO_2:
		case XFER_PIO_1:
		case XFER_PIO_0:
			break;
		default:
			return -1;
	}

169
	if (speed >= XFER_UDMA_0) {
Jack Lee's avatar
Jack Lee committed
170 171 172 173 174 175 176 177 178 179
		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);
180
		if (speed > XFER_UDMA_2) {
Jack Lee's avatar
Jack Lee committed
181 182 183 184
			if (!(reg54 & v_flag))
				pci_write_config_byte(dev, 0x54, reg54 | v_flag);
		} else
			pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
185
	} else {
Jack Lee's avatar
Jack Lee committed
186 187 188 189 190 191 192 193
		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);
194
	}
195 196 197 198 199 200

	if (speed > XFER_PIO_4)
		it8213_tune_pio(drive, it8213_dma_2_pio(speed));
	else
		it8213_tune_pio(drive, speed - XFER_PIO_0);

Jack Lee's avatar
Jack Lee committed
201
	return ide_config_drive_speed(drive, speed);
202
}
Jack Lee's avatar
Jack Lee committed
203 204 205 206 207 208 209 210 211 212 213 214 215

/**
 *	it8213_configure_drive_for_dma	-	set up for DMA transfers
 *	@drive: drive we are going to set up
 *
 *	Set up the drive for DMA, tune the controller and drive as
 *	required. If the drive isn't suitable for DMA or we hit
 *	other problems then we will drop down to PIO and set up
 *	PIO appropriately
 */

static int it8213_config_drive_for_dma (ide_drive_t *drive)
{
216
	if (ide_tune_dma(drive))
217
		return 0;
Jack Lee's avatar
Jack Lee committed
218

219
	it8213_tuneproc(drive, 255);
Jack Lee's avatar
Jack Lee committed
220

221
	return -1;
Jack Lee's avatar
Jack Lee committed
222 223 224 225 226 227 228 229 230 231 232 233 234
}

/**
 *	init_hwif_it8213	-	set up hwif structs
 *	@hwif: interface to set up
 *
 *	We do the basic set up of the interface structure. The IT8212
 *	requires several custom handlers so we override the default
 *	ide DMA handlers appropriately
 */

static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
{
235
	u8 reg42h = 0;
Jack Lee's avatar
Jack Lee committed
236 237 238 239 240 241 242 243 244 245

	hwif->speedproc = &it8213_tune_chipset;
	hwif->tuneproc	= &it8213_tuneproc;

	hwif->autodma = 0;

	hwif->drives[0].autotune = 1;
	hwif->drives[1].autotune = 1;

	if (!hwif->dma_base)
246 247
		return;

Jack Lee's avatar
Jack Lee committed
248 249
	hwif->atapi_dma = 1;
	hwif->ultra_mask = 0x7f;
250 251
	hwif->mwdma_mask = 0x06;
	hwif->swdma_mask = 0x04;
Jack Lee's avatar
Jack Lee committed
252 253 254 255

	pci_read_config_byte(hwif->pci_dev, 0x42, &reg42h);

	hwif->ide_dma_check = &it8213_config_drive_for_dma;
256 257 258

	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
		hwif->cbl = (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
Jack Lee's avatar
Jack Lee committed
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275

	/*
	 *	The BIOS often doesn't set up DMA on this controller
	 *	so we always do it.
	 */
	if (!noautodma)
		hwif->autodma = 1;

	hwif->drives[0].autodma = hwif->autodma;
	hwif->drives[1].autodma = hwif->autodma;
}


#define DECLARE_ITE_DEV(name_str)			\
	{						\
		.name		= name_str,		\
		.init_hwif	= init_hwif_it8213,	\
276
		.autodma	= AUTODMA,		\
Jack Lee's avatar
Jack Lee committed
277 278
		.enablebits	= {{0x41,0x80,0x80}}, \
		.bootable	= ON_BOARD,		\
279
		.host_flags	= IDE_HFLAG_SINGLE,	\
Bartlomiej Zolnierkiewicz's avatar
Bartlomiej Zolnierkiewicz committed
280
		.pio_mask	= ATA_PIO4,		\
Jack Lee's avatar
Jack Lee committed
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
	}

static ide_pci_device_t it8213_chipsets[] __devinitdata = {
	/* 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;
}


static struct pci_device_id it8213_pci_tbl[] = {
306
	{ PCI_VENDOR_ID_ITE, 0x8213, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
Jack Lee's avatar
Jack Lee committed
307 308 309 310 311 312 313 314 315 316 317 318 319
	{ 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)
{
320 321
	return ide_pci_register_driver(&driver);
}
Jack Lee's avatar
Jack Lee committed
322 323 324

module_init(it8213_ide_init);

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