Commit 5a45e01d authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-4.7b' of...

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

Jonathan writes:

2nd set of new device support, features and cleanup for IIO in the 4.7 cycle.

Bit of a bumper set for new drivers but plenty of other stuff here as well!

New device support
* ad5592R ADC/DAC
  - new driver supporting ad5592r and ad5593r combined ADC/DAC and gpio chips.
* Aosong am2315 relative humidity
  - new driver with triggered buffer support in follow up patch.
* bmi160 imu
  - new driver
* bmp280
  - bmp180 support - note there is support in the misc/bmp085 driver. Intent
    is to remove that driver long term.
* invensense mpu6050
  - cleanup leading to explicit support of mpu9150 with a good few cleanups
    along the way.
* Hope RF hp03 pressure and temperature sensor.
  - new driver
* maxim DS1803 potentiometer
  - new driver
* maxim max44000 light and proximity sensor
  - new driver built in a series of steps to support pretty much everything.
* ROHM BH1780 light sensor
  - new driver. There is an existing driver in misc that this is pretty much
    intended to replace.  The discussion on whether to support the non standard
    interface of that driver is some way is continuing.
* st-gyro
  - lsm9ds0-gyro.  The accel/magn side of this will take a while longer as
    extensions to the st library are needed for cases where two types of sensor
    share a single i2c address.
* ti-adc081c
  - support the adc101c and adc121c
* Vishay VEML6070 UV sensor
  - new driver.

New features
* core
  - devm_ APIs for channel_get and channel_get_all.  The first user of these
    is the generic ADC based thermal driver.  As it is going through the
    thermal tree these will be picked up as a patch to that next cycle as that
    is how the author preferred to do it.
  - mounting matrix support.  This new core support allows devices to provide
    to userspace (typically from the device tree) allowing compensation for how
    the sensor is mounted on the device.  First examples are on UAVs but it
    has a more mundane use on typical phone where the chip may be on the front
    or the back of the circuit board and soldered at any angle. Includes
    support for this ABI in ak8975 (which has an older interface, now
    deprecated) and mpu6050.
* tools
  - add a -a option to enable all available channels in generic_buffer sample.
    Makes it somewhat easier to use.
* adis library and drivers
  - support manual self test flag clearing.  This has technically been broken
    for a very long time - result is an offset on readings as the applied field
    is on all the time.
* ak8975
  - triggered buffer support
* bmc150
  - spi support (including splitting the driver into core and i2c parts)
* bmp280
  - oversampling support.
* dht11
  - improved logging - useful to debug timing issues on this quirky device.
* st-sensors
  - read each channel invidivually as not all support the optimization of
  reading in bulk.  This is technically a fix, but will need to be backported
  if desired.
  - support open drain and shared interrupts.
* ti-adc081c
  - triggered buffer support.

Cleanups
* inkern
  - white space fix.
* ad7606
  - use the iio_device_claim_direct_mode call rather than open coding equiv.
* ad799x
  - white space fix.
* ad9523
  - unsigned -> unsigned int
* apds9660
  - brace location tidying up.
  - silence an uninitialized variable warning.
* ak8975
  - else and brace on same line fix.
* at91_adc
  - white space fixes.
* bmc150
  - use regmap stored copy of the device pointer rather than having an
    additional copy.
* bmg160
  - use regmap stored copy of the device pointer rather than having an
    additional copy.
* hid-sensors
  - white space fixes.
* mcp3422
  - white space fix.
* mma7455
  - use regmap to retrieve the device struct rather than carrying another copy
    in the private data.
* ms_sensors
  - white space fix.
* mxs-lradc
  - move current bindings out of staging - some will be shortly deprecated but
    the reality is that we have device trees out there using them so they will
    need to be supported for some time.  They accidentally got left behind
    when the driver graduated from staging.
  - white space cleanup.
  - set INPUT_PROP_DIRECT.
  - move ts config into a better function.
  - move the STMP reset out of the ADC init.
* vf610_adc
  - case label indenting fix.
