Staging/IIO driver patches for 5.8-rc1

Here is the large set of staging and IIO driver changes for 5.8-rc1
 
 Nothing major, but a lot of new IIO drivers are included in here, along
 with other core iio cleanups and changes.
 
 On the staging driver front, again, nothing noticable.  No new deletions
 or additions, just a ton of tiny cleanups all over the tree done by a
 lot of different people.  Most coding style, but many actual real fixes
 and cleanups that are nice to see.
 
 All of these have been in linux-next for a while with no reported
 issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXtzoAQ8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ym9FwCgkW8WZJGnvHLjuuG8C01azCEh/KUAoJRji8jK
 4zCG8NxAPFsQ1QP2SZPq
 =jEyw
 -----END PGP SIGNATURE-----

Merge tag 'staging-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull staging/IIO driver updates from Greg KH:
 "Here is the large set of staging and IIO driver changes for 5.8-rc1

  Nothing major, but a lot of new IIO drivers are included in here,
  along with other core iio cleanups and changes.

  On the staging driver front, again, nothing noticable. No new
  deletions or additions, just a ton of tiny cleanups all over the tree
  done by a lot of different people. Most coding style, but many actual
  real fixes and cleanups that are nice to see.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'staging-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (618 commits)
  staging: rtl8723bs: Use common packet header constants
  staging: sm750fb: Add names to proc_setBLANK args
  staging: most: usb: init return value in default path of switch/case expression
  staging: vchiq: Get rid of VCHIQ_SERVICE_OPENEND callback reason
  staging: vchiq: move vchiq_release_message() into vchiq
  staging: vchi: Get rid of C++ guards
  staging: vchi: Get rid of not implemented function declarations
  staging: vchi: Get rid of vchiq_status_to_vchi()
  staging: vchi: Get rid of vchi_service_set_option()
  staging: vchi: Merge vchi_msg_queue() into vchi_queue_kernel_message()
  staging: vchiq: Move copy callback handling into vchiq
  staging: vchi: Get rid of vchi_queue_user_message()
  staging: vchi: Get rid of vchi_service_destroy()
  staging: most: usb: use function sysfs_streq
  staging: most: usb: add missing put_device calls
  staging: most: usb: use correct error codes
  staging: most: usb: replace code to calculate array index
  staging: most: usb: don't use error path to exit function on success
  staging: most: usb: move allocation of URB out of critical section
  staging: most: usb: return 0 instead of variable
  ...
This commit is contained in:
Linus Torvalds 2020-06-07 10:45:08 -07:00
commit 80ef846e99
355 changed files with 13196 additions and 9070 deletions

View File

@ -0,0 +1,10 @@
What: /sys/bus/iio/devices/iio:deviceX/in_proximity_nearlevel
Date: March 2020
KernelVersion: 5.7
Contact: linux-iio@vger.kernel.org
Description:
Near level for proximity sensors. This is a single integer
value that tells user space when an object should be
considered close to the device. If the value read from the
sensor is above or equal to the value in this file an object
should typically be considered near.

View File

@ -0,0 +1,10 @@
What: /sys/bus/iio/devices/iio:deviceX/in_proximity3_comb_raw
Date: February 2019
KernelVersion: 5.6
Contact: Daniel Campello <campello@chromium.org>
Description:
Proximity measurement indicating that some object is
near the combined sensor. The combined sensor presents
proximity measurements constructed by hardware by
combining measurements taken from a given set of
physical sensors.

View File

@ -1,14 +1,14 @@
What: /sys/bus/most/devices/.../description
What: /sys/bus/most/devices/<dev>/description
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
Provides information about the interface type and the physical
location of the device. Hardware attached via USB, for instance,
Provides information about the physical location of the
device. Hardware attached via USB, for instance,
might return <1-1.1:1.0>
Users:
What: /sys/bus/most/devices/.../interface
What: /sys/bus/most/devices/<dev>/interface
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -16,7 +16,7 @@ Description:
Indicates the type of peripheral interface the device uses.
Users:
What: /sys/bus/most/devices/.../dci
What: /sys/bus/most/devices/<dev>/dci
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -26,7 +26,7 @@ Description:
write the controller's DCI registers.
Users:
What: /sys/bus/most/devices/.../dci/arb_address
What: /sys/bus/most/devices/<dev>/dci/arb_address
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -35,7 +35,7 @@ Description:
application wants to read from or write to.
Users:
What: /sys/bus/most/devices/.../dci/arb_value
What: /sys/bus/most/devices/<dev>/dci/arb_value
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -44,7 +44,7 @@ Description:
is stored in arb_address.
Users:
What: /sys/bus/most/devices/.../dci/mep_eui48_hi
What: /sys/bus/most/devices/<dev>/dci/mep_eui48_hi
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -52,7 +52,7 @@ Description:
This is used to check and configure the MAC address.
Users:
What: /sys/bus/most/devices/.../dci/mep_eui48_lo
What: /sys/bus/most/devices/<dev>/dci/mep_eui48_lo
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -60,7 +60,7 @@ Description:
This is used to check and configure the MAC address.
Users:
What: /sys/bus/most/devices/.../dci/mep_eui48_mi
What: /sys/bus/most/devices/<dev>/dci/mep_eui48_mi
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -68,7 +68,7 @@ Description:
This is used to check and configure the MAC address.
Users:
What: /sys/bus/most/devices/.../dci/mep_filter
What: /sys/bus/most/devices/<dev>/dci/mep_filter
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -76,7 +76,7 @@ Description:
This is used to check and configure the MEP filter address.
Users:
What: /sys/bus/most/devices/.../dci/mep_hash0
What: /sys/bus/most/devices/<dev>/dci/mep_hash0
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -84,7 +84,7 @@ Description:
This is used to check and configure the MEP hash table.
Users:
What: /sys/bus/most/devices/.../dci/mep_hash1
What: /sys/bus/most/devices/<dev>/dci/mep_hash1
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -92,7 +92,7 @@ Description:
This is used to check and configure the MEP hash table.
Users:
What: /sys/bus/most/devices/.../dci/mep_hash2
What: /sys/bus/most/devices/<dev>/dci/mep_hash2
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -100,7 +100,7 @@ Description:
This is used to check and configure the MEP hash table.
Users:
What: /sys/bus/most/devices/.../dci/mep_hash3
What: /sys/bus/most/devices/<dev>/dci/mep_hash3
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -108,7 +108,7 @@ Description:
This is used to check and configure the MEP hash table.
Users:
What: /sys/bus/most/devices/.../dci/ni_state
What: /sys/bus/most/devices/<dev>/dci/ni_state
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -116,7 +116,7 @@ Description:
Indicates the current network interface state.
Users:
What: /sys/bus/most/devices/.../dci/node_address
What: /sys/bus/most/devices/<dev>/dci/node_address
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -124,7 +124,7 @@ Description:
Indicates the current node address.
Users:
What: /sys/bus/most/devices/.../dci/node_position
What: /sys/bus/most/devices/<dev>/dci/node_position
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -132,7 +132,7 @@ Description:
Indicates the current node position.
Users:
What: /sys/bus/most/devices/.../dci/packet_bandwidth
What: /sys/bus/most/devices/<dev>/dci/packet_bandwidth
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -140,7 +140,7 @@ Description:
Indicates the configured packet bandwidth.
Users:
What: /sys/bus/most/devices/.../dci/sync_ep
What: /sys/bus/most/devices/<dev>/dci/sync_ep
Date: June 2016
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -149,7 +149,7 @@ Description:
endpoint.
Users:
What: /sys/bus/most/devices/.../<channel>/
What: /sys/bus/most/devices/<dev>/<channel>/
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
@ -160,91 +160,92 @@ Description:
configure it.
Users:
What: /sys/bus/most/devices/.../<channel>/available_datatypes
What: /sys/bus/most/devices/<dev>/<channel>/available_datatypes
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
Indicates the data types the current channel can transport.
Indicates the data types the channel can transport.
Users:
What: /sys/bus/most/devices/.../<channel>/available_directions
What: /sys/bus/most/devices/<dev>/<channel>/available_directions
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
Indicates the directions the current channel is capable of.
Indicates the directions the channel is capable of.
Users:
What: /sys/bus/most/devices/.../<channel>/number_of_packet_buffers
What: /sys/bus/most/devices/<dev>/<channel>/number_of_packet_buffers
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
Indicates the number of packet buffers the current channel can
Indicates the number of packet buffers the channel can
handle.
Users:
What: /sys/bus/most/devices/.../<channel>/number_of_stream_buffers
What: /sys/bus/most/devices/<dev>/<channel>/number_of_stream_buffers
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
Indicates the number of streaming buffers the current channel can
Indicates the number of streaming buffers the channel can
handle.
Users:
What: /sys/bus/most/devices/.../<channel>/size_of_packet_buffer
What: /sys/bus/most/devices/<dev>/<channel>/size_of_packet_buffer
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
Indicates the size of a packet buffer the current channel can
Indicates the size of a packet buffer the channel can
handle.
Users:
What: /sys/bus/most/devices/.../<channel>/size_of_stream_buffer
What: /sys/bus/most/devices/<dev>/<channel>/size_of_stream_buffer
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
Indicates the size of a streaming buffer the current channel can
Indicates the size of a streaming buffer the channel can
handle.
Users:
What: /sys/bus/most/devices/.../<channel>/set_number_of_buffers
What: /sys/bus/most/devices/<dev>/<channel>/set_number_of_buffers
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
This is to configure the number of buffers of the current channel.
This is to read back the configured number of buffers of
the channel.
Users:
What: /sys/bus/most/devices/.../<channel>/set_buffer_size
What: /sys/bus/most/devices/<dev>/<channel>/set_buffer_size
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
This is to configure the size of a buffer of the current channel.
This is to read back the configured buffer size of the channel.
Users:
What: /sys/bus/most/devices/.../<channel>/set_direction
What: /sys/bus/most/devices/<dev>/<channel>/set_direction
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
This is to configure the direction of the current channel.
This is to read back the configured direction of the channel.
The following strings will be accepted:
'dir_tx',
'dir_rx'
'tx',
'rx'
Users:
What: /sys/bus/most/devices/.../<channel>/set_datatype
What: /sys/bus/most/devices/<dev>/<channel>/set_datatype
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
This is to configure the data type of the current channel.
This is to read back the configured data type of the channel.
The following strings will be accepted:
'control',
'async',
@ -252,30 +253,31 @@ Description:
'isoc_avp'
Users:
What: /sys/bus/most/devices/.../<channel>/set_subbuffer_size
What: /sys/bus/most/devices/<dev>/<channel>/set_subbuffer_size
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
This is to configure the subbuffer size of the current channel.
This is to read back the configured subbuffer size of
the channel.
Users:
What: /sys/bus/most/devices/.../<channel>/set_packets_per_xact
What: /sys/bus/most/devices/<dev>/<channel>/set_packets_per_xact
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
This is to configure the number of packets per transaction of
the current channel. This is only needed network interface
controller is attached via USB.
This is to read back the configured number of packets per
transaction of the channel. This is only applicable when
connected via USB.
Users:
What: /sys/bus/most/devices/.../<channel>/channel_starving
What: /sys/bus/most/devices/<dev>/<channel>/channel_starving
Date: March 2017
KernelVersion: 4.15
Contact: Christian Gromm <christian.gromm@microchip.com>
Description:
Indicates whether current channel ran out of buffers.
Indicates whether channel ran out of buffers.
Users:
What: /sys/bus/most/drivers/most_core/components

View File

@ -1,15 +1,21 @@
* Bosch BMA180 / BMA25x triaxial acceleration sensor
* Bosch BMA023 / BMA150/ BMA180 / BMA25x / SMB380 triaxial acceleration sensor
https://media.digikey.com/pdf/Data%20Sheets/Bosch/BMA150.pdf
http://omapworld.com/BMA180_111_1002839.pdf
http://ae-bst.resource.bosch.com/media/products/dokumente/bma250/bst-bma250-ds002-05.pdf
Required properties:
- compatible : should be one of:
"bosch,bma023"
"bosch,bma150"
"bosch,bma180"
"bosch,bma250"
"bosch,bma254"
"bosch,smb380"
- reg : the I2C address of the sensor
- vdd-supply : regulator phandle connected to the VDD pin
- vddio-supply : regulator phandle connected to the VDDIO pin
Optional properties:

View File

@ -0,0 +1,65 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/adi,ad9467.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AD9467 High-Speed ADC
maintainers:
- Michael Hennerich <michael.hennerich@analog.com>
- Alexandru Ardelean <alexandru.ardelean@analog.com>
description: |
The AD9467 is a 16-bit, monolithic, IF sampling analog-to-digital
converter (ADC).
https://www.analog.com/media/en/technical-documentation/data-sheets/AD9467.pdf
properties:
compatible:
enum:
- adi,ad9467
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
items:
- const: adc-clk
powerdown-gpios:
description:
Pin that controls the powerdown mode of the device.
maxItems: 1
reset-gpios:
description:
Reset pin for the device.
maxItems: 1
required:
- compatible
- reg
- clocks
- clock-names
additionalProperties: false
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "adi,ad9467";
reg = <0>;
clocks = <&adc_clk>;
clock-names = "adc-clk";
};
};
...

View File

@ -0,0 +1,62 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/adi,axi-adc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AXI ADC IP core
maintainers:
- Michael Hennerich <michael.hennerich@analog.com>
- Alexandru Ardelean <alexandru.ardelean@analog.com>
description: |
Analog Devices Generic AXI ADC IP core for interfacing an ADC device
with a high speed serial (JESD204B/C) or source synchronous parallel
interface (LVDS/CMOS).
Usually, some other interface type (i.e SPI) is used as a control
interface for the actual ADC, while this IP core will interface
to the data-lines of the ADC and handle the streaming of data into
memory via DMA.
https://wiki.analog.com/resources/fpga/docs/axi_adc_ip
properties:
compatible:
enum:
- adi,axi-adc-10.0.a
reg:
maxItems: 1
dmas:
maxItems: 1
dma-names:
items:
- const: rx
adi,adc-dev:
$ref: /schemas/types.yaml#/definitions/phandle
description:
A reference to a the actual ADC to which this FPGA ADC interfaces to.
required:
- compatible
- dmas
- reg
- adi,adc-dev
additionalProperties: false
examples:
- |
axi-adc@44a00000 {
compatible = "adi,axi-adc-10.0.a";
reg = <0x44a00000 0x10000>;
dmas = <&rx_dma 0>;
dma-names = "rx";
adi,adc-dev = <&spi_adc>;
};
...

View File

@ -0,0 +1,63 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2020 Alexandru Lazar
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/maxim,max1241.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim MAX1241 12-bit, single-channel analog to digital converter
maintainers:
- Alexandru Lazar <alazar@startmail.com>
description: |
Bindings for the max1241 12-bit, single-channel ADC device. Datasheet
can be found at:
https://datasheets.maximintegrated.com/en/ds/MAX1240-MAX1241.pdf
properties:
compatible:
enum:
- maxim,max1241
reg:
maxItems: 1
vdd-supply:
description:
Device tree identifier of the regulator that powers the ADC.
vref-supply:
description:
Device tree identifier of the regulator that provides the external
reference voltage.
shutdown-gpios:
description:
GPIO spec for the GPIO pin connected to the ADC's /SHDN pin. If
specified, the /SHDN pin will be asserted between conversions,
thus enabling power-down mode.
maxItems: 1
required:
- compatible
- reg
- vdd-supply
- vref-supply
examples:
- |
#include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "maxim,max1241";
reg = <0>;
vdd-supply = <&adc_vdd>;
vref-supply = <&adc_vref>;
spi-max-frequency = <1000000>;
shutdown-gpios = <&gpio 26 1>;
};
};

View File

@ -1,37 +0,0 @@
Rockchip Successive Approximation Register (SAR) A/D Converter bindings
Required properties:
- compatible: should be "rockchip,<name>-saradc" or "rockchip,rk3066-tsadc"
- "rockchip,saradc": for rk3188, rk3288
- "rockchip,rk3066-tsadc": for rk3036
- "rockchip,rk3328-saradc", "rockchip,rk3399-saradc": for rk3328
- "rockchip,rk3399-saradc": for rk3399
- "rockchip,rv1108-saradc", "rockchip,rk3399-saradc": for rv1108
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: The interrupt number to the cpu. The interrupt specifier format
depends on the interrupt controller.
- clocks: Must contain an entry for each entry in clock-names.
- clock-names: Shall be "saradc" for the converter-clock, and "apb_pclk" for
the peripheral clock.
- vref-supply: The regulator supply ADC reference voltage.
- #io-channel-cells: Should be 1, see ../iio-bindings.txt
Optional properties:
- resets: Must contain an entry for each entry in reset-names if need support
this option. See ../reset/reset.txt for details.
- reset-names: Must include the name "saradc-apb".
Example:
saradc: saradc@2006c000 {
compatible = "rockchip,saradc";
reg = <0x2006c000 0x100>;
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
clock-names = "saradc", "apb_pclk";
resets = <&cru SRST_SARADC>;
reset-names = "saradc-apb";
#io-channel-cells = <1>;
vref-supply = <&vcc18>;
};

View File

@ -0,0 +1,80 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/rockchip-saradc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rockchip Successive Approximation Register (SAR) A/D Converter
maintainers:
- Heiko Stuebner <heiko@sntech.de>
properties:
compatible:
oneOf:
- const: rockchip,saradc
- const: rockchip,rk3066-tsadc
- const: rockchip,rk3399-saradc
- items:
- enum:
- rockchip,px30-saradc
- rockchip,rk3308-saradc
- rockchip,rk3328-saradc
- rockchip,rv1108-saradc
- const: rockchip,rk3399-saradc
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: converter clock
- description: peripheral clock
clock-names:
items:
- const: saradc
- const: apb_pclk
resets:
maxItems: 1
reset-names:
const: saradc-apb
vref-supply:
description:
The regulator supply for the ADC reference voltage.
"#io-channel-cells":
const: 1
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- vref-supply
- "#io-channel-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/rk3288-cru.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
saradc: saradc@2006c000 {
compatible = "rockchip,saradc";
reg = <0x2006c000 0x100>;
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
clock-names = "saradc", "apb_pclk";
resets = <&cru SRST_SARADC>;
reset-names = "saradc-apb";
vref-supply = <&vcc18>;
#io-channel-cells = <1>;
};

View File

@ -0,0 +1,53 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/chemical/ams,ccs811.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: AMS CCS811 VOC Sensor
maintainers:
- Narcisa Vasile <narcisaanamaria12@gmail.com>
description: |
Ultra-Low Power Digital Gas Sensor for Monitoring Indoor Air Quality.
properties:
compatible:
enum:
- ams,ccs811
reg:
maxItems: 1
reset-gpios:
description: GPIO connected to the nRESET line. This is an active low
input to CCS811.
maxItems: 1
wakeup-gpios:
description: GPIO connected to the nWAKE line. This is an active low
input to CCS811.
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
voc@5b {
compatible = "ams,ccs811";
reg = <0x5b>;
reset-gpios = <&gpioa 11 GPIO_ACTIVE_LOW>;
wakeup-gpios = <&gpioa 12 GPIO_ACTIVE_LOW>;
};
};
...

View File

@ -4,19 +4,21 @@
$id: http://devicetree.org/schemas/iio/chemical/atlas,sensor.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Atlas Scientific OEM sensors
title: Atlas Scientific OEM + EZO sensors
maintainers:
- Matt Ranostay <matt.ranostay@konsulko.com>
description: |
Atlas Scientific OEM sensors connected via I2C
Atlas Scientific OEM + EZO 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
http://www.atlas-scientific.com/_files/_datasheets/_oem/RTD_oem_datasheet.pdf
http://www.atlas-scientific.com/_files/_datasheets/_probe/EZO_CO2_Datasheet.pdf
properties:
compatible:
@ -25,6 +27,8 @@ properties:
- atlas,ec-sm
- atlas,orp-sm
- atlas,ph-sm
- atlas,rtd-sm
- atlas,co2-ezo
reg:
maxItems: 1

View File

@ -0,0 +1,35 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/common.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Common properties for iio sensors
maintainers:
- Jonathan Cameron <jic23@kernel.org>
- Guido Günther <agx@sigxcpu.org>
description: |
This document defines device tree properties common to several iio
sensors. It doesn't constitue a device tree binding specification by itself but
is meant to be referenced by device tree bindings.
When referenced from sensor tree bindings the properties defined in this
document are defined as follows. The sensor tree bindings are responsible for
defining whether each property is required or optional.
properties:
proximity-near-level:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
For proximity sensors whether an object can be considered near to the
device depends on parameters like sensor position, covering glass and
aperture. This value gives an indication to userspace for which
sensor readings this is the case.
Raw proximity values equal or above this level should be
considered 'near' to the device (an object is near to the
sensor).
...

View File

@ -1,4 +1,4 @@
Linear Technology LTC2632/2636 DAC
Linear Technology LTC2632/2634/2636 DAC
Required properties:
- compatible: Has to contain one of the following:
@ -8,6 +8,12 @@ Required properties:
lltc,ltc2632-h12
lltc,ltc2632-h10
lltc,ltc2632-h8
lltc,ltc2634-l12
lltc,ltc2634-l10
lltc,ltc2634-l8
lltc,ltc2634-h12
lltc,ltc2634-h10
lltc,ltc2634-h8
lltc,ltc2636-l12
lltc,ltc2636-l10
lltc,ltc2636-l8

View File

@ -1,63 +0,0 @@
STMicroelectronics STM32 DAC
The STM32 DAC is a 12-bit voltage output digital-to-analog converter. The DAC
may be configured in 8 or 12-bit mode. It has two output channels, each with
its own converter.
It has built-in noise and triangle waveform generator and supports external
triggers for conversions. The DAC's output buffer allows a high drive output
current.
Contents of a stm32 dac root node:
-----------------------------------
Required properties:
- compatible: Should be one of:
"st,stm32f4-dac-core"
"st,stm32h7-dac-core"
- reg: Offset and length of the device's register set.
- clocks: Must contain an entry for pclk (which feeds the peripheral bus
interface)
- clock-names: Must be "pclk".
- vref-supply: Phandle to the vref+ input analog reference supply.
- #address-cells = <1>;
- #size-cells = <0>;
Optional properties:
- resets: Must contain the phandle to the reset controller.
- A pinctrl state named "default" for each DAC channel may be defined to set
DAC_OUTx pin in mode of operation for analog output on external pin.
Contents of a stm32 dac child node:
-----------------------------------
DAC core node should contain at least one subnode, representing a
DAC instance/channel available on the machine.
Required properties:
- compatible: Must be "st,stm32-dac".
- reg: Must be either 1 or 2, to define (single) channel in use
- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
Documentation/devicetree/bindings/iio/iio-bindings.txt
Example:
dac: dac@40007400 {
compatible = "st,stm32h7-dac-core";
reg = <0x40007400 0x400>;
clocks = <&clk>;
clock-names = "pclk";
vref-supply = <&reg_vref>;
pinctrl-names = "default";
pinctrl-0 = <&dac_out1 &dac_out2>;
#address-cells = <1>;
#size-cells = <0>;
dac1: dac@1 {
compatible = "st,stm32-dac";
#io-channels-cells = <1>;
reg = <1>;
};
dac2: dac@2 {
compatible = "st,stm32-dac";
#io-channels-cells = <1>;
reg = <2>;
};
};

View File

@ -0,0 +1,110 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/iio/dac/st,stm32-dac.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: STMicroelectronics STM32 DAC bindings
description: |
The STM32 DAC is a 12-bit voltage output digital-to-analog converter. The DAC
may be configured in 8 or 12-bit mode. It has two output channels, each with
its own converter.
It has built-in noise and triangle waveform generator and supports external
triggers for conversions. The DAC's output buffer allows a high drive output
current.
maintainers:
- Fabrice Gasnier <fabrice.gasnier@st.com>
properties:
compatible:
enum:
- st,stm32f4-dac-core
- st,stm32h7-dac-core
reg:
maxItems: 1
resets:
maxItems: 1
clocks:
maxItems: 1
clock-names:
items:
- const: pclk
vref-supply:
description: Phandle to the vref input analog reference voltage.
'#address-cells':
const: 1
'#size-cells':
const: 0
additionalProperties: false
required:
- compatible
- reg
- clocks
- clock-names
- vref-supply
- '#address-cells'
- '#size-cells'
patternProperties:
"^dac@[1-2]+$":
type: object
description:
A DAC block node should contain at least one subnode, representing an
DAC instance/channel available on the machine.
properties:
compatible:
const: st,stm32-dac
reg:
description: Must be either 1 or 2, to define (single) channel in use
enum: [1, 2]
'#io-channel-cells':
const: 1
additionalProperties: false
required:
- compatible
- reg
- '#io-channel-cells'
examples:
- |
// Example on stm32mp157c
#include <dt-bindings/clock/stm32mp1-clks.h>
dac: dac@40017000 {
compatible = "st,stm32h7-dac-core";
reg = <0x40017000 0x400>;
clocks = <&rcc DAC12>;
clock-names = "pclk";
vref-supply = <&vref>;
#address-cells = <1>;
#size-cells = <0>;
dac@1 {
compatible = "st,stm32-dac";
#io-channel-cells = <1>;
reg = <1>;
};
dac@2 {
compatible = "st,stm32-dac";
#io-channel-cells = <1>;
reg = <2>;
};
};
...

