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

Commit 26ccb802 authored by Sergei Shtylyov's avatar Sergei Shtylyov Committed by Bartlomiej Zolnierkiewicz
Browse files

hpt366: merge HPT37x speedproc handlers



Continue with the driver rewrite:

- move the interrupt twiddling code from the speedproc handlers into the
    init_hwif_hpt366 which allows to merge the two HPT37x speedproc handlers
    into one;

- get rid of in init_hpt366 which solely consists of the duplicate code, then
    fold init_hpt37x() into init_chipset_hpt366();

- fix hpt3xx_tune_drive() to always set the PIO mode requested, not the best
    possible one, change hpt366_config_drive_xfer_rate() accordingly, simplify
    it a bit;

- group all the DMA related code together init_hwif_hpt366(), and generally
    clean up and beautify it.

Signed-off-by: default avatarSergei Shtylyov <sshtylyov@ru.mvista.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent abc4ad4c
Loading
Loading
Loading
Loading
+88 −170
Original line number Diff line number Diff line
/*
 * linux/drivers/ide/pci/hpt366.c		Version 0.50	May 28, 2006
 * linux/drivers/ide/pci/hpt366.c		Version 0.51	Jun 04, 2006
 *
 * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
 * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
@@ -83,13 +83,16 @@
 * - cache the channel's MCRs' offset; only touch the relevant MCR when detecting
 *   the cable type on HPT374's function 1
 * - rename all the register related variables consistently
 * - make HPT36x's speedproc handler look the same way as HPT37x ones; fix the
 *   PIO timing register mask for HPT37x
 * - move the interrupt twiddling code from the speedproc handlers into the
 *   init_hwif handler, also grouping all the DMA related code together there;
 *   simplify  the init_chipset handler
 * - merge two HPT37x speedproc handlers and fix the PIO timing register mask
 *   there; make HPT36x speedproc handler look the same way as the HPT37x one
 * - fix  the tuneproc handler to always set the PIO mode requested,  not the
 *   best possible one
 *		<source@mvista.com>
 *
 */


#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -507,19 +510,9 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
	struct hpt_info	*info	= ide_get_hwifdata (hwif);
	u8  speed		= hpt3xx_ratefilter(drive, xferspeed);
	u8  itr_addr		= drive->dn ? 0x44 : 0x40;
	u8  mcr_addr		= hwif->select_data + 1;
	u8  mcr			= 0;
	u32 new_itr, old_itr	= 0;
	u32 itr_mask		= (speed < XFER_MW_DMA_0) ? 0x30070000 : 0xc0000000;

	/*
	 * Disable the "fast interrupt" prediction.
	 */
	pci_read_config_byte(dev, mcr_addr, &mcr);
	if (mcr & 0x80)
		pci_write_config_byte(dev, mcr_addr, mcr & ~0x80);

	new_itr = pci_bus_clock_list(speed, info->speed);
	u32 new_itr		= pci_bus_clock_list(speed, info->speed);
	u32 old_itr		= 0;

	/*
	 * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well)
@@ -534,38 +527,16 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
	return ide_config_drive_speed(drive, speed);
}

static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
static int hpt37x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
{
	ide_hwif_t *hwif	= HWIF(drive);
	struct pci_dev  *dev	= hwif->pci_dev;
	struct hpt_info	*info	= ide_get_hwifdata (hwif);
	u8  speed		= hpt3xx_ratefilter(drive, xferspeed);
	u8  mcr_addr		= hwif->select_data + 1;
	u8  itr_addr		= 0x40 + (drive->dn * 4);
	u8  new_mcr		= 0, old_mcr = 0;
	u32 new_itr, old_itr	= 0;
	u32 itr_mask		= (speed < XFER_MW_DMA_0) ? 0x303c0000 : 0xc0000000;

	/*
	 * Disable the "fast interrupt" prediction.
	 * don't holdoff on interrupts. (== 0x01 despite what the docs say) 
	 */
	pci_read_config_byte(dev, mcr_addr, &old_mcr);
	new_mcr = old_mcr;
	if (new_mcr & 0x02)
		new_mcr &= ~0x02;

#ifdef HPT_DELAY_INTERRUPT
	if (new_mcr & 0x01)
		new_mcr &= ~0x01;
#else
	if ((new_mcr & 0x01) == 0)
		new_mcr |= 0x01;
#endif
	if (new_mcr != old_mcr)
		pci_write_config_byte(dev, mcr_addr, new_mcr);

	new_itr = pci_bus_clock_list(speed, info->speed);
	u32 new_itr		= pci_bus_clock_list(speed, info->speed);
	u32 old_itr		= 0;

	pci_read_config_dword(dev, itr_addr, &old_itr);
	new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask);
