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

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

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

Jonathan writes:

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

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

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

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

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

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

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

Other
* Mailmap
  - update Matt Ranostay's email address to the Konsolko one.
parents cc4e33d9 2df79e1b
......@@ -109,6 +109,7 @@ Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@osg.samsung.com>
Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@s-opensource.com>
Matt Ranostay <mranostay@gmail.com> Matthew Ranostay <mranostay@embeddedalley.com>
Matt Ranostay <mranostay@gmail.com> <matt.ranostay@intel.com>
Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting>
Mayuresh Janorkar <mayur@ti.com>
Michael Buesch <m@bues.ch>
Michel Dänzer <michel@tungstengraphics.com>
......
......@@ -55,6 +55,7 @@ Description:
then it is to be found in the base device directory.
What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency_available
What: /sys/bus/iio/devices/iio:deviceX/in_proximity_sampling_frequency_available
What: /sys/.../iio:deviceX/buffer/sampling_frequency_available
What: /sys/bus/iio/devices/triggerX/sampling_frequency_available
KernelVersion: 2.6.35
......@@ -1593,7 +1594,7 @@ Description:
can be processed to siemens per meter.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_raw
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Raw counter device counts from channel Y. For quadrature
......@@ -1601,10 +1602,24 @@ Description:
the counts of a single quadrature signal phase from channel Y.
What: /sys/bus/iio/devices/iio:deviceX/in_indexY_raw
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Raw counter device index value from channel Y. This attribute
provides an absolute positional reference (e.g. a pulse once per
revolution) which may be used to home positional systems as
required.
What: /sys/bus/iio/devices/iio:deviceX/in_count_count_direction_available
KernelVersion: 4.12
Contact: linux-iio@vger.kernel.org
Description:
A list of possible counting directions which are:
- "up" : counter device is increasing.
- "down": counter device is decreasing.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_direction
KernelVersion: 4.12
Contact: linux-iio@vger.kernel.org
Description:
Raw counter device counters direction for channel Y.
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
......
Analog Devices ADXL345 3-Axis, +/-(2g/4g/8g/16g) Digital Accelerometer
http://www.analog.com/en/products/mems/accelerometers/adxl345.html
Required properties:
- compatible : should be "adi,adxl345"
- reg : the I2C address or SPI chip select number of the sensor
Required properties for SPI bus usage:
- spi-max-frequency : set maximum clock frequency, must be 5000000
- spi-cpol and spi-cpha : must be defined for adxl345 to enable SPI mode 3
Optional properties:
- interrupt-parent : phandle to the parent interrupt controller as documented
in Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
- interrupts: interrupt mapping for IRQ as documented in
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
Example for a I2C device node:
accelerometer@2a {
compatible = "adi,adxl345";
reg = <0x53>;
interrupt-parent = <&gpio1>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
};
Example for a SPI device node:
accelerometer@0 {
compatible = "adi,adxl345";
reg = <0>;
spi-max-frequency = <5000000>;
spi-cpol;
spi-cpha;
interrupt-parent = <&gpio1>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
};
......@@ -7,6 +7,7 @@ Required properties:
- "amlogic,meson-gxm-saradc" for GXM
along with the generic "amlogic,meson-saradc"
- reg: the physical base address and length of the registers
- interrupts: the interrupt indicating end of sampling
- clocks: phandle and clock identifier (see clock-names)
- clock-names: mandatory clocks:
- "clkin" for the reference clock (typically XTAL)
......@@ -23,6 +24,7 @@ Example:
compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
#io-channel-cells = <1>;
reg = <0x0 0x8680 0x0 0x34>;
interrupts = <GIC_SPI 73 IRQ_TYPE_EDGE_RISING>;
clocks = <&xtal>,
<&clkc CLKID_SAR_ADC>,
<&clkc CLKID_SANA>,
......
Maxim MAX30102 heart rate and pulse oximeter sensor
* https://datasheets.maximintegrated.com/en/ds/MAX30102.pdf
Required properties:
- compatible: must be "maxim,max30102"
- reg: the I2C address of the sensor
- interrupt-parent: should be the phandle for the interrupt controller
- interrupts: the sole interrupt generated by the device
Refer to interrupt-controller/interrupts.txt for generic
interrupt client node bindings.
Optional properties:
- maxim,red-led-current-microamp: configuration for RED LED current
- maxim,ir-led-current-microamp: configuration for IR LED current
Note that each step is approximately 200 microamps, ranging from 0 uA to
50800 uA.
Example:
max30100@57 {
compatible = "maxim,max30102";
reg = <0x57>;
maxim,red-led-current-microamp = <7000>;
maxim,ir-led-current-microamp = <7000>;
interrupt-parent = <&gpio1>;
interrupts = <16 2>;
};
......@@ -3,6 +3,8 @@
Required properties:
- compatible: must be one of:
"st,lsm6ds3"
"st,lsm6ds3h"
"st,lsm6dsl"
"st,lsm6dsm"
- reg: i2c address of the sensor / spi cs line
......
* Devantech SRF04 ultrasonic range finder
Bit-banging driver using two GPIOs
Required properties:
- compatible: Should be "devantech,srf04"
- trig-gpios: Definition of the GPIO for the triggering (output)
This GPIO is set for about 10 us by the driver to tell the
device it should initiate the measurement cycle.
- echo-gpios: Definition of the GPIO for the echo (input)
This GPIO is set by the device as soon as an ultrasonic
burst is sent out and reset when the first echo is
received.
Thus this GPIO is set while the ultrasonic waves are doing
one round trip.
It needs to be an GPIO which is able to deliver an
interrupt because the time between two interrupts is
measured in the driver.
See Documentation/devicetree/bindings/gpio/gpio.txt for
information on how to specify a consumer gpio.
Example:
srf04@0 {
compatible = "devantech,srf04";
trig-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
echo-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
};
......@@ -3853,6 +3853,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained
F: drivers/usb/dwc3/
DEVANTECH SRF ULTRASONIC RANGER IIO DRIVER
M: Andreas Klinger <ak@it-klinger.de>
L: linux-iio@vger.kernel.org
S: Maintained
F: drivers/iio/proximity/srf*.c
DEVICE COREDUMP (DEV_COREDUMP)
M: Johannes Berg <johannes@sipsolutions.net>
L: linux-kernel@vger.kernel.org
......
......@@ -5,6 +5,37 @@
menu "Accelerometers"
config ADXL345
tristate
config ADXL345_I2C
tristate "Analog Devices ADXL345 3-Axis Digital Accelerometer I2C Driver"
depends on INPUT_ADXL34X=n
depends on I2C
select ADXL345
select REGMAP_I2C
help
Say Y here if you want to build support for the Analog Devices
ADXL345 3-axis digital accelerometer.
To compile this driver as a module, choose M here: the module
will be called adxl345_i2c and you will also get adxl345_core
for the core module.
config ADXL345_SPI
tristate "Analog Devices ADXL345 3-Axis Digital Accelerometer SPI Driver"
depends on INPUT_ADXL34X=n
depends on SPI
select ADXL345
select REGMAP_SPI
help
Say Y here if you want to build support for the Analog Devices
ADXL345 3-axis digital accelerometer.
To compile this driver as a module, choose M here: the module
will be called adxl345_spi and you will also get adxl345_core
for the core module.
config BMA180
tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver"
depends on I2C
......
......@@ -3,6 +3,9 @@
#
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ADXL345) += adxl345_core.o
obj-$(CONFIG_ADXL345_I2C) += adxl345_i2c.o
obj-$(CONFIG_ADXL345_SPI) += adxl345_spi.o
obj-$(CONFIG_BMA180) += bma180.o
obj-$(CONFIG_BMA220) += bma220_spi.o
obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
......
/*
* ADXL345 3-Axis Digital Accelerometer
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*/
#ifndef _ADXL345_H_
#define _ADXL345_H_
int adxl345_core_probe(struct device *dev, struct regmap *regmap,
const char *name);
int adxl345_core_remove(struct device *dev);
#endif /* _ADXL345_H_ */
/*
* ADXL345 3-Axis Digital Accelerometer IIO core driver
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*/
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/iio/iio.h>
#include "adxl345.h"
#define ADXL345_REG_DEVID 0x00
#define ADXL345_REG_POWER_CTL 0x2D
#define ADXL345_REG_DATA_FORMAT 0x31
#define ADXL345_REG_DATAX0 0x32
#define ADXL345_REG_DATAY0 0x34
#define ADXL345_REG_DATAZ0 0x36
#define ADXL345_POWER_CTL_MEASURE BIT(3)
#define ADXL345_POWER_CTL_STANDBY 0x00
#define ADXL345_DATA_FORMAT_FULL_RES BIT(3) /* Up to 13-bits resolution */
#define ADXL345_DATA_FORMAT_2G 0
#define ADXL345_DATA_FORMAT_4G 1
#define ADXL345_DATA_FORMAT_8G 2
#define ADXL345_DATA_FORMAT_16G 3
#define ADXL345_DEVID 0xE5
/*
* In full-resolution mode, scale factor is maintained at ~4 mg/LSB
* in all g ranges.
*
* At +/- 16g with 13-bit resolution, scale is computed as:
* (16 + 16) * 9.81 / (2^13 - 1) = 0.0383
*/
static const int adxl345_uscale = 38300;
struct adxl345_data {
struct regmap *regmap;
u8 data_range;
};
#define ADXL345_CHANNEL(reg, axis) { \
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.address = reg, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec adxl345_channels[] = {
ADXL345_CHANNEL(ADXL345_REG_DATAX0, X),
ADXL345_CHANNEL(ADXL345_REG_DATAY0, Y),
ADXL345_CHANNEL(ADXL345_REG_DATAZ0, Z),
};
static int adxl345_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct adxl345_data *data = iio_priv(indio_dev);
__le16 regval;
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
/*
* Data is stored in adjacent registers:
* ADXL345_REG_DATA(X0/Y0/Z0) contain the least significant byte
* and ADXL345_REG_DATA(X0/Y0/Z0) + 1 the most significant byte
*/
ret = regmap_bulk_read(data->regmap, chan->address, &regval,
sizeof(regval));
if (ret < 0)
return ret;
*val = sign_extend32(le16_to_cpu(regval), 12);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = adxl345_uscale;
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
static const struct iio_info adxl345_info = {
.driver_module = THIS_MODULE,
.read_raw = adxl345_read_raw,
};
int adxl345_core_probe(struct device *dev, struct regmap *regmap,
const char *name)
{
struct adxl345_data *data;
struct iio_dev *indio_dev;
u32 regval;
int ret;
ret = regmap_read(regmap, ADXL345_REG_DEVID, &regval);
if (ret < 0) {
dev_err(dev, "Error reading device ID: %d\n", ret);
return ret;
}
if (regval != ADXL345_DEVID) {
dev_err(dev, "Invalid device ID: %x, expected %x\n",
regval, ADXL345_DEVID);
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
dev_set_drvdata(dev, indio_dev);
data->regmap = regmap;
/* Enable full-resolution mode */
data->data_range = ADXL345_DATA_FORMAT_FULL_RES;
ret = regmap_write(data->regmap, ADXL345_REG_DATA_FORMAT,
data->data_range);
if (ret < 0) {
dev_err(dev, "Failed to set data range: %d\n", ret);
return ret;
}
indio_dev->dev.parent = dev;
indio_dev->name = name;
indio_dev->info = &adxl345_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = adxl345_channels;
indio_dev->num_channels = ARRAY_SIZE(adxl345_channels);
/* Enable measurement mode */
ret = regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
ADXL345_POWER_CTL_MEASURE);
if (ret < 0) {
dev_err(dev, "Failed to enable measurement mode: %d\n", ret);
return ret;
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(dev, "iio_device_register failed: %d\n", ret);
regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
ADXL345_POWER_CTL_STANDBY);
}
return ret;
}
EXPORT_SYMBOL_GPL(adxl345_core_probe);
int adxl345_core_remove(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct adxl345_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
return regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
ADXL345_POWER_CTL_STANDBY);
}
EXPORT_SYMBOL_GPL(adxl345_core_remove);
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer core driver");
MODULE_LICENSE("GPL v2");
/*
* ADXL345 3-Axis Digital Accelerometer I2C driver
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* 7-bit I2C slave address: 0x1D (ALT ADDRESS pin tied to VDDIO) or
* 0x53 (ALT ADDRESS pin grounded)
*/
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include "adxl345.h"
static const struct regmap_config adxl345_i2c_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int adxl345_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regmap *regmap;
regmap = devm_regmap_init_i2c(client, &adxl345_i2c_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "Error initializing i2c regmap: %ld\n",
PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return adxl345_core_probe(&client->dev, regmap, id ? id->name : NULL);
}
static int adxl345_i2c_remove(struct i2c_client *client)
{
return adxl345_core_remove(&client->dev);
}
static const struct i2c_device_id adxl345_i2c_id[] = {
{ "adxl345", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adxl345_i2c_id);
static const struct of_device_id adxl345_of_match[] = {
{ .compatible = "adi,adxl345" },
{ },
};
MODULE_DEVICE_TABLE(of, adxl345_of_match);
static struct i2c_driver adxl345_i2c_driver = {
.driver = {
.name = "adxl345_i2c",
.of_match_table = adxl345_of_match,
},
.probe = adxl345_i2c_probe,
.remove = adxl345_i2c_remove,
.id_table = adxl345_i2c_id,
};
module_i2c_driver(adxl345_i2c_driver);
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer I2C driver");
MODULE_LICENSE("GPL v2");
/*
* ADXL345 3-Axis Digital Accelerometer SPI driver
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*/
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include "adxl345.h"
#define ADXL345_MAX_SPI_FREQ_HZ 5000000
static const struct regmap_config adxl345_spi_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
/* Setting bits 7 and 6 enables multiple-byte read */
.read_flag_mask = BIT(7) | BIT(6),
};
static int adxl345_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct regmap *regmap;
/* Bail out if max_speed_hz exceeds 5 MHz */
if (spi->max_speed_hz > ADXL345_MAX_SPI_FREQ_HZ) {
dev_err(&spi->dev, "SPI CLK, %d Hz exceeds 5 MHz\n",
spi->max_speed_hz);
return -EINVAL;
}
regmap = devm_regmap_init_spi(spi, &adxl345_spi_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return adxl345_core_probe(&spi->dev, regmap, id->name);
}
static int adxl345_spi_remove(struct spi_device *spi)
{
return adxl345_core_remove(&spi->dev);
}
static const struct spi_device_id adxl345_spi_id[] = {
{ "adxl345", 0 },
{ }
};
MODULE_DEVICE_TABLE(spi, adxl345_spi_id);
static const struct of_device_id adxl345_of_match[] = {
{ .compatible = "adi,adxl345" },
{ },
};
MODULE_DEVICE_TABLE(of, adxl345_of_match);
static struct spi_driver adxl345_spi_driver = {
.driver = {
.name = "adxl345_spi",
.of_match_table = adxl345_of_match,
},
.probe = adxl345_spi_probe,
.remove = adxl345_spi_remove,
.id_table = adxl345_spi_id,
};
module_spi_driver(adxl345_spi_driver);
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer SPI driver");
MODULE_LICENSE("GPL v2");
......@@ -305,6 +305,18 @@ config LPC18XX_ADC
To compile this driver as a module, choose M here: the module will be
called lpc18xx_adc.
config LPC32XX_ADC
tristate "NXP LPC32XX ADC"
depends on ARCH_LPC32XX || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to build support for the integrated ADC inside the
LPC32XX SoC. Note that this feature uses the same hardware as the
touchscreen driver, so you should either select only one of the two
drivers (lpc32xx_adc or lpc32xx_ts) or, in the OpenFirmware case,
activate only one via device tree selection. Provides direct access
via sysfs.
config LTC2485
tristate "Linear Technology LTC2485 ADC driver"
depends on I2C
......@@ -494,6 +506,17 @@ config ROCKCHIP_SARADC
To compile this driver as a module, choose M here: the
module will be called rockchip_saradc.
config SPEAR_ADC
tristate "ST SPEAr ADC"
depends on PLAT_SPEAR || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to build support for the integrated ADC inside the
ST SPEAr SoC. Provides direct access via sysfs.
To compile this driver as a module, choose M here: the
module will be called spear_adc.
config STM32_ADC_CORE
tristate "STMicroelectronics STM32 adc core"
depends on ARCH_STM32 || COMPILE_TEST
......
......@@ -30,6 +30,7 @@ obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
obj-$(CONFIG_LTC2485) += ltc2485.o
obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX11100) += max11100.o
......@@ -46,6 +47,7 @@ obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
obj-$(CONFIG_RCAR_GYRO_ADC) += rcar-gyroadc.o
obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
obj-$(CONFIG_STX104) += stx104.o
obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
obj-$(CONFIG_STM32_ADC) += stm32-adc.o
......
......@@ -38,27 +38,30 @@
/*
* LPC32XX registers definitions
*/
#define LPC32XX_ADC_SELECT(x) ((x) + 0x04)
#define LPC32XX_ADC_CTRL(x) ((x) + 0x08)
#define LPC32XX_ADC_VALUE(x) ((x) + 0x48)
/* 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),
},
};
......
......@@ -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, &regval);
fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK,
regval);
if (fifo_chan != chan->channel)
continue;
fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK,
regval);
fifo_val &= (BIT(priv->data->resolution) - 1);
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, &regval);
fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval);
if (fifo_chan != chan->channel) {
dev_err(&indio_dev->dev,
"ADC FIFO entry belongs to channel %d instead of %d\n",
fifo_chan, chan->channel);
return -EINVAL;
}
*val = sum / count;
fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval);
fifo_val &= GENMASK(priv->data->resolution - 1, 0);
*val = fifo_val;
return 0;
}
......@@ -378,6 +380,12 @@ static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
reinit_completion(&priv->done);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_FIFO_IRQ_EN,
MESON_SAR_ADC_REG0_FIFO_IRQ_EN);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
......@@ -391,6 +399,9 @@ static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_SAMPLING_STOP,
MESON_SAR_ADC_REG0_SAMPLING_STOP);
......@@ -643,6 +654,7 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
int ret;
u32 regval;
ret = meson_sar_adc_lock(indio_dev);
if (ret)
......@@ -667,6 +679,9 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
goto err_sana_clk;
}
regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
MESON_SAR_ADC_REG11_BANDGAP_EN,
MESON_SAR_ADC_REG11_BANDGAP_EN);
......@@ -728,6 +743,25 @@ static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
return 0;
}
static irqreturn_t meson_sar_adc_irq(int irq, void *data)
{
struct iio_dev *indio_dev = data;
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
unsigned int cnt, threshold;
u32 regval;
regmap_read(priv->regmap, MESON_SAR_ADC_REG0, &regval);
cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
if (cnt < threshold)
return IRQ_NONE;
complete(&priv->done);
return IRQ_HANDLED;
}
static const struct iio_info meson_sar_adc_iio_info = {
.read_raw = meson_sar_adc_iio_info_read_raw,
.driver_module = THIS_MODULE,
......@@ -770,7 +804,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
struct resource *res;
void __iomem *base;
const struct of_device_id *match;
int ret;
int irq, ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
if (!indio_dev) {
......@@ -779,6 +813,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
}
priv = iio_priv(indio_dev);
init_completion(&priv->done);
match = of_match_device(meson_sar_adc_of_match, &pdev->dev);
priv->data = match->data;
......@@ -797,6 +832,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
if (!irq)
return -EINVAL;
ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED,
dev_name(&pdev->dev), indio_dev);
if (ret)
return ret;
priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
&meson_sar_adc_regmap_config);
if (IS_ERR(priv->regmap))
......
......@@ -318,6 +318,7 @@ static int stx104_probe(struct device *dev, unsigned int id)
}
indio_dev->name = dev_name(dev);
indio_dev->dev.parent = dev;
priv = iio_priv(indio_dev);
priv->base = base[id];
......
......@@ -62,6 +62,9 @@ static struct {
{HID_USAGE_SENSOR_TIME_TIMESTAMP, 0, 1000000000, 0},
{HID_USAGE_SENSOR_TIME_TIMESTAMP, HID_USAGE_SENSOR_UNITS_MILLISECOND,
1000000, 0},
{HID_USAGE_SENSOR_TEMPERATURE, 0, 1000, 0},
{HID_USAGE_SENSOR_TEMPERATURE, HID_USAGE_SENSOR_UNITS_DEGREES, 1000, 0},
};
static int pow_10(unsigned power)
......
......@@ -551,6 +551,7 @@ static int quad8_probe(struct device *dev, unsigned int id)
indio_dev->num_channels = ARRAY_SIZE(quad8_channels);
indio_dev->channels = quad8_channels;
indio_dev->name = dev_name(dev);
indio_dev->dev.parent = dev;
priv = iio_priv(indio_dev);
priv->base = base[id];
......
......@@ -119,6 +119,7 @@ static int cio_dac_probe(struct device *dev, unsigned int id)
indio_dev->channels = cio_dac_channels;
indio_dev->num_channels = CIO_DAC_NUM_CHAN;
indio_dev->name = dev_name(dev);
indio_dev->dev.parent = dev;
priv = iio_priv(indio_dev);
priv->base = base[id];
......
......@@ -46,6 +46,19 @@ config MAX30100
To compile this driver as a module, choose M here: the
module will be called max30100.
config MAX30102
tristate "MAX30102 heart rate and pulse oximeter sensor"
depends on I2C
select REGMAP_I2C
select IIO_BUFFER
select IIO_KFIFO_BUF
help
Say Y here to build I2C interface support for the Maxim
MAX30102 heart rate, and pulse oximeter sensor.
To compile this driver as a module, choose M here: the
module will be called max30102.
endmenu
endmenu
......@@ -7,3 +7,4 @@
obj-$(CONFIG_AFE4403) += afe4403.o
obj-$(CONFIG_AFE4404) += afe4404.o
obj-$(CONFIG_MAX30100) += max30100.o
obj-$(CONFIG_MAX30102) += max30102.o
......@@ -449,6 +449,7 @@ static int max30100_probe(struct i2c_client *client,
indio_dev->available_scan_masks = max30100_scan_masks;
indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
indio_dev->setup_ops = &max30100_buffer_setup_ops;
indio_dev->dev.parent = &client->dev;
data = iio_priv(indio_dev);
data->indio_dev = indio_dev;
......
/*
* 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, &reg);
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, &reg);
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, &reg);
if (ret < 0)
return ret;
*val = reg << 4;
ret = regmap_read(data->regmap, MAX30102_REG_TEMP_FRACTION, &reg);
if (ret < 0)
return ret;
*val |= reg & 0xf;
*val = sign_extend32(*val, 11);
return 0;
}
static int max30102_get_temp(struct max30102_data *data, int *val)
{
int ret;
/* start acquisition */
ret = regmap_update_bits(data->regmap, MAX30102_REG_TEMP_CONFIG,
MAX30102_REG_TEMP_CONFIG_TEMP_EN,
MAX30102_REG_TEMP_CONFIG_TEMP_EN);
if (ret)
return ret;
msleep(35);
return max30102_read_temp(data, val);
}
static int max30102_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct max30102_data *data = iio_priv(indio_dev);
int ret = -EINVAL;
switch (mask) {
case IIO_CHAN_INFO_RAW:
/*
* Temperature reading can only be acquired while engine
* is running
*/
mutex_lock(&indio_dev->mlock);
if (!iio_buffer_enabled(indio_dev))
ret = -EBUSY;
else {
ret = max30102_get_temp(data, val);
if (!ret)
ret = IIO_VAL_INT;
}
mutex_unlock(&indio_dev->mlock);
break;
case IIO_CHAN_INFO_SCALE:
*val = 1; /* 0.0625 */
*val2 = 16;
ret = IIO_VAL_FRACTIONAL;
break;
}
return ret;
}
static const struct iio_info max30102_info = {
.driver_module = THIS_MODULE,
.read_raw = max30102_read_raw,
};
static int max30102_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct max30102_data *data;
struct iio_buffer *buffer;
struct iio_dev *indio_dev;
int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
buffer = devm_iio_kfifo_allocate(&client->dev);
if (!buffer)
return -ENOMEM;
iio_device_attach_buffer(indio_dev, buffer);
indio_dev->name = MAX30102_DRV_NAME;
indio_dev->channels = max30102_channels;
indio_dev->info = &max30102_info;
indio_dev->num_channels = ARRAY_SIZE(max30102_channels);
indio_dev->available_scan_masks = max30102_scan_masks;
indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
indio_dev->setup_ops = &max30102_buffer_setup_ops;
indio_dev->dev.parent = &client->dev;
data = iio_priv(indio_dev);
data->indio_dev = indio_dev;
data->client = client;
mutex_init(&data->lock);
i2c_set_clientdata(client, indio_dev);
data->regmap = devm_regmap_init_i2c(client, &max30102_regmap_config);
if (IS_ERR(data->regmap)) {
dev_err(&client->dev, "regmap initialization failed.\n");
return PTR_ERR(data->regmap);
}
max30102_set_powermode(data, false);
ret = max30102_chip_init(data);
if (ret)
return ret;
if (client->irq <= 0) {
dev_err(&client->dev, "no valid irq defined\n");
return -EINVAL;
}
ret = devm_request_threaded_irq(&client->dev, client->irq,
NULL, max30102_interrupt_handler,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"max30102_irq", indio_dev);
if (ret) {
dev_err(&client->dev, "request irq (%d) failed\n", client->irq);
return ret;
}
return iio_device_register(indio_dev);
}
static int max30102_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct max30102_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
max30102_set_powermode(data, false);
return 0;
}
static const struct i2c_device_id max30102_id[] = {
{ "max30102", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, max30102_id);
static const struct of_device_id max30102_dt_ids[] = {
{ .compatible = "maxim,max30102" },
{ }
};
MODULE_DEVICE_TABLE(of, max30102_dt_ids);
static struct i2c_driver max30102_driver = {
.driver = {
.name = MAX30102_DRV_NAME,
.of_match_table = of_match_ptr(max30102_dt_ids),
},
.probe = max30102_probe,
.remove = max30102_remove,
.id_table = max30102_id,
};
module_i2c_driver(max30102_driver);
MODULE_AUTHOR("Matt Ranostay <matt@ranostay.consulting>");
MODULE_DESCRIPTION("MAX30102 heart rate and pulse oximeter sensor");
MODULE_LICENSE("GPL");
......@@ -8,7 +8,7 @@ config IIO_ST_LSM6DSX
select IIO_ST_LSM6DSX_SPI if (SPI_MASTER)
help
Say yes here to build support for STMicroelectronics LSM6DSx imu
sensor. Supported devices: lsm6ds3, lsm6dsm
sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm
To compile this driver as a module, choose M here: the module
will be called st_lsm6dsx.
......
......@@ -15,11 +15,16 @@
#include <linux/device.h>
#define ST_LSM6DS3_DEV_NAME "lsm6ds3"
#define ST_LSM6DS3H_DEV_NAME "lsm6ds3h"
#define ST_LSM6DSL_DEV_NAME "lsm6dsl"
#define ST_LSM6DSM_DEV_NAME "lsm6dsm"
enum st_lsm6dsx_hw_id {
ST_LSM6DS3_ID,
ST_LSM6DS3H_ID,
ST_LSM6DSL_ID,
ST_LSM6DSM_ID,
ST_LSM6DSX_MAX_ID,
};
#define ST_LSM6DSX_CHAN_SIZE 2
......@@ -50,7 +55,7 @@ struct st_lsm6dsx_reg {
struct st_lsm6dsx_settings {
u8 wai;
u16 max_fifo_size;
enum st_lsm6dsx_hw_id id;
enum st_lsm6dsx_hw_id id[ST_LSM6DSX_MAX_ID];
};
enum st_lsm6dsx_sensor_id {
......
/*
* 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 @@ int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark)
}
/**
* st_lsm6dsx_read_fifo() - LSM6DS3-LSM6DSM read FIFO routine
* st_lsm6dsx_read_fifo() - LSM6DS3-LSM6DS3H-LSM6DSL-LSM6DSM read FIFO routine
* @hw: Pointer to instance of struct st_lsm6dsx_hw.
*
* Read samples from the hw FIFO and push them to IIO buffers.
......
......@@ -17,7 +17,7 @@
* - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
* - FIFO size: 8KB
*
* - LSM6DSM:
* - LSM6DS3H/LSM6DSL/LSM6DSM:
* - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416
* - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
* - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
......@@ -74,12 +74,6 @@
#define ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR 0x24
#define ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR 0x26
#define ST_LSM6DS3_WHOAMI 0x69
#define ST_LSM6DSM_WHOAMI 0x6a
#define ST_LSM6DS3_MAX_FIFO_SIZE 8192
#define ST_LSM6DSM_MAX_FIFO_SIZE 4096
#define ST_LSM6DSX_ACC_FS_2G_GAIN IIO_G_TO_M_S_2(61)
#define ST_LSM6DSX_ACC_FS_4G_GAIN IIO_G_TO_M_S_2(122)
#define ST_LSM6DSX_ACC_FS_8G_GAIN IIO_G_TO_M_S_2(244)
......@@ -164,14 +158,26 @@ static const struct st_lsm6dsx_fs_table_entry st_lsm6dsx_fs_table[] = {
static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
{
.wai = ST_LSM6DS3_WHOAMI,
.max_fifo_size = ST_LSM6DS3_MAX_FIFO_SIZE,
.id = ST_LSM6DS3_ID,
.wai = 0x69,
.max_fifo_size = 8192,
.id = {
[0] = ST_LSM6DS3_ID,
},
},
{
.wai = ST_LSM6DSM_WHOAMI,
.max_fifo_size = ST_LSM6DSM_MAX_FIFO_SIZE,
.id = ST_LSM6DSM_ID,
.wai = 0x69,
.max_fifo_size = 4096,
.id = {
[0] = ST_LSM6DS3H_ID,
},
},
{
.wai = 0x6a,
.max_fifo_size = 4096,
.id = {
[0] = ST_LSM6DSL_ID,
[1] = ST_LSM6DSM_ID,
},
},
};
......@@ -241,11 +247,15 @@ int st_lsm6dsx_write_with_mask(struct st_lsm6dsx_hw *hw, u8 addr, u8 mask,
static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id)
{
int err, i;
int err, i, j;
u8 data;
for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) {
if (id == st_lsm6dsx_sensor_settings[i].id)
for (j = 0; j < ST_LSM6DSX_MAX_ID; j++) {
if (id == st_lsm6dsx_sensor_settings[i].id[j])
break;
}
if (j < ST_LSM6DSX_MAX_ID)
break;
}
......
......@@ -70,6 +70,14 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = {
.compatible = "st,lsm6ds3",
.data = (void *)ST_LSM6DS3_ID,
},
{
.compatible = "st,lsm6ds3h",
.data = (void *)ST_LSM6DS3H_ID,
},
{
.compatible = "st,lsm6dsl",
.data = (void *)ST_LSM6DSL_ID,
},
{
.compatible = "st,lsm6dsm",
.data = (void *)ST_LSM6DSM_ID,
......@@ -80,6 +88,8 @@ MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match);
static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = {
{ ST_LSM6DS3_DEV_NAME, ST_LSM6DS3_ID },
{ ST_LSM6DS3H_DEV_NAME, ST_LSM6DS3H_ID },
{ ST_LSM6DSL_DEV_NAME, ST_LSM6DSL_ID },
{ ST_LSM6DSM_DEV_NAME, ST_LSM6DSM_ID },
{},
};
......
......@@ -87,6 +87,14 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = {
.compatible = "st,lsm6ds3",
.data = (void *)ST_LSM6DS3_ID,
},
{
.compatible = "st,lsm6ds3h",
.data = (void *)ST_LSM6DS3H_ID,
},
{
.compatible = "st,lsm6dsl",
.data = (void *)ST_LSM6DSL_ID,
},
{
.compatible = "st,lsm6dsm",
.data = (void *)ST_LSM6DSM_ID,
......@@ -97,6 +105,8 @@ MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match);
static const struct spi_device_id st_lsm6dsx_spi_id_table[] = {
{ ST_LSM6DS3_DEV_NAME, ST_LSM6DS3_ID },
{ ST_LSM6DS3H_DEV_NAME, ST_LSM6DS3H_ID },
{ ST_LSM6DSL_DEV_NAME, ST_LSM6DSL_ID },
{ ST_LSM6DSM_DEV_NAME, ST_LSM6DSM_ID },
{},
};
......
......@@ -136,6 +136,16 @@ config CM36651
To compile this driver as a module, choose M here:
the module will be called cm36651.
config IIO_CROS_EC_LIGHT_PROX
tristate "ChromeOS EC Light and Proximity Sensors"
depends on IIO_CROS_EC_SENSORS_CORE
help
Say Y here if you use the light and proximity sensors
presented by the ChromeOS EC Sensor hub.
To compile this driver as a module, choose M here:
the module will be called cros_ec_light_prox.
config GP2AP020A00F
tristate "Sharp GP2AP020A00F Proximity/ALS sensor"
depends on I2C
......
......@@ -15,6 +15,7 @@ obj-$(CONFIG_CM3232) += cm3232.o
obj-$(CONFIG_CM3323) += cm3323.o
obj-$(CONFIG_CM3605) += cm3605.o
obj-$(CONFIG_CM36651) += cm36651.o
obj-$(CONFIG_IIO_CROS_EC_LIGHT_PROX) += cros_ec_light_prox.o
obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o
......
/*
* cros_ec_light_prox - Driver for light and prox sensors behing CrosEC.
*
* Copyright (C) 2017 Google, Inc
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/trigger.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/kernel.h>
#include <linux/mfd/cros_ec.h>
#include <linux/mfd/cros_ec_commands.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include "../common/cros_ec_sensors/cros_ec_sensors_core.h"
/*
* We only represent one entry for light or proximity. EC is merging different
* light sensors to return the what the eye would see. For proximity, we
* currently support only one light source.
*/
#define CROS_EC_LIGHT_PROX_MAX_CHANNELS (1 + 1)
/* State data for ec_sensors iio driver. */
struct cros_ec_light_prox_state {
/* Shared by all sensors */
struct cros_ec_sensors_core_state core;
struct iio_chan_spec channels[CROS_EC_LIGHT_PROX_MAX_CHANNELS];
};
static int cros_ec_light_prox_read(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct cros_ec_light_prox_state *st = iio_priv(indio_dev);
u16 data = 0;
s64 val64;
int ret = IIO_VAL_INT;
int idx = chan->scan_index;
mutex_lock(&st->core.cmd_lock);
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (chan->type == IIO_PROXIMITY) {
if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx,
(s16 *)&data) < 0) {
ret = -EIO;
break;
}
*val = data;
} else {
ret = -EINVAL;
}
break;
case IIO_CHAN_INFO_PROCESSED:
if (chan->type == IIO_LIGHT) {
if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx,
(s16 *)&data) < 0) {
ret = -EIO;
break;
}
/*
* The data coming from the light sensor is
* pre-processed and represents the ambient light
* illuminance reading expressed in lux.
*/
*val = data;
ret = IIO_VAL_INT;
} else {
ret = -EINVAL;
}
break;
case IIO_CHAN_INFO_CALIBBIAS:
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
st->core.param.sensor_offset.flags = 0;
if (cros_ec_motion_send_host_cmd(&st->core, 0)) {
ret = -EIO;
break;
}
/* Save values */
st->core.calib[0] = st->core.resp->sensor_offset.offset[0];
*val = st->core.calib[idx];
break;
case IIO_CHAN_INFO_CALIBSCALE:
/*
* RANGE is used for calibration
* scale is a number x.y, where x is coded on 16 bits,
* y coded on 16 bits, between 0 and 9999.
*/
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;
if (cros_ec_motion_send_host_cmd(&st->core, 0)) {
ret = -EIO;
break;
}
val64 = st->core.resp->sensor_range.ret;
*val = val64 >> 16;
*val2 = (val64 & 0xffff) * 100;
ret = IIO_VAL_INT_PLUS_MICRO;
break;
default:
ret = cros_ec_sensors_core_read(&st->core, chan, val, val2,
mask);
break;
}
mutex_unlock(&st->core.cmd_lock);
return ret;
}
static int cros_ec_light_prox_write(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct cros_ec_light_prox_state *st = iio_priv(indio_dev);
int ret = 0;
int idx = chan->scan_index;
mutex_lock(&st->core.cmd_lock);
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
st->core.calib[idx] = val;
/* Send to EC for each axis, even if not complete */
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
st->core.param.sensor_offset.flags = MOTION_SENSE_SET_OFFSET;
st->core.param.sensor_offset.offset[0] = st->core.calib[0];
st->core.param.sensor_offset.temp =
EC_MOTION_SENSE_INVALID_CALIB_TEMP;
if (cros_ec_motion_send_host_cmd(&st->core, 0))
ret = -EIO;
break;
case IIO_CHAN_INFO_CALIBSCALE:
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
st->core.param.sensor_range.data = (val << 16) | (val2 / 100);
if (cros_ec_motion_send_host_cmd(&st->core, 0))
ret = -EIO;
break;
default:
ret = cros_ec_sensors_core_write(&st->core, chan, val, val2,
mask);
break;
}
mutex_unlock(&st->core.cmd_lock);
return ret;
}
static const struct iio_info cros_ec_light_prox_info = {
.read_raw = &cros_ec_light_prox_read,
.write_raw = &cros_ec_light_prox_write,
.driver_module = THIS_MODULE,
};
static int cros_ec_light_prox_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
struct cros_ec_device *ec_device;
struct iio_dev *indio_dev;
struct cros_ec_light_prox_state *state;
struct iio_chan_spec *channel;
int ret;
if (!ec_dev || !ec_dev->ec_dev) {
dev_warn(dev, "No CROS EC device found.\n");
return -EINVAL;
}
ec_device = ec_dev->ec_dev;
indio_dev = devm_iio_device_alloc(dev, sizeof(*state));
if (!indio_dev)
return -ENOMEM;
ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
if (ret)
return ret;
indio_dev->info = &cros_ec_light_prox_info;
state = iio_priv(indio_dev);
state->core.type = state->core.resp->info.type;
state->core.loc = state->core.resp->info.location;
channel = state->channels;
/* Common part */
channel->info_mask_shared_by_all =
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_FREQUENCY);
channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
channel->scan_type.shift = 0;
channel->scan_index = 0;
channel->ext_info = cros_ec_sensors_ext_info;
channel->scan_type.sign = 'u';
state->core.calib[0] = 0;
/* Sensor specific */
switch (state->core.type) {
case MOTIONSENSE_TYPE_LIGHT:
channel->type = IIO_LIGHT;
channel->info_mask_separate =
BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_CALIBBIAS) |
BIT(IIO_CHAN_INFO_CALIBSCALE);
break;
case MOTIONSENSE_TYPE_PROX:
channel->type = IIO_PROXIMITY;
channel->info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_CALIBBIAS) |
BIT(IIO_CHAN_INFO_CALIBSCALE);
break;
default:
dev_warn(dev, "Unknown motion sensor\n");
return -EINVAL;
}
/* Timestamp */
channel++;
channel->type = IIO_TIMESTAMP;
channel->channel = -1;
channel->scan_index = 1;
channel->scan_type.sign = 's';
channel->scan_type.realbits = 64;
channel->scan_type.storagebits = 64;
indio_dev->channels = state->channels;
indio_dev->num_channels = CROS_EC_LIGHT_PROX_MAX_CHANNELS;
state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
cros_ec_sensors_capture, NULL);
if (ret)
return ret;
return devm_iio_device_register(dev, indio_dev);
}
static const struct platform_device_id cros_ec_light_prox_ids[] = {
{
.name = "cros-ec-prox",
},
{
.name = "cros-ec-light",
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, cros_ec_light_prox_ids);
static struct platform_driver cros_ec_light_prox_platform_driver = {
.driver = {
.name = "cros-ec-light-prox",
},
.probe = cros_ec_light_prox_probe,
.id_table = cros_ec_light_prox_ids,
};
module_platform_driver(cros_ec_light_prox_platform_driver);
MODULE_DESCRIPTION("ChromeOS EC light/proximity sensors driver");
MODULE_LICENSE("GPL v2");
......@@ -240,6 +240,13 @@ static int prox_parse_report(struct platform_device *pdev,
st->common_attributes.sensitivity.index,
st->common_attributes.sensitivity.report_id);
}
if (st->common_attributes.sensitivity.index < 0)
sensor_hub_input_get_attribute_info(hsdev,
HID_FEATURE_REPORT, usage_id,
HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS |
HID_USAGE_SENSOR_HUMAN_PRESENCE,
&st->common_attributes.sensitivity);
return ret;
}
......
......@@ -325,6 +325,7 @@ static int lmp91000_probe(struct i2c_client *client,
indio_dev->channels = lmp91000_channels;
indio_dev->num_channels = ARRAY_SIZE(lmp91000_channels);
indio_dev->name = LMP91000_DRV_NAME;
indio_dev->dev.parent = &client->dev;
indio_dev->modes = INDIO_DIRECT_MODE;
i2c_set_clientdata(client, indio_dev);
......
......@@ -32,6 +32,17 @@ config LIDAR_LITE_V2
To compile this driver as a module, choose M here: the
module will be called pulsedlight-lite-v2
config SRF04
tristate "Devantech SRF04 ultrasonic ranger sensor"
depends on GPIOLIB
help
Say Y here to build a driver for Devantech SRF04 ultrasonic
ranger sensor. This driver can be used to measure the distance
of objects. It is using two GPIOs.
To compile this driver as a module, choose M here: the
module will be called srf04.
config SX9500
tristate "SX9500 Semtech proximity sensor"
select IIO_BUFFER
......
......@@ -5,5 +5,6 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AS3935) += as3935.o
obj-$(CONFIG_LIDAR_LITE_V2) += pulsedlight-lidar-lite-v2.o
obj-$(CONFIG_SRF04) += srf04.o
obj-$(CONFIG_SRF08) += srf08.o
obj-$(CONFIG_SX9500) += sx9500.o
......@@ -278,6 +278,7 @@ static int lidar_probe(struct i2c_client *client,
indio_dev->name = LIDAR_DRV_NAME;
indio_dev->channels = lidar_channels;
indio_dev->num_channels = ARRAY_SIZE(lidar_channels);
indio_dev->dev.parent = &client->dev;
indio_dev->modes = INDIO_DIRECT_MODE;
i2c_set_clientdata(client, indio_dev);
......
/*
* SRF04: ultrasonic sensor for distance measuring by using GPIOs
*
* Copyright (c) 2017 Andreas Klinger <ak@it-klinger.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For details about the device see:
* http://www.robot-electronics.co.uk/htm/srf04tech.htm
*
* the measurement cycle as timing diagram looks like:
*
* +---+
* GPIO | |
* trig: --+ +------------------------------------------------------
* ^ ^
* |<->|
* udelay(10)
*
* ultra +-+ +-+ +-+
* sonic | | | | | |
* burst: ---------+ +-+ +-+ +-----------------------------------------
* .
* ultra . +-+ +-+ +-+
* sonic . | | | | | |
* echo: ----------------------------------+ +-+ +-+ +----------------
* . .
* +------------------------+
* GPIO | |
* echo: -------------------+ +---------------
* ^ ^
* interrupt interrupt
* (ts_rising) (ts_falling)
* |<---------------------->|
* pulse time measured
* --> one round trip of ultra sonic waves
*/
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
struct srf04_data {
struct device *dev;
struct gpio_desc *gpiod_trig;
struct gpio_desc *gpiod_echo;
struct mutex lock;
int irqnr;
ktime_t ts_rising;
ktime_t ts_falling;
struct completion rising;
struct completion falling;
};
static irqreturn_t srf04_handle_irq(int irq, void *dev_id)
{
struct iio_dev *indio_dev = dev_id;
struct srf04_data *data = iio_priv(indio_dev);
ktime_t now = ktime_get();
if (gpiod_get_value(data->gpiod_echo)) {
data->ts_rising = now;
complete(&data->rising);
} else {
data->ts_falling = now;
complete(&data->falling);
}
return IRQ_HANDLED;
}
static int srf04_read(struct srf04_data *data)
{
int ret;
ktime_t ktime_dt;
u64 dt_ns;
u32 time_ns, distance_mm;
/*
* just one read-echo-cycle can take place at a time
* ==> lock against concurrent reading calls
*/
mutex_lock(&data->lock);
reinit_completion(&data->rising);
reinit_completion(&data->falling);
gpiod_set_value(data->gpiod_trig, 1);
udelay(10);
gpiod_set_value(data->gpiod_trig, 0);
/* it cannot take more than 20 ms */
ret = wait_for_completion_killable_timeout(&data->rising, HZ/50);
if (ret < 0) {
mutex_unlock(&data->lock);
return ret;
} else if (ret == 0) {
mutex_unlock(&data->lock);
return -ETIMEDOUT;
}
ret = wait_for_completion_killable_timeout(&data->falling, HZ/50);
if (ret < 0) {
mutex_unlock(&data->lock);
return ret;
} else if (ret == 0) {
mutex_unlock(&data->lock);
return -ETIMEDOUT;
}
ktime_dt = ktime_sub(data->ts_falling, data->ts_rising);
mutex_unlock(&data->lock);
dt_ns = ktime_to_ns(ktime_dt);
/*
* measuring more than 3 meters is beyond the capabilities of
* the sensor
* ==> filter out invalid results for not measuring echos of
* another us sensor
*
* formula:
* distance 3 m
* time = ---------- = --------- = 9404389 ns
* speed 319 m/s
*
* using a minimum speed at -20 °C of 319 m/s
*/
if (dt_ns > 9404389)
return -EIO;
time_ns = dt_ns;
/*
* the speed as function of the temperature is approximately:
*
* speed = 331,5 + 0,6 * Temp
* with Temp in °C
* and speed in m/s
*
* use 343 m/s as ultrasonic speed at 20 °C here in absence of the
* temperature
*
* therefore:
* time 343
* distance = ------ * -----
* 10^6 2
* with time in ns
* and distance in mm (one way)
*
* because we limit to 3 meters the multiplication with 343 just
* fits into 32 bit
*/
distance_mm = time_ns * 343 / 2000000;
return distance_mm;
}
static int srf04_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *channel, int *val,
int *val2, long info)
{
struct srf04_data *data = iio_priv(indio_dev);
int ret;
if (channel->type != IIO_DISTANCE)
return -EINVAL;
switch (info) {
case IIO_CHAN_INFO_RAW:
ret = srf04_read(data);
if (ret < 0)
return ret;
*val = ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
/*
* theoretical maximum resolution is 3 mm
* 1 LSB is 1 mm
*/
*val = 0;
*val2 = 1000;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
}
static const struct iio_info srf04_iio_info = {
.driver_module = THIS_MODULE,
.read_raw = srf04_read_raw,
};
static const struct iio_chan_spec srf04_chan_spec[] = {
{
.type = IIO_DISTANCE,
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
},
};
static int srf04_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct srf04_data *data;
struct iio_dev *indio_dev;
int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(struct srf04_data));
if (!indio_dev) {
dev_err(dev, "failed to allocate IIO device\n");
return -ENOMEM;
}
data = iio_priv(indio_dev);
data->dev = dev;
mutex_init(&data->lock);
init_completion(&data->rising);
init_completion(&data->falling);
data->gpiod_trig = devm_gpiod_get(dev, "trig", GPIOD_OUT_LOW);
if (IS_ERR(data->gpiod_trig)) {
dev_err(dev, "failed to get trig-gpios: err=%ld\n",
PTR_ERR(data->gpiod_trig));
return PTR_ERR(data->gpiod_trig);
}
data->gpiod_echo = devm_gpiod_get(dev, "echo", GPIOD_IN);
if (IS_ERR(data->gpiod_echo)) {
dev_err(dev, "failed to get echo-gpios: err=%ld\n",
PTR_ERR(data->gpiod_echo));
return PTR_ERR(data->gpiod_echo);
}
if (gpiod_cansleep(data->gpiod_echo)) {
dev_err(data->dev, "cansleep-GPIOs not supported\n");
return -ENODEV;
}
data->irqnr = gpiod_to_irq(data->gpiod_echo);
if (data->irqnr < 0) {
dev_err(data->dev, "gpiod_to_irq: %d\n", data->irqnr);
return data->irqnr;
}
ret = devm_request_irq(dev, data->irqnr, srf04_handle_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
pdev->name, indio_dev);
if (ret < 0) {
dev_err(data->dev, "request_irq: %d\n", ret);
return ret;
}
platform_set_drvdata(pdev, indio_dev);
indio_dev->name = "srf04";
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &srf04_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = srf04_chan_spec;
indio_dev->num_channels = ARRAY_SIZE(srf04_chan_spec);
return devm_iio_device_register(dev, indio_dev);
}
static const struct of_device_id of_srf04_match[] = {
{ .compatible = "devantech,srf04", },
{},
};
MODULE_DEVICE_TABLE(of, of_srf04_match);
static struct platform_driver srf04_driver = {
.probe = srf04_probe,
.driver = {
.name = "srf04-gpio",
.of_match_table = of_srf04_match,
},
};
module_platform_driver(srf04_driver);
MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
MODULE_DESCRIPTION("SRF04 ultrasonic sensor for distance measuring using GPIOs");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:srf04");
......@@ -19,6 +19,20 @@ config MAXIM_THERMOCOUPLE
This driver can also be built as a module. If so, the module will
be called maxim_thermocouple.
config HID_SENSOR_TEMP
tristate "HID Environmental temperature sensor"
depends on HID_SENSOR_HUB
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select HID_SENSOR_IIO_COMMON
select HID_SENSOR_IIO_TRIGGER
help
Say yes here to build support for the HID SENSOR
temperature driver
To compile this driver as a module, choose M here: the module
will be called hid-sensor-temperature.
config MLX90614
tristate "MLX90614 contact-less infrared sensor"
depends on I2C
......
......@@ -2,6 +2,7 @@
# Makefile for industrial I/O temperature drivers
#
obj-$(CONFIG_HID_SENSOR_TEMP) += hid-sensor-temperature.o
obj-$(CONFIG_MAXIM_THERMOCOUPLE) += maxim_thermocouple.o
obj-$(CONFIG_MLX90614) += mlx90614.o
obj-$(CONFIG_TMP006) += tmp006.o
......
/*
* HID Sensors Driver
* Copyright (c) 2017, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program.
*/
#include <linux/device.h>
#include <linux/hid-sensor-hub.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
struct temperature_state {
struct hid_sensor_common common_attributes;
struct hid_sensor_hub_attribute_info temperature_attr;
s32 temperature_data;
int scale_pre_decml;
int scale_post_decml;
int scale_precision;
int value_offset;
};
/* Channel definitions */
static const struct iio_chan_spec temperature_channels[] = {
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_HYSTERESIS),
},
IIO_CHAN_SOFT_TIMESTAMP(3),
};
/* Adjust channel real bits based on report descriptor */
static void temperature_adjust_channel_bit_mask(struct iio_chan_spec *channels,
int channel, int size)
{
channels[channel].scan_type.sign = 's';
/* Real storage bits will change based on the report desc. */
channels[channel].scan_type.realbits = size * 8;
/* Maximum size of a sample to capture is s32 */
channels[channel].scan_type.storagebits = sizeof(s32) * 8;
}
static int temperature_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct temperature_state *temp_st = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (chan->type != IIO_TEMP)
return -EINVAL;
hid_sensor_power_state(
&temp_st->common_attributes, true);
*val = sensor_hub_input_attr_get_raw_value(
temp_st->common_attributes.hsdev,
HID_USAGE_SENSOR_TEMPERATURE,
HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
temp_st->temperature_attr.report_id,
SENSOR_HUB_SYNC);
hid_sensor_power_state(
&temp_st->common_attributes,
false);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = temp_st->scale_pre_decml;
*val2 = temp_st->scale_post_decml;
return temp_st->scale_precision;
case IIO_CHAN_INFO_OFFSET:
*val = temp_st->value_offset;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SAMP_FREQ:
return hid_sensor_read_samp_freq_value(
&temp_st->common_attributes, val, val2);
case IIO_CHAN_INFO_HYSTERESIS:
return hid_sensor_read_raw_hyst_value(
&temp_st->common_attributes, val, val2);
default:
return -EINVAL;
}
}
static int temperature_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct temperature_state *temp_st = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
return hid_sensor_write_samp_freq_value(
&temp_st->common_attributes, val, val2);
case IIO_CHAN_INFO_HYSTERESIS:
return hid_sensor_write_raw_hyst_value(
&temp_st->common_attributes, val, val2);
default:
return -EINVAL;
}
}
static const struct iio_info temperature_info = {
.driver_module = THIS_MODULE,
.read_raw = &temperature_read_raw,
.write_raw = &temperature_write_raw,
};
/* Callback handler to send event after all samples are received and captured */
static int temperature_proc_event(struct hid_sensor_hub_device *hsdev,
unsigned int usage_id, void *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct temperature_state *temp_st = iio_priv(indio_dev);
if (atomic_read(&temp_st->common_attributes.data_ready))
iio_push_to_buffers_with_timestamp(indio_dev,
&temp_st->temperature_data,
iio_get_time_ns(indio_dev));
return 0;
}
/* Capture samples in local storage */
static int temperature_capture_sample(struct hid_sensor_hub_device *hsdev,
unsigned int usage_id, size_t raw_len,
char *raw_data, void *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct temperature_state *temp_st = iio_priv(indio_dev);
switch (usage_id) {
case HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE:
temp_st->temperature_data = *(s32 *)raw_data;
return 0;
default:
return -EINVAL;
}
}
/* Parse report which is specific to an usage id*/
static int temperature_parse_report(struct platform_device *pdev,
struct hid_sensor_hub_device *hsdev,
struct iio_chan_spec *channels,
unsigned int usage_id,
struct temperature_state *st)
{
int ret;
ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT,
usage_id,
HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
&st->temperature_attr);
if (ret < 0)
return ret;
temperature_adjust_channel_bit_mask(channels, 0,
st->temperature_attr.size);
st->scale_precision = hid_sensor_format_scale(
HID_USAGE_SENSOR_TEMPERATURE,
&st->temperature_attr,
&st->scale_pre_decml, &st->scale_post_decml);
/* Set Sensitivity field ids, when there is no individual modifier */
if (st->common_attributes.sensitivity.index < 0)
sensor_hub_input_get_attribute_info(hsdev,
HID_FEATURE_REPORT, usage_id,
HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS |
HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
&st->common_attributes.sensitivity);
return ret;
}
static struct hid_sensor_hub_callbacks temperature_callbacks = {
.send_event = &temperature_proc_event,
.capture_sample = &temperature_capture_sample,
};
/* Function to initialize the processing for usage id */
static int hid_temperature_probe(struct platform_device *pdev)
{
static const char *name = "temperature";
struct iio_dev *indio_dev;
struct temperature_state *temp_st;
struct iio_chan_spec *temp_chans;
struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*temp_st));
if (!indio_dev)
return -ENOMEM;
temp_st = iio_priv(indio_dev);
temp_st->common_attributes.hsdev = hsdev;
temp_st->common_attributes.pdev = pdev;
ret = hid_sensor_parse_common_attributes(hsdev,
HID_USAGE_SENSOR_TEMPERATURE,
&temp_st->common_attributes);
if (ret)
return ret;
temp_chans = devm_kmemdup(&indio_dev->dev, temperature_channels,
sizeof(temperature_channels), GFP_KERNEL);
if (!temp_chans)
return -ENOMEM;
ret = temperature_parse_report(pdev, hsdev, temp_chans,
HID_USAGE_SENSOR_TEMPERATURE, temp_st);
if (ret)
return ret;
indio_dev->channels = temp_chans;
indio_dev->num_channels = ARRAY_SIZE(temperature_channels);
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &temperature_info;
indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE;
ret = devm_iio_triggered_buffer_setup(&pdev->dev, indio_dev,
&iio_pollfunc_store_time, NULL, NULL);
if (ret)
return ret;
atomic_set(&temp_st->common_attributes.data_ready, 0);
ret = hid_sensor_setup_trigger(indio_dev, name,
&temp_st->common_attributes);
if (ret)
return ret;
platform_set_drvdata(pdev, indio_dev);
temperature_callbacks.pdev = pdev;
ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE,
&temperature_callbacks);
if (ret)
goto error_remove_trigger;
ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
if (ret)
goto error_remove_callback;
return ret;
error_remove_callback:
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE);
error_remove_trigger:
hid_sensor_remove_trigger(&temp_st->common_attributes);
return ret;
}
/* Function to deinitialize the processing for usage id */
static int hid_temperature_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct temperature_state *temp_st = iio_priv(indio_dev);
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE);
hid_sensor_remove_trigger(&temp_st->common_attributes);
return 0;
}
static const struct platform_device_id hid_temperature_ids[] = {
{
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-200033",
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, hid_temperature_ids);
static struct platform_driver hid_temperature_platform_driver = {
.id_table = hid_temperature_ids,
.driver = {
.name = "temperature-sensor",
.pm = &hid_sensor_pm_ops,
},
.probe = hid_temperature_probe,
.remove = hid_temperature_remove,
};
module_platform_driver(hid_temperature_platform_driver);
MODULE_DESCRIPTION("HID Environmental temperature sensor");
MODULE_AUTHOR("Song Hongyan <hongyan.song@intel.com>");
MODULE_LICENSE("GPL v2");
......@@ -231,6 +231,7 @@ static int maxim_thermocouple_probe(struct spi_device *spi)
indio_dev->available_scan_masks = chip->scan_masks;
indio_dev->num_channels = chip->num_channels;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->dev.parent = &spi->dev;
data = iio_priv(indio_dev);
data->spi = spi;
......
......@@ -11,9 +11,10 @@
*
* (7-bit I2C slave address (0x40 - 0x47), changeable via ADR pins)
*
* Note: This driver assumes that the sensor has been calibrated beforehand
*
* TODO: ALERT irq, limit threshold events
* Note:
* 1. This driver assumes that the sensor has been calibrated beforehand
* 2. Limit threshold events are enabled at the start
* 3. Operating mode: INT
*
*/
......@@ -24,25 +25,38 @@
#include <linux/pm.h>
#include <linux/bitops.h>
#include <linux/of.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#define TMP007_TDIE 0x01
#define TMP007_CONFIG 0x02
#define TMP007_TOBJECT 0x03
#define TMP007_STATUS 0x04
#define TMP007_STATUS_MASK 0x05
#define TMP007_TOBJ_HIGH_LIMIT 0x06
#define TMP007_TOBJ_LOW_LIMIT 0x07
#define TMP007_TDIE_HIGH_LIMIT 0x08
#define TMP007_TDIE_LOW_LIMIT 0x09
#define TMP007_MANUFACTURER_ID 0x1e
#define TMP007_DEVICE_ID 0x1f
#define TMP007_CONFIG_CONV_EN BIT(12)
#define TMP007_CONFIG_COMP_EN BIT(5)
#define TMP007_CONFIG_TC_EN BIT(6)
#define TMP007_CONFIG_CR_MASK GENMASK(11, 9)
#define TMP007_CONFIG_ALERT_EN BIT(8)
#define TMP007_CONFIG_CR_SHIFT 9
/* Status register flags */
#define TMP007_STATUS_ALERT BIT(15)
#define TMP007_STATUS_CONV_READY BIT(14)
#define TMP007_STATUS_OHF BIT(13)
#define TMP007_STATUS_OLF BIT(12)
#define TMP007_STATUS_LHF BIT(11)
#define TMP007_STATUS_LLF BIT(10)
#define TMP007_STATUS_DATA_VALID BIT(9)
#define TMP007_MANUFACTURER_MAGIC 0x5449
......@@ -52,7 +66,9 @@
struct tmp007_data {
struct i2c_client *client;
struct mutex lock;
u16 config;
u16 status_mask;
};
static const int tmp007_avgs[5][2] = { {4, 0}, {2, 0}, {1, 0},
......@@ -156,6 +172,188 @@ static int tmp007_write_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
static irqreturn_t tmp007_interrupt_handler(int irq, void *private)
{
struct iio_dev *indio_dev = private;
struct tmp007_data *data = iio_priv(indio_dev);
int ret;
ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS);
if ((ret < 0) || !(ret & (TMP007_STATUS_OHF | TMP007_STATUS_OLF |
TMP007_STATUS_LHF | TMP007_STATUS_LLF)))
return IRQ_NONE;
if (ret & TMP007_STATUS_OHF)
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
IIO_MOD_TEMP_OBJECT,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
iio_get_time_ns(indio_dev));
if (ret & TMP007_STATUS_OLF)
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
IIO_MOD_TEMP_OBJECT,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
iio_get_time_ns(indio_dev));
if (ret & TMP007_STATUS_LHF)
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
IIO_MOD_TEMP_AMBIENT,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
iio_get_time_ns(indio_dev));
if (ret & TMP007_STATUS_LLF)
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
IIO_MOD_TEMP_AMBIENT,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
iio_get_time_ns(indio_dev));
return IRQ_HANDLED;
}
static int tmp007_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, int state)
{
struct tmp007_data *data = iio_priv(indio_dev);
unsigned int status_mask;
int ret;
switch (chan->channel2) {
case IIO_MOD_TEMP_AMBIENT:
if (dir == IIO_EV_DIR_RISING)
status_mask = TMP007_STATUS_LHF;
else
status_mask = TMP007_STATUS_LLF;
break;
case IIO_MOD_TEMP_OBJECT:
if (dir == IIO_EV_DIR_RISING)
status_mask = TMP007_STATUS_OHF;
else
status_mask = TMP007_STATUS_OLF;
break;
default:
return -EINVAL;
}
mutex_lock(&data->lock);
ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
mutex_unlock(&data->lock);
if (ret < 0)
return ret;
if (state)
ret |= status_mask;
else
ret &= ~status_mask;
return i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK,
data->status_mask = ret);
}
static int tmp007_read_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir)
{
struct tmp007_data *data = iio_priv(indio_dev);
unsigned int mask;
switch (chan->channel2) {
case IIO_MOD_TEMP_AMBIENT:
if (dir == IIO_EV_DIR_RISING)
mask = TMP007_STATUS_LHF;
else
mask = TMP007_STATUS_LLF;
break;
case IIO_MOD_TEMP_OBJECT:
if (dir == IIO_EV_DIR_RISING)
mask = TMP007_STATUS_OHF;
else
mask = TMP007_STATUS_OLF;
break;
default:
return -EINVAL;
}
return !!(data->status_mask & mask);
}
static int tmp007_read_thresh(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, enum iio_event_info info,
int *val, int *val2)
{
struct tmp007_data *data = iio_priv(indio_dev);
int ret;
u8 reg;
switch (chan->channel2) {
case IIO_MOD_TEMP_AMBIENT: /* LSB: 0.5 degree Celsius */
if (dir == IIO_EV_DIR_RISING)
reg = TMP007_TDIE_HIGH_LIMIT;
else
reg = TMP007_TDIE_LOW_LIMIT;
break;
case IIO_MOD_TEMP_OBJECT:
if (dir == IIO_EV_DIR_RISING)
reg = TMP007_TOBJ_HIGH_LIMIT;
else
reg = TMP007_TOBJ_LOW_LIMIT;
break;
default:
return -EINVAL;
}
ret = i2c_smbus_read_word_swapped(data->client, reg);
if (ret < 0)
return ret;
/* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */
*val = sign_extend32(ret, 15) >> 7;
return IIO_VAL_INT;
}
static int tmp007_write_thresh(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, enum iio_event_info info,
int val, int val2)
{
struct tmp007_data *data = iio_priv(indio_dev);
u8 reg;
switch (chan->channel2) {
case IIO_MOD_TEMP_AMBIENT:
if (dir == IIO_EV_DIR_RISING)
reg = TMP007_TDIE_HIGH_LIMIT;
else
reg = TMP007_TDIE_LOW_LIMIT;
break;
case IIO_MOD_TEMP_OBJECT:
if (dir == IIO_EV_DIR_RISING)
reg = TMP007_TOBJ_HIGH_LIMIT;
else
reg = TMP007_TOBJ_LOW_LIMIT;
break;
default:
return -EINVAL;
}
/* Full scale threshold value is +/- 256 degree Celsius */
if (val < -256 || val > 255)
return -EINVAL;
/* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */
return i2c_smbus_write_word_swapped(data->client, reg, (val << 7));
}
static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25");
static struct attribute *tmp007_attributes[] = {
......@@ -167,6 +365,36 @@ static const struct attribute_group tmp007_attribute_group = {
.attrs = tmp007_attributes,
};
static const struct iio_event_spec tmp007_obj_event[] = {
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
};
static const struct iio_event_spec tmp007_die_event[] = {
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
};
static const struct iio_chan_spec tmp007_channels[] = {
{
.type = IIO_TEMP,
......@@ -175,6 +403,8 @@ static const struct iio_chan_spec tmp007_channels[] = {
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
.event_spec = tmp007_die_event,
.num_event_specs = ARRAY_SIZE(tmp007_die_event),
},
{
.type = IIO_TEMP,
......@@ -183,12 +413,18 @@ static const struct iio_chan_spec tmp007_channels[] = {
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
.event_spec = tmp007_obj_event,
.num_event_specs = ARRAY_SIZE(tmp007_obj_event),
}
};
static const struct iio_info tmp007_info = {
.read_raw = tmp007_read_raw,
.write_raw = tmp007_write_raw,
.read_event_config = tmp007_read_event_config,
.write_event_config = tmp007_write_event_config,
.read_event_value = tmp007_read_thresh,
.write_event_value = tmp007_write_thresh,
.attrs = &tmp007_attribute_group,
.driver_module = THIS_MODULE,
};
......@@ -214,7 +450,6 @@ static int tmp007_probe(struct i2c_client *client,
struct tmp007_data *data;
struct iio_dev *indio_dev;
int ret;
u16 status;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
return -EOPNOTSUPP;
......@@ -231,6 +466,7 @@ static int tmp007_probe(struct i2c_client *client,
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev;
indio_dev->name = "tmp007";
......@@ -243,7 +479,7 @@ static int tmp007_probe(struct i2c_client *client,
/*
* Set Configuration register:
* 1. Conversion ON
* 2. Comparator mode
* 2. ALERT enable
* 3. Transient correction enable
*/
......@@ -252,7 +488,7 @@ static int tmp007_probe(struct i2c_client *client,
return ret;
data->config = ret;
data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_COMP_EN | TMP007_CONFIG_TC_EN);
data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_ALERT_EN | TMP007_CONFIG_TC_EN);
ret = i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
data->config);
......@@ -260,22 +496,39 @@ static int tmp007_probe(struct i2c_client *client,
return ret;
/*
* Only the following flags can activate ALERT pin. Data conversion/validity flags
* flags can still be polled for getting temperature data
*
* Set Status Mask register:
* 1. Conversion ready enable
* 2. Data valid enable
* 1. Object temperature high limit enable
* 2. Object temperature low limit enable
* 3. TDIE temperature high limit enable
* 4. TDIE temperature low limit enable
*/
ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
if (ret < 0)
goto error_powerdown;
status = ret;
status |= (TMP007_STATUS_CONV_READY | TMP007_STATUS_DATA_VALID);
data->status_mask = ret;
data->status_mask |= (TMP007_STATUS_OHF | TMP007_STATUS_OLF
| TMP007_STATUS_LHF | TMP007_STATUS_LLF);
ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK, status);
ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK, data->status_mask);
if (ret < 0)
goto error_powerdown;
if (client->irq) {
ret = devm_request_threaded_irq(&client->dev, client->irq,
NULL, tmp007_interrupt_handler,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
tmp007_id->name, indio_dev);
if (ret) {
dev_err(&client->dev, "irq request error %d\n", -ret);
goto error_powerdown;
}
}
return iio_device_register(indio_dev);
error_powerdown:
......
......@@ -2,14 +2,7 @@
# Makefile for industrial I/O accelerometer drivers
#
adis16201-y := adis16201_core.o
obj-$(CONFIG_ADIS16201) += adis16201.o
adis16203-y := adis16203_core.o
obj-$(CONFIG_ADIS16203) += adis16203.o
adis16209-y := adis16209_core.o
obj-$(CONFIG_ADIS16209) += adis16209.o
adis16240-y := adis16240_core.o
obj-$(CONFIG_ADIS16240) += adis16240.o
......@@ -20,7 +20,145 @@
#include <linux/iio/buffer.h>
#include <linux/iio/imu/adis.h>
#include "adis16201.h"
#define ADIS16201_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16201_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16201_SUPPLY_OUT 0x02
/* Output, x-axis accelerometer */
#define ADIS16201_XACCL_OUT 0x04
/* Output, y-axis accelerometer */
#define ADIS16201_YACCL_OUT 0x06
/* Output, auxiliary ADC input */
#define ADIS16201_AUX_ADC 0x08
/* Output, temperature */
#define ADIS16201_TEMP_OUT 0x0A
/* Output, x-axis inclination */
#define ADIS16201_XINCL_OUT 0x0C
/* Output, y-axis inclination */
#define ADIS16201_YINCL_OUT 0x0E
/* Calibration, x-axis acceleration offset */
#define ADIS16201_XACCL_OFFS 0x10
/* Calibration, y-axis acceleration offset */
#define ADIS16201_YACCL_OFFS 0x12
/* x-axis acceleration scale factor */
#define ADIS16201_XACCL_SCALE 0x14
/* y-axis acceleration scale factor */
#define ADIS16201_YACCL_SCALE 0x16
/* Calibration, x-axis inclination offset */
#define ADIS16201_XINCL_OFFS 0x18
/* Calibration, y-axis inclination offset */
#define ADIS16201_YINCL_OFFS 0x1A
/* x-axis inclination scale factor */
#define ADIS16201_XINCL_SCALE 0x1C
/* y-axis inclination scale factor */
#define ADIS16201_YINCL_SCALE 0x1E
/* Alarm 1 amplitude threshold */
#define ADIS16201_ALM_MAG1 0x20
/* Alarm 2 amplitude threshold */
#define ADIS16201_ALM_MAG2 0x22
/* Alarm 1, sample period */
#define ADIS16201_ALM_SMPL1 0x24
/* Alarm 2, sample period */
#define ADIS16201_ALM_SMPL2 0x26
/* Alarm control */
#define ADIS16201_ALM_CTRL 0x28
/* Auxiliary DAC data */
#define ADIS16201_AUX_DAC 0x30
/* General-purpose digital input/output control */
#define ADIS16201_GPIO_CTRL 0x32
/* Miscellaneous control */
#define ADIS16201_MSC_CTRL 0x34
/* Internal sample period (rate) control */
#define ADIS16201_SMPL_PRD 0x36
/* Operation, filter configuration */
#define ADIS16201_AVG_CNT 0x38
/* Operation, sleep mode control */
#define ADIS16201_SLP_CNT 0x3A
/* Diagnostics, system status register */
#define ADIS16201_DIAG_STAT 0x3C
/* Operation, system command register */
#define ADIS16201_GLOB_CMD 0x3E
/* MSC_CTRL */
/* Self-test enable */
#define ADIS16201_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16201_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16201_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO1, 0 = DIO0 */
#define ADIS16201_MSC_CTRL_DATA_RDY_DIO1 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16201_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16201_DIAG_STAT_ALARM1 BIT(8)
/* SPI communications failure */
#define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16201_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16201_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16201_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16201_GLOB_CMD_FACTORY_CAL BIT(1)
#define ADIS16201_ERROR_ACTIVE BIT(14)
enum adis16201_scan {
ADIS16201_SCAN_ACC_X,
ADIS16201_SCAN_ACC_Y,
ADIS16201_SCAN_INCLI_X,
ADIS16201_SCAN_INCLI_Y,
ADIS16201_SCAN_SUPPLY,
ADIS16201_SCAN_AUX_ADC,
ADIS16201_SCAN_TEMP,
};
static const u8 adis16201_addresses[] = {
[ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS,
......
#ifndef SPI_ADIS16201_H_
#define SPI_ADIS16201_H_
#define ADIS16201_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16201_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16201_SUPPLY_OUT 0x02
/* Output, x-axis accelerometer */
#define ADIS16201_XACCL_OUT 0x04
/* Output, y-axis accelerometer */
#define ADIS16201_YACCL_OUT 0x06
/* Output, auxiliary ADC input */
#define ADIS16201_AUX_ADC 0x08
/* Output, temperature */
#define ADIS16201_TEMP_OUT 0x0A
/* Output, x-axis inclination */
#define ADIS16201_XINCL_OUT 0x0C
/* Output, y-axis inclination */
#define ADIS16201_YINCL_OUT 0x0E
/* Calibration, x-axis acceleration offset */
#define ADIS16201_XACCL_OFFS 0x10
/* Calibration, y-axis acceleration offset */
#define ADIS16201_YACCL_OFFS 0x12
/* x-axis acceleration scale factor */
#define ADIS16201_XACCL_SCALE 0x14
/* y-axis acceleration scale factor */
#define ADIS16201_YACCL_SCALE 0x16
/* Calibration, x-axis inclination offset */
#define ADIS16201_XINCL_OFFS 0x18
/* Calibration, y-axis inclination offset */
#define ADIS16201_YINCL_OFFS 0x1A
/* x-axis inclination scale factor */
#define ADIS16201_XINCL_SCALE 0x1C
/* y-axis inclination scale factor */
#define ADIS16201_YINCL_SCALE 0x1E
/* Alarm 1 amplitude threshold */
#define ADIS16201_ALM_MAG1 0x20
/* Alarm 2 amplitude threshold */
#define ADIS16201_ALM_MAG2 0x22
/* Alarm 1, sample period */
#define ADIS16201_ALM_SMPL1 0x24
/* Alarm 2, sample period */
#define ADIS16201_ALM_SMPL2 0x26
/* Alarm control */
#define ADIS16201_ALM_CTRL 0x28
/* Auxiliary DAC data */
#define ADIS16201_AUX_DAC 0x30
/* General-purpose digital input/output control */
#define ADIS16201_GPIO_CTRL 0x32
/* Miscellaneous control */
#define ADIS16201_MSC_CTRL 0x34
/* Internal sample period (rate) control */
#define ADIS16201_SMPL_PRD 0x36
/* Operation, filter configuration */
#define ADIS16201_AVG_CNT 0x38
/* Operation, sleep mode control */
#define ADIS16201_SLP_CNT 0x3A
/* Diagnostics, system status register */
#define ADIS16201_DIAG_STAT 0x3C
/* Operation, system command register */
#define ADIS16201_GLOB_CMD 0x3E
/* MSC_CTRL */
/* Self-test enable */
#define ADIS16201_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16201_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16201_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO1, 0 = DIO0 */
#define ADIS16201_MSC_CTRL_DATA_RDY_DIO1 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16201_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16201_DIAG_STAT_ALARM1 BIT(8)
/* SPI communications failure */
#define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16201_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16201_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16201_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16201_GLOB_CMD_FACTORY_CAL BIT(1)
#define ADIS16201_ERROR_ACTIVE BIT(14)
enum adis16201_scan {
ADIS16201_SCAN_ACC_X,
ADIS16201_SCAN_ACC_Y,
ADIS16201_SCAN_INCLI_X,
ADIS16201_SCAN_INCLI_Y,
ADIS16201_SCAN_SUPPLY,
ADIS16201_SCAN_AUX_ADC,
ADIS16201_SCAN_TEMP,
};
#endif /* SPI_ADIS16201_H_ */
......@@ -7,20 +7,140 @@
*/
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/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"
......
#ifndef SPI_ADIS16203_H_
#define SPI_ADIS16203_H_
#define ADIS16203_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16203_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16203_SUPPLY_OUT 0x02
/* Output, auxiliary ADC input */
#define ADIS16203_AUX_ADC 0x08
/* Output, temperature */
#define ADIS16203_TEMP_OUT 0x0A
/* Output, x-axis inclination */
#define ADIS16203_XINCL_OUT 0x0C
/* Output, y-axis inclination */
#define ADIS16203_YINCL_OUT 0x0E
/* Incline null calibration */
#define ADIS16203_INCL_NULL 0x18
/* Alarm 1 amplitude threshold */
#define ADIS16203_ALM_MAG1 0x20
/* Alarm 2 amplitude threshold */
#define ADIS16203_ALM_MAG2 0x22
/* Alarm 1, sample period */
#define ADIS16203_ALM_SMPL1 0x24
/* Alarm 2, sample period */
#define ADIS16203_ALM_SMPL2 0x26
/* Alarm control */
#define ADIS16203_ALM_CTRL 0x28
/* Auxiliary DAC data */
#define ADIS16203_AUX_DAC 0x30
/* General-purpose digital input/output control */
#define ADIS16203_GPIO_CTRL 0x32
/* Miscellaneous control */
#define ADIS16203_MSC_CTRL 0x34
/* Internal sample period (rate) control */
#define ADIS16203_SMPL_PRD 0x36
/* Operation, filter configuration */
#define ADIS16203_AVG_CNT 0x38
/* Operation, sleep mode control */
#define ADIS16203_SLP_CNT 0x3A
/* Diagnostics, system status register */
#define ADIS16203_DIAG_STAT 0x3C
/* Operation, system command register */
#define ADIS16203_GLOB_CMD 0x3E
/* MSC_CTRL */
/* Self-test at power-on: 1 = disabled, 0 = enabled */
#define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST BIT(10)
/* Reverses rotation of both inclination outputs */
#define ADIS16203_MSC_CTRL_REVERSE_ROT_EN BIT(9)
/* Self-test enable */
#define ADIS16203_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16203_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16203_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO1, 0 = DIO0 */
#define ADIS16203_MSC_CTRL_DATA_RDY_DIO1 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16203_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16203_DIAG_STAT_ALARM1 BIT(8)
/* Self-test diagnostic error flag */
#define ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT 5
/* SPI communications failure */
#define ADIS16203_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16203_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16203_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16203_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16203_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16203_GLOB_CMD_CLEAR_STAT BIT(4)
#define ADIS16203_GLOB_CMD_FACTORY_CAL BIT(1)
#define ADIS16203_ERROR_ACTIVE BIT(14)
enum adis16203_scan {
ADIS16203_SCAN_INCLI_X,
ADIS16203_SCAN_INCLI_Y,
ADIS16203_SCAN_SUPPLY,
ADIS16203_SCAN_AUX_ADC,
ADIS16203_SCAN_TEMP,
};
#endif /* SPI_ADIS16203_H_ */
......@@ -21,7 +21,145 @@
#include <linux/iio/buffer.h>
#include <linux/iio/imu/adis.h>
#include "adis16209.h"
#define ADIS16209_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16209_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16209_SUPPLY_OUT 0x02
/* Output, x-axis accelerometer */
#define ADIS16209_XACCL_OUT 0x04
/* Output, y-axis accelerometer */
#define ADIS16209_YACCL_OUT 0x06
/* Output, auxiliary ADC input */
#define ADIS16209_AUX_ADC 0x08
/* Output, temperature */
#define ADIS16209_TEMP_OUT 0x0A
/* Output, x-axis inclination */
#define ADIS16209_XINCL_OUT 0x0C
/* Output, y-axis inclination */
#define ADIS16209_YINCL_OUT 0x0E
/* Output, +/-180 vertical rotational position */
#define ADIS16209_ROT_OUT 0x10
/* Calibration, x-axis acceleration offset null */
#define ADIS16209_XACCL_NULL 0x12
/* Calibration, y-axis acceleration offset null */
#define ADIS16209_YACCL_NULL 0x14
/* Calibration, x-axis inclination offset null */
#define ADIS16209_XINCL_NULL 0x16
/* Calibration, y-axis inclination offset null */
#define ADIS16209_YINCL_NULL 0x18
/* Calibration, vertical rotation offset null */
#define ADIS16209_ROT_NULL 0x1A
/* Alarm 1 amplitude threshold */
#define ADIS16209_ALM_MAG1 0x20
/* Alarm 2 amplitude threshold */
#define ADIS16209_ALM_MAG2 0x22
/* Alarm 1, sample period */
#define ADIS16209_ALM_SMPL1 0x24
/* Alarm 2, sample period */
#define ADIS16209_ALM_SMPL2 0x26
/* Alarm control */
#define ADIS16209_ALM_CTRL 0x28
/* Auxiliary DAC data */
#define ADIS16209_AUX_DAC 0x30
/* General-purpose digital input/output control */
#define ADIS16209_GPIO_CTRL 0x32
/* Miscellaneous control */
#define ADIS16209_MSC_CTRL 0x34
/* Internal sample period (rate) control */
#define ADIS16209_SMPL_PRD 0x36
/* Operation, filter configuration */
#define ADIS16209_AVG_CNT 0x38
/* Operation, sleep mode control */
#define ADIS16209_SLP_CNT 0x3A
/* Diagnostics, system status register */
#define ADIS16209_DIAG_STAT 0x3C
/* Operation, system command register */
#define ADIS16209_GLOB_CMD 0x3E
/* MSC_CTRL */
/* Self-test at power-on: 1 = disabled, 0 = enabled */
#define ADIS16209_MSC_CTRL_PWRUP_SELF_TEST BIT(10)
/* Self-test enable */
#define ADIS16209_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16209_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16209_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
#define ADIS16209_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16209_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16209_DIAG_STAT_ALARM1 BIT(8)
/* Self-test diagnostic error flag: 1 = error condition, 0 = normal operation */
#define ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT 5
/* SPI communications failure */
#define ADIS16209_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16209_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16209_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16209_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16209_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16209_GLOB_CMD_CLEAR_STAT BIT(4)
#define ADIS16209_GLOB_CMD_FACTORY_CAL BIT(1)
#define ADIS16209_ERROR_ACTIVE BIT(14)
#define ADIS16209_SCAN_SUPPLY 0
#define ADIS16209_SCAN_ACC_X 1
#define ADIS16209_SCAN_ACC_Y 2
#define ADIS16209_SCAN_AUX_ADC 3
#define ADIS16209_SCAN_TEMP 4
#define ADIS16209_SCAN_INCLI_X 5
#define ADIS16209_SCAN_INCLI_Y 6
#define ADIS16209_SCAN_ROT 7
static const u8 adis16209_addresses[8][1] = {
[ADIS16209_SCAN_SUPPLY] = { },
......
#ifndef SPI_ADIS16209_H_
#define SPI_ADIS16209_H_
#define ADIS16209_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16209_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16209_SUPPLY_OUT 0x02
/* Output, x-axis accelerometer */
#define ADIS16209_XACCL_OUT 0x04
/* Output, y-axis accelerometer */
#define ADIS16209_YACCL_OUT 0x06
/* Output, auxiliary ADC input */
#define ADIS16209_AUX_ADC 0x08
/* Output, temperature */
#define ADIS16209_TEMP_OUT 0x0A
/* Output, x-axis inclination */
#define ADIS16209_XINCL_OUT 0x0C
/* Output, y-axis inclination */
#define ADIS16209_YINCL_OUT 0x0E
/* Output, +/-180 vertical rotational position */
#define ADIS16209_ROT_OUT 0x10
/* Calibration, x-axis acceleration offset null */
#define ADIS16209_XACCL_NULL 0x12
/* Calibration, y-axis acceleration offset null */
#define ADIS16209_YACCL_NULL 0x14
/* Calibration, x-axis inclination offset null */
#define ADIS16209_XINCL_NULL 0x16
/* Calibration, y-axis inclination offset null */
#define ADIS16209_YINCL_NULL 0x18
/* Calibration, vertical rotation offset null */
#define ADIS16209_ROT_NULL 0x1A
/* Alarm 1 amplitude threshold */
#define ADIS16209_ALM_MAG1 0x20
/* Alarm 2 amplitude threshold */
#define ADIS16209_ALM_MAG2 0x22
/* Alarm 1, sample period */
#define ADIS16209_ALM_SMPL1 0x24
/* Alarm 2, sample period */
#define ADIS16209_ALM_SMPL2 0x26
/* Alarm control */
#define ADIS16209_ALM_CTRL 0x28
/* Auxiliary DAC data */
#define ADIS16209_AUX_DAC 0x30
/* General-purpose digital input/output control */
#define ADIS16209_GPIO_CTRL 0x32
/* Miscellaneous control */
#define ADIS16209_MSC_CTRL 0x34
/* Internal sample period (rate) control */
#define ADIS16209_SMPL_PRD 0x36
/* Operation, filter configuration */
#define ADIS16209_AVG_CNT 0x38
/* Operation, sleep mode control */
#define ADIS16209_SLP_CNT 0x3A
/* Diagnostics, system status register */
#define ADIS16209_DIAG_STAT 0x3C
/* Operation, system command register */
#define ADIS16209_GLOB_CMD 0x3E
/* MSC_CTRL */
/* Self-test at power-on: 1 = disabled, 0 = enabled */
#define ADIS16209_MSC_CTRL_PWRUP_SELF_TEST BIT(10)
/* Self-test enable */
#define ADIS16209_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16209_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16209_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
#define ADIS16209_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16209_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16209_DIAG_STAT_ALARM1 BIT(8)
/* Self-test diagnostic error flag: 1 = error condition, 0 = normal operation */
#define ADIS16209_DIAG_STAT_SELFTEST_FAIL_BIT 5
/* SPI communications failure */
#define ADIS16209_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16209_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16209_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16209_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16209_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16209_GLOB_CMD_CLEAR_STAT BIT(4)
#define ADIS16209_GLOB_CMD_FACTORY_CAL BIT(1)
#define ADIS16209_ERROR_ACTIVE BIT(14)
#define ADIS16209_SCAN_SUPPLY 0
#define ADIS16209_SCAN_ACC_X 1
#define ADIS16209_SCAN_ACC_Y 2
#define ADIS16209_SCAN_AUX_ADC 3
#define ADIS16209_SCAN_TEMP 4
#define ADIS16209_SCAN_INCLI_X 5
#define ADIS16209_SCAN_INCLI_Y 6
#define ADIS16209_SCAN_ROT 7
#endif /* SPI_ADIS16209_H_ */
......@@ -24,7 +24,180 @@
#include <linux/iio/buffer.h>
#include <linux/iio/imu/adis.h>
#include "adis16240.h"
#define ADIS16240_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16240_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16240_SUPPLY_OUT 0x02
/* Output, x-axis accelerometer */
#define ADIS16240_XACCL_OUT 0x04
/* Output, y-axis accelerometer */
#define ADIS16240_YACCL_OUT 0x06
/* Output, z-axis accelerometer */
#define ADIS16240_ZACCL_OUT 0x08
/* Output, auxiliary ADC input */
#define ADIS16240_AUX_ADC 0x0A
/* Output, temperature */
#define ADIS16240_TEMP_OUT 0x0C
/* Output, x-axis acceleration peak */
#define ADIS16240_XPEAK_OUT 0x0E
/* Output, y-axis acceleration peak */
#define ADIS16240_YPEAK_OUT 0x10
/* Output, z-axis acceleration peak */
#define ADIS16240_ZPEAK_OUT 0x12
/* Output, sum-of-squares acceleration peak */
#define ADIS16240_XYZPEAK_OUT 0x14
/* Output, Capture Buffer 1, X and Y acceleration */
#define ADIS16240_CAPT_BUF1 0x16
/* Output, Capture Buffer 2, Z acceleration */
#define ADIS16240_CAPT_BUF2 0x18
/* Diagnostic, error flags */
#define ADIS16240_DIAG_STAT 0x1A
/* Diagnostic, event counter */
#define ADIS16240_EVNT_CNTR 0x1C
/* Diagnostic, check sum value from firmware test */
#define ADIS16240_CHK_SUM 0x1E
/* Calibration, x-axis acceleration offset adjustment */
#define ADIS16240_XACCL_OFF 0x20
/* Calibration, y-axis acceleration offset adjustment */
#define ADIS16240_YACCL_OFF 0x22
/* Calibration, z-axis acceleration offset adjustment */
#define ADIS16240_ZACCL_OFF 0x24
/* Clock, hour and minute */
#define ADIS16240_CLK_TIME 0x2E
/* Clock, month and day */
#define ADIS16240_CLK_DATE 0x30
/* Clock, year */
#define ADIS16240_CLK_YEAR 0x32
/* Wake-up setting, hour and minute */
#define ADIS16240_WAKE_TIME 0x34
/* Wake-up setting, month and day */
#define ADIS16240_WAKE_DATE 0x36
/* Alarm 1 amplitude threshold */
#define ADIS16240_ALM_MAG1 0x38
/* Alarm 2 amplitude threshold */
#define ADIS16240_ALM_MAG2 0x3A
/* Alarm control */
#define ADIS16240_ALM_CTRL 0x3C
/* Capture, external trigger control */
#define ADIS16240_XTRIG_CTRL 0x3E
/* Capture, address pointer */
#define ADIS16240_CAPT_PNTR 0x40
/* Capture, configuration and control */
#define ADIS16240_CAPT_CTRL 0x42
/* General-purpose digital input/output control */
#define ADIS16240_GPIO_CTRL 0x44
/* Miscellaneous control */
#define ADIS16240_MSC_CTRL 0x46
/* Internal sample period (rate) control */
#define ADIS16240_SMPL_PRD 0x48
/* System command */
#define ADIS16240_GLOB_CMD 0x4A
/* MSC_CTRL */
/* Enables sum-of-squares output (XYZPEAK_OUT) */
#define ADIS16240_MSC_CTRL_XYZPEAK_OUT_EN BIT(15)
/* Enables peak tracking output (XPEAK_OUT, YPEAK_OUT, and ZPEAK_OUT) */
#define ADIS16240_MSC_CTRL_X_Y_ZPEAK_OUT_EN BIT(14)
/* Self-test enable: 1 = apply electrostatic force, 0 = disabled */
#define ADIS16240_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16240_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16240_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
#define ADIS16240_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16240_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16240_DIAG_STAT_ALARM1 BIT(8)
/* Capture buffer full: 1 = capture buffer is full */
#define ADIS16240_DIAG_STAT_CPT_BUF_FUL BIT(7)
/* Flash test, checksum flag: 1 = mismatch, 0 = match */
#define ADIS16240_DIAG_STAT_CHKSUM BIT(6)
/* Power-on, self-test flag: 1 = failure, 0 = pass */
#define ADIS16240_DIAG_STAT_PWRON_FAIL_BIT 5
/* Power-on self-test: 1 = in-progress, 0 = complete */
#define ADIS16240_DIAG_STAT_PWRON_BUSY BIT(4)
/* SPI communications failure */
#define ADIS16240_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16240_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16240_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16240_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16240_GLOB_CMD_RESUME BIT(8)
#define ADIS16240_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16240_GLOB_CMD_STANDBY BIT(2)
#define ADIS16240_ERROR_ACTIVE BIT(14)
/* At the moment triggers are only used for ring buffer
* filling. This may change!
*/
#define ADIS16240_SCAN_ACC_X 0
#define ADIS16240_SCAN_ACC_Y 1
#define ADIS16240_SCAN_ACC_Z 2
#define ADIS16240_SCAN_SUPPLY 3
#define ADIS16240_SCAN_AUX_ADC 4
#define ADIS16240_SCAN_TEMP 5
static ssize_t adis16240_spi_read_signed(struct device *dev,
struct device_attribute *attr,
......@@ -65,7 +238,7 @@ static ssize_t adis16240_read_12bit_signed(struct device *dev,
return ret;
}
static IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, S_IRUGO,
static IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, 0444,
adis16240_read_12bit_signed, NULL,
ADIS16240_XYZPEAK_OUT);
......
#ifndef SPI_ADIS16240_H_
#define SPI_ADIS16240_H_
#define ADIS16240_STARTUP_DELAY 220 /* ms */
/* Flash memory write count */
#define ADIS16240_FLASH_CNT 0x00
/* Output, power supply */
#define ADIS16240_SUPPLY_OUT 0x02
/* Output, x-axis accelerometer */
#define ADIS16240_XACCL_OUT 0x04
/* Output, y-axis accelerometer */
#define ADIS16240_YACCL_OUT 0x06
/* Output, z-axis accelerometer */
#define ADIS16240_ZACCL_OUT 0x08
/* Output, auxiliary ADC input */
#define ADIS16240_AUX_ADC 0x0A
/* Output, temperature */
#define ADIS16240_TEMP_OUT 0x0C
/* Output, x-axis acceleration peak */
#define ADIS16240_XPEAK_OUT 0x0E
/* Output, y-axis acceleration peak */
#define ADIS16240_YPEAK_OUT 0x10
/* Output, z-axis acceleration peak */
#define ADIS16240_ZPEAK_OUT 0x12
/* Output, sum-of-squares acceleration peak */
#define ADIS16240_XYZPEAK_OUT 0x14
/* Output, Capture Buffer 1, X and Y acceleration */
#define ADIS16240_CAPT_BUF1 0x16
/* Output, Capture Buffer 2, Z acceleration */
#define ADIS16240_CAPT_BUF2 0x18
/* Diagnostic, error flags */
#define ADIS16240_DIAG_STAT 0x1A
/* Diagnostic, event counter */
#define ADIS16240_EVNT_CNTR 0x1C
/* Diagnostic, check sum value from firmware test */
#define ADIS16240_CHK_SUM 0x1E
/* Calibration, x-axis acceleration offset adjustment */
#define ADIS16240_XACCL_OFF 0x20
/* Calibration, y-axis acceleration offset adjustment */
#define ADIS16240_YACCL_OFF 0x22
/* Calibration, z-axis acceleration offset adjustment */
#define ADIS16240_ZACCL_OFF 0x24
/* Clock, hour and minute */
#define ADIS16240_CLK_TIME 0x2E
/* Clock, month and day */
#define ADIS16240_CLK_DATE 0x30
/* Clock, year */
#define ADIS16240_CLK_YEAR 0x32
/* Wake-up setting, hour and minute */
#define ADIS16240_WAKE_TIME 0x34
/* Wake-up setting, month and day */
#define ADIS16240_WAKE_DATE 0x36
/* Alarm 1 amplitude threshold */
#define ADIS16240_ALM_MAG1 0x38
/* Alarm 2 amplitude threshold */
#define ADIS16240_ALM_MAG2 0x3A
/* Alarm control */
#define ADIS16240_ALM_CTRL 0x3C
/* Capture, external trigger control */
#define ADIS16240_XTRIG_CTRL 0x3E
/* Capture, address pointer */
#define ADIS16240_CAPT_PNTR 0x40
/* Capture, configuration and control */
#define ADIS16240_CAPT_CTRL 0x42
/* General-purpose digital input/output control */
#define ADIS16240_GPIO_CTRL 0x44
/* Miscellaneous control */
#define ADIS16240_MSC_CTRL 0x46
/* Internal sample period (rate) control */
#define ADIS16240_SMPL_PRD 0x48
/* System command */
#define ADIS16240_GLOB_CMD 0x4A
/* MSC_CTRL */
/* Enables sum-of-squares output (XYZPEAK_OUT) */
#define ADIS16240_MSC_CTRL_XYZPEAK_OUT_EN BIT(15)
/* Enables peak tracking output (XPEAK_OUT, YPEAK_OUT, and ZPEAK_OUT) */
#define ADIS16240_MSC_CTRL_X_Y_ZPEAK_OUT_EN BIT(14)
/* Self-test enable: 1 = apply electrostatic force, 0 = disabled */
#define ADIS16240_MSC_CTRL_SELF_TEST_EN BIT(8)
/* Data-ready enable: 1 = enabled, 0 = disabled */
#define ADIS16240_MSC_CTRL_DATA_RDY_EN BIT(2)
/* Data-ready polarity: 1 = active high, 0 = active low */
#define ADIS16240_MSC_CTRL_ACTIVE_HIGH BIT(1)
/* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
#define ADIS16240_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
/* DIAG_STAT */
/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16240_DIAG_STAT_ALARM2 BIT(9)
/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
#define ADIS16240_DIAG_STAT_ALARM1 BIT(8)
/* Capture buffer full: 1 = capture buffer is full */
#define ADIS16240_DIAG_STAT_CPT_BUF_FUL BIT(7)
/* Flash test, checksum flag: 1 = mismatch, 0 = match */
#define ADIS16240_DIAG_STAT_CHKSUM BIT(6)
/* Power-on, self-test flag: 1 = failure, 0 = pass */
#define ADIS16240_DIAG_STAT_PWRON_FAIL_BIT 5
/* Power-on self-test: 1 = in-progress, 0 = complete */
#define ADIS16240_DIAG_STAT_PWRON_BUSY BIT(4)
/* SPI communications failure */
#define ADIS16240_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */
#define ADIS16240_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */
#define ADIS16240_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */
#define ADIS16240_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */
#define ADIS16240_GLOB_CMD_RESUME BIT(8)
#define ADIS16240_GLOB_CMD_SW_RESET BIT(7)
#define ADIS16240_GLOB_CMD_STANDBY BIT(2)
#define ADIS16240_ERROR_ACTIVE BIT(14)
/* At the moment triggers are only used for ring buffer
* filling. This may change!
*/
#define ADIS16240_SCAN_ACC_X 0
#define ADIS16240_SCAN_ACC_Y 1
#define ADIS16240_SCAN_ACC_Z 2
#define ADIS16240_SCAN_SUPPLY 3
#define ADIS16240_SCAN_AUX_ADC 4
#define ADIS16240_SCAN_TEMP 5
#endif /* SPI_ADIS16240_H_ */
......@@ -80,26 +80,4 @@ config AD7280
To compile this driver as a module, choose M here: the
module will be called ad7280a
config LPC32XX_ADC
tristate "NXP LPC32XX ADC"
depends on ARCH_LPC32XX || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to build support for the integrated ADC inside the
LPC32XX SoC. Note that this feature uses the same hardware as the
touchscreen driver, so you should either select only one of the two
drivers (lpc32xx_adc or lpc32xx_ts) or, in the OpenFirmware case,
activate only one via device tree selection. Provides direct access
via sysfs.
config SPEAR_ADC
tristate "ST SPEAr ADC"
depends on PLAT_SPEAR || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to build support for the integrated ADC inside the
ST SPEAr SoC. Provides direct access via sysfs.
To compile this driver as a module, choose M here: the
module will be called spear_adc.
endmenu
......@@ -10,5 +10,3 @@ obj-$(CONFIG_AD7780) += ad7780.o
obj-$(CONFIG_AD7816) += ad7816.o
obj-$(CONFIG_AD7192) += ad7192.o
obj-$(CONFIG_AD7280) += ad7280a.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
......@@ -342,9 +342,9 @@ ad7192_show_scale_available(struct device *dev,
static IIO_DEVICE_ATTR_NAMED(in_v_m_v_scale_available,
in_voltage-voltage_scale_available,
S_IRUGO, ad7192_show_scale_available, NULL, 0);
0444, ad7192_show_scale_available, NULL, 0);
static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO,
static IIO_DEVICE_ATTR(in_voltage_scale_available, 0444,
ad7192_show_scale_available, NULL, 0);
static ssize_t ad7192_show_ac_excitation(struct device *dev,
......@@ -412,11 +412,11 @@ static ssize_t ad7192_set(struct device *dev,
return ret ? ret : len;
}
static IIO_DEVICE_ATTR(bridge_switch_en, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(bridge_switch_en, 0644,
ad7192_show_bridge_switch, ad7192_set,
AD7192_REG_GPOCON);
static IIO_DEVICE_ATTR(ac_excitation_en, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(ac_excitation_en, 0644,
ad7192_show_ac_excitation, ad7192_set,
AD7192_REG_MODE);
......
......@@ -267,7 +267,7 @@ static ssize_t adt7316_store_enabled(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(enabled, 0644,
adt7316_show_enabled,
adt7316_store_enabled,
0);
......@@ -311,7 +311,7 @@ static ssize_t adt7316_store_select_ex_temp(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(select_ex_temp, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(select_ex_temp, 0644,
adt7316_show_select_ex_temp,
adt7316_store_select_ex_temp,
0);
......@@ -352,7 +352,7 @@ static ssize_t adt7316_store_mode(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(mode, 0644,
adt7316_show_mode,
adt7316_store_mode,
0);
......@@ -364,7 +364,7 @@ static ssize_t adt7316_show_all_modes(struct device *dev,
return sprintf(buf, "single_channel\nround_robin\n");
}
static IIO_DEVICE_ATTR(all_modes, S_IRUGO, adt7316_show_all_modes, NULL, 0);
static IIO_DEVICE_ATTR(all_modes, 0444, adt7316_show_all_modes, NULL, 0);
static ssize_t adt7316_show_ad_channel(struct device *dev,
struct device_attribute *attr,
......@@ -446,7 +446,7 @@ static ssize_t adt7316_store_ad_channel(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(ad_channel, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(ad_channel, 0644,
adt7316_show_ad_channel,
adt7316_store_ad_channel,
0);
......@@ -469,7 +469,7 @@ static ssize_t adt7316_show_all_ad_channels(struct device *dev,
"2 - External Temperature\n");
}
static IIO_DEVICE_ATTR(all_ad_channels, S_IRUGO,
static IIO_DEVICE_ATTR(all_ad_channels, 0444,
adt7316_show_all_ad_channels, NULL, 0);
static ssize_t adt7316_show_disable_averaging(struct device *dev,
......@@ -506,7 +506,7 @@ static ssize_t adt7316_store_disable_averaging(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(disable_averaging, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(disable_averaging, 0644,
adt7316_show_disable_averaging,
adt7316_store_disable_averaging,
0);
......@@ -545,7 +545,7 @@ static ssize_t adt7316_store_enable_smbus_timeout(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(enable_smbus_timeout, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(enable_smbus_timeout, 0644,
adt7316_show_enable_smbus_timeout,
adt7316_store_enable_smbus_timeout,
0);
......@@ -583,7 +583,7 @@ static ssize_t adt7316_store_powerdown(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(powerdown, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(powerdown, 0644,
adt7316_show_powerdown,
adt7316_store_powerdown,
0);
......@@ -621,7 +621,7 @@ static ssize_t adt7316_store_fast_ad_clock(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(fast_ad_clock, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(fast_ad_clock, 0644,
adt7316_show_fast_ad_clock,
adt7316_store_fast_ad_clock,
0);
......@@ -674,7 +674,7 @@ static ssize_t adt7316_store_da_high_resolution(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(da_high_resolution, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(da_high_resolution, 0644,
adt7316_show_da_high_resolution,
adt7316_store_da_high_resolution,
0);
......@@ -720,7 +720,7 @@ static ssize_t adt7316_store_AIN_internal_Vref(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(AIN_internal_Vref, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(AIN_internal_Vref, 0644,
adt7316_show_AIN_internal_Vref,
adt7316_store_AIN_internal_Vref,
0);
......@@ -760,7 +760,7 @@ static ssize_t adt7316_store_enable_prop_DACA(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(enable_proportion_DACA, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(enable_proportion_DACA, 0644,
adt7316_show_enable_prop_DACA,
adt7316_store_enable_prop_DACA,
0);
......@@ -799,7 +799,7 @@ static ssize_t adt7316_store_enable_prop_DACB(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(enable_proportion_DACB, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(enable_proportion_DACB, 0644,
adt7316_show_enable_prop_DACB,
adt7316_store_enable_prop_DACB,
0);
......@@ -842,7 +842,7 @@ static ssize_t adt7316_store_DAC_2Vref_ch_mask(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(DAC_2Vref_channels_mask, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(DAC_2Vref_channels_mask, 0644,
adt7316_show_DAC_2Vref_ch_mask,
adt7316_store_DAC_2Vref_ch_mask,
0);
......@@ -902,7 +902,7 @@ static ssize_t adt7316_store_DAC_update_mode(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(DAC_update_mode, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(DAC_update_mode, 0644,
adt7316_show_DAC_update_mode,
adt7316_store_DAC_update_mode,
0);
......@@ -922,7 +922,7 @@ static ssize_t adt7316_show_all_DAC_update_modes(struct device *dev,
return sprintf(buf, "manual\n");
}
static IIO_DEVICE_ATTR(all_DAC_update_modes, S_IRUGO,
static IIO_DEVICE_ATTR(all_DAC_update_modes, 0444,
adt7316_show_all_DAC_update_modes, NULL, 0);
......@@ -961,7 +961,7 @@ static ssize_t adt7316_store_update_DAC(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(update_DAC, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(update_DAC, 0644,
NULL,
adt7316_store_update_DAC,
0);
......@@ -1006,7 +1006,7 @@ static ssize_t adt7316_store_DA_AB_Vref_bypass(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(DA_AB_Vref_bypass, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(DA_AB_Vref_bypass, 0644,
adt7316_show_DA_AB_Vref_bypass,
adt7316_store_DA_AB_Vref_bypass,
0);
......@@ -1051,7 +1051,7 @@ static ssize_t adt7316_store_DA_CD_Vref_bypass(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(DA_CD_Vref_bypass, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(DA_CD_Vref_bypass, 0644,
adt7316_show_DA_CD_Vref_bypass,
adt7316_store_DA_CD_Vref_bypass,
0);
......@@ -1112,7 +1112,7 @@ static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev,
return len;
}
static IIO_DEVICE_ATTR(DAC_internal_Vref, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(DAC_internal_Vref, 0644,
adt7316_show_DAC_internal_Vref,
adt7316_store_DAC_internal_Vref,
0);
......@@ -1201,7 +1201,7 @@ static ssize_t adt7316_show_VDD(struct device *dev,
return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_VDD, buf);
}
static IIO_DEVICE_ATTR(VDD, S_IRUGO, adt7316_show_VDD, NULL, 0);
static IIO_DEVICE_ATTR(VDD, 0444, adt7316_show_VDD, NULL, 0);
static ssize_t adt7316_show_in_temp(struct device *dev,
struct device_attribute *attr,
......@@ -1213,7 +1213,7 @@ static ssize_t adt7316_show_in_temp(struct device *dev,
return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_IN, buf);
}
static IIO_DEVICE_ATTR(in_temp, S_IRUGO, adt7316_show_in_temp, NULL, 0);
static IIO_DEVICE_ATTR(in_temp, 0444, adt7316_show_in_temp, NULL, 0);
static ssize_t adt7316_show_ex_temp_AIN1(struct device *dev,
struct device_attribute *attr,
......@@ -1225,9 +1225,9 @@ static ssize_t adt7316_show_ex_temp_AIN1(struct device *dev,
return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_EX, buf);
}
static IIO_DEVICE_ATTR(ex_temp_AIN1, S_IRUGO, adt7316_show_ex_temp_AIN1,
static IIO_DEVICE_ATTR(ex_temp_AIN1, 0444, adt7316_show_ex_temp_AIN1,
NULL, 0);
static IIO_DEVICE_ATTR(ex_temp, S_IRUGO, adt7316_show_ex_temp_AIN1, NULL, 0);
static IIO_DEVICE_ATTR(ex_temp, 0444, adt7316_show_ex_temp_AIN1, NULL, 0);
static ssize_t adt7316_show_AIN2(struct device *dev,
struct device_attribute *attr,
......@@ -1238,7 +1238,7 @@ static ssize_t adt7316_show_AIN2(struct device *dev,
return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN2, buf);
}
static IIO_DEVICE_ATTR(AIN2, S_IRUGO, adt7316_show_AIN2, NULL, 0);
static IIO_DEVICE_ATTR(AIN2, 0444, adt7316_show_AIN2, NULL, 0);
static ssize_t adt7316_show_AIN3(struct device *dev,
struct device_attribute *attr,
......@@ -1249,7 +1249,7 @@ static ssize_t adt7316_show_AIN3(struct device *dev,
return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN3, buf);
}
static IIO_DEVICE_ATTR(AIN3, S_IRUGO, adt7316_show_AIN3, NULL, 0);
static IIO_DEVICE_ATTR(AIN3, 0444, adt7316_show_AIN3, NULL, 0);
static ssize_t adt7316_show_AIN4(struct device *dev,
struct device_attribute *attr,
......@@ -1260,7 +1260,7 @@ static ssize_t adt7316_show_AIN4(struct device *dev,
return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN4, buf);
}
static IIO_DEVICE_ATTR(AIN4, S_IRUGO, adt7316_show_AIN4, NULL, 0);
static IIO_DEVICE_ATTR(AIN4, 0444, adt7316_show_AIN4, NULL, 0);
static ssize_t adt7316_show_temp_offset(struct adt7316_chip_info *chip,
int offset_addr, char *buf)
......@@ -1325,7 +1325,7 @@ static ssize_t adt7316_store_in_temp_offset(struct device *dev,
len);
}
static IIO_DEVICE_ATTR(in_temp_offset, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(in_temp_offset, 0644,
adt7316_show_in_temp_offset,
adt7316_store_in_temp_offset, 0);
......@@ -1351,7 +1351,7 @@ static ssize_t adt7316_store_ex_temp_offset(struct device *dev,
len);
}
static IIO_DEVICE_ATTR(ex_temp_offset, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(ex_temp_offset, 0644,
adt7316_show_ex_temp_offset,
adt7316_store_ex_temp_offset, 0);
......@@ -1378,7 +1378,7 @@ static ssize_t adt7316_store_in_analog_temp_offset(struct device *dev,
ADT7316_IN_ANALOG_TEMP_OFFSET, buf, len);
}
static IIO_DEVICE_ATTR(in_analog_temp_offset, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(in_analog_temp_offset, 0644,
adt7316_show_in_analog_temp_offset,
adt7316_store_in_analog_temp_offset, 0);
......@@ -1405,7 +1405,7 @@ static ssize_t adt7316_store_ex_analog_temp_offset(struct device *dev,
ADT7316_EX_ANALOG_TEMP_OFFSET, buf, len);
}
static IIO_DEVICE_ATTR(ex_analog_temp_offset, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(ex_analog_temp_offset, 0644,
adt7316_show_ex_analog_temp_offset,
adt7316_store_ex_analog_temp_offset, 0);
......@@ -1500,7 +1500,7 @@ static ssize_t adt7316_store_DAC_A(struct device *dev,
return adt7316_store_DAC(chip, 0, buf, len);
}
static IIO_DEVICE_ATTR(DAC_A, S_IRUGO | S_IWUSR, adt7316_show_DAC_A,
static IIO_DEVICE_ATTR(DAC_A, 0644, adt7316_show_DAC_A,
adt7316_store_DAC_A, 0);
static ssize_t adt7316_show_DAC_B(struct device *dev,
......@@ -1524,7 +1524,7 @@ static ssize_t adt7316_store_DAC_B(struct device *dev,
return adt7316_store_DAC(chip, 1, buf, len);
}
static IIO_DEVICE_ATTR(DAC_B, S_IRUGO | S_IWUSR, adt7316_show_DAC_B,
static IIO_DEVICE_ATTR(DAC_B, 0644, adt7316_show_DAC_B,
adt7316_store_DAC_B, 0);
static ssize_t adt7316_show_DAC_C(struct device *dev,
......@@ -1548,7 +1548,7 @@ static ssize_t adt7316_store_DAC_C(struct device *dev,
return adt7316_store_DAC(chip, 2, buf, len);
}
static IIO_DEVICE_ATTR(DAC_C, S_IRUGO | S_IWUSR, adt7316_show_DAC_C,
static IIO_DEVICE_ATTR(DAC_C, 0644, adt7316_show_DAC_C,
adt7316_store_DAC_C, 0);
static ssize_t adt7316_show_DAC_D(struct device *dev,
......@@ -1572,7 +1572,7 @@ static ssize_t adt7316_store_DAC_D(struct device *dev,
return adt7316_store_DAC(chip, 3, buf, len);
}
static IIO_DEVICE_ATTR(DAC_D, S_IRUGO | S_IWUSR, adt7316_show_DAC_D,
static IIO_DEVICE_ATTR(DAC_D, 0644, adt7316_show_DAC_D,
adt7316_store_DAC_D, 0);
static ssize_t adt7316_show_device_id(struct device *dev,
......@@ -1591,7 +1591,7 @@ static ssize_t adt7316_show_device_id(struct device *dev,
return sprintf(buf, "%d\n", id);
}
static IIO_DEVICE_ATTR(device_id, S_IRUGO, adt7316_show_device_id, NULL, 0);
static IIO_DEVICE_ATTR(device_id, 0444, adt7316_show_device_id, NULL, 0);
static ssize_t adt7316_show_manufactorer_id(struct device *dev,
struct device_attribute *attr,
......@@ -1609,7 +1609,7 @@ static ssize_t adt7316_show_manufactorer_id(struct device *dev,
return sprintf(buf, "%d\n", id);
}
static IIO_DEVICE_ATTR(manufactorer_id, S_IRUGO,
static IIO_DEVICE_ATTR(manufactorer_id, 0444,
adt7316_show_manufactorer_id, NULL, 0);
static ssize_t adt7316_show_device_rev(struct device *dev,
......@@ -1628,7 +1628,7 @@ static ssize_t adt7316_show_device_rev(struct device *dev,
return sprintf(buf, "%d\n", rev);
}
static IIO_DEVICE_ATTR(device_rev, S_IRUGO, adt7316_show_device_rev, NULL, 0);
static IIO_DEVICE_ATTR(device_rev, 0444, adt7316_show_device_rev, NULL, 0);
static ssize_t adt7316_show_bus_type(struct device *dev,
struct device_attribute *attr,
......@@ -1649,7 +1649,7 @@ static ssize_t adt7316_show_bus_type(struct device *dev,
return sprintf(buf, "i2c\n");
}
static IIO_DEVICE_ATTR(bus_type, S_IRUGO, adt7316_show_bus_type, NULL, 0);
static IIO_DEVICE_ATTR(bus_type, 0444, adt7316_show_bus_type, NULL, 0);
static struct attribute *adt7316_attributes[] = {
&iio_dev_attr_all_modes.dev_attr.attr,
......@@ -1972,61 +1972,61 @@ static ssize_t adt7316_set_int_enabled(struct device *dev,
}
static IIO_DEVICE_ATTR(int_mask,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_int_mask, adt7316_set_int_mask,
0);
static IIO_DEVICE_ATTR(in_temp_high_value,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_ad_bound, adt7316_set_ad_bound,
ADT7316_IN_TEMP_HIGH);
static IIO_DEVICE_ATTR(in_temp_low_value,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_ad_bound, adt7316_set_ad_bound,
ADT7316_IN_TEMP_LOW);
static IIO_DEVICE_ATTR(ex_temp_high_value,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_ad_bound, adt7316_set_ad_bound,
ADT7316_EX_TEMP_HIGH);
static IIO_DEVICE_ATTR(ex_temp_low_value,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_ad_bound, adt7316_set_ad_bound,
ADT7316_EX_TEMP_LOW);
/* NASTY duplication to be fixed */
static IIO_DEVICE_ATTR(ex_temp_ain1_high_value,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_ad_bound, adt7316_set_ad_bound,
ADT7316_EX_TEMP_HIGH);
static IIO_DEVICE_ATTR(ex_temp_ain1_low_value,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_ad_bound, adt7316_set_ad_bound,
ADT7316_EX_TEMP_LOW);
static IIO_DEVICE_ATTR(ain2_high_value,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_ad_bound, adt7316_set_ad_bound,
ADT7516_AIN2_HIGH);
static IIO_DEVICE_ATTR(ain2_low_value,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_ad_bound, adt7316_set_ad_bound,
ADT7516_AIN2_LOW);
static IIO_DEVICE_ATTR(ain3_high_value,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_ad_bound, adt7316_set_ad_bound,
ADT7516_AIN3_HIGH);
static IIO_DEVICE_ATTR(ain3_low_value,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_ad_bound, adt7316_set_ad_bound,
ADT7516_AIN3_LOW);
static IIO_DEVICE_ATTR(ain4_high_value,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_ad_bound, adt7316_set_ad_bound,
ADT7516_AIN4_HIGH);
static IIO_DEVICE_ATTR(ain4_low_value,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_ad_bound, adt7316_set_ad_bound,
ADT7516_AIN4_LOW);
static IIO_DEVICE_ATTR(int_enabled,
S_IRUGO | S_IWUSR,
0644,
adt7316_show_int_enabled,
adt7316_set_int_enabled, 0);
......
......@@ -41,10 +41,10 @@
#define AD7152_REG_CFG2 26
/* Status Register Bit Designations (AD7152_REG_STATUS) */
#define AD7152_STATUS_RDY1 (1 << 0)
#define AD7152_STATUS_RDY2 (1 << 1)
#define AD7152_STATUS_C1C2 (1 << 2)
#define AD7152_STATUS_PWDN (1 << 7)
#define AD7152_STATUS_RDY1 BIT(0)
#define AD7152_STATUS_RDY2 BIT(1)
#define AD7152_STATUS_C1C2 BIT(2)
#define AD7152_STATUS_PWDN BIT(7)
/* Setup Register Bit Designations (AD7152_REG_CHx_SETUP) */
#define AD7152_SETUP_CAPDIFF (1 << 5)
......
......@@ -22,6 +22,98 @@
#include "ad9832.h"
/* Registers */
#define AD9832_FREQ0LL 0x0
#define AD9832_FREQ0HL 0x1
#define AD9832_FREQ0LM 0x2
#define AD9832_FREQ0HM 0x3
#define AD9832_FREQ1LL 0x4
#define AD9832_FREQ1HL 0x5
#define AD9832_FREQ1LM 0x6
#define AD9832_FREQ1HM 0x7
#define AD9832_PHASE0L 0x8
#define AD9832_PHASE0H 0x9
#define AD9832_PHASE1L 0xA
#define AD9832_PHASE1H 0xB
#define AD9832_PHASE2L 0xC
#define AD9832_PHASE2H 0xD
#define AD9832_PHASE3L 0xE
#define AD9832_PHASE3H 0xF
#define AD9832_PHASE_SYM 0x10
#define AD9832_FREQ_SYM 0x11
#define AD9832_PINCTRL_EN 0x12
#define AD9832_OUTPUT_EN 0x13
/* Command Control Bits */
#define AD9832_CMD_PHA8BITSW 0x1
#define AD9832_CMD_PHA16BITSW 0x0
#define AD9832_CMD_FRE8BITSW 0x3
#define AD9832_CMD_FRE16BITSW 0x2
#define AD9832_CMD_FPSELECT 0x6
#define AD9832_CMD_SYNCSELSRC 0x8
#define AD9832_CMD_SLEEPRESCLR 0xC
#define AD9832_FREQ BIT(11)
#define AD9832_PHASE(x) (((x) & 3) << 9)
#define AD9832_SYNC BIT(13)
#define AD9832_SELSRC BIT(12)
#define AD9832_SLEEP BIT(13)
#define AD9832_RESET BIT(12)
#define AD9832_CLR BIT(11)
#define CMD_SHIFT 12
#define ADD_SHIFT 8
#define AD9832_FREQ_BITS 32
#define AD9832_PHASE_BITS 12
#define RES_MASK(bits) ((1 << (bits)) - 1)
/**
* struct ad9832_state - driver instance specific data
* @spi: spi_device
* @avdd: supply regulator for the analog section
* @dvdd: supply regulator for the digital section
* @mclk: external master clock
* @ctrl_fp: cached frequency/phase control word
* @ctrl_ss: cached sync/selsrc control word
* @ctrl_src: cached sleep/reset/clr word
* @xfer: default spi transfer
* @msg: default spi message
* @freq_xfer: tuning word spi transfer
* @freq_msg: tuning word spi message
* @phase_xfer: tuning word spi transfer
* @phase_msg: tuning word spi message
* @data: spi transmit buffer
* @phase_data: tuning word spi transmit buffer
* @freq_data: tuning word spi transmit buffer
*/
struct ad9832_state {
struct spi_device *spi;
struct regulator *avdd;
struct regulator *dvdd;
unsigned long mclk;
unsigned short ctrl_fp;
unsigned short ctrl_ss;
unsigned short ctrl_src;
struct spi_transfer xfer;
struct spi_message msg;
struct spi_transfer freq_xfer[4];
struct spi_message freq_msg;
struct spi_transfer phase_xfer[2];
struct spi_message phase_msg;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
union {
__be16 freq_data[4]____cacheline_aligned;
__be16 phase_data[2];
__be16 data;
};
};
static unsigned long ad9832_calc_freqreg(unsigned long mclk, unsigned long fout)
{
unsigned long long freqreg = (u64)fout *
......
......@@ -8,98 +8,6 @@
#ifndef IIO_DDS_AD9832_H_
#define IIO_DDS_AD9832_H_
/* Registers */
#define AD9832_FREQ0LL 0x0
#define AD9832_FREQ0HL 0x1
#define AD9832_FREQ0LM 0x2
#define AD9832_FREQ0HM 0x3
#define AD9832_FREQ1LL 0x4
#define AD9832_FREQ1HL 0x5
#define AD9832_FREQ1LM 0x6
#define AD9832_FREQ1HM 0x7
#define AD9832_PHASE0L 0x8
#define AD9832_PHASE0H 0x9
#define AD9832_PHASE1L 0xA
#define AD9832_PHASE1H 0xB
#define AD9832_PHASE2L 0xC
#define AD9832_PHASE2H 0xD
#define AD9832_PHASE3L 0xE
#define AD9832_PHASE3H 0xF
#define AD9832_PHASE_SYM 0x10
#define AD9832_FREQ_SYM 0x11
#define AD9832_PINCTRL_EN 0x12
#define AD9832_OUTPUT_EN 0x13
/* Command Control Bits */
#define AD9832_CMD_PHA8BITSW 0x1
#define AD9832_CMD_PHA16BITSW 0x0
#define AD9832_CMD_FRE8BITSW 0x3
#define AD9832_CMD_FRE16BITSW 0x2
#define AD9832_CMD_FPSELECT 0x6
#define AD9832_CMD_SYNCSELSRC 0x8
#define AD9832_CMD_SLEEPRESCLR 0xC
#define AD9832_FREQ BIT(11)
#define AD9832_PHASE(x) (((x) & 3) << 9)
#define AD9832_SYNC BIT(13)
#define AD9832_SELSRC BIT(12)
#define AD9832_SLEEP BIT(13)
#define AD9832_RESET BIT(12)
#define AD9832_CLR BIT(11)
#define CMD_SHIFT 12
#define ADD_SHIFT 8
#define AD9832_FREQ_BITS 32
#define AD9832_PHASE_BITS 12
#define RES_MASK(bits) ((1 << (bits)) - 1)
/**
* struct ad9832_state - driver instance specific data
* @spi: spi_device
* @avdd: supply regulator for the analog section
* @dvdd: supply regulator for the digital section
* @mclk: external master clock
* @ctrl_fp: cached frequency/phase control word
* @ctrl_ss: cached sync/selsrc control word
* @ctrl_src: cached sleep/reset/clr word
* @xfer: default spi transfer
* @msg: default spi message
* @freq_xfer: tuning word spi transfer
* @freq_msg: tuning word spi message
* @phase_xfer: tuning word spi transfer
* @phase_msg: tuning word spi message
* @data: spi transmit buffer
* @phase_data: tuning word spi transmit buffer
* @freq_data: tuning word spi transmit buffer
*/
struct ad9832_state {
struct spi_device *spi;
struct regulator *avdd;
struct regulator *dvdd;
unsigned long mclk;
unsigned short ctrl_fp;
unsigned short ctrl_ss;
unsigned short ctrl_src;
struct spi_transfer xfer;
struct spi_message msg;
struct spi_transfer freq_xfer[4];
struct spi_message freq_msg;
struct spi_transfer phase_xfer[2];
struct spi_message phase_msg;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
union {
__be16 freq_data[4]____cacheline_aligned;
__be16 phase_data[2];
__be16 data;
};
};
/*
* TODO: struct ad9832_platform_data needs to go into include/linux/iio
*/
......
......@@ -25,6 +25,78 @@
#include "ad9834.h"
/* Registers */
#define AD9834_REG_CMD 0
#define AD9834_REG_FREQ0 BIT(14)
#define AD9834_REG_FREQ1 BIT(15)
#define AD9834_REG_PHASE0 (BIT(15) | BIT(14))
#define AD9834_REG_PHASE1 (BIT(15) | BIT(14) | BIT(13))
/* Command Control Bits */
#define AD9834_B28 BIT(13)
#define AD9834_HLB BIT(12)
#define AD9834_FSEL BIT(11)
#define AD9834_PSEL BIT(10)
#define AD9834_PIN_SW BIT(9)
#define AD9834_RESET BIT(8)
#define AD9834_SLEEP1 BIT(7)
#define AD9834_SLEEP12 BIT(6)
#define AD9834_OPBITEN BIT(5)
#define AD9834_SIGN_PIB BIT(4)
#define AD9834_DIV2 BIT(3)
#define AD9834_MODE BIT(1)
#define AD9834_FREQ_BITS 28
#define AD9834_PHASE_BITS 12
#define RES_MASK(bits) (BIT(bits) - 1)
/**
* struct ad9834_state - driver instance specific data
* @spi: spi_device
* @reg: supply regulator
* @mclk: external master clock
* @control: cached control word
* @xfer: default spi transfer
* @msg: default spi message
* @freq_xfer: tuning word spi transfer
* @freq_msg: tuning word spi message
* @data: spi transmit buffer
* @freq_data: tuning word spi transmit buffer
*/
struct ad9834_state {
struct spi_device *spi;
struct regulator *reg;
unsigned int mclk;
unsigned short control;
unsigned short devid;
struct spi_transfer xfer;
struct spi_message msg;
struct spi_transfer freq_xfer[2];
struct spi_message freq_msg;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
__be16 data ____cacheline_aligned;
__be16 freq_data[2];
};
/**
* ad9834_supported_device_ids:
*/
enum ad9834_supported_device_ids {
ID_AD9833,
ID_AD9834,
ID_AD9837,
ID_AD9838,
};
static unsigned int ad9834_calc_freqreg(unsigned long mclk, unsigned long fout)
{
unsigned long long freqreg = (u64)fout * (u64)BIT(AD9834_FREQ_BITS);
......
......@@ -8,67 +8,6 @@
#ifndef IIO_DDS_AD9834_H_
#define IIO_DDS_AD9834_H_
/* Registers */
#define AD9834_REG_CMD 0
#define AD9834_REG_FREQ0 BIT(14)
#define AD9834_REG_FREQ1 BIT(15)
#define AD9834_REG_PHASE0 (BIT(15) | BIT(14))
#define AD9834_REG_PHASE1 (BIT(15) | BIT(14) | BIT(13))
/* Command Control Bits */
#define AD9834_B28 BIT(13)
#define AD9834_HLB BIT(12)
#define AD9834_FSEL BIT(11)
#define AD9834_PSEL BIT(10)
#define AD9834_PIN_SW BIT(9)
#define AD9834_RESET BIT(8)
#define AD9834_SLEEP1 BIT(7)
#define AD9834_SLEEP12 BIT(6)
#define AD9834_OPBITEN BIT(5)
#define AD9834_SIGN_PIB BIT(4)
#define AD9834_DIV2 BIT(3)
#define AD9834_MODE BIT(1)
#define AD9834_FREQ_BITS 28
#define AD9834_PHASE_BITS 12
#define RES_MASK(bits) (BIT(bits) - 1)
/**
* struct ad9834_state - driver instance specific data
* @spi: spi_device
* @reg: supply regulator
* @mclk: external master clock
* @control: cached control word
* @xfer: default spi transfer
* @msg: default spi message
* @freq_xfer: tuning word spi transfer
* @freq_msg: tuning word spi message
* @data: spi transmit buffer
* @freq_data: tuning word spi transmit buffer
*/
struct ad9834_state {
struct spi_device *spi;
struct regulator *reg;
unsigned int mclk;
unsigned short control;
unsigned short devid;
struct spi_transfer xfer;
struct spi_message msg;
struct spi_transfer freq_xfer[2];
struct spi_message freq_msg;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
__be16 data ____cacheline_aligned;
__be16 freq_data[2];
};
/*
* TODO: struct ad7887_platform_data needs to go into include/linux/iio
*/
......@@ -97,15 +36,4 @@ struct ad9834_platform_data {
bool en_signbit_msb_out;
};
/**
* ad9834_supported_device_ids:
*/
enum ad9834_supported_device_ids {
ID_AD9833,
ID_AD9834,
ID_AD9837,
ID_AD9838,
};
#endif /* IIO_DDS_AD9834_H_ */
......@@ -345,12 +345,12 @@ static ssize_t ad5933_store_frequency(struct device *dev,
return ret ? ret : len;
}
static IIO_DEVICE_ATTR(out_voltage0_freq_start, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(out_voltage0_freq_start, 0644,
ad5933_show_frequency,
ad5933_store_frequency,
AD5933_REG_FREQ_START);
static IIO_DEVICE_ATTR(out_voltage0_freq_increment, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(out_voltage0_freq_increment, 0644,
ad5933_show_frequency,
ad5933_store_frequency,
AD5933_REG_FREQ_INC);
......@@ -469,32 +469,32 @@ static ssize_t ad5933_store(struct device *dev,
return ret ? ret : len;
}
static IIO_DEVICE_ATTR(out_voltage0_scale, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(out_voltage0_scale, 0644,
ad5933_show,
ad5933_store,
AD5933_OUT_RANGE);
static IIO_DEVICE_ATTR(out_voltage0_scale_available, S_IRUGO,
static IIO_DEVICE_ATTR(out_voltage0_scale_available, 0444,
ad5933_show,
NULL,
AD5933_OUT_RANGE_AVAIL);
static IIO_DEVICE_ATTR(in_voltage0_scale, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(in_voltage0_scale, 0644,
ad5933_show,
ad5933_store,
AD5933_IN_PGA_GAIN);
static IIO_DEVICE_ATTR(in_voltage0_scale_available, S_IRUGO,
static IIO_DEVICE_ATTR(in_voltage0_scale_available, 0444,
ad5933_show,
NULL,
AD5933_IN_PGA_GAIN_AVAIL);
static IIO_DEVICE_ATTR(out_voltage0_freq_points, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(out_voltage0_freq_points, 0644,
ad5933_show,
ad5933_store,
AD5933_FREQ_POINTS);
static IIO_DEVICE_ATTR(out_voltage0_settling_cycles, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(out_voltage0_settling_cycles, 0644,
ad5933_show,
ad5933_store,
AD5933_OUT_SETTLING_CYCLES);
......
......@@ -3,6 +3,7 @@
* ISL29028 is Concurrent Ambient Light and Proximity Sensor
*
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2016-2017 Brian Masney <masneyb@onstation.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
......@@ -63,6 +64,9 @@
#define ISL29028_POWER_OFF_DELAY_MS 2000
static const unsigned int isl29028_prox_sleep_time[] = {800, 400, 200, 100, 75,
50, 12, 0};
enum isl29028_als_ir_mode {
ISL29028_MODE_NONE = 0,
ISL29028_MODE_ALS,
......@@ -78,22 +82,29 @@ struct isl29028_chip {
enum isl29028_als_ir_mode als_ir_mode;
};
static int isl29028_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)
};
......
......@@ -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,
......
#ifndef _ADE7753_H
#define _ADE7753_H
#define ADE7753_WAVEFORM 0x01
#define ADE7753_AENERGY 0x02
#define ADE7753_RAENERGY 0x03
#define ADE7753_LAENERGY 0x04
#define ADE7753_VAENERGY 0x05
#define ADE7753_RVAENERGY 0x06
#define ADE7753_LVAENERGY 0x07
#define ADE7753_LVARENERGY 0x08
#define ADE7753_MODE 0x09
#define ADE7753_IRQEN 0x0A
#define ADE7753_STATUS 0x0B
#define ADE7753_RSTSTATUS 0x0C
#define ADE7753_CH1OS 0x0D
#define ADE7753_CH2OS 0x0E
#define ADE7753_GAIN 0x0F
#define ADE7753_PHCAL 0x10
#define ADE7753_APOS 0x11
#define ADE7753_WGAIN 0x12
#define ADE7753_WDIV 0x13
#define ADE7753_CFNUM 0x14
#define ADE7753_CFDEN 0x15
#define ADE7753_IRMS 0x16
#define ADE7753_VRMS 0x17
#define ADE7753_IRMSOS 0x18
#define ADE7753_VRMSOS 0x19
#define ADE7753_VAGAIN 0x1A
#define ADE7753_VADIV 0x1B
#define ADE7753_LINECYC 0x1C
#define ADE7753_ZXTOUT 0x1D
#define ADE7753_SAGCYC 0x1E
#define ADE7753_SAGLVL 0x1F
#define ADE7753_IPKLVL 0x20
#define ADE7753_VPKLVL 0x21
#define ADE7753_IPEAK 0x22
#define ADE7753_RSTIPEAK 0x23
#define ADE7753_VPEAK 0x24
#define ADE7753_RSTVPEAK 0x25
#define ADE7753_TEMP 0x26
#define ADE7753_PERIOD 0x27
#define ADE7753_TMODE 0x3D
#define ADE7753_CHKSUM 0x3E
#define ADE7753_DIEREV 0x3F
#define ADE7753_READ_REG(a) a
#define ADE7753_WRITE_REG(a) ((a) | 0x80)
#define ADE7753_MAX_TX 4
#define ADE7753_MAX_RX 4
#define ADE7753_STARTUP_DELAY 1000
#define ADE7753_SPI_SLOW (u32)(300 * 1000)
#define ADE7753_SPI_BURST (u32)(1000 * 1000)
#define ADE7753_SPI_FAST (u32)(2000 * 1000)
/**
* struct ade7753_state - device instance specific data
* @us: actual spi_device
* @tx: transmit buffer
* @rx: receive buffer
* @buf_lock: mutex to protect tx and rx
**/
struct ade7753_state {
struct spi_device *us;
struct mutex buf_lock;
u8 tx[ADE7753_MAX_TX] ____cacheline_aligned;
u8 rx[ADE7753_MAX_RX];
};
#endif
......@@ -426,9 +426,7 @@ static int ade7854_set_irq(struct device *dev, bool enable)
else
irqen &= ~BIT(17);
ret = st->write_reg_32(dev, ADE7854_MASK0, irqen);
return ret;
return st->write_reg_32(dev, ADE7854_MASK0, irqen);
}
static int ade7854_initial_setup(struct iio_dev *indio_dev)
......
......@@ -81,94 +81,94 @@
IIO_DEVICE_ATTR(reactive_power_c_gain, _mode, _show, _store, _addr)
#define IIO_DEV_ATTR_CURRENT_A(_show, _addr) \
IIO_DEVICE_ATTR(current_a, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(current_a, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_CURRENT_B(_show, _addr) \
IIO_DEVICE_ATTR(current_b, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(current_b, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_CURRENT_C(_show, _addr) \
IIO_DEVICE_ATTR(current_c, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(current_c, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_VOLT_A(_show, _addr) \
IIO_DEVICE_ATTR(volt_a, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(volt_a, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_VOLT_B(_show, _addr) \
IIO_DEVICE_ATTR(volt_b, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(volt_b, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_VOLT_C(_show, _addr) \
IIO_DEVICE_ATTR(volt_c, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(volt_c, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_AENERGY(_show, _addr) \
IIO_DEVICE_ATTR(aenergy, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(aenergy, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_LENERGY(_show, _addr) \
IIO_DEVICE_ATTR(lenergy, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(lenergy, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_RAENERGY(_show, _addr) \
IIO_DEVICE_ATTR(raenergy, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(raenergy, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_LAENERGY(_show, _addr) \
IIO_DEVICE_ATTR(laenergy, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(laenergy, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_VAENERGY(_show, _addr) \
IIO_DEVICE_ATTR(vaenergy, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(vaenergy, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_LVAENERGY(_show, _addr) \
IIO_DEVICE_ATTR(lvaenergy, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(lvaenergy, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_RVAENERGY(_show, _addr) \
IIO_DEVICE_ATTR(rvaenergy, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(rvaenergy, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_LVARENERGY(_show, _addr) \
IIO_DEVICE_ATTR(lvarenergy, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(lvarenergy, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_CHKSUM(_show, _addr) \
IIO_DEVICE_ATTR(chksum, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(chksum, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_ANGLE0(_show, _addr) \
IIO_DEVICE_ATTR(angle0, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(angle0, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_ANGLE1(_show, _addr) \
IIO_DEVICE_ATTR(angle1, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(angle1, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_ANGLE2(_show, _addr) \
IIO_DEVICE_ATTR(angle2, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(angle2, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_AWATTHR(_show, _addr) \
IIO_DEVICE_ATTR(awatthr, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(awatthr, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_BWATTHR(_show, _addr) \
IIO_DEVICE_ATTR(bwatthr, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(bwatthr, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_CWATTHR(_show, _addr) \
IIO_DEVICE_ATTR(cwatthr, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(cwatthr, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_AFWATTHR(_show, _addr) \
IIO_DEVICE_ATTR(afwatthr, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(afwatthr, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_BFWATTHR(_show, _addr) \
IIO_DEVICE_ATTR(bfwatthr, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(bfwatthr, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_CFWATTHR(_show, _addr) \
IIO_DEVICE_ATTR(cfwatthr, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(cfwatthr, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_AVARHR(_show, _addr) \
IIO_DEVICE_ATTR(avarhr, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(avarhr, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_BVARHR(_show, _addr) \
IIO_DEVICE_ATTR(bvarhr, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(bvarhr, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_CVARHR(_show, _addr) \
IIO_DEVICE_ATTR(cvarhr, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(cvarhr, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_AVAHR(_show, _addr) \
IIO_DEVICE_ATTR(avahr, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(avahr, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_BVAHR(_show, _addr) \
IIO_DEVICE_ATTR(bvahr, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(bvahr, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_CVAHR(_show, _addr) \
IIO_DEVICE_ATTR(cvahr, S_IRUGO, _show, NULL, _addr)
IIO_DEVICE_ATTR(cvahr, 0444, _show, NULL, _addr)
#define IIO_DEV_ATTR_IOS(_mode, _show, _store, _addr) \
IIO_DEVICE_ATTR(ios, _mode, _show, _store, _addr)
......
......@@ -531,36 +531,36 @@ static int ad2s1210_read_raw(struct iio_dev *indio_dev,
return ret;
}
static IIO_DEVICE_ATTR(fclkin, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(fclkin, 0644,
ad2s1210_show_fclkin, ad2s1210_store_fclkin, 0);
static IIO_DEVICE_ATTR(fexcit, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(fexcit, 0644,
ad2s1210_show_fexcit, ad2s1210_store_fexcit, 0);
static IIO_DEVICE_ATTR(control, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(control, 0644,
ad2s1210_show_control, ad2s1210_store_control, 0);
static IIO_DEVICE_ATTR(bits, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(bits, 0644,
ad2s1210_show_resolution, ad2s1210_store_resolution, 0);
static IIO_DEVICE_ATTR(fault, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(fault, 0644,
ad2s1210_show_fault, ad2s1210_clear_fault, 0);
static IIO_DEVICE_ATTR(los_thrd, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(los_thrd, 0644,
ad2s1210_show_reg, ad2s1210_store_reg,
AD2S1210_REG_LOS_THRD);
static IIO_DEVICE_ATTR(dos_ovr_thrd, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(dos_ovr_thrd, 0644,
ad2s1210_show_reg, ad2s1210_store_reg,
AD2S1210_REG_DOS_OVR_THRD);
static IIO_DEVICE_ATTR(dos_mis_thrd, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(dos_mis_thrd, 0644,
ad2s1210_show_reg, ad2s1210_store_reg,
AD2S1210_REG_DOS_MIS_THRD);
static IIO_DEVICE_ATTR(dos_rst_max_thrd, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(dos_rst_max_thrd, 0644,
ad2s1210_show_reg, ad2s1210_store_reg,
AD2S1210_REG_DOS_RST_MAX_THRD);
static IIO_DEVICE_ATTR(dos_rst_min_thrd, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(dos_rst_min_thrd, 0644,
ad2s1210_show_reg, ad2s1210_store_reg,
AD2S1210_REG_DOS_RST_MIN_THRD);
static IIO_DEVICE_ATTR(lot_high_thrd, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(lot_high_thrd, 0644,
ad2s1210_show_reg, ad2s1210_store_reg,
AD2S1210_REG_LOT_HIGH_THRD);
static IIO_DEVICE_ATTR(lot_low_thrd, S_IRUGO | S_IWUSR,
static IIO_DEVICE_ATTR(lot_low_thrd, 0644,
ad2s1210_show_reg, ad2s1210_store_reg,
AD2S1210_REG_LOT_LOW_THRD);
......
......@@ -45,6 +45,10 @@
#define HID_USAGE_SENSOR_DATA_ATMOSPHERIC_PRESSURE 0x200430
#define HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE 0x200431
/* Tempreture (200033) */
#define HID_USAGE_SENSOR_TEMPERATURE 0x200033
#define HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE 0x200434
/* Gyro 3D: (200076) */
#define HID_USAGE_SENSOR_GYRO_3D 0x200076
#define HID_USAGE_SENSOR_DATA_ANGL_VELOCITY 0x200456
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment