提交 1c46ae0a 编写于 作者: G Greg Kroah-Hartman

Merge tag 'iio-for-4.3b-2' of...

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

Jonathan writes:

Second set of new device support, features and cleanup for the 4.3 cycle.
Take 2 also includes a fix set that was too late for the 4.2 cycle.

As we had a lot of tools and docs work in this set, I have broken those
out into their own categories in this description.

Fixes from the pull request '4th set of IIO fixes for the 4.2 cycle'.
* Poll functions for both event chardev and the buffer one were returning
  negative error codes (via a positive value).
* A recent change to lsiio adding some error handling that was wrong and
  stopped the tool working.
* bmg160 was missing some dependencies in Kconfig
* berlin2-adc had a misshandled register (wrote a value rather than a bitmap)

New device support
* TI opt3001 light sensor
* TXC PA12 ALS and proximity sensor.
* mcp3301 ADC support (in mcp320x driver)
* ST lsm303agr accelerometer and magnetometer drivers (plus some st-sensors
  common support to allow different WHOAMI register addresses, devices with
  fixed scale and allow interrupt equiped magnetometers).
* ADIS16305, ADIS16367, ADIS16445IMUs (in the adis16400 driver)
* ADIS16266 gyro (in the adis16260 driver)
* ADIS16137 gyro (in the adis16136 driver)

New functionality
* mmc35240 DT bindings.
* Inverse unit conversion macros to aid handing of values written to sysfs
  attributes.

Core cleanup
* Forward declaration of struct iio_trigger to avoid a compile warning.

Driver cleanup / fixes
* mxs-lradc
  - Clarify which parts are supported.
  - Fix spelling erorrs.
  - Missing/extra includes
  - reorder includes
  - add datasheet name listings for all usable channels (to allow them
    to be bound by name from consumer drivers)
* acpi-als - add some function prefixes as per general iio style.
* bmc150_magn - replace a magic value with the existing define.
* vf610 - determine possible sample frequencies taking into account the
  electrical characteristics (defining a minimum sample time)
* dht11
  - whitespace
  - additional docs
  - avoid mulitple assignments in one line
  - Use the new funciton ktime_get_resolution_ns to cleanup a nasty trick
    previously used for timing.
* Fix all drivers that consider 0 a valid IRQ for historical reasons.
* Export I2C module alias info where previously missing (to allow autoprobing)
* Export OF module alias info where previously missing.
* mmc35240 - switch some variables into arrays to improve readability.
* mlx90614 - define some magic numbers for readability.
* bmc150_magn
  - expand area locked by a mutex to cover all the use of the
    data->buffer.
  - use descriptive naming for a mask instead of a magic value.
* berin2-adc
  - pass up an error code rather that a generic error
  - constify the iio_chan_spec
  - some other little tidy ups.
* stk8312
  - fix a dependency on triggered buffers in kconfig
  - add a check for invalid attribute values
  - improve error handling by returning error codes where possible and
    return immediately where relevant
  - rework macro defs to use GENMASK etc
  - change some variable types to reduce unnecessary casting
  - clean up code style
  - drop a local buffer copy for bulk reads and use the one in data->buffer
     instead.
* adis16400 - the adis16448 gyroscope scale was wrong.
* adis16480 - some more wrong scales for various parts.
* adis16300 - has an undocumented product id and serial number registers so
  use them.
* iio_simple_dummy - fix some wrong code indentation.
* bmc150-accel - use the chip ID to detect the chip present rather than
  verifying the expected part was there.  This was in response to a wrong
  ACPI entry on the WinBook TW100.
* mma8452
  - fix _get_hp_filter_index
  - drop a double include
  - pass up an error code rather than rewriting it
  - range check input values to attribute writes
  - register defs tidy up using GENMASK and reordering them to be easier to
    follow.
  - various coding style cleanups
  - put the Kconfig entry in the write place (alphabetically).

Tools related
* Tools cleanup - drop an explicity NULL comparison, some unnecessary braces,
  use the ARRAY_SIZE macro, send error messages to stderr instead of dropping
  them in the middle of normal output.
* Fix tools to allow that scale and offset attributes are optional.
* More tools fixes including allowing true 32bit data (previously an overflow
  prevented more than 31bits)
* Drop a stray header guard that ended up in a c file.
* Make calc_digits static as it isn't exported or in the header.
* Set ci_array pointer to NULL after free as a protection against non safe
  usage of the tools core code.  Also convert a double pointer to a single
  one as the extra level of indirection was unnecessary.

Docs
* DocBook introduction by Daniel Baluta.  Glad we are beginning to
  draw together some more introductory docs to suplement the various
  tools / examples.
* Drop bytes_per_datum sysfs attribute docs as it no longer exists.
* A whole load of missing / fixing of kernel-doc for the core of IIO.
* Document the trigger name sysfs attribute in the ABI docs.
* Minor typos in the ABI docs related to power down modes.
......@@ -493,7 +493,7 @@ Contact: linux-iio@vger.kernel.org
Description:
Specifies the output powerdown mode.
DAC output stage is disconnected from the amplifier and
1kohm_to_gnd: connected to ground via an 1kOhm resistor,
1kohm_to_gnd: connected to ground via an 1kOhm resistor,
6kohm_to_gnd: connected to ground via a 6kOhm resistor,
20kohm_to_gnd: connected to ground via a 20kOhm resistor,
100kohm_to_gnd: connected to ground via an 100kOhm resistor,
......@@ -503,9 +503,9 @@ Description:
outX_powerdown_mode_available. If Y is not present the
mode is shared across all outputs.
What: /sys/.../iio:deviceX/out_votlageY_powerdown_mode_available
What: /sys/.../iio:deviceX/out_voltageY_powerdown_mode_available
What: /sys/.../iio:deviceX/out_voltage_powerdown_mode_available
What: /sys/.../iio:deviceX/out_altvotlageY_powerdown_mode_available
What: /sys/.../iio:deviceX/out_altvoltageY_powerdown_mode_available
What: /sys/.../iio:deviceX/out_altvoltage_powerdown_mode_available
KernelVersion: 2.6.38
Contact: linux-iio@vger.kernel.org
......@@ -1040,13 +1040,6 @@ Contact: linux-iio@vger.kernel.org
Description:
Number of scans contained by the buffer.
What: /sys/bus/iio/devices/iio:deviceX/buffer/bytes_per_datum
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
Bytes per scan. Due to alignment fun, the scan may be larger
than implied directly by the scan_element parameters.
What: /sys/bus/iio/devices/iio:deviceX/buffer/enable
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
......
......@@ -9,3 +9,12 @@ Description:
automated testing or in situations, where other trigger methods
are not applicable. For example no RTC or spare GPIOs.
X is the IIO index of the trigger.
What: /sys/bus/iio/devices/triggerX/name
KernelVersion: 2.6.39
Contact: linux-iio@vger.kernel.org
Description:
The name attribute holds a description string for the current
trigger. In order to associate the trigger with an IIO device
one should write this name string to
/sys/bus/iio/devices/iio:deviceY/trigger/current_trigger.
......@@ -15,7 +15,7 @@ DOCBOOKS := z8530book.xml device-drivers.xml \
80211.xml debugobjects.xml sh.xml regulator.xml \
alsa-driver-api.xml writing-an-alsa-driver.xml \
tracepoint.xml drm.xml media_api.xml w1.xml \
writing_musb_glue_layer.xml crypto-API.xml
writing_musb_glue_layer.xml crypto-API.xml iio.xml
include Documentation/DocBook/media/Makefile
......
此差异已折叠。
......@@ -18,6 +18,7 @@ Required properties:
"mcp3202"
"mcp3204"
"mcp3208"
"mcp3301"
Examples:
......
......@@ -17,6 +17,11 @@ Recommended properties:
- Frequency in normal mode (ADLPC=0, ADHSC=0)
- Frequency in high-speed mode (ADLPC=0, ADHSC=1)
- Frequency in low-power mode (ADLPC=1, ADHSC=0)
- min-sample-time: Minimum sampling time in nanoseconds. This value has
to be chosen according to the conversion mode and the connected analog
source resistance (R_as) and capacitance (C_as). Refer the datasheet's
operating requirements. A safe default across a wide range of R_as and
C_as as well as conversion modes is 1000ns.
Example:
adc0: adc@4003b000 {
......
* MEMSIC MMC35240 magnetometer sensor
Required properties:
- compatible : should be "memsic,mmc35240"
- reg : the I2C address of the magnetometer
Example:
mmc35240@30 {
compatible = "memsic,mmc35240";
reg = <0x30>;
};
......@@ -35,6 +35,7 @@ Accelerometers:
- st,lsm303dl-accel
- st,lsm303dlm-accel
- st,lsm330-accel
- st,lsm303agr-accel
Gyroscopes:
- st,l3g4200d-gyro
......@@ -46,6 +47,7 @@ Gyroscopes:
- st,lsm330-gyro
Magnetometers:
- st,lsm303agr-magn
- st,lsm303dlh-magn
- st,lsm303dlhc-magn
- st,lsm303dlm-magn
......
* Freescale i.MX28 LRADC device driver
* Freescale MXS LRADC device driver
Required properties:
- compatible: Should be "fsl,imx23-lradc" for i.MX23 SoC and "fsl,imx28-lradc"
......
......@@ -86,18 +86,6 @@ config KXSD9
To compile this driver as a module, choose M here: the module
will be called kxsd9.
config MMA8452
tristate "Freescale MMA8452Q Accelerometer Driver"
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for the Freescale MMA8452Q 3-axis
accelerometer.
To compile this driver as a module, choose M here: the module
will be called mma8452.
config KXCJK1013
tristate "Kionix 3-Axis Accelerometer Driver"
depends on I2C
......@@ -111,6 +99,18 @@ config KXCJK1013
To compile this driver as a module, choose M here: the module will
be called kxcjk-1013.
config MMA8452
tristate "Freescale MMA8452Q Accelerometer Driver"
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for the Freescale MMA8452Q 3-axis
accelerometer.
To compile this driver as a module, choose M here: the module
will be called mma8452.
config MMA9551_CORE
tristate
......@@ -140,6 +140,8 @@ config MMA9553
config STK8312
tristate "Sensortek STK8312 3-Axis Accelerometer Driver"
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to get support for the Sensortek STK8312 3-axis
accelerometer.
......
......@@ -151,6 +151,7 @@ struct bmc150_scale_info {
};
struct bmc150_accel_chip_info {
const char *name;
u8 chip_id;
const struct iio_chan_spec *channels;
int num_channels;
......@@ -345,63 +346,6 @@ static int bmc150_accel_any_motion_setup(struct bmc150_accel_trigger *t,
return 0;
}
static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
{
int ret;
ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_CHIP_ID);
if (ret < 0) {
dev_err(&data->client->dev, "Error: Reading chip id\n");
return ret;
}
dev_dbg(&data->client->dev, "Chip Id %x\n", ret);
if (ret != data->chip_info->chip_id) {
dev_err(&data->client->dev, "Invalid chip %x\n", ret);
return -ENODEV;
}
ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
if (ret < 0)
return ret;
/* Set Bandwidth */
ret = bmc150_accel_set_bw(data, BMC150_ACCEL_DEF_BW, 0);
if (ret < 0)
return ret;
/* Set Default Range */
ret = i2c_smbus_write_byte_data(data->client,
BMC150_ACCEL_REG_PMU_RANGE,
BMC150_ACCEL_DEF_RANGE_4G);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_pmu_range\n");
return ret;
}
data->range = BMC150_ACCEL_DEF_RANGE_4G;
/* Set default slope duration and thresholds */
data->slope_thres = BMC150_ACCEL_DEF_SLOPE_THRESHOLD;
data->slope_dur = BMC150_ACCEL_DEF_SLOPE_DURATION;
ret = bmc150_accel_update_slope(data);
if (ret < 0)
return ret;
/* Set default as latched interrupts */
ret = i2c_smbus_write_byte_data(data->client,
BMC150_ACCEL_REG_INT_RST_LATCH,
BMC150_ACCEL_INT_MODE_LATCH_INT |
BMC150_ACCEL_INT_MODE_LATCH_RESET);
if (ret < 0) {
dev_err(&data->client->dev,
"Error writing reg_int_rst_latch\n");
return ret;
}
return 0;
}
static int bmc150_accel_get_bw(struct bmc150_accel_data *data, int *val,
int *val2)
{
......@@ -1119,6 +1063,7 @@ enum {
static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
[bmc150] = {
.name = "BMC150A",
.chip_id = 0xFA,
.channels = bmc150_accel_channels,
.num_channels = ARRAY_SIZE(bmc150_accel_channels),
......@@ -1128,6 +1073,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
{76590, BMC150_ACCEL_DEF_RANGE_16G} },
},
[bmi055] = {
.name = "BMI055A",
.chip_id = 0xFA,
.channels = bmc150_accel_channels,
.num_channels = ARRAY_SIZE(bmc150_accel_channels),
......@@ -1137,6 +1083,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
{76590, BMC150_ACCEL_DEF_RANGE_16G} },
},
[bma255] = {
.name = "BMA0255",
.chip_id = 0xFA,
.channels = bmc150_accel_channels,
.num_channels = ARRAY_SIZE(bmc150_accel_channels),
......@@ -1146,6 +1093,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
{76590, BMC150_ACCEL_DEF_RANGE_16G} },
},
[bma250e] = {
.name = "BMA250E",
.chip_id = 0xF9,
.channels = bma250e_accel_channels,
.num_channels = ARRAY_SIZE(bma250e_accel_channels),
......@@ -1155,6 +1103,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
{306457, BMC150_ACCEL_DEF_RANGE_16G} },
},
[bma222e] = {
.name = "BMA222E",
.chip_id = 0xF8,
.channels = bma222e_accel_channels,
.num_channels = ARRAY_SIZE(bma222e_accel_channels),
......@@ -1164,6 +1113,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
{1225831, BMC150_ACCEL_DEF_RANGE_16G} },
},
[bma280] = {
.name = "BMA0280",
.chip_id = 0xFB,
.channels = bma280_accel_channels,
.num_channels = ARRAY_SIZE(bma280_accel_channels),
......@@ -1410,20 +1360,6 @@ static irqreturn_t bmc150_accel_irq_handler(int irq, void *private)
return IRQ_NONE;
}
static const char *bmc150_accel_match_acpi_device(struct device *dev, int *data)
{
const struct acpi_device_id *id;
id = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!id)
return NULL;
*data = (int)id->driver_data;
return dev_name(dev);
}
static int bmc150_accel_gpio_probe(struct i2c_client *client,
struct bmc150_accel_data *data)
{
......@@ -1618,6 +1554,70 @@ static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = {
.postdisable = bmc150_accel_buffer_postdisable,
};
static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
{
int ret, i;
ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_CHIP_ID);
if (ret < 0) {
dev_err(&data->client->dev, "Error: Reading chip id\n");
return ret;
}
dev_dbg(&data->client->dev, "Chip Id %x\n", ret);
for (i = 0; i < ARRAY_SIZE(bmc150_accel_chip_info_tbl); i++) {
if (bmc150_accel_chip_info_tbl[i].chip_id == ret) {
data->chip_info = &bmc150_accel_chip_info_tbl[i];
break;
}
}
if (!data->chip_info) {
dev_err(&data->client->dev, "Unsupported chip %x\n", ret);
return -ENODEV;
}
ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
if (ret < 0)
return ret;
/* Set Bandwidth */
ret = bmc150_accel_set_bw(data, BMC150_ACCEL_DEF_BW, 0);
if (ret < 0)
return ret;
/* Set Default Range */
ret = i2c_smbus_write_byte_data(data->client,
BMC150_ACCEL_REG_PMU_RANGE,
BMC150_ACCEL_DEF_RANGE_4G);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_pmu_range\n");
return ret;
}
data->range = BMC150_ACCEL_DEF_RANGE_4G;
/* Set default slope duration and thresholds */
data->slope_thres = BMC150_ACCEL_DEF_SLOPE_THRESHOLD;
data->slope_dur = BMC150_ACCEL_DEF_SLOPE_DURATION;
ret = bmc150_accel_update_slope(data);
if (ret < 0)
return ret;
/* Set default as latched interrupts */
ret = i2c_smbus_write_byte_data(data->client,
BMC150_ACCEL_REG_INT_RST_LATCH,
BMC150_ACCEL_INT_MODE_LATCH_INT |
BMC150_ACCEL_INT_MODE_LATCH_RESET);
if (ret < 0) {
dev_err(&data->client->dev,
"Error writing reg_int_rst_latch\n");
return ret;
}
return 0;
}
static int bmc150_accel_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
......@@ -1625,7 +1625,6 @@ static int bmc150_accel_probe(struct i2c_client *client,
struct iio_dev *indio_dev;
int ret;
const char *name = NULL;
int chip_id = 0;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
......@@ -1635,15 +1634,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
i2c_set_clientdata(client, indio_dev);
data->client = client;
if (id) {
if (id)
name = id->name;
chip_id = id->driver_data;
}
if (ACPI_HANDLE(&client->dev))
name = bmc150_accel_match_acpi_device(&client->dev, &chip_id);
data->chip_info = &bmc150_accel_chip_info_tbl[chip_id];
ret = bmc150_accel_chip_init(data);
if (ret < 0)
......@@ -1654,7 +1646,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
indio_dev->dev.parent = &client->dev;
indio_dev->channels = data->chip_info->channels;
indio_dev->num_channels = data->chip_info->num_channels;
indio_dev->name = name;
indio_dev->name = name ? name : data->chip_info->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &bmc150_accel_info;
......@@ -1670,7 +1662,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
if (client->irq < 0)
client->irq = bmc150_accel_gpio_probe(client, data);
if (client->irq >= 0) {
if (client->irq > 0) {
ret = devm_request_threaded_irq(
&client->dev, client->irq,
bmc150_accel_irq_handler,
......
......@@ -1240,7 +1240,7 @@ static int kxcjk1013_probe(struct i2c_client *client,
if (client->irq < 0)
client->irq = kxcjk1013_gpio_probe(client, data);
if (client->irq >= 0) {
if (client->irq > 0) {
ret = devm_request_threaded_irq(&client->dev, client->irq,
kxcjk1013_data_rdy_trig_poll,
kxcjk1013_event_handler,
......
......@@ -16,7 +16,6 @@
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
......@@ -24,54 +23,51 @@
#include <linux/iio/events.h>
#include <linux/delay.h>
#define MMA8452_STATUS 0x00
#define MMA8452_OUT_X 0x01 /* MSB first, 12-bit */
#define MMA8452_OUT_Y 0x03
#define MMA8452_OUT_Z 0x05
#define MMA8452_INT_SRC 0x0c
#define MMA8452_WHO_AM_I 0x0d
#define MMA8452_DATA_CFG 0x0e
#define MMA8452_HP_FILTER_CUTOFF 0x0f
#define MMA8452_HP_FILTER_CUTOFF_SEL_MASK (BIT(0) | BIT(1))
#define MMA8452_TRANSIENT_CFG 0x1d
#define MMA8452_TRANSIENT_CFG_ELE BIT(4)
#define MMA8452_TRANSIENT_CFG_CHAN(chan) BIT(chan + 1)
#define MMA8452_TRANSIENT_CFG_HPF_BYP BIT(0)
#define MMA8452_TRANSIENT_SRC 0x1e
#define MMA8452_TRANSIENT_SRC_XTRANSE BIT(1)
#define MMA8452_TRANSIENT_SRC_YTRANSE BIT(3)
#define MMA8452_TRANSIENT_SRC_ZTRANSE BIT(5)
#define MMA8452_TRANSIENT_THS 0x1f
#define MMA8452_TRANSIENT_THS_MASK 0x7f
#define MMA8452_TRANSIENT_COUNT 0x20
#define MMA8452_OFF_X 0x2f
#define MMA8452_OFF_Y 0x30
#define MMA8452_OFF_Z 0x31
#define MMA8452_CTRL_REG1 0x2a
#define MMA8452_CTRL_REG2 0x2b
#define MMA8452_CTRL_REG2_RST BIT(6)
#define MMA8452_CTRL_REG4 0x2d
#define MMA8452_CTRL_REG5 0x2e
#define MMA8452_MAX_REG 0x31
#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
#define MMA8452_CTRL_DR_MASK (BIT(5) | BIT(4) | BIT(3))
#define MMA8452_CTRL_DR_SHIFT 3
#define MMA8452_CTRL_DR_DEFAULT 0x4 /* 50 Hz sample frequency */
#define MMA8452_CTRL_ACTIVE BIT(0)
#define MMA8452_DATA_CFG_FS_MASK (BIT(1) | BIT(0))
#define MMA8452_DATA_CFG_FS_2G 0
#define MMA8452_DATA_CFG_FS_4G 1
#define MMA8452_DATA_CFG_FS_8G 2
#define MMA8452_DATA_CFG_HPF_MASK BIT(4)
#define MMA8452_INT_DRDY BIT(0)
#define MMA8452_INT_TRANS BIT(5)
#define MMA8452_DEVICE_ID 0x2a
#define MMA8452_STATUS 0x00
#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
#define MMA8452_OUT_X 0x01 /* MSB first, 12-bit */
#define MMA8452_OUT_Y 0x03
#define MMA8452_OUT_Z 0x05
#define MMA8452_INT_SRC 0x0c
#define MMA8452_WHO_AM_I 0x0d
#define MMA8452_DATA_CFG 0x0e
#define MMA8452_DATA_CFG_FS_MASK GENMASK(1, 0)
#define MMA8452_DATA_CFG_FS_2G 0
#define MMA8452_DATA_CFG_FS_4G 1
#define MMA8452_DATA_CFG_FS_8G 2
#define MMA8452_DATA_CFG_HPF_MASK BIT(4)
#define MMA8452_HP_FILTER_CUTOFF 0x0f
#define MMA8452_HP_FILTER_CUTOFF_SEL_MASK GENMASK(1, 0)
#define MMA8452_TRANSIENT_CFG 0x1d
#define MMA8452_TRANSIENT_CFG_HPF_BYP BIT(0)
#define MMA8452_TRANSIENT_CFG_CHAN(chan) BIT(chan + 1)
#define MMA8452_TRANSIENT_CFG_ELE BIT(4)
#define MMA8452_TRANSIENT_SRC 0x1e
#define MMA8452_TRANSIENT_SRC_XTRANSE BIT(1)
#define MMA8452_TRANSIENT_SRC_YTRANSE BIT(3)
#define MMA8452_TRANSIENT_SRC_ZTRANSE BIT(5)
#define MMA8452_TRANSIENT_THS 0x1f
#define MMA8452_TRANSIENT_THS_MASK GENMASK(6, 0)
#define MMA8452_TRANSIENT_COUNT 0x20
#define MMA8452_CTRL_REG1 0x2a
#define MMA8452_CTRL_ACTIVE BIT(0)
#define MMA8452_CTRL_DR_MASK GENMASK(5, 3)
#define MMA8452_CTRL_DR_SHIFT 3
#define MMA8452_CTRL_DR_DEFAULT 0x4 /* 50 Hz sample frequency */
#define MMA8452_CTRL_REG2 0x2b
#define MMA8452_CTRL_REG2_RST BIT(6)
#define MMA8452_CTRL_REG4 0x2d
#define MMA8452_CTRL_REG5 0x2e
#define MMA8452_OFF_X 0x2f
#define MMA8452_OFF_Y 0x30
#define MMA8452_OFF_Z 0x31
#define MMA8452_MAX_REG 0x31
#define MMA8452_INT_DRDY BIT(0)
#define MMA8452_INT_TRANS BIT(5)
#define MMA8452_DEVICE_ID 0x2a
struct mma8452_data {
struct i2c_client *client;
......@@ -91,30 +87,34 @@ static int mma8452_drdy(struct mma8452_data *data)
return ret;
if ((ret & MMA8452_STATUS_DRDY) == MMA8452_STATUS_DRDY)
return 0;
msleep(20);
}
dev_err(&data->client->dev, "data not ready\n");
return -EIO;
}
static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
{
int ret = mma8452_drdy(data);
if (ret < 0)
return ret;
return i2c_smbus_read_i2c_block_data(data->client,
MMA8452_OUT_X, 3 * sizeof(__be16), (u8 *) buf);
return i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X,
3 * sizeof(__be16), (u8 *)buf);
}
static ssize_t mma8452_show_int_plus_micros(char *buf,
const int (*vals)[2], int n)
static ssize_t mma8452_show_int_plus_micros(char *buf, const int (*vals)[2],
int n)
{
size_t len = 0;
while (n-- > 0)
len += scnprintf(buf + len, PAGE_SIZE - len,
"%d.%06d ", vals[n][0], vals[n][1]);
len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06d ",
vals[n][0], vals[n][1]);
/* replace trailing space by newline */
buf[len - 1] = '\n';
......@@ -123,7 +123,7 @@ static ssize_t mma8452_show_int_plus_micros(char *buf,
}
static int mma8452_get_int_plus_micros_index(const int (*vals)[2], int n,
int val, int val2)
int val, int val2)
{
while (n-- > 0)
if (val == vals[n][0] && val2 == vals[n][1])
......@@ -147,7 +147,7 @@ static const int mma8452_samp_freq[8][2] = {
* Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048
* The userspace interface uses m/s^2 and we declare micro units
* So scale factor is given by:
* g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
* g * N * 1000000 / 2048 for N = 2, 4, 8 and g = 9.80665
*/
static const int mma8452_scales[3][2] = {
{0, 9577}, {0, 19154}, {0, 38307}
......@@ -178,17 +178,19 @@ static const int mma8452_hp_filter_cutoff[8][4][2] = {
};
static ssize_t mma8452_show_samp_freq_avail(struct device *dev,
struct device_attribute *attr, char *buf)
struct device_attribute *attr,
char *buf)
{
return mma8452_show_int_plus_micros(buf, mma8452_samp_freq,
ARRAY_SIZE(mma8452_samp_freq));
ARRAY_SIZE(mma8452_samp_freq));
}
static ssize_t mma8452_show_scale_avail(struct device *dev,
struct device_attribute *attr, char *buf)
struct device_attribute *attr,
char *buf)
{
return mma8452_show_int_plus_micros(buf, mma8452_scales,
ARRAY_SIZE(mma8452_scales));
ARRAY_SIZE(mma8452_scales));
}
static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev,
......@@ -205,22 +207,23 @@ static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev,
static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail);
static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO,
mma8452_show_scale_avail, NULL, 0);
mma8452_show_scale_avail, NULL, 0);
static IIO_DEVICE_ATTR(in_accel_filter_high_pass_3db_frequency_available,
S_IRUGO, mma8452_show_hp_cutoff_avail, NULL, 0);
S_IRUGO, mma8452_show_hp_cutoff_avail, NULL, 0);
static int mma8452_get_samp_freq_index(struct mma8452_data *data,
int val, int val2)
int val, int val2)
{
return mma8452_get_int_plus_micros_index(mma8452_samp_freq,
ARRAY_SIZE(mma8452_samp_freq), val, val2);
ARRAY_SIZE(mma8452_samp_freq),
val, val2);
}
static int mma8452_get_scale_index(struct mma8452_data *data,
int val, int val2)
static int mma8452_get_scale_index(struct mma8452_data *data, int val, int val2)
{
return mma8452_get_int_plus_micros_index(mma8452_scales,
ARRAY_SIZE(mma8452_scales), val, val2);
ARRAY_SIZE(mma8452_scales),
val, val2);
}
static int mma8452_get_hp_filter_index(struct mma8452_data *data,
......@@ -229,7 +232,7 @@ static int mma8452_get_hp_filter_index(struct mma8452_data *data,
int i = mma8452_get_odr_index(data);
return mma8452_get_int_plus_micros_index(mma8452_hp_filter_cutoff[i],
ARRAY_SIZE(mma8452_scales[0]), val, val2);
ARRAY_SIZE(mma8452_hp_filter_cutoff[0]), val, val2);
}
static int mma8452_read_hp_filter(struct mma8452_data *data, int *hz, int *uHz)
......@@ -266,25 +269,31 @@ static int mma8452_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&data->lock);
if (ret < 0)
return ret;
*val = sign_extend32(
be16_to_cpu(buffer[chan->scan_index]) >> 4, 11);
*val = sign_extend32(be16_to_cpu(buffer[chan->scan_index]) >> 4,
11);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK;
*val = mma8452_scales[i][0];
*val2 = mma8452_scales[i][1];
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ:
i = mma8452_get_odr_index(data);
*val = mma8452_samp_freq[i][0];
*val2 = mma8452_samp_freq[i][1];
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_CALIBBIAS:
ret = i2c_smbus_read_byte_data(data->client, MMA8452_OFF_X +
chan->scan_index);
ret = i2c_smbus_read_byte_data(data->client,
MMA8452_OFF_X + chan->scan_index);
if (ret < 0)
return ret;
*val = sign_extend32(ret, 7);
return IIO_VAL_INT;
case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
if (data->data_cfg & MMA8452_DATA_CFG_HPF_MASK) {
......@@ -295,21 +304,23 @@ static int mma8452_read_raw(struct iio_dev *indio_dev,
*val = 0;
*val2 = 0;
}
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
static int mma8452_standby(struct mma8452_data *data)
{
return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1,
data->ctrl_reg1 & ~MMA8452_CTRL_ACTIVE);
data->ctrl_reg1 & ~MMA8452_CTRL_ACTIVE);
}
static int mma8452_active(struct mma8452_data *data)
{
return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1,
data->ctrl_reg1);
data->ctrl_reg1);
}
static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
......@@ -334,6 +345,7 @@ static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
ret = 0;
fail:
mutex_unlock(&data->lock);
return ret;
}
......@@ -344,12 +356,13 @@ static int mma8452_set_hp_filter_frequency(struct mma8452_data *data,
i = mma8452_get_hp_filter_index(data, val, val2);
if (i < 0)
return -EINVAL;
return i;
reg = i2c_smbus_read_byte_data(data->client,
MMA8452_HP_FILTER_CUTOFF);
if (reg < 0)
return reg;
reg &= ~MMA8452_HP_FILTER_CUTOFF_SEL_MASK;
reg |= i;
......@@ -370,25 +383,30 @@ static int mma8452_write_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SAMP_FREQ:
i = mma8452_get_samp_freq_index(data, val, val2);
if (i < 0)
return -EINVAL;
return i;
data->ctrl_reg1 &= ~MMA8452_CTRL_DR_MASK;
data->ctrl_reg1 |= i << MMA8452_CTRL_DR_SHIFT;
return mma8452_change_config(data, MMA8452_CTRL_REG1,
data->ctrl_reg1);
data->ctrl_reg1);
case IIO_CHAN_INFO_SCALE:
i = mma8452_get_scale_index(data, val, val2);
if (i < 0)
return -EINVAL;
return i;
data->data_cfg &= ~MMA8452_DATA_CFG_FS_MASK;
data->data_cfg |= i;
return mma8452_change_config(data, MMA8452_DATA_CFG,
data->data_cfg);
data->data_cfg);
case IIO_CHAN_INFO_CALIBBIAS:
if (val < -128 || val > 127)
return -EINVAL;
return mma8452_change_config(data, MMA8452_OFF_X +
chan->scan_index, val);
return mma8452_change_config(data,
MMA8452_OFF_X + chan->scan_index,
val);
case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
if (val == 0 && val2 == 0) {
......@@ -399,8 +417,9 @@ static int mma8452_write_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
}
return mma8452_change_config(data, MMA8452_DATA_CFG,
data->data_cfg);
data->data_cfg);
default:
return -EINVAL;
......@@ -425,6 +444,7 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev,
return ret;
*val = ret & MMA8452_TRANSIENT_THS_MASK;
return IIO_VAL_INT;
case IIO_EV_INFO_PERIOD:
......@@ -437,6 +457,7 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev,
mma8452_get_odr_index(data)];
*val = us / USEC_PER_SEC;
*val2 = us % USEC_PER_SEC;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_EV_INFO_HIGH_PASS_FILTER_3DB:
......@@ -453,6 +474,7 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
}
return IIO_VAL_INT_PLUS_MICRO;
default:
......@@ -472,19 +494,22 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev,
switch (info) {
case IIO_EV_INFO_VALUE:
return mma8452_change_config(data, MMA8452_TRANSIENT_THS,
val & MMA8452_TRANSIENT_THS_MASK);
if (val < 0 || val > MMA8452_TRANSIENT_THS_MASK)
return -EINVAL;
return mma8452_change_config(data, MMA8452_TRANSIENT_THS, val);
case IIO_EV_INFO_PERIOD:
steps = (val * USEC_PER_SEC + val2) /
mma8452_transient_time_step_us[
mma8452_get_odr_index(data)];
if (steps > 0xff)
if (steps < 0 || steps > 0xff)
return -EINVAL;
return mma8452_change_config(data, MMA8452_TRANSIENT_COUNT,
steps);
case IIO_EV_INFO_HIGH_PASS_FILTER_3DB:
reg = i2c_smbus_read_byte_data(data->client,
MMA8452_TRANSIENT_CFG);
......@@ -499,6 +524,7 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
}
return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, reg);
default:
......@@ -608,15 +634,16 @@ static irqreturn_t mma8452_trigger_handler(int irq, void *p)
u8 buffer[16]; /* 3 16-bit channels + padding + ts */
int ret;
ret = mma8452_read(data, (__be16 *) buffer);
ret = mma8452_read(data, (__be16 *)buffer);
if (ret < 0)
goto done;
iio_push_to_buffers_with_timestamp(indio_dev, buffer,
iio_get_time_ns());
iio_get_time_ns());
done:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
......@@ -674,10 +701,10 @@ static struct attribute_group mma8452_event_attribute_group = {
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_CALIBBIAS), \
BIT(IIO_CHAN_INFO_CALIBBIAS), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \
.scan_index = idx, \
.scan_type = { \
.sign = 's', \
......@@ -780,6 +807,7 @@ static int mma8452_trigger_setup(struct iio_dev *indio_dev)
return ret;
indio_dev->trig = trig;
return 0;
}
......@@ -849,7 +877,7 @@ static int mma8452_probe(struct i2c_client *client,
data->data_cfg = MMA8452_DATA_CFG_FS_2G;
ret = i2c_smbus_write_byte_data(client, MMA8452_DATA_CFG,
data->data_cfg);
data->data_cfg);
if (ret < 0)
return ret;
......@@ -891,14 +919,14 @@ static int mma8452_probe(struct i2c_client *client,
}
data->ctrl_reg1 = MMA8452_CTRL_ACTIVE |
(MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT);
(MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT);
ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1,
data->ctrl_reg1);
if (ret < 0)
goto trigger_cleanup;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
mma8452_trigger_handler, NULL);
mma8452_trigger_handler, NULL);
if (ret < 0)
goto trigger_cleanup;
......@@ -968,6 +996,7 @@ static const struct of_device_id mma8452_dt_ids[] = {
{ .compatible = "fsl,mma8452" },
{ }
};
MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
static struct i2c_driver mma8452_driver = {
.driver = {
......
......@@ -1149,7 +1149,7 @@ static int mma9553_probe(struct i2c_client *client,
if (client->irq < 0)
client->irq = mma9553_gpio_probe(client);
if (client->irq >= 0) {
if (client->irq > 0) {
ret = devm_request_threaded_irq(&client->dev, client->irq,
mma9553_irq_handler,
mma9553_event_handler,
......
......@@ -26,6 +26,7 @@
#define LSM303DLH_ACCEL_DEV_NAME "lsm303dlh_accel"
#define LSM303DLM_ACCEL_DEV_NAME "lsm303dlm_accel"
#define LSM330_ACCEL_DEV_NAME "lsm330_accel"
#define LSM303AGR_ACCEL_DEV_NAME "lsm303agr_accel"
/**
* struct st_sensors_platform_data - default accel platform data
......
......@@ -226,12 +226,14 @@ static const struct iio_chan_spec st_accel_16bit_channels[] = {
static const struct st_sensor_settings st_accel_sensors_settings[] = {
{
.wai = ST_ACCEL_1_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LIS3DH_ACCEL_DEV_NAME,
[1] = LSM303DLHC_ACCEL_DEV_NAME,
[2] = LSM330D_ACCEL_DEV_NAME,
[3] = LSM330DL_ACCEL_DEV_NAME,
[4] = LSM330DLC_ACCEL_DEV_NAME,
[5] = LSM303AGR_ACCEL_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
.odr = {
......@@ -297,6 +299,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
},
{
.wai = ST_ACCEL_2_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LIS331DLH_ACCEL_DEV_NAME,
[1] = LSM303DL_ACCEL_DEV_NAME,
......@@ -359,6 +362,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
},
{
.wai = ST_ACCEL_3_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LSM330_ACCEL_DEV_NAME,
},
......@@ -437,6 +441,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
},
{
.wai = ST_ACCEL_4_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LIS3LV02DL_ACCEL_DEV_NAME,
},
......@@ -494,6 +499,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
},
{
.wai = ST_ACCEL_5_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LIS331DL_ACCEL_DEV_NAME,
},
......
......@@ -68,6 +68,10 @@ static const struct of_device_id st_accel_of_match[] = {
.compatible = "st,lsm330-accel",
.data = LSM330_ACCEL_DEV_NAME,
},
{
.compatible = "st,lsm303agr-accel",
.data = LSM303AGR_ACCEL_DEV_NAME,
},
{},
};
MODULE_DEVICE_TABLE(of, st_accel_of_match);
......@@ -116,6 +120,7 @@ static const struct i2c_device_id st_accel_id_table[] = {
{ LSM303DL_ACCEL_DEV_NAME },
{ LSM303DLM_ACCEL_DEV_NAME },
{ LSM330_ACCEL_DEV_NAME },
{ LSM303AGR_ACCEL_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
......
......@@ -57,6 +57,7 @@ static const struct spi_device_id st_accel_id_table[] = {
{ LSM303DL_ACCEL_DEV_NAME },
{ LSM303DLM_ACCEL_DEV_NAME },
{ LSM330_ACCEL_DEV_NAME },
{ LSM303AGR_ACCEL_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(spi, st_accel_id_table);
......
......@@ -37,16 +37,16 @@
#define STK8312_REG_OTPDATA 0x3E
#define STK8312_REG_OTPCTRL 0x3F
#define STK8312_MODE_ACTIVE 0x01
#define STK8312_MODE_ACTIVE BIT(0)
#define STK8312_MODE_STANDBY 0x00
#define STK8312_DREADY_BIT 0x10
#define STK8312_INT_MODE 0xC0
#define STK8312_RNG_MASK 0xC0
#define STK8312_SR_MASK 0x07
#define STK8312_SR_400HZ_IDX 0
#define STK8312_MODE_INT_AH_PP 0xC0 /* active-high, push-pull */
#define STK8312_DREADY_BIT BIT(4)
#define STK8312_RNG_6G 1
#define STK8312_RNG_SHIFT 6
#define STK8312_READ_RETRIES 16
#define STK8312_ALL_CHANNEL_MASK 7
#define STK8312_RNG_MASK GENMASK(7, 6)
#define STK8312_SR_MASK GENMASK(2, 0)
#define STK8312_SR_400HZ_IDX 0
#define STK8312_ALL_CHANNEL_MASK GENMASK(2, 0)
#define STK8312_ALL_CHANNEL_SIZE 3
#define STK8312_DRIVER_NAME "stk8312"
......@@ -69,8 +69,8 @@ static const int stk8312_scale_table[][2] = {
};
static const struct {
u16 val;
u32 val2;
int val;
int val2;
} stk8312_samp_freq_table[] = {
{400, 0}, {200, 0}, {100, 0}, {50, 0}, {25, 0},
{12, 500000}, {6, 250000}, {3, 125000}
......@@ -103,7 +103,7 @@ static const struct iio_chan_spec stk8312_channels[] = {
struct stk8312_data {
struct i2c_client *client;
struct mutex lock;
int range;
u8 range;
u8 sample_rate_idx;
u8 mode;
struct iio_trigger *dready_trig;
......@@ -144,22 +144,25 @@ static int stk8312_otp_init(struct stk8312_data *data)
if (ret < 0)
goto exit_err;
count--;
} while (!(ret & 0x80) && count > 0);
} while (!(ret & BIT(7)) && count > 0);
if (count == 0)
if (count == 0) {
ret = -ETIMEDOUT;
goto exit_err;
}
ret = i2c_smbus_read_byte_data(client, STK8312_REG_OTPDATA);
if (ret == 0)
ret = -EINVAL;
if (ret < 0)
goto exit_err;
ret = i2c_smbus_write_byte_data(data->client,
STK8312_REG_AFECTRL, ret);
ret = i2c_smbus_write_byte_data(data->client, STK8312_REG_AFECTRL, ret);
if (ret < 0)
goto exit_err;
msleep(150);
return ret;
return 0;
exit_err:
dev_err(&client->dev, "failed to initialize sensor\n");
......@@ -203,8 +206,11 @@ static int stk8312_set_interrupts(struct stk8312_data *data, u8 int_mask)
return ret;
ret = i2c_smbus_write_byte_data(client, STK8312_REG_INTSU, int_mask);
if (ret < 0)
if (ret < 0) {
dev_err(&client->dev, "failed to set interrupts\n");
stk8312_set_mode(data, mode);
return ret;
}
return stk8312_set_mode(data, mode);
}
......@@ -228,7 +234,7 @@ static int stk8312_data_rdy_trigger_set_state(struct iio_trigger *trig,
data->dready_trigger_on = state;
return ret;
return 0;
}
static const struct iio_trigger_ops stk8312_trigger_ops = {
......@@ -236,7 +242,7 @@ static const struct iio_trigger_ops stk8312_trigger_ops = {
.owner = THIS_MODULE,
};
static int stk8312_set_sample_rate(struct stk8312_data *data, int rate)
static int stk8312_set_sample_rate(struct stk8312_data *data, u8 rate)
{
int ret;
u8 masked_reg;
......@@ -253,20 +259,24 @@ static int stk8312_set_sample_rate(struct stk8312_data *data, int rate)
return ret;
ret = i2c_smbus_read_byte_data(client, STK8312_REG_SR);
if (ret < 0) {
dev_err(&client->dev, "failed to set sampling rate\n");
return ret;
}
if (ret < 0)
goto err_activate;
masked_reg = (ret & (~STK8312_SR_MASK)) | rate;
ret = i2c_smbus_write_byte_data(client, STK8312_REG_SR, masked_reg);
if (ret < 0)
dev_err(&client->dev, "failed to set sampling rate\n");
else
data->sample_rate_idx = rate;
goto err_activate;
data->sample_rate_idx = rate;
return stk8312_set_mode(data, mode);
err_activate:
dev_err(&client->dev, "failed to set sampling rate\n");
stk8312_set_mode(data, mode);
return ret;
}
static int stk8312_set_range(struct stk8312_data *data, u8 range)
......@@ -288,21 +298,25 @@ static int stk8312_set_range(struct stk8312_data *data, u8 range)
return ret;
ret = i2c_smbus_read_byte_data(client, STK8312_REG_STH);
if (ret < 0) {
dev_err(&client->dev, "failed to change sensor range\n");
return ret;
}
if (ret < 0)
goto err_activate;
masked_reg = ret & (~STK8312_RNG_MASK);
masked_reg |= range << STK8312_RNG_SHIFT;
ret = i2c_smbus_write_byte_data(client, STK8312_REG_STH, masked_reg);
if (ret < 0)
dev_err(&client->dev, "failed to change sensor range\n");
else
data->range = range;
goto err_activate;
data->range = range;
return stk8312_set_mode(data, mode);
err_activate:
dev_err(&client->dev, "failed to change sensor range\n");
stk8312_set_mode(data, mode);
return ret;
}
static int stk8312_read_accel(struct stk8312_data *data, u8 address)
......@@ -335,18 +349,21 @@ static int stk8312_read_raw(struct iio_dev *indio_dev,
ret = stk8312_set_mode(data, data->mode | STK8312_MODE_ACTIVE);
if (ret < 0) {
mutex_unlock(&data->lock);
return -EINVAL;
return ret;
}
ret = stk8312_read_accel(data, chan->address);
if (ret < 0) {
stk8312_set_mode(data,
data->mode & (~STK8312_MODE_ACTIVE));
mutex_unlock(&data->lock);
return -EINVAL;
return ret;
}
*val = sign_extend32(ret, 7);
stk8312_set_mode(data, data->mode & (~STK8312_MODE_ACTIVE));
ret = stk8312_set_mode(data,
data->mode & (~STK8312_MODE_ACTIVE));
mutex_unlock(&data->lock);
if (ret < 0)
return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = stk8312_scale_table[data->range - 1][0];
......@@ -418,7 +435,6 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct stk8312_data *data = iio_priv(indio_dev);
int bit, ret, i = 0;
u8 buffer[STK8312_ALL_CHANNEL_SIZE];
mutex_lock(&data->lock);
/*
......@@ -429,18 +445,15 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p)
ret = i2c_smbus_read_i2c_block_data(data->client,
STK8312_REG_XOUT,
STK8312_ALL_CHANNEL_SIZE,
buffer);
data->buffer);
if (ret < STK8312_ALL_CHANNEL_SIZE) {
dev_err(&data->client->dev, "register read failed\n");
mutex_unlock(&data->lock);
goto err;
}
data->buffer[0] = buffer[0];
data->buffer[1] = buffer[1];
data->buffer[2] = buffer[2];
} else {
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->masklength) {
indio_dev->masklength) {
ret = stk8312_read_accel(data, bit);
if (ret < 0) {
mutex_unlock(&data->lock);
......@@ -547,11 +560,12 @@ static int stk8312_probe(struct i2c_client *client,
return ret;
}
data->sample_rate_idx = STK8312_SR_400HZ_IDX;
ret = stk8312_set_range(data, 1);
ret = stk8312_set_range(data, STK8312_RNG_6G);
if (ret < 0)
return ret;
ret = stk8312_set_mode(data, STK8312_INT_MODE | STK8312_MODE_ACTIVE);
ret = stk8312_set_mode(data,
STK8312_MODE_INT_AH_PP | STK8312_MODE_ACTIVE);
if (ret < 0)
return ret;
......@@ -606,7 +620,7 @@ static int stk8312_probe(struct i2c_client *client,
goto err_buffer_cleanup;
}
return ret;
return 0;
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
......@@ -662,6 +676,7 @@ static const struct i2c_device_id stk8312_i2c_id[] = {
{"STK8312", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, stk8312_i2c_id);
static const struct acpi_device_id stk8312_acpi_id[] = {
{"STK8312", 0},
......@@ -672,7 +687,7 @@ MODULE_DEVICE_TABLE(acpi, stk8312_acpi_id);
static struct i2c_driver stk8312_driver = {
.driver = {
.name = "stk8312",
.name = STK8312_DRIVER_NAME,
.pm = STK8312_PM_OPS,
.acpi_match_table = ACPI_PTR(stk8312_acpi_id),
},
......
......@@ -572,6 +572,7 @@ static const struct i2c_device_id stk8ba50_i2c_id[] = {
{"stk8ba50", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, stk8ba50_i2c_id);
static const struct acpi_device_id stk8ba50_acpi_id[] = {
{"STK8BA50", 0},
......
......@@ -228,8 +228,8 @@ config MCP320X
depends on SPI
help
Say yes here to build support for Microchip Technology's
MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204 or
MCP3208 analog to digital converter.
MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204,
MCP3208 or MCP3301 analog to digital converter.
This driver can also be built as a module. If so, the module will be
called mcp320x.
......
......@@ -26,7 +26,7 @@
#define BERLIN2_SM_CTRL 0x14
#define BERLIN2_SM_CTRL_SM_SOC_INT BIT(1)
#define BERLIN2_SM_CTRL_SOC_SM_INT BIT(2)
#define BERLIN2_SM_CTRL_ADC_SEL(x) (BIT(x) << 5) /* 0-15 */
#define BERLIN2_SM_CTRL_ADC_SEL(x) ((x) << 5) /* 0-15 */
#define BERLIN2_SM_CTRL_ADC_SEL_MASK (0xf << 5)
#define BERLIN2_SM_CTRL_ADC_POWER BIT(9)
#define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV2 (0x0 << 10)
......@@ -53,14 +53,14 @@
#define BERLIN2_SM_ADC_MASK 0x3ff
#define BERLIN2_SM_ADC_STATUS 0x1c
#define BERLIN2_SM_ADC_STATUS_DATA_RDY(x) BIT(x) /* 0-15 */
#define BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK 0xf
#define BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK GENMASK(15, 0)
#define BERLIN2_SM_ADC_STATUS_INT_EN(x) (BIT(x) << 16) /* 0-15 */
#define BERLIN2_SM_ADC_STATUS_INT_EN_MASK (0xf << 16)
#define BERLIN2_SM_ADC_STATUS_INT_EN_MASK GENMASK(31, 16)
#define BERLIN2_SM_TSEN_STATUS 0x24
#define BERLIN2_SM_TSEN_STATUS_DATA_RDY BIT(0)
#define BERLIN2_SM_TSEN_STATUS_INT_EN BIT(1)
#define BERLIN2_SM_TSEN_DATA 0x28
#define BERLIN2_SM_TSEN_MASK 0xfff
#define BERLIN2_SM_TSEN_MASK GENMASK(9, 0)
#define BERLIN2_SM_TSEN_CTRL 0x74
#define BERLIN2_SM_TSEN_CTRL_START BIT(8)
#define BERLIN2_SM_TSEN_CTRL_SETTLING_4 (0x0 << 21) /* 4 us */
......@@ -86,7 +86,7 @@ struct berlin2_adc_priv {
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
}
static struct iio_chan_spec berlin2_adc_channels[] = {
static const struct iio_chan_spec berlin2_adc_channels[] = {
BERLIN2_ADC_CHANNEL(0, IIO_VOLTAGE), /* external input */
BERLIN2_ADC_CHANNEL(1, IIO_VOLTAGE), /* external input */
BERLIN2_ADC_CHANNEL(2, IIO_VOLTAGE), /* external input */
......@@ -103,7 +103,6 @@ static struct iio_chan_spec berlin2_adc_channels[] = {
BERLIN2_ADC_CHANNEL(7, IIO_VOLTAGE), /* reserved */
IIO_CHAN_SOFT_TIMESTAMP(8), /* timestamp */
};
#define BERLIN2_N_CHANNELS ARRAY_SIZE(berlin2_adc_channels)
static int berlin2_adc_read(struct iio_dev *indio_dev, int channel)
{
......@@ -221,7 +220,7 @@ static int berlin2_adc_read_raw(struct iio_dev *indio_dev,
return temp;
if (temp > 2047)
temp = -(4096 - temp);
temp -= 4096;
/* Convert to milli Celsius */
*val = ((temp * 100000) / 264 - 270000);
......@@ -286,8 +285,7 @@ static int berlin2_adc_probe(struct platform_device *pdev)
int irq, tsen_irq;
int ret;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct berlin2_adc_priv));
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
if (!indio_dev)
return -ENOMEM;
......@@ -301,11 +299,11 @@ static int berlin2_adc_probe(struct platform_device *pdev)
irq = platform_get_irq_byname(pdev, "adc");
if (irq < 0)
return -ENODEV;
return irq;
tsen_irq = platform_get_irq_byname(pdev, "tsen");
if (tsen_irq < 0)
return -ENODEV;
return tsen_irq;
ret = devm_request_irq(&pdev->dev, irq, berlin2_adc_irq, 0,
pdev->dev.driver->name, indio_dev);
......@@ -325,8 +323,8 @@ static int berlin2_adc_probe(struct platform_device *pdev)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &berlin2_adc_info;
indio_dev->num_channels = BERLIN2_N_CHANNELS;
indio_dev->channels = berlin2_adc_channels;
indio_dev->num_channels = ARRAY_SIZE(berlin2_adc_channels);
/* Power up the ADC */
regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
......
......@@ -25,6 +25,7 @@
* http://ww1.microchip.com/downloads/en/DeviceDoc/21290D.pdf mcp3201
* http://ww1.microchip.com/downloads/en/DeviceDoc/21034D.pdf mcp3202
* http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf mcp3204/08
* http://ww1.microchip.com/downloads/en/DeviceDoc/21700E.pdf mcp3301
*
* 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
......@@ -47,6 +48,7 @@ enum {
mcp3202,
mcp3204,
mcp3208,
mcp3301,
};
struct mcp320x_chip_info {
......@@ -76,6 +78,7 @@ static int mcp320x_channel_to_tx_data(int device_index,
switch (device_index) {
case mcp3001:
case mcp3201:
case mcp3301:
return 0;
case mcp3002:
case mcp3202:
......@@ -102,7 +105,7 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
adc->tx_buf = mcp320x_channel_to_tx_data(device_index,
channel, differential);
if (device_index != mcp3001 && device_index != mcp3201) {
if (device_index != mcp3001 && device_index != mcp3201 && device_index != mcp3301) {
ret = spi_sync(adc->spi, &adc->msg);
if (ret < 0)
return ret;
......@@ -125,6 +128,8 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
case mcp3204:
case mcp3208:
return (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4);
case mcp3301:
return sign_extend32((adc->rx_buf[0] & 0x1f) << 8 | adc->rx_buf[1], 12);
default:
return -EINVAL;
}
......@@ -274,6 +279,11 @@ static const struct mcp320x_chip_info mcp320x_chip_infos[] = {
.num_channels = ARRAY_SIZE(mcp3208_channels),
.resolution = 12
},
[mcp3301] = {
.channels = mcp3201_channels,
.num_channels = ARRAY_SIZE(mcp3201_channels),
.resolution = 13
},
};
static int mcp320x_probe(struct spi_device *spi)
......@@ -368,6 +378,9 @@ static const struct of_device_id mcp320x_dt_ids[] = {
}, {
.compatible = "mcp3208",
.data = &mcp320x_chip_infos[mcp3208],
}, {
.compatible = "mcp3301",
.data = &mcp320x_chip_infos[mcp3301],
}, {
}
};
......@@ -383,6 +396,7 @@ static const struct spi_device_id mcp320x_id[] = {
{ "mcp3202", mcp3202 },
{ "mcp3204", mcp3204 },
{ "mcp3208", mcp3208 },
{ "mcp3301", mcp3301 },
{ }
};
MODULE_DEVICE_TABLE(spi, mcp320x_id);
......
......@@ -68,6 +68,9 @@
#define VF610_ADC_CLK_DIV8 0x60
#define VF610_ADC_CLK_MASK 0x60
#define VF610_ADC_ADLSMP_LONG 0x10
#define VF610_ADC_ADSTS_SHORT 0x100
#define VF610_ADC_ADSTS_NORMAL 0x200
#define VF610_ADC_ADSTS_LONG 0x300
#define VF610_ADC_ADSTS_MASK 0x300
#define VF610_ADC_ADLPC_EN 0x80
#define VF610_ADC_ADHSC_EN 0x400
......@@ -98,6 +101,8 @@
#define VF610_ADC_CALF 0x2
#define VF610_ADC_TIMEOUT msecs_to_jiffies(100)
#define DEFAULT_SAMPLE_TIME 1000
enum clk_sel {
VF610_ADCIOC_BUSCLK_SET,
VF610_ADCIOC_ALTCLK_SET,
......@@ -124,6 +129,17 @@ enum conversion_mode_sel {
VF610_ADC_CONV_LOW_POWER,
};
enum lst_adder_sel {
VF610_ADCK_CYCLES_3,
VF610_ADCK_CYCLES_5,
VF610_ADCK_CYCLES_7,
VF610_ADCK_CYCLES_9,
VF610_ADCK_CYCLES_13,
VF610_ADCK_CYCLES_17,
VF610_ADCK_CYCLES_21,
VF610_ADCK_CYCLES_25,
};
struct vf610_adc_feature {
enum clk_sel clk_sel;
enum vol_ref vol_ref;
......@@ -132,6 +148,8 @@ struct vf610_adc_feature {
int clk_div;
int sample_rate;
int res_mode;
u32 lst_adder_index;
u32 default_sample_time;
bool calibration;
bool ovwren;
......@@ -155,11 +173,13 @@ struct vf610_adc {
};
static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
static const u32 vf610_lst_adder[] = { 3, 5, 7, 9, 13, 17, 21, 25 };
static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
{
struct vf610_adc_feature *adc_feature = &info->adc_feature;
unsigned long adck_rate, ipg_rate = clk_get_rate(info->clk);
u32 adck_period, lst_addr_min;
int divisor, i;
adck_rate = info->max_adck_rate[adc_feature->conv_mode];
......@@ -173,6 +193,19 @@ static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
adc_feature->clk_div = 8;
}
/*
* Determine the long sample time adder value to be used based
* on the default minimum sample time provided.
*/
adck_period = NSEC_PER_SEC / adck_rate;
lst_addr_min = adc_feature->default_sample_time / adck_period;
for (i = 0; i < ARRAY_SIZE(vf610_lst_adder); i++) {
if (vf610_lst_adder[i] > lst_addr_min) {
adc_feature->lst_adder_index = i;
break;
}
}
/*
* Calculate ADC sample frequencies
* Sample time unit is ADCK cycles. ADCK clk source is ipg clock,
......@@ -182,12 +215,13 @@ static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
* SFCAdder: fixed to 6 ADCK cycles
* AverageNum: 1, 4, 8, 16, 32 samples for hardware average.
* BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
* LSTAdder(Long Sample Time): fixed to 3 ADCK cycles
* LSTAdder(Long Sample Time): 3, 5, 7, 9, 13, 17, 21, 25 ADCK cycles
*/
adck_rate = ipg_rate / info->adc_feature.clk_div;
for (i = 0; i < ARRAY_SIZE(vf610_hw_avgs); i++)
info->sample_freq_avail[i] =
adck_rate / (6 + vf610_hw_avgs[i] * (25 + 3));
adck_rate / (6 + vf610_hw_avgs[i] *
(25 + vf610_lst_adder[adc_feature->lst_adder_index]));
}
static inline void vf610_adc_cfg_init(struct vf610_adc *info)
......@@ -347,8 +381,40 @@ static void vf610_adc_sample_set(struct vf610_adc *info)
break;
}
/* Use the short sample mode */
cfg_data &= ~(VF610_ADC_ADLSMP_LONG | VF610_ADC_ADSTS_MASK);
/*
* Set ADLSMP and ADSTS based on the Long Sample Time Adder value
* determined.
*/
switch (adc_feature->lst_adder_index) {
case VF610_ADCK_CYCLES_3:
break;
case VF610_ADCK_CYCLES_5:
cfg_data |= VF610_ADC_ADSTS_SHORT;
break;
case VF610_ADCK_CYCLES_7:
cfg_data |= VF610_ADC_ADSTS_NORMAL;
break;
case VF610_ADCK_CYCLES_9:
cfg_data |= VF610_ADC_ADSTS_LONG;
break;
case VF610_ADCK_CYCLES_13:
cfg_data |= VF610_ADC_ADLSMP_LONG;
break;
case VF610_ADCK_CYCLES_17:
cfg_data |= VF610_ADC_ADLSMP_LONG;
cfg_data |= VF610_ADC_ADSTS_SHORT;
break;
case VF610_ADCK_CYCLES_21:
cfg_data |= VF610_ADC_ADLSMP_LONG;
cfg_data |= VF610_ADC_ADSTS_NORMAL;
break;
case VF610_ADCK_CYCLES_25:
cfg_data |= VF610_ADC_ADLSMP_LONG;
cfg_data |= VF610_ADC_ADSTS_NORMAL;
break;
default:
dev_err(info->dev, "error in sample time select\n");
}
/* update hardware average selection */
cfg_data &= ~VF610_ADC_AVGS_MASK;
......@@ -713,6 +779,11 @@ static int vf610_adc_probe(struct platform_device *pdev)
of_property_read_u32_array(pdev->dev.of_node, "fsl,adck-max-frequency",
info->max_adck_rate, 3);
ret = of_property_read_u32(pdev->dev.of_node, "min-sample-time",
&info->adc_feature.default_sample_time);
if (ret)
info->adc_feature.default_sample_time = DEFAULT_SAMPLE_TIME;
platform_set_drvdata(pdev, indio_dev);
init_completion(&info->completion);
......
......@@ -126,6 +126,9 @@ static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
int err, i = 0;
struct st_sensor_data *sdata = iio_priv(indio_dev);
if (sdata->sensor_settings->fs.addr == 0)
return 0;
err = st_sensors_match_fs(sdata->sensor_settings, fs, &i);
if (err < 0)
goto st_accel_set_fullscale_error;
......@@ -479,46 +482,43 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev,
int num_sensors_list,
const struct st_sensor_settings *sensor_settings)
{
u8 wai;
int i, n, err;
u8 wai;
struct st_sensor_data *sdata = iio_priv(indio_dev);
err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
ST_SENSORS_DEFAULT_WAI_ADDRESS, &wai);
if (err < 0) {
dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n");
goto read_wai_error;
}
for (i = 0; i < num_sensors_list; i++) {
if (sensor_settings[i].wai == wai)
for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) {
if (strcmp(indio_dev->name,
sensor_settings[i].sensors_supported[n]) == 0) {
break;
}
}
if (n < ST_SENSORS_MAX_4WAI)
break;
}
if (i == num_sensors_list)
goto device_not_supported;
if (i == num_sensors_list) {
dev_err(&indio_dev->dev, "device name %s not recognized.\n",
indio_dev->name);
return -ENODEV;
}
for (n = 0; n < ARRAY_SIZE(sensor_settings[i].sensors_supported); n++) {
if (strcmp(indio_dev->name,
&sensor_settings[i].sensors_supported[n][0]) == 0)
break;
err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
sensor_settings[i].wai_addr, &wai);
if (err < 0) {
dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n");
return err;
}
if (n == ARRAY_SIZE(sensor_settings[i].sensors_supported)) {
dev_err(&indio_dev->dev, "device name \"%s\" and WhoAmI (0x%02x) mismatch",
indio_dev->name, wai);
goto sensor_name_mismatch;
if (sensor_settings[i].wai != wai) {
dev_err(&indio_dev->dev, "%s: WhoAmI mismatch (0x%x).\n",
indio_dev->name, wai);
return -EINVAL;
}
sdata->sensor_settings =
(struct st_sensor_settings *)&sensor_settings[i];
return i;
device_not_supported:
dev_err(&indio_dev->dev, "device not supported: WhoAmI (0x%x).\n", wai);
sensor_name_mismatch:
err = -ENODEV;
read_wai_error:
return err;
}
EXPORT_SYMBOL(st_sensors_check_device_support);
......
......@@ -53,7 +53,8 @@ config ADXRS450
config BMG160
tristate "BOSCH BMG160 Gyro Sensor"
depends on I2C
select IIO_TRIGGERED_BUFFER if IIO_BUFFER
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Bosch BMG160 Tri-axis Gyro Sensor
driver. This driver also supports BMI055 gyroscope.
......
......@@ -473,6 +473,7 @@ enum adis16136_id {
ID_ADIS16133,
ID_ADIS16135,
ID_ADIS16136,
ID_ADIS16137,
};
static const struct adis16136_chip_info adis16136_chip_info[] = {
......@@ -488,6 +489,10 @@ static const struct adis16136_chip_info adis16136_chip_info[] = {
.precision = IIO_DEGREE_TO_RAD(450),
.fullscale = 24623,
},
[ID_ADIS16137] = {
.precision = IIO_DEGREE_TO_RAD(1000),
.fullscale = 24609,
},
};
static int adis16136_probe(struct spi_device *spi)
......@@ -557,6 +562,7 @@ static const struct spi_device_id adis16136_ids[] = {
{ "adis16133", ID_ADIS16133 },
{ "adis16135", ID_ADIS16135 },
{ "adis16136", ID_ADIS16136 },
{ "adis16137", ID_ADIS16137 },
{ }
};
MODULE_DEVICE_TABLE(spi, adis16136_ids);
......
......@@ -101,19 +101,24 @@
#define ADIS16260_SCAN_TEMP 3
#define ADIS16260_SCAN_ANGL 4
/* Power down the device */
static int adis16260_stop_device(struct iio_dev *indio_dev)
{
struct adis *adis = iio_priv(indio_dev);
int ret;
u16 val = ADIS16260_SLP_CNT_POWER_OFF;
struct adis16260_chip_info {
unsigned int gyro_max_val;
unsigned int gyro_max_scale;
const struct iio_chan_spec *channels;
unsigned int num_channels;
};
ret = adis_write_reg_16(adis, ADIS16260_SLP_CNT, val);
if (ret)
dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
struct adis16260 {
const struct adis16260_chip_info *info;
return ret;
}
struct adis adis;
};
enum adis16260_type {
ADIS16251,
ADIS16260,
ADIS16266,
};
static const struct iio_chan_spec adis16260_channels[] = {
ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
......@@ -131,6 +136,55 @@ static const struct iio_chan_spec adis16260_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(5),
};
static const struct iio_chan_spec adis16266_channels[] = {
ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
BIT(IIO_CHAN_INFO_CALIBBIAS) |
BIT(IIO_CHAN_INFO_CALIBSCALE),
BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,
BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,
BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,
BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
IIO_CHAN_SOFT_TIMESTAMP(4),
};
static const struct adis16260_chip_info adis16260_chip_info_table[] = {
[ADIS16251] = {
.gyro_max_scale = 80,
.gyro_max_val = IIO_RAD_TO_DEGREE(4368),
.channels = adis16260_channels,
.num_channels = ARRAY_SIZE(adis16260_channels),
},
[ADIS16260] = {
.gyro_max_scale = 320,
.gyro_max_val = IIO_RAD_TO_DEGREE(4368),
.channels = adis16260_channels,
.num_channels = ARRAY_SIZE(adis16260_channels),
},
[ADIS16266] = {
.gyro_max_scale = 14000,
.gyro_max_val = IIO_RAD_TO_DEGREE(3357),
.channels = adis16266_channels,
.num_channels = ARRAY_SIZE(adis16266_channels),
},
};
/* Power down the device */
static int adis16260_stop_device(struct iio_dev *indio_dev)
{
struct adis16260 *adis16260 = iio_priv(indio_dev);
int ret;
u16 val = ADIS16260_SLP_CNT_POWER_OFF;
ret = adis_write_reg_16(&adis16260->adis, ADIS16260_SLP_CNT, val);
if (ret)
dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
return ret;
}
static const u8 adis16260_addresses[][2] = {
[ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },
};
......@@ -140,7 +194,9 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
int *val, int *val2,
long mask)
{
struct adis *adis = iio_priv(indio_dev);
struct adis16260 *adis16260 = iio_priv(indio_dev);
const struct adis16260_chip_info *info = adis16260->info;
struct adis *adis = &adis16260->adis;
int ret;
u8 addr;
s16 val16;
......@@ -152,15 +208,9 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
*val = 0;
if (spi_get_device_id(adis->spi)->driver_data) {
/* 0.01832 degree / sec */
*val2 = IIO_DEGREE_TO_RAD(18320);
} else {
/* 0.07326 degree / sec */
*val2 = IIO_DEGREE_TO_RAD(73260);
}
return IIO_VAL_INT_PLUS_MICRO;
*val = info->gyro_max_scale;
*val2 = info->gyro_max_val;
return IIO_VAL_FRACTIONAL;
case IIO_INCLI:
*val = 0;
*val2 = IIO_DEGREE_TO_RAD(36630);
......@@ -224,7 +274,8 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
int val2,
long mask)
{
struct adis *adis = iio_priv(indio_dev);
struct adis16260 *adis16260 = iio_priv(indio_dev);
struct adis *adis = &adis16260->adis;
int ret;
u8 addr;
u8 t;
......@@ -305,35 +356,42 @@ static const struct adis_data adis16260_data = {
static int adis16260_probe(struct spi_device *spi)
{
const struct spi_device_id *id;
struct adis16260 *adis16260;
struct iio_dev *indio_dev;
struct adis *adis;
int ret;
id = spi_get_device_id(spi);
if (!id)
return -ENODEV;
/* setup the industrialio driver allocated elements */
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis));
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis16260));
if (!indio_dev)
return -ENOMEM;
adis = iio_priv(indio_dev);
adis16260 = iio_priv(indio_dev);
/* this is only used for removal purposes */
spi_set_drvdata(spi, indio_dev);
indio_dev->name = spi_get_device_id(spi)->name;
adis16260->info = &adis16260_chip_info_table[id->driver_data];
indio_dev->name = id->name;
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &adis16260_info;
indio_dev->channels = adis16260_channels;
indio_dev->num_channels = ARRAY_SIZE(adis16260_channels);
indio_dev->channels = adis16260->info->channels;
indio_dev->num_channels = adis16260->info->num_channels;
indio_dev->modes = INDIO_DIRECT_MODE;
ret = adis_init(adis, indio_dev, spi, &adis16260_data);
ret = adis_init(&adis16260->adis, indio_dev, spi, &adis16260_data);
if (ret)
return ret;
ret = adis_setup_buffer_and_trigger(adis, indio_dev, NULL);
ret = adis_setup_buffer_and_trigger(&adis16260->adis, indio_dev, NULL);
if (ret)
return ret;
/* Get the device into a sane initial state */
ret = adis_initial_startup(adis);
ret = adis_initial_startup(&adis16260->adis);
if (ret)
goto error_cleanup_buffer_trigger;
ret = iio_device_register(indio_dev);
......@@ -343,18 +401,18 @@ static int adis16260_probe(struct spi_device *spi)
return 0;
error_cleanup_buffer_trigger:
adis_cleanup_buffer_and_trigger(adis, indio_dev);
adis_cleanup_buffer_and_trigger(&adis16260->adis, indio_dev);
return ret;
}
static int adis16260_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct adis *adis = iio_priv(indio_dev);
struct adis16260 *adis16260 = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
adis16260_stop_device(indio_dev);
adis_cleanup_buffer_and_trigger(adis, indio_dev);
adis_cleanup_buffer_and_trigger(&adis16260->adis, indio_dev);
return 0;
}
......@@ -364,11 +422,12 @@ static int adis16260_remove(struct spi_device *spi)
* support for the on chip filtering.
*/
static const struct spi_device_id adis16260_id[] = {
{"adis16260", 0},
{"adis16265", 0},
{"adis16250", 0},
{"adis16255", 0},
{"adis16251", 1},
{"adis16260", ADIS16260},
{"adis16265", ADIS16260},
{"adis16266", ADIS16266},
{"adis16250", ADIS16260},
{"adis16255", ADIS16260},
{"adis16251", ADIS16251},
{}
};
MODULE_DEVICE_TABLE(spi, adis16260_id);
......
......@@ -131,6 +131,7 @@ static const struct iio_chan_spec st_gyro_16bit_channels[] = {
static const struct st_sensor_settings st_gyro_sensors_settings[] = {
{
.wai = ST_GYRO_1_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = L3G4200D_GYRO_DEV_NAME,
[1] = LSM330DL_GYRO_DEV_NAME,
......@@ -190,6 +191,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
},
{
.wai = ST_GYRO_2_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = L3GD20_GYRO_DEV_NAME,
[1] = LSM330D_GYRO_DEV_NAME,
......@@ -252,6 +254,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
},
{
.wai = ST_GYRO_3_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = L3GD20_GYRO_DEV_NAME,
},
......
......@@ -33,6 +33,7 @@
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/timekeeping.h>
#include <linux/iio/iio.h>
......@@ -46,7 +47,8 @@
* Note that when reading the sensor actually 84 edges are detected, but
* since the last edge is not significant, we only store 83:
*/
#define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE + 1)
#define DHT11_EDGES_PER_READ (2 * DHT11_BITS_PER_READ + \
DHT11_EDGES_PREAMBLE + 1)
/* Data transmission timing (nano seconds) */
#define DHT11_START_TRANSMISSION 18 /* ms */
......@@ -62,6 +64,7 @@ struct dht11 {
int irq;
struct completion completion;
/* The iio sysfs interface doesn't prevent concurrent reads: */
struct mutex lock;
s64 timestamp;
......@@ -87,32 +90,20 @@ static unsigned char dht11_decode_byte(int *timing, int threshold)
return ret;
}
static int dht11_decode(struct dht11 *dht11, int offset)
static int dht11_decode(struct dht11 *dht11, int offset, int timeres)
{
int i, t, timing[DHT11_BITS_PER_READ], threshold,
timeres = DHT11_SENSOR_RESPONSE;
int i, t, timing[DHT11_BITS_PER_READ], threshold;
unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum;
/* Calculate timestamp resolution */
for (i = 1; i < dht11->num_edges; ++i) {
t = dht11->edges[i].ts - dht11->edges[i-1].ts;
if (t > 0 && t < timeres)
timeres = t;
}
if (2*timeres > DHT11_DATA_BIT_HIGH) {
pr_err("dht11: timeresolution %d too bad for decoding\n",
timeres);
return -EIO;
}
threshold = DHT11_DATA_BIT_HIGH / timeres;
if (DHT11_DATA_BIT_LOW/timeres + 1 >= threshold)
if (DHT11_DATA_BIT_LOW / timeres + 1 >= threshold)
pr_err("dht11: WARNING: decoding ambiguous\n");
/* scale down with timeres and check validity */
for (i = 0; i < DHT11_BITS_PER_READ; ++i) {
t = dht11->edges[offset + 2*i + 2].ts -
dht11->edges[offset + 2*i + 1].ts;
if (!dht11->edges[offset + 2*i + 1].value)
t = dht11->edges[offset + 2 * i + 2].ts -
dht11->edges[offset + 2 * i + 1].ts;
if (!dht11->edges[offset + 2 * i + 1].value)
return -EIO; /* lost synchronisation */
timing[i] = t / timeres;
}
......@@ -126,7 +117,7 @@ static int dht11_decode(struct dht11 *dht11, int offset)
if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum)
return -EIO;
dht11->timestamp = iio_get_time_ns();
dht11->timestamp = ktime_get_real_ns();
if (hum_int < 20) { /* DHT22 */
dht11->temperature = (((temp_int & 0x7f) << 8) + temp_dec) *
((temp_int & 0x80) ? -100 : 100);
......@@ -154,7 +145,7 @@ static irqreturn_t dht11_handle_irq(int irq, void *data)
/* TODO: Consider making the handler safe for IRQ sharing */
if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) {
dht11->edges[dht11->num_edges].ts = iio_get_time_ns();
dht11->edges[dht11->num_edges].ts = ktime_get_real_ns();
dht11->edges[dht11->num_edges++].value =
gpio_get_value(dht11->gpio);
......@@ -166,14 +157,26 @@ static irqreturn_t dht11_handle_irq(int irq, void *data)
}
static int dht11_read_raw(struct iio_dev *iio_dev,
const struct iio_chan_spec *chan,
const struct iio_chan_spec *chan,
int *val, int *val2, long m)
{
struct dht11 *dht11 = iio_priv(iio_dev);
int ret;
int ret, timeres;
mutex_lock(&dht11->lock);
if (dht11->timestamp + DHT11_DATA_VALID_TIME < iio_get_time_ns()) {
if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_real_ns()) {
timeres = ktime_get_resolution_ns();
if (DHT11_DATA_BIT_HIGH < 2 * timeres) {
dev_err(dht11->dev, "timeresolution %dns too low\n",
timeres);
/* In theory a better clock could become available
* at some point ... and there is no error code
* that really fits better.
*/
ret = -EAGAIN;
goto err;
}
reinit_completion(&dht11->completion);
dht11->num_edges = 0;
......@@ -192,13 +195,13 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
goto err;
ret = wait_for_completion_killable_timeout(&dht11->completion,
HZ);
HZ);
free_irq(dht11->irq, iio_dev);
if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) {
dev_err(&iio_dev->dev,
"Only %d signal edges detected\n",
"Only %d signal edges detected\n",
dht11->num_edges);
ret = -ETIMEDOUT;
}
......@@ -206,9 +209,10 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
goto err;
ret = dht11_decode(dht11,
dht11->num_edges == DHT11_EDGES_PER_READ ?
dht11->num_edges == DHT11_EDGES_PER_READ ?
DHT11_EDGES_PREAMBLE :
DHT11_EDGES_PREAMBLE - 2);
DHT11_EDGES_PREAMBLE - 2,
timeres);
if (ret)
goto err;
}
......@@ -261,9 +265,10 @@ static int dht11_probe(struct platform_device *pdev)
dht11 = iio_priv(iio);
dht11->dev = dev;
dht11->gpio = ret = of_get_gpio(node, 0);
ret = of_get_gpio(node, 0);
if (ret < 0)
return ret;
dht11->gpio = ret;
ret = devm_gpio_request_one(dev, dht11->gpio, GPIOF_IN, pdev->name);
if (ret)
return ret;
......@@ -274,7 +279,7 @@ static int dht11_probe(struct platform_device *pdev)
return -EINVAL;
}
dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1;
dht11->timestamp = ktime_get_real_ns() - DHT11_DATA_VALID_TIME - 1;
dht11->num_edges = -1;
platform_set_drvdata(pdev, iio);
......
......@@ -139,7 +139,9 @@ enum adis16400_chip_variant {
ADIS16360,
ADIS16362,
ADIS16364,
ADIS16367,
ADIS16400,
ADIS16445,
ADIS16448,
};
......@@ -622,6 +624,17 @@ static const struct iio_chan_spec adis16400_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
};
static const struct iio_chan_spec adis16445_channels[] = {
ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 16),
ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 16),
ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 16),
ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 16),
ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 16),
ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 16),
ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12),
IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
};
static const struct iio_chan_spec adis16448_channels[] = {
ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 16),
ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 16),
......@@ -696,7 +709,8 @@ static struct adis16400_chip_info adis16400_chips[] = {
[ADIS16300] = {
.channels = adis16300_channels,
.num_channels = ARRAY_SIZE(adis16300_channels),
.flags = ADIS16400_HAS_SLOW_MODE,
.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE |
ADIS16400_HAS_SERIAL_NUMBER,
.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
.accel_scale_micro = 5884,
.temp_scale_nano = 140000000, /* 0.14 C */
......@@ -763,6 +777,18 @@ static struct adis16400_chip_info adis16400_chips[] = {
.set_freq = adis16400_set_freq,
.get_freq = adis16400_get_freq,
},
[ADIS16367] = {
.channels = adis16350_channels,
.num_channels = ARRAY_SIZE(adis16350_channels),
.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE |
ADIS16400_HAS_SERIAL_NUMBER,
.gyro_scale_micro = IIO_DEGREE_TO_RAD(2000), /* 0.2 deg/s */
.accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
.temp_scale_nano = 136000000, /* 0.136 C */
.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
.set_freq = adis16400_set_freq,
.get_freq = adis16400_get_freq,
},
[ADIS16400] = {
.channels = adis16400_channels,
.num_channels = ARRAY_SIZE(adis16400_channels),
......@@ -774,13 +800,26 @@ static struct adis16400_chip_info adis16400_chips[] = {
.set_freq = adis16400_set_freq,
.get_freq = adis16400_get_freq,
},
[ADIS16445] = {
.channels = adis16445_channels,
.num_channels = ARRAY_SIZE(adis16445_channels),
.flags = ADIS16400_HAS_PROD_ID |
ADIS16400_HAS_SERIAL_NUMBER |
ADIS16400_BURST_DIAG_STAT,
.gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */
.accel_scale_micro = IIO_G_TO_M_S_2(250), /* 1/4000 g */
.temp_scale_nano = 73860000, /* 0.07386 C */
.temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
.set_freq = adis16334_set_freq,
.get_freq = adis16334_get_freq,
},
[ADIS16448] = {
.channels = adis16448_channels,
.num_channels = ARRAY_SIZE(adis16448_channels),
.flags = ADIS16400_HAS_PROD_ID |
ADIS16400_HAS_SERIAL_NUMBER |
ADIS16400_BURST_DIAG_STAT,
.gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */
.gyro_scale_micro = IIO_DEGREE_TO_RAD(40000), /* 0.04 deg/s */
.accel_scale_micro = IIO_G_TO_M_S_2(833), /* 1/1200 g */
.temp_scale_nano = 73860000, /* 0.07386 C */
.temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
......@@ -926,6 +965,7 @@ static int adis16400_remove(struct spi_device *spi)
static const struct spi_device_id adis16400_id[] = {
{"adis16300", ADIS16300},
{"adis16305", ADIS16300},
{"adis16334", ADIS16334},
{"adis16350", ADIS16350},
{"adis16354", ADIS16350},
......@@ -934,8 +974,10 @@ static const struct spi_device_id adis16400_id[] = {
{"adis16362", ADIS16362},
{"adis16364", ADIS16364},
{"adis16365", ADIS16360},
{"adis16367", ADIS16367},
{"adis16400", ADIS16400},
{"adis16405", ADIS16400},
{"adis16445", ADIS16445},
{"adis16448", ADIS16448},
{}
};
......
......@@ -110,6 +110,10 @@
struct adis16480_chip_info {
unsigned int num_channels;
const struct iio_chan_spec *channels;
unsigned int gyro_max_val;
unsigned int gyro_max_scale;
unsigned int accel_max_val;
unsigned int accel_max_scale;
};
struct adis16480 {
......@@ -497,19 +501,21 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev,
static int adis16480_read_raw(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, int *val, int *val2, long info)
{
struct adis16480 *st = iio_priv(indio_dev);
switch (info) {
case IIO_CHAN_INFO_RAW:
return adis_single_conversion(indio_dev, chan, 0, val);
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
*val = 0;
*val2 = IIO_DEGREE_TO_RAD(20000); /* 0.02 degree/sec */
return IIO_VAL_INT_PLUS_MICRO;
*val = st->chip_info->gyro_max_scale;
*val2 = st->chip_info->gyro_max_val;
return IIO_VAL_FRACTIONAL;
case IIO_ACCEL:
*val = 0;
*val2 = IIO_G_TO_M_S_2(800); /* 0.8 mg */
return IIO_VAL_INT_PLUS_MICRO;
*val = st->chip_info->accel_max_scale;
*val2 = st->chip_info->accel_max_val;
return IIO_VAL_FRACTIONAL;
case IIO_MAGN:
*val = 0;
*val2 = 100; /* 0.0001 gauss */
......@@ -674,18 +680,39 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
[ADIS16375] = {
.channels = adis16485_channels,
.num_channels = ARRAY_SIZE(adis16485_channels),
/*
* storing the value in rad/degree and the scale in degree
* gives us the result in rad and better precession than
* storing the scale directly in rad.
*/
.gyro_max_val = IIO_RAD_TO_DEGREE(22887),
.gyro_max_scale = 300,
.accel_max_val = IIO_M_S_2_TO_G(21973),
.accel_max_scale = 18,
},
[ADIS16480] = {
.channels = adis16480_channels,
.num_channels = ARRAY_SIZE(adis16480_channels),
.gyro_max_val = IIO_RAD_TO_DEGREE(22500),
.gyro_max_scale = 450,
.accel_max_val = IIO_M_S_2_TO_G(12500),
.accel_max_scale = 5,
},
[ADIS16485] = {
.channels = adis16485_channels,
.num_channels = ARRAY_SIZE(adis16485_channels),
.gyro_max_val = IIO_RAD_TO_DEGREE(22500),
.gyro_max_scale = 450,
.accel_max_val = IIO_M_S_2_TO_G(20000),
.accel_max_scale = 5,
},
[ADIS16488] = {
.channels = adis16480_channels,
.num_channels = ARRAY_SIZE(adis16480_channels),
.gyro_max_val = IIO_RAD_TO_DEGREE(22500),
.gyro_max_scale = 450,
.accel_max_val = IIO_M_S_2_TO_G(22500),
.accel_max_scale = 18,
},
};
......
......@@ -1363,7 +1363,7 @@ static int kmx61_probe(struct i2c_client *client,
if (client->irq < 0)
client->irq = kmx61_gpio_probe(client, data);
if (client->irq >= 0) {
if (client->irq > 0) {
ret = devm_request_threaded_irq(&client->dev, client->irq,
kmx61_data_rdy_trig_poll,
kmx61_event_handler,
......@@ -1445,10 +1445,10 @@ static int kmx61_probe(struct i2c_client *client,
err_iio_unregister_acc:
iio_device_unregister(data->acc_indio_dev);
err_buffer_cleanup_mag:
if (client->irq >= 0)
if (client->irq > 0)
iio_triggered_buffer_cleanup(data->mag_indio_dev);
err_buffer_cleanup_acc:
if (client->irq >= 0)
if (client->irq > 0)
iio_triggered_buffer_cleanup(data->acc_indio_dev);
err_trigger_unregister_motion:
iio_trigger_unregister(data->motion_trig);
......@@ -1472,7 +1472,7 @@ static int kmx61_remove(struct i2c_client *client)
iio_device_unregister(data->acc_indio_dev);
iio_device_unregister(data->mag_indio_dev);
if (client->irq >= 0) {
if (client->irq > 0) {
iio_triggered_buffer_cleanup(data->acc_indio_dev);
iio_triggered_buffer_cleanup(data->mag_indio_dev);
iio_trigger_unregister(data->acc_dready_trig);
......
......@@ -91,9 +91,16 @@ static bool iio_buffer_ready(struct iio_dev *indio_dev, struct iio_buffer *buf,
/**
* iio_buffer_read_first_n_outer() - chrdev read for buffer access
* @filp: File structure pointer for the char device
* @buf: Destination buffer for iio buffer read
* @n: First n bytes to read
* @f_ps: Long offset provided by the user as a seek position
*
* This function relies on all buffer implementations having an
* iio_buffer as their first element.
*
* Return: negative values corresponding to error codes or ret != 0
* for ending the reading activity
**/
ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
size_t n, loff_t *f_ps)
......@@ -143,6 +150,12 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
/**
* iio_buffer_poll() - poll the buffer to find out if it has data
* @filp: File structure pointer for device access
* @wait: Poll table structure pointer for which the driver adds
* a wait queue
*
* Return: (POLLIN | POLLRDNORM) if data is available for reading
* or 0 for other cases
*/
unsigned int iio_buffer_poll(struct file *filp,
struct poll_table_struct *wait)
......@@ -151,7 +164,7 @@ unsigned int iio_buffer_poll(struct file *filp,
struct iio_buffer *rb = indio_dev->buffer;
if (!indio_dev->info)
return -ENODEV;
return 0;
poll_wait(filp, &rb->pollq, wait);
if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
......@@ -1136,7 +1149,7 @@ int iio_scan_mask_query(struct iio_dev *indio_dev,
EXPORT_SYMBOL_GPL(iio_scan_mask_query);
/**
* struct iio_demux_table() - table describing demux memcpy ops
* struct iio_demux_table - table describing demux memcpy ops
* @from: index to copy from
* @to: index to copy to
* @length: how many bytes to copy
......
......@@ -406,10 +406,16 @@ EXPORT_SYMBOL_GPL(iio_enum_write);
/**
* iio_format_value() - Formats a IIO value into its string representation
* @buf: The buffer to which the formated value gets written
* @type: One of the IIO_VAL_... constants. This decides how the val and val2
* parameters are formatted.
* @vals: pointer to the values, exact meaning depends on the type parameter.
* @buf: The buffer to which the formatted value gets written
* @type: One of the IIO_VAL_... constants. This decides how the val
* and val2 parameters are formatted.
* @size: Number of IIO value entries contained in vals
* @vals: Pointer to the values, exact meaning depends on the
* type parameter.
*
* Return: 0 by default, a negative number on failure or the
* total number of characters written for a type that belongs
* to the IIO_VAL_... constant.
*/
ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
{
......@@ -1096,6 +1102,11 @@ EXPORT_SYMBOL_GPL(devm_iio_device_free);
/**
* iio_chrdev_open() - chrdev file open for buffer access and ioctls
* @inode: Inode structure for identifying the device in the file system
* @filp: File structure for iio device used to keep and later access
* private data
*
* Return: 0 on success or -EBUSY if the device is already opened
**/
static int iio_chrdev_open(struct inode *inode, struct file *filp)
{
......@@ -1114,7 +1125,11 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp)
/**
* iio_chrdev_release() - chrdev file close buffer access and ioctls
**/
* @inode: Inode structure pointer for the char device
* @filp: File structure pointer for the char device
*
* Return: 0 for successful release
*/
static int iio_chrdev_release(struct inode *inode, struct file *filp)
{
struct iio_dev *indio_dev = container_of(inode->i_cdev,
......
......@@ -32,6 +32,7 @@
* @dev_attr_list: list of event interface sysfs attribute
* @flags: file operations related flags including busy flag.
* @group: event interface sysfs attribute group
* @read_lock: lock to protect kfifo read operations
*/
struct iio_event_interface {
wait_queue_head_t wait;
......@@ -75,6 +76,11 @@ EXPORT_SYMBOL(iio_push_event);
/**
* iio_event_poll() - poll the event queue to find out if it has data
* @filep: File structure pointer to identify the device
* @wait: Poll table pointer to add the wait queue on
*
* Return: (POLLIN | POLLRDNORM) if data is available for reading
* or a negative error code on failure
*/
static unsigned int iio_event_poll(struct file *filep,
struct poll_table_struct *wait)
......@@ -84,7 +90,7 @@ static unsigned int iio_event_poll(struct file *filep,
unsigned int events = 0;
if (!indio_dev->info)
return -ENODEV;
return events;
poll_wait(filep, &ev_int->wait, wait);
......
......@@ -40,7 +40,14 @@ static DEFINE_MUTEX(iio_trigger_list_lock);
/**
* iio_trigger_read_name() - retrieve useful identifying name
**/
* @dev: device associated with the iio_trigger
* @attr: pointer to the device_attribute structure that is
* being processed
* @buf: buffer to print the name into
*
* Return: a negative number on failure or the number of written
* characters on success.
*/
static ssize_t iio_trigger_read_name(struct device *dev,
struct device_attribute *attr,
char *buf)
......@@ -288,10 +295,17 @@ EXPORT_SYMBOL_GPL(iio_dealloc_pollfunc);
/**
* iio_trigger_read_current() - trigger consumer sysfs query current trigger
* @dev: device associated with an industrial I/O device
* @attr: pointer to the device_attribute structure that
* is being processed
* @buf: buffer where the current trigger name will be printed into
*
* For trigger consumers the current_trigger interface allows the trigger
* used by the device to be queried.
**/
*
* Return: a negative number on failure, the number of characters written
* on success or 0 if no trigger is available
*/
static ssize_t iio_trigger_read_current(struct device *dev,
struct device_attribute *attr,
char *buf)
......@@ -305,11 +319,18 @@ static ssize_t iio_trigger_read_current(struct device *dev,
/**
* iio_trigger_write_current() - trigger consumer sysfs set current trigger
* @dev: device associated with an industrial I/O device
* @attr: device attribute that is being processed
* @buf: string buffer that holds the name of the trigger
* @len: length of the trigger name held by buf
*
* For trigger consumers the current_trigger interface allows the trigger
* used for this device to be specified at run time based on the trigger's
* name.
**/
*
* Return: negative error code on failure or length of the buffer
* on success
*/
static ssize_t iio_trigger_write_current(struct device *dev,
struct device_attribute *attr,
const char *buf,
......
......@@ -210,6 +210,27 @@ config LTR501
This driver can also be built as a module. If so, the module
will be called ltr501.
config OPT3001
tristate "Texas Instruments OPT3001 Light Sensor"
depends on I2C
help
If you say Y or M here, you get support for Texas Instruments
OPT3001 Ambient Light Sensor.
If built as a dynamically linked module, it will be called
opt3001.
config PA12203001
tristate "TXC PA12203001 light and proximity sensor"
depends on I2C
select REGMAP_I2C
help
If you say yes here you get support for the TXC PA12203001
ambient light and proximity sensor.
This driver can also be built as a module. If so, the module
will be called pa12203001.
config STK3310
tristate "STK3310 ALS and proximity sensor"
depends on I2C
......
......@@ -19,6 +19,8 @@ obj-$(CONFIG_ISL29125) += isl29125.o
obj-$(CONFIG_JSA1212) += jsa1212.o
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
obj-$(CONFIG_LTR501) += ltr501.o
obj-$(CONFIG_OPT3001) += opt3001.o
obj-$(CONFIG_PA12203001) += pa12203001.o
obj-$(CONFIG_RPR0521) += rpr0521.o
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
obj-$(CONFIG_STK3310) += stk3310.o
......
......@@ -65,20 +65,20 @@ static const struct iio_chan_spec acpi_als_channels[] = {
* to acpi_als_channels[], the evt_buffer below will grow
* automatically.
*/
#define EVT_NR_SOURCES ARRAY_SIZE(acpi_als_channels)
#define EVT_BUFFER_SIZE \
(sizeof(s64) + (EVT_NR_SOURCES * sizeof(s32)))
#define ACPI_ALS_EVT_NR_SOURCES ARRAY_SIZE(acpi_als_channels)
#define ACPI_ALS_EVT_BUFFER_SIZE \
(sizeof(s64) + (ACPI_ALS_EVT_NR_SOURCES * sizeof(s32)))
struct acpi_als {
struct acpi_device *device;
struct mutex lock;
s32 evt_buffer[EVT_BUFFER_SIZE];
s32 evt_buffer[ACPI_ALS_EVT_BUFFER_SIZE];
};
/*
* All types of properties the ACPI0008 block can report. The ALI, ALC, ALT
* and ALP can all be handled by als_read_value() below, while the ALR is
* and ALP can all be handled by acpi_als_read_value() below, while the ALR is
* special.
*
* The _ALR property returns tables that can be used to fine-tune the values
......@@ -93,7 +93,7 @@ struct acpi_als {
#define ACPI_ALS_POLLING "_ALP"
#define ACPI_ALS_TABLES "_ALR"
static int als_read_value(struct acpi_als *als, char *prop, s32 *val)
static int acpi_als_read_value(struct acpi_als *als, char *prop, s32 *val)
{
unsigned long long temp_val;
acpi_status status;
......@@ -122,11 +122,11 @@ static void acpi_als_notify(struct acpi_device *device, u32 event)
mutex_lock(&als->lock);
memset(buffer, 0, EVT_BUFFER_SIZE);
memset(buffer, 0, ACPI_ALS_EVT_BUFFER_SIZE);
switch (event) {
case ACPI_ALS_NOTIFY_ILLUMINANCE:
ret = als_read_value(als, ACPI_ALS_ILLUMINANCE, &val);
ret = acpi_als_read_value(als, ACPI_ALS_ILLUMINANCE, &val);
if (ret < 0)
goto out;
*buffer++ = val;
......@@ -159,7 +159,7 @@ static int acpi_als_read_raw(struct iio_dev *indio_dev,
if (chan->type != IIO_LIGHT)
return -EINVAL;
ret = als_read_value(als, ACPI_ALS_ILLUMINANCE, &temp_val);
ret = acpi_als_read_value(als, ACPI_ALS_ILLUMINANCE, &temp_val);
if (ret < 0)
return ret;
......
......@@ -353,6 +353,7 @@ static const struct of_device_id cm32181_of_match[] = {
{ .compatible = "capella,cm32181" },
{ }
};
MODULE_DEVICE_TABLE(of, cm32181_of_match);
static struct i2c_driver cm32181_driver = {
.driver = {
......
......@@ -417,6 +417,7 @@ static const struct of_device_id cm3232_of_match[] = {
{.compatible = "capella,cm3232"},
{}
};
MODULE_DEVICE_TABLE(of, cm3232_of_match);
static struct i2c_driver cm3232_driver = {
.driver = {
......
......@@ -731,6 +731,7 @@ static const struct of_device_id cm36651_of_match[] = {
{ .compatible = "capella,cm36651" },
{ }
};
MODULE_DEVICE_TABLE(of, cm36651_of_match);
static struct i2c_driver cm36651_driver = {
.driver = {
......
......@@ -1634,6 +1634,7 @@ static const struct of_device_id gp2ap020a00f_of_match[] = {
{ .compatible = "sharp,gp2ap020a00f" },
{ }
};
MODULE_DEVICE_TABLE(of, gp2ap020a00f_of_match);
#endif
static struct i2c_driver gp2ap020a00f_driver = {
......
/**
* opt3001.c - Texas Instruments OPT3001 Light Sensor
*
* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
*
* Author: Andreas Dannenberg <dannenberg@ti.com>
* Based on previous work from: Felipe Balbi <balbi@ti.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 of the License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define OPT3001_RESULT 0x00
#define OPT3001_CONFIGURATION 0x01
#define OPT3001_LOW_LIMIT 0x02
#define OPT3001_HIGH_LIMIT 0x03
#define OPT3001_MANUFACTURER_ID 0x7e
#define OPT3001_DEVICE_ID 0x7f
#define OPT3001_CONFIGURATION_RN_MASK (0xf << 12)
#define OPT3001_CONFIGURATION_RN_AUTO (0xc << 12)
#define OPT3001_CONFIGURATION_CT BIT(11)
#define OPT3001_CONFIGURATION_M_MASK (3 << 9)
#define OPT3001_CONFIGURATION_M_SHUTDOWN (0 << 9)
#define OPT3001_CONFIGURATION_M_SINGLE (1 << 9)
#define OPT3001_CONFIGURATION_M_CONTINUOUS (2 << 9) /* also 3 << 9 */
#define OPT3001_CONFIGURATION_OVF BIT(8)
#define OPT3001_CONFIGURATION_CRF BIT(7)
#define OPT3001_CONFIGURATION_FH BIT(6)
#define OPT3001_CONFIGURATION_FL BIT(5)
#define OPT3001_CONFIGURATION_L BIT(4)
#define OPT3001_CONFIGURATION_POL BIT(3)
#define OPT3001_CONFIGURATION_ME BIT(2)
#define OPT3001_CONFIGURATION_FC_MASK (3 << 0)
/* The end-of-conversion enable is located in the low-limit register */
#define OPT3001_LOW_LIMIT_EOC_ENABLE 0xc000
#define OPT3001_REG_EXPONENT(n) ((n) >> 12)
#define OPT3001_REG_MANTISSA(n) ((n) & 0xfff)
/*
* Time to wait for conversion result to be ready. The device datasheet
* worst-case max value is 880ms. Add some slack to be on the safe side.
*/
#define OPT3001_RESULT_READY_TIMEOUT msecs_to_jiffies(1000)
struct opt3001 {
struct i2c_client *client;
struct device *dev;
struct mutex lock;
u16 ok_to_ignore_lock:1;
u16 result_ready:1;
wait_queue_head_t result_ready_queue;
u16 result;
u32 int_time;
u32 mode;
u16 high_thresh_mantissa;
u16 low_thresh_mantissa;
u8 high_thresh_exp;
u8 low_thresh_exp;
};
struct opt3001_scale {
int val;
int val2;
};
static const struct opt3001_scale opt3001_scales[] = {
{
.val = 40,
.val2 = 950000,
},
{
.val = 81,
.val2 = 900000,
},
{
.val = 163,
.val2 = 800000,
},
{
.val = 327,
.val2 = 600000,
},
{
.val = 655,
.val2 = 200000,
},
{
.val = 1310,
.val2 = 400000,
},
{
.val = 2620,
.val2 = 800000,
},
{
.val = 5241,
.val2 = 600000,
},
{
.val = 10483,
.val2 = 200000,
},
{
.val = 20966,
.val2 = 400000,
},
{
.val = 83865,
.val2 = 600000,
},
};
static int opt3001_find_scale(const struct opt3001 *opt, int val,
int val2, u8 *exponent)
{
int i;
for (i = 0; i < ARRAY_SIZE(opt3001_scales); i++) {
const struct opt3001_scale *scale = &opt3001_scales[i];
/*
* Combine the integer and micro parts for comparison
* purposes. Use milli lux precision to avoid 32-bit integer
* overflows.
*/
if ((val * 1000 + val2 / 1000) <=
(scale->val * 1000 + scale->val2 / 1000)) {
*exponent = i;
return 0;
}
}
return -EINVAL;
}
static void opt3001_to_iio_ret(struct opt3001 *opt, u8 exponent,
u16 mantissa, int *val, int *val2)
{
int lux;
lux = 10 * (mantissa << exponent);
*val = lux / 1000;
*val2 = (lux - (*val * 1000)) * 1000;
}
static void opt3001_set_mode(struct opt3001 *opt, u16 *reg, u16 mode)
{
*reg &= ~OPT3001_CONFIGURATION_M_MASK;
*reg |= mode;
opt->mode = mode;
}
static IIO_CONST_ATTR_INT_TIME_AVAIL("0.1 0.8");
static struct attribute *opt3001_attributes[] = {
&iio_const_attr_integration_time_available.dev_attr.attr,
NULL
};
static const struct attribute_group opt3001_attribute_group = {
.attrs = opt3001_attributes,
};
static const struct iio_event_spec opt3001_event_spec[] = {
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
};
static const struct iio_chan_spec opt3001_channels[] = {
{
.type = IIO_LIGHT,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_INT_TIME),
.event_spec = opt3001_event_spec,
.num_event_specs = ARRAY_SIZE(opt3001_event_spec),
},
IIO_CHAN_SOFT_TIMESTAMP(1),
};
static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2)
{
int ret;
u16 mantissa;
u16 reg;
u8 exponent;
u16 value;
/*
* Enable the end-of-conversion interrupt mechanism. Note that doing
* so will overwrite the low-level limit value however we will restore
* this value later on.
*/
ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT,
OPT3001_LOW_LIMIT_EOC_ENABLE);
if (ret < 0) {
dev_err(opt->dev, "failed to write register %02x\n",
OPT3001_LOW_LIMIT);
return ret;
}
/* Reset data-ready indicator flag (will be set in the IRQ routine) */
opt->result_ready = false;
/* Allow IRQ to access the device despite lock being set */
opt->ok_to_ignore_lock = true;
/* Configure for single-conversion mode and start a new conversion */
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
OPT3001_CONFIGURATION);
goto err;
}
reg = ret;
opt3001_set_mode(opt, &reg, OPT3001_CONFIGURATION_M_SINGLE);
ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
reg);
if (ret < 0) {
dev_err(opt->dev, "failed to write register %02x\n",
OPT3001_CONFIGURATION);
goto err;
}
/* Wait for the IRQ to indicate the conversion is complete */
ret = wait_event_timeout(opt->result_ready_queue, opt->result_ready,
OPT3001_RESULT_READY_TIMEOUT);
err:
/* Disallow IRQ to access the device while lock is active */
opt->ok_to_ignore_lock = false;
if (ret == 0)
return -ETIMEDOUT;
else if (ret < 0)
return ret;
/*
* Disable the end-of-conversion interrupt mechanism by restoring the
* low-level limit value (clearing OPT3001_LOW_LIMIT_EOC_ENABLE). Note
* that selectively clearing those enable bits would affect the actual
* limit value due to bit-overlap and therefore can't be done.
*/
value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa;
ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT,
value);
if (ret < 0) {
dev_err(opt->dev, "failed to write register %02x\n",
OPT3001_LOW_LIMIT);
return ret;
}
exponent = OPT3001_REG_EXPONENT(opt->result);
mantissa = OPT3001_REG_MANTISSA(opt->result);
opt3001_to_iio_ret(opt, exponent, mantissa, val, val2);
return IIO_VAL_INT_PLUS_MICRO;
}
static int opt3001_get_int_time(struct opt3001 *opt, int *val, int *val2)
{
*val = 0;
*val2 = opt->int_time;
return IIO_VAL_INT_PLUS_MICRO;
}
static int opt3001_set_int_time(struct opt3001 *opt, int time)
{
int ret;
u16 reg;
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
OPT3001_CONFIGURATION);
return ret;
}
reg = ret;
switch (time) {
case 100000:
reg &= ~OPT3001_CONFIGURATION_CT;
opt->int_time = 100000;
break;
case 800000:
reg |= OPT3001_CONFIGURATION_CT;
opt->int_time = 800000;
break;
default:
return -EINVAL;
}
return i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
reg);
}
static int opt3001_read_raw(struct iio_dev *iio,
struct iio_chan_spec const *chan, int *val, int *val2,
long mask)
{
struct opt3001 *opt = iio_priv(iio);
int ret;
if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
return -EBUSY;
if (chan->type != IIO_LIGHT)
return -EINVAL;
mutex_lock(&opt->lock);
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
ret = opt3001_get_lux(opt, val, val2);
break;
case IIO_CHAN_INFO_INT_TIME:
ret = opt3001_get_int_time(opt, val, val2);
break;
default:
ret = -EINVAL;
}
mutex_unlock(&opt->lock);
return ret;
}
static int opt3001_write_raw(struct iio_dev *iio,
struct iio_chan_spec const *chan, int val, int val2,
long mask)
{
struct opt3001 *opt = iio_priv(iio);
int ret;
if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
return -EBUSY;
if (chan->type != IIO_LIGHT)
return -EINVAL;
if (mask != IIO_CHAN_INFO_INT_TIME)
return -EINVAL;
if (val != 0)
return -EINVAL;
mutex_lock(&opt->lock);
ret = opt3001_set_int_time(opt, val2);
mutex_unlock(&opt->lock);
return ret;
}
static int opt3001_read_event_value(struct iio_dev *iio,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, enum iio_event_info info,
int *val, int *val2)
{
struct opt3001 *opt = iio_priv(iio);
int ret = IIO_VAL_INT_PLUS_MICRO;
mutex_lock(&opt->lock);
switch (dir) {
case IIO_EV_DIR_RISING:
opt3001_to_iio_ret(opt, opt->high_thresh_exp,
opt->high_thresh_mantissa, val, val2);
break;
case IIO_EV_DIR_FALLING:
opt3001_to_iio_ret(opt, opt->low_thresh_exp,
opt->low_thresh_mantissa, val, val2);
break;
default:
ret = -EINVAL;
}
mutex_unlock(&opt->lock);
return ret;
}
static int opt3001_write_event_value(struct iio_dev *iio,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, enum iio_event_info info,
int val, int val2)
{
struct opt3001 *opt = iio_priv(iio);
int ret;
u16 mantissa;
u16 value;
u16 reg;
u8 exponent;
if (val < 0)
return -EINVAL;
mutex_lock(&opt->lock);
ret = opt3001_find_scale(opt, val, val2, &exponent);
if (ret < 0) {
dev_err(opt->dev, "can't find scale for %d.%06u\n", val, val2);
goto err;
}
mantissa = (((val * 1000) + (val2 / 1000)) / 10) >> exponent;
value = (exponent << 12) | mantissa;
switch (dir) {
case IIO_EV_DIR_RISING:
reg = OPT3001_HIGH_LIMIT;
opt->high_thresh_mantissa = mantissa;
opt->high_thresh_exp = exponent;
break;
case IIO_EV_DIR_FALLING:
reg = OPT3001_LOW_LIMIT;
opt->low_thresh_mantissa = mantissa;
opt->low_thresh_exp = exponent;
break;
default:
ret = -EINVAL;
goto err;
}
ret = i2c_smbus_write_word_swapped(opt->client, reg, value);
if (ret < 0) {
dev_err(opt->dev, "failed to write register %02x\n", reg);
goto err;
}
err:
mutex_unlock(&opt->lock);
return ret;
}
static int opt3001_read_event_config(struct iio_dev *iio,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir)
{
struct opt3001 *opt = iio_priv(iio);
return opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS;
}
static int opt3001_write_event_config(struct iio_dev *iio,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, int state)
{
struct opt3001 *opt = iio_priv(iio);
int ret;
u16 mode;
u16 reg;
if (state && opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
return 0;
if (!state && opt->mode == OPT3001_CONFIGURATION_M_SHUTDOWN)
return 0;
mutex_lock(&opt->lock);
mode = state ? OPT3001_CONFIGURATION_M_CONTINUOUS
: OPT3001_CONFIGURATION_M_SHUTDOWN;
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
OPT3001_CONFIGURATION);
goto err;
}
reg = ret;
opt3001_set_mode(opt, &reg, mode);
ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
reg);
if (ret < 0) {
dev_err(opt->dev, "failed to write register %02x\n",
OPT3001_CONFIGURATION);
goto err;
}
err:
mutex_unlock(&opt->lock);
return ret;
}
static const struct iio_info opt3001_info = {
.driver_module = THIS_MODULE,
.attrs = &opt3001_attribute_group,
.read_raw = opt3001_read_raw,
.write_raw = opt3001_write_raw,
.read_event_value = opt3001_read_event_value,
.write_event_value = opt3001_write_event_value,
.read_event_config = opt3001_read_event_config,
.write_event_config = opt3001_write_event_config,
};
static int opt3001_read_id(struct opt3001 *opt)
{
char manufacturer[2];
u16 device_id;
int ret;
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_MANUFACTURER_ID);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
OPT3001_MANUFACTURER_ID);
return ret;
}
manufacturer[0] = ret >> 8;
manufacturer[1] = ret & 0xff;
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_DEVICE_ID);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
OPT3001_DEVICE_ID);
return ret;
}
device_id = ret;
dev_info(opt->dev, "Found %c%c OPT%04x\n", manufacturer[0],
manufacturer[1], device_id);
return 0;
}
static int opt3001_configure(struct opt3001 *opt)
{
int ret;
u16 reg;
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
OPT3001_CONFIGURATION);
return ret;
}
reg = ret;
/* Enable automatic full-scale setting mode */
reg &= ~OPT3001_CONFIGURATION_RN_MASK;
reg |= OPT3001_CONFIGURATION_RN_AUTO;
/* Reflect status of the device's integration time setting */
if (reg & OPT3001_CONFIGURATION_CT)
opt->int_time = 800000;
else
opt->int_time = 100000;
/* Ensure device is in shutdown initially */
opt3001_set_mode(opt, &reg, OPT3001_CONFIGURATION_M_SHUTDOWN);
/* Configure for latched window-style comparison operation */
reg |= OPT3001_CONFIGURATION_L;
reg &= ~OPT3001_CONFIGURATION_POL;
reg &= ~OPT3001_CONFIGURATION_ME;
reg &= ~OPT3001_CONFIGURATION_FC_MASK;
ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
reg);
if (ret < 0) {
dev_err(opt->dev, "failed to write register %02x\n",
OPT3001_CONFIGURATION);
return ret;
}
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_LOW_LIMIT);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
OPT3001_LOW_LIMIT);
return ret;
}
opt->low_thresh_mantissa = OPT3001_REG_MANTISSA(ret);
opt->low_thresh_exp = OPT3001_REG_EXPONENT(ret);
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_HIGH_LIMIT);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
OPT3001_HIGH_LIMIT);
return ret;
}
opt->high_thresh_mantissa = OPT3001_REG_MANTISSA(ret);
opt->high_thresh_exp = OPT3001_REG_EXPONENT(ret);
return 0;
}
static irqreturn_t opt3001_irq(int irq, void *_iio)
{
struct iio_dev *iio = _iio;
struct opt3001 *opt = iio_priv(iio);
int ret;
if (!opt->ok_to_ignore_lock)
mutex_lock(&opt->lock);
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
OPT3001_CONFIGURATION);
goto out;
}
if ((ret & OPT3001_CONFIGURATION_M_MASK) ==
OPT3001_CONFIGURATION_M_CONTINUOUS) {
if (ret & OPT3001_CONFIGURATION_FH)
iio_push_event(iio,
IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
iio_get_time_ns());
if (ret & OPT3001_CONFIGURATION_FL)
iio_push_event(iio,
IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
iio_get_time_ns());
} else if (ret & OPT3001_CONFIGURATION_CRF) {
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_RESULT);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
OPT3001_RESULT);
goto out;
}
opt->result = ret;
opt->result_ready = true;
wake_up(&opt->result_ready_queue);
}
out:
if (!opt->ok_to_ignore_lock)
mutex_unlock(&opt->lock);
return IRQ_HANDLED;
}
static int opt3001_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct iio_dev *iio;
struct opt3001 *opt;
int irq = client->irq;
int ret;
iio = devm_iio_device_alloc(dev, sizeof(*opt));
if (!iio)
return -ENOMEM;
opt = iio_priv(iio);
opt->client = client;
opt->dev = dev;
mutex_init(&opt->lock);
init_waitqueue_head(&opt->result_ready_queue);
i2c_set_clientdata(client, iio);
ret = opt3001_read_id(opt);
if (ret)
return ret;
ret = opt3001_configure(opt);
if (ret)
return ret;
iio->name = client->name;
iio->channels = opt3001_channels;
iio->num_channels = ARRAY_SIZE(opt3001_channels);
iio->dev.parent = dev;
iio->modes = INDIO_DIRECT_MODE;
iio->info = &opt3001_info;
ret = devm_iio_device_register(dev, iio);
if (ret) {
dev_err(dev, "failed to register IIO device\n");
return ret;
}
ret = request_threaded_irq(irq, NULL, opt3001_irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"opt3001", iio);
if (ret) {
dev_err(dev, "failed to request IRQ #%d\n", irq);
return ret;
}
return 0;
}
static int opt3001_remove(struct i2c_client *client)
{
struct iio_dev *iio = i2c_get_clientdata(client);
struct opt3001 *opt = iio_priv(iio);
int ret;
u16 reg;
free_irq(client->irq, iio);
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
OPT3001_CONFIGURATION);
return ret;
}
reg = ret;
opt3001_set_mode(opt, &reg, OPT3001_CONFIGURATION_M_SHUTDOWN);
ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
reg);
if (ret < 0) {
dev_err(opt->dev, "failed to write register %02x\n",
OPT3001_CONFIGURATION);
return ret;
}
return 0;
}
static const struct i2c_device_id opt3001_id[] = {
{ "opt3001", 0 },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(i2c, opt3001_id);
static const struct of_device_id opt3001_of_match[] = {
{ .compatible = "ti,opt3001" },
{ }
};
static struct i2c_driver opt3001_driver = {
.probe = opt3001_probe,
.remove = opt3001_remove,
.id_table = opt3001_id,
.driver = {
.name = "opt3001",
.of_match_table = of_match_ptr(opt3001_of_match),
.owner = THIS_MODULE,
},
};
module_i2c_driver(opt3001_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Andreas Dannenberg <dannenberg@ti.com>");
MODULE_DESCRIPTION("Texas Instruments OPT3001 Light Sensor Driver");
/*
* Copyright (c) 2015 Intel Corporation
*
* Driver for TXC PA12203001 Proximity and Ambient Light Sensor.
*
* 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.
* To do: Interrupt support.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/mutex.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#define PA12203001_DRIVER_NAME "pa12203001"
#define PA12203001_REG_CFG0 0x00
#define PA12203001_REG_CFG1 0x01
#define PA12203001_REG_CFG2 0x02
#define PA12203001_REG_CFG3 0x03
#define PA12203001_REG_ADL 0x0b
#define PA12203001_REG_PDH 0x0e
#define PA12203001_REG_POFS 0x10
#define PA12203001_REG_PSET 0x11
#define PA12203001_ALS_EN_MASK BIT(0)
#define PA12203001_PX_EN_MASK BIT(1)
#define PA12203001_PX_NORMAL_MODE_MASK GENMASK(7, 6)
#define PA12203001_AFSR_MASK GENMASK(5, 4)
#define PA12203001_AFSR_SHIFT 4
#define PA12203001_PSCAN 0x03
/* als range 31000, ps, als disabled */
#define PA12203001_REG_CFG0_DEFAULT 0x30
/* led current: 100 mA */
#define PA12203001_REG_CFG1_DEFAULT 0x20
/* ps mode: normal, interrupts not active */
#define PA12203001_REG_CFG2_DEFAULT 0xcc
#define PA12203001_REG_CFG3_DEFAULT 0x00
#define PA12203001_SLEEP_DELAY_MS 3000
#define PA12203001_CHIP_ENABLE 0xff
#define PA12203001_CHIP_DISABLE 0x00
/* available scales: corresponding to [500, 4000, 7000, 31000] lux */
static const int pa12203001_scales[] = { 7629, 61036, 106813, 473029};
struct pa12203001_data {
struct i2c_client *client;
/* protect device states */
struct mutex lock;
bool als_enabled;
bool px_enabled;
bool als_needs_enable;
bool px_needs_enable;
struct regmap *map;
};
static const struct {
u8 reg;
u8 val;
} regvals[] = {
{PA12203001_REG_CFG0, PA12203001_REG_CFG0_DEFAULT},
{PA12203001_REG_CFG1, PA12203001_REG_CFG1_DEFAULT},
{PA12203001_REG_CFG2, PA12203001_REG_CFG2_DEFAULT},
{PA12203001_REG_CFG3, PA12203001_REG_CFG3_DEFAULT},
{PA12203001_REG_PSET, PA12203001_PSCAN},
};
static IIO_CONST_ATTR(in_illuminance_scale_available,
"0.007629 0.061036 0.106813 0.473029");
static struct attribute *pa12203001_attrs[] = {
&iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
NULL
};
static const struct attribute_group pa12203001_attr_group = {
.attrs = pa12203001_attrs,
};
static const struct iio_chan_spec pa12203001_channels[] = {
{
.type = IIO_LIGHT,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
},
{
.type = IIO_PROXIMITY,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
}
};
static const struct regmap_range pa12203001_volatile_regs_ranges[] = {
regmap_reg_range(PA12203001_REG_ADL, PA12203001_REG_ADL + 1),
regmap_reg_range(PA12203001_REG_PDH, PA12203001_REG_PDH),
};
static const struct regmap_access_table pa12203001_volatile_regs = {
.yes_ranges = pa12203001_volatile_regs_ranges,
.n_yes_ranges = ARRAY_SIZE(pa12203001_volatile_regs_ranges),
};
static const struct regmap_config pa12203001_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = PA12203001_REG_PSET,
.cache_type = REGCACHE_RBTREE,
.volatile_table = &pa12203001_volatile_regs,
};
static inline int pa12203001_als_enable(struct pa12203001_data *data, u8 enable)
{
int ret;
ret = regmap_update_bits(data->map, PA12203001_REG_CFG0,
PA12203001_ALS_EN_MASK, enable);
if (ret < 0)
return ret;
data->als_enabled = !!enable;
return 0;
}
static inline int pa12203001_px_enable(struct pa12203001_data *data, u8 enable)
{
int ret;
ret = regmap_update_bits(data->map, PA12203001_REG_CFG0,
PA12203001_PX_EN_MASK, enable);
if (ret < 0)
return ret;
data->px_enabled = !!enable;
return 0;
}
static int pa12203001_set_power_state(struct pa12203001_data *data, bool on,
u8 mask)
{
#ifdef CONFIG_PM
int ret;
if (on && (mask & PA12203001_ALS_EN_MASK)) {
mutex_lock(&data->lock);
if (data->px_enabled) {
ret = pa12203001_als_enable(data,
PA12203001_ALS_EN_MASK);
if (ret < 0)
goto err;
} else {
data->als_needs_enable = true;
}
mutex_unlock(&data->lock);
}
if (on && (mask & PA12203001_PX_EN_MASK)) {
mutex_lock(&data->lock);
if (data->als_enabled) {
ret = pa12203001_px_enable(data, PA12203001_PX_EN_MASK);
if (ret < 0)
goto err;
} else {
data->px_needs_enable = true;
}
mutex_unlock(&data->lock);
}
if (on) {
ret = pm_runtime_get_sync(&data->client->dev);
if (ret < 0)
pm_runtime_put_noidle(&data->client->dev);
} else {
pm_runtime_mark_last_busy(&data->client->dev);
ret = pm_runtime_put_autosuspend(&data->client->dev);
}
return ret;
err:
mutex_unlock(&data->lock);
return ret;
#endif
return 0;
}
static int pa12203001_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
{
struct pa12203001_data *data = iio_priv(indio_dev);
int ret;
u8 dev_mask;
unsigned int reg_byte;
__le16 reg_word;
switch (mask) {
case IIO_CHAN_INFO_RAW:
switch (chan->type) {
case IIO_LIGHT:
dev_mask = PA12203001_ALS_EN_MASK;
ret = pa12203001_set_power_state(data, true, dev_mask);
if (ret < 0)
return ret;
/*
* ALS ADC value is stored in registers
* PA12203001_REG_ADL and in PA12203001_REG_ADL + 1.
*/
ret = regmap_bulk_read(data->map, PA12203001_REG_ADL,
&reg_word, 2);
if (ret < 0)
goto reg_err;
*val = le16_to_cpu(reg_word);
ret = pa12203001_set_power_state(data, false, dev_mask);
if (ret < 0)
return ret;
break;
case IIO_PROXIMITY:
dev_mask = PA12203001_PX_EN_MASK;
ret = pa12203001_set_power_state(data, true, dev_mask);
if (ret < 0)
return ret;
ret = regmap_read(data->map, PA12203001_REG_PDH,
&reg_byte);
if (ret < 0)
goto reg_err;
*val = reg_byte;
ret = pa12203001_set_power_state(data, false, dev_mask);
if (ret < 0)
return ret;
break;
default:
return -EINVAL;
}
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte);
if (ret < 0)
return ret;
*val = 0;
reg_byte = (reg_byte & PA12203001_AFSR_MASK);
*val2 = pa12203001_scales[reg_byte >> 4];
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
reg_err:
pa12203001_set_power_state(data, false, dev_mask);
return ret;
}
static int pa12203001_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val,
int val2, long mask)
{
struct pa12203001_data *data = iio_priv(indio_dev);
int i, ret, new_val;
unsigned int reg_byte;
switch (mask) {
case IIO_CHAN_INFO_SCALE:
ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte);
if (val != 0 || ret < 0)
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(pa12203001_scales); i++) {
if (val2 == pa12203001_scales[i]) {
new_val = i << PA12203001_AFSR_SHIFT;
return regmap_update_bits(data->map,
PA12203001_REG_CFG0,
PA12203001_AFSR_MASK,
new_val);
}
}
break;
default:
break;
}
return -EINVAL;
}
static const struct iio_info pa12203001_info = {
.driver_module = THIS_MODULE,
.read_raw = pa12203001_read_raw,
.write_raw = pa12203001_write_raw,
.attrs = &pa12203001_attr_group,
};
static int pa12203001_init(struct iio_dev *indio_dev)
{
struct pa12203001_data *data = iio_priv(indio_dev);
int i, ret;
for (i = 0; i < ARRAY_SIZE(regvals); i++) {
ret = regmap_write(data->map, regvals[i].reg, regvals[i].val);
if (ret < 0)
return ret;
}
return 0;
}
static int pa12203001_power_chip(struct iio_dev *indio_dev, u8 state)
{
struct pa12203001_data *data = iio_priv(indio_dev);
int ret;
mutex_lock(&data->lock);
ret = pa12203001_als_enable(data, state);
if (ret < 0)
goto out;
ret = pa12203001_px_enable(data, state);
out:
mutex_unlock(&data->lock);
return ret;
}
static int pa12203001_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pa12203001_data *data;
struct iio_dev *indio_dev;
int ret;
indio_dev = devm_iio_device_alloc(&client->dev,
sizeof(struct pa12203001_data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
data->map = devm_regmap_init_i2c(client, &pa12203001_regmap_config);
if (IS_ERR(data->map))
return PTR_ERR(data->map);
mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev;
indio_dev->info = &pa12203001_info;
indio_dev->name = PA12203001_DRIVER_NAME;
indio_dev->channels = pa12203001_channels;
indio_dev->num_channels = ARRAY_SIZE(pa12203001_channels);
indio_dev->modes = INDIO_DIRECT_MODE;
ret = pa12203001_init(indio_dev);
if (ret < 0)
return ret;
ret = pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
if (ret < 0)
return ret;
ret = pm_runtime_set_active(&client->dev);
if (ret < 0) {
pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
return ret;
}
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);
}
static int pa12203001_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);
return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
}
#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM)
static int pa12203001_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
}
#endif
#ifdef CONFIG_PM_SLEEP
static int pa12203001_resume(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
return pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
}
#endif
#ifdef CONFIG_PM
static int pa12203001_runtime_resume(struct device *dev)
{
struct pa12203001_data *data;
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
mutex_lock(&data->lock);
if (data->als_needs_enable) {
pa12203001_als_enable(data, PA12203001_ALS_EN_MASK);
data->als_needs_enable = false;
}
if (data->px_needs_enable) {
pa12203001_px_enable(data, PA12203001_PX_EN_MASK);
data->px_needs_enable = false;
}
mutex_unlock(&data->lock);
return 0;
}
#endif
static const struct dev_pm_ops pa12203001_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pa12203001_suspend, pa12203001_resume)
SET_RUNTIME_PM_OPS(pa12203001_suspend, pa12203001_runtime_resume, NULL)
};
static const struct acpi_device_id pa12203001_acpi_match[] = {
{ "TXCPA122", 0},
{}
};
MODULE_DEVICE_TABLE(acpi, pa12203001_acpi_match);
static const struct i2c_device_id pa12203001_id[] = {
{"txcpa122", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, pa12203001_id);
static struct i2c_driver pa12203001_driver = {
.driver = {
.name = PA12203001_DRIVER_NAME,
.pm = &pa12203001_pm_ops,
.acpi_match_table = ACPI_PTR(pa12203001_acpi_match),
},
.probe = pa12203001_probe,
.remove = pa12203001_remove,
.id_table = pa12203001_id,
};
module_i2c_driver(pa12203001_driver);
MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
MODULE_DESCRIPTION("Driver for TXC PA12203001 Proximity and Light Sensor");
MODULE_LICENSE("GPL v2");
......@@ -676,6 +676,7 @@ static const struct i2c_device_id stk3310_i2c_id[] = {
{"STK3311", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, stk3310_i2c_id);
static const struct acpi_device_id stk3310_acpi_id[] = {
{"STK3310", 0},
......
......@@ -85,6 +85,7 @@
#define BMC150_MAGN_REG_HIGH_THRESH 0x50
#define BMC150_MAGN_REG_REP_XY 0x51
#define BMC150_MAGN_REG_REP_Z 0x52
#define BMC150_MAGN_REG_REP_DATAMASK GENMASK(7, 0)
#define BMC150_MAGN_REG_TRIM_START 0x5D
#define BMC150_MAGN_REG_TRIM_END 0x71
......@@ -559,7 +560,7 @@ static int bmc150_magn_write_raw(struct iio_dev *indio_dev,
}
ret = regmap_update_bits(data->regmap,
BMC150_MAGN_REG_REP_XY,
0xFF,
BMC150_MAGN_REG_REP_DATAMASK,
BMC150_MAGN_REPXY_TO_REGVAL
(val));
mutex_unlock(&data->mutex);
......@@ -575,7 +576,7 @@ static int bmc150_magn_write_raw(struct iio_dev *indio_dev,
}
ret = regmap_update_bits(data->regmap,
BMC150_MAGN_REG_REP_Z,
0xFF,
BMC150_MAGN_REG_REP_DATAMASK,
BMC150_MAGN_REPZ_TO_REGVAL
(val));
mutex_unlock(&data->mutex);
......@@ -651,7 +652,9 @@ static const struct iio_info bmc150_magn_info = {
.driver_module = THIS_MODULE,
};
static const unsigned long bmc150_magn_scan_masks[] = {0x07, 0};
static const unsigned long bmc150_magn_scan_masks[] = {
BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
0};
static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p)
{
......@@ -662,7 +665,6 @@ static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p)
mutex_lock(&data->mutex);
ret = bmc150_magn_read_xyz(data, data->buffer);
mutex_unlock(&data->mutex);
if (ret < 0)
goto err;
......@@ -670,6 +672,7 @@ static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p)
pf->timestamp);
err:
mutex_unlock(&data->mutex);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
......@@ -781,29 +784,23 @@ static int bmc150_magn_data_rdy_trigger_set_state(struct iio_trigger *trig,
if (state == data->dready_trigger_on)
goto err_unlock;
ret = bmc150_magn_set_power_state(data, state);
if (ret < 0)
goto err_unlock;
ret = regmap_update_bits(data->regmap, BMC150_MAGN_REG_INT_DRDY,
BMC150_MAGN_MASK_DRDY_EN,
state << BMC150_MAGN_SHIFT_DRDY_EN);
if (ret < 0)
goto err_poweroff;
goto err_unlock;
data->dready_trigger_on = state;
if (state) {
ret = bmc150_magn_reset_intr(data);
if (ret < 0)
goto err_poweroff;
goto err_unlock;
}
mutex_unlock(&data->mutex);
return 0;
err_poweroff:
bmc150_magn_set_power_state(data, false);
err_unlock:
mutex_unlock(&data->mutex);
return ret;
......@@ -1041,6 +1038,9 @@ static int bmc150_magn_runtime_suspend(struct device *dev)
return 0;
}
/*
* Should be called with data->mutex held.
*/
static int bmc150_magn_runtime_resume(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
......
......@@ -316,31 +316,31 @@ static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3])
static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index,
__le16 buf[], int *val)
{
int raw_x, raw_y, raw_z;
int sens_x, sens_y, sens_z;
int raw[3];
int sens[3];
int nfo;
raw_x = le16_to_cpu(buf[AXIS_X]);
raw_y = le16_to_cpu(buf[AXIS_Y]);
raw_z = le16_to_cpu(buf[AXIS_Z]);
raw[AXIS_X] = le16_to_cpu(buf[AXIS_X]);
raw[AXIS_Y] = le16_to_cpu(buf[AXIS_Y]);
raw[AXIS_Z] = le16_to_cpu(buf[AXIS_Z]);
sens_x = mmc35240_props_table[data->res].sens[AXIS_X];
sens_y = mmc35240_props_table[data->res].sens[AXIS_Y];
sens_z = mmc35240_props_table[data->res].sens[AXIS_Z];
sens[AXIS_X] = mmc35240_props_table[data->res].sens[AXIS_X];
sens[AXIS_Y] = mmc35240_props_table[data->res].sens[AXIS_Y];
sens[AXIS_Z] = mmc35240_props_table[data->res].sens[AXIS_Z];
nfo = mmc35240_props_table[data->res].nfo;
switch (index) {
case AXIS_X:
*val = (raw_x - nfo) * 1000 / sens_x;
*val = (raw[AXIS_X] - nfo) * 1000 / sens[AXIS_X];
break;
case AXIS_Y:
*val = (raw_y - nfo) * 1000 / sens_y -
(raw_z - nfo) * 1000 / sens_z;
*val = (raw[AXIS_Y] - nfo) * 1000 / sens[AXIS_Y] -
(raw[AXIS_Z] - nfo) * 1000 / sens[AXIS_Z];
break;
case AXIS_Z:
*val = (raw_y - nfo) * 1000 / sens_y +
(raw_z - nfo) * 1000 / sens_z;
*val = (raw[AXIS_Y] - nfo) * 1000 / sens[AXIS_Y] +
(raw[AXIS_Z] - nfo) * 1000 / sens[AXIS_Z];
break;
default:
return -EINVAL;
......@@ -559,6 +559,12 @@ static const struct dev_pm_ops mmc35240_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(mmc35240_suspend, mmc35240_resume)
};
static const struct of_device_id mmc35240_of_match[] = {
{ .compatible = "memsic,mmc35240", },
{ }
};
MODULE_DEVICE_TABLE(of, mmc35240_of_match);
static const struct acpi_device_id mmc35240_acpi_match[] = {
{"MMC35240", 0},
{ },
......@@ -574,6 +580,7 @@ MODULE_DEVICE_TABLE(i2c, mmc35240_id);
static struct i2c_driver mmc35240_driver = {
.driver = {
.name = MMC35240_DRV_NAME,
.of_match_table = mmc35240_of_match,
.pm = &mmc35240_pm_ops,
.acpi_match_table = ACPI_PTR(mmc35240_acpi_match),
},
......
......@@ -18,6 +18,7 @@
#define LSM303DLHC_MAGN_DEV_NAME "lsm303dlhc_magn"
#define LSM303DLM_MAGN_DEV_NAME "lsm303dlm_magn"
#define LIS3MDL_MAGN_DEV_NAME "lis3mdl"
#define LSM303AGR_MAGN_DEV_NAME "lsm303agr_magn"
int st_magn_common_probe(struct iio_dev *indio_dev);
void st_magn_common_remove(struct iio_dev *indio_dev);
......@@ -25,6 +26,8 @@ void st_magn_common_remove(struct iio_dev *indio_dev);
#ifdef CONFIG_IIO_BUFFER
int st_magn_allocate_ring(struct iio_dev *indio_dev);
void st_magn_deallocate_ring(struct iio_dev *indio_dev);
int st_magn_trig_set_state(struct iio_trigger *trig, bool state);
#define ST_MAGN_TRIGGER_SET_STATE (&st_magn_trig_set_state)
#else /* CONFIG_IIO_BUFFER */
static inline int st_magn_probe_trigger(struct iio_dev *indio_dev, int irq)
{
......
......@@ -23,6 +23,13 @@
#include <linux/iio/common/st_sensors.h>
#include "st_magn.h"
int st_magn_trig_set_state(struct iio_trigger *trig, bool state)
{
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
return st_sensors_set_dataready_irq(indio_dev, state);
}
static int st_magn_buffer_preenable(struct iio_dev *indio_dev)
{
return st_sensors_set_enable(indio_dev, true);
......
......@@ -43,6 +43,7 @@
#define ST_MAGN_FS_AVL_8000MG 8000
#define ST_MAGN_FS_AVL_8100MG 8100
#define ST_MAGN_FS_AVL_12000MG 12000
#define ST_MAGN_FS_AVL_15000MG 15000
#define ST_MAGN_FS_AVL_16000MG 16000
/* CUSTOM VALUES FOR SENSOR 0 */
......@@ -157,6 +158,29 @@
#define ST_MAGN_2_OUT_Y_L_ADDR 0x2a
#define ST_MAGN_2_OUT_Z_L_ADDR 0x2c
/* CUSTOM VALUES FOR SENSOR 3 */
#define ST_MAGN_3_WAI_ADDR 0x4f
#define ST_MAGN_3_WAI_EXP 0x40
#define ST_MAGN_3_ODR_ADDR 0x60
#define ST_MAGN_3_ODR_MASK 0x0c
#define ST_MAGN_3_ODR_AVL_10HZ_VAL 0x00
#define ST_MAGN_3_ODR_AVL_20HZ_VAL 0x01
#define ST_MAGN_3_ODR_AVL_50HZ_VAL 0x02
#define ST_MAGN_3_ODR_AVL_100HZ_VAL 0x03
#define ST_MAGN_3_PW_ADDR 0x60
#define ST_MAGN_3_PW_MASK 0x03
#define ST_MAGN_3_PW_ON 0x00
#define ST_MAGN_3_PW_OFF 0x03
#define ST_MAGN_3_BDU_ADDR 0x62
#define ST_MAGN_3_BDU_MASK 0x10
#define ST_MAGN_3_DRDY_IRQ_ADDR 0x62
#define ST_MAGN_3_DRDY_INT_MASK 0x01
#define ST_MAGN_3_FS_AVL_15000_GAIN 1500
#define ST_MAGN_3_MULTIREAD_BIT false
#define ST_MAGN_3_OUT_X_L_ADDR 0x68
#define ST_MAGN_3_OUT_Y_L_ADDR 0x6a
#define ST_MAGN_3_OUT_Z_L_ADDR 0x6c
static const struct iio_chan_spec st_magn_16bit_channels[] = {
ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
......@@ -189,9 +213,26 @@ static const struct iio_chan_spec st_magn_2_16bit_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(3)
};
static const struct iio_chan_spec st_magn_3_16bit_channels[] = {
ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
ST_MAGN_3_OUT_X_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
ST_MAGN_3_OUT_Y_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
ST_MAGN_3_OUT_Z_L_ADDR),
IIO_CHAN_SOFT_TIMESTAMP(3)
};
static const struct st_sensor_settings st_magn_sensors_settings[] = {
{
.wai = 0, /* This sensor has no valid WhoAmI report 0 */
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LSM303DLH_MAGN_DEV_NAME,
},
......@@ -268,6 +309,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
},
{
.wai = ST_MAGN_1_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LSM303DLHC_MAGN_DEV_NAME,
[1] = LSM303DLM_MAGN_DEV_NAME,
......@@ -346,6 +388,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
},
{
.wai = ST_MAGN_2_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LIS3MDL_MAGN_DEV_NAME,
},
......@@ -399,6 +442,48 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
.multi_read_bit = ST_MAGN_2_MULTIREAD_BIT,
.bootime = 2,
},
{
.wai = ST_MAGN_3_WAI_EXP,
.wai_addr = ST_MAGN_3_WAI_ADDR,
.sensors_supported = {
[0] = LSM303AGR_MAGN_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_magn_3_16bit_channels,
.odr = {
.addr = ST_MAGN_3_ODR_ADDR,
.mask = ST_MAGN_3_ODR_MASK,
.odr_avl = {
{ 10, ST_MAGN_3_ODR_AVL_10HZ_VAL, },
{ 20, ST_MAGN_3_ODR_AVL_20HZ_VAL, },
{ 50, ST_MAGN_3_ODR_AVL_50HZ_VAL, },
{ 100, ST_MAGN_3_ODR_AVL_100HZ_VAL, },
},
},
.pw = {
.addr = ST_MAGN_3_PW_ADDR,
.mask = ST_MAGN_3_PW_MASK,
.value_on = ST_MAGN_3_PW_ON,
.value_off = ST_MAGN_3_PW_OFF,
},
.fs = {
.fs_avl = {
[0] = {
.num = ST_MAGN_FS_AVL_15000MG,
.gain = ST_MAGN_3_FS_AVL_15000_GAIN,
},
},
},
.bdu = {
.addr = ST_MAGN_3_BDU_ADDR,
.mask = ST_MAGN_3_BDU_MASK,
},
.drdy_irq = {
.addr = ST_MAGN_3_DRDY_IRQ_ADDR,
.mask_int1 = ST_MAGN_3_DRDY_INT_MASK,
},
.multi_read_bit = ST_MAGN_3_MULTIREAD_BIT,
.bootime = 2,
},
};
static int st_magn_read_raw(struct iio_dev *indio_dev,
......@@ -477,6 +562,16 @@ static const struct iio_info magn_info = {
.write_raw = &st_magn_write_raw,
};
#ifdef CONFIG_IIO_TRIGGER
static const struct iio_trigger_ops st_magn_trigger_ops = {
.owner = THIS_MODULE,
.set_trigger_state = ST_MAGN_TRIGGER_SET_STATE,
};
#define ST_MAGN_TRIGGER_OPS (&st_magn_trigger_ops)
#else
#define ST_MAGN_TRIGGER_OPS NULL
#endif
int st_magn_common_probe(struct iio_dev *indio_dev)
{
struct st_sensor_data *mdata = iio_priv(indio_dev);
......@@ -513,7 +608,8 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
return err;
if (irq > 0) {
err = st_sensors_allocate_trigger(indio_dev, NULL);
err = st_sensors_allocate_trigger(indio_dev,
ST_MAGN_TRIGGER_OPS);
if (err < 0)
goto st_magn_probe_trigger_error;
}
......
......@@ -36,6 +36,10 @@ static const struct of_device_id st_magn_of_match[] = {
.compatible = "st,lis3mdl-magn",
.data = LIS3MDL_MAGN_DEV_NAME,
},
{
.compatible = "st,lsm303agr-magn",
.data = LSM303AGR_MAGN_DEV_NAME,
},
{},
};
MODULE_DEVICE_TABLE(of, st_magn_of_match);
......@@ -79,6 +83,7 @@ static const struct i2c_device_id st_magn_id_table[] = {
{ LSM303DLHC_MAGN_DEV_NAME },
{ LSM303DLM_MAGN_DEV_NAME },
{ LIS3MDL_MAGN_DEV_NAME },
{ LSM303AGR_MAGN_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(i2c, st_magn_id_table);
......
......@@ -51,6 +51,7 @@ static const struct spi_device_id st_magn_id_table[] = {
{ LSM303DLHC_MAGN_DEV_NAME },
{ LSM303DLM_MAGN_DEV_NAME },
{ LIS3MDL_MAGN_DEV_NAME },
{ LSM303AGR_MAGN_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(spi, st_magn_id_table);
......
......@@ -178,6 +178,7 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = {
static const struct st_sensor_settings st_press_sensors_settings[] = {
{
.wai = ST_PRESS_LPS331AP_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LPS331AP_PRESS_DEV_NAME,
},
......@@ -225,6 +226,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
},
{
.wai = ST_PRESS_LPS001WP_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LPS001WP_PRESS_DEV_NAME,
},
......@@ -260,6 +262,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
},
{
.wai = ST_PRESS_LPS25H_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LPS25H_PRESS_DEV_NAME,
},
......
......@@ -65,6 +65,13 @@
#define MLX90614_AUTOSLEEP_DELAY 5000 /* default autosleep delay */
/* Magic constants */
#define MLX90614_CONST_OFFSET_DEC -13657 /* decimal part of the Kelvin offset */
#define MLX90614_CONST_OFFSET_REM 500000 /* remainder of offset (273.15*50) */
#define MLX90614_CONST_SCALE 20 /* Scale in milliKelvin (0.02 * 1000) */
#define MLX90614_CONST_RAW_EMISSIVITY_MAX 65535 /* max value for emissivity */
#define MLX90614_CONST_EMISSIVITY_RESOLUTION 15259 /* 1/65535 ~ 0.000015259 */
struct mlx90614_data {
struct i2c_client *client;
struct mutex lock; /* for EEPROM access only */
......@@ -204,11 +211,11 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev,
*val = ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_OFFSET:
*val = -13657;
*val2 = 500000;
*val = MLX90614_CONST_OFFSET_DEC;
*val2 = MLX90614_CONST_OFFSET_REM;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SCALE:
*val = 20;
*val = MLX90614_CONST_SCALE;
return IIO_VAL_INT;
case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
mlx90614_power_get(data, false);
......@@ -221,12 +228,12 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
if (ret == 65535) {
if (ret == MLX90614_CONST_RAW_EMISSIVITY_MAX) {
*val = 1;
*val2 = 0;
} else {
*val = 0;
*val2 = ret * 15259; /* 1/65535 ~ 0.000015259 */
*val2 = ret * MLX90614_CONST_EMISSIVITY_RESOLUTION;
}
return IIO_VAL_INT_PLUS_NANO;
default:
......@@ -245,7 +252,8 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
if (val < 0 || val2 < 0 || val > 1 || (val == 1 && val2 != 0))
return -EINVAL;
val = val * 65535 + val2 / 15259; /* 1/65535 ~ 0.000015259 */
val = val * MLX90614_CONST_RAW_EMISSIVITY_MAX +
val2 / MLX90614_CONST_EMISSIVITY_RESOLUTION;
mlx90614_power_get(data, false);
mutex_lock(&data->lock);
......
此差异已折叠。
......@@ -166,6 +166,7 @@ struct st_sensor_transfer_function {
/**
* struct st_sensor_settings - ST specific sensor settings
* @wai: Contents of WhoAmI register.
* @wai_addr: The address of WhoAmI register.
* @sensors_supported: List of supported sensors by struct itself.
* @ch: IIO channels for the sensor.
* @odr: Output data rate register and ODR list available.
......@@ -179,6 +180,7 @@ struct st_sensor_transfer_function {
*/
struct st_sensor_settings {
u8 wai;
u8 wai_addr;
char sensors_supported[ST_SENSORS_MAX_4WAI][ST_SENSORS_MAX_NAME];
struct iio_chan_spec *ch;
int num_ch;
......
......@@ -100,7 +100,7 @@ void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff);
/**
* iio_channel_cb_get_channels() - get access to the underlying channels.
* @cb_buff: The callback buffer from whom we want the channel
* @cb_buffer: The callback buffer from whom we want the channel
* information.
*
* This function allows one to obtain information about the channels.
......
......@@ -644,6 +644,15 @@ int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer,
*/
#define IIO_DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL)
/**
* IIO_RAD_TO_DEGREE() - Convert rad to degree
* @rad: A value in rad
*
* Returns the given value converted from rad to degree
*/
#define IIO_RAD_TO_DEGREE(rad) \
(((rad) * 18000000ULL + 314159ULL / 2) / 314159ULL)
/**
* IIO_G_TO_M_S_2() - Convert g to meter / second**2
* @g: A value in g
......@@ -652,4 +661,12 @@ int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer,
*/
#define IIO_G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL)
/**
* IIO_M_S_2_TO_G() - Convert meter / second**2 to g
* @ms2: A value in meter / second**2
*
* Returns the given value converted from meter / second**2 to g
*/
#define IIO_M_S_2_TO_G(ms2) (((ms2) * 100000ULL + 980665ULL / 2) / 980665ULL)
#endif /* _INDUSTRIAL_IO_H_ */
......@@ -18,7 +18,8 @@ struct iio_chan_spec;
* struct iio_dev_attr - iio specific device attribute
* @dev_attr: underlying device attribute
* @address: associated register address
* @l: list head for maintaining list of dynamically created attrs.
* @l: list head for maintaining list of dynamically created attrs
* @c: specification for the underlying channel
*/
struct iio_dev_attr {
struct device_attribute dev_attr;
......
......@@ -18,6 +18,9 @@ struct iio_subirq {
bool enabled;
};
struct iio_dev;
struct iio_trigger;
/**
* struct iio_trigger_ops - operations structure for an iio_trigger.
* @owner: used to monitor usage count of the trigger.
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -18,6 +18,8 @@
#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
#define FORMAT_TYPE_FILE "%s_type"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
extern const char *iio_dir;
/**
......@@ -58,7 +60,7 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
int iioutils_get_param_float(float *output, const char *param_name,
const char *device_dir, const char *name,
const char *generic_name);
void bsort_channel_array_by_index(struct iio_channel_info **ci_array, int cnt);
void bsort_channel_array_by_index(struct iio_channel_info *ci_array, int cnt);
int build_channel_array(const char *device_dir,
struct iio_channel_info **ci_array, int *counter);
int find_type_by_name(const char *name, const char *type);
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册