Commit 6a8b25ab authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

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

Jonathan writes:

1st round of IIO new device support, features and cleanup for the 4.18 cycle

A nice mix this time of excellent cleanups (many to send drivers
speeding toward staging graduations) and new drivers / device support.
A good part of this is Brian Masney's never ending task on the tsl2x7x
driver.  The end is in sight so hopefully we'll get that one out of
staging very soon!

New device support
* AD5686
  - Support AD5685R (was wrongly present as AD5685)
  - Support AD5672R, AD5676, AD5676, AD5684R and AD5686R 4 and 8 channel
    SPI DACs with various precisions.
  - Support AD5671R, AD5675R, AD5694, AD5694R, AD5695R, AD5696 and AD5696R
    I2C DACs with various percisions and numbers of channels.
* Analog front end rescale driver - New driver.
  - Support current sensing usings a shunt resistor.
  - Support simple voltage dividers.
  - support simple current sense amplifiers.
* TI dac5571
  - New driver and device bindings supporting:
    dac5571, dac6571, dac7571, dac5574, dac6574, dac7574,
    dac5573, dac6573 and dac7573
* Meson-adc
  - Support for Meson AXG with DT bindings.
* mpu6050
  - Support the mpu9255 which only requires additional WHOAMI entry and
    compatible string.
* st_lsm6dsx
  - Support for lsm330dlc combinded accelerometer and gyro sensors with
    DT bindings.
* stm32_adc
  - Add support for STM32MP1 with bindings.

Staging graduations
* adis16201 after some excelent cleanup by Himanshu Jha.
* adis16029 after some excelent cleanup by Shreeya Patel.

New features:
* ABI docs
  - Add core ABI docs for angle channels.
* inv_mpu6050
  - Provide support for the full range of interrupts the device
    supports.
* st_accel
  - Add SMO8840 ACPI ID seen in the wild on some Lenovo machines.
* stx104
  - Provide a multiple gpio get function.

Cleanups / Minor fixes
* core
  - Use new nested structure support to improve kernel-doc.
* ad2s1200
  - Use be16_to_cpup instead of opencoding.
* ad5686
  - Indentation tidy up.
  - Switch to SPDX
  - Refactor to allow various numbers of channels.
  - Refactor to separate core and SPI specific support, prior to
    addition of i2c equivalent devices.
* ad7606
  - Use drvdata directly from device rather than boucing via the
    platform_device structure.
* ad7746
  - Replace opencoded byte swapped i2c calls with _swapped variants.
  - White space and line break readability improvements.
  - Reorder includes and variable declarations where appropriate.
* ad7791
  - Changes to the AD ADC library used by this driver took in the
    sampling frequency.  This lead to be the wrong path being the one
    tied to the resulting attribute, so it didn't work, and a warning
    to be printed.
* ad7780
  - Remove apparent support for sampling frequency control on devices
    that don't support changing the sampling attributes.
* ade7854
  - Fix a read of the wrong number of bits.
  - Improve error handling on i2c read/write errors.
  - Rework i2c and spi code to reduce duplication.
* adis16201 (staging)
  - Improve meaning inherent in some macro names by adding units etc
    where relevant.
  - Adjust comments to improve detail and drop the irrelevant.
  - Rename register address definitions definitions to add a _REG
    postfix, clearly separating them from field definitions. Reorganize
    the definitions to group register address and fields.
  - Use sign_extend32 rather than open coding.
  - Reverse Xmas tree ordering where appropriate and align function args.
  - Remove unused headers.
  - Use GENMASK where appropriate instead of open coding.
* adis16209 (staging)
  - Indent field definitions to visually separate them from
    register address definitions.
  - Use reverse xmas tree ordering where appropriate.
  - Add some whitespace where it will help readability.
  - Drop some unused headers.
  - Use GENMASK where appropriate.
* ad2s1200
  - Drop unnecessary includes and reorder alphabetically.
  - Reverse xmas tree and blank line cleanups.
* atlas-ph-sensor
  - Use msleep instead of usleep_range where the precise value doesn't
    matter and the delays are long.
* bcm150
  - Drop transaction splitting as core now handles it.
* cros_ec
  - Move the shared header to the include/iio/common directory.
    This brings it inline with the other multiple type devices.
  - Use drvdata directly from device rather than boucing via the
    platform_device structure.
* hid-sensors
  - Use drvdata directly from device rather than boucing via the
    platform_device structure.
* inv_mpu6050
  - Clear out a second function definition for the same function.
  - Don't flush fifo when the iio buffer is full but just drop excess
    data.
  - Tidy up set_power_itg and ensure it is used in the right places.
  - Use set_power_itg rather than opencoding it again in the i2c mux
    control.
  - Make sure error paths disable the power if undoing power on.
  - Used managed devm_ functions during probe. Delete remove function.
  - Refactor to pull raw data read out of read_raw function.
  - Simplify data reading error paths.
  - Only enable the i2c mux for chips with the i2c aux bus (not icm20608)
  - Fix a potential deadlock due to varying lock ordering.
  - Fix an issue where first sample from gyro after enabling is unstable
    by dropping the first sample.
  - Fix an issue where the user_ctrl register is incorrectly overwritten.
  - Tidy up some grammar and spelling minor issus.
* mcp320x
  - Use vendor compatible strings.
* mcp4018
  - Switch to using i2c .probe_new.
* mcp4351
  - switch to using i2c .probe_new.
* meson-adc
  - rework handing on common ADC platform data so it can be shared
    across multiple families of SoCs.
* sca3000
  - Fix an error handling path if the ring configure fails.
* st_lsm6dsx
  - Fix a wrong fifo threshold mask (no actual effect)
* stm32-dfsdm
  - Style fixes and cleanups.
  - Check filter ID is in range and check spi-max-frequency.
* tsl2x7x (staging)
  - Drop some unnecessary function calls, unused variables and
    unnecessary local variables.
  - Fix wrong interrupt type.
  - Avoid unnecessary double clear of interrupt.
  - Simplify proximity calibration call which did various things
    unrelated to actually calibrating.
  - Separate control of the proximity and ALS interrupts.
  - Improve consistency of logging.
  - Separate ALS and proximity persistence settings as they have
    separate hardware controls.
  - Tidy up variable ordering.
  - Add Brian to copyright notice given consider work on this driver.
  - Take advantage of hardware support for I2C address auto increment.
  - Combine individuaal enable and period attributes for the two
    directions on the threshold events into a single value as the
    hardware doesn't separate them.
  - Move integration_time* attributes from light channel to
    intensity value as they effect the intensity readings directly
    and the light reading only indirectly.  Hence this better
    reflects reality. Also move the calibscale_available.
  - Avoid returning an error in the IRQ handler.
  - Hard code the reg value in _clear_interrupts as it only takes
    one value in the code.   Result is the function has little
    purpose so opencode the two remaining i2c_smbus_write_byte
    calls.
  - Drop some unnecessary checking of the chip status register.
  - Tidy up return path in _write_interrupt_config.
  - Tidy up the ID verification code.
  - Move the power and diode settings defines into the header as these
    are needed for platform data configuration.
  - Various renames and comment cleanups for consistency and clarity.
  - Use actual device defaults for default startup settings.
  - SPDX
  - Add some range sanity checking to sysfs attribute writes.
  - Don't provide event interfaces if the interrupt line isn't available.
  - Use IIO_CONST_ATTR macro for calibscale_available as it's a constant
    string.
  - Fix the integration time and lux equations.
  - Make device IDs explicit index values in the device_channel_config array.
parents 26a5e9b8 d58c67d1
......@@ -190,6 +190,13 @@ Description:
but should match other such assignments on device).
Units after application of scale and offset are m/s^2.
What: /sys/bus/iio/devices/iio:deviceX/in_angl_raw
KernelVersion: 4.17
Contact: linux-iio@vger.kernel.org
Description:
Angle of rotation. Units after application of scale and offset
are radians.
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_raw
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_raw
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_raw
......@@ -297,6 +304,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_pressure_offset
What: /sys/bus/iio/devices/iio:deviceX/in_humidityrelative_offset
What: /sys/bus/iio/devices/iio:deviceX/in_magn_offset
What: /sys/bus/iio/devices/iio:deviceX/in_rot_offset
What: /sys/bus/iio/devices/iio:deviceX/in_angl_offset
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
......@@ -350,6 +358,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_humidityrelative_scale
What: /sys/bus/iio/devices/iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_scale
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance_scale
What: /sys/bus/iio/devices/iio:deviceX/in_countY_scale
What: /sys/bus/iio/devices/iio:deviceX/in_angl_scale
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
......
......@@ -7,6 +7,7 @@ Required properties:
- "amlogic,meson-gxbb-saradc" for GXBB
- "amlogic,meson-gxl-saradc" for GXL
- "amlogic,meson-gxm-saradc" for GXM
- "amlogic,meson-axg-saradc" for AXG
along with the generic "amlogic,meson-saradc"
- reg: the physical base address and length of the registers
- interrupts: the interrupt indicating end of sampling
......
......@@ -49,7 +49,7 @@ Required properties:
Examples:
spi_controller {
mcp3x0x@0 {
compatible = "mcp3002";
compatible = "microchip,mcp3002";
reg = <0>;
spi-max-frequency = <1000000>;
vref-supply = <&vref_reg>;
......
......@@ -24,8 +24,11 @@ Required properties:
- compatible: Should be one of:
"st,stm32f4-adc-core"
"st,stm32h7-adc-core"
"st,stm32mp1-adc-core"
- reg: Offset and length of the ADC block register set.
- interrupts: Must contain the interrupt for ADC block.
- interrupts: One or more interrupts for ADC block. Some parts like stm32f4
and stm32h7 share a common ADC interrupt line. stm32mp1 has two separate
interrupt lines, one for each ADC within ADC block.
- clocks: Core can use up to two clocks, depending on part used:
- "adc" clock: for the analog circuitry, common to all ADCs.
It's required on stm32f4.
......@@ -53,6 +56,7 @@ Required properties:
- compatible: Should be one of:
"st,stm32f4-adc"
"st,stm32h7-adc"
"st,stm32mp1-adc"
- reg: Offset of ADC instance in ADC block (e.g. may be 0x0, 0x100, 0x200).
- clocks: Input clock private to this ADC instance. It's required only on
stm32f4, that has per instance clock input for registers access.
......
Current Sense Amplifier
=======================
When an io-channel measures the output voltage from a current sense
amplifier, the interesting mesaurement is almost always the current
through the sense resistor, not the voltage output. This binding
describes such a current sense circuit.
Required properties:
- compatible : "current-sense-amplifier"
- io-channels : Channel node of a voltage io-channel.
- sense-resistor-micro-ohms : The sense resistance in microohms.
Optional properties:
- sense-gain-mult: Amplifier gain multiplier. The default is <1>.
- sense-gain-div: Amplifier gain divider. The default is <1>.
Example:
sysi {
compatible = "current-sense-amplifier";
io-channels = <&tiadc 0>;
sense-resistor-micro-ohms = <20000>;
sense-gain-mul = <50>;
};
Current Sense Shunt
===================
When an io-channel measures the voltage over a current sense shunt,
the interesting mesaurement is almost always the current through the
shunt, not the voltage over it. This binding describes such a current
sense circuit.
Required properties:
- compatible : "current-sense-shunt"
- io-channels : Channel node of a voltage io-channel.
- shunt-resistor-micro-ohms : The shunt resistance in microohms.
Example:
The system current is measured by measuring the voltage over a
3.3 ohms shunt resistor.
sysi {
compatible = "current-sense-shunt";
io-channels = <&tiadc 0>;
/* Divide the voltage by 3300000/1000000 (or 3.3) for the current. */
shunt-resistor-micro-ohms = <3300000>;
};
&i2c {
tiadc: adc@48 {
compatible = "ti,ads1015";
reg = <0x48>;
#io-channel-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 { /* IN0,IN1 differential */
reg = <0>;
ti,gain = <1>;
ti,datarate = <4>;
};
};
};
Voltage divider
===============
When an io-channel measures the midpoint of a voltage divider, the
interesting voltage is often the voltage over the full resistance
of the divider. This binding describes the voltage divider in such
a curcuit.
Vin ----.
|
.-----.
| R |
'-----'
|
+---- Vout
|
.-----.
| Rout|
'-----'
|
GND
Required properties:
- compatible : "voltage-divider"
- io-channels : Channel node of a voltage io-channel measuring Vout.
- output-ohms : Resistance Rout over which the output voltage is measured.
See full-ohms.
- full-ohms : Resistance R + Rout for the full divider. The io-channel
is scaled by the Rout / (R + Rout) quotient.
Example:
The system voltage is circa 12V, but divided down with a 22/222
voltage divider (R = 200 Ohms, Rout = 22 Ohms) and fed to an ADC.
sysv {
compatible = "voltage-divider";
io-channels = <&maxadc 1>;
/* Scale the system voltage by 22/222 to fit the ADC range. */
output-ohms = <22>;
full-ohms = <222>; /* 200 + 22 */
};
&spi {
maxadc: adc@0 {
compatible = "maxim,max1027";
reg = <0>;
#io-channel-cells = <1>;
interrupt-parent = <&gpio5>;
interrupts = <15 IRQ_TYPE_EDGE_RISING>;
spi-max-frequency = <1000000>;
};
};
* Texas Instruments DAC5571 Family
Required properties:
- compatible: Should contain
"ti,dac5571"
"ti,dac6571"
"ti,dac7571"
"ti,dac5574"
"ti,dac6574"
"ti,dac7574"
"ti,dac5573"
"ti,dac6573"
"ti,dac7573"
- reg: Should contain the DAC I2C address
Optional properties:
- vref-supply: The regulator supply for DAC reference voltage
Example:
dac@0 {
compatible = "ti,dac5571";
reg = <0x4C>;
vref-supply = <&vdd_supply>;
};
......@@ -8,10 +8,16 @@ Required properties:
"invensense,mpu6500"
"invensense,mpu9150"
"invensense,mpu9250"
"invensense,mpu9255"
"invensense,icm20608"
- reg : the I2C address of the sensor
- interrupt-parent : should be the phandle for the interrupt controller
- interrupts : interrupt mapping for GPIO IRQ
- interrupts: interrupt mapping for IRQ. It should be configured with flags
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_LEVEL_LOW or
IRQ_TYPE_EDGE_FALLING.
Refer to interrupt-controller/interrupts.txt for generic interrupt client node
bindings.
Optional properties:
- mount-matrix: an optional 3x3 mounting rotation matrix
......@@ -24,7 +30,7 @@ Example:
compatible = "invensense,mpu6050";
reg = <0x68>;
interrupt-parent = <&gpio1>;
interrupts = <18 1>;
interrupts = <18 IRQ_TYPE_EDGE_RISING>;
mount-matrix = "-0.984807753012208", /* x0 */
"0", /* y0 */
"-0.173648177666930", /* z0 */
......@@ -41,7 +47,7 @@ Example:
compatible = "invensense,mpu9250";
reg = <0x68>;
interrupt-parent = <&gpio3>;
interrupts = <21 1>;
interrupts = <21 IRQ_TYPE_LEVEL_HIGH>;
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
......
......@@ -6,6 +6,7 @@ Required properties:
"st,lsm6ds3h"
"st,lsm6dsl"
"st,lsm6dsm"
"st,ism330dlc"
- reg: i2c address of the sensor / spi cs line
Optional properties:
......
......@@ -794,6 +794,14 @@ M: Michael Hanselmann <linux-kernel@hansmi.ch>
S: Supported
F: drivers/macintosh/ams/
ANALOG DEVICES INC AD5686 DRIVER
M: Stefan Popa <stefan.popa@analog.com>
L: linux-pm@vger.kernel.org
W: http://ez.analog.com/community/linux-device-drivers
S: Supported
F: drivers/iio/dac/ad5686*
F: drivers/iio/dac/ad5696*
ANALOG DEVICES INC AD9389B DRIVER
M: Hans Verkuil <hans.verkuil@cisco.com>
L: linux-media@vger.kernel.org
......@@ -6914,6 +6922,15 @@ F: drivers/staging/iio/
F: include/linux/iio/
F: tools/iio/
IIO UNIT CONVERTER
M: Peter Rosin <peda@axentia.se>
L: linux-iio@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/iio/afe/current-sense-amplifier.txt
F: Documentation/devicetree/bindings/iio/afe/current-sense-shunt.txt
F: Documentation/devicetree/bindings/iio/afe/voltage-divider.txt
F: drivers/iio/afe/iio-rescale.c
IKANOS/ADI EAGLE ADSL USB DRIVER
M: Matthieu Castet <castet.matthieu@free.fr>
M: Stanislaw Gruszka <stf_xl@wp.pl>
......
......@@ -70,6 +70,7 @@ config IIO_TRIGGERED_EVENT
source "drivers/iio/accel/Kconfig"
source "drivers/iio/adc/Kconfig"
source "drivers/iio/afe/Kconfig"
source "drivers/iio/amplifiers/Kconfig"
source "drivers/iio/chemical/Kconfig"
source "drivers/iio/common/Kconfig"
......
......@@ -15,6 +15,7 @@ obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o
obj-y += accel/
obj-y += adc/
obj-y += afe/
obj-y += amplifiers/
obj-y += buffer/
obj-y += chemical/
......
......@@ -5,6 +5,30 @@
menu "Accelerometers"
config ADIS16201
tristate "Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer"
depends on SPI
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say Y here to build support for Analog Devices adis16201 dual-axis
digital inclinometer and accelerometer.
To compile this driver as a module, say M here: the module will
be called adis16201.
config ADIS16209
tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer"
depends on SPI
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say Y here to build support for Analog Devices adis16209 dual-axis digital inclinometer
and accelerometer.
To compile this driver as a module, say M here: the module will be
called adis16209.
config ADXL345
tristate
......
......@@ -4,6 +4,8 @@
#
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ADIS16201) += adis16201.o
obj-$(CONFIG_ADIS16209) += adis16209.o
obj-$(CONFIG_ADXL345) += adxl345_core.o
obj-$(CONFIG_ADXL345_I2C) += adxl345_i2c.o
obj-$(CONFIG_ADXL345_SPI) += adxl345_spi.o
......
......@@ -6,7 +6,6 @@
* Licensed under the GPL-2 or later.
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/list.h>
......@@ -16,8 +15,6 @@
#include <linux/sysfs.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
#include <linux/iio/imu/adis.h>
#define ADIS16209_STARTUP_DELAY_MS 220
......@@ -115,25 +112,22 @@ static int adis16209_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct adis *st = iio_priv(indio_dev);
int bits;
s16 val16;
u8 addr;
int m;
if (mask != IIO_CHAN_INFO_CALIBBIAS)
return -EINVAL;
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
switch (chan->type) {
case IIO_ACCEL:
case IIO_INCLI:
bits = 14;
m = GENMASK(13, 0);
break;
default:
return -EINVAL;
}
val16 = val & ((1 << bits) - 1);
addr = adis16209_addresses[chan->scan_index][0];
return adis_write_reg_16(st, addr, val16);
}
return -EINVAL;
return adis_write_reg_16(st, adis16209_addresses[chan->scan_index][0],
val & m);
}
static int adis16209_read_raw(struct iio_dev *indio_dev,
......@@ -195,7 +189,7 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_OFFSET:
/*
* The raw ADC value is 0x4FE when the temperature
* is 25 degrees and the scale factor per milli
* is 45 degrees and the scale factor per milli
* degree celcius is -470.
*/
*val = 25000 / -470 - 0x4FE;
......@@ -270,13 +264,14 @@ static const struct adis_data adis16209_data = {
static int adis16209_probe(struct spi_device *spi)
{
int ret;
struct adis *st;
struct iio_dev *indio_dev;
struct adis *st;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
spi_set_drvdata(spi, indio_dev);
......@@ -290,6 +285,7 @@ static int adis16209_probe(struct spi_device *spi)
ret = adis_init(st, indio_dev, spi, &adis16209_data);
if (ret)
return ret;
ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
if (ret)
return ret;
......
......@@ -837,29 +837,12 @@ static int bmc150_accel_fifo_transfer(struct bmc150_accel_data *data,
int sample_length = 3 * 2;
int ret;
int total_length = samples * sample_length;
int i;
size_t step = regmap_get_raw_read_max(data->regmap);
if (!step || step > total_length)
step = total_length;
else if (step < total_length)
step = sample_length;
/*
* Seems we have a bus with size limitation so we have to execute
* multiple reads
*/
for (i = 0; i < total_length; i += step) {
ret = regmap_raw_read(data->regmap, BMC150_ACCEL_REG_FIFO_DATA,
&buffer[i], step);
if (ret)
break;
}
buffer, total_length);
if (ret)
dev_err(dev,
"Error transferring data from fifo in single steps of %zu\n",
step);
"Error transferring data from fifo: %d\n", ret);
return ret;
}
......
......@@ -1277,7 +1277,7 @@ static int sca3000_configure_ring(struct iio_dev *indio_dev)
{
struct iio_buffer *buffer;
buffer = iio_kfifo_allocate();
buffer = devm_iio_kfifo_allocate(&indio_dev->dev);
if (!buffer)
return -ENOMEM;
......@@ -1287,11 +1287,6 @@ static int sca3000_configure_ring(struct iio_dev *indio_dev)
return 0;
}
static void sca3000_unconfigure_ring(struct iio_dev *indio_dev)
{
iio_kfifo_free(indio_dev->buffer);
}
static inline
int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state)
{
......@@ -1486,7 +1481,9 @@ static int sca3000_probe(struct spi_device *spi)
}
indio_dev->modes = INDIO_DIRECT_MODE;
sca3000_configure_ring(indio_dev);
ret = sca3000_configure_ring(indio_dev);
if (ret)
return ret;
if (spi->irq) {
ret = request_threaded_irq(spi->irq,
......@@ -1546,8 +1543,6 @@ static int sca3000_remove(struct spi_device *spi)
if (spi->irq)
free_irq(spi->irq, indio_dev);
sca3000_unconfigure_ring(indio_dev);
return 0;
}
......
......@@ -107,6 +107,7 @@ MODULE_DEVICE_TABLE(of, st_accel_of_match);
#ifdef CONFIG_ACPI
static const struct acpi_device_id st_accel_acpi_match[] = {
{"SMO8840", LNG2DM},
{"SMO8A90", LNG2DM},
{ },
};
......
......@@ -153,6 +153,17 @@ struct ad7791_state {
const struct ad7791_chip_info *info;
};
static const int ad7791_sample_freq_avail[8][2] = {
[AD7791_FILTER_RATE_120] = { 120, 0 },
[AD7791_FILTER_RATE_100] = { 100, 0 },
[AD7791_FILTER_RATE_33_3] = { 33, 300000 },
[AD7791_FILTER_RATE_20] = { 20, 0 },
[AD7791_FILTER_RATE_16_6] = { 16, 600000 },
[AD7791_FILTER_RATE_16_7] = { 16, 700000 },
[AD7791_FILTER_RATE_13_3] = { 13, 300000 },
[AD7791_FILTER_RATE_9_5] = { 9, 500000 },
};
static struct ad7791_state *ad_sigma_delta_to_ad7791(struct ad_sigma_delta *sd)
{
return container_of(sd, struct ad7791_state, sd);
......@@ -202,6 +213,7 @@ static int ad7791_read_raw(struct iio_dev *indio_dev,
{
struct ad7791_state *st = iio_priv(indio_dev);
bool unipolar = !!(st->mode & AD7791_MODE_UNIPOLAR);
unsigned int rate;
switch (info) {
case IIO_CHAN_INFO_RAW:
......@@ -239,63 +251,56 @@ static int ad7791_read_raw(struct iio_dev *indio_dev,
*val2 = chan->scan_type.realbits - 1;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_SAMP_FREQ:
rate = st->filter & AD7791_FILTER_RATE_MASK;
*val = ad7791_sample_freq_avail[rate][0];
*val2 = ad7791_sample_freq_avail[rate][1];
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
static const char * const ad7791_sample_freq_avail[] = {
[AD7791_FILTER_RATE_120] = "120",
[AD7791_FILTER_RATE_100] = "100",
[AD7791_FILTER_RATE_33_3] = "33.3",
[AD7791_FILTER_RATE_20] = "20",
[AD7791_FILTER_RATE_16_6] = "16.6",
[AD7791_FILTER_RATE_16_7] = "16.7",
[AD7791_FILTER_RATE_13_3] = "13.3",
[AD7791_FILTER_RATE_9_5] = "9.5",
};
static ssize_t ad7791_read_frequency(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7791_state *st = iio_priv(indio_dev);
unsigned int rate = st->filter & AD7791_FILTER_RATE_MASK;
return sprintf(buf, "%s\n", ad7791_sample_freq_avail[rate]);
}
static ssize_t ad7791_write_frequency(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
static int ad7791_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val, int val2, long mask)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7791_state *st = iio_priv(indio_dev);
int i, ret;
i = sysfs_match_string(ad7791_sample_freq_avail, buf);
if (i < 0)
return i;
int ret, i;
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) {
if (ad7791_sample_freq_avail[i][0] == val &&
ad7791_sample_freq_avail[i][1] == val2)
break;
}
if (i == ARRAY_SIZE(ad7791_sample_freq_avail)) {
ret = -EINVAL;
break;
}
st->filter &= ~AD7791_FILTER_RATE_MASK;
st->filter |= i;
ad_sd_write_reg(&st->sd, AD7791_REG_FILTER, sizeof(st->filter),
ad_sd_write_reg(&st->sd, AD7791_REG_FILTER,
sizeof(st->filter),
st->filter);
iio_device_release_direct_mode(indio_dev);
break;
default:
ret = -EINVAL;
}
return len;
iio_device_release_direct_mode(indio_dev);
return ret;
}
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
ad7791_read_frequency,
ad7791_write_frequency);
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("120 100 33.3 20 16.7 16.6 13.3 9.5");
static struct attribute *ad7791_attributes[] = {
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
NULL
};
......@@ -306,12 +311,14 @@ static const struct attribute_group ad7791_attribute_group = {
static const struct iio_info ad7791_info = {
.read_raw = &ad7791_read_raw,
.write_raw = &ad7791_write_raw,
.attrs = &ad7791_attribute_group,
.validate_trigger = ad_sd_validate_trigger,
};
static const struct iio_info ad7791_no_filter_info = {
.read_raw = &ad7791_read_raw,
.write_raw = &ad7791_write_raw,
.validate_trigger = ad_sd_validate_trigger,
};
......
......@@ -219,15 +219,19 @@ enum meson_sar_adc_chan7_mux_sel {
CHAN7_MUX_CH7_INPUT = 0x7,
};
struct meson_sar_adc_data {
struct meson_sar_adc_param {
bool has_bl30_integration;
unsigned long clock_rate;
u32 bandgap_reg;
unsigned int resolution;
const char *name;
const struct regmap_config *regmap_config;
};
struct meson_sar_adc_data {
const struct meson_sar_adc_param *param;
const char *name;
};
struct meson_sar_adc_priv {
struct regmap *regmap;
struct regulator *vref;
......@@ -276,7 +280,7 @@ static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val)
/* use val_calib = scale * val_raw + offset calibration function */
tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias;
return clamp(tmp, 0, (1 << priv->data->resolution) - 1);
return clamp(tmp, 0, (1 << priv->data->param->resolution) - 1);
}
static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev)
......@@ -328,7 +332,7 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
}
fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval);
fifo_val &= GENMASK(priv->data->resolution - 1, 0);
fifo_val &= GENMASK(priv->data->param->resolution - 1, 0);
*val = meson_sar_adc_calib_val(indio_dev, fifo_val);
return 0;
......@@ -447,7 +451,7 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev)
mutex_lock(&indio_dev->mlock);
if (priv->data->has_bl30_integration) {
if (priv->data->param->has_bl30_integration) {
/* prevent BL30 from using the SAR ADC while we are using it */
regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
MESON_SAR_ADC_DELAY_KERNEL_BUSY,
......@@ -475,7 +479,7 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
if (priv->data->has_bl30_integration)
if (priv->data->param->has_bl30_integration)
/* allow BL30 to use the SAR ADC again */
regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0);
......@@ -559,7 +563,7 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev,
}
*val = ret / 1000;
*val2 = priv->data->resolution;
*val2 = priv->data->param->resolution;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_CALIBBIAS:
......@@ -632,7 +636,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
*/
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT);
if (priv->data->has_bl30_integration) {
if (priv->data->param->has_bl30_integration) {
/*
* leave sampling delay and the input clocks as configured by
* BL30 to make sure BL30 gets the values it expects when
......@@ -712,7 +716,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
return ret;
}
ret = clk_set_rate(priv->adc_clk, priv->data->clock_rate);
ret = clk_set_rate(priv->adc_clk, priv->data->param->clock_rate);
if (ret) {
dev_err(indio_dev->dev.parent,
"failed to set adc clock rate\n");
......@@ -725,14 +729,15 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
const struct meson_sar_adc_param *param = priv->data->param;
u32 enable_mask;
if (priv->data->bandgap_reg == MESON_SAR_ADC_REG11)
if (param->bandgap_reg == MESON_SAR_ADC_REG11)
enable_mask = MESON_SAR_ADC_REG11_BANDGAP_EN;
else
enable_mask = MESON_SAR_ADC_DELTA_10_TS_VBG_EN;
regmap_update_bits(priv->regmap, priv->data->bandgap_reg, enable_mask,
regmap_update_bits(priv->regmap, param->bandgap_reg, enable_mask,
on_off ? enable_mask : 0);
}
......@@ -844,8 +849,8 @@ static int meson_sar_adc_calib(struct iio_dev *indio_dev)
int ret, nominal0, nominal1, value0, value1;
/* use points 25% and 75% for calibration */
nominal0 = (1 << priv->data->resolution) / 4;
nominal1 = (1 << priv->data->resolution) * 3 / 4;
nominal0 = (1 << priv->data->param->resolution) / 4;
nominal1 = (1 << priv->data->param->resolution) * 3 / 4;
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4);
usleep_range(10, 20);
......@@ -883,51 +888,60 @@ static const struct iio_info meson_sar_adc_iio_info = {
.read_raw = meson_sar_adc_iio_info_read_raw,
};
static const struct meson_sar_adc_data meson_sar_adc_meson8_data = {
.has_bl30_integration = false,
.clock_rate = 1150000,
.bandgap_reg = MESON_SAR_ADC_DELTA_10,
.regmap_config = &meson_sar_adc_regmap_config_meson8,
.resolution = 10,
.name = "meson-meson8-saradc",
};
static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = {
static const struct meson_sar_adc_param meson_sar_adc_meson8_param = {
.has_bl30_integration = false,
.clock_rate = 1150000,
.bandgap_reg = MESON_SAR_ADC_DELTA_10,
.regmap_config = &meson_sar_adc_regmap_config_meson8,
.resolution = 10,
.name = "meson-meson8b-saradc",
};
static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = {
static const struct meson_sar_adc_param meson_sar_adc_gxbb_param = {
.has_bl30_integration = true,
.clock_rate = 1200000,
.bandgap_reg = MESON_SAR_ADC_REG11,
.regmap_config = &meson_sar_adc_regmap_config_gxbb,
.resolution = 10,
.name = "meson-gxbb-saradc",
};
static const struct meson_sar_adc_data meson_sar_adc_gxl_data = {
static const struct meson_sar_adc_param meson_sar_adc_gxl_param = {
.has_bl30_integration = true,
.clock_rate = 1200000,
.bandgap_reg = MESON_SAR_ADC_REG11,
.regmap_config = &meson_sar_adc_regmap_config_gxbb,
.resolution = 12,
};
static const struct meson_sar_adc_data meson_sar_adc_meson8_data = {
.param = &meson_sar_adc_meson8_param,
.name = "meson-meson8-saradc",
};
static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = {
.param = &meson_sar_adc_meson8_param,
.name = "meson-meson8b-saradc",
};
static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = {
.param = &meson_sar_adc_gxbb_param,
.name = "meson-gxbb-saradc",
};
static const struct meson_sar_adc_data meson_sar_adc_gxl_data = {
.param = &meson_sar_adc_gxl_param,
.name = "meson-gxl-saradc",
};
static const struct meson_sar_adc_data meson_sar_adc_gxm_data = {
.has_bl30_integration = true,
.clock_rate = 1200000,
.bandgap_reg = MESON_SAR_ADC_REG11,
.regmap_config = &meson_sar_adc_regmap_config_gxbb,
.resolution = 12,
.param = &meson_sar_adc_gxl_param,
.name = "meson-gxm-saradc",
};
static const struct meson_sar_adc_data meson_sar_adc_axg_data = {
.param = &meson_sar_adc_gxl_param,
.name = "meson-axg-saradc",
};
static const struct of_device_id meson_sar_adc_of_match[] = {
{
.compatible = "amlogic,meson8-saradc",
......@@ -946,6 +960,9 @@ static const struct of_device_id meson_sar_adc_of_match[] = {
}, {
.compatible = "amlogic,meson-gxm-saradc",
.data = &meson_sar_adc_gxm_data,
}, {
.compatible = "amlogic,meson-axg-saradc",
.data = &meson_sar_adc_axg_data,
},
{},
};
......@@ -1001,7 +1018,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
return ret;
priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
priv->data->regmap_config);
priv->data->param->regmap_config);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
......
......@@ -34,9 +34,6 @@
#define STM32F4_ADC_ADCPRE_SHIFT 16
#define STM32F4_ADC_ADCPRE_MASK GENMASK(17, 16)
/* STM32 F4 maximum analog clock rate (from datasheet) */
#define STM32F4_ADC_MAX_CLK_RATE 36000000
/* STM32H7 - common registers for all ADC instances */
#define STM32H7_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
......@@ -51,9 +48,6 @@
#define STM32H7_CKMODE_SHIFT 16
#define STM32H7_CKMODE_MASK GENMASK(17, 16)
/* STM32 H7 maximum analog clock rate (from datasheet) */
#define STM32H7_ADC_MAX_CLK_RATE 36000000
/**
* stm32_adc_common_regs - stm32 common registers, compatible dependent data
* @csr: common status register offset
......@@ -74,15 +68,17 @@ struct stm32_adc_priv;
* stm32_adc_priv_cfg - stm32 core compatible configuration data
* @regs: common registers for all instances
* @clk_sel: clock selection routine
* @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet)
*/
struct stm32_adc_priv_cfg {
const struct stm32_adc_common_regs *regs;
int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *);
u32 max_clk_rate_hz;
};
/**
* struct stm32_adc_priv - stm32 ADC core private data
* @irq: irq for ADC block
* @irq: irq(s) for ADC block
* @domain: irq domain reference
* @aclk: clock reference for the analog circuitry
* @bclk: bus clock common for all ADCs, depends on part used
......@@ -91,7 +87,7 @@ struct stm32_adc_priv_cfg {
* @common: common data for all ADC instances
*/
struct stm32_adc_priv {
int irq;
int irq[STM32_ADC_MAX_ADCS];
struct irq_domain *domain;
struct clk *aclk;
struct clk *bclk;
......@@ -133,7 +129,7 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev,
}
for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE)
if ((rate / stm32f4_pclk_div[i]) <= priv->cfg->max_clk_rate_hz)
break;
}
if (i >= ARRAY_SIZE(stm32f4_pclk_div)) {
......@@ -222,7 +218,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
if (ckmode)
continue;
if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
if ((rate / div) <= priv->cfg->max_clk_rate_hz)
goto out;
}
}
......@@ -242,7 +238,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
if (!ckmode)
continue;
if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
if ((rate / div) <= priv->cfg->max_clk_rate_hz)
goto out;
}
......@@ -328,11 +324,24 @@ static int stm32_adc_irq_probe(struct platform_device *pdev,
struct stm32_adc_priv *priv)
{
struct device_node *np = pdev->dev.of_node;
unsigned int i;
priv->irq = platform_get_irq(pdev, 0);
if (priv->irq < 0) {
for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
priv->irq[i] = platform_get_irq(pdev, i);
if (priv->irq[i] < 0) {
/*
* At least one interrupt must be provided, make others
* optional:
* - stm32f4/h7 shares a common interrupt.
* - stm32mp1, has one line per ADC (either for ADC1,
* ADC2 or both).
*/
if (i && priv->irq[i] == -ENXIO)
continue;
dev_err(&pdev->dev, "failed to get irq\n");
return priv->irq;
return priv->irq[i];
}
}
priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS, 0,
......@@ -343,8 +352,12 @@ static int stm32_adc_irq_probe(struct platform_device *pdev,
return -ENOMEM;
}
irq_set_chained_handler(priv->irq, stm32_adc_irq_handler);
irq_set_handler_data(priv->irq, priv);
for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
if (priv->irq[i] < 0)
continue;
irq_set_chained_handler(priv->irq[i], stm32_adc_irq_handler);
irq_set_handler_data(priv->irq[i], priv);
}
return 0;
}
......@@ -353,11 +366,17 @@ static void stm32_adc_irq_remove(struct platform_device *pdev,
struct stm32_adc_priv *priv)
{
int hwirq;
unsigned int i;
for (hwirq = 0; hwirq < STM32_ADC_MAX_ADCS; hwirq++)
irq_dispose_mapping(irq_find_mapping(priv->domain, hwirq));
irq_domain_remove(priv->domain);
irq_set_chained_handler(priv->irq, NULL);
for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
if (priv->irq[i] < 0)
continue;
irq_set_chained_handler(priv->irq[i], NULL);
}
}
static int stm32_adc_probe(struct platform_device *pdev)
......@@ -497,11 +516,19 @@ static int stm32_adc_remove(struct platform_device *pdev)
static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = {
.regs = &stm32f4_adc_common_regs,
.clk_sel = stm32f4_adc_clk_sel,
.max_clk_rate_hz = 36000000,
};
static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = {
.regs = &stm32h7_adc_common_regs,
.clk_sel = stm32h7_adc_clk_sel,
.max_clk_rate_hz = 36000000,
};
static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = {
.regs = &stm32h7_adc_common_regs,
.clk_sel = stm32h7_adc_clk_sel,
.max_clk_rate_hz = 40000000,
};
static const struct of_device_id stm32_adc_of_match[] = {
......@@ -511,6 +538,9 @@ static const struct of_device_id stm32_adc_of_match[] = {
}, {
.compatible = "st,stm32h7-adc-core",
.data = (void *)&stm32h7_adc_priv_cfg
}, {
.compatible = "st,stm32mp1-adc-core",
.data = (void *)&stm32mp1_adc_priv_cfg
}, {
},
};
......
......@@ -84,6 +84,7 @@
#define STM32H7_ADC_CALFACT2 0xC8
/* STM32H7_ADC_ISR - bit fields */
#define STM32MP1_VREGREADY BIT(12)
#define STM32H7_EOC BIT(2)
#define STM32H7_ADRDY BIT(0)
......@@ -249,6 +250,7 @@ struct stm32_adc;
* @adc_info: per instance input channels definitions
* @trigs: external trigger sources
* @clk_required: clock is required
* @has_vregready: vregready status flag presence
* @selfcalib: optional routine for self-calibration
* @prepare: optional prepare routine (power-up, enable)
* @start_conv: routine to start conversions
......@@ -261,6 +263,7 @@ struct stm32_adc_cfg {
const struct stm32_adc_info *adc_info;
struct stm32_adc_trig_info *trigs;
bool clk_required;
bool has_vregready;
int (*selfcalib)(struct stm32_adc *);
int (*prepare)(struct stm32_adc *);
void (*start_conv)(struct stm32_adc *, bool dma);
......@@ -695,8 +698,12 @@ static void stm32h7_adc_stop_conv(struct stm32_adc *adc)
stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK);
}
static void stm32h7_adc_exit_pwr_down(struct stm32_adc *adc)
static int stm32h7_adc_exit_pwr_down(struct stm32_adc *adc)
{
struct iio_dev *indio_dev = iio_priv_to_dev(adc);
int ret;
u32 val;
/* Exit deep power down, then enable ADC voltage regulator */
stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADVREGEN);
......@@ -705,7 +712,20 @@ static void stm32h7_adc_exit_pwr_down(struct stm32_adc *adc)
stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST);
/* Wait for startup time */
if (!adc->cfg->has_vregready) {
usleep_range(10, 20);
return 0;
}
ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_ISR, val,
val & STM32MP1_VREGREADY, 100,
STM32_ADC_TIMEOUT_US);
if (ret) {
stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
dev_err(&indio_dev->dev, "Failed to exit power down\n");
}
return ret;
}
static void stm32h7_adc_enter_pwr_down(struct stm32_adc *adc)
......@@ -888,7 +908,9 @@ static int stm32h7_adc_selfcalib(struct stm32_adc *adc)
int ret;
u32 val;
stm32h7_adc_exit_pwr_down(adc);
ret = stm32h7_adc_exit_pwr_down(adc);
if (ret)
return ret;
/*
* Select calibration mode:
......@@ -952,7 +974,10 @@ static int stm32h7_adc_prepare(struct stm32_adc *adc)
{
int ret;
stm32h7_adc_exit_pwr_down(adc);
ret = stm32h7_adc_exit_pwr_down(adc);
if (ret)
return ret;
stm32_adc_writel(adc, STM32H7_ADC_DIFSEL, adc->difsel);
ret = stm32h7_adc_enable(adc);
......@@ -1944,9 +1969,23 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = {
.smp_cycles = stm32h7_adc_smp_cycles,
};
static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
.regs = &stm32h7_adc_regspec,
.adc_info = &stm32h7_adc_info,
.trigs = stm32h7_adc_trigs,
.has_vregready = true,
.selfcalib = stm32h7_adc_selfcalib,
.start_conv = stm32h7_adc_start_conv,
.stop_conv = stm32h7_adc_stop_conv,
.prepare = stm32h7_adc_prepare,
.unprepare = stm32h7_adc_unprepare,
.smp_cycles = stm32h7_adc_smp_cycles,
};
static const struct of_device_id stm32_adc_of_match[] = {
{ .compatible = "st,stm32f4-adc", .data = (void *)&stm32f4_adc_cfg },
{ .compatible = "st,stm32h7-adc", .data = (void *)&stm32h7_adc_cfg },
{ .compatible = "st,stm32mp1-adc", .data = (void *)&stm32mp1_adc_cfg },
{},
};
MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
......
......@@ -253,7 +253,8 @@ static int stm32_dfsdm_start_filter(struct stm32_dfsdm *dfsdm,
DFSDM_CR1_RSWSTART(1));
}
static void stm32_dfsdm_stop_filter(struct stm32_dfsdm *dfsdm, unsigned int fl_id)
static void stm32_dfsdm_stop_filter(struct stm32_dfsdm *dfsdm,
unsigned int fl_id)
{
/* Disable conversion */
regmap_update_bits(dfsdm->regmap, DFSDM_CR1(fl_id),
......@@ -1093,7 +1094,6 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
char *name;
int ret, irq, val;
dev_data = of_device_get_match_data(dev);
iio = devm_iio_device_alloc(dev, sizeof(*adc));
if (!iio) {
......@@ -1111,8 +1111,8 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, adc);
ret = of_property_read_u32(dev->of_node, "reg", &adc->fl_id);
if (ret != 0) {
dev_err(dev, "Missing reg property\n");
if (ret != 0 || adc->fl_id >= adc->dfsdm->num_fls) {
dev_err(dev, "Missing or bad reg property\n");
return -EINVAL;
}
......@@ -1161,7 +1161,6 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
if (ret < 0)
goto err_cleanup;
dev_err(dev, "of_platform_populate\n");
if (dev_data->type == DFSDM_AUDIO) {
ret = of_platform_populate(np, NULL, NULL, dev);
if (ret < 0) {
......
......@@ -227,6 +227,11 @@ static int stm32_dfsdm_parse_of(struct platform_device *pdev,
}
priv->spi_clk_out_div = div_u64_rem(clk_freq, spi_freq, &rem) - 1;
if (!priv->spi_clk_out_div) {
/* spi_clk_out_div == 0 means ckout is OFF */
dev_err(&pdev->dev, "spi-max-frequency not achievable\n");
return -EINVAL;
}
priv->dfsdm.spi_master_freq = spi_freq;
if (rem) {
......
......@@ -233,6 +233,16 @@ static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset)
return !!(inb(stx104gpio->base) & BIT(offset));
}
static int stx104_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
unsigned long *bits)
{
struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
*bits = inb(stx104gpio->base);
return 0;
}
static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
......@@ -342,6 +352,7 @@ static int stx104_probe(struct device *dev, unsigned int id)
stx104gpio->chip.direction_input = stx104_gpio_direction_input;
stx104gpio->chip.direction_output = stx104_gpio_direction_output;
stx104gpio->chip.get = stx104_gpio_get;
stx104gpio->chip.get_multiple = stx104_gpio_get_multiple;
stx104gpio->chip.set = stx104_gpio_set;
stx104gpio->chip.set_multiple = stx104_gpio_set_multiple;
stx104gpio->base = base[id] + 3;
......
#
# Analog Front End drivers
#
# When adding new entries keep the list in alphabetical order
menu "Analog Front Ends"
config IIO_RESCALE
tristate "IIO rescale"
depends on OF || COMPILE_TEST
help
Say yes here to build support for the IIO rescaling
that handles voltage dividers, current sense shunts and
current sense amplifiers.
To compile this driver as a module, choose M here: the
module will be called iio-rescale.
endmenu
#
# Makefile for industrial I/O Analog Front Ends (AFE)
#
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_IIO_RESCALE) += iio-rescale.o
// SPDX-License-Identifier: GPL-2.0
/*
* IIO rescale driver
*
* Copyright (C) 2018 Axentia Technologies AB
*
* Author: Peter Rosin <peda@axentia.se>
*/
#include <linux/err.h>
#include <linux/gcd.h>
#include <linux/iio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/property.h>
struct rescale;
struct rescale_cfg {
enum iio_chan_type type;
int (*props)(struct device *dev, struct rescale *rescale);
};
struct rescale {
const struct rescale_cfg *cfg;
struct iio_channel *source;
struct iio_chan_spec chan;
struct iio_chan_spec_ext_info *ext_info;
s32 numerator;
s32 denominator;
};
static int rescale_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct rescale *rescale = iio_priv(indio_dev);
unsigned long long tmp;
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
return iio_read_channel_raw(rescale->source, val);
case IIO_CHAN_INFO_SCALE:
ret = iio_read_channel_scale(rescale->source, val, val2);
switch (ret) {
case IIO_VAL_FRACTIONAL:
*val *= rescale->numerator;
*val2 *= rescale->denominator;
return ret;
case IIO_VAL_INT:
*val *= rescale->numerator;
if (rescale->denominator == 1)
return ret;
*val2 = rescale->denominator;
return IIO_VAL_FRACTIONAL;
case IIO_VAL_FRACTIONAL_LOG2:
tmp = *val * 1000000000LL;
do_div(tmp, rescale->denominator);
tmp *= rescale->numerator;
do_div(tmp, 1000000000LL);
*val = tmp;
return ret;
default:
return -EOPNOTSUPP;
}
default:
return -EINVAL;
}
}
static int rescale_read_avail(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
const int **vals, int *type, int *length,
long mask)
{
struct rescale *rescale = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
*type = IIO_VAL_INT;
return iio_read_avail_channel_raw(rescale->source,
vals, length);
default:
return -EINVAL;
}
}
static const struct iio_info rescale_info = {
.read_raw = rescale_read_raw,
.read_avail = rescale_read_avail,
};
static ssize_t rescale_read_ext_info(struct iio_dev *indio_dev,
uintptr_t private,
struct iio_chan_spec const *chan,
char *buf)
{
struct rescale *rescale = iio_priv(indio_dev);
return iio_read_channel_ext_info(rescale->source,
rescale->ext_info[private].name,
buf);
}
static ssize_t rescale_write_ext_info(struct iio_dev *indio_dev,
uintptr_t private,
struct iio_chan_spec const *chan,
const char *buf, size_t len)
{
struct rescale *rescale = iio_priv(indio_dev);
return iio_write_channel_ext_info(rescale->source,
rescale->ext_info[private].name,
buf, len);
}
static int rescale_configure_channel(struct device *dev,
struct rescale *rescale)
{
struct iio_chan_spec *chan = &rescale->chan;
struct iio_chan_spec const *schan = rescale->source->channel;
chan->indexed = 1;
chan->output = schan->output;
chan->ext_info = rescale->ext_info;
chan->type = rescale->cfg->type;
if (!iio_channel_has_info(schan, IIO_CHAN_INFO_RAW) ||
!iio_channel_has_info(schan, IIO_CHAN_INFO_SCALE)) {
dev_err(dev, "source channel does not support raw/scale\n");
return -EINVAL;
}
chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE);
if (iio_channel_has_available(schan, IIO_CHAN_INFO_RAW))
chan->info_mask_separate_available |= BIT(IIO_CHAN_INFO_RAW);
return 0;
}
static int rescale_current_sense_amplifier_props(struct device *dev,
struct rescale *rescale)
{
u32 sense;
u32 gain_mult = 1;
u32 gain_div = 1;
u32 factor;
int ret;
ret = device_property_read_u32(dev, "sense-resistor-micro-ohms",
&sense);
if (ret) {
dev_err(dev, "failed to read the sense resistance: %d\n", ret);
return ret;
}
device_property_read_u32(dev, "sense-gain-mult", &gain_mult);
device_property_read_u32(dev, "sense-gain-div", &gain_div);
/*
* Calculate the scaling factor, 1 / (gain * sense), or
* gain_div / (gain_mult * sense), while trying to keep the
* numerator/denominator from overflowing.
*/
factor = gcd(sense, 1000000);
rescale->numerator = 1000000 / factor;
rescale->denominator = sense / factor;
factor = gcd(rescale->numerator, gain_mult);
rescale->numerator /= factor;
rescale->denominator *= gain_mult / factor;
factor = gcd(rescale->denominator, gain_div);
rescale->numerator *= gain_div / factor;
rescale->denominator /= factor;
return 0;
}
static int rescale_current_sense_shunt_props(struct device *dev,
struct rescale *rescale)
{
u32 shunt;
u32 factor;
int ret;
ret = device_property_read_u32(dev, "shunt-resistor-micro-ohms",
&shunt);
if (ret) {
dev_err(dev, "failed to read the shunt resistance: %d\n", ret);
return ret;
}
factor = gcd(shunt, 1000000);
rescale->numerator = 1000000 / factor;
rescale->denominator = shunt / factor;
return 0;
}
static int rescale_voltage_divider_props(struct device *dev,
struct rescale *rescale)
{
int ret;
u32 factor;
ret = device_property_read_u32(dev, "output-ohms",
&rescale->denominator);
if (ret) {
dev_err(dev, "failed to read output-ohms: %d\n", ret);
return ret;
}
ret = device_property_read_u32(dev, "full-ohms",
&rescale->numerator);
if (ret) {
dev_err(dev, "failed to read full-ohms: %d\n", ret);
return ret;
}
factor = gcd(rescale->numerator, rescale->denominator);
rescale->numerator /= factor;
rescale->denominator /= factor;
return 0;
}
enum rescale_variant {
CURRENT_SENSE_AMPLIFIER,
CURRENT_SENSE_SHUNT,
VOLTAGE_DIVIDER,
};
static const struct rescale_cfg rescale_cfg[] = {
[CURRENT_SENSE_AMPLIFIER] = {
.type = IIO_CURRENT,
.props = rescale_current_sense_amplifier_props,
},
[CURRENT_SENSE_SHUNT] = {
.type = IIO_CURRENT,
.props = rescale_current_sense_shunt_props,
},
[VOLTAGE_DIVIDER] = {
.type = IIO_VOLTAGE,
.props = rescale_voltage_divider_props,
},
};
static const struct of_device_id rescale_match[] = {
{ .compatible = "current-sense-amplifier",
.data = &rescale_cfg[CURRENT_SENSE_AMPLIFIER], },
{ .compatible = "current-sense-shunt",
.data = &rescale_cfg[CURRENT_SENSE_SHUNT], },
{ .compatible = "voltage-divider",
.data = &rescale_cfg[VOLTAGE_DIVIDER], },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, rescale_match);
static int rescale_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct iio_dev *indio_dev;
struct iio_channel *source;
struct rescale *rescale;
int sizeof_ext_info;
int sizeof_priv;
int i;
int ret;
source = devm_iio_channel_get(dev, NULL);
if (IS_ERR(source)) {
if (PTR_ERR(source) != -EPROBE_DEFER)
dev_err(dev, "failed to get source channel\n");
return PTR_ERR(source);
}
sizeof_ext_info = iio_get_channel_ext_info_count(source);
if (sizeof_ext_info) {
sizeof_ext_info += 1; /* one extra entry for the sentinel */
sizeof_ext_info *= sizeof(*rescale->ext_info);
}
sizeof_priv = sizeof(*rescale) + sizeof_ext_info;
indio_dev = devm_iio_device_alloc(dev, sizeof_priv);
if (!indio_dev)
return -ENOMEM;
rescale = iio_priv(indio_dev);
rescale->cfg = of_device_get_match_data(dev);
rescale->numerator = 1;
rescale->denominator = 1;
ret = rescale->cfg->props(dev, rescale);
if (ret)
return ret;
if (!rescale->numerator || !rescale->denominator) {
dev_err(dev, "invalid scaling factor.\n");
return -EINVAL;
}
platform_set_drvdata(pdev, indio_dev);
rescale->source = source;
indio_dev->name = dev_name(dev);
indio_dev->dev.parent = dev;
indio_dev->info = &rescale_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = &rescale->chan;
indio_dev->num_channels = 1;
if (sizeof_ext_info) {
rescale->ext_info = devm_kmemdup(dev,
source->channel->ext_info,
sizeof_ext_info, GFP_KERNEL);
if (!rescale->ext_info)
return -ENOMEM;
for (i = 0; rescale->ext_info[i].name; ++i) {
struct iio_chan_spec_ext_info *ext_info =
&rescale->ext_info[i];
if (source->channel->ext_info[i].read)
ext_info->read = rescale_read_ext_info;
if (source->channel->ext_info[i].write)
ext_info->write = rescale_write_ext_info;
ext_info->private = i;
}
}
ret = rescale_configure_channel(dev, rescale);
if (ret)
return ret;
return devm_iio_device_register(dev, indio_dev);
}
static struct platform_driver rescale_driver = {
.probe = rescale_probe,
.driver = {
.name = "iio-rescale",
.of_match_table = rescale_match,
},
};
module_platform_driver(rescale_driver);
MODULE_DESCRIPTION("IIO rescale driver");
MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
MODULE_LICENSE("GPL v2");
......@@ -61,9 +61,9 @@
#define ATLAS_REG_ORP_CALIB_STATUS 0x0d
#define ATLAS_REG_ORP_DATA 0x0e
#define ATLAS_PH_INT_TIME_IN_US 450000
#define ATLAS_EC_INT_TIME_IN_US 650000
#define ATLAS_ORP_INT_TIME_IN_US 450000
#define ATLAS_PH_INT_TIME_IN_MS 450
#define ATLAS_EC_INT_TIME_IN_MS 650
#define ATLAS_ORP_INT_TIME_IN_MS 450
enum {
ATLAS_PH_SM,
......@@ -270,21 +270,21 @@ static struct atlas_device atlas_devices[] = {
.num_channels = 3,
.data_reg = ATLAS_REG_PH_DATA,
.calibration = &atlas_check_ph_calibration,
.delay = ATLAS_PH_INT_TIME_IN_US,
.delay = ATLAS_PH_INT_TIME_IN_MS,
},
[ATLAS_EC_SM] = {
.channels = atlas_ec_channels,
.num_channels = 5,
.data_reg = ATLAS_REG_EC_DATA,
.calibration = &atlas_check_ec_calibration,
.delay = ATLAS_EC_INT_TIME_IN_US,
.delay = ATLAS_EC_INT_TIME_IN_MS,
},
[ATLAS_ORP_SM] = {
.channels = atlas_orp_channels,
.num_channels = 2,
.data_reg = ATLAS_REG_ORP_DATA,
.calibration = &atlas_check_orp_calibration,
.delay = ATLAS_ORP_INT_TIME_IN_US,
.delay = ATLAS_ORP_INT_TIME_IN_MS,
},
};
......@@ -393,7 +393,7 @@ static int atlas_read_measurement(struct atlas_data *data, int reg, __be32 *val)
}
if (suspended)
usleep_range(data->chip->delay, data->chip->delay + 100000);
msleep(data->chip->delay);
ret = regmap_bulk_read(data->regmap, reg, (u8 *) val, sizeof(*val));
......
......@@ -19,6 +19,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/iio/buffer.h>
#include <linux/iio/common/cros_ec_sensors_core.h>
#include <linux/iio/iio.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/trigger_consumer.h>
......@@ -31,8 +32,6 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include "cros_ec_sensors_core.h"
#define CROS_EC_SENSORS_MAX_CHANNELS 4
/* State data for ec_sensors iio driver. */
......
......@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/iio/buffer.h>
#include <linux/iio/common/cros_ec_sensors_core.h>
#include <linux/iio/iio.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/trigger_consumer.h>
......@@ -27,8 +28,6 @@
#include <linux/sysfs.h>
#include <linux/platform_device.h>
#include "cros_ec_sensors_core.h"
static char *cros_ec_loc[] = {
[MOTIONSENSE_LOC_BASE] = "base",
[MOTIONSENSE_LOC_LID] = "lid",
......@@ -448,8 +447,7 @@ EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write);
static int __maybe_unused cros_ec_sensors_prepare(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
if (st->curr_sampl_freq == 0)
......@@ -471,8 +469,7 @@ static int __maybe_unused cros_ec_sensors_prepare(struct device *dev)
static void __maybe_unused cros_ec_sensors_complete(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
if (st->curr_sampl_freq == 0)
......
......@@ -304,8 +304,7 @@ EXPORT_SYMBOL(hid_sensor_setup_trigger);
static int __maybe_unused hid_sensor_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
return _hid_sensor_power_state(attrb, false);
......@@ -313,8 +312,7 @@ static int __maybe_unused hid_sensor_suspend(struct device *dev)
static int __maybe_unused hid_sensor_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
schedule_work(&attrb->work);
return 0;
......@@ -322,8 +320,7 @@ static int __maybe_unused hid_sensor_resume(struct device *dev)
static int __maybe_unused hid_sensor_runtime_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev);
return _hid_sensor_power_state(attrb, true);
}
......
......@@ -131,16 +131,31 @@ config LTC2632
module will be called ltc2632.
config AD5686
tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver"
tristate
config AD5686_SPI
tristate "Analog Devices AD5686 and similar multi-channel DACs (SPI)"
depends on SPI
select AD5686
help
Say yes here to build support for Analog Devices AD5686R, AD5685R,
AD5684R, AD5791 Voltage Output Digital to
Analog Converter.
Say yes here to build support for Analog Devices AD5672R, AD5676,
AD5676R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, AD5686R.
Voltage Output Digital to Analog Converter.
To compile this driver as a module, choose M here: the
module will be called ad5686.
config AD5696_I2C
tristate "Analog Devices AD5696 and similar multi-channel DACs (I2C)"
depends on I2C
select AD5686
help
Say yes here to build support for Analog Devices AD5671R, AD5675R,
AD5694, AD5694R, AD5695R, AD5696, AD5696R Voltage Output Digital to
Analog Converter.
To compile this driver as a module, choose M here: the module will be
called ad5696.
config AD5755
tristate "Analog Devices AD5755/AD5755-1/AD5757/AD5735/AD5737 DAC driver"
depends on SPI_MASTER
......@@ -321,6 +336,16 @@ config TI_DAC082S085
If compiled as a module, it will be called ti-dac082s085.
config TI_DAC5571
tristate "Texas Instruments 8/10/12/16-bit 1/2/4-channel DAC driver"
depends on I2C
help
Driver for the Texas Instruments
DAC5571, DAC6571, DAC7571, DAC5574, DAC6574, DAC7574, DAC5573,
DAC6573, DAC7573, DAC8571, DAC8574.
If compiled as a module, it will be called ti-dac5571.
config VF610_DAC
tristate "Vybrid vf610 DAC driver"
depends on OF
......
......@@ -20,6 +20,8 @@ obj-$(CONFIG_AD5761) += ad5761.o
obj-$(CONFIG_AD5764) += ad5764.o
obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_AD5686_SPI) += ad5686-spi.o
obj-$(CONFIG_AD5696_I2C) += ad5696-i2c.o
obj-$(CONFIG_AD7303) += ad7303.o
obj-$(CONFIG_AD8801) += ad8801.o
obj-$(CONFIG_CIO_DAC) += cio-dac.o
......@@ -35,4 +37,5 @@ obj-$(CONFIG_MCP4922) += mcp4922.o
obj-$(CONFIG_STM32_DAC_CORE) += stm32-dac-core.o
obj-$(CONFIG_STM32_DAC) += stm32-dac.o
obj-$(CONFIG_TI_DAC082S085) += ti-dac082s085.o
obj-$(CONFIG_TI_DAC5571) += ti-dac5571.o
obj-$(CONFIG_VF610_DAC) += vf610_dac.o
// SPDX-License-Identifier: GPL-2.0+
/*
* AD5672R, AD5676, AD5676R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, AD5686R
* Digital to analog converters driver
*
* Copyright 2018 Analog Devices Inc.
*/
#include "ad5686.h"
#include <linux/module.h>
#include <linux/spi/spi.h>
static int ad5686_spi_write(struct ad5686_state *st,
u8 cmd, u8 addr, u16 val)
{
struct spi_device *spi = to_spi_device(st->dev);
st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
AD5686_ADDR(addr) |
val);
return spi_write(spi, &st->data[0].d8[1], 3);
}
static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
{
struct spi_transfer t[] = {
{
.tx_buf = &st->data[0].d8[1],
.len = 3,
.cs_change = 1,
}, {
.tx_buf = &st->data[1].d8[1],
.rx_buf = &st->data[2].d8[1],
.len = 3,
},
};
struct spi_device *spi = to_spi_device(st->dev);
int ret;
st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_READBACK_ENABLE) |
AD5686_ADDR(addr));
st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP));
ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t));
if (ret < 0)
return ret;
return be32_to_cpu(st->data[2].d32);
}
static int ad5686_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
return ad5686_probe(&spi->dev, id->driver_data, id->name,
ad5686_spi_write, ad5686_spi_read);
}
static int ad5686_spi_remove(struct spi_device *spi)
{
return ad5686_remove(&spi->dev);
}
static const struct spi_device_id ad5686_spi_id[] = {
{"ad5672r", ID_AD5672R},
{"ad5676", ID_AD5676},
{"ad5676r", ID_AD5676R},
{"ad5684", ID_AD5684},
{"ad5684r", ID_AD5684R},
{"ad5685", ID_AD5685R}, /* Does not exist */
{"ad5685r", ID_AD5685R},
{"ad5686", ID_AD5686},
{"ad5686r", ID_AD5686R},
{}
};
MODULE_DEVICE_TABLE(spi, ad5686_spi_id);
static struct spi_driver ad5686_spi_driver = {
.driver = {
.name = "ad5686",
},
.probe = ad5686_spi_probe,
.remove = ad5686_spi_remove,
.id_table = ad5686_spi_id,
};
module_spi_driver(ad5686_spi_driver);
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD5686 and similar multi-channel DACs");
MODULE_LICENSE("GPL v2");
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* This file is part of AD5686 DAC driver
*
* Copyright 2018 Analog Devices Inc.
*/
#ifndef __DRIVERS_IIO_DAC_AD5686_H__
#define __DRIVERS_IIO_DAC_AD5686_H__
#include <linux/types.h>
#include <linux/cache.h>
#include <linux/mutex.h>
#include <linux/kernel.h>
#define AD5686_ADDR(x) ((x) << 16)
#define AD5686_CMD(x) ((x) << 20)
#define AD5686_ADDR_DAC(chan) (0x1 << (chan))
#define AD5686_ADDR_ALL_DAC 0xF
#define AD5686_CMD_NOOP 0x0
#define AD5686_CMD_WRITE_INPUT_N 0x1
#define AD5686_CMD_UPDATE_DAC_N 0x2
#define AD5686_CMD_WRITE_INPUT_N_UPDATE_N 0x3
#define AD5686_CMD_POWERDOWN_DAC 0x4
#define AD5686_CMD_LDAC_MASK 0x5
#define AD5686_CMD_RESET 0x6
#define AD5686_CMD_INTERNAL_REFER_SETUP 0x7
#define AD5686_CMD_DAISY_CHAIN_ENABLE 0x8
#define AD5686_CMD_READBACK_ENABLE 0x9
#define AD5686_LDAC_PWRDN_NONE 0x0
#define AD5686_LDAC_PWRDN_1K 0x1
#define AD5686_LDAC_PWRDN_100K 0x2
#define AD5686_LDAC_PWRDN_3STATE 0x3
/**
* ad5686_supported_device_ids:
*/
enum ad5686_supported_device_ids {
ID_AD5671R,
ID_AD5672R,
ID_AD5675R,
ID_AD5676,
ID_AD5676R,
ID_AD5684,
ID_AD5684R,
ID_AD5685R,
ID_AD5686,
ID_AD5686R,
ID_AD5694,
ID_AD5694R,
ID_AD5695R,
ID_AD5696,
ID_AD5696R,
};
struct ad5686_state;
typedef int (*ad5686_write_func)(struct ad5686_state *st,
u8 cmd, u8 addr, u16 val);
typedef int (*ad5686_read_func)(struct ad5686_state *st, u8 addr);
/**
* struct ad5686_chip_info - chip specific information
* @int_vref_mv: AD5620/40/60: the internal reference voltage
* @num_channels: number of channels
* @channel: channel specification
*/
struct ad5686_chip_info {
u16 int_vref_mv;
unsigned int num_channels;
struct iio_chan_spec *channels;
};
/**
* struct ad5446_state - driver instance specific data
* @spi: spi_device
* @chip_info: chip model specific constants, available modes etc
* @reg: supply regulator
* @vref_mv: actual reference voltage used
* @pwr_down_mask: power down mask
* @pwr_down_mode: current power down mode
* @data: spi transfer buffers
*/
struct ad5686_state {
struct device *dev;
const struct ad5686_chip_info *chip_info;
struct regulator *reg;
unsigned short vref_mv;
unsigned int pwr_down_mask;
unsigned int pwr_down_mode;
ad5686_write_func write;
ad5686_read_func read;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
union {
__be32 d32;
__be16 d16;
u8 d8[4];
} data[3] ____cacheline_aligned;
};
int ad5686_probe(struct device *dev,
enum ad5686_supported_device_ids chip_type,
const char *name, ad5686_write_func write,
ad5686_read_func read);
int ad5686_remove(struct device *dev);
#endif /* __DRIVERS_IIO_DAC_AD5686_H__ */
// SPDX-License-Identifier: GPL-2.0+
/*
* AD5671R, AD5675R, AD5694, AD5694R, AD5695R, AD5696, AD5696R
* Digital to analog converters driver
*
* Copyright 2018 Analog Devices Inc.
*/
#include "ad5686.h"
#include <linux/module.h>
#include <linux/i2c.h>
static int ad5686_i2c_read(struct ad5686_state *st, u8 addr)
{
struct i2c_client *i2c = to_i2c_client(st->dev);
struct i2c_msg msg[2] = {
{
.addr = i2c->addr,
.flags = i2c->flags,
.len = 3,
.buf = &st->data[0].d8[1],
},
{
.addr = i2c->addr,
.flags = i2c->flags | I2C_M_RD,
.len = 2,
.buf = (char *)&st->data[0].d16,
},
};
int ret;
st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP) |
AD5686_ADDR(addr) |
0x00);
ret = i2c_transfer(i2c->adapter, msg, 2);
if (ret < 0)
return ret;
return be16_to_cpu(st->data[0].d16);
}
static int ad5686_i2c_write(struct ad5686_state *st,
u8 cmd, u8 addr, u16 val)
{
struct i2c_client *i2c = to_i2c_client(st->dev);
int ret;
st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | AD5686_ADDR(addr)
| val);
ret = i2c_master_send(i2c, &st->data[0].d8[1], 3);
if (ret < 0)
return ret;
return (ret != 3) ? -EIO : 0;
}
static int ad5686_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
return ad5686_probe(&i2c->dev, id->driver_data, id->name,
ad5686_i2c_write, ad5686_i2c_read);
}
static int ad5686_i2c_remove(struct i2c_client *i2c)
{
return ad5686_remove(&i2c->dev);
}
static const struct i2c_device_id ad5686_i2c_id[] = {
{"ad5671r", ID_AD5671R},
{"ad5675r", ID_AD5675R},
{"ad5694", ID_AD5694},
{"ad5694r", ID_AD5694R},
{"ad5695r", ID_AD5695R},
{"ad5696", ID_AD5696},
{"ad5696r", ID_AD5696R},
{}
};
MODULE_DEVICE_TABLE(i2c, ad5686_i2c_id);
static struct i2c_driver ad5686_i2c_driver = {
.driver = {
.name = "ad5696",
},
.probe = ad5686_i2c_probe,
.remove = ad5686_i2c_remove,
.id_table = ad5686_i2c_id,
};
module_i2c_driver(ad5686_i2c_driver);
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD5686 and similar multi-channel DACs");
MODULE_LICENSE("GPL v2");
This diff is collapsed.
This diff is collapsed.
......@@ -29,25 +29,18 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
{
struct iio_dev *indio_dev = i2c_mux_priv(muxc);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
int ret = 0;
int ret;
/* Use the same mutex which was used everywhere to protect power-op */
mutex_lock(&st->lock);
if (!st->powerup_count) {
ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
ret = inv_mpu6050_set_power_itg(st, true);
if (ret)
goto write_error;
goto error_unlock;
usleep_range(INV_MPU6050_REG_UP_TIME_MIN,
INV_MPU6050_REG_UP_TIME_MAX);
}
if (!ret) {
st->powerup_count++;
ret = regmap_write(st->map, st->reg->int_pin_cfg,
INV_MPU6050_INT_PIN_CFG |
INV_MPU6050_BIT_BYPASS_EN);
}
write_error:
st->irq_mask | INV_MPU6050_BIT_BYPASS_EN);
error_unlock:
mutex_unlock(&st->lock);
return ret;
......@@ -59,12 +52,11 @@ static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id)
struct inv_mpu6050_state *st = iio_priv(indio_dev);
mutex_lock(&st->lock);
/* It doesn't really mattter, if any of the calls fails */
regmap_write(st->map, st->reg->int_pin_cfg, INV_MPU6050_INT_PIN_CFG);
st->powerup_count--;
if (!st->powerup_count)
regmap_write(st->map, st->reg->pwr_mgmt_1,
INV_MPU6050_BIT_SLEEP);
/* It doesn't really matter if any of the calls fail */
regmap_write(st->map, st->reg->int_pin_cfg, st->irq_mask);
inv_mpu6050_set_power_itg(st, false);
mutex_unlock(&st->lock);
return 0;
......@@ -133,29 +125,32 @@ static int inv_mpu_probe(struct i2c_client *client,
return result;
st = iio_priv(dev_get_drvdata(&client->dev));
switch (st->chip_type) {
case INV_ICM20608:
/* no i2c auxiliary bus on the chip */
break;
default:
/* declare i2c auxiliary bus */
st->muxc = i2c_mux_alloc(client->adapter, &client->dev,
1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
inv_mpu6050_select_bypass,
inv_mpu6050_deselect_bypass);
if (!st->muxc) {
result = -ENOMEM;
goto out_unreg_device;
}
if (!st->muxc)
return -ENOMEM;
st->muxc->priv = dev_get_drvdata(&client->dev);
result = i2c_mux_add_adapter(st->muxc, 0, 0, 0);
if (result)
goto out_unreg_device;
return result;
result = inv_mpu_acpi_create_mux_client(client);
if (result)
goto out_del_mux;
break;
}
return 0;
out_del_mux:
i2c_mux_del_adapters(st->muxc);
out_unreg_device:
inv_mpu_core_remove(&client->dev);
return result;
}
......@@ -164,10 +159,12 @@ static int inv_mpu_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
if (st->muxc) {
inv_mpu_acpi_delete_mux_client(client);
i2c_mux_del_adapters(st->muxc);
}
return inv_mpu_core_remove(&client->dev);
return 0;
}
/*
......@@ -179,6 +176,7 @@ static const struct i2c_device_id inv_mpu_id[] = {
{"mpu6500", INV_MPU6500},
{"mpu9150", INV_MPU9150},
{"mpu9250", INV_MPU9250},
{"mpu9255", INV_MPU9255},
{"icm20608", INV_ICM20608},
{}
};
......@@ -202,6 +200,10 @@ static const struct of_device_id inv_of_match[] = {
.compatible = "invensense,mpu9250",
.data = (void *)INV_MPU9250
},
{
.compatible = "invensense,mpu9255",
.data = (void *)INV_MPU9255
},
{
.compatible = "invensense,icm20608",
.data = (void *)INV_ICM20608
......
......@@ -40,6 +40,7 @@
* @raw_accl: Address of first accel register.
* @temperature: temperature register
* @int_enable: Interrupt enable register.
* @int_status: Interrupt status register.
* @pwr_mgmt_1: Controls chip's power state and clock source.
* @pwr_mgmt_2: Controls power state of individual sensors.
* @int_pin_cfg; Controls interrupt pin configuration.
......@@ -60,6 +61,7 @@ struct inv_mpu6050_reg_map {
u8 raw_accl;
u8 temperature;
u8 int_enable;
u8 int_status;
u8 pwr_mgmt_1;
u8 pwr_mgmt_2;
u8 int_pin_cfg;
......@@ -74,6 +76,7 @@ enum inv_devices {
INV_MPU6000,
INV_MPU9150,
INV_MPU9250,
INV_MPU9255,
INV_ICM20608,
INV_NUM_PARTS
};
......@@ -94,6 +97,7 @@ struct inv_mpu6050_chip_config {
unsigned int accl_fifo_enable:1;
unsigned int gyro_fifo_enable:1;
u16 fifo_rate;
u8 user_ctrl;
};
/**
......@@ -125,6 +129,7 @@ struct inv_mpu6050_hw {
* @timestamps: kfifo queue to store time stamp.
* @map regmap pointer.
* @irq interrupt number.
* @irq_mask the int_pin_cfg mask to configure interrupt type.
*/
struct inv_mpu6050_state {
#define TIMESTAMP_FIFO_SIZE 16
......@@ -143,6 +148,8 @@ struct inv_mpu6050_state {
DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
struct regmap *map;
int irq;
u8 irq_mask;
unsigned skip_samples;
};
/*register and associated bit definition*/
......@@ -166,6 +173,9 @@ struct inv_mpu6050_state {
#define INV_MPU6050_REG_TEMPERATURE 0x41
#define INV_MPU6050_REG_RAW_GYRO 0x43
#define INV_MPU6050_REG_INT_STATUS 0x3A
#define INV_MPU6050_BIT_RAW_DATA_RDY_INT 0x01
#define INV_MPU6050_REG_USER_CTRL 0x6A
#define INV_MPU6050_BIT_FIFO_RST 0x04
#define INV_MPU6050_BIT_DMP_RST 0x08
......@@ -215,8 +225,12 @@ struct inv_mpu6050_state {
#define INV_MPU6050_OUTPUT_DATA_SIZE 24
#define INV_MPU6050_REG_INT_PIN_CFG 0x37
#define INV_MPU6050_ACTIVE_HIGH 0x00
#define INV_MPU6050_ACTIVE_LOW 0x80
/* enable level triggering */
#define INV_MPU6050_LATCH_INT_EN 0x20
#define INV_MPU6050_BIT_BYPASS_EN 0x2
#define INV_MPU6050_INT_PIN_CFG 0
/* init parameters */
#define INV_MPU6050_INIT_FIFO_RATE 50
......@@ -232,6 +246,7 @@ struct inv_mpu6050_state {
#define INV_MPU6500_WHOAMI_VALUE 0x70
#define INV_MPU9150_WHOAMI_VALUE 0x68
#define INV_MPU9250_WHOAMI_VALUE 0x71
#define INV_MPU9255_WHOAMI_VALUE 0x73
#define INV_ICM20608_WHOAMI_VALUE 0xAF
/* scan element definition */
......@@ -287,8 +302,7 @@ enum inv_mpu6050_clock_sel_e {
irqreturn_t inv_mpu6050_irq_handler(int irq, void *p);
irqreturn_t inv_mpu6050_read_fifo(int irq, void *p);
int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev);
void inv_mpu6050_remove_trigger(struct inv_mpu6050_state *st);
int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type);
int inv_reset_fifo(struct iio_dev *indio_dev);
int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask);
int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val);
......@@ -297,6 +311,4 @@ int inv_mpu_acpi_create_mux_client(struct i2c_client *client);
void inv_mpu_acpi_delete_mux_client(struct i2c_client *client);
int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
int (*inv_mpu_bus_setup)(struct iio_dev *), int chip_type);
int inv_mpu_core_remove(struct device *dev);
int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on);
extern const struct dev_pm_ops inv_mpu_pmops;
......@@ -51,13 +51,14 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
if (result)
goto reset_fifo_fail;
/* disable fifo reading */
result = regmap_write(st->map, st->reg->user_ctrl, 0);
result = regmap_write(st->map, st->reg->user_ctrl,
st->chip_config.user_ctrl);
if (result)
goto reset_fifo_fail;
/* reset FIFO*/
result = regmap_write(st->map, st->reg->user_ctrl,
INV_MPU6050_BIT_FIFO_RST);
d = st->chip_config.user_ctrl | INV_MPU6050_BIT_FIFO_RST;
result = regmap_write(st->map, st->reg->user_ctrl, d);
if (result)
goto reset_fifo_fail;
......@@ -72,9 +73,9 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
if (result)
return result;
}
/* enable FIFO reading and I2C master interface*/
result = regmap_write(st->map, st->reg->user_ctrl,
INV_MPU6050_BIT_FIFO_EN);
/* enable FIFO reading */
d = st->chip_config.user_ctrl | INV_MPU6050_BIT_FIFO_EN;
result = regmap_write(st->map, st->reg->user_ctrl, d);
if (result)
goto reset_fifo_fail;
/* enable sensor output to FIFO */
......@@ -127,8 +128,23 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
u8 data[INV_MPU6050_OUTPUT_DATA_SIZE];
u16 fifo_count;
s64 timestamp;
int int_status;
mutex_lock(&st->lock);
/* ack interrupt and check status */
result = regmap_read(st->map, st->reg->int_status, &int_status);
if (result) {
dev_err(regmap_get_device(st->map),
"failed to ack interrupt\n");
goto flush_fifo;
}
if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) {
dev_warn(regmap_get_device(st->map),
"spurious interrupt with status 0x%x\n", int_status);
goto end_session;
}
if (!(st->chip_config.accl_fifo_enable |
st->chip_config.gyro_fifo_enable))
goto end_session;
......@@ -140,7 +156,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
/*
* read fifo_count register to know how many bytes inside FIFO
* read fifo_count register to know how many bytes are inside the FIFO
* right now
*/
result = regmap_bulk_read(st->map, st->reg->fifo_count_h, data,
......@@ -150,7 +166,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
fifo_count = be16_to_cpup((__be16 *)(&data[0]));
if (fifo_count < bytes_per_datum)
goto end_session;
/* fifo count can't be odd number, if it is odd, reset fifo*/
/* fifo count can't be an odd number. If it is odd, reset the FIFO. */
if (fifo_count & 1)
goto flush_fifo;
if (fifo_count > INV_MPU6050_FIFO_THRESHOLD)
......@@ -170,10 +186,13 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
if (result == 0)
timestamp = 0;
result = iio_push_to_buffers_with_timestamp(indio_dev, data,
/* skip first samples if needed */
if (st->skip_samples)
st->skip_samples--;
else
iio_push_to_buffers_with_timestamp(indio_dev, data,
timestamp);
if (result)
goto flush_fifo;
fifo_count -= bytes_per_datum;
}
......
......@@ -31,8 +31,9 @@ static int inv_mpu_i2c_disable(struct iio_dev *indio_dev)
if (ret)
return ret;
ret = regmap_write(st->map, INV_MPU6050_REG_USER_CTRL,
INV_MPU6050_BIT_I2C_IF_DIS);
st->chip_config.user_ctrl |= INV_MPU6050_BIT_I2C_IF_DIS;
ret = regmap_write(st->map, st->reg->user_ctrl,
st->chip_config.user_ctrl);
if (ret) {
inv_mpu6050_set_power_itg(st, false);
return ret;
......@@ -69,11 +70,6 @@ static int inv_mpu_probe(struct spi_device *spi)
inv_mpu_i2c_disable, chip_type);
}
static int inv_mpu_remove(struct spi_device *spi)
{
return inv_mpu_core_remove(&spi->dev);
}
/*
* device id table is used to identify what device can be
* supported by this driver
......@@ -83,6 +79,7 @@ static const struct spi_device_id inv_mpu_id[] = {
{"mpu6500", INV_MPU6500},
{"mpu9150", INV_MPU9150},
{"mpu9250", INV_MPU9250},
{"mpu9255", INV_MPU9255},
{"icm20608", INV_ICM20608},
{}
};
......@@ -97,7 +94,6 @@ MODULE_DEVICE_TABLE(acpi, inv_acpi_match);
static struct spi_driver inv_mpu_driver = {
.probe = inv_mpu_probe,
.remove = inv_mpu_remove,
.id_table = inv_mpu_id,
.driver = {
.acpi_match_table = ACPI_PTR(inv_acpi_match),
......
......@@ -49,49 +49,66 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
if (result)
return result;
inv_scan_query(indio_dev);
st->skip_samples = 0;
if (st->chip_config.gyro_fifo_enable) {
result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_BIT_PWR_GYRO_STBY);
if (result)
return result;
goto error_power_off;
/* gyro first sample is out of specs, skip it */
st->skip_samples = 1;
}
if (st->chip_config.accl_fifo_enable) {
result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_BIT_PWR_ACCL_STBY);
if (result)
return result;
goto error_gyro_off;
}
result = inv_reset_fifo(indio_dev);
if (result)
return result;
goto error_accl_off;
} else {
result = regmap_write(st->map, st->reg->fifo_en, 0);
if (result)
return result;
goto error_accl_off;
result = regmap_write(st->map, st->reg->int_enable, 0);
if (result)
return result;
goto error_accl_off;
result = regmap_write(st->map, st->reg->user_ctrl, 0);
result = regmap_write(st->map, st->reg->user_ctrl,
st->chip_config.user_ctrl);
if (result)
return result;
goto error_accl_off;
result = inv_mpu6050_switch_engine(st, false,
INV_MPU6050_BIT_PWR_GYRO_STBY);
INV_MPU6050_BIT_PWR_ACCL_STBY);
if (result)
return result;
goto error_accl_off;
result = inv_mpu6050_switch_engine(st, false,
INV_MPU6050_BIT_PWR_ACCL_STBY);
INV_MPU6050_BIT_PWR_GYRO_STBY);
if (result)
return result;
goto error_gyro_off;
result = inv_mpu6050_set_power_itg(st, false);
if (result)
return result;
goto error_power_off;
}
return 0;
error_accl_off:
if (st->chip_config.accl_fifo_enable)
inv_mpu6050_switch_engine(st, false,
INV_MPU6050_BIT_PWR_ACCL_STBY);
error_gyro_off:
if (st->chip_config.gyro_fifo_enable)
inv_mpu6050_switch_engine(st, false,
INV_MPU6050_BIT_PWR_GYRO_STBY);
error_power_off:
inv_mpu6050_set_power_itg(st, false);
return result;
}
/**
......@@ -117,7 +134,7 @@ static const struct iio_trigger_ops inv_mpu_trigger_ops = {
.set_trigger_state = &inv_mpu_data_rdy_trigger_set_state,
};
int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type)
{
int ret;
struct inv_mpu6050_state *st = iio_priv(indio_dev);
......@@ -131,7 +148,7 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
ret = devm_request_irq(&indio_dev->dev, st->irq,
&iio_trigger_generic_data_rdy_poll,
IRQF_TRIGGER_RISING,
irq_type,
"inv_mpu",
st->trig);
if (ret)
......@@ -141,7 +158,7 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
st->trig->ops = &inv_mpu_trigger_ops;
iio_trigger_set_drvdata(st->trig, indio_dev);
ret = iio_trigger_register(st->trig);
ret = devm_iio_trigger_register(&indio_dev->dev, st->trig);
if (ret)
return ret;
......@@ -149,8 +166,3 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
return 0;
}
void inv_mpu6050_remove_trigger(struct inv_mpu6050_state *st)
{
iio_trigger_unregister(st->trig);
}
......@@ -8,7 +8,8 @@ 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, lsm6ds3h, lsm6dsl, lsm6dsm
sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm,
ism330dlc
To compile this driver as a module, choose M here: the module
will be called st_lsm6dsx.
......
......@@ -18,12 +18,14 @@
#define ST_LSM6DS3H_DEV_NAME "lsm6ds3h"
#define ST_LSM6DSL_DEV_NAME "lsm6dsl"
#define ST_LSM6DSM_DEV_NAME "lsm6dsm"
#define ST_ISM330DLC_DEV_NAME "ism330dlc"
enum st_lsm6dsx_hw_id {
ST_LSM6DS3_ID,
ST_LSM6DS3H_ID,
ST_LSM6DSL_ID,
ST_LSM6DSM_ID,
ST_ISM330DLC_ID,
ST_LSM6DSX_MAX_ID,
};
......
/*
* STMicroelectronics st_lsm6dsx FIFO buffer library driver
*
* 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):
* LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC: 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
......@@ -276,7 +276,7 @@ static inline int st_lsm6dsx_read_block(struct st_lsm6dsx_hw *hw, u8 *data,
#define ST_LSM6DSX_IIO_BUFF_SIZE (ALIGN(ST_LSM6DSX_SAMPLE_SIZE, \
sizeof(s64)) + sizeof(s64))
/**
* st_lsm6dsx_read_fifo() - LSM6DS3-LSM6DS3H-LSM6DSL-LSM6DSM read FIFO routine
* st_lsm6dsx_read_fifo() - hw FIFO read 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
*
* - LSM6DS3H/LSM6DSL/LSM6DSM:
* - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC:
* - 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
......@@ -252,6 +252,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.id = {
[0] = ST_LSM6DSL_ID,
[1] = ST_LSM6DSM_ID,
[2] = ST_ISM330DLC_ID,
},
.decimator = {
[ST_LSM6DSX_ID_ACC] = {
......@@ -266,11 +267,11 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fifo_ops = {
.fifo_th = {
.addr = 0x06,
.mask = GENMASK(11, 0),
.mask = GENMASK(10, 0),
},
.fifo_diff = {
.addr = 0x3a,
.mask = GENMASK(11, 0),
.mask = GENMASK(10, 0),
},
.th_wl = 3, /* 1LSB = 2B */
},
......
......@@ -57,6 +57,10 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = {
.compatible = "st,lsm6dsm",
.data = (void *)ST_LSM6DSM_ID,
},
{
.compatible = "st,ism330dlc",
.data = (void *)ST_ISM330DLC_ID,
},
{},
};
MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match);
......@@ -66,6 +70,7 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = {
{ ST_LSM6DS3H_DEV_NAME, ST_LSM6DS3H_ID },
{ ST_LSM6DSL_DEV_NAME, ST_LSM6DSL_ID },
{ ST_LSM6DSM_DEV_NAME, ST_LSM6DSM_ID },
{ ST_ISM330DLC_DEV_NAME, ST_ISM330DLC_ID },
{},
};
MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table);
......
......@@ -57,6 +57,10 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = {
.compatible = "st,lsm6dsm",
.data = (void *)ST_LSM6DSM_ID,
},
{
.compatible = "st,ism330dlc",
.data = (void *)ST_ISM330DLC_ID,
},
{},
};
MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match);
......@@ -66,6 +70,7 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = {
{ ST_LSM6DS3H_DEV_NAME, ST_LSM6DS3H_ID },
{ ST_LSM6DSL_DEV_NAME, ST_LSM6DSL_ID },
{ ST_LSM6DSM_DEV_NAME, ST_LSM6DSM_ID },
{ ST_ISM330DLC_DEV_NAME, ST_ISM330DLC_ID },
{},
};
MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table);
......
......@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/iio/buffer.h>
#include <linux/iio/common/cros_ec_sensors_core.h>
#include <linux/iio/iio.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/trigger.h>
......@@ -29,8 +30,6 @@
#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
......
......@@ -99,6 +99,23 @@ static const struct iio_info mcp4018_info = {
.write_raw = mcp4018_write_raw,
};
static const struct i2c_device_id mcp4018_id[] = {
{ "mcp4017-502", MCP4018_502 },
{ "mcp4017-103", MCP4018_103 },
{ "mcp4017-503", MCP4018_503 },
{ "mcp4017-104", MCP4018_104 },
{ "mcp4018-502", MCP4018_502 },
{ "mcp4018-103", MCP4018_103 },
{ "mcp4018-503", MCP4018_503 },
{ "mcp4018-104", MCP4018_104 },
{ "mcp4019-502", MCP4018_502 },
{ "mcp4019-103", MCP4018_103 },
{ "mcp4019-503", MCP4018_503 },
{ "mcp4019-104", MCP4018_104 },
{}
};
MODULE_DEVICE_TABLE(i2c, mcp4018_id);
#ifdef CONFIG_OF
#define MCP4018_COMPATIBLE(of_compatible, cfg) { \
......@@ -125,8 +142,7 @@ MODULE_DEVICE_TABLE(of, mcp4018_of_match);
#endif
static int mcp4018_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int mcp4018_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct mcp4018_data *data;
......@@ -150,7 +166,7 @@ static int mcp4018_probe(struct i2c_client *client,
if (match)
data->cfg = of_device_get_match_data(dev);
else
data->cfg = &mcp4018_cfg[id->driver_data];
data->cfg = &mcp4018_cfg[i2c_match_id(mcp4018_id, client)->driver_data];
indio_dev->dev.parent = dev;
indio_dev->info = &mcp4018_info;
......@@ -161,29 +177,12 @@ static int mcp4018_probe(struct i2c_client *client,
return devm_iio_device_register(dev, indio_dev);
}
static const struct i2c_device_id mcp4018_id[] = {
{ "mcp4017-502", MCP4018_502 },
{ "mcp4017-103", MCP4018_103 },
{ "mcp4017-503", MCP4018_503 },
{ "mcp4017-104", MCP4018_104 },
{ "mcp4018-502", MCP4018_502 },
{ "mcp4018-103", MCP4018_103 },
{ "mcp4018-503", MCP4018_503 },
{ "mcp4018-104", MCP4018_104 },
{ "mcp4019-502", MCP4018_502 },
{ "mcp4019-103", MCP4018_103 },
{ "mcp4019-503", MCP4018_503 },
{ "mcp4019-104", MCP4018_104 },
{}
};
MODULE_DEVICE_TABLE(i2c, mcp4018_id);
static struct i2c_driver mcp4018_driver = {
.driver = {
.name = "mcp4018",
.of_match_table = of_match_ptr(mcp4018_of_match),
},
.probe = mcp4018_probe,
.probe_new = mcp4018_probe,
.id_table = mcp4018_id,
};
......
......@@ -209,6 +209,75 @@ static const struct iio_info mcp4531_info = {
.write_raw = mcp4531_write_raw,
};
static const struct i2c_device_id mcp4531_id[] = {
{ "mcp4531-502", MCP453x_502 },
{ "mcp4531-103", MCP453x_103 },
{ "mcp4531-503", MCP453x_503 },
{ "mcp4531-104", MCP453x_104 },
{ "mcp4532-502", MCP453x_502 },
{ "mcp4532-103", MCP453x_103 },
{ "mcp4532-503", MCP453x_503 },
{ "mcp4532-104", MCP453x_104 },
{ "mcp4541-502", MCP454x_502 },
{ "mcp4541-103", MCP454x_103 },
{ "mcp4541-503", MCP454x_503 },
{ "mcp4541-104", MCP454x_104 },
{ "mcp4542-502", MCP454x_502 },
{ "mcp4542-103", MCP454x_103 },
{ "mcp4542-503", MCP454x_503 },
{ "mcp4542-104", MCP454x_104 },
{ "mcp4551-502", MCP455x_502 },
{ "mcp4551-103", MCP455x_103 },
{ "mcp4551-503", MCP455x_503 },
{ "mcp4551-104", MCP455x_104 },
{ "mcp4552-502", MCP455x_502 },
{ "mcp4552-103", MCP455x_103 },
{ "mcp4552-503", MCP455x_503 },
{ "mcp4552-104", MCP455x_104 },
{ "mcp4561-502", MCP456x_502 },
{ "mcp4561-103", MCP456x_103 },
{ "mcp4561-503", MCP456x_503 },
{ "mcp4561-104", MCP456x_104 },
{ "mcp4562-502", MCP456x_502 },
{ "mcp4562-103", MCP456x_103 },
{ "mcp4562-503", MCP456x_503 },
{ "mcp4562-104", MCP456x_104 },
{ "mcp4631-502", MCP463x_502 },
{ "mcp4631-103", MCP463x_103 },
{ "mcp4631-503", MCP463x_503 },
{ "mcp4631-104", MCP463x_104 },
{ "mcp4632-502", MCP463x_502 },
{ "mcp4632-103", MCP463x_103 },
{ "mcp4632-503", MCP463x_503 },
{ "mcp4632-104", MCP463x_104 },
{ "mcp4641-502", MCP464x_502 },
{ "mcp4641-103", MCP464x_103 },
{ "mcp4641-503", MCP464x_503 },
{ "mcp4641-104", MCP464x_104 },
{ "mcp4642-502", MCP464x_502 },
{ "mcp4642-103", MCP464x_103 },
{ "mcp4642-503", MCP464x_503 },
{ "mcp4642-104", MCP464x_104 },
{ "mcp4651-502", MCP465x_502 },
{ "mcp4651-103", MCP465x_103 },
{ "mcp4651-503", MCP465x_503 },
{ "mcp4651-104", MCP465x_104 },
{ "mcp4652-502", MCP465x_502 },
{ "mcp4652-103", MCP465x_103 },
{ "mcp4652-503", MCP465x_503 },
{ "mcp4652-104", MCP465x_104 },
{ "mcp4661-502", MCP466x_502 },
{ "mcp4661-103", MCP466x_103 },
{ "mcp4661-503", MCP466x_503 },
{ "mcp4661-104", MCP466x_104 },
{ "mcp4662-502", MCP466x_502 },
{ "mcp4662-103", MCP466x_103 },
{ "mcp4662-503", MCP466x_503 },
{ "mcp4662-104", MCP466x_104 },
{}
};
MODULE_DEVICE_TABLE(i2c, mcp4531_id);
#ifdef CONFIG_OF
#define MCP4531_COMPATIBLE(of_compatible, cfg) { \
......@@ -286,8 +355,7 @@ static const struct of_device_id mcp4531_of_match[] = {
MODULE_DEVICE_TABLE(of, mcp4531_of_match);
#endif
static int mcp4531_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int mcp4531_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct mcp4531_data *data;
......@@ -311,7 +379,7 @@ static int mcp4531_probe(struct i2c_client *client,
if (match)
data->cfg = of_device_get_match_data(dev);
else
data->cfg = &mcp4531_cfg[id->driver_data];
data->cfg = &mcp4531_cfg[i2c_match_id(mcp4531_id, client)->driver_data];
indio_dev->dev.parent = dev;
indio_dev->info = &mcp4531_info;
......@@ -322,81 +390,12 @@ static int mcp4531_probe(struct i2c_client *client,
return devm_iio_device_register(dev, indio_dev);
}
static const struct i2c_device_id mcp4531_id[] = {
{ "mcp4531-502", MCP453x_502 },
{ "mcp4531-103", MCP453x_103 },
{ "mcp4531-503", MCP453x_503 },
{ "mcp4531-104", MCP453x_104 },
{ "mcp4532-502", MCP453x_502 },
{ "mcp4532-103", MCP453x_103 },
{ "mcp4532-503", MCP453x_503 },
{ "mcp4532-104", MCP453x_104 },
{ "mcp4541-502", MCP454x_502 },
{ "mcp4541-103", MCP454x_103 },
{ "mcp4541-503", MCP454x_503 },
{ "mcp4541-104", MCP454x_104 },
{ "mcp4542-502", MCP454x_502 },
{ "mcp4542-103", MCP454x_103 },
{ "mcp4542-503", MCP454x_503 },
{ "mcp4542-104", MCP454x_104 },
{ "mcp4551-502", MCP455x_502 },
{ "mcp4551-103", MCP455x_103 },
{ "mcp4551-503", MCP455x_503 },
{ "mcp4551-104", MCP455x_104 },
{ "mcp4552-502", MCP455x_502 },
{ "mcp4552-103", MCP455x_103 },
{ "mcp4552-503", MCP455x_503 },
{ "mcp4552-104", MCP455x_104 },
{ "mcp4561-502", MCP456x_502 },
{ "mcp4561-103", MCP456x_103 },
{ "mcp4561-503", MCP456x_503 },
{ "mcp4561-104", MCP456x_104 },
{ "mcp4562-502", MCP456x_502 },
{ "mcp4562-103", MCP456x_103 },
{ "mcp4562-503", MCP456x_503 },
{ "mcp4562-104", MCP456x_104 },
{ "mcp4631-502", MCP463x_502 },
{ "mcp4631-103", MCP463x_103 },
{ "mcp4631-503", MCP463x_503 },
{ "mcp4631-104", MCP463x_104 },
{ "mcp4632-502", MCP463x_502 },
{ "mcp4632-103", MCP463x_103 },
{ "mcp4632-503", MCP463x_503 },
{ "mcp4632-104", MCP463x_104 },
{ "mcp4641-502", MCP464x_502 },
{ "mcp4641-103", MCP464x_103 },
{ "mcp4641-503", MCP464x_503 },
{ "mcp4641-104", MCP464x_104 },
{ "mcp4642-502", MCP464x_502 },
{ "mcp4642-103", MCP464x_103 },
{ "mcp4642-503", MCP464x_503 },
{ "mcp4642-104", MCP464x_104 },
{ "mcp4651-502", MCP465x_502 },
{ "mcp4651-103", MCP465x_103 },
{ "mcp4651-503", MCP465x_503 },
{ "mcp4651-104", MCP465x_104 },
{ "mcp4652-502", MCP465x_502 },
{ "mcp4652-103", MCP465x_103 },
{ "mcp4652-503", MCP465x_503 },
{ "mcp4652-104", MCP465x_104 },
{ "mcp4661-502", MCP466x_502 },
{ "mcp4661-103", MCP466x_103 },
{ "mcp4661-503", MCP466x_503 },
{ "mcp4661-104", MCP466x_104 },
{ "mcp4662-502", MCP466x_502 },
{ "mcp4662-103", MCP466x_103 },
{ "mcp4662-503", MCP466x_503 },
{ "mcp4662-104", MCP466x_104 },
{}
};
MODULE_DEVICE_TABLE(i2c, mcp4531_id);
static struct i2c_driver mcp4531_driver = {
.driver = {
.name = "mcp4531",
.of_match_table = of_match_ptr(mcp4531_of_match),
},
.probe = mcp4531_probe,
.probe_new = mcp4531_probe,
.id_table = mcp4531_id,
};
......
......@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/iio/buffer.h>
#include <linux/iio/common/cros_ec_sensors_core.h>
#include <linux/iio/iio.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/trigger.h>
......@@ -28,8 +29,6 @@
#include <linux/slab.h>
#include <linux/platform_device.h>
#include "../common/cros_ec_sensors/cros_ec_sensors_core.h"
/*
* One channel for pressure, the other for timestamp.
*/
......
......@@ -3,18 +3,6 @@
#
menu "Accelerometers"
config ADIS16201
tristate "Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer"
depends on SPI
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say Y here to build support for Analog Devices adis16201 dual-axis
digital inclinometer and accelerometer.
To compile this driver as a module, say M here: the module will
be called adis16201.
config ADIS16203
tristate "Analog Devices ADIS16203 Programmable 360 Degrees Inclinometer"
depends on SPI
......@@ -27,18 +15,6 @@ config ADIS16203
To compile this driver as a module, say M here: the module will be
called adis16203.
config ADIS16209
tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer"
depends on SPI
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say Y here to build support for Analog Devices adis16209 dual-axis digital inclinometer
and accelerometer.
To compile this driver as a module, say M here: the module will be
called adis16209.
config ADIS16240
tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder"
depends on SPI
......
......@@ -2,7 +2,5 @@
# Makefile for industrial I/O accelerometer drivers
#
obj-$(CONFIG_ADIS16201) += adis16201.o
obj-$(CONFIG_ADIS16203) += adis16203.o
obj-$(CONFIG_ADIS16209) += adis16209.o
obj-$(CONFIG_ADIS16240) += adis16240.o
......@@ -18,8 +18,7 @@
static int ad7606_par16_read_block(struct device *dev,
int count, void *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ad7606_state *st = iio_priv(indio_dev);
insw((unsigned long)st->base_address, buf, count);
......@@ -34,8 +33,7 @@ static const struct ad7606_bus_ops ad7606_par16_bops = {
static int ad7606_par8_read_block(struct device *dev,
int count, void *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ad7606_state *st = iio_priv(indio_dev);
insb((unsigned long)st->base_address, buf, count * 2);
......
......@@ -128,7 +128,7 @@ static const struct ad_sigma_delta_info ad7780_sigma_delta_info = {
};
#define AD7780_CHANNEL(bits, wordsize) \
AD_SD_CHANNEL(1, 0, 0, bits, 32, wordsize - bits)
AD_SD_CHANNEL_NO_SAMP_FREQ(1, 0, 0, bits, 32, wordsize - bits)
static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
[ID_AD7170] = {
......
......@@ -6,15 +6,15 @@
* Licensed under the GPL-2.
*/
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/sysfs.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
......@@ -220,8 +220,8 @@ static int ad7746_select_channel(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan)
{
struct ad7746_chip_info *chip = iio_priv(indio_dev);
int ret, delay, idx;
u8 vt_setup, cap_setup;
int ret, delay, idx;
switch (chan->type) {
case IIO_CAPACITANCE:
......@@ -289,8 +289,8 @@ static inline ssize_t ad7746_start_calib(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7746_chip_info *chip = iio_priv(indio_dev);
bool doit;
int ret, timeout = 10;
bool doit;
ret = strtobool(buf, &doit);
if (ret < 0)
......@@ -410,8 +410,7 @@ static struct attribute *ad7746_attributes[] = {
&iio_dev_attr_in_capacitance1_calibbias_calibration.dev_attr.attr,
&iio_dev_attr_in_voltage0_calibscale_calibration.dev_attr.attr,
&iio_const_attr_in_voltage_sampling_frequency_available.dev_attr.attr,
&iio_const_attr_in_capacitance_sampling_frequency_available.
dev_attr.attr,
&iio_const_attr_in_capacitance_sampling_frequency_available.dev_attr.attr,
NULL,
};
......@@ -451,26 +450,26 @@ static int ad7746_write_raw(struct iio_dev *indio_dev,
goto out;
}
ret = i2c_smbus_write_word_data(chip->client, reg, swab16(val));
ret = i2c_smbus_write_word_swapped(chip->client, reg, val);
if (ret < 0)
goto out;
ret = 0;
break;
case IIO_CHAN_INFO_CALIBBIAS:
if ((val < 0) | (val > 0xFFFF)) {
if (val < 0 || val > 0xFFFF) {
ret = -EINVAL;
goto out;
}
ret = i2c_smbus_write_word_data(chip->client,
AD7746_REG_CAP_OFFH, swab16(val));
ret = i2c_smbus_write_word_swapped(chip->client,
AD7746_REG_CAP_OFFH, val);
if (ret < 0)
goto out;
ret = 0;
break;
case IIO_CHAN_INFO_OFFSET:
if ((val < 0) | (val > 43008000)) { /* 21pF */
if (val < 0 || val > 43008000) { /* 21pF */
ret = -EINVAL;
goto out;
}
......@@ -556,7 +555,8 @@ static int ad7746_read_raw(struct iio_dev *indio_dev,
/* Now read the actual register */
ret = i2c_smbus_read_i2c_block_data(chip->client,
chan->address >> 8, 3, &chip->data.d8[1]);
chan->address >> 8, 3,
&chip->data.d8[1]);
if (ret < 0)
goto out;
......@@ -594,21 +594,21 @@ static int ad7746_read_raw(struct iio_dev *indio_dev,
goto out;
}
ret = i2c_smbus_read_word_data(chip->client, reg);
ret = i2c_smbus_read_word_swapped(chip->client, reg);
if (ret < 0)
goto out;
/* 1 + gain_val / 2^16 */
*val = 1;
*val2 = (15625 * swab16(ret)) / 1024;
*val2 = (15625 * ret) / 1024;
ret = IIO_VAL_INT_PLUS_MICRO;
break;
case IIO_CHAN_INFO_CALIBBIAS:
ret = i2c_smbus_read_word_data(chip->client,
ret = i2c_smbus_read_word_swapped(chip->client,
AD7746_REG_CAP_OFFH);
if (ret < 0)
goto out;
*val = swab16(ret);
*val = ret;
ret = IIO_VAL_INT;
break;
......@@ -680,8 +680,8 @@ static int ad7746_probe(struct i2c_client *client,
struct ad7746_platform_data *pdata = client->dev.platform_data;
struct ad7746_chip_info *chip;
struct iio_dev *indio_dev;
int ret = 0;
unsigned char regval = 0;
int ret = 0;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
if (!indio_dev)
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Device driver for monitoring ambient light intensity (lux)
* and proximity (prox) within the TAOS TSL2X7X family of devices.
*
* Copyright (c) 2012, TAOS Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __TSL2X7X_H
#define __TSL2X7X_H
struct tsl2x7x_lux {
unsigned int ratio;
unsigned int ch0;
unsigned int ch1;
};
/* Max number of segments allowable in LUX table */
#define TSL2X7X_MAX_LUX_TABLE_SIZE 9
#define TSL2X7X_MAX_LUX_TABLE_SIZE 6
/* The default LUX tables all have 3 elements. */
#define TSL2X7X_DEF_LUX_TABLE_SZ 3
#define TSL2X7X_DEFAULT_TABLE_BYTES (sizeof(struct tsl2x7x_lux) * \
TSL2X7X_DEF_LUX_TABLE_SZ)
/* Proximity diode to use */
#define TSL2X7X_DIODE0 0x01
#define TSL2X7X_DIODE1 0x02
#define TSL2X7X_DIODE_BOTH 0x03
/* LED Power */
#define TSL2X7X_100_mA 0x00
#define TSL2X7X_50_mA 0x01
#define TSL2X7X_25_mA 0x02
#define TSL2X7X_13_mA 0x03
#define TSL2X7X_MAX_TIMER_CNT 0xFF
/**
* struct tsl2x7x_default_settings - power on defaults unless
* overridden by platform data.
* @als_time: ALS Integration time - multiple of 50mS
* @als_gain: Index into the ALS gain table.
* @als_gain_trim: default gain trim to account for
* aperture effects.
* @wait_time: Time between PRX and ALS cycles
* in 2.7 periods
* @prx_time: 5.2ms prox integration time -
* decrease in 2.7ms periods
* @prx_gain: Proximity gain index
* @prox_config: Prox configuration filters.
* @als_cal_target: Known external ALS reading for
* calibration.
* @interrupts_en: Enable/Disable - 0x00 = none, 0x10 = als,
* 0x20 = prx, 0x30 = bth
* @persistence: H/W Filters, Number of 'out of limits'
* ADC readings PRX/ALS.
* struct tsl2x7x_settings - Settings for the tsl2x7x driver
* @als_time: Integration time of the ALS channel ADCs in 2.73 ms
* increments. Total integration time is
* (256 - als_time) * 2.73.
* @als_gain: Index into the tsl2x7x_als_gain array.
* @als_gain_trim: Default gain trim to account for aperture effects.
* @wait_time: Time between proximity and ALS cycles in 2.73
* periods.
* @prox_time: Integration time of the proximity ADC in 2.73 ms
* increments. Total integration time is
* (256 - prx_time) * 2.73.
* @prox_gain: Index into the tsl2x7x_prx_gain array.
* @als_prox_config: The value of the ALS / Proximity configuration
* register.
* @als_cal_target: Known external ALS reading for calibration.
* @als_persistence: H/W Filters, Number of 'out of limits' ALS readings.
* @als_interrupt_en: Enable/Disable ALS interrupts
* @als_thresh_low: CH0 'low' count to trigger interrupt.
* @als_thresh_high: CH0 'high' count to trigger interrupt.
* @prox_persistence: H/W Filters, Number of 'out of limits' proximity
* readings.
* @prox_interrupt_en: Enable/Disable proximity interrupts.
* @prox_thres_low: Low threshold proximity detection.
* @prox_thres_high: High threshold proximity detection
* @prox_pulse_count: Number if proximity emitter pulses
* @prox_max_samples_cal: Used for prox cal.
* @prox_thres_high: High threshold proximity detection.
* @prox_pulse_count: Number if proximity emitter pulses.
* @prox_max_samples_cal: The number of samples that are taken when performing
* a proximity calibration.
* @prox_diode Which diode(s) to use for driving the external
* LED(s) for proximity sensing.
* @prox_power The amount of power to use for the external LED(s).
*/
struct tsl2x7x_settings {
int als_time;
int als_gain;
int als_gain_trim;
int wait_time;
int prx_time;
int prox_time;
int prox_gain;
int prox_config;
int als_prox_config;
int als_cal_target;
u8 interrupts_en;
u8 persistence;
u8 als_persistence;
bool als_interrupt_en;
int als_thresh_low;
int als_thresh_high;
u8 prox_persistence;
bool prox_interrupt_en;
int prox_thres_low;
int prox_thres_high;
int prox_pulse_count;
......@@ -84,9 +90,6 @@ struct tsl2x7x_settings {
/**
* struct tsl2X7X_platform_data - Platform callback, glass and defaults
* @platform_power: Suspend/resume platform callback
* @power_on: Power on callback
* @power_off: Power off callback
* @platform_lux_table: Device specific glass coefficents
* @platform_default_settings: Device specific power on defaults
*
......
This diff is collapsed.
This diff is collapsed.
......@@ -27,13 +27,13 @@ static ssize_t ade7854_read_8bit(struct device *dev,
char *buf)
{
int ret;
u8 val = 0;
u32 val = 0;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = st->read_reg_8(dev, this_attr->address, &val);
if (ret)
ret = st->read_reg(dev, this_attr->address, &val, 8);
if (ret < 0)
return ret;
return sprintf(buf, "%u\n", val);
......@@ -44,13 +44,13 @@ static ssize_t ade7854_read_16bit(struct device *dev,
char *buf)
{
int ret;
u16 val = 0;
u32 val = 0;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = st->read_reg_16(dev, this_attr->address, &val);
if (ret)
ret = st->read_reg(dev, this_attr->address, &val, 16);
if (ret < 0)
return ret;
return sprintf(buf, "%u\n", val);
......@@ -66,8 +66,8 @@ static ssize_t ade7854_read_24bit(struct device *dev,
struct ade7854_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
ret = st->read_reg_24(dev, this_attr->address, &val);
if (ret)
ret = st->read_reg(dev, this_attr->address, &val, 24);
if (ret < 0)
return ret;
return sprintf(buf, "%u\n", val);
......@@ -83,8 +83,8 @@ static ssize_t ade7854_read_32bit(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
ret = st->read_reg_32(dev, this_attr->address, &val);
if (ret)
ret = st->read_reg(dev, this_attr->address, &val, 32);
if (ret < 0)
return ret;
return sprintf(buf, "%u\n", val);
......@@ -105,7 +105,7 @@ static ssize_t ade7854_write_8bit(struct device *dev,
ret = kstrtou8(buf, 10, &val);
if (ret)
goto error_ret;
ret = st->write_reg_8(dev, this_attr->address, val);
ret = st->write_reg(dev, this_attr->address, val, 8);
error_ret:
return ret ? ret : len;
......@@ -126,7 +126,7 @@ static ssize_t ade7854_write_16bit(struct device *dev,
ret = kstrtou16(buf, 10, &val);
if (ret)
goto error_ret;
ret = st->write_reg_16(dev, this_attr->address, val);
ret = st->write_reg(dev, this_attr->address, val, 16);
error_ret:
return ret ? ret : len;
......@@ -147,7 +147,7 @@ static ssize_t ade7854_write_24bit(struct device *dev,
ret = kstrtou32(buf, 10, &val);
if (ret)
goto error_ret;
ret = st->write_reg_24(dev, this_attr->address, val);
ret = st->write_reg(dev, this_attr->address, val, 24);
error_ret:
return ret ? ret : len;
......@@ -168,7 +168,7 @@ static ssize_t ade7854_write_32bit(struct device *dev,
ret = kstrtou32(buf, 10, &val);
if (ret)
goto error_ret;
ret = st->write_reg_32(dev, this_attr->address, val);
ret = st->write_reg(dev, this_attr->address, val, 32);
error_ret:
return ret ? ret : len;
......@@ -178,12 +178,12 @@ static int ade7854_reset(struct device *dev)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
u16 val;
u32 val;
st->read_reg_16(dev, ADE7854_CONFIG, &val);
st->read_reg(dev, ADE7854_CONFIG, &val, 16);
val |= BIT(7); /* Software Chip Reset */
return st->write_reg_16(dev, ADE7854_CONFIG, val);
return st->write_reg(dev, ADE7854_CONFIG, val, 16);
}
static IIO_DEV_ATTR_AIGAIN(0644,
......@@ -415,8 +415,8 @@ static int ade7854_set_irq(struct device *dev, bool enable)
int ret;
u32 irqen;
ret = st->read_reg_32(dev, ADE7854_MASK0, &irqen);
if (ret)
ret = st->read_reg(dev, ADE7854_MASK0, &irqen, 32);
if (ret < 0)
return ret;
if (enable)
......@@ -426,7 +426,7 @@ static int ade7854_set_irq(struct device *dev, bool enable)
else
irqen &= ~BIT(17);
return st->write_reg_32(dev, ADE7854_MASK0, irqen);
return st->write_reg(dev, ADE7854_MASK0, irqen, 32);
}
static int ade7854_initial_setup(struct iio_dev *indio_dev)
......
......@@ -146,6 +146,8 @@
/**
* struct ade7854_state - device instance specific data
* @spi: actual spi_device
* @read_reg Wrapper function for I2C and SPI read
* @write_reg Wrapper function for I2C and SPI write
* @indio_dev: industrial I/O device structure
* @buf_lock: mutex to protect tx and rx
* @tx: transmit buffer
......@@ -154,14 +156,10 @@
struct ade7854_state {
struct spi_device *spi;
struct i2c_client *i2c;
int (*read_reg_8)(struct device *dev, u16 reg_address, u8 *val);
int (*read_reg_16)(struct device *dev, u16 reg_address, u16 *val);
int (*read_reg_24)(struct device *dev, u16 reg_address, u32 *val);
int (*read_reg_32)(struct device *dev, u16 reg_address, u32 *val);
int (*write_reg_8)(struct device *dev, u16 reg_address, u8 val);
int (*write_reg_16)(struct device *dev, u16 reg_address, u16 val);
int (*write_reg_24)(struct device *dev, u16 reg_address, u32 val);
int (*write_reg_32)(struct device *dev, u16 reg_address, u32 val);
int (*read_reg)(struct device *dev, u16 reg_address, u32 *val,
int bits);
int (*write_reg)(struct device *dev, u16 reg_address, u32 val,
int bits);
int irq;
struct mutex buf_lock;
u8 tx[ADE7854_MAX_TX] ____cacheline_aligned;
......
This diff is collapsed.
This diff is collapsed.
......@@ -16,7 +16,9 @@
#ifndef __CROS_EC_SENSORS_CORE_H
#define __CROS_EC_SENSORS_CORE_H
#include <linux/iio/iio.h>
#include <linux/irqreturn.h>
#include <linux/mfd/cros_ec.h>
enum {
CROS_EC_SENSOR_X,
......@@ -103,6 +105,7 @@ int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, unsigned long scan_mask,
int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask,
s16 *data);
struct platform_device;
/**
* cros_ec_sensors_core_init() - basic initialization of the core structure
* @pdev: platform device created for the sensors
......
......@@ -183,18 +183,18 @@ struct iio_event_spec {
* @address: Driver specific identifier.
* @scan_index: Monotonic index to give ordering in scans when read
* from a buffer.
* @scan_type: sign: 's' or 'u' to specify signed or unsigned
* realbits: Number of valid bits of data
* storagebits: Realbits + padding
* shift: Shift right by this before masking out
* @scan_type: struct describing the scan type
* @scan_type.sign: 's' or 'u' to specify signed or unsigned
* @scan_type.realbits: Number of valid bits of data
* @scan_type.storagebits: Realbits + padding
* @scan_type.shift: Shift right by this before masking out
* realbits.
* repeat: Number of times real/storage bits
* repeats. When the repeat element is
* more than 1, then the type element in
* sysfs will show a repeat value.
* Otherwise, the number of repetitions is
* omitted.
* endianness: little or big endian
* @scan_type.repeat: Number of times real/storage bits repeats.
* When the repeat element is more than 1, then
* the type element in sysfs will show a repeat
* value. Otherwise, the number of repetitions
* is omitted.
* @scan_type.endianness: little or big endian
* @info_mask_separate: What information is to be exported that is specific to
* this channel.
* @info_mask_separate_available: What availability information is to be
......
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