mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
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. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAli8K40RHGppYzIzQGtl cm5lbC5vcmcACgkQVIU0mcT0FogLWBAAoclyQ3AwUecfujFcGx/ZJuba63M+qPIk SvmUCocnCjfgLI5WnB4J6rMldoD7CMAhrOpFeFuJlr/g6f4WMToJVT6PdHEtMqvB Rci/ODa9QNDPBpA1sLGCFu704yzBxQTmq53V1d9kZBJ/FxTqwOZamStjKAC2EskX yuslGGGSdveIYfmBfHIY1VlT2xwuf9xmyhi0STAIn86ViATH/Hhz2xWNBjaHxTrs gJ6sLGmwh9RYO1KlXSUmbXHd9mWoME2iIsEVGsPzILPkHuHsjvVtjPmQkHB6cT8v W1OvYJqHz7CbOmcqOVCUbtho/sdw9uhdGkc+Vm9ilxukfVFu9I3cnTTV6um7rj76 /bKf4qB0B/BlXgyfGdGY/gmotSI53sPeG7Vp0nd/5ZmYXKhP4NS+rRB1ipy71nGV YY/fmgrAobm3wrmWdMUOhBCH/hfN8aSR3S6exJarEejfIpOzu3GeVP8706krKvwO 1HOHBVyJ5gt+WI18kvYC78Mhs5HVeKCSuHf8eJ1bZHOUoVtIHtN4HnF5wCa0on/t Qu0am0SW596J95EUVMsodNYXUTP6JwcQeKt65VvXSq2jcnqylPT95SuroVqZ3NNH Lpq7kfjfV4p/n6G9EUE/7+RBXZL0BboI7v8GbIvodfXmFk099mkEbHnpMRffc6XQ o1TUYqzAQPI= =rlqq -----END PGP SIGNATURE----- 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.
This commit is contained in:
commit
34ff6c2fe3
1
.mailmap
1
.mailmap
@ -109,6 +109,7 @@ Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@osg.samsung.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> <matt.ranostay@intel.com>
|
||||
Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting>
|
||||
Mayuresh Janorkar <mayur@ti.com>
|
||||
Michael Buesch <m@bues.ch>
|
||||
Michel Dänzer <michel@tungstengraphics.com>
|
||||
|
@ -55,6 +55,7 @@ Description:
|
||||
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/in_proximity_sampling_frequency_available
|
||||
What: /sys/.../iio:deviceX/buffer/sampling_frequency_available
|
||||
What: /sys/bus/iio/devices/triggerX/sampling_frequency_available
|
||||
KernelVersion: 2.6.35
|
||||
@ -1593,7 +1594,7 @@ Description:
|
||||
can be processed to siemens per meter.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_countY_raw
|
||||
KernelVersion: 4.9
|
||||
KernelVersion: 4.10
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Raw counter device counts from channel Y. For quadrature
|
||||
@ -1601,10 +1602,24 @@ Description:
|
||||
the counts of a single quadrature signal phase from channel Y.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_indexY_raw
|
||||
KernelVersion: 4.9
|
||||
KernelVersion: 4.10
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Raw counter device index value from channel Y. This attribute
|
||||
provides an absolute positional reference (e.g. a pulse once per
|
||||
revolution) which may be used to home positional systems as
|
||||
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.
|
||||
|
@ -1,24 +1,16 @@
|
||||
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_noise_error_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_synchronous_mode_available
|
||||
KernelVersion: 4.9
|
||||
KernelVersion: 4.10
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Discrete set of available values for the respective counter
|
||||
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
|
||||
KernelVersion: 4.9
|
||||
KernelVersion: 4.10
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Count mode for channel Y. Four count modes are available:
|
||||
@ -52,7 +44,7 @@ Description:
|
||||
continuously throughout.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_countY_noise_error
|
||||
KernelVersion: 4.9
|
||||
KernelVersion: 4.10
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Read-only attribute that indicates whether excessive noise is
|
||||
@ -60,14 +52,14 @@ Description:
|
||||
irrelevant in non-quadrature clock mode.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_countY_preset
|
||||
KernelVersion: 4.9
|
||||
KernelVersion: 4.10
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
If the counter device supports preset registers, the preset
|
||||
count for channel Y is provided by this attribute.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_countY_quadrature_mode
|
||||
KernelVersion: 4.9
|
||||
KernelVersion: 4.10
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Configure channel Y counter for non-quadrature or quadrature
|
||||
@ -88,7 +80,7 @@ Description:
|
||||
decoded for UP/DN clock.
|
||||
|
||||
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
|
||||
Description:
|
||||
Whether to set channel Y counter with channel Y preset value
|
||||
@ -96,14 +88,14 @@ Description:
|
||||
Valid attribute values are boolean.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_indexY_index_polarity
|
||||
KernelVersion: 4.9
|
||||
KernelVersion: 4.10
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Active level of channel Y index input; irrelevant in
|
||||
non-synchronous load mode.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_indexY_synchronous_mode
|
||||
KernelVersion: 4.9
|
||||
KernelVersion: 4.10
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Configure channel Y counter for non-synchronous or synchronous
|
||||
|
38
Documentation/devicetree/bindings/iio/accel/adxl345.txt
Normal file
38
Documentation/devicetree/bindings/iio/accel/adxl345.txt
Normal file
@ -0,0 +1,38 @@
|
||||
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:
|
||||
- "amlogic,meson-gxm-saradc" for GXM
|
||||
along with the generic "amlogic,meson-saradc"
|
||||
- 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)
|
||||
- clock-names: mandatory clocks:
|
||||
- "clkin" for the reference clock (typically XTAL)
|
||||
@ -23,6 +24,7 @@ Example:
|
||||
compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <0x0 0x8680 0x0 0x34>;
|
||||
interrupts = <GIC_SPI 73 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&xtal>,
|
||||
<&clkc CLKID_SAR_ADC>,
|
||||
<&clkc CLKID_SANA>,
|
||||
|
30
Documentation/devicetree/bindings/iio/health/max30102.txt
Normal file
30
Documentation/devicetree/bindings/iio/health/max30102.txt
Normal file
@ -0,0 +1,30 @@
|
||||
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 @@
|
||||
Required properties:
|
||||
- compatible: must be one of:
|
||||
"st,lsm6ds3"
|
||||
"st,lsm6ds3h"
|
||||
"st,lsm6dsl"
|
||||
"st,lsm6dsm"
|
||||
- reg: i2c address of the sensor / spi cs line
|
||||
|
||||
|
@ -0,0 +1,28 @@
|
||||
* 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
|
||||
S: Maintained
|
||||
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)
|
||||
M: Johannes Berg <johannes@sipsolutions.net>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
|
@ -5,6 +5,37 @@
|
||||
|
||||
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
|
||||
tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver"
|
||||
depends on I2C
|
||||
|
@ -3,6 +3,9 @@
|
||||
#
|
||||
|
||||
# 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_BMA220) += bma220_spi.o
|
||||
obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
|
||||
|
18
drivers/iio/accel/adxl345.h
Normal file
18
drivers/iio/accel/adxl345.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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_ */
|
179
drivers/iio/accel/adxl345_core.c
Normal file
179
drivers/iio/accel/adxl345_core.c
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* 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, ®val,
|
||||
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, ®val);
|
||||
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");
|
73
drivers/iio/accel/adxl345_i2c.c
Normal file
73
drivers/iio/accel/adxl345_i2c.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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");
|
81
drivers/iio/accel/adxl345_spi.c
Normal file
81
drivers/iio/accel/adxl345_spi.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
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
|
||||
tristate "Linear Technology LTC2485 ADC driver"
|
||||
depends on I2C
|
||||
@ -494,6 +506,17 @@ config ROCKCHIP_SARADC
|
||||
To compile this driver as a module, choose M here: the
|
||||
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
|
||||
tristate "STMicroelectronics STM32 adc core"
|
||||
depends on ARCH_STM32 || COMPILE_TEST
|
||||
|
@ -30,6 +30,7 @@ obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
|
||||
obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
|
||||
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
|
||||
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
|
||||
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
|
||||
obj-$(CONFIG_LTC2485) += ltc2485.o
|
||||
obj-$(CONFIG_MAX1027) += max1027.o
|
||||
obj-$(CONFIG_MAX11100) += max11100.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_RCAR_GYRO_ADC) += rcar-gyroadc.o
|
||||
obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
|
||||
obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
|
||||
obj-$(CONFIG_STX104) += stx104.o
|
||||
obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
|
||||
obj-$(CONFIG_STM32_ADC) += stm32-adc.o
|
||||
|
@ -38,27 +38,30 @@
|
||||
/*
|
||||
* LPC32XX registers definitions
|
||||
*/
|
||||
#define LPC32XX_ADC_SELECT(x) ((x) + 0x04)
|
||||
#define LPC32XX_ADC_CTRL(x) ((x) + 0x08)
|
||||
#define LPC32XX_ADC_VALUE(x) ((x) + 0x48)
|
||||
#define LPC32XXAD_SELECT(x) ((x) + 0x04)
|
||||
#define LPC32XXAD_CTRL(x) ((x) + 0x08)
|
||||
#define LPC32XXAD_VALUE(x) ((x) + 0x48)
|
||||
|
||||
/* Bit definitions for LPC32XX_ADC_SELECT: */
|
||||
#define AD_REFm 0x00000200 /* constant, always write this value! */
|
||||
#define AD_REFp 0x00000080 /* constant, always write this value! */
|
||||
#define AD_IN 0x00000010 /* multiple of this is the */
|
||||
/* channel number: 0, 1, 2 */
|
||||
#define AD_INTERNAL 0x00000004 /* constant, always write this value! */
|
||||
/* Bit definitions for LPC32XXAD_SELECT: */
|
||||
/* constant, always write this value! */
|
||||
#define LPC32XXAD_REFm 0x00000200
|
||||
/* constant, always write this value! */
|
||||
#define LPC32XXAD_REFp 0x00000080
|
||||
/* multiple of this is the channel number: 0, 1, 2 */
|
||||
#define LPC32XXAD_IN 0x00000010
|
||||
/* constant, always write this value! */
|
||||
#define LPC32XXAD_INTERNAL 0x00000004
|
||||
|
||||
/* Bit definitions for LPC32XX_ADC_CTRL: */
|
||||
#define AD_STROBE 0x00000002
|
||||
#define AD_PDN_CTRL 0x00000004
|
||||
/* Bit definitions for LPC32XXAD_CTRL: */
|
||||
#define LPC32XXAD_STROBE 0x00000002
|
||||
#define LPC32XXAD_PDN_CTRL 0x00000004
|
||||
|
||||
/* Bit definitions for LPC32XX_ADC_VALUE: */
|
||||
#define ADC_VALUE_MASK 0x000003FF
|
||||
/* Bit definitions for LPC32XXAD_VALUE: */
|
||||
#define LPC32XXAD_VALUE_MASK 0x000003FF
|
||||
|
||||
#define MOD_NAME "lpc32xx-adc"
|
||||
#define LPC32XXAD_NAME "lpc32xx-adc"
|
||||
|
||||
struct lpc32xx_adc_info {
|
||||
struct lpc32xx_adc_state {
|
||||
void __iomem *adc_base;
|
||||
struct clk *clk;
|
||||
struct completion completion;
|
||||
@ -72,20 +75,21 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
|
||||
int *val2,
|
||||
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) {
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
clk_prepare_enable(info->clk);
|
||||
clk_prepare_enable(st->clk);
|
||||
/* Measurement setup */
|
||||
__raw_writel(AD_INTERNAL | (chan->address) | AD_REFp | AD_REFm,
|
||||
LPC32XX_ADC_SELECT(info->adc_base));
|
||||
__raw_writel(LPC32XXAD_INTERNAL | (chan->address) |
|
||||
LPC32XXAD_REFp | LPC32XXAD_REFm,
|
||||
LPC32XXAD_SELECT(st->adc_base));
|
||||
/* Trigger conversion */
|
||||
__raw_writel(AD_PDN_CTRL | AD_STROBE,
|
||||
LPC32XX_ADC_CTRL(info->adc_base));
|
||||
wait_for_completion(&info->completion); /* set by ISR */
|
||||
clk_disable_unprepare(info->clk);
|
||||
*val = info->value;
|
||||
__raw_writel(LPC32XXAD_PDN_CTRL | LPC32XXAD_STROBE,
|
||||
LPC32XXAD_CTRL(st->adc_base));
|
||||
wait_for_completion(&st->completion); /* set by ISR */
|
||||
clk_disable_unprepare(st->clk);
|
||||
*val = st->value;
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
|
||||
return IIO_VAL_INT;
|
||||
@ -104,7 +108,7 @@ static const struct iio_info lpc32xx_adc_iio_info = {
|
||||
.indexed = 1, \
|
||||
.channel = _index, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||
.address = AD_IN * _index, \
|
||||
.address = LPC32XXAD_IN * _index, \
|
||||
.scan_index = _index, \
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
struct lpc32xx_adc_info *info = dev_id;
|
||||
struct lpc32xx_adc_state *st = dev_id;
|
||||
|
||||
/* Read value and clear irq */
|
||||
info->value = __raw_readl(LPC32XX_ADC_VALUE(info->adc_base)) &
|
||||
ADC_VALUE_MASK;
|
||||
complete(&info->completion);
|
||||
st->value = __raw_readl(LPC32XXAD_VALUE(st->adc_base)) &
|
||||
LPC32XXAD_VALUE_MASK;
|
||||
complete(&st->completion);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int lpc32xx_adc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lpc32xx_adc_info *info = NULL;
|
||||
struct lpc32xx_adc_state *st = NULL;
|
||||
struct resource *res;
|
||||
int retval = -ENODEV;
|
||||
struct iio_dev *iodev = NULL;
|
||||
@ -140,23 +144,23 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
|
||||
iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
|
||||
if (!iodev)
|
||||
return -ENOMEM;
|
||||
|
||||
info = iio_priv(iodev);
|
||||
st = iio_priv(iodev);
|
||||
|
||||
info->adc_base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!info->adc_base) {
|
||||
st->adc_base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!st->adc_base) {
|
||||
dev_err(&pdev->dev, "failed mapping memory\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
info->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(info->clk)) {
|
||||
st->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(st->clk)) {
|
||||
dev_err(&pdev->dev, "failed getting clock\n");
|
||||
return PTR_ERR(info->clk);
|
||||
return PTR_ERR(st->clk);
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
@ -166,7 +170,7 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0,
|
||||
MOD_NAME, info);
|
||||
LPC32XXAD_NAME, st);
|
||||
if (retval < 0) {
|
||||
dev_err(&pdev->dev, "failed requesting interrupt\n");
|
||||
return retval;
|
||||
@ -174,9 +178,9 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
|
||||
|
||||
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->info = &lpc32xx_adc_iio_info;
|
||||
iodev->modes = INDIO_DIRECT_MODE;
|
||||
@ -203,7 +207,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_adc_match);
|
||||
static struct platform_driver lpc32xx_adc_driver = {
|
||||
.probe = lpc32xx_adc_probe,
|
||||
.driver = {
|
||||
.name = MOD_NAME,
|
||||
.name = LPC32XXAD_NAME,
|
||||
.of_match_table = of_match_ptr(lpc32xx_adc_match),
|
||||
},
|
||||
};
|
@ -18,7 +18,9 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
@ -163,6 +165,7 @@
|
||||
#define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8)
|
||||
|
||||
#define MESON_SAR_ADC_MAX_FIFO_SIZE 32
|
||||
#define MESON_SAR_ADC_TIMEOUT 100 /* ms */
|
||||
|
||||
#define MESON_SAR_ADC_CHAN(_chan) { \
|
||||
.type = IIO_VOLTAGE, \
|
||||
@ -229,6 +232,7 @@ struct meson_sar_adc_priv {
|
||||
struct clk_gate clk_gate;
|
||||
struct clk *adc_div_clk;
|
||||
struct clk_divider clk_div;
|
||||
struct completion done;
|
||||
};
|
||||
|
||||
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,
|
||||
int *val)
|
||||
{
|
||||
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 (ret)
|
||||
return ret;
|
||||
if(!wait_for_completion_timeout(&priv->done,
|
||||
msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT)))
|
||||
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, ®val);
|
||||
|
||||
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++;
|
||||
count = meson_sar_adc_get_fifo_count(indio_dev);
|
||||
if (count != 1) {
|
||||
dev_err(&indio_dev->dev,
|
||||
"ADC FIFO has %d element(s) instead of one\n", count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!count)
|
||||
return -ENOENT;
|
||||
regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val);
|
||||
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;
|
||||
}
|
||||
@ -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);
|
||||
|
||||
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,
|
||||
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)
|
||||
{
|
||||
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,
|
||||
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)
|
||||
{
|
||||
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
||||
int ret;
|
||||
u32 regval;
|
||||
|
||||
ret = meson_sar_adc_lock(indio_dev);
|
||||
if (ret)
|
||||
@ -667,6 +679,9 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
|
||||
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,
|
||||
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)
|
||||
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, ®val);
|
||||
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 = {
|
||||
.read_raw = meson_sar_adc_iio_info_read_raw,
|
||||
.driver_module = THIS_MODULE,
|
||||
@ -770,7 +804,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
const struct of_device_id *match;
|
||||
int ret;
|
||||
int irq, ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
|
||||
if (!indio_dev) {
|
||||
@ -779,6 +813,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
priv = iio_priv(indio_dev);
|
||||
init_completion(&priv->done);
|
||||
|
||||
match = of_match_device(meson_sar_adc_of_match, &pdev->dev);
|
||||
priv->data = match->data;
|
||||
@ -797,6 +832,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
|
||||
if (IS_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,
|
||||
&meson_sar_adc_regmap_config);
|
||||
if (IS_ERR(priv->regmap))
|
||||
|
@ -318,6 +318,7 @@ static int stx104_probe(struct device *dev, unsigned int id)
|
||||
}
|
||||
|
||||
indio_dev->name = dev_name(dev);
|
||||
indio_dev->dev.parent = dev;
|
||||
|
||||
priv = iio_priv(indio_dev);
|
||||
priv->base = base[id];
|
||||
|
@ -62,6 +62,9 @@ static struct {
|
||||
{HID_USAGE_SENSOR_TIME_TIMESTAMP, 0, 1000000000, 0},
|
||||
{HID_USAGE_SENSOR_TIME_TIMESTAMP, HID_USAGE_SENSOR_UNITS_MILLISECOND,
|
||||
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)
|
||||
|
@ -551,6 +551,7 @@ static int quad8_probe(struct device *dev, unsigned int id)
|
||||
indio_dev->num_channels = ARRAY_SIZE(quad8_channels);
|
||||
indio_dev->channels = quad8_channels;
|
||||
indio_dev->name = dev_name(dev);
|
||||
indio_dev->dev.parent = dev;
|
||||
|
||||
priv = iio_priv(indio_dev);
|
||||
priv->base = base[id];
|
||||
|
@ -119,6 +119,7 @@ static int cio_dac_probe(struct device *dev, unsigned int id)
|
||||
indio_dev->channels = cio_dac_channels;
|
||||
indio_dev->num_channels = CIO_DAC_NUM_CHAN;
|
||||
indio_dev->name = dev_name(dev);
|
||||
indio_dev->dev.parent = dev;
|
||||
|
||||
priv = iio_priv(indio_dev);
|
||||
priv->base = base[id];
|
||||
|
@ -46,6 +46,19 @@ config MAX30100
|
||||
To compile this driver as a module, choose M here: the
|
||||
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
|
||||
|
@ -7,3 +7,4 @@
|
||||
obj-$(CONFIG_AFE4403) += afe4403.o
|
||||
obj-$(CONFIG_AFE4404) += afe4404.o
|
||||
obj-$(CONFIG_MAX30100) += max30100.o
|
||||
obj-$(CONFIG_MAX30102) += max30102.o
|
||||
|
@ -449,6 +449,7 @@ static int max30100_probe(struct i2c_client *client,
|
||||
indio_dev->available_scan_masks = max30100_scan_masks;
|
||||
indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
|
||||
indio_dev->setup_ops = &max30100_buffer_setup_ops;
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
|
||||
data = iio_priv(indio_dev);
|
||||
data->indio_dev = indio_dev;
|
||||
|
486
drivers/iio/health/max30102.c
Normal file
486
drivers/iio/health/max30102.c
Normal file
@ -0,0 +1,486 @@
|
||||
/*
|
||||
* max30102.c - Support for MAX30102 heart rate and pulse oximeter sensor
|
||||
*
|
||||
* Copyright (C) 2017 Matt Ranostay <matt@ranostay.consulting>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* TODO: proximity power saving feature
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/kfifo_buf.h>
|
||||
|
||||
#define MAX30102_REGMAP_NAME "max30102_regmap"
|
||||
#define MAX30102_DRV_NAME "max30102"
|
||||
|
||||
#define MAX30102_REG_INT_STATUS 0x00
|
||||
#define MAX30102_REG_INT_STATUS_PWR_RDY BIT(0)
|
||||
#define MAX30102_REG_INT_STATUS_PROX_INT BIT(4)
|
||||
#define MAX30102_REG_INT_STATUS_ALC_OVF BIT(5)
|
||||
#define MAX30102_REG_INT_STATUS_PPG_RDY BIT(6)
|
||||
#define MAX30102_REG_INT_STATUS_FIFO_RDY BIT(7)
|
||||
|
||||
#define MAX30102_REG_INT_ENABLE 0x02
|
||||
#define MAX30102_REG_INT_ENABLE_PROX_INT_EN BIT(4)
|
||||
#define MAX30102_REG_INT_ENABLE_ALC_OVF_EN BIT(5)
|
||||
#define MAX30102_REG_INT_ENABLE_PPG_EN BIT(6)
|
||||
#define MAX30102_REG_INT_ENABLE_FIFO_EN BIT(7)
|
||||
#define MAX30102_REG_INT_ENABLE_MASK 0xf0
|
||||
#define MAX30102_REG_INT_ENABLE_MASK_SHIFT 4
|
||||
|
||||
#define MAX30102_REG_FIFO_WR_PTR 0x04
|
||||
#define MAX30102_REG_FIFO_OVR_CTR 0x05
|
||||
#define MAX30102_REG_FIFO_RD_PTR 0x06
|
||||
#define MAX30102_REG_FIFO_DATA 0x07
|
||||
#define MAX30102_REG_FIFO_DATA_ENTRY_LEN 6
|
||||
|
||||
#define MAX30102_REG_FIFO_CONFIG 0x08
|
||||
#define MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES BIT(1)
|
||||
#define MAX30102_REG_FIFO_CONFIG_AVG_SHIFT 5
|
||||
#define MAX30102_REG_FIFO_CONFIG_AFULL BIT(0)
|
||||
|
||||
#define MAX30102_REG_MODE_CONFIG 0x09
|
||||
#define MAX30102_REG_MODE_CONFIG_MODE_SPO2_EN BIT(0)
|
||||
#define MAX30102_REG_MODE_CONFIG_MODE_HR_EN BIT(1)
|
||||
#define MAX30102_REG_MODE_CONFIG_MODE_MASK 0x03
|
||||
#define MAX30102_REG_MODE_CONFIG_PWR BIT(7)
|
||||
|
||||
#define MAX30102_REG_SPO2_CONFIG 0x0a
|
||||
#define MAX30102_REG_SPO2_CONFIG_PULSE_411_US 0x03
|
||||
#define MAX30102_REG_SPO2_CONFIG_SR_400HZ 0x03
|
||||
#define MAX30102_REG_SPO2_CONFIG_SR_MASK 0x07
|
||||
#define MAX30102_REG_SPO2_CONFIG_SR_MASK_SHIFT 2
|
||||
#define MAX30102_REG_SPO2_CONFIG_ADC_4096_STEPS BIT(0)
|
||||
#define MAX30102_REG_SPO2_CONFIG_ADC_MASK_SHIFT 5
|
||||
|
||||
#define MAX30102_REG_RED_LED_CONFIG 0x0c
|
||||
#define MAX30102_REG_IR_LED_CONFIG 0x0d
|
||||
|
||||
#define MAX30102_REG_TEMP_CONFIG 0x21
|
||||
#define MAX30102_REG_TEMP_CONFIG_TEMP_EN BIT(0)
|
||||
|
||||
#define MAX30102_REG_TEMP_INTEGER 0x1f
|
||||
#define MAX30102_REG_TEMP_FRACTION 0x20
|
||||
|
||||
struct max30102_data {
|
||||
struct i2c_client *client;
|
||||
struct iio_dev *indio_dev;
|
||||
struct mutex lock;
|
||||
struct regmap *regmap;
|
||||
|
||||
u8 buffer[8];
|
||||
__be32 processed_buffer[2]; /* 2 x 18-bit (padded to 32-bits) */
|
||||
};
|
||||
|
||||
static const struct regmap_config max30102_regmap_config = {
|
||||
.name = MAX30102_REGMAP_NAME,
|
||||
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static const unsigned long max30102_scan_masks[] = {0x3, 0};
|
||||
|
||||
static const struct iio_chan_spec max30102_channels[] = {
|
||||
{
|
||||
.type = IIO_INTENSITY,
|
||||
.channel2 = IIO_MOD_LIGHT_RED,
|
||||
.modified = 1,
|
||||
|
||||
.scan_index = 0,
|
||||
.scan_type = {
|
||||
.sign = 'u',
|
||||
.shift = 8,
|
||||
.realbits = 18,
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_BE,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = IIO_INTENSITY,
|
||||
.channel2 = IIO_MOD_LIGHT_IR,
|
||||
.modified = 1,
|
||||
|
||||
.scan_index = 1,
|
||||
.scan_type = {
|
||||
.sign = 'u',
|
||||
.shift = 8,
|
||||
.realbits = 18,
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_BE,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
.info_mask_separate =
|
||||
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
||||
.scan_index = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static int max30102_set_powermode(struct max30102_data *data, bool state)
|
||||
{
|
||||
return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
|
||||
MAX30102_REG_MODE_CONFIG_PWR,
|
||||
state ? 0 : MAX30102_REG_MODE_CONFIG_PWR);
|
||||
}
|
||||
|
||||
static int max30102_buffer_postenable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct max30102_data *data = iio_priv(indio_dev);
|
||||
|
||||
return max30102_set_powermode(data, true);
|
||||
}
|
||||
|
||||
static int max30102_buffer_predisable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct max30102_data *data = iio_priv(indio_dev);
|
||||
|
||||
return max30102_set_powermode(data, false);
|
||||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops max30102_buffer_setup_ops = {
|
||||
.postenable = max30102_buffer_postenable,
|
||||
.predisable = max30102_buffer_predisable,
|
||||
};
|
||||
|
||||
static inline int max30102_fifo_count(struct max30102_data *data)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(data->regmap, MAX30102_REG_INT_STATUS, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* FIFO has one sample slot left */
|
||||
if (val & MAX30102_REG_INT_STATUS_FIFO_RDY)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max30102_read_measurement(struct max30102_data *data)
|
||||
{
|
||||
int ret;
|
||||
u8 *buffer = (u8 *) &data->buffer;
|
||||
|
||||
ret = i2c_smbus_read_i2c_block_data(data->client,
|
||||
MAX30102_REG_FIFO_DATA,
|
||||
MAX30102_REG_FIFO_DATA_ENTRY_LEN,
|
||||
buffer);
|
||||
|
||||
memcpy(&data->processed_buffer[0], &buffer[0], 3);
|
||||
memcpy(&data->processed_buffer[1], &buffer[3], 3);
|
||||
|
||||
return (ret == MAX30102_REG_FIFO_DATA_ENTRY_LEN) ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
static irqreturn_t max30102_interrupt_handler(int irq, void *private)
|
||||
{
|
||||
struct iio_dev *indio_dev = private;
|
||||
struct max30102_data *data = iio_priv(indio_dev);
|
||||
int ret, cnt = 0;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
|
||||
while (cnt || (cnt = max30102_fifo_count(data)) > 0) {
|
||||
ret = max30102_read_measurement(data);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
iio_push_to_buffers(data->indio_dev, data->processed_buffer);
|
||||
cnt--;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int max30102_get_current_idx(unsigned int val, int *reg)
|
||||
{
|
||||
/* each step is 0.200 mA */
|
||||
*reg = val / 200;
|
||||
|
||||
return *reg > 0xff ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static int max30102_led_init(struct max30102_data *data)
|
||||
{
|
||||
struct device *dev = &data->client->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
unsigned int val;
|
||||
int reg, ret;
|
||||
|
||||
ret = of_property_read_u32(np, "maxim,red-led-current-microamp", &val);
|
||||
if (ret) {
|
||||
dev_info(dev, "no red-led-current-microamp set\n");
|
||||
|
||||
/* Default to 7 mA RED LED */
|
||||
val = 7000;
|
||||
}
|
||||
|
||||
ret = max30102_get_current_idx(val, ®);
|
||||
if (ret) {
|
||||
dev_err(dev, "invalid RED LED current setting %d\n", val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(data->regmap, MAX30102_REG_RED_LED_CONFIG, reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = of_property_read_u32(np, "maxim,ir-led-current-microamp", &val);
|
||||
if (ret) {
|
||||
dev_info(dev, "no ir-led-current-microamp set\n");
|
||||
|
||||
/* Default to 7 mA IR LED */
|
||||
val = 7000;
|
||||
}
|
||||
|
||||
ret = max30102_get_current_idx(val, ®);
|
||||
if (ret) {
|
||||
dev_err(dev, "invalid IR LED current setting %d", val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return regmap_write(data->regmap, MAX30102_REG_IR_LED_CONFIG, reg);
|
||||
}
|
||||
|
||||
static int max30102_chip_init(struct max30102_data *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* setup LED current settings */
|
||||
ret = max30102_led_init(data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* enable 18-bit HR + SPO2 readings at 400Hz */
|
||||
ret = regmap_write(data->regmap, MAX30102_REG_SPO2_CONFIG,
|
||||
(MAX30102_REG_SPO2_CONFIG_ADC_4096_STEPS
|
||||
<< MAX30102_REG_SPO2_CONFIG_ADC_MASK_SHIFT) |
|
||||
(MAX30102_REG_SPO2_CONFIG_SR_400HZ
|
||||
<< MAX30102_REG_SPO2_CONFIG_SR_MASK_SHIFT) |
|
||||
MAX30102_REG_SPO2_CONFIG_PULSE_411_US);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* enable SPO2 mode */
|
||||
ret = regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
|
||||
MAX30102_REG_MODE_CONFIG_MODE_MASK,
|
||||
MAX30102_REG_MODE_CONFIG_MODE_HR_EN |
|
||||
MAX30102_REG_MODE_CONFIG_MODE_SPO2_EN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* average 4 samples + generate FIFO interrupt */
|
||||
ret = regmap_write(data->regmap, MAX30102_REG_FIFO_CONFIG,
|
||||
(MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES
|
||||
<< MAX30102_REG_FIFO_CONFIG_AVG_SHIFT) |
|
||||
MAX30102_REG_FIFO_CONFIG_AFULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* enable FIFO interrupt */
|
||||
return regmap_update_bits(data->regmap, MAX30102_REG_INT_ENABLE,
|
||||
MAX30102_REG_INT_ENABLE_MASK,
|
||||
MAX30102_REG_INT_ENABLE_FIFO_EN);
|
||||
}
|
||||
|
||||
static int max30102_read_temp(struct max30102_data *data, int *val)
|
||||
{
|
||||
int ret;
|
||||
unsigned int reg;
|
||||
|
||||
ret = regmap_read(data->regmap, MAX30102_REG_TEMP_INTEGER, ®);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = reg << 4;
|
||||
|
||||
ret = regmap_read(data->regmap, MAX30102_REG_TEMP_FRACTION, ®);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*val |= reg & 0xf;
|
||||
*val = sign_extend32(*val, 11);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max30102_get_temp(struct max30102_data *data, int *val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* start acquisition */
|
||||
ret = regmap_update_bits(data->regmap, MAX30102_REG_TEMP_CONFIG,
|
||||
MAX30102_REG_TEMP_CONFIG_TEMP_EN,
|
||||
MAX30102_REG_TEMP_CONFIG_TEMP_EN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
msleep(35);
|
||||
|
||||
return max30102_read_temp(data, val);
|
||||
}
|
||||
|
||||
static int max30102_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct max30102_data *data = iio_priv(indio_dev);
|
||||
int ret = -EINVAL;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
/*
|
||||
* Temperature reading can only be acquired while engine
|
||||
* is running
|
||||
*/
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
|
||||
if (!iio_buffer_enabled(indio_dev))
|
||||
ret = -EBUSY;
|
||||
else {
|
||||
ret = max30102_get_temp(data, val);
|
||||
if (!ret)
|
||||
ret = IIO_VAL_INT;
|
||||
}
|
||||
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
break;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*val = 1; /* 0.0625 */
|
||||
*val2 = 16;
|
||||
ret = IIO_VAL_FRACTIONAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct iio_info max30102_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = max30102_read_raw,
|
||||
};
|
||||
|
||||
static int max30102_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max30102_data *data;
|
||||
struct iio_buffer *buffer;
|
||||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
buffer = devm_iio_kfifo_allocate(&client->dev);
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
iio_device_attach_buffer(indio_dev, buffer);
|
||||
|
||||
indio_dev->name = MAX30102_DRV_NAME;
|
||||
indio_dev->channels = max30102_channels;
|
||||
indio_dev->info = &max30102_info;
|
||||
indio_dev->num_channels = ARRAY_SIZE(max30102_channels);
|
||||
indio_dev->available_scan_masks = max30102_scan_masks;
|
||||
indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
|
||||
indio_dev->setup_ops = &max30102_buffer_setup_ops;
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
|
||||
data = iio_priv(indio_dev);
|
||||
data->indio_dev = indio_dev;
|
||||
data->client = client;
|
||||
|
||||
mutex_init(&data->lock);
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
|
||||
data->regmap = devm_regmap_init_i2c(client, &max30102_regmap_config);
|
||||
if (IS_ERR(data->regmap)) {
|
||||
dev_err(&client->dev, "regmap initialization failed.\n");
|
||||
return PTR_ERR(data->regmap);
|
||||
}
|
||||
max30102_set_powermode(data, false);
|
||||
|
||||
ret = max30102_chip_init(data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (client->irq <= 0) {
|
||||
dev_err(&client->dev, "no valid irq defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, max30102_interrupt_handler,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"max30102_irq", indio_dev);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "request irq (%d) failed\n", client->irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return iio_device_register(indio_dev);
|
||||
}
|
||||
|
||||
static int max30102_remove(struct i2c_client *client)
|
||||
{
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
||||
struct max30102_data *data = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
max30102_set_powermode(data, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id max30102_id[] = {
|
||||
{ "max30102", 0 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max30102_id);
|
||||
|
||||
static const struct of_device_id max30102_dt_ids[] = {
|
||||
{ .compatible = "maxim,max30102" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, max30102_dt_ids);
|
||||
|
||||
static struct i2c_driver max30102_driver = {
|
||||
.driver = {
|
||||
.name = MAX30102_DRV_NAME,
|
||||
.of_match_table = of_match_ptr(max30102_dt_ids),
|
||||
},
|
||||
.probe = max30102_probe,
|
||||
.remove = max30102_remove,
|
||||
.id_table = max30102_id,
|
||||
};
|
||||
module_i2c_driver(max30102_driver);
|
||||
|
||||
MODULE_AUTHOR("Matt Ranostay <matt@ranostay.consulting>");
|
||||
MODULE_DESCRIPTION("MAX30102 heart rate and pulse oximeter sensor");
|
||||
MODULE_LICENSE("GPL");
|
@ -8,7 +8,7 @@ config IIO_ST_LSM6DSX
|
||||
select IIO_ST_LSM6DSX_SPI if (SPI_MASTER)
|
||||
help
|
||||
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
|
||||
will be called st_lsm6dsx.
|
||||
|
@ -15,11 +15,16 @@
|
||||
#include <linux/device.h>
|
||||
|
||||
#define ST_LSM6DS3_DEV_NAME "lsm6ds3"
|
||||
#define ST_LSM6DS3H_DEV_NAME "lsm6ds3h"
|
||||
#define ST_LSM6DSL_DEV_NAME "lsm6dsl"
|
||||
#define ST_LSM6DSM_DEV_NAME "lsm6dsm"
|
||||
|
||||
enum st_lsm6dsx_hw_id {
|
||||
ST_LSM6DS3_ID,
|
||||
ST_LSM6DS3H_ID,
|
||||
ST_LSM6DSL_ID,
|
||||
ST_LSM6DSM_ID,
|
||||
ST_LSM6DSX_MAX_ID,
|
||||
};
|
||||
|
||||
#define ST_LSM6DSX_CHAN_SIZE 2
|
||||
@ -50,7 +55,7 @@ struct st_lsm6dsx_reg {
|
||||
struct st_lsm6dsx_settings {
|
||||
u8 wai;
|
||||
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 {
|
||||
|
@ -1,9 +1,10 @@
|
||||
/*
|
||||
* STMicroelectronics st_lsm6dsx FIFO buffer library driver
|
||||
*
|
||||
* LSM6DS3/LSM6DSM: The FIFO buffer can be configured to store data
|
||||
* from gyroscope and accelerometer. Samples are queued without any tag
|
||||
* according to a specific pattern based on 'FIFO data sets' (6 bytes each):
|
||||
* LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM: The FIFO buffer can be configured
|
||||
* to store data from gyroscope and accelerometer. Samples are queued
|
||||
* without any tag according to a specific pattern based on 'FIFO data sets'
|
||||
* (6 bytes each):
|
||||
* - 1st data set is reserved for gyroscope data
|
||||
* - 2nd data set is reserved for accelerometer data
|
||||
* The FIFO pattern changes depending on the ODRs and decimation factors
|
||||
@ -206,7 +207,7 @@ out:
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* Read samples from the hw FIFO and push them to IIO buffers.
|
||||
|
@ -17,7 +17,7 @@
|
||||
* - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
|
||||
* - FIFO size: 8KB
|
||||
*
|
||||
* - LSM6DSM:
|
||||
* - LSM6DS3H/LSM6DSL/LSM6DSM:
|
||||
* - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416
|
||||
* - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
|
||||
* - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
|
||||
@ -74,12 +74,6 @@
|
||||
#define ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR 0x24
|
||||
#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_4G_GAIN IIO_G_TO_M_S_2(122)
|
||||
#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[] = {
|
||||
|
||||
static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
|
||||
{
|
||||
.wai = ST_LSM6DS3_WHOAMI,
|
||||
.max_fifo_size = ST_LSM6DS3_MAX_FIFO_SIZE,
|
||||
.id = ST_LSM6DS3_ID,
|
||||
.wai = 0x69,
|
||||
.max_fifo_size = 8192,
|
||||
.id = {
|
||||
[0] = ST_LSM6DS3_ID,
|
||||
},
|
||||
},
|
||||
{
|
||||
.wai = ST_LSM6DSM_WHOAMI,
|
||||
.max_fifo_size = ST_LSM6DSM_MAX_FIFO_SIZE,
|
||||
.id = ST_LSM6DSM_ID,
|
||||
.wai = 0x69,
|
||||
.max_fifo_size = 4096,
|
||||
.id = {
|
||||
[0] = ST_LSM6DS3H_ID,
|
||||
},
|
||||
},
|
||||
{
|
||||
.wai = 0x6a,
|
||||
.max_fifo_size = 4096,
|
||||
.id = {
|
||||
[0] = ST_LSM6DSL_ID,
|
||||
[1] = ST_LSM6DSM_ID,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -241,11 +247,15 @@ out:
|
||||
|
||||
static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id)
|
||||
{
|
||||
int err, i;
|
||||
int err, i, j;
|
||||
u8 data;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,14 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = {
|
||||
.compatible = "st,lsm6ds3",
|
||||
.data = (void *)ST_LSM6DS3_ID,
|
||||
},
|
||||
{
|
||||
.compatible = "st,lsm6ds3h",
|
||||
.data = (void *)ST_LSM6DS3H_ID,
|
||||
},
|
||||
{
|
||||
.compatible = "st,lsm6dsl",
|
||||
.data = (void *)ST_LSM6DSL_ID,
|
||||
},
|
||||
{
|
||||
.compatible = "st,lsm6dsm",
|
||||
.data = (void *)ST_LSM6DSM_ID,
|
||||
@ -80,6 +88,8 @@ MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match);
|
||||
|
||||
static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = {
|
||||
{ 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 },
|
||||
{},
|
||||
};
|
||||
|
@ -87,6 +87,14 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = {
|
||||
.compatible = "st,lsm6ds3",
|
||||
.data = (void *)ST_LSM6DS3_ID,
|
||||
},
|
||||
{
|
||||
.compatible = "st,lsm6ds3h",
|
||||
.data = (void *)ST_LSM6DS3H_ID,
|
||||
},
|
||||
{
|
||||
.compatible = "st,lsm6dsl",
|
||||
.data = (void *)ST_LSM6DSL_ID,
|
||||
},
|
||||
{
|
||||
.compatible = "st,lsm6dsm",
|
||||
.data = (void *)ST_LSM6DSM_ID,
|
||||
@ -97,6 +105,8 @@ MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match);
|
||||
|
||||
static const struct spi_device_id st_lsm6dsx_spi_id_table[] = {
|
||||
{ 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 },
|
||||
{},
|
||||
};
|
||||
|
@ -136,6 +136,16 @@ config CM36651
|
||||
To compile this driver as a module, choose M here:
|
||||
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
|
||||
tristate "Sharp GP2AP020A00F Proximity/ALS sensor"
|
||||
depends on I2C
|
||||
|
@ -15,6 +15,7 @@ obj-$(CONFIG_CM3232) += cm3232.o
|
||||
obj-$(CONFIG_CM3323) += cm3323.o
|
||||
obj-$(CONFIG_CM3605) += cm3605.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_HID_SENSOR_ALS) += hid-sensor-als.o
|
||||
obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o
|
||||
|
289
drivers/iio/light/cros_ec_light_prox.c
Normal file
289
drivers/iio/light/cros_ec_light_prox.c
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* 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,
|
||||
st->common_attributes.sensitivity.index,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -325,6 +325,7 @@ static int lmp91000_probe(struct i2c_client *client,
|
||||
indio_dev->channels = lmp91000_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(lmp91000_channels);
|
||||
indio_dev->name = LMP91000_DRV_NAME;
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
|
||||
|
@ -32,6 +32,17 @@ config LIDAR_LITE_V2
|
||||
To compile this driver as a module, choose M here: the
|
||||
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
|
||||
tristate "SX9500 Semtech proximity sensor"
|
||||
select IIO_BUFFER
|
||||
|
@ -5,5 +5,6 @@
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
obj-$(CONFIG_AS3935) += as3935.o
|
||||
obj-$(CONFIG_LIDAR_LITE_V2) += pulsedlight-lidar-lite-v2.o
|
||||
obj-$(CONFIG_SRF04) += srf04.o
|
||||
obj-$(CONFIG_SRF08) += srf08.o
|
||||
obj-$(CONFIG_SX9500) += sx9500.o
|
||||
|
@ -278,6 +278,7 @@ static int lidar_probe(struct i2c_client *client,
|
||||
indio_dev->name = LIDAR_DRV_NAME;
|
||||
indio_dev->channels = lidar_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(lidar_channels);
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
|
304
drivers/iio/proximity/srf04.c
Normal file
304
drivers/iio/proximity/srf04.c
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
* 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
|
||||
This driver can also be built as a module. If so, the module will
|
||||
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
|
||||
tristate "MLX90614 contact-less infrared sensor"
|
||||
depends on I2C
|
||||
|
@ -2,6 +2,7 @@
|
||||
# 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_MLX90614) += mlx90614.o
|
||||
obj-$(CONFIG_TMP006) += tmp006.o
|
||||
|
311
drivers/iio/temperature/hid-sensor-temperature.c
Normal file
311
drivers/iio/temperature/hid-sensor-temperature.c
Normal file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
* 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)
|
||||
indio_dev->available_scan_masks = chip->scan_masks;
|
||||
indio_dev->num_channels = chip->num_channels;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->dev.parent = &spi->dev;
|
||||
|
||||
data = iio_priv(indio_dev);
|
||||
data->spi = spi;
|
||||
|
@ -11,9 +11,10 @@
|
||||
*
|
||||
* (7-bit I2C slave address (0x40 - 0x47), changeable via ADR pins)
|
||||
*
|
||||
* Note: This driver assumes that the sensor has been calibrated beforehand
|
||||
*
|
||||
* TODO: ALERT irq, limit threshold events
|
||||
* Note:
|
||||
* 1. This driver assumes that the sensor has been calibrated beforehand
|
||||
* 2. Limit threshold events are enabled at the start
|
||||
* 3. Operating mode: INT
|
||||
*
|
||||
*/
|
||||
|
||||
@ -24,25 +25,38 @@
|
||||
#include <linux/pm.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/events.h>
|
||||
|
||||
#define TMP007_TDIE 0x01
|
||||
#define TMP007_CONFIG 0x02
|
||||
#define TMP007_TOBJECT 0x03
|
||||
#define TMP007_STATUS 0x04
|
||||
#define TMP007_STATUS_MASK 0x05
|
||||
#define TMP007_TOBJ_HIGH_LIMIT 0x06
|
||||
#define TMP007_TOBJ_LOW_LIMIT 0x07
|
||||
#define TMP007_TDIE_HIGH_LIMIT 0x08
|
||||
#define TMP007_TDIE_LOW_LIMIT 0x09
|
||||
#define TMP007_MANUFACTURER_ID 0x1e
|
||||
#define TMP007_DEVICE_ID 0x1f
|
||||
|
||||
#define TMP007_CONFIG_CONV_EN BIT(12)
|
||||
#define TMP007_CONFIG_COMP_EN BIT(5)
|
||||
#define TMP007_CONFIG_TC_EN BIT(6)
|
||||
#define TMP007_CONFIG_CR_MASK GENMASK(11, 9)
|
||||
#define TMP007_CONFIG_ALERT_EN BIT(8)
|
||||
#define TMP007_CONFIG_CR_SHIFT 9
|
||||
|
||||
/* Status register flags */
|
||||
#define TMP007_STATUS_ALERT BIT(15)
|
||||
#define TMP007_STATUS_CONV_READY BIT(14)
|
||||
#define TMP007_STATUS_OHF BIT(13)
|
||||
#define TMP007_STATUS_OLF BIT(12)
|
||||
#define TMP007_STATUS_LHF BIT(11)
|
||||
#define TMP007_STATUS_LLF BIT(10)
|
||||
#define TMP007_STATUS_DATA_VALID BIT(9)
|
||||
|
||||
#define TMP007_MANUFACTURER_MAGIC 0x5449
|
||||
@ -52,7 +66,9 @@
|
||||
|
||||
struct tmp007_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex lock;
|
||||
u16 config;
|
||||
u16 status_mask;
|
||||
};
|
||||
|
||||
static const int tmp007_avgs[5][2] = { {4, 0}, {2, 0}, {1, 0},
|
||||
@ -156,6 +172,188 @@ static int tmp007_write_raw(struct iio_dev *indio_dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static irqreturn_t tmp007_interrupt_handler(int irq, void *private)
|
||||
{
|
||||
struct iio_dev *indio_dev = private;
|
||||
struct tmp007_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS);
|
||||
if ((ret < 0) || !(ret & (TMP007_STATUS_OHF | TMP007_STATUS_OLF |
|
||||
TMP007_STATUS_LHF | TMP007_STATUS_LLF)))
|
||||
return IRQ_NONE;
|
||||
|
||||
if (ret & TMP007_STATUS_OHF)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
|
||||
IIO_MOD_TEMP_OBJECT,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_RISING),
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
if (ret & TMP007_STATUS_OLF)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
|
||||
IIO_MOD_TEMP_OBJECT,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_FALLING),
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
if (ret & TMP007_STATUS_LHF)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
|
||||
IIO_MOD_TEMP_AMBIENT,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_RISING),
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
if (ret & TMP007_STATUS_LLF)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
|
||||
IIO_MOD_TEMP_AMBIENT,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_FALLING),
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int tmp007_write_event_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, enum iio_event_type type,
|
||||
enum iio_event_direction dir, int state)
|
||||
{
|
||||
struct tmp007_data *data = iio_priv(indio_dev);
|
||||
unsigned int status_mask;
|
||||
int ret;
|
||||
|
||||
switch (chan->channel2) {
|
||||
case IIO_MOD_TEMP_AMBIENT:
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
status_mask = TMP007_STATUS_LHF;
|
||||
else
|
||||
status_mask = TMP007_STATUS_LLF;
|
||||
break;
|
||||
case IIO_MOD_TEMP_OBJECT:
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
status_mask = TMP007_STATUS_OHF;
|
||||
else
|
||||
status_mask = TMP007_STATUS_OLF;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
|
||||
mutex_unlock(&data->lock);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (state)
|
||||
ret |= status_mask;
|
||||
else
|
||||
ret &= ~status_mask;
|
||||
|
||||
return i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK,
|
||||
data->status_mask = ret);
|
||||
}
|
||||
|
||||
static int tmp007_read_event_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, enum iio_event_type type,
|
||||
enum iio_event_direction dir)
|
||||
{
|
||||
struct tmp007_data *data = iio_priv(indio_dev);
|
||||
unsigned int mask;
|
||||
|
||||
switch (chan->channel2) {
|
||||
case IIO_MOD_TEMP_AMBIENT:
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
mask = TMP007_STATUS_LHF;
|
||||
else
|
||||
mask = TMP007_STATUS_LLF;
|
||||
break;
|
||||
case IIO_MOD_TEMP_OBJECT:
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
mask = TMP007_STATUS_OHF;
|
||||
else
|
||||
mask = TMP007_STATUS_OLF;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return !!(data->status_mask & mask);
|
||||
}
|
||||
|
||||
static int tmp007_read_thresh(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, enum iio_event_type type,
|
||||
enum iio_event_direction dir, enum iio_event_info info,
|
||||
int *val, int *val2)
|
||||
{
|
||||
struct tmp007_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
u8 reg;
|
||||
|
||||
switch (chan->channel2) {
|
||||
case IIO_MOD_TEMP_AMBIENT: /* LSB: 0.5 degree Celsius */
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
reg = TMP007_TDIE_HIGH_LIMIT;
|
||||
else
|
||||
reg = TMP007_TDIE_LOW_LIMIT;
|
||||
break;
|
||||
case IIO_MOD_TEMP_OBJECT:
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
reg = TMP007_TOBJ_HIGH_LIMIT;
|
||||
else
|
||||
reg = TMP007_TOBJ_LOW_LIMIT;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = i2c_smbus_read_word_swapped(data->client, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */
|
||||
*val = sign_extend32(ret, 15) >> 7;
|
||||
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
|
||||
static int tmp007_write_thresh(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, enum iio_event_type type,
|
||||
enum iio_event_direction dir, enum iio_event_info info,
|
||||
int val, int val2)
|
||||
{
|
||||
struct tmp007_data *data = iio_priv(indio_dev);
|
||||
u8 reg;
|
||||
|
||||
switch (chan->channel2) {
|
||||
case IIO_MOD_TEMP_AMBIENT:
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
reg = TMP007_TDIE_HIGH_LIMIT;
|
||||
else
|
||||
reg = TMP007_TDIE_LOW_LIMIT;
|
||||
break;
|
||||
case IIO_MOD_TEMP_OBJECT:
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
reg = TMP007_TOBJ_HIGH_LIMIT;
|
||||
else
|
||||
reg = TMP007_TOBJ_LOW_LIMIT;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Full scale threshold value is +/- 256 degree Celsius */
|
||||
if (val < -256 || val > 255)
|
||||
return -EINVAL;
|
||||
|
||||
/* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */
|
||||
return i2c_smbus_write_word_swapped(data->client, reg, (val << 7));
|
||||
}
|
||||
|
||||
static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25");
|
||||
|
||||
static struct attribute *tmp007_attributes[] = {
|
||||
@ -167,6 +365,36 @@ static const struct attribute_group tmp007_attribute_group = {
|
||||
.attrs = tmp007_attributes,
|
||||
};
|
||||
|
||||
static const struct iio_event_spec tmp007_obj_event[] = {
|
||||
{
|
||||
.type = IIO_EV_TYPE_THRESH,
|
||||
.dir = IIO_EV_DIR_RISING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
},
|
||||
{
|
||||
.type = IIO_EV_TYPE_THRESH,
|
||||
.dir = IIO_EV_DIR_FALLING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct iio_event_spec tmp007_die_event[] = {
|
||||
{
|
||||
.type = IIO_EV_TYPE_THRESH,
|
||||
.dir = IIO_EV_DIR_RISING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
},
|
||||
{
|
||||
.type = IIO_EV_TYPE_THRESH,
|
||||
.dir = IIO_EV_DIR_FALLING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec tmp007_channels[] = {
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
@ -175,6 +403,8 @@ static const struct iio_chan_spec tmp007_channels[] = {
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
|
||||
.event_spec = tmp007_die_event,
|
||||
.num_event_specs = ARRAY_SIZE(tmp007_die_event),
|
||||
},
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
@ -183,12 +413,18 @@ static const struct iio_chan_spec tmp007_channels[] = {
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
|
||||
.event_spec = tmp007_obj_event,
|
||||
.num_event_specs = ARRAY_SIZE(tmp007_obj_event),
|
||||
}
|
||||
};
|
||||
|
||||
static const struct iio_info tmp007_info = {
|
||||
.read_raw = tmp007_read_raw,
|
||||
.write_raw = tmp007_write_raw,
|
||||
.read_event_config = tmp007_read_event_config,
|
||||
.write_event_config = tmp007_write_event_config,
|
||||
.read_event_value = tmp007_read_thresh,
|
||||
.write_event_value = tmp007_write_thresh,
|
||||
.attrs = &tmp007_attribute_group,
|
||||
.driver_module = THIS_MODULE,
|
||||
};
|
||||
@ -214,7 +450,6 @@ static int tmp007_probe(struct i2c_client *client,
|
||||
struct tmp007_data *data;
|
||||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
u16 status;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return -EOPNOTSUPP;
|
||||
@ -231,6 +466,7 @@ static int tmp007_probe(struct i2c_client *client,
|
||||
data = iio_priv(indio_dev);
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
data->client = client;
|
||||
mutex_init(&data->lock);
|
||||
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
indio_dev->name = "tmp007";
|
||||
@ -243,7 +479,7 @@ static int tmp007_probe(struct i2c_client *client,
|
||||
/*
|
||||
* Set Configuration register:
|
||||
* 1. Conversion ON
|
||||
* 2. Comparator mode
|
||||
* 2. ALERT enable
|
||||
* 3. Transient correction enable
|
||||
*/
|
||||
|
||||
@ -252,7 +488,7 @@ static int tmp007_probe(struct i2c_client *client,
|
||||
return ret;
|
||||
|
||||
data->config = ret;
|
||||
data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_COMP_EN | TMP007_CONFIG_TC_EN);
|
||||
data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_ALERT_EN | TMP007_CONFIG_TC_EN);
|
||||
|
||||
ret = i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
|
||||
data->config);
|
||||
@ -260,22 +496,39 @@ static int tmp007_probe(struct i2c_client *client,
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Only the following flags can activate ALERT pin. Data conversion/validity flags
|
||||
* flags can still be polled for getting temperature data
|
||||
*
|
||||
* Set Status Mask register:
|
||||
* 1. Conversion ready enable
|
||||
* 2. Data valid enable
|
||||
* 1. Object temperature high limit enable
|
||||
* 2. Object temperature low limit enable
|
||||
* 3. TDIE temperature high limit enable
|
||||
* 4. TDIE temperature low limit enable
|
||||
*/
|
||||
|
||||
ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
|
||||
if (ret < 0)
|
||||
goto error_powerdown;
|
||||
|
||||
status = ret;
|
||||
status |= (TMP007_STATUS_CONV_READY | TMP007_STATUS_DATA_VALID);
|
||||
data->status_mask = ret;
|
||||
data->status_mask |= (TMP007_STATUS_OHF | TMP007_STATUS_OLF
|
||||
| TMP007_STATUS_LHF | TMP007_STATUS_LLF);
|
||||
|
||||
ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK, status);
|
||||
ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK, data->status_mask);
|
||||
if (ret < 0)
|
||||
goto error_powerdown;
|
||||
|
||||
if (client->irq) {
|
||||
ret = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, tmp007_interrupt_handler,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
tmp007_id->name, indio_dev);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "irq request error %d\n", -ret);
|
||||
goto error_powerdown;
|
||||
}
|
||||
}
|
||||
|
||||
return iio_device_register(indio_dev);
|
||||
|
||||
error_powerdown:
|
||||
|
@ -2,14 +2,7 @@
|
||||
# Makefile for industrial I/O accelerometer drivers
|
||||
#
|
||||
|
||||
adis16201-y := adis16201_core.o
|
||||
obj-$(CONFIG_ADIS16201) += adis16201.o
|
||||
|
||||
adis16203-y := adis16203_core.o
|
||||
obj-$(CONFIG_ADIS16203) += adis16203.o
|
||||
|
||||
adis16209-y := adis16209_core.o
|
||||
obj-$(CONFIG_ADIS16209) += adis16209.o
|
||||
|
||||
adis16240-y := adis16240_core.o
|
||||
obj-$(CONFIG_ADIS16240) += adis16240.o
|
||||
|
@ -20,7 +20,145 @@
|
||||
#include <linux/iio/buffer.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[] = {
|
||||
[ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS,
|
@ -1,144 +0,0 @@
|
||||
#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 @@
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/imu/adis.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
|
||||
#include "adis16203.h"
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/sysfs.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,
|
||||
};
|
||||
|
||||
#define DRIVER_NAME "adis16203"
|
||||
|
@ -1,125 +0,0 @@
|
||||
#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 @@
|
||||
#include <linux/iio/buffer.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] = {
|
||||
[ADIS16209_SCAN_SUPPLY] = { },
|
@ -1,144 +0,0 @@
|
||||
#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 @@
|
||||
#include <linux/iio/buffer.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,
|
||||
struct device_attribute *attr,
|
||||
@ -65,7 +238,7 @@ static ssize_t adis16240_read_12bit_signed(struct device *dev,
|
||||
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_XYZPEAK_OUT);
|
||||
|
@ -1,179 +0,0 @@
|
||||
#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
|
||||
To compile this driver as a module, choose M here: the
|
||||
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
|
||||
|
@ -10,5 +10,3 @@ obj-$(CONFIG_AD7780) += ad7780.o
|
||||
obj-$(CONFIG_AD7816) += ad7816.o
|
||||
obj-$(CONFIG_AD7192) += ad7192.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,
|
||||
|
||||
static IIO_DEVICE_ATTR_NAMED(in_v_m_v_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);
|
||||
|
||||
static ssize_t ad7192_show_ac_excitation(struct device *dev,
|
||||
@ -412,11 +412,11 @@ static ssize_t ad7192_set(struct device *dev,
|
||||
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_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_REG_MODE);
|
||||
|
||||
|
@ -267,7 +267,7 @@ static ssize_t adt7316_store_enabled(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(enabled, 0644,
|
||||
adt7316_show_enabled,
|
||||
adt7316_store_enabled,
|
||||
0);
|
||||
@ -311,7 +311,7 @@ static ssize_t adt7316_store_select_ex_temp(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(select_ex_temp, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(select_ex_temp, 0644,
|
||||
adt7316_show_select_ex_temp,
|
||||
adt7316_store_select_ex_temp,
|
||||
0);
|
||||
@ -352,7 +352,7 @@ static ssize_t adt7316_store_mode(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(mode, 0644,
|
||||
adt7316_show_mode,
|
||||
adt7316_store_mode,
|
||||
0);
|
||||
@ -364,7 +364,7 @@ static ssize_t adt7316_show_all_modes(struct device *dev,
|
||||
return sprintf(buf, "single_channel\nround_robin\n");
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(all_modes, S_IRUGO, adt7316_show_all_modes, NULL, 0);
|
||||
static IIO_DEVICE_ATTR(all_modes, 0444, adt7316_show_all_modes, NULL, 0);
|
||||
|
||||
static ssize_t adt7316_show_ad_channel(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
@ -446,7 +446,7 @@ static ssize_t adt7316_store_ad_channel(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(ad_channel, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(ad_channel, 0644,
|
||||
adt7316_show_ad_channel,
|
||||
adt7316_store_ad_channel,
|
||||
0);
|
||||
@ -469,7 +469,7 @@ static ssize_t adt7316_show_all_ad_channels(struct device *dev,
|
||||
"2 - External Temperature\n");
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(all_ad_channels, S_IRUGO,
|
||||
static IIO_DEVICE_ATTR(all_ad_channels, 0444,
|
||||
adt7316_show_all_ad_channels, NULL, 0);
|
||||
|
||||
static ssize_t adt7316_show_disable_averaging(struct device *dev,
|
||||
@ -506,7 +506,7 @@ static ssize_t adt7316_store_disable_averaging(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(disable_averaging, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(disable_averaging, 0644,
|
||||
adt7316_show_disable_averaging,
|
||||
adt7316_store_disable_averaging,
|
||||
0);
|
||||
@ -545,7 +545,7 @@ static ssize_t adt7316_store_enable_smbus_timeout(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(enable_smbus_timeout, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(enable_smbus_timeout, 0644,
|
||||
adt7316_show_enable_smbus_timeout,
|
||||
adt7316_store_enable_smbus_timeout,
|
||||
0);
|
||||
@ -583,7 +583,7 @@ static ssize_t adt7316_store_powerdown(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(powerdown, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(powerdown, 0644,
|
||||
adt7316_show_powerdown,
|
||||
adt7316_store_powerdown,
|
||||
0);
|
||||
@ -621,7 +621,7 @@ static ssize_t adt7316_store_fast_ad_clock(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(fast_ad_clock, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(fast_ad_clock, 0644,
|
||||
adt7316_show_fast_ad_clock,
|
||||
adt7316_store_fast_ad_clock,
|
||||
0);
|
||||
@ -674,7 +674,7 @@ static ssize_t adt7316_store_da_high_resolution(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(da_high_resolution, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(da_high_resolution, 0644,
|
||||
adt7316_show_da_high_resolution,
|
||||
adt7316_store_da_high_resolution,
|
||||
0);
|
||||
@ -720,7 +720,7 @@ static ssize_t adt7316_store_AIN_internal_Vref(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(AIN_internal_Vref, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(AIN_internal_Vref, 0644,
|
||||
adt7316_show_AIN_internal_Vref,
|
||||
adt7316_store_AIN_internal_Vref,
|
||||
0);
|
||||
@ -760,7 +760,7 @@ static ssize_t adt7316_store_enable_prop_DACA(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(enable_proportion_DACA, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(enable_proportion_DACA, 0644,
|
||||
adt7316_show_enable_prop_DACA,
|
||||
adt7316_store_enable_prop_DACA,
|
||||
0);
|
||||
@ -799,7 +799,7 @@ static ssize_t adt7316_store_enable_prop_DACB(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(enable_proportion_DACB, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(enable_proportion_DACB, 0644,
|
||||
adt7316_show_enable_prop_DACB,
|
||||
adt7316_store_enable_prop_DACB,
|
||||
0);
|
||||
@ -842,7 +842,7 @@ static ssize_t adt7316_store_DAC_2Vref_ch_mask(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(DAC_2Vref_channels_mask, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(DAC_2Vref_channels_mask, 0644,
|
||||
adt7316_show_DAC_2Vref_ch_mask,
|
||||
adt7316_store_DAC_2Vref_ch_mask,
|
||||
0);
|
||||
@ -902,7 +902,7 @@ static ssize_t adt7316_store_DAC_update_mode(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(DAC_update_mode, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(DAC_update_mode, 0644,
|
||||
adt7316_show_DAC_update_mode,
|
||||
adt7316_store_DAC_update_mode,
|
||||
0);
|
||||
@ -922,7 +922,7 @@ static ssize_t adt7316_show_all_DAC_update_modes(struct device *dev,
|
||||
return sprintf(buf, "manual\n");
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(all_DAC_update_modes, S_IRUGO,
|
||||
static IIO_DEVICE_ATTR(all_DAC_update_modes, 0444,
|
||||
adt7316_show_all_DAC_update_modes, NULL, 0);
|
||||
|
||||
|
||||
@ -961,7 +961,7 @@ static ssize_t adt7316_store_update_DAC(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(update_DAC, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(update_DAC, 0644,
|
||||
NULL,
|
||||
adt7316_store_update_DAC,
|
||||
0);
|
||||
@ -1006,7 +1006,7 @@ static ssize_t adt7316_store_DA_AB_Vref_bypass(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(DA_AB_Vref_bypass, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(DA_AB_Vref_bypass, 0644,
|
||||
adt7316_show_DA_AB_Vref_bypass,
|
||||
adt7316_store_DA_AB_Vref_bypass,
|
||||
0);
|
||||
@ -1051,7 +1051,7 @@ static ssize_t adt7316_store_DA_CD_Vref_bypass(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(DA_CD_Vref_bypass, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(DA_CD_Vref_bypass, 0644,
|
||||
adt7316_show_DA_CD_Vref_bypass,
|
||||
adt7316_store_DA_CD_Vref_bypass,
|
||||
0);
|
||||
@ -1112,7 +1112,7 @@ static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(DAC_internal_Vref, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(DAC_internal_Vref, 0644,
|
||||
adt7316_show_DAC_internal_Vref,
|
||||
adt7316_store_DAC_internal_Vref,
|
||||
0);
|
||||
@ -1201,7 +1201,7 @@ static ssize_t adt7316_show_VDD(struct device *dev,
|
||||
|
||||
return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_VDD, buf);
|
||||
}
|
||||
static IIO_DEVICE_ATTR(VDD, S_IRUGO, adt7316_show_VDD, NULL, 0);
|
||||
static IIO_DEVICE_ATTR(VDD, 0444, adt7316_show_VDD, NULL, 0);
|
||||
|
||||
static ssize_t adt7316_show_in_temp(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
@ -1213,7 +1213,7 @@ static ssize_t adt7316_show_in_temp(struct device *dev,
|
||||
return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_IN, buf);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(in_temp, S_IRUGO, adt7316_show_in_temp, NULL, 0);
|
||||
static IIO_DEVICE_ATTR(in_temp, 0444, adt7316_show_in_temp, NULL, 0);
|
||||
|
||||
static ssize_t adt7316_show_ex_temp_AIN1(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
@ -1225,9 +1225,9 @@ static ssize_t adt7316_show_ex_temp_AIN1(struct device *dev,
|
||||
return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_EX, buf);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(ex_temp_AIN1, S_IRUGO, adt7316_show_ex_temp_AIN1,
|
||||
static IIO_DEVICE_ATTR(ex_temp_AIN1, 0444, adt7316_show_ex_temp_AIN1,
|
||||
NULL, 0);
|
||||
static IIO_DEVICE_ATTR(ex_temp, S_IRUGO, adt7316_show_ex_temp_AIN1, NULL, 0);
|
||||
static IIO_DEVICE_ATTR(ex_temp, 0444, adt7316_show_ex_temp_AIN1, NULL, 0);
|
||||
|
||||
static ssize_t adt7316_show_AIN2(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
@ -1238,7 +1238,7 @@ static ssize_t adt7316_show_AIN2(struct device *dev,
|
||||
|
||||
return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN2, buf);
|
||||
}
|
||||
static IIO_DEVICE_ATTR(AIN2, S_IRUGO, adt7316_show_AIN2, NULL, 0);
|
||||
static IIO_DEVICE_ATTR(AIN2, 0444, adt7316_show_AIN2, NULL, 0);
|
||||
|
||||
static ssize_t adt7316_show_AIN3(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
@ -1249,7 +1249,7 @@ static ssize_t adt7316_show_AIN3(struct device *dev,
|
||||
|
||||
return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN3, buf);
|
||||
}
|
||||
static IIO_DEVICE_ATTR(AIN3, S_IRUGO, adt7316_show_AIN3, NULL, 0);
|
||||
static IIO_DEVICE_ATTR(AIN3, 0444, adt7316_show_AIN3, NULL, 0);
|
||||
|
||||
static ssize_t adt7316_show_AIN4(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
@ -1260,7 +1260,7 @@ static ssize_t adt7316_show_AIN4(struct device *dev,
|
||||
|
||||
return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN4, buf);
|
||||
}
|
||||
static IIO_DEVICE_ATTR(AIN4, S_IRUGO, adt7316_show_AIN4, NULL, 0);
|
||||
static IIO_DEVICE_ATTR(AIN4, 0444, adt7316_show_AIN4, NULL, 0);
|
||||
|
||||
static ssize_t adt7316_show_temp_offset(struct adt7316_chip_info *chip,
|
||||
int offset_addr, char *buf)
|
||||
@ -1325,7 +1325,7 @@ static ssize_t adt7316_store_in_temp_offset(struct device *dev,
|
||||
len);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(in_temp_offset, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(in_temp_offset, 0644,
|
||||
adt7316_show_in_temp_offset,
|
||||
adt7316_store_in_temp_offset, 0);
|
||||
|
||||
@ -1351,7 +1351,7 @@ static ssize_t adt7316_store_ex_temp_offset(struct device *dev,
|
||||
len);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(ex_temp_offset, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(ex_temp_offset, 0644,
|
||||
adt7316_show_ex_temp_offset,
|
||||
adt7316_store_ex_temp_offset, 0);
|
||||
|
||||
@ -1378,7 +1378,7 @@ static ssize_t adt7316_store_in_analog_temp_offset(struct device *dev,
|
||||
ADT7316_IN_ANALOG_TEMP_OFFSET, buf, len);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(in_analog_temp_offset, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(in_analog_temp_offset, 0644,
|
||||
adt7316_show_in_analog_temp_offset,
|
||||
adt7316_store_in_analog_temp_offset, 0);
|
||||
|
||||
@ -1405,7 +1405,7 @@ static ssize_t adt7316_store_ex_analog_temp_offset(struct device *dev,
|
||||
ADT7316_EX_ANALOG_TEMP_OFFSET, buf, len);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(ex_analog_temp_offset, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(ex_analog_temp_offset, 0644,
|
||||
adt7316_show_ex_analog_temp_offset,
|
||||
adt7316_store_ex_analog_temp_offset, 0);
|
||||
|
||||
@ -1500,7 +1500,7 @@ static ssize_t adt7316_store_DAC_A(struct device *dev,
|
||||
return adt7316_store_DAC(chip, 0, buf, len);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(DAC_A, S_IRUGO | S_IWUSR, adt7316_show_DAC_A,
|
||||
static IIO_DEVICE_ATTR(DAC_A, 0644, adt7316_show_DAC_A,
|
||||
adt7316_store_DAC_A, 0);
|
||||
|
||||
static ssize_t adt7316_show_DAC_B(struct device *dev,
|
||||
@ -1524,7 +1524,7 @@ static ssize_t adt7316_store_DAC_B(struct device *dev,
|
||||
return adt7316_store_DAC(chip, 1, buf, len);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(DAC_B, S_IRUGO | S_IWUSR, adt7316_show_DAC_B,
|
||||
static IIO_DEVICE_ATTR(DAC_B, 0644, adt7316_show_DAC_B,
|
||||
adt7316_store_DAC_B, 0);
|
||||
|
||||
static ssize_t adt7316_show_DAC_C(struct device *dev,
|
||||
@ -1548,7 +1548,7 @@ static ssize_t adt7316_store_DAC_C(struct device *dev,
|
||||
return adt7316_store_DAC(chip, 2, buf, len);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(DAC_C, S_IRUGO | S_IWUSR, adt7316_show_DAC_C,
|
||||
static IIO_DEVICE_ATTR(DAC_C, 0644, adt7316_show_DAC_C,
|
||||
adt7316_store_DAC_C, 0);
|
||||
|
||||
static ssize_t adt7316_show_DAC_D(struct device *dev,
|
||||
@ -1572,7 +1572,7 @@ static ssize_t adt7316_store_DAC_D(struct device *dev,
|
||||
return adt7316_store_DAC(chip, 3, buf, len);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(DAC_D, S_IRUGO | S_IWUSR, adt7316_show_DAC_D,
|
||||
static IIO_DEVICE_ATTR(DAC_D, 0644, adt7316_show_DAC_D,
|
||||
adt7316_store_DAC_D, 0);
|
||||
|
||||
static ssize_t adt7316_show_device_id(struct device *dev,
|
||||
@ -1591,7 +1591,7 @@ static ssize_t adt7316_show_device_id(struct device *dev,
|
||||
return sprintf(buf, "%d\n", id);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(device_id, S_IRUGO, adt7316_show_device_id, NULL, 0);
|
||||
static IIO_DEVICE_ATTR(device_id, 0444, adt7316_show_device_id, NULL, 0);
|
||||
|
||||
static ssize_t adt7316_show_manufactorer_id(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
@ -1609,7 +1609,7 @@ static ssize_t adt7316_show_manufactorer_id(struct device *dev,
|
||||
return sprintf(buf, "%d\n", id);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(manufactorer_id, S_IRUGO,
|
||||
static IIO_DEVICE_ATTR(manufactorer_id, 0444,
|
||||
adt7316_show_manufactorer_id, NULL, 0);
|
||||
|
||||
static ssize_t adt7316_show_device_rev(struct device *dev,
|
||||
@ -1628,7 +1628,7 @@ static ssize_t adt7316_show_device_rev(struct device *dev,
|
||||
return sprintf(buf, "%d\n", rev);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(device_rev, S_IRUGO, adt7316_show_device_rev, NULL, 0);
|
||||
static IIO_DEVICE_ATTR(device_rev, 0444, adt7316_show_device_rev, NULL, 0);
|
||||
|
||||
static ssize_t adt7316_show_bus_type(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
@ -1649,7 +1649,7 @@ static ssize_t adt7316_show_bus_type(struct device *dev,
|
||||
return sprintf(buf, "i2c\n");
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(bus_type, S_IRUGO, adt7316_show_bus_type, NULL, 0);
|
||||
static IIO_DEVICE_ATTR(bus_type, 0444, adt7316_show_bus_type, NULL, 0);
|
||||
|
||||
static struct attribute *adt7316_attributes[] = {
|
||||
&iio_dev_attr_all_modes.dev_attr.attr,
|
||||
@ -1972,61 +1972,61 @@ static ssize_t adt7316_set_int_enabled(struct device *dev,
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(int_mask,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_int_mask, adt7316_set_int_mask,
|
||||
0);
|
||||
static IIO_DEVICE_ATTR(in_temp_high_value,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_ad_bound, adt7316_set_ad_bound,
|
||||
ADT7316_IN_TEMP_HIGH);
|
||||
static IIO_DEVICE_ATTR(in_temp_low_value,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_ad_bound, adt7316_set_ad_bound,
|
||||
ADT7316_IN_TEMP_LOW);
|
||||
static IIO_DEVICE_ATTR(ex_temp_high_value,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_ad_bound, adt7316_set_ad_bound,
|
||||
ADT7316_EX_TEMP_HIGH);
|
||||
static IIO_DEVICE_ATTR(ex_temp_low_value,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_ad_bound, adt7316_set_ad_bound,
|
||||
ADT7316_EX_TEMP_LOW);
|
||||
|
||||
/* NASTY duplication to be fixed */
|
||||
static IIO_DEVICE_ATTR(ex_temp_ain1_high_value,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_ad_bound, adt7316_set_ad_bound,
|
||||
ADT7316_EX_TEMP_HIGH);
|
||||
static IIO_DEVICE_ATTR(ex_temp_ain1_low_value,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_ad_bound, adt7316_set_ad_bound,
|
||||
ADT7316_EX_TEMP_LOW);
|
||||
static IIO_DEVICE_ATTR(ain2_high_value,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_ad_bound, adt7316_set_ad_bound,
|
||||
ADT7516_AIN2_HIGH);
|
||||
static IIO_DEVICE_ATTR(ain2_low_value,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_ad_bound, adt7316_set_ad_bound,
|
||||
ADT7516_AIN2_LOW);
|
||||
static IIO_DEVICE_ATTR(ain3_high_value,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_ad_bound, adt7316_set_ad_bound,
|
||||
ADT7516_AIN3_HIGH);
|
||||
static IIO_DEVICE_ATTR(ain3_low_value,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_ad_bound, adt7316_set_ad_bound,
|
||||
ADT7516_AIN3_LOW);
|
||||
static IIO_DEVICE_ATTR(ain4_high_value,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_ad_bound, adt7316_set_ad_bound,
|
||||
ADT7516_AIN4_HIGH);
|
||||
static IIO_DEVICE_ATTR(ain4_low_value,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_ad_bound, adt7316_set_ad_bound,
|
||||
ADT7516_AIN4_LOW);
|
||||
static IIO_DEVICE_ATTR(int_enabled,
|
||||
S_IRUGO | S_IWUSR,
|
||||
0644,
|
||||
adt7316_show_int_enabled,
|
||||
adt7316_set_int_enabled, 0);
|
||||
|
||||
|
@ -41,10 +41,10 @@
|
||||
#define AD7152_REG_CFG2 26
|
||||
|
||||
/* Status Register Bit Designations (AD7152_REG_STATUS) */
|
||||
#define AD7152_STATUS_RDY1 (1 << 0)
|
||||
#define AD7152_STATUS_RDY2 (1 << 1)
|
||||
#define AD7152_STATUS_C1C2 (1 << 2)
|
||||
#define AD7152_STATUS_PWDN (1 << 7)
|
||||
#define AD7152_STATUS_RDY1 BIT(0)
|
||||
#define AD7152_STATUS_RDY2 BIT(1)
|
||||
#define AD7152_STATUS_C1C2 BIT(2)
|
||||
#define AD7152_STATUS_PWDN BIT(7)
|
||||
|
||||
/* Setup Register Bit Designations (AD7152_REG_CHx_SETUP) */
|
||||
#define AD7152_SETUP_CAPDIFF (1 << 5)
|
||||
|
@ -22,6 +22,98 @@
|
||||
|
||||
#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)
|
||||
{
|
||||
unsigned long long freqreg = (u64)fout *
|
||||
|
@ -8,98 +8,6 @@
|
||||
#ifndef IIO_DDS_AD9832_H_
|
||||
#define IIO_DDS_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;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO: struct ad9832_platform_data needs to go into include/linux/iio
|
||||
*/
|
||||
|
@ -25,6 +25,78 @@
|
||||
|
||||
#include "ad9834.h"
|
||||
|
||||
/* Registers */
|
||||
|
||||
#define AD9834_REG_CMD 0
|
||||
#define AD9834_REG_FREQ0 BIT(14)
|
||||
#define AD9834_REG_FREQ1 BIT(15)
|
||||
#define AD9834_REG_PHASE0 (BIT(15) | BIT(14))
|
||||
#define AD9834_REG_PHASE1 (BIT(15) | BIT(14) | BIT(13))
|
||||
|
||||
/* Command Control Bits */
|
||||
|
||||
#define AD9834_B28 BIT(13)
|
||||
#define AD9834_HLB BIT(12)
|
||||
#define AD9834_FSEL BIT(11)
|
||||
#define AD9834_PSEL BIT(10)
|
||||
#define AD9834_PIN_SW BIT(9)
|
||||
#define AD9834_RESET BIT(8)
|
||||
#define AD9834_SLEEP1 BIT(7)
|
||||
#define AD9834_SLEEP12 BIT(6)
|
||||
#define AD9834_OPBITEN BIT(5)
|
||||
#define AD9834_SIGN_PIB BIT(4)
|
||||
#define AD9834_DIV2 BIT(3)
|
||||
#define AD9834_MODE BIT(1)
|
||||
|
||||
#define AD9834_FREQ_BITS 28
|
||||
#define AD9834_PHASE_BITS 12
|
||||
|
||||
#define RES_MASK(bits) (BIT(bits) - 1)
|
||||
|
||||
/**
|
||||
* struct ad9834_state - driver instance specific data
|
||||
* @spi: spi_device
|
||||
* @reg: supply regulator
|
||||
* @mclk: external master clock
|
||||
* @control: cached control word
|
||||
* @xfer: default spi transfer
|
||||
* @msg: default spi message
|
||||
* @freq_xfer: tuning word spi transfer
|
||||
* @freq_msg: tuning word spi message
|
||||
* @data: spi transmit buffer
|
||||
* @freq_data: tuning word spi transmit buffer
|
||||
*/
|
||||
|
||||
struct ad9834_state {
|
||||
struct spi_device *spi;
|
||||
struct regulator *reg;
|
||||
unsigned int mclk;
|
||||
unsigned short control;
|
||||
unsigned short devid;
|
||||
struct spi_transfer xfer;
|
||||
struct spi_message msg;
|
||||
struct spi_transfer freq_xfer[2];
|
||||
struct spi_message freq_msg;
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
*/
|
||||
__be16 data ____cacheline_aligned;
|
||||
__be16 freq_data[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* ad9834_supported_device_ids:
|
||||
*/
|
||||
|
||||
enum ad9834_supported_device_ids {
|
||||
ID_AD9833,
|
||||
ID_AD9834,
|
||||
ID_AD9837,
|
||||
ID_AD9838,
|
||||
};
|
||||
|
||||
static unsigned int ad9834_calc_freqreg(unsigned long mclk, unsigned long fout)
|
||||
{
|
||||
unsigned long long freqreg = (u64)fout * (u64)BIT(AD9834_FREQ_BITS);
|
||||
|
@ -8,67 +8,6 @@
|
||||
#ifndef IIO_DDS_AD9834_H_
|
||||
#define IIO_DDS_AD9834_H_
|
||||
|
||||
/* Registers */
|
||||
|
||||
#define AD9834_REG_CMD 0
|
||||
#define AD9834_REG_FREQ0 BIT(14)
|
||||
#define AD9834_REG_FREQ1 BIT(15)
|
||||
#define AD9834_REG_PHASE0 (BIT(15) | BIT(14))
|
||||
#define AD9834_REG_PHASE1 (BIT(15) | BIT(14) | BIT(13))
|
||||
|
||||
/* Command Control Bits */
|
||||
|
||||
#define AD9834_B28 BIT(13)
|
||||
#define AD9834_HLB BIT(12)
|
||||
#define AD9834_FSEL BIT(11)
|
||||
#define AD9834_PSEL BIT(10)
|
||||
#define AD9834_PIN_SW BIT(9)
|
||||
#define AD9834_RESET BIT(8)
|
||||
#define AD9834_SLEEP1 BIT(7)
|
||||
#define AD9834_SLEEP12 BIT(6)
|
||||
#define AD9834_OPBITEN BIT(5)
|
||||
#define AD9834_SIGN_PIB BIT(4)
|
||||
#define AD9834_DIV2 BIT(3)
|
||||
#define AD9834_MODE BIT(1)
|
||||
|
||||
#define AD9834_FREQ_BITS 28
|
||||
#define AD9834_PHASE_BITS 12
|
||||
|
||||
#define RES_MASK(bits) (BIT(bits) - 1)
|
||||
|
||||
/**
|
||||
* struct ad9834_state - driver instance specific data
|
||||
* @spi: spi_device
|
||||
* @reg: supply regulator
|
||||
* @mclk: external master clock
|
||||
* @control: cached control word
|
||||
* @xfer: default spi transfer
|
||||
* @msg: default spi message
|
||||
* @freq_xfer: tuning word spi transfer
|
||||
* @freq_msg: tuning word spi message
|
||||
* @data: spi transmit buffer
|
||||
* @freq_data: tuning word spi transmit buffer
|
||||
*/
|
||||
|
||||
struct ad9834_state {
|
||||
struct spi_device *spi;
|
||||
struct regulator *reg;
|
||||
unsigned int mclk;
|
||||
unsigned short control;
|
||||
unsigned short devid;
|
||||
struct spi_transfer xfer;
|
||||
struct spi_message msg;
|
||||
struct spi_transfer freq_xfer[2];
|
||||
struct spi_message freq_msg;
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
*/
|
||||
__be16 data ____cacheline_aligned;
|
||||
__be16 freq_data[2];
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO: struct ad7887_platform_data needs to go into include/linux/iio
|
||||
*/
|
||||
@ -97,15 +36,4 @@ struct ad9834_platform_data {
|
||||
bool en_signbit_msb_out;
|
||||
};
|
||||
|
||||
/**
|
||||
* ad9834_supported_device_ids:
|
||||
*/
|
||||
|
||||
enum ad9834_supported_device_ids {
|
||||
ID_AD9833,
|
||||
ID_AD9834,
|
||||
ID_AD9837,
|
||||
ID_AD9838,
|
||||
};
|
||||
|
||||
#endif /* IIO_DDS_AD9834_H_ */
|
||||
|
@ -345,12 +345,12 @@ static ssize_t ad5933_store_frequency(struct device *dev,
|
||||
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_store_frequency,
|
||||
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_store_frequency,
|
||||
AD5933_REG_FREQ_INC);
|
||||
@ -469,32 +469,32 @@ static ssize_t ad5933_store(struct device *dev,
|
||||
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_store,
|
||||
AD5933_OUT_RANGE);
|
||||
|
||||
static IIO_DEVICE_ATTR(out_voltage0_scale_available, S_IRUGO,
|
||||
static IIO_DEVICE_ATTR(out_voltage0_scale_available, 0444,
|
||||
ad5933_show,
|
||||
NULL,
|
||||
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_store,
|
||||
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,
|
||||
NULL,
|
||||
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_store,
|
||||
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_store,
|
||||
AD5933_OUT_SETTLING_CYCLES);
|
||||
|
@ -3,6 +3,7 @@
|
||||
* ISL29028 is Concurrent Ambient Light and Proximity Sensor
|
||||
*
|
||||
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2016-2017 Brian Masney <masneyb@onstation.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@ -63,6 +64,9 @@
|
||||
|
||||
#define ISL29028_POWER_OFF_DELAY_MS 2000
|
||||
|
||||
static const unsigned int isl29028_prox_sleep_time[] = {800, 400, 200, 100, 75,
|
||||
50, 12, 0};
|
||||
|
||||
enum isl29028_als_ir_mode {
|
||||
ISL29028_MODE_NONE = 0,
|
||||
ISL29028_MODE_ALS,
|
||||
@ -78,22 +82,29 @@ struct isl29028_chip {
|
||||
enum isl29028_als_ir_mode als_ir_mode;
|
||||
};
|
||||
|
||||
static int isl29028_find_prox_sleep_time_index(int sampling)
|
||||
{
|
||||
unsigned int period = DIV_ROUND_UP(1000, sampling);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(isl29028_prox_sleep_time); ++i) {
|
||||
if (period >= isl29028_prox_sleep_time[i])
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
|
||||
unsigned int sampling)
|
||||
{
|
||||
struct device *dev = regmap_get_device(chip->regmap);
|
||||
static unsigned int prox_period[] = {800, 400, 200, 100, 75, 50, 12, 0};
|
||||
unsigned int period = DIV_ROUND_UP(1000, sampling);
|
||||
int sel, ret;
|
||||
|
||||
for (sel = 0; sel < ARRAY_SIZE(prox_period); ++sel) {
|
||||
if (period >= prox_period[sel])
|
||||
break;
|
||||
}
|
||||
int sleep_index, ret;
|
||||
|
||||
sleep_index = isl29028_find_prox_sleep_time_index(sampling);
|
||||
ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
|
||||
ISL29028_CONF_PROX_SLP_MASK,
|
||||
sel << ISL29028_CONF_PROX_SLP_SH);
|
||||
sleep_index << ISL29028_CONF_PROX_SLP_SH);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s(): Error %d setting the proximity sampling\n",
|
||||
@ -108,7 +119,7 @@ static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
|
||||
|
||||
static int isl29028_enable_proximity(struct isl29028_chip *chip)
|
||||
{
|
||||
int ret;
|
||||
int sleep_index, ret;
|
||||
|
||||
ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling);
|
||||
if (ret < 0)
|
||||
@ -121,7 +132,8 @@ static int isl29028_enable_proximity(struct isl29028_chip *chip)
|
||||
return ret;
|
||||
|
||||
/* Wait for conversion to be complete for first sample */
|
||||
mdelay(DIV_ROUND_UP(1000, chip->prox_sampling));
|
||||
sleep_index = isl29028_find_prox_sleep_time_index(chip->prox_sampling);
|
||||
msleep(isl29028_prox_sleep_time[sleep_index]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -192,7 +204,7 @@ static int isl29028_set_als_ir_mode(struct isl29028_chip *chip,
|
||||
return ret;
|
||||
|
||||
/* Need to wait for conversion time if ALS/IR mode enabled */
|
||||
mdelay(ISL29028_CONV_TIME_MS);
|
||||
msleep(ISL29028_CONV_TIME_MS);
|
||||
|
||||
chip->als_ir_mode = mode;
|
||||
|
||||
@ -645,7 +657,8 @@ static int __maybe_unused isl29028_resume(struct device *dev)
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops isl29028_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(isl29028_suspend, isl29028_resume)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SET_RUNTIME_PM_OPS(isl29028_suspend, isl29028_resume, NULL)
|
||||
};
|
||||
|
||||
|
@ -6,22 +6,88 @@
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include "meter.h"
|
||||
#include "ade7753.h"
|
||||
|
||||
#define ADE7753_WAVEFORM 0x01
|
||||
#define ADE7753_AENERGY 0x02
|
||||
#define ADE7753_RAENERGY 0x03
|
||||
#define ADE7753_LAENERGY 0x04
|
||||
#define ADE7753_VAENERGY 0x05
|
||||
#define ADE7753_RVAENERGY 0x06
|
||||
#define ADE7753_LVAENERGY 0x07
|
||||
#define ADE7753_LVARENERGY 0x08
|
||||
#define ADE7753_MODE 0x09
|
||||
#define ADE7753_IRQEN 0x0A
|
||||
#define ADE7753_STATUS 0x0B
|
||||
#define ADE7753_RSTSTATUS 0x0C
|
||||
#define ADE7753_CH1OS 0x0D
|
||||
#define ADE7753_CH2OS 0x0E
|
||||
#define ADE7753_GAIN 0x0F
|
||||
#define ADE7753_PHCAL 0x10
|
||||
#define ADE7753_APOS 0x11
|
||||
#define ADE7753_WGAIN 0x12
|
||||
#define ADE7753_WDIV 0x13
|
||||
#define ADE7753_CFNUM 0x14
|
||||
#define ADE7753_CFDEN 0x15
|
||||
#define ADE7753_IRMS 0x16
|
||||
#define ADE7753_VRMS 0x17
|
||||
#define ADE7753_IRMSOS 0x18
|
||||
#define ADE7753_VRMSOS 0x19
|
||||
#define ADE7753_VAGAIN 0x1A
|
||||
#define ADE7753_VADIV 0x1B
|
||||
#define ADE7753_LINECYC 0x1C
|
||||
#define ADE7753_ZXTOUT 0x1D
|
||||
#define ADE7753_SAGCYC 0x1E
|
||||
#define ADE7753_SAGLVL 0x1F
|
||||
#define ADE7753_IPKLVL 0x20
|
||||
#define ADE7753_VPKLVL 0x21
|
||||
#define ADE7753_IPEAK 0x22
|
||||
#define ADE7753_RSTIPEAK 0x23
|
||||
#define ADE7753_VPEAK 0x24
|
||||
#define ADE7753_RSTVPEAK 0x25
|
||||
#define ADE7753_TEMP 0x26
|
||||
#define ADE7753_PERIOD 0x27
|
||||
#define ADE7753_TMODE 0x3D
|
||||
#define ADE7753_CHKSUM 0x3E
|
||||
#define ADE7753_DIEREV 0x3F
|
||||
|
||||
#define ADE7753_READ_REG(a) a
|
||||
#define ADE7753_WRITE_REG(a) ((a) | 0x80)
|
||||
|
||||
#define ADE7753_MAX_TX 4
|
||||
#define ADE7753_MAX_RX 4
|
||||
#define ADE7753_STARTUP_DELAY 1000
|
||||
|
||||
#define ADE7753_SPI_SLOW (u32)(300 * 1000)
|
||||
#define ADE7753_SPI_BURST (u32)(1000 * 1000)
|
||||
#define ADE7753_SPI_FAST (u32)(2000 * 1000)
|
||||
|
||||
/**
|
||||
* struct ade7753_state - device instance specific data
|
||||
* @us: actual spi_device
|
||||
* @tx: transmit buffer
|
||||
* @rx: receive buffer
|
||||
* @buf_lock: mutex to protect tx and rx
|
||||
**/
|
||||
struct ade7753_state {
|
||||
struct spi_device *us;
|
||||
struct mutex buf_lock;
|
||||
u8 tx[ADE7753_MAX_TX] ____cacheline_aligned;
|
||||
u8 rx[ADE7753_MAX_RX];
|
||||
};
|
||||
|
||||
static int ade7753_spi_write_reg_8(struct device *dev,
|
||||
u8 reg_address,
|
||||
|
@ -1,72 +0,0 @@
|
||||
#ifndef _ADE7753_H
|
||||
#define _ADE7753_H
|
||||
|
||||
#define ADE7753_WAVEFORM 0x01
|
||||
#define ADE7753_AENERGY 0x02
|
||||
#define ADE7753_RAENERGY 0x03
|
||||
#define ADE7753_LAENERGY 0x04
|
||||
#define ADE7753_VAENERGY 0x05
|
||||
#define ADE7753_RVAENERGY 0x06
|
||||
#define ADE7753_LVAENERGY 0x07
|
||||
#define ADE7753_LVARENERGY 0x08
|
||||
#define ADE7753_MODE 0x09
|
||||
#define ADE7753_IRQEN 0x0A
|
||||
#define ADE7753_STATUS 0x0B
|
||||
#define ADE7753_RSTSTATUS 0x0C
|
||||
#define ADE7753_CH1OS 0x0D
|
||||
#define ADE7753_CH2OS 0x0E
|
||||
#define ADE7753_GAIN 0x0F
|
||||
#define ADE7753_PHCAL 0x10
|
||||
#define ADE7753_APOS 0x11
|
||||
#define ADE7753_WGAIN 0x12
|
||||
#define ADE7753_WDIV 0x13
|
||||
#define ADE7753_CFNUM 0x14
|
||||
#define ADE7753_CFDEN 0x15
|
||||
#define ADE7753_IRMS 0x16
|
||||
#define ADE7753_VRMS 0x17
|
||||
#define ADE7753_IRMSOS 0x18
|
||||
#define ADE7753_VRMSOS 0x19
|
||||
#define ADE7753_VAGAIN 0x1A
|
||||
#define ADE7753_VADIV 0x1B
|
||||
#define ADE7753_LINECYC 0x1C
|
||||
#define ADE7753_ZXTOUT 0x1D
|
||||
#define ADE7753_SAGCYC 0x1E
|
||||
#define ADE7753_SAGLVL 0x1F
|
||||
#define ADE7753_IPKLVL 0x20
|
||||
#define ADE7753_VPKLVL 0x21
|
||||
#define ADE7753_IPEAK 0x22
|
||||
#define ADE7753_RSTIPEAK 0x23
|
||||
#define ADE7753_VPEAK 0x24
|
||||
#define ADE7753_RSTVPEAK 0x25
|
||||
#define ADE7753_TEMP 0x26
|
||||
#define ADE7753_PERIOD 0x27
|
||||
#define ADE7753_TMODE 0x3D
|
||||
#define ADE7753_CHKSUM 0x3E
|
||||
#define ADE7753_DIEREV 0x3F
|
||||
|
||||
#define ADE7753_READ_REG(a) a
|
||||
#define ADE7753_WRITE_REG(a) ((a) | 0x80)
|
||||
|
||||
#define ADE7753_MAX_TX 4
|
||||
#define ADE7753_MAX_RX 4
|
||||
#define ADE7753_STARTUP_DELAY 1000
|
||||
|
||||
#define ADE7753_SPI_SLOW (u32)(300 * 1000)
|
||||
#define ADE7753_SPI_BURST (u32)(1000 * 1000)
|
||||
#define ADE7753_SPI_FAST (u32)(2000 * 1000)
|
||||
|
||||
/**
|
||||
* struct ade7753_state - device instance specific data
|
||||
* @us: actual spi_device
|
||||
* @tx: transmit buffer
|
||||
* @rx: receive buffer
|
||||
* @buf_lock: mutex to protect tx and rx
|
||||
**/
|
||||
struct ade7753_state {
|
||||
struct spi_device *us;
|
||||
struct mutex buf_lock;
|
||||
u8 tx[ADE7753_MAX_TX] ____cacheline_aligned;
|
||||
u8 rx[ADE7753_MAX_RX];
|
||||
};
|
||||
|
||||
#endif
|
@ -426,9 +426,7 @@ static int ade7854_set_irq(struct device *dev, bool enable)
|
||||
else
|
||||
irqen &= ~BIT(17);
|
||||
|
||||
ret = st->write_reg_32(dev, ADE7854_MASK0, irqen);
|
||||
|
||||
return ret;
|
||||
return st->write_reg_32(dev, ADE7854_MASK0, irqen);
|
||||
}
|
||||
|
||||
static int ade7854_initial_setup(struct iio_dev *indio_dev)
|
||||
|
@ -81,94 +81,94 @@
|
||||
IIO_DEVICE_ATTR(reactive_power_c_gain, _mode, _show, _store, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_CURRENT_A(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(current_a, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(current_a, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_CURRENT_B(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(current_b, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(current_b, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_CURRENT_C(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(current_c, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(current_c, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_VOLT_A(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(volt_a, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(volt_a, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_VOLT_B(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(volt_b, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(volt_b, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_VOLT_C(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(volt_c, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(volt_c, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_AENERGY(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(aenergy, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(aenergy, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_LENERGY(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(lenergy, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(lenergy, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_RAENERGY(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(raenergy, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(raenergy, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_LAENERGY(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(laenergy, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(laenergy, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_VAENERGY(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(vaenergy, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(vaenergy, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_LVAENERGY(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(lvaenergy, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(lvaenergy, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_RVAENERGY(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(rvaenergy, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(rvaenergy, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_LVARENERGY(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(lvarenergy, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(lvarenergy, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_CHKSUM(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(chksum, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(chksum, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_ANGLE0(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(angle0, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(angle0, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_ANGLE1(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(angle1, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(angle1, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_ANGLE2(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(angle2, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(angle2, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_AWATTHR(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(awatthr, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(awatthr, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_BWATTHR(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(bwatthr, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(bwatthr, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_CWATTHR(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(cwatthr, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(cwatthr, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_AFWATTHR(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(afwatthr, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(afwatthr, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_BFWATTHR(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(bfwatthr, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(bfwatthr, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_CFWATTHR(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(cfwatthr, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(cfwatthr, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_AVARHR(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(avarhr, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(avarhr, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_BVARHR(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(bvarhr, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(bvarhr, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_CVARHR(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(cvarhr, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(cvarhr, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_AVAHR(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(avahr, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(avahr, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_BVAHR(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(bvahr, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(bvahr, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_CVAHR(_show, _addr) \
|
||||
IIO_DEVICE_ATTR(cvahr, S_IRUGO, _show, NULL, _addr)
|
||||
IIO_DEVICE_ATTR(cvahr, 0444, _show, NULL, _addr)
|
||||
|
||||
#define IIO_DEV_ATTR_IOS(_mode, _show, _store, _addr) \
|
||||
IIO_DEVICE_ATTR(ios, _mode, _show, _store, _addr)
|
||||
|
@ -531,36 +531,36 @@ error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(fclkin, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(fclkin, 0644,
|
||||
ad2s1210_show_fclkin, ad2s1210_store_fclkin, 0);
|
||||
static IIO_DEVICE_ATTR(fexcit, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(fexcit, 0644,
|
||||
ad2s1210_show_fexcit, ad2s1210_store_fexcit, 0);
|
||||
static IIO_DEVICE_ATTR(control, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(control, 0644,
|
||||
ad2s1210_show_control, ad2s1210_store_control, 0);
|
||||
static IIO_DEVICE_ATTR(bits, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(bits, 0644,
|
||||
ad2s1210_show_resolution, ad2s1210_store_resolution, 0);
|
||||
static IIO_DEVICE_ATTR(fault, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(fault, 0644,
|
||||
ad2s1210_show_fault, ad2s1210_clear_fault, 0);
|
||||
|
||||
static IIO_DEVICE_ATTR(los_thrd, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(los_thrd, 0644,
|
||||
ad2s1210_show_reg, ad2s1210_store_reg,
|
||||
AD2S1210_REG_LOS_THRD);
|
||||
static IIO_DEVICE_ATTR(dos_ovr_thrd, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(dos_ovr_thrd, 0644,
|
||||
ad2s1210_show_reg, ad2s1210_store_reg,
|
||||
AD2S1210_REG_DOS_OVR_THRD);
|
||||
static IIO_DEVICE_ATTR(dos_mis_thrd, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(dos_mis_thrd, 0644,
|
||||
ad2s1210_show_reg, ad2s1210_store_reg,
|
||||
AD2S1210_REG_DOS_MIS_THRD);
|
||||
static IIO_DEVICE_ATTR(dos_rst_max_thrd, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(dos_rst_max_thrd, 0644,
|
||||
ad2s1210_show_reg, ad2s1210_store_reg,
|
||||
AD2S1210_REG_DOS_RST_MAX_THRD);
|
||||
static IIO_DEVICE_ATTR(dos_rst_min_thrd, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(dos_rst_min_thrd, 0644,
|
||||
ad2s1210_show_reg, ad2s1210_store_reg,
|
||||
AD2S1210_REG_DOS_RST_MIN_THRD);
|
||||
static IIO_DEVICE_ATTR(lot_high_thrd, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(lot_high_thrd, 0644,
|
||||
ad2s1210_show_reg, ad2s1210_store_reg,
|
||||
AD2S1210_REG_LOT_HIGH_THRD);
|
||||
static IIO_DEVICE_ATTR(lot_low_thrd, S_IRUGO | S_IWUSR,
|
||||
static IIO_DEVICE_ATTR(lot_low_thrd, 0644,
|
||||
ad2s1210_show_reg, ad2s1210_store_reg,
|
||||
AD2S1210_REG_LOT_LOW_THRD);
|
||||
|
||||
|
@ -45,6 +45,10 @@
|
||||
#define HID_USAGE_SENSOR_DATA_ATMOSPHERIC_PRESSURE 0x200430
|
||||
#define HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE 0x200431
|
||||
|
||||
/* Tempreture (200033) */
|
||||
#define HID_USAGE_SENSOR_TEMPERATURE 0x200033
|
||||
#define HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE 0x200434
|
||||
|
||||
/* Gyro 3D: (200076) */
|
||||
#define HID_USAGE_SENSOR_GYRO_3D 0x200076
|
||||
#define HID_USAGE_SENSOR_DATA_ANGL_VELOCITY 0x200456
|
||||
|
Loading…
Reference in New Issue
Block a user