staging: comedi: 8255_pci: support memory mapped i/o boards
authorH Hartley Sweeten <hartleys@visionengravers.com>
Thu, 13 Sep 2012 17:23:40 +0000 (10:23 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 14 Sep 2012 03:13:03 +0000 (20:13 -0700)
Some of the PCI based 8255 boards that can be supported by this driver
use memory mapped i/o. Add the code needed to support these boards.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/comedi/drivers/8255_pci.c

index 314b21b56508bb3cc72168dfa59a8c3f6612d2ad..93990fabd1257a7a4021c86a0be6073c56baf751 100644 (file)
@@ -71,6 +71,7 @@ struct pci_8255_boardinfo {
        unsigned short vendor;
        unsigned short device;
        int dio_badr;
+       int is_mmio;
        int n_8255;
 };
 
@@ -120,6 +121,22 @@ static const struct pci_8255_boardinfo pci_8255_boards[] = {
        },
 };
 
+struct pci_8255_private {
+       void __iomem *mmio_base;
+};
+
+static int pci_8255_mmio(int dir, int port, int data, unsigned long iobase)
+{
+       void __iomem *mmio_base = (void __iomem *)iobase;
+
+       if (dir) {
+               writeb(data, mmio_base + port);
+               return 0;
+       } else {
+               return readb(mmio_base  + port);
+       }
+}
+
 static const void *pci_8255_find_boardinfo(struct comedi_device *dev,
                                              struct pci_dev *pcidev)
 {
@@ -139,7 +156,10 @@ static int pci_8255_attach_pci(struct comedi_device *dev,
                               struct pci_dev *pcidev)
 {
        const struct pci_8255_boardinfo *board;
+       struct pci_8255_private *devpriv;
        struct comedi_subdevice *s;
+       resource_size_t iobase;
+       unsigned long len;
        int ret;
        int i;
 
@@ -151,10 +171,23 @@ static int pci_8255_attach_pci(struct comedi_device *dev,
        dev->board_ptr = board;
        dev->board_name = board->name;
 
+       ret = alloc_private(dev, sizeof(*devpriv));
+       if (ret < 0)
+               return ret;
+       devpriv = dev->private;
+
        ret = comedi_pci_enable(pcidev, dev->board_name);
        if (ret)
                return ret;
-       dev->iobase = pci_resource_start(pcidev, board->dio_badr);
+       iobase = pci_resource_start(pcidev, board->dio_badr);
+       len = pci_resource_len(pcidev, board->dio_badr);
+
+       if (board->is_mmio) {
+               devpriv->mmio_base = ioremap(iobase, len);
+               if (!devpriv->mmio_base)
+                       return -ENOMEM;
+       }
+       dev->iobase = iobase;
 
        /*
         * One, two, or four subdevices are setup by this driver depending
@@ -167,7 +200,13 @@ static int pci_8255_attach_pci(struct comedi_device *dev,
 
        for (i = 0; i < board->n_8255; i++) {
                s = &dev->subdevices[i];
-               ret = subdev_8255_init(dev, s, NULL, dev->iobase + (i * 4));
+               if (board->is_mmio) {
+                       iobase = (unsigned long)(devpriv->mmio_base + (i * 4));
+                       ret = subdev_8255_init(dev, s, pci_8255_mmio, iobase);
+               } else {
+                       iobase = dev->iobase + (i * 4);
+                       ret = subdev_8255_init(dev, s, NULL, iobase);
+               }
                if (ret)
                        return ret;
        }
@@ -182,6 +221,7 @@ static void pci_8255_detach(struct comedi_device *dev)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
        const struct pci_8255_boardinfo *board = comedi_board(dev);
+       struct pci_8255_private *devpriv = dev->private;
        struct comedi_subdevice *s;
        int i;
 
@@ -192,6 +232,8 @@ static void pci_8255_detach(struct comedi_device *dev)
                }
        }
        if (pcidev) {
+               if (devpriv->mmio_base)
+                       iounmap(devpriv->mmio_base);
                if (dev->iobase)
                        comedi_pci_disable(pcidev);
        }