diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-03-06 13:17:21 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-03-06 13:17:21 +0100 |
commit | 34ff6c2fe366f389dbe45badb5d100bd3aa02bea (patch) | |
tree | 4d5086eba6117b53f0397ccee9a31851cabeb4e5 | |
parent | cc4e33d961276bd2e72add5188a124f51c11801d (diff) | |
parent | 2df79e1bddc46ea6ce9746a171220c3f68e378da (diff) |
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.
74 files changed, 3403 insertions, 1128 deletions
@@ -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> diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 530809ccfacf..8c24d0892f61 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -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. diff --git a/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 b/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 index ba676520b953..7fac2c268d9a 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 +++ b/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 @@ -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 diff --git a/Documentation/devicetree/bindings/iio/accel/adxl345.txt b/Documentation/devicetree/bindings/iio/accel/adxl345.txt new file mode 100644 index 000000000000..e7111b02c02c --- /dev/null +++ b/Documentation/devicetree/bindings/iio/accel/adxl345.txt @@ -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>; + }; diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt index f9e3ff2c656e..047189192aec 100644 --- a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt +++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt @@ -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>, diff --git a/Documentation/devicetree/bindings/iio/health/max30102.txt b/Documentation/devicetree/bindings/iio/health/max30102.txt new file mode 100644 index 000000000000..c695e7cbeefb --- /dev/null +++ b/Documentation/devicetree/bindings/iio/health/max30102.txt @@ -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>; +}; diff --git a/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt index cf81afdf7803..8305fb05ffda 100644 --- a/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt +++ b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt @@ -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 diff --git a/Documentation/devicetree/bindings/iio/proximity/devantech-srf04.txt b/Documentation/devicetree/bindings/iio/proximity/devantech-srf04.txt new file mode 100644 index 000000000000..d4dc7a227e2e --- /dev/null +++ b/Documentation/devicetree/bindings/iio/proximity/devantech-srf04.txt @@ -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>; +}; diff --git a/MAINTAINERS b/MAINTAINERS index c265a5fe4848..8aec9065cc1b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -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 diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index ef8401ac1141..15de262015df 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -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 diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 69fe8edc57a2..31fba1974e95 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -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 diff --git a/drivers/iio/accel/adxl345.h b/drivers/iio/accel/adxl345.h new file mode 100644 index 000000000000..c1ddf3927c47 --- /dev/null +++ b/drivers/iio/accel/adxl345.h @@ -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_ */ diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c new file mode 100644 index 000000000000..9ccb5828db98 --- /dev/null +++ b/drivers/iio/accel/adxl345_core.c @@ -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"); diff --git a/drivers/iio/accel/adxl345_i2c.c b/drivers/iio/accel/adxl345_i2c.c new file mode 100644 index 000000000000..05e1ec49700c --- /dev/null +++ b/drivers/iio/accel/adxl345_i2c.c @@ -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"); diff --git a/drivers/iio/accel/adxl345_spi.c b/drivers/iio/accel/adxl345_spi.c new file mode 100644 index 000000000000..6d658196f81c --- /dev/null +++ b/drivers/iio/accel/adxl345_spi.c @@ -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"); diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index dedae7adbce9..d777a972586d 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -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 diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index d0012620cd1c..b11bb5767543 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -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 diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/iio/adc/lpc32xx_adc.c index b51f237cd817..0de709b4288b 100644 --- a/drivers/staging/iio/adc/lpc32xx_adc.c +++ b/drivers/iio/adc/lpc32xx_adc.c @@ -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) - -/* 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 LPC32XX_ADC_CTRL: */ -#define AD_STROBE 0x00000002 -#define AD_PDN_CTRL 0x00000004 - -/* Bit definitions for LPC32XX_ADC_VALUE: */ -#define ADC_VALUE_MASK 0x000003FF - -#define MOD_NAME "lpc32xx-adc" - -struct lpc32xx_adc_info { +#define LPC32XXAD_SELECT(x) ((x) + 0x04) +#define LPC32XXAD_CTRL(x) ((x) + 0x08) +#define LPC32XXAD_VALUE(x) ((x) + 0x48) + +/* 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 LPC32XXAD_CTRL: */ +#define LPC32XXAD_STROBE 0x00000002 +#define LPC32XXAD_PDN_CTRL 0x00000004 + +/* Bit definitions for LPC32XXAD_VALUE: */ +#define LPC32XXAD_VALUE_MASK 0x000003FF + +#define LPC32XXAD_NAME "lpc32xx-adc" + +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), }, }; diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 89def6034f40..cde9ca7a01b8 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -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; - - 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); + if(!wait_for_completion_timeout(&priv->done, + msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT))) + return -ETIMEDOUT; - 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); @@ -392,6 +400,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)) diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/iio/adc/spear_adc.c index 5dd61f6a57b9..5dd61f6a57b9 100644 --- a/drivers/staging/iio/adc/spear_adc.c +++ b/drivers/iio/adc/spear_adc.c diff --git a/drivers/iio/adc/stx104.c b/drivers/iio/adc/stx104.c index be2de48844bc..2df84fa5e3fc 100644 --- a/drivers/iio/adc/stx104.c +++ b/drivers/iio/adc/stx104.c @@ -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]; diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index 7afdac42ed42..9338f94ce1dc 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c @@ -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) diff --git a/drivers/iio/counter/104-quad-8.c b/drivers/iio/counter/104-quad-8.c index f9b8fc9ae13f..ba3d9030cd51 100644 --- a/drivers/iio/counter/104-quad-8.c +++ b/drivers/iio/counter/104-quad-8.c @@ -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]; diff --git a/drivers/iio/dac/cio-dac.c b/drivers/iio/dac/cio-dac.c index 5a743e2a779d..a0464227a3a0 100644 --- a/drivers/iio/dac/cio-dac.c +++ b/drivers/iio/dac/cio-dac.c @@ -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]; diff --git a/drivers/iio/health/Kconfig b/drivers/iio/health/Kconfig index c5f004a8e447..a2ecb4c94c2a 100644 --- a/drivers/iio/health/Kconfig +++ b/drivers/iio/health/Kconfig @@ -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 diff --git a/drivers/iio/health/Makefile b/drivers/iio/health/Makefile index 9955a2ae8df1..3558f9d64954 100644 --- a/drivers/iio/health/Makefile +++ b/drivers/iio/health/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_AFE4403) += afe4403.o obj-$(CONFIG_AFE4404) += afe4404.o obj-$(CONFIG_MAX30100) += max30100.o +obj-$(CONFIG_MAX30102) += max30102.o diff --git a/drivers/iio/health/max30100.c b/drivers/iio/health/max30100.c index f6e283c4d686..849d71747f9f 100644 --- a/drivers/iio/health/max30100.c +++ b/drivers/iio/health/max30100.c @@ -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; diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c new file mode 100644 index 000000000000..839b875c29b9 --- /dev/null +++ b/drivers/iio/health/max30102.c @@ -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"); diff --git a/drivers/iio/imu/st_lsm6dsx/Kconfig b/drivers/iio/imu/st_lsm6dsx/Kconfig index 935d4cd071a3..e57337159b57 100644 --- a/drivers/iio/imu/st_lsm6dsx/Kconfig +++ b/drivers/iio/imu/st_lsm6dsx/Kconfig @@ -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. diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 69deafe1c10d..6a9849e6b30a 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -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 { diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index 78532ce07449..e71eccedd340 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -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. diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index c92ddcc190e2..c4332232ad71 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -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; } diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c index ea3041186e1e..2e4ed26fcbbd 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c @@ -71,6 +71,14 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = { .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 }, {}, }; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c index fbe72470ed1e..1bf4a582e6cf 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c @@ -88,6 +88,14 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = { .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 }, {}, }; diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 5f731ead9d46..2afcbacc0f7e 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -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 diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index c13a2399e6df..edfd69b6dc6d 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -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 diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c new file mode 100644 index 000000000000..721722376fd0 --- /dev/null +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -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"); diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c index 45ca056f019e..73fced8a63b7 100644 --- a/drivers/iio/light/hid-sensor-prox.c +++ b/drivers/iio/light/hid-sensor-prox.c @@ -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; } diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c index e22714365022..afa8de3418d0 100644 --- a/drivers/iio/potentiostat/lmp91000.c +++ b/drivers/iio/potentiostat/lmp91000.c @@ -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); diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index ab96cb7a0054..5b81a8c9d438 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig @@ -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 diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile index e914c2a5dd49..ed1b6f4cc209 100644 --- a/drivers/iio/proximity/Makefile +++ b/drivers/iio/proximity/Makefile @@ -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 diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c index 20c16a08c9d9..36c1ddc251aa 100644 --- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c @@ -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); diff --git a/drivers/iio/proximity/srf04.c b/drivers/iio/proximity/srf04.c new file mode 100644 index 000000000000..e37667f933b3 --- /dev/null +++ b/drivers/iio/proximity/srf04.c @@ -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"); diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig index 3089e8d0a32d..5378976d6d27 100644 --- a/drivers/iio/temperature/Kconfig +++ b/drivers/iio/temperature/Kconfig @@ -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 diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile index 4c4377480726..ad1d668de546 100644 --- a/drivers/iio/temperature/Makefile +++ b/drivers/iio/temperature/Makefile @@ -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 diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c new file mode 100644 index 000000000000..c01efeca4002 --- /dev/null +++ b/drivers/iio/temperature/hid-sensor-temperature.c @@ -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"); diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c index f962f31a5eb2..557214202eff 100644 --- a/drivers/iio/temperature/maxim_thermocouple.c +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -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; diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c index f04d0d1f6ac8..0615324d054c 100644 --- a/drivers/iio/temperature/tmp007.c +++ b/drivers/iio/temperature/tmp007.c @@ -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: diff --git a/drivers/staging/iio/accel/Makefile b/drivers/staging/iio/accel/Makefile index febb137b60c4..5d8ad21a0dae 100644 --- a/drivers/staging/iio/accel/Makefile +++ b/drivers/staging/iio/accel/Makefile @@ -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 diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201.c index 7963d4a83f84..d6c8658c88b9 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201.c @@ -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, diff --git a/drivers/staging/iio/accel/adis16201.h b/drivers/staging/iio/accel/adis16201.h deleted file mode 100644 index 64844adcaacd..000000000000 --- a/drivers/staging/iio/accel/adis16201.h +++ /dev/null @@ -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_ */ diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203.c index bd8119a23339..68189aded729 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203.c @@ -7,20 +7,140 @@ */ #include <linux/delay.h> -#include <linux/mutex.h> #include <linux/device.h> + +#include <linux/iio/buffer.h> +#include <linux/iio/iio.h> +#include <linux/iio/imu/adis.h> +#include <linux/iio/sysfs.h> + #include <linux/kernel.h> -#include <linux/spi/spi.h> +#include <linux/module.h> +#include <linux/mutex.h> #include <linux/slab.h> +#include <linux/spi/spi.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/imu/adis.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 -#include "adis16203.h" +/* Auxiliary DAC data */ +#define ADIS16203_AUX_DAC 0x30 + +/* General-purpose digital input/output control */ +#define ADIS16203_GPIO_CTRL 0x32 + +/* Miscellaneous control */ +#define ADIS16203_MSC_CTRL 0x34 + +/* Internal sample period (rate) control */ +#define ADIS16203_SMPL_PRD 0x36 + +/* Operation, filter configuration */ +#define ADIS16203_AVG_CNT 0x38 + +/* Operation, sleep mode control */ +#define ADIS16203_SLP_CNT 0x3A + +/* Diagnostics, system status register */ +#define ADIS16203_DIAG_STAT 0x3C + +/* Operation, system command register */ +#define ADIS16203_GLOB_CMD 0x3E + +/* MSC_CTRL */ + +/* Self-test at power-on: 1 = disabled, 0 = enabled */ +#define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST BIT(10) + +/* Reverses rotation of both inclination outputs */ +#define ADIS16203_MSC_CTRL_REVERSE_ROT_EN BIT(9) + +/* Self-test enable */ +#define ADIS16203_MSC_CTRL_SELF_TEST_EN BIT(8) + +/* Data-ready enable: 1 = enabled, 0 = disabled */ +#define ADIS16203_MSC_CTRL_DATA_RDY_EN BIT(2) + +/* Data-ready polarity: 1 = active high, 0 = active low */ +#define ADIS16203_MSC_CTRL_ACTIVE_HIGH BIT(1) + +/* Data-ready line selection: 1 = DIO1, 0 = DIO0 */ +#define ADIS16203_MSC_CTRL_DATA_RDY_DIO1 BIT(0) + +/* DIAG_STAT */ + +/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16203_DIAG_STAT_ALARM2 BIT(9) + +/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16203_DIAG_STAT_ALARM1 BIT(8) + +/* Self-test diagnostic error flag */ +#define ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT 5 + +/* SPI communications failure */ +#define ADIS16203_DIAG_STAT_SPI_FAIL_BIT 3 + +/* Flash update failure */ +#define ADIS16203_DIAG_STAT_FLASH_UPT_BIT 2 + +/* Power supply above 3.625 V */ +#define ADIS16203_DIAG_STAT_POWER_HIGH_BIT 1 + +/* Power supply below 3.15 V */ +#define ADIS16203_DIAG_STAT_POWER_LOW_BIT 0 + +/* GLOB_CMD */ + +#define ADIS16203_GLOB_CMD_SW_RESET BIT(7) +#define ADIS16203_GLOB_CMD_CLEAR_STAT BIT(4) +#define ADIS16203_GLOB_CMD_FACTORY_CAL BIT(1) + +#define ADIS16203_ERROR_ACTIVE BIT(14) + +enum adis16203_scan { + ADIS16203_SCAN_INCLI_X, + ADIS16203_SCAN_INCLI_Y, + ADIS16203_SCAN_SUPPLY, + ADIS16203_SCAN_AUX_ADC, + ADIS16203_SCAN_TEMP, +}; #define DRIVER_NAME "adis16203" diff --git a/drivers/staging/iio/accel/adis16203.h b/drivers/staging/iio/accel/adis16203.h deleted file mode 100644 index b483e4e6475b..000000000000 --- a/drivers/staging/iio/accel/adis16203.h +++ /dev/null @@ -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_ */ diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209.c index a599e19303d3..8ff537f89d45 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209.c @@ -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] = { }, diff --git a/drivers/staging/iio/accel/adis16209.h b/drivers/staging/iio/accel/adis16209.h deleted file mode 100644 index 315f1c0c46e8..000000000000 --- a/drivers/staging/iio/accel/adis16209.h +++ /dev/null @@ -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_ */ diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240.c index d5b99e610d08..27d7f6ad8c4c 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240.c @@ -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); diff --git a/drivers/staging/iio/accel/adis16240.h b/drivers/staging/iio/accel/adis16240.h deleted file mode 100644 index b2cb37b95913..000000000000 --- a/drivers/staging/iio/accel/adis16240.h +++ /dev/null @@ -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_ */ diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index deff89973d53..e17efb03bac0 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -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 diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index ac09485923b6..bf18bdd7c99d 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -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 diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 1fb68c01abd5..4fc8588f0392 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -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); diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 6054c7298fce..aa251c245981 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -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); diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c index b91b50f345bd..e8609b866fec 100644 --- a/drivers/staging/iio/cdc/ad7152.c +++ b/drivers/staging/iio/cdc/ad7152.c @@ -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) diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c index a5b2f068168d..8d40c8e37173 100644 --- a/drivers/staging/iio/frequency/ad9832.c +++ b/drivers/staging/iio/frequency/ad9832.c @@ -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 * diff --git a/drivers/staging/iio/frequency/ad9832.h b/drivers/staging/iio/frequency/ad9832.h index 1b08b04482a4..39d326cc1af9 100644 --- a/drivers/staging/iio/frequency/ad9832.h +++ b/drivers/staging/iio/frequency/ad9832.h @@ -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 */ diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c index 19216af1dfc9..f92ff7fef6f3 100644 --- a/drivers/staging/iio/frequency/ad9834.c +++ b/drivers/staging/iio/frequency/ad9834.c @@ -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); diff --git a/drivers/staging/iio/frequency/ad9834.h b/drivers/staging/iio/frequency/ad9834.h index 40fdd5da7bd0..ae620f38eb49 100644 --- a/drivers/staging/iio/frequency/ad9834.h +++ b/drivers/staging/iio/frequency/ad9834.h @@ -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_ */ diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 5e96352fa4ac..297665d3fe11 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -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); diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c index 6bb6d37cc7d1..5375e7a81205 100644 --- a/drivers/staging/iio/light/isl29028.c +++ b/drivers/staging/iio/light/isl29028.c @@ -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_set_proxim_sampling(struct isl29028_chip *chip, - unsigned int sampling) +static int isl29028_find_prox_sleep_time_index(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; + int i; - for (sel = 0; sel < ARRAY_SIZE(prox_period); ++sel) { - if (period >= prox_period[sel]) + 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); + 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) }; diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index 671dc9971610..dfd8b71d6a41 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -6,22 +6,88 @@ * Licensed under the GPL-2 or later. */ -#include <linux/interrupt.h> -#include <linux/irq.h> #include <linux/delay.h> -#include <linux/mutex.h> #include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/irq.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, diff --git a/drivers/staging/iio/meter/ade7753.h b/drivers/staging/iio/meter/ade7753.h deleted file mode 100644 index bfe749156bce..000000000000 --- a/drivers/staging/iio/meter/ade7753.h +++ /dev/null @@ -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 diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c index e8007f0c5186..c6cffc11b0ba 100644 --- a/drivers/staging/iio/meter/ade7854.c +++ b/drivers/staging/iio/meter/ade7854.c @@ -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) diff --git a/drivers/staging/iio/meter/meter.h b/drivers/staging/iio/meter/meter.h index dfba510f29be..0e37f23853f1 100644 --- a/drivers/staging/iio/meter/meter.h +++ b/drivers/staging/iio/meter/meter.h @@ -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) diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index 6b992634f009..90b57c03609c 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -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); diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h index 30c7dc45e45f..46dd1f27d2f2 100644 --- a/include/linux/hid-sensor-ids.h +++ b/include/linux/hid-sensor-ids.h @@ -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 |