root/drivers/staging/comedi/drivers/adl_pci7x3x.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. adl_pci7x3x_do_insn_bits
  2. adl_pci7x3x_di_insn_bits
  3. adl_pci7x3x_auto_attach
  4. adl_pci7x3x_pci_probe

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * COMEDI driver for the ADLINK PCI-723x/743x series boards.
   4  * Copyright (C) 2012 H Hartley Sweeten <hsweeten@visionengravers.com>
   5  *
   6  * Based on the adl_pci7230 driver written by:
   7  *      David Fernandez <dfcastelao@gmail.com>
   8  * and the adl_pci7432 driver written by:
   9  *      Michel Lachaine <mike@mikelachaine.ca>
  10  *
  11  * COMEDI - Linux Control and Measurement Device Interface
  12  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
  13  */
  14 
  15 /*
  16  * Driver: adl_pci7x3x
  17  * Description: 32/64-Channel Isolated Digital I/O Boards
  18  * Devices: [ADLink] PCI-7230 (adl_pci7230), PCI-7233 (adl_pci7233),
  19  *   PCI-7234 (adl_pci7234), PCI-7432 (adl_pci7432), PCI-7433 (adl_pci7433),
  20  *   PCI-7434 (adl_pci7434)
  21  * Author: H Hartley Sweeten <hsweeten@visionengravers.com>
  22  * Updated: Thu, 02 Aug 2012 14:27:46 -0700
  23  * Status: untested
  24  *
  25  * One or two subdevices are setup by this driver depending on
  26  * the number of digital inputs and/or outputs provided by the
  27  * board. Each subdevice has a maximum of 32 channels.
  28  *
  29  *      PCI-7230 - 2 subdevices: 0 - 16 input, 1 - 16 output
  30  *      PCI-7233 - 1 subdevice: 0 - 32 input
  31  *      PCI-7234 - 1 subdevice: 0 - 32 output
  32  *      PCI-7432 - 2 subdevices: 0 - 32 input, 1 - 32 output
  33  *      PCI-7433 - 2 subdevices: 0 - 32 input, 1 - 32 input
  34  *      PCI-7434 - 2 subdevices: 0 - 32 output, 1 - 32 output
  35  *
  36  * The PCI-7230, PCI-7432 and PCI-7433 boards also support external
  37  * interrupt signals on digital input channels 0 and 1. The PCI-7233
  38  * has dual-interrupt sources for change-of-state (COS) on any 16
  39  * digital input channels of LSB and for COS on any 16 digital input
  40  * lines of MSB. Interrupts are not currently supported by this
  41  * driver.
  42  *
  43  * Configuration Options: not applicable, uses comedi PCI auto config
  44  */
  45 
  46 #include <linux/module.h>
  47 
  48 #include "../comedi_pci.h"
  49 
  50 /*
  51  * Register I/O map (32-bit access only)
  52  */
  53 #define PCI7X3X_DIO_REG         0x00
  54 #define PCI743X_DIO_REG         0x04
  55 
  56 enum apci1516_boardid {
  57         BOARD_PCI7230,
  58         BOARD_PCI7233,
  59         BOARD_PCI7234,
  60         BOARD_PCI7432,
  61         BOARD_PCI7433,
  62         BOARD_PCI7434,
  63 };
  64 
  65 struct adl_pci7x3x_boardinfo {
  66         const char *name;
  67         int nsubdevs;
  68         int di_nchan;
  69         int do_nchan;
  70 };
  71 
  72 static const struct adl_pci7x3x_boardinfo adl_pci7x3x_boards[] = {
  73         [BOARD_PCI7230] = {
  74                 .name           = "adl_pci7230",
  75                 .nsubdevs       = 2,
  76                 .di_nchan       = 16,
  77                 .do_nchan       = 16,
  78         },
  79         [BOARD_PCI7233] = {
  80                 .name           = "adl_pci7233",
  81                 .nsubdevs       = 1,
  82                 .di_nchan       = 32,
  83         },
  84         [BOARD_PCI7234] = {
  85                 .name           = "adl_pci7234",
  86                 .nsubdevs       = 1,
  87                 .do_nchan       = 32,
  88         },
  89         [BOARD_PCI7432] = {
  90                 .name           = "adl_pci7432",
  91                 .nsubdevs       = 2,
  92                 .di_nchan       = 32,
  93                 .do_nchan       = 32,
  94         },
  95         [BOARD_PCI7433] = {
  96                 .name           = "adl_pci7433",
  97                 .nsubdevs       = 2,
  98                 .di_nchan       = 64,
  99         },
 100         [BOARD_PCI7434] = {
 101                 .name           = "adl_pci7434",
 102                 .nsubdevs       = 2,
 103                 .do_nchan       = 64,
 104         }
 105 };
 106 
 107 static int adl_pci7x3x_do_insn_bits(struct comedi_device *dev,
 108                                     struct comedi_subdevice *s,
 109                                     struct comedi_insn *insn,
 110                                     unsigned int *data)
 111 {
 112         unsigned long reg = (unsigned long)s->private;
 113 
 114         if (comedi_dio_update_state(s, data)) {
 115                 unsigned int val = s->state;
 116 
 117                 if (s->n_chan == 16) {
 118                         /*
 119                          * It seems the PCI-7230 needs the 16-bit DO state
 120                          * to be shifted left by 16 bits before being written
 121                          * to the 32-bit register.  Set the value in both
 122                          * halves of the register to be sure.
 123                          */
 124                         val |= val << 16;
 125                 }
 126                 outl(val, dev->iobase + reg);
 127         }
 128 
 129         data[1] = s->state;
 130 
 131         return insn->n;
 132 }
 133 
 134 static int adl_pci7x3x_di_insn_bits(struct comedi_device *dev,
 135                                     struct comedi_subdevice *s,
 136                                     struct comedi_insn *insn,
 137                                     unsigned int *data)
 138 {
 139         unsigned long reg = (unsigned long)s->private;
 140 
 141         data[1] = inl(dev->iobase + reg);
 142 
 143         return insn->n;
 144 }
 145 
 146 static int adl_pci7x3x_auto_attach(struct comedi_device *dev,
 147                                    unsigned long context)
 148 {
 149         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 150         const struct adl_pci7x3x_boardinfo *board = NULL;
 151         struct comedi_subdevice *s;
 152         int subdev;
 153         int nchan;
 154         int ret;
 155 
 156         if (context < ARRAY_SIZE(adl_pci7x3x_boards))
 157                 board = &adl_pci7x3x_boards[context];
 158         if (!board)
 159                 return -ENODEV;
 160         dev->board_ptr = board;
 161         dev->board_name = board->name;
 162 
 163         ret = comedi_pci_enable(dev);
 164         if (ret)
 165                 return ret;
 166         dev->iobase = pci_resource_start(pcidev, 2);
 167 
 168         ret = comedi_alloc_subdevices(dev, board->nsubdevs);
 169         if (ret)
 170                 return ret;
 171 
 172         subdev = 0;
 173 
 174         if (board->di_nchan) {
 175                 nchan = min(board->di_nchan, 32);
 176 
 177                 s = &dev->subdevices[subdev];
 178                 /* Isolated digital inputs 0 to 15/31 */
 179                 s->type         = COMEDI_SUBD_DI;
 180                 s->subdev_flags = SDF_READABLE;
 181                 s->n_chan       = nchan;
 182                 s->maxdata      = 1;
 183                 s->insn_bits    = adl_pci7x3x_di_insn_bits;
 184                 s->range_table  = &range_digital;
 185 
 186                 s->private      = (void *)PCI7X3X_DIO_REG;
 187 
 188                 subdev++;
 189 
 190                 nchan = board->di_nchan - nchan;
 191                 if (nchan) {
 192                         s = &dev->subdevices[subdev];
 193                         /* Isolated digital inputs 32 to 63 */
 194                         s->type         = COMEDI_SUBD_DI;
 195                         s->subdev_flags = SDF_READABLE;
 196                         s->n_chan       = nchan;
 197                         s->maxdata      = 1;
 198                         s->insn_bits    = adl_pci7x3x_di_insn_bits;
 199                         s->range_table  = &range_digital;
 200 
 201                         s->private      = (void *)PCI743X_DIO_REG;
 202 
 203                         subdev++;
 204                 }
 205         }
 206 
 207         if (board->do_nchan) {
 208                 nchan = min(board->do_nchan, 32);
 209 
 210                 s = &dev->subdevices[subdev];
 211                 /* Isolated digital outputs 0 to 15/31 */
 212                 s->type         = COMEDI_SUBD_DO;
 213                 s->subdev_flags = SDF_WRITABLE;
 214                 s->n_chan       = nchan;
 215                 s->maxdata      = 1;
 216                 s->insn_bits    = adl_pci7x3x_do_insn_bits;
 217                 s->range_table  = &range_digital;
 218 
 219                 s->private      = (void *)PCI7X3X_DIO_REG;
 220 
 221                 subdev++;
 222 
 223                 nchan = board->do_nchan - nchan;
 224                 if (nchan) {
 225                         s = &dev->subdevices[subdev];
 226                         /* Isolated digital outputs 32 to 63 */
 227                         s->type         = COMEDI_SUBD_DO;
 228                         s->subdev_flags = SDF_WRITABLE;
 229                         s->n_chan       = nchan;
 230                         s->maxdata      = 1;
 231                         s->insn_bits    = adl_pci7x3x_do_insn_bits;
 232                         s->range_table  = &range_digital;
 233 
 234                         s->private      = (void *)PCI743X_DIO_REG;
 235 
 236                         subdev++;
 237                 }
 238         }
 239 
 240         return 0;
 241 }
 242 
 243 static struct comedi_driver adl_pci7x3x_driver = {
 244         .driver_name    = "adl_pci7x3x",
 245         .module         = THIS_MODULE,
 246         .auto_attach    = adl_pci7x3x_auto_attach,
 247         .detach         = comedi_pci_detach,
 248 };
 249 
 250 static int adl_pci7x3x_pci_probe(struct pci_dev *dev,
 251                                  const struct pci_device_id *id)
 252 {
 253         return comedi_pci_auto_config(dev, &adl_pci7x3x_driver,
 254                                       id->driver_data);
 255 }
 256 
 257 static const struct pci_device_id adl_pci7x3x_pci_table[] = {
 258         { PCI_VDEVICE(ADLINK, 0x7230), BOARD_PCI7230 },
 259         { PCI_VDEVICE(ADLINK, 0x7233), BOARD_PCI7233 },
 260         { PCI_VDEVICE(ADLINK, 0x7234), BOARD_PCI7234 },
 261         { PCI_VDEVICE(ADLINK, 0x7432), BOARD_PCI7432 },
 262         { PCI_VDEVICE(ADLINK, 0x7433), BOARD_PCI7433 },
 263         { PCI_VDEVICE(ADLINK, 0x7434), BOARD_PCI7434 },
 264         { 0 }
 265 };
 266 MODULE_DEVICE_TABLE(pci, adl_pci7x3x_pci_table);
 267 
 268 static struct pci_driver adl_pci7x3x_pci_driver = {
 269         .name           = "adl_pci7x3x",
 270         .id_table       = adl_pci7x3x_pci_table,
 271         .probe          = adl_pci7x3x_pci_probe,
 272         .remove         = comedi_pci_auto_unconfig,
 273 };
 274 module_comedi_pci_driver(adl_pci7x3x_driver, adl_pci7x3x_pci_driver);
 275 
 276 MODULE_DESCRIPTION("ADLINK PCI-723x/743x Isolated Digital I/O boards");
 277 MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
 278 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */