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 #include <linux/types.h> 20 21 #define CIO_DAC_NUM_CHAN 16 22 23 #define CIO_DAC_CHAN(chan) { \ 24 .type = IIO_VOLTAGE, \ 25 .channel = chan, \ 26 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 27 .indexed = 1, \ 28 .output = 1 \ 29 } 30 31 #define CIO_DAC_EXTENT 32 32 33 static unsigned int base[max_num_isa_dev(CIO_DAC_EXTENT)]; 34 static unsigned int num_cio_dac; 35 module_param_hw_array(base, uint, ioport, &num_cio_dac, 0); 36 MODULE_PARM_DESC(base, "Measurement Computing CIO-DAC base addresses"); 37 38 /** 39 * struct cio_dac_iio - IIO device private data structure 40 * @chan_out_states: channels' output states 41 * @base: base memory address of the DAC device 42 */ 43 struct cio_dac_iio { 44 int chan_out_states[CIO_DAC_NUM_CHAN]; 45 u16 __iomem *base; 46 }; 47 48 static int cio_dac_read_raw(struct iio_dev *indio_dev, 49 struct iio_chan_spec const *chan, int *val, int *val2, long mask) 50 { 51 struct cio_dac_iio *const priv = iio_priv(indio_dev); 52 53 if (mask != IIO_CHAN_INFO_RAW) 54 return -EINVAL; 55 56 *val = priv->chan_out_states[chan->channel]; 57 58 return IIO_VAL_INT; 59 } 60 61 static int cio_dac_write_raw(struct iio_dev *indio_dev, 62 struct iio_chan_spec const *chan, int val, int val2, long mask) 63 { 64 struct cio_dac_iio *const priv = iio_priv(indio_dev); 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 iowrite16(val, priv->base + chan->channel); 75 76 return 0; 77 } 78 79 static const struct iio_info cio_dac_info = { 80 .read_raw = cio_dac_read_raw, 81 .write_raw = cio_dac_write_raw 82 }; 83 84 static 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 91 static 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 priv = iio_priv(indio_dev); 109 priv->base = devm_ioport_map(dev, base[id], CIO_DAC_EXTENT); 110 if (!priv->base) 111 return -ENOMEM; 112 113 indio_dev->info = &cio_dac_info; 114 indio_dev->modes = INDIO_DIRECT_MODE; 115 indio_dev->channels = cio_dac_channels; 116 indio_dev->num_channels = CIO_DAC_NUM_CHAN; 117 indio_dev->name = dev_name(dev); 118 119 /* initialize DAC outputs to 0V */ 120 for (i = 0; i < CIO_DAC_NUM_CHAN; i++) 121 iowrite16(0, priv->base + i); 122 123 return devm_iio_device_register(dev, indio_dev); 124 } 125 126 static struct isa_driver cio_dac_driver = { 127 .probe = cio_dac_probe, 128 .driver = { 129 .name = "cio-dac" 130 } 131 }; 132 133 module_isa_driver(cio_dac_driver, num_cio_dac); 134 135 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 136 MODULE_DESCRIPTION("Measurement Computing CIO-DAC IIO driver"); 137 MODULE_LICENSE("GPL v2"); 138