Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d6b3289 authored by Bartlomiej Zolnierkiewicz's avatar Bartlomiej Zolnierkiewicz Committed by David S. Miller
Browse files

cy82c693: fix PIO timings calculations



Just use the standard ide_timing_compute() helper to calculate
PIO timings.  This fixes many issues with the open-coded version
like using 16-bit timings when 8-bit ones should be used or not
accounting for the enhanced cycle time specified by the device.

Based on libata pata_cypress host driver.

Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 22cabc26
Loading
Loading
Loading
Loading
+20 −86
Original line number Diff line number Diff line
/*
 *  Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
 *  Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
 *  Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
 *
 * CYPRESS CY82C693 chipset IDE controller
 *
@@ -81,80 +82,6 @@
#define CY82_INDEX_CHANNEL1	0x31
#define CY82_INDEX_TIMEOUT	0x32

/* the min and max PCI bus speed in MHz - from datasheet */
#define CY82C963_MIN_BUS_SPEED	25
#define CY82C963_MAX_BUS_SPEED	33

/* the struct for the PIO mode timings */
typedef struct pio_clocks_s {
	u8	address_time;	/* Address setup (clocks) */
	u8	time_16r;	/* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */
	u8	time_16w;	/* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */
	u8	time_8;		/* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */
} pio_clocks_t;

/*
 * calc clocks using bus_speed
 * returns (rounded up) time in bus clocks for time in ns
 */
static int calc_clk(int time, int bus_speed)
{
	int clocks;

	clocks = (time*bus_speed+999)/1000 - 1;

	if (clocks < 0)
		clocks = 0;

	if (clocks > 0x0F)
		clocks = 0x0F;

	return clocks;
}

/*
 * compute the values for the clock registers for PIO
 * mode and pci_clk [MHz] speed
 *
 * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used
 *       for mode 3 and 4 drives 8 and 16-bit timings are the same
 *
 */
static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
{
	struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
	int clk1, clk2;
	int bus_speed = ide_pci_clk ? ide_pci_clk : 33;

	/* we don't check against CY82C693's min and max speed,
	 * so you can play with the idebus=xx parameter
	 */

	/* let's calc the address setup time clocks */
	p_pclk->address_time = (u8)calc_clk(t->setup, bus_speed);

	/* let's calc the active and recovery time clocks */
	clk1 = calc_clk(t->active, bus_speed);

	/* calc recovery timing */
	clk2 = t->cycle - t->active - t->setup;

	clk2 = calc_clk(clk2, bus_speed);

	clk1 = (clk1<<4)|clk2;	/* combine active and recovery clocks */

	/* note: we use the same values for 16bit IOR and IOW
	 *	those are all the same, since I don't have other
	 *	timings than those from ide-lib.c
	 */

	p_pclk->time_16r = (u8)clk1;
	p_pclk->time_16w = (u8)clk1;

	/* what are good values for 8bit ?? */
	p_pclk->time_8 = (u8)clk1;
}

/*
 * set DMA mode a specific channel for CY82C693
 */
@@ -190,8 +117,11 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
	ide_hwif_t *hwif = drive->hwif;
	struct pci_dev *dev = to_pci_dev(hwif->dev);
	pio_clocks_t pclk;
	int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
	const unsigned long T = 1000000 / bus_speed;
	unsigned int addrCtrl;
	struct ide_timing t;
	u8 time_16, time_8;

	/* select primary or secondary channel */
	if (hwif->index > 0) {  /* drive is on the secondary channel */
@@ -204,8 +134,12 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
		}
	}

	/* let's calc the values for this PIO mode */
	compute_clocks(pio, &pclk);
	ide_timing_compute(drive, XFER_PIO_0 + pio, &t, T, 1);

	time_16 = clamp_val(t.recover - 1, 0, 15) |
		  (clamp_val(t.active - 1, 0, 15) << 4);
	time_8 = clamp_val(t.act8b - 1, 0, 15) |
		 (clamp_val(t.rec8b - 1, 0, 15) << 4);

	/* now let's write  the clocks registers */
	if ((drive->dn & 1) == 0) {
@@ -217,13 +151,13 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);

		addrCtrl &= (~0xF);
		addrCtrl |= (unsigned int)pclk.address_time;
		addrCtrl |= clamp_val(t.setup - 1, 0, 15);
		pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);

		/* now let's set the remaining registers */
		pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r);
		pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w);
		pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8);
		pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, time_16);
		pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, time_16);
		pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, time_8);
	} else {
		/*
		 * set slave drive
@@ -233,13 +167,13 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);

		addrCtrl &= (~0xF0);
		addrCtrl |= ((unsigned int)pclk.address_time<<4);
		addrCtrl |= (clamp_val(t.setup - 1, 0, 15) << 4);
		pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);

		/* now let's set the remaining registers */
		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, pclk.time_16r);
		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, pclk.time_16w);
		pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, pclk.time_8);
		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, time_16);
		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, time_16);
		pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, time_8);
	}
}

@@ -325,6 +259,6 @@ static void __exit cy82c693_ide_exit(void)
module_init(cy82c693_ide_init);
module_exit(cy82c693_ide_exit);

MODULE_AUTHOR("Andreas Krebs, Andre Hedrick");
MODULE_AUTHOR("Andreas Krebs, Andre Hedrick, Bartlomiej Zolnierkiewicz");
MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE");
MODULE_LICENSE("GPL");