Commit 34ff6c2f authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

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

Jonathan writes:

First set of IIO new device support, features and cleanup for the 4.12 cycle.

Quite a bit of outreachy activity here with a driver from a current intern
and a number of cleanup patches as part of the next round.

Getting a pull request in early this cycle as it's looking like another large
cycle for IIO.

New device support
* adxl345
  - initial device support. Note, once complete support is done the intent
    is to superceded the driver in input/misc.
  - bindings.
  - conversion from i2c direct calls to regmap and driver split.
  - spi support.
* chromeos light and proximity.
  - new driver.
* devantech srf04 ultrasonic ranger
  - new driver with device tree bindings.
* hid temperature
  - new driver for environemntal temperature support from hid devices.
* max30102 oximeter
  - new driver with device tree bindings.
* st lsm6dsx
  - refactor and addition of device support for lsm6dsl and lsm6ds3h.

Staging graduation
* isl29028 including copyright notice update to reflect Brian's work.
* lpc32xx_adc.
* spear adc. It's not perfect and there are some datasheet disagreements, but
  it works and is good enough to graduate.

New features
* documentation
  - abi docs for in_proximity_sampling_frequency_available.
  - generalise counting direction ABI docs as a second driver is going to
  use them.
* hid-sensor-prox
  - Add support for HID_USAGE_SENSOR_HUMAN_PRESENCE if used on a particular
  device.
* isl29028
  - runtime pm.
* meson-saradc
  - switch from polling to interrupt mode and improved read_raw_sample function
  to avoid unnecessary loop.
* tmp007
  - interrupt and threshold event support.

Cleanups and minor fixes
* ad2s1210
  - permissions to octal.
* ad7192
  - permissions to octal.
  - use BIT macro.
* ad9832
  - merge header definitions into source file.
* ad9834
  - merge header definitions into source file.
* ade7753
  - merge header definitions into source file.
  - cleanup include ordering.
* ade7854
  - simplify return logic.
* adis16201
  - merge header definitions into source file.
  - rename _core.c to .c as there is nothing else.
* adis16203
  - merge header definitions into source file.
  - rename _core.c to .c as there is nothing else.
* adis16209
  - merge header definitions into source file.
  - rename _core.c to .c as there is nothing else.
* adis16240
  - permissions to octal.
  - merge header definitions into source file.
  - rename _core.c to .c as there is nothing else.
* adt7136
  - permissions to octal.
* cio-dac
  - set missing parent device.
* documentation
  - update version numbers on sysfs ABI for counter bits that didn't quite.
  make 4.9.
* isl29028
  - mdelay to msleep.
  - incorrrect sleep time when taking first proximity reading.
* lmp91000
  - set missing parent device.
* lpc32xx
  - Consistent prefixes for defines.
  - rename local state structure to _state.
* max30100
  - set missing parent device.
* max30102
  - set missing parent device.
* maxim-thermocouple
  - set missing parent device.
* meter driver header
  - permissions to octal.
* pulsedlight-lidar-lite-v2
  - set missing parent device.
* quad-8
  - set missing parent device.
* st104
  - set missing parent device.

Other
* Mailmap
  - update Matt Ranostay's email address to the Konsolko one.
