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

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

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

Jonathan writes:

First set of new device support, features and cleanups for IIO in the 4.5 cycle

Usual mixed bag, but the big item perhaps in this series is the DMA buffer
support added by Lars-Peter Clausen. It's been in the works for a long time
and it will be interesting to see what hardware support shows up now that
this is available.

New core features + associate cleanup.
* Add generic DMA buffer infrastructure
* Add a DMAengine framework based buffer
 Also associated minor changes.
   - Set the device buffer watermark based on the minimum watermark for all
     attached buffers rather than just the 'primary' one.
   - iio_buffer_init - only set the watermark default if one hasn't already
     been provided.  This allows simple support for devices with a fixed
     watermark.
   - read only attribute for watermark on fixed watermark devices.
   - add explicit buffer enable/disable callbacks to allow the buffer to
     do more than trivial actions when it is being turned on and off.
* IIO_VAL_INT support in write_raw_get_fmt function.

New device support
* Freescale MMA7455/7456L accelerometers
* Memsic MXC6255XC accelerometer
* ST lis2dh12 accelerometer
* TI ADS8688 ADC
* TI Palamas (twl6035/7) gpadc

New driver features
* mma8452
  - support either of the available interrupt pins to cope with the case
    where board layout has lead to a particular one being connected.

Staging graduation
* Dummy driver
  - this driver acts as both an example and a test device for those with
    out hardware to develop userspace code against.

Cleanups and minor bits and bobs.
* treewide
  - Sort out the ordering of iio_device_register/unregister vs runtime
    pm function calls so that it's all nice and consistent and not race
    prone.
  - Check sscanf return values.  None of the cases will actually happen as
    the strings are supplied internally, but best to be consistent on this.
* ad7780
  - switch over to the gpio descriptor interface and remove the now unused
    platform data which gets rid of a header entirely.
* ad7793
  - drop a pointless else statement.
* at91_adc
  - Swap kmalloc_array in for a kmalloc doing the same job.
* dummy
  - get rid of some commented out lines that snuck in during the move of
    the driver.
* lm3533-als
  - Print an error message on provision of an invalid resistance.
* mcp320x
  - Add compatible strings with vendor prefix and deprecate those with
    no vendor prefix.
* mxs-lradc
  - Use BIT macro in various places rather than shifted ones.
* pa12203001
  - Power off the chip if the registration fails.
* pulsedlight-lidar-lite
  - add runtime PM support.
* xilinx XADC
  - constify an iio_buffer_setup_ops structure.
parents f84a1870 4ac4e086
......@@ -7,13 +7,18 @@ Required properties:
* "fsl,mma8453"
* "fsl,mma8652"
* "fsl,mma8653"
- reg: the I2C address of the chip
Optional properties:
- interrupt-parent: should be the phandle for the interrupt controller
- interrupts: interrupt mapping for GPIO IRQ
- interrupt-names: should contain "INT1" and/or "INT2", the accelerometer's
interrupt line in use.
Example:
mma8453fc@1d {
......@@ -21,4 +26,5 @@ Example:
reg = <0x1d>;
interrupt-parent = <&gpio1>;
interrupts = <5 0>;
interrupt-names = "INT2";
};
......@@ -10,16 +10,28 @@ must be specified.
Required properties:
- compatible: Must be one of the following, depending on the
model:
"mcp3001"
"mcp3002"
"mcp3004"
"mcp3008"
"mcp3201"
"mcp3202"
"mcp3204"
"mcp3208"
"mcp3301"
"mcp3001" (DEPRECATED)
"mcp3002" (DEPRECATED)
"mcp3004" (DEPRECATED)
"mcp3008" (DEPRECATED)
"mcp3201" (DEPRECATED)
"mcp3202" (DEPRECATED)
"mcp3204" (DEPRECATED)
"mcp3208" (DEPRECATED)
"mcp3301" (DEPRECATED)
"microchip,mcp3001"
"microchip,mcp3002"
"microchip,mcp3004"
"microchip,mcp3008"
"microchip,mcp3201"
"microchip,mcp3202"
"microchip,mcp3204"
"microchip,mcp3208"
"microchip,mcp3301"
NOTE: The use of the compatibles with no vendor prefix
is deprecated and only listed because old DT use them.
Examples:
spi_controller {
......
* Palmas general purpose ADC IP block devicetree bindings
Channels list:
0 battery type
1 battery temp NTC (optional current source)
2 GP
3 temp (with ext. diode, optional current source)
4 GP
5 GP
6 VBAT_SENSE
7 VCC_SENSE
8 Backup Battery voltage
9 external charger (VCHG)
10 VBUS
11 DC-DC current probe (how does this work?)
12 internal die temp
13 internal die temp
14 USB ID pin voltage
15 test network
Required properties:
- compatible : Must be "ti,palmas-gpadc".
- #io-channel-cells: Should be set to <1>.
Optional sub-nodes:
ti,channel0-current-microamp: Channel 0 current in uA.
Values are rounded to derive 0uA, 5uA, 15uA, 20uA.
ti,channel3-current-microamp: Channel 3 current in uA.
Values are rounded to derive 0uA, 10uA, 400uA, 800uA.
ti,enable-extended-delay: Enable extended delay.
Example:
pmic {
compatible = "ti,twl6035-pmic", "ti,palmas-pmic";
...
gpadc {
compatible = "ti,palmas-gpadc";
interrupts = <18 0
16 0
17 0>;
#io-channel-cells = <1>;
ti,channel0-current-microamp = <5>;
ti,channel3-current-microamp = <10>;
};
};
...
};
* Texas Instruments' ADS8684 and ADS8688 ADC chip
Required properties:
- compatible: Should be "ti,ads8684" or "ti,ads8688"
- reg: spi chip select number for the device
Recommended properties:
- spi-max-frequency: Definition as per
Documentation/devicetree/bindings/spi/spi-bus.txt
Optional properties:
- vref-supply: The regulator supply for ADC reference voltage
Example:
adc@0 {
compatible = "ti,ads8688";
reg = <0>;
vref-supply = <&vdd_supply>;
spi-max-frequency = <1000000>;
};
......@@ -36,6 +36,7 @@ Accelerometers:
- st,lsm303dlm-accel
- st,lsm330-accel
- st,lsm303agr-accel
- st,lis2dh12-accel
Gyroscopes:
- st,l3g4200d-gyro
......
......@@ -50,6 +50,7 @@ source "drivers/iio/amplifiers/Kconfig"
source "drivers/iio/chemical/Kconfig"
source "drivers/iio/common/Kconfig"
source "drivers/iio/dac/Kconfig"
source "drivers/iio/dummy/Kconfig"
source "drivers/iio/frequency/Kconfig"
source "drivers/iio/gyro/Kconfig"
source "drivers/iio/humidity/Kconfig"
......
......@@ -16,6 +16,7 @@ obj-y += buffer/
obj-y += chemical/
obj-y += common/
obj-y += dac/
obj-y += dummy/
obj-y += gyro/
obj-y += frequency/
obj-y += humidity/
......
......@@ -64,7 +64,7 @@ config IIO_ST_ACCEL_3AXIS
help
Say yes here to build support for STMicroelectronics accelerometers:
LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
LIS331DLH, LSM303DL, LSM303DLM, LSM330.
LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12.
This driver can also be built as a module. If so, these modules
will be created:
......@@ -107,6 +107,35 @@ config KXCJK1013
To compile this driver as a module, choose M here: the module will
be called kxcjk-1013.
config MMA7455
tristate
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
config MMA7455_I2C
tristate "Freescale MMA7455L/MMA7456L Accelerometer I2C Driver"
depends on I2C
select MMA7455
select REGMAP_I2C
help
Say yes here to build support for the Freescale MMA7455L and
MMA7456L 3-axis accelerometer.
To compile this driver as a module, choose M here: the module
will be called mma7455_i2c.
config MMA7455_SPI
tristate "Freescale MMA7455L/MMA7456L Accelerometer SPI Driver"
depends on SPI_MASTER
select MMA7455
select REGMAP_SPI
help
Say yes here to build support for the Freescale MMA7455L and
MMA7456L 3-axis accelerometer.
To compile this driver as a module, choose M here: the module
will be called mma7455_spi.
config MMA8452
tristate "Freescale MMA8452Q and similar Accelerometers Driver"
depends on I2C
......@@ -158,6 +187,17 @@ config MXC4005
To compile this driver as a module, choose M. The module will be
called mxc4005.
config MXC6255
tristate "Memsic MXC6255 Orientation Sensing Accelerometer Driver"
depends on I2C
select REGMAP_I2C
help
Say yes here to build support for the Memsic MXC6255 Orientation
Sensing Accelerometer Driver.
To compile this driver as a module, choose M here: the module will be
called mxc6255.
config STK8312
tristate "Sensortek STK8312 3-Axis Accelerometer Driver"
depends on I2C
......
......@@ -10,6 +10,11 @@ obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
obj-$(CONFIG_KXSD9) += kxsd9.o
obj-$(CONFIG_MMA7455) += mma7455_core.o
obj-$(CONFIG_MMA7455_I2C) += mma7455_i2c.o
obj-$(CONFIG_MMA7455_SPI) += mma7455_spi.o
obj-$(CONFIG_MMA8452) += mma8452.o
obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o
......@@ -17,6 +22,7 @@ obj-$(CONFIG_MMA9551) += mma9551.o
obj-$(CONFIG_MMA9553) += mma9553.o
obj-$(CONFIG_MXC4005) += mxc4005.o
obj-$(CONFIG_MXC6255) += mxc6255.o
obj-$(CONFIG_STK8312) += stk8312.o
obj-$(CONFIG_STK8BA50) += stk8ba50.o
......
......@@ -1623,24 +1623,22 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
}
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(dev, "Unable to register iio device\n");
goto err_trigger_unregister;
}
ret = pm_runtime_set_active(dev);
if (ret)
goto err_iio_unregister;
goto err_trigger_unregister;
pm_runtime_enable(dev);
pm_runtime_set_autosuspend_delay(dev, BMC150_AUTO_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(dev);
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(dev, "Unable to register iio device\n");
goto err_trigger_unregister;
}
return 0;
err_iio_unregister:
iio_device_unregister(indio_dev);
err_trigger_unregister:
bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1);
err_buffer_cleanup:
......@@ -1655,12 +1653,12 @@ int bmc150_accel_core_remove(struct device *dev)
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmc150_accel_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
pm_runtime_disable(data->dev);
pm_runtime_set_suspended(data->dev);
pm_runtime_put_noidle(data->dev);
iio_device_unregister(indio_dev);
bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1);
iio_triggered_buffer_cleanup(indio_dev);
......
......@@ -1264,25 +1264,23 @@ static int kxcjk1013_probe(struct i2c_client *client,
goto err_trigger_unregister;
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "unable to register iio device\n");
goto err_buffer_cleanup;
}
ret = pm_runtime_set_active(&client->dev);
if (ret)
goto err_iio_unregister;
goto err_buffer_cleanup;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev,
KXCJK1013_SLEEP_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "unable to register iio device\n");
goto err_buffer_cleanup;
}
return 0;
err_iio_unregister:
iio_device_unregister(indio_dev);
err_buffer_cleanup:
if (data->dready_trig)
iio_triggered_buffer_cleanup(indio_dev);
......@@ -1302,12 +1300,12 @@ static int kxcjk1013_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct kxcjk1013_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);
iio_device_unregister(indio_dev);
if (data->dready_trig) {
iio_triggered_buffer_cleanup(indio_dev);
iio_trigger_unregister(data->dready_trig);
......
/*
* IIO accel driver for Freescale MMA7455L 3-axis 10-bit accelerometer
* Copyright 2015 Joachim Eastwood <manabian@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.
*/
#ifndef __MMA7455_H
#define __MMA7455_H
extern const struct regmap_config mma7455_core_regmap;
int mma7455_core_probe(struct device *dev, struct regmap *regmap,
const char *name);
int mma7455_core_remove(struct device *dev);
#endif
/*
* IIO accel core driver for Freescale MMA7455L 3-axis 10-bit accelerometer
* Copyright 2015 Joachim Eastwood <manabian@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.
*
* UNSUPPORTED hardware features:
* - 8-bit mode with different scales
* - INT1/INT2 interrupts
* - Offset calibration
* - Events
*/
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include "mma7455.h"
#define MMA7455_REG_XOUTL 0x00
#define MMA7455_REG_XOUTH 0x01
#define MMA7455_REG_YOUTL 0x02
#define MMA7455_REG_YOUTH 0x03
#define MMA7455_REG_ZOUTL 0x04
#define MMA7455_REG_ZOUTH 0x05
#define MMA7455_REG_STATUS 0x09
#define MMA7455_STATUS_DRDY BIT(0)
#define MMA7455_REG_WHOAMI 0x0f
#define MMA7455_WHOAMI_ID 0x55
#define MMA7455_REG_MCTL 0x16
#define MMA7455_MCTL_MODE_STANDBY 0x00
#define MMA7455_MCTL_MODE_MEASURE 0x01
#define MMA7455_REG_CTL1 0x18
#define MMA7455_CTL1_DFBW_MASK BIT(7)
#define MMA7455_CTL1_DFBW_125HZ BIT(7)
#define MMA7455_CTL1_DFBW_62_5HZ 0
#define MMA7455_REG_TW 0x1e
/*
* When MMA7455 is used in 10-bit it has a fullscale of -8g
* corresponding to raw value -512. The userspace interface
* uses m/s^2 and we declare micro units.
* So scale factor is given by:
* g * 8 * 1e6 / 512 = 153228.90625, with g = 9.80665
*/
#define MMA7455_10BIT_SCALE 153229
struct mma7455_data {
struct regmap *regmap;
struct device *dev;
};
static int mma7455_drdy(struct mma7455_data *mma7455)
{
unsigned int reg;
int tries = 3;
int ret;
while (tries-- > 0) {
ret = regmap_read(mma7455->regmap, MMA7455_REG_STATUS, &reg);
if (ret)
return ret;
if (reg & MMA7455_STATUS_DRDY)
return 0;
msleep(20);
}
dev_warn(mma7455->dev, "data not ready\n");
return -EIO;
}
static irqreturn_t mma7455_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct mma7455_data *mma7455 = iio_priv(indio_dev);
u8 buf[16]; /* 3 x 16-bit channels + padding + ts */
int ret;
ret = mma7455_drdy(mma7455);
if (ret)
goto done;
ret = regmap_bulk_read(mma7455->regmap, MMA7455_REG_XOUTL, buf,
sizeof(__le16) * 3);
if (ret)
goto done;
iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns());
done:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
static int mma7455_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct mma7455_data *mma7455 = iio_priv(indio_dev);
unsigned int reg;
__le16 data;
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (iio_buffer_enabled(indio_dev))
return -EBUSY;
ret = mma7455_drdy(mma7455);
if (ret)
return ret;
ret = regmap_bulk_read(mma7455->regmap, chan->address, &data,
sizeof(data));
if (ret)
return ret;
*val = sign_extend32(le16_to_cpu(data), 9);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = MMA7455_10BIT_SCALE;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ:
ret = regmap_read(mma7455->regmap, MMA7455_REG_CTL1, &reg);
if (ret)
return ret;
if (reg & MMA7455_CTL1_DFBW_MASK)
*val = 250;
else
*val = 125;
return IIO_VAL_INT;
}
return -EINVAL;
}
static int mma7455_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct mma7455_data *mma7455 = iio_priv(indio_dev);
int i;
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
if (val == 250 && val2 == 0)
i = MMA7455_CTL1_DFBW_125HZ;
else if (val == 125 && val2 == 0)
i = MMA7455_CTL1_DFBW_62_5HZ;
else
return -EINVAL;
return regmap_update_bits(mma7455->regmap, MMA7455_REG_CTL1,
MMA7455_CTL1_DFBW_MASK, i);
case IIO_CHAN_INFO_SCALE:
/* In 10-bit mode there is only one scale available */
if (val == 0 && val2 == MMA7455_10BIT_SCALE)
return 0;
break;
}
return -EINVAL;
}
static IIO_CONST_ATTR(sampling_frequency_available, "125 250");
static struct attribute *mma7455_attributes[] = {
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
NULL
};
static const struct attribute_group mma7455_group = {
.attrs = mma7455_attributes,
};
static const struct iio_info mma7455_info = {
.attrs = &mma7455_group,
.read_raw = mma7455_read_raw,
.write_raw = mma7455_write_raw,
.driver_module = THIS_MODULE,
};
#define MMA7455_CHANNEL(axis, idx) { \
.type = IIO_ACCEL, \
.modified = 1, \
.address = MMA7455_REG_##axis##OUTL,\
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
BIT(IIO_CHAN_INFO_SCALE), \
.scan_index = idx, \
.scan_type = { \
.sign = 's', \
.realbits = 10, \
.storagebits = 16, \
.endianness = IIO_LE, \
}, \
}
static const struct iio_chan_spec mma7455_channels[] = {
MMA7455_CHANNEL(X, 0),
MMA7455_CHANNEL(Y, 1),
MMA7455_CHANNEL(Z, 2),
IIO_CHAN_SOFT_TIMESTAMP(3),
};
static const unsigned long mma7455_scan_masks[] = {0x7, 0};
const struct regmap_config mma7455_core_regmap = {
.reg_bits = 8,
.val_bits = 8,
.max_register = MMA7455_REG_TW,
};
EXPORT_SYMBOL_GPL(mma7455_core_regmap);
int mma7455_core_probe(struct device *dev, struct regmap *regmap,
const char *name)
{
struct mma7455_data *mma7455;
struct iio_dev *indio_dev;
unsigned int reg;
int ret;
ret = regmap_read(regmap, MMA7455_REG_WHOAMI, &reg);
if (ret) {
dev_err(dev, "unable to read reg\n");
return ret;
}
if (reg != MMA7455_WHOAMI_ID) {
dev_err(dev, "device id mismatch\n");
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(dev, sizeof(*mma7455));
if (!indio_dev)
return -ENOMEM;
dev_set_drvdata(dev, indio_dev);
mma7455 = iio_priv(indio_dev);
mma7455->regmap = regmap;
mma7455->dev = dev;
indio_dev->info = &mma7455_info;
indio_dev->name = name;
indio_dev->dev.parent = dev;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = mma7455_channels;
indio_dev->num_channels = ARRAY_SIZE(mma7455_channels);
indio_dev->available_scan_masks = mma7455_scan_masks;
regmap_write(mma7455->regmap, MMA7455_REG_MCTL,
MMA7455_MCTL_MODE_MEASURE);
ret = iio_triggered_buffer_setup(indio_dev, NULL,
mma7455_trigger_handler, NULL);
if (ret) {
dev_err(dev, "unable to setup triggered buffer\n");
return ret;
}
ret = iio_device_register(indio_dev);
if (ret) {
dev_err(dev, "unable to register device\n");
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(mma7455_core_probe);
int mma7455_core_remove(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct mma7455_data *mma7455 = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
regmap_write(mma7455->regmap, MMA7455_REG_MCTL,
MMA7455_MCTL_MODE_STANDBY);
return 0;
}
EXPORT_SYMBOL_GPL(mma7455_core_remove);
MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
MODULE_DESCRIPTION("Freescale MMA7455L core accelerometer driver");
MODULE_LICENSE("GPL v2");
/*
* IIO accel I2C driver for Freescale MMA7455L 3-axis 10-bit accelerometer
* Copyright 2015 Joachim Eastwood <manabian@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/i2c.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include "mma7455.h"
static int mma7455_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct regmap *regmap;
const char *name = NULL;
regmap = devm_regmap_init_i2c(i2c, &mma7455_core_regmap);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
if (id)
name = id->name;
return mma7455_core_probe(&i2c->dev, regmap, name);
}
static int mma7455_i2c_remove(struct i2c_client *i2c)
{
return mma7455_core_remove(&i2c->dev);
}
static const struct i2c_device_id mma7455_i2c_ids[] = {
{ "mma7455", 0 },
{ "mma7456", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, mma7455_i2c_ids);
static struct i2c_driver mma7455_i2c_driver = {
.probe = mma7455_i2c_probe,
.remove = mma7455_i2c_remove,
.id_table = mma7455_i2c_ids,
.driver = {
.name = "mma7455-i2c",
},
};
module_i2c_driver(mma7455_i2c_driver);
MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
MODULE_DESCRIPTION("Freescale MMA7455L I2C accelerometer driver");
MODULE_LICENSE("GPL v2");
/*
* IIO accel SPI driver for Freescale MMA7455L 3-axis 10-bit accelerometer
* Copyright 2015 Joachim Eastwood <manabian@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/regmap.h>
#include <linux/spi/spi.h>
#include "mma7455.h"
static int mma7455_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct regmap *regmap;
regmap = devm_regmap_init_spi(spi, &mma7455_core_regmap);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
return mma7455_core_probe(&spi->dev, regmap, id->name);
}
static int mma7455_spi_remove(struct spi_device *spi)
{
return mma7455_core_remove(&spi->dev);
}
static const struct spi_device_id mma7455_spi_ids[] = {
{ "mma7455", 0 },
{ "mma7456", 0 },
{ }
};
MODULE_DEVICE_TABLE(spi, mma7455_spi_ids);
static struct spi_driver mma7455_spi_driver = {
.probe = mma7455_spi_probe,
.remove = mma7455_spi_remove,
.id_table = mma7455_spi_ids,
.driver = {
.name = "mma7455-spi",
},
};
module_spi_driver(mma7455_spi_driver);
MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
MODULE_DESCRIPTION("Freescale MMA7455L SPI accelerometer driver");
MODULE_LICENSE("GPL v2");
......@@ -29,6 +29,7 @@
#include <linux/iio/events.h>
#include <linux/delay.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#define MMA8452_STATUS 0x00
#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
......@@ -1130,13 +1131,21 @@ static int mma8452_probe(struct i2c_client *client,
MMA8452_INT_FF_MT;
int enabled_interrupts = MMA8452_INT_TRANS |
MMA8452_INT_FF_MT;
int irq2;
/* Assume wired to INT1 pin */
ret = i2c_smbus_write_byte_data(client,
MMA8452_CTRL_REG5,
supported_interrupts);
if (ret < 0)
return ret;
irq2 = of_irq_get_byname(client->dev.of_node, "INT2");
if (irq2 == client->irq) {
dev_dbg(&client->dev, "using interrupt line INT2\n");
} else {
ret = i2c_smbus_write_byte_data(client,
MMA8452_CTRL_REG5,
supported_interrupts);
if (ret < 0)
return ret;
dev_dbg(&client->dev, "using interrupt line INT1\n");
}
ret = i2c_smbus_write_byte_data(client,
MMA8452_CTRL_REG4,
......
......@@ -495,25 +495,23 @@ static int mma9551_probe(struct i2c_client *client,
if (ret < 0)
goto out_poweroff;
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "unable to register iio device\n");
goto out_poweroff;
}
ret = pm_runtime_set_active(&client->dev);
if (ret < 0)
goto out_iio_unregister;
goto out_poweroff;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev,
MMA9551_AUTO_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "unable to register iio device\n");
goto out_poweroff;
}
return 0;
out_iio_unregister:
iio_device_unregister(indio_dev);
out_poweroff:
mma9551_set_device_state(client, false);
......@@ -525,11 +523,12 @@ static int mma9551_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct mma9551_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);
iio_device_unregister(indio_dev);
mutex_lock(&data->mutex);
mma9551_set_device_state(data->client, false);
mutex_unlock(&data->mutex);
......
......@@ -1133,27 +1133,24 @@ static int mma9553_probe(struct i2c_client *client,
}
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "unable to register iio device\n");
goto out_poweroff;
}
ret = pm_runtime_set_active(&client->dev);
if (ret < 0)
goto out_iio_unregister;
goto out_poweroff;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev,
MMA9551_AUTO_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
dev_dbg(&indio_dev->dev, "Registered device %s\n", name);
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "unable to register iio device\n");
goto out_poweroff;
}
dev_dbg(&indio_dev->dev, "Registered device %s\n", name);
return 0;
out_iio_unregister:
iio_device_unregister(indio_dev);
out_poweroff:
mma9551_set_device_state(client, false);
return ret;
......@@ -1164,11 +1161,12 @@ static int mma9553_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct mma9553_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);
iio_device_unregister(indio_dev);
mutex_lock(&data->mutex);
mma9551_set_device_state(data->client, false);
mutex_unlock(&data->mutex);
......
/*
* MXC6255 - MEMSIC orientation sensing accelerometer
*
* Copyright (c) 2015, 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 MXC6255 (7-bit I2C slave address 0x15).
*/
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/iio/iio.h>
#include <linux/delay.h>
#include <linux/acpi.h>
#include <linux/regmap.h>
#include <linux/iio/sysfs.h>
#define MXC6255_DRV_NAME "mxc6255"
#define MXC6255_REGMAP_NAME "mxc6255_regmap"
#define MXC6255_REG_XOUT 0x00
#define MXC6255_REG_YOUT 0x01
#define MXC6255_REG_CHIP_ID 0x08
#define MXC6255_CHIP_ID 0x05
/*
* MXC6255 has only one measurement range: +/- 2G.
* The acceleration output is an 8-bit value.
*
* Scale is calculated as follows:
* (2 + 2) * 9.80665 / (2^8 - 1) = 0.153829
*
* Scale value for +/- 2G measurement range
*/
#define MXC6255_SCALE 153829
enum mxc6255_axis {
AXIS_X,
AXIS_Y,
};
struct mxc6255_data {
struct i2c_client *client;
struct regmap *regmap;
};
static int mxc6255_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct mxc6255_data *data = iio_priv(indio_dev);
unsigned int reg;
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
ret = regmap_read(data->regmap, chan->address, &reg);
if (ret < 0) {
dev_err(&data->client->dev,
"Error reading reg %lu\n", chan->address);
return ret;
}
*val = sign_extend32(reg, 7);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = MXC6255_SCALE;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
}
static const struct iio_info mxc6255_info = {
.driver_module = THIS_MODULE,
.read_raw = mxc6255_read_raw,
};
#define MXC6255_CHANNEL(_axis, reg) { \
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = IIO_MOD_##_axis, \
.address = reg, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec mxc6255_channels[] = {
MXC6255_CHANNEL(X, MXC6255_REG_XOUT),
MXC6255_CHANNEL(Y, MXC6255_REG_YOUT),
};
static bool mxc6255_is_readable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case MXC6255_REG_XOUT:
case MXC6255_REG_YOUT:
case MXC6255_REG_CHIP_ID:
return true;
default:
return false;
}
}
static const struct regmap_config mxc6255_regmap_config = {
.name = MXC6255_REGMAP_NAME,
.reg_bits = 8,
.val_bits = 8,
.readable_reg = mxc6255_is_readable_reg,
};
static int mxc6255_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct mxc6255_data *data;
struct iio_dev *indio_dev;
struct regmap *regmap;
unsigned int chip_id;
int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
regmap = devm_regmap_init_i2c(client, &mxc6255_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "Error initializing regmap\n");
return PTR_ERR(regmap);
}
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
data->regmap = regmap;
indio_dev->name = MXC6255_DRV_NAME;
indio_dev->dev.parent = &client->dev;
indio_dev->channels = mxc6255_channels;
indio_dev->num_channels = ARRAY_SIZE(mxc6255_channels);
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &mxc6255_info;
ret = regmap_read(data->regmap, MXC6255_REG_CHIP_ID, &chip_id);
if (ret < 0) {
dev_err(&client->dev, "Error reading chip id %d\n", ret);
return ret;
}
if (chip_id != MXC6255_CHIP_ID) {
dev_err(&client->dev, "Invalid chip id %x\n", chip_id);
return -ENODEV;
}
dev_dbg(&client->dev, "Chip id %x\n", chip_id);
ret = devm_iio_device_register(&client->dev, indio_dev);
if (ret < 0) {
dev_err(&client->dev, "Could not register IIO device\n");
return ret;
}
return 0;
}
static const struct acpi_device_id mxc6255_acpi_match[] = {
{"MXC6255", 0},
{ }
};
MODULE_DEVICE_TABLE(acpi, mxc6255_acpi_match);
static const struct i2c_device_id mxc6255_id[] = {
{"mxc6255", 0},
{ }
};
MODULE_DEVICE_TABLE(i2c, mxc6255_id);
static struct i2c_driver mxc6255_driver = {
.driver = {
.name = MXC6255_DRV_NAME,
.acpi_match_table = ACPI_PTR(mxc6255_acpi_match),
},
.probe = mxc6255_probe,
.id_table = mxc6255_id,
};
module_i2c_driver(mxc6255_driver);
MODULE_AUTHOR("Teodora Baluta <teodora.baluta@intel.com>");
MODULE_DESCRIPTION("MEMSIC MXC6255 orientation sensing accelerometer driver");
MODULE_LICENSE("GPL v2");
......@@ -27,6 +27,7 @@
#define LSM303DLM_ACCEL_DEV_NAME "lsm303dlm_accel"
#define LSM330_ACCEL_DEV_NAME "lsm330_accel"
#define LSM303AGR_ACCEL_DEV_NAME "lsm303agr_accel"
#define LIS2DH12_ACCEL_DEV_NAME "lis2dh12_accel"
/**
* struct st_sensors_platform_data - default accel platform data
......
......@@ -232,6 +232,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
[3] = LSM330DL_ACCEL_DEV_NAME,
[4] = LSM330DLC_ACCEL_DEV_NAME,
[5] = LSM303AGR_ACCEL_DEV_NAME,
[6] = LIS2DH12_ACCEL_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
.odr = {
......
......@@ -72,6 +72,10 @@ static const struct of_device_id st_accel_of_match[] = {
.compatible = "st,lsm303agr-accel",
.data = LSM303AGR_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis2dh12-accel",
.data = LIS2DH12_ACCEL_DEV_NAME,
},
{},
};
MODULE_DEVICE_TABLE(of, st_accel_of_match);
......@@ -121,6 +125,7 @@ static const struct i2c_device_id st_accel_id_table[] = {
{ LSM303DLM_ACCEL_DEV_NAME },
{ LSM330_ACCEL_DEV_NAME },
{ LSM303AGR_ACCEL_DEV_NAME },
{ LIS2DH12_ACCEL_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
......
......@@ -58,6 +58,7 @@ static const struct spi_device_id st_accel_id_table[] = {
{ LSM303DLM_ACCEL_DEV_NAME },
{ LSM330_ACCEL_DEV_NAME },
{ LSM303AGR_ACCEL_DEV_NAME },
{ LIS2DH12_ACCEL_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(spi, st_accel_id_table);
......
......@@ -275,6 +275,14 @@ config NAU7802
To compile this driver as a module, choose M here: the
module will be called nau7802.
config PALMAS_GPADC
tristate "TI Palmas General Purpose ADC"
depends on MFD_PALMAS
help
Palmas series pmic chip by Texas Instruments (twl6035/6037)
is used in smartphones and tablets and supports a 16 channel
general purpose ADC.
config QCOM_SPMI_IADC
tristate "Qualcomm SPMI PMIC current ADC"
depends on SPMI
......@@ -333,6 +341,16 @@ config TI_ADC128S052
This driver can also be built as a module. If so, the module will be
called ti-adc128s052.
config TI_ADS8688
tristate "Texas Instruments ADS8688"
depends on SPI && OF
help
If you say yes here you get support for Texas Instruments ADS8684 and
and ADS8688 ADC chips
This driver can also be built as a module. If so, the module will be
called ti-ads8688.
config TI_AM335X_ADC
tristate "TI's AM335X ADC driver"
depends on MFD_TI_AM335X_TSCADC
......
......@@ -27,11 +27,13 @@ obj-$(CONFIG_MCP320X) += mcp320x.o
obj-$(CONFIG_MCP3422) += mcp3422.o
obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
obj-$(CONFIG_NAU7802) += nau7802.o
obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o
obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o
obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
......
......@@ -478,10 +478,9 @@ static int ad7793_read_raw(struct iio_dev *indio_dev,
*val2 = st->
scale_avail[(st->conf >> 8) & 0x7][1];
return IIO_VAL_INT_PLUS_NANO;
} else {
/* 1170mV / 2^23 * 6 */
scale_uv = (1170ULL * 1000000000ULL * 6ULL);
}
/* 1170mV / 2^23 * 6 */
scale_uv = (1170ULL * 1000000000ULL * 6ULL);
break;
case IIO_TEMP:
/* 1170mV / 0.81 mV/C / 2^23 */
......
......@@ -742,7 +742,7 @@ static int at91_adc_of_get_resolution(struct at91_adc_state *st,
return count;
}
resolutions = kmalloc(count * sizeof(*resolutions), GFP_KERNEL);
resolutions = kmalloc_array(count, sizeof(*resolutions), GFP_KERNEL);
if (!resolutions)
return -ENOMEM;
......
......@@ -354,6 +354,7 @@ static int mcp320x_remove(struct spi_device *spi)
#if defined(CONFIG_OF)
static const struct of_device_id mcp320x_dt_ids[] = {
/* NOTE: The use of compatibles with no vendor prefix is deprecated. */
{
.compatible = "mcp3001",
.data = &mcp320x_chip_infos[mcp3001],
......@@ -381,6 +382,33 @@ static const struct of_device_id mcp320x_dt_ids[] = {
}, {
.compatible = "mcp3301",
.data = &mcp320x_chip_infos[mcp3301],
}, {
.compatible = "microchip,mcp3001",
.data = &mcp320x_chip_infos[mcp3001],
}, {
.compatible = "microchip,mcp3002",
.data = &mcp320x_chip_infos[mcp3002],
}, {
.compatible = "microchip,mcp3004",
.data = &mcp320x_chip_infos[mcp3004],
}, {
.compatible = "microchip,mcp3008",
.data = &mcp320x_chip_infos[mcp3008],
}, {
.compatible = "microchip,mcp3201",
.data = &mcp320x_chip_infos[mcp3201],
}, {
.compatible = "microchip,mcp3202",
.data = &mcp320x_chip_infos[mcp3202],
}, {
.compatible = "microchip,mcp3204",
.data = &mcp320x_chip_infos[mcp3204],
}, {
.compatible = "microchip,mcp3208",
.data = &mcp320x_chip_infos[mcp3208],
}, {
.compatible = "microchip,mcp3301",
.data = &mcp320x_chip_infos[mcp3301],
}, {
}
};
......
This diff is collapsed.
This diff is collapsed.
......@@ -803,7 +803,7 @@ static int xadc_preenable(struct iio_dev *indio_dev)
return ret;
}
static struct iio_buffer_setup_ops xadc_buffer_ops = {
static const struct iio_buffer_setup_ops xadc_buffer_ops = {
.preenable = &xadc_preenable,
.postenable = &iio_triggered_buffer_postenable,
.predisable = &iio_triggered_buffer_predisable,
......
......@@ -9,6 +9,26 @@ config IIO_BUFFER_CB
Should be selected by any drivers that do in-kernel push
usage. That is, those where the data is pushed to the consumer.
config IIO_BUFFER_DMA
tristate
help
Provides the generic IIO DMA buffer infrastructure that can be used by
drivers for devices with DMA support to implement the IIO buffer.
Should be selected by drivers that want to use the generic DMA buffer
infrastructure.
config IIO_BUFFER_DMAENGINE
tristate
select IIO_BUFFER_DMA
help
Provides a bonding of the generic IIO DMA buffer infrastructure with the
DMAengine framework. This can be used by converter drivers with a DMA port
connected to an external DMA controller which is supported by the
DMAengine framework.
Should be selected by drivers that want to use this functionality.
config IIO_KFIFO_BUF
tristate "Industrial I/O buffering based on kfifo"
help
......
......@@ -4,5 +4,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_IIO_BUFFER_CB) += industrialio-buffer-cb.o
obj-$(CONFIG_IIO_BUFFER_DMA) += industrialio-buffer-dma.o
obj-$(CONFIG_IIO_BUFFER_DMAENGINE) += industrialio-buffer-dmaengine.o
obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o
obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
This diff is collapsed.
/*
* Copyright 2014-2015 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2 or later.
*/
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
#include <linux/err.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/buffer-dma.h>
#include <linux/iio/buffer-dmaengine.h>
/*
* The IIO DMAengine buffer combines the generic IIO DMA buffer infrastructure
* with the DMAengine framework. The generic IIO DMA buffer infrastructure is
* used to manage the buffer memory and implement the IIO buffer operations
* while the DMAengine framework is used to perform the DMA transfers. Combined
* this results in a device independent fully functional DMA buffer
* implementation that can be used by device drivers for peripherals which are
* connected to a DMA controller which has a DMAengine driver implementation.
*/
struct dmaengine_buffer {
struct iio_dma_buffer_queue queue;
struct dma_chan *chan;
struct list_head active;
size_t align;
size_t max_size;
};
static struct dmaengine_buffer *iio_buffer_to_dmaengine_buffer(
struct iio_buffer *buffer)
{
return container_of(buffer, struct dmaengine_buffer, queue.buffer);
}
static void iio_dmaengine_buffer_block_done(void *data)
{
struct iio_dma_buffer_block *block = data;
unsigned long flags;
spin_lock_irqsave(&block->queue->list_lock, flags);
list_del(&block->head);
spin_unlock_irqrestore(&block->queue->list_lock, flags);
iio_dma_buffer_block_done(block);
}
static int iio_dmaengine_buffer_submit_block(struct iio_dma_buffer_queue *queue,
struct iio_dma_buffer_block *block)
{
struct dmaengine_buffer *dmaengine_buffer =
iio_buffer_to_dmaengine_buffer(&queue->buffer);
struct dma_async_tx_descriptor *desc;
dma_cookie_t cookie;
block->bytes_used = min(block->size, dmaengine_buffer->max_size);
block->bytes_used = rounddown(block->bytes_used,
dmaengine_buffer->align);
desc = dmaengine_prep_slave_single(dmaengine_buffer->chan,
block->phys_addr, block->bytes_used, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT);
if (!desc)
return -ENOMEM;
desc->callback = iio_dmaengine_buffer_block_done;
desc->callback_param = block;
cookie = dmaengine_submit(desc);
if (dma_submit_error(cookie))
return dma_submit_error(cookie);
spin_lock_irq(&dmaengine_buffer->queue.list_lock);
list_add_tail(&block->head, &dmaengine_buffer->active);
spin_unlock_irq(&dmaengine_buffer->queue.list_lock);
dma_async_issue_pending(dmaengine_buffer->chan);
return 0;
}
static void iio_dmaengine_buffer_abort(struct iio_dma_buffer_queue *queue)
{
struct dmaengine_buffer *dmaengine_buffer =
iio_buffer_to_dmaengine_buffer(&queue->buffer);
dmaengine_terminate_all(dmaengine_buffer->chan);
/* FIXME: There is a slight chance of a race condition here.
* dmaengine_terminate_all() does not guarantee that all transfer
* callbacks have finished running. Need to introduce a
* dmaengine_terminate_all_sync().
*/
iio_dma_buffer_block_list_abort(queue, &dmaengine_buffer->active);
}
static void iio_dmaengine_buffer_release(struct iio_buffer *buf)
{
struct dmaengine_buffer *dmaengine_buffer =
iio_buffer_to_dmaengine_buffer(buf);
iio_dma_buffer_release(&dmaengine_buffer->queue);
kfree(dmaengine_buffer);
}
static const struct iio_buffer_access_funcs iio_dmaengine_buffer_ops = {
.read_first_n = iio_dma_buffer_read,
.set_bytes_per_datum = iio_dma_buffer_set_bytes_per_datum,
.set_length = iio_dma_buffer_set_length,
.request_update = iio_dma_buffer_request_update,
.enable = iio_dma_buffer_enable,
.disable = iio_dma_buffer_disable,
.data_available = iio_dma_buffer_data_available,
.release = iio_dmaengine_buffer_release,
.modes = INDIO_BUFFER_HARDWARE,
.flags = INDIO_BUFFER_FLAG_FIXED_WATERMARK,
};
static const struct iio_dma_buffer_ops iio_dmaengine_default_ops = {
.submit = iio_dmaengine_buffer_submit_block,
.abort = iio_dmaengine_buffer_abort,
};
/**
* iio_dmaengine_buffer_alloc() - Allocate new buffer which uses DMAengine
* @dev: Parent device for the buffer
* @channel: DMA channel name, typically "rx".
*
* This allocates a new IIO buffer which internally uses the DMAengine framework
* to perform its transfers. The parent device will be used to request the DMA
* channel.
*
* Once done using the buffer iio_dmaengine_buffer_free() should be used to
* release it.
*/
struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
const char *channel)
{
struct dmaengine_buffer *dmaengine_buffer;
unsigned int width, src_width, dest_width;
struct dma_slave_caps caps;
struct dma_chan *chan;
int ret;
dmaengine_buffer = kzalloc(sizeof(*dmaengine_buffer), GFP_KERNEL);
if (!dmaengine_buffer)
return ERR_PTR(-ENOMEM);
chan = dma_request_slave_channel_reason(dev, channel);
if (IS_ERR(chan)) {
ret = PTR_ERR(chan);
goto err_free;
}
ret = dma_get_slave_caps(chan, &caps);
if (ret < 0)
goto err_free;
/* Needs to be aligned to the maximum of the minimums */
if (caps.src_addr_widths)
src_width = __ffs(caps.src_addr_widths);
else
src_width = 1;
if (caps.dst_addr_widths)
dest_width = __ffs(caps.dst_addr_widths);
else
dest_width = 1;
width = max(src_width, dest_width);
INIT_LIST_HEAD(&dmaengine_buffer->active);
dmaengine_buffer->chan = chan;
dmaengine_buffer->align = width;
dmaengine_buffer->max_size = dma_get_max_seg_size(chan->device->dev);
iio_dma_buffer_init(&dmaengine_buffer->queue, chan->device->dev,
&iio_dmaengine_default_ops);
dmaengine_buffer->queue.buffer.access = &iio_dmaengine_buffer_ops;
return &dmaengine_buffer->queue.buffer;
err_free:
kfree(dmaengine_buffer);
return ERR_PTR(ret);
}
EXPORT_SYMBOL(iio_dmaengine_buffer_alloc);
/**
* iio_dmaengine_buffer_free() - Free dmaengine buffer
* @buffer: Buffer to free
*
* Frees a buffer previously allocated with iio_dmaengine_buffer_alloc().
*/
void iio_dmaengine_buffer_free(struct iio_buffer *buffer)
{
struct dmaengine_buffer *dmaengine_buffer =
iio_buffer_to_dmaengine_buffer(buffer);
iio_dma_buffer_exit(&dmaengine_buffer->queue);
dma_release_channel(dmaengine_buffer->chan);
iio_buffer_put(buffer);
}
EXPORT_SYMBOL_GPL(iio_dmaengine_buffer_free);
#
# Industrial I/O subsystem Dummy Driver configuration
#
menu "IIO dummy driver"
depends on IIO
config IIO_DUMMY_EVGEN
tristate
config IIO_SIMPLE_DUMMY
tristate "An example driver with no hardware requirements"
help
Driver intended mainly as documentation for how to write
a driver. May also be useful for testing userspace code
without hardware.
if IIO_SIMPLE_DUMMY
config IIO_SIMPLE_DUMMY_EVENTS
bool "Event generation support"
select IIO_DUMMY_EVGEN
help
Add some dummy events to the simple dummy driver.
config IIO_SIMPLE_DUMMY_BUFFER
bool "Buffered capture support"
select IIO_BUFFER
select IIO_TRIGGER
select IIO_KFIFO_BUF
help
Add buffered data capture to the simple dummy driver.
endif # IIO_SIMPLE_DUMMY
endmenu
#
# Makefile for the IIO Dummy Driver
#
obj-$(CONFIG_IIO_SIMPLE_DUMMY) += iio_dummy.o
iio_dummy-y := iio_simple_dummy.o
iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_EVENTS) += iio_simple_dummy_events.o
iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_BUFFER) += iio_simple_dummy_buffer.o
obj-$(CONFIG_IIO_DUMMY_EVGEN) += iio_dummy_evgen.o
......@@ -435,7 +435,9 @@ static int adis16136_initial_setup(struct iio_dev *indio_dev)
if (ret)
return ret;
sscanf(indio_dev->name, "adis%u\n", &device_id);
ret = sscanf(indio_dev->name, "adis%u\n", &device_id);
if (ret != 1)
return -EINVAL;
if (prod_id != device_id)
dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
......
......@@ -1077,25 +1077,23 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
goto err_trigger_unregister;
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(dev, "unable to register iio device\n");
goto err_buffer_cleanup;
}
ret = pm_runtime_set_active(dev);
if (ret)
goto err_iio_unregister;
goto err_buffer_cleanup;
pm_runtime_enable(dev);
pm_runtime_set_autosuspend_delay(dev,
BMG160_AUTO_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(dev);
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(dev, "unable to register iio device\n");
goto err_buffer_cleanup;
}
return 0;
err_iio_unregister:
iio_device_unregister(indio_dev);
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
err_trigger_unregister:
......@@ -1113,11 +1111,12 @@ void bmg160_core_remove(struct device *dev)
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmg160_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
pm_runtime_put_noidle(dev);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
if (data->dready_trig) {
......
......@@ -288,7 +288,11 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
if (ret)
goto err_ret;
sscanf(indio_dev->name, "adis%u\n", &device_id);
ret = sscanf(indio_dev->name, "adis%u\n", &device_id);
if (ret != 1) {
ret = -EINVAL;
goto err_ret;
}
if (prod_id != device_id)
dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
......
......@@ -765,7 +765,9 @@ static int adis16480_initial_setup(struct iio_dev *indio_dev)
if (ret)
return ret;
sscanf(indio_dev->name, "adis%u\n", &device_id);
ret = sscanf(indio_dev->name, "adis%u\n", &device_id);
if (ret != 1)
return -EINVAL;
if (prod_id != device_id)
dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
......
......@@ -1390,6 +1390,14 @@ static int kmx61_probe(struct i2c_client *client,
}
}
ret = pm_runtime_set_active(&client->dev);
if (ret < 0)
goto err_buffer_cleanup_mag;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
ret = iio_device_register(data->acc_indio_dev);
if (ret < 0) {
dev_err(&client->dev, "Failed to register acc iio device\n");
......@@ -1402,18 +1410,8 @@ static int kmx61_probe(struct i2c_client *client,
goto err_iio_unregister_acc;
}
ret = pm_runtime_set_active(&client->dev);
if (ret < 0)
goto err_iio_unregister_mag;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
return 0;
err_iio_unregister_mag:
iio_device_unregister(data->mag_indio_dev);
err_iio_unregister_acc:
iio_device_unregister(data->acc_indio_dev);
err_buffer_cleanup_mag:
......@@ -1437,13 +1435,13 @@ static int kmx61_remove(struct i2c_client *client)
{
struct kmx61_data *data = i2c_get_clientdata(client);
iio_device_unregister(data->acc_indio_dev);
iio_device_unregister(data->mag_indio_dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);
iio_device_unregister(data->acc_indio_dev);
iio_device_unregister(data->mag_indio_dev);
if (client->irq > 0) {
iio_triggered_buffer_cleanup(data->acc_indio_dev);
iio_triggered_buffer_cleanup(data->mag_indio_dev);
......
......@@ -193,7 +193,8 @@ void iio_buffer_init(struct iio_buffer *buffer)
INIT_LIST_HEAD(&buffer->buffer_list);
init_waitqueue_head(&buffer->pollq);
kref_init(&buffer->ref);
buffer->watermark = 1;
if (!buffer->watermark)
buffer->watermark = 1;
}
EXPORT_SYMBOL(iio_buffer_init);
......@@ -567,6 +568,22 @@ static void iio_buffer_deactivate_all(struct iio_dev *indio_dev)
iio_buffer_deactivate(buffer);
}
static int iio_buffer_enable(struct iio_buffer *buffer,
struct iio_dev *indio_dev)
{
if (!buffer->access->enable)
return 0;
return buffer->access->enable(buffer, indio_dev);
}
static int iio_buffer_disable(struct iio_buffer *buffer,
struct iio_dev *indio_dev)
{
if (!buffer->access->disable)
return 0;
return buffer->access->disable(buffer, indio_dev);
}
static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
struct iio_buffer *buffer)
{
......@@ -610,6 +627,7 @@ static void iio_free_scan_mask(struct iio_dev *indio_dev,
struct iio_device_config {
unsigned int mode;
unsigned int watermark;
const unsigned long *scan_mask;
unsigned int scan_bytes;
bool scan_timestamp;
......@@ -642,10 +660,14 @@ static int iio_verify_update(struct iio_dev *indio_dev,
if (buffer == remove_buffer)
continue;
modes &= buffer->access->modes;
config->watermark = min(config->watermark, buffer->watermark);
}
if (insert_buffer)
if (insert_buffer) {
modes &= insert_buffer->access->modes;
config->watermark = min(config->watermark,
insert_buffer->watermark);
}
/* Definitely possible for devices to support both of these. */
if ((modes & INDIO_BUFFER_TRIGGERED) && indio_dev->trig) {
......@@ -713,6 +735,7 @@ static int iio_verify_update(struct iio_dev *indio_dev,
static int iio_enable_buffers(struct iio_dev *indio_dev,
struct iio_device_config *config)
{
struct iio_buffer *buffer;
int ret;
indio_dev->active_scan_mask = config->scan_mask;
......@@ -743,6 +766,16 @@ static int iio_enable_buffers(struct iio_dev *indio_dev,
}
}
if (indio_dev->info->hwfifo_set_watermark)
indio_dev->info->hwfifo_set_watermark(indio_dev,
config->watermark);
list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
ret = iio_buffer_enable(buffer, indio_dev);
if (ret)
goto err_disable_buffers;
}
indio_dev->currentmode = config->mode;
if (indio_dev->setup_ops->postenable) {
......@@ -750,12 +783,16 @@ static int iio_enable_buffers(struct iio_dev *indio_dev,
if (ret) {
dev_dbg(&indio_dev->dev,
"Buffer not started: postenable failed (%d)\n", ret);
goto err_run_postdisable;
goto err_disable_buffers;
}
}
return 0;
err_disable_buffers:
list_for_each_entry_continue_reverse(buffer, &indio_dev->buffer_list,
buffer_list)
iio_buffer_disable(buffer, indio_dev);
err_run_postdisable:
indio_dev->currentmode = INDIO_DIRECT_MODE;
if (indio_dev->setup_ops->postdisable)
......@@ -768,6 +805,7 @@ static int iio_enable_buffers(struct iio_dev *indio_dev,
static int iio_disable_buffers(struct iio_dev *indio_dev)
{
struct iio_buffer *buffer;
int ret = 0;
int ret2;
......@@ -788,6 +826,12 @@ static int iio_disable_buffers(struct iio_dev *indio_dev)
ret = ret2;
}
list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
ret2 = iio_buffer_disable(buffer, indio_dev);
if (ret2 && !ret)
ret = ret2;
}
indio_dev->currentmode = INDIO_DIRECT_MODE;
if (indio_dev->setup_ops->postdisable) {
......@@ -974,9 +1018,6 @@ static ssize_t iio_buffer_store_watermark(struct device *dev,
}
buffer->watermark = val;
if (indio_dev->info->hwfifo_set_watermark)
indio_dev->info->hwfifo_set_watermark(indio_dev, val);
out:
mutex_unlock(&indio_dev->mlock);
......@@ -991,6 +1032,8 @@ static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR,
iio_buffer_show_enable, iio_buffer_store_enable);
static DEVICE_ATTR(watermark, S_IRUGO | S_IWUSR,
iio_buffer_show_watermark, iio_buffer_store_watermark);
static struct device_attribute dev_attr_watermark_ro = __ATTR(watermark,
S_IRUGO, iio_buffer_show_watermark, NULL);
static struct attribute *iio_buffer_attrs[] = {
&dev_attr_length.attr,
......@@ -1033,6 +1076,9 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
if (!buffer->access->set_length)
attr[0] = &dev_attr_length_ro.attr;
if (buffer->access->flags & INDIO_BUFFER_FLAG_FIXED_WATERMARK)
attr[2] = &dev_attr_watermark_ro.attr;
if (buffer->attrs)
memcpy(&attr[ARRAY_SIZE(iio_buffer_attrs)], buffer->attrs,
sizeof(struct attribute *) * attrcount);
......
......@@ -512,6 +512,12 @@ int iio_str_to_fixpoint(const char *str, int fract_mult,
int i = 0, f = 0;
bool integer_part = true, negative = false;
if (fract_mult == 0) {
*fract = 0;
return kstrtoint(str, 0, integer);
}
if (str[0] == '-') {
negative = true;
str++;
......@@ -571,6 +577,9 @@ static ssize_t iio_write_channel_info(struct device *dev,
if (indio_dev->info->write_raw_get_fmt)
switch (indio_dev->info->write_raw_get_fmt(indio_dev,
this_attr->c, this_attr->address)) {
case IIO_VAL_INT:
fract_mult = 0;
break;
case IIO_VAL_INT_PLUS_MICRO:
fract_mult = 100000;
break;
......
......@@ -743,8 +743,10 @@ static int lm3533_als_set_resistor(struct lm3533_als *als, u8 val)
{
int ret;
if (val < LM3533_ALS_RESISTOR_MIN || val > LM3533_ALS_RESISTOR_MAX)
if (val < LM3533_ALS_RESISTOR_MIN || val > LM3533_ALS_RESISTOR_MAX) {
dev_err(&als->pdev->dev, "invalid resistor value\n");
return -EINVAL;
};
ret = lm3533_write(als->lm3533, LM3533_REG_ALS_RESISTOR_SELECT, val);
if (ret) {
......
......@@ -381,17 +381,23 @@ static int pa12203001_probe(struct i2c_client *client,
return ret;
ret = pm_runtime_set_active(&client->dev);
if (ret < 0) {
pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
return ret;
}
if (ret < 0)
goto out_err;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev,
PA12203001_SLEEP_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
return iio_device_register(indio_dev);
ret = iio_device_register(indio_dev);
if (ret < 0)
goto out_err;
return 0;
out_err:
pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
return ret;
}
static int pa12203001_remove(struct i2c_client *client)
......
......@@ -507,34 +507,28 @@ static int rpr0521_probe(struct i2c_client *client,
dev_err(&client->dev, "rpr0521 chip init failed\n");
return ret;
}
ret = iio_device_register(indio_dev);
if (ret < 0)
return ret;
ret = pm_runtime_set_active(&client->dev);
if (ret < 0)
goto err_iio_unregister;
return ret;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
return 0;
err_iio_unregister:
iio_device_unregister(indio_dev);
return ret;
return iio_device_register(indio_dev);
}
static int rpr0521_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);
iio_device_unregister(indio_dev);
rpr0521_poweroff(iio_priv(indio_dev));
return 0;
......
......@@ -928,27 +928,24 @@ static int bmc150_magn_probe(struct i2c_client *client,
goto err_free_irq;
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "unable to register iio device\n");
goto err_buffer_cleanup;
}
ret = pm_runtime_set_active(&client->dev);
if (ret)
goto err_iio_unregister;
goto err_buffer_cleanup;
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev,
BMC150_MAGN_AUTO_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(&client->dev);
dev_dbg(&indio_dev->dev, "Registered device %s\n", name);
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "unable to register iio device\n");
goto err_buffer_cleanup;
}
dev_dbg(&indio_dev->dev, "Registered device %s\n", name);
return 0;
err_iio_unregister:
iio_device_unregister(indio_dev);
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
err_free_irq:
......@@ -967,11 +964,12 @@ static int bmc150_magn_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct bmc150_magn_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
pm_runtime_put_noidle(&client->dev);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
if (client->irq > 0)
......
......@@ -13,7 +13,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* TODO: runtime pm, interrupt mode, and signal strength reporting
* TODO: interrupt mode, and signal strength reporting
*/
#include <linux/err.h>
......@@ -21,6 +21,7 @@
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
......@@ -37,6 +38,7 @@
#define LIDAR_REG_DATA_HBYTE 0x0f
#define LIDAR_REG_DATA_LBYTE 0x10
#define LIDAR_REG_PWR_CONTROL 0x65
#define LIDAR_DRV_NAME "lidar"
......@@ -90,6 +92,12 @@ static inline int lidar_write_control(struct lidar_data *data, int val)
return i2c_smbus_write_byte_data(data->client, LIDAR_REG_CONTROL, val);
}
static inline int lidar_write_power(struct lidar_data *data, int val)
{
return i2c_smbus_write_byte_data(data->client,
LIDAR_REG_PWR_CONTROL, val);
}
static int lidar_read_measurement(struct lidar_data *data, u16 *reg)
{
int ret;
......@@ -116,6 +124,8 @@ static int lidar_get_measurement(struct lidar_data *data, u16 *reg)
int tries = 10;
int ret;
pm_runtime_get_sync(&client->dev);
/* start sample */
ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE);
if (ret < 0) {
......@@ -144,6 +154,8 @@ static int lidar_get_measurement(struct lidar_data *data, u16 *reg)
}
ret = -EIO;
}
pm_runtime_mark_last_busy(&client->dev);
pm_runtime_put_autosuspend(&client->dev);
return ret;
}
......@@ -243,6 +255,17 @@ static int lidar_probe(struct i2c_client *client,
if (ret)
goto error_unreg_buffer;
pm_runtime_set_autosuspend_delay(&client->dev, 1000);
pm_runtime_use_autosuspend(&client->dev);
ret = pm_runtime_set_active(&client->dev);
if (ret)
goto error_unreg_buffer;
pm_runtime_enable(&client->dev);
pm_runtime_mark_last_busy(&client->dev);
pm_runtime_idle(&client->dev);
return 0;
error_unreg_buffer:
......@@ -258,6 +281,9 @@ static int lidar_remove(struct i2c_client *client)
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
return 0;
}
......@@ -273,10 +299,38 @@ static const struct of_device_id lidar_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, lidar_dt_ids);
#ifdef CONFIG_PM
static int lidar_pm_runtime_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct lidar_data *data = iio_priv(indio_dev);
return lidar_write_power(data, 0x0f);
}
static int lidar_pm_runtime_resume(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct lidar_data *data = iio_priv(indio_dev);
int ret = lidar_write_power(data, 0);
/* regulator and FPGA needs settling time */
usleep_range(15000, 20000);
return ret;
}
#endif
static const struct dev_pm_ops lidar_pm_ops = {
SET_RUNTIME_PM_OPS(lidar_pm_runtime_suspend,
lidar_pm_runtime_resume, NULL)
};
static struct i2c_driver lidar_driver = {
.driver = {
.name = LIDAR_DRV_NAME,
.of_match_table = of_match_ptr(lidar_dt_ids),
.pm = &lidar_pm_ops,
},
.probe = lidar_probe,
.remove = lidar_remove,
......
......@@ -17,33 +17,4 @@ source "drivers/staging/iio/meter/Kconfig"
source "drivers/staging/iio/resolver/Kconfig"
source "drivers/staging/iio/trigger/Kconfig"
config IIO_DUMMY_EVGEN
tristate
select IRQ_WORK
config IIO_SIMPLE_DUMMY
tristate "An example driver with no hardware requirements"
help
Driver intended mainly as documentation for how to write
a driver. May also be useful for testing userspace code
without hardware.
if IIO_SIMPLE_DUMMY
config IIO_SIMPLE_DUMMY_EVENTS
bool "Event generation support"
select IIO_DUMMY_EVGEN
help
Add some dummy events to the simple dummy driver.
config IIO_SIMPLE_DUMMY_BUFFER
bool "Buffered capture support"
select IIO_BUFFER
select IIO_TRIGGER
select IIO_KFIFO_BUF
help
Add buffered data capture to the simple dummy driver.
endif # IIO_SIMPLE_DUMMY
endmenu
......@@ -2,13 +2,6 @@
# Makefile for the industrial I/O core.
#
obj-$(CONFIG_IIO_SIMPLE_DUMMY) += iio_dummy.o
iio_dummy-y := iio_simple_dummy.o
iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_EVENTS) += iio_simple_dummy_events.o
iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_BUFFER) += iio_simple_dummy_buffer.o
obj-$(CONFIG_IIO_DUMMY_EVGEN) += iio_dummy_evgen.o
obj-y += accel/
obj-y += adc/
obj-y += addac/
......
......@@ -15,15 +15,13 @@
#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <linux/sched.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/adc/ad_sigma_delta.h>
#include "ad7780.h"
#define AD7780_RDY BIT(7)
#define AD7780_FILTER BIT(6)
#define AD7780_ERR BIT(5)
......@@ -42,7 +40,7 @@ struct ad7780_chip_info {
struct ad7780_state {
const struct ad7780_chip_info *chip_info;
struct regulator *reg;
int powerdown_gpio;
struct gpio_desc *powerdown_gpio;
unsigned int gain;
u16 int_vref_mv;
......@@ -77,8 +75,7 @@ static int ad7780_set_mode(struct ad_sigma_delta *sigma_delta,
break;
}
if (gpio_is_valid(st->powerdown_gpio))
gpio_set_value(st->powerdown_gpio, val);
gpiod_set_value(st->powerdown_gpio, val);
return 0;
}
......@@ -163,7 +160,6 @@ static const struct iio_info ad7780_info = {
static int ad7780_probe(struct spi_device *spi)
{
struct ad7780_platform_data *pdata = spi->dev.platform_data;
struct ad7780_state *st;
struct iio_dev *indio_dev;
int ret, voltage_uv = 0;
......@@ -189,12 +185,10 @@ static int ad7780_probe(struct spi_device *spi)
st->chip_info =
&ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data];
if (pdata && pdata->vref_mv)
st->int_vref_mv = pdata->vref_mv;
else if (voltage_uv)
if (voltage_uv)
st->int_vref_mv = voltage_uv / 1000;
else
dev_warn(&spi->dev, "reference voltage unspecified\n");
dev_warn(&spi->dev, "Reference voltage unspecified\n");
spi_set_drvdata(spi, indio_dev);
......@@ -205,18 +199,14 @@ static int ad7780_probe(struct spi_device *spi)
indio_dev->num_channels = 1;
indio_dev->info = &ad7780_info;
if (pdata && gpio_is_valid(pdata->gpio_pdrst)) {
ret = devm_gpio_request_one(&spi->dev,
pdata->gpio_pdrst,
GPIOF_OUT_INIT_LOW,
"AD7780 /PDRST");
if (ret) {
dev_err(&spi->dev, "failed to request GPIO PDRST\n");
goto error_disable_reg;
}
st->powerdown_gpio = pdata->gpio_pdrst;
} else {
st->powerdown_gpio = -1;
st->powerdown_gpio = devm_gpiod_get_optional(&spi->dev,
"powerdown",
GPIOD_OUT_LOW);
if (IS_ERR(st->powerdown_gpio)) {
ret = PTR_ERR(st->powerdown_gpio);
dev_err(&spi->dev, "Failed to request powerdown GPIO: %d\n",
ret);
goto error_disable_reg;
}
ret = ad_sd_setup_buffer_and_trigger(indio_dev);
......
/*
* AD7780/AD7781 SPI ADC driver
*
* Copyright 2011 Analog Devices Inc.
*
* Licensed under the GPL-2.
*/
#ifndef IIO_ADC_AD7780_H_
#define IIO_ADC_AD7780_H_
/*
* TODO: struct ad7780_platform_data needs to go into include/linux/iio
*/
/* NOTE:
* The AD7780 doesn't feature a dedicated SPI chip select, in addition it
* features a dual use data out ready DOUT/RDY output.
* In order to avoid contentions on the SPI bus, it's therefore necessary
* to use spi bus locking combined with a dedicated GPIO to control the
* power down reset signal of the AD7780.
*
* The DOUT/RDY output must also be wired to an interrupt capable GPIO.
*/
struct ad7780_platform_data {
u16 vref_mv;
int gpio_pdrst;
};
#endif /* IIO_ADC_AD7780_H_ */
......@@ -324,7 +324,7 @@ struct mxs_lradc {
#define LRADC_DELAY_TRIGGER(x) \
(((x) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) & \
LRADC_DELAY_TRIGGER_LRADCS_MASK)
#define LRADC_DELAY_KICK (1 << 20)
#define LRADC_DELAY_KICK BIT(20)
#define LRADC_DELAY_TRIGGER_DELAYS_MASK (0xf << 16)
#define LRADC_DELAY_TRIGGER_DELAYS_OFFSET 16
#define LRADC_DELAY_TRIGGER_DELAYS(x) \
......
/*
* Copyright 2013-2015 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2.
*/
#ifndef __INDUSTRIALIO_DMA_BUFFER_H__
#define __INDUSTRIALIO_DMA_BUFFER_H__
#include <linux/list.h>
#include <linux/kref.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/iio/buffer.h>
struct iio_dma_buffer_queue;
struct iio_dma_buffer_ops;
struct device;
struct iio_buffer_block {
u32 size;
u32 bytes_used;
};
/**
* enum iio_block_state - State of a struct iio_dma_buffer_block
* @IIO_BLOCK_STATE_DEQUEUED: Block is not queued
* @IIO_BLOCK_STATE_QUEUED: Block is on the incoming queue
* @IIO_BLOCK_STATE_ACTIVE: Block is currently being processed by the DMA
* @IIO_BLOCK_STATE_DONE: Block is on the outgoing queue
* @IIO_BLOCK_STATE_DEAD: Block has been marked as to be freed
*/
enum iio_block_state {
IIO_BLOCK_STATE_DEQUEUED,
IIO_BLOCK_STATE_QUEUED,
IIO_BLOCK_STATE_ACTIVE,
IIO_BLOCK_STATE_DONE,
IIO_BLOCK_STATE_DEAD,
};
/**
* struct iio_dma_buffer_block - IIO buffer block
* @head: List head
* @size: Total size of the block in bytes
* @bytes_used: Number of bytes that contain valid data
* @vaddr: Virutal address of the blocks memory
* @phys_addr: Physical address of the blocks memory
* @queue: Parent DMA buffer queue
* @kref: kref used to manage the lifetime of block
* @state: Current state of the block
*/
struct iio_dma_buffer_block {
/* May only be accessed by the owner of the block */
struct list_head head;
size_t bytes_used;
/*
* Set during allocation, constant thereafter. May be accessed read-only
* by anybody holding a reference to the block.
*/
void *vaddr;
dma_addr_t phys_addr;
size_t size;
struct iio_dma_buffer_queue *queue;
/* Must not be accessed outside the core. */
struct kref kref;
/*
* Must not be accessed outside the core. Access needs to hold
* queue->list_lock if the block is not owned by the core.
*/
enum iio_block_state state;
};
/**
* struct iio_dma_buffer_queue_fileio - FileIO state for the DMA buffer
* @blocks: Buffer blocks used for fileio
* @active_block: Block being used in read()
* @pos: Read offset in the active block
* @block_size: Size of each block
*/
struct iio_dma_buffer_queue_fileio {
struct iio_dma_buffer_block *blocks[2];
struct iio_dma_buffer_block *active_block;
size_t pos;
size_t block_size;
};
/**
* struct iio_dma_buffer_queue - DMA buffer base structure
* @buffer: IIO buffer base structure
* @dev: Parent device
* @ops: DMA buffer callbacks
* @lock: Protects the incoming list, active and the fields in the fileio
* substruct
* @list_lock: Protects lists that contain blocks which can be modified in
* atomic context as well as blocks on those lists. This is the outgoing queue
* list and typically also a list of active blocks in the part that handles
* the DMA controller
* @incoming: List of buffers on the incoming queue
* @outgoing: List of buffers on the outgoing queue
* @active: Whether the buffer is currently active
* @fileio: FileIO state
*/
struct iio_dma_buffer_queue {
struct iio_buffer buffer;
struct device *dev;
const struct iio_dma_buffer_ops *ops;
struct mutex lock;
spinlock_t list_lock;
struct list_head incoming;
struct list_head outgoing;
bool active;
struct iio_dma_buffer_queue_fileio fileio;
};
/**
* struct iio_dma_buffer_ops - DMA buffer callback operations
* @submit: Called when a block is submitted to the DMA controller
* @abort: Should abort all pending transfers
*/
struct iio_dma_buffer_ops {
int (*submit)(struct iio_dma_buffer_queue *queue,
struct iio_dma_buffer_block *block);
void (*abort)(struct iio_dma_buffer_queue *queue);
};
void iio_dma_buffer_block_done(struct iio_dma_buffer_block *block);
void iio_dma_buffer_block_list_abort(struct iio_dma_buffer_queue *queue,
struct list_head *list);
int iio_dma_buffer_enable(struct iio_buffer *buffer,
struct iio_dev *indio_dev);
int iio_dma_buffer_disable(struct iio_buffer *buffer,
struct iio_dev *indio_dev);
int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n,
char __user *user_buffer);
size_t iio_dma_buffer_data_available(struct iio_buffer *buffer);
int iio_dma_buffer_set_bytes_per_datum(struct iio_buffer *buffer, size_t bpd);
int iio_dma_buffer_set_length(struct iio_buffer *buffer, int length);
int iio_dma_buffer_request_update(struct iio_buffer *buffer);
int iio_dma_buffer_init(struct iio_dma_buffer_queue *queue,
struct device *dma_dev, const struct iio_dma_buffer_ops *ops);
void iio_dma_buffer_exit(struct iio_dma_buffer_queue *queue);
void iio_dma_buffer_release(struct iio_dma_buffer_queue *queue);
#endif
/*
* Copyright 2014-2015 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2 or later.
*/
#ifndef __IIO_DMAENGINE_H__
#define __IIO_DMAENGINE_H__
struct iio_buffer;
struct device;
struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
const char *channel);
void iio_dmaengine_buffer_free(struct iio_buffer *buffer);
#endif
......@@ -17,6 +17,12 @@
struct iio_buffer;
/**
* INDIO_BUFFER_FLAG_FIXED_WATERMARK - Watermark level of the buffer can not be
* configured. It has a fixed value which will be buffer specific.
*/
#define INDIO_BUFFER_FLAG_FIXED_WATERMARK BIT(0)
/**
* struct iio_buffer_access_funcs - access functions for buffers.
* @store_to: actually store stuff to the buffer
......@@ -27,9 +33,15 @@ struct iio_buffer;
* storage.
* @set_bytes_per_datum:set number of bytes per datum
* @set_length: set number of datums in buffer
* @enable: called if the buffer is attached to a device and the
* device starts sampling. Calls are balanced with
* @disable.
* @disable: called if the buffer is attached to a device and the
* device stops sampling. Calles are balanced with @enable.
* @release: called when the last reference to the buffer is dropped,
* should free all resources allocated by the buffer.
* @modes: Supported operating modes by this buffer type
* @flags: A bitmask combination of INDIO_BUFFER_FLAG_*
*
* The purpose of this structure is to make the buffer element
* modular as event for a given driver, different usecases may require
......@@ -51,9 +63,13 @@ struct iio_buffer_access_funcs {
int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd);
int (*set_length)(struct iio_buffer *buffer, int length);
int (*enable)(struct iio_buffer *buffer, struct iio_dev *indio_dev);
int (*disable)(struct iio_buffer *buffer, struct iio_dev *indio_dev);
void (*release)(struct iio_buffer *buffer);
unsigned int modes;
unsigned int flags;
};
/**
......
......@@ -134,21 +134,32 @@ struct palmas_pmic_driver_data {
struct regulator_config config);
};
struct palmas_adc_wakeup_property {
int adc_channel_number;
int adc_high_threshold;
int adc_low_threshold;
};
struct palmas_gpadc_platform_data {
/* Channel 3 current source is only enabled during conversion */
int ch3_current;
int ch3_current; /* 0: off; 1: 10uA; 2: 400uA; 3: 800 uA */
/* Channel 0 current source can be used for battery detection.
* If used for battery detection this will cause a permanent current
* consumption depending on current level set here.
*/
int ch0_current;
int ch0_current; /* 0: off; 1: 5uA; 2: 15uA; 3: 20 uA */
bool extended_delay; /* use extended delay for conversion */
/* default BAT_REMOVAL_DAT setting on device probe */
int bat_removal;
/* Sets the START_POLARITY bit in the RT_CTRL register */
int start_polarity;
int auto_conversion_period_ms;
struct palmas_adc_wakeup_property *adc_wakeup1_data;
struct palmas_adc_wakeup_property *adc_wakeup2_data;
};
struct palmas_reg_init {
......@@ -405,28 +416,7 @@ struct palmas_gpadc_calibration {
s32 offset_error;
};
struct palmas_gpadc {
struct device *dev;
struct palmas *palmas;
int ch3_current;
int ch0_current;
int gpadc_force;
int bat_removal;
struct mutex reading_lock;
struct completion irq_complete;
int eoc_sw_irq;
struct palmas_gpadc_calibration *palmas_cal_tbl;
int conv0_channel;
int conv1_channel;
int rt_channel;
};
#define PALMAS_DATASHEET_NAME(_name) "palmas-gpadc-chan-"#_name
struct palmas_gpadc_result {
s32 raw_code;
......@@ -520,6 +510,43 @@ enum palmas_irqs {
PALMAS_NUM_IRQ,
};
/* Palmas GPADC Channels */
enum {
PALMAS_ADC_CH_IN0,
PALMAS_ADC_CH_IN1,
PALMAS_ADC_CH_IN2,
PALMAS_ADC_CH_IN3,
PALMAS_ADC_CH_IN4,
PALMAS_ADC_CH_IN5,
PALMAS_ADC_CH_IN6,
PALMAS_ADC_CH_IN7,
PALMAS_ADC_CH_IN8,
PALMAS_ADC_CH_IN9,
PALMAS_ADC_CH_IN10,
PALMAS_ADC_CH_IN11,
PALMAS_ADC_CH_IN12,
PALMAS_ADC_CH_IN13,
PALMAS_ADC_CH_IN14,
PALMAS_ADC_CH_IN15,
PALMAS_ADC_CH_MAX,
};
/* Palmas GPADC Channel0 Current Source */
enum {
PALMAS_ADC_CH0_CURRENT_SRC_0,
PALMAS_ADC_CH0_CURRENT_SRC_5,
PALMAS_ADC_CH0_CURRENT_SRC_15,
PALMAS_ADC_CH0_CURRENT_SRC_20,
};
/* Palmas GPADC Channel3 Current Source */
enum {
PALMAS_ADC_CH3_CURRENT_SRC_0,
PALMAS_ADC_CH3_CURRENT_SRC_10,
PALMAS_ADC_CH3_CURRENT_SRC_400,
PALMAS_ADC_CH3_CURRENT_SRC_800,
};
struct palmas_pmic {
struct palmas *palmas;
struct device *dev;
......
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