View File

@ -2,7 +2,7 @@
Required properties:
- compatible : should be "bosch,bmg160" or "bosch,bmi055_gyro"
- compatible : should be "bosch,bmg160", "bosch,bmi055_gyro" or "bosch,bmi088_gyro"
- reg : the I2C address of the sensor (0x69)
Optional properties:

View File

@ -0,0 +1,137 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/imu/adi,adis16475.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices ADIS16475 and similar IMUs
maintainers:
- Nuno Sá <nuno.sa@analog.com>
description: |
Analog Devices ADIS16475 and similar IMUs
https://www.analog.com/media/en/technical-documentation/data-sheets/ADIS16475.pdf
properties:
compatible:
enum:
- adi,adis16475-1
- adi,adis16475-2
- adi,adis16475-3
- adi,adis16477-1
- adi,adis16477-2
- adi,adis16477-3
- adi,adis16470
- adi,adis16465-1
- adi,adis16465-2
- adi,adis16465-3
- adi,adis16467-1
- adi,adis16467-2
- adi,adis16467-3
- adi,adis16500
- adi,adis16505-1
- adi,adis16505-2
- adi,adis16505-3
- adi,adis16507-1
- adi,adis16507-2
- adi,adis16507-3
reg:
maxItems: 1
spi-cpha: true
spi-cpol: true
spi-max-frequency:
maximum: 2000000
interrupts:
maxItems: 1
clocks:
maxItems: 1
reset-gpios:
description:
Must be the device tree identifier of the RESET pin. If specified,
it will be asserted during driver probe. As the line is active low,
it should be marked GPIO_ACTIVE_LOW.
maxItems: 1
adi,sync-mode:
description:
Configures the device SYNC pin. The following modes are supported
0 - output_sync
1 - direct_sync
2 - scaled_sync
3 - pulse_sync
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 3
adi,scaled-output-hz:
description:
This property must be present if the clock mode is scaled-sync through
clock-names property. In this mode, the input clock can have a range
of 1Hz to 128HZ which must be scaled to originate an allowable sample
rate. This property specifies that rate.
minimum: 1900
maximum: 2100
required:
- compatible
- reg
- interrupts
- spi-cpha
- spi-cpol
allOf:
- if:
properties:
compatible:
contains:
enum:
- adi,adis16500
- adi,adis16505-1
- adi,adis16505-2
- adi,adis16505-3
- adi,adis16507-1
- adi,adis16507-2
- adi,adis16507-3
then:
properties:
adi,sync-mode:
minimum: 0
maximum: 2
- if:
properties:
adi,sync-mode:
enum: [1, 2, 3]
then:
dependencies:
adi,sync-mode: [ clocks ]
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
adis16475: adis16475-3@0 {
compatible = "adi,adis16475-3";
reg = <0>;
spi-cpha;
spi-cpol;
spi-max-frequency = <2000000>;
interrupts = <4 IRQ_TYPE_EDGE_RISING>;
interrupt-parent = <&gpio>;
};
};
...

View File

@ -0,0 +1,49 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/light/amstaos,tsl2563.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: AMS TAOS TSL2563 ambient light sensor
maintainers:
- Sebastian Reichel <sre@kernel.org>
description: |
Ambient light sensor with an i2c interface.
properties:
compatible:
enum:
- amstaos,tsl2560
- amstaos,tsl2561
- amstaos,tsl2562
- amstaos,tsl2563
reg:
maxItems: 1
amstaos,cover-comp-gain:
description: Multiplier for gain compensation
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [1, 16]
required:
- compatible
- reg
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
light-sensor@29 {
compatible = "amstaos,tsl2563";
reg = <0x29>;
amstaos,cover-comp-gain = <16>;
};
};
...

View File

@ -1,19 +0,0 @@
* AMS TAOS TSL2563 ambient light sensor
Required properties:
- compatible : should be "amstaos,tsl2563"
- reg : the I2C address of the sensor
Optional properties:
- amstaos,cover-comp-gain : integer used as multiplier for gain
compensation (default = 1)
Example:
tsl2563@29 {
compatible = "amstaos,tsl2563";
reg = <0x29>;
amstaos,cover-comp-gain = <16>;
};

View File

@ -1,24 +0,0 @@
VISHAY VCNL4000 - Ambient Light and proximity sensor
This driver supports the VCNL4000/10/20/40 and VCNL4200 chips
Required properties:
-compatible: must be one of :
vishay,vcnl4000
vishay,vcnl4010
vishay,vcnl4020
vishay,vcnl4040
vishay,vcnl4200
-reg: I2C address of the sensor, should be one from below based on the model:
0x13
0x51
0x60
Example:
light-sensor@51 {
compatible = "vishay,vcnl4200";
reg = <0x51>;
};

View File

@ -0,0 +1,50 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/light/vishay,vcnl4000.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: VISHAY VCNL4000 ambient light and proximity sensor
maintainers:
- Peter Meerwald <pmeerw@pmeerw.net>
description: |
Ambient light sensing with proximity detection over an i2c
interface.
allOf:
- $ref: ../common.yaml#
properties:
compatible:
enum:
- vishay,vcnl4000
- vishay,vcnl4010
- vishay,vcnl4020
- vishay,vcnl4040
- vishay,vcnl4200
reg:
maxItems: 1
proximity-near-level: true
required:
- compatible
- reg
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
light-sensor@51 {
compatible = "vishay,vcnl4200";
reg = <0x51>;
proximity-near-level = <220>;
};
};
...

View File

@ -2,7 +2,9 @@
Required properties:
- compatible : should be "asahi-kasei,ak8974"
- compatible:
* "asahi-kasei,ak8974"
* "alps,hscdtd008a"
- reg : the I2C address of the magnetometer
Optional properties:

View File

@ -0,0 +1,62 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/proximity/vishay,vcnl3020.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Integrated Proximity Sensor With Infrared Emitter
maintainers:
- Ivan Mikhaylov <i.mikhaylov@yadro.com>
description: |
The VCNL3020 is a fully integrated proximity sensor. Fully integrated means
that the infrared emitter is included in the package. It has 16-bit
resolution. It includes a signal processing IC and features standard I2C
communication interface. It features an interrupt function.
Specifications about the devices can be found at:
https://www.vishay.com/docs/84150/vcnl3020.pdf
properties:
compatible:
enum:
- vishay,vcnl3020
reg:
maxItems: 1
interrupts:
maxItems: 1
vdd-supply:
description: Regulator that provides power to the sensor
vddio-supply:
description: Regulator that provides power to the bus
vishay,led-current-microamp:
description:
The driver current for the LED used in proximity sensing.
enum: [0, 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000,
100000, 110000, 120000, 130000, 140000, 150000, 160000, 170000,
180000, 190000, 200000]
default: 20000
required:
- compatible
- reg
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
proximity@13 {
compatible = "vishay,vcnl3020";
reg = <0x13>;
vishay,led-current-microamp = <200000>;
};
};

View File

@ -50,6 +50,7 @@ Accelerometers:
- st,lis3dhh
- st,lis3de
- st,lis2de12
- st,lis2hh12
Gyroscopes:
- st,l3g4200d-gyro

View File

@ -284,21 +284,13 @@ I2C
IIO
devm_iio_device_alloc()
devm_iio_device_free()
devm_iio_device_register()
devm_iio_device_unregister()
devm_iio_kfifo_allocate()
devm_iio_kfifo_free()
devm_iio_triggered_buffer_setup()
devm_iio_triggered_buffer_cleanup()
devm_iio_trigger_alloc()
devm_iio_trigger_free()
devm_iio_trigger_register()
devm_iio_trigger_unregister()
devm_iio_channel_get()
devm_iio_channel_release()
devm_iio_channel_get_all()
devm_iio_channel_release_all()
INPUT
devm_input_allocate_device()

View File

@ -4,9 +4,7 @@ Triggers
* struct :c:type:`iio_trigger` — industrial I/O trigger device
* :c:func:`devm_iio_trigger_alloc` — Resource-managed iio_trigger_alloc
* :c:func:`devm_iio_trigger_free` — Resource-managed iio_trigger_free
* :c:func:`devm_iio_trigger_register` — Resource-managed iio_trigger_register
* :c:func:`devm_iio_trigger_unregister` — Resource-managed
iio_trigger_unregister
* :c:func:`iio_trigger_validate_own_device` — Check if a trigger and IIO
device belong to the same device

View File

@ -294,6 +294,7 @@ F: drivers/gpio/gpio-104-idio-16.c
ACCES 104-QUAD-8 DRIVER
M: William Breathitt Gray <vilhelm.gray@gmail.com>
M: Syed Nayyar Waris <syednwaris@gmail.com>
L: linux-iio@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-bus-counter-104-quad-8
@ -1042,6 +1043,14 @@ W: http://ez.analog.com/community/linux-device-drivers
F: Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml
F: drivers/iio/imu/adis16460.c
ANALOG DEVICES INC ADIS16475 DRIVER
M: Nuno Sa <nuno.sa@analog.com>
L: linux-iio@vger.kernel.org
W: http://ez.analog.com/community/linux-device-drivers
S: Supported
F: drivers/iio/imu/adis16475.c
F: Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml
ANALOG DEVICES INC ADM1177 DRIVER
M: Beniamin Bia <beniamin.bia@analog.com>
M: Michael Hennerich <Michael.Hennerich@analog.com>
@ -7094,6 +7103,7 @@ GASKET DRIVER FRAMEWORK
M: Rob Springer <rspringer@google.com>
M: Todd Poynor <toddpoynor@google.com>
M: Ben Chan <benchan@chromium.org>
M: Richard Yeh <rcy@google.com>
S: Maintained
F: drivers/staging/gasket/

View File

@ -89,13 +89,13 @@ config ADXL372_I2C
module will be called adxl372_i2c.
config BMA180
tristate "Bosch BMA180/BMA25x 3-Axis Accelerometer Driver"
depends on I2C
tristate "Bosch BMA023/BMA1x0/BMA25x 3-Axis Accelerometer Driver"
depends on I2C && INPUT_BMA150=n
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say Y here if you want to build a driver for the Bosch BMA180 or
BMA25x triaxial acceleration sensor.
Say Y here if you want to build a driver for the Bosch BMA023, BMA150
BMA180, SMB380, or BMA25x triaxial acceleration sensor.
To compile this driver as a module, choose M here: the
module will be called bma180.
@ -238,7 +238,7 @@ config IIO_ST_ACCEL_3AXIS
Say yes here to build support for STMicroelectronics accelerometers:
LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL,
LNG2DM, LIS3DE, LIS2DE12
LNG2DM, LIS3DE, LIS2DE12, LIS2HH12
This driver can also be built as a module. If so, these modules
will be created:

View File

@ -7,6 +7,7 @@
* Support for BMA250 (c) Peter Meerwald <pmeerw@pmeerw.net>
*
* SPI is not supported by driver
* BMA023/BMA150/SMB380: 7-bit I2C slave address 0x38
* BMA180: 7-bit I2C slave address 0x40 or 0x41
* BMA250: 7-bit I2C slave address 0x18 or 0x19
* BMA254: 7-bit I2C slave address 0x18 or 0x19
@ -33,6 +34,8 @@
#define BMA180_IRQ_NAME "bma180_event"
enum chip_ids {
BMA023,
BMA150,
BMA180,
BMA250,
BMA254,
@ -48,7 +51,7 @@ struct bma180_part_info {
unsigned int num_scales;
const int *bw_table;
unsigned int num_bw;
int center_temp;
int temp_offset;
u8 int_reset_reg, int_reset_mask;
u8 sleep_reg, sleep_mask;
@ -57,13 +60,25 @@ struct bma180_part_info {
u8 power_reg, power_mask, lowpower_val;
u8 int_enable_reg, int_enable_mask;
u8 int_map_reg, int_enable_dataready_int1_mask;
u8 softreset_reg;
u8 softreset_reg, softreset_val;
int (*chip_config)(struct bma180_data *data);
void (*chip_disable)(struct bma180_data *data);
};
/* Register set */
#define BMA023_CTRL_REG0 0x0a
#define BMA023_CTRL_REG1 0x0b
#define BMA023_CTRL_REG2 0x14
#define BMA023_CTRL_REG3 0x15
#define BMA023_RANGE_MASK GENMASK(4, 3) /* Range of accel values */
#define BMA023_BW_MASK GENMASK(2, 0) /* Accel bandwidth */
#define BMA023_SLEEP BIT(0)
#define BMA023_INT_RESET_MASK BIT(6)
#define BMA023_NEW_DATA_INT BIT(5) /* Intr every new accel data is ready */
#define BMA023_RESET_VAL BIT(1)
#define BMA180_CHIP_ID 0x00 /* Need to distinguish BMA180 from other */
#define BMA180_ACC_X_LSB 0x02 /* First of 6 registers of accel data */
#define BMA180_TEMP 0x08
@ -94,6 +109,7 @@ struct bma180_part_info {
/* We have to write this value in reset register to do soft reset */
#define BMA180_RESET_VAL 0xb6
#define BMA023_ID_REG_VAL 0x02
#define BMA180_ID_REG_VAL 0x03
#define BMA250_ID_REG_VAL 0x03
#define BMA254_ID_REG_VAL 0xfa /* 250 decimal */
@ -156,6 +172,9 @@ enum bma180_chan {
TEMP
};
static int bma023_bw_table[] = { 25, 50, 100, 190, 375, 750, 1500 }; /* Hz */
static int bma023_scale_table[] = { 2452, 4903, 9709, };
static int bma180_bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */
static int bma180_scale_table[] = { 1275, 1863, 2452, 3727, 4903, 9709, 19417 };
@ -319,7 +338,8 @@ static int bma180_set_pmode(struct bma180_data *data, bool mode)
static int bma180_soft_reset(struct bma180_data *data)
{
int ret = i2c_smbus_write_byte_data(data->client,
data->part_info->softreset_reg, BMA180_RESET_VAL);
data->part_info->softreset_reg,
data->part_info->softreset_val);
if (ret)
dev_err(&data->client->dev, "failed to reset the chip\n");
@ -349,17 +369,37 @@ static int bma180_chip_init(struct bma180_data *data)
*/
msleep(20);
ret = bma180_set_new_data_intr_state(data, false);
if (ret)
return ret;
return bma180_set_new_data_intr_state(data, false);
}
return bma180_set_pmode(data, false);
static int bma023_chip_config(struct bma180_data *data)
{
int ret = bma180_chip_init(data);
if (ret)
goto err;
ret = bma180_set_bw(data, 50); /* 50 Hz */
if (ret)
goto err;
ret = bma180_set_scale(data, 2452); /* 2 G */
if (ret)
goto err;
return 0;
err:
dev_err(&data->client->dev, "failed to config the chip\n");
return ret;
}
static int bma180_chip_config(struct bma180_data *data)
{
int ret = bma180_chip_init(data);
if (ret)
goto err;
ret = bma180_set_pmode(data, false);
if (ret)
goto err;
ret = bma180_set_bits(data, BMA180_CTRL_REG0, BMA180_DIS_WAKE_UP, 1);
@ -389,6 +429,9 @@ static int bma25x_chip_config(struct bma180_data *data)
{
int ret = bma180_chip_init(data);
if (ret)
goto err;
ret = bma180_set_pmode(data, false);
if (ret)
goto err;
ret = bma180_set_bw(data, 16); /* 16 Hz */
@ -413,6 +456,17 @@ err:
return ret;
}
static void bma023_chip_disable(struct bma180_data *data)
{
if (bma180_set_sleep_state(data, true))
goto err;
return;
err:
dev_err(&data->client->dev, "failed to disable the chip\n");
}
static void bma180_chip_disable(struct bma180_data *data)
{
if (bma180_set_new_data_intr_state(data, false))
@ -512,8 +566,12 @@ static int bma180_read_raw(struct iio_dev *indio_dev,
iio_device_release_direct_mode(indio_dev);
if (ret < 0)
return ret;
*val = sign_extend32(ret >> chan->scan_type.shift,
chan->scan_type.realbits - 1);
if (chan->scan_type.sign == 's') {
*val = sign_extend32(ret >> chan->scan_type.shift,
chan->scan_type.realbits - 1);
} else {
*val = ret;
}
return IIO_VAL_INT;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
*val = data->bw;
@ -531,7 +589,7 @@ static int bma180_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
case IIO_CHAN_INFO_OFFSET:
*val = data->part_info->center_temp;
*val = data->part_info->temp_offset;
return IIO_VAL_INT;
default:
return -EINVAL;
@ -609,6 +667,11 @@ static const struct iio_enum bma180_power_mode_enum = {
.set = bma180_set_power_mode,
};
static const struct iio_chan_spec_ext_info bma023_ext_info[] = {
IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bma180_accel_get_mount_matrix),
{ }
};
static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
IIO_ENUM("power_mode", true, &bma180_power_mode_enum),
IIO_ENUM_AVAILABLE("power_mode", &bma180_power_mode_enum),
@ -616,6 +679,35 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
{ }
};
#define BMA023_ACC_CHANNEL(_axis, _bits) { \
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = IIO_MOD_##_axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
.scan_index = AXIS_##_axis, \
.scan_type = { \
.sign = 's', \
.realbits = _bits, \
.storagebits = 16, \
.shift = 16 - _bits, \
}, \
.ext_info = bma023_ext_info, \
}
#define BMA150_TEMP_CHANNEL { \
.type = IIO_TEMP, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), \
.scan_index = TEMP, \
.scan_type = { \
.sign = 'u', \
.realbits = 8, \
.storagebits = 16, \
}, \
}
#define BMA180_ACC_CHANNEL(_axis, _bits) { \
.type = IIO_ACCEL, \
.modified = 1, \
@ -645,6 +737,21 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
}, \
}
static const struct iio_chan_spec bma023_channels[] = {
BMA023_ACC_CHANNEL(X, 10),
BMA023_ACC_CHANNEL(Y, 10),
BMA023_ACC_CHANNEL(Z, 10),
IIO_CHAN_SOFT_TIMESTAMP(4),
};
static const struct iio_chan_spec bma150_channels[] = {
BMA023_ACC_CHANNEL(X, 10),
BMA023_ACC_CHANNEL(Y, 10),
BMA023_ACC_CHANNEL(Z, 10),
BMA150_TEMP_CHANNEL,
IIO_CHAN_SOFT_TIMESTAMP(4),
};
static const struct iio_chan_spec bma180_channels[] = {
BMA180_ACC_CHANNEL(X, 14),
BMA180_ACC_CHANNEL(Y, 14),
@ -670,6 +777,63 @@ static const struct iio_chan_spec bma254_channels[] = {
};
static const struct bma180_part_info bma180_part_info[] = {
[BMA023] = {
.chip_id = BMA023_ID_REG_VAL,
.channels = bma023_channels,
.num_channels = ARRAY_SIZE(bma023_channels),
.scale_table = bma023_scale_table,
.num_scales = ARRAY_SIZE(bma023_scale_table),
.bw_table = bma023_bw_table,
.num_bw = ARRAY_SIZE(bma023_bw_table),
/* No temperature channel */
.temp_offset = 0,
.int_reset_reg = BMA023_CTRL_REG0,
.int_reset_mask = BMA023_INT_RESET_MASK,
.sleep_reg = BMA023_CTRL_REG0,
.sleep_mask = BMA023_SLEEP,
.bw_reg = BMA023_CTRL_REG2,
.bw_mask = BMA023_BW_MASK,
.scale_reg = BMA023_CTRL_REG2,
.scale_mask = BMA023_RANGE_MASK,
/* No power mode on bma023 */
.power_reg = 0,
.power_mask = 0,
.lowpower_val = 0,
.int_enable_reg = BMA023_CTRL_REG3,
.int_enable_mask = BMA023_NEW_DATA_INT,
.softreset_reg = BMA023_CTRL_REG0,
.softreset_val = BMA023_RESET_VAL,
.chip_config = bma023_chip_config,
.chip_disable = bma023_chip_disable,
},
[BMA150] = {
.chip_id = BMA023_ID_REG_VAL,
.channels = bma150_channels,
.num_channels = ARRAY_SIZE(bma150_channels),
.scale_table = bma023_scale_table,
.num_scales = ARRAY_SIZE(bma023_scale_table),
.bw_table = bma023_bw_table,
.num_bw = ARRAY_SIZE(bma023_bw_table),
.temp_offset = -60, /* 0 LSB @ -30 degree C */
.int_reset_reg = BMA023_CTRL_REG0,
.int_reset_mask = BMA023_INT_RESET_MASK,
.sleep_reg = BMA023_CTRL_REG0,
.sleep_mask = BMA023_SLEEP,
.bw_reg = BMA023_CTRL_REG2,
.bw_mask = BMA023_BW_MASK,
.scale_reg = BMA023_CTRL_REG2,
.scale_mask = BMA023_RANGE_MASK,
/* No power mode on bma150 */
.power_reg = 0,
.power_mask = 0,
.lowpower_val = 0,
.int_enable_reg = BMA023_CTRL_REG3,
.int_enable_mask = BMA023_NEW_DATA_INT,
.softreset_reg = BMA023_CTRL_REG0,
.softreset_val = BMA023_RESET_VAL,
.chip_config = bma023_chip_config,
.chip_disable = bma023_chip_disable,
},
[BMA180] = {
.chip_id = BMA180_ID_REG_VAL,
.channels = bma180_channels,
@ -678,7 +842,7 @@ static const struct bma180_part_info bma180_part_info[] = {
.num_scales = ARRAY_SIZE(bma180_scale_table),
.bw_table = bma180_bw_table,
.num_bw = ARRAY_SIZE(bma180_bw_table),
.center_temp = 48, /* 0 LSB @ 24 degree C */
.temp_offset = 48, /* 0 LSB @ 24 degree C */
.int_reset_reg = BMA180_CTRL_REG0,
.int_reset_mask = BMA180_RESET_INT,
.sleep_reg = BMA180_CTRL_REG0,
@ -693,6 +857,7 @@ static const struct bma180_part_info bma180_part_info[] = {
.int_enable_reg = BMA180_CTRL_REG3,
.int_enable_mask = BMA180_NEW_DATA_INT,
.softreset_reg = BMA180_RESET,
.softreset_val = BMA180_RESET_VAL,
.chip_config = bma180_chip_config,
.chip_disable = bma180_chip_disable,
},
@ -704,7 +869,7 @@ static const struct bma180_part_info bma180_part_info[] = {
.num_scales = ARRAY_SIZE(bma25x_scale_table),
.bw_table = bma25x_bw_table,
.num_bw = ARRAY_SIZE(bma25x_bw_table),
.center_temp = 48, /* 0 LSB @ 24 degree C */
.temp_offset = 48, /* 0 LSB @ 24 degree C */
.int_reset_reg = BMA250_INT_RESET_REG,
.int_reset_mask = BMA250_INT_RESET_MASK,
.sleep_reg = BMA250_POWER_REG,
@ -721,6 +886,7 @@ static const struct bma180_part_info bma180_part_info[] = {
.int_map_reg = BMA250_INT_MAP_REG,
.int_enable_dataready_int1_mask = BMA250_INT1_DATA_MASK,
.softreset_reg = BMA250_RESET_REG,
.softreset_val = BMA180_RESET_VAL,
.chip_config = bma25x_chip_config,
.chip_disable = bma25x_chip_disable,
},
@ -732,7 +898,7 @@ static const struct bma180_part_info bma180_part_info[] = {
.num_scales = ARRAY_SIZE(bma25x_scale_table),
.bw_table = bma25x_bw_table,
.num_bw = ARRAY_SIZE(bma25x_bw_table),
.center_temp = 46, /* 0 LSB @ 23 degree C */
.temp_offset = 46, /* 0 LSB @ 23 degree C */
.int_reset_reg = BMA254_INT_RESET_REG,
.int_reset_mask = BMA254_INT_RESET_MASK,
.sleep_reg = BMA254_POWER_REG,
@ -749,6 +915,7 @@ static const struct bma180_part_info bma180_part_info[] = {
.int_map_reg = BMA254_INT_MAP_REG,
.int_enable_dataready_int1_mask = BMA254_INT1_DATA_MASK,
.softreset_reg = BMA254_RESET_REG,
.softreset_val = BMA180_RESET_VAL,
.chip_config = bma25x_chip_config,
.chip_disable = bma25x_chip_disable,
},
@ -990,15 +1157,26 @@ static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume);
#endif
static const struct i2c_device_id bma180_ids[] = {
{ "bma023", BMA023 },
{ "bma150", BMA150 },
{ "bma180", BMA180 },
{ "bma250", BMA250 },
{ "bma254", BMA254 },
{ "smb380", BMA150 },
{ }
};
MODULE_DEVICE_TABLE(i2c, bma180_ids);
static const struct of_device_id bma180_of_match[] = {
{
.compatible = "bosch,bma023",
.data = (void *)BMA023
},
{
.compatible = "bosch,bma150",
.data = (void *)BMA150
},
{
.compatible = "bosch,bma180",
.data = (void *)BMA180
@ -1011,6 +1189,10 @@ static const struct of_device_id bma180_of_match[] = {
.compatible = "bosch,bma254",
.data = (void *)BMA254
},
{
.compatible = "bosch,smb380",
.data = (void *)BMA150
},
{ }
};
MODULE_DEVICE_TABLE(of, bma180_of_match);
@ -1030,5 +1212,5 @@ module_i2c_driver(bma180_driver);
MODULE_AUTHOR("Kravchenko Oleksandr <x0199363@ti.com>");
MODULE_AUTHOR("Texas Instruments, Inc.");
MODULE_DESCRIPTION("Bosch BMA180/BMA25x triaxial acceleration sensor");
MODULE_DESCRIPTION("Bosch BMA023/BMA1x0/BMA25x triaxial acceleration sensor");
MODULE_LICENSE("GPL");

View File

@ -6,6 +6,7 @@
*/
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
@ -226,7 +227,7 @@ static struct i2c_driver dmard06_driver = {
.id_table = dmard06_id,
.driver = {
.name = DMARD06_DRV_NAME,
.of_match_table = of_match_ptr(dmard06_of_match),
.of_match_table = dmard06_of_match,
.pm = DMARD06_PM_OPS,
},
};

View File

@ -14,8 +14,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
enum accel_3d_channel {
@ -391,18 +389,13 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
NULL, NULL);
if (ret) {
dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
goto error_free_dev_mem;
}
atomic_set(&accel_state->common_attributes.data_ready, 0);
ret = hid_sensor_setup_trigger(indio_dev, name,
&accel_state->common_attributes);
if (ret < 0) {
dev_err(&pdev->dev, "trigger setup failed\n");
goto error_unreg_buffer_funcs;
goto error_free_dev_mem;
}
ret = iio_device_register(indio_dev);
@ -426,9 +419,7 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
hid_sensor_remove_trigger(&accel_state->common_attributes);
error_unreg_buffer_funcs:
iio_triggered_buffer_cleanup(indio_dev);
hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
error_free_dev_mem:
kfree(indio_dev->channels);
return ret;
@ -443,8 +434,7 @@ static int hid_accel_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(&accel_state->common_attributes);
iio_triggered_buffer_cleanup(indio_dev);
hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
kfree(indio_dev->channels);
return 0;

View File

@ -2,6 +2,7 @@
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/delay.h>
@ -21,8 +22,8 @@ static int kxsd9_i2c_probe(struct i2c_client *i2c,
regmap = devm_regmap_init_i2c(i2c, &config);
if (IS_ERR(regmap)) {
dev_err(&i2c->dev, "Failed to register i2c regmap %d\n",
(int)PTR_ERR(regmap));
dev_err(&i2c->dev, "Failed to register i2c regmap: %pe\n",
regmap);
return PTR_ERR(regmap);
}
@ -36,15 +37,11 @@ static int kxsd9_i2c_remove(struct i2c_client *client)
return kxsd9_common_remove(&client->dev);
}
#ifdef CONFIG_OF
static const struct of_device_id kxsd9_of_match[] = {
{ .compatible = "kionix,kxsd9", },
{ },
};
MODULE_DEVICE_TABLE(of, kxsd9_of_match);
#else
#define kxsd9_of_match NULL
#endif
static const struct i2c_device_id kxsd9_i2c_id[] = {
{"kxsd9", 0},
@ -55,7 +52,7 @@ MODULE_DEVICE_TABLE(i2c, kxsd9_i2c_id);
static struct i2c_driver kxsd9_i2c_driver = {
.driver = {
.name = "kxsd9",
.of_match_table = of_match_ptr(kxsd9_of_match),
.of_match_table = kxsd9_of_match,
.pm = &kxsd9_dev_pm_ops,
},
.probe = kxsd9_i2c_probe,

View File

@ -135,7 +135,7 @@ static int mxc4005_read_xyz(struct mxc4005_data *data)
int ret;
ret = regmap_bulk_read(data->regmap, MXC4005_REG_XOUT_UPPER,
(u8 *) data->buffer, sizeof(data->buffer));
data->buffer, sizeof(data->buffer));
if (ret < 0) {
dev_err(data->dev, "failed to read axes\n");
return ret;
@ -150,7 +150,7 @@ static int mxc4005_read_axis(struct mxc4005_data *data,
__be16 reg;
int ret;
ret = regmap_bulk_read(data->regmap, addr, (u8 *) &reg, sizeof(reg));
ret = regmap_bulk_read(data->regmap, addr, &reg, sizeof(reg));
if (ret < 0) {
dev_err(data->dev, "failed to read reg %02x\n", addr);
return ret;

View File

@ -35,6 +35,7 @@ enum st_accel_type {
LIS2DW12,
LIS3DHH,
LIS2DE12,
LIS2HH12,
ST_ACCEL_MAX,
};
@ -59,6 +60,7 @@ enum st_accel_type {
#define LIS3DHH_ACCEL_DEV_NAME "lis3dhh"
#define LIS3DE_ACCEL_DEV_NAME "lis3de"
#define LIS2DE12_ACCEL_DEV_NAME "lis2de12"
#define LIS2HH12_ACCEL_DEV_NAME "lis2hh12"
/**
* struct st_sensors_platform_data - default accel platform data

View File

@ -37,8 +37,7 @@ static int st_accel_buffer_postenable(struct iio_dev *indio_dev)
if (err < 0)
return err;
err = st_sensors_set_axis_enable(indio_dev,
(u8)indio_dev->active_scan_mask[0]);
err = st_sensors_set_axis_enable(indio_dev, indio_dev->active_scan_mask[0]);
if (err < 0)
goto st_accel_buffer_predisable;

View File

@ -904,6 +904,83 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.multi_read_bit = true,
.bootime = 2,
},
{
.wai = 0x41,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LIS2HH12_ACCEL_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_accel_16bit_channels,
.odr = {
.addr = 0x20,
.mask = 0x70,
.odr_avl = {
{ .hz = 10, .value = 0x01, },
{ .hz = 50, .value = 0x02, },
{ .hz = 100, .value = 0x03, },
{ .hz = 200, .value = 0x04, },
{ .hz = 400, .value = 0x05, },
{ .hz = 800, .value = 0x06, },
},
},
.pw = {
.addr = 0x20,
.mask = 0x70,
.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
},
.enable_axis = {
.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
},
.fs = {
.addr = 0x23,
.mask = 0x30,
.fs_avl = {
[0] = {
.num = ST_ACCEL_FS_AVL_2G,
.value = 0x00,
.gain = IIO_G_TO_M_S_2(61),
},
[1] = {
.num = ST_ACCEL_FS_AVL_4G,
.value = 0x02,
.gain = IIO_G_TO_M_S_2(122),
},
[2] = {
.num = ST_ACCEL_FS_AVL_8G,
.value = 0x03,
.gain = IIO_G_TO_M_S_2(244),
},
},
},
.bdu = {
.addr = 0x20,
.mask = 0x08,
},
.drdy_irq = {
.int1 = {
.addr = 0x22,
.mask = 0x01,
},
.int2 = {
.addr = 0x25,
.mask = 0x01,
},
.addr_ihl = 0x24,
.mask_ihl = 0x02,
.stat_drdy = {
.addr = ST_SENSORS_DEFAULT_STAT_ADDR,
.mask = 0x07,
},
},
.sim = {
.addr = 0x23,
.value = BIT(0),
},
.multi_read_bit = true,
.bootime = 2,
},
};
static int st_accel_read_raw(struct iio_dev *indio_dev,
@ -1170,8 +1247,7 @@ EXPORT_SYMBOL(st_accel_get_settings);
int st_accel_common_probe(struct iio_dev *indio_dev)
{
struct st_sensor_data *adata = iio_priv(indio_dev);
struct st_sensors_platform_data *pdata =
(struct st_sensors_platform_data *)adata->dev->platform_data;
struct st_sensors_platform_data *pdata = dev_get_platdata(adata->dev);
struct iio_chan_spec *channels;
size_t channels_size;
int err;
@ -1204,8 +1280,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
"failed to apply ACPI orientation data: %d\n", err);
indio_dev->channels = channels;
adata->current_fullscale = (struct st_sensor_fullscale_avl *)
&adata->sensor_settings->fs.fs_avl[0];
adata->current_fullscale = &adata->sensor_settings->fs.fs_avl[0];
adata->odr = adata->sensor_settings->odr.odr_avl[0].hz;
if (!pdata)

View File

@ -104,6 +104,10 @@ static const struct of_device_id st_accel_of_match[] = {
.compatible = "st,lis2de12",
.data = LIS2DE12_ACCEL_DEV_NAME,
},
{
.compatible = "st,lis2hh12",
.data = LIS2HH12_ACCEL_DEV_NAME,
},
{},
};
MODULE_DEVICE_TABLE(of, st_accel_of_match);
@ -138,6 +142,7 @@ static const struct i2c_device_id st_accel_id_table[] = {
{ LIS2DW12_ACCEL_DEV_NAME },
{ LIS3DE_ACCEL_DEV_NAME },
{ LIS2DE12_ACCEL_DEV_NAME },
{ LIS2HH12_ACCEL_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(i2c, st_accel_id_table);

View File

@ -246,6 +246,41 @@ config AD799X
To compile this driver as a module, choose M here: the module will be
called ad799x.
config AD9467
tristate "Analog Devices AD9467 High Speed ADC driver"
depends on SPI
select ADI_AXI_ADC
help
Say yes here to build support for Analog Devices:
* AD9467 16-Bit, 200 MSPS/250 MSPS Analog-to-Digital Converter
The driver requires the assistance of the AXI ADC IP core to operate,
since SPI is used for configuration only, while data has to be
streamed into memory via DMA.
To compile this driver as a module, choose M here: the module will be
called ad9467.
config ADI_AXI_ADC
tristate "Analog Devices Generic AXI ADC IP core driver"
select IIO_BUFFER
select IIO_BUFFER_HW_CONSUMER
select IIO_BUFFER_DMAENGINE
help
Say yes here to build support for Analog Devices Generic
AXI ADC IP core. The IP core is used for interfacing with
analog-to-digital (ADC) converters that require either a high-speed
serial interface (JESD204B/C) or a source synchronous parallel
interface (LVDS/CMOS).
Typically (for such devices) SPI will be used for configuration only,
while this IP core handles the streaming of data into memory via DMA.
Link: https://wiki.analog.com/resources/fpga/docs/axi_adc_ip
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 adi-axi-adc.
config ASPEED_ADC
tristate "Aspeed ADC"
depends on ARCH_ASPEED || COMPILE_TEST
@ -595,6 +630,16 @@ config MAX1118
To compile this driver as a module, choose M here: the module will be
called max1118.
config MAX1241
tristate "Maxim max1241 ADC driver"
depends on SPI_MASTER
help
Say yes here to build support for Maxim max1241 12-bit, single-channel
ADC.
To compile this driver as a module, choose M here: the module will be
called max1241.
config MAX1363
tristate "Maxim max1363 ADC driver"
depends on I2C

View File

@ -26,6 +26,8 @@ obj-$(CONFIG_AD7793) += ad7793.o
obj-$(CONFIG_AD7887) += ad7887.o
obj-$(CONFIG_AD7949) += ad7949.o
obj-$(CONFIG_AD799X) += ad799x.o
obj-$(CONFIG_AD9467) += ad9467.o
obj-$(CONFIG_ADI_AXI_ADC) += adi-axi-adc.o
obj-$(CONFIG_ASPEED_ADC) += aspeed_adc.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o
@ -57,6 +59,7 @@ obj-$(CONFIG_LTC2497) += ltc2497.o ltc2497-core.o
obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX11100) += max11100.o
obj-$(CONFIG_MAX1118) += max1118.o
obj-$(CONFIG_MAX1241) += max1241.o
obj-$(CONFIG_MAX1363) += max1363.o
obj-$(CONFIG_MAX9611) += max9611.o
obj-$(CONFIG_MCP320X) += mcp320x.o

View File

@ -12,9 +12,11 @@
#include <linux/sysfs.h>
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio/consumer.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@ -27,6 +29,8 @@ struct ad7476_state;
struct ad7476_chip_info {
unsigned int int_vref_uv;
struct iio_chan_spec channel[2];
/* channels used when convst gpio is defined */
struct iio_chan_spec convst_channel[2];
void (*reset)(struct ad7476_state *);
};
@ -34,6 +38,7 @@ struct ad7476_state {
struct spi_device *spi;
const struct ad7476_chip_info *chip_info;
struct regulator *reg;
struct gpio_desc *convst_gpio;
struct spi_transfer xfer;
struct spi_message msg;
/*
@ -64,6 +69,17 @@ enum ad7476_supported_device_ids {
ID_ADS7868,
};
static void ad7091_convst(struct ad7476_state *st)
{
if (!st->convst_gpio)
return;
gpiod_set_value(st->convst_gpio, 0);
udelay(1); /* CONVST pulse width: 10 ns min */
gpiod_set_value(st->convst_gpio, 1);
udelay(1); /* Conversion time: 650 ns max */
}
static irqreturn_t ad7476_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
@ -71,6 +87,8 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p)
struct ad7476_state *st = iio_priv(indio_dev);
int b_sent;
ad7091_convst(st);
b_sent = spi_sync(st->spi, &st->msg);
if (b_sent < 0)
goto done;
@ -93,6 +111,8 @@ static int ad7476_scan_direct(struct ad7476_state *st)
{
int ret;
ad7091_convst(st);
ret = spi_sync(st->spi, &st->msg);
if (ret)
return ret;
@ -160,6 +180,8 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
#define AD7940_CHAN(bits) _AD7476_CHAN((bits), 15 - (bits), \
BIT(IIO_CHAN_INFO_RAW))
#define AD7091R_CHAN(bits) _AD7476_CHAN((bits), 16 - (bits), 0)
#define AD7091R_CONVST_CHAN(bits) _AD7476_CHAN((bits), 16 - (bits), \
BIT(IIO_CHAN_INFO_RAW))
#define ADS786X_CHAN(bits) _AD7476_CHAN((bits), 12 - (bits), \
BIT(IIO_CHAN_INFO_RAW))
@ -167,6 +189,8 @@ static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
[ID_AD7091R] = {
.channel[0] = AD7091R_CHAN(12),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
.convst_channel[0] = AD7091R_CONVST_CHAN(12),
.convst_channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
.reset = ad7091_reset,
},
[ID_AD7276] = {
@ -232,6 +256,13 @@ static const struct iio_info ad7476_info = {
.read_raw = &ad7476_read_raw,
};
static void ad7476_reg_disable(void *data)
{
struct ad7476_state *st = data;
regulator_disable(st->reg);
}
static int ad7476_probe(struct spi_device *spi)
{
struct ad7476_state *st;
@ -254,6 +285,17 @@ static int ad7476_probe(struct spi_device *spi)
if (ret)
return ret;
ret = devm_add_action_or_reset(&spi->dev, ad7476_reg_disable,
st);
if (ret)
return ret;
st->convst_gpio = devm_gpiod_get_optional(&spi->dev,
"adi,conversion-start",
GPIOD_OUT_LOW);
if (IS_ERR(st->convst_gpio))
return PTR_ERR(st->convst_gpio);
spi_set_drvdata(spi, indio_dev);
st->spi = spi;
@ -266,6 +308,9 @@ static int ad7476_probe(struct spi_device *spi)
indio_dev->channels = st->chip_info->channel;
indio_dev->num_channels = 2;
indio_dev->info = &ad7476_info;
if (st->convst_gpio)
indio_dev->channels = st->chip_info->convst_channel;
/* Setup default message */
st->xfer.rx_buf = &st->data;
@ -295,19 +340,8 @@ error_disable_reg:
return ret;
}
static int ad7476_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad7476_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
regulator_disable(st->reg);
return 0;
}
static const struct spi_device_id ad7476_id[] = {
{"ad7091", ID_AD7091R},
{"ad7091r", ID_AD7091R},
{"ad7273", ID_AD7277},
{"ad7274", ID_AD7276},
@ -343,7 +377,6 @@ static struct spi_driver ad7476_driver = {
.name = "ad7476",
},
.probe = ad7476_probe,
.remove = ad7476_remove,
.id_table = ad7476_id,
};
module_spi_driver(ad7476_driver);

View File

@ -206,10 +206,29 @@ static const struct ad_sigma_delta_info ad7780_sigma_delta_info = {
.irq_flags = IRQF_TRIGGER_LOW,
};
#define AD7780_CHANNEL(bits, wordsize) \
AD_SD_CHANNEL(1, 0, 0, bits, 32, (wordsize) - (bits))
#define AD7170_CHANNEL(bits, wordsize) \
AD_SD_CHANNEL_NO_SAMP_FREQ(1, 0, 0, bits, 32, (wordsize) - (bits))
#define _AD7780_CHANNEL(_bits, _wordsize, _mask_all) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = 0, \
.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 = _mask_all, \
.scan_index = 1, \
.scan_type = { \
.sign = 'u', \
.realbits = (_bits), \
.storagebits = 32, \
.shift = (_wordsize) - (_bits), \
.endianness = IIO_BE, \
}, \
}
#define AD7780_CHANNEL(_bits, _wordsize) \
_AD7780_CHANNEL(_bits, _wordsize, BIT(IIO_CHAN_INFO_SAMP_FREQ))
#define AD7170_CHANNEL(_bits, _wordsize) \
_AD7780_CHANNEL(_bits, _wordsize, 0)
static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
[ID_AD7170] = {

View File

@ -64,25 +64,73 @@
#define AD7791_MODE_SEL_MASK (0x3 << 6)
#define AD7791_MODE_SEL(x) ((x) << 6)
#define __AD7991_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
_storagebits, _shift, _extend_name, _type, _mask_all) \
{ \
.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 = _mask_all, \
.scan_index = (_si), \
.scan_type = { \
.sign = 'u', \
.realbits = (_bits), \
.storagebits = (_storagebits), \
.shift = (_shift), \
.endianness = IIO_BE, \
}, \
}
#define AD7991_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
_storagebits, _shift) \
__AD7991_CHANNEL(_si, _channel, _channel, _address, _bits, \
_storagebits, _shift, "shorted", IIO_VOLTAGE, \
BIT(IIO_CHAN_INFO_SAMP_FREQ))
#define AD7991_CHANNEL(_si, _channel, _address, _bits, \
_storagebits, _shift) \
__AD7991_CHANNEL(_si, _channel, -1, _address, _bits, \
_storagebits, _shift, NULL, IIO_VOLTAGE, \
BIT(IIO_CHAN_INFO_SAMP_FREQ))
#define AD7991_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
_storagebits, _shift) \
__AD7991_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
_storagebits, _shift, NULL, IIO_VOLTAGE, \
BIT(IIO_CHAN_INFO_SAMP_FREQ))
#define AD7991_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \
_shift) \
__AD7991_CHANNEL(_si, _channel, -1, _address, _bits, \
_storagebits, _shift, "supply", IIO_VOLTAGE, \
BIT(IIO_CHAN_INFO_SAMP_FREQ))
#define DECLARE_AD7787_CHANNELS(name, bits, storagebits) \
const struct iio_chan_spec name[] = { \
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
AD7991_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
(bits), (storagebits), 0), \
AD_SD_CHANNEL(1, 1, AD7791_CH_AIN2, (bits), (storagebits), 0), \
AD_SD_SHORTED_CHANNEL(2, 0, AD7791_CH_AIN1N_AIN1N, \
AD7991_CHANNEL(1, 1, AD7791_CH_AIN2, (bits), (storagebits), 0), \
AD7991_SHORTED_CHANNEL(2, 0, AD7791_CH_AIN1N_AIN1N, \
(bits), (storagebits), 0), \
AD_SD_SUPPLY_CHANNEL(3, 2, AD7791_CH_AVDD_MONITOR, \
AD7991_SUPPLY_CHANNEL(3, 2, AD7791_CH_AVDD_MONITOR, \
(bits), (storagebits), 0), \
IIO_CHAN_SOFT_TIMESTAMP(4), \
}
#define DECLARE_AD7791_CHANNELS(name, bits, storagebits) \
const struct iio_chan_spec name[] = { \
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
AD7991_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
(bits), (storagebits), 0), \
AD_SD_SHORTED_CHANNEL(1, 0, AD7791_CH_AIN1N_AIN1N, \
AD7991_SHORTED_CHANNEL(1, 0, AD7791_CH_AIN1N_AIN1N, \
(bits), (storagebits), 0), \
AD_SD_SUPPLY_CHANNEL(2, 1, AD7791_CH_AVDD_MONITOR, \
AD7991_SUPPLY_CHANNEL(2, 1, AD7791_CH_AVDD_MONITOR, \
(bits), (storagebits), 0), \
IIO_CHAN_SOFT_TIMESTAMP(3), \
}
@ -444,5 +492,5 @@ static struct spi_driver ad7791_driver = {
module_spi_driver(ad7791_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Analog Device AD7787/AD7788/AD7789/AD7790/AD7791 ADC driver");
MODULE_DESCRIPTION("Analog Devices AD7787/AD7788/AD7789/AD7790/AD7791 ADC driver");
MODULE_LICENSE("GPL v2");

View File

@ -354,29 +354,28 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
static IIO_CONST_ATTR_NAMED(sampling_frequency_available_ad7797,
sampling_frequency_available, "123 62 50 33 17 16 12 10 8 6 4");
static ssize_t ad7793_show_scale_available(struct device *dev,
struct device_attribute *attr, char *buf)
static int ad7793_read_avail(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
const int **vals, int *type, int *length,
long mask)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7793_state *st = iio_priv(indio_dev);
int i, len = 0;
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
len += sprintf(buf + len, "%d.%09u ", st->scale_avail[i][0],
st->scale_avail[i][1]);
switch (mask) {
case IIO_CHAN_INFO_SCALE:
*vals = (int *)st->scale_avail;
*type = IIO_VAL_INT_PLUS_NANO;
/* Values are stored in a 2D matrix */
*length = ARRAY_SIZE(st->scale_avail) * 2;
len += sprintf(buf + len, "\n");
return len;
return IIO_AVAIL_LIST;
default:
return -EINVAL;
}
}
static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available,
in_voltage-voltage_scale_available, S_IRUGO,
ad7793_show_scale_available, NULL, 0);
static struct attribute *ad7793_attributes[] = {
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_in_m_in_scale_available.dev_attr.attr,
NULL
};
@ -534,6 +533,7 @@ static const struct iio_info ad7793_info = {
.read_raw = &ad7793_read_raw,
.write_raw = &ad7793_write_raw,
.write_raw_get_fmt = &ad7793_write_raw_get_fmt,
.read_avail = ad7793_read_avail,
.attrs = &ad7793_attribute_group,
.validate_trigger = ad_sd_validate_trigger,
};
@ -546,47 +546,113 @@ static const struct iio_info ad7797_info = {
.validate_trigger = ad_sd_validate_trigger,
};
#define __AD7793_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
_storagebits, _shift, _extend_name, _type, _mask_type_av, _mask_all) \
{ \
.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_type_available = (_mask_type_av), \
.info_mask_shared_by_all = _mask_all, \
.scan_index = (_si), \
.scan_type = { \
.sign = 'u', \
.realbits = (_bits), \
.storagebits = (_storagebits), \
.shift = (_shift), \
.endianness = IIO_BE, \
}, \
}
#define AD7793_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
_storagebits, _shift) \
__AD7793_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
_storagebits, _shift, NULL, IIO_VOLTAGE, \
BIT(IIO_CHAN_INFO_SCALE), \
BIT(IIO_CHAN_INFO_SAMP_FREQ))
#define AD7793_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
_storagebits, _shift) \
__AD7793_CHANNEL(_si, _channel, _channel, _address, _bits, \
_storagebits, _shift, "shorted", IIO_VOLTAGE, \
BIT(IIO_CHAN_INFO_SCALE), \
BIT(IIO_CHAN_INFO_SAMP_FREQ))
#define AD7793_TEMP_CHANNEL(_si, _address, _bits, _storagebits, _shift) \
__AD7793_CHANNEL(_si, 0, -1, _address, _bits, \
_storagebits, _shift, NULL, IIO_TEMP, \
0, \
BIT(IIO_CHAN_INFO_SAMP_FREQ))
#define AD7793_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \
_shift) \
__AD7793_CHANNEL(_si, _channel, -1, _address, _bits, \
_storagebits, _shift, "supply", IIO_VOLTAGE, \
0, \
BIT(IIO_CHAN_INFO_SAMP_FREQ))
#define AD7797_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
_storagebits, _shift) \
__AD7793_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
_storagebits, _shift, NULL, IIO_VOLTAGE, \
0, \
BIT(IIO_CHAN_INFO_SAMP_FREQ))
#define AD7797_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
_storagebits, _shift) \
__AD7793_CHANNEL(_si, _channel, _channel, _address, _bits, \
_storagebits, _shift, "shorted", IIO_VOLTAGE, \
0, \
BIT(IIO_CHAN_INFO_SAMP_FREQ))
#define DECLARE_AD7793_CHANNELS(_name, _b, _sb, _s) \
const struct iio_chan_spec _name##_channels[] = { \
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), (_s)), \
AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), (_s)), \
AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), (_s)), \
AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), (_s)), \
AD_SD_TEMP_CHANNEL(4, AD7793_CH_TEMP, (_b), (_sb), (_s)), \
AD_SD_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), (_s)), \
AD7793_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), (_s)), \
AD7793_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), (_s)), \
AD7793_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), (_s)), \
AD7793_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), (_s)), \
AD7793_TEMP_CHANNEL(4, AD7793_CH_TEMP, (_b), (_sb), (_s)), \
AD7793_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), (_s)), \
IIO_CHAN_SOFT_TIMESTAMP(6), \
}
#define DECLARE_AD7795_CHANNELS(_name, _b, _sb) \
const struct iio_chan_spec _name##_channels[] = { \
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
AD_SD_DIFF_CHANNEL(3, 3, 3, AD7795_CH_AIN4P_AIN4M, (_b), (_sb), 0), \
AD_SD_DIFF_CHANNEL(4, 4, 4, AD7795_CH_AIN5P_AIN5M, (_b), (_sb), 0), \
AD_SD_DIFF_CHANNEL(5, 5, 5, AD7795_CH_AIN6P_AIN6M, (_b), (_sb), 0), \
AD_SD_SHORTED_CHANNEL(6, 0, AD7795_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
AD_SD_TEMP_CHANNEL(7, AD7793_CH_TEMP, (_b), (_sb), 0), \
AD_SD_SUPPLY_CHANNEL(8, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
AD7793_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
AD7793_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
AD7793_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
AD7793_DIFF_CHANNEL(3, 3, 3, AD7795_CH_AIN4P_AIN4M, (_b), (_sb), 0), \
AD7793_DIFF_CHANNEL(4, 4, 4, AD7795_CH_AIN5P_AIN5M, (_b), (_sb), 0), \
AD7793_DIFF_CHANNEL(5, 5, 5, AD7795_CH_AIN6P_AIN6M, (_b), (_sb), 0), \
AD7793_SHORTED_CHANNEL(6, 0, AD7795_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
AD7793_TEMP_CHANNEL(7, AD7793_CH_TEMP, (_b), (_sb), 0), \
AD7793_SUPPLY_CHANNEL(8, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
IIO_CHAN_SOFT_TIMESTAMP(9), \
}
#define DECLARE_AD7797_CHANNELS(_name, _b, _sb) \
const struct iio_chan_spec _name##_channels[] = { \
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
AD_SD_SHORTED_CHANNEL(1, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
AD_SD_TEMP_CHANNEL(2, AD7793_CH_TEMP, (_b), (_sb), 0), \
AD_SD_SUPPLY_CHANNEL(3, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
AD7797_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
AD7797_SHORTED_CHANNEL(1, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
AD7793_TEMP_CHANNEL(2, AD7793_CH_TEMP, (_b), (_sb), 0), \
AD7793_SUPPLY_CHANNEL(3, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
IIO_CHAN_SOFT_TIMESTAMP(4), \
}
#define DECLARE_AD7799_CHANNELS(_name, _b, _sb) \
const struct iio_chan_spec _name##_channels[] = { \
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
AD_SD_SUPPLY_CHANNEL(4, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
AD7793_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
AD7793_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
AD7793_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
AD7793_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
AD7793_SUPPLY_CHANNEL(4, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
IIO_CHAN_SOFT_TIMESTAMP(5), \
}

422
drivers/iio/adc/ad9467.c Normal file
View File

@ -0,0 +1,422 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Analog Devices AD9467 SPI ADC driver
*
* Copyright 2012-2020 Analog Devices Inc.
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/of_device.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/clk.h>
#include <linux/iio/adc/adi-axi-adc.h>
/*
* ADI High-Speed ADC common spi interface registers
* See Application-Note AN-877:
* https://www.analog.com/media/en/technical-documentation/application-notes/AN-877.pdf
*/
#define AN877_ADC_REG_CHIP_PORT_CONF 0x00
#define AN877_ADC_REG_CHIP_ID 0x01
#define AN877_ADC_REG_CHIP_GRADE 0x02
#define AN877_ADC_REG_CHAN_INDEX 0x05
#define AN877_ADC_REG_TRANSFER 0xFF
#define AN877_ADC_REG_MODES 0x08
#define AN877_ADC_REG_TEST_IO 0x0D
#define AN877_ADC_REG_ADC_INPUT 0x0F
#define AN877_ADC_REG_OFFSET 0x10
#define AN877_ADC_REG_OUTPUT_MODE 0x14
#define AN877_ADC_REG_OUTPUT_ADJUST 0x15
#define AN877_ADC_REG_OUTPUT_PHASE 0x16
#define AN877_ADC_REG_OUTPUT_DELAY 0x17
#define AN877_ADC_REG_VREF 0x18
#define AN877_ADC_REG_ANALOG_INPUT 0x2C
/* AN877_ADC_REG_TEST_IO */
#define AN877_ADC_TESTMODE_OFF 0x0
#define AN877_ADC_TESTMODE_MIDSCALE_SHORT 0x1
#define AN877_ADC_TESTMODE_POS_FULLSCALE 0x2
#define AN877_ADC_TESTMODE_NEG_FULLSCALE 0x3
#define AN877_ADC_TESTMODE_ALT_CHECKERBOARD 0x4
#define AN877_ADC_TESTMODE_PN23_SEQ 0x5
#define AN877_ADC_TESTMODE_PN9_SEQ 0x6
#define AN877_ADC_TESTMODE_ONE_ZERO_TOGGLE 0x7
#define AN877_ADC_TESTMODE_USER 0x8
#define AN877_ADC_TESTMODE_BIT_TOGGLE 0x9
#define AN877_ADC_TESTMODE_SYNC 0xA
#define AN877_ADC_TESTMODE_ONE_BIT_HIGH 0xB
#define AN877_ADC_TESTMODE_MIXED_BIT_FREQUENCY 0xC
#define AN877_ADC_TESTMODE_RAMP 0xF
/* AN877_ADC_REG_TRANSFER */
#define AN877_ADC_TRANSFER_SYNC 0x1
/* AN877_ADC_REG_OUTPUT_MODE */
#define AN877_ADC_OUTPUT_MODE_OFFSET_BINARY 0x0
#define AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT 0x1
#define AN877_ADC_OUTPUT_MODE_GRAY_CODE 0x2
/* AN877_ADC_REG_OUTPUT_PHASE */
#define AN877_ADC_OUTPUT_EVEN_ODD_MODE_EN 0x20
#define AN877_ADC_INVERT_DCO_CLK 0x80
/* AN877_ADC_REG_OUTPUT_DELAY */
#define AN877_ADC_DCO_DELAY_ENABLE 0x80
/*
* Analog Devices AD9467 16-Bit, 200/250 MSPS ADC
*/
#define CHIPID_AD9467 0x50
#define AD9467_DEF_OUTPUT_MODE 0x08
#define AD9467_REG_VREF_MASK 0x0F
enum {
ID_AD9467,
};
struct ad9467_state {
struct spi_device *spi;
struct clk *clk;
unsigned int output_mode;
struct gpio_desc *pwrdown_gpio;
struct gpio_desc *reset_gpio;
};
static int ad9467_spi_read(struct spi_device *spi, unsigned int reg)
{
unsigned char tbuf[2], rbuf[1];
int ret;
tbuf[0] = 0x80 | (reg >> 8);
tbuf[1] = reg & 0xFF;
ret = spi_write_then_read(spi,
tbuf, ARRAY_SIZE(tbuf),
rbuf, ARRAY_SIZE(rbuf));
if (ret < 0)
return ret;
return rbuf[0];
}
static int ad9467_spi_write(struct spi_device *spi, unsigned int reg,
unsigned int val)
{
unsigned char buf[3];
buf[0] = reg >> 8;
buf[1] = reg & 0xFF;
buf[2] = val;
return spi_write(spi, buf, ARRAY_SIZE(buf));
}
static int ad9467_reg_access(struct adi_axi_adc_conv *conv, unsigned int reg,
unsigned int writeval, unsigned int *readval)
{
struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
struct spi_device *spi = st->spi;
int ret;
if (readval == NULL) {
ret = ad9467_spi_write(spi, reg, writeval);
ad9467_spi_write(spi, AN877_ADC_REG_TRANSFER,
AN877_ADC_TRANSFER_SYNC);
return ret;
}
ret = ad9467_spi_read(spi, reg);
if (ret < 0)
return ret;
*readval = ret;
return 0;
}
static const unsigned int ad9467_scale_table[][2] = {
{2000, 0}, {2100, 6}, {2200, 7},
{2300, 8}, {2400, 9}, {2500, 10},
};
static void __ad9467_get_scale(struct adi_axi_adc_conv *conv, int index,
unsigned int *val, unsigned int *val2)
{
const struct adi_axi_adc_chip_info *info = conv->chip_info;
const struct iio_chan_spec *chan = &info->channels[0];
unsigned int tmp;
tmp = (info->scale_table[index][0] * 1000000ULL) >>
chan->scan_type.realbits;
*val = tmp / 1000000;
*val2 = tmp % 1000000;
}
#define AD9467_CHAN(_chan, _si, _bits, _sign) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = _chan, \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.scan_index = _si, \
.scan_type = { \
.sign = _sign, \
.realbits = _bits, \
.storagebits = 16, \
}, \
}
static const struct iio_chan_spec ad9467_channels[] = {
AD9467_CHAN(0, 0, 16, 'S'),
};
static const struct adi_axi_adc_chip_info ad9467_chip_tbl[] = {
[ID_AD9467] = {
.id = CHIPID_AD9467,
.max_rate = 250000000UL,
.scale_table = ad9467_scale_table,
.num_scales = ARRAY_SIZE(ad9467_scale_table),
.channels = ad9467_channels,
.num_channels = ARRAY_SIZE(ad9467_channels),
},
};
static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2)
{
const struct adi_axi_adc_chip_info *info = conv->chip_info;
struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
unsigned int i, vref_val, vref_mask;
vref_val = ad9467_spi_read(st->spi, AN877_ADC_REG_VREF);
switch (info->id) {
case CHIPID_AD9467:
vref_mask = AD9467_REG_VREF_MASK;
break;
default:
vref_mask = 0xFFFF;
break;
}
vref_val &= vref_mask;
for (i = 0; i < info->num_scales; i++) {
if (vref_val == info->scale_table[i][1])
break;
}
if (i == info->num_scales)
return -ERANGE;
__ad9467_get_scale(conv, i, val, val2);
return IIO_VAL_INT_PLUS_MICRO;
}
static int ad9467_set_scale(struct adi_axi_adc_conv *conv, int val, int val2)
{
const struct adi_axi_adc_chip_info *info = conv->chip_info;
struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
unsigned int scale_val[2];
unsigned int i;
if (val != 0)
return -EINVAL;
for (i = 0; i < info->num_scales; i++) {
__ad9467_get_scale(conv, i, &scale_val[0], &scale_val[1]);
if (scale_val[0] != val || scale_val[1] != val2)
continue;
ad9467_spi_write(st->spi, AN877_ADC_REG_VREF,
info->scale_table[i][1]);
ad9467_spi_write(st->spi, AN877_ADC_REG_TRANSFER,
AN877_ADC_TRANSFER_SYNC);
return 0;
}
return -EINVAL;
}
static int ad9467_read_raw(struct adi_axi_adc_conv *conv,
struct iio_chan_spec const *chan,
int *val, int *val2, long m)
{
struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
switch (m) {
case IIO_CHAN_INFO_SCALE:
return ad9467_get_scale(conv, val, val2);
case IIO_CHAN_INFO_SAMP_FREQ:
*val = clk_get_rate(st->clk);
return IIO_VAL_INT;
default:
return -EINVAL;
}
}
static int ad9467_write_raw(struct adi_axi_adc_conv *conv,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
const struct adi_axi_adc_chip_info *info = conv->chip_info;
struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
long r_clk;
switch (mask) {
case IIO_CHAN_INFO_SCALE:
return ad9467_set_scale(conv, val, val2);
case IIO_CHAN_INFO_SAMP_FREQ:
r_clk = clk_round_rate(st->clk, val);
if (r_clk < 0 || r_clk > info->max_rate) {
dev_warn(&st->spi->dev,
"Error setting ADC sample rate %ld", r_clk);
return -EINVAL;
}
return clk_set_rate(st->clk, r_clk);
default:
return -EINVAL;
}
}
static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode)
{
int ret;
ret = ad9467_spi_write(spi, AN877_ADC_REG_OUTPUT_MODE, mode);
if (ret < 0)
return ret;
return ad9467_spi_write(spi, AN877_ADC_REG_TRANSFER,
AN877_ADC_TRANSFER_SYNC);
}
static int ad9467_preenable_setup(struct adi_axi_adc_conv *conv)
{
struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
return ad9467_outputmode_set(st->spi, st->output_mode);
}
static int ad9467_setup(struct ad9467_state *st, unsigned int chip_id)
{
switch (chip_id) {
case CHIPID_AD9467:
st->output_mode = AD9467_DEF_OUTPUT_MODE |
AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT;
return 0;
default:
return -EINVAL;
}
}
static void ad9467_clk_disable(void *data)
{
struct ad9467_state *st = data;
clk_disable_unprepare(st->clk);
}
static int ad9467_probe(struct spi_device *spi)
{
const struct adi_axi_adc_chip_info *info;
struct adi_axi_adc_conv *conv;
struct ad9467_state *st;
unsigned int id;
int ret;
info = of_device_get_match_data(&spi->dev);
if (!info)
return -ENODEV;
conv = devm_adi_axi_adc_conv_register(&spi->dev, sizeof(*st));
if (IS_ERR(conv))
return PTR_ERR(conv);
st = adi_axi_adc_conv_priv(conv);
st->spi = spi;
st->clk = devm_clk_get(&spi->dev, "adc-clk");
if (IS_ERR(st->clk))
return PTR_ERR(st->clk);
ret = clk_prepare_enable(st->clk);
if (ret < 0)
return ret;
ret = devm_add_action_or_reset(&spi->dev, ad9467_clk_disable, st);
if (ret)
return ret;
st->pwrdown_gpio = devm_gpiod_get_optional(&spi->dev, "powerdown",
GPIOD_OUT_LOW);
if (IS_ERR(st->pwrdown_gpio))
return PTR_ERR(st->pwrdown_gpio);
st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(st->reset_gpio))
return PTR_ERR(st->reset_gpio);
if (st->reset_gpio) {
udelay(1);
ret = gpiod_direction_output(st->reset_gpio, 1);
if (ret)
return ret;
mdelay(10);
}
spi_set_drvdata(spi, st);
conv->chip_info = info;
id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID);
if (id != conv->chip_info->id) {
dev_err(&spi->dev, "Unrecognized CHIP_ID 0x%X\n", id);
return -ENODEV;
}
conv->reg_access = ad9467_reg_access;
conv->write_raw = ad9467_write_raw;
conv->read_raw = ad9467_read_raw;
conv->preenable_setup = ad9467_preenable_setup;
return ad9467_setup(st, id);
}
static const struct of_device_id ad9467_of_match[] = {
{ .compatible = "adi,ad9467", .data = &ad9467_chip_tbl[ID_AD9467], },
{}
};
MODULE_DEVICE_TABLE(of, ad9467_of_match);
static struct spi_driver ad9467_driver = {
.driver = {
.name = "ad9467",
.of_match_table = ad9467_of_match,
},
.probe = ad9467_probe,
};
module_spi_driver(ad9467_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD9467 ADC driver");
MODULE_LICENSE("GPL v2");

View File

@ -70,9 +70,7 @@ int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
switch (size) {
case 3:
data[1] = val >> 16;
data[2] = val >> 8;
data[3] = val;
put_unaligned_be24(val, &data[1]);
break;
case 2:
put_unaligned_be16(val, &data[1]);
@ -157,9 +155,7 @@ int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta,
*val = get_unaligned_be32(sigma_delta->data);
break;
case 3:
*val = (sigma_delta->data[0] << 16) |
(sigma_delta->data[1] << 8) |
sigma_delta->data[2];
*val = get_unaligned_be24(&sigma_delta->data[0]);
break;
case 2:
*val = get_unaligned_be16(sigma_delta->data);

View File

@ -0,0 +1,482 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Analog Devices Generic AXI ADC IP core
* Link: https://wiki.analog.com/resources/fpga/docs/axi_adc_ip
*
* Copyright 2012-2020 Analog Devices Inc.
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
#include <linux/iio/buffer-dmaengine.h>
#include <linux/fpga/adi-axi-common.h>
#include <linux/iio/adc/adi-axi-adc.h>
/**
* Register definitions:
* https://wiki.analog.com/resources/fpga/docs/axi_adc_ip#register_map
*/
/* ADC controls */
#define ADI_AXI_REG_RSTN 0x0040
#define ADI_AXI_REG_RSTN_CE_N BIT(2)
#define ADI_AXI_REG_RSTN_MMCM_RSTN BIT(1)
#define ADI_AXI_REG_RSTN_RSTN BIT(0)
/* ADC Channel controls */
#define ADI_AXI_REG_CHAN_CTRL(c) (0x0400 + (c) * 0x40)
#define ADI_AXI_REG_CHAN_CTRL_LB_OWR BIT(11)
#define ADI_AXI_REG_CHAN_CTRL_PN_SEL_OWR BIT(10)
#define ADI_AXI_REG_CHAN_CTRL_IQCOR_EN BIT(9)
#define ADI_AXI_REG_CHAN_CTRL_DCFILT_EN BIT(8)
#define ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT BIT(6)
#define ADI_AXI_REG_CHAN_CTRL_FMT_TYPE BIT(5)
#define ADI_AXI_REG_CHAN_CTRL_FMT_EN BIT(4)
#define ADI_AXI_REG_CHAN_CTRL_PN_TYPE_OWR BIT(1)
#define ADI_AXI_REG_CHAN_CTRL_ENABLE BIT(0)
#define ADI_AXI_REG_CHAN_CTRL_DEFAULTS \
(ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT | \
ADI_AXI_REG_CHAN_CTRL_FMT_EN | \
ADI_AXI_REG_CHAN_CTRL_ENABLE)
struct adi_axi_adc_core_info {
unsigned int version;
};
struct adi_axi_adc_state {
struct mutex lock;
struct adi_axi_adc_client *client;
void __iomem *regs;
};
struct adi_axi_adc_client {
struct list_head entry;
struct adi_axi_adc_conv conv;
struct adi_axi_adc_state *state;
struct device *dev;
const struct adi_axi_adc_core_info *info;
};
static LIST_HEAD(registered_clients);
static DEFINE_MUTEX(registered_clients_lock);
static struct adi_axi_adc_client *conv_to_client(struct adi_axi_adc_conv *conv)
{
return container_of(conv, struct adi_axi_adc_client, conv);
}
void *adi_axi_adc_conv_priv(struct adi_axi_adc_conv *conv)
{
struct adi_axi_adc_client *cl = conv_to_client(conv);
return (char *)cl + ALIGN(sizeof(struct adi_axi_adc_client), IIO_ALIGN);
}
EXPORT_SYMBOL_GPL(adi_axi_adc_conv_priv);
static void adi_axi_adc_write(struct adi_axi_adc_state *st,
unsigned int reg,
unsigned int val)
{
iowrite32(val, st->regs + reg);
}
static unsigned int adi_axi_adc_read(struct adi_axi_adc_state *st,
unsigned int reg)
{
return ioread32(st->regs + reg);
}
static int adi_axi_adc_config_dma_buffer(struct device *dev,
struct iio_dev *indio_dev)
{
struct iio_buffer *buffer;
const char *dma_name;
if (!device_property_present(dev, "dmas"))
return 0;
if (device_property_read_string(dev, "dma-names", &dma_name))
dma_name = "rx";
buffer = devm_iio_dmaengine_buffer_alloc(indio_dev->dev.parent,
dma_name);
if (IS_ERR(buffer))
return PTR_ERR(buffer);
indio_dev->modes |= INDIO_BUFFER_HARDWARE;
iio_device_attach_buffer(indio_dev, buffer);
return 0;
}
static int adi_axi_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct adi_axi_adc_state *st = iio_priv(indio_dev);
struct adi_axi_adc_conv *conv = &st->client->conv;
if (!conv->read_raw)
return -EOPNOTSUPP;
return conv->read_raw(conv, chan, val, val2, mask);
}
static int adi_axi_adc_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct adi_axi_adc_state *st = iio_priv(indio_dev);
struct adi_axi_adc_conv *conv = &st->client->conv;
if (!conv->write_raw)
return -EOPNOTSUPP;
return conv->write_raw(conv, chan, val, val2, mask);
}
static int adi_axi_adc_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct adi_axi_adc_state *st = iio_priv(indio_dev);
struct adi_axi_adc_conv *conv = &st->client->conv;
unsigned int i, ctrl;
for (i = 0; i < conv->chip_info->num_channels; i++) {
ctrl = adi_axi_adc_read(st, ADI_AXI_REG_CHAN_CTRL(i));
if (test_bit(i, scan_mask))
ctrl |= ADI_AXI_REG_CHAN_CTRL_ENABLE;
else
ctrl &= ~ADI_AXI_REG_CHAN_CTRL_ENABLE;
adi_axi_adc_write(st, ADI_AXI_REG_CHAN_CTRL(i), ctrl);
}
return 0;
}
static struct adi_axi_adc_conv *adi_axi_adc_conv_register(struct device *dev,
size_t sizeof_priv)
{
struct adi_axi_adc_client *cl;
size_t alloc_size;
alloc_size = ALIGN(sizeof(struct adi_axi_adc_client), IIO_ALIGN);
if (sizeof_priv)
alloc_size += ALIGN(sizeof_priv, IIO_ALIGN);
cl = kzalloc(alloc_size, GFP_KERNEL);
if (!cl)
return ERR_PTR(-ENOMEM);
mutex_lock(&registered_clients_lock);
cl->dev = get_device(dev);
list_add_tail(&cl->entry, &registered_clients);
mutex_unlock(&registered_clients_lock);
return &cl->conv;
}
static void adi_axi_adc_conv_unregister(struct adi_axi_adc_conv *conv)
{
struct adi_axi_adc_client *cl = conv_to_client(conv);
mutex_lock(&registered_clients_lock);
list_del(&cl->entry);
put_device(cl->dev);
mutex_unlock(&registered_clients_lock);
kfree(cl);
}
static void devm_adi_axi_adc_conv_release(struct device *dev, void *res)
{
adi_axi_adc_conv_unregister(*(struct adi_axi_adc_conv **)res);
}
struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev,
size_t sizeof_priv)
{
struct adi_axi_adc_conv **ptr, *conv;
ptr = devres_alloc(devm_adi_axi_adc_conv_release, sizeof(*ptr),
GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
conv = adi_axi_adc_conv_register(dev, sizeof_priv);
if (IS_ERR(conv)) {
devres_free(ptr);
return ERR_CAST(conv);
}
*ptr = conv;
devres_add(dev, ptr);
return conv;
}
EXPORT_SYMBOL_GPL(devm_adi_axi_adc_conv_register);
static ssize_t in_voltage_scale_available_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct adi_axi_adc_state *st = iio_priv(indio_dev);
struct adi_axi_adc_conv *conv = &st->client->conv;
size_t len = 0;
int i;
for (i = 0; i < conv->chip_info->num_scales; i++) {
const unsigned int *s = conv->chip_info->scale_table[i];
len += scnprintf(buf + len, PAGE_SIZE - len,
"%u.%06u ", s[0], s[1]);
}
buf[len - 1] = '\n';
return len;
}
static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0);
enum {
ADI_AXI_ATTR_SCALE_AVAIL,
};
#define ADI_AXI_ATTR(_en_, _file_) \
[ADI_AXI_ATTR_##_en_] = &iio_dev_attr_##_file_.dev_attr.attr
static struct attribute *adi_axi_adc_attributes[] = {
ADI_AXI_ATTR(SCALE_AVAIL, in_voltage_scale_available),
NULL
};
static umode_t axi_adc_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct adi_axi_adc_state *st = iio_priv(indio_dev);
struct adi_axi_adc_conv *conv = &st->client->conv;
switch (n) {
case ADI_AXI_ATTR_SCALE_AVAIL:
if (!conv->chip_info->num_scales)
return 0;
return attr->mode;
default:
return attr->mode;
}
}
static const struct attribute_group adi_axi_adc_attribute_group = {
.attrs = adi_axi_adc_attributes,
.is_visible = axi_adc_attr_is_visible,
};
static const struct iio_info adi_axi_adc_info = {
.read_raw = &adi_axi_adc_read_raw,
.write_raw = &adi_axi_adc_write_raw,
.attrs = &adi_axi_adc_attribute_group,
.update_scan_mode = &adi_axi_adc_update_scan_mode,
};
static const struct adi_axi_adc_core_info adi_axi_adc_10_0_a_info = {
.version = ADI_AXI_PCORE_VER(10, 0, 'a'),
};
static struct adi_axi_adc_client *adi_axi_adc_attach_client(struct device *dev)
{
const struct adi_axi_adc_core_info *info;
struct adi_axi_adc_client *cl;
struct device_node *cln;
info = of_device_get_match_data(dev);
if (!info)
return ERR_PTR(-ENODEV);
cln = of_parse_phandle(dev->of_node, "adi,adc-dev", 0);
if (!cln) {
dev_err(dev, "No 'adi,adc-dev' node defined\n");
return ERR_PTR(-ENODEV);
}
mutex_lock(&registered_clients_lock);
list_for_each_entry(cl, &registered_clients, entry) {
if (!cl->dev)
continue;
if (cl->dev->of_node != cln)
continue;
if (!try_module_get(dev->driver->owner)) {
mutex_unlock(&registered_clients_lock);
return ERR_PTR(-ENODEV);
}
get_device(dev);
cl->info = info;
mutex_unlock(&registered_clients_lock);
return cl;
}
mutex_unlock(&registered_clients_lock);
return ERR_PTR(-EPROBE_DEFER);
}
static int adi_axi_adc_setup_channels(struct device *dev,
struct adi_axi_adc_state *st)
{
struct adi_axi_adc_conv *conv = &st->client->conv;
int i, ret;
if (conv->preenable_setup) {
ret = conv->preenable_setup(conv);
if (ret)
return ret;
}
for (i = 0; i < conv->chip_info->num_channels; i++) {
adi_axi_adc_write(st, ADI_AXI_REG_CHAN_CTRL(i),
ADI_AXI_REG_CHAN_CTRL_DEFAULTS);
}
return 0;
}
static void axi_adc_reset(struct adi_axi_adc_state *st)
{
adi_axi_adc_write(st, ADI_AXI_REG_RSTN, 0);
mdelay(10);
adi_axi_adc_write(st, ADI_AXI_REG_RSTN, ADI_AXI_REG_RSTN_MMCM_RSTN);
mdelay(10);
adi_axi_adc_write(st, ADI_AXI_REG_RSTN,
ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
}
static void adi_axi_adc_cleanup(void *data)
{
struct adi_axi_adc_client *cl = data;
put_device(cl->dev);
module_put(cl->dev->driver->owner);
}
static int adi_axi_adc_probe(struct platform_device *pdev)
{
struct adi_axi_adc_conv *conv;
struct iio_dev *indio_dev;
struct adi_axi_adc_client *cl;
struct adi_axi_adc_state *st;
unsigned int ver;
int ret;
cl = adi_axi_adc_attach_client(&pdev->dev);
if (IS_ERR(cl))
return PTR_ERR(cl);
ret = devm_add_action_or_reset(&pdev->dev, adi_axi_adc_cleanup, cl);
if (ret)
return ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
st->client = cl;
cl->state = st;
mutex_init(&st->lock);
st->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(st->regs))
return PTR_ERR(st->regs);
conv = &st->client->conv;
axi_adc_reset(st);
ver = adi_axi_adc_read(st, ADI_AXI_REG_VERSION);
if (cl->info->version > ver) {
dev_err(&pdev->dev,
"IP core version is too old. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
ADI_AXI_PCORE_VER_MAJOR(cl->info->version),
ADI_AXI_PCORE_VER_MINOR(cl->info->version),
ADI_AXI_PCORE_VER_PATCH(cl->info->version),
ADI_AXI_PCORE_VER_MAJOR(ver),
ADI_AXI_PCORE_VER_MINOR(ver),
ADI_AXI_PCORE_VER_PATCH(ver));
return -ENODEV;
}
indio_dev->info = &adi_axi_adc_info;
indio_dev->dev.parent = &pdev->dev;
indio_dev->name = "adi-axi-adc";
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->num_channels = conv->chip_info->num_channels;
indio_dev->channels = conv->chip_info->channels;
ret = adi_axi_adc_config_dma_buffer(&pdev->dev, indio_dev);
if (ret)
return ret;
ret = adi_axi_adc_setup_channels(&pdev->dev, st);
if (ret)
return ret;
ret = devm_iio_device_register(&pdev->dev, indio_dev);
if (ret)
return ret;
dev_info(&pdev->dev, "AXI ADC IP core (%d.%.2d.%c) probed\n",
ADI_AXI_PCORE_VER_MAJOR(ver),
ADI_AXI_PCORE_VER_MINOR(ver),
ADI_AXI_PCORE_VER_PATCH(ver));
return 0;
}
/* Match table for of_platform binding */
static const struct of_device_id adi_axi_adc_of_match[] = {
{ .compatible = "adi,axi-adc-10.0.a", .data = &adi_axi_adc_10_0_a_info },
{ /* end of list */ }
};
MODULE_DEVICE_TABLE(of, adi_axi_adc_of_match);
static struct platform_driver adi_axi_adc_driver = {
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = adi_axi_adc_of_match,
},
.probe = adi_axi_adc_probe,
};
module_platform_driver(adi_axi_adc_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices Generic AXI ADC IP core driver");
MODULE_LICENSE("GPL v2");

View File

@ -8,6 +8,7 @@
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/interrupt.h>
@ -100,6 +101,8 @@
#define AT91_SAMA5D2_IER_YRDY BIT(21)
/* Interrupt Enable Register - TS pressure measurement ready */
#define AT91_SAMA5D2_IER_PRDY BIT(22)
/* Interrupt Enable Register - Data ready */
#define AT91_SAMA5D2_IER_DRDY BIT(24)
/* Interrupt Enable Register - general overrun error */
#define AT91_SAMA5D2_IER_GOVRE BIT(25)
/* Interrupt Enable Register - Pen detect */
@ -486,6 +489,21 @@ static inline int at91_adc_of_xlate(struct iio_dev *indio_dev,
return at91_adc_chan_xlate(indio_dev, iiospec->args[0]);
}
static unsigned int at91_adc_active_scan_mask_to_reg(struct iio_dev *indio_dev)
{
u32 mask = 0;
u8 bit;
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->num_channels) {
struct iio_chan_spec const *chan =
at91_adc_chan_get(indio_dev, bit);
mask |= BIT(chan->channel);
}
return mask & GENMASK(11, 0);
}
static void at91_adc_config_emr(struct at91_adc_state *st)
{
/* configure the extended mode register */
@ -710,7 +728,6 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
struct iio_dev *indio = iio_trigger_get_drvdata(trig);
struct at91_adc_state *st = iio_priv(indio);
u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR);
u8 bit;
/* clear TRGMOD */
status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK;
@ -721,50 +738,6 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
/* set/unset hw trigger */
at91_adc_writel(st, AT91_SAMA5D2_TRGR, status);
for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
struct iio_chan_spec const *chan = at91_adc_chan_get(indio, bit);
u32 cor;
if (!chan)
continue;
/* these channel types cannot be handled by this trigger */
if (chan->type == IIO_POSITIONRELATIVE ||
chan->type == IIO_PRESSURE)
continue;
if (state) {
cor = at91_adc_readl(st, AT91_SAMA5D2_COR);
if (chan->differential)
cor |= (BIT(chan->channel) |
BIT(chan->channel2)) <<
AT91_SAMA5D2_COR_DIFF_OFFSET;
else
cor &= ~(BIT(chan->channel) <<
AT91_SAMA5D2_COR_DIFF_OFFSET);
at91_adc_writel(st, AT91_SAMA5D2_COR, cor);
}
if (state) {
at91_adc_writel(st, AT91_SAMA5D2_CHER,
BIT(chan->channel));
/* enable irq only if not using DMA */
if (!st->dma_st.dma_chan) {
at91_adc_writel(st, AT91_SAMA5D2_IER,
BIT(chan->channel));
}
} else {
/* disable irq only if not using DMA */
if (!st->dma_st.dma_chan) {
at91_adc_writel(st, AT91_SAMA5D2_IDR,
BIT(chan->channel));
}
at91_adc_writel(st, AT91_SAMA5D2_CHDR,
BIT(chan->channel));
}
}
return 0;
}
@ -781,6 +754,7 @@ static int at91_adc_reenable_trigger(struct iio_trigger *trig)
/* Needed to ACK the DRDY interruption */
at91_adc_readl(st, AT91_SAMA5D2_LCDR);
return 0;
}
@ -888,18 +862,37 @@ static int at91_adc_dma_start(struct iio_dev *indio_dev)
return 0;
}
static int at91_adc_buffer_postenable(struct iio_dev *indio_dev)
static bool at91_adc_buffer_check_use_irq(struct iio_dev *indio,
struct at91_adc_state *st)
{
/* if using DMA, we do not use our own IRQ (we use DMA-controller) */
if (st->dma_st.dma_chan)
return false;
/* if the trigger is not ours, then it has its own IRQ */
if (iio_trigger_validate_own_device(indio->trig, indio))
return false;
return true;
}
static bool at91_adc_current_chan_is_touch(struct iio_dev *indio_dev)
{
struct at91_adc_state *st = iio_priv(indio_dev);
return !!bitmap_subset(indio_dev->active_scan_mask,
&st->touch_st.channels_bitmask,
AT91_SAMA5D2_MAX_CHAN_IDX + 1);
}
static int at91_adc_buffer_preenable(struct iio_dev *indio_dev)
{
int ret;
u8 bit;
struct at91_adc_state *st = iio_priv(indio_dev);
/* check if we are enabling triggered buffer or the touchscreen */
if (bitmap_subset(indio_dev->active_scan_mask,
&st->touch_st.channels_bitmask,
AT91_SAMA5D2_MAX_CHAN_IDX + 1)) {
/* touchscreen enabling */
if (at91_adc_current_chan_is_touch(indio_dev))
return at91_adc_configure_touch(st, true);
}
/* if we are not in triggered mode, we cannot enable the buffer. */
if (!(indio_dev->currentmode & INDIO_ALL_TRIGGERED_MODES))
return -EINVAL;
@ -911,41 +904,65 @@ static int at91_adc_buffer_postenable(struct iio_dev *indio_dev)
return ret;
}
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->num_channels) {
struct iio_chan_spec const *chan =
at91_adc_chan_get(indio_dev, bit);
u32 cor;
if (!chan)
continue;
/* these channel types cannot be handled by this trigger */
if (chan->type == IIO_POSITIONRELATIVE ||
chan->type == IIO_PRESSURE)
continue;
cor = at91_adc_readl(st, AT91_SAMA5D2_COR);
if (chan->differential)
cor |= (BIT(chan->channel) | BIT(chan->channel2)) <<
AT91_SAMA5D2_COR_DIFF_OFFSET;
else
cor &= ~(BIT(chan->channel) <<
AT91_SAMA5D2_COR_DIFF_OFFSET);
at91_adc_writel(st, AT91_SAMA5D2_COR, cor);
at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel));
}
if (at91_adc_buffer_check_use_irq(indio_dev, st))
at91_adc_writel(st, AT91_SAMA5D2_IER, AT91_SAMA5D2_IER_DRDY);
return 0;
}
static int at91_adc_buffer_postenable(struct iio_dev *indio_dev)
{
if (at91_adc_current_chan_is_touch(indio_dev))
return 0;
return iio_triggered_buffer_postenable(indio_dev);
}
static int at91_adc_buffer_predisable(struct iio_dev *indio_dev)
static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev)
{
struct at91_adc_state *st = iio_priv(indio_dev);
int ret;
u8 bit;
/* check if we are disabling triggered buffer or the touchscreen */
if (bitmap_subset(indio_dev->active_scan_mask,
&st->touch_st.channels_bitmask,
AT91_SAMA5D2_MAX_CHAN_IDX + 1)) {
/* touchscreen disable */
if (at91_adc_current_chan_is_touch(indio_dev))
return at91_adc_configure_touch(st, false);
}
/* if we are not in triggered mode, nothing to do here */
if (!(indio_dev->currentmode & INDIO_ALL_TRIGGERED_MODES))
return -EINVAL;
/* continue with the triggered buffer */
ret = iio_triggered_buffer_predisable(indio_dev);
if (ret < 0)
dev_err(&indio_dev->dev, "buffer predisable failed\n");
if (!st->dma_st.dma_chan)
return ret;
/* if we are using DMA we must clear registers and end DMA */
dmaengine_terminate_sync(st->dma_st.dma_chan);
/*
* For each enabled channel we must read the last converted value
* For each enable channel we must disable it in hardware.
* In the case of DMA, we must read the last converted value
* to clear EOC status and not get a possible interrupt later.
* This value is being read by DMA from LCDR anyway
* This value is being read by DMA from LCDR anyway, so it's not lost.
*/
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->num_channels) {
@ -958,16 +975,37 @@ static int at91_adc_buffer_predisable(struct iio_dev *indio_dev)
if (chan->type == IIO_POSITIONRELATIVE ||
chan->type == IIO_PRESSURE)
continue;
at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
if (st->dma_st.dma_chan)
at91_adc_readl(st, chan->address);
}
if (at91_adc_buffer_check_use_irq(indio_dev, st))
at91_adc_writel(st, AT91_SAMA5D2_IDR, AT91_SAMA5D2_IER_DRDY);
/* read overflow register to clear possible overflow status */
at91_adc_readl(st, AT91_SAMA5D2_OVER);
return ret;
/* if we are using DMA we must clear registers and end DMA */
if (st->dma_st.dma_chan)
dmaengine_terminate_sync(st->dma_st.dma_chan);
return 0;
}
static int at91_adc_buffer_predisable(struct iio_dev *indio_dev)
{
if (at91_adc_current_chan_is_touch(indio_dev))
return 0;
return iio_triggered_buffer_predisable(indio_dev);
}
static const struct iio_buffer_setup_ops at91_buffer_setup_ops = {
.preenable = &at91_adc_buffer_preenable,
.postdisable = &at91_adc_buffer_postdisable,
.postenable = &at91_adc_buffer_postenable,
.predisable = &at91_adc_buffer_predisable,
};
@ -1015,6 +1053,22 @@ static void at91_adc_trigger_handler_nodma(struct iio_dev *indio_dev,
int i = 0;
int val;
u8 bit;
u32 mask = at91_adc_active_scan_mask_to_reg(indio_dev);
unsigned int timeout = 50;
/*
* Check if the conversion is ready. If not, wait a little bit, and
* in case of timeout exit with an error.
*/
while ((at91_adc_readl(st, AT91_SAMA5D2_ISR) & mask) != mask &&
timeout) {
usleep_range(50, 100);
timeout--;
}
/* Cannot read data, not ready. Continue without reporting data */
if (!timeout)
return;
for_each_set_bit(bit, indio_dev->active_scan_mask,
indio_dev->num_channels) {
@ -1102,6 +1156,13 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct at91_adc_state *st = iio_priv(indio_dev);
/*
* If it's not our trigger, start a conversion now, as we are
* actually polling the trigger now.
*/
if (iio_trigger_validate_own_device(indio_dev->trig, indio_dev))
at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START);
if (st->dma_st.dma_chan)
at91_adc_trigger_handler_dma(indio_dev);
else
@ -1114,20 +1175,9 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
static int at91_adc_buffer_init(struct iio_dev *indio)
{
struct at91_adc_state *st = iio_priv(indio);
if (st->selected_trig->hw_trig) {
return devm_iio_triggered_buffer_setup(&indio->dev, indio,
&iio_pollfunc_store_time,
&at91_adc_trigger_handler, &at91_buffer_setup_ops);
}
/*
* we need to prepare the buffer ops in case we will get
* another buffer attached (like a callback buffer for the touchscreen)
*/
indio->setup_ops = &at91_buffer_setup_ops;
return 0;
return devm_iio_triggered_buffer_setup(&indio->dev, indio,
&iio_pollfunc_store_time,
&at91_adc_trigger_handler, &at91_buffer_setup_ops);
}
static unsigned at91_adc_startup_time(unsigned startup_time_min,
@ -1281,7 +1331,8 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
status = at91_adc_readl(st, AT91_SAMA5D2_XPOSR);
status = at91_adc_readl(st, AT91_SAMA5D2_YPOSR);
status = at91_adc_readl(st, AT91_SAMA5D2_PRESSR);
} else if (iio_buffer_enabled(indio) && !st->dma_st.dma_chan) {
} else if (iio_buffer_enabled(indio) &&
(status & AT91_SAMA5D2_IER_DRDY)) {
/* triggered buffer without DMA */
disable_irq_nosync(irq);
iio_trigger_poll(indio->trig);
@ -1901,14 +1952,10 @@ static __maybe_unused int at91_adc_resume(struct device *dev)
return 0;
/* check if we are enabling triggered buffer or the touchscreen */
if (bitmap_subset(indio_dev->active_scan_mask,
&st->touch_st.channels_bitmask,
AT91_SAMA5D2_MAX_CHAN_IDX + 1)) {
/* touchscreen enabling */
if (at91_adc_current_chan_is_touch(indio_dev))
return at91_adc_configure_touch(st, true);
} else {
else
return at91_adc_configure_trigger(st->trig, true);
}
/* not needed but more explicit */
return 0;

View File

@ -1152,7 +1152,6 @@ static int at91_adc_probe(struct platform_device *pdev)
int ret;
struct iio_dev *idev;
struct at91_adc_state *st;
struct resource *res;
u32 reg;
idev = devm_iio_device_alloc(&pdev->dev, sizeof(struct at91_adc_state));
@ -1182,9 +1181,7 @@ static int at91_adc_probe(struct platform_device *pdev)
if (st->irq < 0)
return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
st->reg_base = devm_ioremap_resource(&pdev->dev, res);
st->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(st->reg_base))
return PTR_ERR(st->reg_base);

View File

@ -449,9 +449,6 @@ static void exynos_adc_exynos7_init_hw(struct exynos_adc *info)
{
u32 con1, con2;
if (info->data->needs_adc_phy)
regmap_write(info->pmu_map, info->data->phy_offset, 1);
con1 = ADC_V2_CON1_SOFT_RESET;
writel(con1, ADC_V2_CON1(info->regs));
@ -531,8 +528,19 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
unsigned long timeout;
int ret;
if (mask != IIO_CHAN_INFO_RAW)
if (mask == IIO_CHAN_INFO_SCALE) {
ret = regulator_get_voltage(info->vdd);
if (ret < 0)
return ret;
/* Regulator voltage is in uV, but need mV */
*val = ret / 1000;
*val2 = info->data->mask;
return IIO_VAL_FRACTIONAL;
} else if (mask != IIO_CHAN_INFO_RAW) {
return -EINVAL;
}
mutex_lock(&indio_dev->mlock);
reinit_completion(&info->completion);
@ -683,6 +691,7 @@ static const struct iio_info exynos_adc_iio_info = {
.channel = _index, \
.address = _index, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \
.datasheet_name = _id, \
}

View File

@ -294,7 +294,6 @@ static int mx25_gcq_probe(struct platform_device *pdev)
struct mx25_gcq_priv *priv;
struct mx25_tsadc *tsadc = dev_get_drvdata(pdev->dev.parent);
struct device *dev = &pdev->dev;
struct resource *res;
void __iomem *mem;
int ret;
int i;
@ -305,8 +304,7 @@ static int mx25_gcq_probe(struct platform_device *pdev)
priv = iio_priv(indio_dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mem = devm_ioremap_resource(dev, res);
mem = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mem))
return PTR_ERR(mem);

View File

@ -75,7 +75,7 @@ static int mrfld_adc_single_conv(struct iio_dev *indio_dev,
struct regmap *regmap = adc->regmap;
unsigned int req;
long timeout;
u8 buf[2];
__be16 value;
int ret;
reinit_completion(&adc->completion);
@ -105,11 +105,11 @@ static int mrfld_adc_single_conv(struct iio_dev *indio_dev,
goto done;
}
ret = regmap_bulk_read(regmap, chan->address, buf, 2);
ret = regmap_bulk_read(regmap, chan->address, &value, sizeof(value));
if (ret)
goto done;
*result = get_unaligned_be16(buf);
*result = be16_to_cpu(value);
ret = IIO_VAL_INT;
done:

227
drivers/iio/adc/max1241.c Normal file
View File

@ -0,0 +1,227 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* MAX1241 low-power, 12-bit serial ADC
*
* Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX1240-MAX1241.pdf
*/
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/module.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#define MAX1241_VAL_MASK GENMASK(11, 0)
#define MAX1241_SHUTDOWN_DELAY_USEC 4
enum max1241_id {
max1241,
};
struct max1241 {
struct spi_device *spi;
struct mutex lock;
struct regulator *vdd;
struct regulator *vref;
struct gpio_desc *shutdown;
__be16 data ____cacheline_aligned;
};
static const struct iio_chan_spec max1241_channels[] = {
{
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
},
};
static int max1241_read(struct max1241 *adc)
{
struct spi_transfer xfers[] = {
/*
* Begin conversion by bringing /CS low for at least
* tconv us.
*/
{
.len = 0,
.delay.value = 8,
.delay.unit = SPI_DELAY_UNIT_USECS,
},
/*
* Then read two bytes of data in our RX buffer.
*/
{
.rx_buf = &adc->data,
.len = 2,
},
};
return spi_sync_transfer(adc->spi, xfers, ARRAY_SIZE(xfers));
}
static int max1241_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
int ret, vref_uV;
struct max1241 *adc = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&adc->lock);
if (adc->shutdown) {
gpiod_set_value(adc->shutdown, 0);
udelay(MAX1241_SHUTDOWN_DELAY_USEC);
ret = max1241_read(adc);
gpiod_set_value(adc->shutdown, 1);
} else
ret = max1241_read(adc);
if (ret) {
mutex_unlock(&adc->lock);
return ret;
}
*val = (be16_to_cpu(adc->data) >> 3) & MAX1241_VAL_MASK;
mutex_unlock(&adc->lock);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
vref_uV = regulator_get_voltage(adc->vref);
if (vref_uV < 0)
return vref_uV;
*val = vref_uV / 1000;
*val2 = 12;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
}
static const struct iio_info max1241_info = {
.read_raw = max1241_read_raw,
};
static void max1241_disable_vdd_action(void *data)
{
struct max1241 *adc = data;
struct device *dev = &adc->spi->dev;
int err;
err = regulator_disable(adc->vdd);
if (err)
dev_err(dev, "could not disable vdd regulator.\n");
}
static void max1241_disable_vref_action(void *data)
{
struct max1241 *adc = data;
struct device *dev = &adc->spi->dev;
int err;
err = regulator_disable(adc->vref);
if (err)
dev_err(dev, "could not disable vref regulator.\n");
}
static int max1241_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
struct iio_dev *indio_dev;
struct max1241 *adc;
int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
if (!indio_dev)
return -ENOMEM;
adc = iio_priv(indio_dev);
adc->spi = spi;
mutex_init(&adc->lock);
spi_set_drvdata(spi, indio_dev);
adc->vdd = devm_regulator_get(dev, "vdd");
if (IS_ERR(adc->vdd)) {
dev_err(dev, "failed to get vdd regulator\n");
return PTR_ERR(adc->vdd);
}
ret = regulator_enable(adc->vdd);
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, max1241_disable_vdd_action, adc);
if (ret) {
dev_err(dev, "could not set up vdd regulator cleanup action\n");
return ret;
}
adc->vref = devm_regulator_get(dev, "vref");
if (IS_ERR(adc->vref)) {
dev_err(dev, "failed to get vref regulator\n");
return PTR_ERR(adc->vref);
}
ret = regulator_enable(adc->vref);
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, max1241_disable_vref_action, adc);
if (ret) {
dev_err(dev, "could not set up vref regulator cleanup action\n");
return ret;
}
adc->shutdown = devm_gpiod_get_optional(dev, "shutdown",
GPIOD_OUT_HIGH);
if (IS_ERR(adc->shutdown))
return PTR_ERR(adc->shutdown);
if (adc->shutdown)
dev_dbg(dev, "shutdown pin passed, low-power mode enabled");
else
dev_dbg(dev, "no shutdown pin passed, low-power mode disabled");
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->dev.parent = dev;
indio_dev->info = &max1241_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = max1241_channels;
indio_dev->num_channels = ARRAY_SIZE(max1241_channels);
return devm_iio_device_register(dev, indio_dev);
}
static const struct spi_device_id max1241_id[] = {
{ "max1241", max1241 },
{}
};
static const struct of_device_id max1241_dt_ids[] = {
{ .compatible = "maxim,max1241" },
{}
};
MODULE_DEVICE_TABLE(of, max1241_dt_ids);
static struct spi_driver max1241_spi_driver = {
.driver = {
.name = "max1241",
.of_match_table = max1241_dt_ids,
},
.probe = max1241_probe,
.id_table = max1241_id,
};
module_spi_driver(max1241_spi_driver);
MODULE_AUTHOR("Alexandru Lazar <alazar@startmail.com>");
MODULE_DESCRIPTION("MAX1241 ADC driver");
MODULE_LICENSE("GPL v2");

