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

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

staging: comedi: dmm32at: use 8255 module for Digital I/O subdevice



The Dimond-MM-32-AT board uses an internal 82C55-type digital I/O circuit to
provide the 24 digital I/O lines. The only quirk is the need to set the page
selection bits in the control register to select page 1 addresses.

Instead of duplicating the 8255 code, provide an (*io) callback and use the
8255 module to support this subdevice.

This also removes the need for the private data in this driver.

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 c5f1b1e5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -384,6 +384,7 @@ config COMEDI_DT282X

config COMEDI_DMM32AT
	tristate "Diamond Systems MM-32-AT PC/104 board support"
	select COMEDI_8255
	---help---
	  Enable support for Diamond Systems MM-32-AT PC/104 boards

+12 −111
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ Configuration Options:
#include <linux/interrupt.h>
#include "../comedidev.h"

#include "8255.h"
#include "comedi_fc.h"

/* Board register addresses */
@@ -69,10 +70,7 @@ Configuration Options:
#define DMM32AT_CLK2 0x0e
#define DMM32AT_CLKCT 0x0f

#define DMM32AT_DIOA 0x0c
#define DMM32AT_DIOB 0x0d
#define DMM32AT_DIOC 0x0e
#define DMM32AT_DIOCONF 0x0f
#define DMM32AT_8255_IOBASE		0x0c  /* Page 1 registers */

/* Board register values. */

@@ -113,13 +111,6 @@ Configuration Options:
#define DMM32AT_CLKCT1 0x56	/* mode3 counter 1 - write low byte only */
#define DMM32AT_CLKCT2 0xb6	/*  mode3 counter 2 - write high and low byte */

/* DMM32AT_DIOCONF 0x0f */
#define DMM32AT_DIENABLE 0x80
#define DMM32AT_DIRA 0x10
#define DMM32AT_DIRB 0x02
#define DMM32AT_DIRCL 0x01
#define DMM32AT_DIRCH 0x08

/* board AI ranges in comedi structure */
static const struct comedi_lrange dmm32at_airanges = {
	4, {
@@ -150,10 +141,6 @@ static const struct comedi_lrange dmm32at_aoranges = {
	}
};

struct dmm32at_private {
	unsigned char dio_config;
};

static void dmm32at_ai_set_chanspec(struct comedi_device *dev,
				    struct comedi_subdevice *s,
				    unsigned int chanspec, int nchan)
@@ -472,91 +459,22 @@ static int dmm32at_ao_insn_write(struct comedi_device *dev,
	return insn->n;
}

static int dmm32at_dio_insn_bits(struct comedi_device *dev,
				 struct comedi_subdevice *s,
				 struct comedi_insn *insn,
				 unsigned int *data)
static int dmm32at_8255_io(struct comedi_device *dev,
			   int dir, int port, int data, unsigned long regbase)
{
	struct dmm32at_private *devpriv = dev->private;
	unsigned int mask;
	unsigned int val;

	mask = comedi_dio_update_state(s, data);
	if (mask) {
	/* get access to the DIO regs */
	outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);

		/* if either part of dio is set for output */
		if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) ||
		    ((devpriv->dio_config & DMM32AT_DIRCH) == 0)) {
			val = (s->state & 0x00ff0000) >> 16;
			outb(val, dev->iobase + DMM32AT_DIOC);
		}
		if ((devpriv->dio_config & DMM32AT_DIRB) == 0) {
			val = (s->state & 0x0000ff00) >> 8;
			outb(val, dev->iobase + DMM32AT_DIOB);
		}
		if ((devpriv->dio_config & DMM32AT_DIRA) == 0) {
			val = (s->state & 0x000000ff);
			outb(val, dev->iobase + DMM32AT_DIOA);
		}
	}

	val = inb(dev->iobase + DMM32AT_DIOA);
	val |= inb(dev->iobase + DMM32AT_DIOB) << 8;
	val |= inb(dev->iobase + DMM32AT_DIOC) << 16;
	s->state = val;

	data[1] = val;

	return insn->n;
}

static int dmm32at_dio_insn_config(struct comedi_device *dev,
				   struct comedi_subdevice *s,
				   struct comedi_insn *insn,
				   unsigned int *data)
{
	struct dmm32at_private *devpriv = dev->private;
	unsigned int chan = CR_CHAN(insn->chanspec);
	unsigned int mask;
	unsigned char chanbit;
	int ret;

	if (chan < 8) {
		mask = 0x0000ff;
		chanbit = DMM32AT_DIRA;
	} else if (chan < 16) {
		mask = 0x00ff00;
		chanbit = DMM32AT_DIRB;
	} else if (chan < 20) {
		mask = 0x0f0000;
		chanbit = DMM32AT_DIRCL;
	} else {
		mask = 0xf00000;
		chanbit = DMM32AT_DIRCH;
	if (dir) {
		outb(data, dev->iobase + regbase + port);
		return 0;
	}

	ret = comedi_dio_insn_config(dev, s, insn, data, mask);
	if (ret)
		return ret;

	if (data[0] == INSN_CONFIG_DIO_OUTPUT)
		devpriv->dio_config &= ~chanbit;
	else
		devpriv->dio_config |= chanbit;
	/* get access to the DIO regs */
	outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
	/* set the DIO's to the new configuration setting */
	outb(devpriv->dio_config, dev->iobase + DMM32AT_DIOCONF);

	return insn->n;
	return inb(dev->iobase + regbase + port);
}

/* Make sure the board is there and put it to a known state */
static int dmm32at_reset(struct comedi_device *dev)
{
	struct dmm32at_private *devpriv = dev->private;
	unsigned char aihi, ailo, fifostat, aistat, intstat, airback;

	/* reset the board */
@@ -593,28 +511,15 @@ static int dmm32at_reset(struct comedi_device *dev)
	    aistat != 0x60 || intstat != 0x00 || airback != 0x0c)
		return -EIO;

	/* get access to the DIO regs */
	outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
	/* set the DIO's to the defualt input setting */
	devpriv->dio_config = DMM32AT_DIRA | DMM32AT_DIRB |
			      DMM32AT_DIRCL | DMM32AT_DIRCH |
			      DMM32AT_DIENABLE;
	outb(devpriv->dio_config, dev->iobase + DMM32AT_DIOCONF);

	return 0;
}

static int dmm32at_attach(struct comedi_device *dev,
			  struct comedi_devconfig *it)
{
	struct dmm32at_private *devpriv;
	struct comedi_subdevice *s;
	int ret;

	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
	if (!devpriv)
		return -ENOMEM;

	ret = comedi_request_region(dev, it->options[0], 0x10);
	if (ret)
		return ret;
@@ -669,13 +574,9 @@ static int dmm32at_attach(struct comedi_device *dev,

	/* Digital I/O subdevice */
	s = &dev->subdevices[2];
	s->type		= COMEDI_SUBD_DIO;
	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
	s->n_chan	= 24;
	s->maxdata	= 1;
	s->range_table	= &range_digital;
	s->insn_bits	= dmm32at_dio_insn_bits;
	s->insn_config	= dmm32at_dio_insn_config;
	ret = subdev_8255_init(dev, s, dmm32at_8255_io, DMM32AT_8255_IOBASE);
	if (ret)
		return ret;

	return 0;
}