From: Greg Kroah-Hartman Date: Wed, 14 Sep 2016 18:42:03 +0000 (+0200) Subject: Merge tag 'iio-for-4.9b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio... X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=552edf8d79096c7458cdc2a7b1f9936e7925e2aa;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git Merge tag 'iio-for-4.9b' of git://git./linux/kernel/git/jic23/iio into staging-next Jonathan writes: Second set of iio new device support, features and cleanups for the 4.9 cycle. New device support * ad8801 dac - new driver supporting ad8801 and ad8803 DACs. * adc12138 - new driver supporting TI adc12130/adc12132 and adc12138 ADCs. * ltc2485 adc - new driver * mxc6255 - add support for the mxc6225 part name and fixup the ID check so it works. * vz89x VOC sensor - add support for the vz89te part which drops the voc_short channel and adds CRCs compared to other supported parts. New features * core - immutable triggers. These effectively grant exclusive control over a trigger. The typical usecase is a device representing an analog part (perhaps a MUX) that needs to control the sampling of a downstream ADC. - resource managed trigger registration and triggered_buffer_init. - iio_push_event now protected against case of the event interface registration not having yet occured. Only matters if an interrupt can occur during this window - might happen on shared interrupt lines. - helper to let a driver query if the trigger it is using is provided by itself (using the convention of both device and trigger having the same parent). * tools - iio-utils. Used channel modifier scaling in preference to generic scaling when both exist. * at91-adc - Add support for touchscreen switches closure time needed by some newer parts. * stx104 - support the ADC channels on this ADC/DAC board. As these are the primary feature of the board also move the driver to the iio/adc directory. * sx9500 - device tree bindings. Cleanups / Fixes * ad5755 - fix an off-by-one on devnr limit check (introduced earlier this cycle) * ad7266 - drop NULL check on devm_regulator_get_optional as it can't return NULL. * ak8974 - avoid an unused functional warning due to rework in PM core code. - remove .owner field setting as done by i2c_core. * ina2xx - clear out a left over debug field from chip global data. * hid-sensors - avoid an unused functional warning due to rework in PM core code. * maxim-thermocouple - fix non static symbol warnings. * ms5611 - fetch and enable regulators unconditionally when they aren't optional. * sca3000 - whitespace cleanup. * st_sensors - fetch and enable regulators unconditionally rather than having them supported as optional regulators (missunderstanding on my part amongst others a while back) - followup to previous patch fixes error checking on the regulators. - mark symbols static where possible. - use the 'is it my trigger' help function. This prevents the odd case of another device triggering from the st-sensors trigger whilst the st-sensors trigger is itself not using it but rather using say an hrtimer. * ti-ads1015 - add missing of_node_put. * vz89x - rework to all support of new devices. - prevent reading of a corrupted buffer. - fixup a return value of 0/1 in a bool returning function. Address updates - Vlad Dogaru email address change. --- 552edf8d79096c7458cdc2a7b1f9936e7925e2aa diff --cc .mailmap index de22daefd9da,89a2f9499912..377d16f2b0b8 --- a/.mailmap +++ b/.mailmap @@@ -159,8 -158,7 +159,9 @@@ Valdis Kletnieks Viresh Kumar Viresh Kumar + Vlad Dogaru +Vladimir Davydov +Vladimir Davydov Takashi YOSHII Yusuke Goda Gustavo Padovan diff --cc drivers/iio/adc/stx104.c index 000000000000,7ca12d58e750..7e3645749eaf mode 000000,100644..100644 --- a/drivers/iio/adc/stx104.c +++ b/drivers/iio/adc/stx104.c @@@ -1,0 -1,360 +1,380 @@@ + /* + * 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 + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #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 + + static unsigned int base[max_num_isa_dev(STX104_EXTENT)]; + static unsigned int num_stx104; + module_param_array(base, uint, &num_stx104, 0); + MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses"); + + /** + * struct stx104_iio - IIO device private data structure + * @chan_out_states: channels' output states + * @base: base port address of the IIO device + */ + struct stx104_iio { + unsigned int chan_out_states[STX104_NUM_OUT_CHAN]; + unsigned int base; + }; + + /** + * struct stx104_gpio - GPIO device private data structure + * @chip: instance of the gpio_chip + * @lock: synchronization lock to prevent I/O race conditions + * @base: base port address of the GPIO device + * @out_state: output bits state + */ + struct stx104_gpio { + struct gpio_chip chip; + spinlock_t lock; + unsigned int base; + unsigned int out_state; + }; + ++/** ++ * struct stx104_dev - STX104 device private data structure ++ * @indio_dev: IIO device ++ * @chip: instance of the gpio_chip ++ */ ++struct stx104_dev { ++ struct iio_dev *indio_dev; ++ struct gpio_chip *chip; ++}; ++ + 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; + } + + 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); + + 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; + } + + return -EINVAL; + } + + static const struct iio_info stx104_info = { + .driver_module = THIS_MODULE, + .read_raw = stx104_read_raw, + .write_raw = stx104_write_raw + }; + + /* 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, + unsigned int offset) + { ++ /* GPIO 0-3 are input only, while the rest are output only */ + if (offset < 4) + return 1; + + return 0; + } + + static int stx104_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) + { + if (offset >= 4) + return -EINVAL; + + return 0; + } + + static int stx104_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) + { + if (offset < 4) + return -EINVAL; + + chip->set(chip, offset, value); + return 0; + } + + static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset) + { + struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip); + + if (offset >= 4) + return -EINVAL; + + return !!(inb(stx104gpio->base) & BIT(offset)); + } + + static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) + { + struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip); + const unsigned int mask = BIT(offset) >> 4; + unsigned long flags; + + if (offset < 4) + return; + + spin_lock_irqsave(&stx104gpio->lock, flags); + + if (value) + stx104gpio->out_state |= mask; + else + stx104gpio->out_state &= ~mask; + + outb(stx104gpio->out_state, stx104gpio->base); + + spin_unlock_irqrestore(&stx104gpio->lock, flags); + } + + static int stx104_probe(struct device *dev, unsigned int id) + { + struct iio_dev *indio_dev; + struct stx104_iio *priv; + struct stx104_gpio *stx104gpio; ++ struct stx104_dev *stx104dev; + int err; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); + if (!indio_dev) + return -ENOMEM; + + stx104gpio = devm_kzalloc(dev, sizeof(*stx104gpio), GFP_KERNEL); + if (!stx104gpio) + return -ENOMEM; + ++ stx104dev = devm_kzalloc(dev, sizeof(*stx104dev), GFP_KERNEL); ++ if (!stx104dev) ++ return -ENOMEM; ++ + if (!devm_request_region(dev, base[id], STX104_EXTENT, + dev_name(dev))) { + dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", + base[id], base[id] + STX104_EXTENT); + return -EBUSY; + } + + indio_dev->info = &stx104_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + /* 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); + - err = devm_iio_device_register(dev, indio_dev); - if (err) { - dev_err(dev, "IIO device registering failed (%d)\n", err); - return err; - } - + stx104gpio->chip.label = dev_name(dev); + stx104gpio->chip.parent = dev; + stx104gpio->chip.owner = THIS_MODULE; + stx104gpio->chip.base = -1; + stx104gpio->chip.ngpio = 8; + stx104gpio->chip.get_direction = stx104_gpio_get_direction; + stx104gpio->chip.direction_input = stx104_gpio_direction_input; + stx104gpio->chip.direction_output = stx104_gpio_direction_output; + stx104gpio->chip.get = stx104_gpio_get; + stx104gpio->chip.set = stx104_gpio_set; + stx104gpio->base = base[id] + 3; + stx104gpio->out_state = 0x0; + + spin_lock_init(&stx104gpio->lock); + - dev_set_drvdata(dev, stx104gpio); ++ stx104dev->indio_dev = indio_dev; ++ stx104dev->chip = &stx104gpio->chip; ++ dev_set_drvdata(dev, stx104dev); + + err = gpiochip_add_data(&stx104gpio->chip, stx104gpio); + if (err) { + dev_err(dev, "GPIO registering failed (%d)\n", err); + return err; + } + ++ err = iio_device_register(indio_dev); ++ if (err) { ++ dev_err(dev, "IIO device registering failed (%d)\n", err); ++ gpiochip_remove(&stx104gpio->chip); ++ return err; ++ } ++ + return 0; + } + + static int stx104_remove(struct device *dev, unsigned int id) + { - struct stx104_gpio *const stx104gpio = dev_get_drvdata(dev); ++ struct stx104_dev *const stx104dev = dev_get_drvdata(dev); + - gpiochip_remove(&stx104gpio->chip); ++ iio_device_unregister(stx104dev->indio_dev); ++ gpiochip_remove(stx104dev->chip); + + return 0; + } + + static struct isa_driver stx104_driver = { + .probe = stx104_probe, + .driver = { + .name = "stx104" + }, + .remove = stx104_remove + }; + + module_isa_driver(stx104_driver, num_stx104); + + MODULE_AUTHOR("William Breathitt Gray "); + MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver"); + MODULE_LICENSE("GPL v2");