View File

@ -150,6 +150,7 @@ struct max1363_chip_info {
* @current_mode: the scan mode of this chip
* @requestedmask: a valid requested set of channels
* @reg: supply regulator
* @lock lock to ensure state is consistent
* @monitor_on: whether monitor mode is enabled
* @monitor_speed: parameter corresponding to device monitor speed setting
* @mask_high: bitmask for enabled high thresholds
@ -169,6 +170,7 @@ struct max1363_state {
const struct max1363_mode *current_mode;
u32 requestedmask;
struct regulator *reg;
struct mutex lock;
/* Using monitor modes and buffer at the same time is
currently not supported */
@ -364,7 +366,11 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
struct max1363_state *st = iio_priv(indio_dev);
struct i2c_client *client = st->client;
mutex_lock(&indio_dev->mlock);
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
mutex_lock(&st->lock);
/*
* If monitor mode is enabled, the method for reading a single
* channel will have to be rather different and has not yet
@ -372,7 +378,7 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
*
* Also, cannot read directly if buffered capture enabled.
*/
if (st->monitor_on || iio_buffer_enabled(indio_dev)) {
if (st->monitor_on) {
ret = -EBUSY;
goto error_ret;
}
@ -404,8 +410,10 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
data = rxbuf[0];
}
*val = data;
error_ret:
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
iio_device_release_direct_mode(indio_dev);
return ret;
}
@ -705,9 +713,9 @@ static ssize_t max1363_monitor_store_freq(struct device *dev,
if (!found)
return -EINVAL;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->monitor_speed = i;
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return 0;
}
@ -810,12 +818,12 @@ static int max1363_read_event_config(struct iio_dev *indio_dev,
int val;
int number = chan->channel;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
if (dir == IIO_EV_DIR_FALLING)
val = (1 << number) & st->mask_low;
else
val = (1 << number) & st->mask_high;
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return val;
}
@ -962,7 +970,11 @@ static int max1363_write_event_config(struct iio_dev *indio_dev,
u16 unifiedmask;
int number = chan->channel;
mutex_lock(&indio_dev->mlock);
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
mutex_lock(&st->lock);
unifiedmask = st->mask_low | st->mask_high;
if (dir == IIO_EV_DIR_FALLING) {
@ -989,7 +1001,8 @@ static int max1363_write_event_config(struct iio_dev *indio_dev,
max1363_monitor_mode_update(st, !!(st->mask_high | st->mask_low));
error_ret:
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
iio_device_release_direct_mode(indio_dev);
return ret;
}
@ -1587,6 +1600,7 @@ static int max1363_probe(struct i2c_client *client,
st = iio_priv(indio_dev);
mutex_init(&st->lock);
st->reg = devm_regulator_get(&client->dev, "vcc");
if (IS_ERR(st->reg)) {
ret = PTR_ERR(st->reg);

View File

@ -19,6 +19,7 @@
#include <linux/delay.h>
#include <linux/sysfs.h>
#include <linux/of.h>
#include <asm/unaligned.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@ -117,11 +118,11 @@ static int mcp3422_read(struct mcp3422 *adc, int *value, u8 *config)
if (sample_rate == MCP3422_SRATE_3) {
ret = i2c_master_recv(adc->i2c, buf, 4);
temp = buf[0] << 16 | buf[1] << 8 | buf[2];
temp = get_unaligned_be24(&buf[0]);
*config = buf[3];
} else {
ret = i2c_master_recv(adc->i2c, buf, 3);
temp = buf[0] << 8 | buf[1];
temp = get_unaligned_be16(&buf[0]);
*config = buf[2];
}

View File

@ -65,12 +65,14 @@ struct stm32_adc_priv;
* @clk_sel: clock selection routine
* @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet)
* @has_syscfg: SYSCFG capability flags
* @num_irqs: number of interrupt lines
*/
struct stm32_adc_priv_cfg {
const struct stm32_adc_common_regs *regs;
int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *);
u32 max_clk_rate_hz;
unsigned int has_syscfg;
unsigned int num_irqs;
};
/**
@ -375,21 +377,15 @@ static int stm32_adc_irq_probe(struct platform_device *pdev,
struct device_node *np = pdev->dev.of_node;
unsigned int i;
for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
/*
* Interrupt(s) must be provided, depending on the compatible:
* - stm32f4/h7 shares a common interrupt line.
* - stm32mp1, has one line per ADC
*/
for (i = 0; i < priv->cfg->num_irqs; i++) {
priv->irq[i] = platform_get_irq(pdev, i);
if (priv->irq[i] < 0) {
/*
* At least one interrupt must be provided, make others
* optional:
* - stm32f4/h7 shares a common interrupt.
* - stm32mp1, has one line per ADC (either for ADC1,
* ADC2 or both).
*/
if (i && priv->irq[i] == -ENXIO)
continue;
if (priv->irq[i] < 0)
return priv->irq[i];
}
}
priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS, 0,
@ -400,9 +396,7 @@ static int stm32_adc_irq_probe(struct platform_device *pdev,
return -ENOMEM;
}
for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
if (priv->irq[i] < 0)
continue;
for (i = 0; i < priv->cfg->num_irqs; i++) {
irq_set_chained_handler(priv->irq[i], stm32_adc_irq_handler);
irq_set_handler_data(priv->irq[i], priv);
}
@ -420,11 +414,8 @@ static void stm32_adc_irq_remove(struct platform_device *pdev,
irq_dispose_mapping(irq_find_mapping(priv->domain, hwirq));
irq_domain_remove(priv->domain);
for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
if (priv->irq[i] < 0)
continue;
for (i = 0; i < priv->cfg->num_irqs; i++)
irq_set_chained_handler(priv->irq[i], NULL);
}
}
static int stm32_adc_core_switches_supply_en(struct stm32_adc_priv *priv,
@ -817,6 +808,7 @@ static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = {
.regs = &stm32f4_adc_common_regs,
.clk_sel = stm32f4_adc_clk_sel,
.max_clk_rate_hz = 36000000,
.num_irqs = 1,
};
static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = {
@ -824,6 +816,7 @@ static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = {
.clk_sel = stm32h7_adc_clk_sel,
.max_clk_rate_hz = 36000000,
.has_syscfg = HAS_VBOOSTER,
.num_irqs = 1,
};
static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = {
@ -831,6 +824,7 @@ static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = {
.clk_sel = stm32h7_adc_clk_sel,
.max_clk_rate_hz = 40000000,
.has_syscfg = HAS_VBOOSTER | HAS_ANASWVDD,
.num_irqs = 2,
};
static const struct of_device_id stm32_adc_of_match[] = {

View File

@ -496,7 +496,6 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
struct iio_dev *indio_dev)
{
struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
struct resource *mem;
void __iomem *base;
int ret;
@ -508,8 +507,7 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
indio_dev->num_channels = ARRAY_SIZE(sun8i_a33_gpadc_channels);
indio_dev->channels = sun8i_a33_gpadc_channels;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, mem);
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);

View File

@ -22,6 +22,8 @@
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/sysfs.h>
#include <asm/unaligned.h>
/* Commands */
#define ADS124S08_CMD_NOP 0x00
#define ADS124S08_CMD_WAKEUP 0x02
@ -188,7 +190,6 @@ static int ads124s_read(struct iio_dev *indio_dev, unsigned int chan)
{
struct ads124s_private *priv = iio_priv(indio_dev);
int ret;
u32 tmp;
struct spi_transfer t[] = {
{
.tx_buf = &priv->data[0],
@ -208,9 +209,7 @@ static int ads124s_read(struct iio_dev *indio_dev, unsigned int chan)
if (ret < 0)
return ret;
tmp = priv->data[2] << 16 | priv->data[3] << 8 | priv->data[4];
return tmp;
return get_unaligned_be24(&priv->data[2]);
}
static int ads124s_read_raw(struct iio_dev *indio_dev,

View File

@ -3,7 +3,7 @@
* Xilinx XADC driver
*
* Copyright 2013-2014 Analog Devices Inc.
* Author: Lars-Peter Clauen <lars@metafoo.de>
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Documentation for the parts can be found at:
* - XADC hardmacro: Xilinx UG480
@ -663,7 +663,7 @@ static int xadc_trigger_set_state(struct iio_trigger *trigger, bool state)
mutex_lock(&xadc->mutex);
if (state) {
/* Only one of the two triggers can be active at the a time. */
/* Only one of the two triggers can be active at a time. */
if (xadc->trigger != NULL) {
ret = -EBUSY;
goto err_out;

View File

@ -3,7 +3,7 @@
* Xilinx XADC driver
*
* Copyright 2013 Analog Devices Inc.
* Author: Lars-Peter Clauen <lars@metafoo.de>
* Author: Lars-Peter Clausen <lars@metafoo.de>
*/
#include <linux/iio/events.h>

View File

@ -3,7 +3,7 @@
* Xilinx XADC driver
*
* Copyright 2013 Analog Devices Inc.
* Author: Lars-Peter Clauen <lars@metafoo.de>
* Author: Lars-Peter Clausen <lars@metafoo.de>
*/
#ifndef __IIO_XILINX_XADC__

View File

@ -12,7 +12,6 @@
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/iio/buffer.h>
#include <linux/iio/buffer_impl.h>
#include <linux/iio/buffer-dma.h>
#include <linux/dma-mapping.h>

View File

@ -134,7 +134,7 @@ static ssize_t iio_dmaengine_buffer_get_length_align(struct device *dev,
struct dmaengine_buffer *dmaengine_buffer =
iio_buffer_to_dmaengine_buffer(indio_dev->buffer);
return sprintf(buf, "%u\n", dmaengine_buffer->align);
return sprintf(buf, "%zu\n", dmaengine_buffer->align);
}
static IIO_DEVICE_ATTR(length_align_bytes, 0444,
@ -229,6 +229,45 @@ void iio_dmaengine_buffer_free(struct iio_buffer *buffer)
}
EXPORT_SYMBOL_GPL(iio_dmaengine_buffer_free);
static void __devm_iio_dmaengine_buffer_free(struct device *dev, void *res)
{
iio_dmaengine_buffer_free(*(struct iio_buffer **)res);
}
/**
* devm_iio_dmaengine_buffer_alloc() - Resource-managed iio_dmaengine_buffer_alloc()
* @dev: Parent device for the buffer
* @channel: DMA channel name, typically "rx".
*
* This allocates a new IIO buffer which internally uses the DMAengine framework
* to perform its transfers. The parent device will be used to request the DMA
* channel.
*
* The buffer will be automatically de-allocated once the device gets destroyed.
*/
struct iio_buffer *devm_iio_dmaengine_buffer_alloc(struct device *dev,
const char *channel)
{
struct iio_buffer **bufferp, *buffer;
bufferp = devres_alloc(__devm_iio_dmaengine_buffer_free,
sizeof(*bufferp), GFP_KERNEL);
if (!bufferp)
return ERR_PTR(-ENOMEM);
buffer = iio_dmaengine_buffer_alloc(dev, channel);
if (IS_ERR(buffer)) {
devres_free(bufferp);
return buffer;
}
*bufferp = buffer;
devres_add(dev, bufferp);
return buffer;
}
EXPORT_SYMBOL_GPL(devm_iio_dmaengine_buffer_alloc);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("DMA buffer for the IIO framework");
MODULE_LICENSE("GPL");

View File

@ -142,17 +142,6 @@ static void devm_iio_hw_consumer_release(struct device *dev, void *res)
iio_hw_consumer_free(*(struct iio_hw_consumer **)res);
}
static int devm_iio_hw_consumer_match(struct device *dev, void *res, void *data)
{
struct iio_hw_consumer **r = res;
if (!r || !*r) {
WARN_ON(!r || !*r);
return 0;
}
return *r == data;
}
/**
* devm_iio_hw_consumer_alloc - Resource-managed iio_hw_consumer_alloc()
* @dev: Pointer to consumer device.
@ -160,9 +149,6 @@ static int devm_iio_hw_consumer_match(struct device *dev, void *res, void *data)
* Managed iio_hw_consumer_alloc. iio_hw_consumer allocated with this function
* is automatically freed on driver detach.
*
* If an iio_hw_consumer allocated with this function needs to be freed
* separately, devm_iio_hw_consumer_free() must be used.
*
* returns pointer to allocated iio_hw_consumer on success, NULL on failure.
*/
struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev)
@ -186,23 +172,6 @@ struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev)
}
EXPORT_SYMBOL_GPL(devm_iio_hw_consumer_alloc);
/**
* devm_iio_hw_consumer_free - Resource-managed iio_hw_consumer_free()
* @dev: Pointer to consumer device.
* @hwc: iio_hw_consumer to free.
*
* Free iio_hw_consumer allocated with devm_iio_hw_consumer_alloc().
*/
void devm_iio_hw_consumer_free(struct device *dev, struct iio_hw_consumer *hwc)
{
int rc;
rc = devres_release(dev, devm_iio_hw_consumer_release,
devm_iio_hw_consumer_match, hwc);
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_iio_hw_consumer_free);
/**
* iio_hw_consumer_enable() - Enable IIO hardware consumer
* @hwc: iio_hw_consumer to enable.

View File

@ -126,17 +126,6 @@ int devm_iio_triggered_buffer_setup(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_setup);
void devm_iio_triggered_buffer_cleanup(struct device *dev,
struct iio_dev *indio_dev)
{
int rc;
rc = devres_release(dev, devm_iio_triggered_buffer_clean,
devm_iio_device_match, indio_dev);
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_cleanup);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("IIO helper functions for setting up triggered buffers");
MODULE_LICENSE("GPL");

View File

@ -179,16 +179,6 @@ static void devm_iio_kfifo_release(struct device *dev, void *res)
iio_kfifo_free(*(struct iio_buffer **)res);
}
static int devm_iio_kfifo_match(struct device *dev, void *res, void *data)
{
struct iio_buffer **r = res;
if (WARN_ON(!r || !*r))
return 0;
return *r == data;
}
/**
* devm_iio_fifo_allocate - Resource-managed iio_kfifo_allocate()
* @dev: Device to allocate kfifo buffer for
@ -216,16 +206,4 @@ struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev)
}
EXPORT_SYMBOL(devm_iio_kfifo_allocate);
/**
* devm_iio_fifo_free - Resource-managed iio_kfifo_free()
* @dev: Device the buffer belongs to
* @r: The buffer associated with the device
*/
void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r)
{
WARN_ON(devres_release(dev, devm_iio_kfifo_release,
devm_iio_kfifo_match, r));
}
EXPORT_SYMBOL(devm_iio_kfifo_free);
MODULE_LICENSE("GPL");

View File

@ -22,6 +22,17 @@ config ATLAS_PH_SENSOR
To compile this driver as module, choose M here: the
module will be called atlas-ph-sensor.
config ATLAS_EZO_SENSOR
tristate "Atlas Scientific EZO sensors"
depends on I2C
help
Say Y here to build I2C interface support for the following
Atlas Scientific EZO sensors
* CO2 EZO Sensor
To compile this driver as module, choose M here: the
module will be called atlas-ezo-sensor.
config BME680
tristate "Bosch Sensortec BME680 sensor driver"
depends on (I2C || SPI)

View File

@ -5,6 +5,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-sensor.o
obj-$(CONFIG_ATLAS_EZO_SENSOR) += atlas-ezo-sensor.o
obj-$(CONFIG_BME680) += bme680_core.o
obj-$(CONFIG_BME680_I2C) += bme680_i2c.o
obj-$(CONFIG_BME680_SPI) += bme680_spi.o

View File

@ -0,0 +1,177 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* atlas-ezo-sensor.c - Support for Atlas Scientific EZO sensors
*
* Copyright (C) 2020 Konsulko Group
* Author: Matt Ranostay <matt.ranostay@konsulko.com>
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/of_device.h>
#include <linux/iio/iio.h>
#define ATLAS_EZO_DRV_NAME "atlas-ezo-sensor"
#define ATLAS_CO2_INT_TIME_IN_MS 950
enum {
ATLAS_CO2_EZO,
};
struct atlas_ezo_device {
const struct iio_chan_spec *channels;
int num_channels;
int delay;
};
struct atlas_ezo_data {
struct i2c_client *client;
struct atlas_ezo_device *chip;
/* lock to avoid multiple concurrent read calls */
struct mutex lock;
u8 buffer[8];
};
static const struct iio_chan_spec atlas_co2_ezo_channels[] = {
{
.type = IIO_CONCENTRATION,
.modified = 1,
.channel2 = IIO_MOD_CO2,
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
.scan_index = 0,
.scan_type = {
.sign = 'u',
.realbits = 32,
.storagebits = 32,
.endianness = IIO_CPU,
},
},
};
static struct atlas_ezo_device atlas_ezo_devices[] = {
[ATLAS_CO2_EZO] = {
.channels = atlas_co2_ezo_channels,
.num_channels = 1,
.delay = ATLAS_CO2_INT_TIME_IN_MS,
},
};
static int atlas_ezo_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct atlas_ezo_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
int ret = 0;
if (chan->type != IIO_CONCENTRATION)
return -EINVAL;
switch (mask) {
case IIO_CHAN_INFO_RAW: {
long tmp;
mutex_lock(&data->lock);
tmp = i2c_smbus_write_byte(client, 'R');
if (tmp < 0) {
mutex_unlock(&data->lock);
return tmp;
}
msleep(data->chip->delay);
tmp = i2c_master_recv(client, data->buffer, sizeof(data->buffer));
if (tmp < 0 || data->buffer[0] != 1) {
mutex_unlock(&data->lock);
return -EBUSY;
}
ret = kstrtol(data->buffer + 1, 10, &tmp);
*val = tmp;
mutex_unlock(&data->lock);
return ret ? ret : IIO_VAL_INT;
}
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = 100; /* 0.0001 */
return IIO_VAL_INT_PLUS_MICRO;
}
return ret;
}
static const struct iio_info atlas_info = {
.read_raw = atlas_ezo_read_raw,
};
static const struct i2c_device_id atlas_ezo_id[] = {
{ "atlas-co2-ezo", ATLAS_CO2_EZO },
{}
};
MODULE_DEVICE_TABLE(i2c, atlas_ezo_id);
static const struct of_device_id atlas_ezo_dt_ids[] = {
{ .compatible = "atlas,co2-ezo", .data = (void *)ATLAS_CO2_EZO, },
{}
};
MODULE_DEVICE_TABLE(of, atlas_ezo_dt_ids);
static int atlas_ezo_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct atlas_ezo_data *data;
struct atlas_ezo_device *chip;
const struct of_device_id *of_id;
struct iio_dev *indio_dev;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
of_id = of_match_device(atlas_ezo_dt_ids, &client->dev);
if (!of_id)
chip = &atlas_ezo_devices[id->driver_data];
else
chip = &atlas_ezo_devices[(unsigned long)of_id->data];
indio_dev->info = &atlas_info;
indio_dev->name = ATLAS_EZO_DRV_NAME;
indio_dev->channels = chip->channels;
indio_dev->num_channels = chip->num_channels;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->dev.parent = &client->dev;
data = iio_priv(indio_dev);
data->client = client;
data->chip = chip;
mutex_init(&data->lock);
return devm_iio_device_register(&client->dev, indio_dev);
};
static struct i2c_driver atlas_ezo_driver = {
.driver = {
.name = ATLAS_EZO_DRV_NAME,
.of_match_table = atlas_ezo_dt_ids,
},
.probe = atlas_ezo_probe,
.id_table = atlas_ezo_id,
};
module_i2c_driver(atlas_ezo_driver);
MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
MODULE_DESCRIPTION("Atlas Scientific EZO sensors");
MODULE_LICENSE("GPL");

View File

@ -53,6 +53,8 @@
#define ATLAS_REG_DO_CALIB_STATUS_PRESSURE BIT(0)
#define ATLAS_REG_DO_CALIB_STATUS_DO BIT(1)
#define ATLAS_REG_RTD_DATA 0x0e
#define ATLAS_REG_PH_TEMP_DATA 0x0e
#define ATLAS_REG_PH_DATA 0x16
@ -72,12 +74,14 @@
#define ATLAS_EC_INT_TIME_IN_MS 650
#define ATLAS_ORP_INT_TIME_IN_MS 450
#define ATLAS_DO_INT_TIME_IN_MS 450
#define ATLAS_RTD_INT_TIME_IN_MS 450
enum {
ATLAS_PH_SM,
ATLAS_EC_SM,
ATLAS_ORP_SM,
ATLAS_DO_SM,
ATLAS_RTD_SM,
};
struct atlas_data {
@ -218,6 +222,22 @@ static const struct iio_chan_spec atlas_do_channels[] = {
},
};
static const struct iio_chan_spec atlas_rtd_channels[] = {
{
.type = IIO_TEMP,
.address = ATLAS_REG_RTD_DATA,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
.scan_index = 0,
.scan_type = {
.sign = 's',
.realbits = 32,
.storagebits = 32,
.endianness = IIO_BE,
},
},
IIO_CHAN_SOFT_TIMESTAMP(1),
};
static int atlas_check_ph_calibration(struct atlas_data *data)
{
struct device *dev = &data->client->dev;
@ -362,6 +382,12 @@ static struct atlas_device atlas_devices[] = {
.calibration = &atlas_check_do_calibration,
.delay = ATLAS_DO_INT_TIME_IN_MS,
},
[ATLAS_RTD_SM] = {
.channels = atlas_rtd_channels,
.num_channels = 2,
.data_reg = ATLAS_REG_RTD_DATA,
.delay = ATLAS_RTD_INT_TIME_IN_MS,
},
};
static int atlas_set_powermode(struct atlas_data *data, int on)
@ -438,8 +464,7 @@ static irqreturn_t atlas_trigger_handler(int irq, void *private)
int ret;
ret = regmap_bulk_read(data->regmap, data->chip->data_reg,
(u8 *) &data->buffer,
sizeof(__be32) * channels);
&data->buffer, sizeof(__be32) * channels);
if (!ret)
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
@ -475,7 +500,7 @@ static int atlas_read_measurement(struct atlas_data *data, int reg, __be32 *val)
if (suspended)
msleep(data->chip->delay);
ret = regmap_bulk_read(data->regmap, reg, (u8 *) val, sizeof(*val));
ret = regmap_bulk_read(data->regmap, reg, val, sizeof(*val));
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
@ -490,6 +515,7 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
struct atlas_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
case IIO_CHAN_INFO_RAW: {
int ret;
__be32 reg;
@ -497,7 +523,7 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
switch (chan->type) {
case IIO_TEMP:
ret = regmap_bulk_read(data->regmap, chan->address,
(u8 *) &reg, sizeof(reg));
&reg, sizeof(reg));
break;
case IIO_PH:
case IIO_CONCENTRATION:
@ -578,6 +604,7 @@ static const struct i2c_device_id atlas_id[] = {
{ "atlas-ec-sm", ATLAS_EC_SM},
{ "atlas-orp-sm", ATLAS_ORP_SM},
{ "atlas-do-sm", ATLAS_DO_SM},
{ "atlas-rtd-sm", ATLAS_RTD_SM},
{}
};
MODULE_DEVICE_TABLE(i2c, atlas_id);
@ -587,6 +614,7 @@ static const struct of_device_id atlas_dt_ids[] = {
{ .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, },
{ .compatible = "atlas,orp-sm", .data = (void *)ATLAS_ORP_SM, },
{ .compatible = "atlas,do-sm", .data = (void *)ATLAS_DO_SM, },
{ .compatible = "atlas,rtd-sm", .data = (void *)ATLAS_RTD_SM, },
{ }
};
MODULE_DEVICE_TABLE(of, atlas_dt_ids);

View File

@ -114,14 +114,16 @@ static int bme680_read_calib(struct bme680_data *data,
__le16 buf;
/* Temperature related coefficients */
ret = regmap_bulk_read(data->regmap, BME680_T1_LSB_REG, (u8 *) &buf, 2);
ret = regmap_bulk_read(data->regmap, BME680_T1_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_T1_LSB_REG\n");
return ret;
}
calib->par_t1 = le16_to_cpu(buf);
ret = regmap_bulk_read(data->regmap, BME680_T2_LSB_REG, (u8 *) &buf, 2);
ret = regmap_bulk_read(data->regmap, BME680_T2_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_T2_LSB_REG\n");
return ret;
@ -136,14 +138,16 @@ static int bme680_read_calib(struct bme680_data *data,
calib->par_t3 = tmp;
/* Pressure related coefficients */
ret = regmap_bulk_read(data->regmap, BME680_P1_LSB_REG, (u8 *) &buf, 2);
ret = regmap_bulk_read(data->regmap, BME680_P1_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P1_LSB_REG\n");
return ret;
}
calib->par_p1 = le16_to_cpu(buf);
ret = regmap_bulk_read(data->regmap, BME680_P2_LSB_REG, (u8 *) &buf, 2);
ret = regmap_bulk_read(data->regmap, BME680_P2_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P2_LSB_REG\n");
return ret;
@ -157,14 +161,16 @@ static int bme680_read_calib(struct bme680_data *data,
}
calib->par_p3 = tmp;
ret = regmap_bulk_read(data->regmap, BME680_P4_LSB_REG, (u8 *) &buf, 2);
ret = regmap_bulk_read(data->regmap, BME680_P4_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P4_LSB_REG\n");
return ret;
}
calib->par_p4 = le16_to_cpu(buf);
ret = regmap_bulk_read(data->regmap, BME680_P5_LSB_REG, (u8 *) &buf, 2);
ret = regmap_bulk_read(data->regmap, BME680_P5_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P5_LSB_REG\n");
return ret;
@ -185,14 +191,16 @@ static int bme680_read_calib(struct bme680_data *data,
}
calib->par_p7 = tmp;
ret = regmap_bulk_read(data->regmap, BME680_P8_LSB_REG, (u8 *) &buf, 2);
ret = regmap_bulk_read(data->regmap, BME680_P8_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P8_LSB_REG\n");
return ret;
}
calib->par_p8 = le16_to_cpu(buf);
ret = regmap_bulk_read(data->regmap, BME680_P9_LSB_REG, (u8 *) &buf, 2);
ret = regmap_bulk_read(data->regmap, BME680_P9_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_P9_LSB_REG\n");
return ret;
@ -276,8 +284,8 @@ static int bme680_read_calib(struct bme680_data *data,
}
calib->par_gh1 = tmp;
ret = regmap_bulk_read(data->regmap, BME680_GH2_LSB_REG, (u8 *) &buf,
2);
ret = regmap_bulk_read(data->regmap, BME680_GH2_LSB_REG,
&buf, sizeof(buf));
if (ret < 0) {
dev_err(dev, "failed to read BME680_GH2_LSB_REG\n");
return ret;
@ -615,7 +623,7 @@ static int bme680_read_temp(struct bme680_data *data, int *val)
return ret;
ret = regmap_bulk_read(data->regmap, BME680_REG_TEMP_MSB,
(u8 *) &tmp, 3);
&tmp, 3);
if (ret < 0) {
dev_err(dev, "failed to read temperature\n");
return ret;
@ -656,7 +664,7 @@ static int bme680_read_press(struct bme680_data *data,
return ret;
ret = regmap_bulk_read(data->regmap, BME680_REG_PRESS_MSB,
(u8 *) &tmp, 3);
&tmp, 3);
if (ret < 0) {
dev_err(dev, "failed to read pressure\n");
return ret;
@ -689,7 +697,7 @@ static int bme680_read_humid(struct bme680_data *data,
return ret;
ret = regmap_bulk_read(data->regmap, BM6880_REG_HUMIDITY_MSB,
(u8 *) &tmp, 2);
&tmp, sizeof(tmp));
if (ret < 0) {
dev_err(dev, "failed to read humidity\n");
return ret;
@ -754,7 +762,7 @@ static int bme680_read_gas(struct bme680_data *data,
}
ret = regmap_bulk_read(data->regmap, BME680_REG_GAS_MSB,
(u8 *) &tmp, 2);
&tmp, sizeof(tmp));
if (ret < 0) {
dev_err(dev, "failed to read gas resistance\n");
return ret;

View File

@ -16,6 +16,7 @@
*/
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
@ -36,6 +37,7 @@
#define CCS811_ERR 0xE0
/* Used to transition from boot to application mode */
#define CCS811_APP_START 0xF4
#define CCS811_SW_RESET 0xFF
/* Status register flags */
#define CCS811_STATUS_ERROR BIT(0)
@ -74,6 +76,7 @@ struct ccs811_data {
struct mutex lock; /* Protect readings */
struct ccs811_reading buffer;
struct iio_trigger *drdy_trig;
struct gpio_desc *wakeup_gpio;
bool drdy_trig_on;
};
@ -166,10 +169,25 @@ static int ccs811_setup(struct i2c_client *client)
CCS811_MODE_IAQ_1SEC);
}
static void ccs811_set_wakeup(struct ccs811_data *data, bool enable)
{
if (!data->wakeup_gpio)
return;
gpiod_set_value(data->wakeup_gpio, enable);
if (enable)
usleep_range(50, 60);
else
usleep_range(20, 30);
}
static int ccs811_get_measurement(struct ccs811_data *data)
{
int ret, tries = 11;
ccs811_set_wakeup(data, true);
/* Maximum waiting time: 1s, as measurements are made every second */
while (tries-- > 0) {
ret = i2c_smbus_read_byte_data(data->client, CCS811_STATUS);
@ -183,9 +201,12 @@ static int ccs811_get_measurement(struct ccs811_data *data)
if (!(ret & CCS811_STATUS_DATA_READY))
return -EIO;
return i2c_smbus_read_i2c_block_data(data->client,
ret = i2c_smbus_read_i2c_block_data(data->client,
CCS811_ALG_RESULT_DATA, 8,
(char *)&data->buffer);
ccs811_set_wakeup(data, false);
return ret;
}
static int ccs811_read_raw(struct iio_dev *indio_dev,
@ -336,6 +357,45 @@ static irqreturn_t ccs811_data_rdy_trigger_poll(int irq, void *private)
return IRQ_HANDLED;
}
static int ccs811_reset(struct i2c_client *client)
{
struct gpio_desc *reset_gpio;
int ret;
reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(reset_gpio))
return PTR_ERR(reset_gpio);
/* Try to reset using nRESET pin if available else do SW reset */
if (reset_gpio) {
gpiod_set_value(reset_gpio, 1);
usleep_range(20, 30);
gpiod_set_value(reset_gpio, 0);
} else {
/*
* As per the datasheet, this sequence of values needs to be
* written to the SW_RESET register for triggering the soft
* reset in the device and placing it in boot mode.
*/
static const u8 reset_seq[] = {
0x11, 0xE5, 0x72, 0x8A,
};
ret = i2c_smbus_write_i2c_block_data(client, CCS811_SW_RESET,
sizeof(reset_seq), reset_seq);
if (ret < 0) {
dev_err(&client->dev, "Failed to reset sensor\n");
return ret;
}
}
/* tSTART delay required after reset */
usleep_range(1000, 2000);
return 0;
}
static int ccs811_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@ -348,37 +408,60 @@ static int ccs811_probe(struct i2c_client *client,
| I2C_FUNC_SMBUS_READ_I2C_BLOCK))
return -EOPNOTSUPP;
/* Check hardware id (should be 0x81 for this family of devices) */
ret = i2c_smbus_read_byte_data(client, CCS811_HW_ID);
if (ret < 0)
return ret;
if (ret != CCS811_HW_ID_VALUE) {
dev_err(&client->dev, "hardware id doesn't match CCS81x\n");
return -ENODEV;
}
ret = i2c_smbus_read_byte_data(client, CCS811_HW_VERSION);
if (ret < 0)
return ret;
if ((ret & CCS811_HW_VERSION_MASK) != CCS811_HW_VERSION_VALUE) {
dev_err(&client->dev, "no CCS811 sensor\n");
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
ret = ccs811_setup(client);
if (ret < 0)
return ret;
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
data->wakeup_gpio = devm_gpiod_get_optional(&client->dev, "wakeup",
GPIOD_OUT_HIGH);
if (IS_ERR(data->wakeup_gpio))
return PTR_ERR(data->wakeup_gpio);
ccs811_set_wakeup(data, true);
ret = ccs811_reset(client);
if (ret) {
ccs811_set_wakeup(data, false);
return ret;
}
/* Check hardware id (should be 0x81 for this family of devices) */
ret = i2c_smbus_read_byte_data(client, CCS811_HW_ID);
if (ret < 0) {
ccs811_set_wakeup(data, false);
return ret;
}
if (ret != CCS811_HW_ID_VALUE) {
dev_err(&client->dev, "hardware id doesn't match CCS81x\n");
ccs811_set_wakeup(data, false);
return -ENODEV;
}
ret = i2c_smbus_read_byte_data(client, CCS811_HW_VERSION);
if (ret < 0) {
ccs811_set_wakeup(data, false);
return ret;
}
if ((ret & CCS811_HW_VERSION_MASK) != CCS811_HW_VERSION_VALUE) {
dev_err(&client->dev, "no CCS811 sensor\n");
ccs811_set_wakeup(data, false);
return -ENODEV;
}
ret = ccs811_setup(client);
if (ret < 0) {
ccs811_set_wakeup(data, false);
return ret;
}
ccs811_set_wakeup(data, false);
mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev;
@ -466,9 +549,16 @@ static const struct i2c_device_id ccs811_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ccs811_id);
static const struct of_device_id ccs811_dt_ids[] = {
{ .compatible = "ams,ccs811" },
{ }
};
MODULE_DEVICE_TABLE(of, ccs811_dt_ids);
static struct i2c_driver ccs811_driver = {
.driver = {
.name = "ccs811",
.of_match_table = ccs811_dt_ids,
},
.probe = ccs811_probe,
.remove = ccs811_remove,

View File

@ -73,6 +73,11 @@ struct pms7003_state {
struct pms7003_frame frame;
struct completion frame_ready;
struct mutex lock; /* must be held whenever state gets touched */
/* Used to construct scan to push to the IIO buffer */
struct {
u16 data[3]; /* PM1, PM2P5, PM10 */
s64 ts;
} scan;
};
static int pms7003_do_cmd(struct pms7003_state *state, enum pms7003_cmd cmd)
@ -104,7 +109,6 @@ static irqreturn_t pms7003_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct pms7003_state *state = iio_priv(indio_dev);
struct pms7003_frame *frame = &state->frame;
u16 data[3 + 1 + 4]; /* PM1, PM2P5, PM10, padding, timestamp */
int ret;
mutex_lock(&state->lock);
@ -114,12 +118,15 @@ static irqreturn_t pms7003_trigger_handler(int irq, void *p)
goto err;
}
data[PM1] = pms7003_get_pm(frame->data + PMS7003_PM1_OFFSET);
data[PM2P5] = pms7003_get_pm(frame->data + PMS7003_PM2P5_OFFSET);
data[PM10] = pms7003_get_pm(frame->data + PMS7003_PM10_OFFSET);
state->scan.data[PM1] =
pms7003_get_pm(frame->data + PMS7003_PM1_OFFSET);
state->scan.data[PM2P5] =
pms7003_get_pm(frame->data + PMS7003_PM2P5_OFFSET);
state->scan.data[PM10] =
pms7003_get_pm(frame->data + PMS7003_PM10_OFFSET);
mutex_unlock(&state->lock);
iio_push_to_buffers_with_timestamp(indio_dev, data,
iio_push_to_buffers_with_timestamp(indio_dev, &state->scan,
iio_get_time_ns(indio_dev));
err:
iio_trigger_notify_done(indio_dev->trig);

View File

@ -230,15 +230,18 @@ static irqreturn_t sps30_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct sps30_state *state = iio_priv(indio_dev);
int ret;
s32 data[4 + 2]; /* PM1, PM2P5, PM4, PM10, timestamp */
struct {
s32 data[4]; /* PM1, PM2P5, PM4, PM10 */
s64 ts;
} scan;
mutex_lock(&state->lock);
ret = sps30_do_meas(state, data, 4);
ret = sps30_do_meas(state, scan.data, ARRAY_SIZE(scan.data));
mutex_unlock(&state->lock);
if (ret)
goto err;
iio_push_to_buffers_with_timestamp(indio_dev, data,
iio_push_to_buffers_with_timestamp(indio_dev, &scan,
iio_get_time_ns(indio_dev));
err:
iio_trigger_notify_done(indio_dev->trig);

View File

@ -13,6 +13,8 @@
#include <linux/hid-sensor-hub.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/buffer.h>
#include <linux/iio/sysfs.h>
#include "hid-sensor-trigger.h"
@ -222,7 +224,8 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
return hid_sensor_power_state(iio_trigger_get_drvdata(trig), state);
}
void hid_sensor_remove_trigger(struct hid_sensor_common *attrb)
void hid_sensor_remove_trigger(struct iio_dev *indio_dev,
struct hid_sensor_common *attrb)
{
if (atomic_read(&attrb->runtime_pm_enable))
pm_runtime_disable(&attrb->pdev->dev);
@ -233,6 +236,7 @@ void hid_sensor_remove_trigger(struct hid_sensor_common *attrb)
cancel_work_sync(&attrb->work);
iio_trigger_unregister(attrb->trigger);
iio_trigger_free(attrb->trigger);
iio_triggered_buffer_cleanup(indio_dev);
}
EXPORT_SYMBOL(hid_sensor_remove_trigger);
@ -246,11 +250,18 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
int ret;
struct iio_trigger *trig;
ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
NULL, NULL);
if (ret) {
dev_err(&indio_dev->dev, "Triggered Buffer Setup Failed\n");
return ret;
}
trig = iio_trigger_alloc("%s-dev%d", name, indio_dev->id);
if (trig == NULL) {
dev_err(&indio_dev->dev, "Trigger Allocate Failed\n");
ret = -ENOMEM;
goto error_ret;
goto error_triggered_buffer_cleanup;
}
trig->dev.parent = indio_dev->dev.parent;
@ -284,7 +295,8 @@ error_unreg_trigger:
iio_trigger_unregister(trig);
error_free_trig:
iio_trigger_free(trig);
error_ret:
error_triggered_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
EXPORT_SYMBOL(hid_sensor_setup_trigger);

View File

@ -13,7 +13,8 @@ extern const struct dev_pm_ops hid_sensor_pm_ops;
int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
struct hid_sensor_common *attrb);
void hid_sensor_remove_trigger(struct hid_sensor_common *attrb);
void hid_sensor_remove_trigger(struct iio_dev *indio_dev,
struct hid_sensor_common *attrb);
int hid_sensor_power_state(struct hid_sensor_common *st, bool state);
#endif

View File

@ -20,11 +20,6 @@
#include "st_sensors_core.h"
static inline u32 st_sensors_get_unaligned_le24(const u8 *p)
{
return (s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8;
}
int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
u8 reg_addr, u8 mask, u8 data)
{
@ -150,8 +145,7 @@ static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
if (err < 0)
goto st_accel_set_fullscale_error;
sdata->current_fullscale = (struct st_sensor_fullscale_avl *)
&sdata->sensor_settings->fs.fs_avl[i];
sdata->current_fullscale = &sdata->sensor_settings->fs.fs_avl[i];
return err;
st_accel_set_fullscale_error:
@ -278,8 +272,7 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
!sdata->sensor_settings->drdy_irq.int2.addr) {
if (pdata->drdy_int_pin)
dev_info(&indio_dev->dev,
"DRDY on pin INT%d specified, but sensor "
"does not support interrupts\n",
"DRDY on pin INT%d specified, but sensor does not support interrupts\n",
pdata->drdy_int_pin);
return 0;
}
@ -545,7 +538,7 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
else if (byte_for_channel == 2)
*data = (s16)get_unaligned_le16(outdata);
else if (byte_for_channel == 3)
*data = (s32)st_sensors_get_unaligned_le24(outdata);
*data = (s32)sign_extend32(get_unaligned_le24(outdata), 23);
st_sensors_free_memory:
kfree(outdata);

View File

@ -49,8 +49,8 @@ int st_sensors_i2c_configure(struct iio_dev *indio_dev,
sdata->regmap = devm_regmap_init_i2c(client, config);
if (IS_ERR(sdata->regmap)) {
dev_err(&client->dev, "Failed to register i2c regmap (%d)\n",
(int)PTR_ERR(sdata->regmap));
dev_err(&client->dev, "Failed to register i2c regmap (%ld)\n",
PTR_ERR(sdata->regmap));
return PTR_ERR(sdata->regmap);
}

View File

@ -44,7 +44,7 @@ static bool st_sensors_is_spi_3_wire(struct spi_device *spi)
if (device_property_read_bool(dev, "spi-3wire"))
return true;
pdata = (struct st_sensors_platform_data *)dev->platform_data;
pdata = dev_get_platdata(dev);
if (pdata && pdata->spi_3wire)
return true;
@ -101,8 +101,8 @@ int st_sensors_spi_configure(struct iio_dev *indio_dev,
sdata->regmap = devm_regmap_init_spi(spi, config);
if (IS_ERR(sdata->regmap)) {
dev_err(&spi->dev, "Failed to register spi regmap (%d)\n",
(int)PTR_ERR(sdata->regmap));
dev_err(&spi->dev, "Failed to register spi regmap (%ld)\n",
PTR_ERR(sdata->regmap));
return PTR_ERR(sdata->regmap);
}

View File

@ -44,8 +44,7 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
sdata->sensor_settings->drdy_irq.stat_drdy.addr,
&status);
if (ret < 0) {
dev_err(sdata->dev,
"error checking samples available\n");
dev_err(sdata->dev, "error checking samples available\n");
return ret;
}
@ -148,9 +147,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
case IRQF_TRIGGER_LOW:
if (!sdata->sensor_settings->drdy_irq.addr_ihl) {
dev_err(&indio_dev->dev,
"falling/low specified for IRQ "
"but hardware supports only rising/high: "
"will request rising/high\n");
"falling/low specified for IRQ but hardware supports only rising/high: will request rising/high\n");
if (irq_trig == IRQF_TRIGGER_FALLING)
irq_trig = IRQF_TRIGGER_RISING;
if (irq_trig == IRQF_TRIGGER_LOW)
@ -163,8 +160,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
if (err < 0)
goto iio_trigger_free;
dev_info(&indio_dev->dev,
"interrupts on the falling edge or "
"active low level\n");
"interrupts on the falling edge or active low level\n");
}
break;
case IRQF_TRIGGER_RISING:
@ -178,8 +174,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
default:
/* This is the most preferred mode, if possible */
dev_err(&indio_dev->dev,
"unsupported IRQ trigger specified (%lx), enforce "
"rising edge\n", irq_trig);
"unsupported IRQ trigger specified (%lx), enforce rising edge\n", irq_trig);
irq_trig = IRQF_TRIGGER_RISING;
}

View File

@ -279,12 +279,12 @@ config LTC1660
module will be called ltc1660.
config LTC2632
tristate "Linear Technology LTC2632-12/10/8 and LTC2636-12/10/8 DAC spi driver"
tristate "Linear Technology LTC2632-12/10/8 and similar 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).
LTC2632, LTC2634 and LTC2636 DAC resolution 12/10/8 bit
low 0-2.5V and high 0-4.096V range converters.
To compile this driver as a module, choose M here: the
module will be called ltc2632.

View File

@ -67,6 +67,7 @@ struct ad5360_chip_info {
* @chip_info: chip model specific constants, available modes etc
* @vref_reg: vref supply regulators
* @ctrl: control register cache
* @lock lock to protect the data buffer during SPI ops
* @data: spi transfer buffers
*/
@ -75,6 +76,7 @@ struct ad5360_state {
const struct ad5360_chip_info *chip_info;
struct regulator_bulk_data vref_reg[3];
unsigned int ctrl;
struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the
@ -205,10 +207,11 @@ static int ad5360_write(struct iio_dev *indio_dev, unsigned int cmd,
unsigned int addr, unsigned int val, unsigned int shift)
{
int ret;
struct ad5360_state *st = iio_priv(indio_dev);
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
ret = ad5360_write_unlocked(indio_dev, cmd, addr, val, shift);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -229,7 +232,7 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type,
},
};
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->data[0].d32 = cpu_to_be32(AD5360_CMD(AD5360_CMD_SPECIAL_FUNCTION) |
AD5360_ADDR(AD5360_REG_SF_READBACK) |
@ -240,7 +243,7 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type,
if (ret >= 0)
ret = be32_to_cpu(st->data[1].d32) & 0xffff;
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -261,7 +264,7 @@ static int ad5360_update_ctrl(struct iio_dev *indio_dev, unsigned int set,
struct ad5360_state *st = iio_priv(indio_dev);
unsigned int ret;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->ctrl |= set;
st->ctrl &= ~clr;
@ -269,7 +272,7 @@ static int ad5360_update_ctrl(struct iio_dev *indio_dev, unsigned int set,
ret = ad5360_write_unlocked(indio_dev, AD5360_CMD_SPECIAL_FUNCTION,
AD5360_REG_SF_CTRL, st->ctrl, 0);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -479,6 +482,8 @@ static int ad5360_probe(struct spi_device *spi)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->num_channels = st->chip_info->num_channels;
mutex_init(&st->lock);
ret = ad5360_alloc_channels(indio_dev);
if (ret) {
dev_err(&spi->dev, "Failed to allocate channel spec: %d\n", ret);

View File

@ -51,6 +51,7 @@ struct ad5380_chip_info {
* @vref_reg: vref supply regulator
* @vref: actual reference voltage used in uA
* @pwr_down: whether the chip is currently in power down mode
* @lock lock to protect the data buffer during regmap ops
*/
struct ad5380_state {
@ -59,6 +60,7 @@ struct ad5380_state {
struct regulator *vref_reg;
int vref;
bool pwr_down;
struct mutex lock;
};
enum ad5380_type {
@ -98,7 +100,7 @@ static ssize_t ad5380_write_dac_powerdown(struct iio_dev *indio_dev,
if (ret)
return ret;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
if (pwr_down)
ret = regmap_write(st->regmap, AD5380_REG_SF_PWR_DOWN, 0);
@ -107,7 +109,7 @@ static ssize_t ad5380_write_dac_powerdown(struct iio_dev *indio_dev,
st->pwr_down = pwr_down;
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret ? ret : len;
}
@ -390,6 +392,8 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap,
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->num_channels = st->chip_info->num_channels;
mutex_init(&st->lock);
ret = ad5380_alloc_channels(indio_dev);
if (ret) {
dev_err(dev, "Failed to allocate channel spec: %d\n", ret);

View File

@ -62,12 +62,14 @@
* @current_range: current range which the device is configured for
* @data: spi transfer buffers
* @fault_mask: software masking of events
* @lock lock to protect the data buffer during SPI ops
*/
struct ad5421_state {
struct spi_device *spi;
unsigned int ctrl;
enum ad5421_current_range current_range;
unsigned int fault_mask;
struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the
@ -142,11 +144,12 @@ static int ad5421_write_unlocked(struct iio_dev *indio_dev,
static int ad5421_write(struct iio_dev *indio_dev, unsigned int reg,
unsigned int val)
{
struct ad5421_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
ret = ad5421_write_unlocked(indio_dev, reg, val);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -166,7 +169,7 @@ static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg)
},
};
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16));
@ -174,7 +177,7 @@ static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg)
if (ret >= 0)
ret = be32_to_cpu(st->data[1].d32) & 0xffff;
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -185,14 +188,14 @@ static int ad5421_update_ctrl(struct iio_dev *indio_dev, unsigned int set,
struct ad5421_state *st = iio_priv(indio_dev);
unsigned int ret;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->ctrl &= ~clr;
st->ctrl |= set;
ret = ad5421_write_unlocked(indio_dev, AD5421_REG_CTRL, st->ctrl);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -400,12 +403,12 @@ static int ad5421_write_event_config(struct iio_dev *indio_dev,
return -EINVAL;
}
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
if (state)
st->fault_mask |= mask;
else
st->fault_mask &= ~mask;
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return 0;
}
@ -491,6 +494,8 @@ static int ad5421_probe(struct spi_device *spi)
indio_dev->channels = ad5421_channels;
indio_dev->num_channels = ARRAY_SIZE(ad5421_channels);
mutex_init(&st->lock);
st->ctrl = AD5421_CTRL_WATCHDOG_DISABLE |
AD5421_CTRL_AUTO_FAULT_READBACK;

View File

@ -21,6 +21,8 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <asm/unaligned.h>
#define MODE_PWRDWN_1k 0x1
#define MODE_PWRDWN_100k 0x2
#define MODE_PWRDWN_TRISTATE 0x3
@ -31,6 +33,7 @@
* @chip_info: chip model specific constants, available modes etc
* @reg: supply regulator
* @vref_mv: actual reference voltage used
* @lock lock to protect the data buffer during write ops
*/
struct ad5446_state {
@ -41,6 +44,7 @@ struct ad5446_state {
unsigned cached_val;
unsigned pwr_down_mode;
unsigned pwr_down;
struct mutex lock;
};
/**
@ -110,7 +114,7 @@ static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev,
if (ret)
return ret;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->pwr_down = powerdown;
if (st->pwr_down) {
@ -121,7 +125,7 @@ static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev,
}
ret = st->chip_info->write(st, val);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret ? ret : len;
}
@ -195,11 +199,11 @@ static int ad5446_write_raw(struct iio_dev *indio_dev,
return -EINVAL;
val <<= chan->scan_type.shift;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->cached_val = val;
if (!st->pwr_down)
ret = st->chip_info->write(st, val);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
break;
default:
ret = -EINVAL;
@ -254,6 +258,8 @@ static int ad5446_probe(struct device *dev, const char *name,
indio_dev->channels = &st->chip_info->channel;
indio_dev->num_channels = 1;
mutex_init(&st->lock);
st->pwr_down_mode = MODE_PWRDWN_1k;
if (st->chip_info->int_vref_mv)
@ -302,9 +308,7 @@ static int ad5660_write(struct ad5446_state *st, unsigned val)
struct spi_device *spi = to_spi_device(st->dev);
uint8_t data[3];
data[0] = (val >> 16) & 0xFF;
data[1] = (val >> 8) & 0xFF;
data[2] = val & 0xFF;
put_unaligned_be24(val, &data[0]);
return spi_write(spi, data, sizeof(data));
}

View File

@ -56,11 +56,13 @@ struct ad5449_chip_info {
* @has_sdo: whether the SDO line is connected
* @dac_cache: Cache for the DAC values
* @data: spi transfer buffers
* @lock lock to protect the data buffer during SPI ops
*/
struct ad5449 {
struct spi_device *spi;
const struct ad5449_chip_info *chip_info;
struct regulator_bulk_data vref_reg[AD5449_MAX_VREFS];
struct mutex lock;
bool has_sdo;
uint16_t dac_cache[AD5449_MAX_CHANNELS];
@ -87,10 +89,10 @@ static int ad5449_write(struct iio_dev *indio_dev, unsigned int addr,
struct ad5449 *st = iio_priv(indio_dev);
int ret;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->data[0] = cpu_to_be16((addr << 12) | val);
ret = spi_write(st->spi, st->data, 2);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -112,7 +114,7 @@ static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr,
},
};
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->data[0] = cpu_to_be16(addr << 12);
st->data[1] = cpu_to_be16(AD5449_CMD_NOOP);
@ -123,7 +125,7 @@ static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr,
*val = be16_to_cpu(st->data[1]);
out_unlock:
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -302,6 +304,8 @@ static int ad5449_spi_probe(struct spi_device *spi)
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
mutex_init(&st->lock);
if (st->chip_info->has_ctrl) {
unsigned int ctrl = 0x00;
if (pdata) {

View File

@ -156,7 +156,6 @@ static void ad5592r_gpio_cleanup(struct ad5592r_state *st)
static int ad5592r_reset(struct ad5592r_state *st)
{
struct gpio_desc *gpio;
struct iio_dev *iio_dev = iio_priv_to_dev(st);
gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(gpio))
@ -166,10 +165,10 @@ static int ad5592r_reset(struct ad5592r_state *st)
udelay(1);
gpiod_set_value(gpio, 1);
} else {
mutex_lock(&iio_dev->mlock);
mutex_lock(&st->lock);
/* Writing this magic value resets the device */
st->ops->reg_write(st, AD5592R_REG_RESET, 0xdac);
mutex_unlock(&iio_dev->mlock);
mutex_unlock(&st->lock);
}
udelay(250);
@ -197,7 +196,6 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
const struct ad5592r_rw_ops *ops = st->ops;
int ret;
unsigned i;
struct iio_dev *iio_dev = iio_priv_to_dev(st);
u8 pulldown = 0, tristate = 0, dac = 0, adc = 0;
u16 read_back;
@ -247,7 +245,7 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
}
}
mutex_lock(&iio_dev->mlock);
mutex_lock(&st->lock);
/* Pull down unused pins to GND */
ret = ops->reg_write(st, AD5592R_REG_PULLDOWN, pulldown);
@ -285,7 +283,7 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
ret = -EIO;
err_unlock:
mutex_unlock(&iio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -314,11 +312,11 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev,
if (!chan->output)
return -EINVAL;
mutex_lock(&iio_dev->mlock);
mutex_lock(&st->lock);
ret = st->ops->write_dac(st, chan->channel, val);
if (!ret)
st->cached_dac[chan->channel] = val;
mutex_unlock(&iio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
case IIO_CHAN_INFO_SCALE:
if (chan->type == IIO_VOLTAGE) {
@ -333,12 +331,12 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev,
else
return -EINVAL;
mutex_lock(&iio_dev->mlock);
mutex_lock(&st->lock);
ret = st->ops->reg_read(st, AD5592R_REG_CTRL,
&st->cached_gp_ctrl);
if (ret < 0) {
mutex_unlock(&iio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -360,7 +358,7 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev,
ret = st->ops->reg_write(st, AD5592R_REG_CTRL,
st->cached_gp_ctrl);
mutex_unlock(&iio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -382,7 +380,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
switch (m) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&iio_dev->mlock);
mutex_lock(&st->lock);
if (!chan->output) {
ret = st->ops->read_adc(st, chan->channel, &read_val);
@ -419,7 +417,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
} else {
int mult;
mutex_lock(&iio_dev->mlock);
mutex_lock(&st->lock);
if (chan->output)
mult = !!(st->cached_gp_ctrl &
@ -437,7 +435,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
case IIO_CHAN_INFO_OFFSET:
ret = ad5592r_get_vref(st);
mutex_lock(&iio_dev->mlock);
mutex_lock(&st->lock);
if (st->cached_gp_ctrl & AD5592R_REG_CTRL_ADC_RANGE)
*val = (-34365 * 25) / ret;
@ -450,7 +448,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
}
unlock:
mutex_unlock(&iio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -625,6 +623,8 @@ int ad5592r_probe(struct device *dev, const char *name,
iio_dev->info = &ad5592r_info;
iio_dev->modes = INDIO_DIRECT_MODE;
mutex_init(&st->lock);
ad5592r_init_scales(st, ad5592r_get_vref(st));
ret = ad5592r_reset(st);

View File

@ -52,6 +52,7 @@ struct ad5592r_state {
struct regulator *reg;
struct gpio_chip gpiochip;
struct mutex gpio_lock; /* Protect cached gpio_out, gpio_val, etc. */
struct mutex lock;
unsigned int num_channels;
const struct ad5592r_rw_ops *ops;
int scale_avail[2][2];

View File

@ -98,7 +98,7 @@ static int ad5592r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value)
return 0;
}
static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value)
static int ad5592r_gpio_read(struct ad5592r_state *st, u8 *value)
{
int ret;
@ -121,7 +121,7 @@ static const struct ad5592r_rw_ops ad5592r_rw_ops = {
.read_adc = ad5592r_read_adc,
.reg_write = ad5592r_reg_write,
.reg_read = ad5592r_reg_read,
.gpio_read = ad5593r_gpio_read,
.gpio_read = ad5592r_gpio_read,
};
static int ad5592r_spi_probe(struct spi_device *spi)

View File

@ -134,5 +134,5 @@ static struct i2c_driver ad5593r_driver = {
module_i2c_driver(ad5593r_driver);
MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters");
MODULE_DESCRIPTION("Analog Devices AD5593R multi-channel converters");
MODULE_LICENSE("GPL v2");

View File

@ -18,6 +18,8 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <asm/unaligned.h>
#include "ad5624r.h"
static int ad5624r_spi_write(struct spi_device *spi,
@ -35,11 +37,9 @@ static int ad5624r_spi_write(struct spi_device *spi,
* for the AD5664R, AD5644R, and AD5624R, respectively.
*/
data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << shift);
msg[0] = data >> 16;
msg[1] = data >> 8;
msg[2] = data;
put_unaligned_be24(data, &msg[0]);
return spi_write(spi, msg, 3);
return spi_write(spi, msg, sizeof(msg));
}
static int ad5624r_read_raw(struct iio_dev *indio_dev,

View File

@ -127,9 +127,9 @@ static int ad5686_read_raw(struct iio_dev *indio_dev,
switch (m) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
ret = st->read(st, chan->address);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
if (ret < 0)
return ret;
*val = (ret >> chan->scan_type.shift) &
@ -157,12 +157,12 @@ static int ad5686_write_raw(struct iio_dev *indio_dev,
if (val > (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
ret = st->write(st,
AD5686_CMD_WRITE_INPUT_N_UPDATE_N,
chan->address,
val << chan->scan_type.shift);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
break;
default:
ret = -EINVAL;
@ -468,6 +468,8 @@ int ad5686_probe(struct device *dev,
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
mutex_init(&st->lock);
switch (st->chip_info->regmap_type) {
case AD5310_REGMAP:
cmd = AD5686_CMD_CONTROL_REG;

View File

@ -117,6 +117,7 @@ struct ad5686_chip_info {
* @pwr_down_mask: power down mask
* @pwr_down_mode: current power down mode
* @use_internal_vref: set to true if the internal reference voltage is used
* @lock lock to protect the data buffer during regmap ops
* @data: spi transfer buffers
*/
@ -130,6 +131,7 @@ struct ad5686_state {
ad5686_write_func write;
ad5686_read_func read;
bool use_internal_vref;
struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the

View File

@ -82,6 +82,7 @@ struct ad5755_chip_info {
* @pwr_down: bitmask which contains hether a channel is powered down or not
* @ctrl: software shadow of the channel ctrl registers
* @channels: iio channel spec for the device
* @lock lock to protect the data buffer during SPI ops
* @data: spi transfer buffers
*/
struct ad5755_state {
@ -90,6 +91,7 @@ struct ad5755_state {
unsigned int pwr_down;
unsigned int ctrl[AD5755_NUM_CHANNELS];
struct iio_chan_spec channels[AD5755_NUM_CHANNELS];
struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the
@ -174,11 +176,12 @@ static int ad5755_write_ctrl_unlocked(struct iio_dev *indio_dev,
static int ad5755_write(struct iio_dev *indio_dev, unsigned int reg,
unsigned int val)
{
struct ad5755_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
ret = ad5755_write_unlocked(indio_dev, reg, val);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -186,11 +189,12 @@ static int ad5755_write(struct iio_dev *indio_dev, unsigned int reg,
static int ad5755_write_ctrl(struct iio_dev *indio_dev, unsigned int channel,
unsigned int reg, unsigned int val)
{
struct ad5755_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
ret = ad5755_write_ctrl_unlocked(indio_dev, channel, reg, val);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -211,7 +215,7 @@ static int ad5755_read(struct iio_dev *indio_dev, unsigned int addr)
},
};
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->data[0].d32 = cpu_to_be32(AD5755_READ_FLAG | (addr << 16));
st->data[1].d32 = cpu_to_be32(AD5755_NOOP);
@ -220,7 +224,7 @@ static int ad5755_read(struct iio_dev *indio_dev, unsigned int addr)
if (ret >= 0)
ret = be32_to_cpu(st->data[1].d32) & 0xffff;
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -246,7 +250,7 @@ static int ad5755_set_channel_pwr_down(struct iio_dev *indio_dev,
struct ad5755_state *st = iio_priv(indio_dev);
unsigned int mask = BIT(channel);
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
if ((bool)(st->pwr_down & mask) == pwr_down)
goto out_unlock;
@ -266,7 +270,7 @@ static int ad5755_set_channel_pwr_down(struct iio_dev *indio_dev,
}
out_unlock:
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return 0;
}
@ -746,6 +750,8 @@ static int ad5755_probe(struct spi_device *spi)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->num_channels = AD5755_NUM_CHANNELS;
mutex_init(&st->lock);
if (spi->dev.of_node)
pdata = ad5755_parse_dt(&spi->dev);
else

View File

@ -57,11 +57,13 @@ enum ad5761_supported_device_ids {
* @use_intref: true when the internal voltage reference is used
* @vref: actual voltage reference in mVolts
* @range: output range mode used
* @lock lock to protect the data buffer during SPI ops
* @data: cache aligned spi buffer
*/
struct ad5761_state {
struct spi_device *spi;
struct regulator *vref_reg;
struct mutex lock;
bool use_intref;
int vref;
@ -124,9 +126,9 @@ static int ad5761_spi_write(struct iio_dev *indio_dev, u8 addr, u16 val)
struct ad5761_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
ret = _ad5761_spi_write(st, addr, val);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -163,9 +165,9 @@ static int ad5761_spi_read(struct iio_dev *indio_dev, u8 addr, u16 *val)
struct ad5761_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
ret = _ad5761_spi_read(st, addr, val);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -368,6 +370,8 @@ static int ad5761_probe(struct spi_device *spi)
if (pdata)
voltage_range = pdata->voltage_range;
mutex_init(&st->lock);
ret = ad5761_spi_set_range(st, voltage_range);
if (ret)
goto disable_regulator_err;

View File

@ -46,6 +46,7 @@ struct ad5764_chip_info {
* @spi: spi_device
* @chip_info: chip info
* @vref_reg: vref supply regulators
* @lock lock to protect the data buffer during SPI ops
* @data: spi transfer buffers
*/
@ -53,6 +54,7 @@ struct ad5764_state {
struct spi_device *spi;
const struct ad5764_chip_info *chip_info;
struct regulator_bulk_data vref_reg[2];
struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the
@ -126,11 +128,11 @@ static int ad5764_write(struct iio_dev *indio_dev, unsigned int reg,
struct ad5764_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->data[0].d32 = cpu_to_be32((reg << 16) | val);
ret = spi_write(st->spi, &st->data[0].d8[1], 3);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -151,7 +153,7 @@ static int ad5764_read(struct iio_dev *indio_dev, unsigned int reg,
},
};
mutex_lock(&indio_dev->mlock);
mutex_lock(&st->lock);
st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16));
@ -159,7 +161,7 @@ static int ad5764_read(struct iio_dev *indio_dev, unsigned int reg,
if (ret >= 0)
*val = be32_to_cpu(st->data[1].d32) & 0xffff;
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&st->lock);
return ret;
}
@ -295,6 +297,8 @@ static int ad5764_probe(struct spi_device *spi)
indio_dev->num_channels = AD5764_NUM_CHANNELS;
indio_dev->channels = st->chip_info->channels;
mutex_init(&st->lock);
if (st->chip_info->int_vref == 0) {
st->vref_reg[0].supply = "vrefAB";
st->vref_reg[1].supply = "vrefCD";

View File

@ -12,6 +12,8 @@
#include <linux/iio/iio.h>
#include <linux/regulator/consumer.h>
#include <asm/unaligned.h>
#define LTC2632_CMD_WRITE_INPUT_N 0x0
#define LTC2632_CMD_UPDATE_DAC_N 0x1
#define LTC2632_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2
@ -24,6 +26,7 @@
/**
* struct ltc2632_chip_info - chip specific information
* @channels: channel spec for the DAC
* @num_channels: DAC channel count of the chip
* @vref_mv: internal reference voltage
*/
struct ltc2632_chip_info {
@ -53,6 +56,12 @@ enum ltc2632_supported_device_ids {
ID_LTC2632H12,
ID_LTC2632H10,
ID_LTC2632H8,
ID_LTC2634L12,
ID_LTC2634L10,
ID_LTC2634L8,
ID_LTC2634H12,
ID_LTC2634H10,
ID_LTC2634H8,
ID_LTC2636L12,
ID_LTC2636L10,
ID_LTC2636L8,
@ -75,9 +84,7 @@ static int ltc2632_spi_write(struct spi_device *spi,
* 10-, 8-bit input code followed by 4, 6, or 8 don't care bits.
*/
data = (cmd << 20) | (addr << 16) | (val << shift);
msg[0] = data >> 16;
msg[1] = data >> 8;
msg[2] = data;
put_unaligned_be24(data, &msg[0]);
return spi_write(spi, msg, sizeof(msg));
}
@ -235,6 +242,36 @@ static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = {
.num_channels = 2,
.vref_mv = 4096,
},
[ID_LTC2634L12] = {
.channels = ltc2632x12_channels,
.num_channels = 4,
.vref_mv = 2500,
},
[ID_LTC2634L10] = {
.channels = ltc2632x10_channels,
.num_channels = 4,
.vref_mv = 2500,
},
[ID_LTC2634L8] = {
.channels = ltc2632x8_channels,
.num_channels = 4,
.vref_mv = 2500,
},
[ID_LTC2634H12] = {
.channels = ltc2632x12_channels,
.num_channels = 4,
.vref_mv = 4096,
},
[ID_LTC2634H10] = {
.channels = ltc2632x10_channels,
.num_channels = 4,
.vref_mv = 4096,
},
[ID_LTC2634H8] = {
.channels = ltc2632x8_channels,
.num_channels = 4,
.vref_mv = 4096,
},
[ID_LTC2636L12] = {
.channels = ltc2632x12_channels,
.num_channels = 8,
@ -356,6 +393,12 @@ static const struct spi_device_id ltc2632_id[] = {
{ "ltc2632-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H12] },
{ "ltc2632-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H10] },
{ "ltc2632-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H8] },
{ "ltc2634-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L12] },
{ "ltc2634-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L10] },
{ "ltc2634-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L8] },
{ "ltc2634-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H12] },
{ "ltc2634-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H10] },
{ "ltc2634-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H8] },
{ "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] },
@ -385,6 +428,24 @@ static const struct of_device_id ltc2632_of_match[] = {
}, {
.compatible = "lltc,ltc2632-h8",
.data = &ltc2632_chip_info_tbl[ID_LTC2632H8]
}, {
.compatible = "lltc,ltc2634-l12",
.data = &ltc2632_chip_info_tbl[ID_LTC2634L12]
}, {
.compatible = "lltc,ltc2634-l10",
.data = &ltc2632_chip_info_tbl[ID_LTC2634L10]
}, {
.compatible = "lltc,ltc2634-l8",
.data = &ltc2632_chip_info_tbl[ID_LTC2634L8]
}, {
.compatible = "lltc,ltc2634-h12",
.data = &ltc2632_chip_info_tbl[ID_LTC2634H12]
}, {
.compatible = "lltc,ltc2634-h10",
.data = &ltc2632_chip_info_tbl[ID_LTC2634H10]
}, {
.compatible = "lltc,ltc2634-h8",
.data = &ltc2632_chip_info_tbl[ID_LTC2634H8]
}, {
.compatible = "lltc,ltc2636-l12",
.data = &ltc2632_chip_info_tbl[ID_LTC2636L12]

View File

@ -36,6 +36,7 @@ struct vf610_dac {
struct device *dev;
enum vf610_conversion_mode_sel conv_mode;
void __iomem *regs;
struct mutex lock;
};
static void vf610_dac_init(struct vf610_dac *info)
@ -64,7 +65,7 @@ static int vf610_set_conversion_mode(struct iio_dev *indio_dev,
struct vf610_dac *info = iio_priv(indio_dev);
int val;
mutex_lock(&indio_dev->mlock);
mutex_lock(&info->lock);
info->conv_mode = mode;
val = readl(info->regs + VF610_DACx_STATCTRL);
if (mode)
@ -72,7 +73,7 @@ static int vf610_set_conversion_mode(struct iio_dev *indio_dev,
else
val &= ~VF610_DAC_LPEN;
writel(val, info->regs + VF610_DACx_STATCTRL);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&info->lock);
return 0;
}
@ -147,9 +148,9 @@ static int vf610_write_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
mutex_lock(&info->lock);
writel(VF610_DAC_DAT0(val), info->regs);
mutex_unlock(&indio_dev->mlock);
mutex_unlock(&info->lock);
return 0;
default:
@ -205,6 +206,8 @@ static int vf610_dac_probe(struct platform_device *pdev)
indio_dev->channels = vf610_dac_iio_channels;
indio_dev->num_channels = ARRAY_SIZE(vf610_dac_iio_channels);
mutex_init(&info->lock);
ret = clk_prepare_enable(info->clk);
if (ret) {
dev_err(&pdev->dev,

View File

@ -61,7 +61,7 @@ config BMG160
help
Say yes here to build support for BOSCH BMG160 Tri-axis Gyro Sensor
driver connected via I2C or SPI. This driver also supports BMI055
gyroscope.
and BMI088 gyroscope.
This driver can also be built as a module. If so, the module
will be called bmg160_i2c or bmg160_spi.

View File

@ -12,6 +12,8 @@
#include <linux/iio/iio.h>
#include <asm/unaligned.h>
#define ADIS16130_CON 0x0
#define ADIS16130_CON_RD (1 << 6)
#define ADIS16130_IOP 0x1
@ -59,7 +61,7 @@ static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val)
ret = spi_sync_transfer(st->us, &xfer, 1);
if (ret == 0)
*val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3];
*val = get_unaligned_be24(&st->buf[1]);
mutex_unlock(&st->buf_lock);
return ret;

View File

@ -148,16 +148,14 @@ DEFINE_DEBUGFS_ATTRIBUTE(adis16136_flash_count_fops,
static int adis16136_debugfs_init(struct iio_dev *indio_dev)
{
struct adis16136 *adis16136 = iio_priv(indio_dev);
struct dentry *d = iio_get_debugfs_dentry(indio_dev);
debugfs_create_file_unsafe("serial_number", 0400,
indio_dev->debugfs_dentry, adis16136,
&adis16136_serial_fops);
d, adis16136, &adis16136_serial_fops);
debugfs_create_file_unsafe("product_id", 0400,
indio_dev->debugfs_dentry,
adis16136, &adis16136_product_id_fops);
d, adis16136, &adis16136_product_id_fops);
debugfs_create_file_unsafe("flash_count", 0400,
indio_dev->debugfs_dentry,
adis16136, &adis16136_flash_count_fops);
d, adis16136, &adis16136_flash_count_fops);
return 0;
}

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