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