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

Jonathan writes:

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

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

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

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

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

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

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

Other
* Mailmap
  - update Matt Ranostay's email address to the Konsolko one.
This commit is contained in:
Greg Kroah-Hartman
2017-03-06 13:17:21 +01:00
74 changed files with 3400 additions and 1125 deletions

View File

@@ -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>

View File

@@ -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.

View File

@@ -1,24 +1,16 @@
What: /sys/bus/iio/devices/iio:deviceX/in_count_count_direction_available
What: /sys/bus/iio/devices/iio:deviceX/in_count_count_mode_available
What: /sys/bus/iio/devices/iio:deviceX/in_count_noise_error_available
What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available
What: /sys/bus/iio/devices/iio:deviceX/in_index_index_polarity_available
What: /sys/bus/iio/devices/iio:deviceX/in_index_synchronous_mode_available
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Discrete set of available values for the respective counter
configuration are listed in this file.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_direction
KernelVersion: 4.9
Contact: linux-iio@vger.kernel.org
Description:
Read-only attribute that indicates whether the counter for
channel Y is counting up or down.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_count_mode
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Count mode for channel Y. Four count modes are available:
@@ -52,7 +44,7 @@ Description:
continuously throughout.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_noise_error
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Read-only attribute that indicates whether excessive noise is
@@ -60,14 +52,14 @@ Description:
irrelevant in non-quadrature clock mode.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_preset
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
If the counter device supports preset registers, the preset
count for channel Y is provided by this attribute.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_quadrature_mode
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Configure channel Y counter for non-quadrature or quadrature
@@ -88,7 +80,7 @@ Description:
decoded for UP/DN clock.
What: /sys/bus/iio/devices/iio:deviceX/in_countY_set_to_preset_on_index
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Whether to set channel Y counter with channel Y preset value
@@ -96,14 +88,14 @@ Description:
Valid attribute values are boolean.
What: /sys/bus/iio/devices/iio:deviceX/in_indexY_index_polarity
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Active level of channel Y index input; irrelevant in
non-synchronous load mode.
What: /sys/bus/iio/devices/iio:deviceX/in_indexY_synchronous_mode
KernelVersion: 4.9
KernelVersion: 4.10
Contact: linux-iio@vger.kernel.org
Description:
Configure channel Y counter for non-synchronous or synchronous

View File

@@ -0,0 +1,38 @@
Analog Devices ADXL345 3-Axis, +/-(2g/4g/8g/16g) Digital Accelerometer
http://www.analog.com/en/products/mems/accelerometers/adxl345.html
Required properties:
- compatible : should be "adi,adxl345"
- reg : the I2C address or SPI chip select number of the sensor
Required properties for SPI bus usage:
- spi-max-frequency : set maximum clock frequency, must be 5000000
- spi-cpol and spi-cpha : must be defined for adxl345 to enable SPI mode 3
Optional properties:
- interrupt-parent : phandle to the parent interrupt controller as documented
in Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
- interrupts: interrupt mapping for IRQ as documented in
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
Example for a I2C device node:
accelerometer@2a {
compatible = "adi,adxl345";
reg = <0x53>;
interrupt-parent = <&gpio1>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
};
Example for a SPI device node:
accelerometer@0 {
compatible = "adi,adxl345";
reg = <0>;
spi-max-frequency = <5000000>;
spi-cpol;
spi-cpha;
interrupt-parent = <&gpio1>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
};

View File

@@ -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>,

View File

@@ -0,0 +1,30 @@
Maxim MAX30102 heart rate and pulse oximeter sensor
* https://datasheets.maximintegrated.com/en/ds/MAX30102.pdf
Required properties:
- compatible: must be "maxim,max30102"
- reg: the I2C address of the sensor
- interrupt-parent: should be the phandle for the interrupt controller
- interrupts: the sole interrupt generated by the device
Refer to interrupt-controller/interrupts.txt for generic
interrupt client node bindings.
Optional properties:
- maxim,red-led-current-microamp: configuration for RED LED current
- maxim,ir-led-current-microamp: configuration for IR LED current
Note that each step is approximately 200 microamps, ranging from 0 uA to
50800 uA.
Example:
max30100@57 {
compatible = "maxim,max30102";
reg = <0x57>;
maxim,red-led-current-microamp = <7000>;
maxim,ir-led-current-microamp = <7000>;
interrupt-parent = <&gpio1>;
interrupts = <16 2>;
};

View File

@@ -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

View File

