2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-01 09:43:34 +08:00

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.
 -----BEGIN PGP SIGNATURE-----
 
 iQIuBAABCAAYBQJX1wW9ERxqaWMyM0BrZXJuZWwub3JnAAoJEFSFNJnE9BaII9UP
 /jXkXtaL62pvipMuEujmpR7j/A+GhmSWHhnbJ9XXeGZStGMUummTyaM+6WZoCKUH
 bMtZh/ETsn+FI7mD7P/FtwHauoxSmndcaAfB6cDKQMVakbXbz4VHrim256cY3gvq
 dzF5nYX+wDue6D7k55VPrtV1isBfipeCXKBtzBlAXaVE2FK2qKP+PIlAln8Ql5/l
 b5B3pvqu0YVED4t2MzyVWcVidPOEh9GgwHu7Ba+kjVi6zuB4w+r5ZreIObb5IR54
 FDcEwL6vV9AlmX15Pc18NO+50bZ8TvgT4y7ISqaOwszaIEoDAc0hXT7TdUOscmtt
 LIbhzHVMVkPSjxvtpz2ui8GfqzhxLi3ZzfNHRegOqH4b2Cpoh4zdwn7nCyJEHZV5
 simAL00FGjzp6B4Zp+Ly6ygKzpF3iXZce0Qjlr/ge+ioNIrfuK10sdLw8NZA5GUB
 JcFYijcFLUb0Cu/KjZ7njlfdAN9Tt94xzpnllM8+j4M50Nhbw05YNhIxB7RxmeSH
 Y44/oBLG51SgtlIg5Z4rULRAcOC5dty73Inb0n4lbN/pjgIcnh+EYtPeI2fA8vyB
 XYqr4xx+A3ZX1yKpYLYO+JYtVsVq9RGYdb501uBhEE3/GWEpxZvbyqHnPwwfM+Pf
 ZNuBceBxM3yyi4Z/lKkZnQbaF/1fFoG7FO1n6iRpb8Ci
 =V1xL
 -----END PGP SIGNATURE-----

Merge tag 'iio-for-4.9b' of git://git.kernel.org/pub/scm/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.
This commit is contained in:
Greg Kroah-Hartman 2016-09-14 20:42:03 +02:00
commit 552edf8d79
38 changed files with 1608 additions and 138 deletions

View File

@ -159,6 +159,7 @@ Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
Viresh Kumar <vireshk@kernel.org> <viresh.kumar@st.com>
Viresh Kumar <vireshk@kernel.org> <viresh.linux@gmail.com>
Viresh Kumar <vireshk@kernel.org> <viresh.kumar2@arm.com>
Vlad Dogaru <ddvlad@gmail.com> <vlad.dogaru@intel.com>
Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@virtuozzo.com>
Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@parallels.com>
Takashi YOSHII <takashi.yoshii.zj@renesas.com>

View File

@ -0,0 +1,37 @@
* Texas Instruments' ADC12130/ADC12132/ADC12138
Required properties:
- compatible: Should be one of
* "ti,adc12130"
* "ti,adc12132"
* "ti,adc12138"
- reg: SPI chip select number for the device
- interrupts: Should contain interrupt for EOC (end of conversion)
- clocks: phandle to conversion clock input
- spi-max-frequency: Definision as per
Documentation/devicetree/bindings/spi/spi-bus.txt
- vref-p-supply: The regulator supply for positive analog voltage reference
Optional properties:
- vref-n-supply: The regulator supply for negative analog voltage reference
(Note that this must not go below GND or exceed vref-p)
If not specified, this is assumed to be analog ground.
- ti,acquisition-time: The number of conversion clock periods for the S/H's
acquisition time. Should be one of 6, 10, 18, 34. If not specified,
default value of 10 is used.
For high source impedances, this value can be increased to 18 or 34.
For less ADC accuracy and/or slower CCLK frequencies this value may be
decreased to 6. See section 6.0 INPUT SOURCE RESISTANCE in the
datasheet for details.
Example:
adc@0 {
compatible = "ti,adc12138";
reg = <0>;
interrupts = <28 IRQ_TYPE_EDGE_RISING>;
interrupt-parent = <&gpio1>;
clocks = <&cclk>;
vref-p-supply = <&ldo4_reg>;
spi-max-frequency = <5000000>;
ti,acquisition-time = <6>;
};

View File

@ -0,0 +1,24 @@
Semtech's SX9500 capacitive proximity button device driver
Required properties:
- compatible: must be "semtech,sx9500"
- reg: i2c address where to find the device
- interrupt-parent : should be the phandle for the interrupt controller
- interrupts : the sole interrupt generated by the device
Refer to interrupt-controller/interrupts.txt for generic
interrupt client node bindings.
Optional properties:
- reset-gpios: Reference to the GPIO connected to the device's active
low reset pin.
Example:
sx9500@28 {
compatible = "semtech,sx9500";
reg = <0x28>;
interrupt-parent = <&gpio2>;
interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
};

View File

@ -266,8 +266,12 @@ IIO
devm_iio_device_unregister()
devm_iio_kfifo_allocate()
devm_iio_kfifo_free()
devm_iio_triggered_buffer_setup()
devm_iio_triggered_buffer_cleanup()
devm_iio_trigger_alloc()
devm_iio_trigger_free()
devm_iio_trigger_register()
devm_iio_trigger_unregister()
devm_iio_channel_get()
devm_iio_channel_release()
devm_iio_channel_get_all()

View File

@ -810,11 +810,11 @@ L: alsa-devel@alsa-project.org (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@gmail.com>
L: linux-iio@vger.kernel.org
S: Maintained
F: drivers/iio/dac/stx104.c
F: drivers/iio/adc/stx104.c
APM DRIVER
M: Jiri Kosina <jikos@kernel.org>

View File

@ -154,7 +154,7 @@ static int mxc6255_probe(struct i2c_client *client,
return ret;
}
if (chip_id != MXC6255_CHIP_ID) {
if ((chip_id & 0x1f) != MXC6255_CHIP_ID) {
dev_err(&client->dev, "Invalid chip id %x\n", chip_id);
return -ENODEV;
}
@ -171,12 +171,14 @@ static int mxc6255_probe(struct i2c_client *client,
}
static const struct acpi_device_id mxc6255_acpi_match[] = {
{"MXC6225", 0},
{"MXC6255", 0},
{ }
};
MODULE_DEVICE_TABLE(acpi, mxc6255_acpi_match);
static const struct i2c_device_id mxc6255_id[] = {
{"mxc6225", 0},
{"mxc6255", 0},
{ }
};

View File

@ -264,6 +264,15 @@ config LPC18XX_ADC
To compile this driver as a module, choose M here: the module will be
called lpc18xx_adc.
config LTC2485
tristate "Linear Technology LTC2485 ADC driver"
depends on I2C
help
Say yes here to build support for Linear Technology LTC2485 ADC.
To compile this driver as a module, choose M here: the module will be
called ltc2485.
config MAX1027
tristate "Maxim max1027 ADC driver"
depends on SPI
@ -410,6 +419,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
@ -430,6 +454,18 @@ config TI_ADC0832
This driver can also be built as a module. If so, the module will be
called ti-adc0832.
config TI_ADC12138
tristate "Texas Instruments ADC12130/ADC12132/ADC12138"
depends on SPI
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
If you say yes here you get support for Texas Instruments ADC12130,
ADC12132 and ADC12138 chips.
This driver can also be built as a module. If so, the module will be
called ti-adc12138.
config TI_ADC128S052
tristate "Texas Instruments ADC128S052/ADC122S021/ADC124S021"
depends on SPI

View File

@ -27,6 +27,7 @@ obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_LTC2485) += ltc2485.o
obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX1363) += max1363.o
obj-$(CONFIG_MCP320X) += mcp320x.o
@ -39,8 +40,10 @@ 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_ADC12138) += ti-adc12138.o
obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o
obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o
obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o

View File

@ -481,7 +481,7 @@ error_free_gpios:
if (!st->fixed_addr)
gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
error_disable_reg:
if (!IS_ERR_OR_NULL(st->reg))
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
return ret;
@ -496,7 +496,7 @@ static int ad7266_remove(struct spi_device *spi)
iio_triggered_buffer_cleanup(indio_dev);
if (!st->fixed_addr)
gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
if (!IS_ERR_OR_NULL(st->reg))
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
return 0;

View File

@ -113,6 +113,7 @@
#define AT91_ADC_TSMR_TSAV (3 << 4) /* Averages samples */
#define AT91_ADC_TSMR_TSAV_(x) ((x) << 4)
#define AT91_ADC_TSMR_SCTIM (0x0f << 16) /* Switch closure time */
#define AT91_ADC_TSMR_SCTIM_(x) ((x) << 16)
#define AT91_ADC_TSMR_PENDBC (0x0f << 28) /* Pen Debounce time */
#define AT91_ADC_TSMR_PENDBC_(x) ((x) << 28)
#define AT91_ADC_TSMR_NOTSDMA (1 << 22) /* No Touchscreen DMA */
@ -150,6 +151,7 @@
#define MAX_RLPOS_BITS 10
#define TOUCH_SAMPLE_PERIOD_US_RL 10000 /* 10ms, the SoC can't keep up with 2ms */
#define TOUCH_SHTIM 0xa
#define TOUCH_SCTIM_US 10 /* 10us for the Touchscreen Switches Closure Time */
/**
* struct at91_adc_reg_desc - Various informations relative to registers
@ -1001,7 +1003,9 @@ static void atmel_ts_close(struct input_dev *dev)
static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz)
{
struct iio_dev *idev = iio_priv_to_dev(st);
u32 reg = 0;
u32 tssctim = 0;
int i = 0;
/* a Pen Detect Debounce Time is necessary for the ADC Touch to avoid
@ -1034,11 +1038,20 @@ static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz)
return 0;
}
/* Touchscreen Switches Closure time needed for allowing the value to
* stabilize.
* Switch Closure Time = (TSSCTIM * 4) ADCClock periods
*/
tssctim = DIV_ROUND_UP(TOUCH_SCTIM_US * adc_clk_khz / 1000, 4);
dev_dbg(&idev->dev, "adc_clk at: %d KHz, tssctim at: %d\n",
adc_clk_khz, tssctim);
if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_4WIRE)
reg = AT91_ADC_TSMR_TSMODE_4WIRE_PRESS;
else
reg = AT91_ADC_TSMR_TSMODE_5WIRE;
reg |= AT91_ADC_TSMR_SCTIM_(tssctim) & AT91_ADC_TSMR_SCTIM;
reg |= AT91_ADC_TSMR_TSAV_(st->caps->ts_filter_average)
& AT91_ADC_TSMR_TSAV;
reg |= AT91_ADC_TSMR_PENDBC_(st->ts_pendbc) & AT91_ADC_TSMR_PENDBC;

View File

@ -114,7 +114,6 @@ struct ina2xx_chip_info {
struct mutex state_lock;
unsigned int shunt_resistor;
int avg;
s64 prev_ns; /* track buffer capture time, check for underruns */
int int_time_vbus; /* Bus voltage integration time uS */
int int_time_vshunt; /* Shunt voltage integration time uS */
bool allow_async_readout;
@ -509,8 +508,6 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
iio_push_to_buffers_with_timestamp(indio_dev,
(unsigned int *)data, time_a);
chip->prev_ns = time_a;
return (unsigned long)(time_b - time_a) / 1000;
};
@ -554,8 +551,6 @@ static int ina2xx_buffer_enable(struct iio_dev *indio_dev)
dev_dbg(&indio_dev->dev, "Async readout mode: %d\n",
chip->allow_async_readout);
chip->prev_ns = iio_get_time_ns(indio_dev);
chip->task = kthread_run(ina2xx_capture_thread, (void *)indio_dev,
"%s:%d-%uus", indio_dev->name, indio_dev->id,
sampling_us);

148
drivers/iio/adc/ltc2485.c Normal file
View File

@ -0,0 +1,148 @@
/*
* ltc2485.c - Driver for Linear Technology LTC2485 ADC
*
* Copyright (C) 2016 Alison Schofield <amsfield22@gmail.com>
*
* 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.
*
* Datasheet: http://cds.linear.com/docs/en/datasheet/2485fd.pdf
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
/* Power-on configuration: rejects both 50/60Hz, operates at 1x speed */
#define LTC2485_CONFIG_DEFAULT 0
struct ltc2485_data {
struct i2c_client *client;
ktime_t time_prev; /* last conversion */
};
static void ltc2485_wait_conv(struct ltc2485_data *data)
{
const unsigned int conv_time = 147; /* conversion time ms */
unsigned int time_elapsed;
/* delay if conversion time not passed since last read or write */
time_elapsed = ktime_ms_delta(ktime_get(), data->time_prev);
if (time_elapsed < conv_time)
msleep(conv_time - time_elapsed);
}
static int ltc2485_read(struct ltc2485_data *data, int *val)
{
struct i2c_client *client = data->client;
__be32 buf = 0;
int ret;
ltc2485_wait_conv(data);
ret = i2c_master_recv(client, (char *)&buf, 4);
if (ret < 0) {
dev_err(&client->dev, "i2c_master_recv failed\n");
return ret;
}
data->time_prev = ktime_get();
*val = sign_extend32(be32_to_cpu(buf) >> 6, 24);
return ret;
}
static int ltc2485_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct ltc2485_data *data = iio_priv(indio_dev);
int ret;
if (mask == IIO_CHAN_INFO_RAW) {
ret = ltc2485_read(data, val);
if (ret < 0)
return ret;
return IIO_VAL_INT;
} else if (mask == IIO_CHAN_INFO_SCALE) {
*val = 5000; /* on board vref millivolts */
*val2 = 25; /* 25 (24 + sign) data bits */
return IIO_VAL_FRACTIONAL_LOG2;
} else {
return -EINVAL;
}
}
static const struct iio_chan_spec ltc2485_channel[] = {
{
.type = IIO_VOLTAGE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)
},
};
static const struct iio_info ltc2485_info = {
.read_raw = ltc2485_read_raw,
.driver_module = THIS_MODULE,
};
static int ltc2485_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
struct ltc2485_data *data;
int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
I2C_FUNC_SMBUS_WRITE_BYTE))
return -EOPNOTSUPP;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
indio_dev->dev.parent = &client->dev;
indio_dev->name = id->name;
indio_dev->info = &ltc2485_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = ltc2485_channel;
indio_dev->num_channels = ARRAY_SIZE(ltc2485_channel);
ret = i2c_smbus_write_byte(data->client, LTC2485_CONFIG_DEFAULT);
if (ret < 0)
return ret;
data->time_prev = ktime_get();
return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id ltc2485_id[] = {
{ "ltc2485", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltc2485_id);
static struct i2c_driver ltc2485_driver = {
.driver = {
.name = "ltc2485",
},
.probe = ltc2485_probe,
.id_table = ltc2485_id,
};
module_i2c_driver(ltc2485_driver);
MODULE_AUTHOR("Alison Schofield <amsfield22@gmail.com>");
MODULE_DESCRIPTION("Linear Technology LTC2485 ADC driver");
MODULE_LICENSE("GPL v2");

View File

@ -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;
};
/**
@ -79,28 +90,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;
if (mask != IIO_CHAN_INFO_RAW)
return -EINVAL;
switch (mask) {
case IIO_CHAN_INFO_HARDWAREGAIN:
/* get gain configuration */
adc_config = inb(priv->base + 11);
gain = adc_config & 0x3;
*val = priv->chan_out_states[chan->channel];
*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;
}
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);
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 = {
@ -109,9 +187,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,
@ -204,13 +295,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);
@ -271,5 +376,5 @@ static struct isa_driver stx104_driver = {
module_isa_driver(stx104_driver, num_stx104);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("Apex Embedded Systems STX104 DAC driver");
MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,552 @@
/*
* ADC12130/ADC12132/ADC12138 12-bit plus sign ADC driver
*
* Copyright (c) 2016 Akinobu Mita <akinobu.mita@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* Datasheet: http://www.ti.com/lit/ds/symlink/adc12138.pdf
*/
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/clk.h>
#include <linux/spi/spi.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/regulator/consumer.h>
#define ADC12138_MODE_AUTO_CAL 0x08
#define ADC12138_MODE_READ_STATUS 0x0c
#define ADC12138_MODE_ACQUISITION_TIME_6 0x0e
#define ADC12138_MODE_ACQUISITION_TIME_10 0x4e
#define ADC12138_MODE_ACQUISITION_TIME_18 0x8e
#define ADC12138_MODE_ACQUISITION_TIME_34 0xce
#define ADC12138_STATUS_CAL BIT(6)
enum {
adc12130,
adc12132,
adc12138,
};
struct adc12138 {
struct spi_device *spi;
unsigned int id;
/* conversion clock */
struct clk *cclk;
/* positive analog voltage reference */
struct regulator *vref_p;
/* negative analog voltage reference */
struct regulator *vref_n;
struct mutex lock;
struct completion complete;
/* The number of cclk periods for the S/H's acquisition time */
unsigned int acquisition_time;
u8 tx_buf[2] ____cacheline_aligned;
u8 rx_buf[2];
};
#define ADC12138_VOLTAGE_CHANNEL(chan) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = chan, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
| BIT(IIO_CHAN_INFO_OFFSET), \
.scan_index = chan, \
.scan_type = { \
.sign = 's', \
.realbits = 13, \
.storagebits = 16, \
.shift = 3, \
.endianness = IIO_BE, \
}, \
}
#define ADC12138_VOLTAGE_CHANNEL_DIFF(chan1, chan2, si) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (chan1), \
.channel2 = (chan2), \
.differential = 1, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
| BIT(IIO_CHAN_INFO_OFFSET), \
.scan_index = si, \
.scan_type = { \
.sign = 's', \
.realbits = 13, \
.storagebits = 16, \
.shift = 3, \
.endianness = IIO_BE, \
}, \
}
static const struct iio_chan_spec adc12132_channels[] = {
ADC12138_VOLTAGE_CHANNEL(0),
ADC12138_VOLTAGE_CHANNEL(1),
ADC12138_VOLTAGE_CHANNEL_DIFF(0, 1, 2),
ADC12138_VOLTAGE_CHANNEL_DIFF(1, 0, 3),
IIO_CHAN_SOFT_TIMESTAMP(4),
};
static const struct iio_chan_spec adc12138_channels[] = {
ADC12138_VOLTAGE_CHANNEL(0),
ADC12138_VOLTAGE_CHANNEL(1),
ADC12138_VOLTAGE_CHANNEL(2),
ADC12138_VOLTAGE_CHANNEL(3),
ADC12138_VOLTAGE_CHANNEL(4),
ADC12138_VOLTAGE_CHANNEL(5),
ADC12138_VOLTAGE_CHANNEL(6),
ADC12138_VOLTAGE_CHANNEL(7),
ADC12138_VOLTAGE_CHANNEL_DIFF(0, 1, 8),
ADC12138_VOLTAGE_CHANNEL_DIFF(1, 0, 9),
ADC12138_VOLTAGE_CHANNEL_DIFF(2, 3, 10),
ADC12138_VOLTAGE_CHANNEL_DIFF(3, 2, 11),
ADC12138_VOLTAGE_CHANNEL_DIFF(4, 5, 12),
ADC12138_VOLTAGE_CHANNEL_DIFF(5, 4, 13),
ADC12138_VOLTAGE_CHANNEL_DIFF(6, 7, 14),
ADC12138_VOLTAGE_CHANNEL_DIFF(7, 6, 15),
IIO_CHAN_SOFT_TIMESTAMP(16),
};
static int adc12138_mode_programming(struct adc12138 *adc, u8 mode,
void *rx_buf, int len)
{
struct spi_transfer xfer = {
.tx_buf = adc->tx_buf,
.rx_buf = adc->rx_buf,
.len = len,
};
int ret;
/* Skip unused bits for ADC12130 and ADC12132 */
if (adc->id != adc12138)
mode = (mode & 0xc0) | ((mode & 0x0f) << 2);
adc->tx_buf[0] = mode;
ret = spi_sync_transfer(adc->spi, &xfer, 1);
if (ret)
return ret;
memcpy(rx_buf, adc->rx_buf, len);
return 0;
}
static int adc12138_read_status(struct adc12138 *adc)
{
u8 rx_buf[2];
int ret;
ret = adc12138_mode_programming(adc, ADC12138_MODE_READ_STATUS,
rx_buf, 2);
if (ret)
return ret;
return (rx_buf[0] << 1) | (rx_buf[1] >> 7);
}
static int __adc12138_start_conv(struct adc12138 *adc,
struct iio_chan_spec const *channel,
void *data, int len)
{
const u8 ch_to_mux[] = { 0, 4, 1, 5, 2, 6, 3, 7 };
u8 mode = (ch_to_mux[channel->channel] << 4) |
(channel->differential ? 0 : 0x80);
return adc12138_mode_programming(adc, mode, data, len);
}
static int adc12138_start_conv(struct adc12138 *adc,
struct iio_chan_spec const *channel)
{
u8 trash;
return __adc12138_start_conv(adc, channel, &trash, 1);
}
static int adc12138_start_and_read_conv(struct adc12138 *adc,
struct iio_chan_spec const *channel,
__be16 *data)
{
return __adc12138_start_conv(adc, channel, data, 2);
}
static int adc12138_read_conv_data(struct adc12138 *adc, __be16 *value)
{
/* Issue a read status instruction and read previous conversion data */
return adc12138_mode_programming(adc, ADC12138_MODE_READ_STATUS,
value, sizeof(*value));
}
static int adc12138_wait_eoc(struct adc12138 *adc, unsigned long timeout)
{
if (!wait_for_completion_timeout(&adc->complete, timeout))
return -ETIMEDOUT;
return 0;
}
static int adc12138_adc_conversion(struct adc12138 *adc,
struct iio_chan_spec const *channel,
__be16 *value)
{
int ret;
reinit_completion(&adc->complete);
ret = adc12138_start_conv(adc, channel);
if (ret)
return ret;
ret = adc12138_wait_eoc(adc, msecs_to_jiffies(100));
if (ret)
return ret;
return adc12138_read_conv_data(adc, value);
}
static int adc12138_read_raw(struct iio_dev *iio,
struct iio_chan_spec const *channel, int *value,
int *shift, long mask)
{
struct adc12138 *adc = iio_priv(iio);
int ret;
__be16 data;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&adc->lock);
ret = adc12138_adc_conversion(adc, channel, &data);
mutex_unlock(&adc->lock);
if (ret)
return ret;
*value = sign_extend32(be16_to_cpu(data) >> 3, 12);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
ret = regulator_get_voltage(adc->vref_p);
if (ret < 0)
return ret;
*value = ret;
if (!IS_ERR(adc->vref_n)) {
ret = regulator_get_voltage(adc->vref_n);
if (ret < 0)
return ret;
*value -= ret;
}
/* convert regulator output voltage to mV */
*value /= 1000;
*shift = channel->scan_type.realbits - 1;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_OFFSET:
if (!IS_ERR(adc->vref_n)) {
*value = regulator_get_voltage(adc->vref_n);
if (*value < 0)
return *value;
} else {
*value = 0;
}
/* convert regulator output voltage to mV */
*value /= 1000;
return IIO_VAL_INT;
}
return -EINVAL;
}
static const struct iio_info adc12138_info = {
.read_raw = adc12138_read_raw,
.driver_module = THIS_MODULE,
};
static int adc12138_init(struct adc12138 *adc)
{
int ret;
int status;
u8 mode;
u8 trash;
reinit_completion(&adc->complete);
ret = adc12138_mode_programming(adc, ADC12138_MODE_AUTO_CAL, &trash, 1);
if (ret)
return ret;
/* data output at this time has no significance */
status = adc12138_read_status(adc);
if (status < 0)
return status;
adc12138_wait_eoc(adc, msecs_to_jiffies(100));
status = adc12138_read_status(adc);
if (status & ADC12138_STATUS_CAL) {
dev_warn(&adc->spi->dev,
"Auto Cal sequence is still in progress: %#x\n",
status);
return -EIO;
}
switch (adc->acquisition_time) {
case 6:
mode = ADC12138_MODE_ACQUISITION_TIME_6;
break;
case 10:
mode = ADC12138_MODE_ACQUISITION_TIME_10;
break;
case 18:
mode = ADC12138_MODE_ACQUISITION_TIME_18;
break;
case 34:
mode = ADC12138_MODE_ACQUISITION_TIME_34;
break;
default:
return -EINVAL;
}
return adc12138_mode_programming(adc, mode, &trash, 1);
}
static irqreturn_t adc12138_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adc12138 *adc = iio_priv(indio_dev);
__be16 data[20] = { }; /* 16x 2 bytes ADC data + 8 bytes timestamp */
__be16 trash;
int ret;
int scan_index;
int i = 0;
mutex_lock(&adc->lock);
for_each_set_bit(scan_index, indio_dev->active_scan_mask,
indio_dev->masklength) {
const struct iio_chan_spec *scan_chan =
&indio_dev->channels[scan_index];
reinit_completion(&adc->complete);
ret = adc12138_start_and_read_conv(adc, scan_chan,
i ? &data[i - 1] : &trash);
if (ret) {
dev_warn(&adc->spi->dev,
"failed to start conversion\n");
goto out;
}
ret = adc12138_wait_eoc(adc, msecs_to_jiffies(100));
if (ret) {
dev_warn(&adc->spi->dev, "wait eoc timeout\n");
goto out;
}
i++;
}
if (i) {
ret = adc12138_read_conv_data(adc, &data[i - 1]);
if (ret) {
dev_warn(&adc->spi->dev,
"failed to get conversion data\n");
goto out;
}
}
iio_push_to_buffers_with_timestamp(indio_dev, data,
iio_get_time_ns(indio_dev));
out:
mutex_unlock(&adc->lock);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
static irqreturn_t adc12138_eoc_handler(int irq, void *p)
{
struct iio_dev *indio_dev = p;
struct adc12138 *adc = iio_priv(indio_dev);
complete(&adc->complete);
return IRQ_HANDLED;
}
static int adc12138_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct adc12138 *adc;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
if (!indio_dev)
return -ENOMEM;
adc = iio_priv(indio_dev);
adc->spi = spi;
adc->id = spi_get_device_id(spi)->driver_data;
mutex_init(&adc->lock);
init_completion(&adc->complete);
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &adc12138_info;
indio_dev->modes = INDIO_DIRECT_MODE;
switch (adc->id) {
case adc12130:
case adc12132:
indio_dev->channels = adc12132_channels;
indio_dev->num_channels = ARRAY_SIZE(adc12132_channels);
break;
case adc12138:
indio_dev->channels = adc12138_channels;
indio_dev->num_channels = ARRAY_SIZE(adc12138_channels);
break;
default:
return -EINVAL;
}
ret = of_property_read_u32(spi->dev.of_node, "ti,acquisition-time",
&adc->acquisition_time);
if (ret)
adc->acquisition_time = 10;
adc->cclk = devm_clk_get(&spi->dev, NULL);
if (IS_ERR(adc->cclk))
return PTR_ERR(adc->cclk);
adc->vref_p = devm_regulator_get(&spi->dev, "vref-p");
if (IS_ERR(adc->vref_p))
return PTR_ERR(adc->vref_p);
adc->vref_n = devm_regulator_get_optional(&spi->dev, "vref-n");
if (IS_ERR(adc->vref_n)) {
/*
* Assume vref_n is 0V if an optional regulator is not
* specified, otherwise return the error code.
*/
ret = PTR_ERR(adc->vref_n);
if (ret != -ENODEV)
return ret;
}
ret = devm_request_irq(&spi->dev, spi->irq, adc12138_eoc_handler,
IRQF_TRIGGER_RISING, indio_dev->name, indio_dev);
if (ret)
return ret;
ret = clk_prepare_enable(adc->cclk);
if (ret)
return ret;
ret = regulator_enable(adc->vref_p);
if (ret)
goto err_clk_disable;
if (!IS_ERR(adc->vref_n)) {
ret = regulator_enable(adc->vref_n);
if (ret)
goto err_vref_p_disable;
}
ret = adc12138_init(adc);
if (ret)
goto err_vref_n_disable;
spi_set_drvdata(spi, indio_dev);
ret = iio_triggered_buffer_setup(indio_dev, NULL,
adc12138_trigger_handler, NULL);
if (ret)
goto err_vref_n_disable;
ret = iio_device_register(indio_dev);
if (ret)
goto err_buffer_cleanup;
return 0;
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
err_vref_n_disable:
if (!IS_ERR(adc->vref_n))
regulator_disable(adc->vref_n);
err_vref_p_disable:
regulator_disable(adc->vref_p);
err_clk_disable:
clk_disable_unprepare(adc->cclk);
return ret;
}
static int adc12138_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct adc12138 *adc = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
if (!IS_ERR(adc->vref_n))
regulator_disable(adc->vref_n);
regulator_disable(adc->vref_p);
clk_disable_unprepare(adc->cclk);
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id adc12138_dt_ids[] = {
{ .compatible = "ti,adc12130", },
{ .compatible = "ti,adc12132", },
{ .compatible = "ti,adc12138", },
{}
};
MODULE_DEVICE_TABLE(of, adc12138_dt_ids);
#endif
static const struct spi_device_id adc12138_id[] = {
{ "adc12130", adc12130 },
{ "adc12132", adc12132 },
{ "adc12138", adc12138 },
{}
};
MODULE_DEVICE_TABLE(spi, adc12138_id);
static struct spi_driver adc12138_driver = {
.driver = {
.name = "adc12138",
.of_match_table = of_match_ptr(adc12138_dt_ids),
},
.probe = adc12138_probe,
.remove = adc12138_remove,
.id_table = adc12138_id,
};
module_spi_driver(adc12138_driver);
MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
MODULE_DESCRIPTION("ADC12130/ADC12132/ADC12138 driver");
MODULE_LICENSE("GPL v2");

