Commit 281d90e2 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

Jonathan writes:

First set of new IIO device support, fatures and cleanups for the 5.7 cycle

Includes changes for the counter subsystem

Core Feature
* Explicitly handle sysfs values in dB, including correctly handling the
  needed postfix dB.
* Add a TODO to suggest suitable activities for new contributors to IIO now
  the vast majority of drivers are out of staging (and the remaining ones
  there are 'hard'). Also update the TODO in staging to remove stale entries.

Staging graduations
* ad7192 ADC.

New device support
* ad5770r
  - New driver for this 6 channel DAC including DT bindings.
* ad8366
  - Add supprot for the hmc1119 attenuator.
* al3010
  - New driver supporting this Dyna-image light sensors.
  - Power management and DT bindings added in additional patches.
* atlas-sensor
  - Add support for atlas DO-SM device.  Reads disolved oxygen in a solution.
* gpap002x00f
  - New driver and bindings to support the GP2AP002A00F and GP2AP002S00F light
    and proximity sensors. There is some limited existing support in
    input.  The intent is to drop this driver once IIO driver is in place.
* hmc425a
  - New driver for this attenuator.
* icp10100
  - New driver for this presure sensor.
* ltc2632
  - Add support for the ltc2636 8 channel DAC. Includes bindings and some
    tidying up of the driver.
* inv_mpu6050
  - Support IAM20680, ICM20609, ICM20689 and ICM20690.
    Includes related tidy up and rework of low pass filter bandwidth
    handling to give suitable values for all chips.

Binding conversions to yaml or missing bindings docs.
* atlas-sensor, including consolidation of previous 3 separate docs into 1.
* ad7923, previously no doc.
* max1363, split into max1238 and max1363 to simplify yaml.
* stm32-adc

Features
* (counter) 104-quad-8
  - Support a filter clock prescaler.
  - Support reporting of encoder cable status.
* ad7124
  - Low pass filter support.
  - Debugfs interface to access registers directly.
* ad8366
  - Support control of hardware gain.
* inv_mpu6050
  - Runtime pm with autosuspend.
* npcm adc
  - Add reset support. This is a breaking change if DT is not in sync,
    however this device is a BMC so the ecosystem is closed enought that
    this should not be a problem.
* srf04
  - Add power management with DT bindings for the GPIO.
* stm32-timer-trigger
  - Power management.
* (counter) stm32-timer-cnt
  - Power management.
* vcnl4000
  - Enable runtime PM for devices that don't use on demand measurement.

Cleanups and minor fixes
* core
  - Avoid double read when using debugfs.  Whilst we provide no guarantees
    on lack of side effects using the debugfs interfaces, this one is
    generate unexpected results so let us tidy it up.
* dac/Kconfig
  - Alphabetic order.
* ad5755
  - Grammar and minor other fixes.
* ad7124
  - Fail probe if get_voltage fails as no meaningful readings can be had
    without knowing the external reference.
  - Switch to selection between different channel attributes rather than
    building the arrays at runtime.
  - Remove the spi_device_id table as the driver cannot be probled without
    more information that can be provided without dt.
  - Update sysfs docs to provide more inormation and bring remaining docs for
    this part out of staging.
* ad9292
  - Use new SPI transfer delay structure.
* adis library
  - Add unlocked version of adis_initial_startup and refactor the function.
  - Add a product ID santiy check.
  - Add support for different self test registers.
  - Use new SPI delay structure.
  - Add new docs and tidy up existing.
* adis16136
  - Initialize adis_data statically.
* adis16400
  - Initialize adis_data statically.
* adis16460
  - Use core __adis_initial_Startup now it supports everything needed.
* adis16480
  - Initialize adis_data statically.
  - Use core __adis_initial_startup now it supports everything needed.
* al3320a
  - Add missing DT binding docs.
  - Tidy up code formatting.
  - Simplify error paths using devm_add_action_or_reset.
  - Ensure autoloading works by adding the of_match_table.
* atlas-sensor
  - Drop false requirement for interrupt line, the value can be polled using
    a sysfs or hrtimer type trigger.
* exynos-adc
  - Silence warning message on deferring probe.
* gp2ap002
  - Greatly simplify the Lux LUT.
  - Reorder actions around buffer setup and tear down as part of a sub-system
    wide standardization of these.
* inv_mpu6050
  - Various lttle tidyups.
  - Simpliy I2C aux MUX handling by enabling it only at startup. It never
    needs to be disabled.
  - Simplify polling rate when magnetometer enabled by putting only under
    control of userspace.
  - Always execute full reset on devices supporting spi. It does no harm
    when using i2c and makes for simpler code.
  - Reduce over the top sleep times for vddio regulator power up.
  - Greatly simplify power and engine management.
  - Fix some delays in polled reads (only visible due to other changes)
  - Stop preventing sampling rate changes whilst running as there is no
    adverse consequence of doing so.
  - Prevent attempting to read the temperature if neither accel nor
    gyro is enabled.
* lmp9100
  - Reorder actions around buffer setup and tear down as part of a sub-system
    wide standardization of these.
* max1118
  - Use new SPI transfer delay structure.
* mcp320x
  - Use new SPI transfer delay structure.
* si1133
  - Read full 24 bit signed integer instead o dropping last 8 bits of value.
    Not a critical fix as just adds precision.
* st_sensors
  - Use st_sensors_dev_name_probe instead of open coded version in st_accel
  - Handle potential memory allocation failure.
* st_lsm6dsx
  - Fix some wrong structure element naming in documentation.
  - Add missing return value check.
* stm32_timer_cnt
  - Drop some unused left over IIO headers from this count subsystem driver.
  - Ensure the clock is enabled in master mode.  Theoretical issue rather
    than one known to happen in the wild.
* tlc4541
  - Use new SPI delay structure.

* tag 'iio-5.7a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (98 commits)
  iio: dac: Kconfig: sort symbols alphabetically
  iio: light: gp2ap020a00f: fix iio_triggered_buffer_{predisable,postenable} positions
  iio: potentiostat: lmp9100: fix iio_triggered_buffer_{predisable,postenable} positions
  iio: trigger: stm32-timer: add power management support
  iio: trigger: stm32-timer: rename enabled flag
  iio: add a TODO
  counter: 104-quad-8: Support Differential Encoder Cable Status
  counter: 104-quad-8: Support Filter Clock Prescaler
  iio: pressure: icp10100: add driver for InvenSense ICP-101xx
  iio: industrialio-core: Fix debugfs read
  iio: imu: adis: add a note better explaining state_lock
  iio: imu: adis: update 'adis_data' struct doc-string
  iio: imu: adis: add doc-string for 'adis' struct
  iio: imu: adis_buffer: Use new structure for SPI transfer delays
  iio: adc: ti-tlc4541: Use new structure for SPI transfer delays
  iio: adc: mcp320x: Use new structure for SPI transfer delays
  iio: adc: max1118: Use new structure for SPI transfer delays
  iio: adc: ad9292: Use new structure for SPI transfer delays
  iio: adc: exynos: Silence warning about regulators during deferred probe
  staging: iio: update TODO
  ...
