mirror of
https://github.com/suyu-emu/horinux.git
synced 2026-09-21 14:15:21 -07:00
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:
@@ -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>
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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()
|
||||
|
||||
+2
-2
@@ -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>
|
||||
|
||||
@@ -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},
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 = <c2485_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");
|
||||
@@ -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");
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
+166
-35
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user