parents 4145ba76 fbced0e9
...@@ -1512,3 +1512,56 @@ Contact: linux-iio@vger.kernel.org ...@@ -1512,3 +1512,56 @@ Contact: linux-iio@vger.kernel.org
Description: Description:
Raw (unscaled no offset etc.) pH reading of a substance as a negative Raw (unscaled no offset etc.) pH reading of a substance as a negative
base-10 logarithm of hydrodium ions in a litre of water. base-10 logarithm of hydrodium ions in a litre of water.
What: /sys/bus/iio/devices/iio:deviceX/mount_matrix
What: /sys/bus/iio/devices/iio:deviceX/in_mount_matrix
What: /sys/bus/iio/devices/iio:deviceX/out_mount_matrix
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_mount_matrix
What: /sys/bus/iio/devices/iio:deviceX/in_accel_mount_matrix
KernelVersion: 4.6
Contact: linux-iio@vger.kernel.org
Description:
Mounting matrix for IIO sensors. This is a rotation matrix which
informs userspace about sensor chip's placement relative to the
main hardware it is mounted on.
Main hardware placement is defined according to the local
reference frame related to the physical quantity the sensor
measures.
Given that the rotation matrix is defined in a board specific
way (platform data and / or device-tree), the main hardware
reference frame definition is left to the implementor's choice
(see below for a magnetometer example).
Applications should apply this rotation matrix to samples so
that when main hardware reference frame is aligned onto local
reference frame, then sensor chip reference frame is also
perfectly aligned with it.
Matrix is a 3x3 unitary matrix and typically looks like
[0, 1, 0; 1, 0, 0; 0, 0, -1]. Identity matrix
[1, 0, 0; 0, 1, 0; 0, 0, 1] means sensor chip and main hardware
are perfectly aligned with each other.
For example, a mounting matrix for a magnetometer sensor informs
userspace about sensor chip's ORIENTATION relative to the main
hardware.
More specifically, main hardware orientation is defined with
respect to the LOCAL EARTH GEOMAGNETIC REFERENCE FRAME where :
* Y is in the ground plane and positive towards magnetic North ;
* X is in the ground plane, perpendicular to the North axis and
positive towards the East ;
* Z is perpendicular to the ground plane and positive upwards.
An implementor might consider that for a hand-held device, a
'natural' orientation would be 'front facing camera at the top'.
The main hardware reference frame could then be described as :
* Y is in the plane of the screen and is positive towards the
top of the screen ;
* X is in the plane of the screen, perpendicular to Y axis, and
positive towards the right hand side of the screen ;
* Z is perpendicular to the screen plane and positive out of the
screen.
Another example for a quadrotor UAV might be :
* Y is in the plane of the propellers and positive towards the
front-view camera;
* X is in the plane of the propellers, perpendicular to Y axis,
and positive towards the starboard side of the UAV ;
* Z is perpendicular to propellers plane and positive upwards.
Analog Devices AD5592R/AD5593R DAC/ADC device driver
Required properties for the AD5592R:
- compatible: Must be "adi,ad5592r"
- reg: SPI chip select number for the device
- spi-max-frequency: Max SPI frequency to use (< 30000000)
- spi-cpol: The AD5592R requires inverse clock polarity (CPOL) mode
Required properties for the AD5593R:
- compatible: Must be "adi,ad5593r"
- reg: I2C address of the device
Required properties for all supported chips:
- #address-cells: Should be 1.
- #size-cells: Should be 0.
- channel nodes:
Each child node represents one channel and has the following
Required properties:
* reg: Pin on which this channel is connected to.
* adi,mode: Mode or function of this channel.
Macros specifying the valid values
can be found in <dt-bindings/iio/adi,ad5592r.h>.
The following values are currently supported:
* CH_MODE_UNUSED (the pin is unused)
* CH_MODE_ADC (the pin is ADC input)
* CH_MODE_DAC (the pin is DAC output)
* CH_MODE_DAC_AND_ADC (the pin is DAC output
but can be monitored by an ADC, since
there is no disadvantage this
this should be considered as the
preferred DAC mode)
* CH_MODE_GPIO (the pin is registered
with GPIOLIB)
Optional properties:
* adi,off-state: State of this channel when unused or the
device gets removed. Macros specifying the
valid values can be found in
<dt-bindings/iio/adi,ad5592r.h>.
* CH_OFFSTATE_PULLDOWN (the pin is pulled down)
* CH_OFFSTATE_OUT_LOW (the pin is output low)
* CH_OFFSTATE_OUT_HIGH (the pin is output high)
* CH_OFFSTATE_OUT_TRISTATE (the pin is
tristated output)
Optional properties:
- vref-supply: Phandle to the external reference voltage supply. This should
only be set if there is an external reference voltage connected to the VREF
pin. If the property is not set the internal 2.5V reference is used.
- reset-gpios : GPIO spec for the RESET pin. If specified, it will be
asserted during driver probe.
- gpio-controller: Marks the device node as a GPIO controller.
- #gpio-cells: Should be 2. The first cell is the GPIO number and the second
cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>.
AD5592R Example:
#include <dt-bindings/iio/adi,ad5592r.h>
vref: regulator-vref {
compatible = "regulator-fixed";
regulator-name = "vref-ad559x";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
ad5592r@0 {
#size-cells = <0>;
#address-cells = <1>;
#gpio-cells = <2>;
compatible = "adi,ad5592r";
reg = <0>;
spi-max-frequency = <1000000>;
spi-cpol;
vref-supply = <&vref>; /* optional */
reset-gpios = <&gpio0 86 0>; /* optional */
gpio-controller;
channel@0 {
reg = <0>;
adi,mode = <CH_MODE_DAC>;
};
channel@1 {
reg = <1>;
adi,mode = <CH_MODE_ADC>;
};
channel@2 {
reg = <2>;
adi,mode = <CH_MODE_DAC_AND_ADC>;
};
channel@3 {
reg = <3>;
adi,mode = <CH_MODE_DAC_AND_ADC>;
adi,off-state = <CH_OFFSTATE_PULLDOWN>;
};
channel@4 {
reg = <4>;
adi,mode = <CH_MODE_UNUSED>;
adi,off-state = <CH_OFFSTATE_PULLDOWN>;
};
channel@5 {
reg = <5>;
adi,mode = <CH_MODE_GPIO>;
adi,off-state = <CH_OFFSTATE_PULLDOWN>;
};
channel@6 {
reg = <6>;
adi,mode = <CH_MODE_GPIO>;
adi,off-state = <CH_OFFSTATE_PULLDOWN>;
};
channel@7 {
reg = <7>;
adi,mode = <CH_MODE_GPIO>;
adi,off-state = <CH_OFFSTATE_PULLDOWN>;
};
};
AD5593R Example:
#include <dt-bindings/iio/adi,ad5592r.h>
ad5593r@10 {
#size-cells = <0>;
#address-cells = <1>;
#gpio-cells = <2>;
compatible = "adi,ad5593r";
reg = <0x10>;
gpio-controller;
channel@0 {
reg = <0>;
adi,mode = <CH_MODE_DAC>;
adi,off-state = <CH_OFFSTATE_PULLDOWN>;
};
channel@1 {
reg = <1>;
adi,mode = <CH_MODE_ADC>;
adi,off-state = <CH_OFFSTATE_PULLDOWN>;
};
channel@2 {
reg = <2>;
adi,mode = <CH_MODE_DAC_AND_ADC>;
adi,off-state = <CH_OFFSTATE_PULLDOWN>;
};
channel@6 {
reg = <6>;
adi,mode = <CH_MODE_GPIO>;
adi,off-state = <CH_OFFSTATE_PULLDOWN>;
};
};
...@@ -8,10 +8,23 @@ Required properties: ...@@ -8,10 +8,23 @@ Required properties:
- interrupt-parent : should be the phandle for the interrupt controller - interrupt-parent : should be the phandle for the interrupt controller
- interrupts : interrupt mapping for GPIO IRQ - interrupts : interrupt mapping for GPIO IRQ
Optional properties:
- mount-matrix: an optional 3x3 mounting rotation matrix
Example: Example:
mpu6050@68 { mpu6050@68 {
compatible = "invensense,mpu6050"; compatible = "invensense,mpu6050";
reg = <0x68>; reg = <0x68>;
interrupt-parent = <&gpio1>; interrupt-parent = <&gpio1>;
interrupts = <18 1>; interrupts = <18 1>;
mount-matrix = "-0.984807753012208", /* x0 */
"0", /* y0 */
"-0.173648177666930", /* z0 */
"0", /* x1 */
"-1", /* y1 */
"0", /* z1 */
"-0.173648177666930", /* x2 */
"0", /* y2 */
"0.984807753012208"; /* z2 */
}; };
...@@ -9,6 +9,7 @@ Optional properties: ...@@ -9,6 +9,7 @@ Optional properties:
- gpios : should be device tree identifier of the magnetometer DRDY pin - gpios : should be device tree identifier of the magnetometer DRDY pin
- vdd-supply: an optional regulator that needs to be on to provide VDD - vdd-supply: an optional regulator that needs to be on to provide VDD
- mount-matrix: an optional 3x3 mounting rotation matrix
Example: Example:
...@@ -17,4 +18,13 @@ ak8975@0c { ...@@ -17,4 +18,13 @@ ak8975@0c {
reg = <0x0c>; reg = <0x0c>;
gpios = <&gpj0 7 0>; gpios = <&gpj0 7 0>;
vdd-supply = <&ldo_3v3_gnss>; vdd-supply = <&ldo_3v3_gnss>;
mount-matrix = "-0.984807753012208", /* x0 */
"0", /* y0 */
"-0.173648177666930", /* z0 */
"0", /* x1 */
"-1", /* y1 */
"0", /* z1 */
"-0.173648177666930", /* x2 */
"0", /* y2 */
"0.984807753012208"; /* z2 */
}; };
* Maxim Integrated DS1803 digital potentiometer driver
The node for this driver must be a child node of a I2C controller, hence
all mandatory properties for your controller must be specified. See directory:
Documentation/devicetree/bindings/i2c
for more details.
Required properties:
- compatible: Must be one of the following, depending on the
model:
"maxim,ds1803-010",
"maxim,ds1803-050",
"maxim,ds1803-100"
Example:
ds1803: ds1803@1 {
reg = <0x28>;
compatible = "maxim,ds1803-010";
};
HopeRF HP03 digital pressure/temperature sensors
Required properties:
- compatible: must be "hoperf,hp03"
- xclr-gpio: must be device tree identifier of the XCLR pin.
The XCLR pin is a reset of the ADC in the chip,
it must be pulled HI before the conversion and
readout of the value from the ADC registers and
pulled LO afterward.
Example:
hp03@0x77 {
compatible = "hoperf,hp03";
reg = <0x77>;
xclr-gpio = <&portc 0 0x0>;
};
...@@ -16,6 +16,10 @@ Optional properties: ...@@ -16,6 +16,10 @@ 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). This property is not configurable "data ready" (valid values: 1 or 2). This property is not configurable
on all sensors. on all sensors.
- 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 binding is taken from pinctrl/pinctrl-bindings.txt)
This is a boolean property.
Sensors may also have applicable pin control settings, those use the Sensors may also have applicable pin control settings, those use the
standard bindings from pinctrl/pinctrl-bindings.txt. standard bindings from pinctrl/pinctrl-bindings.txt.
...@@ -47,6 +51,7 @@ Gyroscopes: ...@@ -47,6 +51,7 @@ Gyroscopes:
- st,l3gd20-gyro - st,l3gd20-gyro
- st,l3g4is-gyro - st,l3g4is-gyro
- st,lsm330-gyro - st,lsm330-gyro
- st,lsm9ds0-gyro
Magnetometers: Magnetometers:
- st,lsm303agr-magn - st,lsm303agr-magn
......
...@@ -267,6 +267,10 @@ IIO ...@@ -267,6 +267,10 @@ IIO
devm_iio_kfifo_free() devm_iio_kfifo_free()
devm_iio_trigger_alloc() devm_iio_trigger_alloc()
devm_iio_trigger_free() devm_iio_trigger_free()
devm_iio_channel_get()
devm_iio_channel_release()
devm_iio_channel_get_all()
devm_iio_channel_release_all()
IO region IO region
devm_release_mem_region() devm_release_mem_region()
......
This diff is collapsed.
...@@ -55,11 +55,11 @@ ...@@ -55,11 +55,11 @@
struct mma7455_data { struct mma7455_data {
struct regmap *regmap; struct regmap *regmap;
struct device *dev;
}; };
static int mma7455_drdy(struct mma7455_data *mma7455) static int mma7455_drdy(struct mma7455_data *mma7455)
{ {
struct device *dev = regmap_get_device(mma7455->regmap);
unsigned int reg; unsigned int reg;
int tries = 3; int tries = 3;
int ret; int ret;
...@@ -75,7 +75,7 @@ static int mma7455_drdy(struct mma7455_data *mma7455) ...@@ -75,7 +75,7 @@ static int mma7455_drdy(struct mma7455_data *mma7455)
msleep(20); msleep(20);
} }
dev_warn(mma7455->dev, "data not ready\n"); dev_warn(dev, "data not ready\n");
return -EIO; return -EIO;
} }
...@@ -260,7 +260,6 @@ int mma7455_core_probe(struct device *dev, struct regmap *regmap, ...@@ -260,7 +260,6 @@ int mma7455_core_probe(struct device *dev, struct regmap *regmap,
dev_set_drvdata(dev, indio_dev); dev_set_drvdata(dev, indio_dev);
mma7455 = iio_priv(indio_dev); mma7455 = iio_priv(indio_dev);
mma7455->regmap = regmap; mma7455->regmap = regmap;
mma7455->dev = dev;
indio_dev->info = &mma7455_info; indio_dev->info = &mma7455_info;
indio_dev->name = name; indio_dev->name = name;
......
...@@ -99,6 +99,8 @@ ...@@ -99,6 +99,8 @@
#define ST_ACCEL_2_DRDY_IRQ_INT2_MASK 0x10 #define ST_ACCEL_2_DRDY_IRQ_INT2_MASK 0x10
#define ST_ACCEL_2_IHL_IRQ_ADDR 0x22 #define ST_ACCEL_2_IHL_IRQ_ADDR 0x22
#define ST_ACCEL_2_IHL_IRQ_MASK 0x80 #define ST_ACCEL_2_IHL_IRQ_MASK 0x80
#define ST_ACCEL_2_OD_IRQ_ADDR 0x22
#define ST_ACCEL_2_OD_IRQ_MASK 0x40
#define ST_ACCEL_2_MULTIREAD_BIT true #define ST_ACCEL_2_MULTIREAD_BIT true
/* CUSTOM VALUES FOR SENSOR 3 */ /* CUSTOM VALUES FOR SENSOR 3 */
...@@ -180,6 +182,8 @@ ...@@ -180,6 +182,8 @@
#define ST_ACCEL_5_DRDY_IRQ_INT2_MASK 0x20 #define ST_ACCEL_5_DRDY_IRQ_INT2_MASK 0x20
#define ST_ACCEL_5_IHL_IRQ_ADDR 0x22 #define ST_ACCEL_5_IHL_IRQ_ADDR 0x22
#define ST_ACCEL_5_IHL_IRQ_MASK 0x80 #define ST_ACCEL_5_IHL_IRQ_MASK 0x80
#define ST_ACCEL_5_OD_IRQ_ADDR 0x22
#define ST_ACCEL_5_OD_IRQ_MASK 0x40
#define ST_ACCEL_5_IG1_EN_ADDR 0x21 #define ST_ACCEL_5_IG1_EN_ADDR 0x21
#define ST_ACCEL_5_IG1_EN_MASK 0x08 #define ST_ACCEL_5_IG1_EN_MASK 0x08
#define ST_ACCEL_5_MULTIREAD_BIT false #define ST_ACCEL_5_MULTIREAD_BIT false
...@@ -332,6 +336,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { ...@@ -332,6 +336,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK, .mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK,
.addr_ihl = ST_ACCEL_1_IHL_IRQ_ADDR, .addr_ihl = ST_ACCEL_1_IHL_IRQ_ADDR,
.mask_ihl = ST_ACCEL_1_IHL_IRQ_MASK, .mask_ihl = ST_ACCEL_1_IHL_IRQ_MASK,
.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
}, },
.multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT, .multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT,
.bootime = 2, .bootime = 2,
...@@ -397,6 +402,9 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { ...@@ -397,6 +402,9 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK, .mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK,
.addr_ihl = ST_ACCEL_2_IHL_IRQ_ADDR, .addr_ihl = ST_ACCEL_2_IHL_IRQ_ADDR,
.mask_ihl = ST_ACCEL_2_IHL_IRQ_MASK, .mask_ihl = ST_ACCEL_2_IHL_IRQ_MASK,
.addr_od = ST_ACCEL_2_OD_IRQ_ADDR,
.mask_od = ST_ACCEL_2_OD_IRQ_MASK,
.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
}, },
.multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT, .multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT,
.bootime = 2, .bootime = 2,
...@@ -474,6 +482,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { ...@@ -474,6 +482,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.mask_int2 = ST_ACCEL_3_DRDY_IRQ_INT2_MASK, .mask_int2 = ST_ACCEL_3_DRDY_IRQ_INT2_MASK,
.addr_ihl = ST_ACCEL_3_IHL_IRQ_ADDR, .addr_ihl = ST_ACCEL_3_IHL_IRQ_ADDR,
.mask_ihl = ST_ACCEL_3_IHL_IRQ_MASK, .mask_ihl = ST_ACCEL_3_IHL_IRQ_MASK,
.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
.ig1 = { .ig1 = {
.en_addr = ST_ACCEL_3_IG1_EN_ADDR, .en_addr = ST_ACCEL_3_IG1_EN_ADDR,
.en_mask = ST_ACCEL_3_IG1_EN_MASK, .en_mask = ST_ACCEL_3_IG1_EN_MASK,
...@@ -532,6 +541,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { ...@@ -532,6 +541,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.drdy_irq = { .drdy_irq = {
.addr = ST_ACCEL_4_DRDY_IRQ_ADDR, .addr = ST_ACCEL_4_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_4_DRDY_IRQ_INT1_MASK, .mask_int1 = ST_ACCEL_4_DRDY_IRQ_INT1_MASK,
.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
}, },
.multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT, .multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT,
.bootime = 2, /* guess */ .bootime = 2, /* guess */
...@@ -583,6 +593,9 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { ...@@ -583,6 +593,9 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK, .mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK,
.addr_ihl = ST_ACCEL_5_IHL_IRQ_ADDR, .addr_ihl = ST_ACCEL_5_IHL_IRQ_ADDR,
.mask_ihl = ST_ACCEL_5_IHL_IRQ_MASK, .mask_ihl = ST_ACCEL_5_IHL_IRQ_MASK,
.addr_od = ST_ACCEL_5_OD_IRQ_ADDR,
.mask_od = ST_ACCEL_5_OD_IRQ_MASK,
.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
}, },
.multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT, .multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT,
.bootime = 2, /* guess */ .bootime = 2, /* guess */
......
...@@ -385,11 +385,11 @@ config ROCKCHIP_SARADC ...@@ -385,11 +385,11 @@ config ROCKCHIP_SARADC
module will be called rockchip_saradc. module will be called rockchip_saradc.
config TI_ADC081C config TI_ADC081C
tristate "Texas Instruments ADC081C021/027" tristate "Texas Instruments ADC081C/ADC101C/ADC121C family"
depends on I2C depends on I2C
help help
If you say yes here you get support for Texas Instruments ADC081C021 If you say yes here you get support for Texas Instruments ADC081C,
and ADC081C027 ADC chips. ADC101C and ADC121C ADC chips.
This driver can also be built as a module. If so, the module will be This driver can also be built as a module. If so, the module will be
called ti-adc081c. called ti-adc081c.
......
...@@ -477,7 +477,7 @@ static int ad799x_read_event_value(struct iio_dev *indio_dev, ...@@ -477,7 +477,7 @@ static int ad799x_read_event_value(struct iio_dev *indio_dev,
if (ret < 0) if (ret < 0)
return ret; return ret;
*val = (ret >> chan->scan_type.shift) & *val = (ret >> chan->scan_type.shift) &
GENMASK(chan->scan_type.realbits - 1 , 0); GENMASK(chan->scan_type.realbits - 1, 0);
return IIO_VAL_INT; return IIO_VAL_INT;
} }
......
...@@ -797,8 +797,8 @@ static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz) ...@@ -797,8 +797,8 @@ static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz)
* Startup Time = <lookup_table_value> / ADC Clock * Startup Time = <lookup_table_value> / ADC Clock
*/ */
const int startup_lookup[] = { 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,
768, 832, 896, 960 768, 832, 896, 960
}; };
...@@ -924,14 +924,14 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, ...@@ -924,14 +924,14 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
ret = -EINVAL; ret = -EINVAL;
goto error_ret; goto error_ret;
} }
trig->name = name; trig->name = name;
if (of_property_read_u32(trig_node, "trigger-value", &prop)) { if (of_property_read_u32(trig_node, "trigger-value", &prop)) {
dev_err(&idev->dev, "Missing trigger-value property in the DT.\n"); dev_err(&idev->dev, "Missing trigger-value property in the DT.\n");
ret = -EINVAL; ret = -EINVAL;
goto error_ret; goto error_ret;
} }
trig->value = prop; trig->value = prop;
trig->is_external = of_property_read_bool(trig_node, "trigger-external"); trig->is_external = of_property_read_bool(trig_node, "trigger-external");
i++; i++;
} }
......
...@@ -61,9 +61,9 @@ ...@@ -61,9 +61,9 @@
static const int mcp3422_scales[4][4] = { static const int mcp3422_scales[4][4] = {
{ 1000000, 500000, 250000, 125000 }, { 1000000, 500000, 250000, 125000 },
{ 250000 , 125000, 62500 , 31250 }, { 250000, 125000, 62500, 31250 },
{ 62500 , 31250 , 15625 , 7812 }, { 62500, 31250, 15625, 7812 },
{ 15625 , 7812 , 3906 , 1953 } }; { 15625, 7812, 3906, 1953 } };
/* Constant msleep times for data acquisitions */ /* Constant msleep times for data acquisitions */
static const int mcp3422_read_times[4] = { static const int mcp3422_read_times[4] = {
......
...@@ -686,6 +686,17 @@ static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc) ...@@ -686,6 +686,17 @@ static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc)
static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc)
{ {
/* Configure the touchscreen type */
if (lradc->soc == IMX28_LRADC) {
mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
LRADC_CTRL0);
if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE)
mxs_lradc_reg_set(lradc,
LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
LRADC_CTRL0);
}
mxs_lradc_setup_touch_detection(lradc); mxs_lradc_setup_touch_detection(lradc);
lradc->cur_plate = LRADC_TOUCH; lradc->cur_plate = LRADC_TOUCH;
...@@ -1127,6 +1138,7 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc) ...@@ -1127,6 +1138,7 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc)
__set_bit(EV_ABS, input->evbit); __set_bit(EV_ABS, input->evbit);
__set_bit(EV_KEY, input->evbit); __set_bit(EV_KEY, input->evbit);
__set_bit(BTN_TOUCH, input->keybit); __set_bit(BTN_TOUCH, input->keybit);
__set_bit(INPUT_PROP_DIRECT, input->propbit);
input_set_abs_params(input, ABS_X, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0); input_set_abs_params(input, ABS_X, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0);
input_set_abs_params(input, ABS_Y, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0); input_set_abs_params(input, ABS_Y, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0);
input_set_abs_params(input, ABS_PRESSURE, 0, LRADC_SINGLE_SAMPLE_MASK, input_set_abs_params(input, ABS_PRESSURE, 0, LRADC_SINGLE_SAMPLE_MASK,
...@@ -1475,18 +1487,13 @@ static const struct iio_chan_spec mx28_lradc_chan_spec[] = { ...@@ -1475,18 +1487,13 @@ static const struct iio_chan_spec mx28_lradc_chan_spec[] = {
MXS_ADC_CHAN(15, IIO_VOLTAGE, "VDD5V"), MXS_ADC_CHAN(15, IIO_VOLTAGE, "VDD5V"),
}; };
static int mxs_lradc_hw_init(struct mxs_lradc *lradc) static void mxs_lradc_hw_init(struct mxs_lradc *lradc)
{ {
/* The ADC always uses DELAY CHANNEL 0. */ /* The ADC always uses DELAY CHANNEL 0. */
const u32 adc_cfg = const u32 adc_cfg =
(1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + 0)) | (1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + 0)) |
(LRADC_DELAY_TIMER_PER << LRADC_DELAY_DELAY_OFFSET); (LRADC_DELAY_TIMER_PER << LRADC_DELAY_DELAY_OFFSET);
int ret = stmp_reset_block(lradc->base);
if (ret)
return ret;
/* Configure DELAY CHANNEL 0 for generic ADC sampling. */ /* Configure DELAY CHANNEL 0 for generic ADC sampling. */
mxs_lradc_reg_wrt(lradc, adc_cfg, LRADC_DELAY(0)); mxs_lradc_reg_wrt(lradc, adc_cfg, LRADC_DELAY(0));
...@@ -1495,20 +1502,8 @@ static int mxs_lradc_hw_init(struct mxs_lradc *lradc) ...@@ -1495,20 +1502,8 @@ static int mxs_lradc_hw_init(struct mxs_lradc *lradc)
mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
/* Configure the touchscreen type */
if (lradc->soc == IMX28_LRADC) {
mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
LRADC_CTRL0);
if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE)
mxs_lradc_reg_set(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
LRADC_CTRL0);
}
/* Start internal temperature sensing. */ /* Start internal temperature sensing. */
mxs_lradc_reg_wrt(lradc, 0, LRADC_CTRL2); mxs_lradc_reg_wrt(lradc, 0, LRADC_CTRL2);
return 0;
} }
static void mxs_lradc_hw_stop(struct mxs_lradc *lradc) static void mxs_lradc_hw_stop(struct mxs_lradc *lradc)
...@@ -1708,11 +1703,13 @@ static int mxs_lradc_probe(struct platform_device *pdev) ...@@ -1708,11 +1703,13 @@ static int mxs_lradc_probe(struct platform_device *pdev)
} }
} }
/* Configure the hardware. */ ret = stmp_reset_block(lradc->base);
ret = mxs_lradc_hw_init(lradc);
if (ret) if (ret)
goto err_dev; goto err_dev;
/* Configure the hardware. */
mxs_lradc_hw_init(lradc);
/* Register the touchscreen input device. */ /* Register the touchscreen input device. */
if (touch_ret == 0) { if (touch_ret == 0) {
ret = mxs_lradc_ts_register(lradc); ret = mxs_lradc_ts_register(lradc);
......
/* /*
* TI ADC081C/ADC101C/ADC121C 8/10/12-bit ADC driver
*
* Copyright (C) 2012 Avionic Design GmbH * Copyright (C) 2012 Avionic Design GmbH
* Copyright (C) 2016 Intel
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*
* Datasheets:
* http://www.ti.com/lit/ds/symlink/adc081c021.pdf
* http://www.ti.com/lit/ds/symlink/adc101c021.pdf
* http://www.ti.com/lit/ds/symlink/adc121c021.pdf
*
* The devices have a very similar interface and differ mostly in the number of
* bits handled. For the 8-bit and 10-bit models the least-significant 4 or 2
* bits of value registers are reserved.
*/ */
#include <linux/err.h> #include <linux/err.h>
...@@ -12,11 +24,17 @@ ...@@ -12,11 +24,17 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
struct adc081c { struct adc081c {
struct i2c_client *i2c; struct i2c_client *i2c;
struct regulator *ref; struct regulator *ref;
/* 8, 10 or 12 */
int bits;
}; };
#define REG_CONV_RES 0x00 #define REG_CONV_RES 0x00
...@@ -34,7 +52,7 @@ static int adc081c_read_raw(struct iio_dev *iio, ...@@ -34,7 +52,7 @@ static int adc081c_read_raw(struct iio_dev *iio,
if (err < 0) if (err < 0)
return err; return err;
*value = (err >> 4) & 0xff; *value = (err & 0xFFF) >> (12 - adc->bits);
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
...@@ -43,7 +61,7 @@ static int adc081c_read_raw(struct iio_dev *iio, ...@@ -43,7 +61,7 @@ static int adc081c_read_raw(struct iio_dev *iio,
return err; return err;
*value = err / 1000; *value = err / 1000;
*shift = 8; *shift = adc->bits;
return IIO_VAL_FRACTIONAL_LOG2; return IIO_VAL_FRACTIONAL_LOG2;
...@@ -54,10 +72,53 @@ static int adc081c_read_raw(struct iio_dev *iio, ...@@ -54,10 +72,53 @@ static int adc081c_read_raw(struct iio_dev *iio,
return -EINVAL; return -EINVAL;
} }
static const struct iio_chan_spec adc081c_channel = { #define ADCxx1C_CHAN(_bits) { \
.type = IIO_VOLTAGE, .type = IIO_VOLTAGE, \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.scan_type = { \
.sign = 'u', \
.realbits = (_bits), \
.storagebits = 16, \
.shift = 12 - (_bits), \
.endianness = IIO_CPU, \
}, \
}
#define DEFINE_ADCxx1C_CHANNELS(_name, _bits) \
static const struct iio_chan_spec _name ## _channels[] = { \
ADCxx1C_CHAN((_bits)), \
IIO_CHAN_SOFT_TIMESTAMP(1), \
}; \
#define ADC081C_NUM_CHANNELS 2
struct adcxx1c_model {
const struct iio_chan_spec* channels;
int bits;
};
#define ADCxx1C_MODEL(_name, _bits) \
{ \
.channels = _name ## _channels, \
.bits = (_bits), \
}
DEFINE_ADCxx1C_CHANNELS(adc081c, 8);
DEFINE_ADCxx1C_CHANNELS(adc101c, 10);
DEFINE_ADCxx1C_CHANNELS(adc121c, 12);
/* Model ids are indexes in _models array */
enum adcxx1c_model_id {
ADC081C = 0,
ADC101C = 1,
ADC121C = 2,
};
static struct adcxx1c_model adcxx1c_models[] = {
ADCxx1C_MODEL(adc081c, 8),
ADCxx1C_MODEL(adc101c, 10),
ADCxx1C_MODEL(adc121c, 12),
}; };
static const struct iio_info adc081c_info = { static const struct iio_info adc081c_info = {
...@@ -65,11 +126,30 @@ static const struct iio_info adc081c_info = { ...@@ -65,11 +126,30 @@ static const struct iio_info adc081c_info = {
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
}; };
static irqreturn_t adc081c_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adc081c *data = iio_priv(indio_dev);
u16 buf[8]; /* 2 bytes data + 6 bytes padding + 8 bytes timestamp */
int ret;
ret = i2c_smbus_read_word_swapped(data->i2c, REG_CONV_RES);
if (ret < 0)
goto out;
buf[0] = ret;
iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns());
out:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
static int adc081c_probe(struct i2c_client *client, static int adc081c_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct iio_dev *iio; struct iio_dev *iio;
struct adc081c *adc; struct adc081c *adc;
struct adcxx1c_model *model = &adcxx1c_models[id->driver_data];
int err; int err;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
...@@ -81,6 +161,7 @@ static int adc081c_probe(struct i2c_client *client, ...@@ -81,6 +161,7 @@ static int adc081c_probe(struct i2c_client *client,
adc = iio_priv(iio); adc = iio_priv(iio);
adc->i2c = client; adc->i2c = client;
adc->bits = model->bits;
adc->ref = devm_regulator_get(&client->dev, "vref"); adc->ref = devm_regulator_get(&client->dev, "vref");
if (IS_ERR(adc->ref)) if (IS_ERR(adc->ref))
...@@ -95,18 +176,26 @@ static int adc081c_probe(struct i2c_client *client, ...@@ -95,18 +176,26 @@ static int adc081c_probe(struct i2c_client *client,
iio->modes = INDIO_DIRECT_MODE; iio->modes = INDIO_DIRECT_MODE;
iio->info = &adc081c_info; iio->info = &adc081c_info;
iio->channels = &adc081c_channel; iio->channels = model->channels;
iio->num_channels = 1; iio->num_channels = ADC081C_NUM_CHANNELS;
err = iio_triggered_buffer_setup(iio, NULL, adc081c_trigger_handler, NULL);
if (err < 0) {
dev_err(&client->dev, "iio triggered buffer setup failed\n");
goto err_regulator_disable;
}
err = iio_device_register(iio); err = iio_device_register(iio);
if (err < 0) if (err < 0)
goto regulator_disable; goto err_buffer_cleanup;
i2c_set_clientdata(client, iio); i2c_set_clientdata(client, iio);
return 0; return 0;
regulator_disable: err_buffer_cleanup:
iio_triggered_buffer_cleanup(iio);
err_regulator_disable:
regulator_disable(adc->ref); regulator_disable(adc->ref);
return err; return err;
...@@ -118,13 +207,16 @@ static int adc081c_remove(struct i2c_client *client) ...@@ -118,13 +207,16 @@ static int adc081c_remove(struct i2c_client *client)
struct adc081c *adc = iio_priv(iio); struct adc081c *adc = iio_priv(iio);
iio_device_unregister(iio); iio_device_unregister(iio);
iio_triggered_buffer_cleanup(iio);
regulator_disable(adc->ref); regulator_disable(adc->ref);
return 0; return 0;
} }
static const struct i2c_device_id adc081c_id[] = { static const struct i2c_device_id adc081c_id[] = {
{ "adc081c", 0 }, { "adc081c", ADC081C },
{ "adc101c", ADC101C },
{ "adc121c", ADC121C },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, adc081c_id); MODULE_DEVICE_TABLE(i2c, adc081c_id);
...@@ -132,6 +224,8 @@ MODULE_DEVICE_TABLE(i2c, adc081c_id); ...@@ -132,6 +224,8 @@ MODULE_DEVICE_TABLE(i2c, adc081c_id);
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id adc081c_of_match[] = { static const struct of_device_id adc081c_of_match[] = {
{ .compatible = "ti,adc081c" }, { .compatible = "ti,adc081c" },
{ .compatible = "ti,adc101c" },
{ .compatible = "ti,adc121c" },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, adc081c_of_match); MODULE_DEVICE_TABLE(of, adc081c_of_match);
...@@ -149,5 +243,5 @@ static struct i2c_driver adc081c_driver = { ...@@ -149,5 +243,5 @@ static struct i2c_driver adc081c_driver = {
module_i2c_driver(adc081c_driver); module_i2c_driver(adc081c_driver);
MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>"); MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
MODULE_DESCRIPTION("Texas Instruments ADC081C021/027 driver"); MODULE_DESCRIPTION("Texas Instruments ADC081C/ADC101C/ADC121C driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -714,19 +714,19 @@ static int vf610_write_raw(struct iio_dev *indio_dev, ...@@ -714,19 +714,19 @@ static int vf610_write_raw(struct iio_dev *indio_dev,
int i; int i;
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
for (i = 0; for (i = 0;
i < ARRAY_SIZE(info->sample_freq_avail); i < ARRAY_SIZE(info->sample_freq_avail);
i++) i++)
if (val == info->sample_freq_avail[i]) { if (val == info->sample_freq_avail[i]) {
info->adc_feature.sample_rate = i; info->adc_feature.sample_rate = i;
vf610_adc_sample_set(info); vf610_adc_sample_set(info);
return 0; return 0;
} }
break; break;
default: default:
break; break;
} }
return -EINVAL; return -EINVAL;
......
...@@ -115,7 +115,7 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state) ...@@ -115,7 +115,7 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state)
return ret; return ret;
} }
return 0; return 0;
#else #else
atomic_set(&st->user_requested_state, state); atomic_set(&st->user_requested_state, state);
return _hid_sensor_power_state(st, state); return _hid_sensor_power_state(st, state);
......
...@@ -106,7 +106,7 @@ int ms_sensors_convert_and_read(void *cli, u8 conv, u8 rd, ...@@ -106,7 +106,7 @@ int ms_sensors_convert_and_read(void *cli, u8 conv, u8 rd,
unsigned int delay, u32 *adc) unsigned int delay, u32 *adc)
{ {
int ret; int ret;
__be32 buf = 0; __be32 buf = 0;
struct i2c_client *client = (struct i2c_client *)cli; struct i2c_client *client = (struct i2c_client *)cli;
/* Trigger conversion */ /* Trigger conversion */
......
...@@ -24,67 +24,30 @@ ...@@ -24,67 +24,30 @@
int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
{ {
u8 addr[3]; /* no ST sensor has more than 3 channels */ int i, len;
int i, n = 0, len; int total = 0;
struct st_sensor_data *sdata = iio_priv(indio_dev); struct st_sensor_data *sdata = iio_priv(indio_dev);
unsigned int num_data_channels = sdata->num_data_channels; unsigned int num_data_channels = sdata->num_data_channels;
unsigned int byte_for_channel =
indio_dev->channels[0].scan_type.storagebits >> 3;
for (i = 0; i < num_data_channels; i++) { for (i = 0; i < num_data_channels; i++) {
unsigned int bytes_to_read;
if (test_bit(i, indio_dev->active_scan_mask)) { if (test_bit(i, indio_dev->active_scan_mask)) {
addr[n] = indio_dev->channels[i].address; bytes_to_read = indio_dev->channels[i].scan_type.storagebits >> 3;
n++;
}
}
switch (n) {
case 1:
len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
addr[0], byte_for_channel, buf, sdata->multiread_bit);
break;
case 2:
if ((addr[1] - addr[0]) == byte_for_channel) {
len = sdata->tf->read_multiple_byte(&sdata->tb, len = sdata->tf->read_multiple_byte(&sdata->tb,
sdata->dev, addr[0], byte_for_channel * n, sdata->dev, indio_dev->channels[i].address,
buf, sdata->multiread_bit); bytes_to_read,
} else { buf + total, sdata->multiread_bit);
u8 *rx_array;
rx_array = kmalloc(byte_for_channel * num_data_channels,
GFP_KERNEL);
if (!rx_array)
return -ENOMEM;
len = sdata->tf->read_multiple_byte(&sdata->tb, if (len < bytes_to_read)
sdata->dev, addr[0], return -EIO;
byte_for_channel * num_data_channels,
rx_array, sdata->multiread_bit); /* Advance the buffer pointer */
if (len < 0) { total += len;
kfree(rx_array);
return len;
}
for (i = 0; i < n * byte_for_channel; i++) {
if (i < n)
buf[i] = rx_array[i];
else
buf[i] = rx_array[n + i];
}
kfree(rx_array);
len = byte_for_channel * n;
} }
break;
case 3:
len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
addr[0], byte_for_channel * num_data_channels,
buf, sdata->multiread_bit);
break;
default:
return -EINVAL;
} }
if (len != byte_for_channel * n)
return -EIO;
return len; return total;
} }
EXPORT_SYMBOL(st_sensors_get_buffer_element); EXPORT_SYMBOL(st_sensors_get_buffer_element);
...@@ -95,6 +58,24 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p) ...@@ -95,6 +58,24 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev; struct iio_dev *indio_dev = pf->indio_dev;
struct st_sensor_data *sdata = iio_priv(indio_dev); struct st_sensor_data *sdata = iio_priv(indio_dev);
/* If we have a status register, check if this IRQ came from us */
if (sdata->sensor_settings->drdy_irq.addr_stat_drdy) {
u8 status;
len = sdata->tf->read_byte(&sdata->tb, sdata->dev,
sdata->sensor_settings->drdy_irq.addr_stat_drdy,
&status);
if (len < 0)
dev_err(sdata->dev, "could not read channel status\n");
/*
* If this was not caused by any channels on this sensor,
* return IRQ_NONE
*/
if (!(status & (u8)indio_dev->active_scan_mask[0]))
return IRQ_NONE;
}
len = st_sensors_get_buffer_element(indio_dev, sdata->buffer_data); len = st_sensors_get_buffer_element(indio_dev, sdata->buffer_data);
if (len < 0) if (len < 0)
goto st_sensors_get_buffer_element_error; goto st_sensors_get_buffer_element_error;
......
...@@ -301,6 +301,14 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, ...@@ -301,6 +301,14 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
return -EINVAL; return -EINVAL;
} }
if (pdata->open_drain) {
if (!sdata->sensor_settings->drdy_irq.addr_od)
dev_err(&indio_dev->dev,
"open drain requested but unsupported.\n");
else
sdata->int_pin_open_drain = true;
}
return 0; return 0;
} }
...@@ -321,6 +329,8 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, ...@@ -321,6 +329,8 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev,
else else
pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0; pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0;
pdata->open_drain = of_property_read_bool(np, "drive-open-drain");
return pdata; return pdata;
} }
#else #else
...@@ -374,6 +384,16 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, ...@@ -374,6 +384,16 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev,
return err; return err;
} }
if (sdata->int_pin_open_drain) {
dev_info(&indio_dev->dev,
"set interrupt line to open drain mode\n");
err = st_sensors_write_data_with_mask(indio_dev,
sdata->sensor_settings->drdy_irq.addr_od,
sdata->sensor_settings->drdy_irq.mask_od, 1);
if (err < 0)
return err;
}
err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
return err; return err;
......
...@@ -64,6 +64,19 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, ...@@ -64,6 +64,19 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
"rising edge\n", irq_trig); "rising edge\n", irq_trig);
irq_trig = IRQF_TRIGGER_RISING; irq_trig = IRQF_TRIGGER_RISING;
} }
/*
* If the interrupt pin is Open Drain, by definition this
* means that the interrupt line may be shared with other
* peripherals. But to do this we also need to have a status
* register and mask to figure out if this sensor was firing
* the IRQ or not, so we can tell the interrupt handle that
* it was "our" interrupt.
*/
if (sdata->int_pin_open_drain &&
sdata->sensor_settings->drdy_irq.addr_stat_drdy)
irq_trig |= IRQF_SHARED;
err = request_threaded_irq(irq, err = request_threaded_irq(irq,
iio_trigger_generic_data_rdy_poll, iio_trigger_generic_data_rdy_poll,
NULL, NULL,
......
...@@ -74,6 +74,33 @@ config AD5449 ...@@ -74,6 +74,33 @@ config AD5449
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called ad5449. module will be called ad5449.
config AD5592R_BASE
tristate
config AD5592R
tristate "Analog Devices AD5592R ADC/DAC driver"
depends on SPI_MASTER
select GPIOLIB
select AD5592R_BASE
help
Say yes here to build support for Analog Devices AD5592R
Digital to Analog / Analog to Digital Converter.
To compile this driver as a module, choose M here: the
module will be called ad5592r.
config AD5593R
tristate "Analog Devices AD5593R ADC/DAC driver"
depends on I2C
select GPIOLIB
select AD5592R_BASE
help
Say yes here to build support for Analog Devices AD5593R
Digital to Analog / Analog to Digital Converter.
To compile this driver as a module, choose M here: the
module will be called ad5593r.
config AD5504 config AD5504
tristate "Analog Devices AD5504/AD5501 DAC SPI driver" tristate "Analog Devices AD5504/AD5501 DAC SPI driver"
depends on SPI depends on SPI
......
...@@ -11,6 +11,9 @@ obj-$(CONFIG_AD5064) += ad5064.o ...@@ -11,6 +11,9 @@ obj-$(CONFIG_AD5064) += ad5064.o
obj-$(CONFIG_AD5504) += ad5504.o obj-$(CONFIG_AD5504) += ad5504.o
obj-$(CONFIG_AD5446) += ad5446.o obj-$(CONFIG_AD5446) += ad5446.o
obj-$(CONFIG_AD5449) += ad5449.o obj-$(CONFIG_AD5449) += ad5449.o
obj-$(CONFIG_AD5592R_BASE) += ad5592r-base.o
obj-$(CONFIG_AD5592R) += ad5592r.o
obj-$(CONFIG_AD5593R) += ad5593r.o
obj-$(CONFIG_AD5755) += ad5755.o obj-$(CONFIG_AD5755) += ad5755.o
obj-$(CONFIG_AD5761) += ad5761.o obj-$(CONFIG_AD5761) += ad5761.o
obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5764) += ad5764.o
......
This diff is collapsed.
/*
* AD5592R / AD5593R Digital <-> Analog converters driver
*
* Copyright 2015-2016 Analog Devices Inc.
* Author: Paul Cercueil <paul.cercueil@analog.com>
*
* Licensed under the GPL-2.
*/
#ifndef __DRIVERS_IIO_DAC_AD5592R_BASE_H__
#define __DRIVERS_IIO_DAC_AD5592R_BASE_H__
#include <linux/types.h>
#include <linux/cache.h>
#include <linux/mutex.h>
#include <linux/gpio/driver.h>
struct device;
struct ad5592r_state;
enum ad5592r_registers {
AD5592R_REG_NOOP = 0x0,
AD5592R_REG_DAC_READBACK = 0x1,
AD5592R_REG_ADC_SEQ = 0x2,
AD5592R_REG_CTRL = 0x3,
AD5592R_REG_ADC_EN = 0x4,
AD5592R_REG_DAC_EN = 0x5,
AD5592R_REG_PULLDOWN = 0x6,
AD5592R_REG_LDAC = 0x7,
AD5592R_REG_GPIO_OUT_EN = 0x8,
AD5592R_REG_GPIO_SET = 0x9,
AD5592R_REG_GPIO_IN_EN = 0xA,
AD5592R_REG_PD = 0xB,
AD5592R_REG_OPEN_DRAIN = 0xC,
AD5592R_REG_TRISTATE = 0xD,
AD5592R_REG_RESET = 0xF,
};
#define AD5592R_REG_PD_EN_REF BIT(9)
#define AD5592R_REG_CTRL_ADC_RANGE BIT(5)
#define AD5592R_REG_CTRL_DAC_RANGE BIT(4)
struct ad5592r_rw_ops {
int (*write_dac)(struct ad5592r_state *st, unsigned chan, u16 value);
int (*read_adc)(struct ad5592r_state *st, unsigned chan, u16 *value);
int (*reg_write)(struct ad5592r_state *st, u8 reg, u16 value);
int (*reg_read)(struct ad5592r_state *st, u8 reg, u16 *value);
int (*gpio_read)(struct ad5592r_state *st, u8 *value);
};
struct ad5592r_state {
struct device *dev;
struct regulator *reg;
struct gpio_chip gpiochip;
struct mutex gpio_lock; /* Protect cached gpio_out, gpio_val, etc. */
unsigned int num_channels;
const struct ad5592r_rw_ops *ops;
int scale_avail[2][2];
u16 cached_dac[8];
u16 cached_gp_ctrl;
u8 channel_modes[8];
u8 channel_offstate[8];
u8 gpio_map;
u8 gpio_out;
u8 gpio_in;
u8 gpio_val;
__be16 spi_msg ____cacheline_aligned;
__be16 spi_msg_nop;
};
int ad5592r_probe(struct device *dev, const char *name,
const struct ad5592r_rw_ops *ops);
int ad5592r_remove(struct device *dev);
#endif /* __DRIVERS_IIO_DAC_AD5592R_BASE_H__ */
/*
* AD5592R Digital <-> Analog converters driver
*
* Copyright 2015-2016 Analog Devices Inc.
* Author: Paul Cercueil <paul.cercueil@analog.com>
*
* Licensed under the GPL-2.
*/
#include "ad5592r-base.h"
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/spi/spi.h>
#define AD5592R_GPIO_READBACK_EN BIT(10)
#define AD5592R_LDAC_READBACK_EN BIT(6)
static int ad5592r_spi_wnop_r16(struct ad5592r_state *st, u16 *buf)
{
struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
struct spi_transfer t = {
.tx_buf = &st->spi_msg_nop,
.rx_buf = buf,
.len = 2
};
st->spi_msg_nop = 0; /* NOP */
return spi_sync_transfer(spi, &t, 1);
}
static int ad5592r_write_dac(struct ad5592r_state *st, unsigned chan, u16 value)
{
struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
st->spi_msg = cpu_to_be16(BIT(15) | (chan << 12) | value);
return spi_write(spi, &st->spi_msg, sizeof(st->spi_msg));
}
static int ad5592r_read_adc(struct ad5592r_state *st, unsigned chan, u16 *value)
{
struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
int ret;
st->spi_msg = cpu_to_be16((AD5592R_REG_ADC_SEQ << 11) | BIT(chan));
ret = spi_write(spi, &st->spi_msg, sizeof(st->spi_msg));
if (ret)
return ret;
/*
* Invalid data:
* See Figure 40. Single-Channel ADC Conversion Sequence
*/
ret = ad5592r_spi_wnop_r16(st, &st->spi_msg);
if (ret)
return ret;
ret = ad5592r_spi_wnop_r16(st, &st->spi_msg);
if (ret)
return ret;
*value = be16_to_cpu(st->spi_msg);
return 0;
}
static int ad5592r_reg_write(struct ad5592r_state *st, u8 reg, u16 value)
{
struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
st->spi_msg = cpu_to_be16((reg << 11) | value);
return spi_write(spi, &st->spi_msg, sizeof(st->spi_msg));
}
static int ad5592r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value)
{
struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
int ret;
st->spi_msg = cpu_to_be16((AD5592R_REG_LDAC << 11) |
AD5592R_LDAC_READBACK_EN | (reg << 2));
ret = spi_write(spi, &st->spi_msg, sizeof(st->spi_msg));
if (ret)
return ret;
ret = ad5592r_spi_wnop_r16(st, &st->spi_msg);
if (ret)
return ret;
*value = be16_to_cpu(st->spi_msg);
return 0;
}
static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value)
{
int ret;
ret = ad5592r_reg_write(st, AD5592R_REG_GPIO_IN_EN,
AD5592R_GPIO_READBACK_EN | st->gpio_in);
if (ret)
return ret;
ret = ad5592r_spi_wnop_r16(st, &st->spi_msg);
if (ret)
return ret;
*value = (u8) be16_to_cpu(st->spi_msg);
return 0;
}
static const struct ad5592r_rw_ops ad5592r_rw_ops = {
.write_dac = ad5592r_write_dac,
.read_adc = ad5592r_read_adc,
.reg_write = ad5592r_reg_write,
.reg_read = ad5592r_reg_read,
.gpio_read = ad5593r_gpio_read,
};
static int ad5592r_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
return ad5592r_probe(&spi->dev, id->name, &ad5592r_rw_ops);
}
static int ad5592r_spi_remove(struct spi_device *spi)
{
return ad5592r_remove(&spi->dev);
}
static const struct spi_device_id ad5592r_spi_ids[] = {
{ .name = "ad5592r", },
{}
};
MODULE_DEVICE_TABLE(spi, ad5592r_spi_ids);
static const struct of_device_id ad5592r_of_match[] = {
{ .compatible = "adi,ad5592r", },
{},
};
MODULE_DEVICE_TABLE(of, ad5592r_of_match);
static struct spi_driver ad5592r_spi_driver = {
.driver = {
.name = "ad5592r",
.of_match_table = of_match_ptr(ad5592r_of_match),
},
.probe = ad5592r_spi_probe,
.remove = ad5592r_spi_remove,
.id_table = ad5592r_spi_ids,
};
module_spi_driver(ad5592r_spi_driver);
MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters");
MODULE_LICENSE("GPL v2");
/*
* AD5593R Digital <-> Analog converters driver
*
* Copyright 2015-2016 Analog Devices Inc.
* Author: Paul Cercueil <paul.cercueil@analog.com>
*
* Licensed under the GPL-2.
*/
#include "ad5592r-base.h"
#include <linux/bitops.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
#define AD5593R_MODE_CONF (0 << 4)
#define AD5593R_MODE_DAC_WRITE (1 << 4)
#define AD5593R_MODE_ADC_READBACK (4 << 4)
#define AD5593R_MODE_DAC_READBACK (5 << 4)
#define AD5593R_MODE_GPIO_READBACK (6 << 4)
#define AD5593R_MODE_REG_READBACK (7 << 4)
static int ad5593r_write_dac(struct ad5592r_state *st, unsigned chan, u16 value)
{
struct i2c_client *i2c = to_i2c_client(st->dev);
return i2c_smbus_write_word_swapped(i2c,
AD5593R_MODE_DAC_WRITE | chan, value);
}
static int ad5593r_read_adc(struct ad5592r_state *st, unsigned chan, u16 *value)
{
struct i2c_client *i2c = to_i2c_client(st->dev);
s32 val;
val = i2c_smbus_write_word_swapped(i2c,
AD5593R_MODE_CONF | AD5592R_REG_ADC_SEQ, BIT(chan));
if (val < 0)
return (int) val;
val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_ADC_READBACK);
if (val < 0)
return (int) val;
*value = (u16) val;
return 0;
}
static int ad5593r_reg_write(struct ad5592r_state *st, u8 reg, u16 value)
{
struct i2c_client *i2c = to_i2c_client(st->dev);
return i2c_smbus_write_word_swapped(i2c,
AD5593R_MODE_CONF | reg, value);
}
static int ad5593r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value)
{
struct i2c_client *i2c = to_i2c_client(st->dev);
s32 val;
val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_REG_READBACK | reg);
if (val < 0)
return (int) val;
*value = (u16) val;
return 0;
}
static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value)
{
struct i2c_client *i2c = to_i2c_client(st->dev);
s32 val;
val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_GPIO_READBACK);
if (val < 0)
return (int) val;
*value = (u8) val;
return 0;
}
static const struct ad5592r_rw_ops ad5593r_rw_ops = {
.write_dac = ad5593r_write_dac,
.read_adc = ad5593r_read_adc,
.reg_write = ad5593r_reg_write,
.reg_read = ad5593r_reg_read,
.gpio_read = ad5593r_gpio_read,
};
static int ad5593r_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
return ad5592r_probe(&i2c->dev, id->name, &ad5593r_rw_ops);
}
static int ad5593r_i2c_remove(struct i2c_client *i2c)
{
return ad5592r_remove(&i2c->dev);
}
static const struct i2c_device_id ad5593r_i2c_ids[] = {
{ .name = "ad5593r", },
{},
};
MODULE_DEVICE_TABLE(i2c, ad5593r_i2c_ids);
static const struct of_device_id ad5593r_of_match[] = {
{ .compatible = "adi,ad5593r", },
{},
};
MODULE_DEVICE_TABLE(of, ad5593r_of_match);
static struct i2c_driver ad5593r_driver = {
.driver = {
.name = "ad5593r",
.of_match_table = of_match_ptr(ad5593r_of_match),
},
.probe = ad5593r_i2c_probe,
.remove = ad5593r_i2c_remove,
.id_table = ad5593r_i2c_ids,
};
module_i2c_driver(ad5593r_driver);
MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters");
MODULE_LICENSE("GPL v2");
...@@ -284,7 +284,7 @@ struct ad9523_state { ...@@ -284,7 +284,7 @@ struct ad9523_state {
} data[2] ____cacheline_aligned; } data[2] ____cacheline_aligned;
}; };
static int ad9523_read(struct iio_dev *indio_dev, unsigned addr) static int ad9523_read(struct iio_dev *indio_dev, unsigned int addr)
{ {
struct ad9523_state *st = iio_priv(indio_dev); struct ad9523_state *st = iio_priv(indio_dev);
int ret; int ret;
...@@ -318,7 +318,8 @@ static int ad9523_read(struct iio_dev *indio_dev, unsigned addr) ...@@ -318,7 +318,8 @@ static int ad9523_read(struct iio_dev *indio_dev, unsigned addr)
return ret; return ret;
}; };
static int ad9523_write(struct iio_dev *indio_dev, unsigned addr, unsigned val) static int ad9523_write(struct iio_dev *indio_dev,
unsigned int addr, unsigned int val)
{ {
struct ad9523_state *st = iio_priv(indio_dev); struct ad9523_state *st = iio_priv(indio_dev);
int ret; int ret;
...@@ -351,11 +352,11 @@ static int ad9523_io_update(struct iio_dev *indio_dev) ...@@ -351,11 +352,11 @@ static int ad9523_io_update(struct iio_dev *indio_dev)
} }
static int ad9523_vco_out_map(struct iio_dev *indio_dev, static int ad9523_vco_out_map(struct iio_dev *indio_dev,
unsigned ch, unsigned out) unsigned int ch, unsigned int out)
{ {
struct ad9523_state *st = iio_priv(indio_dev); struct ad9523_state *st = iio_priv(indio_dev);
int ret; int ret;
unsigned mask; unsigned int mask;
switch (ch) { switch (ch) {
case 0 ... 3: case 0 ... 3:
...@@ -405,7 +406,7 @@ static int ad9523_vco_out_map(struct iio_dev *indio_dev, ...@@ -405,7 +406,7 @@ static int ad9523_vco_out_map(struct iio_dev *indio_dev,
} }
static int ad9523_set_clock_provider(struct iio_dev *indio_dev, static int ad9523_set_clock_provider(struct iio_dev *indio_dev,
unsigned ch, unsigned long freq) unsigned int ch, unsigned long freq)
{ {
struct ad9523_state *st = iio_priv(indio_dev); struct ad9523_state *st = iio_priv(indio_dev);
long tmp1, tmp2; long tmp1, tmp2;
...@@ -619,7 +620,7 @@ static int ad9523_read_raw(struct iio_dev *indio_dev, ...@@ -619,7 +620,7 @@ static int ad9523_read_raw(struct iio_dev *indio_dev,
long m) long m)
{ {
struct ad9523_state *st = iio_priv(indio_dev); struct ad9523_state *st = iio_priv(indio_dev);
unsigned code; unsigned int code;
int ret; int ret;
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
...@@ -655,7 +656,7 @@ static int ad9523_write_raw(struct iio_dev *indio_dev, ...@@ -655,7 +656,7 @@ static int ad9523_write_raw(struct iio_dev *indio_dev,
long mask) long mask)
{ {
struct ad9523_state *st = iio_priv(indio_dev); struct ad9523_state *st = iio_priv(indio_dev);
unsigned reg; unsigned int reg;
int ret, tmp, code; int ret, tmp, code;
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
...@@ -709,8 +710,8 @@ static int ad9523_write_raw(struct iio_dev *indio_dev, ...@@ -709,8 +710,8 @@ static int ad9523_write_raw(struct iio_dev *indio_dev,
} }
static int ad9523_reg_access(struct iio_dev *indio_dev, static int ad9523_reg_access(struct iio_dev *indio_dev,
unsigned reg, unsigned writeval, unsigned int reg, unsigned int writeval,
unsigned *readval) unsigned int *readval)
{ {
int ret; int ret;
......
...@@ -93,7 +93,7 @@ config IIO_ST_GYRO_3AXIS ...@@ -93,7 +93,7 @@ config IIO_ST_GYRO_3AXIS
select IIO_TRIGGERED_BUFFER if (IIO_BUFFER) select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
help help
Say yes here to build support for STMicroelectronics gyroscopes: Say yes here to build support for STMicroelectronics gyroscopes:
L3G4200D, LSM330DL, L3GD20, LSM330DLC, L3G4IS, LSM330. L3G4200D, LSM330DL, L3GD20, LSM330DLC, L3G4IS, LSM330, LSM9DS0.
This driver can also be built as a module. If so, these modules This driver can also be built as a module. If so, these modules
will be created: will be created:
......
This diff is collapsed.
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define L3GD20_GYRO_DEV_NAME "l3gd20" #define L3GD20_GYRO_DEV_NAME "l3gd20"
#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"
/** /**
* struct st_sensors_platform_data - gyro platform data * struct st_sensors_platform_data - gyro platform data
......
...@@ -190,6 +190,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { ...@@ -190,6 +190,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
* drain settings, but only for INT1 and not * drain settings, but only for INT1 and not
* for the DRDY line on INT2. * for the DRDY line on INT2.
*/ */
.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
}, },
.multi_read_bit = ST_GYRO_1_MULTIREAD_BIT, .multi_read_bit = ST_GYRO_1_MULTIREAD_BIT,
.bootime = 2, .bootime = 2,
...@@ -203,6 +204,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { ...@@ -203,6 +204,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
[2] = LSM330DLC_GYRO_DEV_NAME, [2] = LSM330DLC_GYRO_DEV_NAME,
[3] = L3G4IS_GYRO_DEV_NAME, [3] = L3G4IS_GYRO_DEV_NAME,
[4] = LSM330_GYRO_DEV_NAME, [4] = LSM330_GYRO_DEV_NAME,
[5] = LSM9DS0_GYRO_DEV_NAME,
}, },
.ch = (struct iio_chan_spec *)st_gyro_16bit_channels, .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
.odr = { .odr = {
...@@ -258,6 +260,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { ...@@ -258,6 +260,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
* drain settings, but only for INT1 and not * drain settings, but only for INT1 and not
* for the DRDY line on INT2. * for the DRDY line on INT2.
*/ */
.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
}, },
.multi_read_bit = ST_GYRO_2_MULTIREAD_BIT, .multi_read_bit = ST_GYRO_2_MULTIREAD_BIT,
.bootime = 2, .bootime = 2,
...@@ -322,6 +325,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { ...@@ -322,6 +325,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
* drain settings, but only for INT1 and not * drain settings, but only for INT1 and not
* for the DRDY line on INT2. * for the DRDY line on INT2.
*/ */
.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
}, },
.multi_read_bit = ST_GYRO_3_MULTIREAD_BIT, .multi_read_bit = ST_GYRO_3_MULTIREAD_BIT,
.bootime = 2, .bootime = 2,
......
...@@ -48,6 +48,10 @@ static const struct of_device_id st_gyro_of_match[] = { ...@@ -48,6 +48,10 @@ static const struct of_device_id st_gyro_of_match[] = {
.compatible = "st,lsm330-gyro", .compatible = "st,lsm330-gyro",
.data = LSM330_GYRO_DEV_NAME, .data = LSM330_GYRO_DEV_NAME,
}, },
{
.compatible = "st,lsm9ds0-gyro",
.data = LSM9DS0_GYRO_DEV_NAME,
},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, st_gyro_of_match); MODULE_DEVICE_TABLE(of, st_gyro_of_match);
...@@ -93,6 +97,7 @@ static const struct i2c_device_id st_gyro_id_table[] = { ...@@ -93,6 +97,7 @@ static const struct i2c_device_id st_gyro_id_table[] = {
{ L3GD20_GYRO_DEV_NAME }, { L3GD20_GYRO_DEV_NAME },
{ L3G4IS_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME },
{ LSM330_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME },
{ LSM9DS0_GYRO_DEV_NAME },
{}, {},
}; };
MODULE_DEVICE_TABLE(i2c, st_gyro_id_table); MODULE_DEVICE_TABLE(i2c, st_gyro_id_table);
......
...@@ -54,6 +54,7 @@ static const struct spi_device_id st_gyro_id_table[] = { ...@@ -54,6 +54,7 @@ static const struct spi_device_id st_gyro_id_table[] = {
{ L3GD20_GYRO_DEV_NAME }, { L3GD20_GYRO_DEV_NAME },
{ L3G4IS_GYRO_DEV_NAME }, { L3G4IS_GYRO_DEV_NAME },
{ LSM330_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME },
{ LSM9DS0_GYRO_DEV_NAME },
{}, {},
}; };
MODULE_DEVICE_TABLE(spi, st_gyro_id_table); MODULE_DEVICE_TABLE(spi, st_gyro_id_table);
......
...@@ -3,6 +3,16 @@ ...@@ -3,6 +3,16 @@
# #
menu "Humidity sensors" menu "Humidity sensors"
config AM2315
tristate "Aosong AM2315 relative humidity and temperature sensor"
depends on I2C
help
If you say yes here you get support for the Aosong AM2315
relative humidity and ambient temperature sensor.
This driver can also be built as a module. If so, the module will
be called am2315.
config DHT11 config DHT11
tristate "DHT11 (and compatible sensors) driver" tristate "DHT11 (and compatible sensors) driver"
depends on GPIOLIB || COMPILE_TEST depends on GPIOLIB || COMPILE_TEST
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# Makefile for IIO humidity sensor drivers # Makefile for IIO humidity sensor drivers
# #
obj-$(CONFIG_AM2315) += am2315.o
obj-$(CONFIG_DHT11) += dht11.o obj-$(CONFIG_DHT11) += dht11.o
obj-$(CONFIG_HDC100X) += hdc100x.o obj-$(CONFIG_HDC100X) += hdc100x.o
obj-$(CONFIG_HTU21) += htu21.o obj-$(CONFIG_HTU21) += htu21.o
......
/**
* Aosong AM2315 relative humidity and temperature
*
* Copyright (c) 2016, Intel Corporation.
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* 7-bit I2C address: 0x5C.
*/
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#define AM2315_REG_HUM_MSB 0x00
#define AM2315_REG_HUM_LSB 0x01
#define AM2315_REG_TEMP_MSB 0x02
#define AM2315_REG_TEMP_LSB 0x03
#define AM2315_FUNCTION_READ 0x03
#define AM2315_HUM_OFFSET 2
#define AM2315_TEMP_OFFSET 4
#define AM2315_ALL_CHANNEL_MASK GENMASK(1, 0)
#define AM2315_DRIVER_NAME "am2315"
struct am2315_data {
struct i2c_client *client;
struct mutex lock;
s16 buffer[8]; /* 2x16-bit channels + 2x16 padding + 4x16 timestamp */
};
struct am2315_sensor_data {
s16 hum_data;
s16 temp_data;
};
static const struct iio_chan_spec am2315_channels[] = {
{
.type = IIO_HUMIDITYRELATIVE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.scan_index = 0,
.scan_type = {
.sign = 's',
.realbits = 16,
.storagebits = 16,
.endianness = IIO_CPU,
},
},
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.scan_index = 1,
.scan_type = {
.sign = 's',
.realbits = 16,
.storagebits = 16,
.endianness = IIO_CPU,
},
},
IIO_CHAN_SOFT_TIMESTAMP(2),
};
/* CRC calculation algorithm, as specified in the datasheet (page 13). */
static u16 am2315_crc(u8 *data, u8 nr_bytes)
{
int i;
u16 crc = 0xffff;
while (nr_bytes--) {
crc ^= *data++;
for (i = 0; i < 8; i++) {
if (crc & 0x01) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
/* Simple function that sends a few bytes to the device to wake it up. */
static void am2315_ping(struct i2c_client *client)
{
i2c_smbus_read_byte_data(client, AM2315_REG_HUM_MSB);
}
static int am2315_read_data(struct am2315_data *data,
struct am2315_sensor_data *sensor_data)
{
int ret;
/* tx_buf format: <function code> <start addr> <nr of regs to read> */
u8 tx_buf[3] = { AM2315_FUNCTION_READ, AM2315_REG_HUM_MSB, 4 };
/*
* rx_buf format:
* <function code> <number of registers read>
* <humidity MSB> <humidity LSB> <temp MSB> <temp LSB>
* <CRC LSB> <CRC MSB>
*/
u8 rx_buf[8];
u16 crc;
/* First wake up the device. */
am2315_ping(data->client);
mutex_lock(&data->lock);
ret = i2c_master_send(data->client, tx_buf, sizeof(tx_buf));
if (ret < 0) {
dev_err(&data->client->dev, "failed to send read request\n");
goto exit_unlock;
}
/* Wait 2-3 ms, then read back the data sent by the device. */
usleep_range(2000, 3000);
/* Do a bulk data read, then pick out what we need. */
ret = i2c_master_recv(data->client, rx_buf, sizeof(rx_buf));
if (ret < 0) {
dev_err(&data->client->dev, "failed to read sensor data\n");
goto exit_unlock;
}
mutex_unlock(&data->lock);
/*
* Do a CRC check on the data and compare it to the value
* calculated by the device.
*/
crc = am2315_crc(rx_buf, sizeof(rx_buf) - 2);
if ((crc & 0xff) != rx_buf[6] || (crc >> 8) != rx_buf[7]) {
dev_err(&data->client->dev, "failed to verify sensor data\n");
return -EIO;
}
sensor_data->hum_data = (rx_buf[AM2315_HUM_OFFSET] << 8) |
rx_buf[AM2315_HUM_OFFSET + 1];
sensor_data->temp_data = (rx_buf[AM2315_TEMP_OFFSET] << 8) |
rx_buf[AM2315_TEMP_OFFSET + 1];
return ret;
exit_unlock:
mutex_unlock(&data->lock);
return ret;
}
static irqreturn_t am2315_trigger_handler(int irq, void *p)
{
int i;
int ret;
int bit;
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct am2315_data *data = iio_priv(indio_dev);
struct am2315_sensor_data sensor_data;
ret = am2315_read_data(data, &sensor_data);
if (ret < 0) {
mutex_unlock(&data->lock);
goto err;
}
mutex_lock(&data->lock);
if (*(indio_dev->active_scan_mask) == AM2315_ALL_CHANNEL_MASK) {
data->buffer[0] = sensor_data.hum_data;
data->buffer[1] = sensor_data.temp_data;
} else {
i = 0;
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->masklength) {
data->buffer[i] = (bit ? sensor_data.temp_data :
sensor_data.hum_data);
i++;
}
}
mutex_unlock(&data->lock);
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
pf->timestamp);
err:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
static int am2315_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
int ret;
struct am2315_sensor_data sensor_data;
struct am2315_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
ret = am2315_read_data(data, &sensor_data);
if (ret < 0)
return ret;
*val = (chan->type == IIO_HUMIDITYRELATIVE) ?
sensor_data.hum_data : sensor_data.temp_data;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 100;
return IIO_VAL_INT;
}
return -EINVAL;
}
static const struct iio_info am2315_info = {
.driver_module = THIS_MODULE,
.read_raw = am2315_read_raw,
};
static int am2315_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
struct iio_dev *indio_dev;
struct am2315_data *data;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev) {
dev_err(&client->dev, "iio allocation failed!\n");
return -ENOMEM;
}
data = iio_priv(indio_dev);
data->client = client;
i2c_set_clientdata(client, indio_dev);
mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev;
indio_dev->info = &am2315_info;
indio_dev->name = AM2315_DRIVER_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = am2315_channels;
indio_dev->num_channels = ARRAY_SIZE(am2315_channels);
ret = iio_triggered_buffer_setup(indio_dev, NULL,
am2315_trigger_handler, NULL);
if (ret < 0) {
dev_err(&client->dev, "iio triggered buffer setup failed\n");
return ret;
}
ret = iio_device_register(indio_dev);
if (ret < 0)
goto err_buffer_cleanup;
return 0;
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
static int am2315_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
return 0;
}
static const struct i2c_device_id am2315_i2c_id[] = {
{"am2315", 0},
{}
};
static const struct acpi_device_id am2315_acpi_id[] = {
{"AOS2315", 0},
{}
};
MODULE_DEVICE_TABLE(acpi, am2315_acpi_id);
static struct i2c_driver am2315_driver = {
.driver = {
.name = "am2315",
.acpi_match_table = ACPI_PTR(am2315_acpi_id),
},
.probe = am2315_probe,
.remove = am2315_remove,
.id_table = am2315_i2c_id,
};
module_i2c_driver(am2315_driver);
MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>");
MODULE_DESCRIPTION("Aosong AM2315 relative humidity and temperature");
MODULE_LICENSE("GPL v2");
...@@ -96,6 +96,24 @@ struct dht11 { ...@@ -96,6 +96,24 @@ struct dht11 {
struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ]; struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ];
}; };
#ifdef CONFIG_DYNAMIC_DEBUG
/*
* dht11_edges_print: show the data as actually received by the
* driver.
*/
static void dht11_edges_print(struct dht11 *dht11)
{
int i;
dev_dbg(dht11->dev, "%d edges detected:\n", dht11->num_edges);
for (i = 1; i < dht11->num_edges; ++i) {
dev_dbg(dht11->dev, "%d: %lld ns %s\n", i,
dht11->edges[i].ts - dht11->edges[i - 1].ts,
dht11->edges[i - 1].value ? "high" : "low");
}
}
#endif /* CONFIG_DYNAMIC_DEBUG */
static unsigned char dht11_decode_byte(char *bits) static unsigned char dht11_decode_byte(char *bits)
{ {
unsigned char ret = 0; unsigned char ret = 0;
...@@ -119,8 +137,12 @@ static int dht11_decode(struct dht11 *dht11, int offset) ...@@ -119,8 +137,12 @@ static int dht11_decode(struct dht11 *dht11, int offset)
for (i = 0; i < DHT11_BITS_PER_READ; ++i) { for (i = 0; i < DHT11_BITS_PER_READ; ++i) {
t = dht11->edges[offset + 2 * i + 2].ts - t = dht11->edges[offset + 2 * i + 2].ts -
dht11->edges[offset + 2 * i + 1].ts; dht11->edges[offset + 2 * i + 1].ts;
if (!dht11->edges[offset + 2 * i + 1].value) if (!dht11->edges[offset + 2 * i + 1].value) {
return -EIO; /* lost synchronisation */ dev_dbg(dht11->dev,
"lost synchronisation at edge %d\n",
offset + 2 * i + 1);
return -EIO;
}
bits[i] = t > DHT11_THRESHOLD; bits[i] = t > DHT11_THRESHOLD;
} }
...@@ -130,8 +152,10 @@ static int dht11_decode(struct dht11 *dht11, int offset) ...@@ -130,8 +152,10 @@ static int dht11_decode(struct dht11 *dht11, int offset)
temp_dec = dht11_decode_byte(&bits[24]); temp_dec = dht11_decode_byte(&bits[24]);
checksum = dht11_decode_byte(&bits[32]); checksum = dht11_decode_byte(&bits[32]);
if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum) if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum) {
dev_dbg(dht11->dev, "invalid checksum\n");
return -EIO; return -EIO;
}
dht11->timestamp = ktime_get_boot_ns(); dht11->timestamp = ktime_get_boot_ns();
if (hum_int < 20) { /* DHT22 */ if (hum_int < 20) { /* DHT22 */
...@@ -182,6 +206,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev, ...@@ -182,6 +206,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
mutex_lock(&dht11->lock); mutex_lock(&dht11->lock);
if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_boot_ns()) { if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_boot_ns()) {
timeres = ktime_get_resolution_ns(); timeres = ktime_get_resolution_ns();
dev_dbg(dht11->dev, "current timeresolution: %dns\n", timeres);
if (timeres > DHT11_MIN_TIMERES) { if (timeres > DHT11_MIN_TIMERES) {
dev_err(dht11->dev, "timeresolution %dns too low\n", dev_err(dht11->dev, "timeresolution %dns too low\n",
timeres); timeres);
...@@ -219,10 +244,13 @@ static int dht11_read_raw(struct iio_dev *iio_dev, ...@@ -219,10 +244,13 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
free_irq(dht11->irq, iio_dev); free_irq(dht11->irq, iio_dev);
#ifdef CONFIG_DYNAMIC_DEBUG
dht11_edges_print(dht11);
#endif
if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) { if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) {
dev_err(&iio_dev->dev, dev_err(dht11->dev, "Only %d signal edges detected\n",
"Only %d signal edges detected\n", dht11->num_edges);
dht11->num_edges);
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
} }
if (ret < 0) if (ret < 0)
......
...@@ -25,6 +25,8 @@ config ADIS16480 ...@@ -25,6 +25,8 @@ config ADIS16480
Say yes here to build support for Analog Devices ADIS16375, ADIS16480, Say yes here to build support for Analog Devices ADIS16375, ADIS16480,
ADIS16485, ADIS16488 inertial sensors. ADIS16485, ADIS16488 inertial sensors.
source "drivers/iio/imu/bmi160/Kconfig"
config KMX61 config KMX61
tristate "Kionix KMX61 6-axis accelerometer and magnetometer" tristate "Kionix KMX61 6-axis accelerometer and magnetometer"
depends on I2C depends on I2C
......
...@@ -13,6 +13,7 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o ...@@ -13,6 +13,7 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o
adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
obj-y += bmi160/
obj-y += inv_mpu6050/ obj-y += inv_mpu6050/
obj-$(CONFIG_KMX61) += kmx61.o obj-$(CONFIG_KMX61) += kmx61.o
...@@ -324,7 +324,12 @@ static int adis_self_test(struct adis *adis) ...@@ -324,7 +324,12 @@ static int adis_self_test(struct adis *adis)
msleep(adis->data->startup_delay); msleep(adis->data->startup_delay);
return adis_check_status(adis); ret = adis_check_status(adis);
if (adis->data->self_test_no_autoclear)
adis_write_reg_16(adis, adis->data->msc_ctrl_reg, 0x00);
return ret;
} }
/** /**
......
#
# BMI160 IMU driver
#
config BMI160
tristate
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
config BMI160_I2C
tristate "Bosch BMI160 I2C driver"
depends on I2C
select BMI160
select REGMAP_I2C
help
If you say yes here you get support for BMI160 IMU on I2C with
accelerometer, gyroscope and external BMG160 magnetometer.
This driver can also be built as a module. If so, the module will be
called bmi160_i2c.
config BMI160_SPI
tristate "Bosch BMI160 SPI driver"
depends on SPI
select BMI160
select REGMAP_SPI
help
If you say yes here you get support for BMI160 IMU on SPI with
accelerometer, gyroscope and external BMG160 magnetometer.
This driver can also be built as a module. If so, the module will be
called bmi160_spi.
#
# Makefile for Bosch BMI160 IMU
#
obj-$(CONFIG_BMI160) += bmi160_core.o
obj-$(CONFIG_BMI160_I2C) += bmi160_i2c.o
obj-$(CONFIG_BMI160_SPI) += bmi160_spi.o
#ifndef BMI160_H_
#define BMI160_H_
extern const struct regmap_config bmi160_regmap_config;
int bmi160_core_probe(struct device *dev, struct regmap *regmap,
const char *name, bool use_spi);
void bmi160_core_remove(struct device *dev);
#endif /* BMI160_H_ */
This diff is collapsed.
/*
* BMI160 - Bosch IMU, I2C bits
*
* Copyright (c) 2016, Intel Corporation.
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* 7-bit I2C slave address is:
* - 0x68 if SDO is pulled to GND
* - 0x69 if SDO is pulled to VDDIO
*/
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/acpi.h>
#include "bmi160.h"
static int bmi160_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regmap *regmap;
const char *name = NULL;
regmap = devm_regmap_init_i2c(client, &bmi160_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "Failed to register i2c regmap %d\n",
(int)PTR_ERR(regmap));
return PTR_ERR(regmap);
}
if (id)
name = id->name;
return bmi160_core_probe(&client->dev, regmap, name, false);
}
static int bmi160_i2c_remove(struct i2c_client *client)
{
bmi160_core_remove(&client->dev);
return 0;
}
static const struct i2c_device_id bmi160_i2c_id[] = {
{"bmi160", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, bmi160_i2c_id);
static const struct acpi_device_id bmi160_acpi_match[] = {
{"BMI0160", 0},
{ },
};
MODULE_DEVICE_TABLE(acpi, bmi160_acpi_match);
static struct i2c_driver bmi160_i2c_driver = {
.driver = {
.name = "bmi160_i2c",
.acpi_match_table = ACPI_PTR(bmi160_acpi_match),
},
.probe = bmi160_i2c_probe,
.remove = bmi160_i2c_remove,
.id_table = bmi160_i2c_id,
};
module_i2c_driver(bmi160_i2c_driver);
MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
MODULE_DESCRIPTION("BMI160 I2C driver");
MODULE_LICENSE("GPL v2");
/*
* BMI160 - Bosch IMU, SPI bits
*
* Copyright (c) 2016, Intel Corporation.
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*/
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/regmap.h>
#include <linux/acpi.h>
#include "bmi160.h"
static int bmi160_spi_probe(struct spi_device *spi)
{
struct regmap *regmap;
const struct spi_device_id *id = spi_get_device_id(spi);
regmap = devm_regmap_init_spi(spi, &bmi160_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&spi->dev, "Failed to register spi regmap %d\n",
(int)PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return bmi160_core_probe(&spi->dev, regmap, id->name, true);
}
static int bmi160_spi_remove(struct spi_device *spi)
{
bmi160_core_remove(&spi->dev);
return 0;
}
static const struct spi_device_id bmi160_spi_id[] = {
{"bmi160", 0},
{}
};
MODULE_DEVICE_TABLE(spi, bmi160_spi_id);
static const struct acpi_device_id bmi160_acpi_match[] = {
{"BMI0160", 0},
{ },
};
MODULE_DEVICE_TABLE(acpi, bmi160_acpi_match);
static struct spi_driver bmi160_spi_driver = {
.probe = bmi160_spi_probe,
.remove = bmi160_spi_remove,
.id_table = bmi160_spi_id,
.driver = {
.acpi_match_table = ACPI_PTR(bmi160_acpi_match),
.name = "bmi160_spi",
},
};
module_spi_driver(bmi160_spi_driver);
MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com");
MODULE_DESCRIPTION("Bosch BMI160 SPI driver");
MODULE_LICENSE("GPL v2");
...@@ -13,10 +13,8 @@ config INV_MPU6050_I2C ...@@ -13,10 +13,8 @@ config INV_MPU6050_I2C
select INV_MPU6050_IIO select INV_MPU6050_IIO
select REGMAP_I2C select REGMAP_I2C
help help
This driver supports the Invensense MPU6050 devices. This driver supports the Invensense MPU6050/6500/9150 motion tracking
This driver can also support MPU6500 in MPU6050 compatibility mode devices over I2C.
and also in MPU6500 mode with some limitations.
It is a gyroscope/accelerometer combo device.
This driver can be built as a module. The module will be called This driver can be built as a module. The module will be called
inv-mpu6050-i2c. inv-mpu6050-i2c.
...@@ -26,7 +24,7 @@ config INV_MPU6050_SPI ...@@ -26,7 +24,7 @@ config INV_MPU6050_SPI
select INV_MPU6050_IIO select INV_MPU6050_IIO
select REGMAP_SPI select REGMAP_SPI
help help
This driver supports the Invensense MPU6050 devices. This driver supports the Invensense MPU6000/6500/9150 motion tracking
It is a gyroscope/accelerometer combo device. devices over SPI.
This driver can be built as a module. The module will be called This driver can be built as a module. The module will be called
inv-mpu6050-spi. inv-mpu6050-spi.
...@@ -88,16 +88,29 @@ static const struct inv_mpu6050_chip_config chip_config_6050 = { ...@@ -88,16 +88,29 @@ static const struct inv_mpu6050_chip_config chip_config_6050 = {
.accl_fs = INV_MPU6050_FS_02G, .accl_fs = INV_MPU6050_FS_02G,
}; };
/* Indexed by enum inv_devices */
static const struct inv_mpu6050_hw hw_info[] = { static const struct inv_mpu6050_hw hw_info[] = {
{ {
.num_reg = 117, .whoami = INV_MPU6050_WHOAMI_VALUE,
.name = "MPU6050",
.reg = &reg_set_6050,
.config = &chip_config_6050,
},
{
.whoami = INV_MPU6500_WHOAMI_VALUE,
.name = "MPU6500", .name = "MPU6500",
.reg = &reg_set_6500, .reg = &reg_set_6500,
.config = &chip_config_6050, .config = &chip_config_6050,
}, },
{ {
.num_reg = 117, .whoami = INV_MPU6000_WHOAMI_VALUE,
.name = "MPU6050", .name = "MPU6000",
.reg = &reg_set_6050,
.config = &chip_config_6050,
},
{
.whoami = INV_MPU9150_WHOAMI_VALUE,
.name = "MPU9150",
.reg = &reg_set_6050, .reg = &reg_set_6050,
.config = &chip_config_6050, .config = &chip_config_6050,
}, },
...@@ -600,6 +613,10 @@ inv_fifo_rate_show(struct device *dev, struct device_attribute *attr, ...@@ -600,6 +613,10 @@ inv_fifo_rate_show(struct device *dev, struct device_attribute *attr,
/** /**
* inv_attr_show() - calling this function will show current * inv_attr_show() - calling this function will show current
* parameters. * parameters.
*
* Deprecated in favor of IIO mounting matrix API.
*
* See inv_get_mount_matrix()
*/ */
static ssize_t inv_attr_show(struct device *dev, struct device_attribute *attr, static ssize_t inv_attr_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -644,6 +661,18 @@ static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev, ...@@ -644,6 +661,18 @@ static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev,
return 0; return 0;
} }
static const struct iio_mount_matrix *
inv_get_mount_matrix(const struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
return &((struct inv_mpu6050_state *)iio_priv(indio_dev))->orientation;
}
static const struct iio_chan_spec_ext_info inv_ext_info[] = {
IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, inv_get_mount_matrix),
{ },
};
#define INV_MPU6050_CHAN(_type, _channel2, _index) \ #define INV_MPU6050_CHAN(_type, _channel2, _index) \
{ \ { \
.type = _type, \ .type = _type, \
...@@ -660,6 +689,7 @@ static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev, ...@@ -660,6 +689,7 @@ static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev,
.shift = 0, \ .shift = 0, \
.endianness = IIO_BE, \ .endianness = IIO_BE, \
}, \ }, \
.ext_info = inv_ext_info, \
} }
static const struct iio_chan_spec inv_mpu_channels[] = { static const struct iio_chan_spec inv_mpu_channels[] = {
...@@ -692,14 +722,16 @@ static IIO_CONST_ATTR(in_accel_scale_available, ...@@ -692,14 +722,16 @@ static IIO_CONST_ATTR(in_accel_scale_available,
"0.000598 0.001196 0.002392 0.004785"); "0.000598 0.001196 0.002392 0.004785");
static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, inv_fifo_rate_show, static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, inv_fifo_rate_show,
inv_mpu6050_fifo_rate_store); inv_mpu6050_fifo_rate_store);
/* Deprecated: kept for userspace backward compatibility. */
static IIO_DEVICE_ATTR(in_gyro_matrix, S_IRUGO, inv_attr_show, NULL, static IIO_DEVICE_ATTR(in_gyro_matrix, S_IRUGO, inv_attr_show, NULL,
ATTR_GYRO_MATRIX); ATTR_GYRO_MATRIX);
static IIO_DEVICE_ATTR(in_accel_matrix, S_IRUGO, inv_attr_show, NULL, static IIO_DEVICE_ATTR(in_accel_matrix, S_IRUGO, inv_attr_show, NULL,
ATTR_ACCL_MATRIX); ATTR_ACCL_MATRIX);
static struct attribute *inv_attributes[] = { static struct attribute *inv_attributes[] = {
&iio_dev_attr_in_gyro_matrix.dev_attr.attr, &iio_dev_attr_in_gyro_matrix.dev_attr.attr, /* deprecated */
&iio_dev_attr_in_accel_matrix.dev_attr.attr, &iio_dev_attr_in_accel_matrix.dev_attr.attr, /* deprecated */
&iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_const_attr_in_accel_scale_available.dev_attr.attr, &iio_const_attr_in_accel_scale_available.dev_attr.attr,
...@@ -726,6 +758,7 @@ static const struct iio_info mpu_info = { ...@@ -726,6 +758,7 @@ static const struct iio_info mpu_info = {
static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
{ {
int result; int result;
unsigned int regval;
st->hw = &hw_info[st->chip_type]; st->hw = &hw_info[st->chip_type];
st->reg = hw_info[st->chip_type].reg; st->reg = hw_info[st->chip_type].reg;
...@@ -736,6 +769,17 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) ...@@ -736,6 +769,17 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
if (result) if (result)
return result; return result;
msleep(INV_MPU6050_POWER_UP_TIME); msleep(INV_MPU6050_POWER_UP_TIME);
/* check chip self-identification */
result = regmap_read(st->map, INV_MPU6050_REG_WHOAMI, &regval);
if (result)
return result;
if (regval != st->hw->whoami) {
dev_warn(regmap_get_device(st->map),
"whoami mismatch got %#02x expected %#02hhx for %s\n",
regval, st->hw->whoami, st->hw->name);
}
/* /*
* toggle power state. After reset, the sleep bit could be on * toggle power state. After reset, the sleep bit could be on
* or off depending on the OTP settings. Toggling power would * or off depending on the OTP settings. Toggling power would
...@@ -774,14 +818,31 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, ...@@ -774,14 +818,31 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
if (!indio_dev) if (!indio_dev)
return -ENOMEM; return -ENOMEM;
BUILD_BUG_ON(ARRAY_SIZE(hw_info) != INV_NUM_PARTS);
if (chip_type < 0 || chip_type >= INV_NUM_PARTS) {
dev_err(dev, "Bad invensense chip_type=%d name=%s\n",
chip_type, name);
return -ENODEV;
}
st = iio_priv(indio_dev); st = iio_priv(indio_dev);
st->chip_type = chip_type; st->chip_type = chip_type;
st->powerup_count = 0; st->powerup_count = 0;
st->irq = irq; st->irq = irq;
st->map = regmap; st->map = regmap;
pdata = dev_get_platdata(dev); pdata = dev_get_platdata(dev);
if (pdata) if (!pdata) {
result = of_iio_read_mount_matrix(dev, "mount-matrix",
&st->orientation);
if (result) {
dev_err(dev, "Failed to retrieve mounting matrix %d\n",
result);
return result;
}
} else {
st->plat_data = *pdata; st->plat_data = *pdata;
}
/* power is turned on inside check chip type*/ /* power is turned on inside check chip type*/
result = inv_check_and_setup_chip(st); result = inv_check_and_setup_chip(st);
if (result) if (result)
......
...@@ -202,13 +202,14 @@ static int inv_mpu_remove(struct i2c_client *client) ...@@ -202,13 +202,14 @@ static int inv_mpu_remove(struct i2c_client *client)
static const struct i2c_device_id inv_mpu_id[] = { static const struct i2c_device_id inv_mpu_id[] = {
{"mpu6050", INV_MPU6050}, {"mpu6050", INV_MPU6050},
{"mpu6500", INV_MPU6500}, {"mpu6500", INV_MPU6500},
{"mpu9150", INV_MPU9150},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, inv_mpu_id); MODULE_DEVICE_TABLE(i2c, inv_mpu_id);
static const struct acpi_device_id inv_acpi_match[] = { static const struct acpi_device_id inv_acpi_match[] = {
{"INVN6500", 0}, {"INVN6500", INV_MPU6500},
{ }, { },
}; };
......
...@@ -68,6 +68,7 @@ enum inv_devices { ...@@ -68,6 +68,7 @@ enum inv_devices {
INV_MPU6050, INV_MPU6050,
INV_MPU6500, INV_MPU6500,
INV_MPU6000, INV_MPU6000,
INV_MPU9150,
INV_NUM_PARTS INV_NUM_PARTS
}; };
...@@ -93,13 +94,13 @@ struct inv_mpu6050_chip_config { ...@@ -93,13 +94,13 @@ struct inv_mpu6050_chip_config {
/** /**
* struct inv_mpu6050_hw - Other important hardware information. * struct inv_mpu6050_hw - Other important hardware information.
* @num_reg: Number of registers on device. * @whoami: Self identification byte from WHO_AM_I register
* @name: name of the chip. * @name: name of the chip.
* @reg: register map of the chip. * @reg: register map of the chip.
* @config: configuration of the chip. * @config: configuration of the chip.
*/ */
struct inv_mpu6050_hw { struct inv_mpu6050_hw {
u8 num_reg; u8 whoami;
u8 *name; u8 *name;
const struct inv_mpu6050_reg_map *reg; const struct inv_mpu6050_reg_map *reg;
const struct inv_mpu6050_chip_config *config; const struct inv_mpu6050_chip_config *config;
...@@ -114,7 +115,8 @@ struct inv_mpu6050_hw { ...@@ -114,7 +115,8 @@ struct inv_mpu6050_hw {
* @hw: Other hardware-specific information. * @hw: Other hardware-specific information.
* @chip_type: chip type. * @chip_type: chip type.
* @time_stamp_lock: spin lock to time stamp. * @time_stamp_lock: spin lock to time stamp.
* @plat_data: platform data. * @plat_data: platform data (deprecated in favor of @orientation).
* @orientation: sensor chip orientation relative to main hardware.
* @timestamps: kfifo queue to store time stamp. * @timestamps: kfifo queue to store time stamp.
* @map regmap pointer. * @map regmap pointer.
* @irq interrupt number. * @irq interrupt number.
...@@ -131,6 +133,7 @@ struct inv_mpu6050_state { ...@@ -131,6 +133,7 @@ struct inv_mpu6050_state {
struct i2c_client *mux_client; struct i2c_client *mux_client;
unsigned int powerup_count; unsigned int powerup_count;
struct inv_mpu6050_platform_data plat_data; struct inv_mpu6050_platform_data plat_data;
struct iio_mount_matrix orientation;
DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE); DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
struct regmap *map; struct regmap *map;
int irq; int irq;
...@@ -215,6 +218,13 @@ struct inv_mpu6050_state { ...@@ -215,6 +218,13 @@ struct inv_mpu6050_state {
#define INV_MPU6050_MIN_FIFO_RATE 4 #define INV_MPU6050_MIN_FIFO_RATE 4
#define INV_MPU6050_ONE_K_HZ 1000 #define INV_MPU6050_ONE_K_HZ 1000
#define INV_MPU6050_REG_WHOAMI 117
#define INV_MPU6000_WHOAMI_VALUE 0x68
#define INV_MPU6050_WHOAMI_VALUE 0x68
#define INV_MPU6500_WHOAMI_VALUE 0x70
#define INV_MPU9150_WHOAMI_VALUE 0x68
/* scan element definition */ /* scan element definition */
enum inv_mpu6050_scan { enum inv_mpu6050_scan {
INV_MPU6050_SCAN_ACCL_X, INV_MPU6050_SCAN_ACCL_X,
......
...@@ -44,9 +44,19 @@ static int inv_mpu_i2c_disable(struct iio_dev *indio_dev) ...@@ -44,9 +44,19 @@ static int inv_mpu_i2c_disable(struct iio_dev *indio_dev)
static int inv_mpu_probe(struct spi_device *spi) static int inv_mpu_probe(struct spi_device *spi)
{ {
struct regmap *regmap; struct regmap *regmap;
const struct spi_device_id *id = spi_get_device_id(spi); const struct spi_device_id *spi_id;
const char *name = id ? id->name : NULL; const struct acpi_device_id *acpi_id;
const int chip_type = id ? id->driver_data : 0; const char *name = NULL;
enum inv_devices chip_type;
if ((spi_id = spi_get_device_id(spi))) {
chip_type = (enum inv_devices)spi_id->driver_data;
name = spi_id->name;
} else if ((acpi_id = acpi_match_device(spi->dev.driver->acpi_match_table, &spi->dev))) {
chip_type = (enum inv_devices)acpi_id->driver_data;
} else {
return -ENODEV;
}
regmap = devm_regmap_init_spi(spi, &inv_mpu_regmap_config); regmap = devm_regmap_init_spi(spi, &inv_mpu_regmap_config);
if (IS_ERR(regmap)) { if (IS_ERR(regmap)) {
...@@ -70,13 +80,15 @@ static int inv_mpu_remove(struct spi_device *spi) ...@@ -70,13 +80,15 @@ static int inv_mpu_remove(struct spi_device *spi)
*/ */
static const struct spi_device_id inv_mpu_id[] = { static const struct spi_device_id inv_mpu_id[] = {
{"mpu6000", INV_MPU6000}, {"mpu6000", INV_MPU6000},
{"mpu6500", INV_MPU6500},
{"mpu9150", INV_MPU9150},
{} {}
}; };
MODULE_DEVICE_TABLE(spi, inv_mpu_id); MODULE_DEVICE_TABLE(spi, inv_mpu_id);
static const struct acpi_device_id inv_acpi_match[] = { static const struct acpi_device_id inv_acpi_match[] = {
{"INVN6000", 0}, {"INVN6000", INV_MPU6000},
{ }, { },
}; };
MODULE_DEVICE_TABLE(acpi, inv_acpi_match); MODULE_DEVICE_TABLE(acpi, inv_acpi_match);
......
...@@ -412,6 +412,88 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, ...@@ -412,6 +412,88 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
} }
EXPORT_SYMBOL_GPL(iio_enum_write); EXPORT_SYMBOL_GPL(iio_enum_write);
static const struct iio_mount_matrix iio_mount_idmatrix = {
.rotation = {
"1", "0", "0",
"0", "1", "0",
"0", "0", "1"
}
};
static int iio_setup_mount_idmatrix(const struct device *dev,
struct iio_mount_matrix *matrix)
{
*matrix = iio_mount_idmatrix;
dev_info(dev, "mounting matrix not found: using identity...\n");
return 0;
}
ssize_t iio_show_mount_matrix(struct iio_dev *indio_dev, uintptr_t priv,
const struct iio_chan_spec *chan, char *buf)
{
const struct iio_mount_matrix *mtx = ((iio_get_mount_matrix_t *)
priv)(indio_dev, chan);
if (IS_ERR(mtx))
return PTR_ERR(mtx);
if (!mtx)
mtx = &iio_mount_idmatrix;
return snprintf(buf, PAGE_SIZE, "%s, %s, %s; %s, %s, %s; %s, %s, %s\n",
mtx->rotation[0], mtx->rotation[1], mtx->rotation[2],
mtx->rotation[3], mtx->rotation[4], mtx->rotation[5],
mtx->rotation[6], mtx->rotation[7], mtx->rotation[8]);
}
EXPORT_SYMBOL_GPL(iio_show_mount_matrix);
/**
* of_iio_read_mount_matrix() - retrieve iio device mounting matrix from
* device-tree "mount-matrix" property
* @dev: device the mounting matrix property is assigned to
* @propname: device specific mounting matrix property name
* @matrix: where to store retrieved matrix
*
* If device is assigned no mounting matrix property, a default 3x3 identity
* matrix will be filled in.
*
* Return: 0 if success, or a negative error code on failure.
*/
#ifdef CONFIG_OF
int of_iio_read_mount_matrix(const struct device *dev,
const char *propname,
struct iio_mount_matrix *matrix)
{
if (dev->of_node) {
int err = of_property_read_string_array(dev->of_node,
propname, matrix->rotation,
ARRAY_SIZE(iio_mount_idmatrix.rotation));
if (err == ARRAY_SIZE(iio_mount_idmatrix.rotation))
return 0;
if (err >= 0)
/* Invalid number of matrix entries. */
return -EINVAL;
if (err != -EINVAL)
/* Invalid matrix declaration format. */
return err;
}
/* Matrix was not declared at all: fallback to identity. */
return iio_setup_mount_idmatrix(dev, matrix);
}
#else
int of_iio_read_mount_matrix(const struct device *dev,
const char *propname,
struct iio_mount_matrix *matrix)
{
return iio_setup_mount_idmatrix(dev, matrix);
}
#endif
EXPORT_SYMBOL(of_iio_read_mount_matrix);
/** /**
* iio_format_value() - Formats a IIO value into its string representation * iio_format_value() - Formats a IIO value into its string representation
* @buf: The buffer to which the formatted value gets written * @buf: The buffer to which the formatted value gets written
......
...@@ -356,6 +356,54 @@ void iio_channel_release(struct iio_channel *channel) ...@@ -356,6 +356,54 @@ void iio_channel_release(struct iio_channel *channel)
} }
EXPORT_SYMBOL_GPL(iio_channel_release); EXPORT_SYMBOL_GPL(iio_channel_release);
static void devm_iio_channel_free(struct device *dev, void *res)
{
struct iio_channel *channel = *(struct iio_channel **)res;
iio_channel_release(channel);
}
static int devm_iio_channel_match(struct device *dev, void *res, void *data)
{
struct iio_channel **r = res;
if (!r || !*r) {
WARN_ON(!r || !*r);
return 0;
}
return *r == data;
}
struct iio_channel *devm_iio_channel_get(struct device *dev,
const char *channel_name)
{
struct iio_channel **ptr, *channel;
ptr = devres_alloc(devm_iio_channel_free, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
channel = iio_channel_get(dev, channel_name);
if (IS_ERR(channel)) {
devres_free(ptr);
return channel;
}
*ptr = channel;
devres_add(dev, ptr);
return channel;
}
EXPORT_SYMBOL_GPL(devm_iio_channel_get);
void devm_iio_channel_release(struct device *dev, struct iio_channel *channel)
{
WARN_ON(devres_release(dev, devm_iio_channel_free,
devm_iio_channel_match, channel));
}
EXPORT_SYMBOL_GPL(devm_iio_channel_release);
struct iio_channel *iio_channel_get_all(struct device *dev) struct iio_channel *iio_channel_get_all(struct device *dev)
{ {
const char *name; const char *name;
...@@ -441,6 +489,42 @@ void iio_channel_release_all(struct iio_channel *channels) ...@@ -441,6 +489,42 @@ void iio_channel_release_all(struct iio_channel *channels)
} }
EXPORT_SYMBOL_GPL(iio_channel_release_all); EXPORT_SYMBOL_GPL(iio_channel_release_all);
static void devm_iio_channel_free_all(struct device *dev, void *res)
{
struct iio_channel *channels = *(struct iio_channel **)res;
iio_channel_release_all(channels);
}
struct iio_channel *devm_iio_channel_get_all(struct device *dev)
{
struct iio_channel **ptr, *channels;
ptr = devres_alloc(devm_iio_channel_free_all, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
channels = iio_channel_get_all(dev);
if (IS_ERR(channels)) {
devres_free(ptr);
return channels;
}
*ptr = channels;
devres_add(dev, ptr);
return channels;
}
EXPORT_SYMBOL_GPL(devm_iio_channel_get_all);
void devm_iio_channel_release_all(struct device *dev,
struct iio_channel *channels)
{
WARN_ON(devres_release(dev, devm_iio_channel_free_all,
devm_iio_channel_match, channels));
}
EXPORT_SYMBOL_GPL(devm_iio_channel_release_all);
static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, static int iio_channel_read(struct iio_channel *chan, int *val, int *val2,
enum iio_chan_info_enum info) enum iio_chan_info_enum info)
{ {
...@@ -452,7 +536,7 @@ static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, ...@@ -452,7 +536,7 @@ static int iio_channel_read(struct iio_channel *chan, int *val, int *val2,
if (val2 == NULL) if (val2 == NULL)
val2 = &unused; val2 = &unused;
if(!iio_channel_has_info(chan->channel, info)) if (!iio_channel_has_info(chan->channel, info))
return -EINVAL; return -EINVAL;
if (chan->indio_dev->info->read_raw_multi) { if (chan->indio_dev->info->read_raw_multi) {
......
...@@ -73,6 +73,17 @@ config BH1750 ...@@ -73,6 +73,17 @@ config BH1750
To compile this driver as a module, choose M here: the module will To compile this driver as a module, choose M here: the module will
be called bh1750. be called bh1750.
config BH1780
tristate "ROHM BH1780 ambient light sensor"
depends on I2C
depends on !SENSORS_BH1780
help
Say Y here to build support for the ROHM BH1780GLI ambient
light sensor.
To compile this driver as a module, choose M here: the module will
be called bh1780.
config CM32181 config CM32181
depends on I2C depends on I2C
tristate "CM32181 driver" tristate "CM32181 driver"
...@@ -223,6 +234,17 @@ config LTR501 ...@@ -223,6 +234,17 @@ config LTR501
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called ltr501. will be called ltr501.
config MAX44000
tristate "MAX44000 Ambient and Infrared Proximity Sensor"
depends on I2C
select REGMAP_I2C
help
Say Y here if you want to build support for Maxim Integrated's
MAX44000 ambient and infrared proximity sensor device.
To compile this driver as a module, choose M here:
the module will be called max44000.
config OPT3001 config OPT3001
tristate "Texas Instruments OPT3001 Light Sensor" tristate "Texas Instruments OPT3001 Light Sensor"
depends on I2C depends on I2C
...@@ -320,4 +342,14 @@ config VCNL4000 ...@@ -320,4 +342,14 @@ config VCNL4000
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called vcnl4000. module will be called vcnl4000.
config VEML6070
tristate "VEML6070 UV A light sensor"
depends on I2C
help
Say Y here if you want to build a driver for the Vishay VEML6070 UV A
light sensor.
To compile this driver as a module, choose M here: the
module will be called veml6070.
endmenu endmenu
...@@ -9,6 +9,7 @@ obj-$(CONFIG_AL3320A) += al3320a.o ...@@ -9,6 +9,7 @@ obj-$(CONFIG_AL3320A) += al3320a.o
obj-$(CONFIG_APDS9300) += apds9300.o obj-$(CONFIG_APDS9300) += apds9300.o
obj-$(CONFIG_APDS9960) += apds9960.o obj-$(CONFIG_APDS9960) += apds9960.o
obj-$(CONFIG_BH1750) += bh1750.o obj-$(CONFIG_BH1750) += bh1750.o
obj-$(CONFIG_BH1780) += bh1780.o
obj-$(CONFIG_CM32181) += cm32181.o obj-$(CONFIG_CM32181) += cm32181.o
obj-$(CONFIG_CM3232) += cm3232.o obj-$(CONFIG_CM3232) += cm3232.o
obj-$(CONFIG_CM3323) += cm3323.o obj-$(CONFIG_CM3323) += cm3323.o
...@@ -20,6 +21,7 @@ obj-$(CONFIG_ISL29125) += isl29125.o ...@@ -20,6 +21,7 @@ obj-$(CONFIG_ISL29125) += isl29125.o
obj-$(CONFIG_JSA1212) += jsa1212.o obj-$(CONFIG_JSA1212) += jsa1212.o
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
obj-$(CONFIG_LTR501) += ltr501.o obj-$(CONFIG_LTR501) += ltr501.o
obj-$(CONFIG_MAX44000) += max44000.o
obj-$(CONFIG_OPT3001) += opt3001.o obj-$(CONFIG_OPT3001) += opt3001.o
obj-$(CONFIG_PA12203001) += pa12203001.o obj-$(CONFIG_PA12203001) += pa12203001.o
obj-$(CONFIG_RPR0521) += rpr0521.o obj-$(CONFIG_RPR0521) += rpr0521.o
...@@ -30,3 +32,4 @@ obj-$(CONFIG_TCS3472) += tcs3472.o ...@@ -30,3 +32,4 @@ obj-$(CONFIG_TCS3472) += tcs3472.o
obj-$(CONFIG_TSL4531) += tsl4531.o obj-$(CONFIG_TSL4531) += tsl4531.o
obj-$(CONFIG_US5182D) += us5182d.o obj-$(CONFIG_US5182D) += us5182d.o
obj-$(CONFIG_VCNL4000) += vcnl4000.o obj-$(CONFIG_VCNL4000) += vcnl4000.o
obj-$(CONFIG_VEML6070) += veml6070.o
...@@ -321,8 +321,12 @@ static const struct iio_chan_spec apds9960_channels[] = { ...@@ -321,8 +321,12 @@ static const struct iio_chan_spec apds9960_channels[] = {
}; };
/* integration time in us */ /* integration time in us */
static const int apds9960_int_time[][2] = static const int apds9960_int_time[][2] = {
{ {28000, 246}, {100000, 219}, {200000, 182}, {700000, 0} }; { 28000, 246},
{100000, 219},
{200000, 182},
{700000, 0}
};
/* gain mapping */ /* gain mapping */
static const int apds9960_pxs_gain_map[] = {1, 2, 4, 8}; static const int apds9960_pxs_gain_map[] = {1, 2, 4, 8};
...@@ -491,9 +495,10 @@ static int apds9960_read_raw(struct iio_dev *indio_dev, ...@@ -491,9 +495,10 @@ static int apds9960_read_raw(struct iio_dev *indio_dev,
case IIO_INTENSITY: case IIO_INTENSITY:
ret = regmap_bulk_read(data->regmap, chan->address, ret = regmap_bulk_read(data->regmap, chan->address,
&buf, 2); &buf, 2);
if (!ret) if (!ret) {
ret = IIO_VAL_INT; ret = IIO_VAL_INT;
*val = le16_to_cpu(buf); *val = le16_to_cpu(buf);
}
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
......
/*
* ROHM 1780GLI Ambient Light Sensor Driver
*
* Copyright (C) 2016 Linaro Ltd.
* Author: Linus Walleij <linus.walleij@linaro.org>
* Loosely based on the previous BH1780 ALS misc driver
* Copyright (C) 2010 Texas Instruments
* Author: Hemanth V <hemanthv@ti.com>
*/
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/bitops.h>
#define BH1780_CMD_BIT BIT(7)
#define BH1780_REG_CONTROL 0x00
#define BH1780_REG_PARTID 0x0A
#define BH1780_REG_MANFID 0x0B
#define BH1780_REG_DLOW 0x0C
#define BH1780_REG_DHIGH 0x0D
#define BH1780_REVMASK GENMASK(3,0)
#define BH1780_POWMASK GENMASK(1,0)
#define BH1780_POFF (0x0)
#define BH1780_PON (0x3)
/* power on settling time in ms */
#define BH1780_PON_DELAY 2
/* max time before value available in ms */
#define BH1780_INTERVAL 250
struct bh1780_data {
struct i2c_client *client;
};
static int bh1780_write(struct bh1780_data *bh1780, u8 reg, u8 val)
{
int ret = i2c_smbus_write_byte_data(bh1780->client,
BH1780_CMD_BIT | reg,
val);
if (ret < 0)
dev_err(&bh1780->client->dev,
"i2c_smbus_write_byte_data failed error "
"%d, register %01x\n",
ret, reg);
return ret;
}
static int bh1780_read(struct bh1780_data *bh1780, u8 reg)
{
int ret = i2c_smbus_read_byte_data(bh1780->client,
BH1780_CMD_BIT | reg);
if (ret < 0)
dev_err(&bh1780->client->dev,
"i2c_smbus_read_byte_data failed error "
"%d, register %01x\n",
ret, reg);
return ret;
}
static int bh1780_read_word(struct bh1780_data *bh1780, u8 reg)
{
int ret = i2c_smbus_read_word_data(bh1780->client,
BH1780_CMD_BIT | reg);
if (ret < 0)
dev_err(&bh1780->client->dev,
"i2c_smbus_read_word_data failed error "
"%d, register %01x\n",
ret, reg);
return ret;
}
static int bh1780_debugfs_reg_access(struct iio_dev *indio_dev,
unsigned int reg, unsigned int writeval,
unsigned int *readval)
{
struct bh1780_data *bh1780 = iio_priv(indio_dev);
int ret;
if (!readval)
bh1780_write(bh1780, (u8)reg, (u8)writeval);
ret = bh1780_read(bh1780, (u8)reg);
if (ret < 0)
return ret;
*readval = ret;
return 0;
}
static int bh1780_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct bh1780_data *bh1780 = iio_priv(indio_dev);
int value;
switch (mask) {
case IIO_CHAN_INFO_RAW:
switch (chan->type) {
case IIO_LIGHT:
pm_runtime_get_sync(&bh1780->client->dev);
value = bh1780_read_word(bh1780, BH1780_REG_DLOW);
if (value < 0)
return value;
pm_runtime_mark_last_busy(&bh1780->client->dev);
pm_runtime_put_autosuspend(&bh1780->client->dev);
*val = value;
return IIO_VAL_INT;
default:
return -EINVAL;
}
case IIO_CHAN_INFO_INT_TIME:
*val = 0;
*val2 = BH1780_INTERVAL * 1000;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
}
static const struct iio_info bh1780_info = {
.driver_module = THIS_MODULE,
.read_raw = bh1780_read_raw,
.debugfs_reg_access = bh1780_debugfs_reg_access,
};
static const struct iio_chan_spec bh1780_channels[] = {
{
.type = IIO_LIGHT,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_INT_TIME)
}
};
static int bh1780_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
struct bh1780_data *bh1780;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct iio_dev *indio_dev;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
return -EIO;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*bh1780));
if (!indio_dev)
return -ENOMEM;
bh1780 = iio_priv(indio_dev);
bh1780->client = client;
i2c_set_clientdata(client, indio_dev);
/* Power up the device */
ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_PON);
if (ret < 0)
return ret;
msleep(BH1780_PON_DELAY);
pm_runtime_get_noresume(&client->dev);
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
ret = bh1780_read(bh1780, BH1780_REG_PARTID);
if (ret < 0)
goto out_disable_pm;
dev_info(&client->dev,
"Ambient Light Sensor, Rev : %lu\n",
(ret & BH1780_REVMASK));
/*
* As the device takes 250 ms to even come up with a fresh
* measurement after power-on, do not shut it down unnecessarily.
* Set autosuspend to a five seconds.
*/
pm_runtime_set_autosuspend_delay(&client->dev, 5000);
pm_runtime_use_autosuspend(&client->dev);
pm_runtime_put(&client->dev);
indio_dev->dev.parent = &client->dev;
indio_dev->info = &bh1780_info;
indio_dev->name = id->name;
indio_dev->channels = bh1780_channels;
indio_dev->num_channels = ARRAY_SIZE(bh1780_channels);
indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_device_register(indio_dev);
if (ret)
goto out_disable_pm;
return 0;
out_disable_pm:
pm_runtime_put_noidle(&client->dev);
pm_runtime_disable(&client->dev);
return ret;
}
static int bh1780_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct bh1780_data *bh1780 = iio_priv(indio_dev);
int ret;
iio_device_unregister(indio_dev);
pm_runtime_get_sync(&client->dev);
pm_runtime_put_noidle(&client->dev);
pm_runtime_disable(&client->dev);
ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_POFF);
if (ret < 0) {
dev_err(&client->dev, "failed to power off\n");
return ret;
}
return 0;
}
#ifdef CONFIG_PM
static int bh1780_runtime_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct bh1780_data *bh1780 = i2c_get_clientdata(client);
int ret;
ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_POFF);
if (ret < 0) {
dev_err(dev, "failed to runtime suspend\n");
return ret;
}
return 0;
}
static int bh1780_runtime_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct bh1780_data *bh1780 = i2c_get_clientdata(client);
int ret;
ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_PON);
if (ret < 0) {
dev_err(dev, "failed to runtime resume\n");
return ret;
}
/* Wait for power on, then for a value to be available */
msleep(BH1780_PON_DELAY + BH1780_INTERVAL);
return 0;
}
#endif /* CONFIG_PM */
static const struct dev_pm_ops bh1780_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(bh1780_runtime_suspend,
bh1780_runtime_resume, NULL)
};
static const struct i2c_device_id bh1780_id[] = {
{ "bh1780", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, bh1780_id);
#ifdef CONFIG_OF
static const struct of_device_id of_bh1780_match[] = {
{ .compatible = "rohm,bh1780gli", },
{},
};
MODULE_DEVICE_TABLE(of, of_bh1780_match);
#endif
static struct i2c_driver bh1780_driver = {
.probe = bh1780_probe,
.remove = bh1780_remove,
.id_table = bh1780_id,
.driver = {
.name = "bh1780",
.pm = &bh1780_dev_pm_ops,
.of_match_table = of_match_ptr(of_bh1780_match),
},
};
module_i2c_driver(bh1780_driver);
MODULE_DESCRIPTION("ROHM BH1780GLI Ambient Light Sensor Driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
This diff is collapsed.
This diff is collapsed.
...@@ -9,6 +9,8 @@ config AK8975 ...@@ -9,6 +9,8 @@ config AK8975
tristate "Asahi Kasei AK 3-Axis Magnetometer" tristate "Asahi Kasei AK 3-Axis Magnetometer"
depends on I2C depends on I2C
depends on GPIOLIB || COMPILE_TEST depends on GPIOLIB || COMPILE_TEST
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help help
Say yes here to build support for Asahi Kasei AK8975, AK8963, Say yes here to build support for Asahi Kasei AK8975, AK8963,
AK09911 or AK09912 3-Axis Magnetometer. AK09911 or AK09912 3-Axis Magnetometer.
...@@ -25,22 +27,41 @@ config AK09911 ...@@ -25,22 +27,41 @@ config AK09911
Deprecated: AK09911 is now supported by AK8975 driver. Deprecated: AK09911 is now supported by AK8975 driver.
config BMC150_MAGN config BMC150_MAGN
tristate "Bosch BMC150 Magnetometer Driver" tristate
depends on I2C
select REGMAP_I2C
select IIO_BUFFER select IIO_BUFFER
select IIO_TRIGGERED_BUFFER select IIO_TRIGGERED_BUFFER
config BMC150_MAGN_I2C
tristate "Bosch BMC150 I2C Magnetometer Driver"
depends on I2C
select BMC150_MAGN
select REGMAP_I2C
help help
Say yes here to build support for the BMC150 magnetometer. Say yes here to build support for the BMC150 magnetometer with
I2C interface.
Currently this only supports the device via an i2c interface. This is a combo module with both accelerometer and magnetometer.
This driver is only implementing magnetometer part, which has
its own address and register map.
To compile this driver as a module, choose M here: the module will be
called bmc150_magn_i2c.
config BMC150_MAGN_SPI
tristate "Bosch BMC150 SPI Magnetometer Driver"
depends on SPI
select BMC150_MAGN
select REGMAP_SPI
help
Say yes here to build support for the BMC150 magnetometer with
SPI interface.
This is a combo module with both accelerometer and magnetometer. This is a combo module with both accelerometer and magnetometer.
This driver is only implementing magnetometer part, which has This driver is only implementing magnetometer part, which has
its own address and register map. its own address and register map.
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called bmc150_magn. called bmc150_magn_spi.
config MAG3110 config MAG3110
tristate "Freescale MAG3110 3-Axis Magnetometer" tristate "Freescale MAG3110 3-Axis Magnetometer"
......
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
# When adding new entries keep the list in alphabetical order # When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AK8975) += ak8975.o obj-$(CONFIG_AK8975) += ak8975.o
obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o
obj-$(CONFIG_BMC150_MAGN_I2C) += bmc150_magn_i2c.o
obj-$(CONFIG_BMC150_MAGN_SPI) += bmc150_magn_spi.o
obj-$(CONFIG_MAG3110) += mag3110.o obj-$(CONFIG_MAG3110) += mag3110.o
obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
obj-$(CONFIG_MMC35240) += mmc35240.o obj-$(CONFIG_MMC35240) += mmc35240.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment