Commit 932f9892 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-5.2a-2' of...

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

Jonathan writes:

First set of new device support, features and fixes for IIO in the 5.2 cycle

Staging graduations
* ad7780
  - Move this ADC driver out of staging.  Included adding some new features
    along the way (see below). Also added DT bindings.

New device support
* adis16480
  - Support the ADIS16495 and ADIS16497 IMU devices making
    heavy use of refactoring of various aspects of the driver in precursor
    patches.
* lsm6dsx
  - Support for the ASM330LHH 6-axis (accelerometer + gyro) sensor.
  - Support for the LSM6DS0X
* matbotix mb1232
  - New driver for this ultrasound ranging device family. Including bindings.
  - Supports mb1202, mb1212, mb1222, mb1232, mb1242, mb7040 and mb7137.
* max31856
  - New driver for this thermocouple temperature sensor.
* meson saradc
  - Support the Meson-G12A (ID addition only).
* stmpe-adc
  - New driver supporting generic ADC alongside touchscreen support which
    previously existed. Includes DT bindings.
* vcnl4000
  - Support for the vcln4040 proximity and light sensor, including adding
    DT bindings for this and parts previously supported.

Features
* core
  - Allow reading of mount matrices from ACPI in addition to DT.
  - Common binding for theromcouple types.
* ad5933
  - Add ABI docs as there are a few 'unsual' elements about this
    device - perhaps because it's our only impedance analyser.
* ad7780
  - Add gain and filter gpio support + readback of current gain and filter.
* adis16480
  - Allow selection fo the dataready pin to be used.
  - Device tree ID table and binding documentation.
  - Support external clock modes, including new bindings.
* bma180
  - Mount matrix support.
* bmc150
  - Mount matrix support.
* bmg160
  - Mount matrix support.
  - DT id table and bindings doc.
* bmp280
  - Put calibration data into the entropy pool.
* hmc5843
  - Mount matrix support.
* itg3200
  - Mount matrix support.
* kxcjk1013
  - Device tree id table, and binding docs.
* lpc32xx
  - Add scale when regulator specified including DT docs for regulator.
* pms7003
  - Add device IDs for all supported parts to driver and binding.
* stm32-dfsdm
  - Enable hw consumer support, scan mode control and a complex set of
    triggered buffer modes.
  - Power management.
* stm32-lptimer-counter
  - power management.
  - Document the pinctrl sleep state binding.
* ti-ads7950
  - GPIO pin support.

Cleanups, minor fixes
* core
  - Use bitmap_zalloc to make it explicit that is what we are doing.
  - Tidy up all the Kconfig files (which had slowly gotten messy)
  - Fix a forwards definition missing issue in iio/driver.h
* ad sigma delta core
  - Improve handling of SPI bus locking vs CS assertion.  This has been
    wrong a long time so not rushing this in.
* ad5064
  - Mlock to local lock.
* ad5933 (staging cleanup)
  - Multiline comment fixes.
  - Include ordering.
  - SPDX.
  - Tidy up Kconfig help which was a bit missleading.
  - Change some non standard attributes to ABI defined ones.
* ad7124
  - White space fix.
* ad7192
  - White space.
  - Use DT clock binding.
  - Improve error reporting.
  - Platform data to DT conversion.
  - Use read_avail callback, mostly to avoid the endless series of
    patches from new contributors trying to falsely put spaces around
    the negative sign.
* ad7280a
  - Add brackets to macros to avoid potential precedence isseus.
  - Add temp vars for event codes to reduce indent and improved readability.
  - Clean out som CamelCase notation.
  - White space.
* ad7606
  - Fix broken file naming in MAINTAINERS.
* ad7780
  - Missing switch defaults to supress warnings and harden the code slightly.
  - Set pattern masks more directly.
  - Add ID values and masks for all supported chips.
  - SPDX + add Renato as a copyright holder as he has done a lot of work on
    this driver.
  - Add brackets to macros to avoid potential precedence issues.
* ad7923
  - White space fixes.
  - Use BIT macro to improve readability.
  - Add brackets to macros to avoid potential precedence issues.
  - Tidy up a null comparisom.
* ad9523
  - Fix a typo in naming of variables.
* adis16400
  - Combine trigger file into main code as no advantage in separate files.
    Rename core file to just adis16400.
  - Squash the header into the c file now there is only one file.
  - Generalize burst mode to support new variants.
* ak8975
  - Local variable to improve readability around mount matrix support.
* as3935
  - Avoid potential race by ensuring remove does exact opposite of
    probe rather than a slightly different order.
* cross_ec
  - Drop some unnecessary includes.
  - Fix some warning and the slightly 'unusual' code.
  - Add some docs for non obvious function.
  - SPDX
* hmc5843
  - Potential unhandled error case.
* iio trigger core
  - Print an error if there is no available irq due to max consumers per
    trigger being set to low.
* iio loop trigger
  - Drop an unlikely on IS_ERR as IS_ERR already has the annotation.
* ingenic-adc
  - Drop a redundant dev_err call as devm_ioremap_resource reports the same
    internally.
* lmp91000
  - Drop some unncessary parentheses and white space tidy up.
  - Invert and if statement to improve readability.
  - Fix a wrong error message.
* lpc32xx
  - Header sorting + drop some unused ones.
* mma8542
  - Mark a switch fallthrough.
* mpu6050
  - Add a local variable to improve code readability around mount matrix
    support.
* mxs-lradc-adc
  - Handle devm_iio_trigger_alloc failure.
* sps30
  - Fix up a kernel version in the ABI docs.
* srf04
  - DT binding doc converted to yaml.
* ssp_sensors
  - Supress a clang build warning due to lack of visibility of conditional
    within a iio_push_to_buffers_with_timestamp.  (reasonable false warning!)
* st_accel
  - Drop pointless less than 0 comparisom of unsigned int.
* stm32-dfsdm
  - Improve accuracy of spi_master_frequency calculation.
  - Improve calculation fo sampling frequency.
  - Rework various internals to simplify adding triggered buffer support.
  - Claim direct mode to avoid racing around read_raw and being in buffered
    mode.
* stmpe
  - Fix a clang false positive warning.
* ti-ads7950
  - Use local lock rather than using the core mlock when not locking around
    the device mode.
* vcnl4000
  - Use word writes instead of byte writes.  It seems byte writes are fine
    for some parts (undocument) but not others that the driver will shortly
    support.

Other
* mailmap
  - Add email address change for Sean Nyekjaer.  Update in relevant drivers

* tag 'iio-for-5.2a-2' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (129 commits)
  iio: ad_sigma_delta: Properly handle SPI bus locking vs CS assertion
  iio: adc: stm32-dfsdm: add PM support
  iio: adc: stm32-dfsdm: improve sampling frequency accuracy
  staging: iio: adc: ad7280a: Tab alignment
  MAINTAINERS: Fix the link to ad7606 dt-bindings
  iio:temperature: Add MAX31856 thermocouple support
  iio:temperature:max31856:Add device tree bind info
  dt-bindings: iio/temperature: Add thermocouple types (and doc)
  devantech-srf04.yaml: transform DT binding to YAML
  iio: frequency: ad9523: Fix typo in ad9523_platform_data
  iio: Make possible to include driver.h first
  dt-bindings: iio: add Bosch BMG160 gyroscope sensor
  iio: gyro: bmg160: add device tree compatibility table
  staging: iio: adc: ad7192: Use read_avail for available attributes
  dt-bindings: iio: light: add vcnl4040 devicetree bindings
  iio: light: vcnl4000 add support for the VCNL4040 proximity and light sensor
  dt-bindings: iio: light: add vcnl4000 devicetree bindings
  iio: light: vcnl4000 add devicetree hooks
  iio: light: vcnl4000 use word writes instead of byte writes
  iio: adc: stm32-dfsdm: claim direct mode for raw read and settings
  ...