parents cc4e33d9 2df79e1b
...@@ -109,6 +109,7 @@ Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@osg.samsung.com> ...@@ -109,6 +109,7 @@ Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@osg.samsung.com>
Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@s-opensource.com> Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@s-opensource.com>
Matt Ranostay <mranostay@gmail.com> Matthew Ranostay <mranostay@embeddedalley.com> Matt Ranostay <mranostay@gmail.com> Matthew Ranostay <mranostay@embeddedalley.com>
Matt Ranostay <mranostay@gmail.com> <matt.ranostay@intel.com> Matt Ranostay <mranostay@gmail.com> <matt.ranostay@intel.com>
Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting>
Mayuresh Janorkar <mayur@ti.com> Mayuresh Janorkar <mayur@ti.com>
Michael Buesch <m@bues.ch> Michael Buesch <m@bues.ch>
Michel Dänzer <michel@tungstengraphics.com> Michel Dänzer <michel@tungstengraphics.com>
......
...@@ -55,6 +55,7 @@ Description: ...@@ -55,6 +55,7 @@ Description:
then it is to be found in the base device directory. then it is to be found in the base device directory.
What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency_available What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency_available
What: /sys/bus/iio/devices/iio:deviceX/in_proximity_sampling_frequency_available
What: /sys/.../iio:deviceX/buffer/sampling_frequency_available What: /sys/.../iio:deviceX/buffer/sampling_frequency_available
What: /sys/bus/iio/devices/triggerX/sampling_frequency_available What: /sys/bus/iio/devices/triggerX/sampling_frequency_available
KernelVersion: 2.6.35 KernelVersion: 2.6.35
...@@ -1593,7 +1594,7 @@ Description: ...@@ -1593,7 +1594,7 @@ Description:
can be processed to siemens per meter. can be processed to siemens per meter.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_raw What: /sys/bus/iio/devices/iio:deviceX/in_countY_raw
KernelVersion: 4.9 KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
Raw counter device counts from channel Y. For quadrature Raw counter device counts from channel Y. For quadrature
...@@ -1601,10 +1602,24 @@ Description: ...@@ -1601,10 +1602,24 @@ Description:
the counts of a single quadrature signal phase from channel Y. the counts of a single quadrature signal phase from channel Y.
What: /sys/bus/iio/devices/iio:deviceX/in_indexY_raw What: /sys/bus/iio/devices/iio:deviceX/in_indexY_raw
KernelVersion: 4.9 KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
Raw counter device index value from channel Y. This attribute Raw counter device index value from channel Y. This attribute
provides an absolute positional reference (e.g. a pulse once per provides an absolute positional reference (e.g. a pulse once per
revolution) which may be used to home positional systems as revolution) which may be used to home positional systems as
required. required.
What: /sys/bus/iio/devices/iio:deviceX/in_count_count_direction_available
KernelVersion: 4.12
Contact: linux-iio@vger.kernel.org
Description:
A list of possible counting directions which are:
- "up" : counter device is increasing.
- "down": counter device is decreasing.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_direction
KernelVersion: 4.12
Contact: linux-iio@vger.kernel.org
Description:
Raw counter device counters direction for channel Y.
What: /sys/bus/iio/devices/iio:deviceX/in_count_count_direction_available
What: /sys/bus/iio/devices/iio:deviceX/in_count_count_mode_available What: /sys/bus/iio/devices/iio:deviceX/in_count_count_mode_available
What: /sys/bus/iio/devices/iio:deviceX/in_count_noise_error_available What: /sys/bus/iio/devices/iio:deviceX/in_count_noise_error_available
What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available
What: /sys/bus/iio/devices/iio:deviceX/in_index_index_polarity_available What: /sys/bus/iio/devices/iio:deviceX/in_index_index_polarity_available
What: /sys/bus/iio/devices/iio:deviceX/in_index_synchronous_mode_available What: /sys/bus/iio/devices/iio:deviceX/in_index_synchronous_mode_available
KernelVersion: 4.9 KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
Discrete set of available values for the respective counter Discrete set of available values for the respective counter
configuration are listed in this file. configuration are listed in this file.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_direction
KernelVersion: 4.9
Contact: linux-iio@vger.kernel.org
Description:
Read-only attribute that indicates whether the counter for
channel Y is counting up or down.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_mode What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_mode
KernelVersion: 4.9 KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
Count mode for channel Y. Four count modes are available: Count mode for channel Y. Four count modes are available:
...@@ -52,7 +44,7 @@ Description: ...@@ -52,7 +44,7 @@ Description:
continuously throughout. continuously throughout.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_noise_error What: /sys/bus/iio/devices/iio:deviceX/in_countY_noise_error
KernelVersion: 4.9 KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
Read-only attribute that indicates whether excessive noise is Read-only attribute that indicates whether excessive noise is
...@@ -60,14 +52,14 @@ Description: ...@@ -60,14 +52,14 @@ Description:
irrelevant in non-quadrature clock mode. irrelevant in non-quadrature clock mode.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_preset What: /sys/bus/iio/devices/iio:deviceX/in_countY_preset
KernelVersion: 4.9 KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
If the counter device supports preset registers, the preset If the counter device supports preset registers, the preset
count for channel Y is provided by this attribute. count for channel Y is provided by this attribute.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_quadrature_mode What: /sys/bus/iio/devices/iio:deviceX/in_countY_quadrature_mode
KernelVersion: 4.9 KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
Configure channel Y counter for non-quadrature or quadrature Configure channel Y counter for non-quadrature or quadrature
...@@ -88,7 +80,7 @@ Description: ...@@ -88,7 +80,7 @@ Description:
decoded for UP/DN clock. decoded for UP/DN clock.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_set_to_preset_on_index What: /sys/bus/iio/devices/iio:deviceX/in_countY_set_to_preset_on_index
KernelVersion: 4.9 KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
Whether to set channel Y counter with channel Y preset value Whether to set channel Y counter with channel Y preset value
...@@ -96,14 +88,14 @@ Description: ...@@ -96,14 +88,14 @@ Description:
Valid attribute values are boolean. Valid attribute values are boolean.
What: /sys/bus/iio/devices/iio:deviceX/in_indexY_index_polarity What: /sys/bus/iio/devices/iio:deviceX/in_indexY_index_polarity
KernelVersion: 4.9 KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
Active level of channel Y index input; irrelevant in Active level of channel Y index input; irrelevant in
non-synchronous load mode. non-synchronous load mode.
What: /sys/bus/iio/devices/iio:deviceX/in_indexY_synchronous_mode What: /sys/bus/iio/devices/iio:deviceX/in_indexY_synchronous_mode
KernelVersion: 4.9 KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
Configure channel Y counter for non-synchronous or synchronous Configure channel Y counter for non-synchronous or synchronous
......
Analog Devices ADXL345 3-Axis, +/-(2g/4g/8g/16g) Digital Accelerometer
http://www.analog.com/en/products/mems/accelerometers/adxl345.html
Required properties:
- compatible : should be "adi,adxl345"
- reg : the I2C address or SPI chip select number of the sensor
Required properties for SPI bus usage:
- spi-max-frequency : set maximum clock frequency, must be 5000000
- spi-cpol and spi-cpha : must be defined for adxl345 to enable SPI mode 3
Optional properties:
- interrupt-parent : phandle to the parent interrupt controller as documented
in Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
- interrupts: interrupt mapping for IRQ as documented in
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
Example for a I2C device node:
accelerometer@2a {
compatible = "adi,adxl345";
reg = <0x53>;
interrupt-parent = <&gpio1>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
};
Example for a SPI device node:
accelerometer@0 {
compatible = "adi,adxl345";
reg = <0>;
spi-max-frequency = <5000000>;
spi-cpol;
spi-cpha;
interrupt-parent = <&gpio1>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
};
...@@ -7,6 +7,7 @@ Required properties: ...@@ -7,6 +7,7 @@ Required properties:
- "amlogic,meson-gxm-saradc" for GXM - "amlogic,meson-gxm-saradc" for GXM
along with the generic "amlogic,meson-saradc" along with the generic "amlogic,meson-saradc"
- reg: the physical base address and length of the registers - reg: the physical base address and length of the registers
- interrupts: the interrupt indicating end of sampling
- clocks: phandle and clock identifier (see clock-names) - clocks: phandle and clock identifier (see clock-names)
- clock-names: mandatory clocks: - clock-names: mandatory clocks:
- "clkin" for the reference clock (typically XTAL) - "clkin" for the reference clock (typically XTAL)
...@@ -23,6 +24,7 @@ Example: ...@@ -23,6 +24,7 @@ Example:
compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc"; compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
#io-channel-cells = <1>; #io-channel-cells = <1>;
reg = <0x0 0x8680 0x0 0x34>; reg = <0x0 0x8680 0x0 0x34>;
interrupts = <GIC_SPI 73 IRQ_TYPE_EDGE_RISING>;
clocks = <&xtal>, clocks = <&xtal>,
<&clkc CLKID_SAR_ADC>, <&clkc CLKID_SAR_ADC>,
<&clkc CLKID_SANA>, <&clkc CLKID_SANA>,
......
Maxim MAX30102 heart rate and pulse oximeter sensor
* https://datasheets.maximintegrated.com/en/ds/MAX30102.pdf
Required properties:
- compatible: must be "maxim,max30102"
- reg: the I2C address of the sensor
- interrupt-parent: should be the phandle for the interrupt controller
- interrupts: the sole interrupt generated by the device
Refer to interrupt-controller/interrupts.txt for generic
interrupt client node bindings.
Optional properties:
- maxim,red-led-current-microamp: configuration for RED LED current
- maxim,ir-led-current-microamp: configuration for IR LED current
Note that each step is approximately 200 microamps, ranging from 0 uA to
50800 uA.
Example:
max30100@57 {
compatible = "maxim,max30102";
reg = <0x57>;
maxim,red-led-current-microamp = <7000>;
maxim,ir-led-current-microamp = <7000>;
interrupt-parent = <&gpio1>;
interrupts = <16 2>;
};
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
Required properties: Required properties:
- compatible: must be one of: - compatible: must be one of:
"st,lsm6ds3" "st,lsm6ds3"
"st,lsm6ds3h"
"st,lsm6dsl"
"st,lsm6dsm" "st,lsm6dsm"
- reg: i2c address of the sensor / spi cs line - reg: i2c address of the sensor / spi cs line
......
* Devantech SRF04 ultrasonic range finder
Bit-banging driver using two GPIOs
Required properties:
- compatible: Should be "devantech,srf04"
- trig-gpios: Definition of the GPIO for the triggering (output)
This GPIO is set for about 10 us by the driver to tell the
device it should initiate the measurement cycle.
- echo-gpios: Definition of the GPIO for the echo (input)
This GPIO is set by the device as soon as an ultrasonic
burst is sent out and reset when the first echo is
received.
Thus this GPIO is set while the ultrasonic waves are doing
one round trip.
It needs to be an GPIO which is able to deliver an
interrupt because the time between two interrupts is
measured in the driver.
See Documentation/devicetree/bindings/gpio/gpio.txt for
information on how to specify a consumer gpio.
Example:
srf04@0 {
compatible = "devantech,srf04";
trig-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
echo-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
};
...@@ -3853,6 +3853,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git ...@@ -3853,6 +3853,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained S: Maintained
F: drivers/usb/dwc3/ F: drivers/usb/dwc3/
DEVANTECH SRF ULTRASONIC RANGER IIO DRIVER
M: Andreas Klinger <ak@it-klinger.de>
L: linux-iio@vger.kernel.org
S: Maintained
F: drivers/iio/proximity/srf*.c
DEVICE COREDUMP (DEV_COREDUMP) DEVICE COREDUMP (DEV_COREDUMP)
M: Johannes Berg <johannes@sipsolutions.net> M: Johannes Berg <johannes@sipsolutions.net>
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
......
...@@ -5,6 +5,37 @@ ...@@ -5,6 +5,37 @@
menu "Accelerometers" menu "Accelerometers"
config ADXL345
tristate
config ADXL345_I2C
tristate "Analog Devices ADXL345 3-Axis Digital Accelerometer I2C Driver"
depends on INPUT_ADXL34X=n
depends on I2C
select ADXL345
select REGMAP_I2C
help
Say Y here if you want to build support for the Analog Devices
ADXL345 3-axis digital accelerometer.
To compile this driver as a module, choose M here: the module
will be called adxl345_i2c and you will also get adxl345_core
for the core module.
config ADXL345_SPI
tristate "Analog Devices ADXL345 3-Axis Digital Accelerometer SPI Driver"
depends on INPUT_ADXL34X=n
depends on SPI
select ADXL345
select REGMAP_SPI
help
Say Y here if you want to build support for the Analog Devices
ADXL345 3-axis digital accelerometer.
To compile this driver as a module, choose M here: the module
will be called adxl345_spi and you will also get adxl345_core
for the core module.
config BMA180 config BMA180
tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver" tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver"
depends on I2C depends on I2C
......
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
# #
# When adding new entries keep the list in alphabetical order # When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ADXL345) += adxl345_core.o
obj-$(CONFIG_ADXL345_I2C) += adxl345_i2c.o
obj-$(CONFIG_ADXL345_SPI) += adxl345_spi.o
obj-$(CONFIG_BMA180) += bma180.o obj-$(CONFIG_BMA180) += bma180.o
obj-$(CONFIG_BMA220) += bma220_spi.o obj-$(CONFIG_BMA220) += bma220_spi.o
obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
......
/*
* ADXL345 3-Axis Digital Accelerometer
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* 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.
*/
#ifndef _ADXL345_H_
#define _ADXL345_H_
int adxl345_core_probe(struct device *dev, struct regmap *regmap,
const char *name);
int adxl345_core_remove(struct device *dev);
#endif /* _ADXL345_H_ */
/*
* ADXL345 3-Axis Digital Accelerometer IIO core driver
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* 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/regmap.h>
#include <linux/iio/iio.h>
#include "adxl345.h"
#define ADXL345_REG_DEVID 0x00
#define ADXL345_REG_POWER_CTL 0x2D
#define ADXL345_REG_DATA_FORMAT 0x31
#define ADXL345_REG_DATAX0 0x32
#define ADXL345_REG_DATAY0 0x34
#define ADXL345_REG_DATAZ0 0x36
#define ADXL345_POWER_CTL_MEASURE BIT(3)
#define ADXL345_POWER_CTL_STANDBY 0x00
#define ADXL345_DATA_FORMAT_FULL_RES BIT(3) /* Up to 13-bits resolution */
#define ADXL345_DATA_FORMAT_2G 0
#define ADXL345_DATA_FORMAT_4G 1
#define ADXL345_DATA_FORMAT_8G 2
#define ADXL345_DATA_FORMAT_16G 3
#define ADXL345_DEVID 0xE5
/*
* In full-resolution mode, scale factor is maintained at ~4 mg/LSB
* in all g ranges.
*
* At +/- 16g with 13-bit resolution, scale is computed as:
* (16 + 16) * 9.81 / (2^13 - 1) = 0.0383
*/
static const int adxl345_uscale = 38300;
struct adxl345_data {
struct regmap *regmap;
u8 data_range;
};
#define ADXL345_CHANNEL(reg, axis) { \
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.address = reg, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec adxl345_channels[] = {
ADXL345_CHANNEL(ADXL345_REG_DATAX0, X),
ADXL345_CHANNEL(ADXL345_REG_DATAY0, Y),
ADXL345_CHANNEL(ADXL345_REG_DATAZ0, Z),
};
static int adxl345_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct adxl345_data *data = iio_priv(indio_dev);
__le16 regval;
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
/*
* Data is stored in adjacent registers:
* ADXL345_REG_DATA(X0/Y0/Z0) contain the least significant byte
* and ADXL345_REG_DATA(X0/Y0/Z0) + 1 the most significant byte
*/
ret = regmap_bulk_read(data->regmap, chan->address, &regval,
sizeof(regval));
if (ret < 0)
return ret;
*val = sign_extend32(le16_to_cpu(regval), 12);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = adxl345_uscale;
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
static const struct iio_info adxl345_info = {
.driver_module = THIS_MODULE,
.read_raw = adxl345_read_raw,
};
int adxl345_core_probe(struct device *dev, struct regmap *regmap,
const char *name)
{
struct adxl345_data *data;
struct iio_dev *indio_dev;
u32 regval;
int ret;
ret = regmap_read(regmap, ADXL345_REG_DEVID, &regval);
if (ret < 0) {
dev_err(dev, "Error reading device ID: %d\n", ret);
return ret;
}
if (regval != ADXL345_DEVID) {
dev_err(dev, "Invalid device ID: %x, expected %x\n",
regval, ADXL345_DEVID);
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
dev_set_drvdata(dev, indio_dev);
data->regmap = regmap;
/* Enable full-resolution mode */
data->data_range = ADXL345_DATA_FORMAT_FULL_RES;
ret = regmap_write(data->regmap, ADXL345_REG_DATA_FORMAT,
data->data_range);
if (ret < 0) {
dev_err(dev, "Failed to set data range: %d\n", ret);
return ret;
}
indio_dev->dev.parent = dev;
indio_dev->name = name;
indio_dev->info = &adxl345_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = adxl345_channels;
indio_dev->num_channels = ARRAY_SIZE(adxl345_channels);
/* Enable measurement mode */
ret = regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
ADXL345_POWER_CTL_MEASURE);
if (ret < 0) {
dev_err(dev, "Failed to enable measurement mode: %d\n", ret);
return ret;
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(dev, "iio_device_register failed: %d\n", ret);
regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
ADXL345_POWER_CTL_STANDBY);
}
return ret;
}
EXPORT_SYMBOL_GPL(adxl345_core_probe);
int adxl345_core_remove(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adxl345_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
return regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
ADXL345_POWER_CTL_STANDBY);
}
EXPORT_SYMBOL_GPL(adxl345_core_remove);
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer core driver");
MODULE_LICENSE("GPL v2");
/*
* ADXL345 3-Axis Digital Accelerometer I2C driver
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* 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: 0x1D (ALT ADDRESS pin tied to VDDIO) or
* 0x53 (ALT ADDRESS pin grounded)
*/
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include "adxl345.h"
static const struct regmap_config adxl345_i2c_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int adxl345_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regmap *regmap;
regmap = devm_regmap_init_i2c(client, &adxl345_i2c_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "Error initializing i2c regmap: %ld\n",
PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return adxl345_core_probe(&client->dev, regmap, id ? id->name : NULL);
}
static int adxl345_i2c_remove(struct i2c_client *client)
{
return adxl345_core_remove(&client->dev);
}
static const struct i2c_device_id adxl345_i2c_id[] = {
{ "adxl345", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adxl345_i2c_id);
static const struct of_device_id adxl345_of_match[] = {
{ .compatible = "adi,adxl345" },
{ },
};
MODULE_DEVICE_TABLE(of, adxl345_of_match);
static struct i2c_driver adxl345_i2c_driver = {
.driver = {
.name = "adxl345_i2c",
.of_match_table = adxl345_of_match,
},
.probe = adxl345_i2c_probe,
.remove = adxl345_i2c_remove,
.id_table = adxl345_i2c_id,
};
module_i2c_driver(adxl345_i2c_driver);
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer I2C driver");
MODULE_LICENSE("GPL v2");
/*
* ADXL345 3-Axis Digital Accelerometer SPI driver
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* 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/regmap.h>
#include <linux/spi/spi.h>
#include "adxl345.h"
#define ADXL345_MAX_SPI_FREQ_HZ 5000000
static const struct regmap_config adxl345_spi_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
/* Setting bits 7 and 6 enables multiple-byte read */
.read_flag_mask = BIT(7) | BIT(6),
};
static int adxl345_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct regmap *regmap;
/* Bail out if max_speed_hz exceeds 5 MHz */
if (spi->max_speed_hz > ADXL345_MAX_SPI_FREQ_HZ) {
dev_err(&spi->dev, "SPI CLK, %d Hz exceeds 5 MHz\n",
spi->max_speed_hz);
return -EINVAL;
}
regmap = devm_regmap_init_spi(spi, &adxl345_spi_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return adxl345_core_probe(&spi->dev, regmap, id->name);
}
static int adxl345_spi_remove(struct spi_device *spi)
{
return adxl345_core_remove(&spi->dev);
}
static const struct spi_device_id adxl345_spi_id[] = {
{ "adxl345", 0 },
{ }
};
MODULE_DEVICE_TABLE(spi, adxl345_spi_id);
static const struct of_device_id adxl345_of_match[] = {
{ .compatible = "adi,adxl345" },
{ },
};
MODULE_DEVICE_TABLE(of, adxl345_of_match);
static struct spi_driver adxl345_spi_driver = {
.driver = {
.name = "adxl345_spi",
.of_match_table = adxl345_of_match,
},
.probe = adxl345_spi_probe,
.remove = adxl345_spi_remove,
.id_table = adxl345_spi_id,
};
module_spi_driver(adxl345_spi_driver);
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer SPI driver");
MODULE_LICENSE("GPL v2");
...@@ -305,6 +305,18 @@ config LPC18XX_ADC ...@@ -305,6 +305,18 @@ config LPC18XX_ADC
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 lpc18xx_adc. called lpc18xx_adc.
config LPC32XX_ADC
tristate "NXP LPC32XX ADC"
depends on ARCH_LPC32XX || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to build support for the integrated ADC inside the
LPC32XX SoC. Note that this feature uses the same hardware as the
touchscreen driver, so you should either select only one of the two
drivers (lpc32xx_adc or lpc32xx_ts) or, in the OpenFirmware case,
activate only one via device tree selection. Provides direct access
via sysfs.
config LTC2485 config LTC2485
tristate "Linear Technology LTC2485 ADC driver" tristate "Linear Technology LTC2485 ADC driver"
depends on I2C depends on I2C
...@@ -494,6 +506,17 @@ config ROCKCHIP_SARADC ...@@ -494,6 +506,17 @@ config ROCKCHIP_SARADC
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 rockchip_saradc. module will be called rockchip_saradc.
config SPEAR_ADC
tristate "ST SPEAr ADC"
depends on PLAT_SPEAR || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to build support for the integrated ADC inside the
ST SPEAr SoC. Provides direct access via sysfs.
To compile this driver as a module, choose M here: the
module will be called spear_adc.
config STM32_ADC_CORE config STM32_ADC_CORE
tristate "STMicroelectronics STM32 adc core" tristate "STMicroelectronics STM32 adc core"
depends on ARCH_STM32 || COMPILE_TEST depends on ARCH_STM32 || COMPILE_TEST
......
...@@ -30,6 +30,7 @@ obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o ...@@ -30,6 +30,7 @@ obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
obj-$(CONFIG_LTC2485) += ltc2485.o obj-$(CONFIG_LTC2485) += ltc2485.o
obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX11100) += max11100.o obj-$(CONFIG_MAX11100) += max11100.o
...@@ -46,6 +47,7 @@ obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o ...@@ -46,6 +47,7 @@ obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
obj-$(CONFIG_RCAR_GYRO_ADC) += rcar-gyroadc.o obj-$(CONFIG_RCAR_GYRO_ADC) += rcar-gyroadc.o
obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
obj-$(CONFIG_STX104) += stx104.o obj-$(CONFIG_STX104) += stx104.o
obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
obj-$(CONFIG_STM32_ADC) += stm32-adc.o obj-$(CONFIG_STM32_ADC) += stm32-adc.o
......
...@@ -38,27 +38,30 @@ ...@@ -38,27 +38,30 @@
/* /*
* LPC32XX registers definitions * LPC32XX registers definitions
*/ */
#define LPC32XX_ADC_SELECT(x) ((x) + 0x04) #define LPC32XXAD_SELECT(x) ((x) + 0x04)
#define LPC32XX_ADC_CTRL(x) ((x) + 0x08) #define LPC32XXAD_CTRL(x) ((x) + 0x08)
#define LPC32XX_ADC_VALUE(x) ((x) + 0x48) #define LPC32XXAD_VALUE(x) ((x) + 0x48)
/* Bit definitions for LPC32XX_ADC_SELECT: */ /* Bit definitions for LPC32XXAD_SELECT: */
#define AD_REFm 0x00000200 /* constant, always write this value! */ /* constant, always write this value! */
#define AD_REFp 0x00000080 /* constant, always write this value! */ #define LPC32XXAD_REFm 0x00000200
#define AD_IN 0x00000010 /* multiple of this is the */ /* constant, always write this value! */
/* channel number: 0, 1, 2 */ #define LPC32XXAD_REFp 0x00000080
#define AD_INTERNAL 0x00000004 /* constant, always write this value! */ /* multiple of this is the channel number: 0, 1, 2 */
#define LPC32XXAD_IN 0x00000010
/* Bit definitions for LPC32XX_ADC_CTRL: */ /* constant, always write this value! */
#define AD_STROBE 0x00000002 #define LPC32XXAD_INTERNAL 0x00000004
#define AD_PDN_CTRL 0x00000004
/* Bit definitions for LPC32XXAD_CTRL: */
/* Bit definitions for LPC32XX_ADC_VALUE: */ #define LPC32XXAD_STROBE 0x00000002
#define ADC_VALUE_MASK 0x000003FF #define LPC32XXAD_PDN_CTRL 0x00000004
#define MOD_NAME "lpc32xx-adc" /* Bit definitions for LPC32XXAD_VALUE: */
#define LPC32XXAD_VALUE_MASK 0x000003FF
struct lpc32xx_adc_info {
#define LPC32XXAD_NAME "lpc32xx-adc"
struct lpc32xx_adc_state {
void __iomem *adc_base; void __iomem *adc_base;
struct clk *clk; struct clk *clk;
struct completion completion; struct completion completion;
...@@ -72,20 +75,21 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev, ...@@ -72,20 +75,21 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
int *val2, int *val2,
long mask) long mask)
{ {
struct lpc32xx_adc_info *info = iio_priv(indio_dev); struct lpc32xx_adc_state *st = iio_priv(indio_dev);
if (mask == IIO_CHAN_INFO_RAW) { if (mask == IIO_CHAN_INFO_RAW) {
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
clk_prepare_enable(info->clk); clk_prepare_enable(st->clk);
/* Measurement setup */ /* Measurement setup */
__raw_writel(AD_INTERNAL | (chan->address) | AD_REFp | AD_REFm, __raw_writel(LPC32XXAD_INTERNAL | (chan->address) |
LPC32XX_ADC_SELECT(info->adc_base)); LPC32XXAD_REFp | LPC32XXAD_REFm,
LPC32XXAD_SELECT(st->adc_base));
/* Trigger conversion */ /* Trigger conversion */
__raw_writel(AD_PDN_CTRL | AD_STROBE, __raw_writel(LPC32XXAD_PDN_CTRL | LPC32XXAD_STROBE,
LPC32XX_ADC_CTRL(info->adc_base)); LPC32XXAD_CTRL(st->adc_base));
wait_for_completion(&info->completion); /* set by ISR */ wait_for_completion(&st->completion); /* set by ISR */
clk_disable_unprepare(info->clk); clk_disable_unprepare(st->clk);
*val = info->value; *val = st->value;
mutex_unlock(&indio_dev->mlock); mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT; return IIO_VAL_INT;
...@@ -104,7 +108,7 @@ static const struct iio_info lpc32xx_adc_iio_info = { ...@@ -104,7 +108,7 @@ static const struct iio_info lpc32xx_adc_iio_info = {
.indexed = 1, \ .indexed = 1, \
.channel = _index, \ .channel = _index, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.address = AD_IN * _index, \ .address = LPC32XXAD_IN * _index, \
.scan_index = _index, \ .scan_index = _index, \
} }
...@@ -116,19 +120,19 @@ static const struct iio_chan_spec lpc32xx_adc_iio_channels[] = { ...@@ -116,19 +120,19 @@ static const struct iio_chan_spec lpc32xx_adc_iio_channels[] = {
static irqreturn_t lpc32xx_adc_isr(int irq, void *dev_id) static irqreturn_t lpc32xx_adc_isr(int irq, void *dev_id)
{ {
struct lpc32xx_adc_info *info = dev_id; struct lpc32xx_adc_state *st = dev_id;
/* Read value and clear irq */ /* Read value and clear irq */
info->value = __raw_readl(LPC32XX_ADC_VALUE(info->adc_base)) & st->value = __raw_readl(LPC32XXAD_VALUE(st->adc_base)) &
ADC_VALUE_MASK; LPC32XXAD_VALUE_MASK;
complete(&info->completion); complete(&st->completion);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int lpc32xx_adc_probe(struct platform_device *pdev) static int lpc32xx_adc_probe(struct platform_device *pdev)
{ {
struct lpc32xx_adc_info *info = NULL; struct lpc32xx_adc_state *st = NULL;
struct resource *res; struct resource *res;
int retval = -ENODEV; int retval = -ENODEV;
struct iio_dev *iodev = NULL; struct iio_dev *iodev = NULL;
...@@ -140,23 +144,23 @@ static int lpc32xx_adc_probe(struct platform_device *pdev) ...@@ -140,23 +144,23 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
return -ENXIO; return -ENXIO;
} }
iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
if (!iodev) if (!iodev)
return -ENOMEM; return -ENOMEM;
info = iio_priv(iodev); st = iio_priv(iodev);
info->adc_base = devm_ioremap(&pdev->dev, res->start, st->adc_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res)); resource_size(res));
if (!info->adc_base) { if (!st->adc_base) {
dev_err(&pdev->dev, "failed mapping memory\n"); dev_err(&pdev->dev, "failed mapping memory\n");
return -EBUSY; return -EBUSY;
} }
info->clk = devm_clk_get(&pdev->dev, NULL); st->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(info->clk)) { if (IS_ERR(st->clk)) {
dev_err(&pdev->dev, "failed getting clock\n"); dev_err(&pdev->dev, "failed getting clock\n");
return PTR_ERR(info->clk); return PTR_ERR(st->clk);
} }
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
...@@ -166,7 +170,7 @@ static int lpc32xx_adc_probe(struct platform_device *pdev) ...@@ -166,7 +170,7 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
} }
retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0, retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0,
MOD_NAME, info); LPC32XXAD_NAME, st);
if (retval < 0) { if (retval < 0) {
dev_err(&pdev->dev, "failed requesting interrupt\n"); dev_err(&pdev->dev, "failed requesting interrupt\n");
return retval; return retval;
...@@ -174,9 +178,9 @@ static int lpc32xx_adc_probe(struct platform_device *pdev) ...@@ -174,9 +178,9 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, iodev); platform_set_drvdata(pdev, iodev);
init_completion(&info->completion); init_completion(&st->completion);
iodev->name = MOD_NAME; iodev->name = LPC32XXAD_NAME;
iodev->dev.parent = &pdev->dev; iodev->dev.parent = &pdev->dev;
iodev->info = &lpc32xx_adc_iio_info; iodev->info = &lpc32xx_adc_iio_info;
iodev->modes = INDIO_DIRECT_MODE; iodev->modes = INDIO_DIRECT_MODE;
...@@ -203,7 +207,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_adc_match); ...@@ -203,7 +207,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_adc_match);
static struct platform_driver lpc32xx_adc_driver = { static struct platform_driver lpc32xx_adc_driver = {
.probe = lpc32xx_adc_probe, .probe = lpc32xx_adc_probe,
.driver = { .driver = {
.name = MOD_NAME, .name = LPC32XXAD_NAME,
.of_match_table = of_match_ptr(lpc32xx_adc_match), .of_match_table = of_match_ptr(lpc32xx_adc_match),
}, },
}; };
......
...@@ -18,7 +18,9 @@ ...@@ -18,7 +18,9 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
...@@ -163,6 +165,7 @@ ...@@ -163,6 +165,7 @@
#define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8) #define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8)
#define MESON_SAR_ADC_MAX_FIFO_SIZE 32 #define MESON_SAR_ADC_MAX_FIFO_SIZE 32
#define MESON_SAR_ADC_TIMEOUT 100 /* ms */
#define MESON_SAR_ADC_CHAN(_chan) { \ #define MESON_SAR_ADC_CHAN(_chan) { \
.type = IIO_VOLTAGE, \ .type = IIO_VOLTAGE, \
...@@ -229,6 +232,7 @@ struct meson_sar_adc_priv { ...@@ -229,6 +232,7 @@ struct meson_sar_adc_priv {
struct clk_gate clk_gate; struct clk_gate clk_gate;
struct clk *adc_div_clk; struct clk *adc_div_clk;
struct clk_divider clk_div; struct clk_divider clk_div;
struct completion done;
}; };
static const struct regmap_config meson_sar_adc_regmap_config = { static const struct regmap_config meson_sar_adc_regmap_config = {
...@@ -274,33 +278,31 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, ...@@ -274,33 +278,31 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
int *val) int *val)
{ {
struct meson_sar_adc_priv *priv = iio_priv(indio_dev); struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
int ret, regval, fifo_chan, fifo_val, sum = 0, count = 0; int regval, fifo_chan, fifo_val, count;
ret = meson_sar_adc_wait_busy_clear(indio_dev); if(!wait_for_completion_timeout(&priv->done,
if (ret) msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT)))
return ret; return -ETIMEDOUT;
while (meson_sar_adc_get_fifo_count(indio_dev) > 0 &&
count < MESON_SAR_ADC_MAX_FIFO_SIZE) {
regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &regval);
fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK,
regval);
if (fifo_chan != chan->channel)
continue;
fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK,
regval);
fifo_val &= (BIT(priv->data->resolution) - 1);
sum += fifo_val; count = meson_sar_adc_get_fifo_count(indio_dev);
count++; if (count != 1) {
dev_err(&indio_dev->dev,
"ADC FIFO has %d element(s) instead of one\n", count);
return -EINVAL;
} }
if (!count) regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &regval);
return -ENOENT; fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval);
if (fifo_chan != chan->channel) {
dev_err(&indio_dev->dev,
"ADC FIFO entry belongs to channel %d instead of %d\n",
fifo_chan, chan->channel);
return -EINVAL;
}
*val = sum / count; fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval);
fifo_val &= GENMASK(priv->data->resolution - 1, 0);
*val = fifo_val;
return 0; return 0;
} }
...@@ -378,6 +380,12 @@ static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev) ...@@ -378,6 +380,12 @@ static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev)
{ {
struct meson_sar_adc_priv *priv = iio_priv(indio_dev); struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
reinit_completion(&priv->done);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_FIFO_IRQ_EN,
MESON_SAR_ADC_REG0_FIFO_IRQ_EN);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE); MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
...@@ -391,6 +399,9 @@ static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev) ...@@ -391,6 +399,9 @@ static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev)
{ {
struct meson_sar_adc_priv *priv = iio_priv(indio_dev); struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_SAMPLING_STOP, MESON_SAR_ADC_REG0_SAMPLING_STOP,
MESON_SAR_ADC_REG0_SAMPLING_STOP); MESON_SAR_ADC_REG0_SAMPLING_STOP);
...@@ -643,6 +654,7 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) ...@@ -643,6 +654,7 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
{ {
struct meson_sar_adc_priv *priv = iio_priv(indio_dev); struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
int ret; int ret;
u32 regval;
ret = meson_sar_adc_lock(indio_dev); ret = meson_sar_adc_lock(indio_dev);
if (ret) if (ret)
...@@ -667,6 +679,9 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) ...@@ -667,6 +679,9 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
goto err_sana_clk; goto err_sana_clk;
} }
regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
MESON_SAR_ADC_REG11_BANDGAP_EN, MESON_SAR_ADC_REG11_BANDGAP_EN,
MESON_SAR_ADC_REG11_BANDGAP_EN); MESON_SAR_ADC_REG11_BANDGAP_EN);
...@@ -728,6 +743,25 @@ static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev) ...@@ -728,6 +743,25 @@ static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
return 0; return 0;
} }
static irqreturn_t meson_sar_adc_irq(int irq, void *data)
{
struct iio_dev *indio_dev = data;
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
unsigned int cnt, threshold;
u32 regval;
regmap_read(priv->regmap, MESON_SAR_ADC_REG0, &regval);
cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
if (cnt < threshold)
return IRQ_NONE;
complete(&priv->done);
return IRQ_HANDLED;
}
static const struct iio_info meson_sar_adc_iio_info = { static const struct iio_info meson_sar_adc_iio_info = {
.read_raw = meson_sar_adc_iio_info_read_raw, .read_raw = meson_sar_adc_iio_info_read_raw,
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
...@@ -770,7 +804,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev) ...@@ -770,7 +804,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
void __iomem *base; void __iomem *base;
const struct of_device_id *match; const struct of_device_id *match;
int ret; int irq, ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
if (!indio_dev) { if (!indio_dev) {
...@@ -779,6 +813,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev) ...@@ -779,6 +813,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
} }
priv = iio_priv(indio_dev); priv = iio_priv(indio_dev);
init_completion(&priv->done);
match = of_match_device(meson_sar_adc_of_match, &pdev->dev); match = of_match_device(meson_sar_adc_of_match, &pdev->dev);
priv->data = match->data; priv->data = match->data;
...@@ -797,6 +832,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev) ...@@ -797,6 +832,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_ERR(base); return PTR_ERR(base);
irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
if (!irq)
return -EINVAL;
ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED,
dev_name(&pdev->dev), indio_dev);
if (ret)
return ret;
priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
&meson_sar_adc_regmap_config); &meson_sar_adc_regmap_config);
if (IS_ERR(priv->regmap)) if (IS_ERR(priv->regmap))
......
...@@ -318,6 +318,7 @@ static int stx104_probe(struct device *dev, unsigned int id) ...@@ -318,6 +318,7 @@ static int stx104_probe(struct device *dev, unsigned int id)
} }
indio_dev->name = dev_name(dev); indio_dev->name = dev_name(dev);
indio_dev->dev.parent = dev;
priv = iio_priv(indio_dev); priv = iio_priv(indio_dev);
priv->base = base[id]; priv->base = base[id];
......
...@@ -62,6 +62,9 @@ static struct { ...@@ -62,6 +62,9 @@ static struct {
{HID_USAGE_SENSOR_TIME_TIMESTAMP, 0, 1000000000, 0}, {HID_USAGE_SENSOR_TIME_TIMESTAMP, 0, 1000000000, 0},
{HID_USAGE_SENSOR_TIME_TIMESTAMP, HID_USAGE_SENSOR_UNITS_MILLISECOND, {HID_USAGE_SENSOR_TIME_TIMESTAMP, HID_USAGE_SENSOR_UNITS_MILLISECOND,
1000000, 0}, 1000000, 0},
{HID_USAGE_SENSOR_TEMPERATURE, 0, 1000, 0},
{HID_USAGE_SENSOR_TEMPERATURE, HID_USAGE_SENSOR_UNITS_DEGREES, 1000, 0},
}; };
static int pow_10(unsigned power) static int pow_10(unsigned power)
......
...@@ -551,6 +551,7 @@ static int quad8_probe(struct device *dev, unsigned int id) ...@@ -551,6 +551,7 @@ static int quad8_probe(struct device *dev, unsigned int id)
indio_dev->num_channels = ARRAY_SIZE(quad8_channels); indio_dev->num_channels = ARRAY_SIZE(quad8_channels);
indio_dev->channels = quad8_channels; indio_dev->channels = quad8_channels;
indio_dev->name = dev_name(dev); indio_dev->name = dev_name(dev);
indio_dev->dev.parent = dev;
priv = iio_priv(indio_dev); priv = iio_priv(indio_dev);
priv->base = base[id]; priv->base = base[id];
......
...@@ -119,6 +119,7 @@ static int cio_dac_probe(struct device *dev, unsigned int id) ...@@ -119,6 +119,7 @@ static int cio_dac_probe(struct device *dev, unsigned int id)
indio_dev->channels = cio_dac_channels; indio_dev->channels = cio_dac_channels;
indio_dev->num_channels = CIO_DAC_NUM_CHAN; indio_dev->num_channels = CIO_DAC_NUM_CHAN;
indio_dev->name = dev_name(dev); indio_dev->name = dev_name(dev);
indio_dev->dev.parent = dev;
priv = iio_priv(indio_dev); priv = iio_priv(indio_dev);
priv->base = base[id]; priv->base = base[id];
......
...@@ -46,6 +46,19 @@ config MAX30100 ...@@ -46,6 +46,19 @@ config MAX30100
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 max30100. module will be called max30100.
config MAX30102
tristate "MAX30102 heart rate and pulse oximeter sensor"
depends on I2C
select REGMAP_I2C
select IIO_BUFFER
select IIO_KFIFO_BUF
help
Say Y here to build I2C interface support for the Maxim
MAX30102 heart rate, and pulse oximeter sensor.
To compile this driver as a module, choose M here: the
module will be called max30102.
endmenu endmenu
endmenu endmenu
...@@ -7,3 +7,4 @@ ...@@ -7,3 +7,4 @@
obj-$(CONFIG_AFE4403) += afe4403.o obj-$(CONFIG_AFE4403) += afe4403.o
obj-$(CONFIG_AFE4404) += afe4404.o obj-$(CONFIG_AFE4404) += afe4404.o
obj-$(CONFIG_MAX30100) += max30100.o obj-$(CONFIG_MAX30100) += max30100.o
obj-$(CONFIG_MAX30102) += max30102.o
...@@ -449,6 +449,7 @@ static int max30100_probe(struct i2c_client *client, ...@@ -449,6 +449,7 @@ static int max30100_probe(struct i2c_client *client,
indio_dev->available_scan_masks = max30100_scan_masks; indio_dev->available_scan_masks = max30100_scan_masks;
indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE); indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
indio_dev->setup_ops = &max30100_buffer_setup_ops; indio_dev->setup_ops = &max30100_buffer_setup_ops;
indio_dev->dev.parent = &client->dev;
data = iio_priv(indio_dev); data = iio_priv(indio_dev);
data->indio_dev = indio_dev; data->indio_dev = indio_dev;
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ config IIO_ST_LSM6DSX ...@@ -8,7 +8,7 @@ config IIO_ST_LSM6DSX
select IIO_ST_LSM6DSX_SPI if (SPI_MASTER) select IIO_ST_LSM6DSX_SPI if (SPI_MASTER)
help help
Say yes here to build support for STMicroelectronics LSM6DSx imu Say yes here to build support for STMicroelectronics LSM6DSx imu
sensor. Supported devices: lsm6ds3, lsm6dsm sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called st_lsm6dsx. will be called st_lsm6dsx.
......
...@@ -15,11 +15,16 @@ ...@@ -15,11 +15,16 @@
#include <linux/device.h> #include <linux/device.h>
#define ST_LSM6DS3_DEV_NAME "lsm6ds3" #define ST_LSM6DS3_DEV_NAME "lsm6ds3"
#define ST_LSM6DS3H_DEV_NAME "lsm6ds3h"
#define ST_LSM6DSL_DEV_NAME "lsm6dsl"
#define ST_LSM6DSM_DEV_NAME "lsm6dsm" #define ST_LSM6DSM_DEV_NAME "lsm6dsm"
enum st_lsm6dsx_hw_id { enum st_lsm6dsx_hw_id {
ST_LSM6DS3_ID, ST_LSM6DS3_ID,
ST_LSM6DS3H_ID,
ST_LSM6DSL_ID,
ST_LSM6DSM_ID, ST_LSM6DSM_ID,
ST_LSM6DSX_MAX_ID,
}; };
#define ST_LSM6DSX_CHAN_SIZE 2 #define ST_LSM6DSX_CHAN_SIZE 2
...@@ -50,7 +55,7 @@ struct st_lsm6dsx_reg { ...@@ -50,7 +55,7 @@ struct st_lsm6dsx_reg {
struct st_lsm6dsx_settings { struct st_lsm6dsx_settings {
u8 wai; u8 wai;
u16 max_fifo_size; u16 max_fifo_size;
enum st_lsm6dsx_hw_id id; enum st_lsm6dsx_hw_id id[ST_LSM6DSX_MAX_ID];
}; };
enum st_lsm6dsx_sensor_id { enum st_lsm6dsx_sensor_id {
......
/* /*
* STMicroelectronics st_lsm6dsx FIFO buffer library driver * STMicroelectronics st_lsm6dsx FIFO buffer library driver
* *
* LSM6DS3/LSM6DSM: The FIFO buffer can be configured to store data * LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM: The FIFO buffer can be configured
* from gyroscope and accelerometer. Samples are queued without any tag * to store data from gyroscope and accelerometer. Samples are queued
* according to a specific pattern based on 'FIFO data sets' (6 bytes each): * without any tag according to a specific pattern based on 'FIFO data sets'
* (6 bytes each):
* - 1st data set is reserved for gyroscope data * - 1st data set is reserved for gyroscope data
* - 2nd data set is reserved for accelerometer data * - 2nd data set is reserved for accelerometer data
* The FIFO pattern changes depending on the ODRs and decimation factors * The FIFO pattern changes depending on the ODRs and decimation factors
...@@ -206,7 +207,7 @@ int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark) ...@@ -206,7 +207,7 @@ int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark)
} }
/** /**
* st_lsm6dsx_read_fifo() - LSM6DS3-LSM6DSM read FIFO routine * st_lsm6dsx_read_fifo() - LSM6DS3-LSM6DS3H-LSM6DSL-LSM6DSM read FIFO routine
* @hw: Pointer to instance of struct st_lsm6dsx_hw. * @hw: Pointer to instance of struct st_lsm6dsx_hw.
* *
* Read samples from the hw FIFO and push them to IIO buffers. * Read samples from the hw FIFO and push them to IIO buffers.
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
* - FIFO size: 8KB * - FIFO size: 8KB
* *
* - LSM6DSM: * - LSM6DS3H/LSM6DSL/LSM6DSM:
* - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416
* - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
* - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
...@@ -74,12 +74,6 @@ ...@@ -74,12 +74,6 @@
#define ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR 0x24 #define ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR 0x24
#define ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR 0x26 #define ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR 0x26
#define ST_LSM6DS3_WHOAMI 0x69
#define ST_LSM6DSM_WHOAMI 0x6a
#define ST_LSM6DS3_MAX_FIFO_SIZE 8192
#define ST_LSM6DSM_MAX_FIFO_SIZE 4096
#define ST_LSM6DSX_ACC_FS_2G_GAIN IIO_G_TO_M_S_2(61) #define ST_LSM6DSX_ACC_FS_2G_GAIN IIO_G_TO_M_S_2(61)
#define ST_LSM6DSX_ACC_FS_4G_GAIN IIO_G_TO_M_S_2(122) #define ST_LSM6DSX_ACC_FS_4G_GAIN IIO_G_TO_M_S_2(122)
#define ST_LSM6DSX_ACC_FS_8G_GAIN IIO_G_TO_M_S_2(244) #define ST_LSM6DSX_ACC_FS_8G_GAIN IIO_G_TO_M_S_2(244)
...@@ -164,14 +158,26 @@ static const struct st_lsm6dsx_fs_table_entry st_lsm6dsx_fs_table[] = { ...@@ -164,14 +158,26 @@ static const struct st_lsm6dsx_fs_table_entry st_lsm6dsx_fs_table[] = {
static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
{ {
.wai = ST_LSM6DS3_WHOAMI, .wai = 0x69,
.max_fifo_size = ST_LSM6DS3_MAX_FIFO_SIZE, .max_fifo_size = 8192,
.id = ST_LSM6DS3_ID, .id = {
[0] = ST_LSM6DS3_ID,
},
}, },
{ {
.wai = ST_LSM6DSM_WHOAMI, .wai = 0x69,
.max_fifo_size = ST_LSM6DSM_MAX_FIFO_SIZE, .max_fifo_size = 4096,
.id = ST_LSM6DSM_ID, .id = {
[0] = ST_LSM6DS3H_ID,
},
},
{
.wai = 0x6a,
.max_fifo_size = 4096,
.id = {
[0] = ST_LSM6DSL_ID,
[1] = ST_LSM6DSM_ID,
},
}, },
}; };
...@@ -241,11 +247,15 @@ int st_lsm6dsx_write_with_mask(struct st_lsm6dsx_hw *hw, u8 addr, u8 mask, ...@@ -241,11 +247,15 @@ int st_lsm6dsx_write_with_mask(struct st_lsm6dsx_hw *hw, u8 addr, u8 mask,
static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id) static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id)
{ {
int err, i; int err, i, j;
u8 data; u8 data;
for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) { for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) {
if (id == st_lsm6dsx_sensor_settings[i].id) for (j = 0; j < ST_LSM6DSX_MAX_ID; j++) {
if (id == st_lsm6dsx_sensor_settings[i].id[j])
break;
}
if (j < ST_LSM6DSX_MAX_ID)
break; break;
} }
......
...@@ -70,6 +70,14 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = { ...@@ -70,6 +70,14 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = {
.compatible = "st,lsm6ds3", .compatible = "st,lsm6ds3",
.data = (void *)ST_LSM6DS3_ID, .data = (void *)ST_LSM6DS3_ID,
}, },
{
.compatible = "st,lsm6ds3h",
.data = (void *)ST_LSM6DS3H_ID,
},
{
.compatible = "st,lsm6dsl",
.data = (void *)ST_LSM6DSL_ID,
},
{ {
.compatible = "st,lsm6dsm", .compatible = "st,lsm6dsm",
.data = (void *)ST_LSM6DSM_ID, .data = (void *)ST_LSM6DSM_ID,
...@@ -80,6 +88,8 @@ MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match); ...@@ -80,6 +88,8 @@ MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match);
static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = { static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = {
{ ST_LSM6DS3_DEV_NAME, ST_LSM6DS3_ID }, { ST_LSM6DS3_DEV_NAME, ST_LSM6DS3_ID },
{ ST_LSM6DS3H_DEV_NAME, ST_LSM6DS3H_ID },
{ ST_LSM6DSL_DEV_NAME, ST_LSM6DSL_ID },
{ ST_LSM6DSM_DEV_NAME, ST_LSM6DSM_ID }, { ST_LSM6DSM_DEV_NAME, ST_LSM6DSM_ID },
{}, {},
}; };
......
...@@ -87,6 +87,14 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = { ...@@ -87,6 +87,14 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = {
.compatible = "st,lsm6ds3", .compatible = "st,lsm6ds3",
.data = (void *)ST_LSM6DS3_ID, .data = (void *)ST_LSM6DS3_ID,
}, },
{
.compatible = "st,lsm6ds3h",
.data = (void *)ST_LSM6DS3H_ID,
},
{
.compatible = "st,lsm6dsl",
.data = (void *)ST_LSM6DSL_ID,
},
{ {
.compatible = "st,lsm6dsm", .compatible = "st,lsm6dsm",
.data = (void *)ST_LSM6DSM_ID, .data = (void *)ST_LSM6DSM_ID,
...@@ -97,6 +105,8 @@ MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match); ...@@ -97,6 +105,8 @@ MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match);
static const struct spi_device_id st_lsm6dsx_spi_id_table[] = { static const struct spi_device_id st_lsm6dsx_spi_id_table[] = {
{ ST_LSM6DS3_DEV_NAME, ST_LSM6DS3_ID }, { ST_LSM6DS3_DEV_NAME, ST_LSM6DS3_ID },
{ ST_LSM6DS3H_DEV_NAME, ST_LSM6DS3H_ID },
{ ST_LSM6DSL_DEV_NAME, ST_LSM6DSL_ID },
{ ST_LSM6DSM_DEV_NAME, ST_LSM6DSM_ID }, { ST_LSM6DSM_DEV_NAME, ST_LSM6DSM_ID },
{}, {},
}; };
......
...@@ -136,6 +136,16 @@ config CM36651 ...@@ -136,6 +136,16 @@ config CM36651
To compile this driver as a module, choose M here: To compile this driver as a module, choose M here:
the module will be called cm36651. the module will be called cm36651.
config IIO_CROS_EC_LIGHT_PROX
tristate "ChromeOS EC Light and Proximity Sensors"
depends on IIO_CROS_EC_SENSORS_CORE
help
Say Y here if you use the light and proximity sensors
presented by the ChromeOS EC Sensor hub.
To compile this driver as a module, choose M here:
the module will be called cros_ec_light_prox.
config GP2AP020A00F config GP2AP020A00F
tristate "Sharp GP2AP020A00F Proximity/ALS sensor" tristate "Sharp GP2AP020A00F Proximity/ALS sensor"
depends on I2C depends on I2C
......
...@@ -15,6 +15,7 @@ obj-$(CONFIG_CM3232) += cm3232.o ...@@ -15,6 +15,7 @@ obj-$(CONFIG_CM3232) += cm3232.o
obj-$(CONFIG_CM3323) += cm3323.o obj-$(CONFIG_CM3323) += cm3323.o
obj-$(CONFIG_CM3605) += cm3605.o obj-$(CONFIG_CM3605) += cm3605.o
obj-$(CONFIG_CM36651) += cm36651.o obj-$(CONFIG_CM36651) += cm36651.o
obj-$(CONFIG_IIO_CROS_EC_LIGHT_PROX) += cros_ec_light_prox.o
obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o
......
/*
* cros_ec_light_prox - Driver for light and prox sensors behing CrosEC.
*
* Copyright (C) 2017 Google, Inc
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/trigger.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/kernel.h>
#include <linux/mfd/cros_ec.h>
#include <linux/mfd/cros_ec_commands.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include "../common/cros_ec_sensors/cros_ec_sensors_core.h"
/*
* We only represent one entry for light or proximity. EC is merging different
* light sensors to return the what the eye would see. For proximity, we
* currently support only one light source.
*/
#define CROS_EC_LIGHT_PROX_MAX_CHANNELS (1 + 1)
/* State data for ec_sensors iio driver. */
struct cros_ec_light_prox_state {
/* Shared by all sensors */
struct cros_ec_sensors_core_state core;
struct iio_chan_spec channels[CROS_EC_LIGHT_PROX_MAX_CHANNELS];
};
static int cros_ec_light_prox_read(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct cros_ec_light_prox_state *st = iio_priv(indio_dev);
u16 data = 0;
s64 val64;
int ret = IIO_VAL_INT;
int idx = chan->scan_index;
mutex_lock(&st->core.cmd_lock);
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (chan->type == IIO_PROXIMITY) {
if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx,
(s16 *)&data) < 0) {
ret = -EIO;
break;
}
*val = data;
} else {
ret = -EINVAL;
}
break;
case IIO_CHAN_INFO_PROCESSED:
if (chan->type == IIO_LIGHT) {
if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx,
(s16 *)&data) < 0) {
ret = -EIO;
break;
}
/*
* The data coming from the light sensor is
* pre-processed and represents the ambient light
* illuminance reading expressed in lux.
*/
*val = data;
ret = IIO_VAL_INT;
} else {
ret = -EINVAL;
}
break;
case IIO_CHAN_INFO_CALIBBIAS:
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
st->core.param.sensor_offset.flags = 0;
if (cros_ec_motion_send_host_cmd(&st->core, 0)) {
ret = -EIO;
break;
}
/* Save values */
st->core.calib[0] = st->core.resp->sensor_offset.offset[0];
*val = st->core.calib[idx];
break;
case IIO_CHAN_INFO_CALIBSCALE:
/*
* RANGE is used for calibration
* scale is a number x.y, where x is coded on 16 bits,
* y coded on 16 bits, between 0 and 9999.
*/
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;
if (cros_ec_motion_send_host_cmd(&st->core, 0)) {
ret = -EIO;
break;
}
val64 = st->core.resp->sensor_range.ret;
*val = val64 >> 16;
*val2 = (val64 & 0xffff) * 100;
ret = IIO_VAL_INT_PLUS_MICRO;
break;
default:
ret = cros_ec_sensors_core_read(&st->core, chan, val, val2,
mask);
break;
}
mutex_unlock(&st->core.cmd_lock);
return ret;
}
static int cros_ec_light_prox_write(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct cros_ec_light_prox_state *st = iio_priv(indio_dev);
int ret = 0;
int idx = chan->scan_index;
mutex_lock(&st->core.cmd_lock);
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
st->core.calib[idx] = val;
/* Send to EC for each axis, even if not complete */
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
st->core.param.sensor_offset.flags = MOTION_SENSE_SET_OFFSET;
st->core.param.sensor_offset.offset[0] = st->core.calib[0];
st->core.param.sensor_offset.temp =
EC_MOTION_SENSE_INVALID_CALIB_TEMP;
if (cros_ec_motion_send_host_cmd(&st->core, 0))
ret = -EIO;
break;
case IIO_CHAN_INFO_CALIBSCALE:
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
st->core.param.sensor_range.data = (val << 16) | (val2 / 100);
if (cros_ec_motion_send_host_cmd(&st->core, 0))
ret = -EIO;
break;
default:
ret = cros_ec_sensors_core_write(&st->core, chan, val, val2,
mask);
break;
}
mutex_unlock(&st->core.cmd_lock);
return ret;
}
static const struct iio_info cros_ec_light_prox_info = {
.read_raw = &cros_ec_light_prox_read,
.write_raw = &cros_ec_light_prox_write,
.driver_module = THIS_MODULE,
};
static int cros_ec_light_prox_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
struct cros_ec_device *ec_device;
struct iio_dev *indio_dev;
struct cros_ec_light_prox_state *state;
struct iio_chan_spec *channel;
int ret;
if (!ec_dev || !ec_dev->ec_dev) {
dev_warn(dev, "No CROS EC device found.\n");
return -EINVAL;
}
ec_device = ec_dev->ec_dev;
indio_dev = devm_iio_device_alloc(dev, sizeof(*state));
if (!indio_dev)
return -ENOMEM;
ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
if (ret)
return ret;
indio_dev->info = &cros_ec_light_prox_info;
state = iio_priv(indio_dev);
state->core.type = state->core.resp->info.type;
state->core.loc = state->core.resp->info.location;
channel = state->channels;
/* Common part */
channel->info_mask_shared_by_all =
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_FREQUENCY);
channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
channel->scan_type.shift = 0;
channel->scan_index = 0;
channel->ext_info = cros_ec_sensors_ext_info;
channel->scan_type.sign = 'u';
state->core.calib[0] = 0;
/* Sensor specific */
switch (state->core.type) {
case MOTIONSENSE_TYPE_LIGHT:
channel->type = IIO_LIGHT;
channel->info_mask_separate =
BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_CALIBBIAS) |
BIT(IIO_CHAN_INFO_CALIBSCALE);
break;
case MOTIONSENSE_TYPE_PROX:
channel->type = IIO_PROXIMITY;
channel->info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_CALIBBIAS) |
BIT(IIO_CHAN_INFO_CALIBSCALE);
break;
default:
dev_warn(dev, "Unknown motion sensor\n");
return -EINVAL;
}
/* Timestamp */
channel++;
channel->type = IIO_TIMESTAMP;
channel->channel = -1;
channel->scan_index = 1;
channel->scan_type.sign = 's';
channel->scan_type.realbits = 64;
channel->scan_type.storagebits = 64;
indio_dev->channels = state->channels;
indio_dev->num_channels = CROS_EC_LIGHT_PROX_MAX_CHANNELS;
state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
cros_ec_sensors_capture, NULL);
if (ret)
return ret;
return devm_iio_device_register(dev, indio_dev);
}
static const struct platform_device_id cros_ec_light_prox_ids[] = {
{
.name = "cros-ec-prox",
},
{
.name = "cros-ec-light",
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, cros_ec_light_prox_ids);
static struct platform_driver cros_ec_light_prox_platform_driver = {
.driver = {
.name = "cros-ec-light-prox",
},
.probe = cros_ec_light_prox_probe,
.id_table = cros_ec_light_prox_ids,
};
module_platform_driver(cros_ec_light_prox_platform_driver);
MODULE_DESCRIPTION("ChromeOS EC light/proximity sensors driver");
MODULE_LICENSE("GPL v2");
...@@ -240,6 +240,13 @@ static int prox_parse_report(struct platform_device *pdev, ...@@ -240,6 +240,13 @@ static int prox_parse_report(struct platform_device *pdev,
st->common_attributes.sensitivity.index, st->common_attributes.sensitivity.index,
st->common_attributes.sensitivity.report_id); st->common_attributes.sensitivity.report_id);
} }
if (st->common_attributes.sensitivity.index < 0)
sensor_hub_input_get_attribute_info(hsdev,
HID_FEATURE_REPORT, usage_id,
HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS |
HID_USAGE_SENSOR_HUMAN_PRESENCE,
&st->common_attributes.sensitivity);
return ret; return ret;
} }
......
...@@ -325,6 +325,7 @@ static int lmp91000_probe(struct i2c_client *client, ...@@ -325,6 +325,7 @@ static int lmp91000_probe(struct i2c_client *client,
indio_dev->channels = lmp91000_channels; indio_dev->channels = lmp91000_channels;
indio_dev->num_channels = ARRAY_SIZE(lmp91000_channels); indio_dev->num_channels = ARRAY_SIZE(lmp91000_channels);
indio_dev->name = LMP91000_DRV_NAME; indio_dev->name = LMP91000_DRV_NAME;
indio_dev->dev.parent = &client->dev;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
i2c_set_clientdata(client, indio_dev); i2c_set_clientdata(client, indio_dev);
......
...@@ -32,6 +32,17 @@ config LIDAR_LITE_V2 ...@@ -32,6 +32,17 @@ config LIDAR_LITE_V2
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 pulsedlight-lite-v2 module will be called pulsedlight-lite-v2
config SRF04
tristate "Devantech SRF04 ultrasonic ranger sensor"
depends on GPIOLIB
help
Say Y here to build a driver for Devantech SRF04 ultrasonic
ranger sensor. This driver can be used to measure the distance
of objects. It is using two GPIOs.
To compile this driver as a module, choose M here: the
module will be called srf04.
config SX9500 config SX9500
tristate "SX9500 Semtech proximity sensor" tristate "SX9500 Semtech proximity sensor"
select IIO_BUFFER select IIO_BUFFER
......
...@@ -5,5 +5,6 @@ ...@@ -5,5 +5,6 @@
# When adding new entries keep the list in alphabetical order # When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AS3935) += as3935.o obj-$(CONFIG_AS3935) += as3935.o
obj-$(CONFIG_LIDAR_LITE_V2) += pulsedlight-lidar-lite-v2.o obj-$(CONFIG_LIDAR_LITE_V2) += pulsedlight-lidar-lite-v2.o
obj-$(CONFIG_SRF04) += srf04.o
obj-$(CONFIG_SRF08) += srf08.o obj-$(CONFIG_SRF08) += srf08.o
obj-$(CONFIG_SX9500) += sx9500.o obj-$(CONFIG_SX9500) += sx9500.o
...@@ -278,6 +278,7 @@ static int lidar_probe(struct i2c_client *client, ...@@ -278,6 +278,7 @@ static int lidar_probe(struct i2c_client *client,
indio_dev->name = LIDAR_DRV_NAME; indio_dev->name = LIDAR_DRV_NAME;
indio_dev->channels = lidar_channels; indio_dev->channels = lidar_channels;
indio_dev->num_channels = ARRAY_SIZE(lidar_channels); indio_dev->num_channels = ARRAY_SIZE(lidar_channels);
indio_dev->dev.parent = &client->dev;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
i2c_set_clientdata(client, indio_dev); i2c_set_clientdata(client, indio_dev);
......
/*
* SRF04: ultrasonic sensor for distance measuring by using GPIOs
*
* Copyright (c) 2017 Andreas Klinger <ak@it-klinger.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For details about the device see:
* http://www.robot-electronics.co.uk/htm/srf04tech.htm
*
* the measurement cycle as timing diagram looks like:
*
* +---+
* GPIO | |
* trig: --+ +------------------------------------------------------
* ^ ^
* |<->|
* udelay(10)
*
* ultra +-+ +-+ +-+
* sonic | | | | | |
* burst: ---------+ +-+ +-+ +-----------------------------------------
* .
* ultra . +-+ +-+ +-+
* sonic . | | | | | |
* echo: ----------------------------------+ +-+ +-+ +----------------
* . .
* +------------------------+
* GPIO | |
* echo: -------------------+ +---------------
* ^ ^
* interrupt interrupt
* (ts_rising) (ts_falling)
* |<---------------------->|
* pulse time measured
* --> one round trip of ultra sonic waves
*/
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
struct srf04_data {
struct device *dev;
struct gpio_desc *gpiod_trig;
struct gpio_desc *gpiod_echo;
struct mutex lock;
int irqnr;
ktime_t ts_rising;
ktime_t ts_falling;
struct completion rising;
struct completion falling;
};
static irqreturn_t srf04_handle_irq(int irq, void *dev_id)
{
struct iio_dev *indio_dev = dev_id;
struct srf04_data *data = iio_priv(indio_dev);
ktime_t now = ktime_get();
if (gpiod_get_value(data->gpiod_echo)) {
data->ts_rising = now;
complete(&data->rising);
} else {
data->ts_falling = now;
complete(&data->falling);
}
return IRQ_HANDLED;
}
static int srf04_read(struct srf04_data *data)
{
int ret;
ktime_t ktime_dt;
u64 dt_ns;
u32 time_ns, distance_mm;
/*
* just one read-echo-cycle can take place at a time
* ==> lock against concurrent reading calls
*/
mutex_lock(&data->lock);
reinit_completion(&data->rising);
reinit_completion(&data->falling);
gpiod_set_value(data->gpiod_trig, 1);
udelay(10);
gpiod_set_value(data->gpiod_trig, 0);
/* it cannot take more than 20 ms */
ret = wait_for_completion_killable_timeout(&data->rising, HZ/50);
if (ret < 0) {
mutex_unlock(&data->lock);
return ret;
} else if (ret == 0) {
mutex_unlock(&data->lock);
return -ETIMEDOUT;
}
ret = wait_for_completion_killable_timeout(&data->falling, HZ/50);
if (ret < 0) {
mutex_unlock(&data->lock);
return ret;
} else if (ret == 0) {
mutex_unlock(&data->lock);
return -ETIMEDOUT;
}
ktime_dt = ktime_sub(data->ts_falling, data->ts_rising);
mutex_unlock(&data->lock);
dt_ns = ktime_to_ns(ktime_dt);
/*
* measuring more than 3 meters is beyond the capabilities of
* the sensor
* ==> filter out invalid results for not measuring echos of
* another us sensor
*
* formula:
* distance 3 m
* time = ---------- = --------- = 9404389 ns
* speed 319 m/s
*
* using a minimum speed at -20 °C of 319 m/s
*/
if (dt_ns > 9404389)
return -EIO;
time_ns = dt_ns;
/*
* the speed as function of the temperature is approximately:
*
* speed = 331,5 + 0,6 * Temp
* with Temp in °C
* and speed in m/s
*
* use 343 m/s as ultrasonic speed at 20 °C here in absence of the
* temperature
*
* therefore:
* time 343
* distance = ------ * -----
* 10^6 2
* with time in ns
* and distance in mm (one way)
*
* because we limit to 3 meters the multiplication with 343 just
* fits into 32 bit
*/
distance_mm = time_ns * 343 / 2000000;
return distance_mm;
}
static int srf04_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *channel, int *val,
int *val2, long info)
{
struct srf04_data *data = iio_priv(indio_dev);
int ret;
if (channel->type != IIO_DISTANCE)
return -EINVAL;
switch (info) {
case IIO_CHAN_INFO_RAW:
ret = srf04_read(data);
if (ret < 0)
return ret;
*val = ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
/*
* theoretical maximum resolution is 3 mm
* 1 LSB is 1 mm
*/
*val = 0;
*val2 = 1000;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
}
static const struct iio_info srf04_iio_info = {
.driver_module = THIS_MODULE,
.read_raw = srf04_read_raw,
};
static const struct iio_chan_spec srf04_chan_spec[] = {
{
.type = IIO_DISTANCE,
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
},
};
static int srf04_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct srf04_data *data;
struct iio_dev *indio_dev;
int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(struct srf04_data));
if (!indio_dev) {
dev_err(dev, "failed to allocate IIO device\n");
return -ENOMEM;
}
data = iio_priv(indio_dev);
data->dev = dev;
mutex_init(&data->lock);
init_completion(&data->rising);
init_completion(&data->falling);
data->gpiod_trig = devm_gpiod_get(dev, "trig", GPIOD_OUT_LOW);
if (IS_ERR(data->gpiod_trig)) {
dev_err(dev, "failed to get trig-gpios: err=%ld\n",
PTR_ERR(data->gpiod_trig));
return PTR_ERR(data->gpiod_trig);
}
data->gpiod_echo = devm_gpiod_get(dev, "echo", GPIOD_IN);
if (IS_ERR(data->gpiod_echo)) {
dev_err(dev, "failed to get echo-gpios: err=%ld\n",
PTR_ERR(data->gpiod_echo));
return PTR_ERR(data->gpiod_echo);
}
if (gpiod_cansleep(data->gpiod_echo)) {
dev_err(data->dev, "cansleep-GPIOs not supported\n");
return -ENODEV;
}
data->irqnr = gpiod_to_irq(data->gpiod_echo);
if (data->irqnr < 0) {
dev_err(data->dev, "gpiod_to_irq: %d\n", data->irqnr);
return data->irqnr;
}
ret = devm_request_irq(dev, data->irqnr, srf04_handle_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
pdev->name, indio_dev);
if (ret < 0) {
dev_err(data->dev, "request_irq: %d\n", ret);
return ret;
}
platform_set_drvdata(pdev, indio_dev);
indio_dev->name = "srf04";
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &srf04_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = srf04_chan_spec;
indio_dev->num_channels = ARRAY_SIZE(srf04_chan_spec);
return devm_iio_device_register(dev, indio_dev);
}
static const struct of_device_id of_srf04_match[] = {
{ .compatible = "devantech,srf04", },
{},
};
MODULE_DEVICE_TABLE(of, of_srf04_match);
static struct platform_driver srf04_driver = {
.probe = srf04_probe,
.driver = {
.name = "srf04-gpio",
.of_match_table = of_srf04_match,
},
};
module_platform_driver(srf04_driver);
MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
MODULE_DESCRIPTION("SRF04 ultrasonic sensor for distance measuring using GPIOs");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:srf04");
...@@ -19,6 +19,20 @@ config MAXIM_THERMOCOUPLE ...@@ -19,6 +19,20 @@ config MAXIM_THERMOCOUPLE
This driver can also be built as a module. If so, the module will This driver can also be built as a module. If so, the module will
be called maxim_thermocouple. be called maxim_thermocouple.
config HID_SENSOR_TEMP
tristate "HID Environmental temperature sensor"
depends on HID_SENSOR_HUB
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
help
Say yes here to build support for the HID SENSOR
temperature driver
To compile this driver as a module, choose M here: the module
will be called hid-sensor-temperature.
config MLX90614 config MLX90614
tristate "MLX90614 contact-less infrared sensor" tristate "MLX90614 contact-less infrared sensor"
depends on I2C depends on I2C
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# Makefile for industrial I/O temperature drivers # Makefile for industrial I/O temperature drivers
# #
obj-$(CONFIG_HID_SENSOR_TEMP) += hid-sensor-temperature.o
obj-$(CONFIG_MAXIM_THERMOCOUPLE) += maxim_thermocouple.o obj-$(CONFIG_MAXIM_THERMOCOUPLE) += maxim_thermocouple.o
obj-$(CONFIG_MLX90614) += mlx90614.o obj-$(CONFIG_MLX90614) += mlx90614.o
obj-$(CONFIG_TMP006) += tmp006.o obj-$(CONFIG_TMP006) += tmp006.o
......
/*
* HID Sensors Driver
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program.
*/
#include <linux/device.h>
#include <linux/hid-sensor-hub.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
struct temperature_state {
struct hid_sensor_common common_attributes;
struct hid_sensor_hub_attribute_info temperature_attr;
s32 temperature_data;
int scale_pre_decml;
int scale_post_decml;
int scale_precision;
int value_offset;
};
/* Channel definitions */
static const struct iio_chan_spec temperature_channels[] = {
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_HYSTERESIS),
},
IIO_CHAN_SOFT_TIMESTAMP(3),
};
/* Adjust channel real bits based on report descriptor */
static void temperature_adjust_channel_bit_mask(struct iio_chan_spec *channels,
int channel, int size)
{
channels[channel].scan_type.sign = 's';
/* Real storage bits will change based on the report desc. */
channels[channel].scan_type.realbits = size * 8;
/* Maximum size of a sample to capture is s32 */
channels[channel].scan_type.storagebits = sizeof(s32) * 8;
}
static int temperature_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct temperature_state *temp_st = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (chan->type != IIO_TEMP)
return -EINVAL;
hid_sensor_power_state(
&temp_st->common_attributes, true);
*val = sensor_hub_input_attr_get_raw_value(
temp_st->common_attributes.hsdev,
HID_USAGE_SENSOR_TEMPERATURE,
HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
temp_st->temperature_attr.report_id,
SENSOR_HUB_SYNC);
hid_sensor_power_state(
&temp_st->common_attributes,
false);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = temp_st->scale_pre_decml;
*val2 = temp_st->scale_post_decml;
return temp_st->scale_precision;
case IIO_CHAN_INFO_OFFSET:
*val = temp_st->value_offset;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SAMP_FREQ:
return hid_sensor_read_samp_freq_value(
&temp_st->common_attributes, val, val2);
case IIO_CHAN_INFO_HYSTERESIS:
return hid_sensor_read_raw_hyst_value(
&temp_st->common_attributes, val, val2);
default:
return -EINVAL;
}
}
static int temperature_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct temperature_state *temp_st = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
return hid_sensor_write_samp_freq_value(
&temp_st->common_attributes, val, val2);
case IIO_CHAN_INFO_HYSTERESIS:
return hid_sensor_write_raw_hyst_value(
&temp_st->common_attributes, val, val2);
default:
return -EINVAL;
}
}
static const struct iio_info temperature_info = {
.driver_module = THIS_MODULE,
.read_raw = &temperature_read_raw,
.write_raw = &temperature_write_raw,
};
/* Callback handler to send event after all samples are received and captured */
static int temperature_proc_event(struct hid_sensor_hub_device *hsdev,
unsigned int usage_id, void *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct temperature_state *temp_st = iio_priv(indio_dev);
if (atomic_read(&temp_st->common_attributes.data_ready))
iio_push_to_buffers_with_timestamp(indio_dev,
&temp_st->temperature_data,
iio_get_time_ns(indio_dev));
return 0;
}
/* Capture samples in local storage */
static int temperature_capture_sample(struct hid_sensor_hub_device *hsdev,
unsigned int usage_id, size_t raw_len,
char *raw_data, void *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct temperature_state *temp_st = iio_priv(indio_dev);
switch (usage_id) {
case HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE:
temp_st->temperature_data = *(s32 *)raw_data;
return 0;
default:
return -EINVAL;
}
}
/* Parse report which is specific to an usage id*/
static int temperature_parse_report(struct platform_device *pdev,
struct hid_sensor_hub_device *hsdev,
struct iio_chan_spec *channels,
unsigned int usage_id,
struct temperature_state *st)
{
int ret;
ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT,
usage_id,
HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
&st->temperature_attr);
if (ret < 0)
return ret;
temperature_adjust_channel_bit_mask(channels, 0,
st->temperature_attr.size);
st->scale_precision = hid_sensor_format_scale(
HID_USAGE_SENSOR_TEMPERATURE,
&st->temperature_attr,
&st->scale_pre_decml, &st->scale_post_decml);
/* Set Sensitivity field ids, when there is no individual modifier */
if (st->common_attributes.sensitivity.index < 0)
sensor_hub_input_get_attribute_info(hsdev,
HID_FEATURE_REPORT, usage_id,
HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS |
HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
&st->common_attributes.sensitivity);
return ret;
}
static struct hid_sensor_hub_callbacks temperature_callbacks = {
.send_event = &temperature_proc_event,
.capture_sample = &temperature_capture_sample,
};
/* Function to initialize the processing for usage id */
static int hid_temperature_probe(struct platform_device *pdev)
{
static const char *name = "temperature";
struct iio_dev *indio_dev;
struct temperature_state *temp_st;
struct iio_chan_spec *temp_chans;
struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*temp_st));
if (!indio_dev)
return -ENOMEM;
temp_st = iio_priv(indio_dev);
temp_st->common_attributes.hsdev = hsdev;
temp_st->common_attributes.pdev = pdev;
ret = hid_sensor_parse_common_attributes(hsdev,
HID_USAGE_SENSOR_TEMPERATURE,
&temp_st->common_attributes);
if (ret)
return ret;
temp_chans = devm_kmemdup(&indio_dev->dev, temperature_channels,
sizeof(temperature_channels), GFP_KERNEL);
if (!temp_chans)
return -ENOMEM;
ret = temperature_parse_report(pdev, hsdev, temp_chans,
HID_USAGE_SENSOR_TEMPERATURE, temp_st);
if (ret)
return ret;
indio_dev->channels = temp_chans;
indio_dev->num_channels = ARRAY_SIZE(temperature_channels);
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &temperature_info;
indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE;
ret = devm_iio_triggered_buffer_setup(&pdev->dev, indio_dev,
&iio_pollfunc_store_time, NULL, NULL);
if (ret)
return ret;
atomic_set(&temp_st->common_attributes.data_ready, 0);
ret = hid_sensor_setup_trigger(indio_dev, name,
&temp_st->common_attributes);
if (ret)
return ret;
platform_set_drvdata(pdev, indio_dev);
temperature_callbacks.pdev = pdev;
ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE,
&temperature_callbacks);
if (ret)
goto error_remove_trigger;
ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
if (ret)
goto error_remove_callback;
return ret;
error_remove_callback:
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE);
error_remove_trigger:
hid_sensor_remove_trigger(&temp_st->common_attributes);
return ret;
}
/* Function to deinitialize the processing for usage id */
static int hid_temperature_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct temperature_state *temp_st = iio_priv(indio_dev);
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE);
hid_sensor_remove_trigger(&temp_st->common_attributes);
return 0;
}
static const struct platform_device_id hid_temperature_ids[] = {
{
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-200033",
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, hid_temperature_ids);
static struct platform_driver hid_temperature_platform_driver = {
.id_table = hid_temperature_ids,
.driver = {
.name = "temperature-sensor",
.pm = &hid_sensor_pm_ops,
},
.probe = hid_temperature_probe,
.remove = hid_temperature_remove,
};
module_platform_driver(hid_temperature_platform_driver);
MODULE_DESCRIPTION("HID Environmental temperature sensor");
MODULE_AUTHOR("Song Hongyan <hongyan.song@intel.com>");
MODULE_LICENSE("GPL v2");
...@@ -231,6 +231,7 @@ static int maxim_thermocouple_probe(struct spi_device *spi) ...@@ -231,6 +231,7 @@ static int maxim_thermocouple_probe(struct spi_device *spi)
indio_dev->available_scan_masks = chip->scan_masks; indio_dev->available_scan_masks = chip->scan_masks;
indio_dev->num_channels = chip->num_channels; indio_dev->num_channels = chip->num_channels;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->dev.parent = &spi->dev;
data = iio_priv(indio_dev); data = iio_priv(indio_dev);
data->spi = spi; data->spi = spi;
......
This diff is collapsed.
...@@ -2,14 +2,7 @@ ...@@ -2,14 +2,7 @@
# Makefile for industrial I/O accelerometer drivers # Makefile for industrial I/O accelerometer drivers
# #
adis16201-y := adis16201_core.o
obj-$(CONFIG_ADIS16201) += adis16201.o obj-$(CONFIG_ADIS16201) += adis16201.o
adis16203-y := adis16203_core.o
obj-$(CONFIG_ADIS16203) += adis16203.o obj-$(CONFIG_ADIS16203) += adis16203.o
adis16209-y := adis16209_core.o
obj-$(CONFIG_ADIS16209) += adis16209.o obj-$(CONFIG_ADIS16209) += adis16209.o
adis16240-y := adis16240_core.o
obj-$(CONFIG_ADIS16240) += adis16240.o obj-$(CONFIG_ADIS16240) += adis16240.o
...@@ -20,7 +20,145 @@ ...@@ -20,7 +20,145 @@
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/iio/imu/adis.h> #include <linux/iio/imu/adis.h>
#include "adis16201.h" #define ADIS16201_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16201_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16201_SUPPLY_OUT 0x02
/* Output, x-axis accelerometer */
#define ADIS16201_XACCL_OUT 0x04
/* Output, y-axis accelerometer */
#define ADIS16201_YACCL_OUT 0x06
/* Output, auxiliary ADC input */
#define ADIS16201_AUX_ADC 0x08
/* Output, temperature */
#define ADIS16201_TEMP_OUT 0x0A
/* Output, x-axis inclination */
#define ADIS16201_XINCL_OUT 0x0C
/* Output, y-axis inclination */
#define ADIS16201_YINCL_OUT 0x0E
/* Calibration, x-axis acceleration offset */
#define ADIS16201_XACCL_OFFS 0x10
/* Calibration, y-axis acceleration offset */
#define ADIS16201_YACCL_OFFS 0x12
/* x-axis acceleration scale factor */
#define ADIS16201_XACCL_SCALE 0x14
/* y-axis acceleration scale factor */
#define ADIS16201_YACCL_SCALE 0x16
/* Calibration, x-axis inclination offset */
#define ADIS16201_XINCL_OFFS 0x18
/* Calibration, y-axis inclination offset */
#define ADIS16201_YINCL_OFFS 0x1A
/* x-axis inclination scale factor */
#define ADIS16201_XINCL_SCALE 0x1C
/* y-axis inclination scale factor */
#define ADIS16201_YINCL_SCALE 0x1E
/* Alarm 1 amplitude threshold */
#define ADIS16201_ALM_MAG1 0x20
/* Alarm 2 amplitude threshold */
#define ADIS16201_ALM_MAG2 0x22
/* Alarm 1, sample period */
#define ADIS16201_ALM_SMPL1 0x24
/* Alarm 2, sample period */
#define ADIS16201_ALM_SMPL2 0x26
/* Alarm control */
#define ADIS16201_ALM_CTRL 0x28
/* Auxiliary DAC data */
#define ADIS16201_AUX_DAC 0x30
/* General-purpose digital input/output control */
#define ADIS16201_GPIO_CTRL 0x32
/* Miscellaneous control */
#define ADIS16201_MSC_CTRL 0x34
/* Internal sample period (rate) control */
#define ADIS16201_SMPL_PRD 0x36
/* Operation, filter configuration */
#define ADIS16201_AVG_CNT 0x38
/* Operation, sleep mode control */
#define ADIS16201_SLP_CNT 0x3A
/* Diagnostics, system status register */
#define ADIS16201_DIAG_STAT 0x3C
/* Operation, system command register */
#define ADIS16201_GLOB_CMD 0x3E
/* MSC_CTRL */
/* Self-test enable */
#define ADIS16201_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16201_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16201_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO1, 0 = DIO0 */
#define ADIS16201_MSC_CTRL_DATA_RDY_DIO1 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16201_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16201_DIAG_STAT_ALARM1 BIT(8)
/* SPI communications failure */
#define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16201_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16201_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16201_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16201_GLOB_CMD_FACTORY_CAL BIT(1)
#define ADIS16201_ERROR_ACTIVE BIT(14)
enum adis16201_scan {
ADIS16201_SCAN_ACC_X,
ADIS16201_SCAN_ACC_Y,
ADIS16201_SCAN_INCLI_X,
ADIS16201_SCAN_INCLI_Y,
ADIS16201_SCAN_SUPPLY,
ADIS16201_SCAN_AUX_ADC,
ADIS16201_SCAN_TEMP,
};
static const u8 adis16201_addresses[] = { static const u8 adis16201_addresses[] = {
[ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS, [ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS,
......
#ifndef SPI_ADIS16201_H_
#define SPI_ADIS16201_H_
#define ADIS16201_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16201_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16201_SUPPLY_OUT 0x02
/* Output, x-axis accelerometer */
#define ADIS16201_XACCL_OUT 0x04
/* Output, y-axis accelerometer */
#define ADIS16201_YACCL_OUT 0x06
/* Output, auxiliary ADC input */
#define ADIS16201_AUX_ADC 0x08
/* Output, temperature */
#define ADIS16201_TEMP_OUT 0x0A
/* Output, x-axis inclination */
#define ADIS16201_XINCL_OUT 0x0C
/* Output, y-axis inclination */
#define ADIS16201_YINCL_OUT 0x0E
/* Calibration, x-axis acceleration offset */
#define ADIS16201_XACCL_OFFS 0x10
/* Calibration, y-axis acceleration offset */
#define ADIS16201_YACCL_OFFS 0x12
/* x-axis acceleration scale factor */
#define ADIS16201_XACCL_SCALE 0x14
/* y-axis acceleration scale factor */
#define ADIS16201_YACCL_SCALE 0x16
/* Calibration, x-axis inclination offset */
#define ADIS16201_XINCL_OFFS 0x18
/* Calibration, y-axis inclination offset */
#define ADIS16201_YINCL_OFFS 0x1A
/* x-axis inclination scale factor */
#define ADIS16201_XINCL_SCALE 0x1C
/* y-axis inclination scale factor */
#define ADIS16201_YINCL_SCALE 0x1E
/* Alarm 1 amplitude threshold */
#define ADIS16201_ALM_MAG1 0x20
/* Alarm 2 amplitude threshold */
#define ADIS16201_ALM_MAG2 0x22
/* Alarm 1, sample period */
#define ADIS16201_ALM_SMPL1 0x24
/* Alarm 2, sample period */
#define ADIS16201_ALM_SMPL2 0x26
/* Alarm control */
#define ADIS16201_ALM_CTRL 0x28
/* Auxiliary DAC data */
#define ADIS16201_AUX_DAC 0x30
/* General-purpose digital input/output control */
#define ADIS16201_GPIO_CTRL 0x32
/* Miscellaneous control */
#define ADIS16201_MSC_CTRL 0x34
/* Internal sample period (rate) control */
#define ADIS16201_SMPL_PRD 0x36
/* Operation, filter configuration */
#define ADIS16201_AVG_CNT 0x38
/* Operation, sleep mode control */
#define ADIS16201_SLP_CNT 0x3A
/* Diagnostics, system status register */
#define ADIS16201_DIAG_STAT 0x3C
/* Operation, system command register */
#define ADIS16201_GLOB_CMD 0x3E
/* MSC_CTRL */
/* Self-test enable */
#define ADIS16201_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16201_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16201_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO1, 0 = DIO0 */
#define ADIS16201_MSC_CTRL_DATA_RDY_DIO1 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16201_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16201_DIAG_STAT_ALARM1 BIT(8)
/* SPI communications failure */
#define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16201_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16201_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16201_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16201_GLOB_CMD_FACTORY_CAL BIT(1)
#define ADIS16201_ERROR_ACTIVE BIT(14)
enum adis16201_scan {
ADIS16201_SCAN_ACC_X,
ADIS16201_SCAN_ACC_Y,
ADIS16201_SCAN_INCLI_X,
ADIS16201_SCAN_INCLI_Y,
ADIS16201_SCAN_SUPPLY,
ADIS16201_SCAN_AUX_ADC,
ADIS16201_SCAN_TEMP,
};
#endif /* SPI_ADIS16201_H_ */
...@@ -7,20 +7,140 @@ ...@@ -7,20 +7,140 @@
*/ */
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/imu/adis.h>
#include <linux/iio/sysfs.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/spi/spi.h> #include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/iio/iio.h> #define ADIS16203_STARTUP_DELAY 220 /* ms */
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h> /* Flash memory write count */
#include <linux/iio/imu/adis.h> #define ADIS16203_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16203_SUPPLY_OUT 0x02
/* Output, auxiliary ADC input */
#define ADIS16203_AUX_ADC 0x08
/* Output, temperature */
#define ADIS16203_TEMP_OUT 0x0A
/* Output, x-axis inclination */
#define ADIS16203_XINCL_OUT 0x0C
/* Output, y-axis inclination */
#define ADIS16203_YINCL_OUT 0x0E
/* Incline null calibration */
#define ADIS16203_INCL_NULL 0x18
/* Alarm 1 amplitude threshold */
#define ADIS16203_ALM_MAG1 0x20
/* Alarm 2 amplitude threshold */
#define ADIS16203_ALM_MAG2 0x22
/* Alarm 1, sample period */
#define ADIS16203_ALM_SMPL1 0x24
/* Alarm 2, sample period */
#define ADIS16203_ALM_SMPL2 0x26
/* Alarm control */
#define ADIS16203_ALM_CTRL 0x28
#include "adis16203.h" /* Auxiliary DAC data */
#define ADIS16203_AUX_DAC 0x30
/* General-purpose digital input/output control */
#define ADIS16203_GPIO_CTRL 0x32
/* Miscellaneous control */
#define ADIS16203_MSC_CTRL 0x34
/* Internal sample period (rate) control */
#define ADIS16203_SMPL_PRD 0x36
/* Operation, filter configuration */
#define ADIS16203_AVG_CNT 0x38
/* Operation, sleep mode control */
#define ADIS16203_SLP_CNT 0x3A
/* Diagnostics, system status register */
#define ADIS16203_DIAG_STAT 0x3C
/* Operation, system command register */
#define ADIS16203_GLOB_CMD 0x3E
/* MSC_CTRL */
/* Self-test at power-on: 1 = disabled, 0 = enabled */
#define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST BIT(10)
/* Reverses rotation of both inclination outputs */
#define ADIS16203_MSC_CTRL_REVERSE_ROT_EN BIT(9)
/* Self-test enable */
#define ADIS16203_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16203_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16203_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO1, 0 = DIO0 */
#define ADIS16203_MSC_CTRL_DATA_RDY_DIO1 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16203_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16203_DIAG_STAT_ALARM1 BIT(8)
/* Self-test diagnostic error flag */
#define ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT 5
/* SPI communications failure */
#define ADIS16203_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16203_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16203_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16203_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16203_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16203_GLOB_CMD_CLEAR_STAT BIT(4)
#define ADIS16203_GLOB_CMD_FACTORY_CAL BIT(1)
#define ADIS16203_ERROR_ACTIVE BIT(14)
enum adis16203_scan {
ADIS16203_SCAN_INCLI_X,
ADIS16203_SCAN_INCLI_Y,
ADIS16203_SCAN_SUPPLY,
ADIS16203_SCAN_AUX_ADC,
ADIS16203_SCAN_TEMP,
};
#define DRIVER_NAME "adis16203" #define DRIVER_NAME "adis16203"
......
#ifndef SPI_ADIS16203_H_
#define SPI_ADIS16203_H_
#define ADIS16203_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16203_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16203_SUPPLY_OUT 0x02
/* Output, auxiliary ADC input */
#define ADIS16203_AUX_ADC 0x08
/* Output, temperature */
#define ADIS16203_TEMP_OUT 0x0A
/* Output, x-axis inclination */
#define ADIS16203_XINCL_OUT 0x0C
/* Output, y-axis inclination */
#define ADIS16203_YINCL_OUT 0x0E
/* Incline null calibration */
#define ADIS16203_INCL_NULL 0x18
/* Alarm 1 amplitude threshold */
#define ADIS16203_ALM_MAG1 0x20
/* Alarm 2 amplitude threshold */
#define ADIS16203_ALM_MAG2 0x22
/* Alarm 1, sample period */
#define ADIS16203_ALM_SMPL1 0x24
/* Alarm 2, sample period */
#define ADIS16203_ALM_SMPL2 0x26
/* Alarm control */
#define ADIS16203_ALM_CTRL 0x28
/* Auxiliary DAC data */
#define ADIS16203_AUX_DAC 0x30
/* General-purpose digital input/output control */
#define ADIS16203_GPIO_CTRL 0x32
/* Miscellaneous control */
#define ADIS16203_MSC_CTRL 0x34
/* Internal sample period (rate) control */
#define ADIS16203_SMPL_PRD 0x36
/* Operation, filter configuration */
#define ADIS16203_AVG_CNT 0x38
/* Operation, sleep mode control */
#define ADIS16203_SLP_CNT 0x3A
/* Diagnostics, system status register */
#define ADIS16203_DIAG_STAT 0x3C
/* Operation, system command register */
#define ADIS16203_GLOB_CMD 0x3E
/* MSC_CTRL */
/* Self-test at power-on: 1 = disabled, 0 = enabled */
#define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST BIT(10)
/* Reverses rotation of both inclination outputs */
#define ADIS16203_MSC_CTRL_REVERSE_ROT_EN BIT(9)
/* Self-test enable */
#define ADIS16203_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16203_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16203_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO1, 0 = DIO0 */
#define ADIS16203_MSC_CTRL_DATA_RDY_DIO1 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16203_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16203_DIAG_STAT_ALARM1 BIT(8)
/* Self-test diagnostic error flag */
#define ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT 5
/* SPI communications failure */
#define ADIS16203_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16203_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16203_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16203_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16203_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16203_GLOB_CMD_CLEAR_STAT BIT(4)
#define ADIS16203_GLOB_CMD_FACTORY_CAL BIT(1)
#define ADIS16203_ERROR_ACTIVE BIT(14)
enum adis16203_scan {
ADIS16203_SCAN_INCLI_X,
ADIS16203_SCAN_INCLI_Y,
ADIS16203_SCAN_SUPPLY,
ADIS16203_SCAN_AUX_ADC,
ADIS16203_SCAN_TEMP,
};
#endif /* SPI_ADIS16203_H_ */
...@@ -21,7 +21,145 @@ ...@@ -21,7 +21,145 @@
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/iio/imu/adis.h> #include <linux/iio/imu/adis.h>
#include "adis16209.h" #define ADIS16209_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16209_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16209_SUPPLY_OUT 0x02
/* Output, x-axis accelerometer */
#define ADIS16209_XACCL_OUT 0x04
/* Output, y-axis accelerometer */
#define ADIS16209_YACCL_OUT 0x06
/* Output, auxiliary ADC input */
#define ADIS16209_AUX_ADC 0x08
/* Output, temperature */
#define ADIS16209_TEMP_OUT 0x0A
/* Output, x-axis inclination */
#define ADIS16209_XINCL_OUT 0x0C
/* Output, y-axis inclination */
#define ADIS16209_YINCL_OUT 0x0E
/* Output, +/-180 vertical rotational position */
#define ADIS16209_ROT_OUT 0x10
/* Calibration, x-axis acceleration offset null */
#define ADIS16209_XACCL_NULL 0x12
/* Calibration, y-axis acceleration offset null */
#define ADIS16209_YACCL_NULL 0x14
/* Calibration, x-axis inclination offset null */
#define ADIS16209_XINCL_NULL 0x16
/* Calibration, y-axis inclination offset null */
#define ADIS16209_YINCL_NULL 0x18
/* Calibration, vertical rotation offset null */
#define ADIS16209_ROT_NULL 0x1A
/* Alarm 1 amplitude threshold */
#define ADIS16209_ALM_MAG1 0x20
/* Alarm 2 amplitude threshold */
#define ADIS16209_ALM_MAG2 0x22
/* Alarm 1, sample period */
#define ADIS16209_ALM_SMPL1 0x24
/* Alarm 2, sample period */
#define ADIS16209_ALM_SMPL2 0x26
/* Alarm control */
#define ADIS16209_ALM_CTRL 0x28
/* Auxiliary DAC data */
#define ADIS16209_AUX_DAC 0x30
/* General-purpose digital input/output control */
#define ADIS16209_GPIO_CTRL 0x32
/* Miscellaneous control */
#define ADIS16209_MSC_CTRL 0x34
/* Internal sample period (rate) control */
#define ADIS16209_SMPL_PRD 0x36
/* Operation, filter configuration */
#define ADIS16209_AVG_CNT 0x38
/* Operation, sleep mode control */
#define ADIS16209_SLP_CNT 0x3A
/* Diagnostics, system status register */
#define ADIS16209_DIAG_STAT 0x3C
/* Operation, system command register */
#define ADIS16209_GLOB_CMD 0x3E
/* MSC_CTRL */
/* Self-test at power-on: 1 = disabled, 0 = enabled */
#define ADIS16209_MSC_CTRL_PWRUP_SELF_TEST BIT(10)
/* Self-test enable */
#define ADIS16209_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16209_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16209_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
#define ADIS16209_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16209_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16209_DIAG_STAT_ALARM1 BIT(8)
/* Self-test diagnostic error flag: 1 = error condition, 0 = normal operation */
#define ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT 5
/* SPI communications failure */
#define ADIS16209_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16209_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16209_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16209_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16209_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16209_GLOB_CMD_CLEAR_STAT BIT(4)
#define ADIS16209_GLOB_CMD_FACTORY_CAL BIT(1)
#define ADIS16209_ERROR_ACTIVE BIT(14)
#define ADIS16209_SCAN_SUPPLY 0
#define ADIS16209_SCAN_ACC_X 1
#define ADIS16209_SCAN_ACC_Y 2
#define ADIS16209_SCAN_AUX_ADC 3
#define ADIS16209_SCAN_TEMP 4
#define ADIS16209_SCAN_INCLI_X 5
#define ADIS16209_SCAN_INCLI_Y 6
#define ADIS16209_SCAN_ROT 7
static const u8 adis16209_addresses[8][1] = { static const u8 adis16209_addresses[8][1] = {
[ADIS16209_SCAN_SUPPLY] = { }, [ADIS16209_SCAN_SUPPLY] = { },
......
#ifndef SPI_ADIS16209_H_
#define SPI_ADIS16209_H_
#define ADIS16209_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16209_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16209_SUPPLY_OUT 0x02
/* Output, x-axis accelerometer */
#define ADIS16209_XACCL_OUT 0x04
/* Output, y-axis accelerometer */
#define ADIS16209_YACCL_OUT 0x06
/* Output, auxiliary ADC input */
#define ADIS16209_AUX_ADC 0x08
/* Output, temperature */
#define ADIS16209_TEMP_OUT 0x0A
/* Output, x-axis inclination */
#define ADIS16209_XINCL_OUT 0x0C
/* Output, y-axis inclination */
#define ADIS16209_YINCL_OUT 0x0E
/* Output, +/-180 vertical rotational position */
#define ADIS16209_ROT_OUT 0x10
/* Calibration, x-axis acceleration offset null */
#define ADIS16209_XACCL_NULL 0x12
/* Calibration, y-axis acceleration offset null */
#define ADIS16209_YACCL_NULL 0x14
/* Calibration, x-axis inclination offset null */
#define ADIS16209_XINCL_NULL 0x16
/* Calibration, y-axis inclination offset null */
#define ADIS16209_YINCL_NULL 0x18
/* Calibration, vertical rotation offset null */
#define ADIS16209_ROT_NULL 0x1A
/* Alarm 1 amplitude threshold */
#define ADIS16209_ALM_MAG1 0x20
/* Alarm 2 amplitude threshold */
#define ADIS16209_ALM_MAG2 0x22
/* Alarm 1, sample period */
#define ADIS16209_ALM_SMPL1 0x24
/* Alarm 2, sample period */
#define ADIS16209_ALM_SMPL2 0x26
/* Alarm control */
#define ADIS16209_ALM_CTRL 0x28
/* Auxiliary DAC data */
#define ADIS16209_AUX_DAC 0x30
/* General-purpose digital input/output control */
#define ADIS16209_GPIO_CTRL 0x32
/* Miscellaneous control */
#define ADIS16209_MSC_CTRL 0x34
/* Internal sample period (rate) control */
#define ADIS16209_SMPL_PRD 0x36
/* Operation, filter configuration */
#define ADIS16209_AVG_CNT 0x38
/* Operation, sleep mode control */
#define ADIS16209_SLP_CNT 0x3A
/* Diagnostics, system status register */
#define ADIS16209_DIAG_STAT 0x3C
/* Operation, system command register */
#define ADIS16209_GLOB_CMD 0x3E
/* MSC_CTRL */
/* Self-test at power-on: 1 = disabled, 0 = enabled */
#define ADIS16209_MSC_CTRL_PWRUP_SELF_TEST BIT(10)
/* Self-test enable */
#define ADIS16209_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16209_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16209_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
#define ADIS16209_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16209_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16209_DIAG_STAT_ALARM1 BIT(8)
/* Self-test diagnostic error flag: 1 = error condition, 0 = normal operation */
#define ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT 5
/* SPI communications failure */
#define ADIS16209_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16209_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16209_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16209_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16209_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16209_GLOB_CMD_CLEAR_STAT BIT(4)
#define ADIS16209_GLOB_CMD_FACTORY_CAL BIT(1)
#define ADIS16209_ERROR_ACTIVE BIT(14)
#define ADIS16209_SCAN_SUPPLY 0
#define ADIS16209_SCAN_ACC_X 1
#define ADIS16209_SCAN_ACC_Y 2
#define ADIS16209_SCAN_AUX_ADC 3
#define ADIS16209_SCAN_TEMP 4
#define ADIS16209_SCAN_INCLI_X 5
#define ADIS16209_SCAN_INCLI_Y 6
#define ADIS16209_SCAN_ROT 7
#endif /* SPI_ADIS16209_H_ */
...@@ -24,7 +24,180 @@ ...@@ -24,7 +24,180 @@
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/iio/imu/adis.h> #include <linux/iio/imu/adis.h>
#include "adis16240.h" #define ADIS16240_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16240_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16240_SUPPLY_OUT 0x02
/* Output, x-axis accelerometer */
#define ADIS16240_XACCL_OUT 0x04
/* Output, y-axis accelerometer */
#define ADIS16240_YACCL_OUT 0x06
/* Output, z-axis accelerometer */
#define ADIS16240_ZACCL_OUT 0x08
/* Output, auxiliary ADC input */
#define ADIS16240_AUX_ADC 0x0A
/* Output, temperature */
#define ADIS16240_TEMP_OUT 0x0C
/* Output, x-axis acceleration peak */
#define ADIS16240_XPEAK_OUT 0x0E
/* Output, y-axis acceleration peak */
#define ADIS16240_YPEAK_OUT 0x10
/* Output, z-axis acceleration peak */
#define ADIS16240_ZPEAK_OUT 0x12
/* Output, sum-of-squares acceleration peak */
#define ADIS16240_XYZPEAK_OUT 0x14
/* Output, Capture Buffer 1, X and Y acceleration */
#define ADIS16240_CAPT_BUF1 0x16
/* Output, Capture Buffer 2, Z acceleration */
#define ADIS16240_CAPT_BUF2 0x18
/* Diagnostic, error flags */
#define ADIS16240_DIAG_STAT 0x1A
/* Diagnostic, event counter */
#define ADIS16240_EVNT_CNTR 0x1C
/* Diagnostic, check sum value from firmware test */
#define ADIS16240_CHK_SUM 0x1E
/* Calibration, x-axis acceleration offset adjustment */
#define ADIS16240_XACCL_OFF 0x20
/* Calibration, y-axis acceleration offset adjustment */
#define ADIS16240_YACCL_OFF 0x22
/* Calibration, z-axis acceleration offset adjustment */
#define ADIS16240_ZACCL_OFF 0x24
/* Clock, hour and minute */
#define ADIS16240_CLK_TIME 0x2E
/* Clock, month and day */
#define ADIS16240_CLK_DATE 0x30
/* Clock, year */
#define ADIS16240_CLK_YEAR 0x32
/* Wake-up setting, hour and minute */
#define ADIS16240_WAKE_TIME 0x34
/* Wake-up setting, month and day */
#define ADIS16240_WAKE_DATE 0x36
/* Alarm 1 amplitude threshold */
#define ADIS16240_ALM_MAG1 0x38
/* Alarm 2 amplitude threshold */
#define ADIS16240_ALM_MAG2 0x3A
/* Alarm control */
#define ADIS16240_ALM_CTRL 0x3C
/* Capture, external trigger control */
#define ADIS16240_XTRIG_CTRL 0x3E
/* Capture, address pointer */
#define ADIS16240_CAPT_PNTR 0x40
/* Capture, configuration and control */
#define ADIS16240_CAPT_CTRL 0x42
/* General-purpose digital input/output control */
#define ADIS16240_GPIO_CTRL 0x44
/* Miscellaneous control */
#define ADIS16240_MSC_CTRL 0x46
/* Internal sample period (rate) control */
#define ADIS16240_SMPL_PRD 0x48
/* System command */
#define ADIS16240_GLOB_CMD 0x4A
/* MSC_CTRL */
/* Enables sum-of-squares output (XYZPEAK_OUT) */
#define ADIS16240_MSC_CTRL_XYZPEAK_OUT_EN BIT(15)
/* Enables peak tracking output (XPEAK_OUT, YPEAK_OUT, and ZPEAK_OUT) */
#define ADIS16240_MSC_CTRL_X_Y_ZPEAK_OUT_EN BIT(14)
/* Self-test enable: 1 = apply electrostatic force, 0 = disabled */
#define ADIS16240_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16240_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16240_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
#define ADIS16240_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16240_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16240_DIAG_STAT_ALARM1 BIT(8)
/* Capture buffer full: 1 = capture buffer is full */
#define ADIS16240_DIAG_STAT_CPT_BUF_FUL BIT(7)
/* Flash test, checksum flag: 1 = mismatch, 0 = match */
#define ADIS16240_DIAG_STAT_CHKSUM BIT(6)
/* Power-on, self-test flag: 1 = failure, 0 = pass */
#define ADIS16240_DIAG_STAT_PWRON_FAIL_BIT 5
/* Power-on self-test: 1 = in-progress, 0 = complete */
#define ADIS16240_DIAG_STAT_PWRON_BUSY BIT(4)
/* SPI communications failure */
#define ADIS16240_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16240_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16240_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16240_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16240_GLOB_CMD_RESUME BIT(8)
#define ADIS16240_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16240_GLOB_CMD_STANDBY BIT(2)
#define ADIS16240_ERROR_ACTIVE BIT(14)
/* At the moment triggers are only used for ring buffer
* filling. This may change!
*/
#define ADIS16240_SCAN_ACC_X 0
#define ADIS16240_SCAN_ACC_Y 1
#define ADIS16240_SCAN_ACC_Z 2
#define ADIS16240_SCAN_SUPPLY 3
#define ADIS16240_SCAN_AUX_ADC 4
#define ADIS16240_SCAN_TEMP 5
static ssize_t adis16240_spi_read_signed(struct device *dev, static ssize_t adis16240_spi_read_signed(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
...@@ -65,7 +238,7 @@ static ssize_t adis16240_read_12bit_signed(struct device *dev, ...@@ -65,7 +238,7 @@ static ssize_t adis16240_read_12bit_signed(struct device *dev,
return ret; return ret;
} }
static IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, S_IRUGO, static IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, 0444,
adis16240_read_12bit_signed, NULL, adis16240_read_12bit_signed, NULL,
ADIS16240_XYZPEAK_OUT); ADIS16240_XYZPEAK_OUT);
......
#ifndef SPI_ADIS16240_H_
#define SPI_ADIS16240_H_
#define ADIS16240_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16240_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16240_SUPPLY_OUT 0x02
/* Output, x-axis accelerometer */
#define ADIS16240_XACCL_OUT 0x04
/* Output, y-axis accelerometer */
#define ADIS16240_YACCL_OUT 0x06
/* Output, z-axis accelerometer */
#define ADIS16240_ZACCL_OUT 0x08
/* Output, auxiliary ADC input */
#define ADIS16240_AUX_ADC 0x0A
/* Output, temperature */
#define ADIS16240_TEMP_OUT 0x0C
/* Output, x-axis acceleration peak */
#define ADIS16240_XPEAK_OUT 0x0E
/* Output, y-axis acceleration peak */
#define ADIS16240_YPEAK_OUT 0x10
/* Output, z-axis acceleration peak */
#define ADIS16240_ZPEAK_OUT 0x12
/* Output, sum-of-squares acceleration peak */
#define ADIS16240_XYZPEAK_OUT 0x14
/* Output, Capture Buffer 1, X and Y acceleration */
#define ADIS16240_CAPT_BUF1 0x16
/* Output, Capture Buffer 2, Z acceleration */
#define ADIS16240_CAPT_BUF2 0x18
/* Diagnostic, error flags */
#define ADIS16240_DIAG_STAT 0x1A
/* Diagnostic, event counter */
#define ADIS16240_EVNT_CNTR 0x1C
/* Diagnostic, check sum value from firmware test */
#define ADIS16240_CHK_SUM 0x1E
/* Calibration, x-axis acceleration offset adjustment */
#define ADIS16240_XACCL_OFF 0x20
/* Calibration, y-axis acceleration offset adjustment */
#define ADIS16240_YACCL_OFF 0x22
/* Calibration, z-axis acceleration offset adjustment */
#define ADIS16240_ZACCL_OFF 0x24
/* Clock, hour and minute */
#define ADIS16240_CLK_TIME 0x2E
/* Clock, month and day */
#define ADIS16240_CLK_DATE 0x30
/* Clock, year */
#define ADIS16240_CLK_YEAR 0x32
/* Wake-up setting, hour and minute */
#define ADIS16240_WAKE_TIME 0x34
/* Wake-up setting, month and day */
#define ADIS16240_WAKE_DATE 0x36
/* Alarm 1 amplitude threshold */
#define ADIS16240_ALM_MAG1 0x38
/* Alarm 2 amplitude threshold */
#define ADIS16240_ALM_MAG2 0x3A
/* Alarm control */
#define ADIS16240_ALM_CTRL 0x3C
/* Capture, external trigger control */
#define ADIS16240_XTRIG_CTRL 0x3E
/* Capture, address pointer */
#define ADIS16240_CAPT_PNTR 0x40
/* Capture, configuration and control */
#define ADIS16240_CAPT_CTRL 0x42
/* General-purpose digital input/output control */
#define ADIS16240_GPIO_CTRL 0x44
/* Miscellaneous control */
#define ADIS16240_MSC_CTRL 0x46
/* Internal sample period (rate) control */
#define ADIS16240_SMPL_PRD 0x48
/* System command */
#define ADIS16240_GLOB_CMD 0x4A
/* MSC_CTRL */
/* Enables sum-of-squares output (XYZPEAK_OUT) */
#define ADIS16240_MSC_CTRL_XYZPEAK_OUT_EN BIT(15)
/* Enables peak tracking output (XPEAK_OUT, YPEAK_OUT, and ZPEAK_OUT) */
#define ADIS16240_MSC_CTRL_X_Y_ZPEAK_OUT_EN BIT(14)
/* Self-test enable: 1 = apply electrostatic force, 0 = disabled */
#define ADIS16240_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16240_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16240_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
#define ADIS16240_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16240_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16240_DIAG_STAT_ALARM1 BIT(8)
/* Capture buffer full: 1 = capture buffer is full */
#define ADIS16240_DIAG_STAT_CPT_BUF_FUL BIT(7)
/* Flash test, checksum flag: 1 = mismatch, 0 = match */
#define ADIS16240_DIAG_STAT_CHKSUM BIT(6)
/* Power-on, self-test flag: 1 = failure, 0 = pass */
#define ADIS16240_DIAG_STAT_PWRON_FAIL_BIT 5
/* Power-on self-test: 1 = in-progress, 0 = complete */
#define ADIS16240_DIAG_STAT_PWRON_BUSY BIT(4)
/* SPI communications failure */
#define ADIS16240_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16240_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16240_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16240_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16240_GLOB_CMD_RESUME BIT(8)
#define ADIS16240_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16240_GLOB_CMD_STANDBY BIT(2)
#define ADIS16240_ERROR_ACTIVE BIT(14)
/* At the moment triggers are only used for ring buffer
* filling. This may change!
*/
#define ADIS16240_SCAN_ACC_X 0
#define ADIS16240_SCAN_ACC_Y 1
#define ADIS16240_SCAN_ACC_Z 2
#define ADIS16240_SCAN_SUPPLY 3
#define ADIS16240_SCAN_AUX_ADC 4
#define ADIS16240_SCAN_TEMP 5
#endif /* SPI_ADIS16240_H_ */
...@@ -80,26 +80,4 @@ config AD7280 ...@@ -80,26 +80,4 @@ config AD7280
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 ad7280a module will be called ad7280a
config LPC32XX_ADC
tristate "NXP LPC32XX ADC"
depends on ARCH_LPC32XX || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to build support for the integrated ADC inside the
LPC32XX SoC. Note that this feature uses the same hardware as the
touchscreen driver, so you should either select only one of the two
drivers (lpc32xx_adc or lpc32xx_ts) or, in the OpenFirmware case,
activate only one via device tree selection. Provides direct access
via sysfs.
config SPEAR_ADC
tristate "ST SPEAr ADC"
depends on PLAT_SPEAR || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to build support for the integrated ADC inside the
ST SPEAr SoC. Provides direct access via sysfs.
To compile this driver as a module, choose M here: the
module will be called spear_adc.
endmenu endmenu
...@@ -10,5 +10,3 @@ obj-$(CONFIG_AD7780) += ad7780.o ...@@ -10,5 +10,3 @@ obj-$(CONFIG_AD7780) += ad7780.o
obj-$(CONFIG_AD7816) += ad7816.o obj-$(CONFIG_AD7816) += ad7816.o
obj-$(CONFIG_AD7192) += ad7192.o obj-$(CONFIG_AD7192) += ad7192.o
obj-$(CONFIG_AD7280) += ad7280a.o obj-$(CONFIG_AD7280) += ad7280a.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
...@@ -342,9 +342,9 @@ ad7192_show_scale_available(struct device *dev, ...@@ -342,9 +342,9 @@ ad7192_show_scale_available(struct device *dev,
static IIO_DEVICE_ATTR_NAMED(in_v_m_v_scale_available, static IIO_DEVICE_ATTR_NAMED(in_v_m_v_scale_available,
in_voltage-voltage_scale_available, in_voltage-voltage_scale_available,
S_IRUGO, ad7192_show_scale_available, NULL, 0); 0444, ad7192_show_scale_available, NULL, 0);
static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO, static IIO_DEVICE_ATTR(in_voltage_scale_available, 0444,
ad7192_show_scale_available, NULL, 0); ad7192_show_scale_available, NULL, 0);
static ssize_t ad7192_show_ac_excitation(struct device *dev, static ssize_t ad7192_show_ac_excitation(struct device *dev,
...@@ -412,11 +412,11 @@ static ssize_t ad7192_set(struct device *dev, ...@@ -412,11 +412,11 @@ static ssize_t ad7192_set(struct device *dev,
return ret ? ret : len; return ret ? ret : len;
} }
static IIO_DEVICE_ATTR(bridge_switch_en, S_IRUGO | S_IWUSR, static IIO_DEVICE_ATTR(bridge_switch_en, 0644,
ad7192_show_bridge_switch, ad7192_set, ad7192_show_bridge_switch, ad7192_set,
AD7192_REG_GPOCON); AD7192_REG_GPOCON);
static IIO_DEVICE_ATTR(ac_excitation_en, S_IRUGO | S_IWUSR, static IIO_DEVICE_ATTR(ac_excitation_en, 0644,
ad7192_show_ac_excitation, ad7192_set, ad7192_show_ac_excitation, ad7192_set,
AD7192_REG_MODE); AD7192_REG_MODE);
......
This diff is collapsed.
...@@ -41,10 +41,10 @@ ...@@ -41,10 +41,10 @@
#define AD7152_REG_CFG2 26 #define AD7152_REG_CFG2 26
/* Status Register Bit Designations (AD7152_REG_STATUS) */ /* Status Register Bit Designations (AD7152_REG_STATUS) */
#define AD7152_STATUS_RDY1 (1 << 0) #define AD7152_STATUS_RDY1 BIT(0)
#define AD7152_STATUS_RDY2 (1 << 1) #define AD7152_STATUS_RDY2 BIT(1)
#define AD7152_STATUS_C1C2 (1 << 2) #define AD7152_STATUS_C1C2 BIT(2)
#define AD7152_STATUS_PWDN (1 << 7) #define AD7152_STATUS_PWDN BIT(7)
/* Setup Register Bit Designations (AD7152_REG_CHx_SETUP) */ /* Setup Register Bit Designations (AD7152_REG_CHx_SETUP) */
#define AD7152_SETUP_CAPDIFF (1 << 5) #define AD7152_SETUP_CAPDIFF (1 << 5)
......
...@@ -22,6 +22,98 @@ ...@@ -22,6 +22,98 @@
#include "ad9832.h" #include "ad9832.h"
/* Registers */
#define AD9832_FREQ0LL 0x0
#define AD9832_FREQ0HL 0x1
#define AD9832_FREQ0LM 0x2
#define AD9832_FREQ0HM 0x3
#define AD9832_FREQ1LL 0x4
#define AD9832_FREQ1HL 0x5
#define AD9832_FREQ1LM 0x6
#define AD9832_FREQ1HM 0x7
#define AD9832_PHASE0L 0x8
#define AD9832_PHASE0H 0x9
#define AD9832_PHASE1L 0xA
#define AD9832_PHASE1H 0xB
#define AD9832_PHASE2L 0xC
#define AD9832_PHASE2H 0xD
#define AD9832_PHASE3L 0xE
#define AD9832_PHASE3H 0xF
#define AD9832_PHASE_SYM 0x10
#define AD9832_FREQ_SYM 0x11
#define AD9832_PINCTRL_EN 0x12
#define AD9832_OUTPUT_EN 0x13
/* Command Control Bits */
#define AD9832_CMD_PHA8BITSW 0x1
#define AD9832_CMD_PHA16BITSW 0x0
#define AD9832_CMD_FRE8BITSW 0x3
#define AD9832_CMD_FRE16BITSW 0x2
#define AD9832_CMD_FPSELECT 0x6
#define AD9832_CMD_SYNCSELSRC 0x8
#define AD9832_CMD_SLEEPRESCLR 0xC
#define AD9832_FREQ BIT(11)
#define AD9832_PHASE(x) (((x) & 3) << 9)
#define AD9832_SYNC BIT(13)
#define AD9832_SELSRC BIT(12)
#define AD9832_SLEEP BIT(13)
#define AD9832_RESET BIT(12)
#define AD9832_CLR BIT(11)
#define CMD_SHIFT 12
#define ADD_SHIFT 8
#define AD9832_FREQ_BITS 32
#define AD9832_PHASE_BITS 12
#define RES_MASK(bits) ((1 << (bits)) - 1)
/**
* struct ad9832_state - driver instance specific data
* @spi: spi_device
* @avdd: supply regulator for the analog section
* @dvdd: supply regulator for the digital section
* @mclk: external master clock
* @ctrl_fp: cached frequency/phase control word
* @ctrl_ss: cached sync/selsrc control word
* @ctrl_src: cached sleep/reset/clr word
* @xfer: default spi transfer
* @msg: default spi message
* @freq_xfer: tuning word spi transfer
* @freq_msg: tuning word spi message
* @phase_xfer: tuning word spi transfer
* @phase_msg: tuning word spi message
* @data: spi transmit buffer
* @phase_data: tuning word spi transmit buffer
* @freq_data: tuning word spi transmit buffer
*/
struct ad9832_state {
struct spi_device *spi;
struct regulator *avdd;
struct regulator *dvdd;
unsigned long mclk;
unsigned short ctrl_fp;
unsigned short ctrl_ss;
unsigned short ctrl_src;
struct spi_transfer xfer;
struct spi_message msg;
struct spi_transfer freq_xfer[4];
struct spi_message freq_msg;
struct spi_transfer phase_xfer[2];
struct spi_message phase_msg;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
union {
__be16 freq_data[4]____cacheline_aligned;
__be16 phase_data[2];
__be16 data;
};
};
static unsigned long ad9832_calc_freqreg(unsigned long mclk, unsigned long fout) static unsigned long ad9832_calc_freqreg(unsigned long mclk, unsigned long fout)
{ {
unsigned long long freqreg = (u64)fout * unsigned long long freqreg = (u64)fout *
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -345,12 +345,12 @@ static ssize_t ad5933_store_frequency(struct device *dev, ...@@ -345,12 +345,12 @@ static ssize_t ad5933_store_frequency(struct device *dev,
return ret ? ret : len; return ret ? ret : len;
} }
static IIO_DEVICE_ATTR(out_voltage0_freq_start, S_IRUGO | S_IWUSR, static IIO_DEVICE_ATTR(out_voltage0_freq_start, 0644,
ad5933_show_frequency, ad5933_show_frequency,
ad5933_store_frequency, ad5933_store_frequency,
AD5933_REG_FREQ_START); AD5933_REG_FREQ_START);
static IIO_DEVICE_ATTR(out_voltage0_freq_increment, S_IRUGO | S_IWUSR, static IIO_DEVICE_ATTR(out_voltage0_freq_increment, 0644,
ad5933_show_frequency, ad5933_show_frequency,
ad5933_store_frequency, ad5933_store_frequency,
AD5933_REG_FREQ_INC); AD5933_REG_FREQ_INC);
...@@ -469,32 +469,32 @@ static ssize_t ad5933_store(struct device *dev, ...@@ -469,32 +469,32 @@ static ssize_t ad5933_store(struct device *dev,
return ret ? ret : len; return ret ? ret : len;
} }
static IIO_DEVICE_ATTR(out_voltage0_scale, S_IRUGO | S_IWUSR, static IIO_DEVICE_ATTR(out_voltage0_scale, 0644,
ad5933_show, ad5933_show,
ad5933_store, ad5933_store,
AD5933_OUT_RANGE); AD5933_OUT_RANGE);
static IIO_DEVICE_ATTR(out_voltage0_scale_available, S_IRUGO, static IIO_DEVICE_ATTR(out_voltage0_scale_available, 0444,
ad5933_show, ad5933_show,
NULL, NULL,
AD5933_OUT_RANGE_AVAIL); AD5933_OUT_RANGE_AVAIL);
static IIO_DEVICE_ATTR(in_voltage0_scale, S_IRUGO | S_IWUSR, static IIO_DEVICE_ATTR(in_voltage0_scale, 0644,
ad5933_show, ad5933_show,
ad5933_store, ad5933_store,
AD5933_IN_PGA_GAIN); AD5933_IN_PGA_GAIN);
static IIO_DEVICE_ATTR(in_voltage0_scale_available, S_IRUGO, static IIO_DEVICE_ATTR(in_voltage0_scale_available, 0444,
ad5933_show, ad5933_show,
NULL, NULL,
AD5933_IN_PGA_GAIN_AVAIL); AD5933_IN_PGA_GAIN_AVAIL);
static IIO_DEVICE_ATTR(out_voltage0_freq_points, S_IRUGO | S_IWUSR, static IIO_DEVICE_ATTR(out_voltage0_freq_points, 0644,
ad5933_show, ad5933_show,
ad5933_store, ad5933_store,
AD5933_FREQ_POINTS); AD5933_FREQ_POINTS);
static IIO_DEVICE_ATTR(out_voltage0_settling_cycles, S_IRUGO | S_IWUSR, static IIO_DEVICE_ATTR(out_voltage0_settling_cycles, 0644,
ad5933_show, ad5933_show,
ad5933_store, ad5933_store,
AD5933_OUT_SETTLING_CYCLES); AD5933_OUT_SETTLING_CYCLES);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -426,9 +426,7 @@ static int ade7854_set_irq(struct device *dev, bool enable) ...@@ -426,9 +426,7 @@ static int ade7854_set_irq(struct device *dev, bool enable)
else else
irqen &= ~BIT(17); irqen &= ~BIT(17);
ret = st->write_reg_32(dev, ADE7854_MASK0, irqen); return st->write_reg_32(dev, ADE7854_MASK0, irqen);
return ret;
} }
static int ade7854_initial_setup(struct iio_dev *indio_dev) static int ade7854_initial_setup(struct iio_dev *indio_dev)
......
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