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

Commit 6cf8ea2e authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman
Browse files

staging: comedi: addi_apci_1564: fix timer iobase for all PLD revisions



The APCI-1564 has different I/O mapping depending on if the PLD revision
is Rev 1.0 or Rev 2.x.

Add a member, 'timer', to the private data for the base address of the
12-bit timer. Fix the register defines so they will work for all PLD
revisions and initialize the devpriv->timer appropriately.

Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 37436196
Loading
Loading
Loading
Loading
+18 −14
Original line number Diff line number Diff line
@@ -52,15 +52,15 @@ static int apci1564_timer_config(struct comedi_device *dev,
	devpriv->tsk_current = current;
	if (data[0] == ADDIDATA_TIMER) {
		/* First Stop The Timer */
		ul_Command1 = inl(dev->iobase + APCI1564_TIMER_CTRL_REG);
		ul_Command1 = inl(devpriv->timer + APCI1564_TIMER_CTRL_REG);
		ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
		/* Stop The Timer */
		outl(ul_Command1, dev->iobase + APCI1564_TIMER_CTRL_REG);
		outl(ul_Command1, devpriv->timer + APCI1564_TIMER_CTRL_REG);

		devpriv->timer_select_mode = ADDIDATA_TIMER;
		if (data[1] == 1) {
			/* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
			outl(0x02, dev->iobase + APCI1564_TIMER_CTRL_REG);
			outl(0x02, devpriv->timer + APCI1564_TIMER_CTRL_REG);
			outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG);
			outl(0x0, dev->iobase + APCI1564_DO_IRQ_REG);
			outl(0x0, dev->iobase + APCI1564_WDOG_IRQ_REG);
@@ -72,19 +72,19 @@ static int apci1564_timer_config(struct comedi_device *dev,
			     devpriv->counters + APCI1564_COUNTER_IRQ_REG(2));
		} else {
			/* disable Timer interrupt */
			outl(0x0, dev->iobase + APCI1564_TIMER_CTRL_REG);
			outl(0x0, devpriv->timer + APCI1564_TIMER_CTRL_REG);
		}

		/*  Loading Timebase */
		outl(data[2], dev->iobase + APCI1564_TIMER_TIMEBASE_REG);
		outl(data[2], devpriv->timer + APCI1564_TIMER_TIMEBASE_REG);

		/* Loading the Reload value */
		outl(data[3], dev->iobase + APCI1564_TIMER_RELOAD_REG);
		outl(data[3], devpriv->timer + APCI1564_TIMER_RELOAD_REG);

		ul_Command1 = inl(dev->iobase + APCI1564_TIMER_CTRL_REG);
		ul_Command1 = inl(devpriv->timer + APCI1564_TIMER_CTRL_REG);
		ul_Command1 = (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
		/* mode 2 */
		outl(ul_Command1, dev->iobase + APCI1564_TIMER_CTRL_REG);
		outl(ul_Command1, devpriv->timer + APCI1564_TIMER_CTRL_REG);
	} else if (data[0] == ADDIDATA_COUNTER) {
		devpriv->timer_select_mode = ADDIDATA_COUNTER;

@@ -146,17 +146,21 @@ static int apci1564_timer_write(struct comedi_device *dev,

	if (devpriv->timer_select_mode == ADDIDATA_TIMER) {
		if (data[1] == 1) {
			ul_Command1 = inl(dev->iobase + APCI1564_TIMER_CTRL_REG);
			ul_Command1 = inl(devpriv->timer +
					  APCI1564_TIMER_CTRL_REG);
			ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;

			/* Enable the Timer */
			outl(ul_Command1, dev->iobase + APCI1564_TIMER_CTRL_REG);
			outl(ul_Command1,
			     devpriv->timer + APCI1564_TIMER_CTRL_REG);
		} else if (data[1] == 0) {
			/* Stop The Timer */

			ul_Command1 = inl(dev->iobase + APCI1564_TIMER_CTRL_REG);
			ul_Command1 = inl(devpriv->timer +
					  APCI1564_TIMER_CTRL_REG);
			ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
			outl(ul_Command1, dev->iobase + APCI1564_TIMER_CTRL_REG);
			outl(ul_Command1,
			     devpriv->timer + APCI1564_TIMER_CTRL_REG);
		}
	} else if (devpriv->timer_select_mode == ADDIDATA_COUNTER) {
		ul_Command1 = inl(devpriv->counters +
@@ -194,10 +198,10 @@ static int apci1564_timer_read(struct comedi_device *dev,

	if (devpriv->timer_select_mode == ADDIDATA_TIMER) {
		/*  Stores the status of the Timer */
		data[0] = inl(dev->iobase + APCI1564_TIMER_STATUS_REG) & 0x1;
		data[0] = inl(devpriv->timer + APCI1564_TIMER_STATUS_REG) & 0x1;

		/*  Stores the Actual value of the Timer */
		data[1] = inl(dev->iobase + APCI1564_TIMER_REG);
		data[1] = inl(devpriv->timer + APCI1564_TIMER_REG);
	} else if (devpriv->timer_select_mode == ADDIDATA_COUNTER) {
		/*  Read the Counter Actual Value. */
		data[0] = inl(devpriv->counters +
+24 −14
Original line number Diff line number Diff line
@@ -51,7 +51,9 @@
#define APCI1564_EEPROM_DO			(1 << 2)
#define APCI1564_EEPROM_CS			(1 << 1)
#define APCI1564_EEPROM_CLK			(1 << 0)
#define APCI1564_REV1_TIMER_IOBASE		0x04
#define APCI1564_REV2_MAIN_IOBASE		0x04
#define APCI1564_REV2_TIMER_IOBASE		0x48

/*
 * PCI BAR 1
@@ -90,18 +92,24 @@
#define APCI1564_WDOG_IRQ_REG			0x38
#define APCI1564_WDOG_WARN_TIMEVAL_REG		0x3c
#define APCI1564_WDOG_WARN_TIMEBASE_REG		0x40
#define APCI1564_TIMER_REG			0x44
#define APCI1564_TIMER_RELOAD_REG		0x48
#define APCI1564_TIMER_TIMEBASE_REG		0x4c
#define APCI1564_TIMER_CTRL_REG			0x50
#define APCI1564_TIMER_STATUS_REG		0x54
#define APCI1564_TIMER_IRQ_REG			0x58
#define APCI1564_TIMER_WARN_TIMEVAL_REG		0x5c  /* Rev 2.x only */
#define APCI1564_TIMER_WARN_TIMEBASE_REG	0x60  /* Rev 2.x only */

/*
 * devpriv->timer Register Map
 *   PLD Revision 1.0 - PCI BAR 0 + 0x04
 *   PLD Revision 2.x - PCI BAR 0 + 0x48
 */
#define APCI1564_TIMER_REG			0x00
#define APCI1564_TIMER_RELOAD_REG		0x04
#define APCI1564_TIMER_TIMEBASE_REG		0x08
#define APCI1564_TIMER_CTRL_REG			0x0c
#define APCI1564_TIMER_STATUS_REG		0x10
#define APCI1564_TIMER_IRQ_REG			0x14
#define APCI1564_TIMER_WARN_TIMEVAL_REG		0x18  /* Rev 2.x only */
#define APCI1564_TIMER_WARN_TIMEBASE_REG	0x1c  /* Rev 2.x only */

struct apci1564_private {
	unsigned long eeprom;		/* base address of EEPROM register */
	unsigned long timer;		/* base address of 12-bit timer */
	unsigned long counters;		/* base address of 32-bit counters */
	unsigned int mode1;		/* riding-edge/high level channels */
	unsigned int mode2;		/* falling-edge/low level channels */
@@ -130,8 +138,8 @@ static int apci1564_reset(struct comedi_device *dev)
	addi_watchdog_reset(dev->iobase + APCI1564_WDOG_REG);

	/* Reset the timer registers */
	outl(0x0, dev->iobase + APCI1564_TIMER_CTRL_REG);
	outl(0x0, dev->iobase + APCI1564_TIMER_RELOAD_REG);
	outl(0x0, devpriv->timer + APCI1564_TIMER_CTRL_REG);
	outl(0x0, devpriv->timer + APCI1564_TIMER_RELOAD_REG);

	/* Reset the counter registers */
	outl(0x0, devpriv->counters + APCI1564_COUNTER_CTRL_REG(0));
@@ -165,17 +173,17 @@ static irqreturn_t apci1564_interrupt(int irq, void *d)
		outl(status, dev->iobase + APCI1564_DI_IRQ_REG);
	}

	status = inl(dev->iobase + APCI1564_TIMER_IRQ_REG);
	status = inl(devpriv->timer + APCI1564_TIMER_IRQ_REG);
	if (status & 0x01) {
		/*  Disable Timer Interrupt */
		ctrl = inl(dev->iobase + APCI1564_TIMER_CTRL_REG);
		outl(0x0, dev->iobase + APCI1564_TIMER_CTRL_REG);
		ctrl = inl(devpriv->timer + APCI1564_TIMER_CTRL_REG);
		outl(0x0, devpriv->timer + APCI1564_TIMER_CTRL_REG);

		/* Send a signal to from kernel to user space */
		send_sig(SIGIO, devpriv->tsk_current, 0);

		/*  Enable Timer Interrupt */
		outl(ctrl, dev->iobase + APCI1564_TIMER_CTRL_REG);
		outl(ctrl, devpriv->timer + APCI1564_TIMER_CTRL_REG);
	}

	for (chan = 0; chan < 4; chan++) {
@@ -441,12 +449,14 @@ static int apci1564_auto_attach(struct comedi_device *dev,
		/* PLD Revision 1.0 I/O Mapping */
		dev->iobase = pci_resource_start(pcidev, 1) +
			      APCI1564_REV1_MAIN_IOBASE;
		devpriv->timer = devpriv->eeprom + APCI1564_REV1_TIMER_IOBASE;
		dev_err(dev->class_dev,
			"PLD Revision 1.0 detected, not yet supported\n");
		return -ENXIO;
	} else {
		/* PLD Revision 2.x I/O Mapping */
		dev->iobase = devpriv->eeprom + APCI1564_REV2_MAIN_IOBASE;
		devpriv->timer = devpriv->eeprom + APCI1564_REV2_TIMER_IOBASE;
		devpriv->counters = pci_resource_start(pcidev, 1);
	}