View File

@ -522,6 +522,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client)
if (pga > 6) {
dev_err(&client->dev, "invalid gain on %s\n",
node->full_name);
of_node_put(node);
return -EINVAL;
}
}
@ -532,6 +533,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client)
dev_err(&client->dev,
"invalid data_rate on %s\n",
node->full_name);
of_node_put(node);
return -EINVAL;
}
}

View File

@ -438,7 +438,7 @@ static int ads8688_probe(struct spi_device *spi)
return 0;
error_out:
if (!IS_ERR_OR_NULL(st->reg))
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
return ret;
@ -451,7 +451,7 @@ static int ads8688_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
if (!IS_ERR_OR_NULL(st->reg))
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
return 0;

View File

@ -98,6 +98,48 @@ void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev)
}
EXPORT_SYMBOL(iio_triggered_buffer_cleanup);
static void devm_iio_triggered_buffer_clean(struct device *dev, void *res)
{
iio_triggered_buffer_cleanup(*(struct iio_dev **)res);
}
int devm_iio_triggered_buffer_setup(struct device *dev,
struct iio_dev *indio_dev,
irqreturn_t (*h)(int irq, void *p),
irqreturn_t (*thread)(int irq, void *p),
const struct iio_buffer_setup_ops *ops)
{
struct iio_dev **ptr;
int ret;
ptr = devres_alloc(devm_iio_triggered_buffer_clean, sizeof(*ptr),
GFP_KERNEL);
if (!ptr)
return -ENOMEM;
*ptr = indio_dev;
ret = iio_triggered_buffer_setup(indio_dev, h, thread, ops);
if (!ret)
devres_add(dev, ptr);
else
devres_free(ptr);
return ret;
}
EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_setup);
void devm_iio_triggered_buffer_cleanup(struct device *dev,
struct iio_dev *indio_dev)
{
int rc;
rc = devres_release(dev, devm_iio_triggered_buffer_clean,
devm_iio_device_match, indio_dev);
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_cleanup);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("IIO helper functions for setting up triggered buffers");
MODULE_LICENSE("GPL");

View File

@ -19,25 +19,55 @@
#include <linux/mutex.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define VZ89X_REG_MEASUREMENT 0x09
#define VZ89X_REG_MEASUREMENT_SIZE 6
#define VZ89X_REG_MEASUREMENT_RD_SIZE 6
#define VZ89X_REG_MEASUREMENT_WR_SIZE 3
#define VZ89X_VOC_CO2_IDX 0
#define VZ89X_VOC_SHORT_IDX 1
#define VZ89X_VOC_TVOC_IDX 2
#define VZ89X_VOC_RESISTANCE_IDX 3
#define VZ89TE_REG_MEASUREMENT 0x0c
#define VZ89TE_REG_MEASUREMENT_RD_SIZE 7
#define VZ89TE_REG_MEASUREMENT_WR_SIZE 6
#define VZ89TE_VOC_TVOC_IDX 0
#define VZ89TE_VOC_CO2_IDX 1
#define VZ89TE_VOC_RESISTANCE_IDX 2
enum {
VZ89X,
VZ89TE,
};
struct vz89x_chip_data;
struct vz89x_data {
struct i2c_client *client;
const struct vz89x_chip_data *chip;
struct mutex lock;
int (*xfer)(struct vz89x_data *data, u8 cmd);
bool is_valid;
unsigned long last_update;
u8 buffer[VZ89X_REG_MEASUREMENT_SIZE];
u8 buffer[VZ89TE_REG_MEASUREMENT_RD_SIZE];
};
struct vz89x_chip_data {
bool (*valid)(struct vz89x_data *data);
const struct iio_chan_spec *channels;
u8 num_channels;
u8 cmd;
u8 read_size;
u8 write_size;
};
static const struct iio_chan_spec vz89x_channels[] = {
@ -70,6 +100,40 @@ static const struct iio_chan_spec vz89x_channels[] = {
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
.address = VZ89X_VOC_RESISTANCE_IDX,
.scan_index = -1,
.scan_type = {
.endianness = IIO_LE,
},
},
};
static const struct iio_chan_spec vz89te_channels[] = {
{
.type = IIO_CONCENTRATION,
.channel2 = IIO_MOD_VOC,
.modified = 1,
.info_mask_separate =
BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_RAW),
.address = VZ89TE_VOC_TVOC_IDX,
},
{
.type = IIO_CONCENTRATION,
.channel2 = IIO_MOD_CO2,
.modified = 1,
.info_mask_separate =
BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_RAW),
.address = VZ89TE_VOC_CO2_IDX,
},
{
.type = IIO_RESISTANCE,
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
.address = VZ89TE_VOC_RESISTANCE_IDX,
.scan_index = -1,
.scan_type = {
.endianness = IIO_BE,
},
},
};
@ -93,29 +157,45 @@ static const struct attribute_group vz89x_attrs_group = {
* always zero, and by also confirming the VOC_short isn't zero.
*/
static int vz89x_measurement_is_valid(struct vz89x_data *data)
static bool vz89x_measurement_is_valid(struct vz89x_data *data)
{
if (data->buffer[VZ89X_VOC_SHORT_IDX] == 0)
return 1;
return true;
return !!(data->buffer[VZ89X_REG_MEASUREMENT_SIZE - 1] > 0);
return !!(data->buffer[data->chip->read_size - 1] > 0);
}
/* VZ89TE device has a modified CRC-8 two complement check */
static bool vz89te_measurement_is_valid(struct vz89x_data *data)
{
u8 crc = 0;
int i, sum = 0;
for (i = 0; i < (data->chip->read_size - 1); i++) {
sum = crc + data->buffer[i];
crc = sum;
crc += sum / 256;
}
return !((0xff - crc) == data->buffer[data->chip->read_size - 1]);
}
static int vz89x_i2c_xfer(struct vz89x_data *data, u8 cmd)
{
const struct vz89x_chip_data *chip = data->chip;
struct i2c_client *client = data->client;
struct i2c_msg msg[2];
int ret;
u8 buf[3] = { cmd, 0, 0};
u8 buf[6] = { cmd, 0, 0, 0, 0, 0xf3 };
msg[0].addr = client->addr;
msg[0].flags = client->flags;
msg[0].len = 3;
msg[0].len = chip->write_size;
msg[0].buf = (char *) &buf;
msg[1].addr = client->addr;
msg[1].flags = client->flags | I2C_M_RD;
msg[1].len = VZ89X_REG_MEASUREMENT_SIZE;
msg[1].len = chip->read_size;
msg[1].buf = (char *) &data->buffer;
ret = i2c_transfer(client->adapter, msg, 2);
@ -133,7 +213,7 @@ static int vz89x_smbus_xfer(struct vz89x_data *data, u8 cmd)
if (ret < 0)
return ret;
for (i = 0; i < VZ89X_REG_MEASUREMENT_SIZE; i++) {
for (i = 0; i < data->chip->read_size; i++) {
ret = i2c_smbus_read_byte(client);
if (ret < 0)
return ret;
@ -145,30 +225,47 @@ static int vz89x_smbus_xfer(struct vz89x_data *data, u8 cmd)
static int vz89x_get_measurement(struct vz89x_data *data)
{
const struct vz89x_chip_data *chip = data->chip;
int ret;
/* sensor can only be polled once a second max per datasheet */
if (!time_after(jiffies, data->last_update + HZ))
return 0;
return data->is_valid ? 0 : -EAGAIN;
ret = data->xfer(data, VZ89X_REG_MEASUREMENT);
data->is_valid = false;
data->last_update = jiffies;
ret = data->xfer(data, chip->cmd);
if (ret < 0)
return ret;
ret = vz89x_measurement_is_valid(data);
ret = chip->valid(data);
if (ret)
return -EAGAIN;
data->last_update = jiffies;
data->is_valid = true;
return 0;
}
static int vz89x_get_resistance_reading(struct vz89x_data *data)
static int vz89x_get_resistance_reading(struct vz89x_data *data,
struct iio_chan_spec const *chan,
int *val)
{
u8 *buf = &data->buffer[VZ89X_VOC_RESISTANCE_IDX];
u8 *tmp = (u8 *) &data->buffer[chan->address];
return buf[0] | (buf[1] << 8);
switch (chan->scan_type.endianness) {
case IIO_LE:
*val = le32_to_cpup((__le32 *) tmp) & GENMASK(23, 0);
break;
case IIO_BE:
*val = be32_to_cpup((__be32 *) tmp) >> 8;
break;
default:
return -EINVAL;
}
return 0;
}
static int vz89x_read_raw(struct iio_dev *indio_dev,
@ -187,15 +284,15 @@ static int vz89x_read_raw(struct iio_dev *indio_dev,
if (ret)
return ret;
switch (chan->address) {
case VZ89X_VOC_CO2_IDX:
case VZ89X_VOC_SHORT_IDX:
case VZ89X_VOC_TVOC_IDX:
switch (chan->type) {
case IIO_CONCENTRATION:
*val = data->buffer[chan->address];
return IIO_VAL_INT;
case VZ89X_VOC_RESISTANCE_IDX:
*val = vz89x_get_resistance_reading(data);
return IIO_VAL_INT;
case IIO_RESISTANCE:
ret = vz89x_get_resistance_reading(data, chan, val);
if (!ret)
return IIO_VAL_INT;
break;
default:
return -EINVAL;
}
@ -210,12 +307,12 @@ static int vz89x_read_raw(struct iio_dev *indio_dev,
}
break;
case IIO_CHAN_INFO_OFFSET:
switch (chan->address) {
case VZ89X_VOC_CO2_IDX:
switch (chan->channel2) {
case IIO_MOD_CO2:
*val = 44;
*val2 = 250000;
return IIO_VAL_INT_PLUS_MICRO;
case VZ89X_VOC_TVOC_IDX:
case IIO_MOD_VOC:
*val = -13;
return IIO_VAL_INT;
default:
@ -232,11 +329,43 @@ static const struct iio_info vz89x_info = {
.driver_module = THIS_MODULE,
};
static const struct vz89x_chip_data vz89x_chips[] = {
{
.valid = vz89x_measurement_is_valid,
.cmd = VZ89X_REG_MEASUREMENT,
.read_size = VZ89X_REG_MEASUREMENT_RD_SIZE,
.write_size = VZ89X_REG_MEASUREMENT_WR_SIZE,
.channels = vz89x_channels,
.num_channels = ARRAY_SIZE(vz89x_channels),
},
{
.valid = vz89te_measurement_is_valid,
.cmd = VZ89TE_REG_MEASUREMENT,
.read_size = VZ89TE_REG_MEASUREMENT_RD_SIZE,
.write_size = VZ89TE_REG_MEASUREMENT_WR_SIZE,
.channels = vz89te_channels,
.num_channels = ARRAY_SIZE(vz89te_channels),
},
};
static const struct of_device_id vz89x_dt_ids[] = {
{ .compatible = "sgx,vz89x", .data = (void *) VZ89X },
{ .compatible = "sgx,vz89te", .data = (void *) VZ89TE },
{ }
};
MODULE_DEVICE_TABLE(of, vz89x_dt_ids);
static int vz89x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
struct vz89x_data *data;
const struct of_device_id *of_id;
int chip_id;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@ -251,8 +380,15 @@ static int vz89x_probe(struct i2c_client *client,
else
return -EOPNOTSUPP;
of_id = of_match_device(vz89x_dt_ids, &client->dev);
if (!of_id)
chip_id = id->driver_data;
else
chip_id = (unsigned long)of_id->data;
i2c_set_clientdata(client, indio_dev);
data->client = client;
data->chip = &vz89x_chips[chip_id];
data->last_update = jiffies - HZ;
mutex_init(&data->lock);
@ -261,24 +397,19 @@ static int vz89x_probe(struct i2c_client *client,
indio_dev->name = dev_name(&client->dev);
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = vz89x_channels;
indio_dev->num_channels = ARRAY_SIZE(vz89x_channels);
indio_dev->channels = data->chip->channels;
indio_dev->num_channels = data->chip->num_channels;
return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id vz89x_id[] = {
{ "vz89x", 0 },
{ "vz89x", VZ89X },
{ "vz89te", VZ89TE },
{ }
};
MODULE_DEVICE_TABLE(i2c, vz89x_id);
static const struct of_device_id vz89x_dt_ids[] = {
{ .compatible = "sgx,vz89x" },
{ }
};
MODULE_DEVICE_TABLE(of, vz89x_dt_ids);
static struct i2c_driver vz89x_driver = {
.driver = {
.name = "vz89x",

View File

@ -199,8 +199,7 @@ error_ret:
}
EXPORT_SYMBOL(hid_sensor_setup_trigger);
#ifdef CONFIG_PM
static int hid_sensor_suspend(struct device *dev)
static int __maybe_unused hid_sensor_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@ -209,7 +208,7 @@ static int hid_sensor_suspend(struct device *dev)
return _hid_sensor_power_state(attrb, false);
}
static int hid_sensor_resume(struct device *dev)
static int __maybe_unused hid_sensor_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@ -218,7 +217,7 @@ static int hid_sensor_resume(struct device *dev)
return 0;
}
static int hid_sensor_runtime_resume(struct device *dev)
static int __maybe_unused hid_sensor_runtime_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@ -226,8 +225,6 @@ static int hid_sensor_runtime_resume(struct device *dev)
return _hid_sensor_power_state(attrb, true);
}
#endif
const struct dev_pm_ops hid_sensor_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(hid_sensor_suspend, hid_sensor_resume)
SET_RUNTIME_PM_OPS(hid_sensor_suspend,

View File

@ -63,7 +63,7 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p)
* the hardware trigger) and the hw_timestamp may get updated.
* By storing it in a local variable first, we are safe.
*/
if (sdata->hw_irq_trigger)
if (iio_trigger_using_own(indio_dev))
timestamp = sdata->hw_timestamp;
else
timestamp = iio_get_time_ns(indio_dev);

View File

@ -234,39 +234,35 @@ int st_sensors_power_enable(struct iio_dev *indio_dev)
int err;
/* Regulators not mandatory, but if requested we should enable them. */
pdata->vdd = devm_regulator_get_optional(indio_dev->dev.parent, "vdd");
if (!IS_ERR(pdata->vdd)) {
err = regulator_enable(pdata->vdd);
if (err != 0) {
dev_warn(&indio_dev->dev,
"Failed to enable specified Vdd supply\n");
return err;
}
} else {
err = PTR_ERR(pdata->vdd);
if (err != -ENODEV)
return err;
pdata->vdd = devm_regulator_get(indio_dev->dev.parent, "vdd");
if (IS_ERR(pdata->vdd)) {
dev_err(&indio_dev->dev, "unable to get Vdd supply\n");
return PTR_ERR(pdata->vdd);
}
err = regulator_enable(pdata->vdd);
if (err != 0) {
dev_warn(&indio_dev->dev,
"Failed to enable specified Vdd supply\n");
return err;
}
pdata->vdd_io = devm_regulator_get_optional(indio_dev->dev.parent, "vddio");
if (!IS_ERR(pdata->vdd_io)) {
err = regulator_enable(pdata->vdd_io);
if (err != 0) {
dev_warn(&indio_dev->dev,
"Failed to enable specified Vdd_IO supply\n");
goto st_sensors_disable_vdd;
}
} else {
pdata->vdd_io = devm_regulator_get(indio_dev->dev.parent, "vddio");
if (IS_ERR(pdata->vdd_io)) {
dev_err(&indio_dev->dev, "unable to get Vdd_IO supply\n");
err = PTR_ERR(pdata->vdd_io);
if (err != -ENODEV)
goto st_sensors_disable_vdd;
goto st_sensors_disable_vdd;
}
err = regulator_enable(pdata->vdd_io);
if (err != 0) {
dev_warn(&indio_dev->dev,
"Failed to enable specified Vdd_IO supply\n");
goto st_sensors_disable_vdd;
}
return 0;
st_sensors_disable_vdd:
if (!IS_ERR_OR_NULL(pdata->vdd))
regulator_disable(pdata->vdd);
regulator_disable(pdata->vdd);
return err;
}
EXPORT_SYMBOL(st_sensors_power_enable);
@ -275,11 +271,8 @@ void st_sensors_power_disable(struct iio_dev *indio_dev)
{
struct st_sensor_data *pdata = iio_priv(indio_dev);
if (!IS_ERR_OR_NULL(pdata->vdd))
regulator_disable(pdata->vdd);
if (!IS_ERR_OR_NULL(pdata->vdd_io))
regulator_disable(pdata->vdd_io);
regulator_disable(pdata->vdd);
regulator_disable(pdata->vdd_io);
}
EXPORT_SYMBOL(st_sensors_power_disable);

View File

@ -66,7 +66,7 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
* @irq: irq number
* @p: private handler data
*/
irqreturn_t st_sensors_irq_handler(int irq, void *p)
static irqreturn_t st_sensors_irq_handler(int irq, void *p)
{
struct iio_trigger *trig = p;
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
@ -82,7 +82,7 @@ irqreturn_t st_sensors_irq_handler(int irq, void *p)
* @irq: irq number
* @p: private handler data
*/
irqreturn_t st_sensors_irq_thread(int irq, void *p)
static irqreturn_t st_sensors_irq_thread(int irq, void *p)
{
struct iio_trigger *trig = p;
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);

View File

@ -190,6 +190,16 @@ config CIO_DAC
base port addresses for the devices may be configured via the base
array module parameter.
config AD8801
tristate "Analog Devices AD8801/AD8803 DAC driver"
depends on SPI_MASTER
help
Say yes here to build support for Analog Devices AD8801, AD8803 Digital to
Analog Converters (DAC).
To compile this driver as a module choose M here: the module will be called
ad8801.
config LPC18XX_DAC
tristate "NXP LPC18xx DAC driver"
depends on ARCH_LPC18XX || COMPILE_TEST
@ -254,16 +264,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

View File

@ -20,6 +20,7 @@ obj-$(CONFIG_AD5764) += ad5764.o
obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_AD7303) += ad7303.o
obj-$(CONFIG_AD8801) += ad8801.o
obj-$(CONFIG_CIO_DAC) += cio-dac.o
obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o
obj-$(CONFIG_M62332) += m62332.o
@ -27,5 +28,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

View File

@ -655,7 +655,7 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
devnr = 0;
for_each_child_of_node(np, pp) {
if (devnr > AD5755_NUM_CHANNELS) {
if (devnr >= AD5755_NUM_CHANNELS) {
dev_err(dev,
"There is to many channels defined in DT\n");
goto error_out;

239
drivers/iio/dac/ad8801.c Normal file
View File

@ -0,0 +1,239 @@
/*
* IIO DAC driver for Analog Devices AD8801 DAC
*
* Copyright (C) 2016 Gwenhael Goavec-Merou
* 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 <linux/iio/iio.h>
#include <linux/module.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/sysfs.h>
#define AD8801_CFG_ADDR_OFFSET 8
enum ad8801_device_ids {
ID_AD8801,
ID_AD8803,
};
struct ad8801_state {
struct spi_device *spi;
unsigned char dac_cache[8]; /* Value write on each channel */
unsigned int vrefh_mv;
unsigned int vrefl_mv;
struct regulator *vrefh_reg;
struct regulator *vrefl_reg;
__be16 data ____cacheline_aligned;
};
static int ad8801_spi_write(struct ad8801_state *state,
u8 channel, unsigned char value)
{
state->data = cpu_to_be16((channel << AD8801_CFG_ADDR_OFFSET) | value);
return spi_write(state->spi, &state->data, sizeof(state->data));
}
static int ad8801_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val, int val2, long mask)
{
struct ad8801_state *state = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (val >= 256 || val < 0)
return -EINVAL;
ret = ad8801_spi_write(state, chan->channel, val);
if (ret == 0)
state->dac_cache[chan->channel] = val;
break;
default:
ret = -EINVAL;
}
return ret;
}
static int ad8801_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long info)
{
struct ad8801_state *state = iio_priv(indio_dev);
switch (info) {
case IIO_CHAN_INFO_RAW:
*val = state->dac_cache[chan->channel];
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = state->vrefh_mv - state->vrefl_mv;
*val2 = 8;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_OFFSET:
*val = state->vrefl_mv;
return IIO_VAL_INT;
default:
return -EINVAL;
}
return -EINVAL;
}
static const struct iio_info ad8801_info = {
.read_raw = ad8801_read_raw,
.write_raw = ad8801_write_raw,
.driver_module = THIS_MODULE,
};
#define AD8801_CHANNEL(chan) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = chan, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_OFFSET), \
}
static const struct iio_chan_spec ad8801_channels[] = {
AD8801_CHANNEL(0),
AD8801_CHANNEL(1),
AD8801_CHANNEL(2),
AD8801_CHANNEL(3),
AD8801_CHANNEL(4),
AD8801_CHANNEL(5),
AD8801_CHANNEL(6),
AD8801_CHANNEL(7),
};
static int ad8801_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct ad8801_state *state;
const struct spi_device_id *id;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state));
if (indio_dev == NULL)
return -ENOMEM;
state = iio_priv(indio_dev);
state->spi = spi;
id = spi_get_device_id(spi);
state->vrefh_reg = devm_regulator_get(&spi->dev, "vrefh");
if (IS_ERR(state->vrefh_reg)) {
dev_err(&spi->dev, "Vrefh regulator not specified\n");
return PTR_ERR(state->vrefh_reg);
}
ret = regulator_enable(state->vrefh_reg);
if (ret) {
dev_err(&spi->dev, "Failed to enable vrefh regulator: %d\n",
ret);
return ret;
}
ret = regulator_get_voltage(state->vrefh_reg);
if (ret < 0) {
dev_err(&spi->dev, "Failed to read vrefh regulator: %d\n",
ret);
goto error_disable_vrefh_reg;
}
state->vrefh_mv = ret / 1000;
if (id->driver_data == ID_AD8803) {
state->vrefl_reg = devm_regulator_get(&spi->dev, "vrefl");
if (IS_ERR(state->vrefl_reg)) {
dev_err(&spi->dev, "Vrefl regulator not specified\n");
ret = PTR_ERR(state->vrefl_reg);
goto error_disable_vrefh_reg;
}
ret = regulator_enable(state->vrefl_reg);
if (ret) {
dev_err(&spi->dev, "Failed to enable vrefl regulator: %d\n",
ret);
goto error_disable_vrefh_reg;
}
ret = regulator_get_voltage(state->vrefl_reg);
if (ret < 0) {
dev_err(&spi->dev, "Failed to read vrefl regulator: %d\n",
ret);
goto error_disable_vrefl_reg;
}
state->vrefl_mv = ret / 1000;
} else {
state->vrefl_mv = 0;
state->vrefl_reg = NULL;
}
spi_set_drvdata(spi, indio_dev);
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &ad8801_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = ad8801_channels;
indio_dev->num_channels = ARRAY_SIZE(ad8801_channels);
indio_dev->name = id->name;
ret = iio_device_register(indio_dev);
if (ret) {
dev_err(&spi->dev, "Failed to register iio device: %d\n",
ret);
goto error_disable_vrefl_reg;
}
return 0;
error_disable_vrefl_reg:
if (state->vrefl_reg)
regulator_disable(state->vrefl_reg);
error_disable_vrefh_reg:
regulator_disable(state->vrefh_reg);
return ret;
}
static int ad8801_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad8801_state *state = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
if (state->vrefl_reg)
regulator_disable(state->vrefl_reg);
regulator_disable(state->vrefh_reg);
return 0;
}
static const struct spi_device_id ad8801_ids[] = {
{"ad8801", ID_AD8801},
{"ad8803", ID_AD8803},
{}
};
MODULE_DEVICE_TABLE(spi, ad8801_ids);
static struct spi_driver ad8801_driver = {
.driver = {
.name = "ad8801",
},
.probe = ad8801_probe,
.remove = ad8801_remove,
.id_table = ad8801_ids,
};
module_spi_driver(ad8801_driver);
MODULE_AUTHOR("Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>");
MODULE_DESCRIPTION("Analog Devices AD8801/AD8803 DAC");
MODULE_LICENSE("GPL v2");

View File

@ -1308,7 +1308,7 @@ static void devm_iio_device_release(struct device *dev, void *res)
iio_device_free(*(struct iio_dev **)res);
}
static int devm_iio_device_match(struct device *dev, void *res, void *data)
int devm_iio_device_match(struct device *dev, void *res, void *data)
{
struct iio_dev **r = res;
if (!r || !*r) {
@ -1317,6 +1317,7 @@ static int devm_iio_device_match(struct device *dev, void *res, void *data)
}
return *r == data;
}
EXPORT_SYMBOL_GPL(devm_iio_device_match);
/**
* devm_iio_device_alloc - Resource-managed iio_device_alloc()

View File

@ -57,6 +57,11 @@ bool iio_event_enabled(const struct iio_event_interface *ev_int)
*
* Note: The caller must make sure that this function is not running
* concurrently for the same indio_dev more than once.
*
* This function may be safely used as soon as a valid reference to iio_dev has
* been obtained via iio_device_alloc(), but any events that are submitted
* before iio_device_register() has successfully completed will be silently
* discarded.
**/
int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
{
@ -64,6 +69,9 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
struct iio_event_data ev;
int copied;
if (!ev_int)
return 0;
/* Does anyone care? */
if (iio_event_enabled(ev_int)) {

View File

@ -119,6 +119,22 @@ void iio_trigger_unregister(struct iio_trigger *trig_info)
}
EXPORT_SYMBOL(iio_trigger_unregister);
int iio_trigger_set_immutable(struct iio_dev *indio_dev, struct iio_trigger *trig)
{
if (!indio_dev || !trig)
return -EINVAL;
mutex_lock(&indio_dev->mlock);
WARN_ON(indio_dev->trig_readonly);
indio_dev->trig = iio_trigger_get(trig);
indio_dev->trig_readonly = true;
mutex_unlock(&indio_dev->mlock);
return 0;
}
EXPORT_SYMBOL(iio_trigger_set_immutable);
/* Search for trigger by name, assuming iio_trigger_list_lock held */
static struct iio_trigger *__iio_trigger_find_by_name(const char *name)
{
@ -255,6 +271,14 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
goto out_free_irq;
}
/*
* Check if we just registered to our own trigger: we determine that
* this is the case if the IIO device and the trigger device share the
* same parent device.
*/
if (pf->indio_dev->dev.parent == trig->dev.parent)
trig->attached_own_device = true;
return ret;
out_free_irq:
@ -279,6 +303,8 @@ static int iio_trigger_detach_poll_func(struct iio_trigger *trig,
if (ret)
return ret;
}
if (pf->indio_dev->dev.parent == trig->dev.parent)
trig->attached_own_device = false;
iio_trigger_put_irq(trig, pf->irq);
free_irq(pf->irq, pf);
module_put(pf->indio_dev->info->driver_module);
@ -384,6 +410,10 @@ static ssize_t iio_trigger_write_current(struct device *dev,
mutex_unlock(&indio_dev->mlock);
return -EBUSY;
}
if (indio_dev->trig_readonly) {
mutex_unlock(&indio_dev->mlock);
return -EPERM;
}
mutex_unlock(&indio_dev->mlock);
trig = iio_trigger_find_by_name(buf, len);
@ -622,6 +652,71 @@ void devm_iio_trigger_free(struct device *dev, struct iio_trigger *iio_trig)
}
EXPORT_SYMBOL_GPL(devm_iio_trigger_free);
static void devm_iio_trigger_unreg(struct device *dev, void *res)
{
iio_trigger_unregister(*(struct iio_trigger **)res);
}
/**
* devm_iio_trigger_register - Resource-managed iio_trigger_register()
* @dev: device this trigger was allocated for
* @trig_info: trigger to register
*
* Managed iio_trigger_register(). The IIO trigger registered with this
* function is automatically unregistered on driver detach. This function
* calls iio_trigger_register() internally. Refer to that function for more
* information.
*
* If an iio_trigger registered with this function needs to be unregistered
* separately, devm_iio_trigger_unregister() must be used.
*
* RETURNS:
* 0 on success, negative error number on failure.
*/
int devm_iio_trigger_register(struct device *dev, struct iio_trigger *trig_info)
{
struct iio_trigger **ptr;
int ret;
ptr = devres_alloc(devm_iio_trigger_unreg, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return -ENOMEM;
*ptr = trig_info;
ret = iio_trigger_register(trig_info);
if (!ret)
devres_add(dev, ptr);
else
devres_free(ptr);
return ret;
}
EXPORT_SYMBOL_GPL(devm_iio_trigger_register);
/**
* devm_iio_trigger_unregister - Resource-managed iio_trigger_unregister()
* @dev: device this iio_trigger belongs to
* @trig_info: the trigger associated with the device
*
* Unregister trigger registered with devm_iio_trigger_register().
*/
void devm_iio_trigger_unregister(struct device *dev,
struct iio_trigger *trig_info)
{
int rc;
rc = devres_release(dev, devm_iio_trigger_unreg, devm_iio_trigger_match,
trig_info);
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_iio_trigger_unregister);
bool iio_trigger_using_own(struct iio_dev *indio_dev)
{
return indio_dev->trig->attached_own_device;
}
EXPORT_SYMBOL(iio_trigger_using_own);
void iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
{
indio_dev->groups[indio_dev->groupcounter++] =

View File

@ -783,8 +783,7 @@ static int __exit ak8974_remove(struct i2c_client *i2c)
return 0;
}
#ifdef CONFIG_PM
static int ak8974_runtime_suspend(struct device *dev)
static int __maybe_unused ak8974_runtime_suspend(struct device *dev)
{
struct ak8974 *ak8974 =
iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
@ -795,7 +794,7 @@ static int ak8974_runtime_suspend(struct device *dev)
return 0;
}
static int ak8974_runtime_resume(struct device *dev)
static int __maybe_unused ak8974_runtime_resume(struct device *dev)
{
struct ak8974 *ak8974 =
iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
@ -822,7 +821,6 @@ out_regulator_disable:
return ret;
}
#endif /* CONFIG_PM */
static const struct dev_pm_ops ak8974_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
@ -847,7 +845,6 @@ MODULE_DEVICE_TABLE(of, ak8974_of_match);
static struct i2c_driver ak8974_driver = {
.driver = {
.name = "ak8974",
.owner = THIS_MODULE,
.pm = &ak8974_dev_pm_ops,
.of_match_table = of_match_ptr(ak8974_of_match),
},

View File

@ -416,8 +416,7 @@ static int ms5611_init(struct iio_dev *indio_dev)
return 0;
err_regulator_disable:
if (!IS_ERR_OR_NULL(st->vdd))
regulator_disable(st->vdd);
regulator_disable(st->vdd);
return ret;
}
@ -425,8 +424,7 @@ static void ms5611_fini(const struct iio_dev *indio_dev)
{
const struct ms5611_state *st = iio_priv(indio_dev);
if (!IS_ERR_OR_NULL(st->vdd))
regulator_disable(st->vdd);
regulator_disable(st->vdd);
}
int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,

View File

@ -1025,6 +1025,12 @@ static const struct acpi_device_id sx9500_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, sx9500_acpi_match);
static const struct of_device_id sx9500_of_match[] = {
{ .compatible = "semtech,sx9500", },
{ }
};
MODULE_DEVICE_TABLE(of, sx9500_of_match);
static const struct i2c_device_id sx9500_id[] = {
{"sx9500", 0},
{ },
@ -1035,6 +1041,7 @@ static struct i2c_driver sx9500_driver = {
.driver = {
.name = SX9500_DRIVER_NAME,
.acpi_match_table = ACPI_PTR(sx9500_acpi_match),
.of_match_table = of_match_ptr(sx9500_of_match),
.pm = &sx9500_pm_ops,
},
.probe = sx9500_probe,

View File

@ -32,7 +32,7 @@ enum {
MAX31855,
};
const struct iio_chan_spec max6675_channels[] = {
static const struct iio_chan_spec max6675_channels[] = {
{ /* thermocouple temperature */
.type = IIO_TEMP,
.info_mask_separate =
@ -49,7 +49,7 @@ const struct iio_chan_spec max6675_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(1),
};
const struct iio_chan_spec max31855_channels[] = {
static const struct iio_chan_spec max31855_channels[] = {
{ /* thermocouple temperature */
.type = IIO_TEMP,
.address = 2,
@ -95,7 +95,7 @@ struct maxim_thermocouple_chip {
u32 status_bit;
};
const struct maxim_thermocouple_chip maxim_thermocouple_chips[] = {
static const struct maxim_thermocouple_chip maxim_thermocouple_chips[] = {
[MAX6675] = {
.channels = max6675_channels,
.num_channels = ARRAY_SIZE(max6675_channels),

View File

@ -412,7 +412,7 @@ static const struct iio_event_spec sca3000_event = {
}, \
.event_spec = &sca3000_event, \
.num_event_specs = 1, \
}
}
static const struct iio_chan_spec sca3000_channels[] = {
SCA3000_CHAN(0, IIO_MOD_X),

View File

@ -483,6 +483,7 @@ struct iio_buffer_setup_ops {
* @scan_timestamp: [INTERN] set if any buffers have requested timestamp
* @scan_index_timestamp:[INTERN] cache of the index to the timestamp
* @trig: [INTERN] current device trigger (buffer modes)
* @trig_readonly [INTERN] mark the current trigger immutable
* @pollfunc: [DRIVER] function run on trigger being received
* @pollfunc_event: [DRIVER] function run on events trigger being received
* @channels: [DRIVER] channel specification structure table
@ -523,6 +524,7 @@ struct iio_dev {
bool scan_timestamp;
unsigned scan_index_timestamp;
struct iio_trigger *trig;
bool trig_readonly;
struct iio_poll_func *pollfunc;
struct iio_poll_func *pollfunc_event;
@ -642,6 +644,7 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv)
}
void iio_device_free(struct iio_dev *indio_dev);
int devm_iio_device_match(struct device *dev, void *res, void *data);
struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv);
void devm_iio_device_free(struct device *dev, struct iio_dev *indio_dev);
struct iio_trigger *devm_iio_trigger_alloc(struct device *dev,

View File

@ -56,6 +56,9 @@ struct iio_trigger_ops {
* @subirqs: [INTERN] information about the 'child' irqs.
* @pool: [INTERN] bitmap of irqs currently in use.
* @pool_lock: [INTERN] protection of the irq pool.
* @attached_own_device:[INTERN] if we are using our own device as trigger,
* i.e. if we registered a poll function to the same
* device as the one providing the trigger.
**/
struct iio_trigger {
const struct iio_trigger_ops *ops;
@ -73,6 +76,7 @@ struct iio_trigger {
struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER];
unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)];
struct mutex pool_lock;
bool attached_own_device;
};
@ -125,12 +129,27 @@ static inline void *iio_trigger_get_drvdata(struct iio_trigger *trig)
**/
int iio_trigger_register(struct iio_trigger *trig_info);
int devm_iio_trigger_register(struct device *dev,
struct iio_trigger *trig_info);
/**
* iio_trigger_unregister() - unregister a trigger from the core
* @trig_info: trigger to be unregistered
**/
void iio_trigger_unregister(struct iio_trigger *trig_info);
void devm_iio_trigger_unregister(struct device *dev,
struct iio_trigger *trig_info);
/**
* iio_trigger_set_immutable() - set an immutable trigger on destination
*
* @indio_dev - IIO device structure containing the device
* @trig - trigger to assign to device
*
**/
int iio_trigger_set_immutable(struct iio_dev *indio_dev, struct iio_trigger *trig);
/**
* iio_trigger_poll() - called on a trigger occurring
* @trig: trigger which occurred
@ -145,6 +164,13 @@ irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private);
__printf(1, 2) struct iio_trigger *iio_trigger_alloc(const char *fmt, ...);
void iio_trigger_free(struct iio_trigger *trig);
/**
* iio_trigger_using_own() - tells us if we use our own HW trigger ourselves
* @indio_dev: device to check
*/
bool iio_trigger_using_own(struct iio_dev *indio_dev);
#else
struct iio_trigger;
struct iio_trigger_ops;

View File

@ -12,4 +12,12 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev,
const struct iio_buffer_setup_ops *setup_ops);
void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev);
int devm_iio_triggered_buffer_setup(struct device *dev,
struct iio_dev *indio_dev,
irqreturn_t (*h)(int irq, void *p),
irqreturn_t (*thread)(int irq, void *p),
const struct iio_buffer_setup_ops *ops);
void devm_iio_triggered_buffer_cleanup(struct device *dev,
struct iio_dev *indio_dev);
#endif

View File

@ -121,10 +121,6 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
ret = -ENOENT;
while (ent = readdir(dp), ent)
/*
* Do we allow devices to override a generic name with
* a specific one?
*/
if ((strcmp(builtname, ent->d_name) == 0) ||
(strcmp(builtname_generic, ent->d_name) == 0)) {
ret = asprintf(&filename,
@ -178,6 +174,13 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
sysfsfp = 0;
free(filename);
filename = 0;
/*
* Avoid having a more generic entry overwriting
* the settings.
*/
if (strcmp(builtname, ent->d_name) == 0)
break;
}
error_close_sysfsfp: