Commit aabb4060 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-4.8a' of...

Merge tag 'iio-for-4.8a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

Jonathan writes:

First round of IIO new device support, features and cleanups for the 4.8 cycle.

New device support
* ads1015
  - add ads1115 support
* bma220 accelerometer
  - new driver
  - triggered buffer support.
* bmc150
  - add bmm150 support.
* bmp280
  - bme280 support with addition of humidity channel.
* max5487 potentiometer
  - new driver
* MMA7660FC accelerometer.
  - New driver
* st-pressure
  - support for the lps22hb
* loop trigger.
  - This one is *nasty* but we have real applications (parrot drones) where
  it is useful.  The trigger basically spins as hard as it can firing off
  a new trigger each time all triggered devices come back to say they are
  done.  It doesn't hang a machine even when doing it on a dummy driver.
  A lot nicer than having this implemented within lots of device drivers
  anyway.

Core stuff
* Add support to create IIO devices via configfs (similar to we did for
triggers a while back) + docs.
* New channel types
  - IIO_ELECTRICAL_CONDUCTIVITY
* Couple of MAINTAINERS patches to list the device tree bindings.
* Make trigger ops structure non optional (comment fix). It hasn't been for
an awful long time, but that's not what the description said.

New features
* ak8975
  - support adapters that are limited to byte data only by allowing the
  emulated block read i2c function that was recently introduced.
* atlas-ph
  - support atlas-ec (electrical conductivity sensor)
* bmi160
  - add available frequency and scale attributes to make the driver
  more user friendly (and avoid having to read the datasheet to know
  what will work).
* dummy
  - move creation to configfs interface.  It's not real hardware so we
  are not that worried about the ABI breakage ;)
* mma8452
  - oversampling ration support
* nau7802
  - expose available gains to make life easier for userspace.
* st-sensors
  - allow use of emulation for SMBus block reads as all the st parts support
  it.
* ti-ads1015
  - list datasheet names to allow their use by inkernel consumers.
* Various module alias additions to help auto probing.  Drop one redundant one
as well.

Cleanups
* ad7266, ad7476, ad7887, ad7923, ad799x
  - use direct mode claim function rather than open coding it during sensor
  read (prevents switching on buffers mid read).
* ad7793, ad7791
  - use direct mode claim to prevent frequency changes when buffers running.
* afe440x - These are ABI breaking but the driver requires custom userspace
  code to do anything useful anyway and that is still being written and under
  control of TI.  Ultimately we may have other libraries to do pulse
  oximetry with these devices but we aren't aware of any yet.
  - kernel-doc format fixes
  - drop ifdef fun around of_match_ptr - it's not worth the mess to save
  a tiny amount of space.
  - drop some unnecessary register initializations.
  - drop the weird locked gain modes as they gain us nothing (can just set
  all gains separately).
  - remove handling of offset attributes seeing as no channels actually have
  them (oops)
  - Drop the LED3 input channel as it's an alias for ALED2.
  - *big one* remove channel names - an experiment that turned out to not
  make sense - see patch for details.
  - use regmap fields to clean up code.
  - tie the tia gain stages to appropriate channels in the ABI as that is
  what they really effect. Same with the LED currents.
  - cleanout some unused defines and fix a missnamed one.
* atlas-ph
  - reorganise to allow support of other similar parts.
* bmc150
  - document supported chips in kconfig help.
* jsa1212
  - drop an unneeded i2c functionality check for functionality the driver
  doesn't use.
* mxs-lradc
  - simply touch screen registration code.
  - remove the touch screen unregister as all devm based now.
  - disable only those channels that are masked in hardware stop (others
  are already dealt with elsewhere)
* st-sensors
  - unexport st_sensors_get_buffer_element as nothing outside the st-sensors
  core driver uses it.
  - fix handling of failure to start up regulators.
* tpl0102
  - drop an i2c functionality test for features that aren't needed.
* ti-am335x
  - use variable name rather than type in sizeof for clarity.
  - use SIMPLE_DEV_PM_OPS helper macro to tidy up a bit.

Tools
* Add install / uninstall to makefile.  Someone cares, so presumably
some people will find it useful!
*  generic_buffer
   - rename to iio_generic_buffer to line up with other tools.
   - handle cleanup when receiving signals
   - Add a --device-num option and a --trigger-num option rather than
   relying on naming which doesn't work if you have two of the same part.
parents 73e81350 bc2e1126
...@@ -19,3 +19,16 @@ KernelVersion: 4.4 ...@@ -19,3 +19,16 @@ KernelVersion: 4.4
Description: Description:
High resolution timers directory. Creating a directory here High resolution timers directory. Creating a directory here
will result in creating a hrtimer trigger in the IIO subsystem. will result in creating a hrtimer trigger in the IIO subsystem.
What: /config/iio/devices
Date: April 2016
KernelVersion: 4.7
Description:
Industrial IO software devices directory.
What: /config/iio/devices/dummy
Date: April 2016
KernelVersion: 4.7
Description:
Dummy IIO devices directory. Creating a directory here will result
in creating a dummy IIO device in the IIO subystem.
...@@ -1565,3 +1565,10 @@ Description: ...@@ -1565,3 +1565,10 @@ Description:
* X is in the plane of the propellers, perpendicular to Y axis, * X is in the plane of the propellers, perpendicular to Y axis,
and positive towards the starboard side of the UAV ; and positive towards the starboard side of the UAV ;
* Z is perpendicular to propellers plane and positive upwards. * Z is perpendicular to propellers plane and positive upwards.
What: /sys/bus/iio/devices/iio:deviceX/in_electricalconductivity_raw
KernelVersion: 4.8
Contact: linux-iio@vger.kernel.org
Description:
Raw (unscaled no offset etc.) electric conductivity reading that
can be processed to siemens per meter.
What: /sys/bus/iio/devices/iio:deviceX/tia_resistanceY What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_raw
/sys/bus/iio/devices/iio:deviceX/tia_capacitanceY Date: May 2016
Date: December 2015
KernelVersion:
Contact: Andrew F. Davis <afd@ti.com>
Description:
Get and set the resistance and the capacitance settings for the
Transimpedance Amplifier. Y is 1 for Rf1 and Cf1, Y is 2 for
Rf2 and Cf2 values.
What: /sys/bus/iio/devices/iio:deviceX/tia_separate_en
Date: December 2015
KernelVersion:
Contact: Andrew F. Davis <afd@ti.com>
Description:
Enable or disable separate settings for the TransImpedance
Amplifier above, when disabled both values are set by the
first channel.
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_ledY_raw
/sys/bus/iio/devices/iio:deviceX/in_intensity_ledY_ambient_raw
Date: December 2015
KernelVersion: KernelVersion:
Contact: Andrew F. Davis <afd@ti.com> Contact: Andrew F. Davis <afd@ti.com>
Description: Description:
Get measured values from the ADC for these stages. Y is the Get measured values from the ADC for these stages. Y is the
specific LED number. The values are expressed in 24-bit twos specific stage number corresponding to datasheet stage names
complement. as follows:
1 -> LED2
2 -> ALED2/LED3
3 -> LED1
4 -> ALED1/LED4
Note that channels 5 and 6 represent LED2-ALED2 and LED1-ALED1
respectively which simply helper channels containing the
calculated difference in the value of stage 1 - 2 and 3 - 4.
The values are expressed in 24-bit twos complement.
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_ledY-ledY_ambient_raw What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_offset
Date: December 2015 Date: May 2016
KernelVersion: KernelVersion:
Contact: Andrew F. Davis <afd@ti.com> Contact: Andrew F. Davis <afd@ti.com>
Description: Description:
Get differential values from the ADC for these stages. Y is the Get and set the offset cancellation DAC setting for these
specific LED number. The values are expressed in 24-bit twos stages. The values are expressed in 5-bit sign-magnitude.
complement for the specified LEDs.
What: /sys/bus/iio/devices/iio:deviceX/out_current_ledY_offset What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_resistance
/sys/bus/iio/devices/iio:deviceX/out_current_ledY_ambient_offset What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_capacitance
Date: December 2015 Date: May 2016
KernelVersion: KernelVersion:
Contact: Andrew F. Davis <afd@ti.com> Contact: Andrew F. Davis <afd@ti.com>
Description: Description:
Get and set the offset cancellation DAC setting for these Get and set the resistance and the capacitance settings for the
stages. The values are expressed in 5-bit sign-magnitude. Transimpedance Amplifier during the associated stage.
What: /sys/bus/iio/devices/iio:deviceX/out_current_ledY_raw What: /sys/bus/iio/devices/iio:deviceX/out_currentY_raw
Date: December 2015 Date: May 2016
KernelVersion: KernelVersion:
Contact: Andrew F. Davis <afd@ti.com> Contact: Andrew F. Davis <afd@ti.com>
Description: Description:
Get and set the LED current for the specified LED. Y is the Get and set the LED current for the specified LED active during
specific LED number. this stage. Y is the specific stage number.
* Atlas Scientific EC-SM OEM sensor
http://www.atlas-scientific.com/_files/_datasheets/_oem/EC_oem_datasheet.pdf
Required properties:
- compatible: must be "atlas,ec-sm"
- reg: the I2C address of the sensor
- 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.
Example:
atlas@64 {
compatible = "atlas,ec-sm";
reg = <0x64>;
interrupt-parent = <&gpio1>;
interrupts = <16 2>;
};
...@@ -64,3 +64,4 @@ Pressure sensors: ...@@ -64,3 +64,4 @@ Pressure sensors:
- st,lps001wp-press - st,lps001wp-press
- st,lps25h-press - st,lps25h-press
- st,lps331ap-press - st,lps331ap-press
- st,lps22hb-press
...@@ -5773,6 +5773,7 @@ R: Lars-Peter Clausen <lars@metafoo.de> ...@@ -5773,6 +5773,7 @@ R: Lars-Peter Clausen <lars@metafoo.de>
R: Peter Meerwald-Stadler <pmeerw@pmeerw.net> R: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
L: linux-iio@vger.kernel.org L: linux-iio@vger.kernel.org
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/iio/
F: drivers/iio/ F: drivers/iio/
F: drivers/staging/iio/ F: drivers/staging/iio/
F: include/linux/iio/ F: include/linux/iio/
...@@ -10841,6 +10842,7 @@ STAGING - INDUSTRIAL IO ...@@ -10841,6 +10842,7 @@ STAGING - INDUSTRIAL IO
M: Jonathan Cameron <jic23@kernel.org> M: Jonathan Cameron <jic23@kernel.org>
L: linux-iio@vger.kernel.org L: linux-iio@vger.kernel.org
S: Odd Fixes S: Odd Fixes
F: Documentation/devicetree/bindings/staging/iio/
F: drivers/staging/iio/ F: drivers/staging/iio/
STAGING - LIRC (LINUX INFRARED REMOTE CONTROL) DRIVERS STAGING - LIRC (LINUX INFRARED REMOTE CONTROL) DRIVERS
......
...@@ -46,6 +46,14 @@ config IIO_CONSUMERS_PER_TRIGGER ...@@ -46,6 +46,14 @@ config IIO_CONSUMERS_PER_TRIGGER
This value controls the maximum number of consumers that a This value controls the maximum number of consumers that a
given trigger may handle. Default is 2. given trigger may handle. Default is 2.
config IIO_SW_DEVICE
tristate "Enable software IIO device support"
select IIO_CONFIGFS
help
Provides IIO core support for software devices. A software
device can be created via configfs or directly by a driver
using the API provided.
config IIO_SW_TRIGGER config IIO_SW_TRIGGER
tristate "Enable software triggers support" tristate "Enable software triggers support"
select IIO_CONFIGFS select IIO_CONFIGFS
......
...@@ -8,6 +8,7 @@ industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o ...@@ -8,6 +8,7 @@ industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o
industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
obj-$(CONFIG_IIO_CONFIGFS) += industrialio-configfs.o obj-$(CONFIG_IIO_CONFIGFS) += industrialio-configfs.o
obj-$(CONFIG_IIO_SW_DEVICE) += industrialio-sw-device.o
obj-$(CONFIG_IIO_SW_TRIGGER) += industrialio-sw-trigger.o obj-$(CONFIG_IIO_SW_TRIGGER) += industrialio-sw-trigger.o
obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o
......
...@@ -17,6 +17,16 @@ config BMA180 ...@@ -17,6 +17,16 @@ config BMA180
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called bma180. module will be called bma180.
config BMA220
tristate "Bosch BMA220 3-Axis Accelerometer Driver"
depends on SPI
help
Say yes here to add support for the Bosch BMA220 triaxial
acceleration sensor.
To compile this driver as a module, choose M here: the
module will be called bma220_spi.
config BMC150_ACCEL config BMC150_ACCEL
tristate "Bosch BMC150 Accelerometer Driver" tristate "Bosch BMC150 Accelerometer Driver"
select IIO_BUFFER select IIO_BUFFER
...@@ -136,6 +146,16 @@ config MMA7455_SPI ...@@ -136,6 +146,16 @@ config MMA7455_SPI
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called mma7455_spi. will be called mma7455_spi.
config MMA7660
tristate "Freescale MMA7660FC 3-Axis Accelerometer Driver"
depends on I2C
help
Say yes here to get support for the Freescale MMA7660FC 3-Axis
accelerometer.
Choosing M will build the driver as a module. If so, the module
will be called mma7660.
config MMA8452 config MMA8452
tristate "Freescale MMA8452Q and similar Accelerometers Driver" tristate "Freescale MMA8452Q and similar Accelerometers Driver"
depends on I2C depends on I2C
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
# When adding new entries keep the list in alphabetical order # When adding new entries keep the list in alphabetical order
obj-$(CONFIG_BMA180) += bma180.o obj-$(CONFIG_BMA180) += bma180.o
obj-$(CONFIG_BMA220) += bma220_spi.o
obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
...@@ -15,6 +16,8 @@ obj-$(CONFIG_MMA7455) += mma7455_core.o ...@@ -15,6 +16,8 @@ obj-$(CONFIG_MMA7455) += mma7455_core.o
obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o
obj-$(CONFIG_MMA7455_SPI) += mma7455_spi.o obj-$(CONFIG_MMA7455_SPI) += mma7455_spi.o
obj-$(CONFIG_MMA7660) += mma7660.o
obj-$(CONFIG_MMA8452) += mma8452.o obj-$(CONFIG_MMA8452) += mma8452.o
obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o
......
/**
* BMA220 Digital triaxial acceleration sensor driver
*
* Copyright (c) 2016, Intel Corporation.
*
* 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.
*/
#include <linux/acpi.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/spi/spi.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#define BMA220_REG_ID 0x00
#define BMA220_REG_ACCEL_X 0x02
#define BMA220_REG_ACCEL_Y 0x03
#define BMA220_REG_ACCEL_Z 0x04
#define BMA220_REG_RANGE 0x11
#define BMA220_REG_SUSPEND 0x18
#define BMA220_CHIP_ID 0xDD
#define BMA220_READ_MASK 0x80
#define BMA220_RANGE_MASK 0x03
#define BMA220_DATA_SHIFT 2
#define BMA220_SUSPEND_SLEEP 0xFF
#define BMA220_SUSPEND_WAKE 0x00
#define BMA220_DEVICE_NAME "bma220"
#define BMA220_SCALE_AVAILABLE "0.623 1.248 2.491 4.983"
#define BMA220_ACCEL_CHANNEL(index, reg, axis) { \
.type = IIO_ACCEL, \
.address = reg, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.scan_index = index, \
.scan_type = { \
.sign = 's', \
.realbits = 6, \
.storagebits = 8, \
.shift = BMA220_DATA_SHIFT, \
.endianness = IIO_CPU, \
}, \
}
enum bma220_axis {
AXIS_X,
AXIS_Y,
AXIS_Z,
};
static IIO_CONST_ATTR(in_accel_scale_available, BMA220_SCALE_AVAILABLE);
static struct attribute *bma220_attributes[] = {
&iio_const_attr_in_accel_scale_available.dev_attr.attr,
NULL,
};
static const struct attribute_group bma220_attribute_group = {
.attrs = bma220_attributes,
};
static const int bma220_scale_table[][4] = {
{0, 623000}, {1, 248000}, {2, 491000}, {4, 983000}
};
struct bma220_data {
struct spi_device *spi_device;
struct mutex lock;
s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 8x8 timestamp */
u8 tx_buf[2] ____cacheline_aligned;
};
static const struct iio_chan_spec bma220_channels[] = {
BMA220_ACCEL_CHANNEL(0, BMA220_REG_ACCEL_X, X),
BMA220_ACCEL_CHANNEL(1, BMA220_REG_ACCEL_Y, Y),
BMA220_ACCEL_CHANNEL(2, BMA220_REG_ACCEL_Z, Z),
IIO_CHAN_SOFT_TIMESTAMP(3),
};
static inline int bma220_read_reg(struct spi_device *spi, u8 reg)
{
return spi_w8r8(spi, reg | BMA220_READ_MASK);
}
static const unsigned long bma220_accel_scan_masks[] = {
BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
0
};
static irqreturn_t bma220_trigger_handler(int irq, void *p)
{
int ret;
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bma220_data *data = iio_priv(indio_dev);
struct spi_device *spi = data->spi_device;
mutex_lock(&data->lock);
data->tx_buf[0] = BMA220_REG_ACCEL_X | BMA220_READ_MASK;
ret = spi_write_then_read(spi, data->tx_buf, 1, data->buffer,
ARRAY_SIZE(bma220_channels) - 1);
if (ret < 0)
goto err;
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
pf->timestamp);
err:
mutex_unlock(&data->lock);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
static int bma220_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
int ret;
u8 range_idx;
struct bma220_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
ret = bma220_read_reg(data->spi_device, chan->address);
if (ret < 0)
return -EINVAL;
*val = sign_extend32(ret >> BMA220_DATA_SHIFT, 5);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
ret = bma220_read_reg(data->spi_device, BMA220_REG_RANGE);
if (ret < 0)
return ret;
range_idx = ret & BMA220_RANGE_MASK;
*val = bma220_scale_table[range_idx][0];
*val2 = bma220_scale_table[range_idx][1];
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
static int bma220_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
int i;
int ret;
int index = -1;
struct bma220_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_SCALE:
for (i = 0; i < ARRAY_SIZE(bma220_scale_table); i++)
if (val == bma220_scale_table[i][0] &&
val2 == bma220_scale_table[i][1]) {
index = i;
break;
}
if (index < 0)
return -EINVAL;
mutex_lock(&data->lock);
data->tx_buf[0] = BMA220_REG_RANGE;
data->tx_buf[1] = index;
ret = spi_write(data->spi_device, data->tx_buf,
sizeof(data->tx_buf));
if (ret < 0)
dev_err(&data->spi_device->dev,
"failed to set measurement range\n");
mutex_unlock(&data->lock);
return 0;
}
return -EINVAL;
}
static const struct iio_info bma220_info = {
.driver_module = THIS_MODULE,
.read_raw = bma220_read_raw,
.write_raw = bma220_write_raw,
.attrs = &bma220_attribute_group,
};
static int bma220_init(struct spi_device *spi)
{
int ret;
ret = bma220_read_reg(spi, BMA220_REG_ID);
if (ret != BMA220_CHIP_ID)
return -ENODEV;
/* Make sure the chip is powered on */
ret = bma220_read_reg(spi, BMA220_REG_SUSPEND);
if (ret < 0)
return ret;
else if (ret == BMA220_SUSPEND_WAKE)
return bma220_read_reg(spi, BMA220_REG_SUSPEND);
return 0;
}
static int bma220_deinit(struct spi_device *spi)
{
int ret;
/* Make sure the chip is powered off */
ret = bma220_read_reg(spi, BMA220_REG_SUSPEND);
if (ret < 0)
return ret;
else if (ret == BMA220_SUSPEND_SLEEP)
return bma220_read_reg(spi, BMA220_REG_SUSPEND);
return 0;
}
static int bma220_probe(struct spi_device *spi)
{
int ret;
struct iio_dev *indio_dev;
struct bma220_data *data;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));
if (!indio_dev) {
dev_err(&spi->dev, "iio allocation failed!\n");
return -ENOMEM;
}
data = iio_priv(indio_dev);
data->spi_device = spi;
spi_set_drvdata(spi, indio_dev);
mutex_init(&data->lock);
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &bma220_info;
indio_dev->name = BMA220_DEVICE_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = bma220_channels;
indio_dev->num_channels = ARRAY_SIZE(bma220_channels);
indio_dev->available_scan_masks = bma220_accel_scan_masks;
ret = bma220_init(data->spi_device);
if (ret < 0)
return ret;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
bma220_trigger_handler, NULL);
if (ret < 0) {
dev_err(&spi->dev, "iio triggered buffer setup failed\n");
goto err_suspend;
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&spi->dev, "iio_device_register failed\n");
iio_triggered_buffer_cleanup(indio_dev);
goto err_suspend;
}
return 0;
err_suspend:
return bma220_deinit(spi);
}
static int bma220_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
return bma220_deinit(spi);
}
#ifdef CONFIG_PM_SLEEP
static int bma220_suspend(struct device *dev)
{
struct bma220_data *data =
iio_priv(spi_get_drvdata(to_spi_device(dev)));
/* The chip can be suspended/woken up by a simple register read. */
return bma220_read_reg(data->spi_device, BMA220_REG_SUSPEND);
}
static int bma220_resume(struct device *dev)
{
struct bma220_data *data =
iio_priv(spi_get_drvdata(to_spi_device(dev)));
return bma220_read_reg(data->spi_device, BMA220_REG_SUSPEND);
}
static SIMPLE_DEV_PM_OPS(bma220_pm_ops, bma220_suspend, bma220_resume);
#define BMA220_PM_OPS (&bma220_pm_ops)
#else
#define BMA220_PM_OPS NULL
#endif
static const struct spi_device_id bma220_spi_id[] = {
{"bma220", 0},
{}
};
static const struct acpi_device_id bma220_acpi_id[] = {
{"BMA0220", 0},
{}
};
MODULE_DEVICE_TABLE(spi, bma220_spi_id);
static struct spi_driver bma220_driver = {
.driver = {
.name = "bma220_spi",
.pm = BMA220_PM_OPS,
.acpi_match_table = ACPI_PTR(bma220_acpi_id),
},
.probe = bma220_probe,
.remove = bma220_remove,
.id_table = bma220_spi_id,
};
module_spi_driver(bma220_driver);
MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>");
MODULE_DESCRIPTION("BMA220 acceleration sensor driver");
MODULE_LICENSE("GPL v2");
/**
* Freescale MMA7660FC 3-Axis Accelerometer
*
* Copyright (c) 2016, Intel Corporation.
*
* 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.
*
* IIO driver for Freescale MMA7660FC; 7-bit I2C address: 0x4c.
*/
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define MMA7660_DRIVER_NAME "mma7660"
#define MMA7660_REG_XOUT 0x00
#define MMA7660_REG_YOUT 0x01
#define MMA7660_REG_ZOUT 0x02
#define MMA7660_REG_OUT_BIT_ALERT BIT(6)
#define MMA7660_REG_MODE 0x07
#define MMA7660_REG_MODE_BIT_MODE BIT(0)
#define MMA7660_REG_MODE_BIT_TON BIT(2)
#define MMA7660_I2C_READ_RETRIES 5
/*
* The accelerometer has one measurement range:
*
* -1.5g - +1.5g (6-bit, signed)
*
* scale = (1.5 + 1.5) * 9.81 / (2^6 - 1) = 0.467142857
*/
#define MMA7660_SCALE_AVAIL "0.467142857"
const int mma7660_nscale = 467142857;
#define MMA7660_CHANNEL(reg, axis) { \
.type = IIO_ACCEL, \
.address = reg, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec mma7660_channels[] = {
MMA7660_CHANNEL(MMA7660_REG_XOUT, X),
MMA7660_CHANNEL(MMA7660_REG_YOUT, Y),
MMA7660_CHANNEL(MMA7660_REG_ZOUT, Z),
};
enum mma7660_mode {
MMA7660_MODE_STANDBY,
MMA7660_MODE_ACTIVE
};
struct mma7660_data {
struct i2c_client *client;
struct mutex lock;
enum mma7660_mode mode;
};
static IIO_CONST_ATTR(in_accel_scale_available, MMA7660_SCALE_AVAIL);
static struct attribute *mma7660_attributes[] = {
&iio_const_attr_in_accel_scale_available.dev_attr.attr,
NULL,
};
static const struct attribute_group mma7660_attribute_group = {
.attrs = mma7660_attributes
};
static int mma7660_set_mode(struct mma7660_data *data,
enum mma7660_mode mode)
{
int ret;
struct i2c_client *client = data->client;
if (mode == data->mode)
return 0;
ret = i2c_smbus_read_byte_data(client, MMA7660_REG_MODE);
if (ret < 0) {
dev_err(&client->dev, "failed to read sensor mode\n");
return ret;
}
if (mode == MMA7660_MODE_ACTIVE) {
ret &= ~MMA7660_REG_MODE_BIT_TON;
ret |= MMA7660_REG_MODE_BIT_MODE;
} else {
ret &= ~MMA7660_REG_MODE_BIT_TON;
ret &= ~MMA7660_REG_MODE_BIT_MODE;
}
ret = i2c_smbus_write_byte_data(client, MMA7660_REG_MODE, ret);
if (ret < 0) {
dev_err(&client->dev, "failed to change sensor mode\n");
return ret;
}
data->mode = mode;
return ret;
}
static int mma7660_read_accel(struct mma7660_data *data, u8 address)
{
int ret, retries = MMA7660_I2C_READ_RETRIES;
struct i2c_client *client = data->client;
/*
* Read data. If the Alert bit is set, the register was read at
* the same time as the device was attempting to update the content.
* The solution is to read the register again. Do this only
* MMA7660_I2C_READ_RETRIES times to avoid spending too much time
* in the kernel.
*/
do {
ret = i2c_smbus_read_byte_data(client, address);
if (ret < 0) {
dev_err(&client->dev, "register read failed\n");
return ret;
}
} while (retries-- > 0 && ret & MMA7660_REG_OUT_BIT_ALERT);
if (ret & MMA7660_REG_OUT_BIT_ALERT) {
dev_err(&client->dev, "all register read retries failed\n");
return -ETIMEDOUT;
}
return ret;
}
static int mma7660_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct mma7660_data *data = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&data->lock);
ret = mma7660_read_accel(data, chan->address);
mutex_unlock(&data->lock);
if (ret < 0)
return ret;
*val = sign_extend32(ret, 5);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = mma7660_nscale;
return IIO_VAL_INT_PLUS_NANO;
default:
return -EINVAL;
}
return -EINVAL;
}
static const struct iio_info mma7660_info = {
.driver_module = THIS_MODULE,
.read_raw = mma7660_read_raw,
.attrs = &mma7660_attribute_group,
};
static int mma7660_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
struct iio_dev *indio_dev;
struct mma7660_data *data;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev) {
dev_err(&client->dev, "iio allocation failed!\n");
return -ENOMEM;
}
data = iio_priv(indio_dev);
data->client = client;
i2c_set_clientdata(client, indio_dev);
mutex_init(&data->lock);
data->mode = MMA7660_MODE_STANDBY;
indio_dev->dev.parent = &client->dev;
indio_dev->info = &mma7660_info;
indio_dev->name = MMA7660_DRIVER_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = mma7660_channels;
indio_dev->num_channels = ARRAY_SIZE(mma7660_channels);
ret = mma7660_set_mode(data, MMA7660_MODE_ACTIVE);
if (ret < 0)
return ret;
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "device_register failed\n");
mma7660_set_mode(data, MMA7660_MODE_STANDBY);
}
return ret;
}
static int mma7660_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
return mma7660_set_mode(iio_priv(indio_dev), MMA7660_MODE_STANDBY);
}
#ifdef CONFIG_PM_SLEEP
static int mma7660_suspend(struct device *dev)
{
struct mma7660_data *data;
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
return mma7660_set_mode(data, MMA7660_MODE_STANDBY);
}
static int mma7660_resume(struct device *dev)
{
struct mma7660_data *data;
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
return mma7660_set_mode(data, MMA7660_MODE_ACTIVE);
}
static SIMPLE_DEV_PM_OPS(mma7660_pm_ops, mma7660_suspend, mma7660_resume);
#define MMA7660_PM_OPS (&mma7660_pm_ops)
#else
#define MMA7660_PM_OPS NULL
#endif
static const struct i2c_device_id mma7660_i2c_id[] = {
{"mma7660", 0},
{}
};
static const struct acpi_device_id mma7660_acpi_id[] = {
{"MMA7660", 0},
{}
};
MODULE_DEVICE_TABLE(acpi, mma7660_acpi_id);
static struct i2c_driver mma7660_driver = {
.driver = {
.name = "mma7660",
.pm = MMA7660_PM_OPS,
.acpi_match_table = ACPI_PTR(mma7660_acpi_id),
},
.probe = mma7660_probe,
.remove = mma7660_remove,
.id_table = mma7660_i2c_id,
};
module_i2c_driver(mma7660_driver);
MODULE_AUTHOR("Constantin Musca <constantin.musca@intel.com>");
MODULE_DESCRIPTION("Freescale MMA7660FC 3-Axis Accelerometer driver");
MODULE_LICENSE("GPL v2");
This diff is collapsed.
...@@ -757,13 +757,15 @@ int st_accel_common_probe(struct iio_dev *indio_dev) ...@@ -757,13 +757,15 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
indio_dev->info = &accel_info; indio_dev->info = &accel_info;
mutex_init(&adata->tb.buf_lock); mutex_init(&adata->tb.buf_lock);
st_sensors_power_enable(indio_dev); err = st_sensors_power_enable(indio_dev);
if (err)
return err;
err = st_sensors_check_device_support(indio_dev, err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_accel_sensors_settings), ARRAY_SIZE(st_accel_sensors_settings),
st_accel_sensors_settings); st_accel_sensors_settings);
if (err < 0) if (err < 0)
return err; goto st_accel_power_off;
adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS; adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS;
adata->multiread_bit = adata->sensor_settings->multi_read_bit; adata->multiread_bit = adata->sensor_settings->multi_read_bit;
...@@ -780,11 +782,11 @@ int st_accel_common_probe(struct iio_dev *indio_dev) ...@@ -780,11 +782,11 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
err = st_sensors_init_sensor(indio_dev, adata->dev->platform_data); err = st_sensors_init_sensor(indio_dev, adata->dev->platform_data);
if (err < 0) if (err < 0)
return err; goto st_accel_power_off;
err = st_accel_allocate_ring(indio_dev); err = st_accel_allocate_ring(indio_dev);
if (err < 0) if (err < 0)
return err; goto st_accel_power_off;
if (irq > 0) { if (irq > 0) {
err = st_sensors_allocate_trigger(indio_dev, err = st_sensors_allocate_trigger(indio_dev,
...@@ -807,6 +809,8 @@ int st_accel_common_probe(struct iio_dev *indio_dev) ...@@ -807,6 +809,8 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
st_sensors_deallocate_trigger(indio_dev); st_sensors_deallocate_trigger(indio_dev);
st_accel_probe_trigger_error: st_accel_probe_trigger_error:
st_accel_deallocate_ring(indio_dev); st_accel_deallocate_ring(indio_dev);
st_accel_power_off:
st_sensors_power_disable(indio_dev);
return err; return err;
} }
......
...@@ -154,12 +154,11 @@ static int ad7266_read_raw(struct iio_dev *indio_dev, ...@@ -154,12 +154,11 @@ static int ad7266_read_raw(struct iio_dev *indio_dev,
switch (m) { switch (m) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
if (iio_buffer_enabled(indio_dev)) ret = iio_device_claim_direct_mode(indio_dev);
return -EBUSY;
ret = ad7266_read_single(st, val, chan->address);
if (ret) if (ret)
return ret; return ret;
ret = ad7266_read_single(st, val, chan->address);
iio_device_release_direct_mode(indio_dev);
*val = (*val >> 2) & 0xfff; *val = (*val >> 2) & 0xfff;
if (chan->scan_type.sign == 's') if (chan->scan_type.sign == 's')
......
...@@ -106,12 +106,11 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, ...@@ -106,12 +106,11 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
switch (m) { switch (m) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) if (ret)
ret = -EBUSY; return ret;
else ret = ad7476_scan_direct(st);
ret = ad7476_scan_direct(st); iio_device_release_direct_mode(indio_dev);
mutex_unlock(&indio_dev->mlock);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -272,30 +272,22 @@ static ssize_t ad7791_write_frequency(struct device *dev, ...@@ -272,30 +272,22 @@ static ssize_t ad7791_write_frequency(struct device *dev,
struct ad7791_state *st = iio_priv(indio_dev); struct ad7791_state *st = iio_priv(indio_dev);
int i, ret; int i, ret;
mutex_lock(&indio_dev->mlock); for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++)
if (iio_buffer_enabled(indio_dev)) { if (sysfs_streq(ad7791_sample_freq_avail[i], buf))
mutex_unlock(&indio_dev->mlock);
return -EBUSY;
}
mutex_unlock(&indio_dev->mlock);
ret = -EINVAL;
for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) {
if (sysfs_streq(ad7791_sample_freq_avail[i], buf)) {
mutex_lock(&indio_dev->mlock);
st->filter &= ~AD7791_FILTER_RATE_MASK;
st->filter |= i;
ad_sd_write_reg(&st->sd, AD7791_REG_FILTER,
sizeof(st->filter), st->filter);
mutex_unlock(&indio_dev->mlock);
ret = 0;
break; break;
} if (i == ARRAY_SIZE(ad7791_sample_freq_avail))
} return -EINVAL;
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
st->filter &= ~AD7791_FILTER_RATE_MASK;
st->filter |= i;
ad_sd_write_reg(&st->sd, AD7791_REG_FILTER, sizeof(st->filter),
st->filter);
iio_device_release_direct_mode(indio_dev);
return ret ? ret : len; return len;
} }
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
......
...@@ -369,13 +369,6 @@ static ssize_t ad7793_write_frequency(struct device *dev, ...@@ -369,13 +369,6 @@ static ssize_t ad7793_write_frequency(struct device *dev,
long lval; long lval;
int i, ret; int i, ret;
mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) {
mutex_unlock(&indio_dev->mlock);
return -EBUSY;
}
mutex_unlock(&indio_dev->mlock);
ret = kstrtol(buf, 10, &lval); ret = kstrtol(buf, 10, &lval);
if (ret) if (ret)
return ret; return ret;
...@@ -383,20 +376,21 @@ static ssize_t ad7793_write_frequency(struct device *dev, ...@@ -383,20 +376,21 @@ static ssize_t ad7793_write_frequency(struct device *dev,
if (lval == 0) if (lval == 0)
return -EINVAL; return -EINVAL;
ret = -EINVAL;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
if (lval == st->chip_info->sample_freq_avail[i]) { if (lval == st->chip_info->sample_freq_avail[i])
mutex_lock(&indio_dev->mlock); break;
st->mode &= ~AD7793_MODE_RATE(-1); if (i == 16)
st->mode |= AD7793_MODE_RATE(i); return -EINVAL;
ad_sd_write_reg(&st->sd, AD7793_REG_MODE,
sizeof(st->mode), st->mode);
mutex_unlock(&indio_dev->mlock);
ret = 0;
}
return ret ? ret : len; ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
st->mode &= ~AD7793_MODE_RATE(-1);
st->mode |= AD7793_MODE_RATE(i);
ad_sd_write_reg(&st->sd, AD7793_REG_MODE, sizeof(st->mode), st->mode);
iio_device_release_direct_mode(indio_dev);
return len;
} }
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
......
...@@ -156,12 +156,11 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, ...@@ -156,12 +156,11 @@ static int ad7887_read_raw(struct iio_dev *indio_dev,
switch (m) { switch (m) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) if (ret)
ret = -EBUSY; return ret;
else ret = ad7887_scan_direct(st, chan->address);
ret = ad7887_scan_direct(st, chan->address); iio_device_release_direct_mode(indio_dev);
mutex_unlock(&indio_dev->mlock);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -233,12 +233,11 @@ static int ad7923_read_raw(struct iio_dev *indio_dev, ...@@ -233,12 +233,11 @@ static int ad7923_read_raw(struct iio_dev *indio_dev,
switch (m) { switch (m) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) if (ret)
ret = -EBUSY; return ret;
else ret = ad7923_scan_direct(st, chan->address);
ret = ad7923_scan_direct(st, chan->address); iio_device_release_direct_mode(indio_dev);
mutex_unlock(&indio_dev->mlock);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -282,12 +282,11 @@ static int ad799x_read_raw(struct iio_dev *indio_dev, ...@@ -282,12 +282,11 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
switch (m) { switch (m) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) if (ret)
ret = -EBUSY; return ret;
else ret = ad799x_scan_direct(st, chan->scan_index);
ret = ad799x_scan_direct(st, chan->scan_index); iio_device_release_direct_mode(indio_dev);
mutex_unlock(&indio_dev->mlock);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -395,11 +394,9 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev, ...@@ -395,11 +394,9 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev,
struct ad799x_state *st = iio_priv(indio_dev); struct ad799x_state *st = iio_priv(indio_dev);
int ret; int ret;
mutex_lock(&indio_dev->mlock); ret = iio_device_claim_direct_mode(indio_dev);
if (iio_buffer_enabled(indio_dev)) { if (ret)
ret = -EBUSY; return ret;
goto done;
}
if (state) if (state)
st->config |= BIT(chan->scan_index) << AD799X_CHANNEL_SHIFT; st->config |= BIT(chan->scan_index) << AD799X_CHANNEL_SHIFT;
...@@ -412,10 +409,7 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev, ...@@ -412,10 +409,7 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev,
st->config &= ~AD7998_ALERT_EN; st->config &= ~AD7998_ALERT_EN;
ret = ad799x_write_config(st, st->config); ret = ad799x_write_config(st, st->config);
iio_device_release_direct_mode(indio_dev);
done:
mutex_unlock(&indio_dev->mlock);
return ret; return ret;
} }
......
...@@ -373,13 +373,6 @@ static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc) ...@@ -373,13 +373,6 @@ static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc)
return LRADC_CTRL0_MX28_PLATE_MASK; return LRADC_CTRL0_MX28_PLATE_MASK;
} }
static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc)
{
if (lradc->soc == IMX23_LRADC)
return LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK;
return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK;
}
static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc) static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc)
{ {
if (lradc->soc == IMX23_LRADC) if (lradc->soc == IMX23_LRADC)
...@@ -1120,18 +1113,16 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc) ...@@ -1120,18 +1113,16 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc)
{ {
struct input_dev *input; struct input_dev *input;
struct device *dev = lradc->dev; struct device *dev = lradc->dev;
int ret;
if (!lradc->use_touchscreen) if (!lradc->use_touchscreen)
return 0; return 0;
input = input_allocate_device(); input = devm_input_allocate_device(dev);
if (!input) if (!input)
return -ENOMEM; return -ENOMEM;
input->name = DRIVER_NAME; input->name = DRIVER_NAME;
input->id.bustype = BUS_HOST; input->id.bustype = BUS_HOST;
input->dev.parent = dev;
input->open = mxs_lradc_ts_open; input->open = mxs_lradc_ts_open;
input->close = mxs_lradc_ts_close; input->close = mxs_lradc_ts_close;
...@@ -1146,20 +1137,8 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc) ...@@ -1146,20 +1137,8 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc)
lradc->ts_input = input; lradc->ts_input = input;
input_set_drvdata(input, lradc); input_set_drvdata(input, lradc);
ret = input_register_device(input);
if (ret)
input_free_device(lradc->ts_input);
return ret;
}
static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc)
{
if (!lradc->use_touchscreen)
return;
mxs_lradc_disable_ts(lradc); return input_register_device(input);
input_unregister_device(lradc->ts_input);
} }
/* /*
...@@ -1510,7 +1489,9 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc) ...@@ -1510,7 +1489,9 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc)
{ {
int i; int i;
mxs_lradc_reg_clear(lradc, mxs_lradc_irq_en_mask(lradc), LRADC_CTRL1); mxs_lradc_reg_clear(lradc,
lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET,
LRADC_CTRL1);
for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++) for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++)
mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i)); mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i));
...@@ -1721,13 +1702,11 @@ static int mxs_lradc_probe(struct platform_device *pdev) ...@@ -1721,13 +1702,11 @@ static int mxs_lradc_probe(struct platform_device *pdev)
ret = iio_device_register(iio); ret = iio_device_register(iio);
if (ret) { if (ret) {
dev_err(dev, "Failed to register IIO device\n"); dev_err(dev, "Failed to register IIO device\n");
goto err_ts; return ret;
} }
return 0; return 0;
err_ts:
mxs_lradc_ts_unregister(lradc);
err_ts_register: err_ts_register:
mxs_lradc_hw_stop(lradc); mxs_lradc_hw_stop(lradc);
err_dev: err_dev:
...@@ -1745,7 +1724,6 @@ static int mxs_lradc_remove(struct platform_device *pdev) ...@@ -1745,7 +1724,6 @@ static int mxs_lradc_remove(struct platform_device *pdev)
struct mxs_lradc *lradc = iio_priv(iio); struct mxs_lradc *lradc = iio_priv(iio);
iio_device_unregister(iio); iio_device_unregister(iio);
mxs_lradc_ts_unregister(lradc);
mxs_lradc_hw_stop(lradc); mxs_lradc_hw_stop(lradc);
mxs_lradc_trigger_remove(iio); mxs_lradc_trigger_remove(iio);
iio_triggered_buffer_cleanup(iio); iio_triggered_buffer_cleanup(iio);
......
...@@ -79,10 +79,29 @@ static const struct iio_chan_spec nau7802_chan_array[] = { ...@@ -79,10 +79,29 @@ static const struct iio_chan_spec nau7802_chan_array[] = {
static const u16 nau7802_sample_freq_avail[] = {10, 20, 40, 80, static const u16 nau7802_sample_freq_avail[] = {10, 20, 40, 80,
10, 10, 10, 320}; 10, 10, 10, 320};
static ssize_t nau7802_show_scales(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct nau7802_state *st = iio_priv(dev_to_iio_dev(dev));
int i, len = 0;
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
len += scnprintf(buf + len, PAGE_SIZE - len, "0.%09d ",
st->scale_avail[i]);
buf[len-1] = '\n';
return len;
}
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 40 80 320"); static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 40 80 320");
static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO, nau7802_show_scales,
NULL, 0);
static struct attribute *nau7802_attributes[] = { static struct attribute *nau7802_attributes[] = {
&iio_const_attr_sampling_frequency_available.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_in_voltage_scale_available.dev_attr.attr,
NULL NULL
}; };
......
...@@ -55,6 +55,11 @@ ...@@ -55,6 +55,11 @@
#define ADS1015_DEFAULT_DATA_RATE 4 #define ADS1015_DEFAULT_DATA_RATE 4
#define ADS1015_DEFAULT_CHAN 0 #define ADS1015_DEFAULT_CHAN 0
enum {
ADS1015,
ADS1115,
};
enum ads1015_channels { enum ads1015_channels {
ADS1015_AIN0_AIN1 = 0, ADS1015_AIN0_AIN1 = 0,
ADS1015_AIN0_AIN3, ADS1015_AIN0_AIN3,
...@@ -71,6 +76,10 @@ static const unsigned int ads1015_data_rate[] = { ...@@ -71,6 +76,10 @@ static const unsigned int ads1015_data_rate[] = {
128, 250, 490, 920, 1600, 2400, 3300, 3300 128, 250, 490, 920, 1600, 2400, 3300, 3300
}; };
static const unsigned int ads1115_data_rate[] = {
8, 16, 32, 64, 128, 250, 475, 860
};
static const struct { static const struct {
int scale; int scale;
int uscale; int uscale;
...@@ -101,6 +110,7 @@ static const struct { ...@@ -101,6 +110,7 @@ static const struct {
.shift = 4, \ .shift = 4, \
.endianness = IIO_CPU, \ .endianness = IIO_CPU, \
}, \ }, \
.datasheet_name = "AIN"#_chan, \
} }
#define ADS1015_V_DIFF_CHAN(_chan, _chan2, _addr) { \ #define ADS1015_V_DIFF_CHAN(_chan, _chan2, _addr) { \
...@@ -121,6 +131,45 @@ static const struct { ...@@ -121,6 +131,45 @@ static const struct {
.shift = 4, \ .shift = 4, \
.endianness = IIO_CPU, \ .endianness = IIO_CPU, \
}, \ }, \
.datasheet_name = "AIN"#_chan"-AIN"#_chan2, \
}
#define ADS1115_V_CHAN(_chan, _addr) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.address = _addr, \
.channel = _chan, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.scan_index = _addr, \
.scan_type = { \
.sign = 's', \
.realbits = 16, \
.storagebits = 16, \
.endianness = IIO_CPU, \
}, \
.datasheet_name = "AIN"#_chan, \
}
#define ADS1115_V_DIFF_CHAN(_chan, _chan2, _addr) { \
.type = IIO_VOLTAGE, \
.differential = 1, \
.indexed = 1, \
.address = _addr, \
.channel = _chan, \
.channel2 = _chan2, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.scan_index = _addr, \
.scan_type = { \
.sign = 's', \
.realbits = 16, \
.storagebits = 16, \
.endianness = IIO_CPU, \
}, \
.datasheet_name = "AIN"#_chan"-AIN"#_chan2, \
} }
struct ads1015_data { struct ads1015_data {
...@@ -131,6 +180,8 @@ struct ads1015_data { ...@@ -131,6 +180,8 @@ struct ads1015_data {
*/ */
struct mutex lock; struct mutex lock;
struct ads1015_channel_data channel_data[ADS1015_CHANNELS]; struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
unsigned int *data_rate;
}; };
static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg) static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg)
...@@ -157,6 +208,18 @@ static const struct iio_chan_spec ads1015_channels[] = { ...@@ -157,6 +208,18 @@ static const struct iio_chan_spec ads1015_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP), IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP),
}; };
static const struct iio_chan_spec ads1115_channels[] = {
ADS1115_V_DIFF_CHAN(0, 1, ADS1015_AIN0_AIN1),
ADS1115_V_DIFF_CHAN(0, 3, ADS1015_AIN0_AIN3),
ADS1115_V_DIFF_CHAN(1, 3, ADS1015_AIN1_AIN3),
ADS1115_V_DIFF_CHAN(2, 3, ADS1015_AIN2_AIN3),
ADS1115_V_CHAN(0, ADS1015_AIN0),
ADS1115_V_CHAN(1, ADS1015_AIN1),
ADS1115_V_CHAN(2, ADS1015_AIN2),
ADS1115_V_CHAN(3, ADS1015_AIN3),
IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP),
};
static int ads1015_set_power_state(struct ads1015_data *data, bool on) static int ads1015_set_power_state(struct ads1015_data *data, bool on)
{ {
int ret; int ret;
...@@ -196,7 +259,7 @@ int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val) ...@@ -196,7 +259,7 @@ int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val)
return ret; return ret;
if (change) { if (change) {
conv_time = DIV_ROUND_UP(USEC_PER_SEC, ads1015_data_rate[dr]); conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]);
usleep_range(conv_time, conv_time + 1); usleep_range(conv_time, conv_time + 1);
} }
...@@ -263,7 +326,7 @@ static int ads1015_set_data_rate(struct ads1015_data *data, int chan, int rate) ...@@ -263,7 +326,7 @@ static int ads1015_set_data_rate(struct ads1015_data *data, int chan, int rate)
int i, ret, rindex = -1; int i, ret, rindex = -1;
for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++) for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++)
if (ads1015_data_rate[i] == rate) { if (data->data_rate[i] == rate) {
rindex = i; rindex = i;
break; break;
} }
...@@ -291,7 +354,9 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, ...@@ -291,7 +354,9 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
mutex_lock(&data->lock); mutex_lock(&data->lock);
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW: {
int shift = chan->scan_type.shift;
if (iio_buffer_enabled(indio_dev)) { if (iio_buffer_enabled(indio_dev)) {
ret = -EBUSY; ret = -EBUSY;
break; break;
...@@ -307,8 +372,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, ...@@ -307,8 +372,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
break; break;
} }
/* 12 bit res, D0 is bit 4 in conversion register */ *val = sign_extend32(*val >> shift, 15 - shift);
*val = sign_extend32(*val >> 4, 11);
ret = ads1015_set_power_state(data, false); ret = ads1015_set_power_state(data, false);
if (ret < 0) if (ret < 0)
...@@ -316,6 +380,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, ...@@ -316,6 +380,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
ret = IIO_VAL_INT; ret = IIO_VAL_INT;
break; break;
}
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
idx = data->channel_data[chan->address].pga; idx = data->channel_data[chan->address].pga;
*val = ads1015_scale[idx].scale; *val = ads1015_scale[idx].scale;
...@@ -324,7 +389,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, ...@@ -324,7 +389,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
break; break;
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
idx = data->channel_data[chan->address].data_rate; idx = data->channel_data[chan->address].data_rate;
*val = ads1015_data_rate[idx]; *val = data->data_rate[idx];
ret = IIO_VAL_INT; ret = IIO_VAL_INT;
break; break;
default: default:
...@@ -380,12 +445,15 @@ static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = { ...@@ -380,12 +445,15 @@ static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = {
}; };
static IIO_CONST_ATTR(scale_available, "3 2 1 0.5 0.25 0.125"); static IIO_CONST_ATTR(scale_available, "3 2 1 0.5 0.25 0.125");
static IIO_CONST_ATTR(sampling_frequency_available,
"128 250 490 920 1600 2400 3300"); static IIO_CONST_ATTR_NAMED(ads1015_sampling_frequency_available,
sampling_frequency_available, "128 250 490 920 1600 2400 3300");
static IIO_CONST_ATTR_NAMED(ads1115_sampling_frequency_available,
sampling_frequency_available, "8 16 32 64 128 250 475 860");
static struct attribute *ads1015_attributes[] = { static struct attribute *ads1015_attributes[] = {
&iio_const_attr_scale_available.dev_attr.attr, &iio_const_attr_scale_available.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr, &iio_const_attr_ads1015_sampling_frequency_available.dev_attr.attr,
NULL, NULL,
}; };
...@@ -393,11 +461,28 @@ static const struct attribute_group ads1015_attribute_group = { ...@@ -393,11 +461,28 @@ static const struct attribute_group ads1015_attribute_group = {
.attrs = ads1015_attributes, .attrs = ads1015_attributes,
}; };
static const struct iio_info ads1015_info = { static struct attribute *ads1115_attributes[] = {
&iio_const_attr_scale_available.dev_attr.attr,
&iio_const_attr_ads1115_sampling_frequency_available.dev_attr.attr,
NULL,
};
static const struct attribute_group ads1115_attribute_group = {
.attrs = ads1115_attributes,
};
static struct iio_info ads1015_info = {
.driver_module = THIS_MODULE,
.read_raw = ads1015_read_raw,
.write_raw = ads1015_write_raw,
.attrs = &ads1015_attribute_group,
};
static struct iio_info ads1115_info = {
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
.read_raw = ads1015_read_raw, .read_raw = ads1015_read_raw,
.write_raw = ads1015_write_raw, .write_raw = ads1015_write_raw,
.attrs = &ads1015_attribute_group, .attrs = &ads1115_attribute_group,
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -500,12 +585,24 @@ static int ads1015_probe(struct i2c_client *client, ...@@ -500,12 +585,24 @@ static int ads1015_probe(struct i2c_client *client,
mutex_init(&data->lock); mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev; indio_dev->dev.parent = &client->dev;
indio_dev->info = &ads1015_info;
indio_dev->name = ADS1015_DRV_NAME; indio_dev->name = ADS1015_DRV_NAME;
indio_dev->channels = ads1015_channels;
indio_dev->num_channels = ARRAY_SIZE(ads1015_channels);
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
switch (id->driver_data) {
case ADS1015:
indio_dev->channels = ads1015_channels;
indio_dev->num_channels = ARRAY_SIZE(ads1015_channels);
indio_dev->info = &ads1015_info;
data->data_rate = (unsigned int *) &ads1015_data_rate;
break;
case ADS1115:
indio_dev->channels = ads1115_channels;
indio_dev->num_channels = ARRAY_SIZE(ads1115_channels);
indio_dev->info = &ads1115_info;
data->data_rate = (unsigned int *) &ads1115_data_rate;
break;
}
/* we need to keep this ABI the same as used by hwmon ADS1015 driver */ /* we need to keep this ABI the same as used by hwmon ADS1015 driver */
ads1015_get_channels_config(client); ads1015_get_channels_config(client);
...@@ -590,7 +687,8 @@ static const struct dev_pm_ops ads1015_pm_ops = { ...@@ -590,7 +687,8 @@ static const struct dev_pm_ops ads1015_pm_ops = {
}; };
static const struct i2c_device_id ads1015_id[] = { static const struct i2c_device_id ads1015_id[] = {
{"ads1015", 0}, {"ads1015", ADS1015},
{"ads1115", ADS1115},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, ads1015_id); MODULE_DEVICE_TABLE(i2c, ads1015_id);
......
...@@ -326,8 +326,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) ...@@ -326,8 +326,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
int i; int i;
indio_dev->num_channels = channels; indio_dev->num_channels = channels;
chan_array = kcalloc(channels, chan_array = kcalloc(channels, sizeof(*chan_array), GFP_KERNEL);
sizeof(struct iio_chan_spec), GFP_KERNEL);
if (chan_array == NULL) if (chan_array == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -467,8 +466,7 @@ static int tiadc_probe(struct platform_device *pdev) ...@@ -467,8 +466,7 @@ static int tiadc_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
indio_dev = devm_iio_device_alloc(&pdev->dev, indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*indio_dev));
sizeof(struct tiadc_device));
if (indio_dev == NULL) { if (indio_dev == NULL) {
dev_err(&pdev->dev, "failed to allocate iio device\n"); dev_err(&pdev->dev, "failed to allocate iio device\n");
return -ENOMEM; return -ENOMEM;
...@@ -531,8 +529,7 @@ static int tiadc_remove(struct platform_device *pdev) ...@@ -531,8 +529,7 @@ static int tiadc_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM static int __maybe_unused tiadc_suspend(struct device *dev)
static int tiadc_suspend(struct device *dev)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct tiadc_device *adc_dev = iio_priv(indio_dev); struct tiadc_device *adc_dev = iio_priv(indio_dev);
...@@ -550,7 +547,7 @@ static int tiadc_suspend(struct device *dev) ...@@ -550,7 +547,7 @@ static int tiadc_suspend(struct device *dev)
return 0; return 0;
} }
static int tiadc_resume(struct device *dev) static int __maybe_unused tiadc_resume(struct device *dev)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct tiadc_device *adc_dev = iio_priv(indio_dev); struct tiadc_device *adc_dev = iio_priv(indio_dev);
...@@ -567,14 +564,7 @@ static int tiadc_resume(struct device *dev) ...@@ -567,14 +564,7 @@ static int tiadc_resume(struct device *dev)
return 0; return 0;
} }
static const struct dev_pm_ops tiadc_pm_ops = { static SIMPLE_DEV_PM_OPS(tiadc_pm_ops, tiadc_suspend, tiadc_resume);
.suspend = tiadc_suspend,
.resume = tiadc_resume,
};
#define TIADC_PM_OPS (&tiadc_pm_ops)
#else
#define TIADC_PM_OPS NULL
#endif
static const struct of_device_id ti_adc_dt_ids[] = { static const struct of_device_id ti_adc_dt_ids[] = {
{ .compatible = "ti,am3359-adc", }, { .compatible = "ti,am3359-adc", },
...@@ -585,7 +575,7 @@ MODULE_DEVICE_TABLE(of, ti_adc_dt_ids); ...@@ -585,7 +575,7 @@ MODULE_DEVICE_TABLE(of, ti_adc_dt_ids);
static struct platform_driver tiadc_driver = { static struct platform_driver tiadc_driver = {
.driver = { .driver = {
.name = "TI-am335x-adc", .name = "TI-am335x-adc",
.pm = TIADC_PM_OPS, .pm = &tiadc_pm_ops,
.of_match_table = ti_adc_dt_ids, .of_match_table = ti_adc_dt_ids,
}, },
.probe = tiadc_probe, .probe = tiadc_probe,
......
...@@ -5,15 +5,17 @@ ...@@ -5,15 +5,17 @@
menu "Chemical Sensors" menu "Chemical Sensors"
config ATLAS_PH_SENSOR config ATLAS_PH_SENSOR
tristate "Atlas Scientific OEM pH-SM sensor" tristate "Atlas Scientific OEM SM sensors"
depends on I2C depends on I2C
select REGMAP_I2C select REGMAP_I2C
select IIO_BUFFER select IIO_BUFFER
select IIO_TRIGGERED_BUFFER select IIO_TRIGGERED_BUFFER
select IRQ_WORK select IRQ_WORK
help help
Say Y here to build I2C interface support for the Atlas Say Y here to build I2C interface support for the following
Scientific OEM pH-SM sensor. Atlas Scientific OEM SM sensors:
* pH SM sensor
* EC SM sensor
To compile this driver as module, choose M here: the To compile this driver as module, choose M here: the
module will be called atlas-ph-sensor. module will be called atlas-ph-sensor.
......
This diff is collapsed.
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors.h>
int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
{ {
int i, len; int i, len;
int total = 0; int total = 0;
...@@ -49,7 +49,6 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) ...@@ -49,7 +49,6 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
return total; return total;
} }
EXPORT_SYMBOL(st_sensors_get_buffer_element);
irqreturn_t st_sensors_trigger_handler(int irq, void *p) irqreturn_t st_sensors_trigger_handler(int irq, void *p)
{ {
......
...@@ -228,7 +228,7 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable) ...@@ -228,7 +228,7 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable)
} }
EXPORT_SYMBOL(st_sensors_set_axis_enable); EXPORT_SYMBOL(st_sensors_set_axis_enable);
void st_sensors_power_enable(struct iio_dev *indio_dev) int st_sensors_power_enable(struct iio_dev *indio_dev)
{ {
struct st_sensor_data *pdata = iio_priv(indio_dev); struct st_sensor_data *pdata = iio_priv(indio_dev);
int err; int err;
...@@ -237,18 +237,37 @@ void st_sensors_power_enable(struct iio_dev *indio_dev) ...@@ -237,18 +237,37 @@ void st_sensors_power_enable(struct iio_dev *indio_dev)
pdata->vdd = devm_regulator_get_optional(indio_dev->dev.parent, "vdd"); pdata->vdd = devm_regulator_get_optional(indio_dev->dev.parent, "vdd");
if (!IS_ERR(pdata->vdd)) { if (!IS_ERR(pdata->vdd)) {
err = regulator_enable(pdata->vdd); err = regulator_enable(pdata->vdd);
if (err != 0) if (err != 0) {
dev_warn(&indio_dev->dev, dev_warn(&indio_dev->dev,
"Failed to enable specified Vdd supply\n"); "Failed to enable specified Vdd supply\n");
return err;
}
} else {
err = PTR_ERR(pdata->vdd);
if (err != -ENODEV)
return err;
} }
pdata->vdd_io = devm_regulator_get_optional(indio_dev->dev.parent, "vddio"); pdata->vdd_io = devm_regulator_get_optional(indio_dev->dev.parent, "vddio");
if (!IS_ERR(pdata->vdd_io)) { if (!IS_ERR(pdata->vdd_io)) {
err = regulator_enable(pdata->vdd_io); err = regulator_enable(pdata->vdd_io);
if (err != 0) if (err != 0) {
dev_warn(&indio_dev->dev, dev_warn(&indio_dev->dev,
"Failed to enable specified Vdd_IO supply\n"); "Failed to enable specified Vdd_IO supply\n");
goto st_sensors_disable_vdd;
}
} else {
err = PTR_ERR(pdata->vdd_io);
if (err != -ENODEV)
goto st_sensors_disable_vdd;
} }
return 0;
st_sensors_disable_vdd:
if (!IS_ERR_OR_NULL(pdata->vdd))
regulator_disable(pdata->vdd);
return err;
} }
EXPORT_SYMBOL(st_sensors_power_enable); EXPORT_SYMBOL(st_sensors_power_enable);
...@@ -256,10 +275,10 @@ void st_sensors_power_disable(struct iio_dev *indio_dev) ...@@ -256,10 +275,10 @@ void st_sensors_power_disable(struct iio_dev *indio_dev)
{ {
struct st_sensor_data *pdata = iio_priv(indio_dev); struct st_sensor_data *pdata = iio_priv(indio_dev);
if (!IS_ERR(pdata->vdd)) if (!IS_ERR_OR_NULL(pdata->vdd))
regulator_disable(pdata->vdd); regulator_disable(pdata->vdd);
if (!IS_ERR(pdata->vdd_io)) if (!IS_ERR_OR_NULL(pdata->vdd_io))
regulator_disable(pdata->vdd_io); regulator_disable(pdata->vdd_io);
} }
EXPORT_SYMBOL(st_sensors_power_disable); EXPORT_SYMBOL(st_sensors_power_disable);
......
...@@ -48,8 +48,8 @@ static int st_sensors_i2c_read_multiple_byte( ...@@ -48,8 +48,8 @@ static int st_sensors_i2c_read_multiple_byte(
if (multiread_bit) if (multiread_bit)
reg_addr |= ST_SENSORS_I2C_MULTIREAD; reg_addr |= ST_SENSORS_I2C_MULTIREAD;
return i2c_smbus_read_i2c_block_data(to_i2c_client(dev), return i2c_smbus_read_i2c_block_data_or_emulated(to_i2c_client(dev),
reg_addr, len, data); reg_addr, len, data);
} }
static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb, static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb,
......
...@@ -10,6 +10,7 @@ config IIO_DUMMY_EVGEN ...@@ -10,6 +10,7 @@ config IIO_DUMMY_EVGEN
config IIO_SIMPLE_DUMMY config IIO_SIMPLE_DUMMY
tristate "An example driver with no hardware requirements" tristate "An example driver with no hardware requirements"
depends on IIO_SW_DEVICE
help help
Driver intended mainly as documentation for how to write Driver intended mainly as documentation for how to write
a driver. May also be useful for testing userspace code a driver. May also be useful for testing userspace code
......
...@@ -17,26 +17,18 @@ ...@@ -17,26 +17,18 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <linux/iio/events.h> #include <linux/iio/events.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/iio/sw_device.h>
#include "iio_simple_dummy.h" #include "iio_simple_dummy.h"
/* static struct config_item_type iio_dummy_type = {
* A few elements needed to fake a bus for this driver .ct_owner = THIS_MODULE,
* Note instances parameter controls how many of these };
* dummy devices are registered.
*/
static unsigned instances = 1;
module_param(instances, uint, 0);
/* Pointer array used to fake bus elements */
static struct iio_dev **iio_dummy_devs;
/* Fake a name for the part number, usually obtained from the id table */
static const char *iio_dummy_part_number = "iio_dummy_part_no";
/** /**
* struct iio_dummy_accel_calibscale - realworld to register mapping * struct iio_dummy_accel_calibscale - realworld to register mapping
...@@ -572,12 +564,18 @@ static int iio_dummy_init_device(struct iio_dev *indio_dev) ...@@ -572,12 +564,18 @@ static int iio_dummy_init_device(struct iio_dev *indio_dev)
* const struct i2c_device_id *id) * const struct i2c_device_id *id)
* SPI: iio_dummy_probe(struct spi_device *spi) * SPI: iio_dummy_probe(struct spi_device *spi)
*/ */
static int iio_dummy_probe(int index) static struct iio_sw_device *iio_dummy_probe(const char *name)
{ {
int ret; int ret;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct iio_dummy_state *st; struct iio_dummy_state *st;
struct iio_sw_device *swd;
swd = kzalloc(sizeof(*swd), GFP_KERNEL);
if (!swd) {
ret = -ENOMEM;
goto error_kzalloc;
}
/* /*
* Allocate an IIO device. * Allocate an IIO device.
* *
...@@ -608,7 +606,7 @@ static int iio_dummy_probe(int index) ...@@ -608,7 +606,7 @@ static int iio_dummy_probe(int index)
* i2c_set_clientdata(client, indio_dev); * i2c_set_clientdata(client, indio_dev);
* spi_set_drvdata(spi, indio_dev); * spi_set_drvdata(spi, indio_dev);
*/ */
iio_dummy_devs[index] = indio_dev; swd->device = indio_dev;
/* /*
* Set the device name. * Set the device name.
...@@ -619,7 +617,7 @@ static int iio_dummy_probe(int index) ...@@ -619,7 +617,7 @@ static int iio_dummy_probe(int index)
* indio_dev->name = id->name; * indio_dev->name = id->name;
* indio_dev->name = spi_get_device_id(spi)->name; * indio_dev->name = spi_get_device_id(spi)->name;
*/ */
indio_dev->name = iio_dummy_part_number; indio_dev->name = kstrdup(name, GFP_KERNEL);
/* Provide description of available channels */ /* Provide description of available channels */
indio_dev->channels = iio_dummy_channels; indio_dev->channels = iio_dummy_channels;
...@@ -646,7 +644,9 @@ static int iio_dummy_probe(int index) ...@@ -646,7 +644,9 @@ static int iio_dummy_probe(int index)
if (ret < 0) if (ret < 0)
goto error_unconfigure_buffer; goto error_unconfigure_buffer;
return 0; iio_swd_group_init_type_name(swd, name, &iio_dummy_type);
return swd;
error_unconfigure_buffer: error_unconfigure_buffer:
iio_simple_dummy_unconfigure_buffer(indio_dev); iio_simple_dummy_unconfigure_buffer(indio_dev);
error_unregister_events: error_unregister_events:
...@@ -654,16 +654,18 @@ static int iio_dummy_probe(int index) ...@@ -654,16 +654,18 @@ static int iio_dummy_probe(int index)
error_free_device: error_free_device:
iio_device_free(indio_dev); iio_device_free(indio_dev);
error_ret: error_ret:
return ret; kfree(swd);
error_kzalloc:
return ERR_PTR(ret);
} }
/** /**
* iio_dummy_remove() - device instance removal function * iio_dummy_remove() - device instance removal function
* @index: device index. * @swd: pointer to software IIO device abstraction
* *
* Parameters follow those of iio_dummy_probe for buses. * Parameters follow those of iio_dummy_probe for buses.
*/ */
static void iio_dummy_remove(int index) static int iio_dummy_remove(struct iio_sw_device *swd)
{ {
/* /*
* Get a pointer to the device instance iio_dev structure * Get a pointer to the device instance iio_dev structure
...@@ -671,7 +673,7 @@ static void iio_dummy_remove(int index) ...@@ -671,7 +673,7 @@ static void iio_dummy_remove(int index)
* struct iio_dev *indio_dev = i2c_get_clientdata(client); * struct iio_dev *indio_dev = i2c_get_clientdata(client);
* struct iio_dev *indio_dev = spi_get_drvdata(spi); * struct iio_dev *indio_dev = spi_get_drvdata(spi);
*/ */
struct iio_dev *indio_dev = iio_dummy_devs[index]; struct iio_dev *indio_dev = swd->device;
/* Unregister the device */ /* Unregister the device */
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
...@@ -684,11 +686,13 @@ static void iio_dummy_remove(int index) ...@@ -684,11 +686,13 @@ static void iio_dummy_remove(int index)
iio_simple_dummy_events_unregister(indio_dev); iio_simple_dummy_events_unregister(indio_dev);
/* Free all structures */ /* Free all structures */
kfree(indio_dev->name);
iio_device_free(indio_dev); iio_device_free(indio_dev);
}
return 0;
}
/** /**
* iio_dummy_init() - device driver registration * module_iio_sw_device_driver() - device driver registration
* *
* Varies depending on bus type of the device. As there is no device * Varies depending on bus type of the device. As there is no device
* here, call probe directly. For information on device registration * here, call probe directly. For information on device registration
...@@ -697,50 +701,18 @@ static void iio_dummy_remove(int index) ...@@ -697,50 +701,18 @@ static void iio_dummy_remove(int index)
* spi: * spi:
* Documentation/spi/spi-summary * Documentation/spi/spi-summary
*/ */
static __init int iio_dummy_init(void) static const struct iio_sw_device_ops iio_dummy_device_ops = {
{ .probe = iio_dummy_probe,
int i, ret; .remove = iio_dummy_remove,
};
if (instances > 10) {
instances = 1;
return -EINVAL;
}
/* Fake a bus */
iio_dummy_devs = kcalloc(instances, sizeof(*iio_dummy_devs),
GFP_KERNEL);
/* Here we have no actual device so call probe */
for (i = 0; i < instances; i++) {
ret = iio_dummy_probe(i);
if (ret < 0)
goto error_remove_devs;
}
return 0;
error_remove_devs:
while (i--)
iio_dummy_remove(i);
kfree(iio_dummy_devs);
return ret;
}
module_init(iio_dummy_init);
/** static struct iio_sw_device_type iio_dummy_device = {
* iio_dummy_exit() - device driver removal .name = "dummy",
* .owner = THIS_MODULE,
* Varies depending on bus type of the device. .ops = &iio_dummy_device_ops,
* As there is no device here, call remove directly. };
*/
static __exit void iio_dummy_exit(void)
{
int i;
for (i = 0; i < instances; i++) module_iio_sw_device_driver(iio_dummy_device);
iio_dummy_remove(i);
kfree(iio_dummy_devs);
}
module_exit(iio_dummy_exit);
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("IIO dummy driver"); MODULE_DESCRIPTION("IIO dummy driver");
......
...@@ -425,13 +425,15 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) ...@@ -425,13 +425,15 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
indio_dev->info = &gyro_info; indio_dev->info = &gyro_info;
mutex_init(&gdata->tb.buf_lock); mutex_init(&gdata->tb.buf_lock);
st_sensors_power_enable(indio_dev); err = st_sensors_power_enable(indio_dev);
if (err)
return err;
err = st_sensors_check_device_support(indio_dev, err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_gyro_sensors_settings), ARRAY_SIZE(st_gyro_sensors_settings),
st_gyro_sensors_settings); st_gyro_sensors_settings);
if (err < 0) if (err < 0)
return err; goto st_gyro_power_off;
gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS; gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS;
gdata->multiread_bit = gdata->sensor_settings->multi_read_bit; gdata->multiread_bit = gdata->sensor_settings->multi_read_bit;
...@@ -445,11 +447,11 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) ...@@ -445,11 +447,11 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
err = st_sensors_init_sensor(indio_dev, err = st_sensors_init_sensor(indio_dev,
(struct st_sensors_platform_data *)&gyro_pdata); (struct st_sensors_platform_data *)&gyro_pdata);
if (err < 0) if (err < 0)
return err; goto st_gyro_power_off;
err = st_gyro_allocate_ring(indio_dev); err = st_gyro_allocate_ring(indio_dev);
if (err < 0) if (err < 0)
return err; goto st_gyro_power_off;
if (irq > 0) { if (irq > 0) {
err = st_sensors_allocate_trigger(indio_dev, err = st_sensors_allocate_trigger(indio_dev,
...@@ -472,6 +474,8 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) ...@@ -472,6 +474,8 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
st_sensors_deallocate_trigger(indio_dev); st_sensors_deallocate_trigger(indio_dev);
st_gyro_probe_trigger_error: st_gyro_probe_trigger_error:
st_gyro_deallocate_ring(indio_dev); st_gyro_deallocate_ring(indio_dev);
st_gyro_power_off:
st_sensors_power_disable(indio_dev);
return err; return err;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -71,8 +71,7 @@ ...@@ -71,8 +71,7 @@
#define AFE440X_CONTROL1_TIMEREN BIT(8) #define AFE440X_CONTROL1_TIMEREN BIT(8)
/* TIAGAIN register fields */ /* TIAGAIN register fields */
#define AFE440X_TIAGAIN_ENSEPGAIN_MASK BIT(15) #define AFE440X_TIAGAIN_ENSEPGAIN BIT(15)
#define AFE440X_TIAGAIN_ENSEPGAIN_SHIFT 15
/* CONTROL2 register fields */ /* CONTROL2 register fields */
#define AFE440X_CONTROL2_PDN_AFE BIT(0) #define AFE440X_CONTROL2_PDN_AFE BIT(0)
...@@ -89,22 +88,7 @@ ...@@ -89,22 +88,7 @@
#define AFE440X_CONTROL0_WRITE 0x0 #define AFE440X_CONTROL0_WRITE 0x0
#define AFE440X_CONTROL0_READ 0x1 #define AFE440X_CONTROL0_READ 0x1
struct afe440x_reg_info { #define AFE440X_INTENSITY_CHAN(_index, _mask) \
unsigned int reg;
unsigned int offreg;
unsigned int shift;
unsigned int mask;
};
#define AFE440X_REG_INFO(_reg, _offreg, _sm) \
{ \
.reg = _reg, \
.offreg = _offreg, \
.shift = _sm ## _SHIFT, \
.mask = _sm ## _MASK, \
}
#define AFE440X_INTENSITY_CHAN(_index, _name, _mask) \
{ \ { \
.type = IIO_INTENSITY, \ .type = IIO_INTENSITY, \
.channel = _index, \ .channel = _index, \
...@@ -116,29 +100,23 @@ struct afe440x_reg_info { ...@@ -116,29 +100,23 @@ struct afe440x_reg_info {
.storagebits = 32, \ .storagebits = 32, \
.endianness = IIO_CPU, \ .endianness = IIO_CPU, \
}, \ }, \
.extend_name = _name, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
_mask, \ _mask, \
.indexed = true, \
} }
#define AFE440X_CURRENT_CHAN(_index, _name) \ #define AFE440X_CURRENT_CHAN(_index) \
{ \ { \
.type = IIO_CURRENT, \ .type = IIO_CURRENT, \
.channel = _index, \ .channel = _index, \
.address = _index, \ .address = _index, \
.scan_index = _index, \ .scan_index = -1, \
.extend_name = _name, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE), \ BIT(IIO_CHAN_INFO_SCALE), \
.indexed = true, \
.output = true, \ .output = true, \
} }
enum afe440x_reg_type {
SIMPLE,
RESISTANCE,
CAPACITANCE,
};
struct afe440x_val_table { struct afe440x_val_table {
int integer; int integer;
int fract; int fract;
...@@ -164,10 +142,7 @@ static DEVICE_ATTR_RO(_name) ...@@ -164,10 +142,7 @@ static DEVICE_ATTR_RO(_name)
struct afe440x_attr { struct afe440x_attr {
struct device_attribute dev_attr; struct device_attribute dev_attr;
unsigned int reg; unsigned int field;
unsigned int shift;
unsigned int mask;
enum afe440x_reg_type type;
const struct afe440x_val_table *val_table; const struct afe440x_val_table *val_table;
unsigned int table_size; unsigned int table_size;
}; };
...@@ -175,17 +150,14 @@ struct afe440x_attr { ...@@ -175,17 +150,14 @@ struct afe440x_attr {
#define to_afe440x_attr(_dev_attr) \ #define to_afe440x_attr(_dev_attr) \
container_of(_dev_attr, struct afe440x_attr, dev_attr) container_of(_dev_attr, struct afe440x_attr, dev_attr)
#define AFE440X_ATTR(_name, _reg, _field, _type, _table, _size) \ #define AFE440X_ATTR(_name, _field, _table) \
struct afe440x_attr afe440x_attr_##_name = { \ struct afe440x_attr afe440x_attr_##_name = { \
.dev_attr = __ATTR(_name, (S_IRUGO | S_IWUSR), \ .dev_attr = __ATTR(_name, (S_IRUGO | S_IWUSR), \
afe440x_show_register, \ afe440x_show_register, \
afe440x_store_register), \ afe440x_store_register), \
.reg = _reg, \ .field = _field, \
.shift = _field ## _SHIFT, \
.mask = _field ## _MASK, \
.type = _type, \
.val_table = _table, \ .val_table = _table, \
.table_size = _size, \ .table_size = ARRAY_SIZE(_table), \
} }
#endif /* _AFE440X_H */ #endif /* _AFE440X_H */
...@@ -278,6 +278,7 @@ static const struct i2c_device_id am2315_i2c_id[] = { ...@@ -278,6 +278,7 @@ static const struct i2c_device_id am2315_i2c_id[] = {
{"am2315", 0}, {"am2315", 0},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, am2315_i2c_id);
static const struct acpi_device_id am2315_acpi_id[] = { static const struct acpi_device_id am2315_acpi_id[] = {
{"AOS2315", 0}, {"AOS2315", 0},
......
...@@ -236,6 +236,7 @@ static const struct i2c_device_id htu21_id[] = { ...@@ -236,6 +236,7 @@ static const struct i2c_device_id htu21_id[] = {
{"ms8607-humidity", MS8607}, {"ms8607-humidity", MS8607},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, htu21_id);
static struct i2c_driver htu21_driver = { static struct i2c_driver htu21_driver = {
.probe = htu21_probe, .probe = htu21_probe,
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/iio/triggered_buffer.h> #include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h> #include <linux/iio/trigger_consumer.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/iio/sysfs.h>
#include "bmi160.h" #include "bmi160.h"
...@@ -466,10 +467,36 @@ static int bmi160_write_raw(struct iio_dev *indio_dev, ...@@ -466,10 +467,36 @@ static int bmi160_write_raw(struct iio_dev *indio_dev,
return 0; return 0;
} }
static
IIO_CONST_ATTR(in_accel_sampling_frequency_available,
"0.78125 1.5625 3.125 6.25 12.5 25 50 100 200 400 800 1600");
static
IIO_CONST_ATTR(in_anglvel_sampling_frequency_available,
"25 50 100 200 400 800 1600 3200");
static
IIO_CONST_ATTR(in_accel_scale_available,
"0.000598 0.001197 0.002394 0.004788");
static
IIO_CONST_ATTR(in_anglvel_scale_available,
"0.001065 0.000532 0.000266 0.000133 0.000066");
static struct attribute *bmi160_attrs[] = {
&iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr,
&iio_const_attr_in_anglvel_sampling_frequency_available.dev_attr.attr,
&iio_const_attr_in_accel_scale_available.dev_attr.attr,
&iio_const_attr_in_anglvel_scale_available.dev_attr.attr,
NULL,
};
static const struct attribute_group bmi160_attrs_group = {
.attrs = bmi160_attrs,
};
static const struct iio_info bmi160_info = { static const struct iio_info bmi160_info = {
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
.read_raw = bmi160_read_raw, .read_raw = bmi160_read_raw,
.write_raw = bmi160_write_raw, .write_raw = bmi160_write_raw,
.attrs = &bmi160_attrs_group,
}; };
static const char *bmi160_match_acpi_device(struct device *dev) static const char *bmi160_match_acpi_device(struct device *dev)
......
...@@ -80,6 +80,7 @@ static const char * const iio_chan_type_name_spec[] = { ...@@ -80,6 +80,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_RESISTANCE] = "resistance", [IIO_RESISTANCE] = "resistance",
[IIO_PH] = "ph", [IIO_PH] = "ph",
[IIO_UVINDEX] = "uvindex", [IIO_UVINDEX] = "uvindex",
[IIO_ELECTRICALCONDUCTIVITY] = "electricalconductivity",
}; };
static const char * const iio_modifier_names[] = { static const char * const iio_modifier_names[] = {
......
/*
* The Industrial I/O core, software IIO devices functions
*
* Copyright (c) 2016 Intel Corporation
*
* 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.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kmod.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/iio/sw_device.h>
#include <linux/iio/configfs.h>
#include <linux/configfs.h>
static struct config_group *iio_devices_group;
static struct config_item_type iio_device_type_group_type;
static struct config_item_type iio_devices_group_type = {
.ct_owner = THIS_MODULE,
};
static LIST_HEAD(iio_device_types_list);
static DEFINE_MUTEX(iio_device_types_lock);
static
struct iio_sw_device_type *__iio_find_sw_device_type(const char *name,
unsigned len)
{
struct iio_sw_device_type *d = NULL, *iter;
list_for_each_entry(iter, &iio_device_types_list, list)
if (!strcmp(iter->name, name)) {
d = iter;
break;
}
return d;
}
int iio_register_sw_device_type(struct iio_sw_device_type *d)
{
struct iio_sw_device_type *iter;
int ret = 0;
mutex_lock(&iio_device_types_lock);
iter = __iio_find_sw_device_type(d->name, strlen(d->name));
if (iter)
ret = -EBUSY;
else
list_add_tail(&d->list, &iio_device_types_list);
mutex_unlock(&iio_device_types_lock);
if (ret)
return ret;
d->group = configfs_register_default_group(iio_devices_group, d->name,
&iio_device_type_group_type);
if (IS_ERR(d->group))
ret = PTR_ERR(d->group);
return ret;
}
EXPORT_SYMBOL(iio_register_sw_device_type);
void iio_unregister_sw_device_type(struct iio_sw_device_type *dt)
{
struct iio_sw_device_type *iter;
mutex_lock(&iio_device_types_lock);
iter = __iio_find_sw_device_type(dt->name, strlen(dt->name));
if (iter)
list_del(&dt->list);
mutex_unlock(&iio_device_types_lock);
configfs_unregister_default_group(dt->group);
}
EXPORT_SYMBOL(iio_unregister_sw_device_type);
static
struct iio_sw_device_type *iio_get_sw_device_type(const char *name)
{
struct iio_sw_device_type *dt;
mutex_lock(&iio_device_types_lock);
dt = __iio_find_sw_device_type(name, strlen(name));
if (dt && !try_module_get(dt->owner))
dt = NULL;
mutex_unlock(&iio_device_types_lock);
return dt;
}
struct iio_sw_device *iio_sw_device_create(const char *type, const char *name)
{
struct iio_sw_device *d;
struct iio_sw_device_type *dt;
dt = iio_get_sw_device_type(type);
if (!dt) {
pr_err("Invalid device type: %s\n", type);
return ERR_PTR(-EINVAL);
}
d = dt->ops->probe(name);
if (IS_ERR(d))
goto out_module_put;
d->device_type = dt;
return d;
out_module_put:
module_put(dt->owner);
return d;
}
EXPORT_SYMBOL(iio_sw_device_create);
void iio_sw_device_destroy(struct iio_sw_device *d)
{
struct iio_sw_device_type *dt = d->device_type;
dt->ops->remove(d);
module_put(dt->owner);
}
EXPORT_SYMBOL(iio_sw_device_destroy);
static struct config_group *device_make_group(struct config_group *group,
const char *name)
{
struct iio_sw_device *d;
d = iio_sw_device_create(group->cg_item.ci_name, name);
if (IS_ERR(d))
return ERR_CAST(d);
config_item_set_name(&d->group.cg_item, "%s", name);
return &d->group;
}
static void device_drop_group(struct config_group *group,
struct config_item *item)
{
struct iio_sw_device *d = to_iio_sw_device(item);
iio_sw_device_destroy(d);
config_item_put(item);
}
static struct configfs_group_operations device_ops = {
.make_group = &device_make_group,
.drop_item = &device_drop_group,
};
static struct config_item_type iio_device_type_group_type = {
.ct_group_ops = &device_ops,
.ct_owner = THIS_MODULE,
};
static int __init iio_sw_device_init(void)
{
iio_devices_group =
configfs_register_default_group(&iio_configfs_subsys.su_group,
"devices",
&iio_devices_group_type);
return PTR_ERR_OR_ZERO(iio_devices_group);
}
module_init(iio_sw_device_init);
static void __exit iio_sw_device_exit(void)
{
configfs_unregister_default_group(iio_devices_group);
}
module_exit(iio_sw_device_exit);
MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
MODULE_DESCRIPTION("Industrial I/O software devices support");
MODULE_LICENSE("GPL v2");
...@@ -68,6 +68,10 @@ int iio_trigger_register(struct iio_trigger *trig_info) ...@@ -68,6 +68,10 @@ int iio_trigger_register(struct iio_trigger *trig_info)
{ {
int ret; int ret;
/* trig_info->ops is required for the module member */
if (!trig_info->ops)
return -EINVAL;
trig_info->id = ida_simple_get(&iio_trigger_ida, 0, 0, GFP_KERNEL); trig_info->id = ida_simple_get(&iio_trigger_ida, 0, 0, GFP_KERNEL);
if (trig_info->id < 0) if (trig_info->id < 0)
return trig_info->id; return trig_info->id;
...@@ -164,8 +168,7 @@ EXPORT_SYMBOL(iio_trigger_poll_chained); ...@@ -164,8 +168,7 @@ EXPORT_SYMBOL(iio_trigger_poll_chained);
void iio_trigger_notify_done(struct iio_trigger *trig) void iio_trigger_notify_done(struct iio_trigger *trig)
{ {
if (atomic_dec_and_test(&trig->use_count) && trig->ops && if (atomic_dec_and_test(&trig->use_count) && trig->ops->try_reenable)
trig->ops->try_reenable)
if (trig->ops->try_reenable(trig)) if (trig->ops->try_reenable(trig))
/* Missed an interrupt so launch new poll now */ /* Missed an interrupt so launch new poll now */
iio_trigger_poll(trig); iio_trigger_poll(trig);
...@@ -219,7 +222,7 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig, ...@@ -219,7 +222,7 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
return ret; return ret;
} }
if (trig->ops && trig->ops->set_trigger_state && notinuse) { if (trig->ops->set_trigger_state && notinuse) {
ret = trig->ops->set_trigger_state(trig, true); ret = trig->ops->set_trigger_state(trig, true);
if (ret < 0) if (ret < 0)
module_put(pf->indio_dev->info->driver_module); module_put(pf->indio_dev->info->driver_module);
...@@ -236,7 +239,7 @@ static int iio_trigger_detach_poll_func(struct iio_trigger *trig, ...@@ -236,7 +239,7 @@ static int iio_trigger_detach_poll_func(struct iio_trigger *trig,
= (bitmap_weight(trig->pool, = (bitmap_weight(trig->pool,
CONFIG_IIO_CONSUMERS_PER_TRIGGER) CONFIG_IIO_CONSUMERS_PER_TRIGGER)
== 1); == 1);
if (trig->ops && trig->ops->set_trigger_state && no_other_users) { if (trig->ops->set_trigger_state && no_other_users) {
ret = trig->ops->set_trigger_state(trig, false); ret = trig->ops->set_trigger_state(trig, false);
if (ret) if (ret)
return ret; return ret;
...@@ -358,7 +361,7 @@ static ssize_t iio_trigger_write_current(struct device *dev, ...@@ -358,7 +361,7 @@ static ssize_t iio_trigger_write_current(struct device *dev,
return ret; return ret;
} }
if (trig && trig->ops && trig->ops->validate_device) { if (trig && trig->ops->validate_device) {
ret = trig->ops->validate_device(trig, indio_dev); ret = trig->ops->validate_device(trig, indio_dev);
if (ret) if (ret)
return ret; return ret;
......
...@@ -325,9 +325,6 @@ static int jsa1212_probe(struct i2c_client *client, ...@@ -325,9 +325,6 @@ static int jsa1212_probe(struct i2c_client *client,
struct regmap *regmap; struct regmap *regmap;
int ret; int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EOPNOTSUPP;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev) if (!indio_dev)
return -ENOMEM; return -ENOMEM;
......
...@@ -44,6 +44,7 @@ config BMC150_MAGN_I2C ...@@ -44,6 +44,7 @@ config BMC150_MAGN_I2C
This driver is only implementing magnetometer part, which has This driver is only implementing magnetometer part, which has
its own address and register map. its own address and register map.
This driver also supports I2C Bosch BMC156 and BMM150 chips.
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called bmc150_magn_i2c. called bmc150_magn_i2c.
...@@ -60,6 +61,7 @@ config BMC150_MAGN_SPI ...@@ -60,6 +61,7 @@ config BMC150_MAGN_SPI
This driver is only implementing magnetometer part, which has This driver is only implementing magnetometer part, which has
its own address and register map. its own address and register map.
This driver also supports SPI Bosch BMC156 and BMM150 chips.
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called bmc150_magn_spi. called bmc150_magn_spi.
......
...@@ -430,8 +430,8 @@ static int ak8975_who_i_am(struct i2c_client *client, ...@@ -430,8 +430,8 @@ static int ak8975_who_i_am(struct i2c_client *client,
* AK8975 | DEVICE_ID | NA * AK8975 | DEVICE_ID | NA
* AK8963 | DEVICE_ID | NA * AK8963 | DEVICE_ID | NA
*/ */
ret = i2c_smbus_read_i2c_block_data(client, AK09912_REG_WIA1, ret = i2c_smbus_read_i2c_block_data_or_emulated(
2, wia_val); client, AK09912_REG_WIA1, 2, wia_val);
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "Error reading WIA\n"); dev_err(&client->dev, "Error reading WIA\n");
return ret; return ret;
...@@ -543,9 +543,9 @@ static int ak8975_setup(struct i2c_client *client) ...@@ -543,9 +543,9 @@ static int ak8975_setup(struct i2c_client *client)
} }
/* Get asa data and store in the device data. */ /* Get asa data and store in the device data. */
ret = i2c_smbus_read_i2c_block_data(client, ret = i2c_smbus_read_i2c_block_data_or_emulated(
data->def->ctrl_regs[ASA_BASE], client, data->def->ctrl_regs[ASA_BASE],
3, data->asa); 3, data->asa);
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "Not able to read asa data\n"); dev_err(&client->dev, "Not able to read asa data\n");
return ret; return ret;
...@@ -686,6 +686,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) ...@@ -686,6 +686,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
struct ak8975_data *data = iio_priv(indio_dev); struct ak8975_data *data = iio_priv(indio_dev);
const struct i2c_client *client = data->client; const struct i2c_client *client = data->client;
const struct ak_def *def = data->def; const struct ak_def *def = data->def;
u16 buff;
int ret; int ret;
mutex_lock(&data->lock); mutex_lock(&data->lock);
...@@ -694,14 +695,17 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) ...@@ -694,14 +695,17 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
if (ret) if (ret)
goto exit; goto exit;
ret = i2c_smbus_read_word_data(client, def->data_regs[index]); ret = i2c_smbus_read_i2c_block_data_or_emulated(
client, def->data_regs[index],
sizeof(buff), (u8*)&buff);
if (ret < 0) if (ret < 0)
goto exit; goto exit;
mutex_unlock(&data->lock); mutex_unlock(&data->lock);
/* Clamp to valid range. */ /* Swap bytes and convert to valid range. */
*val = clamp_t(s16, ret, -def->range, def->range); buff = le16_to_cpu(buff);
*val = clamp_t(s16, buff, -def->range, def->range);
return IIO_VAL_INT; return IIO_VAL_INT;
exit: exit:
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* 3-axis magnetometer driver supporting following I2C Bosch-Sensortec chips: * 3-axis magnetometer driver supporting following I2C Bosch-Sensortec chips:
* - BMC150 * - BMC150
* - BMC156 * - BMC156
* - BMM150
* *
* Copyright (c) 2016, Intel Corporation. * Copyright (c) 2016, Intel Corporation.
* *
...@@ -49,6 +50,7 @@ static int bmc150_magn_i2c_remove(struct i2c_client *client) ...@@ -49,6 +50,7 @@ static int bmc150_magn_i2c_remove(struct i2c_client *client)
static const struct acpi_device_id bmc150_magn_acpi_match[] = { static const struct acpi_device_id bmc150_magn_acpi_match[] = {
{"BMC150B", 0}, {"BMC150B", 0},
{"BMC156B", 0}, {"BMC156B", 0},
{"BMM150B", 0},
{}, {},
}; };
MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match); MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
...@@ -56,6 +58,7 @@ MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match); ...@@ -56,6 +58,7 @@ MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
static const struct i2c_device_id bmc150_magn_i2c_id[] = { static const struct i2c_device_id bmc150_magn_i2c_id[] = {
{"bmc150_magn", 0}, {"bmc150_magn", 0},
{"bmc156_magn", 0}, {"bmc156_magn", 0},
{"bmm150_magn", 0},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, bmc150_magn_i2c_id); MODULE_DEVICE_TABLE(i2c, bmc150_magn_i2c_id);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* 3-axis magnetometer driver support following SPI Bosch-Sensortec chips: * 3-axis magnetometer driver support following SPI Bosch-Sensortec chips:
* - BMC150 * - BMC150
* - BMC156 * - BMC156
* - BMM150
* *
* Copyright (c) 2016, Intel Corporation. * Copyright (c) 2016, Intel Corporation.
* *
...@@ -41,6 +42,7 @@ static int bmc150_magn_spi_remove(struct spi_device *spi) ...@@ -41,6 +42,7 @@ static int bmc150_magn_spi_remove(struct spi_device *spi)
static const struct spi_device_id bmc150_magn_spi_id[] = { static const struct spi_device_id bmc150_magn_spi_id[] = {
{"bmc150_magn", 0}, {"bmc150_magn", 0},
{"bmc156_magn", 0}, {"bmc156_magn", 0},
{"bmm150_magn", 0},
{} {}
}; };
MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id); MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id);
...@@ -48,6 +50,7 @@ MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id); ...@@ -48,6 +50,7 @@ MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id);
static const struct acpi_device_id bmc150_magn_acpi_match[] = { static const struct acpi_device_id bmc150_magn_acpi_match[] = {
{"BMC150B", 0}, {"BMC150B", 0},
{"BMC156B", 0}, {"BMC156B", 0},
{"BMM150B", 0},
{}, {},
}; };
MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match); MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
......
...@@ -588,13 +588,15 @@ int st_magn_common_probe(struct iio_dev *indio_dev) ...@@ -588,13 +588,15 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
indio_dev->info = &magn_info; indio_dev->info = &magn_info;
mutex_init(&mdata->tb.buf_lock); mutex_init(&mdata->tb.buf_lock);
st_sensors_power_enable(indio_dev); err = st_sensors_power_enable(indio_dev);
if (err)
return err;
err = st_sensors_check_device_support(indio_dev, err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_magn_sensors_settings), ARRAY_SIZE(st_magn_sensors_settings),
st_magn_sensors_settings); st_magn_sensors_settings);
if (err < 0) if (err < 0)
return err; goto st_magn_power_off;
mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS; mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS;
mdata->multiread_bit = mdata->sensor_settings->multi_read_bit; mdata->multiread_bit = mdata->sensor_settings->multi_read_bit;
...@@ -607,11 +609,11 @@ int st_magn_common_probe(struct iio_dev *indio_dev) ...@@ -607,11 +609,11 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
err = st_sensors_init_sensor(indio_dev, NULL); err = st_sensors_init_sensor(indio_dev, NULL);
if (err < 0) if (err < 0)
return err; goto st_magn_power_off;
err = st_magn_allocate_ring(indio_dev); err = st_magn_allocate_ring(indio_dev);
if (err < 0) if (err < 0)
return err; goto st_magn_power_off;
if (irq > 0) { if (irq > 0) {
err = st_sensors_allocate_trigger(indio_dev, err = st_sensors_allocate_trigger(indio_dev,
...@@ -634,6 +636,8 @@ int st_magn_common_probe(struct iio_dev *indio_dev) ...@@ -634,6 +636,8 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
st_sensors_deallocate_trigger(indio_dev); st_sensors_deallocate_trigger(indio_dev);
st_magn_probe_trigger_error: st_magn_probe_trigger_error:
st_magn_deallocate_ring(indio_dev); st_magn_deallocate_ring(indio_dev);
st_magn_power_off:
st_sensors_power_disable(indio_dev);
return err; return err;
} }
......
...@@ -15,6 +15,17 @@ config DS1803 ...@@ -15,6 +15,17 @@ config DS1803
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called ds1803. module will be called ds1803.
config MAX5487
tristate "Maxim MAX5487/MAX5488/MAX5489 Digital Potentiometer driver"
depends on SPI
help
Say yes here to build support for the Maxim
MAX5487, MAX5488, MAX5489 digital potentiometer
chips.
To compile this driver as a module, choose M here: the
module will be called max5487.
config MCP4131 config MCP4131
tristate "Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer driver" tristate "Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer driver"
depends on SPI depends on SPI
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
# When adding new entries keep the list in alphabetical order # When adding new entries keep the list in alphabetical order
obj-$(CONFIG_DS1803) += ds1803.o obj-$(CONFIG_DS1803) += ds1803.o
obj-$(CONFIG_MAX5487) += max5487.o
obj-$(CONFIG_MCP4131) += mcp4131.o obj-$(CONFIG_MCP4131) += mcp4131.o
obj-$(CONFIG_MCP4531) += mcp4531.o obj-$(CONFIG_MCP4531) += mcp4531.o
obj-$(CONFIG_TPL0102) += tpl0102.o obj-$(CONFIG_TPL0102) += tpl0102.o
/*
* max5487.c - Support for MAX5487, MAX5488, MAX5489 digital potentiometers
*
* Copyright (C) 2016 Cristina-Gabriela Moraru <cristina.moraru09@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.
*
*/
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/acpi.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/iio.h>
#define MAX5487_WRITE_WIPER_A (0x01 << 8)
#define MAX5487_WRITE_WIPER_B (0x02 << 8)
/* copy both wiper regs to NV regs */
#define MAX5487_COPY_AB_TO_NV (0x23 << 8)
/* copy both NV regs to wiper regs */
#define MAX5487_COPY_NV_TO_AB (0x33 << 8)
#define MAX5487_MAX_POS 255
struct max5487_data {
struct spi_device *spi;
int kohms;
};
#define MAX5487_CHANNEL(ch, addr) { \
.type = IIO_RESISTANCE, \
.indexed = 1, \
.output = 1, \
.channel = ch, \
.address = addr, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec max5487_channels[] = {
MAX5487_CHANNEL(0, MAX5487_WRITE_WIPER_A),
MAX5487_CHANNEL(1, MAX5487_WRITE_WIPER_B),
};
static int max5487_write_cmd(struct spi_device *spi, u16 cmd)
{
return spi_write(spi, (const void *) &cmd, sizeof(u16));
}
static int max5487_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct max5487_data *data = iio_priv(indio_dev);
if (mask != IIO_CHAN_INFO_SCALE)
return -EINVAL;
*val = 1000 * data->kohms;
*val2 = MAX5487_MAX_POS;
return IIO_VAL_FRACTIONAL;
}
static int max5487_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct max5487_data *data = iio_priv(indio_dev);
if (mask != IIO_CHAN_INFO_RAW)
return -EINVAL;
if (val < 0 || val > MAX5487_MAX_POS)
return -EINVAL;
return max5487_write_cmd(data->spi, chan->address | val);
}
static const struct iio_info max5487_info = {
.read_raw = max5487_read_raw,
.write_raw = max5487_write_raw,
.driver_module = THIS_MODULE,
};
static int max5487_spi_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct max5487_data *data;
const struct spi_device_id *id = spi_get_device_id(spi);
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
dev_set_drvdata(&spi->dev, indio_dev);
data = iio_priv(indio_dev);
data->spi = spi;
data->kohms = id->driver_data;
indio_dev->info = &max5487_info;
indio_dev->name = id->name;
indio_dev->dev.parent = &spi->dev;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = max5487_channels;
indio_dev->num_channels = ARRAY_SIZE(max5487_channels);
/* restore both wiper regs from NV regs */
ret = max5487_write_cmd(data->spi, MAX5487_COPY_NV_TO_AB);
if (ret < 0)
return ret;
return iio_device_register(indio_dev);
}
static int max5487_spi_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev);
iio_device_unregister(indio_dev);
/* save both wiper regs to NV regs */
return max5487_write_cmd(spi, MAX5487_COPY_AB_TO_NV);
}
static const struct spi_device_id max5487_id[] = {
{ "MAX5487", 10 },
{ "MAX5488", 50 },
{ "MAX5489", 100 },
{ }
};
MODULE_DEVICE_TABLE(spi, max5487_id);
static const struct acpi_device_id max5487_acpi_match[] = {
{ "MAX5487", 10 },
{ "MAX5488", 50 },
{ "MAX5489", 100 },
{ },
};
MODULE_DEVICE_TABLE(acpi, max5487_acpi_match);
static struct spi_driver max5487_driver = {
.driver = {
.name = "max5487",
.owner = THIS_MODULE,
.acpi_match_table = ACPI_PTR(max5487_acpi_match),
},
.id_table = max5487_id,
.probe = max5487_spi_probe,
.remove = max5487_spi_remove
};
module_spi_driver(max5487_driver);
MODULE_AUTHOR("Cristina-Gabriela Moraru <cristina.moraru09@gmail.com>");
MODULE_DESCRIPTION("max5487 SPI driver");
MODULE_LICENSE("GPL v2");
...@@ -116,10 +116,6 @@ static int tpl0102_probe(struct i2c_client *client, ...@@ -116,10 +116,6 @@ static int tpl0102_probe(struct i2c_client *client,
struct tpl0102_data *data; struct tpl0102_data *data;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_WORD_DATA))
return -EOPNOTSUPP;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev) if (!indio_dev)
return -ENOMEM; return -ENOMEM;
......
...@@ -12,7 +12,8 @@ config BMP280 ...@@ -12,7 +12,8 @@ config BMP280
select REGMAP_I2C select REGMAP_I2C
help help
Say yes here to build support for Bosch Sensortec BMP180 and BMP280 Say yes here to build support for Bosch Sensortec BMP180 and BMP280
pressure and temperature sensors. pressure and temperature sensors. Also supports the BE280 with
an additional humidty sensor channel.
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called bmp280. will be called bmp280.
...@@ -130,7 +131,7 @@ config IIO_ST_PRESS ...@@ -130,7 +131,7 @@ config IIO_ST_PRESS
select IIO_TRIGGERED_BUFFER if (IIO_BUFFER) select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
help help
Say yes here to build support for STMicroelectronics pressure Say yes here to build support for STMicroelectronics pressure
sensors: LPS001WP, LPS25H, LPS331AP. sensors: LPS001WP, LPS25H, LPS331AP, LPS22HB.
This driver can also be built as a module. If so, these modules This driver can also be built as a module. If so, these modules
will be created: will be created:
......
This diff is collapsed.
...@@ -401,6 +401,7 @@ static const struct i2c_device_id hp206c_id[] = { ...@@ -401,6 +401,7 @@ static const struct i2c_device_id hp206c_id[] = {
{"hp206c"}, {"hp206c"},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, hp206c_id);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static const struct acpi_device_id hp206c_acpi_match[] = { static const struct acpi_device_id hp206c_acpi_match[] = {
......
...@@ -173,6 +173,7 @@ static const struct i2c_device_id ms5637_id[] = { ...@@ -173,6 +173,7 @@ static const struct i2c_device_id ms5637_id[] = {
{"ms8607-temppressure", 1}, {"ms8607-temppressure", 1},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, ms5637_id);
static struct i2c_driver ms5637_driver = { static struct i2c_driver ms5637_driver = {
.probe = ms5637_probe, .probe = ms5637_probe,
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#define LPS001WP_PRESS_DEV_NAME "lps001wp" #define LPS001WP_PRESS_DEV_NAME "lps001wp"
#define LPS25H_PRESS_DEV_NAME "lps25h" #define LPS25H_PRESS_DEV_NAME "lps25h"
#define LPS331AP_PRESS_DEV_NAME "lps331ap" #define LPS331AP_PRESS_DEV_NAME "lps331ap"
#define LPS22HB_PRESS_DEV_NAME "lps22hb"
/** /**
* struct st_sensors_platform_data - default press platform data * struct st_sensors_platform_data - default press platform data
......
...@@ -113,6 +113,26 @@ ...@@ -113,6 +113,26 @@
#define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28 #define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28
#define ST_TEMP_LPS25H_OUT_L_ADDR 0x2b #define ST_TEMP_LPS25H_OUT_L_ADDR 0x2b
/* CUSTOM VALUES FOR LPS22HB SENSOR */
#define ST_PRESS_LPS22HB_WAI_EXP 0xb1
#define ST_PRESS_LPS22HB_ODR_ADDR 0x10
#define ST_PRESS_LPS22HB_ODR_MASK 0x70
#define ST_PRESS_LPS22HB_ODR_AVL_1HZ_VAL 0x01
#define ST_PRESS_LPS22HB_ODR_AVL_10HZ_VAL 0x02
#define ST_PRESS_LPS22HB_ODR_AVL_25HZ_VAL 0x03
#define ST_PRESS_LPS22HB_ODR_AVL_50HZ_VAL 0x04
#define ST_PRESS_LPS22HB_ODR_AVL_75HZ_VAL 0x05
#define ST_PRESS_LPS22HB_PW_ADDR 0x10
#define ST_PRESS_LPS22HB_PW_MASK 0x70
#define ST_PRESS_LPS22HB_BDU_ADDR 0x10
#define ST_PRESS_LPS22HB_BDU_MASK 0x02
#define ST_PRESS_LPS22HB_DRDY_IRQ_ADDR 0x12
#define ST_PRESS_LPS22HB_DRDY_IRQ_INT1_MASK 0x04
#define ST_PRESS_LPS22HB_DRDY_IRQ_INT2_MASK 0x08
#define ST_PRESS_LPS22HB_IHL_IRQ_ADDR 0x12
#define ST_PRESS_LPS22HB_IHL_IRQ_MASK 0x80
#define ST_PRESS_LPS22HB_MULTIREAD_BIT true
static const struct iio_chan_spec st_press_1_channels[] = { static const struct iio_chan_spec st_press_1_channels[] = {
{ {
.type = IIO_PRESSURE, .type = IIO_PRESSURE,
...@@ -183,6 +203,27 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = { ...@@ -183,6 +203,27 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(1) IIO_CHAN_SOFT_TIMESTAMP(1)
}; };
static const struct iio_chan_spec st_press_lps22hb_channels[] = {
{
.type = IIO_PRESSURE,
.channel2 = IIO_NO_MOD,
.address = ST_PRESS_1_OUT_XL_ADDR,
.scan_index = 0,
.scan_type = {
.sign = 'u',
.realbits = 24,
.storagebits = 24,
.endianness = IIO_LE,
},
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
.modified = 0,
},
IIO_CHAN_SOFT_TIMESTAMP(1)
};
static const struct st_sensor_settings st_press_sensors_settings[] = { static const struct st_sensor_settings st_press_sensors_settings[] = {
{ {
.wai = ST_PRESS_LPS331AP_WAI_EXP, .wai = ST_PRESS_LPS331AP_WAI_EXP,
...@@ -326,6 +367,51 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { ...@@ -326,6 +367,51 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
.multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT, .multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT,
.bootime = 2, .bootime = 2,
}, },
{
.wai = ST_PRESS_LPS22HB_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LPS22HB_PRESS_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_press_lps22hb_channels,
.num_ch = ARRAY_SIZE(st_press_lps22hb_channels),
.odr = {
.addr = ST_PRESS_LPS22HB_ODR_ADDR,
.mask = ST_PRESS_LPS22HB_ODR_MASK,
.odr_avl = {
{ 1, ST_PRESS_LPS22HB_ODR_AVL_1HZ_VAL, },
{ 10, ST_PRESS_LPS22HB_ODR_AVL_10HZ_VAL, },
{ 25, ST_PRESS_LPS22HB_ODR_AVL_25HZ_VAL, },
{ 50, ST_PRESS_LPS22HB_ODR_AVL_50HZ_VAL, },
{ 75, ST_PRESS_LPS22HB_ODR_AVL_75HZ_VAL, },
},
},
.pw = {
.addr = ST_PRESS_LPS22HB_PW_ADDR,
.mask = ST_PRESS_LPS22HB_PW_MASK,
.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
},
.fs = {
.fs_avl = {
[0] = {
.num = ST_PRESS_FS_AVL_1260MB,
.gain = ST_PRESS_KPASCAL_NANO_SCALE,
},
},
},
.bdu = {
.addr = ST_PRESS_LPS22HB_BDU_ADDR,
.mask = ST_PRESS_LPS22HB_BDU_MASK,
},
.drdy_irq = {
.addr = ST_PRESS_LPS22HB_DRDY_IRQ_ADDR,
.mask_int1 = ST_PRESS_LPS22HB_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_PRESS_LPS22HB_DRDY_IRQ_INT2_MASK,
.addr_ihl = ST_PRESS_LPS22HB_IHL_IRQ_ADDR,
.mask_ihl = ST_PRESS_LPS22HB_IHL_IRQ_MASK,
},
.multi_read_bit = ST_PRESS_LPS22HB_MULTIREAD_BIT,
},
}; };
static int st_press_write_raw(struct iio_dev *indio_dev, static int st_press_write_raw(struct iio_dev *indio_dev,
...@@ -441,23 +527,24 @@ int st_press_common_probe(struct iio_dev *indio_dev) ...@@ -441,23 +527,24 @@ int st_press_common_probe(struct iio_dev *indio_dev)
indio_dev->info = &press_info; indio_dev->info = &press_info;
mutex_init(&press_data->tb.buf_lock); mutex_init(&press_data->tb.buf_lock);
st_sensors_power_enable(indio_dev); err = st_sensors_power_enable(indio_dev);
if (err)
return err;
err = st_sensors_check_device_support(indio_dev, err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_press_sensors_settings), ARRAY_SIZE(st_press_sensors_settings),
st_press_sensors_settings); st_press_sensors_settings);
if (err < 0) if (err < 0)
return err; goto st_press_power_off;
press_data->num_data_channels = ST_PRESS_NUMBER_DATA_CHANNELS; press_data->num_data_channels = ST_PRESS_NUMBER_DATA_CHANNELS;
press_data->multiread_bit = press_data->sensor_settings->multi_read_bit; press_data->multiread_bit = press_data->sensor_settings->multi_read_bit;
indio_dev->channels = press_data->sensor_settings->ch; indio_dev->channels = press_data->sensor_settings->ch;
indio_dev->num_channels = press_data->sensor_settings->num_ch; indio_dev->num_channels = press_data->sensor_settings->num_ch;
if (press_data->sensor_settings->fs.addr != 0) press_data->current_fullscale =
press_data->current_fullscale = (struct st_sensor_fullscale_avl *)
(struct st_sensor_fullscale_avl *) &press_data->sensor_settings->fs.fs_avl[0];
&press_data->sensor_settings->fs.fs_avl[0];
press_data->odr = press_data->sensor_settings->odr.odr_avl[0].hz; press_data->odr = press_data->sensor_settings->odr.odr_avl[0].hz;
...@@ -469,11 +556,11 @@ int st_press_common_probe(struct iio_dev *indio_dev) ...@@ -469,11 +556,11 @@ int st_press_common_probe(struct iio_dev *indio_dev)
err = st_sensors_init_sensor(indio_dev, press_data->dev->platform_data); err = st_sensors_init_sensor(indio_dev, press_data->dev->platform_data);
if (err < 0) if (err < 0)
return err; goto st_press_power_off;
err = st_press_allocate_ring(indio_dev); err = st_press_allocate_ring(indio_dev);
if (err < 0) if (err < 0)
return err; goto st_press_power_off;
if (irq > 0) { if (irq > 0) {
err = st_sensors_allocate_trigger(indio_dev, err = st_sensors_allocate_trigger(indio_dev,
...@@ -496,6 +583,8 @@ int st_press_common_probe(struct iio_dev *indio_dev) ...@@ -496,6 +583,8 @@ int st_press_common_probe(struct iio_dev *indio_dev)
st_sensors_deallocate_trigger(indio_dev); st_sensors_deallocate_trigger(indio_dev);
st_press_probe_trigger_error: st_press_probe_trigger_error:
st_press_deallocate_ring(indio_dev); st_press_deallocate_ring(indio_dev);
st_press_power_off:
st_sensors_power_disable(indio_dev);
return err; return err;
} }
......
...@@ -32,6 +32,10 @@ static const struct of_device_id st_press_of_match[] = { ...@@ -32,6 +32,10 @@ static const struct of_device_id st_press_of_match[] = {
.compatible = "st,lps331ap-press", .compatible = "st,lps331ap-press",
.data = LPS331AP_PRESS_DEV_NAME, .data = LPS331AP_PRESS_DEV_NAME,
}, },
{
.compatible = "st,lps22hb-press",
.data = LPS22HB_PRESS_DEV_NAME,
},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, st_press_of_match); MODULE_DEVICE_TABLE(of, st_press_of_match);
......
...@@ -50,6 +50,7 @@ static const struct spi_device_id st_press_id_table[] = { ...@@ -50,6 +50,7 @@ static const struct spi_device_id st_press_id_table[] = {
{ LPS001WP_PRESS_DEV_NAME }, { LPS001WP_PRESS_DEV_NAME },
{ LPS25H_PRESS_DEV_NAME }, { LPS25H_PRESS_DEV_NAME },
{ LPS331AP_PRESS_DEV_NAME }, { LPS331AP_PRESS_DEV_NAME },
{ LPS22HB_PRESS_DEV_NAME },
{}, {},
}; };
MODULE_DEVICE_TABLE(spi, st_press_id_table); MODULE_DEVICE_TABLE(spi, st_press_id_table);
......
...@@ -461,4 +461,3 @@ module_spi_driver(as3935_driver); ...@@ -461,4 +461,3 @@ module_spi_driver(as3935_driver);
MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>"); MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>");
MODULE_DESCRIPTION("AS3935 lightning sensor"); MODULE_DESCRIPTION("AS3935 lightning sensor");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("spi:as3935");
...@@ -174,6 +174,7 @@ static const struct i2c_device_id tsys02d_id[] = { ...@@ -174,6 +174,7 @@ static const struct i2c_device_id tsys02d_id[] = {
{"tsys02d", 0}, {"tsys02d", 0},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, tsys02d_id);
static struct i2c_driver tsys02d_driver = { static struct i2c_driver tsys02d_driver = {
.probe = tsys02d_probe, .probe = tsys02d_probe,
......
...@@ -24,6 +24,18 @@ config IIO_INTERRUPT_TRIGGER ...@@ -24,6 +24,18 @@ config IIO_INTERRUPT_TRIGGER
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called iio-trig-interrupt. module will be called iio-trig-interrupt.
config IIO_TIGHTLOOP_TRIGGER
tristate "A kthread based hammering loop trigger"
depends on IIO_SW_TRIGGER
help
An experimental trigger, used to allow sensors to be sampled as fast
as possible under the limitations of whatever else is going on.
Uses a tight loop in a kthread. Will only work with lower half only
trigger consumers.
To compile this driver as a module, choose M here: the
module will be called iio-trig-loop.
config IIO_SYSFS_TRIGGER config IIO_SYSFS_TRIGGER
tristate "SYSFS trigger" tristate "SYSFS trigger"
depends on SYSFS depends on SYSFS
......
...@@ -7,3 +7,4 @@ ...@@ -7,3 +7,4 @@
obj-$(CONFIG_IIO_HRTIMER_TRIGGER) += iio-trig-hrtimer.o obj-$(CONFIG_IIO_HRTIMER_TRIGGER) += iio-trig-hrtimer.o
obj-$(CONFIG_IIO_INTERRUPT_TRIGGER) += iio-trig-interrupt.o obj-$(CONFIG_IIO_INTERRUPT_TRIGGER) += iio-trig-interrupt.o
obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o
obj-$(CONFIG_IIO_TIGHTLOOP_TRIGGER) += iio-trig-loop.o
/*
* Copyright 2016 Jonathan Cameron <jic23@kernel.org>
*
* Licensed under the GPL-2.
*
* Based on a mashup of the hrtimer trigger and continuous sampling proposal of
* Gregor Boirie <gregor.boirie@parrot.com>
*
* Note this is still rather experimental and may eat babies.
*
* Todo
* * Protect against connection of devices that 'need' the top half
* handler.
* * Work out how to run top half handlers in this context if it is
* safe to do so (timestamp grabbing for example)
*
* Tested against a max1363. Used about 33% cpu for the thread and 20%
* for generic_buffer piping to /dev/null. Watermark set at 64 on a 128
* element kfifo buffer.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/irq_work.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
#include <linux/iio/sw_trigger.h>
struct iio_loop_info {
struct iio_sw_trigger swt;
struct task_struct *task;
};
static struct config_item_type iio_loop_type = {
.ct_owner = THIS_MODULE,
};
static int iio_loop_thread(void *data)
{
struct iio_trigger *trig = data;
set_freezable();
do {
iio_trigger_poll_chained(trig);
} while (likely(!kthread_freezable_should_stop(NULL)));
return 0;
}
static int iio_loop_trigger_set_state(struct iio_trigger *trig, bool state)
{
struct iio_loop_info *loop_trig = iio_trigger_get_drvdata(trig);
if (state) {
loop_trig->task = kthread_run(iio_loop_thread,
trig, trig->name);
if (unlikely(IS_ERR(loop_trig->task))) {
dev_err(&trig->dev,
"failed to create trigger loop thread\n");
return PTR_ERR(loop_trig->task);
}
} else {
kthread_stop(loop_trig->task);
}
return 0;
}
static const struct iio_trigger_ops iio_loop_trigger_ops = {
.set_trigger_state = iio_loop_trigger_set_state,
.owner = THIS_MODULE,
};
static struct iio_sw_trigger *iio_trig_loop_probe(const char *name)
{
struct iio_loop_info *trig_info;
int ret;
trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL);
if (!trig_info)
return ERR_PTR(-ENOMEM);
trig_info->swt.trigger = iio_trigger_alloc("%s", name);
if (!trig_info->swt.trigger) {
ret = -ENOMEM;
goto err_free_trig_info;
}
iio_trigger_set_drvdata(trig_info->swt.trigger, trig_info);
trig_info->swt.trigger->ops = &iio_loop_trigger_ops;
ret = iio_trigger_register(trig_info->swt.trigger);
if (ret)
goto err_free_trigger;
iio_swt_group_init_type_name(&trig_info->swt, name, &iio_loop_type);
return &trig_info->swt;
err_free_trigger:
iio_trigger_free(trig_info->swt.trigger);
err_free_trig_info:
kfree(trig_info);
return ERR_PTR(ret);
}
static int iio_trig_loop_remove(struct iio_sw_trigger *swt)
{
struct iio_loop_info *trig_info;
trig_info = iio_trigger_get_drvdata(swt->trigger);
iio_trigger_unregister(swt->trigger);
iio_trigger_free(swt->trigger);
kfree(trig_info);
return 0;
}
static const struct iio_sw_trigger_ops iio_trig_loop_ops = {
.probe = iio_trig_loop_probe,
.remove = iio_trig_loop_remove,
};
static struct iio_sw_trigger_type iio_trig_loop = {
.name = "loop",
.owner = THIS_MODULE,
.ops = &iio_trig_loop_ops,
};
module_iio_sw_trigger_driver(iio_trig_loop);
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("Loop based trigger for the iio subsystem");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:iio-trig-loop");
...@@ -251,8 +251,6 @@ struct st_sensor_data { ...@@ -251,8 +251,6 @@ struct st_sensor_data {
#ifdef CONFIG_IIO_BUFFER #ifdef CONFIG_IIO_BUFFER
irqreturn_t st_sensors_trigger_handler(int irq, void *p); irqreturn_t st_sensors_trigger_handler(int irq, void *p);
int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf);
#endif #endif
#ifdef CONFIG_IIO_TRIGGER #ifdef CONFIG_IIO_TRIGGER
...@@ -280,7 +278,7 @@ int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable); ...@@ -280,7 +278,7 @@ int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable);
int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable); int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable);
void st_sensors_power_enable(struct iio_dev *indio_dev); int st_sensors_power_enable(struct iio_dev *indio_dev);
void st_sensors_power_disable(struct iio_dev *indio_dev); void st_sensors_power_disable(struct iio_dev *indio_dev);
......
/*
* Industrial I/O software device interface
*
* Copyright (c) 2016 Intel Corporation
*
* 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.
*/
#ifndef __IIO_SW_DEVICE
#define __IIO_SW_DEVICE
#include <linux/module.h>
#include <linux/device.h>
#include <linux/iio/iio.h>
#include <linux/configfs.h>
#define module_iio_sw_device_driver(__iio_sw_device_type) \
module_driver(__iio_sw_device_type, iio_register_sw_device_type, \
iio_unregister_sw_device_type)
struct iio_sw_device_ops;
struct iio_sw_device_type {
const char *name;
struct module *owner;
const struct iio_sw_device_ops *ops;
struct list_head list;
struct config_group *group;
};
struct iio_sw_device {
struct iio_dev *device;
struct iio_sw_device_type *device_type;
struct config_group group;
};
struct iio_sw_device_ops {
struct iio_sw_device* (*probe)(const char *);
int (*remove)(struct iio_sw_device *);
};
static inline
struct iio_sw_device *to_iio_sw_device(struct config_item *item)
{
return container_of(to_config_group(item), struct iio_sw_device,
group);
}
int iio_register_sw_device_type(struct iio_sw_device_type *dt);
void iio_unregister_sw_device_type(struct iio_sw_device_type *dt);
struct iio_sw_device *iio_sw_device_create(const char *, const char *);
void iio_sw_device_destroy(struct iio_sw_device *);
int iio_sw_device_type_configfs_register(struct iio_sw_device_type *dt);
void iio_sw_device_type_configfs_unregister(struct iio_sw_device_type *dt);
static inline
void iio_swd_group_init_type_name(struct iio_sw_device *d,
const char *name,
struct config_item_type *type)
{
#ifdef CONFIG_CONFIGFS_FS
config_group_init_type_name(&d->group, name, type);
#endif
}
#endif /* __IIO_SW_DEVICE */
...@@ -39,6 +39,7 @@ enum iio_chan_type { ...@@ -39,6 +39,7 @@ enum iio_chan_type {
IIO_RESISTANCE, IIO_RESISTANCE,
IIO_PH, IIO_PH,
IIO_UVINDEX, IIO_UVINDEX,
IIO_ELECTRICALCONDUCTIVITY,
}; };
enum iio_modifier { enum iio_modifier {
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment