On 29/08/16 21:22, William Breathitt Gray wrote: > 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@xxxxxxxxx> Very nice. Applied to the togreg branch of iio.git - initially pushed out as testing for the autobuilders to play with it. Thanks, Jonathan > --- > Changes in v6: > - Use switch-case to branch logic for read_raw/write_raw mask evaluation; this > should make it clearer when evaluating the various possible code paths > - IIO_CHAN_INFO_HARDWAREGAIN is used to expose the device gain setting > - Raw analog input value is returned by IIO_CHAN_INFO_RAW; constants and > values should be exposed to userspace for processing rather than doing all > the math within the driver, so IIO_CHAN_INFO_OFFSET and IIO_CHAN_INFO_SCALE > now expose the relevant offset and scale values necessary for processing > > MAINTAINERS | 4 +- > drivers/iio/adc/Kconfig | 15 ++++ > drivers/iio/adc/Makefile | 1 + > drivers/iio/{dac => adc}/stx104.c | 153 ++++++++++++++++++++++++++++++++------ > drivers/iio/dac/Kconfig | 10 --- > drivers/iio/dac/Makefile | 1 - > 6 files changed, 147 insertions(+), 37 deletions(-) > rename drivers/iio/{dac => adc}/stx104.c (60%) > > diff --git a/MAINTAINERS b/MAINTAINERS > index ae09eb4..6f0ff72 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -809,11 +809,11 @@ L: alsa-devel@xxxxxxxxxxxxxxxx (moderated for non-subscribers) > S: Maintained > F: sound/aoa/ > > -APEX EMBEDDED SYSTEMS STX104 DAC DRIVER > +APEX EMBEDDED SYSTEMS STX104 IIO DRIVER > M: William Breathitt Gray <vilhelm.gray@xxxxxxxxx> > L: linux-iio@xxxxxxxxxxxxxxx > S: Maintained > -F: drivers/iio/dac/stx104.c > +F: drivers/iio/adc/stx104.c > > APM DRIVER > M: Jiri Kosina <jikos@xxxxxxxxxx> > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig > index e4022fd..36695e8 100644 > --- a/drivers/iio/adc/Kconfig > +++ b/drivers/iio/adc/Kconfig > @@ -409,6 +409,21 @@ config ROCKCHIP_SARADC > To compile this driver as a module, choose M here: the > module will be called rockchip_saradc. > > +config STX104 > + tristate "Apex Embedded Systems STX104 driver" > + depends on X86 && ISA_BUS_API > + select GPIOLIB > + help > + Say yes here to build support for the Apex Embedded Systems STX104 > + integrated analog PC/104 card. > + > + This driver supports the 16 channels of single-ended (8 channels of > + differential) analog inputs, 2 channels of analog output, 4 digital > + inputs, and 4 digital outputs provided by the STX104. > + > + The base port addresses for the devices may be configured via the base > + array module parameter. > + > config TI_ADC081C > tristate "Texas Instruments ADC081C/ADC101C/ADC121C family" > depends on I2C > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile > index 33254eb..bdd69d6 100644 > --- a/drivers/iio/adc/Makefile > +++ b/drivers/iio/adc/Makefile > @@ -39,6 +39,7 @@ obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o > obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o > obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o > obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o > +obj-$(CONFIG_STX104) += stx104.o > obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o > obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o > obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o > diff --git a/drivers/iio/dac/stx104.c b/drivers/iio/adc/stx104.c > similarity index 60% > rename from drivers/iio/dac/stx104.c > rename to drivers/iio/adc/stx104.c > index 792a971..7ca12d5 100644 > --- a/drivers/iio/dac/stx104.c > +++ b/drivers/iio/adc/stx104.c > @@ -1,5 +1,5 @@ > /* > - * DAC driver for the Apex Embedded Systems STX104 > + * IIO driver for the Apex Embedded Systems STX104 > * Copyright (C) 2016 William Breathitt Gray > * > * This program is free software; you can redistribute it and/or modify > @@ -20,19 +20,30 @@ > #include <linux/io.h> > #include <linux/ioport.h> > #include <linux/isa.h> > +#include <linux/kernel.h> > #include <linux/module.h> > #include <linux/moduleparam.h> > #include <linux/spinlock.h> > > -#define STX104_NUM_CHAN 2 > - > -#define STX104_CHAN(chan) { \ > +#define STX104_OUT_CHAN(chan) { \ > .type = IIO_VOLTAGE, \ > .channel = chan, \ > .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ > .indexed = 1, \ > .output = 1 \ > } > +#define STX104_IN_CHAN(chan, diff) { \ > + .type = IIO_VOLTAGE, \ > + .channel = chan, \ > + .channel2 = chan, \ > + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_HARDWAREGAIN) | \ > + BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), \ > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ > + .indexed = 1, \ > + .differential = diff \ > +} > + > +#define STX104_NUM_OUT_CHAN 2 > > #define STX104_EXTENT 16 > > @@ -47,8 +58,8 @@ MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses"); > * @base: base port address of the IIO device > */ > struct stx104_iio { > - unsigned chan_out_states[STX104_NUM_CHAN]; > - unsigned base; > + unsigned int chan_out_states[STX104_NUM_OUT_CHAN]; > + unsigned int base; > }; > > /** > @@ -69,28 +80,95 @@ static int stx104_read_raw(struct iio_dev *indio_dev, > struct iio_chan_spec const *chan, int *val, int *val2, long mask) > { > struct stx104_iio *const priv = iio_priv(indio_dev); > + unsigned int adc_config; > + int adbu; > + int gain; > + > + switch (mask) { > + case IIO_CHAN_INFO_HARDWAREGAIN: > + /* get gain configuration */ > + adc_config = inb(priv->base + 11); > + gain = adc_config & 0x3; > + > + *val = 1 << gain; > + return IIO_VAL_INT; > + case IIO_CHAN_INFO_RAW: > + if (chan->output) { > + *val = priv->chan_out_states[chan->channel]; > + return IIO_VAL_INT; > + } > + > + /* select ADC channel */ > + outb(chan->channel | (chan->channel << 4), priv->base + 2); > + > + /* trigger ADC sample capture and wait for completion */ > + outb(0, priv->base); > + while (inb(priv->base + 8) & BIT(7)); > + > + *val = inw(priv->base); > + return IIO_VAL_INT; > + case IIO_CHAN_INFO_OFFSET: > + /* get ADC bipolar/unipolar configuration */ > + adc_config = inb(priv->base + 11); > + adbu = !(adc_config & BIT(2)); > + > + *val = -32768 * adbu; > + return IIO_VAL_INT; > + case IIO_CHAN_INFO_SCALE: > + /* get ADC bipolar/unipolar and gain configuration */ > + adc_config = inb(priv->base + 11); > + adbu = !(adc_config & BIT(2)); > + gain = adc_config & 0x3; > + > + *val = 5; > + *val2 = 15 - adbu + gain; > + return IIO_VAL_FRACTIONAL_LOG2; > + } > > - if (mask != IIO_CHAN_INFO_RAW) > - return -EINVAL; > - > - *val = priv->chan_out_states[chan->channel]; > - > - return IIO_VAL_INT; > + return -EINVAL; > } > > static int stx104_write_raw(struct iio_dev *indio_dev, > struct iio_chan_spec const *chan, int val, int val2, long mask) > { > struct stx104_iio *const priv = iio_priv(indio_dev); > - const unsigned chan_addr_offset = 2 * chan->channel; > > - if (mask != IIO_CHAN_INFO_RAW) > + switch (mask) { > + case IIO_CHAN_INFO_HARDWAREGAIN: > + /* Only four gain states (x1, x2, x4, x8) */ > + switch (val) { > + case 1: > + outb(0, priv->base + 11); > + break; > + case 2: > + outb(1, priv->base + 11); > + break; > + case 4: > + outb(2, priv->base + 11); > + break; > + case 8: > + outb(3, priv->base + 11); > + break; > + default: > + return -EINVAL; > + } > + > + return 0; > + case IIO_CHAN_INFO_RAW: > + if (chan->output) { > + /* DAC can only accept up to a 16-bit value */ > + if ((unsigned int)val > 65535) > + return -EINVAL; > + > + priv->chan_out_states[chan->channel] = val; > + outw(val, priv->base + 4 + 2 * chan->channel); > + > + return 0; > + } > return -EINVAL; > + } > > - priv->chan_out_states[chan->channel] = val; > - outw(val, priv->base + 4 + chan_addr_offset); > - > - return 0; > + return -EINVAL; > } > > static const struct iio_info stx104_info = { > @@ -99,9 +177,22 @@ static const struct iio_info stx104_info = { > .write_raw = stx104_write_raw > }; > > -static const struct iio_chan_spec stx104_channels[STX104_NUM_CHAN] = { > - STX104_CHAN(0), > - STX104_CHAN(1) > +/* single-ended input channels configuration */ > +static const struct iio_chan_spec stx104_channels_sing[] = { > + STX104_OUT_CHAN(0), STX104_OUT_CHAN(1), > + STX104_IN_CHAN(0, 0), STX104_IN_CHAN(1, 0), STX104_IN_CHAN(2, 0), > + STX104_IN_CHAN(3, 0), STX104_IN_CHAN(4, 0), STX104_IN_CHAN(5, 0), > + STX104_IN_CHAN(6, 0), STX104_IN_CHAN(7, 0), STX104_IN_CHAN(8, 0), > + STX104_IN_CHAN(9, 0), STX104_IN_CHAN(10, 0), STX104_IN_CHAN(11, 0), > + STX104_IN_CHAN(12, 0), STX104_IN_CHAN(13, 0), STX104_IN_CHAN(14, 0), > + STX104_IN_CHAN(15, 0) > +}; > +/* differential input channels configuration */ > +static const struct iio_chan_spec stx104_channels_diff[] = { > + STX104_OUT_CHAN(0), STX104_OUT_CHAN(1), > + STX104_IN_CHAN(0, 1), STX104_IN_CHAN(1, 1), STX104_IN_CHAN(2, 1), > + STX104_IN_CHAN(3, 1), STX104_IN_CHAN(4, 1), STX104_IN_CHAN(5, 1), > + STX104_IN_CHAN(6, 1), STX104_IN_CHAN(7, 1) > }; > > static int stx104_gpio_get_direction(struct gpio_chip *chip, > @@ -188,13 +279,27 @@ static int stx104_probe(struct device *dev, unsigned int id) > > indio_dev->info = &stx104_info; > indio_dev->modes = INDIO_DIRECT_MODE; > - indio_dev->channels = stx104_channels; > - indio_dev->num_channels = STX104_NUM_CHAN; > + > + /* determine if differential inputs */ > + if (inb(base[id] + 8) & BIT(5)) { > + indio_dev->num_channels = ARRAY_SIZE(stx104_channels_diff); > + indio_dev->channels = stx104_channels_diff; > + } else { > + indio_dev->num_channels = ARRAY_SIZE(stx104_channels_sing); > + indio_dev->channels = stx104_channels_sing; > + } > + > indio_dev->name = dev_name(dev); > > priv = iio_priv(indio_dev); > priv->base = base[id]; > > + /* configure device for software trigger operation */ > + outb(0, base[id] + 9); > + > + /* initialize gain setting to x1 */ > + outb(0, base[id] + 11); > + > /* initialize DAC output to 0V */ > outw(0, base[id] + 4); > outw(0, base[id] + 6); > @@ -251,5 +356,5 @@ static struct isa_driver stx104_driver = { > module_isa_driver(stx104_driver, num_stx104); > > MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@xxxxxxxxx>"); > -MODULE_DESCRIPTION("Apex Embedded Systems STX104 DAC driver"); > +MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver"); > MODULE_LICENSE("GPL v2"); > diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig > index b9f0442..6048aed 100644 > --- a/drivers/iio/dac/Kconfig > +++ b/drivers/iio/dac/Kconfig > @@ -254,16 +254,6 @@ config MCP4922 > To compile this driver as a module, choose M here: the module > will be called mcp4922. > > -config STX104 > - tristate "Apex Embedded Systems STX104 DAC driver" > - depends on X86 && ISA_BUS_API > - select GPIOLIB > - help > - Say yes here to build support for the 2-channel DAC and GPIO on the > - Apex Embedded Systems STX104 integrated analog PC/104 card. The base > - port addresses for the devices may be configured via the base array > - module parameter. > - > config VF610_DAC > tristate "Vybrid vf610 DAC driver" > depends on OF > diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile > index b1a1206..e6abef9 100644 > --- a/drivers/iio/dac/Makefile > +++ b/drivers/iio/dac/Makefile > @@ -27,5 +27,4 @@ obj-$(CONFIG_MAX517) += max517.o > obj-$(CONFIG_MAX5821) += max5821.o > obj-$(CONFIG_MCP4725) += mcp4725.o > obj-$(CONFIG_MCP4922) += mcp4922.o > -obj-$(CONFIG_STX104) += stx104.o > obj-$(CONFIG_VF610_DAC) += vf610_dac.o > -- To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html