@@ -0,0 +1,28 @@
* Devantech SRF04 ultrasonic range finder
Bit-banging driver using two GPIOs
Required properties:
- compatible: Should be "devantech,srf04"
- trig-gpios: Definition of the GPIO for the triggering (output)
This GPIO is set for about 10 us by the driver to tell the
device it should initiate the measurement cycle.
- echo-gpios: Definition of the GPIO for the echo (input)
This GPIO is set by the device as soon as an ultrasonic
burst is sent out and reset when the first echo is
received.
Thus this GPIO is set while the ultrasonic waves are doing
one round trip.
It needs to be an GPIO which is able to deliver an
interrupt because the time between two interrupts is
measured in the driver.
See Documentation/devicetree/bindings/gpio/gpio.txt for
information on how to specify a consumer gpio.
Example:
srf04@0 {
compatible = "devantech,srf04";
trig-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
echo-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
};

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,18 @@
/*
* ADXL345 3-Axis Digital Accelerometer
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*/
#ifndef _ADXL345_H_
#define _ADXL345_H_
int adxl345_core_probe(struct device *dev, struct regmap *regmap,
const char *name);
int adxl345_core_remove(struct device *dev);
#endif /* _ADXL345_H_ */

View File

@@ -0,0 +1,179 @@
/*
* ADXL345 3-Axis Digital Accelerometer IIO core driver
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*/
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/iio/iio.h>
#include "adxl345.h"
#define ADXL345_REG_DEVID 0x00
#define ADXL345_REG_POWER_CTL 0x2D
#define ADXL345_REG_DATA_FORMAT 0x31
#define ADXL345_REG_DATAX0 0x32
#define ADXL345_REG_DATAY0 0x34
#define ADXL345_REG_DATAZ0 0x36
#define ADXL345_POWER_CTL_MEASURE BIT(3)
#define ADXL345_POWER_CTL_STANDBY 0x00
#define ADXL345_DATA_FORMAT_FULL_RES BIT(3) /* Up to 13-bits resolution */
#define ADXL345_DATA_FORMAT_2G 0
#define ADXL345_DATA_FORMAT_4G 1
#define ADXL345_DATA_FORMAT_8G 2
#define ADXL345_DATA_FORMAT_16G 3
#define ADXL345_DEVID 0xE5
/*
* In full-resolution mode, scale factor is maintained at ~4 mg/LSB
* in all g ranges.
*
* At +/- 16g with 13-bit resolution, scale is computed as:
* (16 + 16) * 9.81 / (2^13 - 1) = 0.0383
*/
static const int adxl345_uscale = 38300;
struct adxl345_data {
struct regmap *regmap;
u8 data_range;
};
#define ADXL345_CHANNEL(reg, axis) { \
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.address = reg, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec adxl345_channels[] = {
ADXL345_CHANNEL(ADXL345_REG_DATAX0, X),
ADXL345_CHANNEL(ADXL345_REG_DATAY0, Y),
ADXL345_CHANNEL(ADXL345_REG_DATAZ0, Z),
};
static int adxl345_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct adxl345_data *data = iio_priv(indio_dev);
__le16 regval;
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
/*
* Data is stored in adjacent registers:
* ADXL345_REG_DATA(X0/Y0/Z0) contain the least significant byte
* and ADXL345_REG_DATA(X0/Y0/Z0) + 1 the most significant byte
*/
ret = regmap_bulk_read(data->regmap, chan->address, &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");

View File

@@ -0,0 +1,73 @@
/*
* ADXL345 3-Axis Digital Accelerometer I2C driver
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* 7-bit I2C slave address: 0x1D (ALT ADDRESS pin tied to VDDIO) or
* 0x53 (ALT ADDRESS pin grounded)
*/
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include "adxl345.h"
static const struct regmap_config adxl345_i2c_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int adxl345_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regmap *regmap;
regmap = devm_regmap_init_i2c(client, &adxl345_i2c_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "Error initializing i2c regmap: %ld\n",
PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return adxl345_core_probe(&client->dev, regmap, id ? id->name : NULL);
}
static int adxl345_i2c_remove(struct i2c_client *client)
{
return adxl345_core_remove(&client->dev);
}
static const struct i2c_device_id adxl345_i2c_id[] = {
{ "adxl345", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adxl345_i2c_id);
static const struct of_device_id adxl345_of_match[] = {
{ .compatible = "adi,adxl345" },
{ },
};
MODULE_DEVICE_TABLE(of, adxl345_of_match);
static struct i2c_driver adxl345_i2c_driver = {
.driver = {
.name = "adxl345_i2c",
.of_match_table = adxl345_of_match,
},
.probe = adxl345_i2c_probe,
.remove = adxl345_i2c_remove,
.id_table = adxl345_i2c_id,
};
module_i2c_driver(adxl345_i2c_driver);
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer I2C driver");
MODULE_LICENSE("GPL v2");

View File

@@ -0,0 +1,81 @@
/*
* ADXL345 3-Axis Digital Accelerometer SPI driver
*
* Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*/
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include "adxl345.h"
#define ADXL345_MAX_SPI_FREQ_HZ 5000000
static const struct regmap_config adxl345_spi_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
/* Setting bits 7 and 6 enables multiple-byte read */
.read_flag_mask = BIT(7) | BIT(6),
};
static int adxl345_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct regmap *regmap;
/* Bail out if max_speed_hz exceeds 5 MHz */
if (spi->max_speed_hz > ADXL345_MAX_SPI_FREQ_HZ) {
dev_err(&spi->dev, "SPI CLK, %d Hz exceeds 5 MHz\n",
spi->max_speed_hz);
return -EINVAL;
}
regmap = devm_regmap_init_spi(spi, &adxl345_spi_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return adxl345_core_probe(&spi->dev, regmap, id->name);
}
static int adxl345_spi_remove(struct spi_device *spi)
{
return adxl345_core_remove(&spi->dev);
}
static const struct spi_device_id adxl345_spi_id[] = {
{ "adxl345", 0 },
{ }
};
MODULE_DEVICE_TABLE(spi, adxl345_spi_id);
static const struct of_device_id adxl345_of_match[] = {
{ .compatible = "adi,adxl345" },
{ },
};
MODULE_DEVICE_TABLE(of, adxl345_of_match);
static struct spi_driver adxl345_spi_driver = {
.driver = {
.name = "adxl345_spi",
.of_match_table = adxl345_of_match,
},
.probe = adxl345_spi_probe,
.remove = adxl345_spi_remove,
.id_table = adxl345_spi_id,
};
module_spi_driver(adxl345_spi_driver);
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer SPI driver");
MODULE_LICENSE("GPL v2");

View File

@@ -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

View File

@@ -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

View File

@@ -38,27 +38,30 @@
/*
* LPC32XX registers definitions
*/
#define LPC32XX_ADC_SELECT(x) ((x) + 0x04)
#define LPC32XX_ADC_CTRL(x) ((x) + 0x08)
#define LPC32XX_ADC_VALUE(x) ((x) + 0x48)
#define LPC32XXAD_SELECT(x) ((x) + 0x04)
#define LPC32XXAD_CTRL(x) ((x) + 0x08)
#define LPC32XXAD_VALUE(x) ((x) + 0x48)
/* Bit definitions for LPC32XX_ADC_SELECT: */
#define AD_REFm 0x00000200 /* constant, always write this value! */
#define AD_REFp 0x00000080 /* constant, always write this value! */
#define AD_IN 0x00000010 /* multiple of this is the */
/* channel number: 0, 1, 2 */
#define AD_INTERNAL 0x00000004 /* constant, always write this value! */
/* Bit definitions for LPC32XXAD_SELECT: */
/* constant, always write this value! */
#define LPC32XXAD_REFm 0x00000200
/* constant, always write this value! */
#define LPC32XXAD_REFp 0x00000080
/* multiple of this is the channel number: 0, 1, 2 */
#define LPC32XXAD_IN 0x00000010
/* constant, always write this value! */
#define LPC32XXAD_INTERNAL 0x00000004
/* Bit definitions for LPC32XX_ADC_CTRL: */
#define AD_STROBE 0x00000002
#define AD_PDN_CTRL 0x00000004
/* Bit definitions for LPC32XXAD_CTRL: */
#define LPC32XXAD_STROBE 0x00000002
#define LPC32XXAD_PDN_CTRL 0x00000004
/* Bit definitions for LPC32XX_ADC_VALUE: */
#define ADC_VALUE_MASK 0x000003FF
/* Bit definitions for LPC32XXAD_VALUE: */
#define LPC32XXAD_VALUE_MASK 0x000003FF
#define MOD_NAME "lpc32xx-adc"
#define LPC32XXAD_NAME "lpc32xx-adc"
struct lpc32xx_adc_info {
struct lpc32xx_adc_state {
void __iomem *adc_base;
struct clk *clk;
struct completion completion;
@@ -72,20 +75,21 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
int *val2,
long mask)
{
struct lpc32xx_adc_info *info = iio_priv(indio_dev);
struct lpc32xx_adc_state *st = iio_priv(indio_dev);
if (mask == IIO_CHAN_INFO_RAW) {
mutex_lock(&indio_dev->mlock);
clk_prepare_enable(info->clk);
clk_prepare_enable(st->clk);
/* Measurement setup */
__raw_writel(AD_INTERNAL | (chan->address) | AD_REFp | AD_REFm,
LPC32XX_ADC_SELECT(info->adc_base));
__raw_writel(LPC32XXAD_INTERNAL | (chan->address) |
LPC32XXAD_REFp | LPC32XXAD_REFm,
LPC32XXAD_SELECT(st->adc_base));
/* Trigger conversion */
__raw_writel(AD_PDN_CTRL | AD_STROBE,
LPC32XX_ADC_CTRL(info->adc_base));
wait_for_completion(&info->completion); /* set by ISR */
clk_disable_unprepare(info->clk);
*val = info->value;
__raw_writel(LPC32XXAD_PDN_CTRL | LPC32XXAD_STROBE,
LPC32XXAD_CTRL(st->adc_base));
wait_for_completion(&st->completion); /* set by ISR */
clk_disable_unprepare(st->clk);
*val = st->value;
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
@@ -104,7 +108,7 @@ static const struct iio_info lpc32xx_adc_iio_info = {
.indexed = 1, \
.channel = _index, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.address = AD_IN * _index, \
.address = LPC32XXAD_IN * _index, \
.scan_index = _index, \
}
@@ -116,19 +120,19 @@ static const struct iio_chan_spec lpc32xx_adc_iio_channels[] = {
static irqreturn_t lpc32xx_adc_isr(int irq, void *dev_id)
{
struct lpc32xx_adc_info *info = dev_id;
struct lpc32xx_adc_state *st = dev_id;
/* Read value and clear irq */
info->value = __raw_readl(LPC32XX_ADC_VALUE(info->adc_base)) &
ADC_VALUE_MASK;
complete(&info->completion);
st->value = __raw_readl(LPC32XXAD_VALUE(st->adc_base)) &
LPC32XXAD_VALUE_MASK;
complete(&st->completion);
return IRQ_HANDLED;
}
static int lpc32xx_adc_probe(struct platform_device *pdev)
{
struct lpc32xx_adc_info *info = NULL;
struct lpc32xx_adc_state *st = NULL;
struct resource *res;
int retval = -ENODEV;
struct iio_dev *iodev = NULL;
@@ -140,23 +144,23 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
return -ENXIO;
}
iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
if (!iodev)
return -ENOMEM;
info = iio_priv(iodev);
st = iio_priv(iodev);
info->adc_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!info->adc_base) {
st->adc_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!st->adc_base) {
dev_err(&pdev->dev, "failed mapping memory\n");
return -EBUSY;
}
info->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(info->clk)) {
st->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(st->clk)) {
dev_err(&pdev->dev, "failed getting clock\n");
return PTR_ERR(info->clk);
return PTR_ERR(st->clk);
}
irq = platform_get_irq(pdev, 0);
@@ -166,7 +170,7 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
}
retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0,
MOD_NAME, info);
LPC32XXAD_NAME, st);
if (retval < 0) {
dev_err(&pdev->dev, "failed requesting interrupt\n");
return retval;
@@ -174,9 +178,9 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, iodev);
init_completion(&info->completion);
init_completion(&st->completion);
iodev->name = MOD_NAME;
iodev->name = LPC32XXAD_NAME;
iodev->dev.parent = &pdev->dev;
iodev->info = &lpc32xx_adc_iio_info;
iodev->modes = INDIO_DIRECT_MODE;
@@ -203,7 +207,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_adc_match);
static struct platform_driver lpc32xx_adc_driver = {
.probe = lpc32xx_adc_probe,
.driver = {
.name = MOD_NAME,
.name = LPC32XXAD_NAME,
.of_match_table = of_match_ptr(lpc32xx_adc_match),
},
};

