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:
commit
1bb866dcb8
|
@ -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.
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
|
@ -125,7 +125,6 @@ oneOf:
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/iio/adi,ad5592r.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
...
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
...
|
|
@ -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:
|
||||
|
|
|
@ -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>;
|
||||
|
||||
|
|
20
MAINTAINERS
20
MAINTAINERS
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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),
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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, <c2617_powerdown_mode_enum),
|
||||
IIO_ENUM_AVAILABLE("powerdown_mode", <c2617_powerdown_mode_enum),
|
||||
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, <c2617_powerdown_mode_enum),
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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),
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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");
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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),
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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");
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 = <r301_info,
|
||||
.info_no_irq = <r301_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
Loading…
Reference in New Issue