diff options
Diffstat (limited to 'drivers/staging/comedi/drivers/ni_6527.c')
-rw-r--r-- | drivers/staging/comedi/drivers/ni_6527.c | 493 |
1 files changed, 0 insertions, 493 deletions
diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c deleted file mode 100644 index f1a45cf7342a..000000000000 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ /dev/null @@ -1,493 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * ni_6527.c - * Comedi driver for National Instruments PCI-6527 - * - * COMEDI - Linux Control and Measurement Device Interface - * Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.org> - */ - -/* - * Driver: ni_6527 - * Description: National Instruments 6527 - * Devices: [National Instruments] PCI-6527 (pci-6527), PXI-6527 (pxi-6527) - * Author: David A. Schleef <ds@schleef.org> - * Updated: Sat, 25 Jan 2003 13:24:40 -0800 - * Status: works - * - * Configuration Options: not applicable, uses PCI auto config - */ - -#include <linux/module.h> -#include <linux/interrupt.h> - -#include "../comedi_pci.h" - -/* - * PCI BAR1 - Register memory map - * - * Manuals (available from ftp://ftp.natinst.com/support/manuals) - * 370106b.pdf 6527 Register Level Programmer Manual - */ -#define NI6527_DI_REG(x) (0x00 + (x)) -#define NI6527_DO_REG(x) (0x03 + (x)) -#define NI6527_ID_REG 0x06 -#define NI6527_CLR_REG 0x07 -#define NI6527_CLR_EDGE BIT(3) -#define NI6527_CLR_OVERFLOW BIT(2) -#define NI6527_CLR_FILT BIT(1) -#define NI6527_CLR_INTERVAL BIT(0) -#define NI6527_CLR_IRQS (NI6527_CLR_EDGE | NI6527_CLR_OVERFLOW) -#define NI6527_CLR_RESET_FILT (NI6527_CLR_FILT | NI6527_CLR_INTERVAL) -#define NI6527_FILT_INTERVAL_REG(x) (0x08 + (x)) -#define NI6527_FILT_ENA_REG(x) (0x0c + (x)) -#define NI6527_STATUS_REG 0x14 -#define NI6527_STATUS_IRQ BIT(2) -#define NI6527_STATUS_OVERFLOW BIT(1) -#define NI6527_STATUS_EDGE BIT(0) -#define NI6527_CTRL_REG 0x15 -#define NI6527_CTRL_FALLING BIT(4) -#define NI6527_CTRL_RISING BIT(3) -#define NI6527_CTRL_IRQ BIT(2) -#define NI6527_CTRL_OVERFLOW BIT(1) -#define NI6527_CTRL_EDGE BIT(0) -#define NI6527_CTRL_DISABLE_IRQS 0 -#define NI6527_CTRL_ENABLE_IRQS (NI6527_CTRL_FALLING | \ - NI6527_CTRL_RISING | \ - NI6527_CTRL_IRQ | NI6527_CTRL_EDGE) -#define NI6527_RISING_EDGE_REG(x) (0x18 + (x)) -#define NI6527_FALLING_EDGE_REG(x) (0x20 + (x)) - -enum ni6527_boardid { - BOARD_PCI6527, - BOARD_PXI6527, -}; - -struct ni6527_board { - const char *name; -}; - -static const struct ni6527_board ni6527_boards[] = { - [BOARD_PCI6527] = { - .name = "pci-6527", - }, - [BOARD_PXI6527] = { - .name = "pxi-6527", - }, -}; - -struct ni6527_private { - unsigned int filter_interval; - unsigned int filter_enable; -}; - -static void ni6527_set_filter_interval(struct comedi_device *dev, - unsigned int val) -{ - struct ni6527_private *devpriv = dev->private; - - if (val != devpriv->filter_interval) { - writeb(val & 0xff, dev->mmio + NI6527_FILT_INTERVAL_REG(0)); - writeb((val >> 8) & 0xff, - dev->mmio + NI6527_FILT_INTERVAL_REG(1)); - writeb((val >> 16) & 0x0f, - dev->mmio + NI6527_FILT_INTERVAL_REG(2)); - - writeb(NI6527_CLR_INTERVAL, dev->mmio + NI6527_CLR_REG); - - devpriv->filter_interval = val; - } -} - -static void ni6527_set_filter_enable(struct comedi_device *dev, - unsigned int val) -{ - writeb(val & 0xff, dev->mmio + NI6527_FILT_ENA_REG(0)); - writeb((val >> 8) & 0xff, dev->mmio + NI6527_FILT_ENA_REG(1)); - writeb((val >> 16) & 0xff, dev->mmio + NI6527_FILT_ENA_REG(2)); -} - -static int ni6527_di_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct ni6527_private *devpriv = dev->private; - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int interval; - - switch (data[0]) { - case INSN_CONFIG_FILTER: - /* - * The deglitch filter interval is specified in nanoseconds. - * The hardware supports intervals in 200ns increments. Round - * the user values up and return the actual interval. - */ - interval = (data[1] + 100) / 200; - data[1] = interval * 200; - - if (interval) { - ni6527_set_filter_interval(dev, interval); - devpriv->filter_enable |= 1 << chan; - } else { - devpriv->filter_enable &= ~(1 << chan); - } - ni6527_set_filter_enable(dev, devpriv->filter_enable); - break; - default: - return -EINVAL; - } - - return insn->n; -} - -static int ni6527_di_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned int val; - - val = readb(dev->mmio + NI6527_DI_REG(0)); - val |= (readb(dev->mmio + NI6527_DI_REG(1)) << 8); - val |= (readb(dev->mmio + NI6527_DI_REG(2)) << 16); - - data[1] = val; - - return insn->n; -} - -static int ni6527_do_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned int mask; - - mask = comedi_dio_update_state(s, data); - if (mask) { - /* Outputs are inverted */ - unsigned int val = s->state ^ 0xffffff; - - if (mask & 0x0000ff) - writeb(val & 0xff, dev->mmio + NI6527_DO_REG(0)); - if (mask & 0x00ff00) - writeb((val >> 8) & 0xff, - dev->mmio + NI6527_DO_REG(1)); - if (mask & 0xff0000) - writeb((val >> 16) & 0xff, - dev->mmio + NI6527_DO_REG(2)); - } - - data[1] = s->state; - - return insn->n; -} - -static irqreturn_t ni6527_interrupt(int irq, void *d) -{ - struct comedi_device *dev = d; - struct comedi_subdevice *s = dev->read_subdev; - unsigned int status; - - status = readb(dev->mmio + NI6527_STATUS_REG); - if (!(status & NI6527_STATUS_IRQ)) - return IRQ_NONE; - - if (status & NI6527_STATUS_EDGE) { - unsigned short val = 0; - - comedi_buf_write_samples(s, &val, 1); - comedi_handle_events(dev, s); - } - - writeb(NI6527_CLR_IRQS, dev->mmio + NI6527_CLR_REG); - - return IRQ_HANDLED; -} - -static int ni6527_intr_cmdtest(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_cmd *cmd) -{ - int err = 0; - - /* Step 1 : check if triggers are trivially valid */ - - err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW); - err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_OTHER); - err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); - err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT); - - if (err) - return 1; - - /* Step 2a : make sure trigger sources are unique */ - /* Step 2b : and mutually compatible */ - - /* Step 3: check if arguments are trivially valid */ - - err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); - err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0); - err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, - cmd->chanlist_len); - err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); - - if (err) - return 3; - - /* Step 4: fix up any arguments */ - - /* Step 5: check channel list if it exists */ - - return 0; -} - -static int ni6527_intr_cmd(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - writeb(NI6527_CLR_IRQS, dev->mmio + NI6527_CLR_REG); - writeb(NI6527_CTRL_ENABLE_IRQS, dev->mmio + NI6527_CTRL_REG); - - return 0; -} - -static int ni6527_intr_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - writeb(NI6527_CTRL_DISABLE_IRQS, dev->mmio + NI6527_CTRL_REG); - - return 0; -} - -static int ni6527_intr_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - data[1] = 0; - return insn->n; -} - -static void ni6527_set_edge_detection(struct comedi_device *dev, - unsigned int mask, - unsigned int rising, - unsigned int falling) -{ - unsigned int i; - - rising &= mask; - falling &= mask; - for (i = 0; i < 2; i++) { - if (mask & 0xff) { - if (~mask & 0xff) { - /* preserve rising-edge detection channels */ - rising |= readb(dev->mmio + - NI6527_RISING_EDGE_REG(i)) & - (~mask & 0xff); - /* preserve falling-edge detection channels */ - falling |= readb(dev->mmio + - NI6527_FALLING_EDGE_REG(i)) & - (~mask & 0xff); - } - /* update rising-edge detection channels */ - writeb(rising & 0xff, - dev->mmio + NI6527_RISING_EDGE_REG(i)); - /* update falling-edge detection channels */ - writeb(falling & 0xff, - dev->mmio + NI6527_FALLING_EDGE_REG(i)); - } - rising >>= 8; - falling >>= 8; - mask >>= 8; - } -} - -static int ni6527_intr_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned int mask = 0xffffffff; - unsigned int rising, falling, shift; - - switch (data[0]) { - case INSN_CONFIG_CHANGE_NOTIFY: - /* check_insn_config_length() does not check this instruction */ - if (insn->n != 3) - return -EINVAL; - rising = data[1]; - falling = data[2]; - ni6527_set_edge_detection(dev, mask, rising, falling); - break; - case INSN_CONFIG_DIGITAL_TRIG: - /* check trigger number */ - if (data[1] != 0) - return -EINVAL; - /* check digital trigger operation */ - switch (data[2]) { - case COMEDI_DIGITAL_TRIG_DISABLE: - rising = 0; - falling = 0; - break; - case COMEDI_DIGITAL_TRIG_ENABLE_EDGES: - /* check shift amount */ - shift = data[3]; - if (shift >= 32) { - mask = 0; - rising = 0; - falling = 0; - } else { - mask <<= shift; - rising = data[4] << shift; - falling = data[5] << shift; - } - break; - default: - return -EINVAL; - } - ni6527_set_edge_detection(dev, mask, rising, falling); - break; - default: - return -EINVAL; - } - - return insn->n; -} - -static void ni6527_reset(struct comedi_device *dev) -{ - /* disable deglitch filters on all channels */ - ni6527_set_filter_enable(dev, 0); - - /* disable edge detection */ - ni6527_set_edge_detection(dev, 0xffffffff, 0, 0); - - writeb(NI6527_CLR_IRQS | NI6527_CLR_RESET_FILT, - dev->mmio + NI6527_CLR_REG); - writeb(NI6527_CTRL_DISABLE_IRQS, dev->mmio + NI6527_CTRL_REG); -} - -static int ni6527_auto_attach(struct comedi_device *dev, - unsigned long context) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct ni6527_board *board = NULL; - struct ni6527_private *devpriv; - struct comedi_subdevice *s; - int ret; - - if (context < ARRAY_SIZE(ni6527_boards)) - board = &ni6527_boards[context]; - if (!board) - return -ENODEV; - dev->board_ptr = board; - dev->board_name = board->name; - - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - - ret = comedi_pci_enable(dev); - if (ret) - return ret; - - dev->mmio = pci_ioremap_bar(pcidev, 1); - if (!dev->mmio) - return -ENOMEM; - - /* make sure this is actually a 6527 device */ - if (readb(dev->mmio + NI6527_ID_REG) != 0x27) - return -ENODEV; - - ni6527_reset(dev); - - ret = request_irq(pcidev->irq, ni6527_interrupt, IRQF_SHARED, - dev->board_name, dev); - if (ret == 0) - dev->irq = pcidev->irq; - - ret = comedi_alloc_subdevices(dev, 3); - if (ret) - return ret; - - /* Digital Input subdevice */ - s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 24; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_config = ni6527_di_insn_config; - s->insn_bits = ni6527_di_insn_bits; - - /* Digital Output subdevice */ - s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 24; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = ni6527_do_insn_bits; - - /* Edge detection interrupt subdevice */ - s = &dev->subdevices[2]; - if (dev->irq) { - dev->read_subdev = s; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE | SDF_CMD_READ; - s->n_chan = 1; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_config = ni6527_intr_insn_config; - s->insn_bits = ni6527_intr_insn_bits; - s->len_chanlist = 1; - s->do_cmdtest = ni6527_intr_cmdtest; - s->do_cmd = ni6527_intr_cmd; - s->cancel = ni6527_intr_cancel; - } else { - s->type = COMEDI_SUBD_UNUSED; - } - - return 0; -} - -static void ni6527_detach(struct comedi_device *dev) -{ - if (dev->mmio) - ni6527_reset(dev); - comedi_pci_detach(dev); -} - -static struct comedi_driver ni6527_driver = { - .driver_name = "ni_6527", - .module = THIS_MODULE, - .auto_attach = ni6527_auto_attach, - .detach = ni6527_detach, -}; - -static int ni6527_pci_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - return comedi_pci_auto_config(dev, &ni6527_driver, id->driver_data); -} - -static const struct pci_device_id ni6527_pci_table[] = { - { PCI_VDEVICE(NI, 0x2b10), BOARD_PXI6527 }, - { PCI_VDEVICE(NI, 0x2b20), BOARD_PCI6527 }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, ni6527_pci_table); - -static struct pci_driver ni6527_pci_driver = { - .name = "ni_6527", - .id_table = ni6527_pci_table, - .probe = ni6527_pci_probe, - .remove = comedi_pci_auto_unconfig, -}; -module_comedi_pci_driver(ni6527_driver, ni6527_pci_driver); - -MODULE_AUTHOR("Comedi https://www.comedi.org"); -MODULE_DESCRIPTION("Comedi driver for National Instruments PCI-6527"); -MODULE_LICENSE("GPL"); |