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:
commit
80ef846e99
|
@ -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.
|
|
@ -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.
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
...
|
|
@ -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>;
|
||||
};
|
||||
...
|
|
@ -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>;
|
||||
};
|
||||
};
|
|
@ -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>;
|
||||
};
|
|
@ -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>;
|
||||
};
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -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
|
||||
|
|
|
@ -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).
|
||||
|
||||
...
|
|
@ -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
|
||||
|
|
|
@ -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 = <®_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>;
|
||||
};
|
||||
};
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -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:
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
...
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
...
|
|
@ -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>;
|
||||
};
|
|
@ -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>;
|
||||
};
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
...
|
|
@ -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:
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
};
|
|
@ -50,6 +50,7 @@ Accelerometers:
|
|||
- st,lis3dhh
|
||||
- st,lis3de
|
||||
- st,lis2de12
|
||||
- st,lis2hh12
|
||||
|
||||
Gyroscopes:
|
||||
- st,l3g4200d-gyro
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
10
MAINTAINERS
10
MAINTAINERS
|
@ -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/
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 *) ®, sizeof(reg));
|
||||
ret = regmap_bulk_read(data->regmap, addr, ®, sizeof(reg));
|
||||
if (ret < 0) {
|
||||
dev_err(data->dev, "failed to read reg %02x\n", addr);
|
||||
return ret;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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] = {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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), \
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
|
@ -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);
|
||||
|
|
|
@ -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(®istered_clients_lock);
|
||||
|
||||
cl->dev = get_device(dev);
|
||||
|
||||
list_add_tail(&cl->entry, ®istered_clients);
|
||||
|
||||
mutex_unlock(®istered_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(®istered_clients_lock);
|
||||
|
||||
list_del(&cl->entry);
|
||||
put_device(cl->dev);
|
||||
|
||||
mutex_unlock(®istered_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(®istered_clients_lock);
|
||||
|
||||
list_for_each_entry(cl, ®istered_clients, entry) {
|
||||
if (!cl->dev)
|
||||
continue;
|
||||
|
||||
if (cl->dev->of_node != cln)
|
||||
continue;
|
||||
|
||||
if (!try_module_get(dev->driver->owner)) {
|
||||
mutex_unlock(®istered_clients_lock);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
get_device(dev);
|
||||
cl->info = info;
|
||||
mutex_unlock(®istered_clients_lock);
|
||||
return cl;
|
||||
}
|
||||
|
||||
mutex_unlock(®istered_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");
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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, \
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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");
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
|
@ -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 *) ®, sizeof(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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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)<c2632_chip_info_tbl[ID_LTC2632H12] },
|
||||
{ "ltc2632-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H10] },
|
||||
{ "ltc2632-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H8] },
|
||||
{ "ltc2634-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L12] },
|
||||
{ "ltc2634-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L10] },
|
||||
{ "ltc2634-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L8] },
|
||||
{ "ltc2634-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H12] },
|
||||
{ "ltc2634-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H10] },
|
||||
{ "ltc2634-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H8] },
|
||||
{ "ltc2636-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L12] },
|
||||
{ "ltc2636-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L10] },
|
||||
{ "ltc2636-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L8] },
|
||||
|
@ -385,6 +428,24 @@ static const struct of_device_id ltc2632_of_match[] = {
|
|||
}, {
|
||||
.compatible = "lltc,ltc2632-h8",
|
||||
.data = <c2632_chip_info_tbl[ID_LTC2632H8]
|
||||
}, {
|
||||
.compatible = "lltc,ltc2634-l12",
|
||||
.data = <c2632_chip_info_tbl[ID_LTC2634L12]
|
||||
}, {
|
||||
.compatible = "lltc,ltc2634-l10",
|
||||
.data = <c2632_chip_info_tbl[ID_LTC2634L10]
|
||||
}, {
|
||||
.compatible = "lltc,ltc2634-l8",
|
||||
.data = <c2632_chip_info_tbl[ID_LTC2634L8]
|
||||
}, {
|
||||
.compatible = "lltc,ltc2634-h12",
|
||||
.data = <c2632_chip_info_tbl[ID_LTC2634H12]
|
||||
}, {
|
||||
.compatible = "lltc,ltc2634-h10",
|
||||
.data = <c2632_chip_info_tbl[ID_LTC2634H10]
|
||||
}, {
|
||||
.compatible = "lltc,ltc2634-h8",
|
||||
.data = <c2632_chip_info_tbl[ID_LTC2634H8]
|
||||
}, {
|
||||
.compatible = "lltc,ltc2636-l12",
|
||||
.data = <c2632_chip_info_tbl[ID_LTC2636L12]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue