Commit 98c2f10d authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

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

Jonathan writes:

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

4 completely new drivers in this set and plenty of other stuff.

One ABI change due to a silly mistake a long time back. Hopefully no
one will notice.  It effects the numerical order of consumer device
channels which was the reverse of the obvious.  It's going the slow
way to allow us some margin to spot if we have broken userspace or
not (seems unlikely)

New Device Support
* ccs811
  - new driver for the Volatile Organic Compounds (VOC) sensor.
* dln2 adc
  - new driver for the ADC on this flexible usb board.
* EP93xx
  - new driver for this Cirrus logic SoC ADC.
* ltc2471
  - new ADC driver support the ltc2471 and ltc2473
* st_accel
  - add trivial table entries to support H3LIS331DL, LIS331DL, LIS3LV02DL.
* st_gyro
  - add L3GD20H support (again) having fixed the various things that were
    broken in the first try.  Includes devicetree binding.
* stm32 dac
  - add support for the DACs in the STM32F4 series

Features
* Documentation
  - add missing power attribute documentation to the ABI docs.
* at91-sama5d2
  - add hardware trigger and buffered capture support with bindings.
  - suspend and resume functionality.
* bmc150
  - support for the BOSC0200 ACPI device id seen on some tablets.
* hdc100x
  - devicetree bindings
  - document supported devices
  - match table and device ids.
* hts221
  - support active low interrupts (with bindings)
  - open drain mode with bindings.
* htu21
  - OF match table and bindings.
* lsm6dsx
  - open drain mode with bindings
* ltc2497
  - add support for board file based consumer mapping.
* ms5367
  - OF match table and bindings.
* mt7622
  - binding document and OF match table.
  - suspend and resume support.
* rpr0521
  - triggered buffer support.
* tsys01
  - OF match table and bindings.

Cleanups and minor fixes
* core
  - fix ordering of IIO channels to entry numbers when using
    iio_map_array_register rather than reversing them.
  - use the new %pOF format specifier rather than full name for the
    device tree nodes.
* ad7280a
  - fix potential issue with macro argument reuse.
* ad7766
  - drop a pointless NULL value check as it's done in the gpiod code.
* adis16400
  - unsigned -> unsigned int.
* at91 adc
  - make some init data static to reduce code size.
* at91-sama5d2 ADC
  - make some init data static to reduce code size.
* da311
  - make some init data static to reduce code size.
* hid-sensor-rotation
  - drop an unnecessary static.
* hts221
  - refactor the write_with_mask code.
  - move the BDU configuration to probe time as there is no reason for it
    to change.
  - avoid overwriting reserved data during power-down.  This is a fix, but
    the infrastructure need was too invasive to send it to mainline except
    in a merge window.  It's not a regression as it was always wrong.
  - avoid reconfigure the sampling frequency multiple times by just
    doing it in the write_raw function directly.
  - refactor the power_on/off calls into a set_enable.
  - move the dry-enable logic into trig_set_state as that is the only
    place it was used.
* ina219
  - fix polling of ina226 conversion ready flag.
* imx7d
  - add vendor name in kconfig for consistency with similar parts.
* mcp3422
  - Change initial channel to 0 as it feels more logical.
  - Check for some errors in probe.
* meson-saradc
  - add a check of of_match_device return value.
* mpu3050
  - allow open drain for any interrupt type.
* rockchip adc
  - add check on of_match_device return value.
* sca3000
  - drop a trailing whitespace.
* stm32 adc
  - make array stm32h7_adc_ckmodes_spec static.
* stm32 dac
  - fix an error message.
* stm32 timers
  - fix clock name in docs to match reality after changes.
* st_accel
  - explicit OF table (spi).
  - add missing entries to OF table (i2c).
  - rename of_device_id table to drop the part name.
  - adding missing lis3l02dq entry to bindings.
  - rename H3LIS331DL_DRIVER_NAME to line up with similar entries in driver.
* st_gyro
  - explicit OF table (spi).
* st_magn
  - explicit OF table (spi).
  - enable multiread for lis3mdl.
* st_pressure
  - explicit OF table (spi).
* st_sensors common.
  - move st_sensors_of_i2c_probe and rename to make it available for spi
  drivers.
* tsc3472
  - don't write an extra byte when writing the ATIME register.
  - add a link to the datasheet.
* tsl2x7x - continued staging cleanups
  - add of_match_table.
  - drop redundant power_state sysfs attribute.
  - drop wrapper tsl2x7x_i2c_read.
  - clean up i2c calls made in tsl2x7x_als_calibrate.
  - refactor the read and write _event_value callbacks to handle additional
    elements.
  - use usleep_range instead of mdelay.
  - check return value from tsl2x7x_invoke_change.
* zpa2326
  - add some newline to the end of logging macros.
parents a29e2490 f3f0ae16
...@@ -119,6 +119,15 @@ Description: ...@@ -119,6 +119,15 @@ Description:
unique to allow association with event codes. Units after unique to allow association with event codes. Units after
application of scale and offset are milliamps. application of scale and offset are milliamps.
What: /sys/bus/iio/devices/iio:deviceX/in_powerY_raw
KernelVersion: 4.5
Contact: linux-iio@vger.kernel.org
Description:
Raw (unscaled no bias removal etc.) power measurement from
channel Y. The number must always be specified and
unique to allow association with event codes. Units after
application of scale and offset are milliwatts.
What: /sys/bus/iio/devices/iio:deviceX/in_capacitanceY_raw What: /sys/bus/iio/devices/iio:deviceX/in_capacitanceY_raw
KernelVersion: 3.2 KernelVersion: 3.2
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
......
...@@ -11,6 +11,11 @@ Required properties: ...@@ -11,6 +11,11 @@ Required properties:
- atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC. - atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC.
- atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC. - atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC.
- atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC. - atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC.
- atmel,trigger-edge-type: One of possible edge types for the ADTRG hardware
trigger pin. When the specific edge type is detected, the conversion will
start. Possible values are rising, falling, or both.
This property uses the IRQ edge types values: IRQ_TYPE_EDGE_RISING ,
IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH
Example: Example:
...@@ -25,4 +30,5 @@ adc: adc@fc030000 { ...@@ -25,4 +30,5 @@ adc: adc@fc030000 {
atmel,startup-time-ms = <4>; atmel,startup-time-ms = <4>;
vddana-supply = <&vdd_3v3_lp_reg>; vddana-supply = <&vdd_3v3_lp_reg>;
vref-supply = <&vdd_3v3_lp_reg>; vref-supply = <&vdd_3v3_lp_reg>;
atmel,trigger-edge-type = <IRQ_TYPE_EDGE_BOTH>;
} }
...@@ -12,6 +12,7 @@ for the Thermal Controller which holds a phandle to the AUXADC. ...@@ -12,6 +12,7 @@ for the Thermal Controller which holds a phandle to the AUXADC.
Required properties: Required properties:
- compatible: Should be one of: - compatible: Should be one of:
- "mediatek,mt2701-auxadc": For MT2701 family of SoCs - "mediatek,mt2701-auxadc": For MT2701 family of SoCs
- "mediatek,mt7622-auxadc": For MT7622 family of SoCs
- "mediatek,mt8173-auxadc": For MT8173 family of SoCs - "mediatek,mt8173-auxadc": For MT8173 family of SoCs
- reg: Address range of the AUXADC unit. - reg: Address range of the AUXADC unit.
- clocks: Should contain a clock specifier for each entry in clock-names - clocks: Should contain a clock specifier for each entry in clock-names
......
...@@ -10,7 +10,9 @@ current. ...@@ -10,7 +10,9 @@ current.
Contents of a stm32 dac root node: Contents of a stm32 dac root node:
----------------------------------- -----------------------------------
Required properties: Required properties:
- compatible: Must be "st,stm32h7-dac-core". - compatible: Should be one of:
"st,stm32f4-dac-core"
"st,stm32h7-dac-core"
- reg: Offset and length of the device's register set. - reg: Offset and length of the device's register set.
- clocks: Must contain an entry for pclk (which feeds the peripheral bus - clocks: Must contain an entry for pclk (which feeds the peripheral bus
interface) interface)
......
* HDC100x temperature + humidity sensors
Required properties:
- compatible: Should contain one of the following:
ti,hdc1000
ti,hdc1008
ti,hdc1010
ti,hdc1050
ti,hdc1080
- reg: i2c address of the sensor
Example:
hdc100x@40 {
compatible = "ti,hdc1000";
reg = <0x40>;
};
...@@ -5,9 +5,18 @@ Required properties: ...@@ -5,9 +5,18 @@ Required properties:
- reg: i2c address of the sensor / spi cs line - reg: i2c address of the sensor / spi cs line
Optional properties: Optional properties:
- drive-open-drain: the interrupt/data ready line will be configured
as open drain, which is useful if several sensors share the same
interrupt line. This is a boolean property.
If the requested interrupt is configured as IRQ_TYPE_LEVEL_HIGH or
IRQ_TYPE_EDGE_RISING a pull-down resistor is needed to drive the line
when it is not active, whereas a pull-up one is needed when interrupt
line is configured as IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_EDGE_FALLING.
Refer to pinctrl/pinctrl-bindings.txt for the property description.
- interrupt-parent: should be the phandle for the interrupt controller - interrupt-parent: should be the phandle for the interrupt controller
- interrupts: interrupt mapping for IRQ. It should be configured with - interrupts: interrupt mapping for IRQ. It should be configured with
flags IRQ_TYPE_LEVEL_HIGH or IRQ_TYPE_EDGE_RISING. flags IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_LEVEL_LOW or
IRQ_TYPE_EDGE_FALLING.
Refer to interrupt-controller/interrupts.txt for generic interrupt Refer to interrupt-controller/interrupts.txt for generic interrupt
client node bindings. client node bindings.
......
*HTU21 - Measurement-Specialties htu21 temperature & humidity sensor and humidity part of MS8607 sensor
Required properties:
- compatible: should be "meas,htu21" or "meas,ms8607-humidity"
- reg: I2C address of the sensor
Example:
htu21@40 {
compatible = "meas,htu21";
reg = <0x40>;
};
...@@ -11,6 +11,14 @@ Required properties: ...@@ -11,6 +11,14 @@ Required properties:
Optional properties: Optional properties:
- st,drdy-int-pin: the pin on the package that will be used to signal - st,drdy-int-pin: the pin on the package that will be used to signal
"data ready" (valid values: 1 or 2). "data ready" (valid values: 1 or 2).
- drive-open-drain: the interrupt/data ready line will be configured
as open drain, which is useful if several sensors share the same
interrupt line. This is a boolean property.
(This binding is taken from pinctrl/pinctrl-bindings.txt)
If the requested interrupt is configured as IRQ_TYPE_LEVEL_HIGH or
IRQ_TYPE_EDGE_RISING a pull-down resistor is needed to drive the line
when it is not active, whereas a pull-up one is needed when interrupt
line is configured as IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_EDGE_FALLING.
- interrupt-parent: should be the phandle for the interrupt controller - interrupt-parent: should be the phandle for the interrupt controller
- interrupts: interrupt mapping for IRQ. It should be configured with - interrupts: interrupt mapping for IRQ. It should be configured with
flags IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_LEVEL_LOW or flags IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_LEVEL_LOW or
......
* MS5637 - Measurement-Specialties MS5637, MS5805, MS5837 and MS8607 pressure & temperature sensor
Required properties:
-compatible: should be one of the following
meas,ms5637
meas,ms5805
meas,ms5837
meas,ms8607-temppressure
-reg: I2C address of the sensor
Example:
ms5637@76 {
compatible = "meas,ms5637";
reg = <0x76>;
};
...@@ -45,6 +45,7 @@ Accelerometers: ...@@ -45,6 +45,7 @@ Accelerometers:
- st,lis2dh12-accel - st,lis2dh12-accel
- st,h3lis331dl-accel - st,h3lis331dl-accel
- st,lng2dm-accel - st,lng2dm-accel
- st,lis3l02dq
Gyroscopes: Gyroscopes:
- st,l3g4200d-gyro - st,l3g4200d-gyro
...@@ -52,6 +53,7 @@ Gyroscopes: ...@@ -52,6 +53,7 @@ Gyroscopes:
- st,lsm330dl-gyro - st,lsm330dl-gyro
- st,lsm330dlc-gyro - st,lsm330dlc-gyro
- st,l3gd20-gyro - st,l3gd20-gyro
- st,l3gd20h-gyro
- st,l3g4is-gyro - st,l3g4is-gyro
- st,lsm330-gyro - st,lsm330-gyro
- st,lsm9ds0-gyro - st,lsm9ds0-gyro
......
* TSYS01 - Measurement Specialties temperature sensor
Required properties:
- compatible: should be "meas,tsys01"
- reg: I2C address of the sensor (changeable via CSB pin)
------------------------
| CSB | Device Address |
------------------------
1 0x76
0 0x77
Example:
tsys01@76 {
compatible = "meas,tsys01";
reg = <0x76>;
};
...@@ -14,7 +14,7 @@ Example: ...@@ -14,7 +14,7 @@ Example:
compatible = "st,stm32-timers"; compatible = "st,stm32-timers";
reg = <0x40010000 0x400>; reg = <0x40010000 0x400>;
clocks = <&rcc 0 160>; clocks = <&rcc 0 160>;
clock-names = "clk_int"; clock-names = "int";
timer@0 { timer@0 {
compatible = "st,stm32-timer-trigger"; compatible = "st,stm32-timer-trigger";
......
Cirrus Logic EP93xx ADC driver.
1. Overview
The driver is intended to work on both low-end (EP9301, EP9302) devices with
5-channel ADC and high-end (EP9307, EP9312, EP9315) devices with 10-channel
touchscreen/ADC module.
2. Channel numbering
Numbering scheme for channels 0..4 is defined in EP9301 and EP9302 datasheets.
EP9307, EP9312 and EP9312 have 3 channels more (total 8), but the numbering is
not defined. So the last three are numbered randomly, let's say.
Assuming ep93xx_adc is IIO device0, you'd find the following entries under
/sys/bus/iio/devices/iio:device0/:
+-----------------+---------------+
| sysfs entry | ball/pin name |
+-----------------+---------------+
| in_voltage0_raw | YM |
| in_voltage1_raw | SXP |
| in_voltage2_raw | SXM |
| in_voltage3_raw | SYP |
| in_voltage4_raw | SYM |
| in_voltage5_raw | XP |
| in_voltage6_raw | XM |
| in_voltage7_raw | YP |
+-----------------+---------------+
...@@ -64,6 +64,7 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = { ...@@ -64,6 +64,7 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = {
{"BMA250E", bma250e}, {"BMA250E", bma250e},
{"BMA222E", bma222e}, {"BMA222E", bma222e},
{"BMA0280", bma280}, {"BMA0280", bma280},
{"BOSC0200"},
{ }, { },
}; };
MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
......
...@@ -139,7 +139,7 @@ static int da311_register_mask_write(struct i2c_client *client, u16 addr, ...@@ -139,7 +139,7 @@ static int da311_register_mask_write(struct i2c_client *client, u16 addr,
/* Init sequence taken from the android driver */ /* Init sequence taken from the android driver */
static int da311_reset(struct i2c_client *client) static int da311_reset(struct i2c_client *client)
{ {
const struct { static const struct {
u16 addr; u16 addr;
u8 mask; u8 mask;
u8 data; u8 data;
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#define SCA3000_LOCKED BIT(5) #define SCA3000_LOCKED BIT(5)
#define SCA3000_EEPROM_CS_ERROR BIT(1) #define SCA3000_EEPROM_CS_ERROR BIT(1)
#define SCA3000_SPI_FRAME_ERROR BIT(0) #define SCA3000_SPI_FRAME_ERROR BIT(0)
/* All reads done using register decrement so no need to directly access LSBs */ /* All reads done using register decrement so no need to directly access LSBs */
#define SCA3000_REG_X_MSB_ADDR 0x05 #define SCA3000_REG_X_MSB_ADDR 0x05
#define SCA3000_REG_Y_MSB_ADDR 0x07 #define SCA3000_REG_Y_MSB_ADDR 0x07
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
#define SCA3000_REG_INT_STATUS_ADDR 0x16 #define SCA3000_REG_INT_STATUS_ADDR 0x16
#define SCA3000_REG_INT_STATUS_THREE_QUARTERS BIT(7) #define SCA3000_REG_INT_STATUS_THREE_QUARTERS BIT(7)
#define SCA3000_REG_INT_STATUS_HALF BIT(6) #define SCA3000_REG_INT_STATUS_HALF BIT(6)
#define SCA3000_INT_STATUS_FREE_FALL BIT(3) #define SCA3000_INT_STATUS_FREE_FALL BIT(3)
#define SCA3000_INT_STATUS_Y_TRIGGER BIT(2) #define SCA3000_INT_STATUS_Y_TRIGGER BIT(2)
#define SCA3000_INT_STATUS_X_TRIGGER BIT(1) #define SCA3000_INT_STATUS_X_TRIGGER BIT(1)
...@@ -124,7 +124,7 @@ ...@@ -124,7 +124,7 @@
#define SCA3000_REG_INT_MASK_ADDR 0x21 #define SCA3000_REG_INT_MASK_ADDR 0x21
#define SCA3000_REG_INT_MASK_PROT_MASK 0x1C #define SCA3000_REG_INT_MASK_PROT_MASK 0x1C
#define SCA3000_REG_INT_MASK_RING_THREE_QUARTER BIT(7) #define SCA3000_REG_INT_MASK_RING_THREE_QUARTER BIT(7)
#define SCA3000_REG_INT_MASK_RING_HALF BIT(6) #define SCA3000_REG_INT_MASK_RING_HALF BIT(6)
......
...@@ -29,10 +29,13 @@ enum st_accel_type { ...@@ -29,10 +29,13 @@ enum st_accel_type {
LIS2DH12, LIS2DH12,
LIS3L02DQ, LIS3L02DQ,
LNG2DM, LNG2DM,
H3LIS331DL,
LIS331DL,
LIS3LV02DL,
ST_ACCEL_MAX, ST_ACCEL_MAX,
}; };
#define H3LIS331DL_DRIVER_NAME "h3lis331dl_accel" #define H3LIS331DL_ACCEL_DEV_NAME "h3lis331dl_accel"
#define LIS3LV02DL_ACCEL_DEV_NAME "lis3lv02dl_accel" #define LIS3LV02DL_ACCEL_DEV_NAME "lis3lv02dl_accel"
#define LSM303DLHC_ACCEL_DEV_NAME "lsm303dlhc_accel" #define LSM303DLHC_ACCEL_DEV_NAME "lsm303dlhc_accel"
#define LIS3DH_ACCEL_DEV_NAME "lis3dh" #define LIS3DH_ACCEL_DEV_NAME "lis3dh"
......
...@@ -444,7 +444,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { ...@@ -444,7 +444,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.wai = 0x32, .wai = 0x32,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = { .sensors_supported = {
[0] = H3LIS331DL_DRIVER_NAME, [0] = H3LIS331DL_ACCEL_DEV_NAME,
}, },
.ch = (struct iio_chan_spec *)st_accel_12bit_channels, .ch = (struct iio_chan_spec *)st_accel_12bit_channels,
.odr = { .odr = {
......
...@@ -84,7 +84,7 @@ static const struct of_device_id st_accel_of_match[] = { ...@@ -84,7 +84,7 @@ static const struct of_device_id st_accel_of_match[] = {
}, },
{ {
.compatible = "st,h3lis331dl-accel", .compatible = "st,h3lis331dl-accel",
.data = H3LIS331DL_DRIVER_NAME, .data = H3LIS331DL_ACCEL_DEV_NAME,
}, },
{ {
.compatible = "st,lis3l02dq", .compatible = "st,lis3l02dq",
...@@ -126,6 +126,9 @@ static const struct i2c_device_id st_accel_id_table[] = { ...@@ -126,6 +126,9 @@ static const struct i2c_device_id st_accel_id_table[] = {
{ LIS2DH12_ACCEL_DEV_NAME, LIS2DH12 }, { LIS2DH12_ACCEL_DEV_NAME, LIS2DH12 },
{ LIS3L02DQ_ACCEL_DEV_NAME, LIS3L02DQ }, { LIS3L02DQ_ACCEL_DEV_NAME, LIS3L02DQ },
{ LNG2DM_ACCEL_DEV_NAME, LNG2DM }, { LNG2DM_ACCEL_DEV_NAME, LNG2DM },
{ H3LIS331DL_ACCEL_DEV_NAME, H3LIS331DL },
{ LIS331DL_ACCEL_DEV_NAME, LIS331DL },
{ LIS3LV02DL_ACCEL_DEV_NAME, LIS3LV02DL },
{}, {},
}; };
MODULE_DEVICE_TABLE(i2c, st_accel_id_table); MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
...@@ -144,7 +147,8 @@ static int st_accel_i2c_probe(struct i2c_client *client, ...@@ -144,7 +147,8 @@ static int st_accel_i2c_probe(struct i2c_client *client,
adata = iio_priv(indio_dev); adata = iio_priv(indio_dev);
if (client->dev.of_node) { if (client->dev.of_node) {
st_sensors_of_i2c_probe(client, st_accel_of_match); st_sensors_of_name_probe(&client->dev, st_accel_of_match,
client->name, sizeof(client->name));
} else if (ACPI_HANDLE(&client->dev)) { } else if (ACPI_HANDLE(&client->dev)) {
ret = st_sensors_match_acpi_device(&client->dev); ret = st_sensors_match_acpi_device(&client->dev);
if ((ret < 0) || (ret >= ST_ACCEL_MAX)) if ((ret < 0) || (ret >= ST_ACCEL_MAX))
......
...@@ -18,6 +18,77 @@ ...@@ -18,6 +18,77 @@
#include <linux/iio/common/st_sensors_spi.h> #include <linux/iio/common/st_sensors_spi.h>
#include "st_accel.h" #include "st_accel.h"
#ifdef CONFIG_OF
/*
* For new single-chip sensors use <device_name> as compatible string.
* For old single-chip devices keep <device_name>-accel to maintain
* compatibility
*/
static const struct of_device_id st_accel_of_match[] = {
{
/* An older compatible */
.compatible = "st,lis302dl-spi",
.data = LIS3LV02DL_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis3lv02dl-accel",
.data = LIS3LV02DL_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis3dh-accel",
.data = LIS3DH_ACCEL_DEV_NAME,
},
{
.compatible = "st,lsm330d-accel",
.data = LSM330D_ACCEL_DEV_NAME,
},
{
.compatible = "st,lsm330dl-accel",
.data = LSM330DL_ACCEL_DEV_NAME,
},
{
.compatible = "st,lsm330dlc-accel",
.data = LSM330DLC_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis331dlh-accel",
.data = LIS331DLH_ACCEL_DEV_NAME,
},
{
.compatible = "st,lsm330-accel",
.data = LSM330_ACCEL_DEV_NAME,
},
{
.compatible = "st,lsm303agr-accel",
.data = LSM303AGR_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis2dh12-accel",
.data = LIS2DH12_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis3l02dq",
.data = LIS3L02DQ_ACCEL_DEV_NAME,
},
{
.compatible = "st,lng2dm-accel",
.data = LNG2DM_ACCEL_DEV_NAME,
},
{
.compatible = "st,h3lis331dl-accel",
.data = H3LIS331DL_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis331dl-accel",
.data = LIS331DL_ACCEL_DEV_NAME,
},
{}
};
MODULE_DEVICE_TABLE(of, st_accel_of_match);
#else
#define st_accel_of_match NULL
#endif
static int st_accel_spi_probe(struct spi_device *spi) static int st_accel_spi_probe(struct spi_device *spi)
{ {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
...@@ -30,6 +101,8 @@ static int st_accel_spi_probe(struct spi_device *spi) ...@@ -30,6 +101,8 @@ static int st_accel_spi_probe(struct spi_device *spi)
adata = iio_priv(indio_dev); adata = iio_priv(indio_dev);
st_sensors_of_name_probe(&spi->dev, st_accel_of_match,
spi->modalias, sizeof(spi->modalias));
st_sensors_spi_configure(indio_dev, spi, adata); st_sensors_spi_configure(indio_dev, spi, adata);
err = st_accel_common_probe(indio_dev); err = st_accel_common_probe(indio_dev);
...@@ -57,22 +130,17 @@ static const struct spi_device_id st_accel_id_table[] = { ...@@ -57,22 +130,17 @@ static const struct spi_device_id st_accel_id_table[] = {
{ LIS2DH12_ACCEL_DEV_NAME }, { LIS2DH12_ACCEL_DEV_NAME },
{ LIS3L02DQ_ACCEL_DEV_NAME }, { LIS3L02DQ_ACCEL_DEV_NAME },
{ LNG2DM_ACCEL_DEV_NAME }, { LNG2DM_ACCEL_DEV_NAME },
{ H3LIS331DL_ACCEL_DEV_NAME },
{ LIS331DL_ACCEL_DEV_NAME },
{ LIS3LV02DL_ACCEL_DEV_NAME },
{}, {},
}; };
MODULE_DEVICE_TABLE(spi, st_accel_id_table); MODULE_DEVICE_TABLE(spi, st_accel_id_table);
#ifdef CONFIG_OF
static const struct of_device_id lis302dl_spi_dt_ids[] = {
{ .compatible = "st,lis302dl-spi" },
{}
};
MODULE_DEVICE_TABLE(of, lis302dl_spi_dt_ids);
#endif
static struct spi_driver st_accel_driver = { static struct spi_driver st_accel_driver = {
.driver = { .driver = {
.name = "st-accel-spi", .name = "st-accel-spi",
.of_match_table = of_match_ptr(lis302dl_spi_dt_ids), .of_match_table = of_match_ptr(st_accel_of_match),
}, },
.probe = st_accel_spi_probe, .probe = st_accel_spi_probe,
.remove = st_accel_spi_remove, .remove = st_accel_spi_remove,
......
...@@ -239,6 +239,15 @@ config DA9150_GPADC ...@@ -239,6 +239,15 @@ config DA9150_GPADC
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called berlin2-adc. called berlin2-adc.
config DLN2_ADC
tristate "Diolan DLN-2 ADC driver support"
depends on MFD_DLN2
help
Say yes here to build support for Diolan DLN-2 ADC.
This driver can also be built as a module. If so, the module will be
called adc_dln2.
config ENVELOPE_DETECTOR config ENVELOPE_DETECTOR
tristate "Envelope detector using a DAC and a comparator" tristate "Envelope detector using a DAC and a comparator"
depends on OF depends on OF
...@@ -249,6 +258,17 @@ config ENVELOPE_DETECTOR ...@@ -249,6 +258,17 @@ config ENVELOPE_DETECTOR
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called envelope-detector. called envelope-detector.
config EP93XX_ADC
tristate "Cirrus Logic EP93XX ADC driver"
depends on ARCH_EP93XX
help
Driver for the ADC module on the EP93XX series of SoC from Cirrus Logic.
It's recommended to switch on CONFIG_HIGH_RES_TIMERS option, in this
case driver will reduce its CPU usage by 90% in some use cases.
To compile this driver as a module, choose M here: the module will be
called ep93xx_adc.
config EXYNOS_ADC config EXYNOS_ADC
tristate "Exynos ADC driver support" tristate "Exynos ADC driver support"
depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST) depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
...@@ -322,7 +342,7 @@ config INA2XX_ADC ...@@ -322,7 +342,7 @@ config INA2XX_ADC
This driver is mutually exclusive with the HWMON version. This driver is mutually exclusive with the HWMON version.
config IMX7D_ADC config IMX7D_ADC
tristate "IMX7D ADC driver" tristate "Freescale IMX7D ADC driver"
depends on ARCH_MXC || COMPILE_TEST depends on ARCH_MXC || COMPILE_TEST
depends on HAS_IOMEM depends on HAS_IOMEM
help help
...@@ -362,6 +382,16 @@ config LPC32XX_ADC ...@@ -362,6 +382,16 @@ config LPC32XX_ADC
activate only one via device tree selection. Provides direct access activate only one via device tree selection. Provides direct access
via sysfs. via sysfs.
config LTC2471
tristate "Linear Technology LTC2471 and LTC2473 ADC driver"
depends on I2C
help
Say yes here to build support for Linear Technology LTC2471 and
LTC2473 16-bit I2C ADC.
This driver can also be built as a module. If so, the module will
be called ltc2471.
config LTC2485 config LTC2485
tristate "Linear Technology LTC2485 ADC driver" tristate "Linear Technology LTC2485 ADC driver"
depends on I2C depends on I2C
......
...@@ -24,7 +24,9 @@ obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o ...@@ -24,7 +24,9 @@ obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o
obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o
obj-$(CONFIG_CPCAP_ADC) += cpcap-adc.o obj-$(CONFIG_CPCAP_ADC) += cpcap-adc.o
obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
obj-$(CONFIG_DLN2_ADC) += dln2-adc.o
obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o
obj-$(CONFIG_EP93XX_ADC) += ep93xx_adc.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o
obj-$(CONFIG_HI8435) += hi8435.o obj-$(CONFIG_HI8435) += hi8435.o
...@@ -34,6 +36,7 @@ obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o ...@@ -34,6 +36,7 @@ obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
obj-$(CONFIG_LTC2471) += ltc2471.o
obj-$(CONFIG_LTC2485) += ltc2485.o obj-$(CONFIG_LTC2485) += ltc2485.o
obj-$(CONFIG_LTC2497) += ltc2497.o obj-$(CONFIG_LTC2497) += ltc2497.o
obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1027) += max1027.o
......
...@@ -103,8 +103,7 @@ static int ad7766_preenable(struct iio_dev *indio_dev) ...@@ -103,8 +103,7 @@ static int ad7766_preenable(struct iio_dev *indio_dev)
return ret; return ret;
} }
if (ad7766->pd_gpio) gpiod_set_value(ad7766->pd_gpio, 0);
gpiod_set_value(ad7766->pd_gpio, 0);
return 0; return 0;
} }
...@@ -113,8 +112,7 @@ static int ad7766_postdisable(struct iio_dev *indio_dev) ...@@ -113,8 +112,7 @@ static int ad7766_postdisable(struct iio_dev *indio_dev)
{ {
struct ad7766 *ad7766 = iio_priv(indio_dev); struct ad7766 *ad7766 = iio_priv(indio_dev);
if (ad7766->pd_gpio) gpiod_set_value(ad7766->pd_gpio, 1);
gpiod_set_value(ad7766->pd_gpio, 1);
/* /*
* The PD pin is synchronous to the clock, so give it some time to * The PD pin is synchronous to the clock, so give it some time to
......
This diff is collapsed.
...@@ -799,7 +799,7 @@ static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz) ...@@ -799,7 +799,7 @@ static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz)
* For sama5d3x and at91sam9x5, the formula changes to: * For sama5d3x and at91sam9x5, the formula changes to:
* Startup Time = <lookup_table_value> / ADC Clock * Startup Time = <lookup_table_value> / ADC Clock
*/ */
const int startup_lookup[] = { static const int startup_lookup[] = {
0, 8, 16, 24, 0, 8, 16, 24,
64, 80, 96, 112, 64, 80, 96, 112,
512, 576, 640, 704, 512, 576, 640, 704,
......
This diff is collapsed.
/*
* Driver for ADC module on the Cirrus Logic EP93xx series of SoCs
*
* Copyright (C) 2015 Alexander Sverdlin
*
* 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.
*
* The driver uses polling to get the conversion status. According to EP93xx
* datasheets, reading ADCResult register starts the conversion, but user is also
* responsible for ensuring that delay between adjacent conversion triggers is
* long enough so that maximum allowed conversion rate is not exceeded. This
* basically renders IRQ mode unusable.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/iio/iio.h>
#include <linux/io.h>
#include <linux/irqflags.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
/*
* This code could benefit from real HR Timers, but jiffy granularity would
* lower ADC conversion rate down to CONFIG_HZ, so we fallback to busy wait
* in such case.
*
* HR Timers-based version loads CPU only up to 10% during back to back ADC
* conversion, while busy wait-based version consumes whole CPU power.
*/
#ifdef CONFIG_HIGH_RES_TIMERS
#define ep93xx_adc_delay(usmin, usmax) usleep_range(usmin, usmax)
#else
#define ep93xx_adc_delay(usmin, usmax) udelay(usmin)
#endif
#define EP93XX_ADC_RESULT 0x08
#define EP93XX_ADC_SDR BIT(31)
#define EP93XX_ADC_SWITCH 0x18
#define EP93XX_ADC_SW_LOCK 0x20
struct ep93xx_adc_priv {
struct clk *clk;
void __iomem *base;
int lastch;
struct mutex lock;
};
#define EP93XX_ADC_CH(index, dname, swcfg) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = index, \
.address = swcfg, \
.datasheet_name = dname, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_OFFSET), \
}
/*
* Numbering scheme for channels 0..4 is defined in EP9301 and EP9302 datasheets.
* EP9307, EP9312 and EP9312 have 3 channels more (total 8), but the numbering is
* not defined. So the last three are numbered randomly, let's say.
*/
static const struct iio_chan_spec ep93xx_adc_channels[8] = {
EP93XX_ADC_CH(0, "YM", 0x608),
EP93XX_ADC_CH(1, "SXP", 0x680),
EP93XX_ADC_CH(2, "SXM", 0x640),
EP93XX_ADC_CH(3, "SYP", 0x620),
EP93XX_ADC_CH(4, "SYM", 0x610),
EP93XX_ADC_CH(5, "XP", 0x601),
EP93XX_ADC_CH(6, "XM", 0x602),
EP93XX_ADC_CH(7, "YP", 0x604),
};
static int ep93xx_read_raw(struct iio_dev *iiodev,
struct iio_chan_spec const *channel, int *value,
int *shift, long mask)
{
struct ep93xx_adc_priv *priv = iio_priv(iiodev);
unsigned long timeout;
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&priv->lock);
if (priv->lastch != channel->channel) {
priv->lastch = channel->channel;
/*
* Switch register is software-locked, unlocking must be
* immediately followed by write
*/
local_irq_disable();
writel_relaxed(0xAA, priv->base + EP93XX_ADC_SW_LOCK);
writel_relaxed(channel->address,
priv->base + EP93XX_ADC_SWITCH);
local_irq_enable();
/*
* Settling delay depends on module clock and could be
* 2ms or 500us
*/
ep93xx_adc_delay(2000, 2000);
}
/* Start the conversion, eventually discarding old result */
readl_relaxed(priv->base + EP93XX_ADC_RESULT);
/* Ensure maximum conversion rate is not exceeded */
ep93xx_adc_delay(DIV_ROUND_UP(1000000, 925),
DIV_ROUND_UP(1000000, 925));
/* At this point conversion must be completed, but anyway... */
ret = IIO_VAL_INT;
timeout = jiffies + msecs_to_jiffies(1) + 1;
while (1) {
u32 t;
t = readl_relaxed(priv->base + EP93XX_ADC_RESULT);
if (t & EP93XX_ADC_SDR) {
*value = sign_extend32(t, 15);
break;
}
if (time_after(jiffies, timeout)) {
dev_err(&iiodev->dev, "Conversion timeout\n");
ret = -ETIMEDOUT;
break;
}
cpu_relax();
}
mutex_unlock(&priv->lock);
return ret;
case IIO_CHAN_INFO_OFFSET:
/* According to datasheet, range is -25000..25000 */
*value = 25000;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
/* Typical supply voltage is 3.3v */
*value = (1ULL << 32) * 3300 / 50000;
*shift = 32;
return IIO_VAL_FRACTIONAL_LOG2;
}
return -EINVAL;
}
static const struct iio_info ep93xx_adc_info = {
.driver_module = THIS_MODULE,
.read_raw = ep93xx_read_raw,
};
static int ep93xx_adc_probe(struct platform_device *pdev)
{
int ret;
struct iio_dev *iiodev;
struct ep93xx_adc_priv *priv;
struct clk *pclk;
struct resource *res;
iiodev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
if (!iiodev)
return -ENOMEM;
priv = iio_priv(iiodev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Cannot obtain memory resource\n");
return -ENXIO;
}
priv->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv->base)) {
dev_err(&pdev->dev, "Cannot map memory resource\n");
return PTR_ERR(priv->base);
}
iiodev->dev.parent = &pdev->dev;
iiodev->name = dev_name(&pdev->dev);
iiodev->modes = INDIO_DIRECT_MODE;
iiodev->info = &ep93xx_adc_info;
iiodev->num_channels = ARRAY_SIZE(ep93xx_adc_channels);
iiodev->channels = ep93xx_adc_channels;
priv->lastch = -1;
mutex_init(&priv->lock);
platform_set_drvdata(pdev, iiodev);
priv->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "Cannot obtain clock\n");
return PTR_ERR(priv->clk);
}
pclk = clk_get_parent(priv->clk);
if (!pclk) {
dev_warn(&pdev->dev, "Cannot obtain parent clock\n");
} else {
/*
* This is actually a place for improvement:
* EP93xx ADC supports two clock divisors -- 4 and 16,
* resulting in conversion rates 3750 and 925 samples per second
* with 500us or 2ms settling time respectively.
* One might find this interesting enough to be configurable.
*/
ret = clk_set_rate(priv->clk, clk_get_rate(pclk) / 16);
if (ret)
dev_warn(&pdev->dev, "Cannot set clock rate\n");
/*
* We can tolerate rate setting failure because the module should
* work in any case.
*/
}
ret = clk_enable(priv->clk);
if (ret) {
dev_err(&pdev->dev, "Cannot enable clock\n");
return ret;
}
ret = iio_device_register(iiodev);
if (ret)
clk_disable(priv->clk);
return ret;
}
static int ep93xx_adc_remove(struct platform_device *pdev)
{
struct iio_dev *iiodev = platform_get_drvdata(pdev);
struct ep93xx_adc_priv *priv = iio_priv(iiodev);
iio_device_unregister(iiodev);
clk_disable(priv->clk);
return 0;
}
static struct platform_driver ep93xx_adc_driver = {
.driver = {
.name = "ep93xx-adc",
},
.probe = ep93xx_adc_probe,
.remove = ep93xx_adc_remove,
};
module_platform_driver(ep93xx_adc_driver);
MODULE_AUTHOR("Alexander Sverdlin <alexander.sverdlin@gmail.com>");
MODULE_DESCRIPTION("Cirrus Logic EP93XX ADC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:ep93xx-adc");
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#define INA226_MASK_ENABLE 0x06 #define INA226_MASK_ENABLE 0x06
#define INA226_CVRF BIT(3) #define INA226_CVRF BIT(3)
#define INA219_CNVR BIT(1)
#define INA2XX_MAX_REGISTERS 8 #define INA2XX_MAX_REGISTERS 8
...@@ -592,6 +593,7 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) ...@@ -592,6 +593,7 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
int bit, ret, i = 0; int bit, ret, i = 0;
s64 time_a, time_b; s64 time_a, time_b;
unsigned int alert; unsigned int alert;
int cnvr_need_clear = 0;
time_a = iio_get_time_ns(indio_dev); time_a = iio_get_time_ns(indio_dev);
...@@ -603,22 +605,30 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) ...@@ -603,22 +605,30 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
* we check the ConVersionReadyFlag. * we check the ConVersionReadyFlag.
* On hardware that supports using the ALERT pin to toggle a * On hardware that supports using the ALERT pin to toggle a
* GPIO a triggered buffer could be used instead. * GPIO a triggered buffer could be used instead.
* For now, we pay for that extra read of the ALERT register * For now, we do an extra read of the MASK_ENABLE register (INA226)
* resp. the BUS_VOLTAGE register (INA219).
*/ */
if (!chip->allow_async_readout) if (!chip->allow_async_readout)
do { do {
ret = regmap_read(chip->regmap, INA226_MASK_ENABLE, if (chip->config->chip_id == ina226) {
&alert); ret = regmap_read(chip->regmap,
INA226_MASK_ENABLE, &alert);
alert &= INA226_CVRF;
} else {
ret = regmap_read(chip->regmap,
INA2XX_BUS_VOLTAGE, &alert);
alert &= INA219_CNVR;
cnvr_need_clear = alert;
}
if (ret < 0) if (ret < 0)
return ret; return ret;
alert &= INA226_CVRF;
} while (!alert); } while (!alert);
/* /*
* Single register reads: bulk_read will not work with ina226 * Single register reads: bulk_read will not work with ina226/219
* as there is no auto-increment of the address register for * as there is no auto-increment of the register pointer.
* data length longer than 16bits.
*/ */
for_each_set_bit(bit, indio_dev->active_scan_mask, for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->masklength) { indio_dev->masklength) {
...@@ -630,6 +640,18 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) ...@@ -630,6 +640,18 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
return ret; return ret;
data[i++] = val; data[i++] = val;
if (INA2XX_SHUNT_VOLTAGE + bit == INA2XX_POWER)
cnvr_need_clear = 0;
}
/* Dummy read on INA219 power register to clear CNVR flag */
if (cnvr_need_clear && chip->config->chip_id == ina219) {
unsigned int val;
ret = regmap_read(chip->regmap, INA2XX_POWER, &val);
if (ret < 0)
return ret;
} }
time_b = iio_get_time_ns(indio_dev); time_b = iio_get_time_ns(indio_dev);
......
/*
* Driver for Linear Technology LTC2471 and LTC2473 voltage monitors
* The LTC2473 is identical to the 2471, but reports a differential signal.
*
* Copyright (C) 2017 Topic Embedded Products
* Author: Mike Looijmans <mike.looijmans@topic.nl>
*
* License: GPLv2
*/
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
enum ltc2471_chips {
ltc2471,
ltc2473,
};
struct ltc2471_data {
struct i2c_client *client;
};
/* Reference voltage is 1.25V */
#define LTC2471_VREF 1250
/* Read two bytes from the I2C bus to obtain the ADC result */
static int ltc2471_get_value(struct i2c_client *client)
{
int ret;
__be16 buf;
ret = i2c_master_recv(client, (char *)&buf, sizeof(buf));
if (ret < 0)
return ret;
if (ret != sizeof(buf))
return -EIO;
/* MSB first */
return be16_to_cpu(buf);
}
static int ltc2471_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long info)
{
struct ltc2471_data *data = iio_priv(indio_dev);
int ret;
switch (info) {
case IIO_CHAN_INFO_RAW:
ret = ltc2471_get_value(data->client);
if (ret < 0)
return ret;
*val = ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
if (chan->differential)
/* Output ranges from -VREF to +VREF */
*val = 2 * LTC2471_VREF;
else
/* Output ranges from 0 to VREF */
*val = LTC2471_VREF;
*val2 = 16; /* 16 data bits */
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_OFFSET:
/* Only differential chip has this property */
*val = -LTC2471_VREF;
return IIO_VAL_INT;
default:
return -EINVAL;
}
}
static const struct iio_chan_spec ltc2471_channel[] = {
{
.type = IIO_VOLTAGE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
},
};
static const struct iio_chan_spec ltc2473_channel[] = {
{
.type = IIO_VOLTAGE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OFFSET),
.differential = 1,
},
};
static const struct iio_info ltc2471_info = {
.read_raw = ltc2471_read_raw,
.driver_module = THIS_MODULE,
};
static int ltc2471_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
struct ltc2471_data *data;
int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -EOPNOTSUPP;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
data->client = client;
indio_dev->dev.parent = &client->dev;
indio_dev->name = id->name;
indio_dev->info = &ltc2471_info;
indio_dev->modes = INDIO_DIRECT_MODE;
if (id->driver_data == ltc2473)
indio_dev->channels = ltc2473_channel;
else
indio_dev->channels = ltc2471_channel;
indio_dev->num_channels = 1;
/* Trigger once to start conversion and check if chip is there */
ret = ltc2471_get_value(client);
if (ret < 0) {
dev_err(&client->dev, "Cannot read from device.\n");
return ret;
}
return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id ltc2471_i2c_id[] = {
{ "ltc2471", ltc2471 },
{ "ltc2473", ltc2473 },
{}
};
MODULE_DEVICE_TABLE(i2c, ltc2471_i2c_id);
static struct i2c_driver ltc2471_i2c_driver = {
.driver = {
.name = "ltc2471",
},
.probe = ltc2471_i2c_probe,
.id_table = ltc2471_i2c_id,
};
module_i2c_driver(ltc2471_i2c_driver);
MODULE_DESCRIPTION("LTC2471/LTC2473 ADC driver");
MODULE_AUTHOR("Topic Embedded Products");
MODULE_LICENSE("GPL v2");
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/driver.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
...@@ -127,13 +128,14 @@ static int ltc2497_read_raw(struct iio_dev *indio_dev, ...@@ -127,13 +128,14 @@ static int ltc2497_read_raw(struct iio_dev *indio_dev,
} }
} }
#define LTC2497_CHAN(_chan, _addr) { \ #define LTC2497_CHAN(_chan, _addr, _ds_name) { \
.type = IIO_VOLTAGE, \ .type = IIO_VOLTAGE, \
.indexed = 1, \ .indexed = 1, \
.channel = (_chan), \ .channel = (_chan), \
.address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \ .address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.datasheet_name = (_ds_name), \
} }
#define LTC2497_CHAN_DIFF(_chan, _addr) { \ #define LTC2497_CHAN_DIFF(_chan, _addr) { \
...@@ -148,22 +150,22 @@ static int ltc2497_read_raw(struct iio_dev *indio_dev, ...@@ -148,22 +150,22 @@ static int ltc2497_read_raw(struct iio_dev *indio_dev,
} }
static const struct iio_chan_spec ltc2497_channel[] = { static const struct iio_chan_spec ltc2497_channel[] = {
LTC2497_CHAN(0, LTC2497_SGL), LTC2497_CHAN(0, LTC2497_SGL, "CH0"),
LTC2497_CHAN(1, LTC2497_SGL), LTC2497_CHAN(1, LTC2497_SGL, "CH1"),
LTC2497_CHAN(2, LTC2497_SGL), LTC2497_CHAN(2, LTC2497_SGL, "CH2"),
LTC2497_CHAN(3, LTC2497_SGL), LTC2497_CHAN(3, LTC2497_SGL, "CH3"),
LTC2497_CHAN(4, LTC2497_SGL), LTC2497_CHAN(4, LTC2497_SGL, "CH4"),
LTC2497_CHAN(5, LTC2497_SGL), LTC2497_CHAN(5, LTC2497_SGL, "CH5"),
LTC2497_CHAN(6, LTC2497_SGL), LTC2497_CHAN(6, LTC2497_SGL, "CH6"),
LTC2497_CHAN(7, LTC2497_SGL), LTC2497_CHAN(7, LTC2497_SGL, "CH7"),
LTC2497_CHAN(8, LTC2497_SGL), LTC2497_CHAN(8, LTC2497_SGL, "CH8"),
LTC2497_CHAN(9, LTC2497_SGL), LTC2497_CHAN(9, LTC2497_SGL, "CH9"),
LTC2497_CHAN(10, LTC2497_SGL), LTC2497_CHAN(10, LTC2497_SGL, "CH10"),
LTC2497_CHAN(11, LTC2497_SGL), LTC2497_CHAN(11, LTC2497_SGL, "CH11"),
LTC2497_CHAN(12, LTC2497_SGL), LTC2497_CHAN(12, LTC2497_SGL, "CH12"),
LTC2497_CHAN(13, LTC2497_SGL), LTC2497_CHAN(13, LTC2497_SGL, "CH13"),
LTC2497_CHAN(14, LTC2497_SGL), LTC2497_CHAN(14, LTC2497_SGL, "CH14"),
LTC2497_CHAN(15, LTC2497_SGL), LTC2497_CHAN(15, LTC2497_SGL, "CH15"),
LTC2497_CHAN_DIFF(0, LTC2497_DIFF), LTC2497_CHAN_DIFF(0, LTC2497_DIFF),
LTC2497_CHAN_DIFF(1, LTC2497_DIFF), LTC2497_CHAN_DIFF(1, LTC2497_DIFF),
LTC2497_CHAN_DIFF(2, LTC2497_DIFF), LTC2497_CHAN_DIFF(2, LTC2497_DIFF),
...@@ -192,6 +194,7 @@ static int ltc2497_probe(struct i2c_client *client, ...@@ -192,6 +194,7 @@ static int ltc2497_probe(struct i2c_client *client,
{ {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct ltc2497_st *st; struct ltc2497_st *st;
struct iio_map *plat_data;
int ret; int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
...@@ -221,19 +224,31 @@ static int ltc2497_probe(struct i2c_client *client, ...@@ -221,19 +224,31 @@ static int ltc2497_probe(struct i2c_client *client,
if (ret < 0) if (ret < 0)
return ret; return ret;
if (client->dev.platform_data) {
plat_data = ((struct iio_map *)client->dev.platform_data);
ret = iio_map_array_register(indio_dev, plat_data);
if (ret) {
dev_err(&indio_dev->dev, "iio map err: %d\n", ret);
goto err_regulator_disable;
}
}
ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT); ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT);
if (ret < 0) if (ret < 0)
goto err_regulator_disable; goto err_array_unregister;
st->addr_prev = LTC2497_CONFIG_DEFAULT; st->addr_prev = LTC2497_CONFIG_DEFAULT;
st->time_prev = ktime_get(); st->time_prev = ktime_get();
ret = iio_device_register(indio_dev); ret = iio_device_register(indio_dev);
if (ret < 0) if (ret < 0)
goto err_regulator_disable; goto err_array_unregister;
return 0; return 0;
err_array_unregister:
iio_map_array_unregister(indio_dev);
err_regulator_disable: err_regulator_disable:
regulator_disable(st->ref); regulator_disable(st->ref);
...@@ -245,6 +260,7 @@ static int ltc2497_remove(struct i2c_client *client) ...@@ -245,6 +260,7 @@ static int ltc2497_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client); struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct ltc2497_st *st = iio_priv(indio_dev); struct ltc2497_st *st = iio_priv(indio_dev);
iio_map_array_unregister(indio_dev);
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
regulator_disable(st->ref); regulator_disable(st->ref);
......
...@@ -549,8 +549,8 @@ static int max9611_probe(struct i2c_client *client, ...@@ -549,8 +549,8 @@ static int max9611_probe(struct i2c_client *client,
ret = of_property_read_u32(of_node, shunt_res_prop, &of_shunt); ret = of_property_read_u32(of_node, shunt_res_prop, &of_shunt);
if (ret) { if (ret) {
dev_err(&client->dev, dev_err(&client->dev,
"Missing %s property for %s node\n", "Missing %s property for %pOF node\n",
shunt_res_prop, of_node->full_name); shunt_res_prop, of_node);
return ret; return ret;
} }
max9611->shunt_resistor_uohm = of_shunt; max9611->shunt_resistor_uohm = of_shunt;
......
...@@ -379,10 +379,12 @@ static int mcp3422_probe(struct i2c_client *client, ...@@ -379,10 +379,12 @@ static int mcp3422_probe(struct i2c_client *client,
/* meaningful default configuration */ /* meaningful default configuration */
config = (MCP3422_CONT_SAMPLING config = (MCP3422_CONT_SAMPLING
| MCP3422_CHANNEL_VALUE(1) | MCP3422_CHANNEL_VALUE(0)
| MCP3422_PGA_VALUE(MCP3422_PGA_1) | MCP3422_PGA_VALUE(MCP3422_PGA_1)
| MCP3422_SAMPLE_RATE_VALUE(MCP3422_SRATE_240)); | MCP3422_SAMPLE_RATE_VALUE(MCP3422_SRATE_240));
mcp3422_update_config(adc, config); err = mcp3422_update_config(adc, config);
if (err < 0)
return err;
err = devm_iio_device_register(&client->dev, indio_dev); err = devm_iio_device_register(&client->dev, indio_dev);
if (err < 0) if (err < 0)
......
...@@ -572,8 +572,8 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev, ...@@ -572,8 +572,8 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
struct clk_init_data init; struct clk_init_data init;
const char *clk_parents[1]; const char *clk_parents[1];
init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_div", init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_div",
of_node_full_name(indio_dev->dev.of_node)); indio_dev->dev.of_node);
init.flags = 0; init.flags = 0;
init.ops = &clk_divider_ops; init.ops = &clk_divider_ops;
clk_parents[0] = __clk_get_name(priv->clkin); clk_parents[0] = __clk_get_name(priv->clkin);
...@@ -591,8 +591,8 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev, ...@@ -591,8 +591,8 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
if (WARN_ON(IS_ERR(priv->adc_div_clk))) if (WARN_ON(IS_ERR(priv->adc_div_clk)))
return PTR_ERR(priv->adc_div_clk); return PTR_ERR(priv->adc_div_clk);
init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_en", init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_en",
of_node_full_name(indio_dev->dev.of_node)); indio_dev->dev.of_node);
init.flags = CLK_SET_RATE_PARENT; init.flags = CLK_SET_RATE_PARENT;
init.ops = &clk_gate_ops; init.ops = &clk_gate_ops;
clk_parents[0] = __clk_get_name(priv->adc_div_clk); clk_parents[0] = __clk_get_name(priv->adc_div_clk);
...@@ -915,6 +915,11 @@ static int meson_sar_adc_probe(struct platform_device *pdev) ...@@ -915,6 +915,11 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
init_completion(&priv->done); init_completion(&priv->done);
match = of_match_device(meson_sar_adc_of_match, &pdev->dev); match = of_match_device(meson_sar_adc_of_match, &pdev->dev);
if (!match) {
dev_err(&pdev->dev, "failed to match device\n");
return -ENODEV;
}
priv->data = match->data; priv->data = match->data;
indio_dev->name = priv->data->name; indio_dev->name = priv->data->name;
......
...@@ -184,6 +184,37 @@ static const struct iio_info mt6577_auxadc_info = { ...@@ -184,6 +184,37 @@ static const struct iio_info mt6577_auxadc_info = {
.read_raw = &mt6577_auxadc_read_raw, .read_raw = &mt6577_auxadc_read_raw,
}; };
static int __maybe_unused mt6577_auxadc_resume(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
int ret;
ret = clk_prepare_enable(adc_dev->adc_clk);
if (ret) {
pr_err("failed to enable auxadc clock\n");
return ret;
}
mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
MT6577_AUXADC_PDN_EN, 0);
mdelay(MT6577_AUXADC_POWER_READY_MS);
return 0;
}
static int __maybe_unused mt6577_auxadc_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
0, MT6577_AUXADC_PDN_EN);
clk_disable_unprepare(adc_dev->adc_clk);
return 0;
}
static int mt6577_auxadc_probe(struct platform_device *pdev) static int mt6577_auxadc_probe(struct platform_device *pdev)
{ {
struct mt6577_auxadc_device *adc_dev; struct mt6577_auxadc_device *adc_dev;
...@@ -269,8 +300,13 @@ static int mt6577_auxadc_remove(struct platform_device *pdev) ...@@ -269,8 +300,13 @@ static int mt6577_auxadc_remove(struct platform_device *pdev)
return 0; return 0;
} }
static SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops,
mt6577_auxadc_suspend,
mt6577_auxadc_resume);
static const struct of_device_id mt6577_auxadc_of_match[] = { static const struct of_device_id mt6577_auxadc_of_match[] = {
{ .compatible = "mediatek,mt2701-auxadc", }, { .compatible = "mediatek,mt2701-auxadc", },
{ .compatible = "mediatek,mt7622-auxadc", },
{ .compatible = "mediatek,mt8173-auxadc", }, { .compatible = "mediatek,mt8173-auxadc", },
{ } { }
}; };
...@@ -280,6 +316,7 @@ static struct platform_driver mt6577_auxadc_driver = { ...@@ -280,6 +316,7 @@ static struct platform_driver mt6577_auxadc_driver = {
.driver = { .driver = {
.name = "mt6577-auxadc", .name = "mt6577-auxadc",
.of_match_table = mt6577_auxadc_of_match, .of_match_table = mt6577_auxadc_of_match,
.pm = &mt6577_auxadc_pm_ops,
}, },
.probe = mt6577_auxadc_probe, .probe = mt6577_auxadc_probe,
.remove = mt6577_auxadc_remove, .remove = mt6577_auxadc_remove,
......
...@@ -224,6 +224,11 @@ static int rockchip_saradc_probe(struct platform_device *pdev) ...@@ -224,6 +224,11 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
info = iio_priv(indio_dev); info = iio_priv(indio_dev);
match = of_match_device(rockchip_saradc_match, &pdev->dev); match = of_match_device(rockchip_saradc_match, &pdev->dev);
if (!match) {
dev_err(&pdev->dev, "failed to match device\n");
return -ENODEV;
}
info->data = match->data; info->data = match->data;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......
...@@ -172,7 +172,7 @@ struct stm32h7_adc_ck_spec { ...@@ -172,7 +172,7 @@ struct stm32h7_adc_ck_spec {
int div; int div;
}; };
const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = { static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = {
/* 00: CK_ADC[1..3]: Asynchronous clock modes */ /* 00: CK_ADC[1..3]: Asynchronous clock modes */
{ 0, 0, 1 }, { 0, 0, 1 },
{ 0, 1, 2 }, { 0, 1, 2 },
......
...@@ -505,24 +505,24 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) ...@@ -505,24 +505,24 @@ static int ads1015_get_channels_config_of(struct i2c_client *client)
unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE; unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE;
if (of_property_read_u32(node, "reg", &pval)) { if (of_property_read_u32(node, "reg", &pval)) {
dev_err(&client->dev, "invalid reg on %s\n", dev_err(&client->dev, "invalid reg on %pOF\n",
node->full_name); node);
continue; continue;
} }
channel = pval; channel = pval;
if (channel >= ADS1015_CHANNELS) { if (channel >= ADS1015_CHANNELS) {
dev_err(&client->dev, dev_err(&client->dev,
"invalid channel index %d on %s\n", "invalid channel index %d on %pOF\n",
channel, node->full_name); channel, node);
continue; continue;
} }
if (!of_property_read_u32(node, "ti,gain", &pval)) { if (!of_property_read_u32(node, "ti,gain", &pval)) {
pga = pval; pga = pval;
if (pga > 6) { if (pga > 6) {
dev_err(&client->dev, "invalid gain on %s\n", dev_err(&client->dev, "invalid gain on %pOF\n",
node->full_name); node);
of_node_put(node); of_node_put(node);
return -EINVAL; return -EINVAL;
} }
...@@ -532,8 +532,8 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) ...@@ -532,8 +532,8 @@ static int ads1015_get_channels_config_of(struct i2c_client *client)
data_rate = pval; data_rate = pval;
if (data_rate > 7) { if (data_rate > 7) {
dev_err(&client->dev, dev_err(&client->dev,
"invalid data_rate on %s\n", "invalid data_rate on %pOF\n",
node->full_name); node);
of_node_put(node); of_node_put(node);
return -EINVAL; return -EINVAL;
} }
......
...@@ -21,6 +21,13 @@ config ATLAS_PH_SENSOR ...@@ -21,6 +21,13 @@ config ATLAS_PH_SENSOR
To compile this driver as module, choose M here: the To compile this driver as module, choose M here: the
module will be called atlas-ph-sensor. module will be called atlas-ph-sensor.
config CCS811
tristate "AMS CCS811 VOC sensor"
depends on I2C
help
Say Y here to build I2C interface support for the AMS
CCS811 VOC (Volatile Organic Compounds) sensor
config IAQCORE config IAQCORE
tristate "AMS iAQ-Core VOC sensors" tristate "AMS iAQ-Core VOC sensors"
depends on I2C depends on I2C
......
...@@ -4,5 +4,6 @@ ...@@ -4,5 +4,6 @@
# When adding new entries keep the list in alphabetical order # When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-ph-sensor.o obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-ph-sensor.o
obj-$(CONFIG_CCS811) += ccs811.o
obj-$(CONFIG_IAQCORE) += ams-iaq-core.o obj-$(CONFIG_IAQCORE) += ams-iaq-core.o
obj-$(CONFIG_VZ89X) += vz89x.o obj-$(CONFIG_VZ89X) += vz89x.o
/*
* ccs811.c - Support for AMS CCS811 VOC Sensor
*
* Copyright (C) 2017 Narcisa Vasile <narcisaanamaria12@gmail.com>
*
* Datasheet: ams.com/content/download/951091/2269479/CCS811_DS000459_3-00.pdf
*
* 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.
*
* IIO driver for AMS CCS811 (I2C address 0x5A/0x5B set by ADDR Low/High)
*
* TODO:
* 1. Make the drive mode selectable form userspace
* 2. Add support for interrupts
* 3. Adjust time to wait for data to be ready based on selected operation mode
* 4. Read error register and put the information in logs
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/module.h>
#define CCS811_STATUS 0x00
#define CCS811_MEAS_MODE 0x01
#define CCS811_ALG_RESULT_DATA 0x02
#define CCS811_RAW_DATA 0x03
#define CCS811_HW_ID 0x20
#define CCS881_HW_ID_VALUE 0x81
#define CCS811_HW_VERSION 0x21
#define CCS811_HW_VERSION_VALUE 0x10
#define CCS811_HW_VERSION_MASK 0xF0
#define CCS811_ERR 0xE0
/* Used to transition from boot to application mode */
#define CCS811_APP_START 0xF4
/* Status register flags */
#define CCS811_STATUS_ERROR BIT(0)
#define CCS811_STATUS_DATA_READY BIT(3)
#define CCS811_STATUS_APP_VALID_MASK BIT(4)
#define CCS811_STATUS_APP_VALID_LOADED BIT(4)
/*
* Value of FW_MODE bit of STATUS register describes the sensor's state:
* 0: Firmware is in boot mode, this allows new firmware to be loaded
* 1: Firmware is in application mode. CCS811 is ready to take ADC measurements
*/
#define CCS811_STATUS_FW_MODE_MASK BIT(7)
#define CCS811_STATUS_FW_MODE_APPLICATION BIT(7)
/* Measurement modes */
#define CCS811_MODE_IDLE 0x00
#define CCS811_MODE_IAQ_1SEC 0x10
#define CCS811_MODE_IAQ_10SEC 0x20
#define CCS811_MODE_IAQ_60SEC 0x30
#define CCS811_MODE_RAW_DATA 0x40
#define CCS811_VOLTAGE_MASK 0x3FF
struct ccs811_reading {
__be16 co2;
__be16 voc;
u8 status;
u8 error;
__be16 resistance;
} __attribute__((__packed__));
struct ccs811_data {
struct i2c_client *client;
struct mutex lock; /* Protect readings */
struct ccs811_reading buffer;
};
static const struct iio_chan_spec ccs811_channels[] = {
{
.type = IIO_CURRENT,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE)
}, {
.type = IIO_VOLTAGE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE)
}, {
.type = IIO_CONCENTRATION,
.channel2 = IIO_MOD_CO2,
.modified = 1,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE)
}, {
.type = IIO_CONCENTRATION,
.channel2 = IIO_MOD_VOC,
.modified = 1,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE)
},
};
/*
* The CCS811 powers-up in boot mode. A setup write to CCS811_APP_START will
* transition the sensor to application mode.
*/
static int ccs811_start_sensor_application(struct i2c_client *client)
{
int ret;
ret = i2c_smbus_read_byte_data(client, CCS811_STATUS);
if (ret < 0)
return ret;
if ((ret & CCS811_STATUS_APP_VALID_MASK) !=
CCS811_STATUS_APP_VALID_LOADED)
return -EIO;
ret = i2c_smbus_write_byte(client, CCS811_APP_START);
if (ret < 0)
return ret;
ret = i2c_smbus_read_byte_data(client, CCS811_STATUS);
if (ret < 0)
return ret;
if ((ret & CCS811_STATUS_FW_MODE_MASK) !=
CCS811_STATUS_FW_MODE_APPLICATION) {
dev_err(&client->dev, "Application failed to start. Sensor is still in boot mode.\n");
return -EIO;
}
return 0;
}
static int ccs811_setup(struct i2c_client *client)
{
int ret;
ret = ccs811_start_sensor_application(client);
if (ret < 0)
return ret;
return i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE,
CCS811_MODE_IAQ_1SEC);
}
static int ccs811_get_measurement(struct ccs811_data *data)
{
int ret, tries = 11;
/* Maximum waiting time: 1s, as measurements are made every second */
while (tries-- > 0) {
ret = i2c_smbus_read_byte_data(data->client, CCS811_STATUS);
if (ret < 0)
return ret;
if ((ret & CCS811_STATUS_DATA_READY) || tries == 0)
break;
msleep(100);
}
if (!(ret & CCS811_STATUS_DATA_READY))
return -EIO;
return i2c_smbus_read_i2c_block_data(data->client,
CCS811_ALG_RESULT_DATA, 8,
(char *)&data->buffer);
}
static int ccs811_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct ccs811_data *data = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&data->lock);
ret = ccs811_get_measurement(data);
if (ret < 0) {
mutex_unlock(&data->lock);
return ret;
}
switch (chan->type) {
case IIO_VOLTAGE:
*val = be16_to_cpu(data->buffer.resistance) &
CCS811_VOLTAGE_MASK;
ret = IIO_VAL_INT;
break;
case IIO_CURRENT:
*val = be16_to_cpu(data->buffer.resistance) >> 10;
ret = IIO_VAL_INT;
break;
case IIO_CONCENTRATION:
switch (chan->channel2) {
case IIO_MOD_CO2:
*val = be16_to_cpu(data->buffer.co2);
ret = IIO_VAL_INT;
break;
case IIO_MOD_VOC:
*val = be16_to_cpu(data->buffer.voc);
ret = IIO_VAL_INT;
break;
default:
ret = -EINVAL;
}
break;
default:
ret = -EINVAL;
}
mutex_unlock(&data->lock);
return ret;
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
*val = 1;
*val2 = 612903;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CURRENT:
*val = 0;
*val2 = 1000;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CONCENTRATION:
switch (chan->channel2) {
case IIO_MOD_CO2:
*val = 0;
*val2 = 12834;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_MOD_VOC:
*val = 0;
*val2 = 84246;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
default:
return -EINVAL;
}
case IIO_CHAN_INFO_OFFSET:
if (!(chan->type == IIO_CONCENTRATION &&
chan->channel2 == IIO_MOD_CO2))
return -EINVAL;
*val = -400;
return IIO_VAL_INT;
default:
return -EINVAL;
}
}
static const struct iio_info ccs811_info = {
.read_raw = ccs811_read_raw,
.driver_module = THIS_MODULE,
};
static int ccs811_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
struct ccs811_data *data;
int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE
| I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_READ_I2C_BLOCK))
return -EOPNOTSUPP;
/* Check hardware id (should be 0x81 for this family of devices) */
ret = i2c_smbus_read_byte_data(client, CCS811_HW_ID);
if (ret < 0)
return ret;
if (ret != CCS881_HW_ID_VALUE) {
dev_err(&client->dev, "hardware id doesn't match CCS81x\n");
return -ENODEV;
}
ret = i2c_smbus_read_byte_data(client, CCS811_HW_VERSION);
if (ret < 0)
return ret;
if ((ret & CCS811_HW_VERSION_MASK) != CCS811_HW_VERSION_VALUE) {
dev_err(&client->dev, "no CCS811 sensor\n");
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
ret = ccs811_setup(client);
if (ret < 0)
return ret;
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev;
indio_dev->name = id->name;
indio_dev->info = &ccs811_info;
indio_dev->channels = ccs811_channels;
indio_dev->num_channels = ARRAY_SIZE(ccs811_channels);
return iio_device_register(indio_dev);
}
static int ccs811_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
return i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE,
CCS811_MODE_IDLE);
}
static const struct i2c_device_id ccs811_id[] = {
{"ccs811", 0},
{ }
};
MODULE_DEVICE_TABLE(i2c, ccs811_id);
static struct i2c_driver ccs811_driver = {
.driver = {
.name = "ccs811",
},
.probe = ccs811_probe,
.remove = ccs811_remove,
.id_table = ccs811_id,
};
module_i2c_driver(ccs811_driver);
MODULE_AUTHOR("Narcisa Vasile <narcisaanamaria12@gmail.com>");
MODULE_DESCRIPTION("CCS811 volatile organic compounds sensor");
MODULE_LICENSE("GPL v2");
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors.h>
...@@ -345,6 +346,36 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, ...@@ -345,6 +346,36 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev,
return pdata; return pdata;
} }
/**
* st_sensors_of_name_probe() - device tree probe for ST sensor name
* @dev: driver model representation of the device.
* @match: the OF match table for the device, containing compatible strings
* but also a .data field with the corresponding internal kernel name
* used by this sensor.
* @name: device name buffer reference.
* @len: device name buffer length.
*
* In effect this function matches a compatible string to an internal kernel
* name for a certain sensor device, so that the rest of the autodetection can
* rely on that name from this point on. I2C/SPI devices will be renamed
* to match the internal kernel convention.
*/
void st_sensors_of_name_probe(struct device *dev,
const struct of_device_id *match,
char *name, int len)
{
const struct of_device_id *of_id;
of_id = of_match_device(match, dev);
if (!of_id || !of_id->data)
return;
/* The name from the OF match takes precedence if present */
strncpy(name, of_id->data, len);
name[len - 1] = '\0';
}
EXPORT_SYMBOL(st_sensors_of_name_probe);
#else #else
static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev,
struct st_sensors_platform_data *defdata) struct st_sensors_platform_data *defdata)
......
...@@ -79,35 +79,6 @@ void st_sensors_i2c_configure(struct iio_dev *indio_dev, ...@@ -79,35 +79,6 @@ void st_sensors_i2c_configure(struct iio_dev *indio_dev,
} }
EXPORT_SYMBOL(st_sensors_i2c_configure); EXPORT_SYMBOL(st_sensors_i2c_configure);
#ifdef CONFIG_OF
/**
* st_sensors_of_i2c_probe() - device tree probe for ST I2C sensors
* @client: the I2C client device for the sensor
* @match: the OF match table for the device, containing compatible strings
* but also a .data field with the corresponding internal kernel name
* used by this sensor.
*
* In effect this function matches a compatible string to an internal kernel
* name for a certain sensor device, so that the rest of the autodetection can
* rely on that name from this point on. I2C client devices will be renamed
* to match the internal kernel convention.
*/
void st_sensors_of_i2c_probe(struct i2c_client *client,
const struct of_device_id *match)
{
const struct of_device_id *of_id;
of_id = of_match_device(match, &client->dev);
if (!of_id)
return;
/* The name from the OF match takes precedence if present */
strncpy(client->name, of_id->data, sizeof(client->name));
client->name[sizeof(client->name) - 1] = '\0';
}
EXPORT_SYMBOL(st_sensors_of_i2c_probe);
#endif
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
int st_sensors_match_acpi_device(struct device *dev) int st_sensors_match_acpi_device(struct device *dev)
{ {
......
...@@ -42,6 +42,14 @@ struct stm32_dac_priv { ...@@ -42,6 +42,14 @@ struct stm32_dac_priv {
struct stm32_dac_common common; struct stm32_dac_common common;
}; };
/**
* struct stm32_dac_cfg - DAC configuration
* @has_hfsel: DAC has high frequency control
*/
struct stm32_dac_cfg {
bool has_hfsel;
};
static struct stm32_dac_priv *to_stm32_dac_priv(struct stm32_dac_common *com) static struct stm32_dac_priv *to_stm32_dac_priv(struct stm32_dac_common *com)
{ {
return container_of(com, struct stm32_dac_priv, common); return container_of(com, struct stm32_dac_priv, common);
...@@ -57,6 +65,7 @@ static const struct regmap_config stm32_dac_regmap_cfg = { ...@@ -57,6 +65,7 @@ static const struct regmap_config stm32_dac_regmap_cfg = {
static int stm32_dac_probe(struct platform_device *pdev) static int stm32_dac_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct stm32_dac_cfg *cfg;
struct stm32_dac_priv *priv; struct stm32_dac_priv *priv;
struct regmap *regmap; struct regmap *regmap;
struct resource *res; struct resource *res;
...@@ -69,6 +78,8 @@ static int stm32_dac_probe(struct platform_device *pdev) ...@@ -69,6 +78,8 @@ static int stm32_dac_probe(struct platform_device *pdev)
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
cfg = (const struct stm32_dac_cfg *)
of_match_device(dev->driver->of_match_table, dev)->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mmio = devm_ioremap_resource(dev, res); mmio = devm_ioremap_resource(dev, res);
...@@ -121,12 +132,16 @@ static int stm32_dac_probe(struct platform_device *pdev) ...@@ -121,12 +132,16 @@ static int stm32_dac_probe(struct platform_device *pdev)
reset_control_deassert(priv->rst); reset_control_deassert(priv->rst);
} }
/* When clock speed is higher than 80MHz, set HFSEL */ if (cfg && cfg->has_hfsel) {
priv->common.hfsel = (clk_get_rate(priv->pclk) > 80000000UL); /* When clock speed is higher than 80MHz, set HFSEL */
ret = regmap_update_bits(regmap, STM32_DAC_CR, STM32H7_DAC_CR_HFSEL, priv->common.hfsel = (clk_get_rate(priv->pclk) > 80000000UL);
priv->common.hfsel ? STM32H7_DAC_CR_HFSEL : 0); ret = regmap_update_bits(regmap, STM32_DAC_CR,
if (ret) STM32H7_DAC_CR_HFSEL,
goto err_pclk; priv->common.hfsel ?
STM32H7_DAC_CR_HFSEL : 0);
if (ret)
goto err_pclk;
}
platform_set_drvdata(pdev, &priv->common); platform_set_drvdata(pdev, &priv->common);
...@@ -158,8 +173,17 @@ static int stm32_dac_remove(struct platform_device *pdev) ...@@ -158,8 +173,17 @@ static int stm32_dac_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct stm32_dac_cfg stm32h7_dac_cfg = {
.has_hfsel = true,
};
static const struct of_device_id stm32_dac_of_match[] = { static const struct of_device_id stm32_dac_of_match[] = {
{ .compatible = "st,stm32h7-dac-core", }, {
.compatible = "st,stm32f4-dac-core",
}, {
.compatible = "st,stm32h7-dac-core",
.data = (void *)&stm32h7_dac_cfg,
},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, stm32_dac_of_match); MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
......
...@@ -268,7 +268,7 @@ static int stm32_dac_chan_of_init(struct iio_dev *indio_dev) ...@@ -268,7 +268,7 @@ static int stm32_dac_chan_of_init(struct iio_dev *indio_dev)
break; break;
} }
if (i >= ARRAY_SIZE(stm32_dac_channels)) { if (i >= ARRAY_SIZE(stm32_dac_channels)) {
dev_err(&indio_dev->dev, "Invalid st,dac-channel\n"); dev_err(&indio_dev->dev, "Invalid reg property\n");
return -EINVAL; return -EINVAL;
} }
......
...@@ -1063,11 +1063,6 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq) ...@@ -1063,11 +1063,6 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq)
case IRQF_TRIGGER_RISING: case IRQF_TRIGGER_RISING:
dev_info(&indio_dev->dev, dev_info(&indio_dev->dev,
"pulse interrupts on the rising edge\n"); "pulse interrupts on the rising edge\n");
if (mpu3050->irq_opendrain) {
dev_info(&indio_dev->dev,
"rising edge incompatible with open drain\n");
mpu3050->irq_opendrain = false;
}
break; break;
case IRQF_TRIGGER_FALLING: case IRQF_TRIGGER_FALLING:
mpu3050->irq_actl = true; mpu3050->irq_actl = true;
...@@ -1078,11 +1073,6 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq) ...@@ -1078,11 +1073,6 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq)
mpu3050->irq_latch = true; mpu3050->irq_latch = true;
dev_info(&indio_dev->dev, dev_info(&indio_dev->dev,
"interrupts active high level\n"); "interrupts active high level\n");
if (mpu3050->irq_opendrain) {
dev_info(&indio_dev->dev,
"active high incompatible with open drain\n");
mpu3050->irq_opendrain = false;
}
/* /*
* With level IRQs, we mask the IRQ until it is processed, * With level IRQs, we mask the IRQ until it is processed,
* but with edge IRQs (pulses) we can queue several interrupts * but with edge IRQs (pulses) we can queue several interrupts
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#define LSM330DL_GYRO_DEV_NAME "lsm330dl_gyro" #define LSM330DL_GYRO_DEV_NAME "lsm330dl_gyro"
#define LSM330DLC_GYRO_DEV_NAME "lsm330dlc_gyro" #define LSM330DLC_GYRO_DEV_NAME "lsm330dlc_gyro"
#define L3GD20_GYRO_DEV_NAME "l3gd20" #define L3GD20_GYRO_DEV_NAME "l3gd20"
#define L3GD20H_GYRO_DEV_NAME "l3gd20h"
#define L3G4IS_GYRO_DEV_NAME "l3g4is_ui" #define L3G4IS_GYRO_DEV_NAME "l3g4is_ui"
#define LSM330_GYRO_DEV_NAME "lsm330_gyro" #define LSM330_GYRO_DEV_NAME "lsm330_gyro"
#define LSM9DS0_GYRO_DEV_NAME "lsm9ds0_gyro" #define LSM9DS0_GYRO_DEV_NAME "lsm9ds0_gyro"
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#define ST_GYRO_DEFAULT_OUT_Z_L_ADDR 0x2c #define ST_GYRO_DEFAULT_OUT_Z_L_ADDR 0x2c
/* FULLSCALE */ /* FULLSCALE */
#define ST_GYRO_FS_AVL_245DPS 245
#define ST_GYRO_FS_AVL_250DPS 250 #define ST_GYRO_FS_AVL_250DPS 250
#define ST_GYRO_FS_AVL_500DPS 500 #define ST_GYRO_FS_AVL_500DPS 500
#define ST_GYRO_FS_AVL_2000DPS 2000 #define ST_GYRO_FS_AVL_2000DPS 2000
...@@ -196,17 +197,17 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { ...@@ -196,17 +197,17 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
.wai = 0xd7, .wai = 0xd7,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = { .sensors_supported = {
[0] = L3GD20_GYRO_DEV_NAME, [0] = L3GD20H_GYRO_DEV_NAME,
}, },
.ch = (struct iio_chan_spec *)st_gyro_16bit_channels, .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
.odr = { .odr = {
.addr = 0x20, .addr = 0x20,
.mask = 0xc0, .mask = 0xc0,
.odr_avl = { .odr_avl = {
{ .hz = 95, .value = 0x00, }, { .hz = 100, .value = 0x00, },
{ .hz = 190, .value = 0x01, }, { .hz = 200, .value = 0x01, },
{ .hz = 380, .value = 0x02, }, { .hz = 400, .value = 0x02, },
{ .hz = 760, .value = 0x03, }, { .hz = 800, .value = 0x03, },
}, },
}, },
.pw = { .pw = {
...@@ -224,7 +225,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { ...@@ -224,7 +225,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
.mask = 0x30, .mask = 0x30,
.fs_avl = { .fs_avl = {
[0] = { [0] = {
.num = ST_GYRO_FS_AVL_250DPS, .num = ST_GYRO_FS_AVL_245DPS,
.value = 0x00, .value = 0x00,
.gain = IIO_DEGREE_TO_RAD(8750), .gain = IIO_DEGREE_TO_RAD(8750),
}, },
......
...@@ -40,6 +40,10 @@ static const struct of_device_id st_gyro_of_match[] = { ...@@ -40,6 +40,10 @@ static const struct of_device_id st_gyro_of_match[] = {
.compatible = "st,l3gd20-gyro", .compatible = "st,l3gd20-gyro",
.data = L3GD20_GYRO_DEV_NAME, .data = L3GD20_GYRO_DEV_NAME,
}, },
{
.compatible = "st,l3gd20h-gyro",
.data = L3GD20H_GYRO_DEV_NAME,
},
{ {
.compatible = "st,l3g4is-gyro", .compatible = "st,l3g4is-gyro",
.data = L3G4IS_GYRO_DEV_NAME, .data = L3G4IS_GYRO_DEV_NAME,
...@@ -71,7 +75,8 @@ static int st_gyro_i2c_probe(struct i2c_client *client, ...@@ -71,7 +75,8 @@ static int st_gyro_i2c_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
gdata = iio_priv(indio_dev); gdata = iio_priv(indio_dev);
st_sensors_of_i2c_probe(client, st_gyro_of_match); st_sensors_of_name_probe(&client->dev, st_gyro_of_match,
client->name, sizeof(client->name));
st_sensors_i2c_configure(indio_dev, client, gdata); st_sensors_i2c_configure(indio_dev, client, gdata);
...@@ -95,6 +100,7 @@ static const struct i2c_device_id st_gyro_id_table[] = { ...@@ -95,6 +100,7 @@ static const struct i2c_device_id st_gyro_id_table[] = {
{ LSM330DL_GYRO_DEV_NAME }, { LSM330DL_GYRO_DEV_NAME },
{ LSM330DLC_GYRO_DEV_NAME }, { LSM330DLC_GYRO_DEV_NAME },
{ L3GD20_GYRO_DEV_NAME }, { L3GD20_GYRO_DEV_NAME },
{ L3GD20H_GYRO_DEV_NAME },
{ L3G4IS_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME },
{ LSM330_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME },
{ LSM9DS0_GYRO_DEV_NAME }, { LSM9DS0_GYRO_DEV_NAME },
......
...@@ -18,6 +18,56 @@ ...@@ -18,6 +18,56 @@
#include <linux/iio/common/st_sensors_spi.h> #include <linux/iio/common/st_sensors_spi.h>
#include "st_gyro.h" #include "st_gyro.h"
#ifdef CONFIG_OF
/*
* For new single-chip sensors use <device_name> as compatible string.
* For old single-chip devices keep <device_name>-gyro to maintain
* compatibility
*/
static const struct of_device_id st_gyro_of_match[] = {
{
.compatible = "st,l3g4200d-gyro",
.data = L3G4200D_GYRO_DEV_NAME,
},
{
.compatible = "st,lsm330d-gyro",
.data = LSM330D_GYRO_DEV_NAME,
},
{
.compatible = "st,lsm330dl-gyro",
.data = LSM330DL_GYRO_DEV_NAME,
},
{
.compatible = "st,lsm330dlc-gyro",
.data = LSM330DLC_GYRO_DEV_NAME,
},
{
.compatible = "st,l3gd20-gyro",
.data = L3GD20_GYRO_DEV_NAME,
},
{
.compatible = "st,l3gd20h-gyro",
.data = L3GD20H_GYRO_DEV_NAME,
},
{
.compatible = "st,l3g4is-gyro",
.data = L3G4IS_GYRO_DEV_NAME,
},
{
.compatible = "st,lsm330-gyro",
.data = LSM330_GYRO_DEV_NAME,
},
{
.compatible = "st,lsm9ds0-gyro",
.data = LSM9DS0_GYRO_DEV_NAME,
},
{},
};
MODULE_DEVICE_TABLE(of, st_gyro_of_match);
#else
#define st_gyro_of_match NULL
#endif
static int st_gyro_spi_probe(struct spi_device *spi) static int st_gyro_spi_probe(struct spi_device *spi)
{ {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
...@@ -30,6 +80,8 @@ static int st_gyro_spi_probe(struct spi_device *spi) ...@@ -30,6 +80,8 @@ static int st_gyro_spi_probe(struct spi_device *spi)
gdata = iio_priv(indio_dev); gdata = iio_priv(indio_dev);
st_sensors_of_name_probe(&spi->dev, st_gyro_of_match,
spi->modalias, sizeof(spi->modalias));
st_sensors_spi_configure(indio_dev, spi, gdata); st_sensors_spi_configure(indio_dev, spi, gdata);
err = st_gyro_common_probe(indio_dev); err = st_gyro_common_probe(indio_dev);
...@@ -52,6 +104,7 @@ static const struct spi_device_id st_gyro_id_table[] = { ...@@ -52,6 +104,7 @@ static const struct spi_device_id st_gyro_id_table[] = {
{ LSM330DL_GYRO_DEV_NAME }, { LSM330DL_GYRO_DEV_NAME },
{ LSM330DLC_GYRO_DEV_NAME }, { LSM330DLC_GYRO_DEV_NAME },
{ L3GD20_GYRO_DEV_NAME }, { L3GD20_GYRO_DEV_NAME },
{ L3GD20H_GYRO_DEV_NAME },
{ L3G4IS_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME },
{ LSM330_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME },
{ LSM9DS0_GYRO_DEV_NAME }, { LSM9DS0_GYRO_DEV_NAME },
...@@ -62,6 +115,7 @@ MODULE_DEVICE_TABLE(spi, st_gyro_id_table); ...@@ -62,6 +115,7 @@ MODULE_DEVICE_TABLE(spi, st_gyro_id_table);
static struct spi_driver st_gyro_driver = { static struct spi_driver st_gyro_driver = {
.driver = { .driver = {
.name = "st-gyro-spi", .name = "st-gyro-spi",
.of_match_table = of_match_ptr(st_gyro_of_match),
}, },
.probe = st_gyro_spi_probe, .probe = st_gyro_spi_probe,
.remove = st_gyro_spi_remove, .remove = st_gyro_spi_remove,
......
...@@ -31,7 +31,8 @@ config HDC100X ...@@ -31,7 +31,8 @@ config HDC100X
select IIO_TRIGGERED_BUFFER select IIO_TRIGGERED_BUFFER
help help
Say yes here to build support for the Texas Instruments Say yes here to build support for the Texas Instruments
HDC1000 and HDC1008 relative humidity and temperature sensors. HDC1000, HDC1008, HDC1010, HDC1050, and HDC1080 relative
humidity and temperature sensors.
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called hdc100x. will be called hdc100x.
......
...@@ -13,6 +13,12 @@ ...@@ -13,6 +13,12 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* Datasheets:
* http://www.ti.com/product/HDC1000/datasheet
* http://www.ti.com/product/HDC1008/datasheet
* http://www.ti.com/product/HDC1010/datasheet
* http://www.ti.com/product/HDC1050/datasheet
* http://www.ti.com/product/HDC1080/datasheet
*/ */
#include <linux/delay.h> #include <linux/delay.h>
...@@ -414,13 +420,29 @@ static int hdc100x_remove(struct i2c_client *client) ...@@ -414,13 +420,29 @@ static int hdc100x_remove(struct i2c_client *client)
static const struct i2c_device_id hdc100x_id[] = { static const struct i2c_device_id hdc100x_id[] = {
{ "hdc100x", 0 }, { "hdc100x", 0 },
{ "hdc1000", 0 },
{ "hdc1008", 0 },
{ "hdc1010", 0 },
{ "hdc1050", 0 },
{ "hdc1080", 0 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, hdc100x_id); MODULE_DEVICE_TABLE(i2c, hdc100x_id);
static const struct of_device_id hdc100x_dt_ids[] = {
{ .compatible = "ti,hdc1000" },
{ .compatible = "ti,hdc1008" },
{ .compatible = "ti,hdc1010" },
{ .compatible = "ti,hdc1050" },
{ .compatible = "ti,hdc1080" },
{ }
};
MODULE_DEVICE_TABLE(of, hdc100x_dt_ids);
static struct i2c_driver hdc100x_driver = { static struct i2c_driver hdc100x_driver = {
.driver = { .driver = {
.name = "hdc100x", .name = "hdc100x",
.of_match_table = of_match_ptr(hdc100x_dt_ids),
}, },
.probe = hdc100x_probe, .probe = hdc100x_probe,
.remove = hdc100x_remove, .remove = hdc100x_remove,
......
...@@ -30,12 +30,6 @@ struct hts221_transfer_function { ...@@ -30,12 +30,6 @@ struct hts221_transfer_function {
int (*write)(struct device *dev, u8 addr, int len, u8 *data); int (*write)(struct device *dev, u8 addr, int len, u8 *data);
}; };
#define HTS221_AVG_DEPTH 8
struct hts221_avg_avl {
u16 avg;
u8 val;
};
enum hts221_sensor_type { enum hts221_sensor_type {
HTS221_SENSOR_H, HTS221_SENSOR_H,
HTS221_SENSOR_T, HTS221_SENSOR_T,
...@@ -66,10 +60,9 @@ struct hts221_hw { ...@@ -66,10 +60,9 @@ struct hts221_hw {
extern const struct dev_pm_ops hts221_pm_ops; extern const struct dev_pm_ops hts221_pm_ops;
int hts221_config_drdy(struct hts221_hw *hw, bool enable); int hts221_write_with_mask(struct hts221_hw *hw, u8 addr, u8 mask, u8 val);
int hts221_probe(struct iio_dev *iio_dev); int hts221_probe(struct iio_dev *iio_dev);
int hts221_power_on(struct hts221_hw *hw); int hts221_set_enable(struct hts221_hw *hw, bool enable);
int hts221_power_off(struct hts221_hw *hw);
int hts221_allocate_buffers(struct hts221_hw *hw); int hts221_allocate_buffers(struct hts221_hw *hw);
int hts221_allocate_trigger(struct hts221_hw *hw); int hts221_allocate_trigger(struct hts221_hw *hw);
......
...@@ -20,8 +20,16 @@ ...@@ -20,8 +20,16 @@
#include <linux/iio/triggered_buffer.h> #include <linux/iio/triggered_buffer.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/platform_data/st_sensors_pdata.h>
#include "hts221.h" #include "hts221.h"
#define HTS221_REG_DRDY_HL_ADDR 0x22
#define HTS221_REG_DRDY_HL_MASK BIT(7)
#define HTS221_REG_DRDY_PP_OD_ADDR 0x22
#define HTS221_REG_DRDY_PP_OD_MASK BIT(6)
#define HTS221_REG_DRDY_EN_ADDR 0x22
#define HTS221_REG_DRDY_EN_MASK BIT(2)
#define HTS221_REG_STATUS_ADDR 0x27 #define HTS221_REG_STATUS_ADDR 0x27
#define HTS221_RH_DRDY_MASK BIT(1) #define HTS221_RH_DRDY_MASK BIT(1)
#define HTS221_TEMP_DRDY_MASK BIT(0) #define HTS221_TEMP_DRDY_MASK BIT(0)
...@@ -30,8 +38,12 @@ static int hts221_trig_set_state(struct iio_trigger *trig, bool state) ...@@ -30,8 +38,12 @@ static int hts221_trig_set_state(struct iio_trigger *trig, bool state)
{ {
struct iio_dev *iio_dev = iio_trigger_get_drvdata(trig); struct iio_dev *iio_dev = iio_trigger_get_drvdata(trig);
struct hts221_hw *hw = iio_priv(iio_dev); struct hts221_hw *hw = iio_priv(iio_dev);
int err;
err = hts221_write_with_mask(hw, HTS221_REG_DRDY_EN_ADDR,
HTS221_REG_DRDY_EN_MASK, state);
return hts221_config_drdy(hw, state); return err < 0 ? err : 0;
} }
static const struct iio_trigger_ops hts221_trigger_ops = { static const struct iio_trigger_ops hts221_trigger_ops = {
...@@ -67,6 +79,9 @@ static irqreturn_t hts221_trigger_handler_thread(int irq, void *private) ...@@ -67,6 +79,9 @@ static irqreturn_t hts221_trigger_handler_thread(int irq, void *private)
int hts221_allocate_trigger(struct hts221_hw *hw) int hts221_allocate_trigger(struct hts221_hw *hw)
{ {
struct iio_dev *iio_dev = iio_priv_to_dev(hw); struct iio_dev *iio_dev = iio_priv_to_dev(hw);
bool irq_active_low = false, open_drain = false;
struct device_node *np = hw->dev->of_node;
struct st_sensors_platform_data *pdata;
unsigned long irq_type; unsigned long irq_type;
int err; int err;
...@@ -76,6 +91,10 @@ int hts221_allocate_trigger(struct hts221_hw *hw) ...@@ -76,6 +91,10 @@ int hts221_allocate_trigger(struct hts221_hw *hw)
case IRQF_TRIGGER_HIGH: case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING: case IRQF_TRIGGER_RISING:
break; break;
case IRQF_TRIGGER_LOW:
case IRQF_TRIGGER_FALLING:
irq_active_low = true;
break;
default: default:
dev_info(hw->dev, dev_info(hw->dev,
"mode %lx unsupported, using IRQF_TRIGGER_RISING\n", "mode %lx unsupported, using IRQF_TRIGGER_RISING\n",
...@@ -84,6 +103,24 @@ int hts221_allocate_trigger(struct hts221_hw *hw) ...@@ -84,6 +103,24 @@ int hts221_allocate_trigger(struct hts221_hw *hw)
break; break;
} }
err = hts221_write_with_mask(hw, HTS221_REG_DRDY_HL_ADDR,
HTS221_REG_DRDY_HL_MASK, irq_active_low);
if (err < 0)
return err;
pdata = (struct st_sensors_platform_data *)hw->dev->platform_data;
if ((np && of_property_read_bool(np, "drive-open-drain")) ||
(pdata && pdata->open_drain)) {
irq_type |= IRQF_SHARED;
open_drain = true;
}
err = hts221_write_with_mask(hw, HTS221_REG_DRDY_PP_OD_ADDR,
HTS221_REG_DRDY_PP_OD_MASK,
open_drain);
if (err < 0)
return err;
err = devm_request_threaded_irq(hw->dev, hw->irq, NULL, err = devm_request_threaded_irq(hw->dev, hw->irq, NULL,
hts221_trigger_handler_thread, hts221_trigger_handler_thread,
irq_type | IRQF_ONESHOT, irq_type | IRQF_ONESHOT,
...@@ -109,12 +146,12 @@ int hts221_allocate_trigger(struct hts221_hw *hw) ...@@ -109,12 +146,12 @@ int hts221_allocate_trigger(struct hts221_hw *hw)
static int hts221_buffer_preenable(struct iio_dev *iio_dev) static int hts221_buffer_preenable(struct iio_dev *iio_dev)
{ {
return hts221_power_on(iio_priv(iio_dev)); return hts221_set_enable(iio_priv(iio_dev), true);
} }
static int hts221_buffer_postdisable(struct iio_dev *iio_dev) static int hts221_buffer_postdisable(struct iio_dev *iio_dev)
{ {
return hts221_power_off(iio_priv(iio_dev)); return hts221_set_enable(iio_priv(iio_dev), false);
} }
static const struct iio_buffer_setup_ops hts221_buffer_ops = { static const struct iio_buffer_setup_ops hts221_buffer_ops = {
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#define HTS221_REG_CNTRL1_ADDR 0x20 #define HTS221_REG_CNTRL1_ADDR 0x20
#define HTS221_REG_CNTRL2_ADDR 0x21 #define HTS221_REG_CNTRL2_ADDR 0x21
#define HTS221_REG_CNTRL3_ADDR 0x22
#define HTS221_REG_AVG_ADDR 0x10 #define HTS221_REG_AVG_ADDR 0x10
#define HTS221_REG_H_OUT_L 0x28 #define HTS221_REG_H_OUT_L 0x28
...@@ -32,30 +31,9 @@ ...@@ -32,30 +31,9 @@
#define HTS221_HUMIDITY_AVG_MASK 0x07 #define HTS221_HUMIDITY_AVG_MASK 0x07
#define HTS221_TEMP_AVG_MASK 0x38 #define HTS221_TEMP_AVG_MASK 0x38
#define HTS221_ODR_MASK 0x87 #define HTS221_ODR_MASK 0x03
#define HTS221_BDU_MASK BIT(2) #define HTS221_BDU_MASK BIT(2)
#define HTS221_ENABLE_MASK BIT(7)
#define HTS221_DRDY_MASK BIT(2)
#define HTS221_ENABLE_SENSOR BIT(7)
#define HTS221_HUMIDITY_AVG_4 0x00 /* 0.4 %RH */
#define HTS221_HUMIDITY_AVG_8 0x01 /* 0.3 %RH */
#define HTS221_HUMIDITY_AVG_16 0x02 /* 0.2 %RH */
#define HTS221_HUMIDITY_AVG_32 0x03 /* 0.15 %RH */
#define HTS221_HUMIDITY_AVG_64 0x04 /* 0.1 %RH */
#define HTS221_HUMIDITY_AVG_128 0x05 /* 0.07 %RH */
#define HTS221_HUMIDITY_AVG_256 0x06 /* 0.05 %RH */
#define HTS221_HUMIDITY_AVG_512 0x07 /* 0.03 %RH */
#define HTS221_TEMP_AVG_2 0x00 /* 0.08 degC */
#define HTS221_TEMP_AVG_4 0x08 /* 0.05 degC */
#define HTS221_TEMP_AVG_8 0x10 /* 0.04 degC */
#define HTS221_TEMP_AVG_16 0x18 /* 0.03 degC */
#define HTS221_TEMP_AVG_32 0x20 /* 0.02 degC */
#define HTS221_TEMP_AVG_64 0x28 /* 0.015 degC */
#define HTS221_TEMP_AVG_128 0x30 /* 0.01 degC */
#define HTS221_TEMP_AVG_256 0x38 /* 0.007 degC */
/* calibration registers */ /* calibration registers */
#define HTS221_REG_0RH_CAL_X_H 0x36 #define HTS221_REG_0RH_CAL_X_H 0x36
...@@ -73,10 +51,11 @@ struct hts221_odr { ...@@ -73,10 +51,11 @@ struct hts221_odr {
u8 val; u8 val;
}; };
#define HTS221_AVG_DEPTH 8
struct hts221_avg { struct hts221_avg {
u8 addr; u8 addr;
u8 mask; u8 mask;
struct hts221_avg_avl avg_avl[HTS221_AVG_DEPTH]; u16 avg_avl[HTS221_AVG_DEPTH];
}; };
static const struct hts221_odr hts221_odr_table[] = { static const struct hts221_odr hts221_odr_table[] = {
...@@ -90,28 +69,28 @@ static const struct hts221_avg hts221_avg_list[] = { ...@@ -90,28 +69,28 @@ static const struct hts221_avg hts221_avg_list[] = {
.addr = HTS221_REG_AVG_ADDR, .addr = HTS221_REG_AVG_ADDR,
.mask = HTS221_HUMIDITY_AVG_MASK, .mask = HTS221_HUMIDITY_AVG_MASK,
.avg_avl = { .avg_avl = {
{ 4, HTS221_HUMIDITY_AVG_4 }, 4, /* 0.4 %RH */
{ 8, HTS221_HUMIDITY_AVG_8 }, 8, /* 0.3 %RH */
{ 16, HTS221_HUMIDITY_AVG_16 }, 16, /* 0.2 %RH */
{ 32, HTS221_HUMIDITY_AVG_32 }, 32, /* 0.15 %RH */
{ 64, HTS221_HUMIDITY_AVG_64 }, 64, /* 0.1 %RH */
{ 128, HTS221_HUMIDITY_AVG_128 }, 128, /* 0.07 %RH */
{ 256, HTS221_HUMIDITY_AVG_256 }, 256, /* 0.05 %RH */
{ 512, HTS221_HUMIDITY_AVG_512 }, 512, /* 0.03 %RH */
}, },
}, },
{ {
.addr = HTS221_REG_AVG_ADDR, .addr = HTS221_REG_AVG_ADDR,
.mask = HTS221_TEMP_AVG_MASK, .mask = HTS221_TEMP_AVG_MASK,
.avg_avl = { .avg_avl = {
{ 2, HTS221_TEMP_AVG_2 }, 2, /* 0.08 degC */
{ 4, HTS221_TEMP_AVG_4 }, 4, /* 0.05 degC */
{ 8, HTS221_TEMP_AVG_8 }, 8, /* 0.04 degC */
{ 16, HTS221_TEMP_AVG_16 }, 16, /* 0.03 degC */
{ 32, HTS221_TEMP_AVG_32 }, 32, /* 0.02 degC */
{ 64, HTS221_TEMP_AVG_64 }, 64, /* 0.015 degC */
{ 128, HTS221_TEMP_AVG_128 }, 128, /* 0.01 degC */
{ 256, HTS221_TEMP_AVG_256 }, 256, /* 0.007 degC */
}, },
}, },
}; };
...@@ -152,8 +131,7 @@ static const struct iio_chan_spec hts221_channels[] = { ...@@ -152,8 +131,7 @@ static const struct iio_chan_spec hts221_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(2), IIO_CHAN_SOFT_TIMESTAMP(2),
}; };
static int hts221_write_with_mask(struct hts221_hw *hw, u8 addr, u8 mask, int hts221_write_with_mask(struct hts221_hw *hw, u8 addr, u8 mask, u8 val)
u8 val)
{ {
u8 data; u8 data;
int err; int err;
...@@ -166,7 +144,7 @@ static int hts221_write_with_mask(struct hts221_hw *hw, u8 addr, u8 mask, ...@@ -166,7 +144,7 @@ static int hts221_write_with_mask(struct hts221_hw *hw, u8 addr, u8 mask,
goto unlock; goto unlock;
} }
data = (data & ~mask) | (val & mask); data = (data & ~mask) | ((val << __ffs(mask)) & mask);
err = hw->tf->write(hw->dev, addr, sizeof(data), &data); err = hw->tf->write(hw->dev, addr, sizeof(data), &data);
if (err < 0) if (err < 0)
...@@ -199,21 +177,9 @@ static int hts221_check_whoami(struct hts221_hw *hw) ...@@ -199,21 +177,9 @@ static int hts221_check_whoami(struct hts221_hw *hw)
return 0; return 0;
} }
int hts221_config_drdy(struct hts221_hw *hw, bool enable)
{
u8 val = enable ? BIT(2) : 0;
int err;
err = hts221_write_with_mask(hw, HTS221_REG_CNTRL3_ADDR,
HTS221_DRDY_MASK, val);
return err < 0 ? err : 0;
}
static int hts221_update_odr(struct hts221_hw *hw, u8 odr) static int hts221_update_odr(struct hts221_hw *hw, u8 odr)
{ {
int i, err; int i, err;
u8 val;
for (i = 0; i < ARRAY_SIZE(hts221_odr_table); i++) for (i = 0; i < ARRAY_SIZE(hts221_odr_table); i++)
if (hts221_odr_table[i].hz == odr) if (hts221_odr_table[i].hz == odr)
...@@ -222,9 +188,8 @@ static int hts221_update_odr(struct hts221_hw *hw, u8 odr) ...@@ -222,9 +188,8 @@ static int hts221_update_odr(struct hts221_hw *hw, u8 odr)
if (i == ARRAY_SIZE(hts221_odr_table)) if (i == ARRAY_SIZE(hts221_odr_table))
return -EINVAL; return -EINVAL;
val = HTS221_ENABLE_SENSOR | HTS221_BDU_MASK | hts221_odr_table[i].val;
err = hts221_write_with_mask(hw, HTS221_REG_CNTRL1_ADDR, err = hts221_write_with_mask(hw, HTS221_REG_CNTRL1_ADDR,
HTS221_ODR_MASK, val); HTS221_ODR_MASK, hts221_odr_table[i].val);
if (err < 0) if (err < 0)
return err; return err;
...@@ -241,14 +206,13 @@ static int hts221_update_avg(struct hts221_hw *hw, ...@@ -241,14 +206,13 @@ static int hts221_update_avg(struct hts221_hw *hw,
const struct hts221_avg *avg = &hts221_avg_list[type]; const struct hts221_avg *avg = &hts221_avg_list[type];
for (i = 0; i < HTS221_AVG_DEPTH; i++) for (i = 0; i < HTS221_AVG_DEPTH; i++)
if (avg->avg_avl[i].avg == val) if (avg->avg_avl[i] == val)
break; break;
if (i == HTS221_AVG_DEPTH) if (i == HTS221_AVG_DEPTH)
return -EINVAL; return -EINVAL;
err = hts221_write_with_mask(hw, avg->addr, avg->mask, err = hts221_write_with_mask(hw, avg->addr, avg->mask, i);
avg->avg_avl[i].val);
if (err < 0) if (err < 0)
return err; return err;
...@@ -283,7 +247,7 @@ hts221_sysfs_rh_oversampling_avail(struct device *dev, ...@@ -283,7 +247,7 @@ hts221_sysfs_rh_oversampling_avail(struct device *dev,
for (i = 0; i < ARRAY_SIZE(avg->avg_avl); i++) for (i = 0; i < ARRAY_SIZE(avg->avg_avl); i++)
len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
avg->avg_avl[i].avg); avg->avg_avl[i]);
buf[len - 1] = '\n'; buf[len - 1] = '\n';
return len; return len;
...@@ -300,36 +264,22 @@ hts221_sysfs_temp_oversampling_avail(struct device *dev, ...@@ -300,36 +264,22 @@ hts221_sysfs_temp_oversampling_avail(struct device *dev,
for (i = 0; i < ARRAY_SIZE(avg->avg_avl); i++) for (i = 0; i < ARRAY_SIZE(avg->avg_avl); i++)
len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
avg->avg_avl[i].avg); avg->avg_avl[i]);
buf[len - 1] = '\n'; buf[len - 1] = '\n';
return len; return len;
} }
int hts221_power_on(struct hts221_hw *hw) int hts221_set_enable(struct hts221_hw *hw, bool enable)
{
int err;
err = hts221_update_odr(hw, hw->odr);
if (err < 0)
return err;
hw->enabled = true;
return 0;
}
int hts221_power_off(struct hts221_hw *hw)
{ {
__le16 data = 0;
int err; int err;
err = hw->tf->write(hw->dev, HTS221_REG_CNTRL1_ADDR, sizeof(data), err = hts221_write_with_mask(hw, HTS221_REG_CNTRL1_ADDR,
(u8 *)&data); HTS221_ENABLE_MASK, enable);
if (err < 0) if (err < 0)
return err; return err;
hw->enabled = false; hw->enabled = enable;
return 0; return 0;
} }
...@@ -484,7 +434,7 @@ static int hts221_read_oneshot(struct hts221_hw *hw, u8 addr, int *val) ...@@ -484,7 +434,7 @@ static int hts221_read_oneshot(struct hts221_hw *hw, u8 addr, int *val)
u8 data[HTS221_DATA_SIZE]; u8 data[HTS221_DATA_SIZE];
int err; int err;
err = hts221_power_on(hw); err = hts221_set_enable(hw, true);
if (err < 0) if (err < 0)
return err; return err;
...@@ -494,7 +444,7 @@ static int hts221_read_oneshot(struct hts221_hw *hw, u8 addr, int *val) ...@@ -494,7 +444,7 @@ static int hts221_read_oneshot(struct hts221_hw *hw, u8 addr, int *val)
if (err < 0) if (err < 0)
return err; return err;
hts221_power_off(hw); hts221_set_enable(hw, false);
*val = (s16)get_unaligned_le16(data); *val = (s16)get_unaligned_le16(data);
...@@ -534,13 +484,13 @@ static int hts221_read_raw(struct iio_dev *iio_dev, ...@@ -534,13 +484,13 @@ static int hts221_read_raw(struct iio_dev *iio_dev,
case IIO_HUMIDITYRELATIVE: case IIO_HUMIDITYRELATIVE:
avg = &hts221_avg_list[HTS221_SENSOR_H]; avg = &hts221_avg_list[HTS221_SENSOR_H];
idx = hw->sensors[HTS221_SENSOR_H].cur_avg_idx; idx = hw->sensors[HTS221_SENSOR_H].cur_avg_idx;
*val = avg->avg_avl[idx].avg; *val = avg->avg_avl[idx];
ret = IIO_VAL_INT; ret = IIO_VAL_INT;
break; break;
case IIO_TEMP: case IIO_TEMP:
avg = &hts221_avg_list[HTS221_SENSOR_T]; avg = &hts221_avg_list[HTS221_SENSOR_T];
idx = hw->sensors[HTS221_SENSOR_T].cur_avg_idx; idx = hw->sensors[HTS221_SENSOR_T].cur_avg_idx;
*val = avg->avg_avl[idx].avg; *val = avg->avg_avl[idx];
ret = IIO_VAL_INT; ret = IIO_VAL_INT;
break; break;
default: default:
...@@ -644,8 +594,6 @@ int hts221_probe(struct iio_dev *iio_dev) ...@@ -644,8 +594,6 @@ int hts221_probe(struct iio_dev *iio_dev)
if (err < 0) if (err < 0)
return err; return err;
hw->odr = hts221_odr_table[0].hz;
iio_dev->modes = INDIO_DIRECT_MODE; iio_dev->modes = INDIO_DIRECT_MODE;
iio_dev->dev.parent = hw->dev; iio_dev->dev.parent = hw->dev;
iio_dev->available_scan_masks = hts221_scan_masks; iio_dev->available_scan_masks = hts221_scan_masks;
...@@ -654,6 +602,16 @@ int hts221_probe(struct iio_dev *iio_dev) ...@@ -654,6 +602,16 @@ int hts221_probe(struct iio_dev *iio_dev)
iio_dev->name = HTS221_DEV_NAME; iio_dev->name = HTS221_DEV_NAME;
iio_dev->info = &hts221_info; iio_dev->info = &hts221_info;
/* enable Block Data Update */
err = hts221_write_with_mask(hw, HTS221_REG_CNTRL1_ADDR,
HTS221_BDU_MASK, 1);
if (err < 0)
return err;
err = hts221_update_odr(hw, hts221_odr_table[0].hz);
if (err < 0)
return err;
/* configure humidity sensor */ /* configure humidity sensor */
err = hts221_parse_rh_caldata(hw); err = hts221_parse_rh_caldata(hw);
if (err < 0) { if (err < 0) {
...@@ -661,7 +619,7 @@ int hts221_probe(struct iio_dev *iio_dev) ...@@ -661,7 +619,7 @@ int hts221_probe(struct iio_dev *iio_dev)
return err; return err;
} }
data = hts221_avg_list[HTS221_SENSOR_H].avg_avl[3].avg; data = hts221_avg_list[HTS221_SENSOR_H].avg_avl[3];
err = hts221_update_avg(hw, HTS221_SENSOR_H, data); err = hts221_update_avg(hw, HTS221_SENSOR_H, data);
if (err < 0) { if (err < 0) {
dev_err(hw->dev, "failed to set rh oversampling ratio\n"); dev_err(hw->dev, "failed to set rh oversampling ratio\n");
...@@ -676,7 +634,7 @@ int hts221_probe(struct iio_dev *iio_dev) ...@@ -676,7 +634,7 @@ int hts221_probe(struct iio_dev *iio_dev)
return err; return err;
} }
data = hts221_avg_list[HTS221_SENSOR_T].avg_avl[3].avg; data = hts221_avg_list[HTS221_SENSOR_T].avg_avl[3];
err = hts221_update_avg(hw, HTS221_SENSOR_T, data); err = hts221_update_avg(hw, HTS221_SENSOR_T, data);
if (err < 0) { if (err < 0) {
dev_err(hw->dev, dev_err(hw->dev,
...@@ -702,11 +660,10 @@ static int __maybe_unused hts221_suspend(struct device *dev) ...@@ -702,11 +660,10 @@ static int __maybe_unused hts221_suspend(struct device *dev)
{ {
struct iio_dev *iio_dev = dev_get_drvdata(dev); struct iio_dev *iio_dev = dev_get_drvdata(dev);
struct hts221_hw *hw = iio_priv(iio_dev); struct hts221_hw *hw = iio_priv(iio_dev);
__le16 data = 0;
int err; int err;
err = hw->tf->write(hw->dev, HTS221_REG_CNTRL1_ADDR, sizeof(data), err = hts221_write_with_mask(hw, HTS221_REG_CNTRL1_ADDR,
(u8 *)&data); HTS221_ENABLE_MASK, false);
return err < 0 ? err : 0; return err < 0 ? err : 0;
} }
...@@ -718,7 +675,8 @@ static int __maybe_unused hts221_resume(struct device *dev) ...@@ -718,7 +675,8 @@ static int __maybe_unused hts221_resume(struct device *dev)
int err = 0; int err = 0;
if (hw->enabled) if (hw->enabled)
err = hts221_update_odr(hw, hw->odr); err = hts221_write_with_mask(hw, HTS221_REG_CNTRL1_ADDR,
HTS221_ENABLE_MASK, true);
return err; return err;
} }
......
...@@ -238,11 +238,19 @@ static const struct i2c_device_id htu21_id[] = { ...@@ -238,11 +238,19 @@ static const struct i2c_device_id htu21_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, htu21_id); MODULE_DEVICE_TABLE(i2c, htu21_id);
static const struct of_device_id htu21_of_match[] = {
{ .compatible = "meas,htu21", },
{ .compatible = "meas,ms8607-humidity", },
{ },
};
MODULE_DEVICE_TABLE(of, htu21_of_match);
static struct i2c_driver htu21_driver = { static struct i2c_driver htu21_driver = {
.probe = htu21_probe, .probe = htu21_probe,
.id_table = htu21_id, .id_table = htu21_id,
.driver = { .driver = {
.name = "htu21", .name = "htu21",
.of_match_table = of_match_ptr(htu21_of_match),
}, },
}; };
......
...@@ -217,7 +217,7 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq) ...@@ -217,7 +217,7 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq)
return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val); return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val);
} }
static const unsigned adis16400_3db_divisors[] = { static const unsigned int adis16400_3db_divisors[] = {
[0] = 2, /* Special case */ [0] = 2, /* Special case */
[1] = 6, [1] = 6,
[2] = 12, [2] = 12,
...@@ -890,7 +890,7 @@ static const struct adis_data adis16400_data = { ...@@ -890,7 +890,7 @@ static const struct adis_data adis16400_data = {
static void adis16400_setup_chan_mask(struct adis16400_state *st) static void adis16400_setup_chan_mask(struct adis16400_state *st)
{ {
const struct adis16400_chip_info *chip_info = st->variant; const struct adis16400_chip_info *chip_info = st->variant;
unsigned i; unsigned int i;
for (i = 0; i < chip_info->num_channels; i++) { for (i = 0; i < chip_info->num_channels; i++) {
const struct iio_chan_spec *ch = &chip_info->channels[i]; const struct iio_chan_spec *ch = &chip_info->channels[i];
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/platform_data/st_sensors_pdata.h>
#include "st_lsm6dsx.h" #include "st_lsm6dsx.h"
#define ST_LSM6DSX_REG_FIFO_THL_ADDR 0x06 #define ST_LSM6DSX_REG_FIFO_THL_ADDR 0x06
...@@ -39,6 +41,8 @@ ...@@ -39,6 +41,8 @@
#define ST_LSM6DSX_REG_FIFO_DEC_GXL_ADDR 0x08 #define ST_LSM6DSX_REG_FIFO_DEC_GXL_ADDR 0x08
#define ST_LSM6DSX_REG_HLACTIVE_ADDR 0x12 #define ST_LSM6DSX_REG_HLACTIVE_ADDR 0x12
#define ST_LSM6DSX_REG_HLACTIVE_MASK BIT(5) #define ST_LSM6DSX_REG_HLACTIVE_MASK BIT(5)
#define ST_LSM6DSX_REG_PP_OD_ADDR 0x12
#define ST_LSM6DSX_REG_PP_OD_MASK BIT(4)
#define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a #define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a
#define ST_LSM6DSX_FIFO_MODE_MASK GENMASK(2, 0) #define ST_LSM6DSX_FIFO_MODE_MASK GENMASK(2, 0)
#define ST_LSM6DSX_FIFO_ODR_MASK GENMASK(6, 3) #define ST_LSM6DSX_FIFO_ODR_MASK GENMASK(6, 3)
...@@ -417,6 +421,8 @@ static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = { ...@@ -417,6 +421,8 @@ static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = {
int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
{ {
struct device_node *np = hw->dev->of_node;
struct st_sensors_platform_data *pdata;
struct iio_buffer *buffer; struct iio_buffer *buffer;
unsigned long irq_type; unsigned long irq_type;
bool irq_active_low; bool irq_active_low;
...@@ -444,6 +450,17 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) ...@@ -444,6 +450,17 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
if (err < 0) if (err < 0)
return err; return err;
pdata = (struct st_sensors_platform_data *)hw->dev->platform_data;
if ((np && of_property_read_bool(np, "drive-open-drain")) ||
(pdata && pdata->open_drain)) {
err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_PP_OD_ADDR,
ST_LSM6DSX_REG_PP_OD_MASK, 1);
if (err < 0)
return err;
irq_type |= IRQF_SHARED;
}
err = devm_request_threaded_irq(hw->dev, hw->irq, err = devm_request_threaded_irq(hw->dev, hw->irq,
st_lsm6dsx_handler_irq, st_lsm6dsx_handler_irq,
st_lsm6dsx_handler_thread, st_lsm6dsx_handler_thread,
......
...@@ -44,7 +44,7 @@ int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps) ...@@ -44,7 +44,7 @@ int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps)
} }
mapi->map = &maps[i]; mapi->map = &maps[i];
mapi->indio_dev = indio_dev; mapi->indio_dev = indio_dev;
list_add(&mapi->l, &iio_map_list); list_add_tail(&mapi->l, &iio_map_list);
i++; i++;
} }
error_ret: error_ret:
...@@ -205,8 +205,8 @@ static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np, ...@@ -205,8 +205,8 @@ static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER) if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER)
break; break;
else if (name && index >= 0) { else if (name && index >= 0) {
pr_err("ERROR: could not get IIO channel %s:%s(%i)\n", pr_err("ERROR: could not get IIO channel %pOF:%s(%i)\n",
np->full_name, name ? name : "", index); np, name ? name : "", index);
return NULL; return NULL;
} }
......
This diff is collapsed.
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
* 7-bit I2C slave address 0x39 (TCS34721, TCS34723) or 0x29 (TCS34725, * 7-bit I2C slave address 0x39 (TCS34721, TCS34723) or 0x29 (TCS34725,
* TCS34727) * TCS34727)
* *
* Datasheet: http://ams.com/eng/content/download/319364/1117183/file/TCS3472_Datasheet_EN_v2.pdf
*
* TODO: interrupt support, thresholds, wait time * TODO: interrupt support, thresholds, wait time
*/ */
...@@ -169,7 +171,7 @@ static int tcs3472_write_raw(struct iio_dev *indio_dev, ...@@ -169,7 +171,7 @@ static int tcs3472_write_raw(struct iio_dev *indio_dev,
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
if (val2 == (256 - i) * 2400) { if (val2 == (256 - i) * 2400) {
data->atime = i; data->atime = i;
return i2c_smbus_write_word_data( return i2c_smbus_write_byte_data(
data->client, TCS3472_ATIME, data->client, TCS3472_ATIME,
data->atime); data->atime);
} }
......
...@@ -784,6 +784,7 @@ static const struct iio_info ak8975_info = { ...@@ -784,6 +784,7 @@ static const struct iio_info ak8975_info = {
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
}; };
#ifdef CONFIG_ACPI
static const struct acpi_device_id ak_acpi_match[] = { static const struct acpi_device_id ak_acpi_match[] = {
{"AK8975", AK8975}, {"AK8975", AK8975},
{"AK8963", AK8963}, {"AK8963", AK8963},
...@@ -793,6 +794,7 @@ static const struct acpi_device_id ak_acpi_match[] = { ...@@ -793,6 +794,7 @@ static const struct acpi_device_id ak_acpi_match[] = {
{ }, { },
}; };
MODULE_DEVICE_TABLE(acpi, ak_acpi_match); MODULE_DEVICE_TABLE(acpi, ak_acpi_match);
#endif
static const char *ak8975_match_acpi_device(struct device *dev, static const char *ak8975_match_acpi_device(struct device *dev,
enum asahi_compass_chipset *chipset) enum asahi_compass_chipset *chipset)
......
...@@ -315,7 +315,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = { ...@@ -315,7 +315,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
}, },
}, },
}, },
.multi_read_bit = false, .multi_read_bit = true,
.bootime = 2, .bootime = 2,
}, },
{ {
......
...@@ -59,7 +59,8 @@ static int st_magn_i2c_probe(struct i2c_client *client, ...@@ -59,7 +59,8 @@ static int st_magn_i2c_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
mdata = iio_priv(indio_dev); mdata = iio_priv(indio_dev);
st_sensors_of_i2c_probe(client, st_magn_of_match); st_sensors_of_name_probe(&client->dev, st_magn_of_match,
client->name, sizeof(client->name));
st_sensors_i2c_configure(indio_dev, client, mdata); st_sensors_i2c_configure(indio_dev, client, mdata);
......
...@@ -18,6 +18,28 @@ ...@@ -18,6 +18,28 @@
#include <linux/iio/common/st_sensors_spi.h> #include <linux/iio/common/st_sensors_spi.h>
#include "st_magn.h" #include "st_magn.h"
#ifdef CONFIG_OF
/*
* For new single-chip sensors use <device_name> as compatible string.
* For old single-chip devices keep <device_name>-magn to maintain
* compatibility
*/
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);
#else
#define st_magn_of_match NULL
#endif
static int st_magn_spi_probe(struct spi_device *spi) static int st_magn_spi_probe(struct spi_device *spi)
{ {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
...@@ -30,6 +52,8 @@ static int st_magn_spi_probe(struct spi_device *spi) ...@@ -30,6 +52,8 @@ static int st_magn_spi_probe(struct spi_device *spi)
mdata = iio_priv(indio_dev); mdata = iio_priv(indio_dev);
st_sensors_of_name_probe(&spi->dev, st_magn_of_match,
spi->modalias, sizeof(spi->modalias));
st_sensors_spi_configure(indio_dev, spi, mdata); st_sensors_spi_configure(indio_dev, spi, mdata);
err = st_magn_common_probe(indio_dev); err = st_magn_common_probe(indio_dev);
...@@ -57,6 +81,7 @@ MODULE_DEVICE_TABLE(spi, st_magn_id_table); ...@@ -57,6 +81,7 @@ MODULE_DEVICE_TABLE(spi, st_magn_id_table);
static struct spi_driver st_magn_driver = { static struct spi_driver st_magn_driver = {
.driver = { .driver = {
.name = "st-magn-spi", .name = "st-magn-spi",
.of_match_table = of_match_ptr(st_magn_of_match),
}, },
.probe = st_magn_spi_probe, .probe = st_magn_spi_probe,
.remove = st_magn_spi_remove, .remove = st_magn_spi_remove,
......
...@@ -238,7 +238,7 @@ static int dev_rot_parse_report(struct platform_device *pdev, ...@@ -238,7 +238,7 @@ static int dev_rot_parse_report(struct platform_device *pdev,
static int hid_dev_rot_probe(struct platform_device *pdev) static int hid_dev_rot_probe(struct platform_device *pdev)
{ {
int ret; int ret;
static char *name; char *name;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct dev_rot_state *rot_state; struct dev_rot_state *rot_state;
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
......
...@@ -181,11 +181,21 @@ static const struct i2c_device_id ms5637_id[] = { ...@@ -181,11 +181,21 @@ static const struct i2c_device_id ms5637_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, ms5637_id); MODULE_DEVICE_TABLE(i2c, ms5637_id);
static const struct of_device_id ms5637_of_match[] = {
{ .compatible = "meas,ms5637", },
{ .compatible = "meas,ms5805", },
{ .compatible = "meas,ms5837", },
{ .compatible = "meas,ms8607-temppressure", },
{ },
};
MODULE_DEVICE_TABLE(of, ms5637_of_match);
static struct i2c_driver ms5637_driver = { static struct i2c_driver ms5637_driver = {
.probe = ms5637_probe, .probe = ms5637_probe,
.id_table = ms5637_id, .id_table = ms5637_id,
.driver = { .driver = {
.name = "ms5637" .name = "ms5637",
.of_match_table = of_match_ptr(ms5637_of_match),
}, },
}; };
......
...@@ -77,7 +77,8 @@ static int st_press_i2c_probe(struct i2c_client *client, ...@@ -77,7 +77,8 @@ static int st_press_i2c_probe(struct i2c_client *client,
press_data = iio_priv(indio_dev); press_data = iio_priv(indio_dev);
if (client->dev.of_node) { if (client->dev.of_node) {
st_sensors_of_i2c_probe(client, st_press_of_match); st_sensors_of_name_probe(&client->dev, st_press_of_match,
client->name, sizeof(client->name));
} else if (ACPI_HANDLE(&client->dev)) { } else if (ACPI_HANDLE(&client->dev)) {
ret = st_sensors_match_acpi_device(&client->dev); ret = st_sensors_match_acpi_device(&client->dev);
if ((ret < 0) || (ret >= ST_PRESS_MAX)) if ((ret < 0) || (ret >= ST_PRESS_MAX))
......
...@@ -18,6 +18,36 @@ ...@@ -18,6 +18,36 @@
#include <linux/iio/common/st_sensors_spi.h> #include <linux/iio/common/st_sensors_spi.h>
#include "st_pressure.h" #include "st_pressure.h"
#ifdef CONFIG_OF
/*
* For new single-chip sensors use <device_name> as compatible string.
* For old single-chip devices keep <device_name>-press to maintain
* compatibility
*/
static const struct of_device_id st_press_of_match[] = {
{
.compatible = "st,lps001wp-press",
.data = LPS001WP_PRESS_DEV_NAME,
},
{
.compatible = "st,lps25h-press",
.data = LPS25H_PRESS_DEV_NAME,
},
{
.compatible = "st,lps331ap-press",
.data = LPS331AP_PRESS_DEV_NAME,
},
{
.compatible = "st,lps22hb-press",
.data = LPS22HB_PRESS_DEV_NAME,
},
{},
};
MODULE_DEVICE_TABLE(of, st_press_of_match);
#else
#define st_press_of_match NULL
#endif
static int st_press_spi_probe(struct spi_device *spi) static int st_press_spi_probe(struct spi_device *spi)
{ {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
...@@ -30,6 +60,8 @@ static int st_press_spi_probe(struct spi_device *spi) ...@@ -30,6 +60,8 @@ static int st_press_spi_probe(struct spi_device *spi)
press_data = iio_priv(indio_dev); press_data = iio_priv(indio_dev);
st_sensors_of_name_probe(&spi->dev, st_press_of_match,
spi->modalias, sizeof(spi->modalias));
st_sensors_spi_configure(indio_dev, spi, press_data); st_sensors_spi_configure(indio_dev, spi, press_data);
err = st_press_common_probe(indio_dev); err = st_press_common_probe(indio_dev);
...@@ -58,6 +90,7 @@ MODULE_DEVICE_TABLE(spi, st_press_id_table); ...@@ -58,6 +90,7 @@ MODULE_DEVICE_TABLE(spi, st_press_id_table);
static struct spi_driver st_press_driver = { static struct spi_driver st_press_driver = {
.driver = { .driver = {
.name = "st-press-spi", .name = "st-press-spi",
.of_match_table = of_match_ptr(st_press_of_match),
}, },
.probe = st_press_spi_probe, .probe = st_press_spi_probe,
.remove = st_press_spi_remove, .remove = st_press_spi_remove,
......
...@@ -141,14 +141,14 @@ struct zpa2326_private { ...@@ -141,14 +141,14 @@ struct zpa2326_private {
struct regulator *vdd; struct regulator *vdd;
}; };
#define zpa2326_err(_idev, _format, _arg...) \ #define zpa2326_err(idev, fmt, ...) \
dev_err(_idev->dev.parent, _format, ##_arg) dev_err(idev->dev.parent, fmt "\n", ##__VA_ARGS__)
#define zpa2326_warn(_idev, _format, _arg...) \ #define zpa2326_warn(idev, fmt, ...) \
dev_warn(_idev->dev.parent, _format, ##_arg) dev_warn(idev->dev.parent, fmt "\n", ##__VA_ARGS__)
#define zpa2326_dbg(_idev, _format, _arg...) \ #define zpa2326_dbg(idev, fmt, ...) \
dev_dbg(_idev->dev.parent, _format, ##_arg) dev_dbg(idev->dev.parent, fmt "\n", ##__VA_ARGS__)
bool zpa2326_isreg_writeable(struct device *dev, unsigned int reg) bool zpa2326_isreg_writeable(struct device *dev, unsigned int reg)
{ {
......
...@@ -214,11 +214,18 @@ static const struct i2c_device_id tsys01_id[] = { ...@@ -214,11 +214,18 @@ static const struct i2c_device_id tsys01_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, tsys01_id); MODULE_DEVICE_TABLE(i2c, tsys01_id);
static const struct of_device_id tsys01_of_match[] = {
{ .compatible = "meas,tsys01", },
{ },
};
MODULE_DEVICE_TABLE(of, tsys01_of_match);
static struct i2c_driver tsys01_driver = { static struct i2c_driver tsys01_driver = {
.probe = tsys01_i2c_probe, .probe = tsys01_i2c_probe,
.id_table = tsys01_id, .id_table = tsys01_id,
.driver = { .driver = {
.name = "tsys01", .name = "tsys01",
.of_match_table = of_match_ptr(tsys01_of_match),
}, },
}; };
......
...@@ -99,9 +99,14 @@ ...@@ -99,9 +99,14 @@
#define AD7280A_DEVADDR_MASTER 0 #define AD7280A_DEVADDR_MASTER 0
#define AD7280A_DEVADDR_ALL 0x1F #define AD7280A_DEVADDR_ALL 0x1F
/* 5-bit device address is sent LSB first */ /* 5-bit device address is sent LSB first */
#define AD7280A_DEVADDR(addr) (((addr & 0x1) << 4) | ((addr & 0x2) << 3) | \ static unsigned int ad7280a_devaddr(unsigned int addr)
(addr & 0x4) | ((addr & 0x8) >> 3) | \ {
((addr & 0x10) >> 4)) return ((addr & 0x1) << 4) |
((addr & 0x2) << 3) |
(addr & 0x4) |
((addr & 0x8) >> 3) |
((addr & 0x10) >> 4);
}
/* During a read a valid write is mandatory. /* During a read a valid write is mandatory.
* So writing to the highest available address (Address 0x1F) * So writing to the highest available address (Address 0x1F)
...@@ -372,7 +377,7 @@ static int ad7280_chain_setup(struct ad7280_state *st) ...@@ -372,7 +377,7 @@ static int ad7280_chain_setup(struct ad7280_state *st)
if (ad7280_check_crc(st, val)) if (ad7280_check_crc(st, val))
return -EIO; return -EIO;
if (n != AD7280A_DEVADDR(val >> 27)) if (n != ad7280a_devaddr(val >> 27))
return -EIO; return -EIO;
} }
...@@ -511,7 +516,7 @@ static int ad7280_channel_init(struct ad7280_state *st) ...@@ -511,7 +516,7 @@ static int ad7280_channel_init(struct ad7280_state *st)
st->channels[cnt].info_mask_shared_by_type = st->channels[cnt].info_mask_shared_by_type =
BIT(IIO_CHAN_INFO_SCALE); BIT(IIO_CHAN_INFO_SCALE);
st->channels[cnt].address = st->channels[cnt].address =
AD7280A_DEVADDR(dev) << 8 | ch; ad7280a_devaddr(dev) << 8 | ch;
st->channels[cnt].scan_index = cnt; st->channels[cnt].scan_index = cnt;
st->channels[cnt].scan_type.sign = 'u'; st->channels[cnt].scan_type.sign = 'u';
st->channels[cnt].scan_type.realbits = 12; st->channels[cnt].scan_type.realbits = 12;
...@@ -558,7 +563,7 @@ static int ad7280_attr_init(struct ad7280_state *st) ...@@ -558,7 +563,7 @@ static int ad7280_attr_init(struct ad7280_state *st)
for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_CELL_VOLTAGE_6; for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_CELL_VOLTAGE_6;
ch++, cnt++) { ch++, cnt++) {
st->iio_attr[cnt].address = st->iio_attr[cnt].address =
AD7280A_DEVADDR(dev) << 8 | ch; ad7280a_devaddr(dev) << 8 | ch;
st->iio_attr[cnt].dev_attr.attr.mode = st->iio_attr[cnt].dev_attr.attr.mode =
0644; 0644;
st->iio_attr[cnt].dev_attr.show = st->iio_attr[cnt].dev_attr.show =
...@@ -574,7 +579,7 @@ static int ad7280_attr_init(struct ad7280_state *st) ...@@ -574,7 +579,7 @@ static int ad7280_attr_init(struct ad7280_state *st)
&st->iio_attr[cnt].dev_attr.attr; &st->iio_attr[cnt].dev_attr.attr;
cnt++; cnt++;
st->iio_attr[cnt].address = st->iio_attr[cnt].address =
AD7280A_DEVADDR(dev) << 8 | ad7280a_devaddr(dev) << 8 |
(AD7280A_CB1_TIMER + ch); (AD7280A_CB1_TIMER + ch);
st->iio_attr[cnt].dev_attr.attr.mode = st->iio_attr[cnt].dev_attr.attr.mode =
0644; 0644;
...@@ -918,7 +923,7 @@ static int ad7280_probe(struct spi_device *spi) ...@@ -918,7 +923,7 @@ static int ad7280_probe(struct spi_device *spi)
if (ret) if (ret)
goto error_unregister; goto error_unregister;
ret = ad7280_write(st, AD7280A_DEVADDR(st->slave_num), ret = ad7280_write(st, ad7280a_devaddr(st->slave_num),
AD7280A_ALERT, 0, AD7280A_ALERT, 0,
AD7280A_ALERT_GEN_STATIC_HIGH | AD7280A_ALERT_GEN_STATIC_HIGH |
(pdata->chain_last_alert_ignore & 0xF)); (pdata->chain_last_alert_ignore & 0xF));
......
This diff is collapsed.
...@@ -325,4 +325,16 @@ ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, ...@@ -325,4 +325,16 @@ ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
ssize_t st_sensors_sysfs_scale_avail(struct device *dev, ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
struct device_attribute *attr, char *buf); struct device_attribute *attr, char *buf);
#ifdef CONFIG_OF
void st_sensors_of_name_probe(struct device *dev,
const struct of_device_id *match,
char *name, int len);
#else
static inline void st_sensors_of_name_probe(struct device *dev,
const struct of_device_id *match,
char *name, int len)
{
}
#endif
#endif /* ST_SENSORS_H */ #endif /* ST_SENSORS_H */
...@@ -18,16 +18,6 @@ ...@@ -18,16 +18,6 @@
void st_sensors_i2c_configure(struct iio_dev *indio_dev, void st_sensors_i2c_configure(struct iio_dev *indio_dev,
struct i2c_client *client, struct st_sensor_data *sdata); struct i2c_client *client, struct st_sensor_data *sdata);
#ifdef CONFIG_OF
void st_sensors_of_i2c_probe(struct i2c_client *client,
const struct of_device_id *match);
#else
static inline void st_sensors_of_i2c_probe(struct i2c_client *client,
const struct of_device_id *match)
{
}
#endif
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
int st_sensors_match_acpi_device(struct device *dev); int st_sensors_match_acpi_device(struct device *dev);
#else #else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment