summaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorWilliam Breathitt Gray <vilhelm.gray@gmail.com>2016-08-29 16:22:56 -0400
committerJonathan Cameron <jic23@kernel.org>2016-09-03 12:25:53 -0400
commit4075a283ae83f49f923a2a92935aa72be2c1ca85 (patch)
treed020d085644592906aa40f609f3e150c15291dec /drivers/iio
parentc060991912f8e71f6214204a2019ceceb315c17b (diff)
iio: stx104: Add IIO support for the ADC channels
The Apex Embedded Systems STX104 features 16 channels of single-ended (8 channels of true differential) 16-bit analog input. Differential input configuration may be selected via a physical jumper on the device. Similarly, input polarity (unipolar/bipolar) is configured via a physical jumper on the device. Input gain selection is available to the user via software, thus allowing eight possible input ranges: +-10V, +-5V, +-2.5V, +-1.25V, 0 to 10V, 0 to 5V, 0 to 2.5V, and 0 to 1.25V. Four input gain configurations are supported: x1, x2, x4, and x8. This ADC resolution is 16-bits (1/65536 of full scale). Analog input samples are taken on software trigger; neither FIFO sampling nor interrupt triggering is supported by this driver. The Apex Embedded Systems STX104 is primarily an analog-to-digital converter device. The STX104 IIO driver was initially placed in the DAC directory because only the DAC portion of the STX104 was supported at the time. Now that ADC support has been added to the STX104 IIO driver, the driver should be moved to the more appropriate ADC directory. Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/adc/Kconfig15
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/stx104.c (renamed from drivers/iio/dac/stx104.c)153
-rw-r--r--drivers/iio/dac/Kconfig10
-rw-r--r--drivers/iio/dac/Makefile1
5 files changed, 145 insertions, 35 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 9f8e3813930e..ee7ab81e4cef 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -418,6 +418,21 @@ config ROCKCHIP_SARADC
418 To compile this driver as a module, choose M here: the 418 To compile this driver as a module, choose M here: the
419 module will be called rockchip_saradc. 419 module will be called rockchip_saradc.
420 420
421config STX104
422 tristate "Apex Embedded Systems STX104 driver"
423 depends on X86 && ISA_BUS_API
424 select GPIOLIB
425 help
426 Say yes here to build support for the Apex Embedded Systems STX104
427 integrated analog PC/104 card.
428
429 This driver supports the 16 channels of single-ended (8 channels of
430 differential) analog inputs, 2 channels of analog output, 4 digital
431 inputs, and 4 digital outputs provided by the STX104.
432
433 The base port addresses for the devices may be configured via the base
434 array module parameter.
435
421config TI_ADC081C 436config TI_ADC081C
422 tristate "Texas Instruments ADC081C/ADC101C/ADC121C family" 437 tristate "Texas Instruments ADC081C/ADC101C/ADC121C family"
423 depends on I2C 438 depends on I2C
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index d1a20b658c9a..7a40c04c311f 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
40obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o 40obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
41obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o 41obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
42obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o 42obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
43obj-$(CONFIG_STX104) += stx104.o
43obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o 44obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
44obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o 45obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
45obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o 46obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o
diff --git a/drivers/iio/dac/stx104.c b/drivers/iio/adc/stx104.c
index 792a97164cb2..7ca12d58e750 100644
--- a/drivers/iio/dac/stx104.c
+++ b/drivers/iio/adc/stx104.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * DAC driver for the Apex Embedded Systems STX104 2 * IIO driver for the Apex Embedded Systems STX104
3 * Copyright (C) 2016 William Breathitt Gray 3 * Copyright (C) 2016 William Breathitt Gray
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
@@ -20,19 +20,30 @@
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/ioport.h> 21#include <linux/ioport.h>
22#include <linux/isa.h> 22#include <linux/isa.h>
23#include <linux/kernel.h>
23#include <linux/module.h> 24#include <linux/module.h>
24#include <linux/moduleparam.h> 25#include <linux/moduleparam.h>
25#include <linux/spinlock.h> 26#include <linux/spinlock.h>
26 27
27#define STX104_NUM_CHAN 2 28#define STX104_OUT_CHAN(chan) { \
28
29#define STX104_CHAN(chan) { \
30 .type = IIO_VOLTAGE, \ 29 .type = IIO_VOLTAGE, \
31 .channel = chan, \ 30 .channel = chan, \
32 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 31 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
33 .indexed = 1, \ 32 .indexed = 1, \
34 .output = 1 \ 33 .output = 1 \
35} 34}
35#define STX104_IN_CHAN(chan, diff) { \
36 .type = IIO_VOLTAGE, \
37 .channel = chan, \
38 .channel2 = chan, \
39 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_HARDWAREGAIN) | \
40 BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), \
41 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
42 .indexed = 1, \
43 .differential = diff \
44}
45
46#define STX104_NUM_OUT_CHAN 2
36 47
37#define STX104_EXTENT 16 48#define STX104_EXTENT 16
38 49
@@ -47,8 +58,8 @@ MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
47 * @base: base port address of the IIO device 58 * @base: base port address of the IIO device
48 */ 59 */
49struct stx104_iio { 60struct stx104_iio {
50 unsigned chan_out_states[STX104_NUM_CHAN]; 61 unsigned int chan_out_states[STX104_NUM_OUT_CHAN];
51 unsigned base; 62 unsigned int base;
52}; 63};
53 64
54/** 65/**
@@ -69,28 +80,95 @@ static int stx104_read_raw(struct iio_dev *indio_dev,
69 struct iio_chan_spec const *chan, int *val, int *val2, long mask) 80 struct iio_chan_spec const *chan, int *val, int *val2, long mask)
70{ 81{
71 struct stx104_iio *const priv = iio_priv(indio_dev); 82 struct stx104_iio *const priv = iio_priv(indio_dev);
83 unsigned int adc_config;
84 int adbu;
85 int gain;
86
87 switch (mask) {
88 case IIO_CHAN_INFO_HARDWAREGAIN:
89 /* get gain configuration */
90 adc_config = inb(priv->base + 11);
91 gain = adc_config & 0x3;
92
93 *val = 1 << gain;
94 return IIO_VAL_INT;
95 case IIO_CHAN_INFO_RAW:
96 if (chan->output) {
97 *val = priv->chan_out_states[chan->channel];
98 return IIO_VAL_INT;
99 }
100
101 /* select ADC channel */
102 outb(chan->channel | (chan->channel << 4), priv->base + 2);
103
104 /* trigger ADC sample capture and wait for completion */
105 outb(0, priv->base);
106 while (inb(priv->base + 8) & BIT(7));
107
108 *val = inw(priv->base);
109 return IIO_VAL_INT;
110 case IIO_CHAN_INFO_OFFSET:
111 /* get ADC bipolar/unipolar configuration */
112 adc_config = inb(priv->base + 11);
113 adbu = !(adc_config & BIT(2));
114
115 *val = -32768 * adbu;
116 return IIO_VAL_INT;
117 case IIO_CHAN_INFO_SCALE:
118 /* get ADC bipolar/unipolar and gain configuration */
119 adc_config = inb(priv->base + 11);
120 adbu = !(adc_config & BIT(2));
121 gain = adc_config & 0x3;
122
123 *val = 5;
124 *val2 = 15 - adbu + gain;
125 return IIO_VAL_FRACTIONAL_LOG2;
126 }
72 127
73 if (mask != IIO_CHAN_INFO_RAW) 128 return -EINVAL;
74 return -EINVAL;
75
76 *val = priv->chan_out_states[chan->channel];
77
78 return IIO_VAL_INT;
79} 129}
80 130
81static int stx104_write_raw(struct iio_dev *indio_dev, 131static int stx104_write_raw(struct iio_dev *indio_dev,
82 struct iio_chan_spec const *chan, int val, int val2, long mask) 132 struct iio_chan_spec const *chan, int val, int val2, long mask)
83{ 133{
84 struct stx104_iio *const priv = iio_priv(indio_dev); 134 struct stx104_iio *const priv = iio_priv(indio_dev);
85 const unsigned chan_addr_offset = 2 * chan->channel;
86 135
87 if (mask != IIO_CHAN_INFO_RAW) 136 switch (mask) {
137 case IIO_CHAN_INFO_HARDWAREGAIN:
138 /* Only four gain states (x1, x2, x4, x8) */
139 switch (val) {
140 case 1:
141 outb(0, priv->base + 11);
142 break;
143 case 2:
144 outb(1, priv->base + 11);
145 break;
146 case 4:
147 outb(2, priv->base + 11);
148 break;
149 case 8:
150 outb(3, priv->base + 11);
151 break;
152 default:
153 return -EINVAL;
154 }
155
156 return 0;
157 case IIO_CHAN_INFO_RAW:
158 if (chan->output) {
159 /* DAC can only accept up to a 16-bit value */
160 if ((unsigned int)val > 65535)
161 return -EINVAL;
162
163 priv->chan_out_states[chan->channel] = val;
164 outw(val, priv->base + 4 + 2 * chan->channel);
165
166 return 0;
167 }
88 return -EINVAL; 168 return -EINVAL;
169 }
89 170
90 priv->chan_out_states[chan->channel] = val; 171 return -EINVAL;
91 outw(val, priv->base + 4 + chan_addr_offset);
92
93 return 0;
94} 172}
95 173
96static const struct iio_info stx104_info = { 174static const struct iio_info stx104_info = {
@@ -99,9 +177,22 @@ static const struct iio_info stx104_info = {
99 .write_raw = stx104_write_raw 177 .write_raw = stx104_write_raw
100}; 178};
101 179
102static const struct iio_chan_spec stx104_channels[STX104_NUM_CHAN] = { 180/* single-ended input channels configuration */
103 STX104_CHAN(0), 181static const struct iio_chan_spec stx104_channels_sing[] = {
104 STX104_CHAN(1) 182 STX104_OUT_CHAN(0), STX104_OUT_CHAN(1),
183 STX104_IN_CHAN(0, 0), STX104_IN_CHAN(1, 0), STX104_IN_CHAN(2, 0),
184 STX104_IN_CHAN(3, 0), STX104_IN_CHAN(4, 0), STX104_IN_CHAN(5, 0),
185 STX104_IN_CHAN(6, 0), STX104_IN_CHAN(7, 0), STX104_IN_CHAN(8, 0),
186 STX104_IN_CHAN(9, 0), STX104_IN_CHAN(10, 0), STX104_IN_CHAN(11, 0),
187 STX104_IN_CHAN(12, 0), STX104_IN_CHAN(13, 0), STX104_IN_CHAN(14, 0),
188 STX104_IN_CHAN(15, 0)
189};
190/* differential input channels configuration */
191static const struct iio_chan_spec stx104_channels_diff[] = {
192 STX104_OUT_CHAN(0), STX104_OUT_CHAN(1),
193 STX104_IN_CHAN(0, 1), STX104_IN_CHAN(1, 1), STX104_IN_CHAN(2, 1),
194 STX104_IN_CHAN(3, 1), STX104_IN_CHAN(4, 1), STX104_IN_CHAN(5, 1),
195 STX104_IN_CHAN(6, 1), STX104_IN_CHAN(7, 1)
105}; 196};
106 197
107static int stx104_gpio_get_direction(struct gpio_chip *chip, 198static int stx104_gpio_get_direction(struct gpio_chip *chip,
@@ -188,13 +279,27 @@ static int stx104_probe(struct device *dev, unsigned int id)
188 279
189 indio_dev->info = &stx104_info; 280 indio_dev->info = &stx104_info;
190 indio_dev->modes = INDIO_DIRECT_MODE; 281 indio_dev->modes = INDIO_DIRECT_MODE;
191 indio_dev->channels = stx104_channels; 282
192 indio_dev->num_channels = STX104_NUM_CHAN; 283 /* determine if differential inputs */
284 if (inb(base[id] + 8) & BIT(5)) {
285 indio_dev->num_channels = ARRAY_SIZE(stx104_channels_diff);
286 indio_dev->channels = stx104_channels_diff;
287 } else {
288 indio_dev->num_channels = ARRAY_SIZE(stx104_channels_sing);
289 indio_dev->channels = stx104_channels_sing;
290 }
291
193 indio_dev->name = dev_name(dev); 292 indio_dev->name = dev_name(dev);
194 293
195 priv = iio_priv(indio_dev); 294 priv = iio_priv(indio_dev);
196 priv->base = base[id]; 295 priv->base = base[id];
197 296
297 /* configure device for software trigger operation */
298 outb(0, base[id] + 9);
299
300 /* initialize gain setting to x1 */
301 outb(0, base[id] + 11);
302
198 /* initialize DAC output to 0V */ 303 /* initialize DAC output to 0V */
199 outw(0, base[id] + 4); 304 outw(0, base[id] + 4);
200 outw(0, base[id] + 6); 305 outw(0, base[id] + 6);
@@ -251,5 +356,5 @@ static struct isa_driver stx104_driver = {
251module_isa_driver(stx104_driver, num_stx104); 356module_isa_driver(stx104_driver, num_stx104);
252 357
253MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 358MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
254MODULE_DESCRIPTION("Apex Embedded Systems STX104 DAC driver"); 359MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver");
255MODULE_LICENSE("GPL v2"); 360MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index e8656ba9bbb8..120b24478469 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -264,16 +264,6 @@ config MCP4922
264 To compile this driver as a module, choose M here: the module 264 To compile this driver as a module, choose M here: the module
265 will be called mcp4922. 265 will be called mcp4922.
266 266
267config STX104
268 tristate "Apex Embedded Systems STX104 DAC driver"
269 depends on X86 && ISA_BUS_API
270 select GPIOLIB
271 help
272 Say yes here to build support for the 2-channel DAC and GPIO on the
273 Apex Embedded Systems STX104 integrated analog PC/104 card. The base
274 port addresses for the devices may be configured via the base array
275 module parameter.
276
277config VF610_DAC 267config VF610_DAC
278 tristate "Vybrid vf610 DAC driver" 268 tristate "Vybrid vf610 DAC driver"
279 depends on OF 269 depends on OF
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index c50dbe082a70..27642bbf75f2 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -28,5 +28,4 @@ obj-$(CONFIG_MAX517) += max517.o
28obj-$(CONFIG_MAX5821) += max5821.o 28obj-$(CONFIG_MAX5821) += max5821.o
29obj-$(CONFIG_MCP4725) += mcp4725.o 29obj-$(CONFIG_MCP4725) += mcp4725.o
30obj-$(CONFIG_MCP4922) += mcp4922.o 30obj-$(CONFIG_MCP4922) += mcp4922.o
31obj-$(CONFIG_STX104) += stx104.o
32obj-$(CONFIG_VF610_DAC) += vf610_dac.o 31obj-$(CONFIG_VF610_DAC) += vf610_dac.o