parents 09dd629e fe297f8f
What: /sys/bus/counter/devices/counterX/signalY/cable_fault
KernelVersion: 5.7
Contact: linux-iio@vger.kernel.org
Description:
Read-only attribute that indicates whether a differential
encoder cable fault (not connected or loose wires) is detected
for the respective channel of Signal Y. Valid attribute values
are boolean. Detection must first be enabled via the
corresponding cable_fault_enable attribute.
What: /sys/bus/counter/devices/counterX/signalY/cable_fault_enable
KernelVersion: 5.7
Contact: linux-iio@vger.kernel.org
Description:
Whether detection of differential encoder cable faults for the
respective channel of Signal Y is enabled. Valid attribute
values are boolean.
What: /sys/bus/counter/devices/counterX/signalY/filter_clock_prescaler
KernelVersion: 5.7
Contact: linux-iio@vger.kernel.org
Description:
Filter clock factor for input Signal Y. This prescaler value
affects the inputs of both quadrature pair signals.
What: /sys/bus/counter/devices/counterX/signalY/index_polarity What: /sys/bus/counter/devices/counterX/signalY/index_polarity
KernelVersion: 5.2 KernelVersion: 5.2
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
......
...@@ -2,17 +2,22 @@ What: /sys/bus/iio/devices/iio:deviceX/ac_excitation_en ...@@ -2,17 +2,22 @@ What: /sys/bus/iio/devices/iio:deviceX/ac_excitation_en
KernelVersion: KernelVersion:
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
Reading gives the state of AC excitation. This attribute, if available, is used to enable the AC
Writing '1' enables AC excitation. excitation mode found on some converters. In ac excitation mode,
the polarity of the excitation voltage is reversed on
alternate cycles, to eliminate DC errors.
What: /sys/bus/iio/devices/iio:deviceX/bridge_switch_en What: /sys/bus/iio/devices/iio:deviceX/bridge_switch_en
KernelVersion: KernelVersion:
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
This bridge switch is used to disconnect it when there is a This attribute, if available, is used to close or open the
need to minimize the system current consumption. bridge power down switch found on some converters.
Reading gives the state of the bridge switch. In bridge applications, such as strain gauges and load cells,
Writing '1' enables the bridge switch. the bridge itself consumes the majority of the current in the
system. To minimize the current consumption of the system,
the bridge can be disconnected (when it is not being used
using the bridge_switch_en attribute.
What: /sys/bus/iio/devices/iio:deviceX/in_voltagex_sys_calibration What: /sys/bus/iio/devices/iio:deviceX/in_voltagex_sys_calibration
KernelVersion: KernelVersion:
...@@ -21,6 +26,13 @@ Description: ...@@ -21,6 +26,13 @@ Description:
Initiates the system calibration procedure. This is done on a Initiates the system calibration procedure. This is done on a
single channel at a time. Write '1' to start the calibration. single channel at a time. Write '1' to start the calibration.
What: /sys/bus/iio/devices/iio:deviceX/in_voltage2-voltage2_shorted_raw
KernelVersion:
Contact: linux-iio@vger.kernel.org
Description:
Measure voltage from AIN2 pin connected to AIN(+)
and AIN(-) shorted.
What: /sys/bus/iio/devices/iio:deviceX/in_voltagex_sys_calibration_mode_available What: /sys/bus/iio/devices/iio:deviceX/in_voltagex_sys_calibration_mode_available
KernelVersion: KernelVersion:
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/adi,ad7923.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AD7923 and similars with 4 and 8 Channel ADCs.
maintainers:
- Michael Hennerich <michael.hennerich@analog.com>
- Patrick Vasseur <patrick.vasseur@c-s.fr>
description: |
Analog Devices AD7904, AD7914, AD7923, AD7924 4 Channel ADCs, and AD7908,
AD7918, AD7928 8 Channels ADCs.
Specifications about the part can be found at:
https://www.analog.com/media/en/technical-documentation/data-sheets/AD7923.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD7904_7914_7924.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD7908_7918_7928.pdf
properties:
compatible:
enum:
- adi,ad7904
- adi,ad7914
- adi,ad7923
- adi,ad7924
- adi,ad7908
- adi,ad7918
- adi,ad7928
reg:
maxItems: 1
refin-supply:
description: |
The regulator supply for ADC reference voltage.
'#address-cells':
const: 1
'#size-cells':
const: 0
required:
- compatible
- reg
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
ad7928: adc@0 {
compatible = "adi,ad7928";
reg = <0>;
spi-max-frequency = <25000000>;
refin-supply = <&adc_vref>;
#address-cells = <1>;
#size-cells = <0>;
};
};
* Maxim 1x3x/136x/116xx Analog to Digital Converter (ADC)
The node for this driver must be a child node of a I2C controller, hence
all mandatory properties for your controller must be specified. See directory:
Documentation/devicetree/bindings/i2c
for more details.
Required properties:
- compatible: Should be one of
"maxim,max1361"
"maxim,max1362"
"maxim,max1363"
"maxim,max1364"
"maxim,max1036"
"maxim,max1037"
"maxim,max1038"
"maxim,max1039"
"maxim,max1136"
"maxim,max1137"
"maxim,max1138"
"maxim,max1139"
"maxim,max1236"
"maxim,max1237"
"maxim,max1238"
"maxim,max1239"
"maxim,max11600"
"maxim,max11601"
"maxim,max11602"
"maxim,max11603"
"maxim,max11604"
"maxim,max11605"
"maxim,max11606"
"maxim,max11607"
"maxim,max11608"
"maxim,max11609"
"maxim,max11610"
"maxim,max11611"
"maxim,max11612"
"maxim,max11613"
"maxim,max11614"
"maxim,max11615"
"maxim,max11616"
"maxim,max11617"
"maxim,max11644"
"maxim,max11645"
"maxim,max11646"
"maxim,max11647"
- reg: Should contain the ADC I2C address
Optional properties:
- vcc-supply: phandle to the regulator that provides power to the ADC.
- vref-supply: phandle to the regulator for ADC reference voltage.
- interrupts: IRQ line for the ADC. If not used the driver will use
polling.
Example:
adc: max11644@36 {
compatible = "maxim,max11644";
reg = <0x36>;
vref-supply = <&adc_vref>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/maxim,max1238.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim MAX1238 and similar ADCs
maintainers:
- Jonathan Cameron <jic23@kernel.org>
description: |
Family of simple ADCs with i2c inteface and internal references.
properties:
compatible:
enum:
- maxim,max1036
- maxim,max1037
- maxim,max1038
- maxim,max1039
- maxim,max1136
- maxim,max1137
- maxim,max1138
- maxim,max1139
- maxim,max1236
- maxim,max1237
- maxim,max1238
- maxim,max1239
- maxim,max11600
- maxim,max11601
- maxim,max11602
- maxim,max11603
- maxim,max11604
- maxim,max11605
- maxim,max11606
- maxim,max11607
- maxim,max11608
- maxim,max11609
- maxim,max11610
- maxim,max11611
- maxim,max11612
- maxim,max11613
- maxim,max11614
- maxim,max11615
- maxim,max11616
- maxim,max11617
- maxim,max11644
- maxim,max11645
- maxim,max11646
- maxim,max11647
reg:
maxItems: 1
vcc-supply: true
vref-supply:
description: Optional external reference. If not supplied, internal
reference will be used.
required:
- compatible
- reg
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
adc@36 {
compatible = "maxim,max1238";
reg = <0x36>;
};
};
...
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/maxim,max1363.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim MAX1363 and similar ADCs
maintainers:
- Jonathan Cameron <jic23@kernel.org>
description: |
Family of ADCs with i2c inteface, internal references and threshold
monitoring.
properties:
compatible:
enum:
- maxim,max1361
- maxim,max1362
- maxim,max1363
- maxim,max1364
reg:
maxItems: 1
vcc-supply: true
vref-supply:
description: Optional external reference. If not supplied, internal
reference will be used.
interrupts:
maxItems: 1
required:
- compatible
- reg
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
adc@36 {
compatible = "maxim,max1363";
reg = <0x36>;
};
};
...
...@@ -6,6 +6,7 @@ Required properties: ...@@ -6,6 +6,7 @@ Required properties:
- compatible: "nuvoton,npcm750-adc" for the NPCM7XX BMC. - compatible: "nuvoton,npcm750-adc" for the NPCM7XX BMC.
- reg: specifies physical base address and size of the registers. - reg: specifies physical base address and size of the registers.
- interrupts: Contain the ADC interrupt with flags for falling edge. - interrupts: Contain the ADC interrupt with flags for falling edge.
- resets : phandle to the reset control for this device.
Optional properties: Optional properties:
- clocks: phandle of ADC reference clock, in case the clock is not - clocks: phandle of ADC reference clock, in case the clock is not
...@@ -21,4 +22,5 @@ adc: adc@f000c000 { ...@@ -21,4 +22,5 @@ adc: adc@f000c000 {
reg = <0xf000c000 0x8>; reg = <0xf000c000 0x8>;
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk NPCM7XX_CLK_ADC>; clocks = <&clk NPCM7XX_CLK_ADC>;
resets = <&rstc NPCM7XX_RESET_IPSRST1 NPCM7XX_RESET_ADC>;
}; };
STMicroelectronics STM32 ADC device driver
STM32 ADC is a successive approximation analog-to-digital converter.
It has several multiplexed input channels. Conversions can be performed
in single, continuous, scan or discontinuous mode. Result of the ADC is
stored in a left-aligned or right-aligned 32-bit data register.
Conversions can be launched in software or using hardware triggers.
The analog watchdog feature allows the application to detect if the input
voltage goes beyond the user-defined, higher or lower thresholds.
Each STM32 ADC block can have up to 3 ADC instances.
Each instance supports two contexts to manage conversions, each one has its
own configurable sequence and trigger:
- regular conversion can be done in sequence, running in background
- injected conversions have higher priority, and so have the ability to
interrupt regular conversion sequence (either triggered in SW or HW).
Regular sequence is resumed, in case it has been interrupted.
Contents of a stm32 adc root node:
-----------------------------------
Required properties:
- compatible: Should be one of:
"st,stm32f4-adc-core"
"st,stm32h7-adc-core"
"st,stm32mp1-adc-core"
- reg: Offset and length of the ADC block register set.
- interrupts: One or more interrupts for ADC block. Some parts like stm32f4
and stm32h7 share a common ADC interrupt line. stm32mp1 has two separate
interrupt lines, one for each ADC within ADC block.
- clocks: Core can use up to two clocks, depending on part used:
- "adc" clock: for the analog circuitry, common to all ADCs.
It's required on stm32f4.
It's optional on stm32h7.
- "bus" clock: for registers access, common to all ADCs.
It's not present on stm32f4.
It's required on stm32h7.
- clock-names: Must be "adc" and/or "bus" depending on part used.
- interrupt-controller: Identifies the controller node as interrupt-parent
- vdda-supply: Phandle to the vdda input analog voltage.
- vref-supply: Phandle to the vref input analog reference voltage.
- #interrupt-cells = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
Optional properties:
- A pinctrl state named "default" for each ADC channel may be defined to set
inX ADC pins in mode of operation for analog input on external pin.
- booster-supply: Phandle to the embedded booster regulator that can be used
to supply ADC analog input switches on stm32h7 and stm32mp1.
- vdd-supply: Phandle to the vdd input voltage. It can be used to supply ADC
analog input switches on stm32mp1.
- st,syscfg: Phandle to system configuration controller. It can be used to
control the analog circuitry on stm32mp1.
- st,max-clk-rate-hz: Allow to specify desired max clock rate used by analog
circuitry.
Contents of a stm32 adc child node:
-----------------------------------
An ADC block node should contain at least one subnode, representing an
ADC instance available on the machine.
Required properties:
- compatible: Should be one of:
"st,stm32f4-adc"
"st,stm32h7-adc"
"st,stm32mp1-adc"
- reg: Offset of ADC instance in ADC block (e.g. may be 0x0, 0x100, 0x200).
- clocks: Input clock private to this ADC instance. It's required only on
stm32f4, that has per instance clock input for registers access.
- interrupts: IRQ Line for the ADC (e.g. may be 0 for adc@0, 1 for adc@100 or
2 for adc@200).
- st,adc-channels: List of single-ended channels muxed for this ADC.
It can have up to 16 channels on stm32f4 or 20 channels on stm32h7, numbered
from 0 to 15 or 19 (resp. for in0..in15 or in0..in19).
- st,adc-diff-channels: List of differential channels muxed for this ADC.
Depending on part used, some channels can be configured as differential
instead of single-ended (e.g. stm32h7). List here positive and negative
inputs pairs as <vinp vinn>, <vinp vinn>,... vinp and vinn are numbered
from 0 to 19 on stm32h7)
Note: At least one of "st,adc-channels" or "st,adc-diff-channels" is required.
Both properties can be used together. Some channels can be used as
single-ended and some other ones as differential (mixed). But channels
can't be configured both as single-ended and differential (invalid).
- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
Documentation/devicetree/bindings/iio/iio-bindings.txt
Optional properties:
- dmas: Phandle to dma channel for this ADC instance.
See ../../dma/dma.txt for details.
- dma-names: Must be "rx" when dmas property is being used.
- assigned-resolution-bits: Resolution (bits) to use for conversions. Must
match device available resolutions:
* can be 6, 8, 10 or 12 on stm32f4
* can be 8, 10, 12, 14 or 16 on stm32h7
Default is maximum resolution if unset.
- st,min-sample-time-nsecs: Minimum sampling time in nanoseconds.
Depending on hardware (board) e.g. high/low analog input source impedance,
fine tune of ADC sampling time may be recommended.
This can be either one value or an array that matches 'st,adc-channels' list,
to set sample time resp. for all channels, or independently for each channel.
Example:
adc: adc@40012000 {
compatible = "st,stm32f4-adc-core";
reg = <0x40012000 0x400>;
interrupts = <18>;
clocks = <&rcc 0 168>;
clock-names = "adc";
vref-supply = <&reg_vref>;
interrupt-controller;
pinctrl-names = "default";
pinctrl-0 = <&adc3_in8_pin>;
#interrupt-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "st,stm32f4-adc";
#io-channel-cells = <1>;
reg = <0x0>;
clocks = <&rcc 0 168>;
interrupt-parent = <&adc>;
interrupts = <0>;
st,adc-channels = <8>;
dmas = <&dma2 0 0 0x400 0x0>;
dma-names = "rx";
assigned-resolution-bits = <8>;
};
...
other adc child nodes follow...
};
Example to setup:
- channel 1 as single-ended
- channels 2 & 3 as differential (with resp. 6 & 7 negative inputs)
adc: adc@40022000 {
compatible = "st,stm32h7-adc-core";
...
adc1: adc@0 {
compatible = "st,stm32h7-adc";
...
st,adc-channels = <1>;
st,adc-diff-channels = <2 6>, <3 7>;
};
};
This diff is collapsed.
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/amplifiers/adi,hmc425a.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: HMC425A 6-bit Digital Step Attenuator
maintainers:
- Michael Hennerich <michael.hennerich@analog.com>
- Beniamin Bia <beniamin.bia@analog.com>
description: |
Digital Step Attenuator IIO device with gpio interface.
HMC425A 0.5 dB LSB GaAs MMIC 6-BIT DIGITAL POSITIVE CONTROL ATTENUATOR, 2.2 - 8.0 GHz
https://www.analog.com/media/en/technical-documentation/data-sheets/hmc425A.pdf
properties:
compatible:
enum:
- adi,hmc425a
vcc-supply: true
ctrl-gpios:
description:
Must contain an array of 6 GPIO specifiers, referring to the GPIO pins
connected to the control pins V1-V6.
minItems: 6
maxItems: 6
required:
- compatible
- ctrl-gpios
examples:
- |
#include <dt-bindings/gpio/gpio.h>
gpio_hmc425a: hmc425a {
compatible = "adi,hmc425a";
ctrl-gpios = <&gpio 40 GPIO_ACTIVE_HIGH>,
<&gpio 39 GPIO_ACTIVE_HIGH>,
<&gpio 38 GPIO_ACTIVE_HIGH>,
<&gpio 37 GPIO_ACTIVE_HIGH>,
<&gpio 36 GPIO_ACTIVE_HIGH>,
<&gpio 35 GPIO_ACTIVE_HIGH>;
vcc-supply = <&foo>;
};
...
* Atlas Scientific EC-SM OEM sensor
http://www.atlas-scientific.com/_files/_datasheets/_oem/EC_oem_datasheet.pdf
Required properties:
- compatible: must be "atlas,ec-sm"
- reg: the I2C address of the sensor
- interrupts: the sole interrupt generated by the device
Refer to interrupt-controller/interrupts.txt for generic interrupt client
node bindings.
Example:
atlas@64 {
compatible = "atlas,ec-sm";
reg = <0x64>;
interrupt-parent = <&gpio1>;
interrupts = <16 2>;
};
* Atlas Scientific ORP-SM OEM sensor
https://www.atlas-scientific.com/_files/_datasheets/_oem/ORP_oem_datasheet.pdf
Required properties:
- compatible: must be "atlas,orp-sm"
- reg: the I2C address of the sensor
- interrupts: the sole interrupt generated by the device
Refer to interrupt-controller/interrupts.txt for generic interrupt client
node bindings.
Example:
atlas@66 {
compatible = "atlas,orp-sm";
reg = <0x66>;
interrupt-parent = <&gpio1>;
interrupts = <16 2>;
};
* Atlas Scientific pH-SM OEM sensor
http://www.atlas-scientific.com/_files/_datasheets/_oem/pH_oem_datasheet.pdf
Required properties:
- compatible: must be "atlas,ph-sm"
- reg: the I2C address of the sensor
- interrupts: the sole interrupt generated by the device
Refer to interrupt-controller/interrupts.txt for generic interrupt client
node bindings.
Example:
atlas@65 {
compatible = "atlas,ph-sm";
reg = <0x65>;
interrupt-parent = <&gpio1>;
interrupts = <16 2>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/chemical/atlas,sensor.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Atlas Scientific OEM sensors
maintainers:
- Matt Ranostay <matt.ranostay@konsulko.com>
description: |
Atlas Scientific OEM sensors connected via I2C
Datasheets:
http://www.atlas-scientific.com/_files/_datasheets/_oem/DO_oem_datasheet.pdf
http://www.atlas-scientific.com/_files/_datasheets/_oem/EC_oem_datasheet.pdf
http://www.atlas-scientific.com/_files/_datasheets/_oem/ORP_oem_datasheet.pdf
http://www.atlas-scientific.com/_files/_datasheets/_oem/pH_oem_datasheet.pdf
properties:
compatible:
enum:
- atlas,do-sm
- atlas,ec-sm
- atlas,orp-sm
- atlas,ph-sm
reg:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
atlas@66 {
compatible = "atlas,orp-sm";
reg = <0x66>;
interrupt-parent = <&gpio1>;
interrupts = <16 2>;
};
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2020 Analog Devices Inc.
%YAML 1.2
---
$id: http://devicetree.org/schemas/bindings/iio/dac/adi,ad5770r.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AD5770R DAC device driver
maintainers:
- Mircea Caprioru <mircea.caprioru@analog.com>
description: |
Bindings for the Analog Devices AD5770R current DAC device. Datasheet can be
found here:
https://www.analog.com/media/en/technical-documentation/data-sheets/AD5770R.pdf
properties:
compatible:
enum:
- adi,ad5770r
reg:
maxItems: 1
avdd-supply:
description:
AVdd voltage supply. Represents two different supplies in the datasheet
that are in fact the same.
iovdd-supply:
description:
Voltage supply for the chip interface.
vref-supply:
description: Specify the voltage of the external reference used.
Available reference options are 1.25 V or 2.5 V. If no
external reference declared then the device will use the
internal reference of 1.25 V.
adi,external-resistor:
description: Specify if an external 2.5k ohm resistor is used. If not
specified the device will use an internal 2.5k ohm resistor.
The precision resistor is used for reference current generation.
type: boolean
reset-gpios:
description: GPIO spec for the RESET pin. If specified, it will be
asserted during driver probe.
maxItems: 1
channel0:
description: Represents an external channel which are
connected to the DAC. Channel 0 can act both as a current
source and sink.
type: object
properties:
num:
description: This represents the channel number.
items:
const: 0
adi,range-microamp:
description: Output range of the channel.
oneOf:
- $ref: /schemas/types.yaml#/definitions/int32-array
- items:
- enum: [0 300000]
- enum: [-60000 0]
- enum: [-60000 300000]
channel1:
description: Represents an external channel which are
connected to the DAC.
type: object
properties:
num:
description: This represents the channel number.
items:
const: 1
adi,range-microamp:
description: Output range of the channel.
oneOf:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- items:
- enum: [0 140000]
- enum: [0 250000]
channel2:
description: Represents an external channel which are
connected to the DAC.
type: object
properties:
num:
description: This represents the channel number.
items:
const: 2
adi,range-microamp:
description: Output range of the channel.
oneOf:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- items:
- enum: [0 140000]
- enum: [0 250000]
patternProperties:
"^channel@([3-5])$":
type: object
description: Represents the external channels which are connected to the DAC.
properties:
num:
description: This represents the channel number.
items:
minimum: 3
maximum: 5
adi,range-microamp:
description: Output range of the channel.
oneOf:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- items:
- enum: [0 45000]
- enum: [0 100000]
required:
- reg
- diff-channels
- channel0
- channel1
- channel2
- channel3
- channel4
- channel5
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
ad5770r@0 {
compatible = "ad5770r";
reg = <0>;
spi-max-frequency = <1000000>;
vref-supply = <&vref>;
adi,external-resistor;
reset-gpios = <&gpio 22 0>;
channel@0 {
num = <0>;
adi,range-microamp = <(-60000) 300000>;
};
channel@1 {
num = <1>;
adi,range-microamp = <0 140000>;
};
channel@2 {
num = <2>;
adi,range-microamp = <0 55000>;
};
channel@3 {
num = <3>;
adi,range-microamp = <0 45000>;
};
channel@4 {
num = <4>;
adi,range-microamp = <0 45000>;
};
channel@5 {
num = <5>;
adi,range-microamp = <0 45000>;
};
};
};
...
Linear Technology LTC2632 DAC device driver Linear Technology LTC2632/2636 DAC
Required properties: Required properties:
- compatible: Has to contain one of the following: - compatible: Has to contain one of the following:
...@@ -8,6 +8,12 @@ Required properties: ...@@ -8,6 +8,12 @@ Required properties:
lltc,ltc2632-h12 lltc,ltc2632-h12
lltc,ltc2632-h10 lltc,ltc2632-h10
lltc,ltc2632-h8 lltc,ltc2632-h8
lltc,ltc2636-l12
lltc,ltc2636-l10
lltc,ltc2636-l8
lltc,ltc2636-h12
lltc,ltc2636-h10
lltc,ltc2636-h8
Property rules described in Documentation/devicetree/bindings/spi/spi-bus.txt Property rules described in Documentation/devicetree/bindings/spi/spi-bus.txt
apply. In particular, "reg" and "spi-max-frequency" properties must be given. apply. In particular, "reg" and "spi-max-frequency" properties must be given.
......
...@@ -4,6 +4,7 @@ http://www.invensense.com/mems/gyro/mpu6050.html ...@@ -4,6 +4,7 @@ http://www.invensense.com/mems/gyro/mpu6050.html
Required properties: Required properties:
- compatible : should be one of - compatible : should be one of
"invensense,mpu6000"
"invensense,mpu6050" "invensense,mpu6050"
"invensense,mpu6500" "invensense,mpu6500"
"invensense,mpu6515" "invensense,mpu6515"
...@@ -11,7 +12,11 @@ Required properties: ...@@ -11,7 +12,11 @@ Required properties:
"invensense,mpu9250" "invensense,mpu9250"
"invensense,mpu9255" "invensense,mpu9255"
"invensense,icm20608" "invensense,icm20608"
"invensense,icm20609"
"invensense,icm20689"
"invensense,icm20602" "invensense,icm20602"
"invensense,icm20690"
"invensense,iam20680"
- reg : the I2C address of the sensor - reg : the I2C address of the sensor
- interrupts: interrupt mapping for IRQ. It should be configured with flags - interrupts: interrupt mapping for IRQ. It should be configured with flags
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_LEVEL_LOW or
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/light/dynaimage,al3010.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Dyna-Image AL3010 sensor
maintainers:
- David Heidelberg <david@ixit.cz>
properties:
compatible:
const: dynaimage,al3010
reg:
maxItems: 1
interrupts:
maxItems: 1
vdd-supply:
description: Regulator that provides power to the sensor
required:
- compatible
- reg
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
light-sensor@1c {
compatible = "dynaimage,al3010";
reg = <0x1c>;
vdd-supply = <&vdd_reg>;
interrupts = <0 99 4>;
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/light/dynaimage,al3320a.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Dyna-Image AL3320A sensor
maintainers:
- David Heidelberg <david@ixit.cz>
properties:
compatible:
const: dynaimage,al3320a
reg:
maxItems: 1
interrupts:
maxItems: 1
vdd-supply:
description: Regulator that provides power to the sensor
required:
- compatible
- reg
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
light-sensor@1c {
compatible = "dynaimage,al3320a";
reg = <0x1c>;
vdd-supply = <&vdd_reg>;
interrupts = <0 99 4>;
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/light/sharp,gp2ap002.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sharp GP2AP002A00F and GP2AP002S00F proximity and ambient light sensors
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
description: |
Proximity and ambient light sensor with IR LED for the proximity
sensing and an analog output for light intensity. The ambient light
sensor output is not available on the GP2AP002S00F variant.
properties:
compatible:
enum:
- sharp,gp2ap002a00f
- sharp,gp2ap002s00f
reg:
maxItems: 1
interrupts:
maxItems: 1
description: an interrupt for proximity, usually a GPIO line
vdd-supply:
description: VDD power supply a phandle to a regulator
vio-supply:
description: VIO power supply a phandle to a regulator
io-channels:
maxItems: 1
description: ALSOUT ADC channel to read the ambient light
io-channel-names:
const: alsout
sharp,proximity-far-hysteresis:
$ref: /schemas/types.yaml#/definitions/uint8
description: |
Hysteresis setting for "far" object detection, this setting is
device-unique and adjust the optical setting for proximity detection
of a "far away" object in front of the sensor.
sharp,proximity-close-hysteresis:
$ref: /schemas/types.yaml#/definitions/uint8
description: |
Hysteresis setting for "close" object detection, this setting is
device-unique and adjust the optical setting for proximity detection
of a "close" object in front of the sensor.
required:
- compatible
- reg
- interrupts
- sharp,proximity-far-hysteresis
- sharp,proximity-close-hysteresis
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
light-sensor@44 {
compatible = "sharp,gp2ap002a00f";
reg = <0x44>;
interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
vdd-supply = <&vdd_regulator>;
vio-supply = <&vio_regulator>;
io-channels = <&adc_channel>;
io-channel-names = "alsout";
sharp,proximity-far-hysteresis = /bits/ 8 <0x2f>;
sharp,proximity-close-hysteresis = /bits/ 8 <0x0f>;
};
};
...
...@@ -51,6 +51,24 @@ properties: ...@@ -51,6 +51,24 @@ properties:
the time between two interrupts is measured in the driver. the time between two interrupts is measured in the driver.
maxItems: 1 maxItems: 1
power-gpios:
description:
Definition of the GPIO for power management of connected peripheral
(output).
This GPIO can be used by the external hardware for power management.
When the device gets suspended it's switched off and when it resumes
it's switched on again. After some period of inactivity the driver
get suspended automatically (autosuspend feature).
maxItems: 1
startup-time-ms:
description:
This is the startup time the device needs after a resume to be up and
running.
minimum: 0
maximum: 1000
default: 100
required: required:
- compatible - compatible
- trig-gpios - trig-gpios
......
...@@ -267,6 +267,8 @@ patternProperties: ...@@ -267,6 +267,8 @@ patternProperties:
description: Dragino Technology Co., Limited description: Dragino Technology Co., Limited
"^dserve,.*": "^dserve,.*":
description: dServe Technology B.V. description: dServe Technology B.V.
"^dynaimage,.*":
description: Dyna-Image
"^ea,.*": "^ea,.*":
description: Embedded Artists AB description: Embedded Artists AB
"^ebs-systart,.*": "^ebs-systart,.*":
......
...@@ -931,6 +931,14 @@ S: Supported ...@@ -931,6 +931,14 @@ S: Supported
F: drivers/iio/adc/ad7124.c F: drivers/iio/adc/ad7124.c
F: Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml F: Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml
ANALOG DEVICES INC AD7192 DRIVER
M: Alexandru Tachici <alexandru.tachici@analog.com>
L: linux-iio@vger.kernel.org
W: http://ez.analog.com/community/linux-device-drivers
S: Supported
F: drivers/iio/adc/ad7192.c
F: Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml
ANALOG DEVICES INC AD7292 DRIVER ANALOG DEVICES INC AD7292 DRIVER
M: Marcelo Schmitt <marcelo.schmitt1@gmail.com> M: Marcelo Schmitt <marcelo.schmitt1@gmail.com>
L: linux-iio@vger.kernel.org L: linux-iio@vger.kernel.org
...@@ -1081,6 +1089,15 @@ F: drivers/iio/adc/ltc249* ...@@ -1081,6 +1089,15 @@ F: drivers/iio/adc/ltc249*
X: drivers/iio/*/adjd* X: drivers/iio/*/adjd*
F: drivers/staging/iio/*/ad* F: drivers/staging/iio/*/ad*
ANALOG DEVICES INC HMC425A DRIVER
M: Beniamin Bia <beniamin.bia@analog.com>
M: Michael Hennerich <michael.hennerich@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
W: http://ez.analog.com/community/linux-device-drivers
F: Documentation/devicetree/bindings/iio/amplifiers/adi,hmc425a.yaml
F: drivers/iio/amplifiers/hmc425a.c
ANALOGBITS PLL LIBRARIES ANALOGBITS PLL LIBRARIES
M: Paul Walmsley <paul.walmsley@sifive.com> M: Paul Walmsley <paul.walmsley@sifive.com>
S: Supported S: Supported
...@@ -15055,6 +15072,14 @@ W: http://www.ibm.com/developerworks/linux/linux390/ ...@@ -15055,6 +15072,14 @@ W: http://www.ibm.com/developerworks/linux/linux390/
S: Supported S: Supported
F: net/smc/ F: net/smc/
SHARP GP2AP002A00F/GP2AP002S00F SENSOR DRIVER
M: Linus Walleij <linus.walleij@linaro.org>
L: linux-iio@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
S: Maintained
F: drivers/iio/light/gp2ap002.c
F: Documentation/devicetree/bindings/iio/light/sharp,gp2ap002.yaml
SHARP RJ54N1CB0C SENSOR DRIVER SHARP RJ54N1CB0C SENSOR DRIVER
M: Jacopo Mondi <jacopo@jmondi.org> M: Jacopo Mondi <jacopo@jmondi.org>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
......
...@@ -31,6 +31,7 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses"); ...@@ -31,6 +31,7 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
/** /**
* struct quad8_iio - IIO device private data structure * struct quad8_iio - IIO device private data structure
* @counter: instance of the counter_device * @counter: instance of the counter_device
* @fck_prescaler: array of filter clock prescaler configurations
* @preset: array of preset values * @preset: array of preset values
* @count_mode: array of count mode configurations * @count_mode: array of count mode configurations
* @quadrature_mode: array of quadrature mode configurations * @quadrature_mode: array of quadrature mode configurations
...@@ -39,10 +40,12 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses"); ...@@ -39,10 +40,12 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
* @preset_enable: array of set_to_preset_on_index attribute configurations * @preset_enable: array of set_to_preset_on_index attribute configurations
* @synchronous_mode: array of index function synchronous mode configurations * @synchronous_mode: array of index function synchronous mode configurations
* @index_polarity: array of index function polarity configurations * @index_polarity: array of index function polarity configurations
* @cable_fault_enable: differential encoder cable status enable configurations
* @base: base port address of the IIO device * @base: base port address of the IIO device
*/ */
struct quad8_iio { struct quad8_iio {
struct counter_device counter; struct counter_device counter;
unsigned int fck_prescaler[QUAD8_NUM_COUNTERS];
unsigned int preset[QUAD8_NUM_COUNTERS]; unsigned int preset[QUAD8_NUM_COUNTERS];
unsigned int count_mode[QUAD8_NUM_COUNTERS]; unsigned int count_mode[QUAD8_NUM_COUNTERS];
unsigned int quadrature_mode[QUAD8_NUM_COUNTERS]; unsigned int quadrature_mode[QUAD8_NUM_COUNTERS];
...@@ -51,11 +54,13 @@ struct quad8_iio { ...@@ -51,11 +54,13 @@ struct quad8_iio {
unsigned int preset_enable[QUAD8_NUM_COUNTERS]; unsigned int preset_enable[QUAD8_NUM_COUNTERS];
unsigned int synchronous_mode[QUAD8_NUM_COUNTERS]; unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
unsigned int index_polarity[QUAD8_NUM_COUNTERS]; unsigned int index_polarity[QUAD8_NUM_COUNTERS];
unsigned int cable_fault_enable;
unsigned int base; unsigned int base;
}; };
#define QUAD8_REG_CHAN_OP 0x11 #define QUAD8_REG_CHAN_OP 0x11
#define QUAD8_REG_INDEX_INPUT_LEVELS 0x16 #define QUAD8_REG_INDEX_INPUT_LEVELS 0x16
#define QUAD8_DIFF_ENCODER_CABLE_STATUS 0x17
/* Borrow Toggle flip-flop */ /* Borrow Toggle flip-flop */
#define QUAD8_FLAG_BT BIT(0) #define QUAD8_FLAG_BT BIT(0)
/* Carry Toggle flip-flop */ /* Carry Toggle flip-flop */
...@@ -84,6 +89,8 @@ struct quad8_iio { ...@@ -84,6 +89,8 @@ struct quad8_iio {
#define QUAD8_RLD_PRESET_CNTR 0x08 #define QUAD8_RLD_PRESET_CNTR 0x08
/* Transfer Counter to Output Latch */ /* Transfer Counter to Output Latch */
#define QUAD8_RLD_CNTR_OUT 0x10 #define QUAD8_RLD_CNTR_OUT 0x10
/* Transfer Preset Register LSB to FCK Prescaler */
#define QUAD8_RLD_PRESET_PSC 0x18
#define QUAD8_CHAN_OP_ENABLE_COUNTERS 0x00 #define QUAD8_CHAN_OP_ENABLE_COUNTERS 0x00
#define QUAD8_CHAN_OP_RESET_COUNTERS 0x01 #define QUAD8_CHAN_OP_RESET_COUNTERS 0x01
#define QUAD8_CMR_QUADRATURE_X1 0x08 #define QUAD8_CMR_QUADRATURE_X1 0x08
...@@ -1140,6 +1147,119 @@ static ssize_t quad8_count_preset_enable_write(struct counter_device *counter, ...@@ -1140,6 +1147,119 @@ static ssize_t quad8_count_preset_enable_write(struct counter_device *counter,
return len; return len;
} }
static ssize_t quad8_signal_cable_fault_read(struct counter_device *counter,
struct counter_signal *signal,
void *private, char *buf)
{
const struct quad8_iio *const priv = counter->priv;
const size_t channel_id = signal->id / 2;
const bool disabled = !(priv->cable_fault_enable & BIT(channel_id));
unsigned int status;
unsigned int fault;
if (disabled)
return -EINVAL;
/* Logic 0 = cable fault */
status = inb(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
/* Mask respective channel and invert logic */
fault = !(status & BIT(channel_id));
return sprintf(buf, "%u\n", fault);
}
static ssize_t quad8_signal_cable_fault_enable_read(
struct counter_device *counter, struct counter_signal *signal,
void *private, char *buf)
{
const struct quad8_iio *const priv = counter->priv;
const size_t channel_id = signal->id / 2;
const unsigned int enb = !!(priv->cable_fault_enable & BIT(channel_id));
return sprintf(buf, "%u\n", enb);
}
static ssize_t quad8_signal_cable_fault_enable_write(
struct counter_device *counter, struct counter_signal *signal,
void *private, const char *buf, size_t len)
{
struct quad8_iio *const priv = counter->priv;
const size_t channel_id = signal->id / 2;
bool enable;
int ret;
unsigned int cable_fault_enable;
ret = kstrtobool(buf, &enable);
if (ret)
return ret;
if (enable)
priv->cable_fault_enable |= BIT(channel_id);
else
priv->cable_fault_enable &= ~BIT(channel_id);
/* Enable is active low in Differential Encoder Cable Status register */
cable_fault_enable = ~priv->cable_fault_enable;
outb(cable_fault_enable, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
return len;
}
static ssize_t quad8_signal_fck_prescaler_read(struct counter_device *counter,
struct counter_signal *signal, void *private, char *buf)
{
const struct quad8_iio *const priv = counter->priv;
const size_t channel_id = signal->id / 2;
return sprintf(buf, "%u\n", priv->fck_prescaler[channel_id]);
}
static ssize_t quad8_signal_fck_prescaler_write(struct counter_device *counter,
struct counter_signal *signal, void *private, const char *buf,
size_t len)
{
struct quad8_iio *const priv = counter->priv;
const size_t channel_id = signal->id / 2;
const int base_offset = priv->base + 2 * channel_id;
u8 prescaler;
int ret;
ret = kstrtou8(buf, 0, &prescaler);
if (ret)
return ret;
priv->fck_prescaler[channel_id] = prescaler;
/* Reset Byte Pointer */
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
/* Set filter clock factor */
outb(prescaler, base_offset);
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
base_offset + 1);
return len;
}
static const struct counter_signal_ext quad8_signal_ext[] = {
{
.name = "cable_fault",
.read = quad8_signal_cable_fault_read
},
{
.name = "cable_fault_enable",
.read = quad8_signal_cable_fault_enable_read,
.write = quad8_signal_cable_fault_enable_write
},
{
.name = "filter_clock_prescaler",
.read = quad8_signal_fck_prescaler_read,
.write = quad8_signal_fck_prescaler_write
}
};
static const struct counter_signal_ext quad8_index_ext[] = { static const struct counter_signal_ext quad8_index_ext[] = {
COUNTER_SIGNAL_ENUM("index_polarity", &quad8_index_pol_enum), COUNTER_SIGNAL_ENUM("index_polarity", &quad8_index_pol_enum),
COUNTER_SIGNAL_ENUM_AVAILABLE("index_polarity", &quad8_index_pol_enum), COUNTER_SIGNAL_ENUM_AVAILABLE("index_polarity", &quad8_index_pol_enum),
...@@ -1147,9 +1267,11 @@ static const struct counter_signal_ext quad8_index_ext[] = { ...@@ -1147,9 +1267,11 @@ static const struct counter_signal_ext quad8_index_ext[] = {
COUNTER_SIGNAL_ENUM_AVAILABLE("synchronous_mode", &quad8_syn_mode_enum) COUNTER_SIGNAL_ENUM_AVAILABLE("synchronous_mode", &quad8_syn_mode_enum)
}; };
#define QUAD8_QUAD_SIGNAL(_id, _name) { \ #define QUAD8_QUAD_SIGNAL(_id, _name) { \
.id = (_id), \ .id = (_id), \
.name = (_name) \ .name = (_name), \
.ext = quad8_signal_ext, \
.num_ext = ARRAY_SIZE(quad8_signal_ext) \
} }
#define QUAD8_INDEX_SIGNAL(_id, _name) { \ #define QUAD8_INDEX_SIGNAL(_id, _name) { \
...@@ -1314,6 +1436,12 @@ static int quad8_probe(struct device *dev, unsigned int id) ...@@ -1314,6 +1436,12 @@ static int quad8_probe(struct device *dev, unsigned int id)
base_offset = base[id] + 2 * i; base_offset = base[id] + 2 * i;
/* Reset Byte Pointer */ /* Reset Byte Pointer */
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
/* Reset filter clock factor */
outb(0, base_offset);
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
base_offset + 1);
/* Reset Byte Pointer */
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
/* Reset Preset Register */ /* Reset Preset Register */
for (j = 0; j < 3; j++) for (j = 0; j < 3; j++)
outb(0x00, base_offset); outb(0x00, base_offset);
...@@ -1328,6 +1456,8 @@ static int quad8_probe(struct device *dev, unsigned int id) ...@@ -1328,6 +1456,8 @@ static int quad8_probe(struct device *dev, unsigned int id)
/* Disable index function; negative index polarity */ /* Disable index function; negative index polarity */
outb(QUAD8_CTR_IDR, base_offset + 1); outb(QUAD8_CTR_IDR, base_offset + 1);
} }
/* Disable Differential Encoder Cable Status for all channels */
outb(0xFF, base[id] + QUAD8_DIFF_ENCODER_CABLE_STATUS);
/* Enable all counters */ /* Enable all counters */
outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
......
...@@ -8,10 +8,10 @@ ...@@ -8,10 +8,10 @@
* *
*/ */
#include <linux/counter.h> #include <linux/counter.h>
#include <linux/iio/iio.h>
#include <linux/iio/types.h>
#include <linux/mfd/stm32-timers.h> #include <linux/mfd/stm32-timers.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#define TIM_CCMR_CCXS (BIT(8) | BIT(0)) #define TIM_CCMR_CCXS (BIT(8) | BIT(0))
...@@ -20,11 +20,20 @@ ...@@ -20,11 +20,20 @@
#define TIM_CCER_MASK (TIM_CCER_CC1P | TIM_CCER_CC1NP | \ #define TIM_CCER_MASK (TIM_CCER_CC1P | TIM_CCER_CC1NP | \
TIM_CCER_CC2P | TIM_CCER_CC2NP) TIM_CCER_CC2P | TIM_CCER_CC2NP)
struct stm32_timer_regs {
u32 cr1;
u32 cnt;
u32 smcr;
u32 arr;
};
struct stm32_timer_cnt { struct stm32_timer_cnt {
struct counter_device counter; struct counter_device counter;
struct regmap *regmap; struct regmap *regmap;
struct clk *clk; struct clk *clk;
u32 ceiling; u32 ceiling;
bool enabled;
struct stm32_timer_regs bak;
}; };
/** /**
...@@ -224,6 +233,9 @@ static ssize_t stm32_count_enable_write(struct counter_device *counter, ...@@ -224,6 +233,9 @@ static ssize_t stm32_count_enable_write(struct counter_device *counter,
clk_disable(priv->clk); clk_disable(priv->clk);
} }
/* Keep enabled state to properly handle low power states */
priv->enabled = enable;
return len; return len;
} }
...@@ -358,10 +370,59 @@ static int stm32_timer_cnt_probe(struct platform_device *pdev) ...@@ -358,10 +370,59 @@ static int stm32_timer_cnt_probe(struct platform_device *pdev)
priv->counter.num_signals = ARRAY_SIZE(stm32_signals); priv->counter.num_signals = ARRAY_SIZE(stm32_signals);
priv->counter.priv = priv; priv->counter.priv = priv;
platform_set_drvdata(pdev, priv);
/* Register Counter device */ /* Register Counter device */
return devm_counter_register(dev, &priv->counter); return devm_counter_register(dev, &priv->counter);
} }
static int __maybe_unused stm32_timer_cnt_suspend(struct device *dev)
{
struct stm32_timer_cnt *priv = dev_get_drvdata(dev);
/* Only take care of enabled counter: don't disturb other MFD child */
if (priv->enabled) {
/* Backup registers that may get lost in low power mode */
regmap_read(priv->regmap, TIM_SMCR, &priv->bak.smcr);
regmap_read(priv->regmap, TIM_ARR, &priv->bak.arr);
regmap_read(priv->regmap, TIM_CNT, &priv->bak.cnt);
regmap_read(priv->regmap, TIM_CR1, &priv->bak.cr1);
/* Disable the counter */
regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
clk_disable(priv->clk);
}
return pinctrl_pm_select_sleep_state(dev);
}
static int __maybe_unused stm32_timer_cnt_resume(struct device *dev)
{
struct stm32_timer_cnt *priv = dev_get_drvdata(dev);
int ret;
ret = pinctrl_pm_select_default_state(dev);
if (ret)
return ret;
if (priv->enabled) {
clk_enable(priv->clk);
/* Restore registers that may have been lost */
regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr);
regmap_write(priv->regmap, TIM_ARR, priv->bak.arr);
regmap_write(priv->regmap, TIM_CNT, priv->bak.cnt);
/* Also re-enables the counter */
regmap_write(priv->regmap, TIM_CR1, priv->bak.cr1);
}
return 0;
}
static SIMPLE_DEV_PM_OPS(stm32_timer_cnt_pm_ops, stm32_timer_cnt_suspend,
stm32_timer_cnt_resume);
static const struct of_device_id stm32_timer_cnt_of_match[] = { static const struct of_device_id stm32_timer_cnt_of_match[] = {
{ .compatible = "st,stm32-timer-counter", }, { .compatible = "st,stm32-timer-counter", },
{}, {},
...@@ -373,6 +434,7 @@ static struct platform_driver stm32_timer_cnt_driver = { ...@@ -373,6 +434,7 @@ static struct platform_driver stm32_timer_cnt_driver = {
.driver = { .driver = {
.name = "stm32-timer-counter", .name = "stm32-timer-counter",
.of_match_table = stm32_timer_cnt_of_match, .of_match_table = stm32_timer_cnt_of_match,
.pm = &stm32_timer_cnt_pm_ops,
}, },
}; };
module_platform_driver(stm32_timer_cnt_driver); module_platform_driver(stm32_timer_cnt_driver);
......
2020-02-29
Documentation
- Binding docs for devices that are obviously used via device
tree
- Yaml conversions for abandoned drivers
- ABI Documentation
- Audit driviers/iio/staging/Documentation
- Replace iio_dev->mlock by either a local lock or use
iio_claim_direct.(Requires analysis of the purpose of the lock.)
- Converting drivers from device tree centric to more generic
property handlers.
- Refactor old platform_data constructs from drivers and convert it
to state struct and using property handlers and readers.
Mailing list: linux-iio@vger.kernel.org
...@@ -246,6 +246,7 @@ static const struct adis_data adis16201_data = { ...@@ -246,6 +246,7 @@ static const struct adis_data adis16201_data = {
.diag_stat_reg = ADIS16201_DIAG_STAT_REG, .diag_stat_reg = ADIS16201_DIAG_STAT_REG,
.self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN, .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN,
.self_test_reg = ADIS16201_MSC_CTRL_REG,
.self_test_no_autoclear = true, .self_test_no_autoclear = true,
.timeouts = &adis16201_timeouts, .timeouts = &adis16201_timeouts,
......
...@@ -256,6 +256,7 @@ static const struct adis_data adis16209_data = { ...@@ -256,6 +256,7 @@ static const struct adis_data adis16209_data = {
.diag_stat_reg = ADIS16209_STAT_REG, .diag_stat_reg = ADIS16209_STAT_REG,
.self_test_mask = ADIS16209_MSC_CTRL_SELF_TEST_EN, .self_test_mask = ADIS16209_MSC_CTRL_SELF_TEST_EN,
.self_test_reg = ADIS16209_MSC_CTRL_REG,
.self_test_no_autoclear = true, .self_test_no_autoclear = true,
.timeouts = &adis16209_timeouts, .timeouts = &adis16209_timeouts,
......
...@@ -147,12 +147,9 @@ static int st_accel_i2c_probe(struct i2c_client *client) ...@@ -147,12 +147,9 @@ static int st_accel_i2c_probe(struct i2c_client *client)
const struct st_sensor_settings *settings; const struct st_sensor_settings *settings;
struct st_sensor_data *adata; struct st_sensor_data *adata;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
const char *match;
int ret; int ret;
match = device_get_match_data(&client->dev); st_sensors_dev_name_probe(&client->dev, client->name, sizeof(client->name));
if (match)
strlcpy(client->name, match, sizeof(client->name));
settings = st_accel_get_settings(client->name); settings = st_accel_get_settings(client->name);
if (!settings) { if (!settings) {
......
...@@ -39,6 +39,18 @@ config AD7124 ...@@ -39,6 +39,18 @@ config AD7124
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called ad7124. called ad7124.
config AD7192
tristate "Analog Devices AD7190 AD7192 AD7193 AD7195 ADC driver"
depends on SPI
select AD_SIGMA_DELTA
help
Say yes here to build support for Analog Devices AD7190,
AD7192, AD7193 or AD7195 SPI analog to digital converters (ADC).
If unsure, say N (but it's safe to say "Y").
To compile this driver as a module, choose M here: the
module will be called ad7192.
config AD7266 config AD7266
tristate "Analog Devices AD7265/AD7266 ADC driver" tristate "Analog Devices AD7265/AD7266 ADC driver"
depends on SPI_MASTER depends on SPI_MASTER
......
...@@ -8,6 +8,7 @@ obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o ...@@ -8,6 +8,7 @@ obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
obj-$(CONFIG_AD7091R5) += ad7091r5.o ad7091r-base.o obj-$(CONFIG_AD7091R5) += ad7091r5.o ad7091r-base.o
obj-$(CONFIG_AD7124) += ad7124.o obj-$(CONFIG_AD7124) += ad7124.o
obj-$(CONFIG_AD7192) += ad7192.o
obj-$(CONFIG_AD7266) += ad7266.o obj-$(CONFIG_AD7266) += ad7266.o
obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7291) += ad7291.o
obj-$(CONFIG_AD7292) += ad7292.o obj-$(CONFIG_AD7292) += ad7292.o
......
...@@ -70,6 +70,11 @@ ...@@ -70,6 +70,11 @@
/* AD7124_FILTER_X */ /* AD7124_FILTER_X */
#define AD7124_FILTER_FS_MSK GENMASK(10, 0) #define AD7124_FILTER_FS_MSK GENMASK(10, 0)
#define AD7124_FILTER_FS(x) FIELD_PREP(AD7124_FILTER_FS_MSK, x) #define AD7124_FILTER_FS(x) FIELD_PREP(AD7124_FILTER_FS_MSK, x)
#define AD7124_FILTER_TYPE_MSK GENMASK(23, 21)
#define AD7124_FILTER_TYPE_SEL(x) FIELD_PREP(AD7124_FILTER_TYPE_MSK, x)
#define AD7124_SINC3_FILTER 2
#define AD7124_SINC4_FILTER 0
enum ad7124_ids { enum ad7124_ids {
ID_AD7124_4, ID_AD7124_4,
...@@ -93,6 +98,14 @@ static const unsigned int ad7124_gain[8] = { ...@@ -93,6 +98,14 @@ static const unsigned int ad7124_gain[8] = {
1, 2, 4, 8, 16, 32, 64, 128 1, 2, 4, 8, 16, 32, 64, 128
}; };
static const unsigned int ad7124_reg_size[] = {
1, 2, 3, 3, 2, 1, 3, 3, 1, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3
};
static const int ad7124_master_clk_freq_hz[3] = { static const int ad7124_master_clk_freq_hz[3] = {
[AD7124_LOW_POWER] = 76800, [AD7124_LOW_POWER] = 76800,
[AD7124_MID_POWER] = 153600, [AD7124_MID_POWER] = 153600,
...@@ -119,6 +132,7 @@ struct ad7124_channel_config { ...@@ -119,6 +132,7 @@ struct ad7124_channel_config {
unsigned int vref_mv; unsigned int vref_mv;
unsigned int pga_bits; unsigned int pga_bits;
unsigned int odr; unsigned int odr;
unsigned int filter_type;
}; };
struct ad7124_state { struct ad7124_state {
...@@ -138,7 +152,8 @@ static const struct iio_chan_spec ad7124_channel_template = { ...@@ -138,7 +152,8 @@ static const struct iio_chan_spec ad7124_channel_template = {
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SAMP_FREQ), BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
.scan_type = { .scan_type = {
.sign = 'u', .sign = 'u',
.realbits = 24, .realbits = 24,
...@@ -281,6 +296,58 @@ static int ad7124_set_channel_gain(struct ad7124_state *st, ...@@ -281,6 +296,58 @@ static int ad7124_set_channel_gain(struct ad7124_state *st,
return 0; return 0;
} }
static int ad7124_get_3db_filter_freq(struct ad7124_state *st,
unsigned int channel)
{
unsigned int fadc;
fadc = st->channel_config[channel].odr;
switch (st->channel_config[channel].filter_type) {
case AD7124_SINC3_FILTER:
return DIV_ROUND_CLOSEST(fadc * 230, 1000);
case AD7124_SINC4_FILTER:
return DIV_ROUND_CLOSEST(fadc * 262, 1000);
default:
return -EINVAL;
}
}
static int ad7124_set_3db_filter_freq(struct ad7124_state *st,
unsigned int channel,
unsigned int freq)
{
unsigned int sinc4_3db_odr;
unsigned int sinc3_3db_odr;
unsigned int new_filter;
unsigned int new_odr;
sinc4_3db_odr = DIV_ROUND_CLOSEST(freq * 1000, 230);
sinc3_3db_odr = DIV_ROUND_CLOSEST(freq * 1000, 262);
if (sinc4_3db_odr > sinc3_3db_odr) {
new_filter = AD7124_SINC3_FILTER;
new_odr = sinc4_3db_odr;
} else {
new_filter = AD7124_SINC4_FILTER;
new_odr = sinc3_3db_odr;
}
if (st->channel_config[channel].filter_type != new_filter) {
int ret;
st->channel_config[channel].filter_type = new_filter;
ret = ad7124_spi_write_mask(st, AD7124_FILTER(channel),
AD7124_FILTER_TYPE_MSK,
AD7124_FILTER_TYPE_SEL(new_filter),
3);
if (ret < 0)
return ret;
}
return ad7124_set_channel_odr(st, channel, new_odr);
}
static int ad7124_read_raw(struct iio_dev *indio_dev, static int ad7124_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, struct iio_chan_spec const *chan,
int *val, int *val2, long info) int *val, int *val2, long info)
...@@ -322,6 +389,9 @@ static int ad7124_read_raw(struct iio_dev *indio_dev, ...@@ -322,6 +389,9 @@ static int ad7124_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
*val = st->channel_config[chan->address].odr; *val = st->channel_config[chan->address].odr;
return IIO_VAL_INT;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
*val = ad7124_get_3db_filter_freq(st, chan->scan_index);
return IIO_VAL_INT; return IIO_VAL_INT;
default: default:
return -EINVAL; return -EINVAL;
...@@ -355,11 +425,37 @@ static int ad7124_write_raw(struct iio_dev *indio_dev, ...@@ -355,11 +425,37 @@ static int ad7124_write_raw(struct iio_dev *indio_dev,
gain = DIV_ROUND_CLOSEST(res, val2); gain = DIV_ROUND_CLOSEST(res, val2);
return ad7124_set_channel_gain(st, chan->address, gain); return ad7124_set_channel_gain(st, chan->address, gain);
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
if (val2 != 0)
return -EINVAL;
return ad7124_set_3db_filter_freq(st, chan->address, val);
default: default:
return -EINVAL; return -EINVAL;
} }
} }
static int ad7124_reg_access(struct iio_dev *indio_dev,
unsigned int reg,
unsigned int writeval,
unsigned int *readval)
{
struct ad7124_state *st = iio_priv(indio_dev);
int ret;
if (reg >= ARRAY_SIZE(ad7124_reg_size))
return -EINVAL;
if (readval)
ret = ad_sd_read_reg(&st->sd, reg, ad7124_reg_size[reg],
readval);
else
ret = ad_sd_write_reg(&st->sd, reg, ad7124_reg_size[reg],
writeval);
return ret;
}
static IIO_CONST_ATTR(in_voltage_scale_available, static IIO_CONST_ATTR(in_voltage_scale_available,
"0.000001164 0.000002328 0.000004656 0.000009313 0.000018626 0.000037252 0.000074505 0.000149011 0.000298023"); "0.000001164 0.000002328 0.000004656 0.000009313 0.000018626 0.000037252 0.000074505 0.000149011 0.000298023");
...@@ -375,6 +471,7 @@ static const struct attribute_group ad7124_attrs_group = { ...@@ -375,6 +471,7 @@ static const struct attribute_group ad7124_attrs_group = {
static const struct iio_info ad7124_info = { static const struct iio_info ad7124_info = {
.read_raw = ad7124_read_raw, .read_raw = ad7124_read_raw,
.write_raw = ad7124_write_raw, .write_raw = ad7124_write_raw,
.debugfs_reg_access = &ad7124_reg_access,
.validate_trigger = ad_sd_validate_trigger, .validate_trigger = ad_sd_validate_trigger,
.attrs = &ad7124_attrs_group, .attrs = &ad7124_attrs_group,
}; };
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/of_device.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
...@@ -786,76 +787,105 @@ static const struct iio_info ad7195_info = { ...@@ -786,76 +787,105 @@ static const struct iio_info ad7195_info = {
.validate_trigger = ad_sd_validate_trigger, .validate_trigger = ad_sd_validate_trigger,
}; };
#define __AD719x_CHANNEL(_si, _channel1, _channel2, _address, _extend_name, \
_type, _mask_type_av, _ext_info) \
{ \
.type = (_type), \
.differential = ((_channel2) == -1 ? 0 : 1), \
.indexed = 1, \
.channel = (_channel1), \
.channel2 = (_channel2), \
.address = (_address), \
.extend_name = (_extend_name), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_OFFSET), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
.info_mask_shared_by_type_available = (_mask_type_av), \
.ext_info = (_ext_info), \
.scan_index = (_si), \
.scan_type = { \
.sign = 'u', \
.realbits = 24, \
.storagebits = 32, \
.endianness = IIO_BE, \
}, \
}
#define AD719x_DIFF_CHANNEL(_si, _channel1, _channel2, _address) \
__AD719x_CHANNEL(_si, _channel1, _channel2, _address, NULL, \
IIO_VOLTAGE, BIT(IIO_CHAN_INFO_SCALE), \
ad7192_calibsys_ext_info)
#define AD719x_CHANNEL(_si, _channel1, _address) \
__AD719x_CHANNEL(_si, _channel1, -1, _address, NULL, IIO_VOLTAGE, \
BIT(IIO_CHAN_INFO_SCALE), ad7192_calibsys_ext_info)
#define AD719x_SHORTED_CHANNEL(_si, _channel1, _address) \
__AD719x_CHANNEL(_si, _channel1, -1, _address, "shorted", IIO_VOLTAGE, \
BIT(IIO_CHAN_INFO_SCALE), ad7192_calibsys_ext_info)
#define AD719x_TEMP_CHANNEL(_si, _address) \
__AD719x_CHANNEL(_si, 0, -1, _address, NULL, IIO_TEMP, 0, NULL)
static const struct iio_chan_spec ad7192_channels[] = { static const struct iio_chan_spec ad7192_channels[] = {
AD_SD_DIFF_CHANNEL(0, 1, 2, AD7192_CH_AIN1P_AIN2M, 24, 32, 0), AD719x_DIFF_CHANNEL(0, 1, 2, AD7192_CH_AIN1P_AIN2M),
AD_SD_DIFF_CHANNEL(1, 3, 4, AD7192_CH_AIN3P_AIN4M, 24, 32, 0), AD719x_DIFF_CHANNEL(1, 3, 4, AD7192_CH_AIN3P_AIN4M),
AD_SD_TEMP_CHANNEL(2, AD7192_CH_TEMP, 24, 32, 0), AD719x_TEMP_CHANNEL(2, AD7192_CH_TEMP),
AD_SD_SHORTED_CHANNEL(3, 2, AD7192_CH_AIN2P_AIN2M, 24, 32, 0), AD719x_SHORTED_CHANNEL(3, 2, AD7192_CH_AIN2P_AIN2M),
AD_SD_CHANNEL(4, 1, AD7192_CH_AIN1, 24, 32, 0), AD719x_CHANNEL(4, 1, AD7192_CH_AIN1),
AD_SD_CHANNEL(5, 2, AD7192_CH_AIN2, 24, 32, 0), AD719x_CHANNEL(5, 2, AD7192_CH_AIN2),
AD_SD_CHANNEL(6, 3, AD7192_CH_AIN3, 24, 32, 0), AD719x_CHANNEL(6, 3, AD7192_CH_AIN3),
AD_SD_CHANNEL(7, 4, AD7192_CH_AIN4, 24, 32, 0), AD719x_CHANNEL(7, 4, AD7192_CH_AIN4),
IIO_CHAN_SOFT_TIMESTAMP(8), IIO_CHAN_SOFT_TIMESTAMP(8),
}; };
static const struct iio_chan_spec ad7193_channels[] = { static const struct iio_chan_spec ad7193_channels[] = {
AD_SD_DIFF_CHANNEL(0, 1, 2, AD7193_CH_AIN1P_AIN2M, 24, 32, 0), AD719x_DIFF_CHANNEL(0, 1, 2, AD7193_CH_AIN1P_AIN2M),
AD_SD_DIFF_CHANNEL(1, 3, 4, AD7193_CH_AIN3P_AIN4M, 24, 32, 0), AD719x_DIFF_CHANNEL(1, 3, 4, AD7193_CH_AIN3P_AIN4M),
AD_SD_DIFF_CHANNEL(2, 5, 6, AD7193_CH_AIN5P_AIN6M, 24, 32, 0), AD719x_DIFF_CHANNEL(2, 5, 6, AD7193_CH_AIN5P_AIN6M),
AD_SD_DIFF_CHANNEL(3, 7, 8, AD7193_CH_AIN7P_AIN8M, 24, 32, 0), AD719x_DIFF_CHANNEL(3, 7, 8, AD7193_CH_AIN7P_AIN8M),
AD_SD_TEMP_CHANNEL(4, AD7193_CH_TEMP, 24, 32, 0), AD719x_TEMP_CHANNEL(4, AD7193_CH_TEMP),
AD_SD_SHORTED_CHANNEL(5, 2, AD7193_CH_AIN2P_AIN2M, 24, 32, 0), AD719x_SHORTED_CHANNEL(5, 2, AD7193_CH_AIN2P_AIN2M),
AD_SD_CHANNEL(6, 1, AD7193_CH_AIN1, 24, 32, 0), AD719x_CHANNEL(6, 1, AD7193_CH_AIN1),
AD_SD_CHANNEL(7, 2, AD7193_CH_AIN2, 24, 32, 0), AD719x_CHANNEL(7, 2, AD7193_CH_AIN2),
AD_SD_CHANNEL(8, 3, AD7193_CH_AIN3, 24, 32, 0), AD719x_CHANNEL(8, 3, AD7193_CH_AIN3),
AD_SD_CHANNEL(9, 4, AD7193_CH_AIN4, 24, 32, 0), AD719x_CHANNEL(9, 4, AD7193_CH_AIN4),
AD_SD_CHANNEL(10, 5, AD7193_CH_AIN5, 24, 32, 0), AD719x_CHANNEL(10, 5, AD7193_CH_AIN5),
AD_SD_CHANNEL(11, 6, AD7193_CH_AIN6, 24, 32, 0), AD719x_CHANNEL(11, 6, AD7193_CH_AIN6),
AD_SD_CHANNEL(12, 7, AD7193_CH_AIN7, 24, 32, 0), AD719x_CHANNEL(12, 7, AD7193_CH_AIN7),
AD_SD_CHANNEL(13, 8, AD7193_CH_AIN8, 24, 32, 0), AD719x_CHANNEL(13, 8, AD7193_CH_AIN8),
IIO_CHAN_SOFT_TIMESTAMP(14), IIO_CHAN_SOFT_TIMESTAMP(14),
}; };
static int ad7192_channels_config(struct iio_dev *indio_dev) static int ad7192_channels_config(struct iio_dev *indio_dev)
{ {
struct ad7192_state *st = iio_priv(indio_dev); struct ad7192_state *st = iio_priv(indio_dev);
const struct iio_chan_spec *channels;
struct iio_chan_spec *chan;
int i;
switch (st->devid) { switch (st->devid) {
case ID_AD7193: case ID_AD7193:
channels = ad7193_channels; indio_dev->channels = ad7193_channels;
indio_dev->num_channels = ARRAY_SIZE(ad7193_channels); indio_dev->num_channels = ARRAY_SIZE(ad7193_channels);
break; break;
default: default:
channels = ad7192_channels; indio_dev->channels = ad7192_channels;
indio_dev->num_channels = ARRAY_SIZE(ad7192_channels); indio_dev->num_channels = ARRAY_SIZE(ad7192_channels);
break; break;
} }
chan = devm_kcalloc(indio_dev->dev.parent, indio_dev->num_channels,
sizeof(*chan), GFP_KERNEL);
if (!chan)
return -ENOMEM;
indio_dev->channels = chan;
for (i = 0; i < indio_dev->num_channels; i++) {
*chan = channels[i];
chan->info_mask_shared_by_all |=
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY);
if (chan->type != IIO_TEMP) {
chan->info_mask_shared_by_type_available |=
BIT(IIO_CHAN_INFO_SCALE);
chan->ext_info = ad7192_calibsys_ext_info;
}
chan++;
}
return 0; return 0;
} }
static const struct of_device_id ad7192_of_match[] = {
{ .compatible = "adi,ad7190", .data = (void *)ID_AD7190 },
{ .compatible = "adi,ad7192", .data = (void *)ID_AD7192 },
{ .compatible = "adi,ad7193", .data = (void *)ID_AD7193 },
{ .compatible = "adi,ad7195", .data = (void *)ID_AD7195 },
{}
};
MODULE_DEVICE_TABLE(of, ad7192_of_match);
static int ad7192_probe(struct spi_device *spi) static int ad7192_probe(struct spi_device *spi)
{ {
struct ad7192_state *st; struct ad7192_state *st;
...@@ -899,13 +929,16 @@ static int ad7192_probe(struct spi_device *spi) ...@@ -899,13 +929,16 @@ static int ad7192_probe(struct spi_device *spi)
voltage_uv = regulator_get_voltage(st->avdd); voltage_uv = regulator_get_voltage(st->avdd);
if (voltage_uv) if (voltage_uv > 0) {
st->int_vref_mv = voltage_uv / 1000; st->int_vref_mv = voltage_uv / 1000;
else } else {
ret = voltage_uv;
dev_err(&spi->dev, "Device tree error, reference voltage undefined\n"); dev_err(&spi->dev, "Device tree error, reference voltage undefined\n");
goto error_disable_avdd;
}
spi_set_drvdata(spi, indio_dev); spi_set_drvdata(spi, indio_dev);
st->devid = spi_get_device_id(spi)->driver_data; st->devid = (unsigned long)of_device_get_match_data(&spi->dev);
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
...@@ -986,26 +1019,6 @@ static int ad7192_remove(struct spi_device *spi) ...@@ -986,26 +1019,6 @@ static int ad7192_remove(struct spi_device *spi)
return 0; return 0;
} }
static const struct spi_device_id ad7192_id[] = {
{"ad7190", ID_AD7190},
{"ad7192", ID_AD7192},
{"ad7193", ID_AD7193},
{"ad7195", ID_AD7195},
{}
};
MODULE_DEVICE_TABLE(spi, ad7192_id);
static const struct of_device_id ad7192_of_match[] = {
{ .compatible = "adi,ad7190" },
{ .compatible = "adi,ad7192" },
{ .compatible = "adi,ad7193" },
{ .compatible = "adi,ad7195" },
{}
};
MODULE_DEVICE_TABLE(of, ad7192_of_match);
static struct spi_driver ad7192_driver = { static struct spi_driver ad7192_driver = {
.driver = { .driver = {
.name = "ad7192", .name = "ad7192",
...@@ -1013,7 +1026,6 @@ static struct spi_driver ad7192_driver = { ...@@ -1013,7 +1026,6 @@ static struct spi_driver ad7192_driver = {
}, },
.probe = ad7192_probe, .probe = ad7192_probe,
.remove = ad7192_remove, .remove = ad7192_remove,
.id_table = ad7192_id,
}; };
module_spi_driver(ad7192_driver); module_spi_driver(ad7192_driver);
......
...@@ -122,7 +122,10 @@ static int ad7292_single_conversion(struct ad7292_state *st, ...@@ -122,7 +122,10 @@ static int ad7292_single_conversion(struct ad7292_state *st,
{ {
.tx_buf = &st->d8, .tx_buf = &st->d8,
.len = 4, .len = 4,
.delay_usecs = 6, .delay = {
.value = 6,
.unit = SPI_DELAY_UNIT_USECS
},
}, { }, {
.rx_buf = &st->d16, .rx_buf = &st->d16,
.len = 2, .len = 2,
......
...@@ -836,8 +836,10 @@ static int exynos_adc_probe(struct platform_device *pdev) ...@@ -836,8 +836,10 @@ static int exynos_adc_probe(struct platform_device *pdev)
info->vdd = devm_regulator_get(&pdev->dev, "vdd"); info->vdd = devm_regulator_get(&pdev->dev, "vdd");
if (IS_ERR(info->vdd)) { if (IS_ERR(info->vdd)) {
dev_err(&pdev->dev, "failed getting regulator, err = %ld\n", if (PTR_ERR(info->vdd) != -EPROBE_DEFER)
PTR_ERR(info->vdd)); dev_err(&pdev->dev,
"failed getting regulator, err = %ld\n",
PTR_ERR(info->vdd));
return PTR_ERR(info->vdd); return PTR_ERR(info->vdd);
} }
......
...@@ -71,7 +71,10 @@ static int max1118_read(struct spi_device *spi, int channel) ...@@ -71,7 +71,10 @@ static int max1118_read(struct spi_device *spi, int channel)
*/ */
{ {
.len = 0, .len = 0,
.delay_usecs = 1, /* > CNVST Low Time 100 ns */ .delay = { /* > CNVST Low Time 100 ns */
.value = 1,
.unit = SPI_DELAY_UNIT_USECS
},
.cs_change = 1, .cs_change = 1,
}, },
/* /*
...@@ -81,7 +84,10 @@ static int max1118_read(struct spi_device *spi, int channel) ...@@ -81,7 +84,10 @@ static int max1118_read(struct spi_device *spi, int channel)
*/ */
{ {
.len = 0, .len = 0,
.delay_usecs = 8, .delay = {
.value = 8,
.unit = SPI_DELAY_UNIT_USECS
},
}, },
{ {
.rx_buf = &adc->data, .rx_buf = &adc->data,
......
...@@ -421,7 +421,8 @@ static int mcp320x_probe(struct spi_device *spi) ...@@ -421,7 +421,8 @@ static int mcp320x_probe(struct spi_device *spi)
adc->transfer[1].len++; adc->transfer[1].len++;
/* conversions are started by asserting CS pin for 8 usec */ /* conversions are started by asserting CS pin for 8 usec */
adc->start_conv_transfer.delay_usecs = 8; adc->start_conv_transfer.delay.value = 8;
adc->start_conv_transfer.delay.unit = SPI_DELAY_UNIT_USECS;
spi_message_init_with_transfers(&adc->start_conv_msg, spi_message_init_with_transfers(&adc->start_conv_msg,
&adc->start_conv_transfer, 1); &adc->start_conv_transfer, 1);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/reset.h>
struct npcm_adc { struct npcm_adc {
bool int_status; bool int_status;
...@@ -23,13 +24,9 @@ struct npcm_adc { ...@@ -23,13 +24,9 @@ struct npcm_adc {
struct clk *adc_clk; struct clk *adc_clk;
wait_queue_head_t wq; wait_queue_head_t wq;
struct regulator *vref; struct regulator *vref;
struct regmap *rst_regmap; struct reset_control *reset;
}; };
/* NPCM7xx reset module */
#define NPCM7XX_IPSRST1_OFFSET 0x020
#define NPCM7XX_IPSRST1_ADC_RST BIT(27)
/* ADC registers */ /* ADC registers */
#define NPCM_ADCCON 0x00 #define NPCM_ADCCON 0x00
#define NPCM_ADCDATA 0x04 #define NPCM_ADCDATA 0x04
...@@ -106,13 +103,11 @@ static int npcm_adc_read(struct npcm_adc *info, int *val, u8 channel) ...@@ -106,13 +103,11 @@ static int npcm_adc_read(struct npcm_adc *info, int *val, u8 channel)
msecs_to_jiffies(10)); msecs_to_jiffies(10));
if (ret == 0) { if (ret == 0) {
regtemp = ioread32(info->regs + NPCM_ADCCON); regtemp = ioread32(info->regs + NPCM_ADCCON);
if ((regtemp & NPCM_ADCCON_ADC_CONV) && info->rst_regmap) { if (regtemp & NPCM_ADCCON_ADC_CONV) {
/* if conversion failed - reset ADC module */ /* if conversion failed - reset ADC module */
regmap_write(info->rst_regmap, NPCM7XX_IPSRST1_OFFSET, reset_control_assert(info->reset);
NPCM7XX_IPSRST1_ADC_RST);
msleep(100); msleep(100);
regmap_write(info->rst_regmap, NPCM7XX_IPSRST1_OFFSET, reset_control_deassert(info->reset);
0x0);
msleep(100); msleep(100);
/* Enable ADC and start conversion module */ /* Enable ADC and start conversion module */
...@@ -186,7 +181,6 @@ static int npcm_adc_probe(struct platform_device *pdev) ...@@ -186,7 +181,6 @@ static int npcm_adc_probe(struct platform_device *pdev)
struct npcm_adc *info; struct npcm_adc *info;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
if (!indio_dev) if (!indio_dev)
...@@ -199,6 +193,10 @@ static int npcm_adc_probe(struct platform_device *pdev) ...@@ -199,6 +193,10 @@ static int npcm_adc_probe(struct platform_device *pdev)
if (IS_ERR(info->regs)) if (IS_ERR(info->regs))
return PTR_ERR(info->regs); return PTR_ERR(info->regs);
info->reset = devm_reset_control_get(&pdev->dev, NULL);
if (IS_ERR(info->reset))
return PTR_ERR(info->reset);
info->adc_clk = devm_clk_get(&pdev->dev, NULL); info->adc_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(info->adc_clk)) { if (IS_ERR(info->adc_clk)) {
dev_warn(&pdev->dev, "ADC clock failed: can't read clk\n"); dev_warn(&pdev->dev, "ADC clock failed: can't read clk\n");
...@@ -211,16 +209,6 @@ static int npcm_adc_probe(struct platform_device *pdev) ...@@ -211,16 +209,6 @@ static int npcm_adc_probe(struct platform_device *pdev)
div = div >> NPCM_ADCCON_DIV_SHIFT; div = div >> NPCM_ADCCON_DIV_SHIFT;
info->adc_sample_hz = clk_get_rate(info->adc_clk) / ((div + 1) * 2); info->adc_sample_hz = clk_get_rate(info->adc_clk) / ((div + 1) * 2);
if (of_device_is_compatible(np, "nuvoton,npcm750-adc")) {
info->rst_regmap = syscon_regmap_lookup_by_compatible
("nuvoton,npcm750-rst");
if (IS_ERR(info->rst_regmap)) {
dev_err(&pdev->dev, "Failed to find nuvoton,npcm750-rst\n");
ret = PTR_ERR(info->rst_regmap);
goto err_disable_clk;
}
}
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq <= 0) { if (irq <= 0) {
ret = -EINVAL; ret = -EINVAL;
......
...@@ -189,7 +189,8 @@ static int tlc4541_probe(struct spi_device *spi) ...@@ -189,7 +189,8 @@ static int tlc4541_probe(struct spi_device *spi)
/* Setup default message */ /* Setup default message */
st->scan_single_xfer[0].rx_buf = &st->rx_buf[0]; st->scan_single_xfer[0].rx_buf = &st->rx_buf[0];
st->scan_single_xfer[0].len = 3; st->scan_single_xfer[0].len = 3;
st->scan_single_xfer[1].delay_usecs = 3; st->scan_single_xfer[1].delay.value = 3;
st->scan_single_xfer[1].delay.unit = SPI_DELAY_UNIT_NSECS;
st->scan_single_xfer[2].rx_buf = &st->rx_buf[0]; st->scan_single_xfer[2].rx_buf = &st->rx_buf[0];
st->scan_single_xfer[2].len = 2; st->scan_single_xfer[2].len = 2;
......
...@@ -22,4 +22,14 @@ config AD8366 ...@@ -22,4 +22,14 @@ config AD8366
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called ad8366. module will be called ad8366.
config HMC425
tristate "Analog Devices HMC425A and similar GPIO Gain Amplifiers"
depends on GPIOLIB
help
Say yes here to build support for Analog Devices HMC425A and similar
gain amplifiers or step attenuators.
To compile this driver as a module, choose M here: the
module will be called hmc425a.
endmenu endmenu
...@@ -5,3 +5,4 @@ ...@@ -5,3 +5,4 @@
# When adding new entries keep the list in alphabetical order # When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AD8366) += ad8366.o obj-$(CONFIG_AD8366) += ad8366.o
obj-$(CONFIG_HMC425) += hmc425a.o
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* AD8366 Dual-Digital Variable Gain Amplifier (VGA) * AD8366 Dual-Digital Variable Gain Amplifier (VGA)
* ADA4961 BiCMOS RF Digital Gain Amplifier (DGA) * ADA4961 BiCMOS RF Digital Gain Amplifier (DGA)
* ADL5240 Digitally controlled variable gain amplifier (VGA) * ADL5240 Digitally controlled variable gain amplifier (VGA)
* HMC1119 0.25 dB LSB, 7-Bit, Silicon Digital Attenuator
* *
* Copyright 2012-2019 Analog Devices Inc. * Copyright 2012-2019 Analog Devices Inc.
*/ */
...@@ -27,6 +28,7 @@ enum ad8366_type { ...@@ -27,6 +28,7 @@ enum ad8366_type {
ID_AD8366, ID_AD8366,
ID_ADA4961, ID_ADA4961,
ID_ADL5240, ID_ADL5240,
ID_HMC1119,
}; };
struct ad8366_info { struct ad8366_info {
...@@ -62,6 +64,10 @@ static struct ad8366_info ad8366_infos[] = { ...@@ -62,6 +64,10 @@ static struct ad8366_info ad8366_infos[] = {
.gain_min = -11500, .gain_min = -11500,
.gain_max = 20000, .gain_max = 20000,
}, },
[ID_HMC1119] = {
.gain_min = -31750,
.gain_max = 0,
},
}; };
static int ad8366_write(struct iio_dev *indio_dev, static int ad8366_write(struct iio_dev *indio_dev,
...@@ -84,6 +90,9 @@ static int ad8366_write(struct iio_dev *indio_dev, ...@@ -84,6 +90,9 @@ static int ad8366_write(struct iio_dev *indio_dev,
case ID_ADL5240: case ID_ADL5240:
st->data[0] = (ch_a & 0x3F); st->data[0] = (ch_a & 0x3F);
break; break;
case ID_HMC1119:
st->data[0] = ch_a;
break;
} }
ret = spi_write(st->spi, st->data, indio_dev->num_channels); ret = spi_write(st->spi, st->data, indio_dev->num_channels);
...@@ -118,6 +127,9 @@ static int ad8366_read_raw(struct iio_dev *indio_dev, ...@@ -118,6 +127,9 @@ static int ad8366_read_raw(struct iio_dev *indio_dev,
case ID_ADL5240: case ID_ADL5240:
gain = 20000 - 31500 + code * 500; gain = 20000 - 31500 + code * 500;
break; break;
case ID_HMC1119:
gain = -1 * code * 250;
break;
} }
/* Values in dB */ /* Values in dB */
...@@ -164,6 +176,9 @@ static int ad8366_write_raw(struct iio_dev *indio_dev, ...@@ -164,6 +176,9 @@ static int ad8366_write_raw(struct iio_dev *indio_dev,
case ID_ADL5240: case ID_ADL5240:
code = ((gain - 500 - 20000) / 500) & 0x3F; code = ((gain - 500 - 20000) / 500) & 0x3F;
break; break;
case ID_HMC1119:
code = (abs(gain) / 250) & 0x7F;
break;
} }
mutex_lock(&st->lock); mutex_lock(&st->lock);
...@@ -180,9 +195,22 @@ static int ad8366_write_raw(struct iio_dev *indio_dev, ...@@ -180,9 +195,22 @@ static int ad8366_write_raw(struct iio_dev *indio_dev,
return ret; return ret;
} }
static int ad8366_write_raw_get_fmt(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
long mask)
{
switch (mask) {
case IIO_CHAN_INFO_HARDWAREGAIN:
return IIO_VAL_INT_PLUS_MICRO_DB;
default:
return -EINVAL;
}
}
static const struct iio_info ad8366_info = { static const struct iio_info ad8366_info = {
.read_raw = &ad8366_read_raw, .read_raw = &ad8366_read_raw,
.write_raw = &ad8366_write_raw, .write_raw = &ad8366_write_raw,
.write_raw_get_fmt = &ad8366_write_raw_get_fmt,
}; };
#define AD8366_CHAN(_channel) { \ #define AD8366_CHAN(_channel) { \
...@@ -233,6 +261,7 @@ static int ad8366_probe(struct spi_device *spi) ...@@ -233,6 +261,7 @@ static int ad8366_probe(struct spi_device *spi)
break; break;
case ID_ADA4961: case ID_ADA4961:
case ID_ADL5240: case ID_ADL5240:
case ID_HMC1119:
st->reset_gpio = devm_gpiod_get(&spi->dev, "reset", st->reset_gpio = devm_gpiod_get(&spi->dev, "reset",
GPIOD_OUT_HIGH); GPIOD_OUT_HIGH);
indio_dev->channels = ada4961_channels; indio_dev->channels = ada4961_channels;
...@@ -285,6 +314,7 @@ static const struct spi_device_id ad8366_id[] = { ...@@ -285,6 +314,7 @@ static const struct spi_device_id ad8366_id[] = {
{"ad8366", ID_AD8366}, {"ad8366", ID_AD8366},
{"ada4961", ID_ADA4961}, {"ada4961", ID_ADA4961},
{"adl5240", ID_ADL5240}, {"adl5240", ID_ADL5240},
{"hmc1119", ID_HMC1119},
{} {}
}; };
MODULE_DEVICE_TABLE(spi, ad8366_id); MODULE_DEVICE_TABLE(spi, ad8366_id);
......
// SPDX-License-Identifier: GPL-2.0
/*
* HMC425A and similar Gain Amplifiers
*
* Copyright 2020 Analog Devices Inc.
*/
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/regulator/consumer.h>
#include <linux/sysfs.h>
enum hmc425a_type {
ID_HMC425A,
};
struct hmc425a_chip_info {
const char *name;
const struct iio_chan_spec *channels;
unsigned int num_channels;
unsigned int num_gpios;
int gain_min;
int gain_max;
int default_gain;
};
struct hmc425a_state {
struct regulator *reg;
struct mutex lock; /* protect sensor state */
struct hmc425a_chip_info *chip_info;
struct gpio_descs *gpios;
enum hmc425a_type type;
u32 gain;
};
static int hmc425a_write(struct iio_dev *indio_dev, u32 value)
{
struct hmc425a_state *st = iio_priv(indio_dev);
DECLARE_BITMAP(values, BITS_PER_TYPE(value));
values[0] = value;
gpiod_set_array_value_cansleep(st->gpios->ndescs, st->gpios->desc,
NULL, values);
return 0;
}
static int hmc425a_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long m)
{
struct hmc425a_state *st = iio_priv(indio_dev);
int code, gain = 0;
int ret;
mutex_lock(&st->lock);
switch (m) {
case IIO_CHAN_INFO_HARDWAREGAIN:
code = st->gain;
switch (st->type) {
case ID_HMC425A:
gain = ~code * -500;
break;
}
*val = gain / 1000;
*val2 = (gain % 1000) * 1000;
ret = IIO_VAL_INT_PLUS_MICRO_DB;
break;
default:
ret = -EINVAL;
}
mutex_unlock(&st->lock);
return ret;
};
static int hmc425a_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val,
int val2, long mask)
{
struct hmc425a_state *st = iio_priv(indio_dev);
struct hmc425a_chip_info *inf = st->chip_info;
int code = 0, gain;
int ret;
if (val < 0)
gain = (val * 1000) - (val2 / 1000);
else
gain = (val * 1000) + (val2 / 1000);
if (gain > inf->gain_max || gain < inf->gain_min)
return -EINVAL;
switch (st->type) {
case ID_HMC425A:
code = ~((abs(gain) / 500) & 0x3F);
break;
}
mutex_lock(&st->lock);
switch (mask) {
case IIO_CHAN_INFO_HARDWAREGAIN:
st->gain = code;
ret = hmc425a_write(indio_dev, st->gain);
break;
default:
ret = -EINVAL;
}
mutex_unlock(&st->lock);
return ret;
}
static int hmc425a_write_raw_get_fmt(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
long mask)
{
switch (mask) {
case IIO_CHAN_INFO_HARDWAREGAIN:
return IIO_VAL_INT_PLUS_MICRO_DB;
default:
return -EINVAL;
}
}
static const struct iio_info hmc425a_info = {
.read_raw = &hmc425a_read_raw,
.write_raw = &hmc425a_write_raw,
.write_raw_get_fmt = &hmc425a_write_raw_get_fmt,
};
#define HMC425A_CHAN(_channel) \
{ \
.type = IIO_VOLTAGE, \
.output = 1, \
.indexed = 1, \
.channel = _channel, \
.info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN), \
}
static const struct iio_chan_spec hmc425a_channels[] = {
HMC425A_CHAN(0),
};
/* Match table for of_platform binding */
static const struct of_device_id hmc425a_of_match[] = {
{ .compatible = "adi,hmc425a", .data = (void *)ID_HMC425A },
{},
};
MODULE_DEVICE_TABLE(of, hmc425a_of_match);
static void hmc425a_reg_disable(void *data)
{
struct hmc425a_state *st = data;
regulator_disable(st->reg);
}
static struct hmc425a_chip_info hmc425a_chip_info_tbl[] = {
[ID_HMC425A] = {
.name = "hmc425a",
.channels = hmc425a_channels,
.num_channels = ARRAY_SIZE(hmc425a_channels),
.num_gpios = 6,
.gain_min = -31500,
.gain_max = 0,
.default_gain = -0x40, /* set default gain -31.5db*/
},
};
static int hmc425a_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
struct hmc425a_state *st;
int ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
st->type = (enum hmc425a_type)of_device_get_match_data(&pdev->dev);
st->chip_info = &hmc425a_chip_info_tbl[st->type];
indio_dev->num_channels = st->chip_info->num_channels;
indio_dev->channels = st->chip_info->channels;
indio_dev->name = st->chip_info->name;
st->gain = st->chip_info->default_gain;
st->gpios = devm_gpiod_get_array(&pdev->dev, "ctrl", GPIOD_OUT_LOW);
if (IS_ERR(st->gpios)) {
ret = PTR_ERR(st->gpios);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "failed to get gpios\n");
return ret;
}
if (st->gpios->ndescs != st->chip_info->num_gpios) {
dev_err(&pdev->dev, "%d GPIOs needed to operate\n",
st->chip_info->num_gpios);
return -ENODEV;
}
st->reg = devm_regulator_get(&pdev->dev, "vcc-supply");
if (IS_ERR(st->reg))
return PTR_ERR(st->reg);
ret = regulator_enable(st->reg);
if (ret)
return ret;
ret = devm_add_action_or_reset(&pdev->dev, hmc425a_reg_disable, st);
if (ret)
return ret;
mutex_init(&st->lock);
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &hmc425a_info;
indio_dev->modes = INDIO_DIRECT_MODE;
return devm_iio_device_register(&pdev->dev, indio_dev);
}
static struct platform_driver hmc425a_driver = {
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = hmc425a_of_match,
},
.probe = hmc425a_probe,
};
module_platform_driver(hmc425a_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices HMC425A and similar GPIO control Gain Amplifiers");
MODULE_LICENSE("GPL v2");
...@@ -48,6 +48,11 @@ ...@@ -48,6 +48,11 @@
#define ATLAS_REG_EC_CALIB_STATUS_LOW BIT(2) #define ATLAS_REG_EC_CALIB_STATUS_LOW BIT(2)
#define ATLAS_REG_EC_CALIB_STATUS_HIGH BIT(3) #define ATLAS_REG_EC_CALIB_STATUS_HIGH BIT(3)
#define ATLAS_REG_DO_CALIB_STATUS 0x09
#define ATLAS_REG_DO_CALIB_STATUS_MASK 0x03
#define ATLAS_REG_DO_CALIB_STATUS_PRESSURE BIT(0)
#define ATLAS_REG_DO_CALIB_STATUS_DO BIT(1)
#define ATLAS_REG_PH_TEMP_DATA 0x0e #define ATLAS_REG_PH_TEMP_DATA 0x0e
#define ATLAS_REG_PH_DATA 0x16 #define ATLAS_REG_PH_DATA 0x16
...@@ -60,14 +65,19 @@ ...@@ -60,14 +65,19 @@
#define ATLAS_REG_ORP_CALIB_STATUS 0x0d #define ATLAS_REG_ORP_CALIB_STATUS 0x0d
#define ATLAS_REG_ORP_DATA 0x0e #define ATLAS_REG_ORP_DATA 0x0e
#define ATLAS_REG_DO_TEMP_DATA 0x12
#define ATLAS_REG_DO_DATA 0x22
#define ATLAS_PH_INT_TIME_IN_MS 450 #define ATLAS_PH_INT_TIME_IN_MS 450
#define ATLAS_EC_INT_TIME_IN_MS 650 #define ATLAS_EC_INT_TIME_IN_MS 650
#define ATLAS_ORP_INT_TIME_IN_MS 450 #define ATLAS_ORP_INT_TIME_IN_MS 450
#define ATLAS_DO_INT_TIME_IN_MS 450
enum { enum {
ATLAS_PH_SM, ATLAS_PH_SM,
ATLAS_EC_SM, ATLAS_EC_SM,
ATLAS_ORP_SM, ATLAS_ORP_SM,
ATLAS_DO_SM,
}; };
struct atlas_data { struct atlas_data {
...@@ -76,6 +86,7 @@ struct atlas_data { ...@@ -76,6 +86,7 @@ struct atlas_data {
struct atlas_device *chip; struct atlas_device *chip;
struct regmap *regmap; struct regmap *regmap;
struct irq_work work; struct irq_work work;
unsigned int interrupt_enabled;
__be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */ __be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */
}; };
...@@ -121,7 +132,7 @@ static const struct iio_chan_spec atlas_ph_channels[] = { ...@@ -121,7 +132,7 @@ static const struct iio_chan_spec atlas_ph_channels[] = {
}, },
}; };
#define ATLAS_EC_CHANNEL(_idx, _addr) \ #define ATLAS_CONCENTRATION_CHANNEL(_idx, _addr) \
{\ {\
.type = IIO_CONCENTRATION, \ .type = IIO_CONCENTRATION, \
.indexed = 1, \ .indexed = 1, \
...@@ -152,8 +163,8 @@ static const struct iio_chan_spec atlas_ec_channels[] = { ...@@ -152,8 +163,8 @@ static const struct iio_chan_spec atlas_ec_channels[] = {
.endianness = IIO_BE, .endianness = IIO_BE,
}, },
}, },
ATLAS_EC_CHANNEL(0, ATLAS_REG_TDS_DATA), ATLAS_CONCENTRATION_CHANNEL(0, ATLAS_REG_TDS_DATA),
ATLAS_EC_CHANNEL(1, ATLAS_REG_PSS_DATA), ATLAS_CONCENTRATION_CHANNEL(1, ATLAS_REG_PSS_DATA),
IIO_CHAN_SOFT_TIMESTAMP(3), IIO_CHAN_SOFT_TIMESTAMP(3),
{ {
.type = IIO_TEMP, .type = IIO_TEMP,
...@@ -182,6 +193,19 @@ static const struct iio_chan_spec atlas_orp_channels[] = { ...@@ -182,6 +193,19 @@ static const struct iio_chan_spec atlas_orp_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(1), IIO_CHAN_SOFT_TIMESTAMP(1),
}; };
static const struct iio_chan_spec atlas_do_channels[] = {
ATLAS_CONCENTRATION_CHANNEL(0, ATLAS_REG_DO_DATA),
IIO_CHAN_SOFT_TIMESTAMP(1),
{
.type = IIO_TEMP,
.address = ATLAS_REG_DO_TEMP_DATA,
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
.output = 1,
.scan_index = -1
},
};
static int atlas_check_ph_calibration(struct atlas_data *data) static int atlas_check_ph_calibration(struct atlas_data *data)
{ {
struct device *dev = &data->client->dev; struct device *dev = &data->client->dev;
...@@ -262,7 +286,31 @@ static int atlas_check_orp_calibration(struct atlas_data *data) ...@@ -262,7 +286,31 @@ static int atlas_check_orp_calibration(struct atlas_data *data)
dev_warn(dev, "device has not been calibrated\n"); dev_warn(dev, "device has not been calibrated\n");
return 0; return 0;
}; }
static int atlas_check_do_calibration(struct atlas_data *data)
{
struct device *dev = &data->client->dev;
int ret;
unsigned int val;
ret = regmap_read(data->regmap, ATLAS_REG_DO_CALIB_STATUS, &val);
if (ret)
return ret;
if (!(val & ATLAS_REG_DO_CALIB_STATUS_MASK)) {
dev_warn(dev, "device has not been calibrated\n");
return 0;
}
if (!(val & ATLAS_REG_DO_CALIB_STATUS_PRESSURE))
dev_warn(dev, "device missing atmospheric pressure calibration\n");
if (!(val & ATLAS_REG_DO_CALIB_STATUS_DO))
dev_warn(dev, "device missing dissolved oxygen calibration\n");
return 0;
}
struct atlas_device { struct atlas_device {
const struct iio_chan_spec *channels; const struct iio_chan_spec *channels;
...@@ -295,6 +343,13 @@ static struct atlas_device atlas_devices[] = { ...@@ -295,6 +343,13 @@ static struct atlas_device atlas_devices[] = {
.calibration = &atlas_check_orp_calibration, .calibration = &atlas_check_orp_calibration,
.delay = ATLAS_ORP_INT_TIME_IN_MS, .delay = ATLAS_ORP_INT_TIME_IN_MS,
}, },
[ATLAS_DO_SM] = {
.channels = atlas_do_channels,
.num_channels = 3,
.data_reg = ATLAS_REG_DO_DATA,
.calibration = &atlas_check_do_calibration,
.delay = ATLAS_DO_INT_TIME_IN_MS,
},
}; };
static int atlas_set_powermode(struct atlas_data *data, int on) static int atlas_set_powermode(struct atlas_data *data, int on)
...@@ -304,6 +359,9 @@ static int atlas_set_powermode(struct atlas_data *data, int on) ...@@ -304,6 +359,9 @@ static int atlas_set_powermode(struct atlas_data *data, int on)
static int atlas_set_interrupt(struct atlas_data *data, bool state) static int atlas_set_interrupt(struct atlas_data *data, bool state)
{ {
if (!data->interrupt_enabled)
return 0;
return regmap_update_bits(data->regmap, ATLAS_REG_INT_CONTROL, return regmap_update_bits(data->regmap, ATLAS_REG_INT_CONTROL,
ATLAS_REG_INT_CONTROL_EN, ATLAS_REG_INT_CONTROL_EN,
state ? ATLAS_REG_INT_CONTROL_EN : 0); state ? ATLAS_REG_INT_CONTROL_EN : 0);
...@@ -507,6 +565,7 @@ static const struct i2c_device_id atlas_id[] = { ...@@ -507,6 +565,7 @@ static const struct i2c_device_id atlas_id[] = {
{ "atlas-ph-sm", ATLAS_PH_SM}, { "atlas-ph-sm", ATLAS_PH_SM},
{ "atlas-ec-sm", ATLAS_EC_SM}, { "atlas-ec-sm", ATLAS_EC_SM},
{ "atlas-orp-sm", ATLAS_ORP_SM}, { "atlas-orp-sm", ATLAS_ORP_SM},
{ "atlas-do-sm", ATLAS_DO_SM},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, atlas_id); MODULE_DEVICE_TABLE(i2c, atlas_id);
...@@ -515,6 +574,7 @@ static const struct of_device_id atlas_dt_ids[] = { ...@@ -515,6 +574,7 @@ static const struct of_device_id atlas_dt_ids[] = {
{ .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, }, { .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, },
{ .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, }, { .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, },
{ .compatible = "atlas,orp-sm", .data = (void *)ATLAS_ORP_SM, }, { .compatible = "atlas,orp-sm", .data = (void *)ATLAS_ORP_SM, },
{ .compatible = "atlas,do-sm", .data = (void *)ATLAS_DO_SM, },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, atlas_dt_ids); MODULE_DEVICE_TABLE(of, atlas_dt_ids);
...@@ -572,11 +632,6 @@ static int atlas_probe(struct i2c_client *client, ...@@ -572,11 +632,6 @@ static int atlas_probe(struct i2c_client *client,
if (ret) if (ret)
return ret; return ret;
if (client->irq <= 0) {
dev_err(&client->dev, "no valid irq defined\n");
return -EINVAL;
}
ret = chip->calibration(data); ret = chip->calibration(data);
if (ret) if (ret)
return ret; return ret;
...@@ -596,16 +651,20 @@ static int atlas_probe(struct i2c_client *client, ...@@ -596,16 +651,20 @@ static int atlas_probe(struct i2c_client *client,
init_irq_work(&data->work, atlas_work_handler); init_irq_work(&data->work, atlas_work_handler);
/* interrupt pin toggles on new conversion */ if (client->irq > 0) {
ret = devm_request_threaded_irq(&client->dev, client->irq, /* interrupt pin toggles on new conversion */
NULL, atlas_interrupt_handler, ret = devm_request_threaded_irq(&client->dev, client->irq,
IRQF_TRIGGER_RISING | NULL, atlas_interrupt_handler,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, IRQF_TRIGGER_RISING |
"atlas_irq", IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
indio_dev); "atlas_irq",
if (ret) { indio_dev);
dev_err(&client->dev, "request irq (%d) failed\n", client->irq);
goto unregister_buffer; if (ret)
dev_warn(&client->dev,
"request irq (%d) failed\n", client->irq);
else
data->interrupt_enabled = 1;
} }
ret = atlas_set_powermode(data, 1); ret = atlas_set_powermode(data, 1);
......
...@@ -328,6 +328,8 @@ static struct st_sensors_platform_data *st_sensors_dev_probe(struct device *dev, ...@@ -328,6 +328,8 @@ static struct st_sensors_platform_data *st_sensors_dev_probe(struct device *dev,
return NULL; return NULL;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
if (!device_property_read_u32(dev, "st,drdy-int-pin", &val) && (val <= 2)) if (!device_property_read_u32(dev, "st,drdy-int-pin", &val) && (val <= 2))
pdata->drdy_int_pin = (u8) val; pdata->drdy_int_pin = (u8) val;
else else
...@@ -371,6 +373,8 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, ...@@ -371,6 +373,8 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev,
/* If OF/DT pdata exists, it will take precedence of anything else */ /* If OF/DT pdata exists, it will take precedence of anything else */
of_pdata = st_sensors_dev_probe(indio_dev->dev.parent, pdata); of_pdata = st_sensors_dev_probe(indio_dev->dev.parent, pdata);
if (IS_ERR(of_pdata))
return PTR_ERR(of_pdata);
if (of_pdata) if (of_pdata)
pdata = of_pdata; pdata = of_pdata;
......
...@@ -121,26 +121,6 @@ config AD5624R_SPI ...@@ -121,26 +121,6 @@ config AD5624R_SPI
Say yes here to build support for Analog Devices AD5624R, AD5644R and Say yes here to build support for Analog Devices AD5624R, AD5644R and
AD5664R converters (DAC). This driver uses the common SPI interface. AD5664R converters (DAC). This driver uses the common SPI interface.
config LTC1660
tristate "Linear Technology LTC1660/LTC1665 DAC SPI driver"
depends on SPI
help
Say yes here to build support for Linear Technology
LTC1660 and LTC1665 Digital to Analog Converters.
To compile this driver as a module, choose M here: the
module will be called ltc1660.
config LTC2632
tristate "Linear Technology LTC2632-12/10/8 DAC spi driver"
depends on SPI
help
Say yes here to build support for Linear Technology
LTC2632-12, LTC2632-10, LTC2632-8 converters (DAC).
To compile this driver as a module, choose M here: the
module will be called ltc2632.
config AD5686 config AD5686
tristate tristate
...@@ -208,6 +188,16 @@ config AD5764 ...@@ -208,6 +188,16 @@ config AD5764
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called ad5764. module will be called ad5764.
config AD5770R
tristate "Analog Devices AD5770R IDAC driver"
depends on SPI_MASTER
help
Say yes here to build support for Analog Devices AD5770R Digital to
Analog Converter.
To compile this driver as a module, choose M here: the
module will be called ad5770r.
config AD5791 config AD5791
tristate "Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC SPI driver" tristate "Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC SPI driver"
depends on SPI depends on SPI
...@@ -229,16 +219,6 @@ config AD7303 ...@@ -229,16 +219,6 @@ config AD7303
To compile this driver as module choose M here: the module will be called To compile this driver as module choose M here: the module will be called
ad7303. ad7303.
config CIO_DAC
tristate "Measurement Computing CIO-DAC IIO driver"
depends on X86 && (ISA_BUS || PC104)
select ISA_BUS_API
help
Say yes here to build support for the Measurement Computing CIO-DAC
analog output device family (CIO-DAC16, CIO-DAC08, PC104-DAC06). The
base port addresses for the devices may be configured via the base
array module parameter.
config AD8801 config AD8801
tristate "Analog Devices AD8801/AD8803 DAC driver" tristate "Analog Devices AD8801/AD8803 DAC driver"
depends on SPI_MASTER depends on SPI_MASTER
...@@ -249,6 +229,16 @@ config AD8801 ...@@ -249,6 +229,16 @@ config AD8801
To compile this driver as a module choose M here: the module will be called To compile this driver as a module choose M here: the module will be called
ad8801. ad8801.
config CIO_DAC
tristate "Measurement Computing CIO-DAC IIO driver"
depends on X86 && (ISA_BUS || PC104)
select ISA_BUS_API
help
Say yes here to build support for the Measurement Computing CIO-DAC
analog output device family (CIO-DAC16, CIO-DAC08, PC104-DAC06). The
base port addresses for the devices may be configured via the base
array module parameter.
config DPOT_DAC config DPOT_DAC
tristate "DAC emulation using a DPOT" tristate "DAC emulation using a DPOT"
depends on OF depends on OF
...@@ -278,6 +268,27 @@ config LPC18XX_DAC ...@@ -278,6 +268,27 @@ config LPC18XX_DAC
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called lpc18xx_dac. called lpc18xx_dac.
config LTC1660
tristate "Linear Technology LTC1660/LTC1665 DAC SPI driver"
depends on SPI
help
Say yes here to build support for Linear Technology
LTC1660 and LTC1665 Digital to Analog Converters.
To compile this driver as a module, choose M here: the
module will be called ltc1660.
config LTC2632
tristate "Linear Technology LTC2632-12/10/8 and LTC2636-12/10/8 DAC spi driver"
depends on SPI
help
Say yes here to build support for Linear Technology
LTC2632-12, LTC2632-10, LTC2632-8, LTC2636-12, LTC2636-10 and
LTC2636-8 converters (DAC).
To compile this driver as a module, choose M here: the
module will be called ltc2632.
config M62332 config M62332
tristate "Mitsubishi M62332 DAC driver" tristate "Mitsubishi M62332 DAC driver"
depends on I2C depends on I2C
......
...@@ -19,6 +19,7 @@ obj-$(CONFIG_AD5755) += ad5755.o ...@@ -19,6 +19,7 @@ obj-$(CONFIG_AD5755) += ad5755.o
obj-$(CONFIG_AD5755) += ad5758.o obj-$(CONFIG_AD5755) += ad5758.o
obj-$(CONFIG_AD5761) += ad5761.o obj-$(CONFIG_AD5761) += ad5761.o
obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5764) += ad5764.o
obj-$(CONFIG_AD5770R) += ad5770r.o
obj-$(CONFIG_AD5791) += ad5791.o obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_AD5686_SPI) += ad5686-spi.o obj-$(CONFIG_AD5686_SPI) += ad5686-spi.o
......
...@@ -631,10 +631,9 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev) ...@@ -631,10 +631,9 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
} }
} }
if (i == ARRAY_SIZE(ad5755_dcdc_freq_table)) { if (i == ARRAY_SIZE(ad5755_dcdc_freq_table))
dev_err(dev, dev_err(dev,
"adi,dc-dc-freq out of range selecting 410kHz"); "adi,dc-dc-freq out of range selecting 410kHz\n");
}
} }
pdata->dc_dc_maxv = AD5755_DC_DC_MAXV_23V; pdata->dc_dc_maxv = AD5755_DC_DC_MAXV_23V;
...@@ -645,17 +644,16 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev) ...@@ -645,17 +644,16 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
break; break;
} }
} }
if (i == ARRAY_SIZE(ad5755_dcdc_maxv_table)) { if (i == ARRAY_SIZE(ad5755_dcdc_maxv_table))
dev_err(dev, dev_err(dev,
"adi,dc-dc-maxv out of range selecting 23V"); "adi,dc-dc-maxv out of range selecting 23V\n");
}
} }
devnr = 0; devnr = 0;
for_each_child_of_node(np, pp) { for_each_child_of_node(np, pp) {
if (devnr >= AD5755_NUM_CHANNELS) { if (devnr >= AD5755_NUM_CHANNELS) {
dev_err(dev, dev_err(dev,
"There is to many channels defined in DT\n"); "There are too many channels defined in DT\n");
goto error_out; goto error_out;
} }
...@@ -681,11 +679,10 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev) ...@@ -681,11 +679,10 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
break; break;
} }
} }
if (i == ARRAY_SIZE(ad5755_slew_rate_table)) { if (i == ARRAY_SIZE(ad5755_slew_rate_table))
dev_err(dev, dev_err(dev,
"channel %d slew rate out of range selecting 64kHz", "channel %d slew rate out of range selecting 64kHz\n",
devnr); devnr);
}
pdata->dac[devnr].slew.step_size = AD5755_SLEW_STEP_SIZE_1; pdata->dac[devnr].slew.step_size = AD5755_SLEW_STEP_SIZE_1;
for (i = 0; i < ARRAY_SIZE(ad5755_slew_step_table); i++) { for (i = 0; i < ARRAY_SIZE(ad5755_slew_step_table); i++) {
...@@ -695,11 +692,10 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev) ...@@ -695,11 +692,10 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
break; break;
} }
} }
if (i == ARRAY_SIZE(ad5755_slew_step_table)) { if (i == ARRAY_SIZE(ad5755_slew_step_table))
dev_err(dev, dev_err(dev,
"channel %d slew step size out of range selecting 1 LSB", "channel %d slew step size out of range selecting 1 LSB\n",
devnr); devnr);
}
} else { } else {
pdata->dac[devnr].slew.enable = false; pdata->dac[devnr].slew.enable = false;
pdata->dac[devnr].slew.rate = AD5755_SLEW_RATE_64k; pdata->dac[devnr].slew.rate = AD5755_SLEW_RATE_64k;
......
This diff is collapsed.
...@@ -12,11 +12,6 @@ ...@@ -12,11 +12,6 @@
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#define LTC2632_DAC_CHANNELS 2
#define LTC2632_ADDR_DAC0 0x0
#define LTC2632_ADDR_DAC1 0x1
#define LTC2632_CMD_WRITE_INPUT_N 0x0 #define LTC2632_CMD_WRITE_INPUT_N 0x0
#define LTC2632_CMD_UPDATE_DAC_N 0x1 #define LTC2632_CMD_UPDATE_DAC_N 0x1
#define LTC2632_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 #define LTC2632_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2
...@@ -33,6 +28,7 @@ ...@@ -33,6 +28,7 @@
*/ */
struct ltc2632_chip_info { struct ltc2632_chip_info {
const struct iio_chan_spec *channels; const struct iio_chan_spec *channels;
const size_t num_channels;
const int vref_mv; const int vref_mv;
}; };
...@@ -57,6 +53,12 @@ enum ltc2632_supported_device_ids { ...@@ -57,6 +53,12 @@ enum ltc2632_supported_device_ids {
ID_LTC2632H12, ID_LTC2632H12,
ID_LTC2632H10, ID_LTC2632H10,
ID_LTC2632H8, ID_LTC2632H8,
ID_LTC2636L12,
ID_LTC2636L10,
ID_LTC2636L8,
ID_LTC2636H12,
ID_LTC2636H10,
ID_LTC2636H8,
}; };
static int ltc2632_spi_write(struct spi_device *spi, static int ltc2632_spi_write(struct spi_device *spi,
...@@ -190,39 +192,77 @@ static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = { ...@@ -190,39 +192,77 @@ static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = {
const struct iio_chan_spec _name ## _channels[] = { \ const struct iio_chan_spec _name ## _channels[] = { \
LTC2632_CHANNEL(0, _bits), \ LTC2632_CHANNEL(0, _bits), \
LTC2632_CHANNEL(1, _bits), \ LTC2632_CHANNEL(1, _bits), \
LTC2632_CHANNEL(2, _bits), \
LTC2632_CHANNEL(3, _bits), \
LTC2632_CHANNEL(4, _bits), \
LTC2632_CHANNEL(5, _bits), \
LTC2632_CHANNEL(6, _bits), \
LTC2632_CHANNEL(7, _bits), \
} }
static DECLARE_LTC2632_CHANNELS(ltc2632l12, 12); static DECLARE_LTC2632_CHANNELS(ltc2632x12, 12);
static DECLARE_LTC2632_CHANNELS(ltc2632l10, 10); static DECLARE_LTC2632_CHANNELS(ltc2632x10, 10);
static DECLARE_LTC2632_CHANNELS(ltc2632l8, 8); static DECLARE_LTC2632_CHANNELS(ltc2632x8, 8);
static DECLARE_LTC2632_CHANNELS(ltc2632h12, 12);
static DECLARE_LTC2632_CHANNELS(ltc2632h10, 10);
static DECLARE_LTC2632_CHANNELS(ltc2632h8, 8);
static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = { static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = {
[ID_LTC2632L12] = { [ID_LTC2632L12] = {
.channels = ltc2632l12_channels, .channels = ltc2632x12_channels,
.num_channels = 2,
.vref_mv = 2500, .vref_mv = 2500,
}, },
[ID_LTC2632L10] = { [ID_LTC2632L10] = {
.channels = ltc2632l10_channels, .channels = ltc2632x10_channels,
.num_channels = 2,
.vref_mv = 2500, .vref_mv = 2500,
}, },
[ID_LTC2632L8] = { [ID_LTC2632L8] = {
.channels = ltc2632l8_channels, .channels = ltc2632x8_channels,
.num_channels = 2,
.vref_mv = 2500, .vref_mv = 2500,
}, },
[ID_LTC2632H12] = { [ID_LTC2632H12] = {
.channels = ltc2632h12_channels, .channels = ltc2632x12_channels,
.num_channels = 2,
.vref_mv = 4096, .vref_mv = 4096,
}, },
[ID_LTC2632H10] = { [ID_LTC2632H10] = {
.channels = ltc2632h10_channels, .channels = ltc2632x10_channels,
.num_channels = 2,
.vref_mv = 4096, .vref_mv = 4096,
}, },
[ID_LTC2632H8] = { [ID_LTC2632H8] = {
.channels = ltc2632h8_channels, .channels = ltc2632x8_channels,
.num_channels = 2,
.vref_mv = 4096,
},
[ID_LTC2636L12] = {
.channels = ltc2632x12_channels,
.num_channels = 8,
.vref_mv = 2500,
},
[ID_LTC2636L10] = {
.channels = ltc2632x10_channels,
.num_channels = 8,
.vref_mv = 2500,
},
[ID_LTC2636L8] = {
.channels = ltc2632x8_channels,
.num_channels = 8,
.vref_mv = 2500,
},
[ID_LTC2636H12] = {
.channels = ltc2632x12_channels,
.num_channels = 8,
.vref_mv = 4096,
},
[ID_LTC2636H10] = {
.channels = ltc2632x10_channels,
.num_channels = 8,
.vref_mv = 4096,
},
[ID_LTC2636H8] = {
.channels = ltc2632x8_channels,
.num_channels = 8,
.vref_mv = 4096, .vref_mv = 4096,
}, },
}; };
...@@ -291,7 +331,7 @@ static int ltc2632_probe(struct spi_device *spi) ...@@ -291,7 +331,7 @@ static int ltc2632_probe(struct spi_device *spi)
indio_dev->info = &ltc2632_info; indio_dev->info = &ltc2632_info;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = chip_info->channels; indio_dev->channels = chip_info->channels;
indio_dev->num_channels = LTC2632_DAC_CHANNELS; indio_dev->num_channels = chip_info->num_channels;
return iio_device_register(indio_dev); return iio_device_register(indio_dev);
} }
...@@ -316,6 +356,12 @@ static const struct spi_device_id ltc2632_id[] = { ...@@ -316,6 +356,12 @@ static const struct spi_device_id ltc2632_id[] = {
{ "ltc2632-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H12] }, { "ltc2632-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H12] },
{ "ltc2632-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H10] }, { "ltc2632-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H10] },
{ "ltc2632-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H8] }, { "ltc2632-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H8] },
{ "ltc2636-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L12] },
{ "ltc2636-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L10] },
{ "ltc2636-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L8] },
{ "ltc2636-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636H12] },
{ "ltc2636-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636H10] },
{ "ltc2636-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636H8] },
{} {}
}; };
MODULE_DEVICE_TABLE(spi, ltc2632_id); MODULE_DEVICE_TABLE(spi, ltc2632_id);
...@@ -339,6 +385,24 @@ static const struct of_device_id ltc2632_of_match[] = { ...@@ -339,6 +385,24 @@ static const struct of_device_id ltc2632_of_match[] = {
}, { }, {
.compatible = "lltc,ltc2632-h8", .compatible = "lltc,ltc2632-h8",
.data = &ltc2632_chip_info_tbl[ID_LTC2632H8] .data = &ltc2632_chip_info_tbl[ID_LTC2632H8]
}, {
.compatible = "lltc,ltc2636-l12",
.data = &ltc2632_chip_info_tbl[ID_LTC2636L12]
}, {
.compatible = "lltc,ltc2636-l10",
.data = &ltc2632_chip_info_tbl[ID_LTC2636L10]
}, {
.compatible = "lltc,ltc2636-l8",
.data = &ltc2632_chip_info_tbl[ID_LTC2636L8]
}, {
.compatible = "lltc,ltc2636-h12",
.data = &ltc2632_chip_info_tbl[ID_LTC2636H12]
}, {
.compatible = "lltc,ltc2636-h10",
.data = &ltc2632_chip_info_tbl[ID_LTC2636H10]
}, {
.compatible = "lltc,ltc2636-h8",
.data = &ltc2632_chip_info_tbl[ID_LTC2636H8]
}, },
{} {}
}; };
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
struct adis16136_chip_info { struct adis16136_chip_info {
unsigned int precision; unsigned int precision;
unsigned int fullscale; unsigned int fullscale;
const struct adis_timeout *timeouts; const struct adis_data adis_data;
}; };
struct adis16136 { struct adis16136 {
...@@ -466,22 +466,22 @@ static const char * const adis16136_status_error_msgs[] = { ...@@ -466,22 +466,22 @@ static const char * const adis16136_status_error_msgs[] = {
[ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL] = "Flash checksum error", [ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL] = "Flash checksum error",
}; };
static const struct adis_data adis16136_data = { #define ADIS16136_DATA(_timeouts) \
.diag_stat_reg = ADIS16136_REG_DIAG_STAT, { \
.glob_cmd_reg = ADIS16136_REG_GLOB_CMD, .diag_stat_reg = ADIS16136_REG_DIAG_STAT, \
.msc_ctrl_reg = ADIS16136_REG_MSC_CTRL, .glob_cmd_reg = ADIS16136_REG_GLOB_CMD, \
.msc_ctrl_reg = ADIS16136_REG_MSC_CTRL, \
.self_test_mask = ADIS16136_MSC_CTRL_SELF_TEST, .self_test_reg = ADIS16136_REG_MSC_CTRL, \
.self_test_mask = ADIS16136_MSC_CTRL_SELF_TEST, \
.read_delay = 10, .read_delay = 10, \
.write_delay = 10, .write_delay = 10, \
.status_error_msgs = adis16136_status_error_msgs, \
.status_error_msgs = adis16136_status_error_msgs, .status_error_mask = BIT(ADIS16136_DIAG_STAT_FLASH_UPDATE_FAIL) | \
.status_error_mask = BIT(ADIS16136_DIAG_STAT_FLASH_UPDATE_FAIL) | BIT(ADIS16136_DIAG_STAT_SPI_FAIL) | \
BIT(ADIS16136_DIAG_STAT_SPI_FAIL) | BIT(ADIS16136_DIAG_STAT_SELF_TEST_FAIL) | \
BIT(ADIS16136_DIAG_STAT_SELF_TEST_FAIL) | BIT(ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL), \
BIT(ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL), .timeouts = (_timeouts), \
}; }
enum adis16136_id { enum adis16136_id {
ID_ADIS16133, ID_ADIS16133,
...@@ -506,41 +506,25 @@ static const struct adis16136_chip_info adis16136_chip_info[] = { ...@@ -506,41 +506,25 @@ static const struct adis16136_chip_info adis16136_chip_info[] = {
[ID_ADIS16133] = { [ID_ADIS16133] = {
.precision = IIO_DEGREE_TO_RAD(1200), .precision = IIO_DEGREE_TO_RAD(1200),
.fullscale = 24000, .fullscale = 24000,
.timeouts = &adis16133_timeouts, .adis_data = ADIS16136_DATA(&adis16133_timeouts),
}, },
[ID_ADIS16135] = { [ID_ADIS16135] = {
.precision = IIO_DEGREE_TO_RAD(300), .precision = IIO_DEGREE_TO_RAD(300),
.fullscale = 24000, .fullscale = 24000,
.timeouts = &adis16133_timeouts, .adis_data = ADIS16136_DATA(&adis16133_timeouts),
}, },
[ID_ADIS16136] = { [ID_ADIS16136] = {
.precision = IIO_DEGREE_TO_RAD(450), .precision = IIO_DEGREE_TO_RAD(450),
.fullscale = 24623, .fullscale = 24623,
.timeouts = &adis16136_timeouts, .adis_data = ADIS16136_DATA(&adis16136_timeouts),
}, },
[ID_ADIS16137] = { [ID_ADIS16137] = {
.precision = IIO_DEGREE_TO_RAD(1000), .precision = IIO_DEGREE_TO_RAD(1000),
.fullscale = 24609, .fullscale = 24609,
.timeouts = &adis16136_timeouts, .adis_data = ADIS16136_DATA(&adis16136_timeouts),
}, },
}; };
static struct adis_data *adis16136_adis_data_alloc(struct adis16136 *st,
struct device *dev)
{
struct adis_data *data;
data = devm_kmalloc(dev, sizeof(struct adis_data), GFP_KERNEL);
if (!data)
return ERR_PTR(-ENOMEM);
memcpy(data, &adis16136_data, sizeof(*data));
data->timeouts = st->chip_info->timeouts;
return data;
}
static int adis16136_probe(struct spi_device *spi) static int adis16136_probe(struct spi_device *spi)
{ {
const struct spi_device_id *id = spi_get_device_id(spi); const struct spi_device_id *id = spi_get_device_id(spi);
...@@ -565,9 +549,7 @@ static int adis16136_probe(struct spi_device *spi) ...@@ -565,9 +549,7 @@ static int adis16136_probe(struct spi_device *spi)
indio_dev->info = &adis16136_info; indio_dev->info = &adis16136_info;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
adis16136_data = adis16136_adis_data_alloc(adis16136, &spi->dev); adis16136_data = &adis16136->chip_info->adis_data;
if (IS_ERR(adis16136_data))
return PTR_ERR(adis16136_data);
ret = adis_init(&adis16136->adis, indio_dev, spi, adis16136_data); ret = adis_init(&adis16136->adis, indio_dev, spi, adis16136_data);
if (ret) if (ret)
......
...@@ -346,6 +346,7 @@ static const struct adis_data adis16260_data = { ...@@ -346,6 +346,7 @@ static const struct adis_data adis16260_data = {
.diag_stat_reg = ADIS16260_DIAG_STAT, .diag_stat_reg = ADIS16260_DIAG_STAT,
.self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST, .self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST,
.self_test_reg = ADIS16260_MSC_CTRL,
.timeouts = &adis16260_timeouts, .timeouts = &adis16260_timeouts,
.status_error_msgs = adis1620_status_error_msgs, .status_error_msgs = adis1620_status_error_msgs,
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
*/ */
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -346,8 +347,8 @@ static int adis_self_test(struct adis *adis) ...@@ -346,8 +347,8 @@ static int adis_self_test(struct adis *adis)
int ret; int ret;
const struct adis_timeout *timeouts = adis->data->timeouts; const struct adis_timeout *timeouts = adis->data->timeouts;
ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, ret = __adis_write_reg_16(adis, adis->data->self_test_reg,
adis->data->self_test_mask); adis->data->self_test_mask);
if (ret) { if (ret) {
dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n", dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n",
ret); ret);
...@@ -359,42 +360,71 @@ static int adis_self_test(struct adis *adis) ...@@ -359,42 +360,71 @@ static int adis_self_test(struct adis *adis)
ret = __adis_check_status(adis); ret = __adis_check_status(adis);
if (adis->data->self_test_no_autoclear) if (adis->data->self_test_no_autoclear)
__adis_write_reg_16(adis, adis->data->msc_ctrl_reg, 0x00); __adis_write_reg_16(adis, adis->data->self_test_reg, 0x00);
return ret; return ret;
} }
/** /**
* adis_inital_startup() - Performs device self-test * __adis_initial_startup() - Device initial setup
* @adis: The adis device * @adis: The adis device
* *
* The function performs a HW reset via a reset pin that should be specified
* via GPIOLIB. If no pin is configured a SW reset will be performed.
* The RST pin for the ADIS devices should be configured as ACTIVE_LOW.
*
* After the self-test operation is performed, the function will also check
* that the product ID is as expected. This assumes that drivers providing
* 'prod_id_reg' will also provide the 'prod_id'.
*
* Returns 0 if the device is operational, a negative error code otherwise. * Returns 0 if the device is operational, a negative error code otherwise.
* *
* This function should be called early on in the device initialization sequence * This function should be called early on in the device initialization sequence
* to ensure that the device is in a sane and known state and that it is usable. * to ensure that the device is in a sane and known state and that it is usable.
*/ */
int adis_initial_startup(struct adis *adis) int __adis_initial_startup(struct adis *adis)
{ {
const struct adis_timeout *timeouts = adis->data->timeouts;
struct gpio_desc *gpio;
uint16_t prod_id;
int ret; int ret;
mutex_lock(&adis->state_lock); /* check if the device has rst pin low */
gpio = devm_gpiod_get_optional(&adis->spi->dev, "reset", GPIOD_ASIS);
if (IS_ERR(gpio))
return PTR_ERR(gpio);
if (gpio) {
gpiod_set_value_cansleep(gpio, 1);
msleep(10);
/* bring device out of reset */
gpiod_set_value_cansleep(gpio, 0);
msleep(timeouts->reset_ms);
} else {
ret = __adis_reset(adis);
if (ret)
return ret;
}
ret = adis_self_test(adis); ret = adis_self_test(adis);
if (ret) { if (ret)
dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n"); return ret;
__adis_reset(adis);
ret = adis_self_test(adis);
if (ret) {
dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n");
goto out_unlock;
}
}
out_unlock: if (!adis->data->prod_id_reg)
mutex_unlock(&adis->state_lock); return 0;
return ret;
ret = adis_read_reg_16(adis, adis->data->prod_id_reg, &prod_id);
if (ret)
return ret;
if (prod_id != adis->data->prod_id)
dev_warn(&adis->spi->dev,
"Device ID(%u) and product ID(%u) do not match.",
adis->data->prod_id, prod_id);
return 0;
} }
EXPORT_SYMBOL_GPL(adis_initial_startup); EXPORT_SYMBOL_GPL(__adis_initial_startup);
/** /**
* adis_single_conversion() - Performs a single sample conversion * adis_single_conversion() - Performs a single sample conversion
......
...@@ -156,7 +156,7 @@ struct adis16400_state; ...@@ -156,7 +156,7 @@ struct adis16400_state;
struct adis16400_chip_info { struct adis16400_chip_info {
const struct iio_chan_spec *channels; const struct iio_chan_spec *channels;
const struct adis_timeout *timeouts; const struct adis_data adis_data;
const int num_channels; const int num_channels;
const long flags; const long flags;
unsigned int gyro_scale_micro; unsigned int gyro_scale_micro;
...@@ -930,12 +930,64 @@ static const struct iio_chan_spec adis16334_channels[] = { ...@@ -930,12 +930,64 @@ static const struct iio_chan_spec adis16334_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
}; };
static const char * const adis16400_status_error_msgs[] = {
[ADIS16400_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure",
[ADIS16400_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure",
[ADIS16400_DIAG_STAT_XACCL_FAIL] = "X-axis accelerometer self-test failure",
[ADIS16400_DIAG_STAT_XGYRO_FAIL] = "X-axis gyroscope self-test failure",
[ADIS16400_DIAG_STAT_YGYRO_FAIL] = "Y-axis gyroscope self-test failure",
[ADIS16400_DIAG_STAT_ZGYRO_FAIL] = "Z-axis gyroscope self-test failure",
[ADIS16400_DIAG_STAT_ALARM2] = "Alarm 2 active",
[ADIS16400_DIAG_STAT_ALARM1] = "Alarm 1 active",
[ADIS16400_DIAG_STAT_FLASH_CHK] = "Flash checksum error",
[ADIS16400_DIAG_STAT_SELF_TEST] = "Self test error",
[ADIS16400_DIAG_STAT_OVERFLOW] = "Sensor overrange",
[ADIS16400_DIAG_STAT_SPI_FAIL] = "SPI failure",
[ADIS16400_DIAG_STAT_FLASH_UPT] = "Flash update failed",
[ADIS16400_DIAG_STAT_POWER_HIGH] = "Power supply above 5.25V",
[ADIS16400_DIAG_STAT_POWER_LOW] = "Power supply below 4.75V",
};
#define ADIS16400_DATA(_timeouts) \
{ \
.msc_ctrl_reg = ADIS16400_MSC_CTRL, \
.glob_cmd_reg = ADIS16400_GLOB_CMD, \
.diag_stat_reg = ADIS16400_DIAG_STAT, \
.read_delay = 50, \
.write_delay = 50, \
.self_test_mask = ADIS16400_MSC_CTRL_MEM_TEST, \
.self_test_reg = ADIS16400_MSC_CTRL, \
.status_error_msgs = adis16400_status_error_msgs, \
.status_error_mask = BIT(ADIS16400_DIAG_STAT_ZACCL_FAIL) | \
BIT(ADIS16400_DIAG_STAT_YACCL_FAIL) | \
BIT(ADIS16400_DIAG_STAT_XACCL_FAIL) | \
BIT(ADIS16400_DIAG_STAT_XGYRO_FAIL) | \
BIT(ADIS16400_DIAG_STAT_YGYRO_FAIL) | \
BIT(ADIS16400_DIAG_STAT_ZGYRO_FAIL) | \
BIT(ADIS16400_DIAG_STAT_ALARM2) | \
BIT(ADIS16400_DIAG_STAT_ALARM1) | \
BIT(ADIS16400_DIAG_STAT_FLASH_CHK) | \
BIT(ADIS16400_DIAG_STAT_SELF_TEST) | \
BIT(ADIS16400_DIAG_STAT_OVERFLOW) | \
BIT(ADIS16400_DIAG_STAT_SPI_FAIL) | \
BIT(ADIS16400_DIAG_STAT_FLASH_UPT) | \
BIT(ADIS16400_DIAG_STAT_POWER_HIGH) | \
BIT(ADIS16400_DIAG_STAT_POWER_LOW), \
.timeouts = (_timeouts), \
}
static const struct adis_timeout adis16300_timeouts = { static const struct adis_timeout adis16300_timeouts = {
.reset_ms = ADIS16400_STARTUP_DELAY, .reset_ms = ADIS16400_STARTUP_DELAY,
.sw_reset_ms = ADIS16400_STARTUP_DELAY, .sw_reset_ms = ADIS16400_STARTUP_DELAY,
.self_test_ms = ADIS16400_STARTUP_DELAY, .self_test_ms = ADIS16400_STARTUP_DELAY,
}; };
static const struct adis_timeout adis16334_timeouts = {
.reset_ms = 60,
.sw_reset_ms = 60,
.self_test_ms = 14,
};
static const struct adis_timeout adis16362_timeouts = { static const struct adis_timeout adis16362_timeouts = {
.reset_ms = 130, .reset_ms = 130,
.sw_reset_ms = 130, .sw_reset_ms = 130,
...@@ -972,7 +1024,7 @@ static struct adis16400_chip_info adis16400_chips[] = { ...@@ -972,7 +1024,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
.temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
.set_freq = adis16400_set_freq, .set_freq = adis16400_set_freq,
.get_freq = adis16400_get_freq, .get_freq = adis16400_get_freq,
.timeouts = &adis16300_timeouts, .adis_data = ADIS16400_DATA(&adis16300_timeouts),
}, },
[ADIS16334] = { [ADIS16334] = {
.channels = adis16334_channels, .channels = adis16334_channels,
...@@ -985,6 +1037,7 @@ static struct adis16400_chip_info adis16400_chips[] = { ...@@ -985,6 +1037,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
.temp_offset = 25000000 / 67850, /* 25 C = 0x00 */ .temp_offset = 25000000 / 67850, /* 25 C = 0x00 */
.set_freq = adis16334_set_freq, .set_freq = adis16334_set_freq,
.get_freq = adis16334_get_freq, .get_freq = adis16334_get_freq,
.adis_data = ADIS16400_DATA(&adis16334_timeouts),
}, },
[ADIS16350] = { [ADIS16350] = {
.channels = adis16350_channels, .channels = adis16350_channels,
...@@ -996,7 +1049,7 @@ static struct adis16400_chip_info adis16400_chips[] = { ...@@ -996,7 +1049,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
.flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE, .flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE,
.set_freq = adis16400_set_freq, .set_freq = adis16400_set_freq,
.get_freq = adis16400_get_freq, .get_freq = adis16400_get_freq,
.timeouts = &adis16300_timeouts, .adis_data = ADIS16400_DATA(&adis16300_timeouts),
}, },
[ADIS16360] = { [ADIS16360] = {
.channels = adis16350_channels, .channels = adis16350_channels,
...@@ -1009,7 +1062,7 @@ static struct adis16400_chip_info adis16400_chips[] = { ...@@ -1009,7 +1062,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
.set_freq = adis16400_set_freq, .set_freq = adis16400_set_freq,
.get_freq = adis16400_get_freq, .get_freq = adis16400_get_freq,
.timeouts = &adis16300_timeouts, .adis_data = ADIS16400_DATA(&adis16300_timeouts),
}, },
[ADIS16362] = { [ADIS16362] = {
.channels = adis16350_channels, .channels = adis16350_channels,
...@@ -1022,7 +1075,7 @@ static struct adis16400_chip_info adis16400_chips[] = { ...@@ -1022,7 +1075,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
.set_freq = adis16400_set_freq, .set_freq = adis16400_set_freq,
.get_freq = adis16400_get_freq, .get_freq = adis16400_get_freq,
.timeouts = &adis16362_timeouts, .adis_data = ADIS16400_DATA(&adis16362_timeouts),
}, },
[ADIS16364] = { [ADIS16364] = {
.channels = adis16350_channels, .channels = adis16350_channels,
...@@ -1035,7 +1088,7 @@ static struct adis16400_chip_info adis16400_chips[] = { ...@@ -1035,7 +1088,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
.set_freq = adis16400_set_freq, .set_freq = adis16400_set_freq,
.get_freq = adis16400_get_freq, .get_freq = adis16400_get_freq,
.timeouts = &adis16362_timeouts, .adis_data = ADIS16400_DATA(&adis16362_timeouts),
}, },
[ADIS16367] = { [ADIS16367] = {
.channels = adis16350_channels, .channels = adis16350_channels,
...@@ -1048,7 +1101,7 @@ static struct adis16400_chip_info adis16400_chips[] = { ...@@ -1048,7 +1101,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
.set_freq = adis16400_set_freq, .set_freq = adis16400_set_freq,
.get_freq = adis16400_get_freq, .get_freq = adis16400_get_freq,
.timeouts = &adis16300_timeouts, .adis_data = ADIS16400_DATA(&adis16300_timeouts),
}, },
[ADIS16400] = { [ADIS16400] = {
.channels = adis16400_channels, .channels = adis16400_channels,
...@@ -1060,7 +1113,7 @@ static struct adis16400_chip_info adis16400_chips[] = { ...@@ -1060,7 +1113,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
.temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
.set_freq = adis16400_set_freq, .set_freq = adis16400_set_freq,
.get_freq = adis16400_get_freq, .get_freq = adis16400_get_freq,
.timeouts = &adis16400_timeouts, .adis_data = ADIS16400_DATA(&adis16400_timeouts),
}, },
[ADIS16445] = { [ADIS16445] = {
.channels = adis16445_channels, .channels = adis16445_channels,
...@@ -1074,7 +1127,7 @@ static struct adis16400_chip_info adis16400_chips[] = { ...@@ -1074,7 +1127,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
.temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
.set_freq = adis16334_set_freq, .set_freq = adis16334_set_freq,
.get_freq = adis16334_get_freq, .get_freq = adis16334_get_freq,
.timeouts = &adis16445_timeouts, .adis_data = ADIS16400_DATA(&adis16445_timeouts),
}, },
[ADIS16448] = { [ADIS16448] = {
.channels = adis16448_channels, .channels = adis16448_channels,
...@@ -1088,7 +1141,7 @@ static struct adis16400_chip_info adis16400_chips[] = { ...@@ -1088,7 +1141,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
.temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
.set_freq = adis16334_set_freq, .set_freq = adis16334_set_freq,
.get_freq = adis16334_get_freq, .get_freq = adis16334_get_freq,
.timeouts = &adis16448_timeouts, .adis_data = ADIS16400_DATA(&adis16448_timeouts),
} }
}; };
...@@ -1099,52 +1152,6 @@ static const struct iio_info adis16400_info = { ...@@ -1099,52 +1152,6 @@ static const struct iio_info adis16400_info = {
.debugfs_reg_access = adis_debugfs_reg_access, .debugfs_reg_access = adis_debugfs_reg_access,
}; };
static const char * const adis16400_status_error_msgs[] = {
[ADIS16400_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure",
[ADIS16400_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure",
[ADIS16400_DIAG_STAT_XACCL_FAIL] = "X-axis accelerometer self-test failure",
[ADIS16400_DIAG_STAT_XGYRO_FAIL] = "X-axis gyroscope self-test failure",
[ADIS16400_DIAG_STAT_YGYRO_FAIL] = "Y-axis gyroscope self-test failure",
[ADIS16400_DIAG_STAT_ZGYRO_FAIL] = "Z-axis gyroscope self-test failure",
[ADIS16400_DIAG_STAT_ALARM2] = "Alarm 2 active",
[ADIS16400_DIAG_STAT_ALARM1] = "Alarm 1 active",
[ADIS16400_DIAG_STAT_FLASH_CHK] = "Flash checksum error",
[ADIS16400_DIAG_STAT_SELF_TEST] = "Self test error",
[ADIS16400_DIAG_STAT_OVERFLOW] = "Sensor overrange",
[ADIS16400_DIAG_STAT_SPI_FAIL] = "SPI failure",
[ADIS16400_DIAG_STAT_FLASH_UPT] = "Flash update failed",
[ADIS16400_DIAG_STAT_POWER_HIGH] = "Power supply above 5.25V",
[ADIS16400_DIAG_STAT_POWER_LOW] = "Power supply below 4.75V",
};
static const struct adis_data adis16400_data = {
.msc_ctrl_reg = ADIS16400_MSC_CTRL,
.glob_cmd_reg = ADIS16400_GLOB_CMD,
.diag_stat_reg = ADIS16400_DIAG_STAT,
.read_delay = 50,
.write_delay = 50,
.self_test_mask = ADIS16400_MSC_CTRL_MEM_TEST,
.status_error_msgs = adis16400_status_error_msgs,
.status_error_mask = BIT(ADIS16400_DIAG_STAT_ZACCL_FAIL) |
BIT(ADIS16400_DIAG_STAT_YACCL_FAIL) |
BIT(ADIS16400_DIAG_STAT_XACCL_FAIL) |
BIT(ADIS16400_DIAG_STAT_XGYRO_FAIL) |
BIT(ADIS16400_DIAG_STAT_YGYRO_FAIL) |
BIT(ADIS16400_DIAG_STAT_ZGYRO_FAIL) |
BIT(ADIS16400_DIAG_STAT_ALARM2) |
BIT(ADIS16400_DIAG_STAT_ALARM1) |
BIT(ADIS16400_DIAG_STAT_FLASH_CHK) |
BIT(ADIS16400_DIAG_STAT_SELF_TEST) |
BIT(ADIS16400_DIAG_STAT_OVERFLOW) |
BIT(ADIS16400_DIAG_STAT_SPI_FAIL) |
BIT(ADIS16400_DIAG_STAT_FLASH_UPT) |
BIT(ADIS16400_DIAG_STAT_POWER_HIGH) |
BIT(ADIS16400_DIAG_STAT_POWER_LOW),
};
static void adis16400_setup_chan_mask(struct adis16400_state *st) static void adis16400_setup_chan_mask(struct adis16400_state *st)
{ {
const struct adis16400_chip_info *chip_info = st->variant; const struct adis16400_chip_info *chip_info = st->variant;
...@@ -1158,23 +1165,6 @@ static void adis16400_setup_chan_mask(struct adis16400_state *st) ...@@ -1158,23 +1165,6 @@ static void adis16400_setup_chan_mask(struct adis16400_state *st)
st->avail_scan_mask[0] |= BIT(ch->scan_index); st->avail_scan_mask[0] |= BIT(ch->scan_index);
} }
} }
static struct adis_data *adis16400_adis_data_alloc(struct adis16400_state *st,
struct device *dev)
{
struct adis_data *data;
data = devm_kmalloc(dev, sizeof(struct adis_data), GFP_KERNEL);
if (!data)
return ERR_PTR(-ENOMEM);
memcpy(data, &adis16400_data, sizeof(*data));
data->timeouts = st->variant->timeouts;
return data;
}
static int adis16400_probe(struct spi_device *spi) static int adis16400_probe(struct spi_device *spi)
{ {
struct adis16400_state *st; struct adis16400_state *st;
...@@ -1207,9 +1197,7 @@ static int adis16400_probe(struct spi_device *spi) ...@@ -1207,9 +1197,7 @@ static int adis16400_probe(struct spi_device *spi)
st->adis.burst->extra_len = sizeof(u16); st->adis.burst->extra_len = sizeof(u16);
} }
adis16400_data = adis16400_adis_data_alloc(st, &spi->dev); adis16400_data = &st->variant->adis_data;
if (IS_ERR(adis16400_data))
return PTR_ERR(adis16400_data);
ret = adis_init(&st->adis, indio_dev, spi, adis16400_data); ret = adis_init(&st->adis, indio_dev, spi, adis16400_data);
if (ret) if (ret)
......
...@@ -333,40 +333,6 @@ static int adis16460_enable_irq(struct adis *adis, bool enable) ...@@ -333,40 +333,6 @@ static int adis16460_enable_irq(struct adis *adis, bool enable)
return 0; return 0;
} }
static int adis16460_initial_setup(struct iio_dev *indio_dev)
{
struct adis16460 *st = iio_priv(indio_dev);
uint16_t prod_id;
unsigned int device_id;
int ret;
adis_reset(&st->adis);
msleep(222);
ret = adis_write_reg_16(&st->adis, ADIS16460_REG_GLOB_CMD, BIT(1));
if (ret)
return ret;
msleep(75);
ret = adis_check_status(&st->adis);
if (ret)
return ret;
ret = adis_read_reg_16(&st->adis, ADIS16460_REG_PROD_ID, &prod_id);
if (ret)
return ret;
ret = sscanf(indio_dev->name, "adis%u\n", &device_id);
if (ret != 1)
return -EINVAL;
if (prod_id != device_id)
dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
device_id, prod_id);
return 0;
}
#define ADIS16460_DIAG_STAT_IN_CLK_OOS 7 #define ADIS16460_DIAG_STAT_IN_CLK_OOS 7
#define ADIS16460_DIAG_STAT_FLASH_MEM 6 #define ADIS16460_DIAG_STAT_FLASH_MEM 6
#define ADIS16460_DIAG_STAT_SELF_TEST 5 #define ADIS16460_DIAG_STAT_SELF_TEST 5
...@@ -392,6 +358,10 @@ static const struct adis_timeout adis16460_timeouts = { ...@@ -392,6 +358,10 @@ static const struct adis_timeout adis16460_timeouts = {
static const struct adis_data adis16460_data = { static const struct adis_data adis16460_data = {
.diag_stat_reg = ADIS16460_REG_DIAG_STAT, .diag_stat_reg = ADIS16460_REG_DIAG_STAT,
.glob_cmd_reg = ADIS16460_REG_GLOB_CMD, .glob_cmd_reg = ADIS16460_REG_GLOB_CMD,
.prod_id_reg = ADIS16460_REG_PROD_ID,
.prod_id = 16460,
.self_test_mask = BIT(2),
.self_test_reg = ADIS16460_REG_GLOB_CMD,
.has_paging = false, .has_paging = false,
.read_delay = 5, .read_delay = 5,
.write_delay = 5, .write_delay = 5,
...@@ -439,7 +409,7 @@ static int adis16460_probe(struct spi_device *spi) ...@@ -439,7 +409,7 @@ static int adis16460_probe(struct spi_device *spi)
adis16460_enable_irq(&st->adis, 0); adis16460_enable_irq(&st->adis, 0);
ret = adis16460_initial_setup(indio_dev); ret = __adis_initial_startup(&st->adis);
if (ret) if (ret)
goto error_cleanup_buffer; goto error_cleanup_buffer;
......
This diff is collapsed.
...@@ -97,7 +97,8 @@ int adis_update_scan_mode(struct iio_dev *indio_dev, ...@@ -97,7 +97,8 @@ int adis_update_scan_mode(struct iio_dev *indio_dev,
if (j != scan_count) if (j != scan_count)
adis->xfer[j].cs_change = 1; adis->xfer[j].cs_change = 1;
adis->xfer[j].len = 2; adis->xfer[j].len = 2;
adis->xfer[j].delay_usecs = adis->data->read_delay; adis->xfer[j].delay.value = adis->data->read_delay;
adis->xfer[j].delay.unit = SPI_DELAY_UNIT_USECS;
if (j < scan_count) if (j < scan_count)
adis->xfer[j].tx_buf = &tx[j]; adis->xfer[j].tx_buf = &tx[j];
if (j >= 1) if (j >= 1)
......
...@@ -15,9 +15,9 @@ config INV_MPU6050_I2C ...@@ -15,9 +15,9 @@ config INV_MPU6050_I2C
select INV_MPU6050_IIO select INV_MPU6050_IIO
select REGMAP_I2C select REGMAP_I2C
help help
This driver supports the Invensense MPU6050/6500/6515, This driver supports the Invensense MPU6050/9150,
MPU9150/9250/9255 and ICM20608/20602 motion tracking devices MPU6500/6515/9250/9255, ICM20608/20609/20689, ICM20602/ICM20690 and
over I2C. IAM20680 motion tracking devices over I2C.
This driver can be built as a module. The module will be called This driver can be built as a module. The module will be called
inv-mpu6050-i2c. inv-mpu6050-i2c.
...@@ -27,8 +27,8 @@ config INV_MPU6050_SPI ...@@ -27,8 +27,8 @@ config INV_MPU6050_SPI
select INV_MPU6050_IIO select INV_MPU6050_IIO
select REGMAP_SPI select REGMAP_SPI
help help
This driver supports the Invensense MPU6000/6500/6515, This driver supports the Invensense MPU6000,
MPU9250/9255 and ICM20608/20602 motion tracking devices MPU6500/6515/9250/9255, ICM20608/20609/20689, ICM20602/ICM20690 and
over SPI. IAM20680 motion tracking devices over SPI.
This driver can be built as a module. The module will be called This driver can be built as a module. The module will be called
inv-mpu6050-spi. inv-mpu6050-spi.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -44,9 +44,6 @@ ...@@ -44,9 +44,6 @@
#define INV_MPU_MAGN_REG_ASAY 0x11 #define INV_MPU_MAGN_REG_ASAY 0x11
#define INV_MPU_MAGN_REG_ASAZ 0x12 #define INV_MPU_MAGN_REG_ASAZ 0x12
/* Magnetometer maximum frequency */
#define INV_MPU_MAGN_FREQ_HZ_MAX 50
static bool inv_magn_supported(const struct inv_mpu6050_state *st) static bool inv_magn_supported(const struct inv_mpu6050_state *st)
{ {
switch (st->chip_type) { switch (st->chip_type) {
...@@ -316,59 +313,32 @@ int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st) ...@@ -316,59 +313,32 @@ int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st)
* *
* Returns 0 on success, a negative error code otherwise * Returns 0 on success, a negative error code otherwise
*/ */
int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val) int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val)
{ {
unsigned int user_ctrl, status; unsigned int status;
__be16 data[3]; __be16 data;
uint8_t addr; uint8_t addr;
uint8_t d;
unsigned int period_ms;
int ret; int ret;
/* quit if chip is not supported */ /* quit if chip is not supported */
if (!inv_magn_supported(st)) if (!inv_magn_supported(st))
return -ENODEV; return -ENODEV;
/* Mag data: X - Y - Z */ /* Mag data: XH,XL,YH,YL,ZH,ZL */
switch (axis) { switch (axis) {
case IIO_MOD_X: case IIO_MOD_X:
addr = 0; addr = 0;
break; break;
case IIO_MOD_Y: case IIO_MOD_Y:
addr = 1; addr = 2;
break; break;
case IIO_MOD_Z: case IIO_MOD_Z:
addr = 2; addr = 4;
break; break;
default: default:
return -EINVAL; return -EINVAL;
} }
addr += INV_MPU6050_REG_EXT_SENS_DATA;
/* set sample rate to max mag freq */
d = INV_MPU6050_FIFO_RATE_TO_DIVIDER(INV_MPU_MAGN_FREQ_HZ_MAX);
ret = regmap_write(st->map, st->reg->sample_rate_div, d);
if (ret)
return ret;
/* start i2c master, wait for xfer, stop */
user_ctrl = st->chip_config.user_ctrl | INV_MPU6050_BIT_I2C_MST_EN;
ret = regmap_write(st->map, st->reg->user_ctrl, user_ctrl);
if (ret)
return ret;
/* need to wait 2 periods + half-period margin */
period_ms = 1000 / INV_MPU_MAGN_FREQ_HZ_MAX;
msleep(period_ms * 2 + period_ms / 2);
user_ctrl = st->chip_config.user_ctrl;
ret = regmap_write(st->map, st->reg->user_ctrl, user_ctrl);
if (ret)
return ret;
/* restore sample rate */
d = st->chip_config.divider;
ret = regmap_write(st->map, st->reg->sample_rate_div, d);
if (ret)
return ret;
/* check i2c status and read raw data */ /* check i2c status and read raw data */
ret = regmap_read(st->map, INV_MPU6050_REG_I2C_MST_STATUS, &status); ret = regmap_read(st->map, INV_MPU6050_REG_I2C_MST_STATUS, &status);
...@@ -379,12 +349,11 @@ int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val) ...@@ -379,12 +349,11 @@ int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val)
status & INV_MPU6050_BIT_I2C_SLV1_NACK) status & INV_MPU6050_BIT_I2C_SLV1_NACK)
return -EIO; return -EIO;
ret = regmap_bulk_read(st->map, INV_MPU6050_REG_EXT_SENS_DATA, ret = regmap_bulk_read(st->map, addr, &data, sizeof(data));
data, sizeof(data));
if (ret) if (ret)
return ret; return ret;
*val = (int16_t)be16_to_cpu(data[addr]); *val = (int16_t)be16_to_cpu(data);
return IIO_VAL_INT; return IIO_VAL_INT;
} }
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
#include "inv_mpu_iio.h" #include "inv_mpu_iio.h"
/* Magnetometer maximum frequency */
#define INV_MPU_MAGN_FREQ_HZ_MAX 50
int inv_mpu_magn_probe(struct inv_mpu6050_state *st); int inv_mpu_magn_probe(struct inv_mpu6050_state *st);
/** /**
...@@ -31,6 +34,6 @@ int inv_mpu_magn_set_rate(const struct inv_mpu6050_state *st, int fifo_rate); ...@@ -31,6 +34,6 @@ int inv_mpu_magn_set_rate(const struct inv_mpu6050_state *st, int fifo_rate);
int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st); int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st);
int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val); int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val);
#endif /* INV_MPU_MAGN_H_ */ #endif /* INV_MPU_MAGN_H_ */
This diff is collapsed.
This diff is collapsed.
...@@ -230,8 +230,8 @@ enum st_lsm6dsx_ext_sensor_id { ...@@ -230,8 +230,8 @@ enum st_lsm6dsx_ext_sensor_id {
* @i2c_addr: I2c slave address list. * @i2c_addr: I2c slave address list.
* @wai: Wai address info. * @wai: Wai address info.
* @id: external sensor id. * @id: external sensor id.
* @odr: Output data rate of the sensor [Hz]. * @odr_table: Output data rate of the sensor [Hz].
* @gain: Configured sensor sensitivity. * @fs_table: Configured sensor sensitivity table depending on full scale.
* @temp_comp: Temperature compensation register info (addr + mask). * @temp_comp: Temperature compensation register info (addr + mask).
* @pwr_table: Power on register info (addr + mask). * @pwr_table: Power on register info (addr + mask).
* @off_canc: Offset cancellation register info (addr + mask). * @off_canc: Offset cancellation register info (addr + mask).
......
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.
This diff is collapsed.
This diff is collapsed.
...@@ -4,5 +4,4 @@ ...@@ -4,5 +4,4 @@
# #
obj-$(CONFIG_AD7816) += ad7816.o obj-$(CONFIG_AD7816) += ad7816.o
obj-$(CONFIG_AD7192) += ad7192.o
obj-$(CONFIG_AD7280) += ad7280a.o obj-$(CONFIG_AD7280) += ad7280a.o
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