linux/drivers/comedi/drivers/amplc_dio200.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * comedi/drivers/amplc_dio200.c
   4 *
   5 * Driver for Amplicon PC212E, PC214E, PC215E, PC218E, PC272E.
   6 *
   7 * Copyright (C) 2005-2013 MEV Ltd. <https://www.mev.co.uk/>
   8 *
   9 * COMEDI - Linux Control and Measurement Device Interface
  10 * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
  11 */
  12
  13/*
  14 * Driver: amplc_dio200
  15 * Description: Amplicon 200 Series ISA Digital I/O
  16 * Author: Ian Abbott <abbotti@mev.co.uk>
  17 * Devices: [Amplicon] PC212E (pc212e), PC214E (pc214e), PC215E (pc215e),
  18 *   PC218E (pc218e), PC272E (pc272e)
  19 * Updated: Mon, 18 Mar 2013 14:40:41 +0000
  20 *
  21 * Status: works
  22 *
  23 * Configuration options:
  24 *   [0] - I/O port base address
  25 *   [1] - IRQ (optional, but commands won't work without it)
  26 *
  27 * Passing a zero for an option is the same as leaving it unspecified.
  28 *
  29 * SUBDEVICES
  30 *
  31 *                     PC212E         PC214E         PC215E
  32 *                  -------------  -------------  -------------
  33 *   Subdevices           6              4              5
  34 *    0                 PPI-X          PPI-X          PPI-X
  35 *    1                 CTR-Y1         PPI-Y          PPI-Y
  36 *    2                 CTR-Y2         CTR-Z1*        CTR-Z1
  37 *    3                 CTR-Z1       INTERRUPT*       CTR-Z2
  38 *    4                 CTR-Z2                      INTERRUPT
  39 *    5               INTERRUPT
  40 *
  41 *                     PC218E         PC272E
  42 *                  -------------  -------------
  43 *   Subdevices           7              4
  44 *    0                 CTR-X1         PPI-X
  45 *    1                 CTR-X2         PPI-Y
  46 *    2                 CTR-Y1         PPI-Z
  47 *    3                 CTR-Y2       INTERRUPT
  48 *    4                 CTR-Z1
  49 *    5                 CTR-Z2
  50 *    6               INTERRUPT
  51 *
  52 * Each PPI is a 8255 chip providing 24 DIO channels.  The DIO channels
  53 * are configurable as inputs or outputs in four groups:
  54 *
  55 *   Port A  - channels  0 to  7
  56 *   Port B  - channels  8 to 15
  57 *   Port CL - channels 16 to 19
  58 *   Port CH - channels 20 to 23
  59 *
  60 * Only mode 0 of the 8255 chips is supported.
  61 *
  62 * Each CTR is a 8254 chip providing 3 16-bit counter channels.  Each
  63 * channel is configured individually with INSN_CONFIG instructions.  The
  64 * specific type of configuration instruction is specified in data[0].
  65 * Some configuration instructions expect an additional parameter in
  66 * data[1]; others return a value in data[1].  The following configuration
  67 * instructions are supported:
  68 *
  69 *   INSN_CONFIG_SET_COUNTER_MODE.  Sets the counter channel's mode and
  70 *     BCD/binary setting specified in data[1].
  71 *
  72 *   INSN_CONFIG_8254_READ_STATUS.  Reads the status register value for the
  73 *     counter channel into data[1].
  74 *
  75 *   INSN_CONFIG_SET_CLOCK_SRC.  Sets the counter channel's clock source as
  76 *     specified in data[1] (this is a hardware-specific value).  Not
  77 *     supported on PC214E.  For the other boards, valid clock sources are
  78 *     0 to 7 as follows:
  79 *
  80 *       0.  CLK n, the counter channel's dedicated CLK input from the SK1
  81 *         connector.  (N.B. for other values, the counter channel's CLKn
  82 *         pin on the SK1 connector is an output!)
  83 *       1.  Internal 10 MHz clock.
  84 *       2.  Internal 1 MHz clock.
  85 *       3.  Internal 100 kHz clock.
  86 *       4.  Internal 10 kHz clock.
  87 *       5.  Internal 1 kHz clock.
  88 *       6.  OUT n-1, the output of counter channel n-1 (see note 1 below).
  89 *       7.  Ext Clock, the counter chip's dedicated Ext Clock input from
  90 *         the SK1 connector.  This pin is shared by all three counter
  91 *         channels on the chip.
  92 *
  93 *   INSN_CONFIG_GET_CLOCK_SRC.  Returns the counter channel's current
  94 *     clock source in data[1].  For internal clock sources, data[2] is set
  95 *     to the period in ns.
  96 *
  97 *   INSN_CONFIG_SET_GATE_SRC.  Sets the counter channel's gate source as
  98 *     specified in data[2] (this is a hardware-specific value).  Not
  99 *     supported on PC214E.  For the other boards, valid gate sources are 0
 100 *     to 7 as follows:
 101 *
 102 *       0.  VCC (internal +5V d.c.), i.e. gate permanently enabled.
 103 *       1.  GND (internal 0V d.c.), i.e. gate permanently disabled.
 104 *       2.  GAT n, the counter channel's dedicated GAT input from the SK1
 105 *         connector.  (N.B. for other values, the counter channel's GATn
 106 *         pin on the SK1 connector is an output!)
 107 *       3.  /OUT n-2, the inverted output of counter channel n-2 (see note
 108 *         2 below).
 109 *       4.  Reserved.
 110 *       5.  Reserved.
 111 *       6.  Reserved.
 112 *       7.  Reserved.
 113 *
 114 *   INSN_CONFIG_GET_GATE_SRC.  Returns the counter channel's current gate
 115 *     source in data[2].
 116 *
 117 * Clock and gate interconnection notes:
 118 *
 119 *   1.  Clock source OUT n-1 is the output of the preceding channel on the
 120 *   same counter subdevice if n > 0, or the output of channel 2 on the
 121 *   preceding counter subdevice (see note 3) if n = 0.
 122 *
 123 *   2.  Gate source /OUT n-2 is the inverted output of channel 0 on the
 124 *   same counter subdevice if n = 2, or the inverted output of channel n+1
 125 *   on the preceding counter subdevice (see note 3) if n < 2.
 126 *
 127 *   3.  The counter subdevices are connected in a ring, so the highest
 128 *   counter subdevice precedes the lowest.
 129 *
 130 * The 'INTERRUPT' subdevice pretends to be a digital input subdevice.  The
 131 * digital inputs come from the interrupt status register.  The number of
 132 * channels matches the number of interrupt sources.  The PC214E does not
 133 * have an interrupt status register; see notes on 'INTERRUPT SOURCES'
 134 * below.
 135 *
 136 * INTERRUPT SOURCES
 137 *
 138 *                     PC212E         PC214E         PC215E
 139 *                  -------------  -------------  -------------
 140 *   Sources              6              1              6
 141 *    0               PPI-X-C0       JUMPER-J5      PPI-X-C0
 142 *    1               PPI-X-C3                      PPI-X-C3
 143 *    2              CTR-Y1-OUT1                    PPI-Y-C0
 144 *    3              CTR-Y2-OUT1                    PPI-Y-C3
 145 *    4              CTR-Z1-OUT1                   CTR-Z1-OUT1
 146 *    5              CTR-Z2-OUT1                   CTR-Z2-OUT1
 147 *
 148 *                     PC218E         PC272E
 149 *                  -------------  -------------
 150 *   Sources              6              6
 151 *    0              CTR-X1-OUT1     PPI-X-C0
 152 *    1              CTR-X2-OUT1     PPI-X-C3
 153 *    2              CTR-Y1-OUT1     PPI-Y-C0
 154 *    3              CTR-Y2-OUT1     PPI-Y-C3
 155 *    4              CTR-Z1-OUT1     PPI-Z-C0
 156 *    5              CTR-Z2-OUT1     PPI-Z-C3
 157 *
 158 * When an interrupt source is enabled in the interrupt source enable
 159 * register, a rising edge on the source signal latches the corresponding
 160 * bit to 1 in the interrupt status register.
 161 *
 162 * When the interrupt status register value as a whole (actually, just the
 163 * 6 least significant bits) goes from zero to non-zero, the board will
 164 * generate an interrupt.  No further interrupts will occur until the
 165 * interrupt status register is cleared to zero.  To clear a bit to zero in
 166 * the interrupt status register, the corresponding interrupt source must
 167 * be disabled in the interrupt source enable register (there is no
 168 * separate interrupt clear register).
 169 *
 170 * The PC214E does not have an interrupt source enable register or an
 171 * interrupt status register; its 'INTERRUPT' subdevice has a single
 172 * channel and its interrupt source is selected by the position of jumper
 173 * J5.
 174 *
 175 * COMMANDS
 176 *
 177 * The driver supports a read streaming acquisition command on the
 178 * 'INTERRUPT' subdevice.  The channel list selects the interrupt sources
 179 * to be enabled.  All channels will be sampled together (convert_src ==
 180 * TRIG_NOW).  The scan begins a short time after the hardware interrupt
 181 * occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT,
 182 * scan_begin_arg == 0).  The value read from the interrupt status register
 183 * is packed into a short value, one bit per requested channel, in the
 184 * order they appear in the channel list.
 185 */
 186
 187#include <linux/module.h>
 188#include "../comedidev.h"
 189
 190#include "amplc_dio200.h"
 191
 192/*
 193 * Board descriptions.
 194 */
 195static const struct dio200_board dio200_isa_boards[] = {
 196        {
 197                .name           = "pc212e",
 198                .n_subdevs      = 6,
 199                .sdtype         = {
 200                        sd_8255, sd_8254, sd_8254, sd_8254, sd_8254, sd_intr
 201                },
 202                .sdinfo         = { 0x00, 0x08, 0x0c, 0x10, 0x14, 0x3f },
 203                .has_int_sce    = true,
 204                .has_clk_gat_sce = true,
 205        }, {
 206                .name           = "pc214e",
 207                .n_subdevs      = 4,
 208                .sdtype         = {
 209                        sd_8255, sd_8255, sd_8254, sd_intr
 210                },
 211                .sdinfo         = { 0x00, 0x08, 0x10, 0x01 },
 212        }, {
 213                .name           = "pc215e",
 214                .n_subdevs      = 5,
 215                .sdtype         = {
 216                        sd_8255, sd_8255, sd_8254, sd_8254, sd_intr
 217                },
 218                .sdinfo         = { 0x00, 0x08, 0x10, 0x14, 0x3f },
 219                .has_int_sce    = true,
 220                .has_clk_gat_sce = true,
 221        }, {
 222                .name           = "pc218e",
 223                .n_subdevs      = 7,
 224                .sdtype         = {
 225                        sd_8254, sd_8254, sd_8255, sd_8254, sd_8254, sd_intr
 226                },
 227                .sdinfo         = { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x3f },
 228                .has_int_sce    = true,
 229                .has_clk_gat_sce = true,
 230        }, {
 231                .name           = "pc272e",
 232                .n_subdevs      = 4,
 233                .sdtype         = {
 234                        sd_8255, sd_8255, sd_8255, sd_intr
 235                },
 236                .sdinfo         = { 0x00, 0x08, 0x10, 0x3f },
 237                .has_int_sce = true,
 238        },
 239};
 240
 241static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 242{
 243        int ret;
 244
 245        ret = comedi_request_region(dev, it->options[0], 0x20);
 246        if (ret)
 247                return ret;
 248
 249        return amplc_dio200_common_attach(dev, it->options[1], 0);
 250}
 251
 252static struct comedi_driver amplc_dio200_driver = {
 253        .driver_name    = "amplc_dio200",
 254        .module         = THIS_MODULE,
 255        .attach         = dio200_attach,
 256        .detach         = comedi_legacy_detach,
 257        .board_name     = &dio200_isa_boards[0].name,
 258        .offset         = sizeof(struct dio200_board),
 259        .num_names      = ARRAY_SIZE(dio200_isa_boards),
 260};
 261module_comedi_driver(amplc_dio200_driver);
 262
 263MODULE_AUTHOR("Comedi https://www.comedi.org");
 264MODULE_DESCRIPTION("Comedi driver for Amplicon 200 Series ISA DIO boards");
 265MODULE_LICENSE("GPL");
 266