@@ -577,71 +548,34 @@ static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
	return ide_config_drive_speed(drive, speed);
}

static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed)
{
	ide_hwif_t *hwif	= HWIF(drive);
	struct pci_dev  *dev	= hwif->pci_dev;
	struct hpt_info	*info	= ide_get_hwifdata (hwif);
	u8  speed		= hpt3xx_ratefilter(drive, xferspeed);
	u8  mcr_addr		= hwif->select_data + 1;
	u8  itr_addr		= 0x40 + (drive->dn * 4);
	u8  mcr			= 0;
	u32 new_itr, old_itr	= 0;
	u32 itr_mask		= (speed < XFER_MW_DMA_0) ? 0x303c0000 : 0xc0000000;

	/*
	 * Disable the "fast interrupt" prediction.
	 * don't holdoff on interrupts. (== 0x01 despite what the docs say)
	 */
	pci_read_config_byte (dev, mcr_addr, &mcr);
	pci_write_config_byte(dev, mcr_addr, (mcr & ~0x07));

	new_itr = pci_bus_clock_list(speed, info->speed);
	pci_read_config_dword(dev, itr_addr, &old_itr);
	new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask);
	if (speed < XFER_MW_DMA_0)
		new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
	pci_write_config_dword(dev, itr_addr, new_itr);

	return ide_config_drive_speed(drive, speed);
}

static int hpt3xx_tune_chipset(ide_drive_t *drive, u8 speed)
{
	ide_hwif_t *hwif	= drive->hwif;
	ide_hwif_t *hwif	= HWIF(drive);
	struct hpt_info	*info	= ide_get_hwifdata(hwif);

	if (info->revision >= 8)
		return hpt372_tune_chipset(drive, speed); /* not a typo */
	else if (info->revision >= 5)
		return hpt372_tune_chipset(drive, speed);
	else if (info->revision >= 3)
		return hpt370_tune_chipset(drive, speed);
	if (info->revision >= 3)
		return hpt37x_tune_chipset(drive, speed);
	else	/* hpt368: hpt_minimum_revision(dev, 2) */
		return hpt36x_tune_chipset(drive, speed);
}

static void hpt3xx_tune_drive(ide_drive_t *drive, u8 pio)
{
	pio = ide_get_best_pio_mode(drive, 255, pio, NULL);
	(void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio));
	pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
	(void) hpt3xx_tune_chipset (drive, XFER_PIO_0 + pio);
}

/*
 * This allows the configuration of ide_pci chipset registers
 * for cards that learn about the drive's UDMA, DMA, PIO capabilities
 * after the drive is reported by the OS.  Initially for designed for
 * after the drive is reported by the OS.  Initially designed for
 * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc.
 *
 * check_in_drive_lists(drive, bad_ata66_4)
 * check_in_drive_lists(drive, bad_ata66_3)
 * check_in_drive_lists(drive, bad_ata33)
 *
 */
static int config_chipset_for_dma(ide_drive_t *drive)
{
	u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive));
	ide_hwif_t *hwif = drive->hwif;
	ide_hwif_t *hwif	= HWIF(drive);
	struct hpt_info	*info	= ide_get_hwifdata(hwif);

	if (!speed)
@@ -707,23 +641,20 @@ static void hpt3xx_maskproc (ide_drive_t *drive, int mask)

static int hpt366_config_drive_xfer_rate(ide_drive_t *drive)
{
	ide_hwif_t *hwif	= drive->hwif;
	ide_hwif_t *hwif	= HWIF(drive);
	struct hd_driveid *id	= drive->id;

	drive->init_speed = 0;

	if ((id->capability & 1) && drive->autodma) {

		if (ide_use_dma(drive)) {
			if (config_chipset_for_dma(drive))
		if (ide_use_dma(drive) && config_chipset_for_dma(drive))
			return hwif->ide_dma_on(drive);
		}

		goto fast_ata_pio;

	} else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio:
		hpt3xx_tune_drive(drive, 5);
		hpt3xx_tune_drive(drive, 255);
		return hwif->ide_dma_off_quietly(drive);
	}
	/* IORDY not supported */
@@ -1154,34 +1085,8 @@ init_hpt37X_done:
	udelay(100);
}

static int __devinit init_hpt37x(struct pci_dev *dev)
{
	u8 scr1;

	pci_read_config_byte (dev, 0x5a, &scr1);
	/* interrupt force enable */
	pci_write_config_byte(dev, 0x5a, (scr1 & ~0x10));
	return 0;
}

static int __devinit init_hpt366(struct pci_dev *dev)
{
	u8 mcr	= 0;

	/*
	 * Disable the "fast interrupt" prediction.
	 */
	pci_read_config_byte(dev, 0x51, &mcr);
	if (mcr & 0x80)
		pci_write_config_byte(dev, 0x51, mcr & ~0x80);
									
	return 0;
}

