]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
staging: comedi: dmm32at: use 8255 module for Digital I/O subdevice
authorH Hartley Sweeten <hsweeten@visionengravers.com>
Tue, 11 Nov 2014 23:55:28 +0000 (16:55 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Nov 2014 23:33:24 +0000 (15:33 -0800)
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: H Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/comedi/Kconfig
drivers/staging/comedi/drivers/dmm32at.c

index cf52577349a75bd9fb77ceabbb42c03c26af880c..a8201fe875125467a8b3c52258bfb0feb85cec0b 100644 (file)
@@ -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
 
index dc222d13e318d45d5399f4573859a6ac2542c6ea..df0a47fe0d11e9f8a5221fd882ba4c4a3ec26c36 100644 (file)
@@ -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)
-{
-       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)
+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 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;
-       }
-
-       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;
+       if (dir) {
+               outb(data, dev->iobase + regbase + port);
+               return 0;
+       }
+       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;
 }