parents 44b8ef17 df1d80ae
......@@ -187,6 +187,7 @@ Santosh Shilimkar <ssantosh@kernel.org>
Santosh Shilimkar <santosh.shilimkar@oracle.org>
Sascha Hauer <s.hauer@pengutronix.de>
S.Çağlar Onur <caglar@pardus.org.tr>
Sean Nyekjaer <sean@geanix.com> <sean.nyekjaer@prevas.dk>
Sebastian Reichel <sre@kernel.org> <sre@debian.org>
Sebastian Reichel <sre@kernel.org> <sebastian.reichel@collabora.co.uk>
Shiraz Hashim <shiraz.linux.kernel@gmail.com> <shiraz.hashim@st.com>
......
What: /sys/bus/iio/devices/iio:deviceX/outY_freq_start
What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_frequency_start
Date: March 2019
KernelVersion: 3.1.0
Contact: linux-iio@vger.kernel.org
Description:
Frequency sweep start frequency in Hz.
What: /sys/bus/iio/devices/iio:deviceX/outY_freq_increment
What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_frequency_increment
Date: March 2019
KernelVersion: 3.1.0
Contact: linux-iio@vger.kernel.org
Description:
Frequency increment in Hz (step size) between consecutive
frequency points along the sweep.
What: /sys/bus/iio/devices/iio:deviceX/outY_freq_points
What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_frequency_points
Date: March 2019
KernelVersion: 3.1.0
Contact: linux-iio@vger.kernel.org
Description:
Number of frequency points (steps) in the frequency sweep.
This value, in conjunction with the outY_freq_start and the
outY_freq_increment, determines the frequency sweep range
for the sweep operation.
This value, in conjunction with the
out_altvoltageY_frequency_start and the
out_altvoltageY_frequency_increment, determines the frequency
sweep range for the sweep operation.
What: /sys/bus/iio/devices/iio:deviceX/outY_settling_cycles
What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_settling_cycles
Date: March 2019
KernelVersion: 3.1.0
Contact: linux-iio@vger.kernel.org
Description:
......
What: /sys/bus/iio/devices/iio:deviceX/start_cleaning
Date: December 2018
KernelVersion: 4.22
KernelVersion: 5.0
Contact: linux-iio@vger.kernel.org
Description:
Writing 1 starts sensor self cleaning. Internal fan accelerates
......
What: /sys/bus/iio/devices/iio:deviceX/fault_oc
KernelVersion: 5.1
Contact: linux-iio@vger.kernel.org
Description:
Open-circuit fault. The detection of open-circuit faults,
such as those caused by broken thermocouple wires.
Reading returns either '1' or '0'.
'1' = An open circuit such as broken thermocouple wires
has been detected.
'0' = No open circuit or broken thermocouple wires are detected
What: /sys/bus/iio/devices/iio:deviceX/fault_ovuv
KernelVersion: 5.1
Contact: linux-iio@vger.kernel.org
Description:
Overvoltage or Undervoltage Input Fault. The internal circuitry
is protected from excessive voltages applied to the thermocouple
cables by integrated MOSFETs at the T+ and T- inputs, and the
BIAS output. These MOSFETs turn off when the input voltage is
negative or greater than VDD.
Reading returns either '1' or '0'.
'1' = The input voltage is negative or greater than VDD.
'0' = The input voltage is positive and less than VDD (normal
state).
Kionix KXCJK-1013 Accelerometer device tree bindings
Required properties:
- compatible: Must be one of:
"kionix,kxcjk1013"
"kionix,kxcj91008"
"kionix,kxtj21009"
"kionix,kxtf9"
- reg: i2c slave address
Example:
kxtf9@f {
compatible = "kionix,kxtf9";
reg = <0x0F>;
};
* Analog Devices AD7170/AD7171/AD7780/AD7781
Data sheets:
- AD7170:
* https://www.analog.com/media/en/technical-documentation/data-sheets/AD7170.pdf
- AD7171:
* https://www.analog.com/media/en/technical-documentation/data-sheets/AD7171.pdf
- AD7780:
* https://www.analog.com/media/en/technical-documentation/data-sheets/ad7780.pdf
- AD7781:
* https://www.analog.com/media/en/technical-documentation/data-sheets/AD7781.pdf
Required properties:
- compatible: should be one of
* "adi,ad7170"
* "adi,ad7171"
* "adi,ad7780"
* "adi,ad7781"
- reg: spi chip select number for the device
- vref-supply: the regulator supply for the ADC reference voltage
Optional properties:
- powerdown-gpios: must be the device tree identifier of the PDRST pin. If
specified, it will be asserted during driver probe. As the
line is active high, it should be marked GPIO_ACTIVE_HIGH.
- adi,gain-gpios: must be the device tree identifier of the GAIN pin. Only for
the ad778x chips. If specified, it will be asserted during
driver probe. As the line is active low, it should be marked
GPIO_ACTIVE_LOW.
- adi,filter-gpios: must be the device tree identifier of the FILTER pin. Only
for the ad778x chips. If specified, it will be asserted
during driver probe. As the line is active low, it should be
marked GPIO_ACTIVE_LOW.
Example:
adc@0 {
compatible = "adi,ad7780";
reg = <0>;
vref-supply = <&vdd_supply>
powerdown-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>;
adi,gain-gpios = <&gpio 5 GPIO_ACTIVE_LOW>;
adi,filter-gpios = <&gpio 15 GPIO_ACTIVE_LOW>;
};
......@@ -9,6 +9,7 @@ Required properties:
- "amlogic,meson-gxl-saradc" for GXL
- "amlogic,meson-gxm-saradc" for GXM
- "amlogic,meson-axg-saradc" for AXG
- "amlogic,meson-g12a-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
......
......@@ -6,6 +6,10 @@ Required properties:
region.
- interrupts: The ADC interrupt
Optional:
- vref-supply: The regulator supply ADC reference voltage, optional
for legacy reason, but highly encouraging to us in new device tree
Example:
adc@40048000 {
......@@ -13,4 +17,5 @@ Example:
reg = <0x40048000 0x1000>;
interrupt-parent = <&mic>;
interrupts = <39 0>;
vref-supply = <&vcc>;
};
* Plantower PMS7003 particulate matter sensor
Required properties:
- compatible: must be "plantower,pms7003"
- compatible: must one of:
"plantower,pms1003"
"plantower,pms3003"
"plantower,pms5003"
"plantower,pms6003"
"plantower,pms7003"
"plantower,pmsa003"
- vcc-supply: phandle to the regulator that provides power to the sensor
Optional properties:
......
......@@ -10,8 +10,9 @@ See ../mfd/stm32-lptimer.txt for details about the parent node.
Required properties:
- compatible: Must be "st,stm32-lptimer-counter".
- pinctrl-names: Set to "default".
- pinctrl-0: List of phandles pointing to pin configuration nodes,
- pinctrl-names: Set to "default". An additional "sleep" state can be
defined to set pins in sleep state.
- pinctrl-n: List of phandles pointing to pin configuration nodes,
to set IN1/IN2 pins in mode of operation for Low-Power
Timer input on external pin.
......@@ -21,7 +22,8 @@ Example:
...
counter {
compatible = "st,stm32-lptimer-counter";
pinctrl-names = "default";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&lptim1_in_pins>;
pinctrl-1 = <&lptim1_sleep_in_pins>;
};
};
* Bosch BMG160 triaxial rotation sensor (gyroscope)
Required properties:
- compatible : should be "bosch,bmg160" or "bosch,bmi055_gyro"
- reg : the I2C address of the sensor (0x69)
Optional properties:
- interrupts : interrupt mapping for GPIO IRQ, it should by configured with
flags IRQ_TYPE_EDGE_RISING
Example:
bmg160@69 {
compatible = "bosch,bmg160";
reg = <0x69>;
interrupt-parent = <&gpio6>;
interrupts = <18 (IRQ_TYPE_EDGE_RISING)>;
};
Analog Devices ADIS16480 and similar IMUs
Required properties for the ADIS16480:
- compatible: Must be one of
* "adi,adis16375"
* "adi,adis16480"
* "adi,adis16485"
* "adi,adis16488"
* "adi,adis16495-1"
* "adi,adis16495-2"
* "adi,adis16495-3"
* "adi,adis16497-1"
* "adi,adis16497-2"
* "adi,adis16497-3"
- reg: SPI chip select number for the device
- spi-max-frequency: Max SPI frequency to use
see: Documentation/devicetree/bindings/spi/spi-bus.txt
- spi-cpha: See Documentation/devicetree/bindings/spi/spi-bus.txt
- spi-cpol: See Documentation/devicetree/bindings/spi/spi-bus.txt
- interrupts: interrupt mapping for IRQ, accepted values are:
* IRQF_TRIGGER_RISING
* IRQF_TRIGGER_FALLING
Optional properties:
- interrupt-names: Data ready line selection. Valid values are:
* DIO1
* DIO2
* DIO3
* DIO4
If this field is left empty, DIO1 is assigned as default data ready
signal.
- reset-gpios: must be the device tree identifier of the RESET pin. As the line
is active low, it should be marked GPIO_ACTIVE_LOW.
- clocks: phandle to the external clock. Should be set according to
"clock-names".
If this field is left empty together with the "clock-names" field, then
the internal clock is used.
- clock-names: The name of the external clock to be used. Valid values are:
* sync: In sync mode, the internal clock is disabled and the frequency
of the external clock signal establishes therate of data
collection and processing. See Fig 14 and 15 in the datasheet.
The clock-frequency must be:
* 3000 to 4500 Hz for adis1649x devices.
* 700 to 2400 Hz for adis1648x devices.
* pps: In Pulse Per Second (PPS) Mode, the rate of data collection and
production is equal to the product of the external clock
frequency and the scale factor in the SYNC_SCALE register, see
Table 154 in the datasheet.
The clock-frequency must be:
* 1 to 128 Hz for adis1649x devices.
* This mode is not supported by adis1648x devices.
If this field is left empty together with the "clocks" field, then the
internal clock is used.
- adi,ext-clk-pin: The DIOx line to be used as an external clock input.
Valid values are:
* DIO1
* DIO2
* DIO3
* DIO4
Each DIOx pin supports only one function at a time (data ready line
selection or external clock input). When a single pin has two
two assignments, the enable bit for the lower priority function
automatically resets to zero (disabling the lower priority function).
Data ready has highest priority.
If this field is left empty, DIO2 is assigned as default external clock
input pin.
Example:
imu@0 {
compatible = "adi,adis16495-1";
reg = <0>;
spi-max-frequency = <3200000>;
spi-cpol;
spi-cpha;
interrupts = <25 IRQF_TRIGGER_FALLING>;
interrupt-parent = <&gpio>;
interrupt-names = "DIO2";
clocks = <&adis16495_sync>;
clock-names = "sync";
adi,ext-clk-pin = "DIO1";
};
......@@ -8,6 +8,8 @@ Required properties:
"st,lsm6dsm"
"st,ism330dlc"
"st,lsm6dso"
"st,asm330lhh"
"st,lsm6dsox"
- reg: i2c address of the sensor / spi cs line
Optional properties:
......
VISHAY VCNL4000 - Ambient Light and proximity sensor
This driver supports the VCNL4000/10/20/40 and VCNL4200 chips
Required properties:
-compatible: must be one of :
vishay,vcnl4000
vishay,vcnl4010
vishay,vcnl4020
vishay,vcnl4040
vishay,vcnl4200
-reg: I2C address of the sensor, should be one from below based on the model:
0x13
0x51
0x60
Example:
light-sensor@51 {
compatible = "vishay,vcnl4200";
reg = <0x51>;
};
* Devantech SRF04 ultrasonic range finder
Bit-banging driver using two GPIOs
Required properties:
- compatible: Should be "devantech,srf04"
- trig-gpios: Definition of the GPIO for the triggering (output)
This GPIO is set for about 10 us by the driver to tell the
device it should initiate the measurement cycle.
- echo-gpios: Definition of the GPIO for the echo (input)
This GPIO is set by the device as soon as an ultrasonic
burst is sent out and reset when the first echo is
received.
Thus this GPIO is set while the ultrasonic waves are doing
one round trip.
It needs to be an GPIO which is able to deliver an
interrupt because the time between two interrupts is
measured in the driver.
See Documentation/devicetree/bindings/gpio/gpio.txt for
information on how to specify a consumer gpio.
Example:
srf04@0 {
compatible = "devantech,srf04";
trig-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
echo-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
};
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/proximity/devantech-srf04.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Devantech SRF04 ultrasonic range finder
maintainers:
- Andreas Klinger <ak@it-klinger.de>
description: |
Bit-banging driver using two GPIOs:
- trigger-gpio is raised by the driver to start sending out an ultrasonic
burst
- echo-gpio is held high by the sensor after sending ultrasonic burst
until it is received once again
Specifications about the driver can be found at:
http://www.robot-electronics.co.uk/htm/srf04tech.htm
properties:
compatible:
items:
- const: devantech,srf04
trig-gpios:
description:
Definition of the GPIO for the triggering (output) This GPIO is set
for about 10 us by the driver to tell the device it should initiate
the measurement cycle.
maxItems: 1
echo-gpios:
description:
Definition of the GPIO for the echo (input)
This GPIO is set by the device as soon as an ultrasonic burst is sent
out and reset when the first echo is received.
Thus this GPIO is set while the ultrasonic waves are doing one round
trip.
It needs to be an GPIO which is able to deliver an interrupt because
the time between two interrupts is measured in the driver.
See Documentation/devicetree/bindings/gpio/gpio.txt for information
on how to specify a consumer gpio.
maxItems: 1
required:
- compatible
- trig-gpios
- echo-gpios
examples:
- |
#include <dt-bindings/gpio/gpio.h>
proximity {
compatible = "devantech,srf04";
trig-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
echo-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
};
* MaxBotix I2CXL-MaxSonar ultrasonic distance sensor of type mb1202,
mb1212, mb1222, mb1232, mb1242, mb7040 or mb7137 using the i2c interface
for ranging
Required properties:
- compatible: "maxbotix,mb1202",
"maxbotix,mb1212",
"maxbotix,mb1222",
"maxbotix,mb1232",
"maxbotix,mb1242",
"maxbotix,mb7040" or
"maxbotix,mb7137"
- reg: i2c address of the device, see also i2c/i2c.txt
Optional properties:
- interrupts: Interrupt used to announce the preceding reading
request has finished and that data is available.
If no interrupt is specified the device driver
falls back to wait a fixed amount of time until
data can be retrieved.
Example:
proximity@70 {
compatible = "maxbotix,mb1232";
reg = <0x70>;
interrupt-parent = <&gpio2>;
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
};
Maxim MAX31856 thermocouple support
https://datasheets.maximintegrated.com/en/ds/MAX31856.pdf
Optional property:
- thermocouple-type: Type of thermocouple (THERMOCOUPLE_TYPE_K if
omitted). Supported types are B, E, J, K, N, R, S, T.
Required properties:
- compatible: must be "maxim,max31856"
- reg: SPI chip select number for the device
- spi-max-frequency: As per datasheet max. supported freq is 5000000
- spi-cpha: must be defined for max31856 to enable SPI mode 1
Refer to spi/spi-bus.txt for generic SPI slave bindings.
Example:
temp-sensor@0 {
compatible = "maxim,max31856";
reg = <0>;
spi-max-frequency = <5000000>;
spi-cpha;
thermocouple-type = <THERMOCOUPLE_TYPE_K>;
};
If the temperature sensor device can be configured to use some specific
thermocouple type, you can use the defined types provided in the file
"include/dt-bindings/iio/temperature/thermocouple.h".
Property:
thermocouple-type: A single cell representing the type of the thermocouple
used by the device.
......@@ -210,6 +210,7 @@ kiebackpeter Kieback & Peter GmbH
kinetic Kinetic Technologies
kingdisplay King & Display Technology Co., Ltd.
kingnovel Kingnovel Technology Co., Ltd.
kionix Kionix, Inc.
koe Kaohsiung Opto-Electronics Inc.
kosagi Sutajio Ko-Usagi PTE Ltd.
kyo Kyocera Corporation
......@@ -233,6 +234,7 @@ lsi LSI Corp. (LSI Logic)
lwn Liebherr-Werk Nenzing GmbH
macnica Macnica Americas
marvell Marvell Technology Group Ltd.
maxbotix MaxBotix Inc.
maxim Maxim Integrated Products
mbvl Mobiveil Inc.
mcube mCube
......
......@@ -868,7 +868,7 @@ L: linux-iio@vger.kernel.org
W: http://ez.analog.com/community/linux-device-drivers
S: Supported
F: drivers/iio/adc/ad7606.c
F: Documentation/devicetree/bindings/iio/adc/ad7606.txt
F: Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt
ANALOG DEVICES INC AD7768-1 DRIVER
M: Stefan Popa <stefan.popa@analog.com>
......@@ -950,6 +950,7 @@ F: drivers/dma/dma-axi-dmac.c
ANALOG DEVICES INC IIO DRIVERS
M: Lars-Peter Clausen <lars@metafoo.de>
M: Michael Hennerich <Michael.Hennerich@analog.com>
M: Stefan Popa <stefan.popa@analog.com>
W: http://wiki.analog.com/
W: http://ez.analog.com/community/linux-device-drivers
S: Supported
......@@ -9406,6 +9407,13 @@ S: Maintained
F: Documentation/devicetree/bindings/sound/max9860.txt
F: sound/soc/codecs/max9860.*
MAXBOTIX ULTRASONIC RANGER IIO DRIVER
M: Andreas Klinger <ak@it-klinger.de>
L: linux-iio@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.txt
F: drivers/iio/proximity/mb1232.c
MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER
M: Javier Martinez Canillas <javier@dowhile0.org>
L: linux-kernel@vger.kernel.org
......
......@@ -39,28 +39,28 @@ config IIO_TRIGGER
data now' interrupt.
config IIO_CONSUMERS_PER_TRIGGER
int "Maximum number of consumers per trigger"
depends on IIO_TRIGGER
default "2"
help
This value controls the maximum number of consumers that a
given trigger may handle. Default is 2.
int "Maximum number of consumers per trigger"
depends on IIO_TRIGGER
default "2"
help
This value controls the maximum number of consumers that a
given trigger may handle. Default is 2.
config IIO_SW_DEVICE
tristate "Enable software IIO device support"
select IIO_CONFIGFS
help
Provides IIO core support for software devices. A software
device can be created via configfs or directly by a driver
using the API provided.
Provides IIO core support for software devices. A software
device can be created via configfs or directly by a driver
using the API provided.
config IIO_SW_TRIGGER
tristate "Enable software triggers support"
select IIO_CONFIGFS
help
Provides IIO core support for software triggers. A software
trigger can be created via configfs or directly by a driver
using the API provided.
Provides IIO core support for software triggers. A software
trigger can be created via configfs or directly by a driver
using the API provided.
config IIO_TRIGGERED_EVENT
tristate
......
......@@ -6,28 +6,28 @@
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.
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.
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.
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.
To compile this driver as a module, say M here: the module will be
called adis16209.
config ADXL345
tristate
......@@ -100,16 +100,16 @@ config BMA180
module will be called bma180.
config BMA220
tristate "Bosch BMA220 3-Axis Accelerometer Driver"
tristate "Bosch BMA220 3-Axis Accelerometer Driver"
depends on SPI
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to add support for the Bosch BMA220 triaxial
acceleration sensor.
help
Say yes here to add support for the Bosch BMA220 triaxial
acceleration sensor.
To compile this driver as a module, choose M here: the
module will be called bma220_spi.
To compile this driver as a module, choose M here: the
module will be called bma220_spi.
config BMC150_ACCEL
tristate "Bosch BMC150 Accelerometer Driver"
......
......@@ -116,6 +116,7 @@ struct bma180_data {
struct i2c_client *client;
struct iio_trigger *trig;
const struct bma180_part_info *part_info;
struct iio_mount_matrix orientation;
struct mutex mutex;
bool sleep_state;
int scale;
......@@ -561,6 +562,15 @@ static int bma180_set_power_mode(struct iio_dev *indio_dev,
return ret;
}
static const struct iio_mount_matrix *
bma180_accel_get_mount_matrix(const struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct bma180_data *data = iio_priv(indio_dev);
return &data->orientation;
}
static const struct iio_enum bma180_power_mode_enum = {
.items = bma180_power_modes,
.num_items = ARRAY_SIZE(bma180_power_modes),
......@@ -571,7 +581,8 @@ static const struct iio_enum bma180_power_mode_enum = {
static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
IIO_ENUM("power_mode", true, &bma180_power_mode_enum),
IIO_ENUM_AVAILABLE("power_mode", &bma180_power_mode_enum),
{ },
IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bma180_accel_get_mount_matrix),
{ }
};
#define BMA180_ACC_CHANNEL(_axis, _bits) { \
......@@ -722,6 +733,11 @@ static int bma180_probe(struct i2c_client *client,
chip = id->driver_data;
data->part_info = &bma180_part_info[chip];
ret = iio_read_mount_matrix(&client->dev, "mount-matrix",
&data->orientation);
if (ret)
return ret;
ret = data->part_info->chip_config(data);
if (ret < 0)
goto err_chip_disable;
......
......@@ -204,6 +204,7 @@ struct bmc150_accel_data {
int ev_enable_state;
int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */
const struct bmc150_accel_chip_info *chip_info;
struct iio_mount_matrix orientation;
};
static const struct {
......@@ -796,6 +797,20 @@ static ssize_t bmc150_accel_get_fifo_state(struct device *dev,
return sprintf(buf, "%d\n", state);
}
static const struct iio_mount_matrix *
bmc150_accel_get_mount_matrix(const struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct bmc150_accel_data *data = iio_priv(indio_dev);
return &data->orientation;
}
static const struct iio_chan_spec_ext_info bmc150_accel_ext_info[] = {
IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bmc150_accel_get_mount_matrix),
{ }
};
static IIO_CONST_ATTR(hwfifo_watermark_min, "1");
static IIO_CONST_ATTR(hwfifo_watermark_max,
__stringify(BMC150_ACCEL_FIFO_LENGTH));
......@@ -978,6 +993,7 @@ static const struct iio_event_spec bmc150_accel_event = {
.shift = 16 - (bits), \
.endianness = IIO_LE, \
}, \
.ext_info = bmc150_accel_ext_info, \
.event_spec = &bmc150_accel_event, \
.num_event_specs = 1 \
}
......@@ -1555,6 +1571,11 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
data->regmap = regmap;
ret = iio_read_mount_matrix(dev, "mount-matrix",
&data->orientation);
if (ret)
return ret;
ret = bmc150_accel_chip_init(data);
if (ret < 0)
return ret;
......
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for older Chrome OS EC accelerometer
*
* Copyright 2017 Google, Inc
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This driver uses the memory mapper cros-ec interface to communicate
* with the Chrome OS EC about accelerometer data.
* Accelerometer access is presented through iio sysfs.
......@@ -29,7 +21,6 @@
#include <linux/mfd/cros_ec_commands.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/platform_device.h>
#define DRV_NAME "cros-ec-accel-legacy"
......@@ -353,7 +344,7 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev)
struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
struct iio_dev *indio_dev;
struct cros_ec_accel_legacy_state *state;
int ret, i;
int ret;
if (!ec || !ec->ec_dev) {
dev_warn(&pdev->dev, "No EC device found.\n");
......@@ -381,20 +372,17 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev)
* Present the channel using HTML5 standard:
* need to invert X and Y and invert some lid axis.
*/
for (i = X ; i < MAX_AXIS; i++) {
switch (i) {
case X:
ec_accel_channels[X].scan_index = Y;
case Y:
ec_accel_channels[Y].scan_index = X;
case Z:
ec_accel_channels[Z].scan_index = Z;
}
if (state->sensor_num == MOTIONSENSE_LOC_LID && i != Y)
state->sign[i] = -1;
else
state->sign[i] = 1;
}
ec_accel_channels[X].scan_index = Y;
ec_accel_channels[Y].scan_index = X;
ec_accel_channels[Z].scan_index = Z;
state->sign[Y] = 1;
if (state->sensor_num == MOTIONSENSE_LOC_LID)
state->sign[X] = state->sign[Z] = -1;
else
state->sign[X] = state->sign[Z] = 1;
indio_dev->num_channels = ARRAY_SIZE(ec_accel_channels);
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &cros_ec_accel_legacy_info;
......@@ -419,5 +407,5 @@ module_platform_driver(cros_ec_accel_platform_driver);
MODULE_DESCRIPTION("ChromeOS EC legacy accelerometer driver");
MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
......@@ -1510,10 +1510,20 @@ static const struct i2c_device_id kxcjk1013_id[] = {
MODULE_DEVICE_TABLE(i2c, kxcjk1013_id);
static const struct of_device_id kxcjk1013_of_match[] = {
{ .compatible = "kionix,kxcjk1013", },
{ .compatible = "kionix,kxcj91008", },
{ .compatible = "kionix,kxtj21009", },
{ .compatible = "kionix,kxtf9", },
{ }
};
MODULE_DEVICE_TABLE(of, kxcjk1013_of_match);
static struct i2c_driver kxcjk1013_driver = {
.driver = {
.name = KXCJK1013_DRV_NAME,
.acpi_match_table = ACPI_PTR(kx_acpi_match),
.of_match_table = kxcjk1013_of_match,
.pm = &kxcjk1013_pm_ops,
},
.probe = kxcjk1013_probe,
......
......@@ -420,9 +420,7 @@ int kxsd9_common_probe(struct device *dev,
indio_dev->available_scan_masks = kxsd9_scan_masks;
/* Read the mounting matrix, if present */
ret = of_iio_read_mount_matrix(dev,
"mount-matrix",
&st->orientation);
ret = iio_read_mount_matrix(dev, "mount-matrix", &st->orientation);
if (ret)
return ret;
......
......@@ -1580,7 +1580,7 @@ static int mma8452_probe(struct i2c_client *client,
case FXLS8471_DEVICE_ID:
if (ret == data->chip_info->chip_id)
break;
/* else: fall through */
/* fall through */
default:
ret = -ENODEV;
goto disable_regulators;
......
......@@ -992,7 +992,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev,
goto out;
val = elements[i].integer.value;
if (val < 0 || val > 2)
if (val > 2)
goto out;
/* Avoiding full matrix multiplication, we simply reorder the
......
......@@ -124,6 +124,18 @@ config AD7768_1
To compile this driver as a module, choose M here: the module will be
called ad7768-1.
config AD7780
tristate "Analog Devices AD7780 and similar ADCs driver"
depends on SPI
depends on GPIOLIB || COMPILE_TEST
select AD_SIGMA_DELTA
help
Say yes here to build support for Analog Devices AD7170, AD7171,
AD7780 and AD7781 SPI analog to digital converters (ADC).
To compile this driver as a module, choose M here: the
module will be called ad7780.
config AD7791
tristate "Analog Devices AD7791 ADC driver"
depends on SPI
......@@ -390,7 +402,7 @@ config HX711
This driver uses two GPIOs, one acts as the clock and controls the
channel selection and gain, the other one is used for the measurement
data
data
Currently the raw value is read from the chip and delivered.
To get an actual weight one needs to subtract the
......@@ -585,17 +597,17 @@ config MCP3911
called mcp3911.
config MEDIATEK_MT6577_AUXADC
tristate "MediaTek AUXADC driver"
depends on ARCH_MEDIATEK || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to enable support for MediaTek mt65xx AUXADC.
tristate "MediaTek AUXADC driver"
depends on ARCH_MEDIATEK || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to enable support for MediaTek mt65xx AUXADC.
The driver supports immediate mode operation to read from one of sixteen
channels (external or internal).
The driver supports immediate mode operation to read from one of sixteen
channels (external or internal).
This driver can also be built as a module. If so, the module will be
called mt6577_auxadc.
This driver can also be built as a module. If so, the module will be
called mt6577_auxadc.
config MEN_Z188_ADC
tristate "MEN 16z188 ADC IP Core support"
......
......@@ -16,6 +16,7 @@ obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
obj-$(CONFIG_AD7606) += ad7606.o
obj-$(CONFIG_AD7766) += ad7766.o
obj-$(CONFIG_AD7768_1) += ad7768-1.o
obj-$(CONFIG_AD7780) += ad7780.o
obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AD7793) += ad7793.o
obj-$(CONFIG_AD7887) += ad7887.o
......
......@@ -411,7 +411,7 @@ static int ad7124_init_channel_vref(struct ad7124_state *st,
dev_err(&st->sd.spi->dev,
"Error, trying to use external voltage reference without a %s regulator.\n",
ad7124_ref_names[refsel]);
return PTR_ERR(st->vref[refsel]);
return PTR_ERR(st->vref[refsel]);
}
st->channel_config[channel_number].vref_mv =
regulator_get_voltage(st->vref[refsel]);
......
......@@ -3,6 +3,7 @@
* AD7170/AD7171 and AD7780/AD7781 SPI ADC driver
*
* Copyright 2011 Analog Devices Inc.
* Copyright 2019 Renato Lui Geh
*/
#include <linux/interrupt.h>
......@@ -16,6 +17,7 @@
#include <linux/sched.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/bits.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
......@@ -27,16 +29,25 @@
#define AD7780_ID1 BIT(4)
#define AD7780_ID0 BIT(3)
#define AD7780_GAIN BIT(2)
#define AD7780_PAT1 BIT(1)
#define AD7780_PAT0 BIT(0)
#define AD7780_PATTERN (AD7780_PAT0)
#define AD7780_PATTERN_MASK (AD7780_PAT0 | AD7780_PAT1)
#define AD7170_ID 0
#define AD7171_ID 1
#define AD7780_ID 1
#define AD7781_ID 0
#define AD7170_PAT2 BIT(2)
#define AD7780_ID_MASK (AD7780_ID0 | AD7780_ID1)
#define AD7170_PATTERN (AD7780_PAT0 | AD7170_PAT2)
#define AD7170_PATTERN_MASK (AD7780_PAT0 | AD7780_PAT1 | AD7170_PAT2)
#define AD7780_PATTERN_GOOD 1
#define AD7780_PATTERN_MASK GENMASK(1, 0)
#define AD7170_PATTERN_GOOD 5
#define AD7170_PATTERN_MASK GENMASK(2, 0)
#define AD7780_GAIN_MIDPOINT 64
#define AD7780_FILTER_MIDPOINT 13350
static const unsigned int ad778x_gain[2] = { 1, 128 };
static const unsigned int ad778x_odr_avail[2] = { 10000, 16700 };
struct ad7780_chip_info {
struct iio_chan_spec channel;
......@@ -49,7 +60,11 @@ struct ad7780_state {
const struct ad7780_chip_info *chip_info;
struct regulator *reg;
struct gpio_desc *powerdown_gpio;
unsigned int gain;
struct gpio_desc *gain_gpio;
struct gpio_desc *filter_gpio;
unsigned int gain;
unsigned int odr;
unsigned int int_vref_mv;
struct ad_sigma_delta sd;
};
......@@ -103,17 +118,69 @@ static int ad7780_read_raw(struct iio_dev *indio_dev,
voltage_uv = regulator_get_voltage(st->reg);
if (voltage_uv < 0)
return voltage_uv;
*val = (voltage_uv / 1000) * st->gain;
voltage_uv /= 1000;
*val = voltage_uv * st->gain;
*val2 = chan->scan_type.realbits - 1;
st->int_vref_mv = voltage_uv;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_OFFSET:
*val = -(1 << (chan->scan_type.realbits - 1));
return IIO_VAL_INT;
case IIO_CHAN_INFO_SAMP_FREQ:
*val = st->odr;
return IIO_VAL_INT;
default:
break;
}
return -EINVAL;
}
static int ad7780_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val,
int val2,
long m)
{
struct ad7780_state *st = iio_priv(indio_dev);
const struct ad7780_chip_info *chip_info = st->chip_info;
unsigned long long vref;
unsigned int full_scale, gain;
if (!chip_info->is_ad778x)
return -EINVAL;
switch (m) {
case IIO_CHAN_INFO_SCALE:
if (val != 0)
return -EINVAL;
vref = st->int_vref_mv * 1000000LL;
full_scale = 1 << (chip_info->channel.scan_type.realbits - 1);
gain = DIV_ROUND_CLOSEST_ULL(vref, full_scale);
gain = DIV_ROUND_CLOSEST(gain, val2);
st->gain = gain;
if (gain < AD7780_GAIN_MIDPOINT)
gain = 0;
else
gain = 1;
gpiod_set_value(st->gain_gpio, gain);
break;
case IIO_CHAN_INFO_SAMP_FREQ:
if (1000*val + val2/1000 < AD7780_FILTER_MIDPOINT)
val = 0;
else
val = 1;
st->odr = ad778x_odr_avail[val];
gpiod_set_value(st->filter_gpio, val);
break;
default:
break;
}
return 0;
}
static int ad7780_postprocess_sample(struct ad_sigma_delta *sigma_delta,
unsigned int raw_sample)
{
......@@ -125,10 +192,8 @@ static int ad7780_postprocess_sample(struct ad_sigma_delta *sigma_delta,
return -EIO;
if (chip_info->is_ad778x) {
if (raw_sample & AD7780_GAIN)
st->gain = 1;
else
st->gain = 128;
st->gain = ad778x_gain[raw_sample & AD7780_GAIN];
st->odr = ad778x_odr_avail[raw_sample & AD7780_FILTER];
}
return 0;
......@@ -141,30 +206,32 @@ static const struct ad_sigma_delta_info ad7780_sigma_delta_info = {
};
#define AD7780_CHANNEL(bits, wordsize) \
AD_SD_CHANNEL_NO_SAMP_FREQ(1, 0, 0, bits, 32, wordsize - bits)
AD_SD_CHANNEL(1, 0, 0, bits, 32, (wordsize) - (bits))
#define AD7170_CHANNEL(bits, wordsize) \
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] = {
.channel = AD7780_CHANNEL(12, 24),
.pattern = AD7170_PATTERN,
.channel = AD7170_CHANNEL(12, 24),
.pattern = AD7170_PATTERN_GOOD,
.pattern_mask = AD7170_PATTERN_MASK,
.is_ad778x = false,
},
[ID_AD7171] = {
.channel = AD7780_CHANNEL(16, 24),
.pattern = AD7170_PATTERN,
.channel = AD7170_CHANNEL(16, 24),
.pattern = AD7170_PATTERN_GOOD,
.pattern_mask = AD7170_PATTERN_MASK,
.is_ad778x = false,
},
[ID_AD7780] = {
.channel = AD7780_CHANNEL(24, 32),
.pattern = AD7780_PATTERN,
.pattern = AD7780_PATTERN_GOOD,
.pattern_mask = AD7780_PATTERN_MASK,
.is_ad778x = true,
},
[ID_AD7781] = {
.channel = AD7780_CHANNEL(20, 32),
.pattern = AD7780_PATTERN,
.pattern = AD7780_PATTERN_GOOD,
.pattern_mask = AD7780_PATTERN_MASK,
.is_ad778x = true,
},
......@@ -172,8 +239,47 @@ static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
static const struct iio_info ad7780_info = {
.read_raw = ad7780_read_raw,
.write_raw = ad7780_write_raw,
};
static int ad7780_init_gpios(struct device *dev, struct ad7780_state *st)
{
int ret;
st->powerdown_gpio = devm_gpiod_get_optional(dev,
"powerdown",
GPIOD_OUT_LOW);
if (IS_ERR(st->powerdown_gpio)) {
ret = PTR_ERR(st->powerdown_gpio);
dev_err(dev, "Failed to request powerdown GPIO: %d\n", ret);
return ret;
}
if (!st->chip_info->is_ad778x)
return 0;
st->gain_gpio = devm_gpiod_get_optional(dev,
"adi,gain",
GPIOD_OUT_HIGH);
if (IS_ERR(st->gain_gpio)) {
ret = PTR_ERR(st->gain_gpio);
dev_err(dev, "Failed to request gain GPIO: %d\n", ret);
return ret;
}
st->filter_gpio = devm_gpiod_get_optional(dev,
"adi,filter",
GPIOD_OUT_HIGH);
if (IS_ERR(st->filter_gpio)) {
ret = PTR_ERR(st->filter_gpio);
dev_err(dev, "Failed to request filter GPIO: %d\n", ret);
return ret;
}
return 0;
}
static int ad7780_probe(struct spi_device *spi)
{
struct ad7780_state *st;
......@@ -189,16 +295,6 @@ static int ad7780_probe(struct spi_device *spi)
ad_sd_init(&st->sd, indio_dev, spi, &ad7780_sigma_delta_info);
st->reg = devm_regulator_get(&spi->dev, "avdd");
if (IS_ERR(st->reg))
return PTR_ERR(st->reg);
ret = regulator_enable(st->reg);
if (ret) {
dev_err(&spi->dev, "Failed to enable specified AVdd supply\n");
return ret;
}
st->chip_info =
&ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data];
......@@ -211,14 +307,18 @@ static int ad7780_probe(struct spi_device *spi)
indio_dev->num_channels = 1;
indio_dev->info = &ad7780_info;
st->powerdown_gpio = devm_gpiod_get_optional(&spi->dev,
"powerdown",
GPIOD_OUT_LOW);
if (IS_ERR(st->powerdown_gpio)) {
ret = PTR_ERR(st->powerdown_gpio);
dev_err(&spi->dev, "Failed to request powerdown GPIO: %d\n",
ret);
goto error_disable_reg;
ret = ad7780_init_gpios(&spi->dev, st);
if (ret)
goto error_cleanup_buffer_and_trigger;
st->reg = devm_regulator_get(&spi->dev, "avdd");
if (IS_ERR(st->reg))
return PTR_ERR(st->reg);
ret = regulator_enable(st->reg);
if (ret) {
dev_err(&spi->dev, "Failed to enable specified AVdd supply\n");
return ret;
}
ret = ad_sd_setup_buffer_and_trigger(indio_dev);
......
......@@ -24,9 +24,9 @@
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#define AD7923_WRITE_CR (1 << 11) /* write control register */
#define AD7923_RANGE (1 << 1) /* range to REFin */
#define AD7923_CODING (1 << 0) /* coding is straight binary */
#define AD7923_WRITE_CR BIT(11) /* write control register */
#define AD7923_RANGE BIT(1) /* range to REFin */
#define AD7923_CODING BIT(0) /* coding is straight binary */
#define AD7923_PM_MODE_AS (1) /* auto shutdown */
#define AD7923_PM_MODE_FS (2) /* full shutdown */
#define AD7923_PM_MODE_OPS (3) /* normal operation */
......@@ -40,16 +40,16 @@
#define AD7923_MAX_CHAN 4
#define AD7923_PM_MODE_WRITE(mode) (mode << 4) /* write mode */
#define AD7923_CHANNEL_WRITE(channel) (channel << 6) /* write channel */
#define AD7923_SEQUENCE_WRITE(sequence) (((sequence & 1) << 3) \
+ ((sequence & 2) << 9))
#define AD7923_PM_MODE_WRITE(mode) ((mode) << 4) /* write mode */
#define AD7923_CHANNEL_WRITE(channel) ((channel) << 6) /* write channel */
#define AD7923_SEQUENCE_WRITE(sequence) ((((sequence) & 1) << 3) \
+ (((sequence) & 2) << 9))
/* write sequence fonction */
/* left shift for CR : bit 11 transmit in first */
#define AD7923_SHIFT_REGISTER 4
/* val = value, dec = left shift, bits = number of bits of the mask */
#define EXTRACT(val, dec, bits) ((val >> dec) & ((1 << bits) - 1))
#define EXTRACT(val, dec, bits) (((val) >> (dec)) & ((1 << (bits)) - 1))
struct ad7923_state {
struct spi_device *spi;
......@@ -130,7 +130,7 @@ static const struct ad7923_chip_info ad7923_chip_info[] = {
* ad7923_update_scan_mode() setup the spi transfer buffer for the new scan mask
**/
static int ad7923_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *active_scan_mask)
const unsigned long *active_scan_mask)
{
struct ad7923_state *st = iio_priv(indio_dev);
int i, cmd, len;
......@@ -181,7 +181,7 @@ static irqreturn_t ad7923_trigger_handler(int irq, void *p)
goto done;
iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
iio_get_time_ns(indio_dev));
iio_get_time_ns(indio_dev));
done:
iio_trigger_notify_done(indio_dev->trig);
......@@ -272,7 +272,7 @@ static int ad7923_probe(struct spi_device *spi)
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (indio_dev == NULL)
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
......@@ -314,7 +314,7 @@ static int ad7923_probe(struct spi_device *spi)
return ret;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
&ad7923_trigger_handler, NULL);
&ad7923_trigger_handler, NULL);
if (ret)
goto error_disable_reg;
......
......@@ -62,7 +62,7 @@ int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
struct spi_transfer t = {
.tx_buf = data,
.len = size + 1,
.cs_change = sigma_delta->bus_locked,
.cs_change = sigma_delta->keep_cs_asserted,
};
struct spi_message m;
int ret;
......@@ -217,6 +217,7 @@ static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
spi_bus_lock(sigma_delta->spi->master);
sigma_delta->bus_locked = true;
sigma_delta->keep_cs_asserted = true;
reinit_completion(&sigma_delta->completion);
ret = ad_sigma_delta_set_mode(sigma_delta, mode);
......@@ -234,9 +235,10 @@ static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
ret = 0;
}
out:
sigma_delta->keep_cs_asserted = false;
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
sigma_delta->bus_locked = false;
spi_bus_unlock(sigma_delta->spi->master);
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
return ret;
}
......@@ -289,6 +291,7 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
spi_bus_lock(sigma_delta->spi->master);
sigma_delta->bus_locked = true;
sigma_delta->keep_cs_asserted = true;
reinit_completion(&sigma_delta->completion);
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE);
......@@ -298,9 +301,6 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
ret = wait_for_completion_interruptible_timeout(
&sigma_delta->completion, HZ);
sigma_delta->bus_locked = false;
spi_bus_unlock(sigma_delta->spi->master);
if (ret == 0)
ret = -EIO;
if (ret < 0)
......@@ -321,7 +321,10 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
sigma_delta->irq_dis = true;
}
sigma_delta->keep_cs_asserted = false;
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
sigma_delta->bus_locked = false;
spi_bus_unlock(sigma_delta->spi->master);
mutex_unlock(&indio_dev->mlock);
if (ret)
......@@ -358,6 +361,8 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)
spi_bus_lock(sigma_delta->spi->master);
sigma_delta->bus_locked = true;
sigma_delta->keep_cs_asserted = true;
ret = ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_CONTINUOUS);
if (ret)
goto err_unlock;
......@@ -386,6 +391,7 @@ static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev)
sigma_delta->irq_dis = true;
}
sigma_delta->keep_cs_asserted = false;
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
sigma_delta->bus_locked = false;
......
......@@ -302,10 +302,8 @@ static int ingenic_adc_probe(struct platform_device *pdev)
mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
adc->base = devm_ioremap_resource(dev, mem_base);
if (IS_ERR(adc->base)) {
dev_err(dev, "Unable to ioremap mmio resource\n");
if (IS_ERR(adc->base))
return PTR_ERR(adc->base);
}
adc->clk = devm_clk_get(dev, "adc");
if (IS_ERR(adc->clk)) {
......
......@@ -7,20 +7,15 @@
* Copyright (C) 2011, 2012 Roland Stigge <stigge@antcom.de>
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/completion.h>
#include <linux/of.h>
#include <linux/err.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
/*
* LPC32XX registers definitions
......@@ -52,6 +47,7 @@ struct lpc32xx_adc_state {
void __iomem *adc_base;
struct clk *clk;
struct completion completion;
struct regulator *vref;
u32 value;
};
......@@ -64,7 +60,9 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
{
struct lpc32xx_adc_state *st = iio_priv(indio_dev);
int ret;
if (mask == IIO_CHAN_INFO_RAW) {
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
ret = clk_prepare_enable(st->clk);
if (ret) {
......@@ -84,22 +82,36 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
}
return -EINVAL;
case IIO_CHAN_INFO_SCALE:
*val = regulator_get_voltage(st->vref) / 1000;
*val2 = 10;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
}
static const struct iio_info lpc32xx_adc_iio_info = {
.read_raw = &lpc32xx_read_raw,
};
#define LPC32XX_ADC_CHANNEL(_index) { \
#define LPC32XX_ADC_CHANNEL_BASE(_index) \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = _index, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.address = LPC32XXAD_IN * _index, \
.scan_index = _index, \
.scan_index = _index,
#define LPC32XX_ADC_CHANNEL(_index) { \
LPC32XX_ADC_CHANNEL_BASE(_index) \
}
#define LPC32XX_ADC_SCALE_CHANNEL(_index) { \
LPC32XX_ADC_CHANNEL_BASE(_index) \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
}
static const struct iio_chan_spec lpc32xx_adc_iio_channels[] = {
......@@ -108,6 +120,12 @@ static const struct iio_chan_spec lpc32xx_adc_iio_channels[] = {
LPC32XX_ADC_CHANNEL(2),
};
static const struct iio_chan_spec lpc32xx_adc_iio_scale_channels[] = {
LPC32XX_ADC_SCALE_CHANNEL(0),
LPC32XX_ADC_SCALE_CHANNEL(1),
LPC32XX_ADC_SCALE_CHANNEL(2),
};
static irqreturn_t lpc32xx_adc_isr(int irq, void *dev_id)
{
struct lpc32xx_adc_state *st = dev_id;
......@@ -166,6 +184,15 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
return retval;
}
st->vref = devm_regulator_get(&pdev->dev, "vref");
if (IS_ERR(st->vref)) {
iodev->channels = lpc32xx_adc_iio_channels;
dev_info(&pdev->dev,
"Missing vref regulator: No scaling available\n");
} else {
iodev->channels = lpc32xx_adc_iio_scale_channels;
}
platform_set_drvdata(pdev, iodev);
init_completion(&st->completion);
......@@ -174,7 +201,6 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
iodev->dev.parent = &pdev->dev;
iodev->info = &lpc32xx_adc_iio_info;
iodev->modes = INDIO_DIRECT_MODE;
iodev->channels = lpc32xx_adc_iio_channels;
iodev->num_channels = ARRAY_SIZE(lpc32xx_adc_iio_channels);
retval = devm_iio_device_register(&pdev->dev, iodev);
......
......@@ -1150,6 +1150,11 @@ static const struct meson_sar_adc_data meson_sar_adc_axg_data = {
.name = "meson-axg-saradc",
};
static const struct meson_sar_adc_data meson_sar_adc_g12a_data = {
.param = &meson_sar_adc_gxl_param,
.name = "meson-g12a-saradc",
};
static const struct of_device_id meson_sar_adc_of_match[] = {
{
.compatible = "amlogic,meson8-saradc",
......@@ -1175,6 +1180,9 @@ static const struct of_device_id meson_sar_adc_of_match[] = {
}, {
.compatible = "amlogic,meson-axg-saradc",
.data = &meson_sar_adc_axg_data,
}, {
.compatible = "amlogic,meson-g12a-saradc",
.data = &meson_sar_adc_g12a_data,
},
{},
};
......
......@@ -465,6 +465,8 @@ static int mxs_lradc_adc_trigger_init(struct iio_dev *iio)
trig = devm_iio_trigger_alloc(&iio->dev, "%s-dev%i", iio->name,
iio->id);
if (!trig)
return -ENOMEM;
trig->dev.parent = adc->dev;
iio_trigger_set_drvdata(trig, iio);
......
This diff is collapsed.
......@@ -12,6 +12,8 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/slab.h>
......@@ -90,6 +92,36 @@ struct dfsdm_priv {
struct clk *aclk; /* audio clock */
};
static inline struct dfsdm_priv *to_stm32_dfsdm_priv(struct stm32_dfsdm *dfsdm)
{
return container_of(dfsdm, struct dfsdm_priv, dfsdm);
}
static int stm32_dfsdm_clk_prepare_enable(struct stm32_dfsdm *dfsdm)
{
struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm);
int ret;
ret = clk_prepare_enable(priv->clk);
if (ret || !priv->aclk)
return ret;
ret = clk_prepare_enable(priv->aclk);
if (ret)
clk_disable_unprepare(priv->clk);
return ret;
}
static void stm32_dfsdm_clk_disable_unprepare(struct stm32_dfsdm *dfsdm)
{
struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm);
if (priv->aclk)
clk_disable_unprepare(priv->aclk);
clk_disable_unprepare(priv->clk);
}
/**
* stm32_dfsdm_start_dfsdm - start global dfsdm interface.
*
......@@ -98,24 +130,17 @@ struct dfsdm_priv {
*/
int stm32_dfsdm_start_dfsdm(struct stm32_dfsdm *dfsdm)
{
struct dfsdm_priv *priv = container_of(dfsdm, struct dfsdm_priv, dfsdm);
struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm);
struct device *dev = &priv->pdev->dev;
unsigned int clk_div = priv->spi_clk_out_div, clk_src;
int ret;
if (atomic_inc_return(&priv->n_active_ch) == 1) {
ret = clk_prepare_enable(priv->clk);
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
dev_err(dev, "Failed to start clock\n");
pm_runtime_put_noidle(dev);
goto error_ret;
}
if (priv->aclk) {
ret = clk_prepare_enable(priv->aclk);
if (ret < 0) {
dev_err(dev, "Failed to start audio clock\n");
goto disable_clk;
}
}
/* select clock source, e.g. 0 for "dfsdm" or 1 for "audio" */
clk_src = priv->aclk ? 1 : 0;
......@@ -123,21 +148,21 @@ int stm32_dfsdm_start_dfsdm(struct stm32_dfsdm *dfsdm)
DFSDM_CHCFGR1_CKOUTSRC_MASK,
DFSDM_CHCFGR1_CKOUTSRC(clk_src));
if (ret < 0)
goto disable_aclk;
goto pm_put;
/* Output the SPI CLKOUT (if clk_div == 0 clock if OFF) */
ret = regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(0),
DFSDM_CHCFGR1_CKOUTDIV_MASK,
DFSDM_CHCFGR1_CKOUTDIV(clk_div));
if (ret < 0)
goto disable_aclk;
goto pm_put;
/* Global enable of DFSDM interface */
ret = regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(0),
DFSDM_CHCFGR1_DFSDMEN_MASK,
DFSDM_CHCFGR1_DFSDMEN(1));
if (ret < 0)
goto disable_aclk;
goto pm_put;
}
dev_dbg(dev, "%s: n_active_ch %d\n", __func__,
......@@ -145,11 +170,8 @@ int stm32_dfsdm_start_dfsdm(struct stm32_dfsdm *dfsdm)
return 0;
disable_aclk:
clk_disable_unprepare(priv->aclk);
disable_clk:
clk_disable_unprepare(priv->clk);
pm_put:
pm_runtime_put_sync(dev);
error_ret:
atomic_dec(&priv->n_active_ch);
......@@ -165,7 +187,7 @@ EXPORT_SYMBOL_GPL(stm32_dfsdm_start_dfsdm);
*/
int stm32_dfsdm_stop_dfsdm(struct stm32_dfsdm *dfsdm)
{
struct dfsdm_priv *priv = container_of(dfsdm, struct dfsdm_priv, dfsdm);
struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm);
int ret;
if (atomic_dec_and_test(&priv->n_active_ch)) {
......@@ -183,9 +205,7 @@ int stm32_dfsdm_stop_dfsdm(struct stm32_dfsdm *dfsdm)
if (ret < 0)
return ret;
clk_disable_unprepare(priv->clk);
if (priv->aclk)
clk_disable_unprepare(priv->aclk);
pm_runtime_put_sync(&priv->pdev->dev);
}
dev_dbg(&priv->pdev->dev, "%s: n_active_ch %d\n", __func__,
atomic_read(&priv->n_active_ch));
......@@ -199,7 +219,7 @@ static int stm32_dfsdm_parse_of(struct platform_device *pdev,
{
struct device_node *node = pdev->dev.of_node;
struct resource *res;
unsigned long clk_freq;
unsigned long clk_freq, divider;
unsigned int spi_freq, rem;
int ret;
......@@ -243,13 +263,20 @@ static int stm32_dfsdm_parse_of(struct platform_device *pdev,
return 0;
}
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 */
divider = div_u64_rem(clk_freq, spi_freq, &rem);
/* Round up divider when ckout isn't precise, not to exceed spi_freq */
if (rem)
divider++;
/* programmable divider is in range of [2:256] */
if (divider < 2 || divider > 256) {
dev_err(&pdev->dev, "spi-max-frequency not achievable\n");
return -EINVAL;
}
priv->dfsdm.spi_master_freq = spi_freq;
/* SPI clock output divider is: divider = CKOUTDIV + 1 */
priv->spi_clk_out_div = divider - 1;
priv->dfsdm.spi_master_freq = clk_freq / (priv->spi_clk_out_div + 1);
if (rem) {
dev_warn(&pdev->dev, "SPI clock not accurate\n");
......@@ -318,14 +345,111 @@ static int stm32_dfsdm_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dfsdm);
return devm_of_platform_populate(&pdev->dev);
ret = stm32_dfsdm_clk_prepare_enable(dfsdm);
if (ret) {
dev_err(&pdev->dev, "Failed to start clock\n");
return ret;
}
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
if (ret)
goto pm_put;
pm_runtime_put(&pdev->dev);
return 0;
pm_put:
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
stm32_dfsdm_clk_disable_unprepare(dfsdm);
return ret;
}
static int stm32_dfsdm_core_remove(struct platform_device *pdev)
{
struct stm32_dfsdm *dfsdm = platform_get_drvdata(pdev);
pm_runtime_get_sync(&pdev->dev);
of_platform_depopulate(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
stm32_dfsdm_clk_disable_unprepare(dfsdm);
return 0;
}
static int __maybe_unused stm32_dfsdm_core_suspend(struct device *dev)
{
struct stm32_dfsdm *dfsdm = dev_get_drvdata(dev);
struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm);
int ret;
ret = pm_runtime_force_suspend(dev);
if (ret)
return ret;
/* Balance devm_regmap_init_mmio_clk() clk_prepare() */
clk_unprepare(priv->clk);
return pinctrl_pm_select_sleep_state(dev);
}
static int __maybe_unused stm32_dfsdm_core_resume(struct device *dev)
{
struct stm32_dfsdm *dfsdm = dev_get_drvdata(dev);
struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm);
int ret;
ret = pinctrl_pm_select_default_state(dev);
if (ret)
return ret;
ret = clk_prepare(priv->clk);
if (ret)
return ret;
return pm_runtime_force_resume(dev);
}
static int __maybe_unused stm32_dfsdm_core_runtime_suspend(struct device *dev)
{
struct stm32_dfsdm *dfsdm = dev_get_drvdata(dev);
stm32_dfsdm_clk_disable_unprepare(dfsdm);
return 0;
}
static int __maybe_unused stm32_dfsdm_core_runtime_resume(struct device *dev)
{
struct stm32_dfsdm *dfsdm = dev_get_drvdata(dev);
return stm32_dfsdm_clk_prepare_enable(dfsdm);
}
static const struct dev_pm_ops stm32_dfsdm_core_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(stm32_dfsdm_core_suspend,
stm32_dfsdm_core_resume)
SET_RUNTIME_PM_OPS(stm32_dfsdm_core_runtime_suspend,
stm32_dfsdm_core_runtime_resume,
NULL)
};
static struct platform_driver stm32_dfsdm_driver = {
.probe = stm32_dfsdm_probe,
.remove = stm32_dfsdm_core_remove,
.driver = {
.name = "stm32-dfsdm",
.of_match_table = stm32_dfsdm_of_match,
.pm = &stm32_dfsdm_core_pm_ops,
},
};
......
......@@ -184,9 +184,6 @@ static irqreturn_t stmpe_adc_isr(int irq, void *dev_id)
struct stmpe_adc *info = (struct stmpe_adc *)dev_id;
u16 data;
if (info->channel > STMPE_TEMP_CHANNEL)
return IRQ_NONE;
if (info->channel <= STMPE_ADC_LAST_NR) {
int int_sta;
......@@ -205,6 +202,8 @@ static irqreturn_t stmpe_adc_isr(int irq, void *dev_id)
/* Read value */
stmpe_block_read(info->stmpe, STMPE_REG_TEMP_DATA, 2,
(u8 *) &data);
} else {
return IRQ_NONE;
}
info->value = (u32) be16_to_cpu(data);
......
......@@ -17,6 +17,7 @@
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
......@@ -36,12 +37,15 @@
*/
#define TI_ADS7950_VA_MV_ACPI_DEFAULT 5000
#define TI_ADS7950_CR_GPIO BIT(14)
#define TI_ADS7950_CR_MANUAL BIT(12)
#define TI_ADS7950_CR_WRITE BIT(11)
#define TI_ADS7950_CR_CHAN(ch) ((ch) << 7)
#define TI_ADS7950_CR_RANGE_5V BIT(6)
#define TI_ADS7950_CR_GPIO_DATA BIT(4)
#define TI_ADS7950_MAX_CHAN 16
#define TI_ADS7950_NUM_GPIOS 4
#define TI_ADS7950_TIMESTAMP_SIZE (sizeof(int64_t) / sizeof(__be16))
......@@ -49,6 +53,16 @@
#define TI_ADS7950_EXTRACT(val, dec, bits) \
(((val) >> (dec)) & ((1 << (bits)) - 1))
#define TI_ADS7950_MAN_CMD(cmd) (TI_ADS7950_CR_MANUAL | (cmd))
#define TI_ADS7950_GPIO_CMD(cmd) (TI_ADS7950_CR_GPIO | (cmd))
/* Manual mode configuration */
#define TI_ADS7950_MAN_CMD_SETTINGS(st) \
(TI_ADS7950_MAN_CMD(TI_ADS7950_CR_WRITE | st->cmd_settings_bitmask))
/* GPIO mode configuration */
#define TI_ADS7950_GPIO_CMD_SETTINGS(st) \
(TI_ADS7950_GPIO_CMD(st->gpio_cmd_settings_bitmask))
struct ti_ads7950_state {
struct spi_device *spi;
struct spi_transfer ring_xfer;
......@@ -56,10 +70,36 @@ struct ti_ads7950_state {
struct spi_message ring_msg;
struct spi_message scan_single_msg;
/* Lock to protect the spi xfer buffers */
struct mutex slock;
struct gpio_chip chip;
struct regulator *reg;
unsigned int vref_mv;
unsigned int settings;
/*
* Bitmask of lower 7 bits used for configuration
* These bits only can be written when TI_ADS7950_CR_WRITE
* is set, otherwise it retains its original state.
* [0-3] GPIO signal
* [4] Set following frame to return GPIO signal values
* [5] Powers down device
* [6] Sets Vref range1(2.5v) or range2(5v)
*
* Bits present on Manual/Auto1/Auto2 commands
*/
unsigned int cmd_settings_bitmask;
/*
* Bitmask of GPIO command
* [0-3] GPIO direction
* [4-6] Different GPIO alarm mode configurations
* [7] GPIO 2 as device range input
* [8] GPIO 3 as device power down input
* [9] Reset all registers
* [10-11] N/A
*/
unsigned int gpio_cmd_settings_bitmask;
/*
* DMA (thus cache coherency maintenance) requires the
......@@ -248,7 +288,7 @@ static int ti_ads7950_update_scan_mode(struct iio_dev *indio_dev,
len = 0;
for_each_set_bit(i, active_scan_mask, indio_dev->num_channels) {
cmd = TI_ADS7950_CR_WRITE | TI_ADS7950_CR_CHAN(i) | st->settings;
cmd = TI_ADS7950_MAN_CMD(TI_ADS7950_CR_CHAN(i));
st->tx_buf[len++] = cmd;
}
......@@ -268,6 +308,7 @@ static irqreturn_t ti_ads7950_trigger_handler(int irq, void *p)
struct ti_ads7950_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&st->slock);
ret = spi_sync(st->spi, &st->ring_msg);
if (ret < 0)
goto out;
......@@ -276,6 +317,7 @@ static irqreturn_t ti_ads7950_trigger_handler(int irq, void *p)
iio_get_time_ns(indio_dev));
out:
mutex_unlock(&st->slock);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
......@@ -286,9 +328,8 @@ static int ti_ads7950_scan_direct(struct iio_dev *indio_dev, unsigned int ch)
struct ti_ads7950_state *st = iio_priv(indio_dev);
int ret, cmd;
mutex_lock(&indio_dev->mlock);
cmd = TI_ADS7950_CR_WRITE | TI_ADS7950_CR_CHAN(ch) | st->settings;
mutex_lock(&st->slock);
cmd = TI_ADS7950_MAN_CMD(TI_ADS7950_CR_CHAN(ch));
st->single_tx = cmd;
ret = spi_sync(st->spi, &st->scan_single_msg);
......@@ -298,7 +339,7 @@ static int ti_ads7950_scan_direct(struct iio_dev *indio_dev, unsigned int ch)
ret = st->single_rx;
out:
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->slock);
return ret;
}
......@@ -317,7 +358,7 @@ static int ti_ads7950_get_range(struct ti_ads7950_state *st)
vref /= 1000;
}
if (st->settings & TI_ADS7950_CR_RANGE_5V)
if (st->cmd_settings_bitmask & TI_ADS7950_CR_RANGE_5V)
vref *= 2;
return vref;
......@@ -362,6 +403,132 @@ static const struct iio_info ti_ads7950_info = {
.update_scan_mode = ti_ads7950_update_scan_mode,
};
static void ti_ads7950_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct ti_ads7950_state *st = gpiochip_get_data(chip);
mutex_lock(&st->slock);
if (value)
st->cmd_settings_bitmask |= BIT(offset);
else
st->cmd_settings_bitmask &= ~BIT(offset);
st->single_tx = TI_ADS7950_MAN_CMD_SETTINGS(st);
spi_sync(st->spi, &st->scan_single_msg);
mutex_unlock(&st->slock);
}
static int ti_ads7950_get(struct gpio_chip *chip, unsigned int offset)
{
struct ti_ads7950_state *st = gpiochip_get_data(chip);
int ret;
mutex_lock(&st->slock);
/* If set as output, return the output */
if (st->gpio_cmd_settings_bitmask & BIT(offset)) {
ret = st->cmd_settings_bitmask & BIT(offset);
goto out;
}
/* GPIO data bit sets SDO bits 12-15 to GPIO input */
st->cmd_settings_bitmask |= TI_ADS7950_CR_GPIO_DATA;
st->single_tx = TI_ADS7950_MAN_CMD_SETTINGS(st);
ret = spi_sync(st->spi, &st->scan_single_msg);
if (ret)
goto out;
ret = ((st->single_rx >> 12) & BIT(offset)) ? 1 : 0;
/* Revert back to original settings */
st->cmd_settings_bitmask &= ~TI_ADS7950_CR_GPIO_DATA;
st->single_tx = TI_ADS7950_MAN_CMD_SETTINGS(st);
ret = spi_sync(st->spi, &st->scan_single_msg);
if (ret)
goto out;
out:
mutex_unlock(&st->slock);
return ret;
}
static int ti_ads7950_get_direction(struct gpio_chip *chip,
unsigned int offset)
{
struct ti_ads7950_state *st = gpiochip_get_data(chip);
/* Bitmask is inverted from GPIO framework 0=input/1=output */
return !(st->gpio_cmd_settings_bitmask & BIT(offset));
}
static int _ti_ads7950_set_direction(struct gpio_chip *chip, int offset,
int input)
{
struct ti_ads7950_state *st = gpiochip_get_data(chip);
int ret = 0;
mutex_lock(&st->slock);
/* Only change direction if needed */
if (input && (st->gpio_cmd_settings_bitmask & BIT(offset)))
st->gpio_cmd_settings_bitmask &= ~BIT(offset);
else if (!input && !(st->gpio_cmd_settings_bitmask & BIT(offset)))
st->gpio_cmd_settings_bitmask |= BIT(offset);
else
goto out;
st->single_tx = TI_ADS7950_GPIO_CMD_SETTINGS(st);
ret = spi_sync(st->spi, &st->scan_single_msg);
out:
mutex_unlock(&st->slock);
return ret;
}
static int ti_ads7950_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
return _ti_ads7950_set_direction(chip, offset, 1);
}
static int ti_ads7950_direction_output(struct gpio_chip *chip,
unsigned int offset, int value)
{
ti_ads7950_set(chip, offset, value);
return _ti_ads7950_set_direction(chip, offset, 0);
}
static int ti_ads7950_init_hw(struct ti_ads7950_state *st)
{
int ret = 0;
mutex_lock(&st->slock);
/* Settings for Manual/Auto1/Auto2 commands */
/* Default to 5v ref */
st->cmd_settings_bitmask = TI_ADS7950_CR_RANGE_5V;
st->single_tx = TI_ADS7950_MAN_CMD_SETTINGS(st);
ret = spi_sync(st->spi, &st->scan_single_msg);
if (ret)
goto out;
/* Settings for GPIO command */
st->gpio_cmd_settings_bitmask = 0x0;
st->single_tx = TI_ADS7950_GPIO_CMD_SETTINGS(st);
ret = spi_sync(st->spi, &st->scan_single_msg);
out:
mutex_unlock(&st->slock);
return ret;
}
static int ti_ads7950_probe(struct spi_device *spi)
{
struct ti_ads7950_state *st;
......@@ -386,7 +553,6 @@ static int ti_ads7950_probe(struct spi_device *spi)
spi_set_drvdata(spi, indio_dev);
st->spi = spi;
st->settings = TI_ADS7950_CR_MANUAL | TI_ADS7950_CR_RANGE_5V;
info = &ti_ads7950_chip_info[spi_get_device_id(spi)->driver_data];
......@@ -432,16 +598,19 @@ static int ti_ads7950_probe(struct spi_device *spi)
if (ACPI_COMPANION(&spi->dev))
st->vref_mv = TI_ADS7950_VA_MV_ACPI_DEFAULT;
mutex_init(&st->slock);
st->reg = devm_regulator_get(&spi->dev, "vref");
if (IS_ERR(st->reg)) {
dev_err(&spi->dev, "Failed get get regulator \"vref\"\n");
return PTR_ERR(st->reg);
ret = PTR_ERR(st->reg);
goto error_destroy_mutex;
}
ret = regulator_enable(st->reg);
if (ret) {
dev_err(&spi->dev, "Failed to enable regulator \"vref\"\n");
return ret;
goto error_destroy_mutex;
}
ret = iio_triggered_buffer_setup(indio_dev, NULL,
......@@ -451,18 +620,46 @@ static int ti_ads7950_probe(struct spi_device *spi)
goto error_disable_reg;
}
ret = ti_ads7950_init_hw(st);
if (ret) {
dev_err(&spi->dev, "Failed to init adc chip\n");
goto error_cleanup_ring;
}
ret = iio_device_register(indio_dev);
if (ret) {
dev_err(&spi->dev, "Failed to register iio device\n");
goto error_cleanup_ring;
}
/* Add GPIO chip */
st->chip.label = dev_name(&st->spi->dev);
st->chip.parent = &st->spi->dev;
st->chip.owner = THIS_MODULE;
st->chip.base = -1;
st->chip.ngpio = TI_ADS7950_NUM_GPIOS;
st->chip.get_direction = ti_ads7950_get_direction;
st->chip.direction_input = ti_ads7950_direction_input;
st->chip.direction_output = ti_ads7950_direction_output;
st->chip.get = ti_ads7950_get;
st->chip.set = ti_ads7950_set;
ret = gpiochip_add_data(&st->chip, st);
if (ret) {
dev_err(&spi->dev, "Failed to init GPIOs\n");
goto error_iio_device;
}
return 0;
error_iio_device:
iio_device_unregister(indio_dev);
error_cleanup_ring:
iio_triggered_buffer_cleanup(indio_dev);
error_disable_reg:
regulator_disable(st->reg);
error_destroy_mutex:
mutex_destroy(&st->slock);
return ret;
}
......@@ -472,9 +669,11 @@ static int ti_ads7950_remove(struct spi_device *spi)
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ti_ads7950_state *st = iio_priv(indio_dev);
gpiochip_remove(&st->chip);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
regulator_disable(st->reg);
mutex_destroy(&st->slock);
return 0;
}
......
......@@ -523,6 +523,6 @@ static struct spi_driver ads8688_driver = {
};
module_spi_driver(ads8688_driver);
MODULE_AUTHOR("Sean Nyekjaer <sean.nyekjaer@prevas.dk>");
MODULE_AUTHOR("Sean Nyekjaer <sean@geanix.dk>");
MODULE_DESCRIPTION("Texas Instruments ADS8688 driver");
MODULE_LICENSE("GPL v2");
......@@ -36,7 +36,8 @@ static int iio_buffer_cb_store_to(struct iio_buffer *buffer, const void *data)
static void iio_buffer_cb_release(struct iio_buffer *buffer)
{
struct iio_cb_buffer *cb_buff = buffer_to_cb_buffer(buffer);
kfree(cb_buff->buffer.scan_mask);
bitmap_free(cb_buff->buffer.scan_mask);
kfree(cb_buff);
}
......@@ -74,9 +75,8 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
}
cb_buff->indio_dev = cb_buff->channels[0].indio_dev;
cb_buff->buffer.scan_mask
= kcalloc(BITS_TO_LONGS(cb_buff->indio_dev->masklength),
sizeof(long), GFP_KERNEL);
cb_buff->buffer.scan_mask = bitmap_zalloc(cb_buff->indio_dev->masklength,
GFP_KERNEL);
if (cb_buff->buffer.scan_mask == NULL) {
ret = -ENOMEM;
goto error_release_channels;
......@@ -95,7 +95,7 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
return cb_buff;
error_free_scan_mask:
kfree(cb_buff->buffer.scan_mask);
bitmap_free(cb_buff->buffer.scan_mask);
error_release_channels:
iio_channel_release_all(cb_buff->channels);
error_free_cb_buff:
......
......@@ -12,14 +12,14 @@ config ATLAS_PH_SENSOR
select IIO_TRIGGERED_BUFFER
select IRQ_WORK
help
Say Y here to build I2C interface support for the following
Atlas Scientific OEM SM sensors:
Say Y here to build I2C interface support for the following
Atlas Scientific OEM SM sensors:
* pH SM sensor
* EC SM sensor
* ORP SM sensor
To compile this driver as module, choose M here: the
module will be called atlas-ph-sensor.
To compile this driver as module, choose M here: the
module will be called atlas-ph-sensor.
config BME680
tristate "Bosch Sensortec BME680 sensor driver"
......@@ -47,8 +47,8 @@ config BME680_SPI
config CCS811
tristate "AMS CCS811 VOC sensor"
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say Y here to build I2C interface support for the AMS
CCS811 VOC (Volatile Organic Compounds) sensor
......
......@@ -321,7 +321,12 @@ static int pms7003_probe(struct serdev_device *serdev)
}
static const struct of_device_id pms7003_of_match[] = {
{ .compatible = "plantower,pms1003" },
{ .compatible = "plantower,pms3003" },
{ .compatible = "plantower,pms5003" },
{ .compatible = "plantower,pms6003" },
{ .compatible = "plantower,pms7003" },
{ .compatible = "plantower,pmsa003" },
{ }
};
MODULE_DEVICE_TABLE(of, pms7003_of_match);
......
// SPDX-License-Identifier: GPL-2.0
/*
* cros_ec_sensors - Driver for Chrome OS Embedded Controller sensors.
*
* Copyright (C) 2016 Google, Inc
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This driver uses the cros-ec interface to communicate with the Chrome OS
* EC about sensors data. Data access is presented through iio sysfs.
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/iio/buffer.h>
#include <linux/iio/common/cros_ec_sensors_core.h>
......@@ -30,7 +21,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#define CROS_EC_SENSORS_MAX_CHANNELS 4
......
// SPDX-License-Identifier: GPL-2.0
/*
* cros_ec_sensors_core - Common function for Chrome OS EC sensor driver.
*
* Copyright (C) 2016 Google, Inc
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/delay.h>
......@@ -25,7 +17,6 @@
#include <linux/mfd/cros_ec_commands.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/platform_device.h>
static char *cros_ec_loc[] = {
......@@ -269,6 +260,17 @@ static int cros_ec_sensors_read_data_unsafe(struct iio_dev *indio_dev,
return 0;
}
/**
* cros_ec_sensors_read_lpc() - read acceleration data from EC shared memory.
* @indio_dev: pointer to IIO device.
* @scan_mask: bitmap of the sensor indices to scan.
* @data: location to store data.
*
* Note: this is the safe function for reading the EC data. It guarantees
* that the data sampled was not modified by the EC while being read.
*
* Return: 0 on success, -errno on failure.
*/
int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev,
unsigned long scan_mask, s16 *data)
{
......
......@@ -3,4 +3,4 @@
#
config IIO_MS_SENSORS_I2C
tristate
tristate
......@@ -81,7 +81,7 @@ int ssp_common_process_data(struct iio_dev *indio_dev, void *buf,
unsigned int len, int64_t timestamp)
{
__le32 time;
int64_t calculated_time;
int64_t calculated_time = 0;
struct ssp_sensor_data *spd = iio_priv(indio_dev);
if (indio_dev->scan_bytes == 0)
......
......@@ -14,6 +14,7 @@
#include <linux/iio/iio.h>
#include <linux/mfd/stm32-lptimer.h>
#include <linux/module.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
struct stm32_lptim_cnt {
......@@ -23,6 +24,7 @@ struct stm32_lptim_cnt {
u32 preset;
u32 polarity;
u32 quadrature_mode;
bool enabled;
};
static int stm32_lptim_is_enabled(struct stm32_lptim_cnt *priv)
......@@ -50,6 +52,7 @@ static int stm32_lptim_set_enable_state(struct stm32_lptim_cnt *priv,
if (!enable) {
clk_disable(priv->clk);
priv->enabled = false;
return 0;
}
......@@ -79,6 +82,7 @@ static int stm32_lptim_set_enable_state(struct stm32_lptim_cnt *priv,
regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
return ret;
}
priv->enabled = true;
/* Start LP timer in continuous mode */
return regmap_update_bits(priv->regmap, STM32_LPTIM_CR,
......@@ -361,6 +365,56 @@ static int stm32_lptim_cnt_probe(struct platform_device *pdev)
return devm_iio_device_register(&pdev->dev, indio_dev);
}
#ifdef CONFIG_PM_SLEEP
static int stm32_lptim_cnt_suspend(struct device *dev)
{
struct stm32_lptim_cnt *priv = dev_get_drvdata(dev);
int ret;
/* Only take care of enabled counter: don't disturb other MFD child */
if (priv->enabled) {
ret = stm32_lptim_setup(priv, 0);
if (ret)
return ret;
ret = stm32_lptim_set_enable_state(priv, 0);
if (ret)
return ret;
/* Force enable state for later resume */
priv->enabled = true;
}
return pinctrl_pm_select_sleep_state(dev);
}
static int stm32_lptim_cnt_resume(struct device *dev)
{
struct stm32_lptim_cnt *priv = dev_get_drvdata(dev);
int ret;
ret = pinctrl_pm_select_default_state(dev);
if (ret)
return ret;
if (priv->enabled) {
priv->enabled = false;
ret = stm32_lptim_setup(priv, 1);
if (ret)
return ret;
ret = stm32_lptim_set_enable_state(priv, 1);
if (ret)
return ret;
}
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(stm32_lptim_cnt_pm_ops, stm32_lptim_cnt_suspend,
stm32_lptim_cnt_resume);
static const struct of_device_id stm32_lptim_cnt_of_match[] = {
{ .compatible = "st,stm32-lptimer-counter", },
{},
......@@ -372,6 +426,7 @@ static struct platform_driver stm32_lptim_cnt_driver = {
.driver = {
.name = "stm32-lptimer-counter",
.of_match_table = stm32_lptim_cnt_of_match,
.pm = &stm32_lptim_cnt_pm_ops,
},
};
module_platform_driver(stm32_lptim_cnt_driver);
......
......@@ -112,6 +112,8 @@ struct ad5064_state {
bool use_internal_vref;
ad5064_write_func write;
/* Lock used to maintain consistency between cached and dev state */
struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the
......@@ -248,11 +250,11 @@ static int ad5064_set_powerdown_mode(struct iio_dev *indio_dev,
struct ad5064_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->pwr_down_mode[chan->channel] = mode + 1;
ret = ad5064_sync_powerdown_mode(st, chan);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
......@@ -291,11 +293,11 @@ static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev,
if (ret)
return ret;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->pwr_down[chan->channel] = pwr_down;
ret = ad5064_sync_powerdown_mode(st, chan);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret ? ret : len;
}
......@@ -349,12 +351,12 @@ static int ad5064_write_raw(struct iio_dev *indio_dev,
if (val >= (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
ret = ad5064_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N,
chan->address, val, chan->scan_type.shift);
if (ret == 0)
st->dac_cache[chan->channel] = val;
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
break;
default:
ret = -EINVAL;
......@@ -856,6 +858,7 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type,
return -ENOMEM;
st = iio_priv(indio_dev);
mutex_init(&st->lock);
dev_set_drvdata(dev, indio_dev);
st->chip_info = &ad5064_chip_info_tbl[type];
......
......@@ -429,6 +429,6 @@ static struct i2c_driver dac5571_driver = {
};
module_i2c_driver(dac5571_driver);
MODULE_AUTHOR("Sean Nyekjaer <sean.nyekjaer@prevas.dk>");
MODULE_AUTHOR("Sean Nyekjaer <sean@geanix.dk>");
MODULE_DESCRIPTION("Texas Instruments 8/10/12-bit 1/4-channel DAC driver");
MODULE_LICENSE("GPL v2");
......@@ -872,22 +872,22 @@ static int ad9523_setup(struct iio_dev *indio_dev)
return ret;
ret = ad9523_write(indio_dev, AD9523_PLL2_VCO_DIVIDER,
AD9523_PLL2_VCO_DIV_M1(pdata->pll2_vco_diff_m1) |
AD9523_PLL2_VCO_DIV_M2(pdata->pll2_vco_diff_m2) |
AD_IFE(pll2_vco_diff_m1, 0,
AD9523_PLL2_VCO_DIV_M1(pdata->pll2_vco_div_m1) |
AD9523_PLL2_VCO_DIV_M2(pdata->pll2_vco_div_m2) |
AD_IFE(pll2_vco_div_m1, 0,
AD9523_PLL2_VCO_DIV_M1_PWR_DOWN_EN) |
AD_IFE(pll2_vco_diff_m2, 0,
AD_IFE(pll2_vco_div_m2, 0,
AD9523_PLL2_VCO_DIV_M2_PWR_DOWN_EN));
if (ret < 0)
return ret;
if (pdata->pll2_vco_diff_m1)
if (pdata->pll2_vco_div_m1)
st->vco_out_freq[AD9523_VCO1] =
st->vco_freq / pdata->pll2_vco_diff_m1;
st->vco_freq / pdata->pll2_vco_div_m1;
if (pdata->pll2_vco_diff_m2)
if (pdata->pll2_vco_div_m2)
st->vco_out_freq[AD9523_VCO2] =
st->vco_freq / pdata->pll2_vco_diff_m2;
st->vco_freq / pdata->pll2_vco_div_m2;
st->vco_out_freq[AD9523_VCXO] = pdata->vcxo_freq;
......
......@@ -102,6 +102,7 @@ struct bmg160_data {
struct regmap *regmap;
struct iio_trigger *dready_trig;
struct iio_trigger *motion_trig;
struct iio_mount_matrix orientation;
struct mutex mutex;
s16 buffer[8];
u32 dps_range;
......@@ -794,6 +795,20 @@ static int bmg160_write_event_config(struct iio_dev *indio_dev,
return 0;
}
static const struct iio_mount_matrix *
bmg160_get_mount_matrix(const struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct bmg160_data *data = iio_priv(indio_dev);
return &data->orientation;
}
static const struct iio_chan_spec_ext_info bmg160_ext_info[] = {
IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bmg160_get_mount_matrix),
{ }
};
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 400 1000 2000");
static IIO_CONST_ATTR(in_anglvel_scale_available,
......@@ -831,6 +846,7 @@ static const struct iio_event_spec bmg160_event = {
.storagebits = 16, \
.endianness = IIO_LE, \
}, \
.ext_info = bmg160_ext_info, \
.event_spec = &bmg160_event, \
.num_event_specs = 1 \
}
......@@ -1075,6 +1091,11 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
data->irq = irq;
data->regmap = regmap;
ret = iio_read_mount_matrix(dev, "mount-matrix",
&data->orientation);
if (ret)
return ret;
ret = bmg160_chip_init(data);
if (ret < 0)
return ret;
......
......@@ -54,10 +54,19 @@ static const struct i2c_device_id bmg160_i2c_id[] = {
MODULE_DEVICE_TABLE(i2c, bmg160_i2c_id);
static const struct of_device_id bmg160_of_match[] = {
{ .compatible = "bosch,bmg160" },
{ .compatible = "bosch,bmi055_gyro" },
{ }
};
MODULE_DEVICE_TABLE(of, bmg160_of_match);
static struct i2c_driver bmg160_i2c_driver = {
.driver = {
.name = "bmg160_i2c",
.acpi_match_table = ACPI_PTR(bmg160_acpi_match),
.of_match_table = bmg160_of_match,
.pm = &bmg160_pm_ops,
},
.probe = bmg160_i2c_probe,
......
......@@ -242,6 +242,20 @@ static int itg3200_initial_setup(struct iio_dev *indio_dev)
return ret;
}
static const struct iio_mount_matrix *
itg3200_get_mount_matrix(const struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct itg3200 *data = iio_priv(indio_dev);
return &data->orientation;
}
static const struct iio_chan_spec_ext_info itg3200_ext_info[] = {
IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, itg3200_get_mount_matrix),
{ }
};
#define ITG3200_ST \
{ .sign = 's', .realbits = 16, .storagebits = 16, .endianness = IIO_BE }
......@@ -255,6 +269,7 @@ static int itg3200_initial_setup(struct iio_dev *indio_dev)
.address = ITG3200_REG_GYRO_ ## _mod ## OUT_H, \
.scan_index = ITG3200_SCAN_GYRO_ ## _mod, \
.scan_type = ITG3200_ST, \
.ext_info = itg3200_ext_info, \
}
static const struct iio_chan_spec itg3200_channels[] = {
......@@ -297,6 +312,11 @@ static int itg3200_probe(struct i2c_client *client,
st = iio_priv(indio_dev);
ret = iio_read_mount_matrix(&client->dev, "mount-matrix",
&st->orientation);
if (ret)
return ret;
i2c_set_clientdata(client, indio_dev);
st->i2c = client;
......
......@@ -1149,8 +1149,7 @@ int mpu3050_common_probe(struct device *dev,
mpu3050->divisor = 99;
/* Read the mounting matrix, if present */
ret = of_iio_read_mount_matrix(dev, "mount-matrix",
&mpu3050->orientation);
ret = iio_read_mount_matrix(dev, "mount-matrix", &mpu3050->orientation);
if (ret)
return ret;
......
......@@ -4,16 +4,16 @@
menu "Humidity sensors"
config AM2315
tristate "Aosong AM2315 relative humidity and temperature sensor"
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
If you say yes here you get support for the Aosong AM2315
relative humidity and ambient temperature sensor.
tristate "Aosong AM2315 relative humidity and temperature sensor"
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
If you say yes here you get support for the Aosong AM2315
relative humidity and ambient temperature sensor.
This driver can also be built as a module. If so, the module will
be called am2315.
This driver can also be built as a module. If so, the module will
be called am2315.
config DHT11
tristate "DHT11 (and compatible sensors) driver"
......@@ -78,7 +78,7 @@ config HTS221_SPI
config HTU21
tristate "Measurement Specialties HTU21 humidity & temperature sensor"
depends on I2C
select IIO_MS_SENSORS_I2C
select IIO_MS_SENSORS_I2C
help
If you say yes here you get support for the Measurement Specialties
HTU21 humidity and temperature sensor.
......
......@@ -4,8 +4,6 @@
#
# When adding new entries keep the list in alphabetical order
adis16400-y := adis16400_core.o
adis16400-$(CONFIG_IIO_BUFFER) += adis16400_buffer.o
obj-$(CONFIG_ADIS16400) += adis16400.o
obj-$(CONFIG_ADIS16480) += adis16480.o
......
......@@ -31,8 +31,183 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/imu/adis.h>
#define ADIS16400_STARTUP_DELAY 290 /* ms */
#define ADIS16400_MTEST_DELAY 90 /* ms */
#define ADIS16400_FLASH_CNT 0x00 /* Flash memory write count */
#define ADIS16400_SUPPLY_OUT 0x02 /* Power supply measurement */
#define ADIS16400_XGYRO_OUT 0x04 /* X-axis gyroscope output */
#define ADIS16400_YGYRO_OUT 0x06 /* Y-axis gyroscope output */
#define ADIS16400_ZGYRO_OUT 0x08 /* Z-axis gyroscope output */
#define ADIS16400_XACCL_OUT 0x0A /* X-axis accelerometer output */
#define ADIS16400_YACCL_OUT 0x0C /* Y-axis accelerometer output */
#define ADIS16400_ZACCL_OUT 0x0E /* Z-axis accelerometer output */
#define ADIS16400_XMAGN_OUT 0x10 /* X-axis magnetometer measurement */
#define ADIS16400_YMAGN_OUT 0x12 /* Y-axis magnetometer measurement */
#define ADIS16400_ZMAGN_OUT 0x14 /* Z-axis magnetometer measurement */
#define ADIS16400_TEMP_OUT 0x16 /* Temperature output */
#define ADIS16400_AUX_ADC 0x18 /* Auxiliary ADC measurement */
#define ADIS16350_XTEMP_OUT 0x10 /* X-axis gyroscope temperature measurement */
#define ADIS16350_YTEMP_OUT 0x12 /* Y-axis gyroscope temperature measurement */
#define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */
#define ADIS16300_PITCH_OUT 0x12 /* X axis inclinometer output measurement */
#define ADIS16300_ROLL_OUT 0x14 /* Y axis inclinometer output measurement */
#define ADIS16300_AUX_ADC 0x16 /* Auxiliary ADC measurement */
#define ADIS16448_BARO_OUT 0x16 /* Barometric pressure output */
#define ADIS16448_TEMP_OUT 0x18 /* Temperature output */
/* Calibration parameters */
#define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */
#define ADIS16400_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */
#define ADIS16400_ZGYRO_OFF 0x1E /* Z-axis gyroscope bias offset factor */
#define ADIS16400_XACCL_OFF 0x20 /* X-axis acceleration bias offset factor */
#define ADIS16400_YACCL_OFF 0x22 /* Y-axis acceleration bias offset factor */
#define ADIS16400_ZACCL_OFF 0x24 /* Z-axis acceleration bias offset factor */
#define ADIS16400_XMAGN_HIF 0x26 /* X-axis magnetometer, hard-iron factor */
#define ADIS16400_YMAGN_HIF 0x28 /* Y-axis magnetometer, hard-iron factor */
#define ADIS16400_ZMAGN_HIF 0x2A /* Z-axis magnetometer, hard-iron factor */
#define ADIS16400_XMAGN_SIF 0x2C /* X-axis magnetometer, soft-iron factor */
#define ADIS16400_YMAGN_SIF 0x2E /* Y-axis magnetometer, soft-iron factor */
#define ADIS16400_ZMAGN_SIF 0x30 /* Z-axis magnetometer, soft-iron factor */
#define ADIS16400_GPIO_CTRL 0x32 /* Auxiliary digital input/output control */
#define ADIS16400_MSC_CTRL 0x34 /* Miscellaneous control */
#define ADIS16400_SMPL_PRD 0x36 /* Internal sample period (rate) control */
#define ADIS16400_SENS_AVG 0x38 /* Dynamic range and digital filter control */
#define ADIS16400_SLP_CNT 0x3A /* Sleep mode control */
#define ADIS16400_DIAG_STAT 0x3C /* System status */
/* Alarm functions */
#define ADIS16400_GLOB_CMD 0x3E /* System command */
#define ADIS16400_ALM_MAG1 0x40 /* Alarm 1 amplitude threshold */
#define ADIS16400_ALM_MAG2 0x42 /* Alarm 2 amplitude threshold */
#define ADIS16400_ALM_SMPL1 0x44 /* Alarm 1 sample size */
#define ADIS16400_ALM_SMPL2 0x46 /* Alarm 2 sample size */
#define ADIS16400_ALM_CTRL 0x48 /* Alarm control */
#define ADIS16400_AUX_DAC 0x4A /* Auxiliary DAC data */
#define ADIS16334_LOT_ID1 0x52 /* Lot identification code 1 */
#define ADIS16334_LOT_ID2 0x54 /* Lot identification code 2 */
#define ADIS16400_PRODUCT_ID 0x56 /* Product identifier */
#define ADIS16334_SERIAL_NUMBER 0x58 /* Serial number, lot specific */
#define ADIS16400_ERROR_ACTIVE (1<<14)
#define ADIS16400_NEW_DATA (1<<14)
/* MSC_CTRL */
#define ADIS16400_MSC_CTRL_MEM_TEST (1<<11)
#define ADIS16400_MSC_CTRL_INT_SELF_TEST (1<<10)
#define ADIS16400_MSC_CTRL_NEG_SELF_TEST (1<<9)
#define ADIS16400_MSC_CTRL_POS_SELF_TEST (1<<8)
#define ADIS16400_MSC_CTRL_GYRO_BIAS (1<<7)
#define ADIS16400_MSC_CTRL_ACCL_ALIGN (1<<6)
#define ADIS16400_MSC_CTRL_DATA_RDY_EN (1<<2)
#define ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1)
#define ADIS16400_MSC_CTRL_DATA_RDY_DIO2 (1<<0)
/* SMPL_PRD */
#define ADIS16400_SMPL_PRD_TIME_BASE (1<<7)
#define ADIS16400_SMPL_PRD_DIV_MASK 0x7F
/* DIAG_STAT */
#define ADIS16400_DIAG_STAT_ZACCL_FAIL 15
#define ADIS16400_DIAG_STAT_YACCL_FAIL 14
#define ADIS16400_DIAG_STAT_XACCL_FAIL 13
#define ADIS16400_DIAG_STAT_XGYRO_FAIL 12
#define ADIS16400_DIAG_STAT_YGYRO_FAIL 11
#define ADIS16400_DIAG_STAT_ZGYRO_FAIL 10
#define ADIS16400_DIAG_STAT_ALARM2 9
#define ADIS16400_DIAG_STAT_ALARM1 8
#define ADIS16400_DIAG_STAT_FLASH_CHK 6
#define ADIS16400_DIAG_STAT_SELF_TEST 5
#define ADIS16400_DIAG_STAT_OVERFLOW 4
#define ADIS16400_DIAG_STAT_SPI_FAIL 3
#define ADIS16400_DIAG_STAT_FLASH_UPT 2
#define ADIS16400_DIAG_STAT_POWER_HIGH 1
#define ADIS16400_DIAG_STAT_POWER_LOW 0
/* GLOB_CMD */
#define ADIS16400_GLOB_CMD_SW_RESET (1<<7)
#define ADIS16400_GLOB_CMD_P_AUTO_NULL (1<<4)
#define ADIS16400_GLOB_CMD_FLASH_UPD (1<<3)
#define ADIS16400_GLOB_CMD_DAC_LATCH (1<<2)
#define ADIS16400_GLOB_CMD_FAC_CALIB (1<<1)
#define ADIS16400_GLOB_CMD_AUTO_NULL (1<<0)
/* SLP_CNT */
#define ADIS16400_SLP_CNT_POWER_OFF (1<<8)
#define ADIS16334_RATE_DIV_SHIFT 8
#define ADIS16334_RATE_INT_CLK BIT(0)
#define ADIS16400_SPI_SLOW (u32)(300 * 1000)
#define ADIS16400_SPI_BURST (u32)(1000 * 1000)
#define ADIS16400_SPI_FAST (u32)(2000 * 1000)
#define ADIS16400_HAS_PROD_ID BIT(0)
#define ADIS16400_NO_BURST BIT(1)
#define ADIS16400_HAS_SLOW_MODE BIT(2)
#define ADIS16400_HAS_SERIAL_NUMBER BIT(3)
#define ADIS16400_BURST_DIAG_STAT BIT(4)
struct adis16400_state;
struct adis16400_chip_info {
const struct iio_chan_spec *channels;
const int num_channels;
const long flags;
unsigned int gyro_scale_micro;
unsigned int accel_scale_micro;
int temp_scale_nano;
int temp_offset;
int (*set_freq)(struct adis16400_state *st, unsigned int freq);
int (*get_freq)(struct adis16400_state *st);
};
/**
* struct adis16400_state - device instance specific data
* @variant: chip variant info
* @filt_int: integer part of requested filter frequency
* @adis: adis device
**/
struct adis16400_state {
struct adis16400_chip_info *variant;
int filt_int;
struct adis adis;
unsigned long avail_scan_mask[2];
};
#include "adis16400.h"
/* At the moment triggers are only used for ring buffer
* filling. This may change!
*/
enum {
ADIS16400_SCAN_SUPPLY,
ADIS16400_SCAN_GYRO_X,
ADIS16400_SCAN_GYRO_Y,
ADIS16400_SCAN_GYRO_Z,
ADIS16400_SCAN_ACC_X,
ADIS16400_SCAN_ACC_Y,
ADIS16400_SCAN_ACC_Z,
ADIS16400_SCAN_MAGN_X,
ADIS16400_SCAN_MAGN_Y,
ADIS16400_SCAN_MAGN_Z,
ADIS16400_SCAN_BARO,
ADIS16350_SCAN_TEMP_X,
ADIS16350_SCAN_TEMP_Y,
ADIS16350_SCAN_TEMP_Z,
ADIS16300_SCAN_INCLI_X,
ADIS16300_SCAN_INCLI_Y,
ADIS16400_SCAN_ADC,
ADIS16400_SCAN_TIMESTAMP,
};
#ifdef CONFIG_DEBUG_FS
......@@ -145,6 +320,11 @@ enum adis16400_chip_variant {
ADIS16448,
};
static struct adis_burst adis16400_burst = {
.en = true,
.reg_cmd = ADIS16400_GLOB_CMD,
};
static int adis16334_get_freq(struct adis16400_state *st)
{
int ret;
......@@ -465,6 +645,51 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
}
}
#if IS_ENABLED(CONFIG_IIO_BUFFER)
static irqreturn_t adis16400_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adis16400_state *st = iio_priv(indio_dev);
struct adis *adis = &st->adis;
u32 old_speed_hz = st->adis.spi->max_speed_hz;
void *buffer;
int ret;
if (!adis->buffer)
return -ENOMEM;
if (!(st->variant->flags & ADIS16400_NO_BURST) &&
st->adis.spi->max_speed_hz > ADIS16400_SPI_BURST) {
st->adis.spi->max_speed_hz = ADIS16400_SPI_BURST;
spi_setup(st->adis.spi);
}
ret = spi_sync(adis->spi, &adis->msg);
if (ret)
dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret);
if (!(st->variant->flags & ADIS16400_NO_BURST)) {
st->adis.spi->max_speed_hz = old_speed_hz;
spi_setup(st->adis.spi);
}
if (st->variant->flags & ADIS16400_BURST_DIAG_STAT)
buffer = adis->buffer + sizeof(u16);
else
buffer = adis->buffer;
iio_push_to_buffers_with_timestamp(indio_dev, buffer,
pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
#else
#define adis16400_trigger_handler NULL
#endif /* IS_ENABLED(CONFIG_IIO_BUFFER) */
#define ADIS16400_VOLTAGE_CHAN(addr, bits, name, si, chn) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
......@@ -835,7 +1060,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
static const struct iio_info adis16400_info = {
.read_raw = &adis16400_read_raw,
.write_raw = &adis16400_write_raw,
.update_scan_mode = adis16400_update_scan_mode,
.update_scan_mode = adis_update_scan_mode,
.debugfs_reg_access = adis_debugfs_reg_access,
};
......@@ -926,6 +1151,9 @@ static int adis16400_probe(struct spi_device *spi)
if (!(st->variant->flags & ADIS16400_NO_BURST)) {
adis16400_setup_chan_mask(st);
indio_dev->available_scan_masks = st->avail_scan_mask;
st->adis.burst = &adis16400_burst;
if (st->variant->flags & ADIS16400_BURST_DIAG_STAT)
st->adis.burst->extra_len = sizeof(u16);
}
ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data);
......
/*
* adis16400.h support Analog Devices ADIS16400
* 3d 18g accelerometers,
* 3d gyroscopes,
* 3d 2.5gauss magnetometers via SPI
*
* Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
* Copyright (c) 2007 Jonathan Cameron <jic23@kernel.org>
*
* Loosely based upon lis3l02dq.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef SPI_ADIS16400_H_
#define SPI_ADIS16400_H_
#include <linux/iio/imu/adis.h>
#define ADIS16400_STARTUP_DELAY 290 /* ms */
#define ADIS16400_MTEST_DELAY 90 /* ms */
#define ADIS16400_FLASH_CNT 0x00 /* Flash memory write count */
#define ADIS16400_SUPPLY_OUT 0x02 /* Power supply measurement */
#define ADIS16400_XGYRO_OUT 0x04 /* X-axis gyroscope output */
#define ADIS16400_YGYRO_OUT 0x06 /* Y-axis gyroscope output */
#define ADIS16400_ZGYRO_OUT 0x08 /* Z-axis gyroscope output */
#define ADIS16400_XACCL_OUT 0x0A /* X-axis accelerometer output */
#define ADIS16400_YACCL_OUT 0x0C /* Y-axis accelerometer output */
#define ADIS16400_ZACCL_OUT 0x0E /* Z-axis accelerometer output */
#define ADIS16400_XMAGN_OUT 0x10 /* X-axis magnetometer measurement */
#define ADIS16400_YMAGN_OUT 0x12 /* Y-axis magnetometer measurement */
#define ADIS16400_ZMAGN_OUT 0x14 /* Z-axis magnetometer measurement */
#define ADIS16400_TEMP_OUT 0x16 /* Temperature output */
#define ADIS16400_AUX_ADC 0x18 /* Auxiliary ADC measurement */
#define ADIS16350_XTEMP_OUT 0x10 /* X-axis gyroscope temperature measurement */
#define ADIS16350_YTEMP_OUT 0x12 /* Y-axis gyroscope temperature measurement */
#define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */
#define ADIS16300_PITCH_OUT 0x12 /* X axis inclinometer output measurement */
#define ADIS16300_ROLL_OUT 0x14 /* Y axis inclinometer output measurement */
#define ADIS16300_AUX_ADC 0x16 /* Auxiliary ADC measurement */
#define ADIS16448_BARO_OUT 0x16 /* Barometric pressure output */
#define ADIS16448_TEMP_OUT 0x18 /* Temperature output */
/* Calibration parameters */
#define ADIS16400_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */
#define ADIS16400_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */
#define ADIS16400_ZGYRO_OFF 0x1E /* Z-axis gyroscope bias offset factor */
#define ADIS16400_XACCL_OFF 0x20 /* X-axis acceleration bias offset factor */
#define ADIS16400_YACCL_OFF 0x22 /* Y-axis acceleration bias offset factor */
#define ADIS16400_ZACCL_OFF 0x24 /* Z-axis acceleration bias offset factor */
#define ADIS16400_XMAGN_HIF 0x26 /* X-axis magnetometer, hard-iron factor */
#define ADIS16400_YMAGN_HIF 0x28 /* Y-axis magnetometer, hard-iron factor */
#define ADIS16400_ZMAGN_HIF 0x2A /* Z-axis magnetometer, hard-iron factor */
#define ADIS16400_XMAGN_SIF 0x2C /* X-axis magnetometer, soft-iron factor */
#define ADIS16400_YMAGN_SIF 0x2E /* Y-axis magnetometer, soft-iron factor */
#define ADIS16400_ZMAGN_SIF 0x30 /* Z-axis magnetometer, soft-iron factor */
#define ADIS16400_GPIO_CTRL 0x32 /* Auxiliary digital input/output control */
#define ADIS16400_MSC_CTRL 0x34 /* Miscellaneous control */
#define ADIS16400_SMPL_PRD 0x36 /* Internal sample period (rate) control */
#define ADIS16400_SENS_AVG 0x38 /* Dynamic range and digital filter control */
#define ADIS16400_SLP_CNT 0x3A /* Sleep mode control */
#define ADIS16400_DIAG_STAT 0x3C /* System status */
/* Alarm functions */
#define ADIS16400_GLOB_CMD 0x3E /* System command */
#define ADIS16400_ALM_MAG1 0x40 /* Alarm 1 amplitude threshold */
#define ADIS16400_ALM_MAG2 0x42 /* Alarm 2 amplitude threshold */
#define ADIS16400_ALM_SMPL1 0x44 /* Alarm 1 sample size */
#define ADIS16400_ALM_SMPL2 0x46 /* Alarm 2 sample size */
#define ADIS16400_ALM_CTRL 0x48 /* Alarm control */
#define ADIS16400_AUX_DAC 0x4A /* Auxiliary DAC data */
#define ADIS16334_LOT_ID1 0x52 /* Lot identification code 1 */
#define ADIS16334_LOT_ID2 0x54 /* Lot identification code 2 */
#define ADIS16400_PRODUCT_ID 0x56 /* Product identifier */
#define ADIS16334_SERIAL_NUMBER 0x58 /* Serial number, lot specific */
#define ADIS16400_ERROR_ACTIVE (1<<14)
#define ADIS16400_NEW_DATA (1<<14)
/* MSC_CTRL */
#define ADIS16400_MSC_CTRL_MEM_TEST (1<<11)
#define ADIS16400_MSC_CTRL_INT_SELF_TEST (1<<10)
#define ADIS16400_MSC_CTRL_NEG_SELF_TEST (1<<9)
#define ADIS16400_MSC_CTRL_POS_SELF_TEST (1<<8)
#define ADIS16400_MSC_CTRL_GYRO_BIAS (1<<7)
#define ADIS16400_MSC_CTRL_ACCL_ALIGN (1<<6)
#define ADIS16400_MSC_CTRL_DATA_RDY_EN (1<<2)
#define ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1)
#define ADIS16400_MSC_CTRL_DATA_RDY_DIO2 (1<<0)
/* SMPL_PRD */
#define ADIS16400_SMPL_PRD_TIME_BASE (1<<7)
#define ADIS16400_SMPL_PRD_DIV_MASK 0x7F
/* DIAG_STAT */
#define ADIS16400_DIAG_STAT_ZACCL_FAIL 15
#define ADIS16400_DIAG_STAT_YACCL_FAIL 14
#define ADIS16400_DIAG_STAT_XACCL_FAIL 13
#define ADIS16400_DIAG_STAT_XGYRO_FAIL 12
#define ADIS16400_DIAG_STAT_YGYRO_FAIL 11
#define ADIS16400_DIAG_STAT_ZGYRO_FAIL 10
#define ADIS16400_DIAG_STAT_ALARM2 9
#define ADIS16400_DIAG_STAT_ALARM1 8
#define ADIS16400_DIAG_STAT_FLASH_CHK 6
#define ADIS16400_DIAG_STAT_SELF_TEST 5
#define ADIS16400_DIAG_STAT_OVERFLOW 4
#define ADIS16400_DIAG_STAT_SPI_FAIL 3
#define ADIS16400_DIAG_STAT_FLASH_UPT 2
#define ADIS16400_DIAG_STAT_POWER_HIGH 1
#define ADIS16400_DIAG_STAT_POWER_LOW 0
/* GLOB_CMD */
#define ADIS16400_GLOB_CMD_SW_RESET (1<<7)
#define ADIS16400_GLOB_CMD_P_AUTO_NULL (1<<4)
#define ADIS16400_GLOB_CMD_FLASH_UPD (1<<3)
#define ADIS16400_GLOB_CMD_DAC_LATCH (1<<2)
#define ADIS16400_GLOB_CMD_FAC_CALIB (1<<1)
#define ADIS16400_GLOB_CMD_AUTO_NULL (1<<0)
/* SLP_CNT */
#define ADIS16400_SLP_CNT_POWER_OFF (1<<8)
#define ADIS16334_RATE_DIV_SHIFT 8
#define ADIS16334_RATE_INT_CLK BIT(0)
#define ADIS16400_SPI_SLOW (u32)(300 * 1000)
#define ADIS16400_SPI_BURST (u32)(1000 * 1000)
#define ADIS16400_SPI_FAST (u32)(2000 * 1000)
#define ADIS16400_HAS_PROD_ID BIT(0)
#define ADIS16400_NO_BURST BIT(1)
#define ADIS16400_HAS_SLOW_MODE BIT(2)
#define ADIS16400_HAS_SERIAL_NUMBER BIT(3)
#define ADIS16400_BURST_DIAG_STAT BIT(4)
struct adis16400_state;
struct adis16400_chip_info {
const struct iio_chan_spec *channels;
const int num_channels;
const long flags;
unsigned int gyro_scale_micro;
unsigned int accel_scale_micro;
int temp_scale_nano;
int temp_offset;
int (*set_freq)(struct adis16400_state *st, unsigned int freq);
int (*get_freq)(struct adis16400_state *st);
};
/**
* struct adis16400_state - device instance specific data
* @variant: chip variant info
* @filt_int: integer part of requested filter frequency
* @adis: adis device
**/
struct adis16400_state {
struct adis16400_chip_info *variant;
int filt_int;
struct adis adis;
unsigned long avail_scan_mask[2];
};
/* At the moment triggers are only used for ring buffer
* filling. This may change!
*/
enum {
ADIS16400_SCAN_SUPPLY,
ADIS16400_SCAN_GYRO_X,
ADIS16400_SCAN_GYRO_Y,
ADIS16400_SCAN_GYRO_Z,
ADIS16400_SCAN_ACC_X,
ADIS16400_SCAN_ACC_Y,
ADIS16400_SCAN_ACC_Z,
ADIS16400_SCAN_MAGN_X,
ADIS16400_SCAN_MAGN_Y,
ADIS16400_SCAN_MAGN_Z,
ADIS16400_SCAN_BARO,
ADIS16350_SCAN_TEMP_X,
ADIS16350_SCAN_TEMP_Y,
ADIS16350_SCAN_TEMP_Z,
ADIS16300_SCAN_INCLI_X,
ADIS16300_SCAN_INCLI_Y,
ADIS16400_SCAN_ADC,
ADIS16400_SCAN_TIMESTAMP,
};
#ifdef CONFIG_IIO_BUFFER
ssize_t adis16400_read_data_from_ring(struct device *dev,
struct device_attribute *attr,
char *buf);
int adis16400_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask);
irqreturn_t adis16400_trigger_handler(int irq, void *p);
#else /* CONFIG_IIO_BUFFER */
#define adis16400_update_scan_mode NULL
#define adis16400_trigger_handler NULL
#endif /* CONFIG_IIO_BUFFER */
#endif /* SPI_ADIS16400_H_ */
// SPDX-License-Identifier: GPL-2.0
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/bitops.h>
#include <linux/export.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include "adis16400.h"
int adis16400_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct adis16400_state *st = iio_priv(indio_dev);
struct adis *adis = &st->adis;
unsigned int burst_length;
u8 *tx;
if (st->variant->flags & ADIS16400_NO_BURST)
return adis_update_scan_mode(indio_dev, scan_mask);
kfree(adis->xfer);
kfree(adis->buffer);
/* All but the timestamp channel */
burst_length = (indio_dev->num_channels - 1) * sizeof(u16);
if (st->variant->flags & ADIS16400_BURST_DIAG_STAT)
burst_length += sizeof(u16);
adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL);
if (!adis->xfer)
return -ENOMEM;
adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL);
if (!adis->buffer)
return -ENOMEM;
tx = adis->buffer + burst_length;
tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD);
tx[1] = 0;
adis->xfer[0].tx_buf = tx;
adis->xfer[0].bits_per_word = 8;
adis->xfer[0].len = 2;
adis->xfer[1].rx_buf = adis->buffer;
adis->xfer[1].bits_per_word = 8;
adis->xfer[1].len = burst_length;
spi_message_init(&adis->msg);
spi_message_add_tail(&adis->xfer[0], &adis->msg);
spi_message_add_tail(&adis->xfer[1], &adis->msg);
return 0;
}
irqreturn_t adis16400_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adis16400_state *st = iio_priv(indio_dev);
struct adis *adis = &st->adis;
u32 old_speed_hz = st->adis.spi->max_speed_hz;
void *buffer;
int ret;
if (!adis->buffer)
return -ENOMEM;
if (!(st->variant->flags & ADIS16400_NO_BURST) &&
st->adis.spi->max_speed_hz > ADIS16400_SPI_BURST) {
st->adis.spi->max_speed_hz = ADIS16400_SPI_BURST;
spi_setup(st->adis.spi);
}
ret = spi_sync(adis->spi, &adis->msg);
if (ret)
dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret);
if (!(st->variant->flags & ADIS16400_NO_BURST)) {
st->adis.spi->max_speed_hz = old_speed_hz;
spi_setup(st->adis.spi);
}
if (st->variant->flags & ADIS16400_BURST_DIAG_STAT)
buffer = adis->buffer + sizeof(u16);
else
buffer = adis->buffer;
iio_push_to_buffers_with_timestamp(indio_dev, buffer,
pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
This diff is collapsed.
......@@ -20,6 +20,43 @@
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/imu/adis.h>
static int adis_update_scan_mode_burst(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct adis *adis = iio_device_get_drvdata(indio_dev);
unsigned int burst_length;
u8 *tx;
/* All but the timestamp channel */
burst_length = (indio_dev->num_channels - 1) * sizeof(u16);
burst_length += adis->burst->extra_len;
adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL);
if (!adis->xfer)
return -ENOMEM;
adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL);
if (!adis->buffer)
return -ENOMEM;
tx = adis->buffer + burst_length;
tx[0] = ADIS_READ_REG(adis->burst->reg_cmd);
tx[1] = 0;
adis->xfer[0].tx_buf = tx;
adis->xfer[0].bits_per_word = 8;
adis->xfer[0].len = 2;
adis->xfer[1].rx_buf = adis->buffer;
adis->xfer[1].bits_per_word = 8;
adis->xfer[1].len = burst_length;
spi_message_init(&adis->msg);
spi_message_add_tail(&adis->xfer[0], &adis->msg);
spi_message_add_tail(&adis->xfer[1], &adis->msg);
return 0;
}
int adis_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
......@@ -32,6 +69,9 @@ int adis_update_scan_mode(struct iio_dev *indio_dev,
kfree(adis->xfer);
kfree(adis->buffer);
if (adis->burst && adis->burst->en)
return adis_update_scan_mode_burst(indio_dev, scan_mask);
scan_count = indio_dev->scan_bytes / 2;
adis->xfer = kcalloc(scan_count + 1, sizeof(*adis->xfer), GFP_KERNEL);
......
......@@ -796,12 +796,14 @@ static const struct iio_mount_matrix *
inv_get_mount_matrix(const struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
return &((struct inv_mpu6050_state *)iio_priv(indio_dev))->orientation;
struct inv_mpu6050_state *data = iio_priv(indio_dev);
return &data->orientation;
}
static const struct iio_chan_spec_ext_info inv_ext_info[] = {
IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, inv_get_mount_matrix),
{ },
{ }
};
#define INV_MPU6050_CHAN(_type, _channel2, _index) \
......@@ -1021,8 +1023,8 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
pdata = dev_get_platdata(dev);
if (!pdata) {
result = of_iio_read_mount_matrix(dev, "mount-matrix",
&st->orientation);
result = iio_read_mount_matrix(dev, "mount-matrix",
&st->orientation);
if (result) {
dev_err(dev, "Failed to retrieve mounting matrix %d\n",
result);
......
......@@ -9,7 +9,7 @@ config IIO_ST_LSM6DSX
help
Say yes here to build support for STMicroelectronics LSM6DSx imu
sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm,
ism330dlc, lsm6dso
ism330dlc, lsm6dso, lsm6dsox, asm330lhh
To compile this driver as a module, choose M here: the module
will be called st_lsm6dsx.
......
......@@ -20,6 +20,8 @@
#define ST_LSM6DSM_DEV_NAME "lsm6dsm"
#define ST_ISM330DLC_DEV_NAME "ism330dlc"
#define ST_LSM6DSO_DEV_NAME "lsm6dso"
#define ST_ASM330LHH_DEV_NAME "asm330lhh"
#define ST_LSM6DSOX_DEV_NAME "lsm6dsox"
enum st_lsm6dsx_hw_id {
ST_LSM6DS3_ID,
......@@ -28,6 +30,8 @@ enum st_lsm6dsx_hw_id {
ST_LSM6DSM_ID,
ST_ISM330DLC_ID,
ST_LSM6DSO_ID,
ST_ASM330LHH_ID,
ST_LSM6DSOX_ID,
ST_LSM6DSX_MAX_ID,
};
......
......@@ -13,9 +13,9 @@
* (e.g. Gx, Gy, Gz, Ax, Ay, Az), then data are repeated depending on the
* value of the decimation factor and ODR set for each FIFO data set.
*
* LSM6DSO: The FIFO buffer can be configured to store data from gyroscope and
* accelerometer. Each sample is queued with a tag (1B) indicating data source
* (gyroscope, accelerometer, hw timer).
* LSM6DSO/LSM6DSOX/ASM330LHH: The FIFO buffer can be configured to store data
* from gyroscope and accelerometer. Each sample is queued with a tag (1B)
* indicating data source (gyroscope, accelerometer, hw timer).
*
* FIFO supported modes:
* - BYPASS: FIFO disabled
......@@ -506,7 +506,7 @@ st_lsm6dsx_push_tagged_data(struct st_lsm6dsx_hw *hw, u8 tag,
}
/**
* st_lsm6dsx_read_tagged_fifo() - LSM6DSO read FIFO routine
* st_lsm6dsx_read_tagged_fifo() - LSM6DSO/LSM6DSOX/ASM330LHH read FIFO routine
* @hw: Pointer to instance of struct st_lsm6dsx_hw.
*
* Read samples from the hw FIFO and push them to IIO buffers.
......
......@@ -23,7 +23,7 @@
* - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
* - FIFO size: 4KB
*
* - LSM6DSO
* - LSM6DSO/LSM6DSOX/ASM330LHH
* - 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
......@@ -287,6 +287,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.max_fifo_size = 512,
.id = {
[0] = ST_LSM6DSO_ID,
[1] = ST_LSM6DSOX_ID,
},
.batch = {
[ST_LSM6DSX_ID_ACC] = {
......@@ -347,6 +348,45 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.batch_en = BIT(3),
}
},
{
.wai = 0x6b,
.max_fifo_size = 512,
.id = {
[0] = ST_ASM330LHH_ID,
},
.batch = {
[ST_LSM6DSX_ID_ACC] = {
.addr = 0x09,
.mask = GENMASK(3, 0),
},
[ST_LSM6DSX_ID_GYRO] = {
.addr = 0x09,
.mask = GENMASK(7, 4),
},
},
.fifo_ops = {
.read_fifo = st_lsm6dsx_read_tagged_fifo,
.fifo_th = {
.addr = 0x07,
.mask = GENMASK(8, 0),
},
.fifo_diff = {
.addr = 0x3a,
.mask = GENMASK(8, 0),
},
.th_wl = 1,
},
.ts_settings = {
.timer_en = {
.addr = 0x19,
.mask = BIT(5),
},
.decimator = {
.addr = 0x0a,
.mask = GENMASK(7, 6),
},
},
},
};
static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = {
......
......@@ -65,6 +65,14 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = {
.compatible = "st,lsm6dso",
.data = (void *)ST_LSM6DSO_ID,
},
{
.compatible = "st,asm330lhh",
.data = (void *)ST_ASM330LHH_ID,
},
{
.compatible = "st,lsm6dsox",
.data = (void *)ST_LSM6DSOX_ID,
},
{},
};
MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match);
......@@ -76,6 +84,8 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = {
{ ST_LSM6DSM_DEV_NAME, ST_LSM6DSM_ID },
{ ST_ISM330DLC_DEV_NAME, ST_ISM330DLC_ID },
{ ST_LSM6DSO_DEV_NAME, ST_LSM6DSO_ID },
{ ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID },
{ ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID },
{},
};
MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table);
......
......@@ -65,6 +65,14 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = {
.compatible = "st,lsm6dso",
.data = (void *)ST_LSM6DSO_ID,
},
{
.compatible = "st,asm330lhh",
.data = (void *)ST_ASM330LHH_ID,
},
{
.compatible = "st,lsm6dsox",
.data = (void *)ST_LSM6DSOX_ID,
},
{},
};
MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match);
......@@ -76,6 +84,8 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = {
{ ST_LSM6DSM_DEV_NAME, ST_LSM6DSM_ID },
{ ST_ISM330DLC_DEV_NAME, ST_ISM330DLC_ID },
{ ST_LSM6DSO_DEV_NAME, ST_LSM6DSO_ID },
{ ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID },
{ ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID },
{},
};
MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table);
......
This diff is collapsed.
This diff is collapsed.
......@@ -254,8 +254,11 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
/* Get irq number */
pf->irq = iio_trigger_get_irq(trig);
if (pf->irq < 0)
if (pf->irq < 0) {
pr_err("Could not find an available irq for trigger %s, CONFIG_IIO_CONSUMERS_PER_TRIGGER=%d limit might be exceeded\n",
trig->name, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
goto out_put_module;
}
/* Request irq */
ret = request_threaded_irq(pf->irq, pf->h, pf->thread,
......
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0
/*
* cros_ec_light_prox - Driver for light and prox sensors behing CrosEC.
*
* Copyright (C) 2017 Google, Inc
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/iio/buffer.h>
#include <linux/iio/common/cros_ec_sensors_core.h>
......@@ -28,7 +19,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
/*
* We only represent one entry for light or proximity. EC is merging different
......
This diff is collapsed.
......@@ -733,9 +733,8 @@ static int ak8974_probe(struct i2c_client *i2c,
ak8974->i2c = i2c;
mutex_init(&ak8974->lock);
ret = of_iio_read_mount_matrix(&i2c->dev,
"mount-matrix",
&ak8974->orientation);
ret = iio_read_mount_matrix(&i2c->dev, "mount-matrix",
&ak8974->orientation);
if (ret)
return ret;
......
This diff is collapsed.
This diff is collapsed.
......@@ -43,6 +43,7 @@ struct hmc5843_data {
struct mutex lock;
struct regmap *regmap;
const struct hmc5843_chip_info *variant;
struct iio_mount_matrix orientation;
__be16 buffer[8];
};
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -7,6 +7,7 @@
obj-$(CONFIG_AS3935) += as3935.o
obj-$(CONFIG_ISL29501) += isl29501.o
obj-$(CONFIG_LIDAR_LITE_V2) += pulsedlight-lidar-lite-v2.o
obj-$(CONFIG_MB1232) += mb1232.o
obj-$(CONFIG_RFD77402) += rfd77402.o
obj-$(CONFIG_SRF04) += srf04.o
obj-$(CONFIG_SRF08) += srf08.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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