View File

@@ -18,7 +18,9 @@
#include <linux/io.h>
#include <linux/iio/iio.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@@ -163,6 +165,7 @@
#define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8)
#define MESON_SAR_ADC_MAX_FIFO_SIZE 32
#define MESON_SAR_ADC_TIMEOUT 100 /* ms */
#define MESON_SAR_ADC_CHAN(_chan) { \
.type = IIO_VOLTAGE, \
@@ -229,6 +232,7 @@ struct meson_sar_adc_priv {
struct clk_gate clk_gate;
struct clk *adc_div_clk;
struct clk_divider clk_div;
struct completion done;
};
static const struct regmap_config meson_sar_adc_regmap_config = {
@@ -274,33 +278,31 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
int *val)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
int ret, regval, fifo_chan, fifo_val, sum = 0, count = 0;
int regval, fifo_chan, fifo_val, count;
ret = meson_sar_adc_wait_busy_clear(indio_dev);
if (ret)
return ret;
if(!wait_for_completion_timeout(&priv->done,
msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT)))
return -ETIMEDOUT;
while (meson_sar_adc_get_fifo_count(indio_dev) > 0 &&
count < MESON_SAR_ADC_MAX_FIFO_SIZE) {
regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &regval);
fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK,
regval);
if (fifo_chan != chan->channel)
continue;
fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK,
regval);
fifo_val &= (BIT(priv->data->resolution) - 1);
sum += fifo_val;
count++;
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))

Some files were not shown because too many files have changed in this diff Show More