static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
{
	int ret = 0;

	/*
	 * FIXME: Not portable. Also, why do we enable the ROM in the first place?
	 * We don't seem to be using it.
@@ -1195,13 +1100,14 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
	pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
	pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);

	if (hpt_revision(dev) >= 3)
		ret = init_hpt37x(dev);
	else
		ret = init_hpt366(dev);
	if (hpt_revision(dev) >= 3) {
		u8 scr1 = 0;

	if (ret)
		return ret;
		/* Interrupt force enable. */
		pci_read_config_byte(dev, 0x5a, &scr1);
		if (scr1 & 0x10)
			pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
	}

	return dev->irq;
}
@@ -1212,6 +1118,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
	struct hpt_info *info		= ide_get_hwifdata(hwif);
	int serialize			= HPT_SERIALIZE_IO;
	u8  scr1 = 0, ata66		= (hwif->channel) ? 0x01 : 0x02;
	u8  new_mcr, old_mcr 		= 0;

	/* Cache the channel's MISC. control registers' offset */
	hwif->select_data		= hwif->channel ? 0x54 : 0x50;
@@ -1238,6 +1145,41 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
		hwif->rw_disk = &hpt3xxn_rw_disk;
	}

	/* Serialize access to this device if needed */
	if (serialize && hwif->mate)
		hwif->serialized = hwif->mate->serialized = 1;

	/*
	 * Disable the "fast interrupt" prediction.  Don't hold off
	 * on interrupts. (== 0x01 despite what the docs say)
	 */
	pci_read_config_byte(dev, hwif->select_data + 1, &old_mcr);

	if (info->revision >= 5)		/* HPT372 and newer   */
		new_mcr = old_mcr & ~0x07;
	else if (info->revision >= 3) {		/* HPT370 and HPT370A */
		new_mcr = old_mcr;
		new_mcr &= ~0x02;

#ifdef HPT_DELAY_INTERRUPT
		new_mcr &= ~0x01;
#else
		new_mcr |=  0x01;
#endif
	} else					/* HPT366 and HPT368  */
		new_mcr = old_mcr & ~0x80;

	if (new_mcr != old_mcr)
		pci_write_config_byte(dev, hwif->select_data + 1, new_mcr);

	if (!hwif->dma_base) {
		hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
		return;
	}

	hwif->ultra_mask = 0x7f;
	hwif->mwdma_mask = 0x07;

	/*
	 * The HPT37x uses the CBLID pins as outputs for MA15/MA16
	 * address lines to access an external EEPROM.  To read valid
@@ -1272,33 +1214,12 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
	} else
		pci_read_config_byte (dev, 0x5a, &scr1);

	/* Serialize access to this device */
	if (serialize && hwif->mate)
		hwif->serialized = hwif->mate->serialized = 1;

	/*
	 * Set up ioctl for power status.
	 * NOTE:  power affects both drives on each channel.
	 */
	hwif->busproc = &hpt3xx_busproc;

	if (!hwif->dma_base) {
		hwif->drives[0].autotune = 1;
		hwif->drives[1].autotune = 1;
		return;
	}

	hwif->ultra_mask = 0x7f;
	hwif->mwdma_mask = 0x07;
	if (!hwif->udma_four)
		hwif->udma_four = (scr1 & ata66) ? 0 : 1;

	if (!(hwif->udma_four))
		hwif->udma_four = ((scr1 & ata66) ? 0 : 1);
	hwif->ide_dma_check		= &hpt366_config_drive_xfer_rate;

	if (info->revision >= 8) {
		hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
		hwif->ide_dma_end = &hpt374_ide_dma_end;
	} else if (info->revision >= 5) {
	if (info->revision >= 5) {
		hwif->ide_dma_test_irq	= &hpt374_ide_dma_test_irq;
		hwif->ide_dma_end	= &hpt374_ide_dma_end;
	} else if (info->revision >= 3) {
@@ -1306,15 +1227,12 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
		hwif->ide_dma_end	= &hpt370_ide_dma_end;
		hwif->ide_dma_timeout	= &hpt370_ide_dma_timeout;
		hwif->ide_dma_lostirq	= &hpt370_ide_dma_lostirq;
	} else if (info->revision >= 2)
		hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
	else
	} else
		hwif->ide_dma_lostirq	= &hpt366_ide_dma_lostirq;

	if (!noautodma)
		hwif->autodma = 1;
	hwif->drives[0].autodma = hwif->autodma;
	hwif->drives[1].autodma = hwif->autodma;
	hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
}

static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)