^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * IIO driver for the Measurement Computing CIO-DAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2016 William Breathitt Gray
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This driver supports the following Measurement Computing devices: CIO-DAC16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * CIO-DAC06, and PC104-DAC06.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/iio/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/isa.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define CIO_DAC_NUM_CHAN 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define CIO_DAC_CHAN(chan) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) .type = IIO_VOLTAGE, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) .channel = chan, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) .indexed = 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) .output = 1 \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define CIO_DAC_EXTENT 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static unsigned int base[max_num_isa_dev(CIO_DAC_EXTENT)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static unsigned int num_cio_dac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) module_param_hw_array(base, uint, ioport, &num_cio_dac, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) MODULE_PARM_DESC(base, "Measurement Computing CIO-DAC base addresses");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * struct cio_dac_iio - IIO device private data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * @chan_out_states: channels' output states
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * @base: base port address of the IIO device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct cio_dac_iio {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) int chan_out_states[CIO_DAC_NUM_CHAN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned int base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static int cio_dac_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct iio_chan_spec const *chan, int *val, int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct cio_dac_iio *const priv = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (mask != IIO_CHAN_INFO_RAW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *val = priv->chan_out_states[chan->channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static int cio_dac_write_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct iio_chan_spec const *chan, int val, int val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct cio_dac_iio *const priv = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) const unsigned int chan_addr_offset = 2 * chan->channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (mask != IIO_CHAN_INFO_RAW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* DAC can only accept up to a 16-bit value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if ((unsigned int)val > 65535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) priv->chan_out_states[chan->channel] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) outw(val, priv->base + chan_addr_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static const struct iio_info cio_dac_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .read_raw = cio_dac_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .write_raw = cio_dac_write_raw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static const struct iio_chan_spec cio_dac_channels[CIO_DAC_NUM_CHAN] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) CIO_DAC_CHAN(0), CIO_DAC_CHAN(1), CIO_DAC_CHAN(2), CIO_DAC_CHAN(3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) CIO_DAC_CHAN(4), CIO_DAC_CHAN(5), CIO_DAC_CHAN(6), CIO_DAC_CHAN(7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) CIO_DAC_CHAN(8), CIO_DAC_CHAN(9), CIO_DAC_CHAN(10), CIO_DAC_CHAN(11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) CIO_DAC_CHAN(12), CIO_DAC_CHAN(13), CIO_DAC_CHAN(14), CIO_DAC_CHAN(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int cio_dac_probe(struct device *dev, unsigned int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct cio_dac_iio *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (!indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (!devm_request_region(dev, base[id], CIO_DAC_EXTENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) dev_name(dev))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dev_err(dev, "Unable to request port addresses (0x%X-0x%X)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) base[id], base[id] + CIO_DAC_EXTENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) indio_dev->info = &cio_dac_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) indio_dev->modes = INDIO_DIRECT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) indio_dev->channels = cio_dac_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) indio_dev->num_channels = CIO_DAC_NUM_CHAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) indio_dev->name = dev_name(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) priv = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) priv->base = base[id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* initialize DAC outputs to 0V */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) for (i = 0; i < 32; i += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) outw(0, base[id] + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return devm_iio_device_register(dev, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static struct isa_driver cio_dac_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .probe = cio_dac_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .name = "cio-dac"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) module_isa_driver(cio_dac_driver, num_cio_dac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) MODULE_DESCRIPTION("Measurement Computing CIO-DAC IIO driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) MODULE_LICENSE("GPL v2");