1st set of IIO new device support, features and cleanup for 5.17

Includes some fixes that were either late breaking, low priority or
 complex enough to not be good to rush in late in the cycle.
 
 Tree rebased today to fix up some trivial issues + pull in a fix that
 was previously on the fixes-togreg branch. Vast majority have been
 in linux-next for some time now.
 
 New device support
 * adi,ad7293
   - New driver and bindings for this Power Amplifier drain current
     controller.  A complex device with various related monitoring functions.
 * adi,ad75513R
   - New driver and bindings for this combined ADC and DAC device.
   - A few follow up fixes.
 * adi,admv8818
   - New driver (and type) for this 2-18GHz filter device. Includes
     bindings and ABI documentation to allow clk_notifier based auto
     adjustment of the filters in appropriate applications.
 * liteon,ltr501
   - Support for the ltr303.  ID and chip specific info table.
 * xilinx,ams
   - New generic firmware function fwnode_iomap() as used in this driver.
   - New driver and bindings for this ADC and on-chip sensors as found
     in various Xilinx devices.
 
 Core
 * Introduced IIO_VAL_INT_64 which uses val and val2 in IIO callbacks to
   form a 64 bit integer when higher precision needed.
 * Allow IIO_ENUM_AVAILABLE to be used with different shared values.
 * Fix a long term issue with scheduling whilst atomic when iio_trig_poll()
   is called but no trigger consumers are actually enabled and hence the
   trigger may be reenabled from the interrupt handler.  Seen in the wild
   on the tsc2046.
 * Mark iio_device_type const.
 * buffer: Use a separate index variable to simplify code.
 * buffer-dma: Clear out unused struct iio_buffer_block
 * buffer-dmaengine: Switch to cheaper round_down() as power of 2 values.
 
 Tests/tools
 * format_value
   - Check against NULL returns from allocations in tests.
   - Add IIO_VAL_INT_64 test case.
 * event_monitor
   - Flush the output after event to given more consistent latency
     when tool output piped to other programs.
 
 Driver Features
 * axp20x
   - Add support for NTC thermistor channel and document TS pin binding.
 * arm,scmi
   - Add reading of raw channel values (using IIO_VAL_INT_64)
 * liteon,ltr501
   - Add proximity-near-level support and dt-binding.
 
 Tree wide cleanup
 * Remove no-op trigger ops from multiple drivers.
 * Stop using dev_get_drvdata() on the iio_dev->dev in various drivers
   and then stop assigning it to allow this to be used for other purposes.
   We can always get to the indio_dev using dev_to_iio_dev() which is
   a container_of() based approach. Also cleanup up some related unnecessary
   convoluted cases.
   - atmel,at91-sam5d2
   - nxp,imx7d
   - meas,ms5611
   - st,st_sensors
 * Where available (or easy to introduce) use the scan_type.* values
   in place of a second copy for read_raw and similar paths.
   - adi,ad7266
   - bosch,bma220
   - fsl,mac3110
   - fsl,mma7455
   - fsl,mpl3115
   - kionix,kcjk-1013
   - sensortek,stk8ba50
   - sensortek,stk8312
   - ti,adc12138
   - ti,ads1015
   - vti,sca3000
   - xilinx,xadc-core
 * Switch drives over to generic firmware properties including appropriate
   header changes to avoid including of.h
   - Various DACs had false CONFIG_OF dependencies.
   - dpot-dac
   - envelope-detector
   - adi,ad5755
   - adi,ad5758
   - capella,cm3605
   - maxim,max9611
   - microchip,mcp41010
   - microchip,mcp3911
   - ti,adc12138
 * Trivial clang warning fixes for W=1 warnings.
 
 Driver specific cleanup and minor fixes
 * adi,ad7606
   - Comment fixes.
 * ams,ad3935
   - Drop pointless cast to the same type.
 * atmel,at91-sama5d2
   - Fix wrong cast of iio_dev->dev to platform_device that happened to
     be harmless.
 * fsl,mma7660
   - Stop i2c remove() function returning an error code. Part of a rework
     to eventually stop returning anything from these.
 * fsl,mma8452
   - Use correct type for local irqreturn_t.
 * nxp,imx8mq
   - Maintainer email address update.
 * nxp,lpc18xx_adc
   - Ensure clk_prepare_enable() called before clk_get_rate().
   - Switch of.h for mod_devicetable.h to reflect no of specific functions,
     just the id table.
 * renesas,rzg2l
   - Drop a dev_err() that just duplicates error printed in platform_get_irq()
 * sgx,vz89x
   - Drop pointless cast.
 * st,lsm6dsx
   - Make it possible to disable the sensorhub from DT to avoid a corner
     case where the address of a slave device many be accidentally modified.
 * st,stm32-adc
   - Stop leaking an of_node in an error path.
 * st,stmp2
    - Avoid wrong sized type for bit field which could result in
      over-reading (harmless). Precursor to enabling -Warray-bounds.
 * ti,adc081c
   - Put back some ACPI support for non standards compliant ADC081C
     ID because it is known to be in the wild on some Aaeon boards.
 * ti,ads8688
   - Cleanup redundant local ret variable assignment.
 * ti,ina2xx-adc
   - Use helper macro kthread_run() to replace some boilerplate.
   - Avoid double reference counting.
   - Drop pointless cast.
 * xilinx,xadc
   - Make the IRQ optional as not always wired to the host system.
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAmHB8WsRHGppYzIzQGtl
 cm5lbC5vcmcACgkQVIU0mcT0FoiiUg/8Dsg+oaZ126Wo+xW1FGk8LQ2GjCpIMHnt
 pLW+O1ezBipqCL3pemQeV5b8GcAo5Tia/yplzZxxhbP3GMY9gMkMWqnCdY/81E69
 w1SQF84OvMFdN+jHGAqu0mnyBkHEdT/nLyNMExBXSXMzXWzITY3bWbygMsKeN5Rs
 /GWyiAgqA8PPi6DoMa9tiGiPGxejic7jEVHMLjXk4ytRLndNtD1IxUElD9yTFxhk
 Hteba0hq+Et56nw/yOjz3mP4oSZSd//qPWQJ/qbMcHCvnr6LJ24sqhXiEQXyZ2vA
 hjkoYRXQnzKdPcrYFcre4VY1nJdQ3v0GKCDEFPUHzRJh8iKJleQCH6dIGNNkiRld
 KvBah2SetS43zQ11c4JywAUxENiWrUGIrF6u9xPCLq8Pe9b454r+Fb5BCwR7Ra+7
 bit11aIazCQV98bFwQvwMzPL9L/SZI6cmsbizdjT2VMRBTPIWl4NhQRVoYQjb8v0
 yZ6/S1560ibTxurTStkcGjjBC+mUzvVNuKir2mHaBdzCVAX82+babJcOhxzlI8jh
 9adyfHsBL8HwOWBjxHgybjw87DDtuByiVuVy7h2jAVgQevPknVC1toj4Q2bNCbUj
 tB2Ln6hBIaU29B1dj6GDwGvrCmi9XQzHOd0MSf524E/GlOKy4JEDQZU9bHFW5MKS
 VcQSGTXSG7s=
 =xXvq
 -----END PGP SIGNATURE-----

Merge tag 'iio-for-5.17a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into char-misc-next

Jonathan writes:

1st set of IIO new device support, features and cleanup for 5.17

Includes some fixes that were either late breaking, low priority or
complex enough to not be good to rush in late in the cycle.

Tree rebased today to fix up some trivial issues + pull in a fix that
was previously on the fixes-togreg branch. Vast majority have been
in linux-next for some time now.

New device support
* adi,ad7293
  - New driver and bindings for this Power Amplifier drain current
    controller.  A complex device with various related monitoring functions.
* adi,ad75513R
  - New driver and bindings for this combined ADC and DAC device.
  - A few follow up fixes.
* adi,admv8818
  - New driver (and type) for this 2-18GHz filter device. Includes
    bindings and ABI documentation to allow clk_notifier based auto
    adjustment of the filters in appropriate applications.
* liteon,ltr501
  - Support for the ltr303.  ID and chip specific info table.
* xilinx,ams
  - New generic firmware function fwnode_iomap() as used in this driver.
  - New driver and bindings for this ADC and on-chip sensors as found
    in various Xilinx devices.

Core
* Introduced IIO_VAL_INT_64 which uses val and val2 in IIO callbacks to
  form a 64 bit integer when higher precision needed.
* Allow IIO_ENUM_AVAILABLE to be used with different shared values.
* Fix a long term issue with scheduling whilst atomic when iio_trig_poll()
  is called but no trigger consumers are actually enabled and hence the
  trigger may be reenabled from the interrupt handler.  Seen in the wild
  on the tsc2046.
* Mark iio_device_type const.
* buffer: Use a separate index variable to simplify code.
* buffer-dma: Clear out unused struct iio_buffer_block
* buffer-dmaengine: Switch to cheaper round_down() as power of 2 values.

Tests/tools
* format_value
  - Check against NULL returns from allocations in tests.
  - Add IIO_VAL_INT_64 test case.
* event_monitor
  - Flush the output after event to given more consistent latency
    when tool output piped to other programs.

Driver Features
* axp20x
  - Add support for NTC thermistor channel and document TS pin binding.
* arm,scmi
  - Add reading of raw channel values (using IIO_VAL_INT_64)
* liteon,ltr501
  - Add proximity-near-level support and dt-binding.

Tree wide cleanup
* Remove no-op trigger ops from multiple drivers.
* Stop using dev_get_drvdata() on the iio_dev->dev in various drivers
  and then stop assigning it to allow this to be used for other purposes.
  We can always get to the indio_dev using dev_to_iio_dev() which is
  a container_of() based approach. Also cleanup up some related unnecessary
  convoluted cases.
  - atmel,at91-sam5d2
  - nxp,imx7d
  - meas,ms5611
  - st,st_sensors
* Where available (or easy to introduce) use the scan_type.* values
  in place of a second copy for read_raw and similar paths.
  - adi,ad7266
  - bosch,bma220
  - fsl,mac3110
  - fsl,mma7455
  - fsl,mpl3115
  - kionix,kcjk-1013
  - sensortek,stk8ba50
  - sensortek,stk8312
  - ti,adc12138
  - ti,ads1015
  - vti,sca3000
  - xilinx,xadc-core
* Switch drives over to generic firmware properties including appropriate
  header changes to avoid including of.h
  - Various DACs had false CONFIG_OF dependencies.
  - dpot-dac
  - envelope-detector
  - adi,ad5755
  - adi,ad5758
  - capella,cm3605
  - maxim,max9611
  - microchip,mcp41010
  - microchip,mcp3911
  - ti,adc12138
* Trivial clang warning fixes for W=1 warnings.

Driver specific cleanup and minor fixes
* adi,ad7606
  - Comment fixes.
* ams,ad3935
  - Drop pointless cast to the same type.
* atmel,at91-sama5d2
  - Fix wrong cast of iio_dev->dev to platform_device that happened to
    be harmless.
* fsl,mma7660
  - Stop i2c remove() function returning an error code. Part of a rework
    to eventually stop returning anything from these.
* fsl,mma8452
  - Use correct type for local irqreturn_t.
* nxp,imx8mq
  - Maintainer email address update.
* nxp,lpc18xx_adc
  - Ensure clk_prepare_enable() called before clk_get_rate().
  - Switch of.h for mod_devicetable.h to reflect no of specific functions,
    just the id table.
* renesas,rzg2l
  - Drop a dev_err() that just duplicates error printed in platform_get_irq()
* sgx,vz89x
  - Drop pointless cast.
* st,lsm6dsx
  - Make it possible to disable the sensorhub from DT to avoid a corner
    case where the address of a slave device many be accidentally modified.
* st,stm32-adc
  - Stop leaking an of_node in an error path.
* st,stmp2
   - Avoid wrong sized type for bit field which could result in
     over-reading (harmless). Precursor to enabling -Warray-bounds.
* ti,adc081c
  - Put back some ACPI support for non standards compliant ADC081C
    ID because it is known to be in the wild on some Aaeon boards.
* ti,ads8688
  - Cleanup redundant local ret variable assignment.
* ti,ina2xx-adc
  - Use helper macro kthread_run() to replace some boilerplate.
  - Avoid double reference counting.
  - Drop pointless cast.
* xilinx,xadc
  - Make the IRQ optional as not always wired to the host system.

* tag 'iio-for-5.17a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (103 commits)
  iio: adc: ti-adc081c: Partial revert of removal of ACPI IDs
  iio:addac:ad74413r: Fix uninitialized ret in a path that won't be hit.
  MAINTAINERS: Add maintainer for xilinx-ams
  dt-bindings: iio: adc: Add Xilinx AMS binding documentation
  iio: adc: Add Xilinx AMS driver
  device property: Add fwnode_iomap()
  iio:accel:kxcjk-1013: Mark struct __maybe_unused to avoid warning.
  iio:accel:bmc150: Mark structure __maybe_unused as only needed with for pm ops.
  iio:dummy: Drop set but unused variable len.
  iio:magn:ak8975: Suppress clang W=1 warning about pointer to enum conversion.
  iio:imu:inv_mpu6050: Suppress clang W=1 warning about pointer to enum conversion.
  iio:imu:inv_icm42600: Suppress clang W=1 warning about pointer to enum conversion.
  iio:dac:mcp4725: Suppress clang W=1 warning about pointer to enum conversion.
  iio:amplifiers:hmc425a: Suppress clang W=1 warning about pointer to enum conversion.
  iio:adc:ti-ads1015: Suppress clang W=1 warning about pointer to enum conversion.
  iio:adc:rcar: Suppress clang W=1 warning about pointer to enum conversion.
  iio:adc:ina2xx-adc: Suppress clang W=1 warning about pointer to enum conversion.
  iio:accel:bma180: Suppress clang W=1 warning about pointer to enum conversion.
  drivers:iio:dac: Add AD3552R driver support
  dt-bindings: iio: dac: Add adi,ad3552r.yaml
  ...
This commit is contained in:
Greg Kroah-Hartman 2021-12-22 12:33:01 +01:00
commit 1bb866dcb8
123 changed files with 7226 additions and 459 deletions

View File

@ -0,0 +1,16 @@
What: /sys/bus/iio/devices/iio:deviceX/filter_mode_available
KernelVersion:
Contact: linux-iio@vger.kernel.org
Description:
Reading this returns the valid values that can be written to the
on_altvoltage0_mode attribute:
- auto -> Adjust bandpass filter to track changes in input clock rate.
- manual -> disable/unregister the clock rate notifier / input clock tracking.
What: /sys/bus/iio/devices/iio:deviceX/filter_mode
KernelVersion:
Contact: linux-iio@vger.kernel.org
Description:
This attribute configures the filter mode.
Reading returns the actual mode.

View File

@ -27,6 +27,7 @@ description: |
8 | batt_v
9 | batt_chrg_i
10 | batt_dischrg_i
11 | ts_v
AXP22x
------
@ -34,6 +35,7 @@ description: |
1 | batt_v
2 | batt_chrg_i
3 | batt_dischrg_i
4 | ts_v
AXP813
------
@ -42,6 +44,7 @@ description: |
2 | batt_v
3 | batt_chrg_i
4 | batt_dischrg_i
5 | ts_v
properties:

View File

@ -0,0 +1,227 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/xlnx,zynqmp-ams.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Xilinx Zynq Ultrascale AMS controller
maintainers:
- Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
description: |
The AMS (Analog Monitoring System) includes an ADC as well as on-chip sensors
that can be used to sample external voltages and monitor on-die operating
conditions, such as temperature and supply voltage levels.
The AMS has two SYSMON blocks which are PL (Programmable Logic) SYSMON and
PS (Processing System) SYSMON.
All designs should have AMS registers, but PS and PL are optional. The
AMS controller can work with only PS, only PL and both PS and PL
configurations. Please specify registers according to your design. Devicetree
should always have AMS module property. Providing PS & PL module is optional.
AMS Channel Details
```````````````````
Sysmon Block |Channel| Details |Measurement
|Number | |Type
---------------------------------------------------------------------------------------------------------
AMS CTRL |0 |System PLLs voltage measurement, VCC_PSPLL. |Voltage
|1 |Battery voltage measurement, VCC_PSBATT. |Voltage
|2 |PL Internal voltage measurement, VCCINT. |Voltage
|3 |Block RAM voltage measurement, VCCBRAM. |Voltage
|4 |PL Aux voltage measurement, VCCAUX. |Voltage
|5 |Voltage measurement for six DDR I/O PLLs, VCC_PSDDR_PLL. |Voltage
|6 |VCC_PSINTFP_DDR voltage measurement. |Voltage
---------------------------------------------------------------------------------------------------------
PS Sysmon |7 |LPD temperature measurement. |Temperature
|8 |FPD temperature measurement (REMOTE). |Temperature
|9 |VCC PS LPD voltage measurement (supply1). |Voltage
|10 |VCC PS FPD voltage measurement (supply2). |Voltage
|11 |PS Aux voltage reference (supply3). |Voltage
|12 |DDR I/O VCC voltage measurement. |Voltage
|13 |PS IO Bank 503 voltage measurement (supply5). |Voltage
|14 |PS IO Bank 500 voltage measurement (supply6). |Voltage
|15 |VCCO_PSIO1 voltage measurement. |Voltage
|16 |VCCO_PSIO2 voltage measurement. |Voltage
|17 |VCC_PS_GTR voltage measurement (VPS_MGTRAVCC). |Voltage
|18 |VTT_PS_GTR voltage measurement (VPS_MGTRAVTT). |Voltage
|19 |VCC_PSADC voltage measurement. |Voltage
---------------------------------------------------------------------------------------------------------
PL Sysmon |20 |PL temperature measurement. |Temperature
|21 |PL Internal voltage measurement, VCCINT. |Voltage
|22 |PL Auxiliary voltage measurement, VCCAUX. |Voltage
|23 |ADC Reference P+ voltage measurement. |Voltage
|24 |ADC Reference N- voltage measurement. |Voltage
|25 |PL Block RAM voltage measurement, VCCBRAM. |Voltage
|26 |LPD Internal voltage measurement, VCC_PSINTLP (supply4). |Voltage
|27 |FPD Internal voltage measurement, VCC_PSINTFP (supply5). |Voltage
|28 |PS Auxiliary voltage measurement (supply6). |Voltage
|29 |PL VCCADC voltage measurement (vccams). |Voltage
|30 |Differential analog input signal voltage measurment. |Voltage
|31 |VUser0 voltage measurement (supply7). |Voltage
|32 |VUser1 voltage measurement (supply8). |Voltage
|33 |VUser2 voltage measurement (supply9). |Voltage
|34 |VUser3 voltage measurement (supply10). |Voltage
|35 |Auxiliary ch 0 voltage measurement (VAux0). |Voltage
|36 |Auxiliary ch 1 voltage measurement (VAux1). |Voltage
|37 |Auxiliary ch 2 voltage measurement (VAux2). |Voltage
|38 |Auxiliary ch 3 voltage measurement (VAux3). |Voltage
|39 |Auxiliary ch 4 voltage measurement (VAux4). |Voltage
|40 |Auxiliary ch 5 voltage measurement (VAux5). |Voltage
|41 |Auxiliary ch 6 voltage measurement (VAux6). |Voltage
|42 |Auxiliary ch 7 voltage measurement (VAux7). |Voltage
|43 |Auxiliary ch 8 voltage measurement (VAux8). |Voltage
|44 |Auxiliary ch 9 voltage measurement (VAux9). |Voltage
|45 |Auxiliary ch 10 voltage measurement (VAux10). |Voltage
|46 |Auxiliary ch 11 voltage measurement (VAux11). |Voltage
|47 |Auxiliary ch 12 voltage measurement (VAux12). |Voltage
|48 |Auxiliary ch 13 voltage measurement (VAux13). |Voltage
|49 |Auxiliary ch 14 voltage measurement (VAux14). |Voltage
|50 |Auxiliary ch 15 voltage measurement (VAux15). |Voltage
--------------------------------------------------------------------------------------------------------
properties:
compatible:
enum:
- xlnx,zynqmp-ams
interrupts:
maxItems: 1
reg:
description: AMS Controller register space
maxItems: 1
ranges:
description:
Maps the child address space for PS and/or PL.
maxItems: 1
'#address-cells':
const: 1
'#size-cells':
const: 1
'#io-channel-cells':
const: 1
ams-ps@0:
type: object
description: |
PS (Processing System) SYSMON is memory mapped to PS. This block has
built-in alarm generation logic that is used to interrupt the processor
based on condition set.
properties:
compatible:
enum:
- xlnx,zynqmp-ams-ps
reg:
description: Register Space for PS-SYSMON
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
ams-pl@400:
type: object
description:
PL-SYSMON is capable of monitoring off chip voltage and temperature.
PL-SYSMON block has DRP, JTAG and I2C interface to enable monitoring
from external master. Out of this interface currently only DRP is
supported. This block has alarm generation logic that is used to
interrupt the processor based on condition set.
properties:
compatible:
items:
- enum:
- xlnx,zynqmp-ams-pl
reg:
description: Register Space for PL-SYSMON.
maxItems: 1
'#address-cells':
const: 1
'#size-cells':
const: 0
patternProperties:
"^channel@([2-4][0-9]|50)$":
type: object
description:
Describes the external channels connected.
properties:
reg:
description:
Pair of pins the channel is connected to. This value is
same as Channel Number for a particular channel.
minimum: 20
maximum: 50
xlnx,bipolar:
$ref: /schemas/types.yaml#/definitions/flag
type: boolean
description:
If the set channel is used in bipolar mode.
required:
- reg
additionalProperties: false
required:
- compatible
- reg
- ranges
additionalProperties: false
examples:
- |
bus {
#address-cells = <2>;
#size-cells = <2>;
xilinx_ams: ams@ffa50000 {
compatible = "xlnx,zynqmp-ams";
interrupt-parent = <&gic>;
interrupts = <0 56 4>;
reg = <0x0 0xffa50000 0x0 0x800>;
#address-cells = <1>;
#size-cells = <1>;
#io-channel-cells = <1>;
ranges = <0 0 0xffa50800 0x800>;
ams_ps: ams-ps@0 {
compatible = "xlnx,zynqmp-ams-ps";
reg = <0 0x400>;
};
ams_pl: ams-pl@400 {
compatible = "xlnx,zynqmp-ams-pl";
reg = <0x400 0x400>;
#address-cells = <1>;
#size-cells = <0>;
channel@30 {
reg = <30>;
xlnx,bipolar;
};
channel@31 {
reg = <31>;
};
channel@38 {
reg = <38>;
xlnx,bipolar;
};
};
};
};

View File

@ -0,0 +1,158 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/addac/adi,ad74413r.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AD74412R/AD74413R device
maintainers:
- Cosmin Tanislav <cosmin.tanislav@analog.com>
description: |
The AD74412R and AD74413R are quad-channel software configurable input/output
solutions for building and process control applications. They contain
functionality for analog output, analog input, digital input, resistance
temperature detector, and thermocouple measurements integrated
into a single chip solution with an SPI interface.
The devices feature a 16-bit ADC and four configurable 13-bit DACs to provide
four configurable input/output channels and a suite of diagnostic functions.
The AD74413R differentiates itself from the AD74412R by being HART-compatible.
https://www.analog.com/en/products/ad74412r.html
https://www.analog.com/en/products/ad74413r.html
properties:
compatible:
enum:
- adi,ad74412r
- adi,ad74413r
reg:
maxItems: 1
'#address-cells':
const: 1
'#size-cells':
const: 0
spi-max-frequency:
maximum: 1000000
spi-cpol: true
interrupts:
maxItems: 1
refin-supply: true
shunt-resistor-micro-ohms:
description:
Shunt (sense) resistor value in micro-Ohms.
default: 100000000
required:
- compatible
- reg
- spi-max-frequency
- spi-cpol
- refin-supply
additionalProperties: false
patternProperties:
"^channel@[0-3]$":
type: object
description: Represents the external channels which are connected to the device.
properties:
reg:
description: |
The channel number. It can have up to 4 channels numbered from 0 to 3.
minimum: 0
maximum: 3
adi,ch-func:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Channel function.
HART functions are not supported on AD74412R.
0 - CH_FUNC_HIGH_IMPEDANCE
1 - CH_FUNC_VOLTAGE_OUTPUT
2 - CH_FUNC_CURRENT_OUTPUT
3 - CH_FUNC_VOLTAGE_INPUT
4 - CH_FUNC_CURRENT_INPUT_EXT_POWER
5 - CH_FUNC_CURRENT_INPUT_LOOP_POWER
6 - CH_FUNC_RESISTANCE_INPUT
7 - CH_FUNC_DIGITAL_INPUT_LOGIC
8 - CH_FUNC_DIGITAL_INPUT_LOOP_POWER
9 - CH_FUNC_CURRENT_INPUT_EXT_POWER_HART
10 - CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART
minimum: 0
maximum: 10
default: 0
adi,gpo-comparator:
type: boolean
description: |
Whether to configure GPO as a comparator or not.
When not configured as a comparator, the GPO will be treated as an
output-only GPIO.
required:
- reg
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/iio/addac/adi,ad74413r.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
cs-gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
status = "okay";
ad74413r@0 {
compatible = "adi,ad74413r";
reg = <0>;
spi-max-frequency = <1000000>;
spi-cpol;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&gpio>;
interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
refin-supply = <&ad74413r_refin>;
channel@0 {
reg = <0>;
adi,ch-func = <CH_FUNC_VOLTAGE_OUTPUT>;
};
channel@1 {
reg = <1>;
adi,ch-func = <CH_FUNC_CURRENT_OUTPUT>;
};
channel@2 {
reg = <2>;
adi,ch-func = <CH_FUNC_DIGITAL_INPUT_LOGIC>;
adi,gpo-comparator;
};
channel@3 {
reg = <3>;
adi,ch-func = <CH_FUNC_CURRENT_INPUT_EXT_POWER>;
};
};
};
...

View File

@ -0,0 +1,217 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2020 Analog Devices Inc.
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/dac/adi,ad3552r.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AD2552R DAC device driver
maintainers:
- Mihail Chindris <mihail.chindris@analog.com>
description: |
Bindings for the Analog Devices AD3552R DAC device and similar.
Datasheet can be found here:
https://www.analog.com/media/en/technical-documentation/data-sheets/ad3542r.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/ad3552r.pdf
properties:
compatible:
enum:
- adi,ad3542r
- adi,ad3552r
reg:
maxItems: 1
spi-max-frequency:
maximum: 30000000
reset-gpios:
maxItems: 1
ldac-gpios:
description: |
LDAC pin to be used as a hardware trigger to update the DAC channels.
maxItems: 1
vref-supply:
description:
The regulator to use as an external reference. If it does not exists the
internal reference will be used. External reference must be 2.5V
adi,vref-out-en:
description: Vref I/O driven by internal vref to 2.5V. If not set, Vref pin
will be floating.
type: boolean
adi,sdo-drive-strength:
description: |
Configure SDIO0 and SDIO1 strength levels:
- 0: low SDO drive strength.
- 1: medium low SDO drive strength.
- 2: medium high SDO drive strength.
- 3: high SDO drive strength
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 3]
'#address-cells':
const: 1
'#size-cells':
const: 0
patternProperties:
"^channel@([0-1])$":
type: object
description: Configurations of the DAC Channels
additionalProperties: false
properties:
reg:
description: Channel number
enum: [0, 1]
adi,output-range-microvolt: true
custom-output-range-config:
type: object
description: Configuration of custom range when
adi,output-range-microvolt is not present.
The formulas for calculation the output voltages are
Vout_fs = 2.5 + [(GainN + Offset/1024) * 2.5 * Rfbx * 1.03]
Vout_zs = 2.5 - [(GainP + Offset/1024) * 2.5 * Rfbx * 1.03]
properties:
adi,gain-offset:
description: Gain offset used in the above formula
$ref: /schemas/types.yaml#/definitions/int32
maximum: 511
minimum: -511
adi,gain-scaling-p-inv-log2:
description: GainP = 1 / ( 2 ^ adi,gain-scaling-p-inv-log2)
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 3]
adi,gain-scaling-n-inv-log2:
description: GainN = 1 / ( 2 ^ adi,gain-scaling-n-inv-log2)
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 3]
adi,rfb-ohms:
description: Feedback Resistor
required:
- adi,gain-offset
- adi,gain-scaling-p-inv-log2
- adi,gain-scaling-n-inv-log2
- adi,rfb-ohms
required:
- reg
oneOf:
# If adi,output-range-microvolt is missing,
# custom-output-range-config must be used
- required:
- adi,output-range-microvolt
- required:
- custom-output-range-config
allOf:
- if:
properties:
compatible:
contains:
const: adi,ad3542r
then:
patternProperties:
"^channel@([0-1])$":
type: object
properties:
adi,output-range-microvolt:
description: |
Voltage output range of the channel as <minimum, maximum>
Required connections:
Rfb1x for: 0 to 2.5 V; 0 to 3V; 0 to 5 V;
Rfb2x for: 0 to 10 V; 2.5 to 7.5V; -5 to 5 V;
oneOf:
- items:
- const: 0
- enum: [2500000, 3000000, 5000000, 10000000]
- items:
- const: -2500000
- const: 7500000
- items:
- const: -5000000
- const: 5000000
required:
- adi,output-range-microvolt
- if:
properties:
compatible:
contains:
const: adi,ad3552r
then:
patternProperties:
"^channel@([0-1])$":
type: object
properties:
adi,output-range-microvolt:
description: |
Voltage output range of the channel as <minimum, maximum>
Required connections:
Rfb1x for: 0 to 2.5 V; 0 to 5 V;
Rfb2x for: 0 to 10 V; -5 to 5 V;
Rfb4x for: -10 to 10V
oneOf:
- items:
- const: 0
- enum: [2500000, 5000000, 10000000]
- items:
- const: -5000000
- const: 5000000
- items:
- const: -10000000
- const: 10000000
required:
- compatible
- reg
- spi-max-frequency
additionalProperties: false
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
ad3552r@0 {
compatible = "adi,ad3552r";
reg = <0>;
spi-max-frequency = <20000000>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
adi,output-range-microvolt = <0 10000000>;
};
channel@1 {
reg = <1>;
custom-output-range-config {
adi,gain-offset = <5>;
adi,gain-scaling-p-inv-log2 = <1>;
adi,gain-scaling-n-inv-log2 = <2>;
adi,rfb-ohms = <1>;
};
};
};
};
...

View File

@ -125,7 +125,6 @@ oneOf:
examples:
- |
#include <dt-bindings/iio/adi,ad5592r.h>
spi {
#address-cells = <1>;
#size-cells = <0>;

View File

@ -0,0 +1,61 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/dac/adi,ad7293.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: AD7293 12-Bit Power Amplifier Current Controller with ADC,
DACs, Temperature and Current Sensors
maintainers:
- Antoniu Miclaus <antoniu.miclaus@analog.com>
description: |
Power Amplifier drain current controller containing functionality
for general-purpose monitoring and control of current, voltage,
and temperature, integrated into a single chip solution with an
SPI-compatible interface.
https://www.analog.com/en/products/ad7293.html
properties:
compatible:
enum:
- adi,ad7293
avdd-supply: true
vdrive-supply: true
reset-gpios:
maxItems: 1
reg:
maxItems: 1
spi-max-frequency:
maximum: 1000000
required:
- compatible
- reg
- avdd-supply
- vdrive-supply
additionalProperties: false
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
ad7293@0 {
compatible = "adi,ad7293";
reg = <0>;
spi-max-frequency = <1000000>;
avdd-supply = <&avdd>;
vdrive-supply = <&vdrive>;
reset-gpios = <&gpio 10 0>;
};
};
...

View File

@ -0,0 +1,66 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/filter/adi,admv8818.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ADMV8818 Digitally Tunable, High-Pass and Low-Pass Filter
maintainers:
- Antoniu Miclaus <antoniu.miclaus@analog.com>
description: |
Fully monolithic microwave integrated circuit (MMIC) that
features a digitally selectable frequency of operation.
The device features four independently controlled high-pass
filters (HPFs) and four independently controlled low-pass filters
(LPFs) that span the 2 GHz to 18 GHz frequency range.
https://www.analog.com/en/products/admv8818.html
properties:
compatible:
enum:
- adi,admv8818
reg:
maxItems: 1
spi-max-frequency:
maximum: 10000000
clocks:
description:
Definition of the external clock.
minItems: 1
clock-names:
items:
- const: rf_in
clock-output-names:
maxItems: 1
'#clock-cells':
const: 0
required:
- compatible
- reg
additionalProperties: false
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
admv8818@0 {
compatible = "adi,admv8818";
reg = <0>;
spi-max-frequency = <10000000>;
clocks = <&admv8818_rfin>;
clock-names = "rf_in";
};
};
...

View File

@ -61,6 +61,13 @@ properties:
type: boolean
description: enable/disable internal i2c controller pullup resistors.
st,disable-sensor-hub:
type: boolean
description:
Enable/disable internal i2c controller slave autoprobing at bootstrap.
Disable sensor-hub is useful if i2c controller clock/data lines are
connected through a pull-up with other chip lines (e.g. SDO/SA0).
drive-open-drain:
type: boolean
description:

View File

@ -9,6 +9,9 @@ title: LiteON LTR501 I2C Proximity and Light sensor
maintainers:
- Nikita Travkin <nikita@trvn.ru>
allOf:
- $ref: ../common.yaml#
properties:
compatible:
enum:
@ -25,6 +28,8 @@ properties:
interrupts:
maxItems: 1
proximity-near-level: true
additionalProperties: false
required:
@ -42,6 +47,8 @@ examples:
light-sensor@23 {
compatible = "liteon,ltr559";
reg = <0x23>;
proximity-near-level = <75>;
vdd-supply = <&pm8916_l17>;
vddio-supply = <&pm8916_l6>;

View File

@ -1069,6 +1069,15 @@ W: http://ez.analog.com/community/linux-device-drivers
F: Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml
F: drivers/iio/adc/ad7780.c
ANALOG DEVICES INC AD74413R DRIVER
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
W: http://ez.analog.com/community/linux-device-drivers
F: Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml
F: drivers/iio/addac/ad74413r.c
F: include/dt-bindings/iio/addac/adi,ad74413r.h
ANALOG DEVICES INC AD9389B DRIVER
M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org
@ -13709,9 +13718,9 @@ F: Documentation/devicetree/bindings/display/imx/nxp,imx8mq-dcss.yaml
F: drivers/gpu/drm/imx/dcss/
NXP i.MX 8QXP ADC DRIVER
M: Cai Huoqing <caihuoqing@baidu.com>
M: Cai Huoqing <cai.huoqing@linux.dev>
L: linux-iio@vger.kernel.org
S: Supported
S: Maintained
F: Documentation/devicetree/bindings/iio/adc/nxp,imx8qxp-adc.yaml
F: drivers/iio/adc/imx8qxp-adc.c
@ -20894,6 +20903,13 @@ F: fs/xfs/
F: include/uapi/linux/dqblk_xfs.h
F: include/uapi/linux/fsmap.h
XILINX AMS DRIVER
M: Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
L: linux-iio@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/iio/adc/xlnx,zynqmp-ams.yaml
F: drivers/iio/adc/xilinx-ams.c
XILINX AXI ETHERNET DRIVER
M: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
S: Maintained

View File

@ -958,6 +958,22 @@ int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index)
}
EXPORT_SYMBOL(fwnode_irq_get);
/**
* fwnode_iomap - Maps the memory mapped IO for a given fwnode
* @fwnode: Pointer to the firmware node
* @index: Index of the IO range
*
* Returns a pointer to the mapped memory.
*/
void __iomem *fwnode_iomap(struct fwnode_handle *fwnode, int index)
{
if (IS_ENABLED(CONFIG_OF_ADDRESS) && is_of_node(fwnode))
return of_iomap(to_of_node(fwnode), index);
return NULL;
}
EXPORT_SYMBOL(fwnode_iomap);
/**
* fwnode_graph_get_next_endpoint - Get next endpoint firmware node
* @fwnode: Pointer to the parent firmware node

View File

@ -70,6 +70,7 @@ config IIO_TRIGGERED_EVENT
source "drivers/iio/accel/Kconfig"
source "drivers/iio/adc/Kconfig"
source "drivers/iio/addac/Kconfig"
source "drivers/iio/afe/Kconfig"
source "drivers/iio/amplifiers/Kconfig"
source "drivers/iio/cdc/Kconfig"
@ -77,6 +78,7 @@ source "drivers/iio/chemical/Kconfig"
source "drivers/iio/common/Kconfig"
source "drivers/iio/dac/Kconfig"
source "drivers/iio/dummy/Kconfig"
source "drivers/iio/filter/Kconfig"
source "drivers/iio/frequency/Kconfig"
source "drivers/iio/gyro/Kconfig"
source "drivers/iio/health/Kconfig"

View File

@ -15,6 +15,7 @@ obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o
obj-y += accel/
obj-y += adc/
obj-y += addac/
obj-y += afe/
obj-y += amplifiers/
obj-y += buffer/
@ -24,6 +25,7 @@ obj-y += common/
obj-y += dac/
obj-y += dummy/
obj-y += gyro/
obj-y += filter/
obj-y += frequency/
obj-y += health/
obj-y += humidity/

View File

@ -658,7 +658,7 @@ static const struct iio_chan_spec_ext_info bma023_ext_info[] = {
static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
IIO_ENUM("power_mode", IIO_SHARED_BY_TYPE, &bma180_power_mode_enum),
IIO_ENUM_AVAILABLE("power_mode", &bma180_power_mode_enum),
IIO_ENUM_AVAILABLE("power_mode", IIO_SHARED_BY_TYPE, &bma180_power_mode_enum),
IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bma180_accel_get_mount_matrix),
{ }
};
@ -938,7 +938,7 @@ static int bma180_probe(struct i2c_client *client,
i2c_set_clientdata(client, indio_dev);
data->client = client;
if (client->dev.of_node)
chip = (enum chip_ids)of_device_get_match_data(dev);
chip = (uintptr_t)of_device_get_match_data(dev);
else
chip = id->driver_data;
data->part_info = &bma180_part_info[chip];

View File

@ -27,7 +27,6 @@
#define BMA220_CHIP_ID 0xDD
#define BMA220_READ_MASK BIT(7)
#define BMA220_RANGE_MASK GENMASK(1, 0)
#define BMA220_DATA_SHIFT 2
#define BMA220_SUSPEND_SLEEP 0xFF
#define BMA220_SUSPEND_WAKE 0x00
@ -45,7 +44,7 @@
.sign = 's', \
.realbits = 6, \
.storagebits = 8, \
.shift = BMA220_DATA_SHIFT, \
.shift = 2, \
.endianness = IIO_CPU, \
}, \
}
@ -125,7 +124,8 @@ static int bma220_read_raw(struct iio_dev *indio_dev,
ret = bma220_read_reg(data->spi_device, chan->address);
if (ret < 0)
return -EINVAL;
*val = sign_extend32(ret >> BMA220_DATA_SHIFT, 5);
*val = sign_extend32(ret >> chan->scan_type.shift,
chan->scan_type.realbits - 1);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
ret = bma220_read_reg(data->spi_device, BMA220_REG_RANGE);

View File

@ -170,7 +170,7 @@ static const struct {
{1000, 0, 0x0E},
{2000, 0, 0x0F} };
static const struct {
static __maybe_unused const struct {
int bw_bits;
int msec;
} bmc150_accel_sample_upd_time[] = { {0x08, 64},

View File

@ -315,7 +315,7 @@ static const char *const kxtf9_samp_freq_avail =
"25 50 100 200 400 800";
/* Refer to section 4 of the specification */
static const struct {
static __maybe_unused const struct {
int odr_bits;
int usec;
} odr_start_up_times[KX_MAX_CHIPS][12] = {
@ -927,7 +927,8 @@ static int kxcjk1013_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&data->mutex);
return ret;
}
*val = sign_extend32(ret >> 4, 11);
*val = sign_extend32(ret >> chan->scan_type.shift,
chan->scan_type.realbits - 1);
ret = kxcjk1013_set_power_state(data, false);
}
mutex_unlock(&data->mutex);

View File

@ -134,7 +134,8 @@ static int mma7455_read_raw(struct iio_dev *indio_dev,
if (ret)
return ret;
*val = sign_extend32(le16_to_cpu(data), 9);
*val = sign_extend32(le16_to_cpu(data),
chan->scan_type.realbits - 1);
return IIO_VAL_INT;

View File

@ -210,10 +210,16 @@ static int mma7660_probe(struct i2c_client *client,
static int mma7660_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
int ret;
iio_device_unregister(indio_dev);
return mma7660_set_mode(iio_priv(indio_dev), MMA7660_MODE_STANDBY);
ret = mma7660_set_mode(iio_priv(indio_dev), MMA7660_MODE_STANDBY);
if (ret)
dev_warn(&client->dev, "Failed to put device in stand-by mode (%pe), ignoring\n",
ERR_PTR(ret));
return 0;
}
#ifdef CONFIG_PM_SLEEP

View File

@ -1053,7 +1053,7 @@ static irqreturn_t mma8452_interrupt(int irq, void *p)
{
struct iio_dev *indio_dev = p;
struct mma8452_data *data = iio_priv(indio_dev);
int ret = IRQ_NONE;
irqreturn_t ret = IRQ_NONE;
int src;
src = i2c_smbus_read_byte_data(data->client, MMA8452_INT_SRC);

View File

@ -917,7 +917,7 @@ static const struct iio_enum mma9553_calibgender_enum = {
static const struct iio_chan_spec_ext_info mma9553_ext_info[] = {
IIO_ENUM("calibgender", IIO_SHARED_BY_TYPE, &mma9553_calibgender_enum),
IIO_ENUM_AVAILABLE("calibgender", &mma9553_calibgender_enum),
IIO_ENUM_AVAILABLE("calibgender", IIO_SHARED_BY_TYPE, &mma9553_calibgender_enum),
{},
};

View File

@ -534,6 +534,13 @@ static const struct iio_chan_spec sca3000_channels_with_temp[] = {
BIT(IIO_CHAN_INFO_OFFSET),
/* No buffer support */
.scan_index = -1,
.scan_type = {
.sign = 'u',
.realbits = 9,
.storagebits = 16,
.shift = 5,
.endianness = IIO_BE,
},
},
{
.type = IIO_ACCEL,
@ -730,8 +737,9 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&st->lock);
return ret;
}
*val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF;
*val = sign_extend32(*val, 12);
*val = sign_extend32(be16_to_cpup((__be16 *)st->rx) >>
chan->scan_type.shift,
chan->scan_type.realbits - 1);
} else {
/* get the temperature when available */
ret = sca3000_read_data_short(st,
@ -741,8 +749,9 @@ static int sca3000_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&st->lock);
return ret;
}
*val = ((st->rx[0] & 0x3F) << 3) |
((st->rx[1] & 0xE0) >> 5);
*val = (be16_to_cpup((__be16 *)st->rx) >>
chan->scan_type.shift) &
GENMASK(chan->scan_type.realbits - 1, 0);
}
mutex_unlock(&st->lock);
return IIO_VAL_INT;

View File

@ -355,7 +355,7 @@ static int stk8312_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&data->lock);
return ret;
}
*val = sign_extend32(ret, 7);
*val = sign_extend32(ret, chan->scan_type.realbits - 1);
ret = stk8312_set_mode(data,
data->mode & (~STK8312_MODE_ACTIVE));
mutex_unlock(&data->lock);

View File

@ -227,7 +227,8 @@ static int stk8ba50_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&data->lock);
return -EINVAL;
}
*val = sign_extend32(ret >> STK8BA50_DATA_SHIFT, 9);
*val = sign_extend32(ret >> chan->scan_type.shift,
chan->scan_type.realbits - 1);
stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
mutex_unlock(&data->lock);
return IIO_VAL_INT;

View File

@ -1146,7 +1146,7 @@ config TI_ADS7950
config TI_ADS8344
tristate "Texas Instruments ADS8344"
depends on SPI && OF
depends on SPI
help
If you say yes here you get support for Texas Instruments ADS8344
ADC chips
@ -1156,7 +1156,7 @@ config TI_ADS8344
config TI_ADS8688
tristate "Texas Instruments ADS8688"
depends on SPI && OF
depends on SPI
help
If you say yes here you get support for Texas Instruments ADS8684 and
and ADS8688 ADC chips
@ -1166,7 +1166,7 @@ config TI_ADS8688
config TI_ADS124S08
tristate "Texas Instruments ADS124S08"
depends on SPI && OF
depends on SPI
help
If you say yes here you get support for Texas Instruments ADS124S08
and ADS124S06 ADC chips
@ -1288,4 +1288,19 @@ config XILINX_XADC
The driver can also be build as a module. If so, the module will be called
xilinx-xadc.
config XILINX_AMS
tristate "Xilinx AMS driver"
depends on ARCH_ZYNQMP || COMPILE_TEST
depends on HAS_IOMEM
help
Say yes here to have support for the Xilinx AMS for Ultrascale/Ultrascale+
System Monitor. With this you can measure and monitor the Voltages and
Temperature values on the SOC.
The driver supports Voltage and Temperature monitoring on Xilinx Ultrascale
devices.
The driver can also be built as a module. If so, the module will be called
xilinx-ams.
endmenu

View File

@ -115,4 +115,5 @@ obj-$(CONFIG_VF610_ADC) += vf610_adc.o
obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
xilinx-xadc-y := xilinx-xadc-core.o xilinx-xadc-events.o
obj-$(CONFIG_XILINX_XADC) += xilinx-xadc.o
obj-$(CONFIG_XILINX_AMS) += xilinx-ams.o
obj-$(CONFIG_SD_ADC_MODULATOR) += sd_adc_modulator.o

View File

@ -257,7 +257,8 @@ static const struct iio_chan_spec_ext_info ad7192_calibsys_ext_info[] = {
},
IIO_ENUM("sys_calibration_mode", IIO_SEPARATE,
&ad7192_syscalib_mode_enum),
IIO_ENUM_AVAILABLE("sys_calibration_mode", &ad7192_syscalib_mode_enum),
IIO_ENUM_AVAILABLE("sys_calibration_mode", IIO_SHARED_BY_TYPE,
&ad7192_syscalib_mode_enum),
{}
};

View File

@ -159,7 +159,8 @@ static int ad7266_read_raw(struct iio_dev *indio_dev,
*val = (*val >> 2) & 0xfff;
if (chan->scan_type.sign == 's')
*val = sign_extend32(*val, 11);
*val = sign_extend32(*val,
chan->scan_type.realbits - 1);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:

View File

@ -62,7 +62,7 @@ struct ad7606_chip_info {
* struct ad7606_state - driver instance specific data
* @dev pointer to kernel device
* @chip_info entry in the table of chips that describes this device
* @reg regulator info for the the power supply of the device
* @reg regulator info for the power supply of the device
* @bops bus operations (SPI or parallel)
* @range voltage range selection, selects which scale to apply
* @oversampling oversampling selection

View File

@ -467,9 +467,6 @@ int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig)
}
EXPORT_SYMBOL_GPL(ad_sd_validate_trigger);
static const struct iio_trigger_ops ad_sd_trigger_ops = {
};
static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_dev)
{
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
@ -486,7 +483,6 @@ static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_de
if (sigma_delta->trig == NULL)
return -ENOMEM;
sigma_delta->trig->ops = &ad_sd_trigger_ops;
init_completion(&sigma_delta->completion);
sigma_delta->irq_dis = true;

View File

@ -1662,10 +1662,9 @@ static int at91_adc_write_raw(struct iio_dev *indio_dev,
}
}
static void at91_adc_dma_init(struct platform_device *pdev)
static void at91_adc_dma_init(struct at91_adc_state *st)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct at91_adc_state *st = iio_priv(indio_dev);
struct device *dev = &st->indio_dev->dev;
struct dma_slave_config config = {0};
/* we have 2 bytes for each channel */
unsigned int sample_size = st->soc_info.platform->nr_channels * 2;
@ -1680,9 +1679,9 @@ static void at91_adc_dma_init(struct platform_device *pdev)
if (st->dma_st.dma_chan)
return;
st->dma_st.dma_chan = dma_request_chan(&pdev->dev, "rx");
st->dma_st.dma_chan = dma_request_chan(dev, "rx");
if (IS_ERR(st->dma_st.dma_chan)) {
dev_info(&pdev->dev, "can't get DMA channel\n");
dev_info(dev, "can't get DMA channel\n");
st->dma_st.dma_chan = NULL;
goto dma_exit;
}
@ -1692,7 +1691,7 @@ static void at91_adc_dma_init(struct platform_device *pdev)
&st->dma_st.rx_dma_buf,
GFP_KERNEL);
if (!st->dma_st.rx_buf) {
dev_info(&pdev->dev, "can't allocate coherent DMA area\n");
dev_info(dev, "can't allocate coherent DMA area\n");
goto dma_chan_disable;
}
@ -1705,11 +1704,11 @@ static void at91_adc_dma_init(struct platform_device *pdev)
config.dst_maxburst = 1;
if (dmaengine_slave_config(st->dma_st.dma_chan, &config)) {
dev_info(&pdev->dev, "can't configure DMA slave\n");
dev_info(dev, "can't configure DMA slave\n");
goto dma_free_area;
}
dev_info(&pdev->dev, "using %s for rx DMA transfers\n",
dev_info(dev, "using %s for rx DMA transfers\n",
dma_chan_name(st->dma_st.dma_chan));
return;
@ -1721,13 +1720,12 @@ dma_chan_disable:
dma_release_channel(st->dma_st.dma_chan);
st->dma_st.dma_chan = NULL;
dma_exit:
dev_info(&pdev->dev, "continuing without DMA support\n");
dev_info(dev, "continuing without DMA support\n");
}
static void at91_adc_dma_disable(struct platform_device *pdev)
static void at91_adc_dma_disable(struct at91_adc_state *st)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct at91_adc_state *st = iio_priv(indio_dev);
struct device *dev = &st->indio_dev->dev;
/* we have 2 bytes for each channel */
unsigned int sample_size = st->soc_info.platform->nr_channels * 2;
unsigned int pages = DIV_ROUND_UP(AT91_HWFIFO_MAX_SIZE *
@ -1745,7 +1743,7 @@ static void at91_adc_dma_disable(struct platform_device *pdev)
dma_release_channel(st->dma_st.dma_chan);
st->dma_st.dma_chan = NULL;
dev_info(&pdev->dev, "continuing without DMA support\n");
dev_info(dev, "continuing without DMA support\n");
}
static int at91_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val)
@ -1771,9 +1769,9 @@ static int at91_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val)
*/
if (val == 1)
at91_adc_dma_disable(to_platform_device(&indio_dev->dev));
at91_adc_dma_disable(st);
else if (val > 1)
at91_adc_dma_init(to_platform_device(&indio_dev->dev));
at91_adc_dma_init(st);
/*
* We can start the DMA only after setting the watermark and
@ -1781,7 +1779,7 @@ static int at91_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val)
*/
ret = at91_adc_buffer_prepare(indio_dev);
if (ret)
at91_adc_dma_disable(to_platform_device(&indio_dev->dev));
at91_adc_dma_disable(st);
return ret;
}
@ -1828,7 +1826,7 @@ static void at91_adc_hw_init(struct iio_dev *indio_dev)
static ssize_t at91_adc_get_fifo_state(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct at91_adc_state *st = iio_priv(indio_dev);
return scnprintf(buf, PAGE_SIZE, "%d\n", !!st->dma_st.dma_chan);
@ -1837,7 +1835,7 @@ static ssize_t at91_adc_get_fifo_state(struct device *dev,
static ssize_t at91_adc_get_watermark(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct at91_adc_state *st = iio_priv(indio_dev);
return scnprintf(buf, PAGE_SIZE, "%d\n", st->dma_st.watermark);
@ -2078,7 +2076,7 @@ static int at91_adc_probe(struct platform_device *pdev)
return 0;
dma_disable:
at91_adc_dma_disable(pdev);
at91_adc_dma_disable(st);
per_clk_disable_unprepare:
clk_disable_unprepare(st->per_clk);
vref_disable:
@ -2095,7 +2093,7 @@ static int at91_adc_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
at91_adc_dma_disable(pdev);
at91_adc_dma_disable(st);
clk_disable_unprepare(st->per_clk);

View File

@ -186,6 +186,8 @@ static const struct iio_chan_spec axp20x_adc_channels[] = {
AXP20X_BATT_CHRG_I_H),
AXP20X_ADC_CHANNEL(AXP20X_BATT_DISCHRG_I, "batt_dischrg_i", IIO_CURRENT,
AXP20X_BATT_DISCHRG_I_H),
AXP20X_ADC_CHANNEL(AXP20X_TS_IN, "ts_v", IIO_VOLTAGE,
AXP20X_TS_IN_H),
};
static const struct iio_chan_spec axp22x_adc_channels[] = {
@ -203,6 +205,8 @@ static const struct iio_chan_spec axp22x_adc_channels[] = {
AXP20X_BATT_CHRG_I_H),
AXP20X_ADC_CHANNEL(AXP22X_BATT_DISCHRG_I, "batt_dischrg_i", IIO_CURRENT,
AXP20X_BATT_DISCHRG_I_H),
AXP20X_ADC_CHANNEL(AXP22X_TS_IN, "ts_v", IIO_VOLTAGE,
AXP22X_TS_ADC_H),
};
static const struct iio_chan_spec axp813_adc_channels[] = {
@ -222,6 +226,8 @@ static const struct iio_chan_spec axp813_adc_channels[] = {
AXP20X_BATT_CHRG_I_H),
AXP20X_ADC_CHANNEL(AXP22X_BATT_DISCHRG_I, "batt_dischrg_i", IIO_CURRENT,
AXP20X_BATT_DISCHRG_I_H),
AXP20X_ADC_CHANNEL(AXP813_TS_IN, "ts_v", IIO_VOLTAGE,
AXP288_TS_ADC_H),
};
static int axp20x_adc_raw(struct iio_dev *indio_dev,
@ -296,11 +302,36 @@ static int axp20x_adc_scale_voltage(int channel, int *val, int *val2)
*val2 = 400000;
return IIO_VAL_INT_PLUS_MICRO;
case AXP20X_TS_IN:
/* 0.8 mV per LSB */
*val = 0;
*val2 = 800000;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
}
static int axp22x_adc_scale_voltage(int channel, int *val, int *val2)
{
switch (channel) {
case AXP22X_BATT_V:
/* 1.1 mV per LSB */
*val = 1;
*val2 = 100000;
return IIO_VAL_INT_PLUS_MICRO;
case AXP22X_TS_IN:
/* 0.8 mV per LSB */
*val = 0;
*val2 = 800000;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
}
static int axp813_adc_scale_voltage(int channel, int *val, int *val2)
{
switch (channel) {
@ -314,6 +345,12 @@ static int axp813_adc_scale_voltage(int channel, int *val, int *val2)
*val2 = 100000;
return IIO_VAL_INT_PLUS_MICRO;
case AXP813_TS_IN:
/* 0.8 mV per LSB */
*val = 0;
*val2 = 800000;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
@ -367,12 +404,7 @@ static int axp22x_adc_scale(struct iio_chan_spec const *chan, int *val,
{
switch (chan->type) {
case IIO_VOLTAGE:
if (chan->channel != AXP22X_BATT_V)
return -EINVAL;
*val = 1;
*val2 = 100000;
return IIO_VAL_INT_PLUS_MICRO;
return axp22x_adc_scale_voltage(chan->channel, val, val2);
case IIO_CURRENT:
*val = 1;
@ -476,6 +508,7 @@ static int axp22x_read_raw(struct iio_dev *indio_dev,
{
switch (mask) {
case IIO_CHAN_INFO_OFFSET:
/* For PMIC temp only */
*val = -2677;
return IIO_VAL_INT;

View File

@ -31,14 +31,13 @@
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/iio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>

View File

@ -350,7 +350,7 @@ static const struct iio_enum hi8435_sensing_mode = {
static const struct iio_chan_spec_ext_info hi8435_ext_info[] = {
IIO_ENUM("sensing_mode", IIO_SEPARATE, &hi8435_sensing_mode),
IIO_ENUM_AVAILABLE("sensing_mode", &hi8435_sensing_mode),
IIO_ENUM_AVAILABLE("sensing_mode", IIO_SHARED_BY_TYPE, &hi8435_sensing_mode),
{},
};

View File

@ -522,12 +522,11 @@ static int imx7d_adc_probe(struct platform_device *pdev)
imx7d_adc_feature_config(info);
ret = imx7d_adc_enable(&indio_dev->dev);
ret = imx7d_adc_enable(dev);
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, __imx7d_adc_disable,
&indio_dev->dev);
ret = devm_add_action_or_reset(dev, __imx7d_adc_disable, dev);
if (ret)
return ret;

View File

@ -550,7 +550,7 @@ static ssize_t ina2xx_allow_async_readout_store(struct device *dev,
bool val;
int ret;
ret = strtobool((const char *) buf, &val);
ret = strtobool(buf, &val);
if (ret)
return ret;
@ -842,15 +842,13 @@ static int ina2xx_buffer_enable(struct iio_dev *indio_dev)
dev_dbg(&indio_dev->dev, "Async readout mode: %d\n",
chip->allow_async_readout);
task = kthread_create(ina2xx_capture_thread, (void *)indio_dev,
"%s:%d-%uus", indio_dev->name,
iio_device_id(indio_dev),
sampling_us);
task = kthread_run(ina2xx_capture_thread, (void *)indio_dev,
"%s:%d-%uus", indio_dev->name,
iio_device_id(indio_dev),
sampling_us);
if (IS_ERR(task))
return PTR_ERR(task);
get_task_struct(task);
wake_up_process(task);
chip->task = task;
return 0;
@ -862,7 +860,6 @@ static int ina2xx_buffer_disable(struct iio_dev *indio_dev)
if (chip->task) {
kthread_stop(chip->task);
put_task_struct(chip->task);
chip->task = NULL;
}
@ -974,7 +971,7 @@ static int ina2xx_probe(struct i2c_client *client,
}
if (client->dev.of_node)
type = (enum ina2xx_ids)of_device_get_match_data(&client->dev);
type = (uintptr_t)of_device_get_match_data(&client->dev);
else
type = id->driver_data;
chip->config = &ina2xx_config[type];

View File

@ -157,9 +157,6 @@ static int lpc18xx_adc_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(adc->clk),
"error getting clock\n");
rate = clk_get_rate(adc->clk);
clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET);
adc->vref = devm_regulator_get(&pdev->dev, "vref");
if (IS_ERR(adc->vref))
return dev_err_probe(&pdev->dev, PTR_ERR(adc->vref),
@ -192,6 +189,9 @@ static int lpc18xx_adc_probe(struct platform_device *pdev)
if (ret)
return ret;
rate = clk_get_rate(adc->clk);
clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET);
adc->cr_reg = (clkdiv << LPC18XX_ADC_CR_CLKDIV_SHIFT) |
LPC18XX_ADC_CR_PDN;
writel(adc->cr_reg, adc->base + LPC18XX_ADC_CR);

View File

@ -22,7 +22,8 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
#define DRIVER_NAME "max9611"
@ -513,11 +514,9 @@ static int max9611_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const char * const shunt_res_prop = "shunt-resistor-micro-ohms";
const struct device_node *of_node = client->dev.of_node;
const struct of_device_id *of_id =
of_match_device(max9611_of_table, &client->dev);
struct max9611_dev *max9611;
struct iio_dev *indio_dev;
struct device *dev = &client->dev;
unsigned int of_shunt;
int ret;
@ -528,15 +527,14 @@ static int max9611_probe(struct i2c_client *client,
i2c_set_clientdata(client, indio_dev);
max9611 = iio_priv(indio_dev);
max9611->dev = &client->dev;
max9611->dev = dev;
max9611->i2c_client = client;
mutex_init(&max9611->lock);
ret = of_property_read_u32(of_node, shunt_res_prop, &of_shunt);
ret = device_property_read_u32(dev, shunt_res_prop, &of_shunt);
if (ret) {
dev_err(&client->dev,
"Missing %s property for %pOF node\n",
shunt_res_prop, of_node);
dev_err(dev, "Missing %s property for %pfw node\n",
shunt_res_prop, dev_fwnode(dev));
return ret;
}
max9611->shunt_resistor_uohm = of_shunt;
@ -545,13 +543,13 @@ static int max9611_probe(struct i2c_client *client,
if (ret)
return ret;
indio_dev->name = of_id->data;
indio_dev->name = device_get_match_data(dev);
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &indio_info;
indio_dev->channels = max9611_channels;
indio_dev->num_channels = ARRAY_SIZE(max9611_channels);
return devm_iio_device_register(&client->dev, indio_dev);
return devm_iio_device_register(dev, indio_dev);
}
static struct i2c_driver max9611_driver = {

View File

@ -10,6 +10,8 @@
#include <linux/err.h>
#include <linux/iio/iio.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
@ -200,12 +202,13 @@ static const struct iio_info mcp3911_info = {
.write_raw = mcp3911_write_raw,
};
static int mcp3911_config(struct mcp3911 *adc, struct device_node *of_node)
static int mcp3911_config(struct mcp3911 *adc)
{
struct device *dev = &adc->spi->dev;
u32 configreg;
int ret;
of_property_read_u32(of_node, "device-addr", &adc->dev_addr);
device_property_read_u32(dev, "device-addr", &adc->dev_addr);
if (adc->dev_addr > 3) {
dev_err(&adc->spi->dev,
"invalid device address (%i). Must be in range 0-3.\n",
@ -289,7 +292,7 @@ static int mcp3911_probe(struct spi_device *spi)
}
}
ret = mcp3911_config(adc, spi->dev.of_node);
ret = mcp3911_config(adc);
if (ret)
goto clk_disable;

View File

@ -511,8 +511,7 @@ static int rcar_gyroadc_probe(struct platform_device *pdev)
if (ret)
return ret;
priv->model = (enum rcar_gyroadc_model)
of_device_get_match_data(&pdev->dev);
priv->model = (uintptr_t)of_device_get_match_data(&pdev->dev);
platform_set_drvdata(pdev, indio_dev);

View File

@ -506,10 +506,8 @@ static int rzg2l_adc_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "no irq resource\n");
if (irq < 0)
return irq;
}
ret = devm_request_irq(dev, irq, rzg2l_adc_isr,
0, dev_name(dev), adc);

View File

@ -2025,7 +2025,8 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
if (strlen(name) >= STM32_ADC_CH_SZ) {
dev_err(&indio_dev->dev, "Label %s exceeds %d characters\n",
name, STM32_ADC_CH_SZ);
return -EINVAL;
ret = -EINVAL;
goto err;
}
strncpy(adc->chan_name[val], name, STM32_ADC_CH_SZ);
ret = stm32_adc_populate_int_ch(indio_dev, name, val);

View File

@ -256,6 +256,7 @@ static int stmpe_adc_probe(struct platform_device *pdev)
struct stmpe_adc *info;
struct device_node *np;
u32 norequest_mask = 0;
unsigned long bits;
int irq_temp, irq_adc;
int num_chan = 0;
int i = 0;
@ -309,8 +310,8 @@ static int stmpe_adc_probe(struct platform_device *pdev)
of_property_read_u32(np, "st,norequest-mask", &norequest_mask);
for_each_clear_bit(i, (unsigned long *) &norequest_mask,
(STMPE_ADC_LAST_NR + 1)) {
bits = norequest_mask;
for_each_clear_bit(i, &bits, (STMPE_ADC_LAST_NR + 1)) {
stmpe_adc_voltage_chan(&info->stmpe_adc_iio_channels[num_chan], i);
num_chan++;
}

View File

@ -19,6 +19,7 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
@ -156,13 +157,16 @@ static int adc081c_probe(struct i2c_client *client,
{
struct iio_dev *iio;
struct adc081c *adc;
struct adcxx1c_model *model;
const struct adcxx1c_model *model;
int err;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
return -EOPNOTSUPP;
model = &adcxx1c_models[id->driver_data];
if (dev_fwnode(&client->dev))
model = device_get_match_data(&client->dev);
else
model = &adcxx1c_models[id->driver_data];
iio = devm_iio_device_alloc(&client->dev, sizeof(*adc));
if (!iio)
@ -210,10 +214,17 @@ static const struct i2c_device_id adc081c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, adc081c_id);
static const struct acpi_device_id adc081c_acpi_match[] = {
/* Used on some AAEON boards */
{ "ADC081C", (kernel_ulong_t)&adcxx1c_models[ADC081C] },
{ }
};
MODULE_DEVICE_TABLE(acpi, adc081c_acpi_match);
static const struct of_device_id adc081c_of_match[] = {
{ .compatible = "ti,adc081c" },
{ .compatible = "ti,adc101c" },
{ .compatible = "ti,adc121c" },
{ .compatible = "ti,adc081c", .data = &adcxx1c_models[ADC081C] },
{ .compatible = "ti,adc101c", .data = &adcxx1c_models[ADC101C] },
{ .compatible = "ti,adc121c", .data = &adcxx1c_models[ADC121C] },
{ }
};
MODULE_DEVICE_TABLE(of, adc081c_of_match);
@ -222,6 +233,7 @@ static struct i2c_driver adc081c_driver = {
.driver = {
.name = "adc081c",
.of_match_table = adc081c_of_match,
.acpi_match_table = adc081c_acpi_match,
},
.probe = adc081c_probe,
.id_table = adc081c_id,

View File

@ -11,6 +11,7 @@
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/clk.h>
#include <linux/property.h>
#include <linux/spi/spi.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
@ -239,7 +240,8 @@ static int adc12138_read_raw(struct iio_dev *iio,
if (ret)
return ret;
*value = sign_extend32(be16_to_cpu(data) >> 3, 12);
*value = sign_extend32(be16_to_cpu(data) >> channel->scan_type.shift,
channel->scan_type.realbits - 1);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
@ -429,8 +431,8 @@ static int adc12138_probe(struct spi_device *spi)
return -EINVAL;
}
ret = of_property_read_u32(spi->dev.of_node, "ti,acquisition-time",
&adc->acquisition_time);
ret = device_property_read_u32(&spi->dev, "ti,acquisition-time",
&adc->acquisition_time);
if (ret)
adc->acquisition_time = 10;
@ -516,8 +518,6 @@ static int adc12138_remove(struct spi_device *spi)
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id adc12138_dt_ids[] = {
{ .compatible = "ti,adc12130", },
{ .compatible = "ti,adc12132", },
@ -526,8 +526,6 @@ static const struct of_device_id adc12138_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, adc12138_dt_ids);
#endif
static const struct spi_device_id adc12138_id[] = {
{ "adc12130", adc12130 },
{ "adc12132", adc12132 },
@ -539,7 +537,7 @@ MODULE_DEVICE_TABLE(spi, adc12138_id);
static struct spi_driver adc12138_driver = {
.driver = {
.name = "adc12138",
.of_match_table = of_match_ptr(adc12138_dt_ids),
.of_match_table = adc12138_dt_ids,
},
.probe = adc12138_probe,
.remove = adc12138_remove,

View File

@ -464,9 +464,7 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
mutex_lock(&data->lock);
switch (mask) {
case IIO_CHAN_INFO_RAW: {
int shift = chan->scan_type.shift;
case IIO_CHAN_INFO_RAW:
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
break;
@ -487,7 +485,8 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
goto release_direct;
}
*val = sign_extend32(*val >> shift, 15 - shift);
*val = sign_extend32(*val >> chan->scan_type.shift,
chan->scan_type.realbits - 1);
ret = ads1015_set_power_state(data, false);
if (ret < 0)
@ -497,7 +496,6 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
release_direct:
iio_device_release_direct_mode(indio_dev);
break;
}
case IIO_CHAN_INFO_SCALE:
idx = data->channel_data[chan->address].pga;
*val = ads1015_fullscale_range[idx];
@ -952,7 +950,7 @@ static int ads1015_probe(struct i2c_client *client,
indio_dev->name = ADS1015_DRV_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
chip = (enum chip_ids)device_get_match_data(&client->dev);
chip = (uintptr_t)device_get_match_data(&client->dev);
if (chip == ADSXXXX)
chip = id->driver_data;
switch (chip) {

View File

@ -8,8 +8,7 @@
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/mod_devicetable.h>
#include <linux/slab.h>
#include <linux/sysfs.h>

View File

@ -281,12 +281,10 @@ static int ads8688_write_reg_range(struct iio_dev *indio_dev,
enum ads8688_range range)
{
unsigned int tmp;
int ret;
tmp = ADS8688_PROG_REG_RANGE_CH(chan->channel);
ret = ads8688_prog_write(indio_dev, tmp, range);
return ret;
return ads8688_prog_write(indio_dev, tmp, range);
}
static int ads8688_write_raw(struct iio_dev *indio_dev,

1451
drivers/iio/adc/xilinx-ams.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -107,6 +107,7 @@ static const unsigned int XADC_ZYNQ_UNMASK_TIMEOUT = 500;
#define XADC_AXI_INT_ALARM_MASK 0x3c0f
#define XADC_FLAGS_BUFFERED BIT(0)
#define XADC_FLAGS_IRQ_OPTIONAL BIT(1)
/*
* The XADC hardware supports a samplerate of up to 1MSPS. Unfortunately it does
@ -562,7 +563,7 @@ static const struct xadc_ops xadc_7s_axi_ops = {
.get_dclk_rate = xadc_axi_get_dclk,
.update_alarm = xadc_axi_update_alarm,
.interrupt_handler = xadc_axi_interrupt_handler,
.flags = XADC_FLAGS_BUFFERED,
.flags = XADC_FLAGS_BUFFERED | XADC_FLAGS_IRQ_OPTIONAL,
.type = XADC_TYPE_S7,
};
@ -573,7 +574,7 @@ static const struct xadc_ops xadc_us_axi_ops = {
.get_dclk_rate = xadc_axi_get_dclk,
.update_alarm = xadc_axi_update_alarm,
.interrupt_handler = xadc_axi_interrupt_handler,
.flags = XADC_FLAGS_BUFFERED,
.flags = XADC_FLAGS_BUFFERED | XADC_FLAGS_IRQ_OPTIONAL,
.type = XADC_TYPE_US,
};
@ -943,7 +944,7 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
*val = 1000;
break;
}
*val2 = chan->scan_type.realbits;
*val2 = bits;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_TEMP:
/* Temp in C = (val * 503.975) / 2**bits - 273.15 */
@ -1182,7 +1183,7 @@ static const struct of_device_id xadc_of_match_table[] = {
MODULE_DEVICE_TABLE(of, xadc_of_match_table);
static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
unsigned int *conf)
unsigned int *conf, int irq)
{
struct device *dev = indio_dev->dev.parent;
struct xadc *xadc = iio_priv(indio_dev);
@ -1195,6 +1196,7 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
u32 ext_mux_chan;
u32 reg;
int ret;
int i;
*conf = 0;
@ -1273,6 +1275,14 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
}
of_node_put(chan_node);
/* No IRQ => no events */
if (irq <= 0) {
for (i = 0; i < num_channels; i++) {
channels[i].event_spec = NULL;
channels[i].num_event_specs = 0;
}
}
indio_dev->num_channels = num_channels;
indio_dev->channels = devm_krealloc(dev, channels,
sizeof(*channels) * num_channels,
@ -1307,6 +1317,7 @@ static int xadc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct of_device_id *id;
const struct xadc_ops *ops;
struct iio_dev *indio_dev;
unsigned int bipolar_mask;
unsigned int conf0;
@ -1322,9 +1333,12 @@ static int xadc_probe(struct platform_device *pdev)
if (!id)
return -EINVAL;
irq = platform_get_irq(pdev, 0);
if (irq <= 0)
return -ENXIO;
ops = id->data;
irq = platform_get_irq_optional(pdev, 0);
if (irq < 0 &&
(irq != -ENXIO || !(ops->flags & XADC_FLAGS_IRQ_OPTIONAL)))
return irq;
indio_dev = devm_iio_device_alloc(dev, sizeof(*xadc));
if (!indio_dev)
@ -1345,7 +1359,7 @@ static int xadc_probe(struct platform_device *pdev)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &xadc_info;
ret = xadc_parse_dt(indio_dev, dev->of_node, &conf0);
ret = xadc_parse_dt(indio_dev, dev->of_node, &conf0, irq);
if (ret)
return ret;
@ -1357,14 +1371,16 @@ static int xadc_probe(struct platform_device *pdev)
if (ret)
return ret;
xadc->convst_trigger = xadc_alloc_trigger(indio_dev, "convst");
if (IS_ERR(xadc->convst_trigger))
return PTR_ERR(xadc->convst_trigger);
if (irq > 0) {
xadc->convst_trigger = xadc_alloc_trigger(indio_dev, "convst");
if (IS_ERR(xadc->convst_trigger))
return PTR_ERR(xadc->convst_trigger);
xadc->samplerate_trigger = xadc_alloc_trigger(indio_dev,
"samplerate");
if (IS_ERR(xadc->samplerate_trigger))
return PTR_ERR(xadc->samplerate_trigger);
xadc->samplerate_trigger = xadc_alloc_trigger(indio_dev,
"samplerate");
if (IS_ERR(xadc->samplerate_trigger))
return PTR_ERR(xadc->samplerate_trigger);
}
}
xadc->clk = devm_clk_get(dev, NULL);
@ -1396,15 +1412,17 @@ static int xadc_probe(struct platform_device *pdev)
}
}
ret = devm_request_irq(dev, irq, xadc->ops->interrupt_handler, 0,
dev_name(dev), indio_dev);
if (ret)
return ret;
if (irq > 0) {
ret = devm_request_irq(dev, irq, xadc->ops->interrupt_handler,
0, dev_name(dev), indio_dev);
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, xadc_cancel_delayed_work,
&xadc->zynq_unmask_work);
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, xadc_cancel_delayed_work,
&xadc->zynq_unmask_work);
if (ret)
return ret;
}
ret = xadc->ops->setup(pdev, indio_dev, irq);
if (ret)

20
drivers/iio/addac/Kconfig Normal file
View File

@ -0,0 +1,20 @@
#
# ADC DAC drivers
#
# When adding new entries keep the list in alphabetical order
menu "Analog to digital and digital to analog converters"
config AD74413R
tristate "Analog Devices AD74412R/AD74413R driver"
depends on GPIOLIB && SPI
select REGMAP_SPI
select CRC8
help
Say yes here to build support for Analog Devices AD74412R/AD74413R
quad-channel software configurable input/output solution.
To compile this driver as a module, choose M here: the
module will be called ad74413r.
endmenu

View File

@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for industrial I/O ADDAC drivers
#
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AD74413R) += ad74413r.o

1475
drivers/iio/addac/ad74413r.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -192,7 +192,7 @@ static int hmc425a_probe(struct platform_device *pdev)
return -ENOMEM;
st = iio_priv(indio_dev);
st->type = (enum hmc425a_type)of_device_get_match_data(&pdev->dev);
st->type = (uintptr_t)of_device_get_match_data(&pdev->dev);
st->chip_info = &hmc425a_chip_info_tbl[st->type];
indio_dev->num_channels = st->chip_info->num_channels;

View File

@ -67,7 +67,7 @@ static int iio_dmaengine_buffer_submit_block(struct iio_dma_buffer_queue *queue,
dma_cookie_t cookie;
block->bytes_used = min(block->size, dmaengine_buffer->max_size);
block->bytes_used = rounddown(block->bytes_used,
block->bytes_used = round_down(block->bytes_used,
dmaengine_buffer->align);
desc = dmaengine_prep_slave_single(dmaengine_buffer->chan,

View File

@ -434,9 +434,6 @@ static int atlas_buffer_predisable(struct iio_dev *indio_dev)
return 0;
}
static const struct iio_trigger_ops atlas_interrupt_trigger_ops = {
};
static const struct iio_buffer_setup_ops atlas_buffer_setup_ops = {
.postenable = atlas_buffer_postenable,
.predisable = atlas_buffer_predisable,
@ -645,7 +642,6 @@ static int atlas_probe(struct i2c_client *client,
data->client = client;
data->trig = trig;
data->chip = chip;
trig->ops = &atlas_interrupt_trigger_ops;
iio_trigger_set_drvdata(trig, indio_dev);
i2c_set_clientdata(client, indio_dev);

View File

@ -242,7 +242,7 @@ static int vz89x_get_resistance_reading(struct vz89x_data *data,
struct iio_chan_spec const *chan,
int *val)
{
u8 *tmp = (u8 *) &data->buffer[chan->address];
u8 *tmp = &data->buffer[chan->address];
switch (chan->scan_type.endianness) {
case IIO_LE:

View File

@ -279,6 +279,52 @@ static int scmi_iio_get_odr_val(struct iio_dev *iio_dev, int *val, int *val2)
return 0;
}
static int scmi_iio_read_channel_data(struct iio_dev *iio_dev,
struct iio_chan_spec const *ch, int *val, int *val2)
{
struct scmi_iio_priv *sensor = iio_priv(iio_dev);
u32 sensor_config;
struct scmi_sensor_reading readings[SCMI_IIO_NUM_OF_AXIS];
int err;
sensor_config = FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
SCMI_SENS_CFG_SENSOR_ENABLE);
err = sensor->sensor_ops->config_set(
sensor->ph, sensor->sensor_info->id, sensor_config);
if (err) {
dev_err(&iio_dev->dev,
"Error in enabling sensor %s err %d",
sensor->sensor_info->name, err);
return err;
}
err = sensor->sensor_ops->reading_get_timestamped(
sensor->ph, sensor->sensor_info->id,
sensor->sensor_info->num_axis, readings);
if (err) {
dev_err(&iio_dev->dev,
"Error in reading raw attribute for sensor %s err %d",
sensor->sensor_info->name, err);
return err;
}
sensor_config = FIELD_PREP(SCMI_SENS_CFG_SENSOR_ENABLED_MASK,
SCMI_SENS_CFG_SENSOR_DISABLE);
err = sensor->sensor_ops->config_set(
sensor->ph, sensor->sensor_info->id, sensor_config);
if (err) {
dev_err(&iio_dev->dev,
"Error in disabling sensor %s err %d",
sensor->sensor_info->name, err);
return err;
}
*val = lower_32_bits(readings[ch->scan_index].value);
*val2 = upper_32_bits(readings[ch->scan_index].value);
return IIO_VAL_INT_64;
}
static int scmi_iio_read_raw(struct iio_dev *iio_dev,
struct iio_chan_spec const *ch, int *val,
int *val2, long mask)
@ -300,6 +346,14 @@ static int scmi_iio_read_raw(struct iio_dev *iio_dev,
case IIO_CHAN_INFO_SAMP_FREQ:
ret = scmi_iio_get_odr_val(iio_dev, val, val2);
return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_RAW:
ret = iio_device_claim_direct_mode(iio_dev);
if (ret)
return ret;
ret = scmi_iio_read_channel_data(iio_dev, ch, val, val2);
iio_device_release_direct_mode(iio_dev);
return ret;
default:
return -EINVAL;
}
@ -381,7 +435,8 @@ static void scmi_iio_set_data_channel(struct iio_chan_spec *iio_chan,
iio_chan->type = type;
iio_chan->modified = 1;
iio_chan->channel2 = mod;
iio_chan->info_mask_separate = BIT(IIO_CHAN_INFO_SCALE);
iio_chan->info_mask_separate =
BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_RAW);
iio_chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ);
iio_chan->info_mask_shared_by_type_available =
BIT(IIO_CHAN_INFO_SAMP_FREQ);

View File

@ -638,7 +638,7 @@ ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
struct device_attribute *attr, char *buf)
{
int i, len = 0;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct st_sensor_data *sdata = iio_priv(indio_dev);
mutex_lock(&indio_dev->mlock);
@ -660,7 +660,7 @@ ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
struct device_attribute *attr, char *buf)
{
int i, len = 0, q, r;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct st_sensor_data *sdata = iio_priv(indio_dev);
mutex_lock(&indio_dev->mlock);

View File

@ -6,6 +6,16 @@
menu "Digital to analog converters"
config AD3552R
tristate "Analog Devices AD3552R DAC driver"
depends on SPI_MASTER
help
Say yes here to build support for Analog Devices AD3552R
Digital to Analog Converter.
To compile this driver as a module, choose M here: the
module will be called ad3552r.
config AD5064
tristate "Analog Devices AD5064 and similar multi-channel DAC driver"
depends on (SPI_MASTER && I2C!=m) || I2C
@ -221,6 +231,17 @@ config AD5791
To compile this driver as a module, choose M here: the
module will be called ad5791.
config AD7293
tristate "Analog Devices AD7293 Power Amplifier Current Controller"
depends on SPI
help
Say yes here to build support for Analog Devices AD7293
Power Amplifier Current Controller with
ADC, DACs, and Temperature and Current Sensors
To compile this driver as a module, choose M here: the
module will be called ad7293.
config AD7303
tristate "Analog Devices AD7303 DAC driver"
depends on SPI
@ -329,7 +350,6 @@ config MAX517
config MAX5821
tristate "Maxim MAX5821 DAC driver"
depends on I2C
depends on OF
help
Say yes here to build support for Maxim MAX5821
10 bits DAC.

View File

@ -4,6 +4,7 @@
#
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AD3552R) += ad3552r.o
obj-$(CONFIG_AD5360) += ad5360.o
obj-$(CONFIG_AD5380) += ad5380.o
obj-$(CONFIG_AD5421) += ad5421.o
@ -25,6 +26,7 @@ obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_AD5686_SPI) += ad5686-spi.o
obj-$(CONFIG_AD5696_I2C) += ad5696-i2c.o
obj-$(CONFIG_AD7293) += ad7293.o
obj-$(CONFIG_AD7303) += ad7303.o
obj-$(CONFIG_AD8801) += ad8801.o
obj-$(CONFIG_CIO_DAC) += cio-dac.o

1138
drivers/iio/dac/ad3552r.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -377,7 +377,7 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
.shared = IIO_SEPARATE,
},
IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5064_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5064_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5064_powerdown_mode_enum),
{ },
};
@ -389,7 +389,7 @@ static const struct iio_chan_spec_ext_info ltc2617_ext_info[] = {
.shared = IIO_SEPARATE,
},
IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ltc2617_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ltc2617_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ltc2617_powerdown_mode_enum),
{ },
};

View File

@ -249,7 +249,7 @@ static const struct iio_chan_spec_ext_info ad5380_ext_info[] = {
},
IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
&ad5380_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5380_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5380_powerdown_mode_enum),
{ },
};

View File

@ -142,7 +142,7 @@ static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = {
.shared = IIO_SEPARATE,
},
IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5446_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5446_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5446_powerdown_mode_enum),
{ },
};

View File

@ -241,7 +241,7 @@ static const struct iio_chan_spec_ext_info ad5504_ext_info[] = {
},
IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
&ad5504_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5504_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5504_powerdown_mode_enum),
{ },
};

View File

@ -159,7 +159,7 @@ static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = {
},
IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
&ad5624r_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5624r_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5624r_powerdown_mode_enum),
{ },
};

View File

@ -184,7 +184,7 @@ static const struct iio_chan_spec_ext_info ad5686_ext_info[] = {
.shared = IIO_SEPARATE,
},
IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5686_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5686_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5686_powerdown_mode_enum),
{ },
};

View File

@ -13,10 +13,10 @@
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/property.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/platform_data/ad5755.h>
#define AD5755_NUM_CHANNELS 4
@ -63,6 +63,101 @@
#define AD5755_SLEW_RATE_SHIFT 3
#define AD5755_SLEW_ENABLE BIT(12)
enum ad5755_mode {
AD5755_MODE_VOLTAGE_0V_5V = 0,
AD5755_MODE_VOLTAGE_0V_10V = 1,
AD5755_MODE_VOLTAGE_PLUSMINUS_5V = 2,
AD5755_MODE_VOLTAGE_PLUSMINUS_10V = 3,
AD5755_MODE_CURRENT_4mA_20mA = 4,
AD5755_MODE_CURRENT_0mA_20mA = 5,
AD5755_MODE_CURRENT_0mA_24mA = 6,
};
enum ad5755_dc_dc_phase {
AD5755_DC_DC_PHASE_ALL_SAME_EDGE = 0,
AD5755_DC_DC_PHASE_A_B_SAME_EDGE_C_D_OPP_EDGE = 1,
AD5755_DC_DC_PHASE_A_C_SAME_EDGE_B_D_OPP_EDGE = 2,
AD5755_DC_DC_PHASE_90_DEGREE = 3,
};
enum ad5755_dc_dc_freq {
AD5755_DC_DC_FREQ_250kHZ = 0,
AD5755_DC_DC_FREQ_410kHZ = 1,
AD5755_DC_DC_FREQ_650kHZ = 2,
};
enum ad5755_dc_dc_maxv {
AD5755_DC_DC_MAXV_23V = 0,
AD5755_DC_DC_MAXV_24V5 = 1,
AD5755_DC_DC_MAXV_27V = 2,
AD5755_DC_DC_MAXV_29V5 = 3,
};
enum ad5755_slew_rate {
AD5755_SLEW_RATE_64k = 0,
AD5755_SLEW_RATE_32k = 1,
AD5755_SLEW_RATE_16k = 2,
AD5755_SLEW_RATE_8k = 3,
AD5755_SLEW_RATE_4k = 4,
AD5755_SLEW_RATE_2k = 5,
AD5755_SLEW_RATE_1k = 6,
AD5755_SLEW_RATE_500 = 7,
AD5755_SLEW_RATE_250 = 8,
AD5755_SLEW_RATE_125 = 9,
AD5755_SLEW_RATE_64 = 10,
AD5755_SLEW_RATE_32 = 11,
AD5755_SLEW_RATE_16 = 12,
AD5755_SLEW_RATE_8 = 13,
AD5755_SLEW_RATE_4 = 14,
AD5755_SLEW_RATE_0_5 = 15,
};
enum ad5755_slew_step_size {
AD5755_SLEW_STEP_SIZE_1 = 0,
AD5755_SLEW_STEP_SIZE_2 = 1,
AD5755_SLEW_STEP_SIZE_4 = 2,
AD5755_SLEW_STEP_SIZE_8 = 3,
AD5755_SLEW_STEP_SIZE_16 = 4,
AD5755_SLEW_STEP_SIZE_32 = 5,
AD5755_SLEW_STEP_SIZE_64 = 6,
AD5755_SLEW_STEP_SIZE_128 = 7,
AD5755_SLEW_STEP_SIZE_256 = 8,
};
/**
* struct ad5755_platform_data - AD5755 DAC driver platform data
* @ext_dc_dc_compenstation_resistor: Whether an external DC-DC converter
* compensation register is used.
* @dc_dc_phase: DC-DC converter phase.
* @dc_dc_freq: DC-DC converter frequency.
* @dc_dc_maxv: DC-DC maximum allowed boost voltage.
* @dac: Per DAC instance parameters.
* @dac.mode: The mode to be used for the DAC output.
* @dac.ext_current_sense_resistor: Whether an external current sense resistor
* is used.
* @dac.enable_voltage_overrange: Whether to enable 20% voltage output overrange.
* @dac.slew.enable: Whether to enable digital slew.
* @dac.slew.rate: Slew rate of the digital slew.
* @dac.slew.step_size: Slew step size of the digital slew.
**/
struct ad5755_platform_data {
bool ext_dc_dc_compenstation_resistor;
enum ad5755_dc_dc_phase dc_dc_phase;
enum ad5755_dc_dc_freq dc_dc_freq;
enum ad5755_dc_dc_maxv dc_dc_maxv;
struct {
enum ad5755_mode mode;
bool ext_current_sense_resistor;
bool enable_voltage_overrange;
struct {
bool enable;
enum ad5755_slew_rate rate;
enum ad5755_slew_step_size step_size;
} slew;
} dac[4];
};
/**
* struct ad5755_chip_info - chip specific information
* @channel_template: channel specification
@ -111,7 +206,6 @@ enum ad5755_type {
ID_AD5737,
};
#ifdef CONFIG_OF
static const int ad5755_dcdc_freq_table[][2] = {
{ 250000, AD5755_DC_DC_FREQ_250kHZ },
{ 410000, AD5755_DC_DC_FREQ_410kHZ },
@ -154,7 +248,6 @@ static const int ad5755_slew_step_table[][2] = {
{ 2, AD5755_SLEW_STEP_SIZE_2 },
{ 1, AD5755_SLEW_STEP_SIZE_1 },
};
#endif
static int ad5755_write_unlocked(struct iio_dev *indio_dev,
unsigned int reg, unsigned int val)
@ -604,30 +697,29 @@ static const struct ad5755_platform_data ad5755_default_pdata = {
},
};
#ifdef CONFIG_OF
static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev)
{
struct device_node *np = dev->of_node;
struct device_node *pp;
struct fwnode_handle *pp;
struct ad5755_platform_data *pdata;
unsigned int tmp;
unsigned int tmparray[3];
int devnr, i;
if (!dev_fwnode(dev))
return NULL;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return NULL;
pdata->ext_dc_dc_compenstation_resistor =
of_property_read_bool(np, "adi,ext-dc-dc-compenstation-resistor");
device_property_read_bool(dev, "adi,ext-dc-dc-compenstation-resistor");
if (!of_property_read_u32(np, "adi,dc-dc-phase", &tmp))
pdata->dc_dc_phase = tmp;
else
pdata->dc_dc_phase = AD5755_DC_DC_PHASE_ALL_SAME_EDGE;
pdata->dc_dc_phase = AD5755_DC_DC_PHASE_ALL_SAME_EDGE;
device_property_read_u32(dev, "adi,dc-dc-phase", &pdata->dc_dc_phase);
pdata->dc_dc_freq = AD5755_DC_DC_FREQ_410kHZ;
if (!of_property_read_u32(np, "adi,dc-dc-freq-hz", &tmp)) {
if (!device_property_read_u32(dev, "adi,dc-dc-freq-hz", &tmp)) {
for (i = 0; i < ARRAY_SIZE(ad5755_dcdc_freq_table); i++) {
if (tmp == ad5755_dcdc_freq_table[i][0]) {
pdata->dc_dc_freq = ad5755_dcdc_freq_table[i][1];
@ -641,7 +733,7 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
}
pdata->dc_dc_maxv = AD5755_DC_DC_MAXV_23V;
if (!of_property_read_u32(np, "adi,dc-dc-max-microvolt", &tmp)) {
if (!device_property_read_u32(dev, "adi,dc-dc-max-microvolt", &tmp)) {
for (i = 0; i < ARRAY_SIZE(ad5755_dcdc_maxv_table); i++) {
if (tmp == ad5755_dcdc_maxv_table[i][0]) {
pdata->dc_dc_maxv = ad5755_dcdc_maxv_table[i][1];
@ -654,25 +746,23 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
}
devnr = 0;
for_each_child_of_node(np, pp) {
device_for_each_child_node(dev, pp) {
if (devnr >= AD5755_NUM_CHANNELS) {
dev_err(dev,
"There are too many channels defined in DT\n");
goto error_out;
}
if (!of_property_read_u32(pp, "adi,mode", &tmp))
pdata->dac[devnr].mode = tmp;
else
pdata->dac[devnr].mode = AD5755_MODE_CURRENT_4mA_20mA;
pdata->dac[devnr].mode = AD5755_MODE_CURRENT_4mA_20mA;
fwnode_property_read_u32(pp, "adi,mode", &pdata->dac[devnr].mode);
pdata->dac[devnr].ext_current_sense_resistor =
of_property_read_bool(pp, "adi,ext-current-sense-resistor");
fwnode_property_read_bool(pp, "adi,ext-current-sense-resistor");
pdata->dac[devnr].enable_voltage_overrange =
of_property_read_bool(pp, "adi,enable-voltage-overrange");
fwnode_property_read_bool(pp, "adi,enable-voltage-overrange");
if (!of_property_read_u32_array(pp, "adi,slew", tmparray, 3)) {
if (!fwnode_property_read_u32_array(pp, "adi,slew", tmparray, 3)) {
pdata->dac[devnr].slew.enable = tmparray[0];
pdata->dac[devnr].slew.rate = AD5755_SLEW_RATE_64k;
@ -715,18 +805,11 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
devm_kfree(dev, pdata);
return NULL;
}
#else
static
struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
{
return NULL;
}
#endif
static int ad5755_probe(struct spi_device *spi)
{
enum ad5755_type type = spi_get_device_id(spi)->driver_data;
const struct ad5755_platform_data *pdata = dev_get_platdata(&spi->dev);
const struct ad5755_platform_data *pdata;
struct iio_dev *indio_dev;
struct ad5755_state *st;
int ret;
@ -751,13 +834,10 @@ static int ad5755_probe(struct spi_device *spi)
mutex_init(&st->lock);
if (spi->dev.of_node)
pdata = ad5755_parse_dt(&spi->dev);
else
pdata = spi->dev.platform_data;
pdata = ad5755_parse_fw(&spi->dev);
if (!pdata) {
dev_warn(&spi->dev, "no platform data? using default\n");
dev_warn(&spi->dev, "no firmware provided parameters? using default\n");
pdata = &ad5755_default_pdata;
}

View File

@ -10,9 +10,8 @@
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/gpio/consumer.h>

View File

@ -426,14 +426,6 @@ static ssize_t ad5766_write_ext(struct iio_dev *indio_dev,
.shared = _shared, \
}
#define IIO_ENUM_AVAILABLE_SHARED(_name, _shared, _e) \
{ \
.name = (_name "_available"), \
.shared = _shared, \
.read = iio_enum_available_read, \
.private = (uintptr_t)(_e), \
}
static const struct iio_chan_spec_ext_info ad5766_ext_info[] = {
_AD5766_CHAN_EXT_INFO("dither_enable", AD5766_DITHER_ENABLE,
@ -443,9 +435,8 @@ static const struct iio_chan_spec_ext_info ad5766_ext_info[] = {
_AD5766_CHAN_EXT_INFO("dither_source", AD5766_DITHER_SOURCE,
IIO_SEPARATE),
IIO_ENUM("dither_scale", IIO_SEPARATE, &ad5766_dither_scale_enum),
IIO_ENUM_AVAILABLE_SHARED("dither_scale",
IIO_SEPARATE,
&ad5766_dither_scale_enum),
IIO_ENUM_AVAILABLE("dither_scale", IIO_SEPARATE,
&ad5766_dither_scale_enum),
{}
};

View File

@ -285,7 +285,7 @@ static const struct iio_chan_spec_ext_info ad5791_ext_info[] = {
},
IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
&ad5791_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5791_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5791_powerdown_mode_enum),
{ },
};

934
drivers/iio/dac/ad7293.c Normal file
View File

@ -0,0 +1,934 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* AD7293 driver
*
* Copyright 2021 Analog Devices Inc.
*/
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/gpio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <asm/unaligned.h>
#define AD7293_R1B BIT(16)
#define AD7293_R2B BIT(17)
#define AD7293_PAGE_ADDR_MSK GENMASK(15, 8)
#define AD7293_PAGE(x) FIELD_PREP(AD7293_PAGE_ADDR_MSK, x)
/* AD7293 Register Map Common */
#define AD7293_REG_NO_OP (AD7293_R1B | AD7293_PAGE(0x0) | 0x0)
#define AD7293_REG_PAGE_SELECT (AD7293_R1B | AD7293_PAGE(0x0) | 0x1)
#define AD7293_REG_CONV_CMD (AD7293_R2B | AD7293_PAGE(0x0) | 0x2)
#define AD7293_REG_RESULT (AD7293_R1B | AD7293_PAGE(0x0) | 0x3)
#define AD7293_REG_DAC_EN (AD7293_R1B | AD7293_PAGE(0x0) | 0x4)
#define AD7293_REG_DEVICE_ID (AD7293_R2B | AD7293_PAGE(0x0) | 0xC)
#define AD7293_REG_SOFT_RESET (AD7293_R2B | AD7293_PAGE(0x0) | 0xF)
/* AD7293 Register Map Page 0x0 */
#define AD7293_REG_VIN0 (AD7293_R2B | AD7293_PAGE(0x0) | 0x10)
#define AD7293_REG_VIN1 (AD7293_R2B | AD7293_PAGE(0x0) | 0x11)
#define AD7293_REG_VIN2 (AD7293_R2B | AD7293_PAGE(0x0) | 0x12)
#define AD7293_REG_VIN3 (AD7293_R2B | AD7293_PAGE(0x0) | 0x13)
#define AD7293_REG_TSENSE_INT (AD7293_R2B | AD7293_PAGE(0x0) | 0x20)
#define AD7293_REG_TSENSE_D0 (AD7293_R2B | AD7293_PAGE(0x0) | 0x21)
#define AD7293_REG_TSENSE_D1 (AD7293_R2B | AD7293_PAGE(0x0) | 0x22)
#define AD7293_REG_ISENSE_0 (AD7293_R2B | AD7293_PAGE(0x0) | 0x28)
#define AD7293_REG_ISENSE_1 (AD7293_R2B | AD7293_PAGE(0x0) | 0x29)
#define AD7293_REG_ISENSE_2 (AD7293_R2B | AD7293_PAGE(0x0) | 0x2A)
#define AD7293_REG_ISENSE_3 (AD7293_R2B | AD7293_PAGE(0x0) | 0x2B)
#define AD7293_REG_UNI_VOUT0 (AD7293_R2B | AD7293_PAGE(0x0) | 0x30)
#define AD7293_REG_UNI_VOUT1 (AD7293_R2B | AD7293_PAGE(0x0) | 0x31)
#define AD7293_REG_UNI_VOUT2 (AD7293_R2B | AD7293_PAGE(0x0) | 0x32)
#define AD7293_REG_UNI_VOUT3 (AD7293_R2B | AD7293_PAGE(0x0) | 0x33)
#define AD7293_REG_BI_VOUT0 (AD7293_R2B | AD7293_PAGE(0x0) | 0x34)
#define AD7293_REG_BI_VOUT1 (AD7293_R2B | AD7293_PAGE(0x0) | 0x35)
#define AD7293_REG_BI_VOUT2 (AD7293_R2B | AD7293_PAGE(0x0) | 0x36)
#define AD7293_REG_BI_VOUT3 (AD7293_R2B | AD7293_PAGE(0x0) | 0x37)
/* AD7293 Register Map Page 0x2 */
#define AD7293_REG_DIGITAL_OUT_EN (AD7293_R2B | AD7293_PAGE(0x2) | 0x11)
#define AD7293_REG_DIGITAL_INOUT_FUNC (AD7293_R2B | AD7293_PAGE(0x2) | 0x12)
#define AD7293_REG_DIGITAL_FUNC_POL (AD7293_R2B | AD7293_PAGE(0x2) | 0x13)
#define AD7293_REG_GENERAL (AD7293_R2B | AD7293_PAGE(0x2) | 0x14)
#define AD7293_REG_VINX_RANGE0 (AD7293_R2B | AD7293_PAGE(0x2) | 0x15)
#define AD7293_REG_VINX_RANGE1 (AD7293_R2B | AD7293_PAGE(0x2) | 0x16)
#define AD7293_REG_VINX_DIFF_SE (AD7293_R2B | AD7293_PAGE(0x2) | 0x17)
#define AD7293_REG_VINX_FILTER (AD7293_R2B | AD7293_PAGE(0x2) | 0x18)
#define AD7293_REG_BG_EN (AD7293_R2B | AD7293_PAGE(0x2) | 0x19)
#define AD7293_REG_CONV_DELAY (AD7293_R2B | AD7293_PAGE(0x2) | 0x1A)
#define AD7293_REG_TSENSE_BG_EN (AD7293_R2B | AD7293_PAGE(0x2) | 0x1B)
#define AD7293_REG_ISENSE_BG_EN (AD7293_R2B | AD7293_PAGE(0x2) | 0x1C)
#define AD7293_REG_ISENSE_GAIN (AD7293_R2B | AD7293_PAGE(0x2) | 0x1D)
#define AD7293_REG_DAC_SNOOZE_O (AD7293_R2B | AD7293_PAGE(0x2) | 0x1F)
#define AD7293_REG_DAC_SNOOZE_1 (AD7293_R2B | AD7293_PAGE(0x2) | 0x20)
#define AD7293_REG_RSX_MON_BG_EN (AD7293_R2B | AD7293_PAGE(0x2) | 0x23)
#define AD7293_REG_INTEGR_CL (AD7293_R2B | AD7293_PAGE(0x2) | 0x28)
#define AD7293_REG_PA_ON_CTRL (AD7293_R2B | AD7293_PAGE(0x2) | 0x29)
#define AD7293_REG_RAMP_TIME_0 (AD7293_R2B | AD7293_PAGE(0x2) | 0x2A)
#define AD7293_REG_RAMP_TIME_1 (AD7293_R2B | AD7293_PAGE(0x2) | 0x2B)
#define AD7293_REG_RAMP_TIME_2 (AD7293_R2B | AD7293_PAGE(0x2) | 0x2C)
#define AD7293_REG_RAMP_TIME_3 (AD7293_R2B | AD7293_PAGE(0x2) | 0x2D)
#define AD7293_REG_CL_FR_IT (AD7293_R2B | AD7293_PAGE(0x2) | 0x2E)
#define AD7293_REG_INTX_AVSS_AVDD (AD7293_R2B | AD7293_PAGE(0x2) | 0x2F)
/* AD7293 Register Map Page 0x3 */
#define AD7293_REG_VINX_SEQ (AD7293_R2B | AD7293_PAGE(0x3) | 0x10)
#define AD7293_REG_ISENSEX_TSENSEX_SEQ (AD7293_R2B | AD7293_PAGE(0x3) | 0x11)
#define AD7293_REG_RSX_MON_BI_VOUTX_SEQ (AD7293_R2B | AD7293_PAGE(0x3) | 0x12)
/* AD7293 Register Map Page 0xE */
#define AD7293_REG_VIN0_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x10)
#define AD7293_REG_VIN1_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x11)
#define AD7293_REG_VIN2_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x12)
#define AD7293_REG_VIN3_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x13)
#define AD7293_REG_TSENSE_INT_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x20)
#define AD7293_REG_TSENSE_D0_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x21)
#define AD7293_REG_TSENSE_D1_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x22)
#define AD7293_REG_ISENSE0_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x28)
#define AD7293_REG_ISENSE1_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x29)
#define AD7293_REG_ISENSE2_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x2A)
#define AD7293_REG_ISENSE3_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x2B)
#define AD7293_REG_UNI_VOUT0_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x30)
#define AD7293_REG_UNI_VOUT1_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x31)
#define AD7293_REG_UNI_VOUT2_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x32)
#define AD7293_REG_UNI_VOUT3_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x33)
#define AD7293_REG_BI_VOUT0_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x34)
#define AD7293_REG_BI_VOUT1_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x35)
#define AD7293_REG_BI_VOUT2_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x36)
#define AD7293_REG_BI_VOUT3_OFFSET (AD7293_R1B | AD7293_PAGE(0xE) | 0x37)
/* AD7293 Miscellaneous Definitions */
#define AD7293_READ BIT(7)
#define AD7293_TRANSF_LEN_MSK GENMASK(17, 16)
#define AD7293_REG_ADDR_MSK GENMASK(7, 0)
#define AD7293_REG_VOUT_OFFSET_MSK GENMASK(5, 4)
#define AD7293_REG_DATA_RAW_MSK GENMASK(15, 4)
#define AD7293_REG_VINX_RANGE_GET_CH_MSK(x, ch) (((x) >> (ch)) & 0x1)
#define AD7293_REG_VINX_RANGE_SET_CH_MSK(x, ch) (((x) & 0x1) << (ch))
#define AD7293_CHIP_ID 0x18
enum ad7293_ch_type {
AD7293_ADC_VINX,
AD7293_ADC_TSENSE,
AD7293_ADC_ISENSE,
AD7293_DAC,
};
enum ad7293_max_offset {
AD7293_TSENSE_MIN_OFFSET_CH = 4,
AD7293_ISENSE_MIN_OFFSET_CH = 7,
AD7293_VOUT_MIN_OFFSET_CH = 11,
AD7293_VOUT_MAX_OFFSET_CH = 18,
};
static const int dac_offset_table[] = {0, 1, 2};
static const int isense_gain_table[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
static const int adc_range_table[] = {0, 1, 2, 3};
struct ad7293_state {
struct spi_device *spi;
/* Protect against concurrent accesses to the device, page selection and data content */
struct mutex lock;
struct gpio_desc *gpio_reset;
struct regulator *reg_avdd;
struct regulator *reg_vdrive;
u8 page_select;
u8 data[3] ____cacheline_aligned;
};
static int ad7293_page_select(struct ad7293_state *st, unsigned int reg)
{
int ret;
if (st->page_select != FIELD_GET(AD7293_PAGE_ADDR_MSK, reg)) {
st->data[0] = FIELD_GET(AD7293_REG_ADDR_MSK, AD7293_REG_PAGE_SELECT);
st->data[1] = FIELD_GET(AD7293_PAGE_ADDR_MSK, reg);
ret = spi_write(st->spi, &st->data[0], 2);
if (ret)
return ret;
st->page_select = FIELD_GET(AD7293_PAGE_ADDR_MSK, reg);
}
return 0;
}
static int __ad7293_spi_read(struct ad7293_state *st, unsigned int reg,
u16 *val)
{
int ret;
unsigned int length;
struct spi_transfer t = {0};
length = FIELD_GET(AD7293_TRANSF_LEN_MSK, reg);
ret = ad7293_page_select(st, reg);
if (ret)
return ret;
st->data[0] = AD7293_READ | FIELD_GET(AD7293_REG_ADDR_MSK, reg);
st->data[1] = 0x0;
st->data[2] = 0x0;
t.tx_buf = &st->data[0];
t.rx_buf = &st->data[0];
t.len = length + 1;
ret = spi_sync_transfer(st->spi, &t, 1);
if (ret)
return ret;
if (length == 1)
*val = st->data[1];
else
*val = get_unaligned_be16(&st->data[1]);
return 0;
}
static int ad7293_spi_read(struct ad7293_state *st, unsigned int reg,
u16 *val)
{
int ret;
mutex_lock(&st->lock);
ret = __ad7293_spi_read(st, reg, val);
mutex_unlock(&st->lock);
return ret;
}
static int __ad7293_spi_write(struct ad7293_state *st, unsigned int reg,
u16 val)
{
int ret;
unsigned int length;
length = FIELD_GET(AD7293_TRANSF_LEN_MSK, reg);
ret = ad7293_page_select(st, reg);
if (ret)
return ret;
st->data[0] = FIELD_GET(AD7293_REG_ADDR_MSK, reg);
if (length == 1)
st->data[1] = val;
else
put_unaligned_be16(val, &st->data[1]);
return spi_write(st->spi, &st->data[0], length + 1);
}
static int ad7293_spi_write(struct ad7293_state *st, unsigned int reg,
u16 val)
{
int ret;
mutex_lock(&st->lock);
ret = __ad7293_spi_write(st, reg, val);
mutex_unlock(&st->lock);
return ret;
}
static int __ad7293_spi_update_bits(struct ad7293_state *st, unsigned int reg,
u16 mask, u16 val)
{
int ret;
u16 data, temp;
ret = __ad7293_spi_read(st, reg, &data);
if (ret)
return ret;
temp = (data & ~mask) | (val & mask);
return __ad7293_spi_write(st, reg, temp);
}
static int ad7293_spi_update_bits(struct ad7293_state *st, unsigned int reg,
u16 mask, u16 val)
{
int ret;
mutex_lock(&st->lock);
ret = __ad7293_spi_update_bits(st, reg, mask, val);
mutex_unlock(&st->lock);
return ret;
}
static int ad7293_adc_get_scale(struct ad7293_state *st, unsigned int ch,
u16 *range)
{
int ret;
u16 data;
mutex_lock(&st->lock);
ret = __ad7293_spi_read(st, AD7293_REG_VINX_RANGE1, &data);
if (ret)
goto exit;
*range = AD7293_REG_VINX_RANGE_GET_CH_MSK(data, ch);
ret = __ad7293_spi_read(st, AD7293_REG_VINX_RANGE0, &data);
if (ret)
goto exit;
*range |= AD7293_REG_VINX_RANGE_GET_CH_MSK(data, ch) << 1;
exit:
mutex_unlock(&st->lock);
return ret;
}
static int ad7293_adc_set_scale(struct ad7293_state *st, unsigned int ch,
u16 range)
{
int ret;
unsigned int ch_msk = BIT(ch);
mutex_lock(&st->lock);
ret = __ad7293_spi_update_bits(st, AD7293_REG_VINX_RANGE1, ch_msk,
AD7293_REG_VINX_RANGE_SET_CH_MSK(range, ch));
if (ret)
goto exit;
ret = __ad7293_spi_update_bits(st, AD7293_REG_VINX_RANGE0, ch_msk,
AD7293_REG_VINX_RANGE_SET_CH_MSK((range >> 1), ch));
exit:
mutex_unlock(&st->lock);
return ret;
}
static int ad7293_get_offset(struct ad7293_state *st, unsigned int ch,
u16 *offset)
{
if (ch < AD7293_TSENSE_MIN_OFFSET_CH)
return ad7293_spi_read(st, AD7293_REG_VIN0_OFFSET + ch, offset);
else if (ch < AD7293_ISENSE_MIN_OFFSET_CH)
return ad7293_spi_read(st, AD7293_REG_TSENSE_INT_OFFSET + (ch - 4), offset);
else if (ch < AD7293_VOUT_MIN_OFFSET_CH)
return ad7293_spi_read(st, AD7293_REG_ISENSE0_OFFSET + (ch - 7), offset);
else if (ch <= AD7293_VOUT_MAX_OFFSET_CH)
return ad7293_spi_read(st, AD7293_REG_UNI_VOUT0_OFFSET + (ch - 11), offset);
return -EINVAL;
}
static int ad7293_set_offset(struct ad7293_state *st, unsigned int ch,
u16 offset)
{
if (ch < AD7293_TSENSE_MIN_OFFSET_CH)
return ad7293_spi_write(st, AD7293_REG_VIN0_OFFSET + ch,
offset);
else if (ch < AD7293_ISENSE_MIN_OFFSET_CH)
return ad7293_spi_write(st,
AD7293_REG_TSENSE_INT_OFFSET +
(ch - AD7293_TSENSE_MIN_OFFSET_CH),
offset);
else if (ch < AD7293_VOUT_MIN_OFFSET_CH)
return ad7293_spi_write(st,
AD7293_REG_ISENSE0_OFFSET +
(ch - AD7293_ISENSE_MIN_OFFSET_CH),
offset);
else if (ch <= AD7293_VOUT_MAX_OFFSET_CH)
return ad7293_spi_update_bits(st,
AD7293_REG_UNI_VOUT0_OFFSET +
(ch - AD7293_VOUT_MIN_OFFSET_CH),
AD7293_REG_VOUT_OFFSET_MSK,
FIELD_PREP(AD7293_REG_VOUT_OFFSET_MSK, offset));
return -EINVAL;
}
static int ad7293_isense_set_scale(struct ad7293_state *st, unsigned int ch,
u16 gain)
{
unsigned int ch_msk = (0xf << (4 * ch));
return ad7293_spi_update_bits(st, AD7293_REG_ISENSE_GAIN, ch_msk,
gain << (4 * ch));
}
static int ad7293_isense_get_scale(struct ad7293_state *st, unsigned int ch,
u16 *gain)
{
int ret;
ret = ad7293_spi_read(st, AD7293_REG_ISENSE_GAIN, gain);
if (ret)
return ret;
*gain = (*gain >> (4 * ch)) & 0xf;
return ret;
}
static int ad7293_dac_write_raw(struct ad7293_state *st, unsigned int ch,
u16 raw)
{
int ret;
mutex_lock(&st->lock);
ret = __ad7293_spi_update_bits(st, AD7293_REG_DAC_EN, BIT(ch), BIT(ch));
if (ret)
goto exit;
ret = __ad7293_spi_write(st, AD7293_REG_UNI_VOUT0 + ch,
FIELD_PREP(AD7293_REG_DATA_RAW_MSK, raw));
exit:
mutex_unlock(&st->lock);
return ret;
}
static int ad7293_ch_read_raw(struct ad7293_state *st, enum ad7293_ch_type type,
unsigned int ch, u16 *raw)
{
int ret;
unsigned int reg_wr, reg_rd, data_wr;
switch (type) {
case AD7293_ADC_VINX:
reg_wr = AD7293_REG_VINX_SEQ;
reg_rd = AD7293_REG_VIN0 + ch;
data_wr = BIT(ch);
break;
case AD7293_ADC_TSENSE:
reg_wr = AD7293_REG_ISENSEX_TSENSEX_SEQ;
reg_rd = AD7293_REG_TSENSE_INT + ch;
data_wr = BIT(ch);
break;
case AD7293_ADC_ISENSE:
reg_wr = AD7293_REG_ISENSEX_TSENSEX_SEQ;
reg_rd = AD7293_REG_ISENSE_0 + ch;
data_wr = BIT(ch) << 8;
break;
case AD7293_DAC:
reg_rd = AD7293_REG_UNI_VOUT0 + ch;
break;
default:
return -EINVAL;
}
mutex_lock(&st->lock);
if (type != AD7293_DAC) {
if (type == AD7293_ADC_TSENSE) {
ret = __ad7293_spi_write(st, AD7293_REG_TSENSE_BG_EN,
BIT(ch));
if (ret)
goto exit;
usleep_range(9000, 9900);
} else if (type == AD7293_ADC_ISENSE) {
ret = __ad7293_spi_write(st, AD7293_REG_ISENSE_BG_EN,
BIT(ch));
if (ret)
goto exit;
usleep_range(2000, 7000);
}
ret = __ad7293_spi_write(st, reg_wr, data_wr);
if (ret)
goto exit;
ret = __ad7293_spi_write(st, AD7293_REG_CONV_CMD, 0x82);
if (ret)
goto exit;
}
ret = __ad7293_spi_read(st, reg_rd, raw);
*raw = FIELD_GET(AD7293_REG_DATA_RAW_MSK, *raw);
exit:
mutex_unlock(&st->lock);
return ret;
}
static int ad7293_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long info)
{
struct ad7293_state *st = iio_priv(indio_dev);
int ret;
u16 data;
switch (info) {
case IIO_CHAN_INFO_RAW:
switch (chan->type) {
case IIO_VOLTAGE:
if (chan->output)
ret = ad7293_ch_read_raw(st, AD7293_DAC,
chan->channel, &data);
else
ret = ad7293_ch_read_raw(st, AD7293_ADC_VINX,
chan->channel, &data);
break;
case IIO_CURRENT:
ret = ad7293_ch_read_raw(st, AD7293_ADC_ISENSE,
chan->channel, &data);
break;
case IIO_TEMP:
ret = ad7293_ch_read_raw(st, AD7293_ADC_TSENSE,
chan->channel, &data);
break;
default:
return -EINVAL;
}
if (ret)
return ret;
*val = data;
return IIO_VAL_INT;
case IIO_CHAN_INFO_OFFSET:
switch (chan->type) {
case IIO_VOLTAGE:
if (chan->output) {
ret = ad7293_get_offset(st,
chan->channel + AD7293_VOUT_MIN_OFFSET_CH,
&data);
data = FIELD_GET(AD7293_REG_VOUT_OFFSET_MSK, data);
} else {
ret = ad7293_get_offset(st, chan->channel, &data);
}
break;
case IIO_CURRENT:
ret = ad7293_get_offset(st,
chan->channel + AD7293_ISENSE_MIN_OFFSET_CH,
&data);
break;
case IIO_TEMP:
ret = ad7293_get_offset(st,
chan->channel + AD7293_TSENSE_MIN_OFFSET_CH,
&data);
break;
default:
return -EINVAL;
}
if (ret)
return ret;
*val = data;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
ret = ad7293_adc_get_scale(st, chan->channel, &data);
if (ret)
return ret;
*val = data;
return IIO_VAL_INT;
case IIO_CURRENT:
ret = ad7293_isense_get_scale(st, chan->channel, &data);
if (ret)
return ret;
*val = data;
return IIO_VAL_INT;
case IIO_TEMP:
*val = 1;
*val2 = 8;
return IIO_VAL_FRACTIONAL;
default:
return -EINVAL;
}
default:
return -EINVAL;
}
}
static int ad7293_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long info)
{
struct ad7293_state *st = iio_priv(indio_dev);
switch (info) {
case IIO_CHAN_INFO_RAW:
switch (chan->type) {
case IIO_VOLTAGE:
if (!chan->output)
return -EINVAL;
return ad7293_dac_write_raw(st, chan->channel, val);
default:
return -EINVAL;
}
case IIO_CHAN_INFO_OFFSET:
switch (chan->type) {
case IIO_VOLTAGE:
if (chan->output)
return ad7293_set_offset(st,
chan->channel +
AD7293_VOUT_MIN_OFFSET_CH,
val);
else
return ad7293_set_offset(st, chan->channel, val);
case IIO_CURRENT:
return ad7293_set_offset(st,
chan->channel +
AD7293_ISENSE_MIN_OFFSET_CH,
val);
case IIO_TEMP:
return ad7293_set_offset(st,
chan->channel +
AD7293_TSENSE_MIN_OFFSET_CH,
val);
default:
return -EINVAL;
}
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
return ad7293_adc_set_scale(st, chan->channel, val);
case IIO_CURRENT:
return ad7293_isense_set_scale(st, chan->channel, val);
default:
return -EINVAL;
}
default:
return -EINVAL;
}
}
static int ad7293_reg_access(struct iio_dev *indio_dev,
unsigned int reg,
unsigned int write_val,
unsigned int *read_val)
{
struct ad7293_state *st = iio_priv(indio_dev);
int ret;
if (read_val) {
u16 temp;
ret = ad7293_spi_read(st, reg, &temp);
*read_val = temp;
} else {
ret = ad7293_spi_write(st, reg, (u16)write_val);
}
return ret;
}
static int ad7293_read_avail(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
const int **vals, int *type, int *length,
long info)
{
switch (info) {
case IIO_CHAN_INFO_OFFSET:
*vals = dac_offset_table;
*type = IIO_VAL_INT;
*length = ARRAY_SIZE(dac_offset_table);
return IIO_AVAIL_LIST;
case IIO_CHAN_INFO_SCALE:
*type = IIO_VAL_INT;
switch (chan->type) {
case IIO_VOLTAGE:
*vals = adc_range_table;
*length = ARRAY_SIZE(adc_range_table);
return IIO_AVAIL_LIST;
case IIO_CURRENT:
*vals = isense_gain_table;
*length = ARRAY_SIZE(isense_gain_table);
return IIO_AVAIL_LIST;
default:
return -EINVAL;
}
default:
return -EINVAL;
}
}
#define AD7293_CHAN_ADC(_channel) { \
.type = IIO_VOLTAGE, \
.output = 0, \
.indexed = 1, \
.channel = _channel, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_OFFSET), \
.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE) \
}
#define AD7293_CHAN_DAC(_channel) { \
.type = IIO_VOLTAGE, \
.output = 1, \
.indexed = 1, \
.channel = _channel, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_OFFSET), \
.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_OFFSET) \
}
#define AD7293_CHAN_ISENSE(_channel) { \
.type = IIO_CURRENT, \
.output = 0, \
.indexed = 1, \
.channel = _channel, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_OFFSET) | \
BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE) \
}
#define AD7293_CHAN_TEMP(_channel) { \
.type = IIO_TEMP, \
.output = 0, \
.indexed = 1, \
.channel = _channel, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_OFFSET), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
}
static const struct iio_chan_spec ad7293_channels[] = {
AD7293_CHAN_ADC(0),
AD7293_CHAN_ADC(1),
AD7293_CHAN_ADC(2),
AD7293_CHAN_ADC(3),
AD7293_CHAN_ISENSE(0),
AD7293_CHAN_ISENSE(1),
AD7293_CHAN_ISENSE(2),
AD7293_CHAN_ISENSE(3),
AD7293_CHAN_TEMP(0),
AD7293_CHAN_TEMP(1),
AD7293_CHAN_TEMP(2),
AD7293_CHAN_DAC(0),
AD7293_CHAN_DAC(1),
AD7293_CHAN_DAC(2),
AD7293_CHAN_DAC(3),
AD7293_CHAN_DAC(4),
AD7293_CHAN_DAC(5),
AD7293_CHAN_DAC(6),
AD7293_CHAN_DAC(7)
};
static int ad7293_soft_reset(struct ad7293_state *st)
{
int ret;
ret = __ad7293_spi_write(st, AD7293_REG_SOFT_RESET, 0x7293);
if (ret)
return ret;
return __ad7293_spi_write(st, AD7293_REG_SOFT_RESET, 0x0000);
}
static int ad7293_reset(struct ad7293_state *st)
{
if (st->gpio_reset) {
gpiod_set_value(st->gpio_reset, 0);
usleep_range(100, 1000);
gpiod_set_value(st->gpio_reset, 1);
usleep_range(100, 1000);
return 0;
}
/* Perform a software reset */
return ad7293_soft_reset(st);
}
static int ad7293_properties_parse(struct ad7293_state *st)
{
struct spi_device *spi = st->spi;
st->gpio_reset = devm_gpiod_get_optional(&st->spi->dev, "reset",
GPIOD_OUT_HIGH);
if (IS_ERR(st->gpio_reset))
return dev_err_probe(&spi->dev, PTR_ERR(st->gpio_reset),
"failed to get the reset GPIO\n");
st->reg_avdd = devm_regulator_get(&spi->dev, "avdd");
if (IS_ERR(st->reg_avdd))
return dev_err_probe(&spi->dev, PTR_ERR(st->reg_avdd),
"failed to get the AVDD voltage\n");
st->reg_vdrive = devm_regulator_get(&spi->dev, "vdrive");
if (IS_ERR(st->reg_vdrive))
return dev_err_probe(&spi->dev, PTR_ERR(st->reg_vdrive),
"failed to get the VDRIVE voltage\n");
return 0;
}
static void ad7293_reg_disable(void *data)
{
regulator_disable(data);
}
static int ad7293_init(struct ad7293_state *st)
{
int ret;
u16 chip_id;
struct spi_device *spi = st->spi;
ret = ad7293_properties_parse(st);
if (ret)
return ret;
ret = ad7293_reset(st);
if (ret)
return ret;
ret = regulator_enable(st->reg_avdd);
if (ret) {
dev_err(&spi->dev,
"Failed to enable specified AVDD Voltage!\n");
return ret;
}
ret = devm_add_action_or_reset(&spi->dev, ad7293_reg_disable,
st->reg_avdd);
if (ret)
return ret;
ret = regulator_enable(st->reg_vdrive);
if (ret) {
dev_err(&spi->dev,
"Failed to enable specified VDRIVE Voltage!\n");
return ret;
}
ret = devm_add_action_or_reset(&spi->dev, ad7293_reg_disable,
st->reg_vdrive);
if (ret)
return ret;
ret = regulator_get_voltage(st->reg_avdd);
if (ret < 0) {
dev_err(&spi->dev, "Failed to read avdd regulator: %d\n", ret);
return ret;
}
if (ret > 5500000 || ret < 4500000)
return -EINVAL;
ret = regulator_get_voltage(st->reg_vdrive);
if (ret < 0) {
dev_err(&spi->dev,
"Failed to read vdrive regulator: %d\n", ret);
return ret;
}
if (ret > 5500000 || ret < 1700000)
return -EINVAL;
/* Check Chip ID */
ret = __ad7293_spi_read(st, AD7293_REG_DEVICE_ID, &chip_id);
if (ret)
return ret;
if (chip_id != AD7293_CHIP_ID) {
dev_err(&spi->dev, "Invalid Chip ID.\n");
return -EINVAL;
}
return 0;
}
static const struct iio_info ad7293_info = {
.read_raw = ad7293_read_raw,
.write_raw = ad7293_write_raw,
.read_avail = &ad7293_read_avail,
.debugfs_reg_access = &ad7293_reg_access,
};
static int ad7293_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct ad7293_state *st;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
indio_dev->info = &ad7293_info;
indio_dev->name = "ad7293";
indio_dev->channels = ad7293_channels;
indio_dev->num_channels = ARRAY_SIZE(ad7293_channels);
st->spi = spi;
st->page_select = 0;
mutex_init(&st->lock);
ret = ad7293_init(st);
if (ret)
return ret;
return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id ad7293_id[] = {
{ "ad7293", 0 },
{}
};
MODULE_DEVICE_TABLE(spi, ad7293_id);
static const struct of_device_id ad7293_of_match[] = {
{ .compatible = "adi,ad7293" },
{}
};
MODULE_DEVICE_TABLE(of, ad7293_of_match);
static struct spi_driver ad7293_driver = {
.driver = {
.name = "ad7293",
.of_match_table = ad7293_of_match,
},
.probe = ad7293_probe,
.id_table = ad7293_id,
};
module_spi_driver(ad7293_driver);
MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com");
MODULE_DESCRIPTION("Analog Devices AD7293");
MODULE_LICENSE("GPL v2");

View File

@ -30,7 +30,7 @@
#include <linux/iio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>

View File

@ -16,9 +16,8 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>

View File

@ -137,7 +137,7 @@ static const struct iio_chan_spec_ext_info max5821_ext_info[] = {
.shared = IIO_SEPARATE,
},
IIO_ENUM("powerdown_mode", IIO_SEPARATE, &max5821_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &max5821_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &max5821_powerdown_mode_enum),
{ },
};

View File

@ -221,8 +221,8 @@ static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = {
},
IIO_ENUM("powerdown_mode", IIO_SEPARATE,
&mcp472x_powerdown_mode_enum[MCP4725]),
IIO_ENUM_AVAILABLE("powerdown_mode",
&mcp472x_powerdown_mode_enum[MCP4725]),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE,
&mcp472x_powerdown_mode_enum[MCP4725]),
{ },
};
@ -235,8 +235,8 @@ static const struct iio_chan_spec_ext_info mcp4726_ext_info[] = {
},
IIO_ENUM("powerdown_mode", IIO_SEPARATE,
&mcp472x_powerdown_mode_enum[MCP4726]),
IIO_ENUM_AVAILABLE("powerdown_mode",
&mcp472x_powerdown_mode_enum[MCP4726]),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE,
&mcp472x_powerdown_mode_enum[MCP4726]),
{ },
};
@ -386,7 +386,7 @@ static int mcp4725_probe(struct i2c_client *client,
i2c_set_clientdata(client, indio_dev);
data->client = client;
if (dev_fwnode(&client->dev))
data->id = (enum chip_id)device_get_match_data(&client->dev);
data->id = (uintptr_t)device_get_match_data(&client->dev);
else
data->id = id->driver_data;
pdata = dev_get_platdata(&client->dev);

View File

@ -246,7 +246,7 @@ static const struct iio_chan_spec_ext_info stm32_dac_ext_info[] = {
.shared = IIO_SEPARATE,
},
IIO_ENUM("powerdown_mode", IIO_SEPARATE, &stm32_dac_powerdown_mode_en),
IIO_ENUM_AVAILABLE("powerdown_mode", &stm32_dac_powerdown_mode_en),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &stm32_dac_powerdown_mode_en),
{},
};

View File

@ -160,7 +160,7 @@ static const struct iio_chan_spec_ext_info ti_dac_ext_info[] = {
.shared = IIO_SHARED_BY_TYPE,
},
IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, &ti_dac_powerdown_mode),
IIO_ENUM_AVAILABLE("powerdown_mode", &ti_dac_powerdown_mode),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ti_dac_powerdown_mode),
{ },
};

View File

@ -212,7 +212,7 @@ static const struct iio_chan_spec_ext_info dac5571_ext_info[] = {
.shared = IIO_SEPARATE,
},
IIO_ENUM("powerdown_mode", IIO_SEPARATE, &dac5571_powerdown_mode),
IIO_ENUM_AVAILABLE("powerdown_mode", &dac5571_powerdown_mode),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &dac5571_powerdown_mode),
{},
};

View File

@ -146,7 +146,7 @@ static const struct iio_chan_spec_ext_info ti_dac_ext_info[] = {
.shared = IIO_SHARED_BY_TYPE,
},
IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, &ti_dac_powerdown_mode),
IIO_ENUM_AVAILABLE("powerdown_mode", &ti_dac_powerdown_mode),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ti_dac_powerdown_mode),
{ },
};

View File

@ -45,7 +45,6 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
int len = 0;
u16 *data;
data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
@ -79,7 +78,6 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
indio_dev->masklength, j);
/* random access read from the 'device' */
data[i] = fakedata[j];
len += 2;
}
}

View File

@ -0,0 +1,18 @@
#
# Filter drivers
#
# When adding new entries keep the list in alphabetical order
menu "Filters"
config ADMV8818
tristate "Analog Devices ADMV8818 High-Pass and Low-Pass Filter"
depends on SPI && COMMON_CLK && 64BIT
help
Say yes here to build support for Analog Devices ADMV8818
2 GHz to 18 GHz, Digitally Tunable, High-Pass and Low-Pass Filter.
To compile this driver as a module, choose M here: the
modiule will be called admv8818.
endmenu

View File

@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for industrial I/O Filter drivers
#
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ADMV8818) += admv8818.o

View File

@ -0,0 +1,665 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* ADMV8818 driver
*
* Copyright 2021 Analog Devices Inc.
*/
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/iio/iio.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/notifier.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/units.h>
/* ADMV8818 Register Map */
#define ADMV8818_REG_SPI_CONFIG_A 0x0
#define ADMV8818_REG_SPI_CONFIG_B 0x1
#define ADMV8818_REG_CHIPTYPE 0x3
#define ADMV8818_REG_PRODUCT_ID_L 0x4
#define ADMV8818_REG_PRODUCT_ID_H 0x5
#define ADMV8818_REG_FAST_LATCH_POINTER 0x10
#define ADMV8818_REG_FAST_LATCH_STOP 0x11
#define ADMV8818_REG_FAST_LATCH_START 0x12
#define ADMV8818_REG_FAST_LATCH_DIRECTION 0x13
#define ADMV8818_REG_FAST_LATCH_STATE 0x14
#define ADMV8818_REG_WR0_SW 0x20
#define ADMV8818_REG_WR0_FILTER 0x21
#define ADMV8818_REG_WR1_SW 0x22
#define ADMV8818_REG_WR1_FILTER 0x23
#define ADMV8818_REG_WR2_SW 0x24
#define ADMV8818_REG_WR2_FILTER 0x25
#define ADMV8818_REG_WR3_SW 0x26
#define ADMV8818_REG_WR3_FILTER 0x27
#define ADMV8818_REG_WR4_SW 0x28
#define ADMV8818_REG_WR4_FILTER 0x29
#define ADMV8818_REG_LUT0_SW 0x100
#define ADMV8818_REG_LUT0_FILTER 0x101
#define ADMV8818_REG_LUT127_SW 0x1FE
#define ADMV8818_REG_LUT127_FILTER 0x1FF
/* ADMV8818_REG_SPI_CONFIG_A Map */
#define ADMV8818_SOFTRESET_N_MSK BIT(7)
#define ADMV8818_LSB_FIRST_N_MSK BIT(6)
#define ADMV8818_ENDIAN_N_MSK BIT(5)
#define ADMV8818_SDOACTIVE_N_MSK BIT(4)
#define ADMV8818_SDOACTIVE_MSK BIT(3)
#define ADMV8818_ENDIAN_MSK BIT(2)
#define ADMV8818_LSBFIRST_MSK BIT(1)
#define ADMV8818_SOFTRESET_MSK BIT(0)
/* ADMV8818_REG_SPI_CONFIG_B Map */
#define ADMV8818_SINGLE_INSTRUCTION_MSK BIT(7)
#define ADMV8818_CSB_STALL_MSK BIT(6)
#define ADMV8818_MASTER_SLAVE_RB_MSK BIT(5)
#define ADMV8818_MASTER_SLAVE_TRANSFER_MSK BIT(0)
/* ADMV8818_REG_WR0_SW Map */
#define ADMV8818_SW_IN_SET_WR0_MSK BIT(7)
#define ADMV8818_SW_OUT_SET_WR0_MSK BIT(6)
#define ADMV8818_SW_IN_WR0_MSK GENMASK(5, 3)
#define ADMV8818_SW_OUT_WR0_MSK GENMASK(2, 0)
/* ADMV8818_REG_WR0_FILTER Map */
#define ADMV8818_HPF_WR0_MSK GENMASK(7, 4)
#define ADMV8818_LPF_WR0_MSK GENMASK(3, 0)
enum {
ADMV8818_BW_FREQ,
ADMV8818_CENTER_FREQ
};
enum {
ADMV8818_AUTO_MODE,
ADMV8818_MANUAL_MODE,
};
struct admv8818_state {
struct spi_device *spi;
struct regmap *regmap;
struct clk *clkin;
struct notifier_block nb;
/* Protect against concurrent accesses to the device and data content*/
struct mutex lock;
unsigned int filter_mode;
u64 cf_hz;
};
static const unsigned long long freq_range_hpf[4][2] = {
{1750000000ULL, 3550000000ULL},
{3400000000ULL, 7250000000ULL},
{6600000000, 12000000000},
{12500000000, 19900000000}
};
static const unsigned long long freq_range_lpf[4][2] = {
{2050000000ULL, 3850000000ULL},
{3350000000ULL, 7250000000ULL},
{7000000000, 13000000000},
{12550000000, 18500000000}
};
static const struct regmap_config admv8818_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.read_flag_mask = 0x80,
.max_register = 0x1FF,
};
static const char * const admv8818_modes[] = {
[0] = "auto",
[1] = "manual"
};
static int __admv8818_hpf_select(struct admv8818_state *st, u64 freq)
{
unsigned int hpf_step = 0, hpf_band = 0, i, j;
u64 freq_step;
int ret;
if (freq < freq_range_hpf[0][0])
goto hpf_write;
if (freq > freq_range_hpf[3][1]) {
hpf_step = 15;
hpf_band = 4;
goto hpf_write;
}
for (i = 0; i < 4; i++) {
freq_step = div_u64((freq_range_hpf[i][1] -
freq_range_hpf[i][0]), 15);
if (freq > freq_range_hpf[i][0] &&
(freq < freq_range_hpf[i][1] + freq_step)) {
hpf_band = i + 1;
for (j = 1; j <= 16; j++) {
if (freq < (freq_range_hpf[i][0] + (freq_step * j))) {
hpf_step = j - 1;
break;
}
}
break;
}
}
/* Close HPF frequency gap between 12 and 12.5 GHz */
if (freq >= 12000 * HZ_PER_MHZ && freq <= 12500 * HZ_PER_MHZ) {
hpf_band = 3;
hpf_step = 15;
}
hpf_write:
ret = regmap_update_bits(st->regmap, ADMV8818_REG_WR0_SW,
ADMV8818_SW_IN_SET_WR0_MSK |
ADMV8818_SW_IN_WR0_MSK,
FIELD_PREP(ADMV8818_SW_IN_SET_WR0_MSK, 1) |
FIELD_PREP(ADMV8818_SW_IN_WR0_MSK, hpf_band));
if (ret)
return ret;
return regmap_update_bits(st->regmap, ADMV8818_REG_WR0_FILTER,
ADMV8818_HPF_WR0_MSK,
FIELD_PREP(ADMV8818_HPF_WR0_MSK, hpf_step));
}
static int admv8818_hpf_select(struct admv8818_state *st, u64 freq)
{
int ret;
mutex_lock(&st->lock);
ret = __admv8818_hpf_select(st, freq);
mutex_unlock(&st->lock);
return ret;
}
static int __admv8818_lpf_select(struct admv8818_state *st, u64 freq)
{
unsigned int lpf_step = 0, lpf_band = 0, i, j;
u64 freq_step;
int ret;
if (freq > freq_range_lpf[3][1])
goto lpf_write;
if (freq < freq_range_lpf[0][0]) {
lpf_band = 1;
goto lpf_write;
}
for (i = 0; i < 4; i++) {
if (freq > freq_range_lpf[i][0] && freq < freq_range_lpf[i][1]) {
lpf_band = i + 1;
freq_step = div_u64((freq_range_lpf[i][1] - freq_range_lpf[i][0]), 15);
for (j = 0; j <= 15; j++) {
if (freq < (freq_range_lpf[i][0] + (freq_step * j))) {
lpf_step = j;
break;
}
}
break;
}
}
lpf_write:
ret = regmap_update_bits(st->regmap, ADMV8818_REG_WR0_SW,
ADMV8818_SW_OUT_SET_WR0_MSK |
ADMV8818_SW_OUT_WR0_MSK,
FIELD_PREP(ADMV8818_SW_OUT_SET_WR0_MSK, 1) |
FIELD_PREP(ADMV8818_SW_OUT_WR0_MSK, lpf_band));
if (ret)
return ret;
return regmap_update_bits(st->regmap, ADMV8818_REG_WR0_FILTER,
ADMV8818_LPF_WR0_MSK,
FIELD_PREP(ADMV8818_LPF_WR0_MSK, lpf_step));
}
static int admv8818_lpf_select(struct admv8818_state *st, u64 freq)
{
int ret;
mutex_lock(&st->lock);
ret = __admv8818_lpf_select(st, freq);
mutex_unlock(&st->lock);
return ret;
}
static int admv8818_rfin_band_select(struct admv8818_state *st)
{
int ret;
st->cf_hz = clk_get_rate(st->clkin);
mutex_lock(&st->lock);
ret = __admv8818_hpf_select(st, st->cf_hz);
if (ret)
goto exit;
ret = __admv8818_lpf_select(st, st->cf_hz);
exit:
mutex_unlock(&st->lock);
return ret;
}
static int __admv8818_read_hpf_freq(struct admv8818_state *st, u64 *hpf_freq)
{
unsigned int data, hpf_band, hpf_state;
int ret;
ret = regmap_read(st->regmap, ADMV8818_REG_WR0_SW, &data);
if (ret)
return ret;
hpf_band = FIELD_GET(ADMV8818_SW_IN_WR0_MSK, data);
if (!hpf_band) {
*hpf_freq = 0;
return ret;
}
ret = regmap_read(st->regmap, ADMV8818_REG_WR0_FILTER, &data);
if (ret)
return ret;
hpf_state = FIELD_GET(ADMV8818_HPF_WR0_MSK, data);
*hpf_freq = div_u64(freq_range_hpf[hpf_band - 1][1] - freq_range_hpf[hpf_band - 1][0], 15);
*hpf_freq = freq_range_hpf[hpf_band - 1][0] + (*hpf_freq * hpf_state);
return ret;
}
static int admv8818_read_hpf_freq(struct admv8818_state *st, u64 *hpf_freq)
{
int ret;
mutex_lock(&st->lock);
ret = __admv8818_read_hpf_freq(st, hpf_freq);
mutex_unlock(&st->lock);
return ret;
}
static int __admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq)
{
unsigned int data, lpf_band, lpf_state;
int ret;
ret = regmap_read(st->regmap, ADMV8818_REG_WR0_SW, &data);
if (ret)
return ret;
lpf_band = FIELD_GET(ADMV8818_SW_OUT_WR0_MSK, data);
if (!lpf_band) {
*lpf_freq = 0;
return ret;
}
ret = regmap_read(st->regmap, ADMV8818_REG_WR0_FILTER, &data);
if (ret)
return ret;
lpf_state = FIELD_GET(ADMV8818_LPF_WR0_MSK, data);
*lpf_freq = div_u64(freq_range_lpf[lpf_band - 1][1] - freq_range_lpf[lpf_band - 1][0], 15);
*lpf_freq = freq_range_lpf[lpf_band - 1][0] + (*lpf_freq * lpf_state);
return ret;
}
static int admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq)
{
int ret;
mutex_lock(&st->lock);
ret = __admv8818_read_lpf_freq(st, lpf_freq);
mutex_unlock(&st->lock);
return ret;
}
static int admv8818_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long info)
{
struct admv8818_state *st = iio_priv(indio_dev);
u64 freq = ((u64)val2 << 32 | (u32)val);
switch (info) {
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
return admv8818_lpf_select(st, freq);
case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
return admv8818_hpf_select(st, freq);
default:
return -EINVAL;
}
}
static int admv8818_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long info)
{
struct admv8818_state *st = iio_priv(indio_dev);
int ret;
u64 freq;
switch (info) {
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
ret = admv8818_read_lpf_freq(st, &freq);
if (ret)
return ret;
*val = (u32)freq;
*val2 = (u32)(freq >> 32);
return IIO_VAL_INT_64;
case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
ret = admv8818_read_hpf_freq(st, &freq);
if (ret)
return ret;
*val = (u32)freq;
*val2 = (u32)(freq >> 32);
return IIO_VAL_INT_64;
default:
return -EINVAL;
}
}
static int admv8818_reg_access(struct iio_dev *indio_dev,
unsigned int reg,
unsigned int write_val,
unsigned int *read_val)
{
struct admv8818_state *st = iio_priv(indio_dev);
if (read_val)
return regmap_read(st->regmap, reg, read_val);
else
return regmap_write(st->regmap, reg, write_val);
}
static int admv8818_get_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct admv8818_state *st = iio_priv(indio_dev);
return st->filter_mode;
}
static int admv8818_set_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
unsigned int mode)
{
struct admv8818_state *st = iio_priv(indio_dev);
int ret = 0;
if (!st->clkin) {
if (mode == ADMV8818_MANUAL_MODE)
return 0;
return -EINVAL;
}
switch (mode) {
case ADMV8818_AUTO_MODE:
if (!st->filter_mode)
return 0;
ret = clk_prepare_enable(st->clkin);
if (ret)
return ret;
ret = clk_notifier_register(st->clkin, &st->nb);
if (ret) {
clk_disable_unprepare(st->clkin);
return ret;
}
break;
case ADMV8818_MANUAL_MODE:
if (st->filter_mode)
return 0;
clk_disable_unprepare(st->clkin);
ret = clk_notifier_unregister(st->clkin, &st->nb);
if (ret)
return ret;
break;
default:
return -EINVAL;
}
st->filter_mode = mode;
return ret;
}
static const struct iio_info admv8818_info = {
.write_raw = admv8818_write_raw,
.read_raw = admv8818_read_raw,
.debugfs_reg_access = &admv8818_reg_access,
};
static const struct iio_enum admv8818_mode_enum = {
.items = admv8818_modes,
.num_items = ARRAY_SIZE(admv8818_modes),
.get = admv8818_get_mode,
.set = admv8818_set_mode,
};
static const struct iio_chan_spec_ext_info admv8818_ext_info[] = {
IIO_ENUM("filter_mode", IIO_SHARED_BY_ALL, &admv8818_mode_enum),
IIO_ENUM_AVAILABLE("filter_mode", IIO_SHARED_BY_ALL, &admv8818_mode_enum),
{ },
};
#define ADMV8818_CHAN(_channel) { \
.type = IIO_ALTVOLTAGE, \
.output = 1, \
.indexed = 1, \
.channel = _channel, \
.info_mask_separate = \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \
BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY) \
}
#define ADMV8818_CHAN_BW_CF(_channel, _admv8818_ext_info) { \
.type = IIO_ALTVOLTAGE, \
.output = 1, \
.indexed = 1, \
.channel = _channel, \
.ext_info = _admv8818_ext_info, \
}
static const struct iio_chan_spec admv8818_channels[] = {
ADMV8818_CHAN(0),
ADMV8818_CHAN_BW_CF(0, admv8818_ext_info),
};
static int admv8818_freq_change(struct notifier_block *nb, unsigned long action, void *data)
{
struct admv8818_state *st = container_of(nb, struct admv8818_state, nb);
if (action == POST_RATE_CHANGE)
return notifier_from_errno(admv8818_rfin_band_select(st));
return NOTIFY_OK;
}
static void admv8818_clk_notifier_unreg(void *data)
{
struct admv8818_state *st = data;
if (st->filter_mode == 0)
clk_notifier_unregister(st->clkin, &st->nb);
}
static void admv8818_clk_disable(void *data)
{
struct admv8818_state *st = data;
if (st->filter_mode == 0)
clk_disable_unprepare(st->clkin);
}
static int admv8818_init(struct admv8818_state *st)
{
int ret;
struct spi_device *spi = st->spi;
unsigned int chip_id;
ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
ADMV8818_SOFTRESET_N_MSK |
ADMV8818_SOFTRESET_MSK,
FIELD_PREP(ADMV8818_SOFTRESET_N_MSK, 1) |
FIELD_PREP(ADMV8818_SOFTRESET_MSK, 1));
if (ret) {
dev_err(&spi->dev, "ADMV8818 Soft Reset failed.\n");
return ret;
}
ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
ADMV8818_SDOACTIVE_N_MSK |
ADMV8818_SDOACTIVE_MSK,
FIELD_PREP(ADMV8818_SDOACTIVE_N_MSK, 1) |
FIELD_PREP(ADMV8818_SDOACTIVE_MSK, 1));
if (ret) {
dev_err(&spi->dev, "ADMV8818 SDO Enable failed.\n");
return ret;
}
ret = regmap_read(st->regmap, ADMV8818_REG_CHIPTYPE, &chip_id);
if (ret) {
dev_err(&spi->dev, "ADMV8818 Chip ID read failed.\n");
return ret;
}
if (chip_id != 0x1) {
dev_err(&spi->dev, "ADMV8818 Invalid Chip ID.\n");
return -EINVAL;
}
ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_B,
ADMV8818_SINGLE_INSTRUCTION_MSK,
FIELD_PREP(ADMV8818_SINGLE_INSTRUCTION_MSK, 1));
if (ret) {
dev_err(&spi->dev, "ADMV8818 Single Instruction failed.\n");
return ret;
}
if (st->clkin)
return admv8818_rfin_band_select(st);
else
return 0;
}
static int admv8818_clk_setup(struct admv8818_state *st)
{
struct spi_device *spi = st->spi;
int ret;
st->clkin = devm_clk_get_optional(&spi->dev, "rf_in");
if (IS_ERR(st->clkin))
return dev_err_probe(&spi->dev, PTR_ERR(st->clkin),
"failed to get the input clock\n");
else if (!st->clkin)
return 0;
ret = clk_prepare_enable(st->clkin);
if (ret)
return ret;
ret = devm_add_action_or_reset(&spi->dev, admv8818_clk_disable, st);
if (ret)
return ret;
st->nb.notifier_call = admv8818_freq_change;
ret = clk_notifier_register(st->clkin, &st->nb);
if (ret < 0)
return ret;
return devm_add_action_or_reset(&spi->dev, admv8818_clk_notifier_unreg, st);
}
static int admv8818_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct regmap *regmap;
struct admv8818_state *st;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
regmap = devm_regmap_init_spi(spi, &admv8818_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
st = iio_priv(indio_dev);
st->regmap = regmap;
indio_dev->info = &admv8818_info;
indio_dev->name = "admv8818";
indio_dev->channels = admv8818_channels;
indio_dev->num_channels = ARRAY_SIZE(admv8818_channels);
st->spi = spi;
ret = admv8818_clk_setup(st);
if (ret)
return ret;
mutex_init(&st->lock);
ret = admv8818_init(st);
if (ret)
return ret;
return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id admv8818_id[] = {
{ "admv8818", 0 },
{}
};
MODULE_DEVICE_TABLE(spi, admv8818_id);
static const struct of_device_id admv8818_of_match[] = {
{ .compatible = "adi,admv8818" },
{}
};
MODULE_DEVICE_TABLE(of, admv8818_of_match);
static struct spi_driver admv8818_driver = {
.driver = {
.name = "admv8818",
.of_match_table = admv8818_of_match,
},
.probe = admv8818_probe,
.id_table = admv8818_id,
};
module_spi_driver(admv8818_driver);
MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com");
MODULE_DESCRIPTION("Analog Devices ADMV8818");
MODULE_LICENSE("GPL v2");

View File

@ -345,9 +345,6 @@ err:
return IRQ_HANDLED;
}
static const struct iio_trigger_ops afe4403_trigger_ops = {
};
#define AFE4403_TIMING_PAIRS \
{ AFE440X_LED2STC, 0x000050 }, \
{ AFE440X_LED2ENDC, 0x0003e7 }, \
@ -530,8 +527,6 @@ static int afe4403_probe(struct spi_device *spi)
iio_trigger_set_drvdata(afe->trig, indio_dev);
afe->trig->ops = &afe4403_trigger_ops;
ret = iio_trigger_register(afe->trig);
if (ret) {
dev_err(afe->dev, "Unable to register IIO trigger\n");

View File

@ -347,9 +347,6 @@ err:
return IRQ_HANDLED;
}
static const struct iio_trigger_ops afe4404_trigger_ops = {
};
/* Default timings from data-sheet */
#define AFE4404_TIMING_PAIRS \
{ AFE440X_PRPCOUNT, 39999 }, \
@ -537,8 +534,6 @@ static int afe4404_probe(struct i2c_client *client,
iio_trigger_set_drvdata(afe->trig, indio_dev);
afe->trig->ops = &afe4404_trigger_ops;
ret = iio_trigger_register(afe->trig);
if (ret) {
dev_err(afe->dev, "Unable to register IIO trigger\n");

View File

@ -16,7 +16,7 @@ struct iio_buffer;
struct iio_chan_spec;
struct iio_dev;
extern struct device_type iio_device_type;
extern const struct device_type iio_device_type;
struct iio_dev_buffer_pair {
struct iio_dev *indio_dev;

View File

@ -58,7 +58,7 @@ static int inv_icm42600_probe(struct i2c_client *client)
match = device_get_match_data(&client->dev);
if (!match)
return -EINVAL;
chip = (enum inv_icm42600_chip)match;
chip = (uintptr_t)match;
regmap = devm_regmap_init_i2c(client, &inv_icm42600_regmap_config);
if (IS_ERR(regmap))

View File

@ -57,7 +57,7 @@ static int inv_icm42600_probe(struct spi_device *spi)
match = device_get_match_data(&spi->dev);
if (!match)
return -EINVAL;
chip = (enum inv_icm42600_chip)match;
chip = (uintptr_t)match;
regmap = devm_regmap_init_spi(spi, &inv_icm42600_regmap_config);
if (IS_ERR(regmap))

View File

@ -110,7 +110,7 @@ static int inv_mpu_probe(struct i2c_client *client,
match = device_get_match_data(&client->dev);
if (match) {
chip_type = (enum inv_devices)match;
chip_type = (uintptr_t)match;
name = client->name;
} else if (id) {
chip_type = (enum inv_devices)

View File

@ -45,7 +45,7 @@ static int inv_mpu_probe(struct spi_device *spi)
chip_type = (enum inv_devices)spi_id->driver_data;
name = spi_id->name;
} else if ((match = device_get_match_data(&spi->dev))) {
chip_type = (enum inv_devices)match;
chip_type = (uintptr_t)match;
name = dev_name(&spi->dev);
} else {
return -ENODEV;

View File

@ -2244,7 +2244,9 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
return err;
hub_settings = &hw->settings->shub_settings;
if (hub_settings->master_en.addr) {
if (hub_settings->master_en.addr &&
(!dev_fwnode(dev) ||
!device_property_read_bool(dev, "st,disable-sensor-hub"))) {
err = st_lsm6dsx_shub_probe(hw, name);
if (err < 0)
return err;

View File

@ -1727,8 +1727,7 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
const struct iio_chan_spec *channels;
struct iio_buffer *buffer;
int unwind_idx;
int ret, i;
int ret, i, idx;
size_t sz;
channels = indio_dev->channels;
@ -1743,15 +1742,12 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
if (!iio_dev_opaque->attached_buffers_cnt)
return 0;
for (i = 0; i < iio_dev_opaque->attached_buffers_cnt; i++) {
buffer = iio_dev_opaque->attached_buffers[i];
ret = __iio_buffer_alloc_sysfs_and_mask(buffer, indio_dev, i);
if (ret) {
unwind_idx = i - 1;
for (idx = 0; idx < iio_dev_opaque->attached_buffers_cnt; idx++) {
buffer = iio_dev_opaque->attached_buffers[idx];
ret = __iio_buffer_alloc_sysfs_and_mask(buffer, indio_dev, idx);
if (ret)
goto error_unwind_sysfs_and_mask;
}
}
unwind_idx = iio_dev_opaque->attached_buffers_cnt - 1;
sz = sizeof(*(iio_dev_opaque->buffer_ioctl_handler));
iio_dev_opaque->buffer_ioctl_handler = kzalloc(sz, GFP_KERNEL);
@ -1767,9 +1763,9 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
return 0;
error_unwind_sysfs_and_mask:
for (; unwind_idx >= 0; unwind_idx--) {
buffer = iio_dev_opaque->attached_buffers[unwind_idx];
__iio_buffer_free_sysfs_and_mask(buffer, indio_dev, unwind_idx);
while (idx--) {
buffer = iio_dev_opaque->attached_buffers[idx];
__iio_buffer_free_sysfs_and_mask(buffer, indio_dev, idx);
}
return ret;
}

View File

@ -702,6 +702,9 @@ static ssize_t __iio_format_value(char *buf, size_t offset, unsigned int type,
}
case IIO_VAL_CHAR:
return sysfs_emit_at(buf, offset, "%c", (char)vals[0]);
case IIO_VAL_INT_64:
tmp2 = (s64)((((u64)vals[1]) << 32) | (u32)vals[0]);
return sysfs_emit_at(buf, offset, "%lld", tmp2);
default:
return 0;
}
@ -1619,7 +1622,7 @@ static void iio_dev_release(struct device *device)
kfree(iio_dev_opaque);
}
struct device_type iio_device_type = {
const struct device_type iio_device_type = {
.name = "iio_device",
.release = iio_dev_release,
};
@ -1653,7 +1656,6 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv)
indio_dev->dev.type = &iio_device_type;
indio_dev->dev.bus = &iio_bus_type;
device_initialize(&indio_dev->dev);
iio_device_set_drvdata(indio_dev, (void *)indio_dev);
mutex_init(&indio_dev->mlock);
mutex_init(&iio_dev_opaque->info_exist_lock);
INIT_LIST_HEAD(&iio_dev_opaque->channel_attr_list);

View File

@ -162,6 +162,39 @@ static struct iio_trigger *iio_trigger_acquire_by_name(const char *name)
return trig;
}
static void iio_reenable_work_fn(struct work_struct *work)
{
struct iio_trigger *trig = container_of(work, struct iio_trigger,
reenable_work);
/*
* This 'might' occur after the trigger state is set to disabled -
* in that case the driver should skip reenabling.
*/
trig->ops->reenable(trig);
}
/*
* In general, reenable callbacks may need to sleep and this path is
* not performance sensitive, so just queue up a work item
* to reneable the trigger for us.
*
* Races that can cause this.
* 1) A handler occurs entirely in interrupt context so the counter
* the final decrement is still in this interrupt.
* 2) The trigger has been removed, but one last interrupt gets through.
*
* For (1) we must call reenable, but not in atomic context.
* For (2) it should be safe to call reenanble, if drivers never blindly
* reenable after state is off.
*/
static void iio_trigger_notify_done_atomic(struct iio_trigger *trig)
{
if (atomic_dec_and_test(&trig->use_count) && trig->ops &&
trig->ops->reenable)
schedule_work(&trig->reenable_work);
}
void iio_trigger_poll(struct iio_trigger *trig)
{
int i;
@ -173,7 +206,7 @@ void iio_trigger_poll(struct iio_trigger *trig)
if (trig->subirqs[i].enabled)
generic_handle_irq(trig->subirq_base + i);
else
iio_trigger_notify_done(trig);
iio_trigger_notify_done_atomic(trig);
}
}
}
@ -535,6 +568,7 @@ struct iio_trigger *viio_trigger_alloc(struct device *parent,
trig->dev.type = &iio_trig_type;
trig->dev.bus = &iio_bus_type;
device_initialize(&trig->dev);
INIT_WORK(&trig->reenable_work, iio_reenable_work_fn);
mutex_init(&trig->pool_lock);
trig->subirq_base = irq_alloc_descs(-1, 0,

View File

@ -10,6 +10,7 @@
*/
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
@ -18,7 +19,7 @@
#include <linux/init.h>
#include <linux/leds.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
@ -156,7 +157,6 @@ static int cm3605_probe(struct platform_device *pdev)
struct cm3605 *cm3605;
struct iio_dev *indio_dev;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
enum iio_chan_type ch_type;
u32 rset;
int irq;
@ -171,7 +171,7 @@ static int cm3605_probe(struct platform_device *pdev)
cm3605->dev = dev;
cm3605->dir = IIO_EV_DIR_FALLING;
ret = of_property_read_u32(np, "capella,aset-resistance-ohms", &rset);
ret = device_property_read_u32(dev, "capella,aset-resistance-ohms", &rset);
if (ret) {
dev_info(dev, "no RSET specified, assuming 100K\n");
rset = 100000;

View File

@ -1467,9 +1467,6 @@ static const struct iio_buffer_setup_ops gp2ap020a00f_buffer_setup_ops = {
.predisable = &gp2ap020a00f_buffer_predisable,
};
static const struct iio_trigger_ops gp2ap020a00f_trigger_ops = {
};
static int gp2ap020a00f_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@ -1550,8 +1547,6 @@ static int gp2ap020a00f_probe(struct i2c_client *client,
goto error_uninit_buffer;
}
data->trig->ops = &gp2ap020a00f_trigger_ops;
init_irq_work(&data->work, gp2ap020a00f_iio_trigger_work);
err = iio_trigger_register(data->trig);

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* ltr501.c - Support for Lite-On LTR501 ambient light and proximity sensor
* Support for Lite-On LTR501 and similar ambient light and proximity sensors.
*
* Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net>
*
@ -98,6 +98,7 @@ enum {
ltr501 = 0,
ltr559,
ltr301,
ltr303,
};
struct ltr501_gain {
@ -165,6 +166,7 @@ struct ltr501_data {
struct regmap_field *reg_ps_rate;
struct regmap_field *reg_als_prst;
struct regmap_field *reg_ps_prst;
uint32_t near_level;
};
static const struct ltr501_samp_table ltr501_als_samp_table[] = {
@ -524,6 +526,25 @@ static int ltr501_write_intr_prst(struct ltr501_data *data,
return -EINVAL;
}
static ssize_t ltr501_read_near_level(struct iio_dev *indio_dev,
uintptr_t priv,
const struct iio_chan_spec *chan,
char *buf)
{
struct ltr501_data *data = iio_priv(indio_dev);
return sprintf(buf, "%u\n", data->near_level);
}
static const struct iio_chan_spec_ext_info ltr501_ext_info[] = {
{
.name = "nearlevel",
.shared = IIO_SEPARATE,
.read = ltr501_read_near_level,
},
{ /* sentinel */ }
};
static const struct iio_event_spec ltr501_als_event_spec[] = {
{
.type = IIO_EV_TYPE_THRESH,
@ -608,6 +629,7 @@ static const struct iio_chan_spec ltr501_channels[] = {
},
.event_spec = ltr501_pxs_event_spec,
.num_event_specs = ARRAY_SIZE(ltr501_pxs_event_spec),
.ext_info = ltr501_ext_info,
},
IIO_CHAN_SOFT_TIMESTAMP(3),
};
@ -1231,6 +1253,18 @@ static const struct ltr501_chip_info ltr501_chip_info_tbl[] = {
.channels = ltr301_channels,
.no_channels = ARRAY_SIZE(ltr301_channels),
},
[ltr303] = {
.partid = 0x0A,
.als_gain = ltr559_als_gain_tbl,
.als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
.als_mode_active = BIT(0),
.als_gain_mask = BIT(2) | BIT(3) | BIT(4),
.als_gain_shift = 2,
.info = &ltr301_info,
.info_no_irq = &ltr301_info_no_irq,
.channels = ltr301_channels,
.no_channels = ARRAY_SIZE(ltr301_channels),
},
};
static int ltr501_write_contr(struct ltr501_data *data, u8 als_val, u8 ps_val)
@ -1518,6 +1552,10 @@ static int ltr501_probe(struct i2c_client *client,
if ((partid >> 4) != data->chip_info->partid)
return -ENODEV;
if (device_property_read_u32(&client->dev, "proximity-near-level",
&data->near_level))
data->near_level = 0;
indio_dev->info = data->chip_info->info;
indio_dev->channels = data->chip_info->channels;
indio_dev->num_channels = data->chip_info->no_channels;
@ -1605,6 +1643,7 @@ static const struct i2c_device_id ltr501_id[] = {
{ "ltr501", ltr501},
{ "ltr559", ltr559},
{ "ltr301", ltr301},
{ "ltr303", ltr303},
{ }
};
MODULE_DEVICE_TABLE(i2c, ltr501_id);
@ -1613,6 +1652,7 @@ static const struct of_device_id ltr501_of_match[] = {
{ .compatible = "liteon,ltr501", },
{ .compatible = "liteon,ltr559", },
{ .compatible = "liteon,ltr301", },
{ .compatible = "liteon,ltr303", },
{}
};
MODULE_DEVICE_TABLE(of, ltr501_of_match);

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