diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 5f87dcee78f7..4fc9f6bd4281 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1428,7 +1428,7 @@ KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: The name of the trigger source being used, as per string given - in /sys/class/iio/triggerY/name. + in /sys/bus/iio/devices/triggerY/name. What: /sys/bus/iio/devices/iio:deviceX/bufferY/length KernelVersion: 5.11 diff --git a/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml b/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml index 0ba0df46c3a9..02e734946f44 100644 --- a/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml +++ b/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml @@ -4,20 +4,23 @@ $id: http://devicetree.org/schemas/iio/accel/adi,adxl372.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer +title: Analog Devices ADXL371/ADXL372 3-Axis, +/-(200g) Digital Accelerometer maintainers: - Marcelo Schmitt - Nuno Sá + - Antoniu Miclaus description: | - Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer that supports - both I2C & SPI interfaces + Analog Devices ADXL371/ADXL372 3-Axis, +/-(200g) Digital Accelerometer that + supports both I2C & SPI interfaces + https://www.analog.com/en/products/adxl371.html https://www.analog.com/en/products/adxl372.html properties: compatible: enum: + - adi,adxl371 - adi,adxl372 reg: diff --git a/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml b/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml index c1387e02eb82..7f9c5eec35dd 100644 --- a/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml +++ b/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml @@ -16,25 +16,27 @@ description: properties: compatible: - enum: - # bmc150-accel driver in Linux - - bosch,bma222 - - bosch,bma222e - - bosch,bma250e - - bosch,bma253 - - bosch,bma254 - - bosch,bma255 - - bosch,bma280 - - bosch,bmc150_accel - - bosch,bmc156_accel - - bosch,bmi055_accel + oneOf: + - enum: + - bosch,bma222 + - bosch,bma222e + - bosch,bma250e + - bosch,bma253 + - bosch,bma254 + - bosch,bma255 + - bosch,bma280 + - bosch,bmc150_accel + - bosch,bmc156_accel + - bosch,bmi055_accel - # bma180 driver in Linux - - bosch,bma023 - - bosch,bma150 - - bosch,bma180 - - bosch,bma250 - - bosch,smb380 + - bosch,bma023 + - bosch,bma150 + - bosch,bma180 + - bosch,bma250 + - bosch,smb380 + - items: + - const: bosch,bmx055-accel + - const: bosch,bmc150_accel reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml index e22d518135f2..08b1f9d75f89 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml @@ -19,6 +19,10 @@ description: | * https://www.analog.com/media/en/technical-documentation/data-sheets/ad4030-24-4032-24.pdf * https://www.analog.com/media/en/technical-documentation/data-sheets/ad4630-24_ad4632-24.pdf * https://www.analog.com/media/en/technical-documentation/data-sheets/ad4630-16-4632-16.pdf + * https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4216.pdf + * https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4224.pdf + +$ref: /schemas/spi/spi-peripheral-props.yaml# properties: compatible: @@ -29,6 +33,8 @@ properties: - adi,ad4630-24 - adi,ad4632-16 - adi,ad4632-24 + - adi,adaq4216 + - adi,adaq4224 reg: maxItems: 1 @@ -60,6 +66,14 @@ properties: description: Internal buffered Reference. Used when ref-supply is not connected. + vddh-supply: + description: + PGIA Positive Power Supply. + + vdd-fda-supply: + description: + FDA Positive Power Supply. + cnv-gpios: description: The Convert Input (CNV). It initiates the sampling conversions. @@ -70,6 +84,17 @@ properties: The Reset Input (/RST). Used for asynchronous device reset. maxItems: 1 + pga-gpios: + description: + A0 and A1 pins for gain selection. For devices that have PGA configuration + input pins, pga-gpios should be defined. + minItems: 2 + maxItems: 2 + + pwms: + description: PWM signal connected to the CNV pin. + maxItems: 1 + interrupts: description: The BUSY pin is used to signal that the conversions results are available @@ -107,6 +132,22 @@ allOf: properties: spi-rx-bus-width: maxItems: 1 + # ADAQ devices require a gain property to indicate how hardware PGA is set + - if: + properties: + compatible: + contains: + pattern: ^adi,adaq + then: + required: + - vddh-supply + - vdd-fda-supply + - pga-gpios + properties: + ref-supply: false + else: + properties: + pga-gpios: false examples: - | @@ -148,3 +189,26 @@ examples: reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>; }; }; + - | + #include + + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,adaq4216"; + reg = <0>; + spi-max-frequency = <80000000>; + vdd-5v-supply = <&supply_5V>; + vdd-1v8-supply = <&supply_1_8V>; + vio-supply = <&supply_1_8V>; + refin-supply = <&refin_sup>; + vddh-supply = <&vddh>; + vdd-fda-supply = <&vdd_fda>; + cnv-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>; + pga-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>, + <&gpio0 3 GPIO_ACTIVE_HIGH>; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml index ccd6a0ac1539..79df2696ef24 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml @@ -27,10 +27,13 @@ properties: enum: - adi,ad4080 - adi,ad4081 + - adi,ad4082 - adi,ad4083 - adi,ad4084 + - adi,ad4085 - adi,ad4086 - adi,ad4087 + - adi,ad4088 reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml index b91bfb16ed6b..396e1a1aa805 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml @@ -62,6 +62,11 @@ properties: spi-cpol: true spi-cpha: true + spi-rx-bus-width: + maxItems: 4 + items: + maximum: 1 + vcc-supply: description: A 3V to 3.6V supply that powers the chip. @@ -160,6 +165,23 @@ patternProperties: unevaluatedProperties: false allOf: + # 2-channel chips only have two SDO lines + - if: + properties: + compatible: + enum: + - adi,ad7380 + - adi,ad7381 + - adi,ad7383 + - adi,ad7384 + - adi,ad7386 + - adi,ad7387 + - adi,ad7388 + then: + properties: + spi-rx-bus-width: + maxItems: 2 + # pseudo-differential chips require common mode voltage supplies, # true differential chips don't use them - if: @@ -284,6 +306,7 @@ examples: spi-cpol; spi-cpha; spi-max-frequency = <80000000>; + spi-rx-bus-width = <1>, <1>, <1>, <1>; interrupts = <27 IRQ_TYPE_EDGE_FALLING>; interrupt-parent = <&gpio0>; diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml index bb9825e7346d..70ab4e140e71 100644 --- a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml @@ -27,7 +27,11 @@ properties: - amlogic,meson-gxm-saradc - amlogic,meson-axg-saradc - amlogic,meson-g12a-saradc + # Usage of this generic fallback is not allowed for new devices - const: amlogic,meson-saradc + - items: + - const: amlogic,meson-s4-saradc + - const: amlogic,meson-g12a-saradc reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml index 5cc6a9684077..c884b6e03767 100644 --- a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml +++ b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml @@ -11,6 +11,12 @@ maintainers: - Liam Beguin description: | + LTC2305: + low noise, low power, 2-channel, 12-bit successive approximation ADC with an + I2C compatible serial interface. + + https://www.analog.com/media/en/technical-documentation/data-sheets/23015fb.pdf + LTC2309: low noise, low power, 8-channel, 12-bit successive approximation ADC with an I2C compatible serial interface. @@ -28,6 +34,7 @@ description: | properties: compatible: enum: + - lltc,ltc2305 - lltc,ltc2309 - lltc,ltc2497 - lltc,ltc2499 diff --git a/Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml b/Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml index 9ceb6f18c854..1f77da7f8e06 100644 --- a/Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml @@ -19,6 +19,7 @@ properties: enum: - motorola,cpcap-adc - motorola,mapphone-cpcap-adc + - motorola,mot-cpcap-adc interrupts: maxItems: 1 diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-adc5-gen3.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-adc5-gen3.yaml new file mode 100644 index 000000000000..149f4af8f4b8 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-adc5-gen3.yaml @@ -0,0 +1,151 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/qcom,spmi-adc5-gen3.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm's SPMI PMIC ADC5 Gen3 + +maintainers: + - Jishnu Prakash + +description: | + SPMI PMIC5 Gen3 voltage ADC (ADC) provides interface to clients to read + voltage. It is a 16-bit sigma-delta ADC. It also performs the same thermal + monitoring function as the existing ADC_TM devices. + + The interface is implemented on SDAM (Shared Direct Access Memory) peripherals + on the master PMIC rather than a dedicated ADC peripheral. The number of PMIC + SDAM peripherals allocated for ADC is not correlated with the PMIC used, it is + programmed in FW (PBS) and is fixed per SOC, based on the SOC requirements. + All boards using a particular (SOC + master PMIC) combination will have the + same number of ADC SDAMs supported on that PMIC. + +properties: + compatible: + const: qcom,spmi-adc5-gen3 + + reg: + items: + - description: SDAM0 base address in the SPMI PMIC register map + - description: SDAM1 base address + minItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + "#io-channel-cells": + const: 1 + + "#thermal-sensor-cells": + const: 1 + + interrupts: + items: + - description: SDAM0 end of conversion (EOC) interrupt + - description: SDAM1 EOC interrupt + minItems: 1 + +patternProperties: + "^channel@[0-9a-f]+$": + type: object + unevaluatedProperties: false + $ref: /schemas/iio/adc/qcom,spmi-vadc-common.yaml + description: + Represents the external channels which are connected to the ADC. + + properties: + qcom,decimation: + enum: [ 85, 340, 1360 ] + default: 1360 + + qcom,hw-settle-time: + enum: [ 15, 100, 200, 300, 400, 500, 600, 700, + 1000, 2000, 4000, 8000, 16000, 32000, 64000, 128000 ] + default: 15 + + qcom,avg-samples: + enum: [ 1, 2, 4, 8, 16 ] + default: 1 + + qcom,adc-tm: + description: + ADC_TM is a threshold monitoring feature in HW which can be enabled + on any ADC channel, to trigger an IRQ for threshold violation. In + earlier ADC generations, it was implemented in a separate device + (documented in Documentation/devicetree/bindings/thermal/qcom-spmi-adc-tm5.yaml.) + In Gen3, this feature can be enabled in the same ADC device for any + channel and threshold monitoring and IRQ triggering are handled in FW + (PBS) instead of another dedicated HW block. + This property indicates ADC_TM monitoring is done on this channel. + type: boolean + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + - "#io-channel-cells" + - interrupts + +additionalProperties: false + +examples: + - | + #include + + pmic { + #address-cells = <1>; + #size-cells = <0>; + + adc@9000 { + compatible = "qcom,spmi-adc5-gen3"; + reg = <0x9000>, <0x9100>; + interrupts = <0x0 0x90 0x1 IRQ_TYPE_EDGE_RISING>, + <0x0 0x91 0x1 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + #thermal-sensor-cells = <1>; + + /* PMK8550 Channel nodes */ + channel@3 { + reg = <0x3>; + label = "pmk8550_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + channel@44 { + reg = <0x44>; + label = "pmk8550_xo_therm"; + qcom,pre-scaling = <1 1>; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,adc-tm; + }; + + /* PM8550 Channel nodes */ + channel@103 { + reg = <0x103>; + label = "pm8550_die_temp"; + qcom,pre-scaling = <1 1>; + }; + + /* PM8550B Channel nodes */ + channel@78f { + reg = <0x78f>; + label = "pm8550b_vbat_sns_qbg"; + qcom,pre-scaling = <1 3>; + }; + + /* PM8550VS_C Channel nodes */ + channel@203 { + reg = <0x203>; + label = "pm8550vs_c_die_temp"; + qcom,pre-scaling = <1 1>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc-common.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc-common.yaml new file mode 100644 index 000000000000..3ae252c17b91 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc-common.yaml @@ -0,0 +1,84 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/qcom,spmi-vadc-common.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies, Inc. SPMI PMIC ADC channels + +maintainers: + - Jishnu Prakash + +description: + This defines the common properties used to define Qualcomm VADC channels. + +properties: + reg: + description: + ADC channel number (PMIC-specific for versions after PMIC5 ADC). + maxItems: 1 + + label: + description: + ADC input of the platform as seen in the schematics. + For thermistor inputs connected to generic AMUX or GPIO inputs + these can vary across platform for the same pins. Hence select + the platform schematics name for this channel. + + qcom,decimation: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + This parameter is used to decrease ADC sampling rate. + Quicker measurements can be made by reducing decimation ratio. + + qcom,pre-scaling: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Used for scaling the channel input signal before the signal is + fed to VADC. The configuration for this node is to know the + pre-determined ratio and use it for post scaling. It is a pair of + integers, denoting the numerator and denominator of the fraction by which + input signal is multiplied. For example, <1 3> indicates the signal is scaled + down to 1/3 of its value before ADC measurement. + If property is not found default value depending on chip will be used. + oneOf: + - items: + - const: 1 + - enum: [ 1, 3, 4, 6, 20, 8, 10, 16 ] + - items: + - const: 10 + - const: 81 + + qcom,ratiometric: + type: boolean + description: | + Channel calibration type. + - For compatible property "qcom,spmi-vadc", if this property is + specified VADC will use the VDD reference (1.8V) and GND for + channel calibration. If property is not found, channel will be + calibrated with 0.625V and 1.25V reference channels, also + known as absolute calibration. + - For other compatible properties, if this property is specified + VADC will use the VDD reference (1.875V) and GND for channel + calibration. If property is not found, channel will be calibrated + with 0V and 1.25V reference channels, also known as absolute calibration. + + qcom,hw-settle-time: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Time between AMUX getting configured and the ADC starting + conversion. The 'hw_settle_time' is an index used from valid values + and programmed in hardware to achieve the hardware settling delay. + + qcom,avg-samples: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Number of samples to be used for measurement. + Averaging provides the option to obtain a single measurement + from the ADC that is an average of multiple samples. The value + selected is 2^(value). + +required: + - reg + +additionalProperties: true diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml index b9dc04b0d307..72188041e8b5 100644 --- a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml @@ -15,6 +15,8 @@ description: | voltage. The VADC is a 15-bit sigma-delta ADC. SPMI PMIC5/PMIC7 voltage ADC (ADC) provides interface to clients to read voltage. The VADC is a 16-bit sigma-delta ADC. + Note that PMIC7 ADC is the generation between PMIC5 and PMIC5 Gen3 ADC, + it can be considered like PMIC5 Gen2. properties: compatible: @@ -56,7 +58,7 @@ required: patternProperties: "^channel@[0-9a-f]+$": type: object - additionalProperties: false + unevaluatedProperties: false description: | Represents the external channels which are connected to the ADC. For compatible property "qcom,spmi-vadc" following channels, also known as @@ -64,79 +66,7 @@ patternProperties: configuration nodes should be defined: VADC_REF_625MV and/or VADC_SPARE1(based on PMIC version) VADC_REF_1250MV, VADC_GND_REF and VADC_VDD_VADC. - - properties: - reg: - maxItems: 1 - description: | - ADC channel number. - See include/dt-bindings/iio/qcom,spmi-vadc.h - For PMIC7 ADC, the channel numbers are specified separately per PMIC - in the PMIC-specific files in include/dt-bindings/iio/. - - label: - description: | - ADC input of the platform as seen in the schematics. - For thermistor inputs connected to generic AMUX or GPIO inputs - these can vary across platform for the same pins. Hence select - the platform schematics name for this channel. - - qcom,decimation: - $ref: /schemas/types.yaml#/definitions/uint32 - description: | - This parameter is used to decrease ADC sampling rate. - Quicker measurements can be made by reducing decimation ratio. - - qcom,pre-scaling: - description: | - Used for scaling the channel input signal before the signal is - fed to VADC. The configuration for this node is to know the - pre-determined ratio and use it for post scaling. It is a pair of - integers, denoting the numerator and denominator of the fraction by which - input signal is multiplied. For example, <1 3> indicates the signal is scaled - down to 1/3 of its value before ADC measurement. - If property is not found default value depending on chip will be used. - $ref: /schemas/types.yaml#/definitions/uint32-array - oneOf: - - items: - - const: 1 - - enum: [ 1, 3, 4, 6, 20, 8, 10, 16 ] - - items: - - const: 10 - - const: 81 - - qcom,ratiometric: - description: | - Channel calibration type. - - For compatible property "qcom,spmi-vadc", if this property is - specified VADC will use the VDD reference (1.8V) and GND for - channel calibration. If property is not found, channel will be - calibrated with 0.625V and 1.25V reference channels, also - known as absolute calibration. - - For compatible property "qcom,spmi-adc5", "qcom,spmi-adc7" and - "qcom,spmi-adc-rev2", if this property is specified VADC will use - the VDD reference (1.875V) and GND for channel calibration. If - property is not found, channel will be calibrated with 0V and 1.25V - reference channels, also known as absolute calibration. - type: boolean - - qcom,hw-settle-time: - $ref: /schemas/types.yaml#/definitions/uint32 - description: | - Time between AMUX getting configured and the ADC starting - conversion. The 'hw_settle_time' is an index used from valid values - and programmed in hardware to achieve the hardware settling delay. - - qcom,avg-samples: - $ref: /schemas/types.yaml#/definitions/uint32 - description: | - Number of samples to be used for measurement. - Averaging provides the option to obtain a single measurement - from the ADC that is an average of multiple samples. The value - selected is 2^(value). - - required: - - reg + $ref: /schemas/iio/adc/qcom,spmi-vadc-common.yaml allOf: - if: diff --git a/Documentation/devicetree/bindings/iio/amplifiers/adi,ad8366.yaml b/Documentation/devicetree/bindings/iio/amplifiers/adi,ad8366.yaml new file mode 100644 index 000000000000..065637ce33a5 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/amplifiers/adi,ad8366.yaml @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/amplifiers/adi,ad8366.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: AD8366 and similar Gain Amplifiers and Digital Attenuators + +maintainers: + - Michael Hennerich + - Rodrigo Alencar + +description: + Digital Variable Gain Amplifiers (VGAs) and Digital Attenuators with + SPI interface. + +properties: + compatible: + enum: + - adi,ad8366 + - adi,ada4961 + - adi,adl5240 + - adi,adrf5702 + - adi,adrf5703 + - adi,adrf5720 + - adi,adrf5730 + - adi,adrf5731 + - adi,hmc271a + - adi,hmc792a + - adi,hmc1018a + - adi,hmc1019a + - adi,hmc1119 + + reg: + maxItems: 1 + + vcc-supply: + description: Regulator that provides power to the device. + + reset-gpios: + maxItems: 1 + + enable-gpios: + maxItems: 1 + description: Power-up or Serial Mode Enable GPIO. + +required: + - compatible + - reg + - vcc-supply + +allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml# + - if: + not: + properties: + compatible: + contains: + const: adi,hmc271a + then: + properties: + reset-gpios: false + - if: + not: + properties: + compatible: + contains: + anyOf: + - const: adi,ad8366 + - const: adi,ada4961 + - const: adi,adrf5702 + - const: adi,adrf5703 + - const: adi,adrf5720 + - const: adi,adrf5730 + - const: adi,adrf5731 + - const: adi,hmc792a + - const: adi,hmc1018a + - const: adi,hmc1019a + - const: adi,hmc1119 + then: + properties: + enable-gpios: false + +unevaluatedProperties: false + +examples: + - | + #include + spi { + #address-cells = <1>; + #size-cells = <0>; + + amplifier@0 { + compatible = "adi,ad8366"; + reg = <0>; + spi-max-frequency = <1000000>; + vcc-supply = <&vcc_3v3>; + enable-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/dac/lltc,ltc2632.yaml b/Documentation/devicetree/bindings/iio/dac/lltc,ltc2632.yaml index 733edc7d6d17..50a9cbb44e36 100644 --- a/Documentation/devicetree/bindings/iio/dac/lltc,ltc2632.yaml +++ b/Documentation/devicetree/bindings/iio/dac/lltc,ltc2632.yaml @@ -4,36 +4,49 @@ $id: http://devicetree.org/schemas/iio/dac/lltc,ltc2632.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Linear Technology LTC263x 12-/10-/8-Bit Rail-to-Rail DAC +title: Linear Technology LTC263x and LTC2654 Rail-to-Rail DAC maintainers: - Michael Hennerich description: | - Bindings for the Linear Technology LTC2632/2634/2636 DAC - Datasheet can be found here: https://www.analog.com/media/en/technical-documentation/data-sheets/LTC263[246].pdf + Bindings for the Linear Technology LTC2632/2634/2636/2654 DAC + Datasheet can be found here: + https://www.analog.com/media/en/technical-documentation/data-sheets/LTC263[246].pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/2654f.pdf properties: compatible: - enum: - - lltc,ltc2632-l12 - - lltc,ltc2632-l10 - - lltc,ltc2632-l8 - - lltc,ltc2632-h12 - - lltc,ltc2632-h10 - - lltc,ltc2632-h8 - - lltc,ltc2634-l12 - - lltc,ltc2634-l10 - - lltc,ltc2634-l8 - - lltc,ltc2634-h12 - - lltc,ltc2634-h10 - - lltc,ltc2634-h8 - - lltc,ltc2636-l12 - - lltc,ltc2636-l10 - - lltc,ltc2636-l8 - - lltc,ltc2636-h12 - - lltc,ltc2636-h10 - - lltc,ltc2636-h8 + oneOf: + - enum: + - lltc,ltc2632-l12 + - lltc,ltc2632-l10 + - lltc,ltc2632-l8 + - lltc,ltc2632-h12 + - lltc,ltc2632-h10 + - lltc,ltc2632-h8 + - lltc,ltc2634-l12 + - lltc,ltc2634-l10 + - lltc,ltc2634-l8 + - lltc,ltc2634-h12 + - lltc,ltc2634-h10 + - lltc,ltc2634-h8 + - lltc,ltc2636-l12 + - lltc,ltc2636-l10 + - lltc,ltc2636-l8 + - lltc,ltc2636-h12 + - lltc,ltc2636-h10 + - lltc,ltc2636-h8 + - lltc,ltc2654-l16 + - lltc,ltc2654-h16 + - items: + - enum: + - lltc,ltc2654-l12 + - const: lltc,ltc2634-l12 + - items: + - enum: + - lltc,ltc2654-h12 + - const: lltc,ltc2634-h12 reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/iio/dac/maxim,ds4424.yaml b/Documentation/devicetree/bindings/iio/dac/maxim,ds4424.yaml index 264fa7c5fe3a..4323df2036ac 100644 --- a/Documentation/devicetree/bindings/iio/dac/maxim,ds4424.yaml +++ b/Documentation/devicetree/bindings/iio/dac/maxim,ds4424.yaml @@ -4,18 +4,21 @@ $id: http://devicetree.org/schemas/iio/dac/maxim,ds4424.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Maxim Integrated DS4422/DS4424 7-bit Sink/Source Current DAC +title: Maxim Integrated DS4402/DS4404 and DS4422/DS4424 Current DACs maintainers: - Ismail Kose description: | - Datasheet publicly available at: + Datasheets publicly available at: + https://datasheets.maximintegrated.com/en/ds/DS4402-DS4404.pdf https://datasheets.maximintegrated.com/en/ds/DS4422-DS4424.pdf properties: compatible: enum: + - maxim,ds4402 + - maxim,ds4404 - maxim,ds4422 - maxim,ds4424 @@ -24,9 +27,43 @@ properties: vcc-supply: true + maxim,rfs-ohms: + description: | + Array of resistance values in Ohms for the external Rfs resistors + connected to the FS pins. These values determine the full-scale + output current. The actual resistance depends on the chip variant + and specific hardware design requirements. + minItems: 2 + maxItems: 4 + required: - compatible - reg + - maxim,rfs-ohms + +allOf: + - if: + properties: + compatible: + contains: + enum: + - maxim,ds4402 + - maxim,ds4422 + then: + properties: + maxim,rfs-ohms: + maxItems: 2 + - if: + properties: + compatible: + contains: + enum: + - maxim,ds4404 + - maxim,ds4424 + then: + properties: + maxim,rfs-ohms: + minItems: 4 additionalProperties: false @@ -40,6 +77,7 @@ examples: compatible = "maxim,ds4424"; reg = <0x10>; /* When A0, A1 pins are ground */ vcc-supply = <&vcc_3v3>; + maxim,rfs-ohms = <40000>, <40000>, <40000>, <40000>; }; }; ... diff --git a/Documentation/devicetree/bindings/iio/dac/ti,dac7612.yaml b/Documentation/devicetree/bindings/iio/dac/ti,dac7612.yaml index 20dd1370660d..624c640be4c8 100644 --- a/Documentation/devicetree/bindings/iio/dac/ti,dac7612.yaml +++ b/Documentation/devicetree/bindings/iio/dac/ti,dac7612.yaml @@ -9,7 +9,7 @@ title: Texas Instruments DAC7612 family of DACs description: The DAC7612 is a dual, 12-bit digital-to-analog converter (DAC) with guaranteed 12-bit monotonicity performance over the industrial temperature - range. Is is programmable through an SPI interface. + range. It is programmable through an SPI interface. maintainers: - Ricardo Ribalda Delgado diff --git a/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml b/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml index 3c6fe74af0b8..fcbd4b430e48 100644 --- a/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml +++ b/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml @@ -11,10 +11,14 @@ maintainers: properties: compatible: - enum: - - bosch,bmg160 - - bosch,bmi055_gyro - - bosch,bmi088_gyro + oneOf: + - enum: + - bosch,bmg160 + - bosch,bmi055_gyro + - bosch,bmi088_gyro + - items: + - const: bosch,bmx055-gyro + - const: bosch,bmg160 reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/iio/light/vishay,vcnl4000.yaml b/Documentation/devicetree/bindings/iio/light/vishay,vcnl4000.yaml index 4d1a225e8868..516afef7a545 100644 --- a/Documentation/devicetree/bindings/iio/light/vishay,vcnl4000.yaml +++ b/Documentation/devicetree/bindings/iio/light/vishay,vcnl4000.yaml @@ -18,16 +18,32 @@ allOf: properties: compatible: - enum: - - vishay,vcnl4000 - - vishay,vcnl4010 - - vishay,vcnl4020 - - vishay,vcnl4040 - - vishay,vcnl4200 + oneOf: + - enum: + - capella,cm36672p + - vishay,vcnl4000 + - vishay,vcnl4010 + - vishay,vcnl4020 + - vishay,vcnl4040 + - vishay,vcnl4200 + - items: + - const: capella,cm36686 + - const: vishay,vcnl4040 interrupts: maxItems: 1 + vdd-supply: + description: Regulator providing power to the "VDD" pin. + + vio-supply: + description: Regulator providing power for pull-up of the I/O lines. + Does not connect to the sensor directly, but is needed for the + correct operation of the I2C and interrupt lines. + + vled-supply: + description: Regulator providing power to the IR anode pin. + reg: maxItems: 1 @@ -49,6 +65,9 @@ examples: compatible = "vishay,vcnl4200"; reg = <0x51>; proximity-near-level = <220>; + vdd-supply = <®_vdd>; + vio-supply = <®_vio>; + vled-supply = <®_vled>; }; }; ... diff --git a/Documentation/devicetree/bindings/iio/magnetometer/bosch,bmc150_magn.yaml b/Documentation/devicetree/bindings/iio/magnetometer/bosch,bmc150_magn.yaml index a3838ab0c524..c1a6892b0194 100644 --- a/Documentation/devicetree/bindings/iio/magnetometer/bosch,bmc150_magn.yaml +++ b/Documentation/devicetree/bindings/iio/magnetometer/bosch,bmc150_magn.yaml @@ -21,11 +21,15 @@ properties: description: Note the bmm150_magn is a deprecated compatible as this part contains only a magnetometer. - enum: - - bosch,bmc150_magn - - bosch,bmc156_magn - - bosch,bmm150 - - bosch,bmm150_magn + oneOf: + - enum: + - bosch,bmc150_magn + - bosch,bmc156_magn + - bosch,bmm150 + - bosch,bmm150_magn + - items: + - const: bosch,bmx055-magn + - const: bosch,bmc150_magn reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml b/Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml index 322befc41de6..f7f8be1e379d 100644 --- a/Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml +++ b/Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml @@ -4,14 +4,17 @@ $id: http://devicetree.org/schemas/iio/proximity/st,vl53l0x.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: ST VL53L0X ToF ranging sensor +title: ST VL53L0X/VL53L1X ToF ranging sensor maintainers: - Song Qiang + - Siratul Islam properties: compatible: - const: st,vl53l0x + enum: + - st,vl53l0x + - st,vl53l1x reg: maxItems: 1 @@ -21,6 +24,8 @@ properties: reset-gpios: maxItems: 1 + description: + Phandle to the XSHUT GPIO. Used for hardware reset. vdd-supply: true @@ -28,6 +33,16 @@ required: - compatible - reg +allOf: + - if: + properties: + compatible: + contains: + const: st,vl53l1x + then: + required: + - vdd-supply + additionalProperties: false examples: @@ -38,8 +53,9 @@ examples: #size-cells = <0>; proximity@29 { - compatible = "st,vl53l0x"; + compatible = "st,vl53l1x"; reg = <0x29>; + vdd-supply = <®_3v3>; interrupt-parent = <&gpio>; interrupts = <23 IRQ_TYPE_EDGE_FALLING>; }; diff --git a/Documentation/devicetree/bindings/iio/proximity/tyhx,hx9023s.yaml b/Documentation/devicetree/bindings/iio/proximity/tyhx,hx9023s.yaml index 64ce8bc8bd36..cc5b5284c267 100644 --- a/Documentation/devicetree/bindings/iio/proximity/tyhx,hx9023s.yaml +++ b/Documentation/devicetree/bindings/iio/proximity/tyhx,hx9023s.yaml @@ -28,6 +28,9 @@ properties: vdd-supply: true + firmware-name: + maxItems: 1 + "#address-cells": const: 1 @@ -65,6 +68,7 @@ examples: interrupt-parent = <&pio>; interrupts = <16 IRQ_TYPE_EDGE_FALLING>; vdd-supply = <&pp1800_prox>; + firmware-name = "hx9023s.bin"; #address-cells = <1>; #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml index e5931d18d998..644c42b5e2e5 100644 --- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml +++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml @@ -135,6 +135,7 @@ patternProperties: "^adc@[0-9a-f]+$": type: object oneOf: + - $ref: /schemas/iio/adc/qcom,spmi-adc5-gen3.yaml# - $ref: /schemas/iio/adc/qcom,spmi-iadc.yaml# - $ref: /schemas/iio/adc/qcom,spmi-rradc.yaml# - $ref: /schemas/iio/adc/qcom,spmi-vadc.yaml# diff --git a/Documentation/iio/ad4030.rst b/Documentation/iio/ad4030.rst index b57424b650a8..9caafa4148b0 100644 --- a/Documentation/iio/ad4030.rst +++ b/Documentation/iio/ad4030.rst @@ -92,6 +92,45 @@ Interleaved mode In this mode, both channels conversion results are bit interleaved one SDO line. As such the wiring is the same as `One lane mode`_. +SPI offload wiring +^^^^^^^^^^^^^^^^^^ + +.. code-block:: + + +-------------+ +-------------+ + | CNV |<-----+--| GPIO | + | | +--| PWM0 | + | | | | + | | +--| PWM1 | + | | | +-------------+ + | | +->| TRIGGER | + | CS |<--------| CS | + | | | | + | ADC | | SPI | + | | | | + | SDI |<--------| SDO | + | SDO |-------->| SDI | + | SCLK |<--------| SCLK | + +-------------+ +-------------+ + +In this mode, both the ``cnv-gpios`` and a ``pwms`` properties are required. +The ``pwms`` property specifies the PWM that is connected to the ADC CNV pin. +The SPI offload will have a ``trigger-sources`` property to indicate the SPI +offload (PWM) trigger source. For AD4030 and similar ADCs, there are two +possible data transfer zones for sample N. One of them (zone 1) starts after the +data conversion for sample N is complete while the other one (zone 2) starts 9.8 +nanoseconds after the rising edge of CNV for sample N + 1. + +The configuration depicted in the above diagram is intended to perform data +transfer in zone 2. To achieve high sample rates while meeting ADC timing +requirements, an offset is added between the rising edges of PWM0 and PWM1 to +delay the SPI transfer until 9.8 nanoseconds after CNV rising edge. This +requires a specialized PWM controller that can provide such an offset. +The `AD4630-FMC HDL project`_, for example, can be configured to sample AD4030 +data during zone 2 data read window. + +.. _AD4630-FMC HDL project: https://analogdevicesinc.github.io/hdl/projects/ad4630_fmc/index.html + SPI Clock mode -------------- diff --git a/Documentation/iio/ad7191.rst b/Documentation/iio/ad7191.rst index 977d4fea14b0..fd6a23ad44fd 100644 --- a/Documentation/iio/ad7191.rst +++ b/Documentation/iio/ad7191.rst @@ -63,11 +63,11 @@ Clock Configuration The AD7191 supports both internal and external clock sources: -- When CLKSEL pin is tied LOW: Uses internal 4.92MHz clock (no clock property +- When CLKSEL pin is ACTIVE: Uses internal 4.92MHz clock (no clock property needed) -- When CLKSEL pin is tied HIGH: Requires external clock source +- When CLKSEL pin is INACTIVE: Requires external clock source - Can be a crystal between MCLK1 and MCLK2 pins - - Or a CMOS-compatible clock driving MCLK2 pin + - Or a CMOS-compatible clock driving MCLK1 pin and MCLK2 left unconnected - Must specify the "clocks" property in device tree when using external clock SPI Interface Requirements diff --git a/Documentation/iio/adxl345.rst b/Documentation/iio/adxl345.rst index bb19d64f67c3..978f746a8198 100644 --- a/Documentation/iio/adxl345.rst +++ b/Documentation/iio/adxl345.rst @@ -12,16 +12,21 @@ This driver supports Analog Device's ADXL345/375 on SPI/I2C bus. * `ADXL345 `_ * `ADXL375 `_ -The ADXL345 is a generic purpose low power, 3-axis accelerometer with selectable -measurement ranges. The ADXL345 supports the ±2 g, ±4 g, ±8 g, and ±16 g ranges. +The ADXL345 is a general-purpose, low-power, 3-axis accelerometer with selectable +measurement ranges. The ADXL345 supports the following ranges: + +- ±2g (approx. ±19.61 m/s^2) +- ±4g (approx. ±39.23 m/s^2) +- ±8g (approx. ±78.45 m/s^2) +- ±16g (approx. ±156.91 m/s^2) 2. Device Attributes ==================== -Each IIO device, has a device folder under ``/sys/bus/iio/devices/iio:deviceX``, +Each IIO device has a device folder under ``/sys/bus/iio/devices/iio:deviceX``, where X is the IIO index of the device. Under these folders reside a set of device files, depending on the characteristics and features of the hardware -device in questions. These files are consistently generalized and documented in +device in question. These files are consistently generalized and documented in the IIO ABI documentation. The following table shows the ADXL345 related device files, found in the @@ -42,7 +47,7 @@ specific device folder path ``/sys/bus/iio/devices/iio:deviceX``. +-------------------------------------------+----------------------------------------------------------+ | in_accel_x_raw | Raw X-axis accelerometer channel value. | +-------------------------------------------+----------------------------------------------------------+ -| in_accel_y_calibbias | y-axis acceleration offset correction | +| in_accel_y_calibbias | Y-axis acceleration offset correction | +-------------------------------------------+----------------------------------------------------------+ | in_accel_y_raw | Raw Y-axis accelerometer channel value. | +-------------------------------------------+----------------------------------------------------------+ @@ -68,7 +73,7 @@ present, simply assume its value is 0. +-------------------------------------+---------------------------+ | Channel type | Measurement unit | +-------------------------------------+---------------------------+ -| Acceleration on X, Y, and Z axis | Meters per second squared | +| Acceleration on X, Y, and Z axes | Meters per second squared | +-------------------------------------+---------------------------+ Sensor Events @@ -78,8 +83,8 @@ Specific IIO events are triggered by their corresponding interrupts. The sensor driver supports either none or a single active interrupt (INT) line, selectable from the two available options: INT1 or INT2. The active INT line should be specified in the device tree. If no INT line is configured, the sensor defaults -to FIFO bypass mode, where event detection is disabled and only X, Y, and Z axis -measurements are available. +to FIFO bypass mode, where event detection is disabled and only individual +X, Y, and Z axis measurements are available. The table below lists the ADXL345-related device files located in the device-specific path: ``/sys/bus/iio/devices/iio:deviceX/events``. @@ -90,38 +95,52 @@ listed. +---------------------------------------------+---------------------------------------------+ | Event handle | Description | +---------------------------------------------+---------------------------------------------+ -| in_accel_gesture_doubletap_en | Enable double tap detection on all axis | +| in_accel_gesture_doubletap_en | Enable double tap detection on all axes | +---------------------------------------------+---------------------------------------------+ | in_accel_gesture_doubletap_reset_timeout | Double tap window in [us] | +---------------------------------------------+---------------------------------------------+ -| in_accel_gesture_doubletap_tap2_min_delay | Double tap latent in [us] | +| in_accel_gesture_doubletap_scale | Double tap gesture threshold scale. | ++---------------------------------------------+---------------------------------------------+ +| in_accel_gesture_doubletap_tap2_min_delay | Double tap latency in [us] | ++---------------------------------------------+---------------------------------------------+ +| in_accel_gesture_doubletap_value | Double tap threshold value | ++---------------------------------------------+---------------------------------------------+ +| in_accel_gesture_singletap_scale | Single tap gesture threshold scale. | +---------------------------------------------+---------------------------------------------+ | in_accel_gesture_singletap_timeout | Single tap duration in [us] | +---------------------------------------------+---------------------------------------------+ -| in_accel_gesture_singletap_value | Single tap threshold value in 62.5/LSB | -+---------------------------------------------+---------------------------------------------+ -| in_accel_mag_falling_period | Inactivity time in seconds | -+---------------------------------------------+---------------------------------------------+ -| in_accel_mag_falling_value | Inactivity threshold value in 62.5/LSB | -+---------------------------------------------+---------------------------------------------+ -| in_accel_mag_adaptive_rising_en | Enable AC coupled activity on X axis | +| in_accel_gesture_singletap_value | Single tap threshold value | +---------------------------------------------+---------------------------------------------+ | in_accel_mag_adaptive_falling_period | AC coupled inactivity time in seconds | +---------------------------------------------+---------------------------------------------+ -| in_accel_mag_adaptive_falling_value | AC coupled inactivity threshold in 62.5/LSB | +| in_accel_mag_adaptive_falling_scale | AC coupled inactivity threshold scale. | +---------------------------------------------+---------------------------------------------+ -| in_accel_mag_adaptive_rising_value | AC coupled activity threshold in 62.5/LSB | +| in_accel_mag_adaptive_falling_value | AC coupled inactivity threshold | ++---------------------------------------------+---------------------------------------------+ +| in_accel_mag_adaptive_rising_en | Enable AC coupled activity on X axis | ++---------------------------------------------+---------------------------------------------+ +| in_accel_mag_adaptive_rising_scale | AC coupled activity threshold scale. | ++---------------------------------------------+---------------------------------------------+ +| in_accel_mag_adaptive_rising_value | AC coupled activity threshold | ++---------------------------------------------+---------------------------------------------+ +| in_accel_mag_falling_period | Inactivity time in seconds | ++---------------------------------------------+---------------------------------------------+ +| in_accel_mag_falling_scale | DC coupled inactivity threshold scale. | ++---------------------------------------------+---------------------------------------------+ +| in_accel_mag_falling_value | Inactivity threshold value | +---------------------------------------------+---------------------------------------------+ | in_accel_mag_rising_en | Enable activity detection on X axis | +---------------------------------------------+---------------------------------------------+ -| in_accel_mag_rising_value | Activity threshold value in 62.5/LSB | +| in_accel_mag_rising_scale | DC coupled activity threshold scale. | ++---------------------------------------------+---------------------------------------------+ +| in_accel_mag_rising_value | Activity threshold value | ++---------------------------------------------+---------------------------------------------+ +| in_accel_x&y&z_mag_adaptive_falling_en | Enable AC coupled inactivity on all axes | ++---------------------------------------------+---------------------------------------------+ +| in_accel_x&y&z_mag_falling_en | Enable inactivity detection on all axes | +---------------------------------------------+---------------------------------------------+ | in_accel_x_gesture_singletap_en | Enable single tap detection on X axis | +---------------------------------------------+---------------------------------------------+ -| in_accel_x&y&z_mag_falling_en | Enable inactivity detection on all axis | -+---------------------------------------------+---------------------------------------------+ -| in_accel_x&y&z_mag_adaptive_falling_en | Enable AC coupled inactivity on all axis | -+---------------------------------------------+---------------------------------------------+ | in_accel_y_gesture_singletap_en | Enable single tap detection on Y axis | +---------------------------------------------+---------------------------------------------+ | in_accel_z_gesture_singletap_en | Enable single tap detection on Z axis | @@ -140,8 +159,8 @@ When changing the **g range** configuration, the driver attempts to estimate appropriate activity and inactivity thresholds by scaling the default values based on the ratio of the previous range to the new one. The resulting threshold will never be zero and will always fall between 1 and 255, corresponding to up -to 62.5 g/LSB as specified in the datasheet. However, you can override these -estimated thresholds by setting explicit values. +to 62.5 mg/LSB (0.612915 m/s^2/LSB) as specified in the datasheet. However, +you can override these estimated thresholds by setting explicit values. When **activity** and **inactivity** events are enabled, the driver automatically manages hysteresis behavior by setting the **link** and @@ -270,13 +289,13 @@ Scale range configuration: .. code-block:: bash root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale - 0.478899 + 0.004789 root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale_available - 0.478899 0.957798 1.915595 3.831190 + 0.004789 0.009578 0.019156 0.038312 - root:/sys/bus/iio/devices/iio:device0> echo 1.915595 > ./in_accel_scale + root:/sys/bus/iio/devices/iio:device0> echo 0.019156 > ./in_accel_scale root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale - 1.915595 + 0.019156 Set output data rate (ODR): @@ -312,10 +331,14 @@ Configure one or several events: root:/sys/bus/iio/devices/iio:device0> echo 24 > ./buffer0/length - ## AC coupled activity, threshold [62.5/LSB] + ## Check the event scale factor (0.0625 * 9.80665) + root:/sys/bus/iio/devices/iio:device0> cat ./events/in_accel_gesture_doubletap_scale + 0.612915 + + ## AC coupled activity, threshold [0.612915 m/s^2/LSB] root:/sys/bus/iio/devices/iio:device0> echo 6 > ./events/in_accel_mag_adaptive_rising_value - ## AC coupled inactivity, threshold, [62.5/LSB] + ## AC coupled inactivity, threshold, [0.612915 m/s^2/LSB] root:/sys/bus/iio/devices/iio:device0> echo 4 > ./events/in_accel_mag_adaptive_falling_value ## AC coupled inactivity, time [s] @@ -330,7 +353,7 @@ Configure one or several events: ## doubletap, window [us] root:/sys/bus/iio/devices/iio:device0> echo 0.025 > ./events/in_accel_gesture_doubletap_reset_timeout - ## doubletap, latent [us] + ## doubletap, latency [us] root:/sys/bus/iio/devices/iio:device0> echo 0.025 > ./events/in_accel_gesture_doubletap_tap2_min_delay ## AC coupled activity, enable diff --git a/MAINTAINERS b/MAINTAINERS index 96ea84948d76..48fda1f8332e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -651,8 +651,11 @@ W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/accel/adi,adxl367.yaml F: drivers/iio/accel/adxl367* -ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER +ADXL371/ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER M: Michael Hennerich +M: Marcelo Schmitt +M: Nuno Sá +M: Antoniu Miclaus S: Supported W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml @@ -1591,6 +1594,15 @@ W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml F: drivers/iio/adc/ad7780.c +ANALOG DEVICES INC AD8366 DRIVER +M: Michael Hennerich +M: Rodrigo Alencar +L: linux-iio@vger.kernel.org +S: Supported +W: https://ez.analog.com/linux-software-drivers +F: Documentation/devicetree/bindings/iio/amplifiers/adi,ad8366.yaml +F: drivers/iio/amplifiers/ad8366.c + ANALOG DEVICES INC AD9467 DRIVER M: Michael Hennerich M: Nuno Sa @@ -1699,6 +1711,14 @@ S: Supported W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml +ANALOG DEVICES INC ADL8113 DRIVER +M: Antoniu Miclaus +L: linux-iio@vger.kernel.org +S: Supported +W: https://ez.analog.com/linux-software-drivers +F: Documentation/devicetree/bindings/iio/amplifiers/adi,adl8113.yaml +F: drivers/iio/amplifiers/adl8113.c + ANALOG DEVICES INC ADM1177 DRIVER M: Michael Hennerich L: linux-hwmon@vger.kernel.org @@ -25085,6 +25105,13 @@ S: Maintained F: Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml F: drivers/iio/proximity/vl53l0x-i2c.c +ST VL53L1X ToF RANGER(I2C) IIO DRIVER +M: Siratul Islam +L: linux-iio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml +F: drivers/iio/proximity/vl53l1x-i2c.c + STABLE BRANCH M: Greg Kroah-Hartman M: Sasha Levin diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 3d3f8d8673dd..4094299e2ed8 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -158,24 +158,24 @@ config ADXL372 select IIO_TRIGGERED_BUFFER config ADXL372_SPI - tristate "Analog Devices ADXL372 3-Axis Accelerometer SPI Driver" + tristate "Analog Devices ADXL371/ADXL372 3-Axis Accelerometer SPI Driver" depends on SPI select ADXL372 select REGMAP_SPI help - Say yes here to add support for the Analog Devices ADXL372 triaxial - acceleration sensor. + Say yes here to add support for the Analog Devices ADXL371/ADXL372 + triaxial acceleration sensor. To compile this driver as a module, choose M here: the module will be called adxl372_spi. config ADXL372_I2C - tristate "Analog Devices ADXL372 3-Axis Accelerometer I2C Driver" + tristate "Analog Devices ADXL371/ADXL372 3-Axis Accelerometer I2C Driver" depends on I2C select ADXL372 select REGMAP_I2C help - Say yes here to add support for the Analog Devices ADXL372 triaxial - acceleration sensor. + Say yes here to add support for the Analog Devices ADXL371/ADXL372 + triaxial acceleration sensor. To compile this driver as a module, choose M here: the module will be called adxl372_i2c. diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c index 5127e58eebc7..ba0f97944c6d 100644 --- a/drivers/iio/accel/adis16201.c +++ b/drivers/iio/accel/adis16201.c @@ -147,7 +147,7 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, /* * The raw ADC value is 1278 when the temperature * is 25 degrees and the scale factor per milli - * degree celcius is -470. + * degree Celsius is -470. */ *val = 25000 / -470 - 1278; return IIO_VAL_INT; diff --git a/drivers/iio/accel/adis16209.c b/drivers/iio/accel/adis16209.c index 41ffd92f27fd..04e169f221c4 100644 --- a/drivers/iio/accel/adis16209.c +++ b/drivers/iio/accel/adis16209.c @@ -186,7 +186,7 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, /* * The raw ADC value is 0x4FE when the temperature * is 45 degrees and the scale factor per milli - * degree celcius is -470. + * degree Celsius is -470. */ *val = 25000 / -470 - 0x4FE; return IIO_VAL_INT; diff --git a/drivers/iio/accel/adxl313_core.c b/drivers/iio/accel/adxl313_core.c index 9f5d4d2cb325..084037c89ad3 100644 --- a/drivers/iio/accel/adxl313_core.c +++ b/drivers/iio/accel/adxl313_core.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -356,19 +357,15 @@ static int adxl313_read_axis(struct adxl313_data *data, { int ret; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); ret = regmap_bulk_read(data->regmap, ADXL313_REG_DATA_AXIS(chan->address), &data->transf_buf, sizeof(data->transf_buf)); if (ret) - goto unlock_ret; + return ret; - ret = le16_to_cpu(data->transf_buf); - -unlock_ret: - mutex_unlock(&data->lock); - return ret; + return le16_to_cpu(data->transf_buf); } static int adxl313_read_freq_avail(struct iio_dev *indio_dev, diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 78e3f799ecc1..6c9080d88c60 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -213,6 +213,7 @@ static const struct iio_event_spec adxl345_events[] = { .dir = IIO_EV_DIR_RISING, .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_SCALE) | BIT(IIO_EV_INFO_VALUE), }, { @@ -221,6 +222,7 @@ static const struct iio_event_spec adxl345_events[] = { .dir = IIO_EV_DIR_RISING, .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_SCALE) | BIT(IIO_EV_INFO_VALUE), }, { @@ -228,14 +230,19 @@ static const struct iio_event_spec adxl345_events[] = { .type = IIO_EV_TYPE_GESTURE, .dir = IIO_EV_DIR_SINGLETAP, .mask_separate = BIT(IIO_EV_INFO_ENABLE), - .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | + .mask_shared_by_type = + BIT(IIO_EV_INFO_SCALE) | + BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_TIMEOUT), }, { /* double tap */ .type = IIO_EV_TYPE_GESTURE, .dir = IIO_EV_DIR_DOUBLETAP, - .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | + .mask_shared_by_type = + BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_SCALE) | + BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_RESET_TIMEOUT) | BIT(IIO_EV_INFO_TAP2_MIN_DELAY), }, @@ -274,6 +281,7 @@ static const struct iio_event_spec adxl345_fake_chan_events[] = { .dir = IIO_EV_DIR_FALLING, .mask_separate = BIT(IIO_EV_INFO_ENABLE), .mask_shared_by_type = + BIT(IIO_EV_INFO_SCALE) | BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_PERIOD), }, @@ -283,6 +291,7 @@ static const struct iio_event_spec adxl345_fake_chan_events[] = { .dir = IIO_EV_DIR_FALLING, .mask_separate = BIT(IIO_EV_INFO_ENABLE), .mask_shared_by_type = + BIT(IIO_EV_INFO_SCALE) | BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_PERIOD), }, @@ -1341,6 +1350,16 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, unsigned int tap_threshold; int ret; + /* + * The event threshold LSB is fixed at 62.5 mg/LSB + * 0.0625 * 9.80665 = 0.612915625 m/s^2 + */ + if (info == IIO_EV_INFO_SCALE) { + *val = 0; + *val2 = 612915; + return IIO_VAL_INT_PLUS_MICRO; + } + switch (type) { case IIO_EV_TYPE_MAG: return adxl345_read_mag_value(st, dir, info, @@ -1355,12 +1374,6 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, case IIO_EV_TYPE_GESTURE: switch (info) { case IIO_EV_INFO_VALUE: - /* - * The scale factor would be 62.5mg/LSB (i.e. 0xFF = 16g) but - * not applied here. In context of this general purpose sensor, - * what imports is rather signal intensity than the absolute - * measured g value. - */ ret = regmap_read(st->regmap, ADXL345_REG_THRESH_TAP, &tap_threshold); if (ret) @@ -1401,6 +1414,9 @@ static int adxl345_write_event_value(struct iio_dev *indio_dev, if (ret) return ret; + if (info == IIO_EV_INFO_SCALE) + return -EINVAL; + switch (type) { case IIO_EV_TYPE_MAG: ret = adxl345_write_mag_value(st, dir, info, diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c index 28a8793a53b6..545a21e5a308 100644 --- a/drivers/iio/accel/adxl372.c +++ b/drivers/iio/accel/adxl372.c @@ -1,12 +1,13 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * ADXL372 3-Axis Digital Accelerometer core driver + * ADXL371/ADXL372 3-Axis Digital Accelerometer core driver * * Copyright 2018 Analog Devices Inc. */ #include #include +#include #include #include #include @@ -180,6 +181,16 @@ enum adxl372_odr { ADXL372_ODR_1600HZ, ADXL372_ODR_3200HZ, ADXL372_ODR_6400HZ, + ADXL372_ODR_NUM +}; + +enum adxl371_odr { + ADXL371_ODR_320HZ, + ADXL371_ODR_640HZ, + ADXL371_ODR_1280HZ, + ADXL371_ODR_2560HZ, + ADXL371_ODR_5120HZ, + ADXL371_ODR_NUM }; enum adxl372_bandwidth { @@ -214,14 +225,67 @@ enum adxl372_fifo_mode { ADXL372_FIFO_OLD_SAVED }; -static const int adxl372_samp_freq_tbl[5] = { - 400, 800, 1600, 3200, 6400, +static const int adxl372_samp_freq_tbl[ADXL372_ODR_NUM] = { + [ADXL372_ODR_400HZ] = 400, + [ADXL372_ODR_800HZ] = 800, + [ADXL372_ODR_1600HZ] = 1600, + [ADXL372_ODR_3200HZ] = 3200, + [ADXL372_ODR_6400HZ] = 6400, }; -static const int adxl372_bw_freq_tbl[5] = { - 200, 400, 800, 1600, 3200, +static const int adxl372_bw_freq_tbl[ADXL372_ODR_NUM] = { + [ADXL372_BW_200HZ] = 200, + [ADXL372_BW_400HZ] = 400, + [ADXL372_BW_800HZ] = 800, + [ADXL372_BW_1600HZ] = 1600, + [ADXL372_BW_3200HZ] = 3200, }; +static const int adxl371_samp_freq_tbl[ADXL371_ODR_NUM] = { + [ADXL371_ODR_320HZ] = 320, + [ADXL371_ODR_640HZ] = 640, + [ADXL371_ODR_1280HZ] = 1280, + [ADXL371_ODR_2560HZ] = 2560, + [ADXL371_ODR_5120HZ] = 5120, +}; + +static const int adxl371_bw_freq_tbl[ADXL371_ODR_NUM] = { + [ADXL371_ODR_320HZ] = 160, + [ADXL371_ODR_640HZ] = 320, + [ADXL371_ODR_1280HZ] = 640, + [ADXL371_ODR_2560HZ] = 1280, + [ADXL371_ODR_5120HZ] = 2560, +}; + +const struct adxl372_chip_info adxl371_chip_info = { + .name = "adxl371", + .samp_freq_tbl = adxl371_samp_freq_tbl, + .bw_freq_tbl = adxl371_bw_freq_tbl, + .num_freqs = ARRAY_SIZE(adxl371_samp_freq_tbl), + .act_time_scale_us = 4125, + .act_time_scale_low_us = 8250, + .inact_time_scale_ms = 16, + .inact_time_scale_low_ms = 32, + .max_odr = ADXL371_ODR_5120HZ, + /* Silicon erratum (er001) causes FIFO data misalignment on ADXL371 */ + .fifo_supported = false, +}; +EXPORT_SYMBOL_NS_GPL(adxl371_chip_info, "IIO_ADXL372"); + +const struct adxl372_chip_info adxl372_chip_info = { + .name = "adxl372", + .samp_freq_tbl = adxl372_samp_freq_tbl, + .bw_freq_tbl = adxl372_bw_freq_tbl, + .num_freqs = ARRAY_SIZE(adxl372_samp_freq_tbl), + .act_time_scale_us = 3300, + .act_time_scale_low_us = 6600, + .inact_time_scale_ms = 13, + .inact_time_scale_low_ms = 26, + .max_odr = ADXL372_ODR_6400HZ, + .fifo_supported = true, +}; +EXPORT_SYMBOL_NS_GPL(adxl372_chip_info, "IIO_ADXL372"); + struct adxl372_axis_lookup { unsigned int bits; enum adxl372_fifo_format fifo_format; @@ -257,8 +321,12 @@ static const struct iio_event_spec adxl372_events[] = { .modified = 1, \ .channel2 = IIO_MOD_##axis, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ - BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + .info_mask_shared_by_type = \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ + .info_mask_shared_by_type_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ .scan_index = index, \ .scan_type = { \ @@ -279,6 +347,7 @@ static const struct iio_chan_spec adxl372_channels[] = { }; struct adxl372_state { + const struct adxl372_chip_info *chip_info; int irq; struct device *dev; struct regmap *regmap; @@ -336,18 +405,14 @@ static ssize_t adxl372_write_threshold_value(struct iio_dev *indio_dev, unsigned struct adxl372_state *st = iio_priv(indio_dev); int ret; - mutex_lock(&st->threshold_m); + guard(mutex)(&st->threshold_m); + ret = regmap_write(st->regmap, addr, ADXL372_THRESH_VAL_H_SEL(threshold)); if (ret < 0) - goto unlock; + return ret; - ret = regmap_update_bits(st->regmap, addr + 1, GENMASK(7, 5), - ADXL372_THRESH_VAL_L_SEL(threshold) << 5); - -unlock: - mutex_unlock(&st->threshold_m); - - return ret; + return regmap_update_bits(st->regmap, addr + 1, GENMASK(7, 5), + ADXL372_THRESH_VAL_L_SEL(threshold) << 5); } static int adxl372_read_axis(struct adxl372_state *st, u8 addr) @@ -471,13 +536,14 @@ static int adxl372_set_activity_time_ms(struct adxl372_state *st, int ret; /* - * 3.3 ms per code is the scale factor of the TIME_ACT register for - * ODR = 6400 Hz. It is 6.6 ms per code for ODR = 3200 Hz and below. + * The scale factor of the TIME_ACT register depends on the ODR. + * A higher scale factor is used at the maximum ODR and a lower + * one at all other rates. */ - if (st->odr == ADXL372_ODR_6400HZ) - scale_factor = 3300; + if (st->odr == st->chip_info->max_odr) + scale_factor = st->chip_info->act_time_scale_us; else - scale_factor = 6600; + scale_factor = st->chip_info->act_time_scale_low_us; reg_val = DIV_ROUND_CLOSEST(act_time_ms * 1000, scale_factor); @@ -501,13 +567,14 @@ static int adxl372_set_inactivity_time_ms(struct adxl372_state *st, int ret; /* - * 13 ms per code is the scale factor of the TIME_INACT register for - * ODR = 6400 Hz. It is 26 ms per code for ODR = 3200 Hz and below. + * The scale factor of the TIME_INACT register depends on the ODR. + * A higher scale factor is used at the maximum ODR and a lower + * one at all other rates. */ - if (st->odr == ADXL372_ODR_6400HZ) - scale_factor = 13; + if (st->odr == st->chip_info->max_odr) + scale_factor = st->chip_info->inact_time_scale_ms; else - scale_factor = 26; + scale_factor = st->chip_info->inact_time_scale_low_ms; res = DIV_ROUND_CLOSEST(inact_time_ms, scale_factor); reg_val_h = (res >> 8) & 0xFF; @@ -717,7 +784,7 @@ static int adxl372_setup(struct adxl372_state *st) if (ret < 0) return ret; - ret = adxl372_set_odr(st, ADXL372_ODR_6400HZ); + ret = adxl372_set_odr(st, st->chip_info->max_odr); if (ret < 0) return ret; @@ -777,10 +844,10 @@ static int adxl372_read_raw(struct iio_dev *indio_dev, *val2 = ADXL372_USCALE; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_SAMP_FREQ: - *val = adxl372_samp_freq_tbl[st->odr]; + *val = st->chip_info->samp_freq_tbl[st->odr]; return IIO_VAL_INT; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - *val = adxl372_bw_freq_tbl[st->bw]; + *val = st->chip_info->bw_freq_tbl[st->bw]; return IIO_VAL_INT; } @@ -796,23 +863,17 @@ static int adxl372_write_raw(struct iio_dev *indio_dev, switch (info) { case IIO_CHAN_INFO_SAMP_FREQ: - odr_index = adxl372_find_closest_match(adxl372_samp_freq_tbl, - ARRAY_SIZE(adxl372_samp_freq_tbl), - val); + odr_index = adxl372_find_closest_match(st->chip_info->samp_freq_tbl, + st->chip_info->num_freqs, + val); ret = adxl372_set_odr(st, odr_index); if (ret < 0) return ret; - /* - * The timer period depends on the ODR selected. - * At 3200 Hz and below, it is 6.6 ms; at 6400 Hz, it is 3.3 ms - */ + /* Recalculate activity time as the timer period depends on ODR */ ret = adxl372_set_activity_time_ms(st, st->act_time_ms); if (ret < 0) return ret; - /* - * The timer period depends on the ODR selected. - * At 3200 Hz and below, it is 26 ms; at 6400 Hz, it is 13 ms - */ + /* Recalculate inactivity time as the timer period depends on ODR */ ret = adxl372_set_inactivity_time_ms(st, st->inact_time_ms); if (ret < 0) return ret; @@ -825,9 +886,9 @@ static int adxl372_write_raw(struct iio_dev *indio_dev, return ret; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - bw_index = adxl372_find_closest_match(adxl372_bw_freq_tbl, - ARRAY_SIZE(adxl372_bw_freq_tbl), - val); + bw_index = adxl372_find_closest_match(st->chip_info->bw_freq_tbl, + st->chip_info->num_freqs, + val); return adxl372_set_bandwidth(st, bw_index); default: return -EINVAL; @@ -957,24 +1018,6 @@ static int adxl372_write_event_config(struct iio_dev *indio_dev, const struct ii return adxl372_set_interrupts(st, st->int1_bitmask, 0); } -static ssize_t adxl372_show_filter_freq_avail(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct adxl372_state *st = iio_priv(indio_dev); - int i; - size_t len = 0; - - for (i = 0; i <= st->odr; i++) - len += scnprintf(buf + len, PAGE_SIZE - len, - "%d ", adxl372_bw_freq_tbl[i]); - - buf[len - 1] = '\n'; - - return len; -} - static ssize_t adxl372_get_fifo_enabled(struct device *dev, struct device_attribute *attr, char *buf) @@ -1142,25 +1185,38 @@ static const struct iio_trigger_ops adxl372_peak_data_trigger_ops = { .set_trigger_state = adxl372_peak_dready_trig_set_state, }; -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400"); -static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available, - 0444, adxl372_show_filter_freq_avail, NULL, 0); +static int adxl372_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + struct adxl372_state *st = iio_priv(indio_dev); -static struct attribute *adxl372_attributes[] = { - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group adxl372_attrs_group = { - .attrs = adxl372_attributes, -}; + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = st->chip_info->samp_freq_tbl; + *type = IIO_VAL_INT; + *length = st->chip_info->num_freqs; + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + *vals = st->chip_info->bw_freq_tbl; + *type = IIO_VAL_INT; + /* + * Bandwidth cannot exceed half the sampling frequency + * (Nyquist), so limit available values based on current ODR. + */ + *length = st->odr + 1; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} static const struct iio_info adxl372_info = { .validate_trigger = &adxl372_validate_trigger, - .attrs = &adxl372_attrs_group, .read_raw = adxl372_read_raw, .write_raw = adxl372_write_raw, + .read_avail = adxl372_read_avail, .read_event_config = adxl372_read_event_config, .write_event_config = adxl372_write_event_config, .read_event_value = adxl372_read_event_value, @@ -1175,8 +1231,57 @@ bool adxl372_readable_noinc_reg(struct device *dev, unsigned int reg) } EXPORT_SYMBOL_NS_GPL(adxl372_readable_noinc_reg, "IIO_ADXL372"); +static int adxl372_buffer_setup(struct iio_dev *indio_dev) +{ + struct adxl372_state *st = iio_priv(indio_dev); + struct device *dev = st->dev; + int ret; + + ret = devm_iio_triggered_buffer_setup_ext(dev, indio_dev, NULL, + adxl372_trigger_handler, + IIO_BUFFER_DIRECTION_IN, + &adxl372_buffer_ops, + adxl372_fifo_attributes); + if (ret) + return ret; + + if (!st->irq) + return 0; + + st->dready_trig = devm_iio_trigger_alloc(dev, "%s-dev%d", + indio_dev->name, + iio_device_id(indio_dev)); + if (!st->dready_trig) + return -ENOMEM; + + st->peak_datardy_trig = devm_iio_trigger_alloc(dev, "%s-dev%d-peak", + indio_dev->name, + iio_device_id(indio_dev)); + if (!st->peak_datardy_trig) + return -ENOMEM; + + st->dready_trig->ops = &adxl372_trigger_ops; + st->peak_datardy_trig->ops = &adxl372_peak_data_trigger_ops; + iio_trigger_set_drvdata(st->dready_trig, indio_dev); + iio_trigger_set_drvdata(st->peak_datardy_trig, indio_dev); + ret = devm_iio_trigger_register(dev, st->dready_trig); + if (ret) + return ret; + + ret = devm_iio_trigger_register(dev, st->peak_datardy_trig); + if (ret) + return ret; + + indio_dev->trig = iio_trigger_get(st->dready_trig); + + return devm_request_irq(dev, st->irq, + iio_trigger_generic_data_rdy_poll, + IRQF_TRIGGER_RISING | IRQF_NO_THREAD, + indio_dev->name, st->dready_trig); +} + int adxl372_probe(struct device *dev, struct regmap *regmap, - int irq, const char *name) + int irq, const struct adxl372_chip_info *chip_info) { struct iio_dev *indio_dev; struct adxl372_state *st; @@ -1192,15 +1297,21 @@ int adxl372_probe(struct device *dev, struct regmap *regmap, st->dev = dev; st->regmap = regmap; st->irq = irq; + st->chip_info = chip_info; mutex_init(&st->threshold_m); indio_dev->channels = adxl372_channels; indio_dev->num_channels = ARRAY_SIZE(adxl372_channels); - indio_dev->available_scan_masks = adxl372_channel_masks; - indio_dev->name = name; + indio_dev->name = chip_info->name; indio_dev->info = &adxl372_info; - indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; + + if (chip_info->fifo_supported) { + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; + indio_dev->available_scan_masks = adxl372_channel_masks; + } else { + indio_dev->modes = INDIO_DIRECT_MODE; + } ret = adxl372_setup(st); if (ret < 0) { @@ -1208,48 +1319,8 @@ int adxl372_probe(struct device *dev, struct regmap *regmap, return ret; } - ret = devm_iio_triggered_buffer_setup_ext(dev, - indio_dev, NULL, - adxl372_trigger_handler, - IIO_BUFFER_DIRECTION_IN, - &adxl372_buffer_ops, - adxl372_fifo_attributes); - if (ret < 0) - return ret; - - if (st->irq) { - st->dready_trig = devm_iio_trigger_alloc(dev, - "%s-dev%d", - indio_dev->name, - iio_device_id(indio_dev)); - if (st->dready_trig == NULL) - return -ENOMEM; - - st->peak_datardy_trig = devm_iio_trigger_alloc(dev, - "%s-dev%d-peak", - indio_dev->name, - iio_device_id(indio_dev)); - if (!st->peak_datardy_trig) - return -ENOMEM; - - st->dready_trig->ops = &adxl372_trigger_ops; - st->peak_datardy_trig->ops = &adxl372_peak_data_trigger_ops; - iio_trigger_set_drvdata(st->dready_trig, indio_dev); - iio_trigger_set_drvdata(st->peak_datardy_trig, indio_dev); - ret = devm_iio_trigger_register(dev, st->dready_trig); - if (ret < 0) - return ret; - - ret = devm_iio_trigger_register(dev, st->peak_datardy_trig); - if (ret < 0) - return ret; - - indio_dev->trig = iio_trigger_get(st->dready_trig); - - ret = devm_request_irq(dev, st->irq, - iio_trigger_generic_data_rdy_poll, - IRQF_TRIGGER_RISING | IRQF_NO_THREAD, - indio_dev->name, st->dready_trig); + if (chip_info->fifo_supported) { + ret = adxl372_buffer_setup(indio_dev); if (ret < 0) return ret; } @@ -1259,5 +1330,6 @@ int adxl372_probe(struct device *dev, struct regmap *regmap, EXPORT_SYMBOL_NS_GPL(adxl372_probe, "IIO_ADXL372"); MODULE_AUTHOR("Stefan Popa "); -MODULE_DESCRIPTION("Analog Devices ADXL372 3-axis accelerometer driver"); +MODULE_AUTHOR("Antoniu Miclaus "); +MODULE_DESCRIPTION("Analog Devices ADXL371/ADXL372 3-axis accelerometer driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/iio/accel/adxl372.h b/drivers/iio/accel/adxl372.h index 80a0aa9714fc..353a8b3a9d76 100644 --- a/drivers/iio/accel/adxl372.h +++ b/drivers/iio/accel/adxl372.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * ADXL372 3-Axis Digital Accelerometer + * ADXL371/ADXL372 3-Axis Digital Accelerometer * * Copyright 2018 Analog Devices Inc. */ @@ -10,8 +10,24 @@ #define ADXL372_REVID 0x03 +struct adxl372_chip_info { + const char *name; + const int *samp_freq_tbl; + const int *bw_freq_tbl; + unsigned int num_freqs; + unsigned int act_time_scale_us; + unsigned int act_time_scale_low_us; + unsigned int inact_time_scale_ms; + unsigned int inact_time_scale_low_ms; + unsigned int max_odr; + bool fifo_supported; +}; + +extern const struct adxl372_chip_info adxl371_chip_info; +extern const struct adxl372_chip_info adxl372_chip_info; + int adxl372_probe(struct device *dev, struct regmap *regmap, - int irq, const char *name); + int irq, const struct adxl372_chip_info *chip_info); bool adxl372_readable_noinc_reg(struct device *dev, unsigned int reg); #endif /* _ADXL372_H_ */ diff --git a/drivers/iio/accel/adxl372_i2c.c b/drivers/iio/accel/adxl372_i2c.c index 186d4fe9a556..ca2cabf24938 100644 --- a/drivers/iio/accel/adxl372_i2c.c +++ b/drivers/iio/accel/adxl372_i2c.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * ADXL372 3-Axis Digital Accelerometer I2C driver + * ADXL371/ADXL372 3-Axis Digital Accelerometer I2C driver * * Copyright 2018 Analog Devices Inc. */ @@ -20,11 +20,13 @@ static const struct regmap_config adxl372_regmap_config = { static int adxl372_i2c_probe(struct i2c_client *client) { - const struct i2c_device_id *id = i2c_client_get_device_id(client); + const struct adxl372_chip_info *chip_info; struct regmap *regmap; unsigned int regval; int ret; + chip_info = i2c_get_match_data(client); + regmap = devm_regmap_init_i2c(client, &adxl372_regmap_config); if (IS_ERR(regmap)) return PTR_ERR(regmap); @@ -38,17 +40,19 @@ static int adxl372_i2c_probe(struct i2c_client *client) dev_warn(&client->dev, "I2C might not work properly with other devices on the bus"); - return adxl372_probe(&client->dev, regmap, client->irq, id->name); + return adxl372_probe(&client->dev, regmap, client->irq, chip_info); } static const struct i2c_device_id adxl372_i2c_id[] = { - { "adxl372" }, + { "adxl371", (kernel_ulong_t)&adxl371_chip_info }, + { "adxl372", (kernel_ulong_t)&adxl372_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, adxl372_i2c_id); static const struct of_device_id adxl372_of_match[] = { - { .compatible = "adi,adxl372" }, + { .compatible = "adi,adxl371", .data = &adxl371_chip_info }, + { .compatible = "adi,adxl372", .data = &adxl372_chip_info }, { } }; MODULE_DEVICE_TABLE(of, adxl372_of_match); @@ -65,6 +69,7 @@ static struct i2c_driver adxl372_i2c_driver = { module_i2c_driver(adxl372_i2c_driver); MODULE_AUTHOR("Stefan Popa "); -MODULE_DESCRIPTION("Analog Devices ADXL372 3-axis accelerometer I2C driver"); +MODULE_AUTHOR("Antoniu Miclaus "); +MODULE_DESCRIPTION("Analog Devices ADXL371/ADXL372 3-axis accelerometer I2C driver"); MODULE_LICENSE("GPL"); MODULE_IMPORT_NS("IIO_ADXL372"); diff --git a/drivers/iio/accel/adxl372_spi.c b/drivers/iio/accel/adxl372_spi.c index 39941b519c3b..1f9c1544e547 100644 --- a/drivers/iio/accel/adxl372_spi.c +++ b/drivers/iio/accel/adxl372_spi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * ADXL372 3-Axis Digital Accelerometer SPI driver + * ADXL371/ADXL372 3-Axis Digital Accelerometer SPI driver * * Copyright 2018 Analog Devices Inc. */ @@ -22,24 +22,28 @@ static const struct regmap_config adxl372_spi_regmap_config = { static int adxl372_spi_probe(struct spi_device *spi) { - const struct spi_device_id *id = spi_get_device_id(spi); + const struct adxl372_chip_info *chip_info; struct regmap *regmap; + chip_info = spi_get_device_match_data(spi); + regmap = devm_regmap_init_spi(spi, &adxl372_spi_regmap_config); if (IS_ERR(regmap)) return PTR_ERR(regmap); - return adxl372_probe(&spi->dev, regmap, spi->irq, id->name); + return adxl372_probe(&spi->dev, regmap, spi->irq, chip_info); } static const struct spi_device_id adxl372_spi_id[] = { - { "adxl372", 0 }, + { "adxl371", (kernel_ulong_t)&adxl371_chip_info }, + { "adxl372", (kernel_ulong_t)&adxl372_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, adxl372_spi_id); static const struct of_device_id adxl372_of_match[] = { - { .compatible = "adi,adxl372" }, + { .compatible = "adi,adxl371", .data = &adxl371_chip_info }, + { .compatible = "adi,adxl372", .data = &adxl372_chip_info }, { } }; MODULE_DEVICE_TABLE(of, adxl372_of_match); @@ -56,6 +60,7 @@ static struct spi_driver adxl372_spi_driver = { module_spi_driver(adxl372_spi_driver); MODULE_AUTHOR("Stefan Popa "); -MODULE_DESCRIPTION("Analog Devices ADXL372 3-axis accelerometer SPI driver"); +MODULE_AUTHOR("Antoniu Miclaus "); +MODULE_DESCRIPTION("Analog Devices ADXL371/ADXL372 3-axis accelerometer SPI driver"); MODULE_LICENSE("GPL"); MODULE_IMPORT_NS("IIO_ADXL372"); diff --git a/drivers/iio/accel/adxl380.c b/drivers/iio/accel/adxl380.c index 8fab2fdbe147..2fc838a234c9 100644 --- a/drivers/iio/accel/adxl380.c +++ b/drivers/iio/accel/adxl380.c @@ -31,7 +31,7 @@ #define ADXL319_ID_VAL 382 #define ADXL380_DEVID_AD_REG 0x00 -#define ADLX380_PART_ID_REG 0x02 +#define ADXL380_PART_ID_REG 0x02 #define ADXL380_X_DATA_H_REG 0x15 #define ADXL380_Y_DATA_H_REG 0x17 @@ -1878,7 +1878,7 @@ static int adxl380_setup(struct iio_dev *indio_dev) if (reg_val != ADXL380_DEVID_AD_VAL) dev_warn(st->dev, "Unknown chip id %x\n", reg_val); - ret = regmap_bulk_read(st->regmap, ADLX380_PART_ID_REG, + ret = regmap_bulk_read(st->regmap, ADXL380_PART_ID_REG, &st->transf_buf, 2); if (ret) return ret; diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c index 42ccf0316ce5..2398eb7e12cd 100644 --- a/drivers/iio/accel/bmc150-accel-core.c +++ b/drivers/iio/accel/bmc150-accel-core.c @@ -851,7 +851,7 @@ static ssize_t bmc150_accel_get_fifo_watermark(struct device *dev, wm = data->watermark; mutex_unlock(&data->mutex); - return sprintf(buf, "%d\n", wm); + return sysfs_emit(buf, "%d\n", wm); } static ssize_t bmc150_accel_get_fifo_state(struct device *dev, @@ -866,7 +866,7 @@ static ssize_t bmc150_accel_get_fifo_state(struct device *dev, state = data->fifo_mode; mutex_unlock(&data->mutex); - return sprintf(buf, "%d\n", state); + return sysfs_emit(buf, "%d\n", state); } static const struct iio_mount_matrix * diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c index 4a827be439a2..573831199bba 100644 --- a/drivers/iio/accel/sca3000.c +++ b/drivers/iio/accel/sca3000.c @@ -7,6 +7,7 @@ * See industrialio/accels/sca3000.h for comments. */ +#include #include #include #include @@ -171,6 +172,7 @@ struct sca3000_state { /** * struct sca3000_chip_info - model dependent parameters + * @name: name of the chip * @scale: scale * 10^-6 * @temp_output: some devices have temperature sensors. * @measurement_mode_freq: normal mode sampling frequency @@ -193,6 +195,7 @@ struct sca3000_state { * sca3000 variant. **/ struct sca3000_chip_info { + const char *name; unsigned int scale; bool temp_output; int measurement_mode_freq; @@ -207,69 +210,59 @@ struct sca3000_chip_info { int mot_det_mult_y[7]; }; -enum sca3000_variant { - d01, - e02, - e04, - e05, +static const struct sca3000_chip_info sca3000_chip_info_d01 = { + .name = "sca3000_d01", + .scale = 7357, + .temp_output = true, + .measurement_mode_freq = 250, + .measurement_mode_3db_freq = 45, + .option_mode_1 = SCA3000_OP_MODE_BYPASS, + .option_mode_1_freq = 250, + .option_mode_1_3db_freq = 70, + .mot_det_mult_xz = { 50, 100, 200, 350, 650, 1300 }, + .mot_det_mult_y = { 50, 100, 150, 250, 450, 850, 1750 }, }; -/* - * Note where option modes are not defined, the chip simply does not - * support any. - * Other chips in the sca3000 series use i2c and are not included here. - * - * Some of these devices are only listed in the family data sheet and - * do not actually appear to be available. - */ -static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = { - [d01] = { - .scale = 7357, - .temp_output = true, - .measurement_mode_freq = 250, - .measurement_mode_3db_freq = 45, - .option_mode_1 = SCA3000_OP_MODE_BYPASS, - .option_mode_1_freq = 250, - .option_mode_1_3db_freq = 70, - .mot_det_mult_xz = {50, 100, 200, 350, 650, 1300}, - .mot_det_mult_y = {50, 100, 150, 250, 450, 850, 1750}, - }, - [e02] = { - .scale = 9810, - .measurement_mode_freq = 125, - .measurement_mode_3db_freq = 40, - .option_mode_1 = SCA3000_OP_MODE_NARROW, - .option_mode_1_freq = 63, - .option_mode_1_3db_freq = 11, - .mot_det_mult_xz = {100, 150, 300, 550, 1050, 2050}, - .mot_det_mult_y = {50, 100, 200, 350, 700, 1350, 2700}, - }, - [e04] = { - .scale = 19620, - .measurement_mode_freq = 100, - .measurement_mode_3db_freq = 38, - .option_mode_1 = SCA3000_OP_MODE_NARROW, - .option_mode_1_freq = 50, - .option_mode_1_3db_freq = 9, - .option_mode_2 = SCA3000_OP_MODE_WIDE, - .option_mode_2_freq = 400, - .option_mode_2_3db_freq = 70, - .mot_det_mult_xz = {200, 300, 600, 1100, 2100, 4100}, - .mot_det_mult_y = {100, 200, 400, 7000, 1400, 2700, 54000}, - }, - [e05] = { - .scale = 61313, - .measurement_mode_freq = 200, - .measurement_mode_3db_freq = 60, - .option_mode_1 = SCA3000_OP_MODE_NARROW, - .option_mode_1_freq = 50, - .option_mode_1_3db_freq = 9, - .option_mode_2 = SCA3000_OP_MODE_WIDE, - .option_mode_2_freq = 400, - .option_mode_2_3db_freq = 75, - .mot_det_mult_xz = {600, 900, 1700, 3200, 6100, 11900}, - .mot_det_mult_y = {300, 600, 1200, 2000, 4100, 7800, 15600}, - }, +static const struct sca3000_chip_info sca3000_chip_info_e02 = { + .name = "sca3000_e02", + .scale = 9810, + .measurement_mode_freq = 125, + .measurement_mode_3db_freq = 40, + .option_mode_1 = SCA3000_OP_MODE_NARROW, + .option_mode_1_freq = 63, + .option_mode_1_3db_freq = 11, + .mot_det_mult_xz = { 100, 150, 300, 550, 1050, 2050 }, + .mot_det_mult_y = { 50, 100, 200, 350, 700, 1350, 2700 }, +}; + +static const struct sca3000_chip_info sca3000_chip_info_e04 = { + .name = "sca3000_e04", + .scale = 19620, + .measurement_mode_freq = 100, + .measurement_mode_3db_freq = 38, + .option_mode_1 = SCA3000_OP_MODE_NARROW, + .option_mode_1_freq = 50, + .option_mode_1_3db_freq = 9, + .option_mode_2 = SCA3000_OP_MODE_WIDE, + .option_mode_2_freq = 400, + .option_mode_2_3db_freq = 70, + .mot_det_mult_xz = { 200, 300, 600, 1100, 2100, 4100 }, + .mot_det_mult_y = { 100, 200, 400, 7000, 1400, 2700, 54000 }, +}; + +static const struct sca3000_chip_info sca3000_chip_info_e05 = { + .name = "sca3000_e05", + .scale = 61313, + .measurement_mode_freq = 200, + .measurement_mode_3db_freq = 60, + .option_mode_1 = SCA3000_OP_MODE_NARROW, + .option_mode_1_freq = 50, + .option_mode_1_3db_freq = 9, + .option_mode_2 = SCA3000_OP_MODE_WIDE, + .option_mode_2_freq = 400, + .option_mode_2_3db_freq = 75, + .mot_det_mult_xz = { 600, 900, 1700, 3200, 6100, 11900 }, + .mot_det_mult_y = { 300, 600, 1200, 2000, 4100, 7800, 15600 }, }; static int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val) @@ -1435,24 +1428,42 @@ static const struct iio_info sca3000_info = { .write_event_config = &sca3000_write_event_config, }; +static void sca3000_stop_all_interrupts(void *data) +{ + struct iio_dev *indio_dev = data; + struct sca3000_state *st = iio_priv(indio_dev); + int ret; + + guard(mutex)(&st->lock); + + ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); + if (ret) + return; + + sca3000_write_reg(st, SCA3000_REG_INT_MASK_ADDR, + (st->rx[0] & + ~(SCA3000_REG_INT_MASK_RING_THREE_QUARTER | + SCA3000_REG_INT_MASK_RING_HALF | + SCA3000_REG_INT_MASK_ALL_INTS))); +} + static int sca3000_probe(struct spi_device *spi) { - int ret; + struct device *dev = &spi->dev; struct sca3000_state *st; struct iio_dev *indio_dev; + int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; st = iio_priv(indio_dev); - spi_set_drvdata(spi, indio_dev); st->us = spi; mutex_init(&st->lock); - st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi) - ->driver_data]; + st->info = spi_get_device_match_data(spi); - indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->name = st->info->name; indio_dev->info = &sca3000_info; if (st->info->temp_output) { indio_dev->channels = sca3000_channels_with_temp; @@ -1464,78 +1475,39 @@ static int sca3000_probe(struct spi_device *spi) } indio_dev->modes = INDIO_DIRECT_MODE; - ret = devm_iio_kfifo_buffer_setup(&spi->dev, indio_dev, - &sca3000_ring_setup_ops); + ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, &sca3000_ring_setup_ops); if (ret) return ret; if (spi->irq) { - ret = request_threaded_irq(spi->irq, - NULL, - &sca3000_event_handler, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "sca3000", - indio_dev); + ret = devm_request_threaded_irq(dev, spi->irq, NULL, + &sca3000_event_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "sca3000", + indio_dev); if (ret) return ret; } ret = sca3000_clean_setup(st); if (ret) - goto error_free_irq; + return ret; ret = sca3000_print_rev(indio_dev); if (ret) - goto error_free_irq; + return ret; - ret = iio_device_register(indio_dev); + ret = devm_add_action_or_reset(dev, sca3000_stop_all_interrupts, indio_dev); if (ret) - goto error_free_irq; + return ret; - return 0; - -error_free_irq: - if (spi->irq) - free_irq(spi->irq, indio_dev); - - return ret; -} - -static int sca3000_stop_all_interrupts(struct sca3000_state *st) -{ - int ret; - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); - if (ret) - goto error_ret; - ret = sca3000_write_reg(st, SCA3000_REG_INT_MASK_ADDR, - (st->rx[0] & - ~(SCA3000_REG_INT_MASK_RING_THREE_QUARTER | - SCA3000_REG_INT_MASK_RING_HALF | - SCA3000_REG_INT_MASK_ALL_INTS))); -error_ret: - mutex_unlock(&st->lock); - return ret; -} - -static void sca3000_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct sca3000_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - /* Must ensure no interrupts can be generated after this! */ - sca3000_stop_all_interrupts(st); - if (spi->irq) - free_irq(spi->irq, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id sca3000_id[] = { - {"sca3000_d01", d01}, - {"sca3000_e02", e02}, - {"sca3000_e04", e04}, - {"sca3000_e05", e05}, + { "sca3000_d01", (kernel_ulong_t)&sca3000_chip_info_d01 }, + { "sca3000_e02", (kernel_ulong_t)&sca3000_chip_info_e02 }, + { "sca3000_e04", (kernel_ulong_t)&sca3000_chip_info_e04 }, + { "sca3000_e05", (kernel_ulong_t)&sca3000_chip_info_e05 }, { } }; MODULE_DEVICE_TABLE(spi, sca3000_id); @@ -1545,7 +1517,6 @@ static struct spi_driver sca3000_driver = { .name = "sca3000", }, .probe = sca3000_probe, - .remove = sca3000_remove, .id_table = sca3000_id, }; module_spi_driver(sca3000_driver); diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 60038ae8dfc4..a9dedbb8eb46 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -60,9 +60,14 @@ config AD4030 tristate "Analog Devices AD4030 ADC Driver" depends on SPI depends on GPIOLIB + depends on PWM select REGMAP select IIO_BUFFER + select IIO_BUFFER_DMA + select IIO_BUFFER_DMAENGINE select IIO_TRIGGERED_BUFFER + select SPI_OFFLOAD + select SPI_OFFLOAD_TRIGGER_PWM help Say yes here to build support for Analog Devices AD4030 and AD4630 high speed SPI analog to digital converters (ADC). @@ -413,8 +418,10 @@ config AD7768_1 select REGMAP_SPI select RATIONAL select IIO_BUFFER + select IIO_BUFFER_DMAENGINE select IIO_TRIGGER select IIO_TRIGGERED_BUFFER + select SPI_OFFLOAD help Say yes here to build support for Analog Devices AD7768-1 SPI simultaneously sampling sigma-delta analog to digital converter (ADC). @@ -1366,6 +1373,32 @@ config QCOM_SPMI_ADC5 To compile this driver as a module, choose M here: the module will be called qcom-spmi-adc5. +config QCOM_SPMI_ADC5_GEN3 + tristate "Qualcomm Technologies Inc. SPMI PMIC5 GEN3 ADC" + depends on SPMI && THERMAL + select REGMAP_SPMI + select QCOM_VADC_COMMON + select AUXILIARY_BUS + help + IIO Voltage PMIC5 Gen3 ADC driver for Qualcomm Technologies Inc. + + The driver supports reading multiple channels. The ADC is a 16-bit + sigma-delta ADC. The hardware supports calibrated results for + conversion requests and clients include reading phone power supply + voltage, on board system thermistors connected to the PMIC ADC, + PMIC die temperature, charger temperature, battery current, USB + voltage input and voltage signals connected to supported PMIC GPIO + pins. The hardware supports internal pull-up for thermistors and can + choose between a 30k, 100k or 400k ohm pull up using the ADC channels. + + In addition, the same driver supports ADC thermal monitoring devices + too. They appear as thermal zones with multiple trip points. A thermal + client sets threshold temperature for both warm and cool trips and + gets updated when a threshold is reached. + + To compile this driver as a module, choose M here: the module will + be called qcom-spmi-adc5-gen3. + config RCAR_GYRO_ADC tristate "Renesas R-Car GyroADC driver" depends on ARCH_RCAR_GEN2 || COMPILE_TEST diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index c76550415ff1..097357d146ba 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -116,6 +116,7 @@ obj-$(CONFIG_PAC1934) += pac1934.o obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o obj-$(CONFIG_QCOM_PM8XXX_XOADC) += qcom-pm8xxx-xoadc.o obj-$(CONFIG_QCOM_SPMI_ADC5) += qcom-spmi-adc5.o +obj-$(CONFIG_QCOM_SPMI_ADC5_GEN3) += qcom-spmi-adc5-gen3.o obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o obj-$(CONFIG_QCOM_SPMI_RRADC) += qcom-spmi-rradc.o obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o diff --git a/drivers/iio/adc/ad4030.c b/drivers/iio/adc/ad4030.c index 68446db9bef1..9c5f19321e3b 100644 --- a/drivers/iio/adc/ad4030.c +++ b/drivers/iio/adc/ad4030.c @@ -14,15 +14,26 @@ */ #include +#include #include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include +#include #include #include #include +#include + +#include +#include +#include +#include #define AD4030_REG_INTERFACE_CONFIG_A 0x00 #define AD4030_REG_INTERFACE_CONFIG_A_SW_RESET (BIT(0) | BIT(7)) @@ -37,6 +48,8 @@ #define AD4030_REG_CHIP_GRADE_AD4630_24_GRADE 0x00 #define AD4030_REG_CHIP_GRADE_AD4632_16_GRADE 0x05 #define AD4030_REG_CHIP_GRADE_AD4632_24_GRADE 0x02 +#define AD4030_REG_CHIP_GRADE_ADAQ4216_GRADE 0x1E +#define AD4030_REG_CHIP_GRADE_ADAQ4224_GRADE 0x1C #define AD4030_REG_CHIP_GRADE_MASK_CHIP_GRADE GENMASK(7, 3) #define AD4030_REG_SCRATCH_PAD 0x0A #define AD4030_REG_SPI_REVISION 0x0B @@ -111,6 +124,12 @@ #define AD4632_TCYC_NS 2000 #define AD4632_TCYC_ADJUSTED_NS (AD4632_TCYC_NS - AD4030_TCNVL_NS) #define AD4030_TRESET_COM_DELAY_MS 750 +/* Datasheet says 9.8ns, so use the closest integer value */ +#define AD4030_TQUIET_CNV_DELAY_NS 10 + +/* HARDWARE_GAIN */ +#define ADAQ4616_PGA_PINS 2 +#define ADAQ4616_PGA_GAIN_MAX_NANO (NANO * 2 / 3) enum ad4030_out_mode { AD4030_OUT_DATA_MD_DIFF, @@ -132,15 +151,35 @@ enum { AD4030_SCAN_TYPE_AVG, }; +/* + * Gains computed as fractions of 1000 so they can be expressed by integers. + */ +static const int adaq4216_hw_gains_vpv[] = { + 1 * MILLI / 3, /* 0.333 */ + 5 * MILLI / 9, /* 0.555 */ + 20 * MILLI / 9, /* 0.2222 */ + 20 * MILLI / 3, /* 0.6666 */ +}; + +static const int adaq4216_hw_gains_frac[][2] = { + { 1, 3 }, /* 1/3 V/V gain */ + { 5, 9 }, /* 5/9 V/V gain */ + { 20, 9 }, /* 20/9 V/V gain */ + { 20, 3 }, /* 20/3 V/V gain */ +}; + struct ad4030_chip_info { const char *name; const unsigned long *available_masks; const struct iio_chan_spec channels[AD4030_MAX_IIO_CHANNEL_NB]; + const struct iio_chan_spec offload_channels[AD4030_MAX_IIO_CHANNEL_NB]; u8 grade; u8 precision_bits; + bool has_pga; /* Number of hardware channels */ int num_voltage_inputs; unsigned int tcyc_ns; + unsigned int max_sample_rate_hz; }; struct ad4030_state { @@ -153,6 +192,18 @@ struct ad4030_state { int offset_avail[3]; unsigned int avg_log2; enum ad4030_out_mode mode; + /* Offload sampling */ + struct spi_transfer offload_xfer; + struct spi_message offload_msg; + struct spi_offload *offload; + struct spi_offload_trigger *offload_trigger; + struct spi_offload_trigger_config offload_trigger_config; + struct pwm_device *cnv_trigger; + size_t scale_avail_size; + struct pwm_waveform cnv_wf; + unsigned int scale_avail[ARRAY_SIZE(adaq4216_hw_gains_vpv)][2]; + struct gpio_descs *pga_gpios; + unsigned int pga_index; /* * DMA (thus cache coherency maintenance) requires the transfer buffers @@ -209,8 +260,9 @@ struct ad4030_state { * - voltage0-voltage1 * - voltage2-voltage3 */ -#define AD4030_CHAN_DIFF(_idx, _scan_type) { \ +#define __AD4030_CHAN_DIFF(_idx, _scan_type, _offload, _pga) { \ .info_mask_shared_by_all = \ + (_offload ? BIT(IIO_CHAN_INFO_SAMP_FREQ) : 0) | \ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .info_mask_shared_by_all_available = \ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ @@ -219,6 +271,7 @@ struct ad4030_state { BIT(IIO_CHAN_INFO_CALIBBIAS) | \ BIT(IIO_CHAN_INFO_RAW), \ .info_mask_separate_available = BIT(IIO_CHAN_INFO_CALIBBIAS) | \ + (_pga ? BIT(IIO_CHAN_INFO_SCALE) : 0) | \ BIT(IIO_CHAN_INFO_CALIBSCALE), \ .type = IIO_VOLTAGE, \ .indexed = 1, \ @@ -232,10 +285,33 @@ struct ad4030_state { .num_ext_scan_type = ARRAY_SIZE(_scan_type), \ } +#define AD4030_CHAN_DIFF(_idx, _scan_type) \ + __AD4030_CHAN_DIFF(_idx, _scan_type, 0, 0) + +#define AD4030_OFFLOAD_CHAN_DIFF(_idx, _scan_type) \ + __AD4030_CHAN_DIFF(_idx, _scan_type, 1, 0) + +#define ADAQ4216_CHAN_DIFF(_idx, _scan_type) \ + __AD4030_CHAN_DIFF(_idx, _scan_type, 0, 1) + +#define ADAQ4216_OFFLOAD_CHAN_DIFF(_idx, _scan_type) \ + __AD4030_CHAN_DIFF(_idx, _scan_type, 1, 1) + +/* + * AD4030 can average over 2^N samples, where N = 1, 2, 3, ..., 16. + * We use N = 0 to mean no sample averaging. + */ static const int ad4030_average_modes[] = { - 1, 2, 4, 8, 16, 32, 64, 128, - 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, - 65536, + BIT(0), /* No sampling average */ + BIT(1), BIT(2), BIT(3), BIT(4), + BIT(5), BIT(6), BIT(7), BIT(8), + BIT(9), BIT(10), BIT(11), BIT(12), + BIT(13), BIT(14), BIT(15), BIT(16), +}; + +static const struct spi_offload_config ad4030_offload_config = { + .capability_flags = SPI_OFFLOAD_CAP_TRIGGER | + SPI_OFFLOAD_CAP_RX_STREAM_DMA, }; static int ad4030_enter_config_mode(struct ad4030_state *st) @@ -377,6 +453,65 @@ static const struct regmap_config ad4030_regmap_config = { .max_register = AD4030_REG_DIG_ERR, }; +static void ad4030_fill_scale_avail(struct ad4030_state *st) +{ + unsigned int mag_bits, int_part, fract_part; + u64 range; + + /* + * The maximum precision of differential channels is retrieved from the + * chip properties. The output code of differential channels is in two's + * complement format (i.e. signed), so the MSB is the sign bit and only + * (precision_bits - 1) bits express voltage magnitude. + */ + mag_bits = st->chip->precision_bits - 1; + + for (unsigned int i = 0; i < ARRAY_SIZE(adaq4216_hw_gains_frac); i++) { + range = mult_frac(st->vref_uv, adaq4216_hw_gains_frac[i][1], + adaq4216_hw_gains_frac[i][0]); + /* + * If range were in mV, we would multiply it by NANO below. + * Though, range is in µV so multiply it by MICRO only so the + * result after right shift and division scales output codes to + * millivolts. + */ + int_part = div_u64_rem((range * MICRO) >> mag_bits, NANO, &fract_part); + st->scale_avail[i][0] = int_part; + st->scale_avail[i][1] = fract_part; + } +} + +static int ad4030_set_pga_gain(struct ad4030_state *st) +{ + DECLARE_BITMAP(bitmap, ADAQ4616_PGA_PINS) = { }; + + bitmap_write(bitmap, st->pga_index, 0, ADAQ4616_PGA_PINS); + + return gpiod_multi_set_value_cansleep(st->pga_gpios, bitmap); +} + +static int ad4030_set_pga(struct iio_dev *indio_dev, int gain_int, int gain_fract) +{ + struct ad4030_state *st = iio_priv(indio_dev); + unsigned int mag_bits = st->chip->precision_bits - 1; + unsigned int tmp; + u64 gain_nano; + + if (!st->pga_gpios) + return -EINVAL; + + gain_nano = gain_int * NANO + gain_fract; + if (!in_range(gain_nano, 1, ADAQ4616_PGA_GAIN_MAX_NANO)) + return -EINVAL; + + tmp = DIV_ROUND_CLOSEST_ULL(gain_nano << mag_bits, NANO); + gain_nano = DIV_ROUND_CLOSEST(st->vref_uv, tmp); + st->pga_index = find_closest(gain_nano, adaq4216_hw_gains_vpv, + ARRAY_SIZE(adaq4216_hw_gains_vpv)); + + return ad4030_set_pga_gain(st); +} + static int ad4030_get_chan_scale(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -389,6 +524,13 @@ static int ad4030_get_chan_scale(struct iio_dev *indio_dev, if (IS_ERR(scan_type)) return PTR_ERR(scan_type); + /* The LSB of the 8-bit common-mode data is always vref/256. */ + if (st->chip->has_pga && scan_type->realbits != 8) { + *val = st->scale_avail[st->pga_index][0]; + *val2 = st->scale_avail[st->pga_index][1]; + return IIO_VAL_INT_PLUS_NANO; + } + if (chan->differential) *val = (st->vref_uv * 2) / MILLI; else @@ -451,6 +593,102 @@ static int ad4030_get_chan_calibbias(struct iio_dev *indio_dev, } } +static void ad4030_get_sampling_freq(struct ad4030_state *st, int *freq) +{ + struct spi_offload_trigger_config *config = &st->offload_trigger_config; + + /* + * Conversion data is fetched from the device when the offload transfer + * is triggered. Thus, provide the SPI offload trigger frequency as the + * sampling frequency. + */ + *freq = config->periodic.frequency_hz; +} + +static int ad4030_update_conversion_rate(struct ad4030_state *st, + unsigned int freq_hz, unsigned int avg_log2) +{ + struct spi_offload_trigger_config *config = &st->offload_trigger_config; + unsigned int offload_period_ns, cnv_rate_hz; + struct pwm_waveform cnv_wf = { }; + u64 target = AD4030_TCNVH_NS; + u64 offload_offset_ns; + int ret; + + /* + * When averaging/oversampling over N samples, we fire the offload + * trigger once at every N pulses of the CNV signal. Conversely, the CNV + * signal needs to be N times faster than the offload trigger. Take that + * into account to correctly re-evaluate both the PWM waveform connected + * to CNV and the SPI offload trigger. + */ + cnv_rate_hz = freq_hz << avg_log2; + + cnv_wf.period_length_ns = DIV_ROUND_CLOSEST(NSEC_PER_SEC, cnv_rate_hz); + /* + * The datasheet lists a minimum time of 9.8 ns, but no maximum. If the + * rounded PWM's value is less than 10, increase the target value by 10 + * and attempt to round the waveform again, until the value is at least + * 10 ns. Use a separate variable to represent the target in case the + * rounding is severe enough to keep putting the first few results under + * the minimum 10ns condition checked by the while loop. + */ + do { + cnv_wf.duty_length_ns = target; + ret = pwm_round_waveform_might_sleep(st->cnv_trigger, &cnv_wf); + if (ret) + return ret; + target += AD4030_TCNVH_NS; + } while (cnv_wf.duty_length_ns < AD4030_TCNVH_NS); + + /* + * The CNV waveform period (period_length_ns) might get rounded down by + * pwm_round_waveform_might_sleep(). Check the resultant PWM period + * is not smaller than the minimum data conversion cycle time. + */ + if (!in_range(cnv_wf.period_length_ns, AD4030_TCYC_NS, INT_MAX)) + return -EINVAL; + + offload_period_ns = DIV_ROUND_CLOSEST(NSEC_PER_SEC, freq_hz); + + config->periodic.frequency_hz = DIV_ROUND_UP(HZ_PER_GHZ, offload_period_ns); + + /* + * The hardware does the capture on zone 2 (when SPI trigger PWM + * is used). This means that the SPI trigger signal should happen at + * tsync + tquiet_con_delay being tsync the conversion signal period + * and tquiet_con_delay 9.8ns. Hence set the PWM phase accordingly. + * + * The PWM waveform API only supports nanosecond resolution right now, + * so round this setting to the closest available value. + */ + offload_offset_ns = AD4030_TQUIET_CNV_DELAY_NS; + do { + config->periodic.offset_ns = offload_offset_ns; + ret = spi_offload_trigger_validate(st->offload_trigger, config); + if (ret) + return ret; + offload_offset_ns += AD4030_TQUIET_CNV_DELAY_NS; + } while (config->periodic.offset_ns < AD4030_TQUIET_CNV_DELAY_NS); + + st->cnv_wf = cnv_wf; + + return 0; +} + +static int ad4030_set_sampling_freq(struct iio_dev *indio_dev, int freq_hz) +{ + struct ad4030_state *st = iio_priv(indio_dev); + + if (freq_hz == 0) + return -EINVAL; + + if (!in_range(freq_hz, 0, st->chip->max_sample_rate_hz)) + return -ERANGE; + + return ad4030_update_conversion_rate(st, freq_hz, st->avg_log2); +} + static int ad4030_set_chan_calibscale(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int gain_int, @@ -510,11 +748,30 @@ static int ad4030_set_avg_frame_len(struct iio_dev *dev, int avg_val) struct ad4030_state *st = iio_priv(dev); unsigned int avg_log2 = ilog2(avg_val); unsigned int last_avg_idx = ARRAY_SIZE(ad4030_average_modes) - 1; + int freq_hz; int ret; if (avg_val < 0 || avg_val > ad4030_average_modes[last_avg_idx]) return -EINVAL; + if (st->offload_trigger) { + /* + * The sample averaging and sampling frequency configurations + * are mutually dependent on each other. That's because the + * effective data sample rate is fCNV / 2^N, where N is the + * number of samples being averaged. + * + * When SPI offload is supported and we have control over the + * sample rate, the conversion start signal (CNV) and the SPI + * offload trigger frequencies must be re-evaluated so data is + * fetched only after 'avg_val' conversions. + */ + ad4030_get_sampling_freq(st, &freq_hz); + ret = ad4030_update_conversion_rate(st, freq_hz, avg_log2); + if (ret) + return ret; + } + ret = regmap_write(st->regmap, AD4030_REG_AVG, AD4030_REG_AVG_MASK_AVG_SYNC | FIELD_PREP(AD4030_REG_AVG_MASK_AVG_VAL, avg_log2)); @@ -623,7 +880,7 @@ static int ad4030_conversion(struct iio_dev *indio_dev) /* Add one byte if we are using a differential + common byte mode */ bytes_to_read += (st->mode == AD4030_OUT_DATA_MD_24_DIFF_8_COM || st->mode == AD4030_OUT_DATA_MD_16_DIFF_8_COM) ? 1 : 0; - /* Mulitiply by the number of hardware channels */ + /* Multiply by the number of hardware channels */ bytes_to_read *= st->chip->num_voltage_inputs; for (i = 0; i < cnv_nb; i++) { @@ -742,6 +999,15 @@ static int ad4030_read_avail(struct iio_dev *indio_dev, *length = ARRAY_SIZE(ad4030_average_modes); return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_SCALE: + if (st->scale_avail_size == 1) + *vals = (int *)st->scale_avail[st->pga_index]; + else + *vals = (int *)st->scale_avail; + *length = st->scale_avail_size * 2; /* print int and nano part */ + *type = IIO_VAL_INT_PLUS_NANO; + return IIO_AVAIL_LIST; + default: return -EINVAL; } @@ -767,6 +1033,10 @@ static int ad4030_read_raw_dispatch(struct iio_dev *indio_dev, *val = BIT(st->avg_log2); return IIO_VAL_INT; + case IIO_CHAN_INFO_SAMP_FREQ: + ad4030_get_sampling_freq(st, val); + return IIO_VAL_INT; + default: return -EINVAL; } @@ -807,6 +1077,12 @@ static int ad4030_write_raw_dispatch(struct iio_dev *indio_dev, case IIO_CHAN_INFO_OVERSAMPLING_RATIO: return ad4030_set_avg_frame_len(indio_dev, val); + case IIO_CHAN_INFO_SAMP_FREQ: + return ad4030_set_sampling_freq(indio_dev, val); + + case IIO_CHAN_INFO_SCALE: + return ad4030_set_pga(indio_dev, val, val2); + default: return -EINVAL; } @@ -828,6 +1104,17 @@ static int ad4030_write_raw(struct iio_dev *indio_dev, return ret; } +static int ad4030_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_NANO; + default: + return IIO_VAL_INT_PLUS_MICRO; + } +} + static int ad4030_reg_access(struct iio_dev *indio_dev, unsigned int reg, unsigned int writeval, unsigned int *readval) { @@ -874,6 +1161,7 @@ static const struct iio_info ad4030_iio_info = { .read_avail = ad4030_read_avail, .read_raw = ad4030_read_raw, .write_raw = ad4030_write_raw, + .write_raw_get_fmt = &ad4030_write_raw_get_fmt, .debugfs_reg_access = ad4030_reg_access, .read_label = ad4030_read_label, .get_current_scan_type = ad4030_get_current_scan_type, @@ -896,6 +1184,86 @@ static const struct iio_buffer_setup_ops ad4030_buffer_setup_ops = { .validate_scan_mask = ad4030_validate_scan_mask, }; +static void ad4030_prepare_offload_msg(struct iio_dev *indio_dev) +{ + struct ad4030_state *st = iio_priv(indio_dev); + u8 offload_bpw; + + if (st->mode == AD4030_OUT_DATA_MD_30_AVERAGED_DIFF) + offload_bpw = 32; + else + offload_bpw = st->chip->precision_bits; + + st->offload_xfer.bits_per_word = offload_bpw; + st->offload_xfer.len = spi_bpw_to_bytes(offload_bpw); + st->offload_xfer.offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; + spi_message_init_with_transfers(&st->offload_msg, &st->offload_xfer, 1); +} + +static int ad4030_offload_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad4030_state *st = iio_priv(indio_dev); + unsigned int reg_modes; + int ret; + + /* + * When data from 2 analog input channels is output through a single + * bus line (interleaved mode (LANE_MD == 0b11)) and gets pushed through + * DMA, extra hardware is required to do the de-interleaving. While we + * don't support such hardware configurations, disallow interleaved mode + * when using SPI offload. + */ + ret = regmap_read(st->regmap, AD4030_REG_MODES, ®_modes); + if (ret) + return ret; + + if (st->chip->num_voltage_inputs > 1 && + FIELD_GET(AD4030_REG_MODES_MASK_LANE_MODE, reg_modes) == AD4030_LANE_MD_INTERLEAVED) + return -EINVAL; + + ad4030_prepare_offload_msg(indio_dev); + st->offload_msg.offload = st->offload; + ret = spi_optimize_message(st->spi, &st->offload_msg); + if (ret) + return ret; + + ret = pwm_set_waveform_might_sleep(st->cnv_trigger, &st->cnv_wf, false); + if (ret) + goto out_unoptimize; + + ret = spi_offload_trigger_enable(st->offload, st->offload_trigger, + &st->offload_trigger_config); + if (ret) + goto out_pwm_disable; + + return 0; + +out_pwm_disable: + pwm_disable(st->cnv_trigger); +out_unoptimize: + spi_unoptimize_message(&st->offload_msg); + + return ret; +} + +static int ad4030_offload_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ad4030_state *st = iio_priv(indio_dev); + + spi_offload_trigger_disable(st->offload, st->offload_trigger); + + pwm_disable(st->cnv_trigger); + + spi_unoptimize_message(&st->offload_msg); + + return 0; +} + +static const struct iio_buffer_setup_ops ad4030_offload_buffer_setup_ops = { + .postenable = &ad4030_offload_buffer_postenable, + .predisable = &ad4030_offload_buffer_predisable, +}; + static int ad4030_regulators_get(struct ad4030_state *st) { struct device *dev = &st->spi->dev; @@ -965,6 +1333,24 @@ static int ad4030_detect_chip_info(const struct ad4030_state *st) return 0; } +static int ad4030_pwm_get(struct ad4030_state *st) +{ + struct device *dev = &st->spi->dev; + + st->cnv_trigger = devm_pwm_get(dev, NULL); + if (IS_ERR(st->cnv_trigger)) + return dev_err_probe(dev, PTR_ERR(st->cnv_trigger), + "Failed to get CNV PWM\n"); + + /* + * Preemptively disable the PWM, since we only want to enable it with + * the buffer. + */ + pwm_disable(st->cnv_trigger); + + return 0; +} + static int ad4030_config(struct ad4030_state *st) { int ret; @@ -992,6 +1378,51 @@ static int ad4030_config(struct ad4030_state *st) return 0; } +static int ad4030_spi_offload_setup(struct iio_dev *indio_dev, + struct ad4030_state *st) +{ + struct device *dev = &st->spi->dev; + struct dma_chan *rx_dma; + + indio_dev->setup_ops = &ad4030_offload_buffer_setup_ops; + + st->offload_trigger = devm_spi_offload_trigger_get(dev, st->offload, + SPI_OFFLOAD_TRIGGER_PERIODIC); + if (IS_ERR(st->offload_trigger)) + return dev_err_probe(dev, PTR_ERR(st->offload_trigger), + "failed to get offload trigger\n"); + + st->offload_trigger_config.type = SPI_OFFLOAD_TRIGGER_PERIODIC; + + rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload); + if (IS_ERR(rx_dma)) + return dev_err_probe(dev, PTR_ERR(rx_dma), + "failed to get offload RX DMA\n"); + + return devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma, + IIO_BUFFER_DIRECTION_IN); +} + +static int ad4030_setup_pga(struct device *dev, struct iio_dev *indio_dev, + struct ad4030_state *st) +{ + /* Setup GPIOs for PGA control */ + st->pga_gpios = devm_gpiod_get_array(dev, "pga", GPIOD_OUT_LOW); + if (IS_ERR(st->pga_gpios)) + return dev_err_probe(dev, PTR_ERR(st->pga_gpios), + "Failed to get PGA gpios.\n"); + + if (st->pga_gpios->ndescs != ADAQ4616_PGA_PINS) + return dev_err_probe(dev, -EINVAL, + "Expected %d GPIOs for PGA control.\n", + ADAQ4616_PGA_PINS); + + st->scale_avail_size = ARRAY_SIZE(adaq4216_hw_gains_vpv); + st->pga_index = 0; + + return 0; +} + static int ad4030_probe(struct spi_device *spi) { struct device *dev = &spi->dev; @@ -1034,6 +1465,14 @@ static int ad4030_probe(struct spi_device *spi) if (ret) return ret; + if (st->chip->has_pga) { + ret = ad4030_setup_pga(dev, indio_dev, st); + if (ret) + return ret; + + ad4030_fill_scale_avail(st); + } + ret = ad4030_config(st); if (ret) return ret; @@ -1043,24 +1482,58 @@ static int ad4030_probe(struct spi_device *spi) return dev_err_probe(dev, PTR_ERR(st->cnv_gpio), "Failed to get cnv gpio\n"); - /* - * One hardware channel is split in two software channels when using - * common byte mode. Add one more channel for the timestamp. - */ - indio_dev->num_channels = 2 * st->chip->num_voltage_inputs + 1; indio_dev->name = st->chip->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &ad4030_iio_info; - indio_dev->channels = st->chip->channels; indio_dev->available_scan_masks = st->chip->available_masks; - ret = devm_iio_triggered_buffer_setup(dev, indio_dev, - iio_pollfunc_store_time, - ad4030_trigger_handler, - &ad4030_buffer_setup_ops); - if (ret) - return dev_err_probe(dev, ret, - "Failed to setup triggered buffer\n"); + st->offload = devm_spi_offload_get(dev, spi, &ad4030_offload_config); + ret = PTR_ERR_OR_ZERO(st->offload); + /* Fall back to low speed usage when no SPI offload is available. */ + if (ret == -ENODEV) { + /* + * One hardware channel is split in two software channels when + * using common byte mode. Add one more channel for the timestamp. + */ + indio_dev->num_channels = 2 * st->chip->num_voltage_inputs + 1; + indio_dev->channels = st->chip->channels; + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + iio_pollfunc_store_time, + ad4030_trigger_handler, + &ad4030_buffer_setup_ops); + if (ret) + return dev_err_probe(dev, ret, + "Failed to setup triggered buffer\n"); + } else if (ret) { + return dev_err_probe(dev, ret, "failed to get offload\n"); + } else { + /* + * Offloaded SPI transfers can't support software timestamp so + * no additional timestamp channel is added. + */ + indio_dev->num_channels = st->chip->num_voltage_inputs; + indio_dev->channels = st->chip->offload_channels; + ret = ad4030_spi_offload_setup(indio_dev, st); + if (ret) + return dev_err_probe(dev, ret, + "Failed to setup SPI offload\n"); + + ret = ad4030_pwm_get(st); + if (ret) + return dev_err_probe(dev, ret, "Failed to get PWM\n"); + + /* + * Start with a slower sampling rate so there is some room for + * adjusting the sample averaging and the sampling frequency + * without hitting the maximum conversion rate. + */ + ret = ad4030_update_conversion_rate(st, st->chip->max_sample_rate_hz >> 4, + st->avg_log2); + if (ret) + return dev_err_probe(dev, ret, + "Failed to set offload samp freq\n"); + } return devm_iio_device_register(dev, indio_dev); } @@ -1098,11 +1571,28 @@ static const struct iio_scan_type ad4030_24_scan_types[] = { }, }; +static const struct iio_scan_type ad4030_24_offload_scan_types[] = { + [AD4030_SCAN_TYPE_NORMAL] = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + .shift = 0, + .endianness = IIO_CPU, + }, + [AD4030_SCAN_TYPE_AVG] = { + .sign = 's', + .realbits = 30, + .storagebits = 32, + .shift = 2, + .endianness = IIO_CPU, + }, +}; + static const struct iio_scan_type ad4030_16_scan_types[] = { [AD4030_SCAN_TYPE_NORMAL] = { .sign = 's', - .storagebits = 32, .realbits = 16, + .storagebits = 32, .shift = 16, .endianness = IIO_BE, }, @@ -1115,6 +1605,23 @@ static const struct iio_scan_type ad4030_16_scan_types[] = { } }; +static const struct iio_scan_type ad4030_16_offload_scan_types[] = { + [AD4030_SCAN_TYPE_NORMAL] = { + .sign = 's', + .realbits = 16, + .storagebits = 32, + .shift = 0, + .endianness = IIO_CPU, + }, + [AD4030_SCAN_TYPE_AVG] = { + .sign = 's', + .realbits = 30, + .storagebits = 32, + .shift = 2, + .endianness = IIO_CPU, + }, +}; + static const struct ad4030_chip_info ad4030_24_chip_info = { .name = "ad4030-24", .available_masks = ad4030_channel_masks, @@ -1123,10 +1630,14 @@ static const struct ad4030_chip_info ad4030_24_chip_info = { AD4030_CHAN_CMO(1, 0), IIO_CHAN_SOFT_TIMESTAMP(2), }, + .offload_channels = { + AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_24_offload_scan_types), + }, .grade = AD4030_REG_CHIP_GRADE_AD4030_24_GRADE, .precision_bits = 24, .num_voltage_inputs = 1, .tcyc_ns = AD4030_TCYC_ADJUSTED_NS, + .max_sample_rate_hz = 2 * HZ_PER_MHZ, }; static const struct ad4030_chip_info ad4630_16_chip_info = { @@ -1139,10 +1650,15 @@ static const struct ad4030_chip_info ad4630_16_chip_info = { AD4030_CHAN_CMO(3, 1), IIO_CHAN_SOFT_TIMESTAMP(4), }, + .offload_channels = { + AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_16_offload_scan_types), + AD4030_OFFLOAD_CHAN_DIFF(1, ad4030_16_offload_scan_types), + }, .grade = AD4030_REG_CHIP_GRADE_AD4630_16_GRADE, .precision_bits = 16, .num_voltage_inputs = 2, .tcyc_ns = AD4030_TCYC_ADJUSTED_NS, + .max_sample_rate_hz = 2 * HZ_PER_MHZ, }; static const struct ad4030_chip_info ad4630_24_chip_info = { @@ -1155,10 +1671,15 @@ static const struct ad4030_chip_info ad4630_24_chip_info = { AD4030_CHAN_CMO(3, 1), IIO_CHAN_SOFT_TIMESTAMP(4), }, + .offload_channels = { + AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_24_offload_scan_types), + AD4030_OFFLOAD_CHAN_DIFF(1, ad4030_24_offload_scan_types), + }, .grade = AD4030_REG_CHIP_GRADE_AD4630_24_GRADE, .precision_bits = 24, .num_voltage_inputs = 2, .tcyc_ns = AD4030_TCYC_ADJUSTED_NS, + .max_sample_rate_hz = 2 * HZ_PER_MHZ, }; static const struct ad4030_chip_info ad4632_16_chip_info = { @@ -1171,10 +1692,15 @@ static const struct ad4030_chip_info ad4632_16_chip_info = { AD4030_CHAN_CMO(3, 1), IIO_CHAN_SOFT_TIMESTAMP(4), }, + .offload_channels = { + AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_16_offload_scan_types), + AD4030_OFFLOAD_CHAN_DIFF(1, ad4030_16_offload_scan_types), + }, .grade = AD4030_REG_CHIP_GRADE_AD4632_16_GRADE, .precision_bits = 16, .num_voltage_inputs = 2, .tcyc_ns = AD4632_TCYC_ADJUSTED_NS, + .max_sample_rate_hz = 500 * HZ_PER_KHZ, }; static const struct ad4030_chip_info ad4632_24_chip_info = { @@ -1187,10 +1713,53 @@ static const struct ad4030_chip_info ad4632_24_chip_info = { AD4030_CHAN_CMO(3, 1), IIO_CHAN_SOFT_TIMESTAMP(4), }, + .offload_channels = { + AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_24_offload_scan_types), + AD4030_OFFLOAD_CHAN_DIFF(1, ad4030_24_offload_scan_types), + }, .grade = AD4030_REG_CHIP_GRADE_AD4632_24_GRADE, .precision_bits = 24, .num_voltage_inputs = 2, .tcyc_ns = AD4632_TCYC_ADJUSTED_NS, + .max_sample_rate_hz = 500 * HZ_PER_KHZ, +}; + +static const struct ad4030_chip_info adaq4216_chip_info = { + .name = "adaq4216", + .available_masks = ad4030_channel_masks, + .channels = { + ADAQ4216_CHAN_DIFF(0, ad4030_16_scan_types), + AD4030_CHAN_CMO(1, 0), + IIO_CHAN_SOFT_TIMESTAMP(2), + }, + .offload_channels = { + ADAQ4216_OFFLOAD_CHAN_DIFF(0, ad4030_16_offload_scan_types), + }, + .grade = AD4030_REG_CHIP_GRADE_ADAQ4216_GRADE, + .precision_bits = 16, + .has_pga = true, + .num_voltage_inputs = 1, + .tcyc_ns = AD4030_TCYC_ADJUSTED_NS, + .max_sample_rate_hz = 2 * HZ_PER_MHZ, +}; + +static const struct ad4030_chip_info adaq4224_chip_info = { + .name = "adaq4224", + .available_masks = ad4030_channel_masks, + .channels = { + ADAQ4216_CHAN_DIFF(0, ad4030_24_scan_types), + AD4030_CHAN_CMO(1, 0), + IIO_CHAN_SOFT_TIMESTAMP(2), + }, + .offload_channels = { + ADAQ4216_OFFLOAD_CHAN_DIFF(0, ad4030_24_offload_scan_types), + }, + .grade = AD4030_REG_CHIP_GRADE_ADAQ4224_GRADE, + .precision_bits = 24, + .has_pga = true, + .num_voltage_inputs = 1, + .tcyc_ns = AD4030_TCYC_ADJUSTED_NS, + .max_sample_rate_hz = 2 * HZ_PER_MHZ, }; static const struct spi_device_id ad4030_id_table[] = { @@ -1199,6 +1768,8 @@ static const struct spi_device_id ad4030_id_table[] = { { "ad4630-24", (kernel_ulong_t)&ad4630_24_chip_info }, { "ad4632-16", (kernel_ulong_t)&ad4632_16_chip_info }, { "ad4632-24", (kernel_ulong_t)&ad4632_24_chip_info }, + { "adaq4216", (kernel_ulong_t)&adaq4216_chip_info }, + { "adaq4224", (kernel_ulong_t)&adaq4224_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, ad4030_id_table); @@ -1209,6 +1780,8 @@ static const struct of_device_id ad4030_of_match[] = { { .compatible = "adi,ad4630-24", .data = &ad4630_24_chip_info }, { .compatible = "adi,ad4632-16", .data = &ad4632_16_chip_info }, { .compatible = "adi,ad4632-24", .data = &ad4632_24_chip_info }, + { .compatible = "adi,adaq4216", .data = &adaq4216_chip_info }, + { .compatible = "adi,adaq4224", .data = &adaq4224_chip_info }, { } }; MODULE_DEVICE_TABLE(of, ad4030_of_match); @@ -1226,3 +1799,4 @@ module_spi_driver(ad4030_driver); MODULE_AUTHOR("Esteban Blanc "); MODULE_DESCRIPTION("Analog Devices AD4630 ADC family driver"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER"); diff --git a/drivers/iio/adc/ad4062.c b/drivers/iio/adc/ad4062.c index dd4ad32aa6f5..c864de3b46ba 100644 --- a/drivers/iio/adc/ad4062.c +++ b/drivers/iio/adc/ad4062.c @@ -1199,11 +1199,14 @@ static int ad4062_write_event_value(struct iio_dev *indio_dev, * The AD4062 in burst averaging mode increases realbits from 16-bits to * 20-bits, increasing the storagebits from 16-bits to 32-bits. */ -static inline size_t ad4062_sizeof_storagebits(struct ad4062_state *st) +static inline int ad4062_sizeof_storagebits(struct ad4062_state *st) { const struct iio_scan_type *scan_type = iio_get_current_scan_type(st->indio_dev, st->chip->channels); + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + return BITS_TO_BYTES(scan_type->storagebits); } @@ -1233,7 +1236,12 @@ static int pm_ad4062_triggered_buffer_postenable(struct ad4062_state *st) if (ret) return ret; - st->conv_sizeof = ad4062_sizeof_storagebits(st); + ret = ad4062_sizeof_storagebits(st); + if (ret < 0) + return ret; + + st->conv_sizeof = ret; + st->conv_addr = ad4062_get_conv_addr(st, st->conv_sizeof); /* CONV_READ requires read to trigger first sample. */ struct i3c_xfer xfer_sample[2] = { diff --git a/drivers/iio/adc/ad4080.c b/drivers/iio/adc/ad4080.c index 7cf3b6ed7940..204ad198342b 100644 --- a/drivers/iio/adc/ad4080.c +++ b/drivers/iio/adc/ad4080.c @@ -127,10 +127,13 @@ #define AD4080_SPI_READ BIT(7) #define AD4080_CHIP_ID 0x0050 #define AD4081_CHIP_ID 0x0051 +#define AD4082_CHIP_ID 0x0052 #define AD4083_CHIP_ID 0x0053 #define AD4084_CHIP_ID 0x0054 +#define AD4085_CHIP_ID 0x0055 #define AD4086_CHIP_ID 0x0056 #define AD4087_CHIP_ID 0x0057 +#define AD4088_CHIP_ID 0x0058 #define AD4080_LVDS_CNV_CLK_CNT_MAX 7 @@ -185,7 +188,6 @@ struct ad4080_state { */ struct mutex lock; unsigned int num_lanes; - unsigned int dec_rate; unsigned long clk_rate; enum ad4080_filter_type filter_type; bool lvds_cnv_en; @@ -442,14 +444,20 @@ static const struct iio_chan_spec ad4080_channel = AD4080_CHANNEL_DEFINE(20, 32) static const struct iio_chan_spec ad4081_channel = AD4080_CHANNEL_DEFINE(20, 32); +static const struct iio_chan_spec ad4082_channel = AD4080_CHANNEL_DEFINE(20, 32); + static const struct iio_chan_spec ad4083_channel = AD4080_CHANNEL_DEFINE(16, 16); static const struct iio_chan_spec ad4084_channel = AD4080_CHANNEL_DEFINE(16, 16); +static const struct iio_chan_spec ad4085_channel = AD4080_CHANNEL_DEFINE(16, 16); + static const struct iio_chan_spec ad4086_channel = AD4080_CHANNEL_DEFINE(14, 16); static const struct iio_chan_spec ad4087_channel = AD4080_CHANNEL_DEFINE(14, 16); +static const struct iio_chan_spec ad4088_channel = AD4080_CHANNEL_DEFINE(14, 16); + static const struct ad4080_chip_info ad4080_chip_info = { .name = "ad4080", .product_id = AD4080_CHIP_ID, @@ -470,6 +478,16 @@ static const struct ad4080_chip_info ad4081_chip_info = { .lvds_cnv_clk_cnt_max = 2, }; +static const struct ad4080_chip_info ad4082_chip_info = { + .name = "ad4082", + .product_id = AD4082_CHIP_ID, + .scale_table = ad4080_scale_table, + .num_scales = ARRAY_SIZE(ad4080_scale_table), + .num_channels = 1, + .channels = &ad4082_channel, + .lvds_cnv_clk_cnt_max = 8, +}; + static const struct ad4080_chip_info ad4083_chip_info = { .name = "ad4083", .product_id = AD4083_CHIP_ID, @@ -490,6 +508,16 @@ static const struct ad4080_chip_info ad4084_chip_info = { .lvds_cnv_clk_cnt_max = 2, }; +static const struct ad4080_chip_info ad4085_chip_info = { + .name = "ad4085", + .product_id = AD4085_CHIP_ID, + .scale_table = ad4080_scale_table, + .num_scales = ARRAY_SIZE(ad4080_scale_table), + .num_channels = 1, + .channels = &ad4085_channel, + .lvds_cnv_clk_cnt_max = 8, +}; + static const struct ad4080_chip_info ad4086_chip_info = { .name = "ad4086", .product_id = AD4086_CHIP_ID, @@ -510,6 +538,16 @@ static const struct ad4080_chip_info ad4087_chip_info = { .lvds_cnv_clk_cnt_max = 1, }; +static const struct ad4080_chip_info ad4088_chip_info = { + .name = "ad4088", + .product_id = AD4088_CHIP_ID, + .scale_table = ad4080_scale_table, + .num_scales = ARRAY_SIZE(ad4080_scale_table), + .num_channels = 1, + .channels = &ad4088_channel, + .lvds_cnv_clk_cnt_max = 8, +}; + static int ad4080_setup(struct iio_dev *indio_dev) { struct ad4080_state *st = iio_priv(indio_dev); @@ -666,10 +704,13 @@ static int ad4080_probe(struct spi_device *spi) static const struct spi_device_id ad4080_id[] = { { "ad4080", (kernel_ulong_t)&ad4080_chip_info }, { "ad4081", (kernel_ulong_t)&ad4081_chip_info }, + { "ad4082", (kernel_ulong_t)&ad4082_chip_info }, { "ad4083", (kernel_ulong_t)&ad4083_chip_info }, { "ad4084", (kernel_ulong_t)&ad4084_chip_info }, + { "ad4085", (kernel_ulong_t)&ad4085_chip_info }, { "ad4086", (kernel_ulong_t)&ad4086_chip_info }, { "ad4087", (kernel_ulong_t)&ad4087_chip_info }, + { "ad4088", (kernel_ulong_t)&ad4088_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, ad4080_id); @@ -677,10 +718,13 @@ MODULE_DEVICE_TABLE(spi, ad4080_id); static const struct of_device_id ad4080_of_match[] = { { .compatible = "adi,ad4080", &ad4080_chip_info }, { .compatible = "adi,ad4081", &ad4081_chip_info }, + { .compatible = "adi,ad4082", &ad4082_chip_info }, { .compatible = "adi,ad4083", &ad4083_chip_info }, { .compatible = "adi,ad4084", &ad4084_chip_info }, + { .compatible = "adi,ad4085", &ad4085_chip_info }, { .compatible = "adi,ad4086", &ad4086_chip_info }, { .compatible = "adi,ad4087", &ad4087_chip_info }, + { .compatible = "adi,ad4088", &ad4088_chip_info }, { } }; MODULE_DEVICE_TABLE(of, ad4080_of_match); diff --git a/drivers/iio/adc/ad4170-4.c b/drivers/iio/adc/ad4170-4.c index 82205bfae531..77af0e6b2c59 100644 --- a/drivers/iio/adc/ad4170-4.c +++ b/drivers/iio/adc/ad4170-4.c @@ -275,9 +275,9 @@ static const unsigned int ad4170_reg_size[] = { }; enum ad4170_ref_buf { - AD4170_REF_BUF_PRE, /* Pre-charge referrence buffer */ - AD4170_REF_BUF_FULL, /* Full referrence buffering */ - AD4170_REF_BUF_BYPASS, /* Bypass referrence buffering */ + AD4170_REF_BUF_PRE, /* Pre-charge reference buffer */ + AD4170_REF_BUF_FULL, /* Full reference buffering */ + AD4170_REF_BUF_BYPASS, /* Bypass reference buffering */ }; /* maps adi,positive/negative-reference-buffer property values to enum */ diff --git a/drivers/iio/adc/ad7173.c b/drivers/iio/adc/ad7173.c index d36612352b44..f76a9e08f39e 100644 --- a/drivers/iio/adc/ad7173.c +++ b/drivers/iio/adc/ad7173.c @@ -1763,7 +1763,8 @@ static int ad7173_validate_openwire_ain_inputs(struct ad7173_state *st, static unsigned int ad7173_calc_openwire_thrsh_raw(struct ad7173_state *st, struct iio_chan_spec *chan, struct ad7173_channel *chan_st_priv, - unsigned int thrsh_mv) { + unsigned int thrsh_mv) +{ unsigned int thrsh_raw; thrsh_raw = diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c index 530e1d307860..8b1664f6b102 100644 --- a/drivers/iio/adc/ad7192.c +++ b/drivers/iio/adc/ad7192.c @@ -1402,9 +1402,6 @@ static int ad7192_probe(struct spi_device *spi) st->int_vref_mv = ret == -ENODEV ? avdd_mv : ret / MILLI; st->chip_info = spi_get_device_match_data(spi); - if (!st->chip_info) - return -ENODEV; - indio_dev->name = st->chip_info->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = st->chip_info->info; diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index 3364ac6c4631..0ef36c249ab8 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -409,10 +409,8 @@ static int ad7266_probe(struct spi_device *spi) st->gpios[i] = devm_gpiod_get(&spi->dev, ad7266_gpio_labels[i], GPIOD_OUT_LOW); - if (IS_ERR(st->gpios[i])) { - ret = PTR_ERR(st->gpios[i]); - return ret; - } + if (IS_ERR(st->gpios[i])) + return PTR_ERR(st->gpios[i]); } } } else { diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index bfd908deefc0..9f77990a03f9 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -77,8 +77,7 @@ #define AD7380_CONFIG1_REFSEL BIT(1) #define AD7380_CONFIG1_PMODE BIT(0) -#define AD7380_CONFIG2_SDO2 GENMASK(9, 8) -#define AD7380_CONFIG2_SDO BIT(8) +#define AD7380_CONFIG2_SDO GENMASK(9, 8) #define AD7380_CONFIG2_RESET GENMASK(7, 0) #define AD7380_CONFIG2_RESET_SOFT 0x3C @@ -92,11 +91,6 @@ #define T_CONVERT_X_NS 500 /* xth conversion start time (oversampling) */ #define T_POWERUP_US 5000 /* Power up */ -/* - * AD738x support several SDO lines to increase throughput, but driver currently - * supports only 1 SDO line (standard SPI transaction) - */ -#define AD7380_NUM_SDO_LINES 1 #define AD7380_DEFAULT_GAIN_MILLI 1000 /* @@ -888,6 +882,8 @@ struct ad7380_state { bool resolution_boost_enabled; unsigned int ch; bool seq; + /* How many SDO lines are wired up. */ + u8 num_sdo_lines; unsigned int vref_mv; unsigned int vcm_mv[MAX_NUM_CHANNELS]; unsigned int gain_milli[MAX_NUM_CHANNELS]; @@ -1084,7 +1080,7 @@ static int ad7380_set_ch(struct ad7380_state *st, unsigned int ch) if (oversampling_ratio > 1) xfer.delay.value = T_CONVERT_0_NS + T_CONVERT_X_NS * (oversampling_ratio - 1) * - st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES; + st->chip_info->num_simult_channels / st->num_sdo_lines; return spi_sync_transfer(st->spi, &xfer, 1); } @@ -1113,7 +1109,7 @@ static int ad7380_update_xfers(struct ad7380_state *st, if (oversampling_ratio > 1) t_convert = T_CONVERT_0_NS + T_CONVERT_X_NS * (oversampling_ratio - 1) * - st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES; + st->chip_info->num_simult_channels / st->num_sdo_lines; if (st->seq) { xfer[0].delay.value = xfer[1].delay.value = t_convert; @@ -1198,6 +1194,8 @@ static int ad7380_init_offload_msg(struct ad7380_state *st, xfer->bits_per_word = scan_type->realbits; xfer->offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; xfer->len = AD7380_SPI_BYTES(scan_type) * st->chip_info->num_simult_channels; + if (st->num_sdo_lines > 1) + xfer->multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE; spi_message_init_with_transfers(&st->offload_msg, xfer, 1); st->offload_msg.offload = st->offload; @@ -1793,6 +1791,7 @@ static const struct iio_info ad7380_info = { static int ad7380_init(struct ad7380_state *st, bool external_ref_en) { + u32 sdo; int ret; /* perform hard reset */ @@ -1815,11 +1814,24 @@ static int ad7380_init(struct ad7380_state *st, bool external_ref_en) st->ch = 0; st->seq = false; - /* SPI 1-wire mode */ + /* SDO field has an irregular mapping. */ + switch (st->num_sdo_lines) { + case 1: + sdo = 1; + break; + case 2: + sdo = 0; + break; + case 4: + sdo = 2; + break; + default: + return -EINVAL; + } + return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2, AD7380_CONFIG2_SDO, - FIELD_PREP(AD7380_CONFIG2_SDO, - AD7380_NUM_SDO_LINES)); + FIELD_PREP(AD7380_CONFIG2_SDO, sdo)); } static int ad7380_probe_spi_offload(struct iio_dev *indio_dev, @@ -1842,7 +1854,7 @@ static int ad7380_probe_spi_offload(struct iio_dev *indio_dev, "failed to get offload trigger\n"); sample_rate = st->chip_info->max_conversion_rate_hz * - AD7380_NUM_SDO_LINES / st->chip_info->num_simult_channels; + st->num_sdo_lines / st->chip_info->num_simult_channels; st->sample_freq_range[0] = 1; /* min */ st->sample_freq_range[1] = 1; /* step */ @@ -1850,7 +1862,7 @@ static int ad7380_probe_spi_offload(struct iio_dev *indio_dev, /* * Starting with a quite low frequency, to allow oversampling x32, - * user is then reponsible to adjust the frequency for the specific case. + * user is then responsible to adjust the frequency for the specific case. */ ret = ad7380_set_sample_freq(st, sample_rate / 32); if (ret) @@ -1887,6 +1899,13 @@ static int ad7380_probe(struct spi_device *spi) if (!st->chip_info) return dev_err_probe(dev, -EINVAL, "missing match data\n"); + st->num_sdo_lines = spi->num_rx_lanes; + + if (st->num_sdo_lines < 1 || st->num_sdo_lines > st->chip_info->num_simult_channels) + return dev_err_probe(dev, -EINVAL, + "invalid number of SDO lines (%d)\n", + st->num_sdo_lines); + ret = devm_regulator_bulk_get_enable(dev, st->chip_info->num_supplies, st->chip_info->supplies); @@ -2010,6 +2029,8 @@ static int ad7380_probe(struct spi_device *spi) st->normal_xfer[0].cs_change_delay.value = st->chip_info->timing_specs->t_csh_ns; st->normal_xfer[0].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; st->normal_xfer[1].rx_buf = st->scan_data; + if (st->num_sdo_lines > 1) + st->normal_xfer[1].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE; spi_message_init_with_transfers(&st->normal_msg, st->normal_xfer, ARRAY_SIZE(st->normal_xfer)); @@ -2031,6 +2052,10 @@ static int ad7380_probe(struct spi_device *spi) st->seq_xfer[2].cs_change = 1; st->seq_xfer[2].cs_change_delay.value = st->chip_info->timing_specs->t_csh_ns; st->seq_xfer[2].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; + if (st->num_sdo_lines > 1) { + st->seq_xfer[2].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE; + st->seq_xfer[3].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE; + } spi_message_init_with_transfers(&st->seq_msg, st->seq_xfer, ARRAY_SIZE(st->seq_xfer)); diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c index e16dede687d3..73fb734d06b2 100644 --- a/drivers/iio/adc/ad7768-1.c +++ b/drivers/iio/adc/ad7768-1.c @@ -25,12 +25,15 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -161,6 +164,8 @@ enum ad7768_filter_regval { enum ad7768_scan_type { AD7768_SCAN_TYPE_NORMAL, AD7768_SCAN_TYPE_HIGH_SPEED, + AD7768_SCAN_TYPE_OFFLOAD_NORMAL, + AD7768_SCAN_TYPE_OFFLOAD_HIGH_SPEED, }; enum { @@ -266,6 +271,18 @@ static const struct iio_scan_type ad7768_scan_type[] = { .storagebits = 16, .endianness = IIO_BE, }, + [AD7768_SCAN_TYPE_OFFLOAD_NORMAL] = { + .sign = 's', + .realbits = 24, + .storagebits = 32, + .endianness = IIO_CPU, + }, + [AD7768_SCAN_TYPE_OFFLOAD_HIGH_SPEED] = { + .sign = 's', + .realbits = 16, + .storagebits = 32, + .endianness = IIO_CPU, + }, }; struct ad7768_chip_info { @@ -283,6 +300,8 @@ struct ad7768_chip_info { struct ad7768_state { struct spi_device *spi; + struct spi_offload *offload; + struct spi_offload_trigger *offload_trigger; struct regmap *regmap; struct regmap *regmap24; int vref_uv; @@ -290,7 +309,6 @@ struct ad7768_state { unsigned int vcm_output_sel; struct clk *mclk; unsigned int mclk_freq; - unsigned int mclk_div; unsigned int oversampling_ratio; enum ad7768_filter_type filter_type; unsigned int samp_freq; @@ -306,6 +324,8 @@ struct ad7768_state { struct gpio_desc *gpio_reset; const char *labels[AD7768_MAX_CHANNELS]; struct gpio_chip gpiochip; + struct spi_transfer offload_xfer; + struct spi_message offload_msg; const struct ad7768_chip_info *chip; bool en_spi_sync; struct mutex pga_lock; /* protect device internal state (PGA) */ @@ -464,13 +484,11 @@ static int ad7768_scan_direct(struct iio_dev *indio_dev) int readval, ret; reinit_completion(&st->completion); - - ret = ad7768_set_mode(st, AD7768_ONE_SHOT); - if (ret < 0) - return ret; + enable_irq(st->spi->irq); ret = wait_for_completion_timeout(&st->completion, msecs_to_jiffies(1000)); + disable_irq(st->spi->irq); if (!ret) return -ETIMEDOUT; @@ -487,14 +505,6 @@ static int ad7768_scan_direct(struct iio_dev *indio_dev) if (st->oversampling_ratio == 8) readval >>= 8; - /* - * Any SPI configuration of the AD7768-1 can only be - * performed in continuous conversion mode. - */ - ret = ad7768_set_mode(st, AD7768_CONTINUOUS); - if (ret < 0) - return ret; - return readval; } @@ -1138,6 +1148,10 @@ static int ad7768_get_current_scan_type(const struct iio_dev *indio_dev, { struct ad7768_state *st = iio_priv(indio_dev); + if (st->offload) + return st->oversampling_ratio == 8 ? + AD7768_SCAN_TYPE_OFFLOAD_HIGH_SPEED : AD7768_SCAN_TYPE_OFFLOAD_NORMAL; + return st->oversampling_ratio == 8 ? AD7768_SCAN_TYPE_HIGH_SPEED : AD7768_SCAN_TYPE_NORMAL; } @@ -1252,6 +1266,10 @@ static int ad7768_setup(struct iio_dev *indio_dev) return ret; } + ret = ad7768_set_mode(st, AD7768_CONTINUOUS); + if (ret) + return ret; + /* For backwards compatibility, try the adi,sync-in-gpios property */ st->gpio_sync_in = devm_gpiod_get_optional(&st->spi->dev, "adi,sync-in", GPIOD_OUT_LOW); @@ -1356,8 +1374,94 @@ static const struct iio_buffer_setup_ops ad7768_buffer_ops = { .predisable = &ad7768_buffer_predisable, }; +static int ad7768_offload_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad7768_state *st = iio_priv(indio_dev); + struct spi_offload_trigger_config config = { + .type = SPI_OFFLOAD_TRIGGER_DATA_READY, + }; + const struct iio_scan_type *scan_type; + unsigned int unused; + int ret; + + scan_type = iio_get_current_scan_type(indio_dev, &indio_dev->channels[0]); + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + + st->offload_xfer.len = spi_bpw_to_bytes(scan_type->realbits); + st->offload_xfer.bits_per_word = scan_type->realbits; + st->offload_xfer.offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; + + spi_message_init_with_transfers(&st->offload_msg, &st->offload_xfer, 1); + st->offload_msg.offload = st->offload; + + ret = spi_optimize_message(st->spi, &st->offload_msg); + if (ret) { + dev_err(&st->spi->dev, "failed to prepare offload, err: %d\n", ret); + return ret; + } + + /* + * Write a 1 to the LSB of the INTERFACE_FORMAT register to enter + * continuous read mode. Subsequent data reads do not require an + * initial 8-bit write to query the ADC_DATA register. + */ + ret = regmap_write(st->regmap, AD7768_REG_INTERFACE_FORMAT, 0x01); + if (ret) + goto err_unoptimize_message; + + ret = spi_offload_trigger_enable(st->offload, st->offload_trigger, + &config); + if (ret) + goto err_exit_continuous_read_mode; + + return 0; + +err_exit_continuous_read_mode: + regmap_read(st->regmap24, AD7768_REG24_ADC_DATA, &unused); + +err_unoptimize_message: + spi_unoptimize_message(&st->offload_msg); + + return ret; +} + +static int ad7768_offload_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ad7768_state *st = iio_priv(indio_dev); + unsigned int unused; + + spi_offload_trigger_disable(st->offload, st->offload_trigger); + spi_unoptimize_message(&st->offload_msg); + + /* + * To exit continuous read mode, perform a single read of the ADC_DATA + * reg (0x2C), which allows further configuration of the device. + */ + return regmap_read(st->regmap24, AD7768_REG24_ADC_DATA, &unused); +} + +static const struct iio_buffer_setup_ops ad7768_offload_buffer_ops = { + .postenable = ad7768_offload_buffer_postenable, + .predisable = ad7768_offload_buffer_predisable, +}; + +static int ad7768_set_trigger_state(struct iio_trigger *trig, bool enable) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct ad7768_state *st = iio_priv(indio_dev); + + if (enable) + enable_irq(st->spi->irq); + else + disable_irq(st->spi->irq); + + return 0; +} + static const struct iio_trigger_ops ad7768_trigger_ops = { .validate_device = iio_trigger_validate_own_device, + .set_trigger_state = ad7768_set_trigger_state, }; static int ad7768_set_channel_label(struct iio_dev *indio_dev, @@ -1590,6 +1694,36 @@ static int ad7768_parse_aaf_gain(struct device *dev, struct ad7768_state *st) return 0; } +static bool ad7768_offload_trigger_match(struct spi_offload_trigger *trigger, + enum spi_offload_trigger_type type, + u64 *args, u32 nargs) +{ + if (type != SPI_OFFLOAD_TRIGGER_DATA_READY) + return false; + + /* Up to 2 args are allowed, but only 1 is used */ + if (nargs == 0 || nargs > 2 || args[0] != AD7768_TRIGGER_SOURCE_DRDY) + return false; + + return true; +} + +static int ad7768_offload_trigger_request(struct spi_offload_trigger *trigger, + enum spi_offload_trigger_type type, + u64 *args, u32 nargs) +{ + /* Should already be validated by match, but just in case */ + if (nargs == 0 || nargs > 2) + return -EINVAL; + + return 0; +} + +static const struct spi_offload_trigger_ops ad7768_offload_trigger_ops = { + .match = ad7768_offload_trigger_match, + .request = ad7768_offload_trigger_request, +}; + static const struct ad7768_chip_info ad7768_chip_info = { .name = "ad7768-1", .channel_spec = ad7768_channels, @@ -1627,10 +1761,51 @@ static const struct ad7768_chip_info adaq7769_chip_info = { .has_variable_aaf = true, }; +static const struct spi_offload_config ad7768_spi_offload_config = { + .capability_flags = SPI_OFFLOAD_CAP_TRIGGER | SPI_OFFLOAD_CAP_RX_STREAM_DMA, +}; + +static int ad7768_spi_offload_probe(struct iio_dev *indio_dev, + struct ad7768_state *st) +{ + struct device *dev = &st->spi->dev; + struct spi_offload_trigger_info trigger_info = { + .fwnode = dev_fwnode(dev), + .ops = &ad7768_offload_trigger_ops, + .priv = st, + }; + struct dma_chan *rx_dma; + int ret; + + ret = devm_spi_offload_trigger_register(dev, &trigger_info); + if (ret) + return dev_err_probe(dev, ret, "failed to register offload trigger\n"); + + st->offload_trigger = devm_spi_offload_trigger_get(dev, st->offload, + SPI_OFFLOAD_TRIGGER_DATA_READY); + if (IS_ERR(st->offload_trigger)) + return dev_err_probe(dev, PTR_ERR(st->offload_trigger), + "failed to get offload trigger\n"); + + rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload); + if (IS_ERR(rx_dma)) + return dev_err_probe(dev, PTR_ERR(rx_dma), "failed to get offload RX DMA\n"); + + ret = devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma, + IIO_BUFFER_DIRECTION_IN); + if (ret) + return dev_err_probe(dev, ret, "failed to setup offload RX DMA\n"); + + indio_dev->setup_ops = &ad7768_offload_buffer_ops; + + return 0; +} + static int ad7768_probe(struct spi_device *spi) { struct ad7768_state *st; struct iio_dev *indio_dev; + struct device *dev = &spi->dev; int ret; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); @@ -1721,14 +1896,25 @@ static int ad7768_probe(struct spi_device *spi) return ret; ret = devm_request_irq(&spi->dev, spi->irq, &ad7768_interrupt, - IRQF_TRIGGER_RISING | IRQF_NO_THREAD, + IRQF_TRIGGER_RISING | IRQF_NO_THREAD | IRQF_NO_AUTOEN, indio_dev->name, indio_dev); if (ret) return ret; - ret = ad7768_triggered_buffer_alloc(indio_dev); - if (ret) - return ret; + st->offload = devm_spi_offload_get(dev, spi, &ad7768_spi_offload_config); + ret = PTR_ERR_OR_ZERO(st->offload); + if (ret == -ENODEV) { + /* If not using SPI offload, fall back to low speed usage */ + ret = ad7768_triggered_buffer_alloc(indio_dev); + if (ret) + return ret; + } else if (ret) { + return dev_err_probe(dev, ret, "failed to get SPI offload\n"); + } else { + ret = ad7768_spi_offload_probe(indio_dev, st); + if (ret) + return ret; + } return devm_iio_device_register(&spi->dev, indio_dev); } @@ -1764,3 +1950,4 @@ module_spi_driver(ad7768_driver); MODULE_AUTHOR("Stefan Popa "); MODULE_DESCRIPTION("Analog Devices AD7768-1 ADC driver"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER"); diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index ccf18ce48e34..8ff7b70d6632 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -152,7 +152,6 @@ struct ad7793_chip_info { struct ad7793_state { const struct ad7793_chip_info *chip_info; - u16 int_vref_mv; u16 mode; u16 conf; u32 scale_avail[8][2]; @@ -805,7 +804,7 @@ static int ad7793_probe(struct spi_device *spi) vref_mv = ret / 1000; } else { - vref_mv = 1170; /* Build-in ref */ + vref_mv = 1170; /* Built-in ref */ } st->chip_info = diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c index 87ff95643794..068171d54596 100644 --- a/drivers/iio/adc/ad7887.c +++ b/drivers/iio/adc/ad7887.c @@ -104,7 +104,7 @@ static int ad7887_ring_postdisable(struct iio_dev *indio_dev) { struct ad7887_state *st = iio_priv(indio_dev); - /* dummy read: restore default CH0 settin */ + /* dummy read: restore default CH0 settings */ return spi_sync(st->spi, &st->msg[AD7887_CH0]); } diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c index 0369151c7db1..acc87d486aa4 100644 --- a/drivers/iio/adc/ad7923.c +++ b/drivers/iio/adc/ad7923.c @@ -30,7 +30,7 @@ #define AD7923_PM_MODE_AS (1) /* auto shutdown */ #define AD7923_PM_MODE_FS (2) /* full shutdown */ #define AD7923_PM_MODE_OPS (3) /* normal operation */ -#define AD7923_SEQUENCE_OFF (0) /* no sequence fonction */ +#define AD7923_SEQUENCE_OFF (0) /* no sequence function */ #define AD7923_SEQUENCE_PROTECT (2) /* no interrupt write cycle */ #define AD7923_SEQUENCE_ON (3) /* continuous sequence */ @@ -39,7 +39,7 @@ #define AD7923_CHANNEL_WRITE(channel) ((channel) << 6) /* write channel */ #define AD7923_SEQUENCE_WRITE(sequence) ((((sequence) & 1) << 3) \ + (((sequence) & 2) << 9)) - /* write sequence fonction */ + /* write sequence function */ /* left shift for CR : bit 11 transmit in first */ #define AD7923_SHIFT_REGISTER 4 diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c index 022888545580..0bf67437508f 100644 --- a/drivers/iio/adc/ad9467.c +++ b/drivers/iio/adc/ad9467.c @@ -176,7 +176,6 @@ struct ad9467_state { struct clk *clk; /* used for debugfs */ struct ad9467_chan_test_mode *chan_test; - unsigned int output_mode; unsigned int (*scales)[2]; /* * Times 2 because we may also invert the signal polarity and run the @@ -925,7 +924,11 @@ static int __ad9467_update_clock(struct ad9467_state *st, long r_clk) return ret; guard(mutex)(&st->lock); - return ad9467_calibrate(st); + + if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) + return ad9467_calibrate(st); + + return 0; } static int ad9467_write_raw(struct iio_dev *indio_dev, @@ -1131,12 +1134,15 @@ static ssize_t ad9467_chan_test_mode_read(struct file *file, len = scnprintf(buf, sizeof(buf), "Running \"%s\" Test:\n\t", ad9467_test_modes[chan->mode]); - ret = iio_backend_debugfs_print_chan_status(st->back, chan->idx, - buf + len, - sizeof(buf) - len); - if (ret < 0) - return ret; - len += ret; + if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) { + ret = iio_backend_debugfs_print_chan_status(st->back, + chan->idx, + buf + len, + sizeof(buf) - len); + if (ret < 0) + return ret; + len += ret; + } } else if (chan->mode == AN877_ADC_TESTMODE_OFF) { len = scnprintf(buf, sizeof(buf), "No test Running...\n"); } else { @@ -1175,11 +1181,13 @@ static ssize_t ad9467_chan_test_mode_write(struct file *file, if (mode == AN877_ADC_TESTMODE_OFF) { unsigned int out_mode; - if (chan->mode == AN877_ADC_TESTMODE_PN9_SEQ || - chan->mode == AN877_ADC_TESTMODE_PN23_SEQ) { - ret = ad9467_backend_testmode_off(st, chan->idx); - if (ret) - return ret; + if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) { + if (chan->mode == AN877_ADC_TESTMODE_PN9_SEQ || + chan->mode == AN877_ADC_TESTMODE_PN23_SEQ) { + ret = ad9467_backend_testmode_off(st, chan->idx); + if (ret) + return ret; + } } ret = ad9467_testmode_set(st, chan->idx, mode); @@ -1205,16 +1213,18 @@ static ssize_t ad9467_chan_test_mode_write(struct file *file, return ret; /* some patterns have a backend matching monitoring block */ - if (mode == AN877_ADC_TESTMODE_PN9_SEQ) { - ret = ad9467_backend_testmode_on(st, chan->idx, + if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) { + if (mode == AN877_ADC_TESTMODE_PN9_SEQ) { + ret = ad9467_backend_testmode_on(st, chan->idx, IIO_BACKEND_ADI_PRBS_9A); - if (ret) - return ret; - } else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) { - ret = ad9467_backend_testmode_on(st, chan->idx, + if (ret) + return ret; + } else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) { + ret = ad9467_backend_testmode_on(st, chan->idx, IIO_BACKEND_ADI_PRBS_23A); - if (ret) - return ret; + if (ret) + return ret; + } } } @@ -1280,8 +1290,9 @@ static void ad9467_debugfs_init(struct iio_dev *indio_dev) if (!st->chan_test) return; - debugfs_create_file("calibration_table_dump", 0400, d, st, - &ad9467_calib_table_fops); + if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) + debugfs_create_file("calibration_table_dump", 0400, d, st, + &ad9467_calib_table_fops); for (chan = 0; chan < st->info->num_channels; chan++) { snprintf(attr_name, sizeof(attr_name), "in_voltage%u_test_mode", @@ -1300,12 +1311,13 @@ static void ad9467_debugfs_init(struct iio_dev *indio_dev) static int ad9467_probe(struct spi_device *spi) { + struct device *dev = &spi->dev; struct iio_dev *indio_dev; struct ad9467_state *st; unsigned int id; int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -1320,16 +1332,15 @@ static int ad9467_probe(struct spi_device *spi) if (AD9467_CAN_INVERT(st)) st->calib_map_size *= 2; - st->clk = devm_clk_get_enabled(&spi->dev, "adc-clk"); + st->clk = devm_clk_get_enabled(dev, "adc-clk"); if (IS_ERR(st->clk)) return PTR_ERR(st->clk); - st->pwrdown_gpio = devm_gpiod_get_optional(&spi->dev, "powerdown", - GPIOD_OUT_LOW); + st->pwrdown_gpio = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_LOW); if (IS_ERR(st->pwrdown_gpio)) return PTR_ERR(st->pwrdown_gpio); - ret = ad9467_reset(&spi->dev); + ret = ad9467_reset(dev); if (ret) return ret; @@ -1339,7 +1350,7 @@ static int ad9467_probe(struct spi_device *spi) id = ad9467_spi_read(st, AN877_ADC_REG_CHIP_ID); if (id != st->info->id) { - dev_err(&spi->dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n", + dev_err(dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n", id, st->info->id); return -ENODEV; } @@ -1356,19 +1367,25 @@ static int ad9467_probe(struct spi_device *spi) if (ret) return ret; - ret = devm_iio_backend_request_buffer(&spi->dev, st->back, indio_dev); - if (ret) - return ret; + if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_BUFFER)) { + ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev); + if (ret) + return ret; + } - ret = devm_iio_backend_enable(&spi->dev, st->back); - if (ret) - return ret; + if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_ENABLE)) { + ret = devm_iio_backend_enable(dev, st->back); + if (ret) + return ret; + } - ret = ad9467_calibrate(st); - if (ret) - return ret; + if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) { + ret = ad9467_calibrate(st); + if (ret) + return ret; + } - ret = devm_iio_device_register(&spi->dev, indio_dev); + ret = devm_iio_device_register(dev, indio_dev); if (ret) return ret; diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index 7852884703b0..a955556f9ec8 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -51,8 +51,10 @@ */ void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, u8 comm) { - /* Some variants use the lower two bits of the communications register - * to select the channel */ + /* + * Some variants use the lower two bits of the communications register + * to select the channel. + */ sigma_delta->comm = comm & AD_SD_COMM_CHAN_MASK; } EXPORT_SYMBOL_NS_GPL(ad_sd_set_comm, "IIO_AD_SIGMA_DELTA"); diff --git a/drivers/iio/adc/ade9000.c b/drivers/iio/adc/ade9000.c index db085dc5e526..c9c21fa4a28b 100644 --- a/drivers/iio/adc/ade9000.c +++ b/drivers/iio/adc/ade9000.c @@ -218,9 +218,6 @@ #define ADE9000_ST1_ERROR1_BIT BIT(29) #define ADE9000_ST1_ERROR2_BIT BIT(30) #define ADE9000_ST1_ERROR3_BIT BIT(31) -#define ADE9000_ST_ERROR \ - (ADE9000_ST1_ERROR0 | ADE9000_ST1_ERROR1 | \ - ADE9000_ST1_ERROR2 | ADE9000_ST1_ERROR3) #define ADE9000_ST1_CROSSING_FIRST 6 #define ADE9000_ST1_CROSSING_DEPTH 25 @@ -283,7 +280,6 @@ enum ade9000_wfb_cfg { #define ADE9000_PHASE_C_POS_BIT BIT(6) #define ADE9000_MAX_PHASE_NR 3 -#define AD9000_CHANNELS_PER_PHASE 10 /* * Calculate register address for multi-phase device. @@ -1549,7 +1545,7 @@ static int ade9000_buffer_postdisable(struct iio_dev *indio_dev) ret = regmap_clear_bits(st->regmap, ADE9000_REG_MASK0, interrupts); if (ret) { - dev_err(dev, "Post-disable update maks0 fail\n"); + dev_err(dev, "Post-disable update mask0 fail\n"); return ret; } @@ -1589,10 +1585,9 @@ static int ade9000_reset(struct ade9000_state *st) /* Only wait for completion if IRQ1 is available to signal reset done */ if (fwnode_irq_get_byname(dev_fwnode(dev), "irq1") >= 0) { if (!wait_for_completion_timeout(&st->reset_completion, - msecs_to_jiffies(1000))) { - dev_err(dev, "Reset timeout after 1s\n"); - return -ETIMEDOUT; - } + msecs_to_jiffies(1000))) + return dev_err_probe(dev, -ETIMEDOUT, + "Reset timeout after 1s\n"); } /* If no IRQ available, reset is already complete after the 50ms delay above */ diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c index 5f445e0de9ea..ced0a2321ecf 100644 --- a/drivers/iio/adc/adi-axi-adc.c +++ b/drivers/iio/adc/adi-axi-adc.c @@ -621,6 +621,8 @@ static const struct iio_backend_ops adi_axi_adc_ops = { static const struct iio_backend_info adi_axi_adc_generic = { .name = "axi-adc", .ops = &adi_axi_adc_ops, + .caps = IIO_BACKEND_CAP_CALIBRATION | IIO_BACKEND_CAP_BUFFER | + IIO_BACKEND_CAP_ENABLE, }; static const struct iio_backend_ops adi_ad485x_ops = { @@ -645,6 +647,8 @@ static const struct iio_backend_ops adi_ad485x_ops = { static const struct iio_backend_info axi_ad485x = { .name = "axi-ad485x", .ops = &adi_ad485x_ops, + .caps = IIO_BACKEND_CAP_CALIBRATION | IIO_BACKEND_CAP_BUFFER | + IIO_BACKEND_CAP_ENABLE, }; static const struct iio_backend_ops adi_ad408x_ops = { @@ -665,6 +669,7 @@ static const struct iio_backend_ops adi_ad408x_ops = { static const struct iio_backend_info axi_ad408x = { .name = "axi-ad408x", .ops = &adi_ad408x_ops, + .caps = IIO_BACKEND_CAP_BUFFER | IIO_BACKEND_CAP_ENABLE, }; static int adi_axi_adc_probe(struct platform_device *pdev) diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c index 4be44c524b4d..9b828a3c91da 100644 --- a/drivers/iio/adc/aspeed_adc.c +++ b/drivers/iio/adc/aspeed_adc.c @@ -75,6 +75,8 @@ #define ASPEED_ADC_INIT_POLLING_TIME 500 #define ASPEED_ADC_INIT_TIMEOUT 500000 +/* Battery sensing is typically on the last channel */ +#define ASPEED_ADC_BATTERY_CHANNEL 7 /* * When the sampling rate is too high, the ADC may not have enough charging * time, resulting in a low voltage value. Thus, the default uses a slow @@ -121,6 +123,31 @@ struct aspeed_adc_data { struct adc_gain battery_mode_gain; }; +/* + * Enable multiple consecutive channels starting from channel 0. + * This creates a bitmask for channels 0 to (num_channels - 1). + * For example: num_channels=3 creates mask 0x0007 (channels 0,1,2) + */ +static inline u32 aspeed_adc_channels_mask(unsigned int num_channels) +{ + if (num_channels > 16) + return GENMASK(15, 0); + + return BIT(num_channels) - 1; +} + +static inline unsigned int aspeed_adc_get_active_channels(const struct aspeed_adc_data *data) +{ + /* + * For controllers with battery sensing capability, the last channel + * is reserved for battery sensing and should not be included in + * normal channel operations. + */ + if (data->model_data->bat_sense_sup) + return data->model_data->num_channels - 1; + return data->model_data->num_channels; +} + #define ASPEED_CHAN(_idx, _data_reg_addr) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ @@ -236,10 +263,10 @@ static int aspeed_adc_compensation(struct iio_dev *indio_dev) ASPEED_ADC_CTRL_CHANNEL_ENABLE(0), data->base + ASPEED_REG_ENGINE_CONTROL); /* - * After enable compensating sensing mode need to wait some time for ADC stable - * Experiment result is 1ms. + * After enable compensating sensing mode need to wait some time for the + * ADC stablize. Experiment result is 1ms. */ - mdelay(1); + fsleep(1000); for (index = 0; index < 16; index++) { /* @@ -285,31 +312,48 @@ static int aspeed_adc_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - if (data->battery_sensing && chan->channel == 7) { - adc_engine_control_reg_val = - readl(data->base + ASPEED_REG_ENGINE_CONTROL); + adc_engine_control_reg_val = readl(data->base + ASPEED_REG_ENGINE_CONTROL); + /* + * For battery sensing capable controllers, we need to enable + * the specific channel before reading. This is required because + * the battery channel may not be enabled by default. + */ + if (data->model_data->bat_sense_sup && + chan->channel == ASPEED_ADC_BATTERY_CHANNEL) { + u32 ctrl_reg = adc_engine_control_reg_val & ~ASPEED_ADC_CTRL_CHANNEL; + + ctrl_reg |= ASPEED_ADC_CTRL_CHANNEL_ENABLE(chan->channel); + writel(ctrl_reg, data->base + ASPEED_REG_ENGINE_CONTROL); + /* + * After enable a new channel need to wait some time for ADC stable + * Experiment result is 1ms. + */ + fsleep(1000); + } + + if (data->battery_sensing && chan->channel == ASPEED_ADC_BATTERY_CHANNEL) { writel(adc_engine_control_reg_val | FIELD_PREP(ASPEED_ADC_CH7_MODE, ASPEED_ADC_CH7_BAT) | ASPEED_ADC_BAT_SENSING_ENABLE, data->base + ASPEED_REG_ENGINE_CONTROL); /* - * After enable battery sensing mode need to wait some time for adc stable + * After enable battery sensing mode need to wait some time for ADC stable * Experiment result is 1ms. */ - mdelay(1); + fsleep(1000); *val = readw(data->base + chan->address); *val = (*val * data->battery_mode_gain.mult) / data->battery_mode_gain.div; - /* Restore control register value */ - writel(adc_engine_control_reg_val, - data->base + ASPEED_REG_ENGINE_CONTROL); } else *val = readw(data->base + chan->address); + /* Restore control register value */ + writel(adc_engine_control_reg_val, + data->base + ASPEED_REG_ENGINE_CONTROL); return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: - if (data->battery_sensing && chan->channel == 7) + if (data->battery_sensing && chan->channel == ASPEED_ADC_BATTERY_CHANNEL) *val = (data->cv * data->battery_mode_gain.mult) / data->battery_mode_gain.div; else @@ -610,7 +654,9 @@ static int aspeed_adc_probe(struct platform_device *pdev) /* Start all channels in normal mode. */ adc_engine_control_reg_val = readl(data->base + ASPEED_REG_ENGINE_CONTROL); - adc_engine_control_reg_val |= ASPEED_ADC_CTRL_CHANNEL; + FIELD_MODIFY(ASPEED_ADC_CTRL_CHANNEL, &adc_engine_control_reg_val, + aspeed_adc_channels_mask(aspeed_adc_get_active_channels(data))); + writel(adc_engine_control_reg_val, data->base + ASPEED_REG_ENGINE_CONTROL); diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index aa4ba3f5a506..255970b2e747 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -2259,7 +2259,7 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st, return 0; /* Get the calibration data from NVMEM. */ - temp_calib = devm_nvmem_cell_get(dev, "temperature_calib"); + temp_calib = nvmem_cell_get(dev, "temperature_calib"); if (IS_ERR(temp_calib)) { ret = PTR_ERR(temp_calib); if (ret != -ENOENT) @@ -2268,6 +2268,7 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st, } buf = nvmem_cell_read(temp_calib, &len); + nvmem_cell_put(temp_calib); if (IS_ERR(buf)) { dev_err(dev, "Failed to read calibration data!\n"); return PTR_ERR(buf); @@ -2507,7 +2508,7 @@ static int at91_adc_suspend(struct device *dev) at91_adc_buffer_postdisable(indio_dev); /* - * Do a sofware reset of the ADC before we go to suspend. + * Do a software reset of the ADC before we go to suspend. * this will ensure that all pins are free from being muxed by the ADC * and can be used by for other devices. * Otherwise, ADC will hog them and we can't go to suspend mode. diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 920dd9ffd27a..6e1930f7c65d 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -171,7 +171,7 @@ struct at91_adc_trigger { }; /** - * struct at91_adc_reg_desc - Various informations relative to registers + * struct at91_adc_reg_desc - Various information relative to registers * @channel_base: Base offset for the channel data registers * @drdy_mask: Mask of the DRDY field in the relevant registers * (Interruptions registers mostly) @@ -231,7 +231,7 @@ struct at91_adc_state { struct iio_trigger **trig; bool use_external; u32 vref_mv; - u32 res; /* resolution used for convertions */ + u32 res; /* resolution used for conversions */ wait_queue_head_t wq_data_avail; const struct at91_adc_caps *caps; @@ -304,7 +304,7 @@ static void handle_adc_eoc_trigger(int irq, struct iio_dev *idev) } } -static int at91_ts_sample(struct iio_dev *idev) +static void at91_ts_sample(struct iio_dev *idev) { struct at91_adc_state *st = iio_priv(idev); unsigned int xscale, yscale, reg, z1, z2; @@ -323,7 +323,7 @@ static int at91_ts_sample(struct iio_dev *idev) xscale = (reg >> 16) & xyz_mask; if (xscale == 0) { dev_err(&idev->dev, "Error: xscale == 0!\n"); - return -1; + return; } x /= xscale; @@ -334,7 +334,7 @@ static int at91_ts_sample(struct iio_dev *idev) yscale = (reg >> 16) & xyz_mask; if (yscale == 0) { dev_err(&idev->dev, "Error: yscale == 0!\n"); - return -1; + return; } y /= yscale; @@ -363,8 +363,6 @@ static int at91_ts_sample(struct iio_dev *idev) } else { dev_dbg(&idev->dev, "pressure too low: not reporting\n"); } - - return 0; } static irqreturn_t at91_adc_rl_interrupt(int irq, void *private) diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c index d9ee2ea116a7..f6f72efcc6ed 100644 --- a/drivers/iio/adc/cpcap-adc.c +++ b/drivers/iio/adc/cpcap-adc.c @@ -934,6 +934,17 @@ static const struct cpcap_adc_ato mapphone_adc = { .atox_ps_factor_out = 0, }; +static const struct cpcap_adc_ato mot_adc = { + .ato_in = 0x0300, + .atox_in = 0, + .adc_ps_factor_in = 0x0200, + .atox_ps_factor_in = 0, + .ato_out = 0x0780, + .atox_out = 0, + .adc_ps_factor_out = 0x0600, + .atox_ps_factor_out = 0, +}; + static const struct of_device_id cpcap_adc_id_table[] = { { .compatible = "motorola,cpcap-adc", @@ -942,6 +953,10 @@ static const struct of_device_id cpcap_adc_id_table[] = { .compatible = "motorola,mapphone-cpcap-adc", .data = &mapphone_adc, }, + { + .compatible = "motorola,mot-cpcap-adc", + .data = &mot_adc, + }, { } }; MODULE_DEVICE_TABLE(of, cpcap_adc_id_table); diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c index f8c220f6a7b4..e6268f7ac400 100644 --- a/drivers/iio/adc/fsl-imx25-gcq.c +++ b/drivers/iio/adc/fsl-imx25-gcq.c @@ -47,7 +47,7 @@ struct mx25_gcq_priv { * of register writes, then a wait for a completion callback, * and finally a register read, during which userspace could issue * another read request. This lock protects a read access from - * ocurring before another one has finished. + * occurring before another one has finished. */ struct mutex lock; }; diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 857e1b69d6cd..dd37109a008a 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -121,7 +121,7 @@ static const struct regmap_config ina2xx_regmap_config = { .volatile_reg = ina2xx_is_volatile_reg, }; -enum ina2xx_ids { ina219, ina226 }; +enum ina2xx_ids { ina219, ina226, ina236 }; struct ina2xx_config { const char *name; @@ -175,6 +175,16 @@ static const struct ina2xx_config ina2xx_config[] = { .power_lsb_factor = 25, .chip_id = ina226, }, + [ina236] = { + .name = "ina236", + .config_default = INA226_CONFIG_DEFAULT, + .calibration_value = 2048, + .shunt_voltage_lsb = 2500, + .bus_voltage_shift = 0, + .bus_voltage_lsb = 1600, + .power_lsb_factor = 32, + .chip_id = ina236, + }, }; static int ina2xx_read_raw(struct iio_dev *indio_dev, @@ -499,20 +509,26 @@ static int ina2xx_write_raw(struct iio_dev *indio_dev, break; case IIO_CHAN_INFO_INT_TIME: - if (chip->config->chip_id == ina226) { + switch (chip->config->chip_id) { + case ina226: + case ina236: if (chan->address == INA2XX_SHUNT_VOLTAGE) ret = ina226_set_int_time_vshunt(chip, val2, &tmp); else ret = ina226_set_int_time_vbus(chip, val2, &tmp); - } else { + break; + case ina219: if (chan->address == INA2XX_SHUNT_VOLTAGE) ret = ina219_set_int_time_vshunt(chip, val2, &tmp); else ret = ina219_set_int_time_vbus(chip, val2, &tmp); + break; + default: + ret = -EINVAL; } break; @@ -727,19 +743,27 @@ static int ina2xx_conversion_ready(struct iio_dev *indio_dev) * For now, we do an extra read of the MASK_ENABLE register (INA226) * resp. the BUS_VOLTAGE register (INA219). */ - if (chip->config->chip_id == ina226) { + switch (chip->config->chip_id) { + case ina226: + case ina236: ret = regmap_read(chip->regmap, INA226_MASK_ENABLE, &alert); + if (ret < 0) + return ret; + alert &= INA226_CVRF; - } else { + break; + case ina219: ret = regmap_read(chip->regmap, INA2XX_BUS_VOLTAGE, &alert); + if (ret < 0) + return ret; alert &= INA219_CNVR; + break; + default: + return -EINVAL; } - if (ret < 0) - return ret; - return !!alert; } @@ -998,16 +1022,22 @@ static int ina2xx_probe(struct i2c_client *client) /* Patch the current config register with default. */ val = chip->config->config_default; - if (type == ina226) { + switch (type) { + case ina226: + case ina236: ina226_set_average(chip, INA226_DEFAULT_AVG, &val); ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val); ina226_set_int_time_vshunt(chip, INA226_DEFAULT_IT, &val); - } else { + break; + case ina219: chip->avg = 1; ina219_set_int_time_vbus(chip, INA219_DEFAULT_IT, &val); ina219_set_int_time_vshunt(chip, INA219_DEFAULT_IT, &val); ina219_set_vbus_range_denom(chip, INA219_DEFAULT_BRNG, &val); ina219_set_vshunt_pga_gain(chip, INA219_DEFAULT_PGA, &val); + break; + default: + return -EINVAL; } ret = ina2xx_init(chip, val); @@ -1017,14 +1047,20 @@ static int ina2xx_probe(struct i2c_client *client) } indio_dev->modes = INDIO_DIRECT_MODE; - if (type == ina226) { + switch (type) { + case ina226: + case ina236: indio_dev->channels = ina226_channels; indio_dev->num_channels = ARRAY_SIZE(ina226_channels); indio_dev->info = &ina226_info; - } else { + break; + case ina219: indio_dev->channels = ina219_channels; indio_dev->num_channels = ARRAY_SIZE(ina219_channels); indio_dev->info = &ina219_info; + break; + default: + return -EINVAL; } indio_dev->name = id ? id->name : chip->config->name; @@ -1057,6 +1093,7 @@ static const struct i2c_device_id ina2xx_id[] = { { "ina226", ina226 }, { "ina230", ina226 }, { "ina231", ina226 }, + { "ina236", ina236 }, { } }; MODULE_DEVICE_TABLE(i2c, ina2xx_id); @@ -1082,6 +1119,10 @@ static const struct of_device_id ina2xx_of_match[] = { .compatible = "ti,ina231", .data = (void *)ina226 }, + { + .compatible = "ti,ina236", + .data = (void *)ina236 + }, { } }; MODULE_DEVICE_TABLE(of, ina2xx_of_match); diff --git a/drivers/iio/adc/ltc2309.c b/drivers/iio/adc/ltc2309.c index 5f0d947d0615..316256edf150 100644 --- a/drivers/iio/adc/ltc2309.c +++ b/drivers/iio/adc/ltc2309.c @@ -1,8 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 /* + * The LTC2305 is a 2-Channel, 12-Bit SAR ADC with an I2C Interface. * The LTC2309 is an 8-Channel, 12-Bit SAR ADC with an I2C Interface. * * Datasheet: + * https://www.analog.com/media/en/technical-documentation/data-sheets/23015fb.pdf * https://www.analog.com/media/en/technical-documentation/data-sheets/2309fd.pdf * * Copyright (c) 2023, Liam Beguin @@ -41,23 +43,30 @@ struct ltc2309 { }; /* Order matches expected channel address, See datasheet Table 1. */ +enum ltc2305_channels { + LTC2305_CH0_CH1 = 0x0, + LTC2305_CH1_CH0 = 0x4, + LTC2305_CH0 = 0x8, + LTC2305_CH1 = 0xc, +}; + enum ltc2309_channels { - LTC2309_CH0_CH1 = 0, - LTC2309_CH2_CH3, - LTC2309_CH4_CH5, - LTC2309_CH6_CH7, - LTC2309_CH1_CH0, - LTC2309_CH3_CH2, - LTC2309_CH5_CH4, - LTC2309_CH7_CH6, - LTC2309_CH0, - LTC2309_CH2, - LTC2309_CH4, - LTC2309_CH6, - LTC2309_CH1, - LTC2309_CH3, - LTC2309_CH5, - LTC2309_CH7, + LTC2309_CH0_CH1 = 0x0, + LTC2309_CH2_CH3 = 0x1, + LTC2309_CH4_CH5 = 0x2, + LTC2309_CH6_CH7 = 0x3, + LTC2309_CH1_CH0 = 0x4, + LTC2309_CH3_CH2 = 0x5, + LTC2309_CH5_CH4 = 0x6, + LTC2309_CH7_CH6 = 0x7, + LTC2309_CH0 = 0x8, + LTC2309_CH2 = 0x9, + LTC2309_CH4 = 0xa, + LTC2309_CH6 = 0xb, + LTC2309_CH1 = 0xc, + LTC2309_CH3 = 0xd, + LTC2309_CH5 = 0xe, + LTC2309_CH7 = 0xf, }; #define LTC2309_CHAN(_chan, _addr) { \ @@ -80,6 +89,13 @@ enum ltc2309_channels { .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ } +static const struct iio_chan_spec ltc2305_channels[] = { + LTC2309_CHAN(0, LTC2305_CH0), + LTC2309_CHAN(1, LTC2305_CH1), + LTC2309_DIFF_CHAN(0, 1, LTC2305_CH0_CH1), + LTC2309_DIFF_CHAN(1, 0, LTC2305_CH1_CH0), +}; + static const struct iio_chan_spec ltc2309_channels[] = { LTC2309_CHAN(0, LTC2309_CH0), LTC2309_CHAN(1, LTC2309_CH1), @@ -99,6 +115,24 @@ static const struct iio_chan_spec ltc2309_channels[] = { LTC2309_DIFF_CHAN(7, 6, LTC2309_CH7_CH6), }; +struct ltc2309_chip_info { + const char *name; + const struct iio_chan_spec *channels; + int num_channels; +}; + +static const struct ltc2309_chip_info ltc2305_chip_info = { + .name = "ltc2305", + .channels = ltc2305_channels, + .num_channels = ARRAY_SIZE(ltc2305_channels), +}; + +static const struct ltc2309_chip_info ltc2309_chip_info = { + .name = "ltc2309", + .channels = ltc2309_channels, + .num_channels = ARRAY_SIZE(ltc2309_channels), +}; + static int ltc2309_read_raw_channel(struct ltc2309 *ltc2309, unsigned long address, int *val) { @@ -158,6 +192,7 @@ static const struct iio_info ltc2309_info = { static int ltc2309_probe(struct i2c_client *client) { + const struct ltc2309_chip_info *chip_info; struct iio_dev *indio_dev; struct ltc2309 *ltc2309; int ret; @@ -167,13 +202,15 @@ static int ltc2309_probe(struct i2c_client *client) return -ENOMEM; ltc2309 = iio_priv(indio_dev); + chip_info = i2c_get_match_data(client); + ltc2309->dev = &indio_dev->dev; ltc2309->client = client; - indio_dev->name = "ltc2309"; + indio_dev->name = chip_info->name; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = ltc2309_channels; - indio_dev->num_channels = ARRAY_SIZE(ltc2309_channels); + indio_dev->channels = chip_info->channels; + indio_dev->num_channels = chip_info->num_channels; indio_dev->info = <c2309_info; ret = devm_regulator_get_enable_read_voltage(&client->dev, "vref"); @@ -189,13 +226,15 @@ static int ltc2309_probe(struct i2c_client *client) } static const struct of_device_id ltc2309_of_match[] = { - { .compatible = "lltc,ltc2309" }, + { .compatible = "lltc,ltc2305", .data = <c2305_chip_info }, + { .compatible = "lltc,ltc2309", .data = <c2309_chip_info }, { } }; MODULE_DEVICE_TABLE(of, ltc2309_of_match); static const struct i2c_device_id ltc2309_id[] = { - { "ltc2309" }, + { "ltc2305", (kernel_ulong_t)<c2305_chip_info }, + { "ltc2309", (kernel_ulong_t)<c2309_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, ltc2309_id); diff --git a/drivers/iio/adc/max11410.c b/drivers/iio/adc/max11410.c index 511b2f14dfaf..69351f4f10bb 100644 --- a/drivers/iio/adc/max11410.c +++ b/drivers/iio/adc/max11410.c @@ -912,8 +912,8 @@ static int max11410_self_calibrate(struct max11410_state *st) static int max11410_probe(struct spi_device *spi) { - const char *vrefp_regs[] = { "vref0p", "vref1p", "vref2p" }; - const char *vrefn_regs[] = { "vref0n", "vref1n", "vref2n" }; + static const char * const vrefp_regs[] = { "vref0p", "vref1p", "vref2p" }; + static const char * const vrefn_regs[] = { "vref0n", "vref1n", "vref2n" }; struct device *dev = &spi->dev; struct max11410_state *st; struct iio_dev *indio_dev; diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index 9dd547e62b6c..4d0b79cfeb27 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -121,7 +121,7 @@ enum max1363_modes { }; /** - * struct max1363_chip_info - chip specifc information + * struct max1363_chip_info - chip specific information * @info: iio core function callbacks structure * @channels: channel specification * @num_channels: number of channels @@ -149,7 +149,6 @@ struct max1363_chip_info { * @configbyte: cache of current device config byte * @chip_info: chip model specific constants, available modes, etc. * @current_mode: the scan mode of this chip - * @requestedmask: a valid requested set of channels * @lock: lock to ensure state is consistent * @monitor_on: whether monitor mode is enabled * @monitor_speed: parameter corresponding to device monitor speed setting @@ -169,7 +168,6 @@ struct max1363_state { u8 configbyte; const struct max1363_chip_info *chip_info; const struct max1363_mode *current_mode; - u32 requestedmask; struct mutex lock; /* Using monitor modes and buffer at the same time is @@ -637,48 +635,51 @@ static const enum max1363_modes max11644_mode_list[] = { static const struct iio_chan_spec max11646_channels[] = MAX1363_2X_CHANS(10); static const struct iio_chan_spec max11644_channels[] = MAX1363_2X_CHANS(12); -enum { max1361, - max1362, - max1363, - max1364, - max1036, - max1037, - max1038, - max1039, - max1136, - max1137, - max1138, - max1139, - max1236, - max1237, - max1238, - max1239, - max11600, - max11601, - max11602, - max11603, - max11604, - max11605, - max11606, - max11607, - max11608, - max11609, - max11610, - max11611, - max11612, - max11613, - max11614, - max11615, - max11616, - max11617, - max11644, - max11645, - max11646, - max11647 +enum { + max1361, + max1362, + max1363, + max1364, + max1036, + max1037, + max1038, + max1039, + max1136, + max1137, + max1138, + max1139, + max1236, + max1237, + max1238, + max1239, + max11600, + max11601, + max11602, + max11603, + max11604, + max11605, + max11606, + max11607, + max11608, + max11609, + max11610, + max11611, + max11612, + max11613, + max11614, + max11615, + max11616, + max11617, + max11644, + max11645, + max11646, + max11647, }; -static const int max1363_monitor_speeds[] = { 133000, 665000, 33300, 16600, - 8300, 4200, 2000, 1000 }; +static const int max1363_monitor_speeds[] = { + 133000, 665000, 33300, 16600, + 8300, 4200, 2000, 1000, +}; static ssize_t max1363_monitor_show_freq(struct device *dev, struct device_attribute *attr, diff --git a/drivers/iio/adc/mcp3564.c b/drivers/iio/adc/mcp3564.c index fcdf13f49c48..36675563829e 100644 --- a/drivers/iio/adc/mcp3564.c +++ b/drivers/iio/adc/mcp3564.c @@ -349,7 +349,7 @@ struct mcp3564_chip_info { * struct mcp3564_state - working data for a ADC device * @chip_info: chip specific data * @spi: SPI device structure - * @vref_mv: voltage reference value in miliVolts + * @vref_mv: voltage reference value in millivolts * @lock: synchronize access to driver's state members * @dev_addr: hardware device address * @oversampling: the index inside oversampling list of the ADC diff --git a/drivers/iio/adc/men_z188_adc.c b/drivers/iio/adc/men_z188_adc.c index 90919d282e7b..5bd334ec5655 100644 --- a/drivers/iio/adc/men_z188_adc.c +++ b/drivers/iio/adc/men_z188_adc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * MEN 16z188 Analog to Digial Converter + * MEN 16z188 Analog to Digital Converter * * Copyright (C) 2014 MEN Mikroelektronik GmbH (www.men.de) * Author: Johannes Thumshirn diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 47cd350498a0..23991a3612bd 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -792,7 +792,7 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev) size_t read_len; int ret; - temperature_calib = devm_nvmem_cell_get(dev, "temperature_calib"); + temperature_calib = nvmem_cell_get(dev, "temperature_calib"); if (IS_ERR(temperature_calib)) { ret = PTR_ERR(temperature_calib); @@ -806,13 +806,9 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev) return dev_err_probe(dev, ret, "failed to get temperature_calib cell\n"); } - priv->tsc_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "amlogic,hhi-sysctrl"); - if (IS_ERR(priv->tsc_regmap)) - return dev_err_probe(dev, PTR_ERR(priv->tsc_regmap), - "failed to get amlogic,hhi-sysctrl regmap\n"); - read_len = MESON_SAR_ADC_EFUSE_BYTES; buf = nvmem_cell_read(temperature_calib, &read_len); + nvmem_cell_put(temperature_calib); if (IS_ERR(buf)) return dev_err_probe(dev, PTR_ERR(buf), "failed to read temperature_calib cell\n"); if (read_len != MESON_SAR_ADC_EFUSE_BYTES) { @@ -820,6 +816,11 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev) return dev_err_probe(dev, -EINVAL, "invalid read size of temperature_calib cell\n"); } + priv->tsc_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "amlogic,hhi-sysctrl"); + if (IS_ERR(priv->tsc_regmap)) + return dev_err_probe(dev, PTR_ERR(priv->tsc_regmap), + "failed to get amlogic,hhi-sysctrl regmap\n"); + trimming_bits = priv->param->temperature_trimming_bits; trimming_mask = BIT(trimming_bits) - 1; @@ -1313,6 +1314,11 @@ static const struct meson_sar_adc_data meson_sar_adc_g12a_data = { .name = "meson-g12a-saradc", }; +static const struct meson_sar_adc_data meson_sar_adc_s4_data = { + .param = &meson_sar_adc_g12a_param, + .name = "meson-s4-saradc", +}; + static const struct of_device_id meson_sar_adc_of_match[] = { { .compatible = "amlogic,meson8-saradc", @@ -1341,6 +1347,9 @@ static const struct of_device_id meson_sar_adc_of_match[] = { }, { .compatible = "amlogic,meson-g12a-saradc", .data = &meson_sar_adc_g12a_data, + }, { + .compatible = "amlogic,meson-s4-saradc", + .data = &meson_sar_adc_s4_data, }, { } }; diff --git a/drivers/iio/adc/mt6359-auxadc.c b/drivers/iio/adc/mt6359-auxadc.c index f426a289e867..6b9ed9b1fde2 100644 --- a/drivers/iio/adc/mt6359-auxadc.c +++ b/drivers/iio/adc/mt6359-auxadc.c @@ -322,7 +322,7 @@ static const struct mtk_pmic_auxadc_chan mt6359_auxadc_ch_desc[] = { MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, PMIC_AUXADC_IMP1, 15, 128, 7, 2), MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, PMIC_AUXADC_IMP1, 15, 8, 5, 2), MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, PMIC_AUXADC_IMP1, 15, 8, 1, 1), - MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, PMIC_AUXADC_IMP1, 15 ,8, 1, 1), + MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, PMIC_AUXADC_IMP1, 15, 8, 1, 1), MTK_PMIC_ADC_CHAN(VDCXO, PMIC_AUXADC_RQST0, 6, PMIC_AUXADC_IMP1, 15, 8, 3, 2), MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, PMIC_AUXADC_IMP1, 15, 128, 1, 1), MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, PMIC_AUXADC_IMP1, 15, 256, 1, 1), diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c index 458544cb8ee4..970afb27b839 100644 --- a/drivers/iio/adc/nau7802.c +++ b/drivers/iio/adc/nau7802.c @@ -55,7 +55,6 @@ struct nau7802_state { struct mutex data_lock; u32 vref_mv; u32 conversion_count; - u32 min_conversions; u8 sample_rate; u32 scale_avail[8]; struct completion value_ok; @@ -257,7 +256,7 @@ static int nau7802_read_poll(struct iio_dev *indio_dev, /* * Because there is actually only one ADC for both channels, we have to * wait for enough conversions to happen before getting a significant - * value when changing channels and the values are far appart. + * value when changing channels and the values are far apart. */ do { ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_PUCTRL); diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c index c8283873cdee..ddabb9600d46 100644 --- a/drivers/iio/adc/npcm_adc.c +++ b/drivers/iio/adc/npcm_adc.c @@ -38,7 +38,7 @@ struct npcm_adc { * read access from userspace. Reading a raw value requires a sequence * of register writes, then a wait for a event and finally a register * read, during which userspace could issue another read request. - * This lock protects a read access from ocurring before another one + * This lock protects a read access from occurring before another one * has finished. */ struct mutex lock; diff --git a/drivers/iio/adc/nxp-sar-adc.c b/drivers/iio/adc/nxp-sar-adc.c index 9efa883c277d..a6e4888a8464 100644 --- a/drivers/iio/adc/nxp-sar-adc.c +++ b/drivers/iio/adc/nxp-sar-adc.c @@ -247,7 +247,8 @@ static inline void nxp_sar_adc_calibration_start(void __iomem *base) static inline int nxp_sar_adc_calibration_wait(void __iomem *base) { - u32 msr, ret; + u32 msr; + int ret; ret = readl_poll_timeout(NXP_SAR_ADC_MSR(base), msr, !FIELD_GET(NXP_SAR_ADC_MSR_CALBUSY, msr), diff --git a/drivers/iio/adc/pac1921.c b/drivers/iio/adc/pac1921.c index a0227b57f238..bce7185953ec 100644 --- a/drivers/iio/adc/pac1921.c +++ b/drivers/iio/adc/pac1921.c @@ -856,7 +856,7 @@ static ssize_t pac1921_format_scale_avail(const int (*const scales_tbl)[2], /* * Read available scales for a specific channel * - * NOTE: using extended info insted of iio.read_avail() because access to + * NOTE: using extended info instead of iio.read_avail() because access to * current scales must be locked as they depend on shunt resistor which may * change runtime. Caller of iio.read_avail() would access the table unlocked * instead. diff --git a/drivers/iio/adc/pac1934.c b/drivers/iio/adc/pac1934.c index 712b5e9caba6..23055405a6e0 100644 --- a/drivers/iio/adc/pac1934.c +++ b/drivers/iio/adc/pac1934.c @@ -1351,7 +1351,7 @@ static int pac1934_prep_iio_channels(struct pac1934_chip_info *info, struct iio_ dyn_ch_struct = devm_kzalloc(dev, channel_size, GFP_KERNEL); if (!dyn_ch_struct) - return -EINVAL; + return -ENOMEM; tmp_data = dyn_ch_struct; diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c index 3f433064618e..f777986a6aba 100644 --- a/drivers/iio/adc/palmas_gpadc.c +++ b/drivers/iio/adc/palmas_gpadc.c @@ -105,7 +105,7 @@ struct palmas_gpadc_thresholds { * of register writes, then a wait for a completion callback, * and finally a register read, during which userspace could issue * another read request. This lock protects a read access from - * ocurring before another one has finished. + * occurring before another one has finished. * * This is the palmas_gpadc structure to store run-time information * and pointers for this driver instance. @@ -521,16 +521,16 @@ static int palmas_gpadc_get_low_threshold_raw(struct palmas_gpadc *adc, val = (val * 1000) / adc->adc_info[adc_chan].gain; - if (adc->adc_info[adc_chan].is_uncalibrated) { + if (adc->adc_info[adc_chan].is_uncalibrated) { /* 2% worse */ min_gain_error -= 20; min_offset_error = -36; - } else { + } else { val = (val * adc->adc_info[adc_chan].gain_error - adc->adc_info[adc_chan].offset) / 1000; min_offset_error = -2; - } + } return palmas_gpadc_threshold_with_tolerance(val, min_INL, diff --git a/drivers/iio/adc/qcom-spmi-adc5-gen3.c b/drivers/iio/adc/qcom-spmi-adc5-gen3.c new file mode 100644 index 000000000000..f8168a14b907 --- /dev/null +++ b/drivers/iio/adc/qcom-spmi-adc5-gen3.c @@ -0,0 +1,860 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ADC5_GEN3_VADC_SDAM 0x0 + +struct adc5_chip; + +/** + * struct adc5_channel_prop - ADC channel structure + * @common_props: structure with ADC channel properties (common to TM usage). + * @adc_tm: indicates TM type if the channel is used for TM measurements. + * @chip: pointer to top-level ADC device structure. + */ +struct adc5_channel_prop { + struct adc5_channel_common_prop common_props; + int adc_tm; + struct adc5_chip *chip; +}; + +/** + * struct adc5_chip - ADC private structure. + * @dev: SPMI ADC5 Gen3 device. + * @dev_data: Top-level ADC device data. + * @nchannels: number of ADC channels. + * @chan_props: array of ADC channel properties. + * @iio_chans: array of IIO channels specification. + * @complete: ADC result notification after interrupt is received. + * @lock: ADC lock for access to the peripheral, to prevent concurrent + * requests from multiple clients. + * @data: software configuration data. + * @n_tm_channels: number of ADC channels used for TM measurements. + * @handler: TM callback to be called for threshold violation interrupt + * on first SDAM. + * @tm_aux: pointer to auxiliary TM device. + */ +struct adc5_chip { + struct device *dev; + struct adc5_device_data dev_data; + unsigned int nchannels; + struct adc5_channel_prop *chan_props; + struct iio_chan_spec *iio_chans; + struct completion complete; + struct mutex lock; + const struct adc5_data *data; + unsigned int n_tm_channels; + void (*handler)(struct auxiliary_device *tm_aux); + struct auxiliary_device *tm_aux; +}; + +int adc5_gen3_read(struct adc5_device_data *adc, unsigned int sdam_index, + u16 offset, u8 *data, int len) +{ + return regmap_bulk_read(adc->regmap, + adc->base[sdam_index].base_addr + offset, + data, len); +} +EXPORT_SYMBOL_NS_GPL(adc5_gen3_read, "QCOM_SPMI_ADC5_GEN3"); + +int adc5_gen3_write(struct adc5_device_data *adc, unsigned int sdam_index, + u16 offset, u8 *data, int len) +{ + return regmap_bulk_write(adc->regmap, + adc->base[sdam_index].base_addr + offset, + data, len); +} +EXPORT_SYMBOL_NS_GPL(adc5_gen3_write, "QCOM_SPMI_ADC5_GEN3"); + +static int adc5_gen3_read_voltage_data(struct adc5_chip *adc, u16 *data) +{ + u8 rslt[2]; + int ret; + + ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM, + ADC5_GEN3_CH_DATA0(0), rslt, sizeof(rslt)); + if (ret) + return ret; + + *data = get_unaligned_le16(rslt); + + if (*data == ADC5_USR_DATA_CHECK) { + dev_err(adc->dev, "Invalid data:%#x\n", *data); + return -EINVAL; + } + + dev_dbg(adc->dev, "voltage raw code:%#x\n", *data); + + return 0; +} + +void adc5_gen3_update_dig_param(struct adc5_channel_common_prop *prop, u8 *data) +{ + /* Update calibration select and decimation ratio select */ + *data &= ~(ADC5_GEN3_DIG_PARAM_CAL_SEL_MASK | ADC5_GEN3_DIG_PARAM_DEC_RATIO_SEL_MASK); + *data |= FIELD_PREP(ADC5_GEN3_DIG_PARAM_CAL_SEL_MASK, prop->cal_method); + *data |= FIELD_PREP(ADC5_GEN3_DIG_PARAM_DEC_RATIO_SEL_MASK, prop->decimation); +} +EXPORT_SYMBOL_NS_GPL(adc5_gen3_update_dig_param, "QCOM_SPMI_ADC5_GEN3"); + +#define ADC5_GEN3_READ_CONFIG_REGS 7 + +static int adc5_gen3_configure(struct adc5_chip *adc, + struct adc5_channel_common_prop *prop) +{ + u8 buf[ADC5_GEN3_READ_CONFIG_REGS]; + u8 conv_req = 0; + int ret; + + ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM, ADC5_GEN3_SID, + buf, sizeof(buf)); + if (ret) + return ret; + + /* Write SID */ + buf[0] = FIELD_PREP(ADC5_GEN3_SID_MASK, prop->sid); + + /* + * Use channel 0 by default for immediate conversion and to indicate + * there is an actual conversion request + */ + buf[1] = ADC5_GEN3_CHAN_CONV_REQ | 0; + + buf[2] = ADC5_GEN3_TIME_IMMEDIATE; + + /* Digital param selection */ + adc5_gen3_update_dig_param(prop, &buf[3]); + + /* Update fast average sample value */ + buf[4] = FIELD_PREP(ADC5_GEN3_FAST_AVG_CTL_SAMPLES_MASK, + prop->avg_samples) | ADC5_GEN3_FAST_AVG_CTL_EN; + + /* Select ADC channel */ + buf[5] = prop->channel; + + /* Select HW settle delay for channel */ + buf[6] = FIELD_PREP(ADC5_GEN3_HW_SETTLE_DELAY_MASK, + prop->hw_settle_time_us); + + reinit_completion(&adc->complete); + + ret = adc5_gen3_write(&adc->dev_data, ADC5_GEN3_VADC_SDAM, ADC5_GEN3_SID, + buf, sizeof(buf)); + if (ret) + return ret; + + conv_req = ADC5_GEN3_CONV_REQ_REQ; + return adc5_gen3_write(&adc->dev_data, ADC5_GEN3_VADC_SDAM, + ADC5_GEN3_CONV_REQ, &conv_req, sizeof(conv_req)); +} + +/* + * Worst case delay from PBS in readying handshake bit can be up to 15ms, when + * PBS is busy running other simultaneous transactions, while in the best case, + * it is already ready at this point. Assigning polling delay and retry count + * accordingly. + */ + +#define ADC5_GEN3_HS_DELAY_US 100 +#define ADC5_GEN3_HS_RETRY_COUNT 150 + +int adc5_gen3_poll_wait_hs(struct adc5_device_data *adc, + unsigned int sdam_index) +{ + u8 conv_req = ADC5_GEN3_CONV_REQ_REQ; + int ret, count; + u8 status = 0; + + for (count = 0; count < ADC5_GEN3_HS_RETRY_COUNT; count++) { + ret = adc5_gen3_read(adc, sdam_index, ADC5_GEN3_HS, &status, sizeof(status)); + if (ret) + return ret; + + if (status == ADC5_GEN3_HS_READY) { + ret = adc5_gen3_read(adc, sdam_index, ADC5_GEN3_CONV_REQ, + &conv_req, sizeof(conv_req)); + if (ret) + return ret; + + if (!conv_req) + return 0; + } + + fsleep(ADC5_GEN3_HS_DELAY_US); + } + + pr_err("Setting HS ready bit timed out, sdam_index:%d, status:%#x\n", + sdam_index, status); + return -ETIMEDOUT; +} +EXPORT_SYMBOL_NS_GPL(adc5_gen3_poll_wait_hs, "QCOM_SPMI_ADC5_GEN3"); + +int adc5_gen3_status_clear(struct adc5_device_data *adc, + int sdam_index, u16 offset, u8 *val, int len) +{ + u8 value; + int ret; + + ret = adc5_gen3_write(adc, sdam_index, offset, val, len); + if (ret) + return ret; + + /* To indicate conversion request is only to clear a status */ + value = 0; + ret = adc5_gen3_write(adc, sdam_index, ADC5_GEN3_PERPH_CH, &value, + sizeof(value)); + if (ret) + return ret; + + value = ADC5_GEN3_CONV_REQ_REQ; + return adc5_gen3_write(adc, sdam_index, ADC5_GEN3_CONV_REQ, &value, + sizeof(value)); +} +EXPORT_SYMBOL_NS_GPL(adc5_gen3_status_clear, "QCOM_SPMI_ADC5_GEN3"); + +/* + * Worst case delay from PBS for conversion time can be up to 500ms, when PBS + * has timed out twice, once for the initial attempt and once for a retry of + * the same transaction. + */ + +#define ADC5_GEN3_CONV_TIMEOUT_MS 501 + +static int adc5_gen3_do_conversion(struct adc5_chip *adc, + struct adc5_channel_common_prop *prop, + u16 *data_volt) +{ + unsigned long rc; + int ret; + u8 val; + + guard(mutex)(&adc->lock); + ret = adc5_gen3_poll_wait_hs(&adc->dev_data, ADC5_GEN3_VADC_SDAM); + if (ret) + return ret; + + ret = adc5_gen3_configure(adc, prop); + if (ret) { + dev_err(adc->dev, "ADC configure failed with %d\n", ret); + return ret; + } + + /* No support for polling mode at present */ + rc = wait_for_completion_timeout(&adc->complete, + msecs_to_jiffies(ADC5_GEN3_CONV_TIMEOUT_MS)); + if (!rc) { + dev_err(adc->dev, "Reading ADC channel %s timed out\n", + prop->label); + return -ETIMEDOUT; + } + + ret = adc5_gen3_read_voltage_data(adc, data_volt); + if (ret) + return ret; + + val = BIT(0); + return adc5_gen3_status_clear(&adc->dev_data, ADC5_GEN3_VADC_SDAM, + ADC5_GEN3_EOC_CLR, &val, 1); +} + +static irqreturn_t adc5_gen3_isr(int irq, void *dev_id) +{ + struct adc5_chip *adc = dev_id; + struct device *dev = adc->dev; + struct auxiliary_device *adev; + u8 status, eoc_status, val; + u8 tm_status[2]; + int ret; + + ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM, + ADC5_GEN3_STATUS1, &status, sizeof(status)); + if (ret) { + dev_err(dev, "adc read status1 failed with %d\n", ret); + return IRQ_HANDLED; + } + + ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM, + ADC5_GEN3_EOC_STS, &eoc_status, sizeof(eoc_status)); + if (ret) { + dev_err(dev, "adc read eoc status failed with %d\n", ret); + return IRQ_HANDLED; + } + + if (status & ADC5_GEN3_STATUS1_CONV_FAULT) { + dev_err_ratelimited(dev, + "Unexpected conversion fault, status:%#x, eoc_status:%#x\n", + status, eoc_status); + val = ADC5_GEN3_CONV_ERR_CLR_REQ; + adc5_gen3_status_clear(&adc->dev_data, ADC5_GEN3_VADC_SDAM, + ADC5_GEN3_CONV_ERR_CLR, &val, 1); + return IRQ_HANDLED; + } + + /* CHAN0 is the preconfigured channel for immediate conversion */ + if (eoc_status & ADC5_GEN3_EOC_CHAN_0) + complete(&adc->complete); + + ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM, + ADC5_GEN3_TM_HIGH_STS, tm_status, sizeof(tm_status)); + if (ret) { + dev_err(dev, "adc read TM status failed with %d\n", ret); + return IRQ_HANDLED; + } + + dev_dbg(dev, "Interrupt status:%#x, EOC status:%#x, high:%#x, low:%#x\n", + status, eoc_status, tm_status[0], tm_status[1]); + + if (tm_status[0] || tm_status[1]) { + adev = adc->tm_aux; + if (!adev || !adev->dev.driver) { + dev_err(dev, "adc_tm auxiliary device not initialized\n"); + return IRQ_HANDLED; + } + + adc->handler(adev); + } + + return IRQ_HANDLED; +} + +static int adc5_gen3_fwnode_xlate(struct iio_dev *indio_dev, + const struct fwnode_reference_args *iiospec) +{ + struct adc5_chip *adc = iio_priv(indio_dev); + int i, v_channel; + + for (i = 0; i < adc->nchannels; i++) { + v_channel = ADC5_GEN3_V_CHAN(adc->chan_props[i].common_props); + if (v_channel == iiospec->args[0]) + return i; + } + + return -ENOENT; +} + +static int adc5_gen3_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct adc5_chip *adc = iio_priv(indio_dev); + struct adc5_channel_common_prop *prop; + u16 adc_code_volt; + int ret; + + prop = &adc->chan_props[chan->address].common_props; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + ret = adc5_gen3_do_conversion(adc, prop, &adc_code_volt); + if (ret) + return ret; + + ret = qcom_adc5_hw_scale(prop->scale_fn_type, prop->prescale, + adc->data, adc_code_volt, val); + if (ret) + return ret; + + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int adc5_gen3_read_label(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, char *label) +{ + struct adc5_chip *adc = iio_priv(indio_dev); + struct adc5_channel_prop *prop; + + prop = &adc->chan_props[chan->address]; + return sprintf(label, "%s\n", prop->common_props.label); +} + +static const struct iio_info adc5_gen3_info = { + .read_raw = adc5_gen3_read_raw, + .read_label = adc5_gen3_read_label, + .fwnode_xlate = adc5_gen3_fwnode_xlate, +}; + +struct adc5_channels { + unsigned int prescale_index; + enum iio_chan_type type; + long info_mask; + enum vadc_scale_fn_type scale_fn_type; +}; + +/* In these definitions, _pre refers to an index into adc5_prescale_ratios. */ +#define ADC5_CHAN(_type, _mask, _pre, _scale) \ + { \ + .prescale_index = _pre, \ + .type = _type, \ + .info_mask = _mask, \ + .scale_fn_type = _scale, \ + }, \ + +#define ADC5_CHAN_TEMP(_pre, _scale) \ + ADC5_CHAN(IIO_TEMP, BIT(IIO_CHAN_INFO_PROCESSED), _pre, _scale) \ + +#define ADC5_CHAN_VOLT(_pre, _scale) \ + ADC5_CHAN(IIO_VOLTAGE, BIT(IIO_CHAN_INFO_PROCESSED), _pre, _scale) \ + +#define ADC5_CHAN_CUR(_pre, _scale) \ + ADC5_CHAN(IIO_CURRENT, BIT(IIO_CHAN_INFO_PROCESSED), _pre, _scale) \ + +static const struct adc5_channels adc5_gen3_chans_pmic[ADC5_MAX_CHANNEL] = { + [ADC5_GEN3_REF_GND] = ADC5_CHAN_VOLT(0, SCALE_HW_CALIB_DEFAULT) + [ADC5_GEN3_1P25VREF] = ADC5_CHAN_VOLT(0, SCALE_HW_CALIB_DEFAULT) + [ADC5_GEN3_VPH_PWR] = ADC5_CHAN_VOLT(1, SCALE_HW_CALIB_DEFAULT) + [ADC5_GEN3_VBAT_SNS_QBG] = ADC5_CHAN_VOLT(1, SCALE_HW_CALIB_DEFAULT) + [ADC5_GEN3_USB_SNS_V_16] = ADC5_CHAN_TEMP(8, SCALE_HW_CALIB_DEFAULT) + [ADC5_GEN3_VIN_DIV16_MUX] = ADC5_CHAN_TEMP(8, SCALE_HW_CALIB_DEFAULT) + [ADC5_GEN3_DIE_TEMP] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_PMIC_THERM_PM7) + [ADC5_GEN3_AMUX1_THM_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC5_GEN3_AMUX2_THM_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC5_GEN3_AMUX3_THM_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC5_GEN3_AMUX4_THM_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC5_GEN3_AMUX5_THM_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC5_GEN3_AMUX6_THM_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC5_GEN3_AMUX1_GPIO_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC5_GEN3_AMUX2_GPIO_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC5_GEN3_AMUX3_GPIO_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) + [ADC5_GEN3_AMUX4_GPIO_100K_PU] = ADC5_CHAN_TEMP(0, + SCALE_HW_CALIB_THERM_100K_PU_PM7) +}; + +static int adc5_gen3_get_fw_channel_data(struct adc5_chip *adc, + struct adc5_channel_prop *prop, + struct fwnode_handle *fwnode) +{ + const char *name = fwnode_get_name(fwnode); + const struct adc5_data *data = adc->data; + struct device *dev = adc->dev; + const char *channel_name; + u32 chan, value, sid; + u32 varr[2]; + int ret; + + ret = fwnode_property_read_u32(fwnode, "reg", &chan); + if (ret < 0) + return dev_err_probe(dev, ret, "invalid channel number %s\n", + name); + + /* + * Value read from "reg" is virtual channel number + * virtual channel number = sid << 8 | channel number + */ + sid = FIELD_GET(ADC5_GEN3_VIRTUAL_SID_MASK, chan); + chan = FIELD_GET(ADC5_GEN3_CHANNEL_MASK, chan); + + if (chan > ADC5_MAX_CHANNEL) + return dev_err_probe(dev, -EINVAL, + "%s invalid channel number %d\n", + name, chan); + + prop->common_props.channel = chan; + prop->common_props.sid = sid; + + if (!adc->data->adc_chans[chan].info_mask) + return dev_err_probe(dev, -EINVAL, "Channel %#x not supported\n", chan); + + channel_name = name; + fwnode_property_read_string(fwnode, "label", &channel_name); + prop->common_props.label = channel_name; + + value = data->decimation[ADC5_DECIMATION_DEFAULT]; + fwnode_property_read_u32(fwnode, "qcom,decimation", &value); + ret = qcom_adc5_decimation_from_dt(value, data->decimation); + if (ret < 0) + return dev_err_probe(dev, ret, "%#x invalid decimation %d\n", + chan, value); + prop->common_props.decimation = ret; + + prop->common_props.prescale = adc->data->adc_chans[chan].prescale_index; + ret = fwnode_property_read_u32_array(fwnode, "qcom,pre-scaling", varr, 2); + if (!ret) { + ret = qcom_adc5_prescaling_from_dt(varr[0], varr[1]); + if (ret < 0) + return dev_err_probe(dev, ret, + "%#x invalid pre-scaling <%d %d>\n", + chan, varr[0], varr[1]); + prop->common_props.prescale = ret; + } + + value = data->hw_settle_1[VADC_DEF_HW_SETTLE_TIME]; + fwnode_property_read_u32(fwnode, "qcom,hw-settle-time", &value); + ret = qcom_adc5_hw_settle_time_from_dt(value, data->hw_settle_1); + if (ret < 0) + return dev_err_probe(dev, ret, + "%#x invalid hw-settle-time %d us\n", + chan, value); + prop->common_props.hw_settle_time_us = ret; + + value = BIT(VADC_DEF_AVG_SAMPLES); + fwnode_property_read_u32(fwnode, "qcom,avg-samples", &value); + ret = qcom_adc5_avg_samples_from_dt(value); + if (ret < 0) + return dev_err_probe(dev, ret, "%#x invalid avg-samples %d\n", + chan, value); + prop->common_props.avg_samples = ret; + + if (fwnode_property_read_bool(fwnode, "qcom,ratiometric")) + prop->common_props.cal_method = ADC5_RATIOMETRIC_CAL; + else + prop->common_props.cal_method = ADC5_ABSOLUTE_CAL; + + prop->adc_tm = fwnode_property_read_bool(fwnode, "qcom,adc-tm"); + if (prop->adc_tm) { + adc->n_tm_channels++; + if (adc->n_tm_channels > (adc->dev_data.num_sdams * 8 - 1)) + return dev_err_probe(dev, -EINVAL, + "Number of TM nodes %u greater than channels supported:%u\n", + adc->n_tm_channels, + adc->dev_data.num_sdams * 8 - 1); + } + + return 0; +} + +static const struct adc5_data adc5_gen3_data_pmic = { + .full_scale_code_volt = 0x70e4, + .adc_chans = adc5_gen3_chans_pmic, + .info = &adc5_gen3_info, + .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX]) + { 85, 340, 1360 }, + .hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX]) + { 15, 100, 200, 300, + 400, 500, 600, 700, + 1000, 2000, 4000, 8000, + 16000, 32000, 64000, 128000 }, +}; + +static const struct of_device_id adc5_match_table[] = { + { + .compatible = "qcom,spmi-adc5-gen3", + .data = &adc5_gen3_data_pmic, + }, + { } +}; +MODULE_DEVICE_TABLE(of, adc5_match_table); + +static int adc5_get_fw_data(struct adc5_chip *adc) +{ + const struct adc5_channels *adc_chan; + struct adc5_channel_prop *chan_props; + struct iio_chan_spec *iio_chan; + struct device *dev = adc->dev; + unsigned int index = 0; + int ret; + + adc->nchannels = device_get_child_node_count(dev); + if (!adc->nchannels) + return dev_err_probe(dev, -EINVAL, "No ADC channels found\n"); + + adc->iio_chans = devm_kcalloc(dev, adc->nchannels, + sizeof(*adc->iio_chans), GFP_KERNEL); + if (!adc->iio_chans) + return -ENOMEM; + + adc->chan_props = devm_kcalloc(dev, adc->nchannels, + sizeof(*adc->chan_props), GFP_KERNEL); + if (!adc->chan_props) + return -ENOMEM; + + chan_props = adc->chan_props; + adc->n_tm_channels = 0; + iio_chan = adc->iio_chans; + adc->data = device_get_match_data(dev); + + device_for_each_child_node_scoped(dev, child) { + ret = adc5_gen3_get_fw_channel_data(adc, chan_props, child); + if (ret) + return ret; + + chan_props->chip = adc; + adc_chan = &adc->data->adc_chans[chan_props->common_props.channel]; + chan_props->common_props.scale_fn_type = adc_chan->scale_fn_type; + + iio_chan->channel = ADC5_GEN3_V_CHAN(chan_props->common_props); + iio_chan->info_mask_separate = adc_chan->info_mask; + iio_chan->type = adc_chan->type; + iio_chan->address = index; + iio_chan->indexed = 1; + iio_chan++; + chan_props++; + index++; + } + + return 0; +} + +static void adc5_gen3_uninit_aux(void *data) +{ + auxiliary_device_uninit(data); +} + +static void adc5_gen3_delete_aux(void *data) +{ + auxiliary_device_delete(data); +} + +static void adc5_gen3_aux_device_release(struct device *dev) {} + +static int adc5_gen3_add_aux_tm_device(struct adc5_chip *adc) +{ + struct tm5_aux_dev_wrapper *aux_device; + int i, ret, i_tm = 0; + + aux_device = devm_kzalloc(adc->dev, sizeof(*aux_device), GFP_KERNEL); + if (!aux_device) + return -ENOMEM; + + aux_device->aux_dev.name = "adc5_tm_gen3"; + aux_device->aux_dev.dev.parent = adc->dev; + aux_device->aux_dev.dev.release = adc5_gen3_aux_device_release; + + aux_device->tm_props = devm_kcalloc(adc->dev, adc->n_tm_channels, + sizeof(*aux_device->tm_props), + GFP_KERNEL); + if (!aux_device->tm_props) + return -ENOMEM; + + aux_device->dev_data = &adc->dev_data; + + for (i = 0; i < adc->nchannels; i++) { + if (!adc->chan_props[i].adc_tm) + continue; + aux_device->tm_props[i_tm] = adc->chan_props[i].common_props; + i_tm++; + } + + device_set_of_node_from_dev(&aux_device->aux_dev.dev, adc->dev); + + aux_device->n_tm_channels = adc->n_tm_channels; + + ret = auxiliary_device_init(&aux_device->aux_dev); + if (ret) + return ret; + + ret = devm_add_action_or_reset(adc->dev, adc5_gen3_uninit_aux, + &aux_device->aux_dev); + if (ret) + return ret; + + ret = auxiliary_device_add(&aux_device->aux_dev); + if (ret) + return ret; + ret = devm_add_action_or_reset(adc->dev, adc5_gen3_delete_aux, + &aux_device->aux_dev); + if (ret) + return ret; + + adc->tm_aux = &aux_device->aux_dev; + + return 0; +} + +void adc5_gen3_mutex_lock(struct device *dev) + __acquires(&adc->lock) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev->parent); + struct adc5_chip *adc = iio_priv(indio_dev); + + mutex_lock(&adc->lock); +} +EXPORT_SYMBOL_NS_GPL(adc5_gen3_mutex_lock, "QCOM_SPMI_ADC5_GEN3"); + +void adc5_gen3_mutex_unlock(struct device *dev) + __releases(&adc->lock) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev->parent); + struct adc5_chip *adc = iio_priv(indio_dev); + + mutex_unlock(&adc->lock); +} +EXPORT_SYMBOL_NS_GPL(adc5_gen3_mutex_unlock, "QCOM_SPMI_ADC5_GEN3"); + +int adc5_gen3_get_scaled_reading(struct device *dev, + struct adc5_channel_common_prop *common_props, + int *val) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev->parent); + struct adc5_chip *adc = iio_priv(indio_dev); + u16 adc_code_volt; + int ret; + + ret = adc5_gen3_do_conversion(adc, common_props, &adc_code_volt); + if (ret) + return ret; + + return qcom_adc5_hw_scale(common_props->scale_fn_type, + common_props->prescale, + adc->data, adc_code_volt, val); +} +EXPORT_SYMBOL_NS_GPL(adc5_gen3_get_scaled_reading, "QCOM_SPMI_ADC5_GEN3"); + +int adc5_gen3_therm_code_to_temp(struct device *dev, + struct adc5_channel_common_prop *common_props, + u16 code, int *val) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev->parent); + struct adc5_chip *adc = iio_priv(indio_dev); + + return qcom_adc5_hw_scale(common_props->scale_fn_type, + common_props->prescale, + adc->data, code, val); +} +EXPORT_SYMBOL_NS_GPL(adc5_gen3_therm_code_to_temp, "QCOM_SPMI_ADC5_GEN3"); + +void adc5_gen3_register_tm_event_notifier(struct device *dev, + void (*handler)(struct auxiliary_device *)) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev->parent); + struct adc5_chip *adc = iio_priv(indio_dev); + + adc->handler = handler; +} +EXPORT_SYMBOL_NS_GPL(adc5_gen3_register_tm_event_notifier, "QCOM_SPMI_ADC5_GEN3"); + +static int adc5_gen3_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct iio_dev *indio_dev; + struct adc5_chip *adc; + struct regmap *regmap; + int ret, i; + u32 *reg; + + regmap = dev_get_regmap(dev->parent, NULL); + if (!regmap) + return -ENODEV; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*adc)); + if (!indio_dev) + return -ENOMEM; + + adc = iio_priv(indio_dev); + adc->dev_data.regmap = regmap; + adc->dev = dev; + + ret = device_property_count_u32(dev, "reg"); + if (ret < 0) + return ret; + + adc->dev_data.num_sdams = ret; + + reg = devm_kcalloc(dev, adc->dev_data.num_sdams, sizeof(u32), + GFP_KERNEL); + if (!reg) + return -ENOMEM; + + ret = device_property_read_u32_array(dev, "reg", reg, + adc->dev_data.num_sdams); + if (ret) + return dev_err_probe(dev, ret, + "Failed to read reg property\n"); + + adc->dev_data.base = devm_kcalloc(dev, adc->dev_data.num_sdams, + sizeof(*adc->dev_data.base), + GFP_KERNEL); + if (!adc->dev_data.base) + return -ENOMEM; + + platform_set_drvdata(pdev, indio_dev); + init_completion(&adc->complete); + ret = devm_mutex_init(dev, &adc->lock); + if (ret) + return ret; + + for (i = 0; i < adc->dev_data.num_sdams; i++) { + adc->dev_data.base[i].base_addr = reg[i]; + + ret = platform_get_irq(pdev, i); + if (ret < 0) + return dev_err_probe(dev, ret, + "Getting IRQ %d failed\n", i); + + adc->dev_data.base[i].irq = ret; + + adc->dev_data.base[i].irq_name = devm_kasprintf(dev, GFP_KERNEL, + "sdam%d", i); + if (!adc->dev_data.base[i].irq_name) + return -ENOMEM; + } + + ret = devm_request_irq(dev, adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq, + adc5_gen3_isr, 0, + adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq_name, + adc); + if (ret) + return dev_err_probe(dev, ret, + "Failed to request SDAM%d irq\n", + ADC5_GEN3_VADC_SDAM); + + ret = adc5_get_fw_data(adc); + if (ret) + return ret; + + if (adc->n_tm_channels > 0) { + ret = adc5_gen3_add_aux_tm_device(adc); + if (ret) + dev_err_probe(dev, ret, + "Failed to add auxiliary TM device\n"); + } + + indio_dev->name = "spmi-adc5-gen3"; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &adc5_gen3_info; + indio_dev->channels = adc->iio_chans; + indio_dev->num_channels = adc->nchannels; + + return devm_iio_device_register(dev, indio_dev); +} + +static struct platform_driver adc5_gen3_driver = { + .driver = { + .name = "qcom-spmi-adc5-gen3", + .of_match_table = adc5_match_table, + }, + .probe = adc5_gen3_probe, +}; +module_platform_driver(adc5_gen3_driver); + +MODULE_DESCRIPTION("Qualcomm Technologies Inc. PMIC5 Gen3 ADC driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("QCOM_SPMI_ADC5_GEN3"); diff --git a/drivers/iio/adc/rohm-bd79124.c b/drivers/iio/adc/rohm-bd79124.c index fc0452749b79..40d00bd0cc9d 100644 --- a/drivers/iio/adc/rohm-bd79124.c +++ b/drivers/iio/adc/rohm-bd79124.c @@ -75,7 +75,7 @@ /* * The high limit, low limit and last measurement result are each stored in - * 2 consequtive registers. 4 bits are in the high bits of the first register + * 2 consecutive registers. 4 bits are in the high bits of the first register * and 8 bits in the next register. * * These macros return the address of the first reg for the given channel. @@ -962,7 +962,7 @@ static int bd79124_hw_init(struct bd79124_data *data) if (ret) return ret; - /* Enable writing the measured values to the regsters */ + /* Enable writing the measured values to the registers */ ret = regmap_set_bits(data->map, BD79124_REG_GEN_CFG, BD79124_MSK_STATS_EN); if (ret) diff --git a/drivers/iio/adc/sd_adc_modulator.c b/drivers/iio/adc/sd_adc_modulator.c index 9f7a75168aac..218117c45ec8 100644 --- a/drivers/iio/adc/sd_adc_modulator.c +++ b/drivers/iio/adc/sd_adc_modulator.c @@ -77,6 +77,7 @@ static const struct iio_backend_ops sd_backend_ops = { static const struct iio_backend_info sd_backend_info = { .name = "sd-modulator", .ops = &sd_backend_ops, + .caps = IIO_BACKEND_CAP_ENABLE, }; static int iio_sd_mod_register(struct platform_device *pdev) diff --git a/drivers/iio/adc/spear_adc.c b/drivers/iio/adc/spear_adc.c index 50b0a607baeb..91995489bb1c 100644 --- a/drivers/iio/adc/spear_adc.c +++ b/drivers/iio/adc/spear_adc.c @@ -82,7 +82,7 @@ struct spear_adc_state { * of register writes, then a wait for a completion callback, * and finally a register read, during which userspace could issue * another read request. This lock protects a read access from - * ocurring before another one has finished. + * occurring before another one has finished. */ struct mutex lock; u32 current_clk; diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index e39a4c0db25e..a42d82d61cb8 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -227,7 +227,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, if (priv->aclk) { /* * Asynchronous clock modes (e.g. ckmode == 0) - * From spec: PLL output musn't exceed max rate + * From spec: PLL output mustn't exceed max rate */ rate = clk_get_rate(priv->aclk); if (!rate) { diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 2d7f88459c7c..46106200bb86 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -1662,7 +1662,7 @@ static irqreturn_t stm32_adc_threaded_isr(int irq, void *data) /* * Clear ovr bit to avoid subsequent calls to IRQ handler. * This requires to stop ADC first. OVR bit state in ISR, - * is propaged to CSR register by hardware. + * is propagated to CSR register by hardware. */ adc->cfg->stop_conv(indio_dev); stm32_adc_irq_clear(indio_dev, regs->isr_ovr.mask); diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c index e4dfe76e6362..861c14da75ad 100644 --- a/drivers/iio/adc/sun20i-gpadc-iio.c +++ b/drivers/iio/adc/sun20i-gpadc-iio.c @@ -55,7 +55,7 @@ struct sun20i_gpadc_iio { * of register writes, then a wait for a completion callback, * and finally a register read, during which userspace could issue * another read request. This lock protects a read access from - * ocurring before another one has finished. + * occurring before another one has finished. */ struct mutex lock; }; diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index f2a93c63ca14..c7ffe47449e2 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -231,7 +231,6 @@ static const struct iio_event_spec ads1015_events[] = { } struct ads1015_channel_data { - bool enabled; unsigned int pga; unsigned int data_rate; }; diff --git a/drivers/iio/adc/ti-ads1119.c b/drivers/iio/adc/ti-ads1119.c index c9cedc59cdcd..1157e606bc64 100644 --- a/drivers/iio/adc/ti-ads1119.c +++ b/drivers/iio/adc/ti-ads1119.c @@ -740,8 +740,7 @@ static int ads1119_probe(struct i2c_client *client) NULL, IRQF_ONESHOT, "ads1119", indio_dev); if (ret) - return dev_err_probe(dev, ret, - "Failed to allocate irq\n"); + return ret; st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index bbe1ce577789..4e9359b259fc 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -47,8 +47,6 @@ #define TI_ADS7950_MAX_CHAN 16 #define TI_ADS7950_NUM_GPIOS 4 -#define TI_ADS7950_TIMESTAMP_SIZE (sizeof(int64_t) / sizeof(__be16)) - /* val = value, dec = left shift, bits = number of bits of the mask */ #define TI_ADS7950_EXTRACT(val, dec, bits) \ (((val) >> (dec)) & ((1 << (bits)) - 1)) @@ -105,8 +103,7 @@ struct ti_ads7950_state { * DMA (thus cache coherency maintenance) may require the * transfer buffers to live in their own cache lines. */ - u16 rx_buf[TI_ADS7950_MAX_CHAN + 2 + TI_ADS7950_TIMESTAMP_SIZE] - __aligned(IIO_DMA_MINALIGN); + u16 rx_buf[TI_ADS7950_MAX_CHAN + 2] __aligned(IIO_DMA_MINALIGN); u16 tx_buf[TI_ADS7950_MAX_CHAN + 2]; u16 single_tx; u16 single_rx; @@ -118,21 +115,6 @@ struct ti_ads7950_chip_info { unsigned int num_channels; }; -enum ti_ads7950_id { - TI_ADS7950, - TI_ADS7951, - TI_ADS7952, - TI_ADS7953, - TI_ADS7954, - TI_ADS7955, - TI_ADS7956, - TI_ADS7957, - TI_ADS7958, - TI_ADS7959, - TI_ADS7960, - TI_ADS7961, -}; - #define TI_ADS7950_V_CHAN(index, bits) \ { \ .type = IIO_VOLTAGE, \ @@ -225,55 +207,64 @@ static DECLARE_TI_ADS7950_8_CHANNELS(ti_ads7959, 8); static DECLARE_TI_ADS7950_12_CHANNELS(ti_ads7960, 8); static DECLARE_TI_ADS7950_16_CHANNELS(ti_ads7961, 8); -static const struct ti_ads7950_chip_info ti_ads7950_chip_info[] = { - [TI_ADS7950] = { - .channels = ti_ads7950_channels, - .num_channels = ARRAY_SIZE(ti_ads7950_channels), - }, - [TI_ADS7951] = { - .channels = ti_ads7951_channels, - .num_channels = ARRAY_SIZE(ti_ads7951_channels), - }, - [TI_ADS7952] = { - .channels = ti_ads7952_channels, - .num_channels = ARRAY_SIZE(ti_ads7952_channels), - }, - [TI_ADS7953] = { - .channels = ti_ads7953_channels, - .num_channels = ARRAY_SIZE(ti_ads7953_channels), - }, - [TI_ADS7954] = { - .channels = ti_ads7954_channels, - .num_channels = ARRAY_SIZE(ti_ads7954_channels), - }, - [TI_ADS7955] = { - .channels = ti_ads7955_channels, - .num_channels = ARRAY_SIZE(ti_ads7955_channels), - }, - [TI_ADS7956] = { - .channels = ti_ads7956_channels, - .num_channels = ARRAY_SIZE(ti_ads7956_channels), - }, - [TI_ADS7957] = { - .channels = ti_ads7957_channels, - .num_channels = ARRAY_SIZE(ti_ads7957_channels), - }, - [TI_ADS7958] = { - .channels = ti_ads7958_channels, - .num_channels = ARRAY_SIZE(ti_ads7958_channels), - }, - [TI_ADS7959] = { - .channels = ti_ads7959_channels, - .num_channels = ARRAY_SIZE(ti_ads7959_channels), - }, - [TI_ADS7960] = { - .channels = ti_ads7960_channels, - .num_channels = ARRAY_SIZE(ti_ads7960_channels), - }, - [TI_ADS7961] = { - .channels = ti_ads7961_channels, - .num_channels = ARRAY_SIZE(ti_ads7961_channels), - }, +static const struct ti_ads7950_chip_info ti_ads7950_chip_info = { + .channels = ti_ads7950_channels, + .num_channels = ARRAY_SIZE(ti_ads7950_channels), +}; + +static const struct ti_ads7950_chip_info ti_ads7951_chip_info = { + .channels = ti_ads7951_channels, + .num_channels = ARRAY_SIZE(ti_ads7951_channels), +}; + +static const struct ti_ads7950_chip_info ti_ads7952_chip_info = { + .channels = ti_ads7952_channels, + .num_channels = ARRAY_SIZE(ti_ads7952_channels), +}; + +static const struct ti_ads7950_chip_info ti_ads7953_chip_info = { + .channels = ti_ads7953_channels, + .num_channels = ARRAY_SIZE(ti_ads7953_channels), +}; + +static const struct ti_ads7950_chip_info ti_ads7954_chip_info = { + .channels = ti_ads7954_channels, + .num_channels = ARRAY_SIZE(ti_ads7954_channels), +}; + +static const struct ti_ads7950_chip_info ti_ads7955_chip_info = { + .channels = ti_ads7955_channels, + .num_channels = ARRAY_SIZE(ti_ads7955_channels), +}; + +static const struct ti_ads7950_chip_info ti_ads7956_chip_info = { + .channels = ti_ads7956_channels, + .num_channels = ARRAY_SIZE(ti_ads7956_channels), +}; + +static const struct ti_ads7950_chip_info ti_ads7957_chip_info = { + .channels = ti_ads7957_channels, + .num_channels = ARRAY_SIZE(ti_ads7957_channels), +}; + +static const struct ti_ads7950_chip_info ti_ads7958_chip_info = { + .channels = ti_ads7958_channels, + .num_channels = ARRAY_SIZE(ti_ads7958_channels), +}; + +static const struct ti_ads7950_chip_info ti_ads7959_chip_info = { + .channels = ti_ads7959_channels, + .num_channels = ARRAY_SIZE(ti_ads7959_channels), +}; + +static const struct ti_ads7950_chip_info ti_ads7960_chip_info = { + .channels = ti_ads7960_channels, + .num_channels = ARRAY_SIZE(ti_ads7960_channels), +}; + +static const struct ti_ads7950_chip_info ti_ads7961_chip_info = { + .channels = ti_ads7961_channels, + .num_channels = ARRAY_SIZE(ti_ads7961_channels), }; /* @@ -313,8 +304,10 @@ static irqreturn_t ti_ads7950_trigger_handler(int irq, void *p) if (ret < 0) goto out; - iio_push_to_buffers_with_timestamp(indio_dev, &st->rx_buf[2], - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts_unaligned(indio_dev, &st->rx_buf[2], + sizeof(*st->rx_buf) * + TI_ADS7950_MAX_CHAN, + iio_get_time_ns(indio_dev)); out: mutex_unlock(&st->slock); @@ -561,7 +554,7 @@ static int ti_ads7950_probe(struct spi_device *spi) st->spi = spi; - info = &ti_ads7950_chip_info[spi_get_device_id(spi)->driver_data]; + info = spi_get_device_match_data(spi); indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; @@ -683,35 +676,35 @@ static void ti_ads7950_remove(struct spi_device *spi) } static const struct spi_device_id ti_ads7950_id[] = { - { "ads7950", TI_ADS7950 }, - { "ads7951", TI_ADS7951 }, - { "ads7952", TI_ADS7952 }, - { "ads7953", TI_ADS7953 }, - { "ads7954", TI_ADS7954 }, - { "ads7955", TI_ADS7955 }, - { "ads7956", TI_ADS7956 }, - { "ads7957", TI_ADS7957 }, - { "ads7958", TI_ADS7958 }, - { "ads7959", TI_ADS7959 }, - { "ads7960", TI_ADS7960 }, - { "ads7961", TI_ADS7961 }, + { "ads7950", (kernel_ulong_t)&ti_ads7950_chip_info }, + { "ads7951", (kernel_ulong_t)&ti_ads7951_chip_info }, + { "ads7952", (kernel_ulong_t)&ti_ads7952_chip_info }, + { "ads7953", (kernel_ulong_t)&ti_ads7953_chip_info }, + { "ads7954", (kernel_ulong_t)&ti_ads7954_chip_info }, + { "ads7955", (kernel_ulong_t)&ti_ads7955_chip_info }, + { "ads7956", (kernel_ulong_t)&ti_ads7956_chip_info }, + { "ads7957", (kernel_ulong_t)&ti_ads7957_chip_info }, + { "ads7958", (kernel_ulong_t)&ti_ads7958_chip_info }, + { "ads7959", (kernel_ulong_t)&ti_ads7959_chip_info }, + { "ads7960", (kernel_ulong_t)&ti_ads7960_chip_info }, + { "ads7961", (kernel_ulong_t)&ti_ads7961_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, ti_ads7950_id); static const struct of_device_id ads7950_of_table[] = { - { .compatible = "ti,ads7950", .data = &ti_ads7950_chip_info[TI_ADS7950] }, - { .compatible = "ti,ads7951", .data = &ti_ads7950_chip_info[TI_ADS7951] }, - { .compatible = "ti,ads7952", .data = &ti_ads7950_chip_info[TI_ADS7952] }, - { .compatible = "ti,ads7953", .data = &ti_ads7950_chip_info[TI_ADS7953] }, - { .compatible = "ti,ads7954", .data = &ti_ads7950_chip_info[TI_ADS7954] }, - { .compatible = "ti,ads7955", .data = &ti_ads7950_chip_info[TI_ADS7955] }, - { .compatible = "ti,ads7956", .data = &ti_ads7950_chip_info[TI_ADS7956] }, - { .compatible = "ti,ads7957", .data = &ti_ads7950_chip_info[TI_ADS7957] }, - { .compatible = "ti,ads7958", .data = &ti_ads7950_chip_info[TI_ADS7958] }, - { .compatible = "ti,ads7959", .data = &ti_ads7950_chip_info[TI_ADS7959] }, - { .compatible = "ti,ads7960", .data = &ti_ads7950_chip_info[TI_ADS7960] }, - { .compatible = "ti,ads7961", .data = &ti_ads7950_chip_info[TI_ADS7961] }, + { .compatible = "ti,ads7950", .data = &ti_ads7950_chip_info }, + { .compatible = "ti,ads7951", .data = &ti_ads7951_chip_info }, + { .compatible = "ti,ads7952", .data = &ti_ads7952_chip_info }, + { .compatible = "ti,ads7953", .data = &ti_ads7953_chip_info }, + { .compatible = "ti,ads7954", .data = &ti_ads7954_chip_info }, + { .compatible = "ti,ads7955", .data = &ti_ads7955_chip_info }, + { .compatible = "ti,ads7956", .data = &ti_ads7956_chip_info }, + { .compatible = "ti,ads7957", .data = &ti_ads7957_chip_info }, + { .compatible = "ti,ads7958", .data = &ti_ads7958_chip_info }, + { .compatible = "ti,ads7959", .data = &ti_ads7959_chip_info }, + { .compatible = "ti,ads7960", .data = &ti_ads7960_chip_info }, + { .compatible = "ti,ads7961", .data = &ti_ads7961_chip_info }, { } }; MODULE_DEVICE_TABLE(of, ads7950_of_table); diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index a1a28584de93..1516dd332f90 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -113,10 +113,10 @@ static void tiadc_step_config(struct iio_dev *indio_dev) * There are 16 configurable steps and 8 analog input * lines available which are shared between Touchscreen and ADC. * - * Steps forwards i.e. from 0 towards 16 are used by ADC - * depending on number of input lines needed. + * Steps forward, i.e. from 0 towards 16, are used by ADC + * depending on the number of input lines needed. * Channel would represent which analog input - * needs to be given to ADC to digitalize data. + * needs to be given to ADC to digitize data. */ for (i = 0; i < adc_dev->channels; i++) { int chan; diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c index fe3b31ec976e..f0274cd74973 100644 --- a/drivers/iio/adc/twl4030-madc.c +++ b/drivers/iio/adc/twl4030-madc.c @@ -252,7 +252,7 @@ static const struct s16_fract twl4030_divider_ratios[16] = { {5, 11}, /* CHANNEL 15 */ }; -/* Conversion table from -3 to 55 degrees Celcius */ +/* Conversion table from -3 to 55 degrees Celsius */ static int twl4030_therm_tbl[] = { 30800, 29500, 28300, 27100, 26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c index 3ac774ebf678..7810d6b2b668 100644 --- a/drivers/iio/adc/twl6030-gpadc.c +++ b/drivers/iio/adc/twl6030-gpadc.c @@ -416,7 +416,7 @@ static u8 twl6032_channel_to_reg(int channel) { /* * for any prior chosen channel, when the conversion is ready - * the result is avalable in GPCH0_LSB, GPCH0_MSB. + * the result is available in GPCH0_LSB, GPCH0_MSB. */ return TWL6032_GPADC_GPCH0_LSB; diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c index a20b4d48c5f7..fe930ce5ee30 100644 --- a/drivers/iio/addac/ad74413r.c +++ b/drivers/iio/addac/ad74413r.c @@ -839,12 +839,9 @@ static int _ad74413r_get_single_adc_result(struct ad74413r_state *st, if (ret) return ret; - ret = wait_for_completion_timeout(&st->adc_data_completion, - msecs_to_jiffies(1000)); - if (!ret) { - ret = -ETIMEDOUT; - return ret; - } + if (!wait_for_completion_timeout(&st->adc_data_completion, + msecs_to_jiffies(1000))) + return -ETIMEDOUT; ret = regmap_read(st->regmap, AD74413R_REG_ADC_RESULT_X(channel), &uval); diff --git a/drivers/iio/amplifiers/Kconfig b/drivers/iio/amplifiers/Kconfig index a8a604863eed..9e24421b5e97 100644 --- a/drivers/iio/amplifiers/Kconfig +++ b/drivers/iio/amplifiers/Kconfig @@ -18,7 +18,15 @@ config AD8366 AD8366 Dual-Digital Variable Gain Amplifier (VGA) ADA4961 BiCMOS RF Digital Gain Amplifier (DGA) ADL5240 Digitally controlled variable gain amplifier (VGA) + ADRF5702: 0.125 dB LSB, 8-Bit, Silicon Digital Attenuator + ADRF5703: 0.25 dB LSB, 7-Bit, Silicon Digital Attenuator + ADRF5720: 0.5 dB LSB, 6-Bit, Silicon Digital Attenuator + ADRF5730: 0.5 dB LSB, 6-Bit, Silicon Digital Attenuator + ADRF5731: 2 dB LSB, 4-Bit, Silicon Digital Attenuator + HMC271A: 1dB LSB 5-Bit Digital Attenuator SMT HMC792A 0.25 dB LSB GaAs MMIC 6-Bit Digital Attenuator + HMC1018A: 1.0 dB LSB GaAs MMIC 5-BIT Digital Attenuator + HMC1019A: 0.5 dB LSB GaAs MMIC 5-BIT Digital Attenuator HMC1119 0.25 dB LSB, 7-Bit, Silicon Digital Attenuator To compile this driver as a module, choose M here: the diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c index d06ac786501c..bbf41a1fb3a1 100644 --- a/drivers/iio/amplifiers/ad8366.c +++ b/drivers/iio/amplifiers/ad8366.c @@ -5,46 +5,52 @@ * AD8366 Dual-Digital Variable Gain Amplifier (VGA) * ADA4961 BiCMOS RF Digital Gain Amplifier (DGA) * ADL5240 Digitally controlled variable gain amplifier (VGA) + * ADRF5702: 0.125 dB LSB, 8-Bit, Silicon Digital Attenuator, 50 MHz to 20 GHz + * ADRF5703: 0.25 dB LSB, 7-Bit, Silicon Digital Attenuator, 9 kHz to 20 GHz + * ADRF5720: 0.5 dB LSB, 6-Bit, Silicon Digital Attenuator, 9 kHz to 40 GHz + * ADRF5730: 0.5 dB LSB, 6-Bit, Silicon Digital Attenuator, 100 MHz to 40 GHz + * ADRF5731: 2 dB LSB, 4-Bit, Silicon Digital Attenuator, 100 MHz to 40 GHz + * HMC271A: 1dB LSB 5-Bit Digital Attenuator SMT, 0.7 - 3.7 GHz * HMC792A 0.25 dB LSB GaAs MMIC 6-Bit Digital Attenuator + * HMC1018A: 1.0 dB LSB GaAs MMIC 5-BIT DIGITAL ATTENUATOR, 0.1 - 30 GHz + * HMC1019A: 0.5 dB LSB GaAs MMIC 5-BIT DIGITAL ATTENUATOR, 0.1 - 30 GHz * HMC1119 0.25 dB LSB, 7-Bit, Silicon Digital Attenuator * - * Copyright 2012-2019 Analog Devices Inc. + * Copyright 2012-2026 Analog Devices Inc. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include - -enum ad8366_type { - ID_AD8366, - ID_ADA4961, - ID_ADL5240, - ID_HMC792, - ID_HMC1119, -}; struct ad8366_info { + const char *name; int gain_min; int gain_max; + int gain_step; + size_t num_channels; + size_t (*pack_code)(const unsigned char *code, size_t num_channels, + unsigned char *data); }; struct ad8366_state { struct spi_device *spi; - struct regulator *reg; struct mutex lock; /* protect sensor state */ - struct gpio_desc *reset_gpio; unsigned char ch[2]; - enum ad8366_type type; const struct ad8366_info *info; /* * DMA (thus cache coherency maintenance) may require the @@ -53,60 +59,148 @@ struct ad8366_state { unsigned char data[2] __aligned(IIO_DMA_MINALIGN); }; -static const struct ad8366_info ad8366_infos[] = { - [ID_AD8366] = { - .gain_min = 4500, - .gain_max = 20500, - }, - [ID_ADA4961] = { - .gain_min = -6000, - .gain_max = 15000, - }, - [ID_ADL5240] = { - .gain_min = -11500, - .gain_max = 20000, - }, - [ID_HMC792] = { - .gain_min = -15750, - .gain_max = 0, - }, - [ID_HMC1119] = { - .gain_min = -31750, - .gain_max = 0, - }, +static size_t ad8366_pack_code(const unsigned char *code, size_t num_channels, + unsigned char *data) +{ + u8 ch_a = bitrev8(code[0]) >> 2; + u8 ch_b = bitrev8(code[1]) >> 2; + + put_unaligned_be16((ch_b << 6) | ch_a, &data[0]); + return sizeof(__be16); +} + +static size_t adrf5731_pack_code(const unsigned char *code, size_t num_channels, + unsigned char *data) +{ + data[0] = code[0] << 2; + return 1; +} + +static size_t hmc271_pack_code(const unsigned char *code, size_t num_channels, + unsigned char *data) +{ + data[0] = bitrev8(code[0]) >> 3; + return 1; +} + +static const struct ad8366_info ad8366_chip_info = { + .name = "ad8366", + .gain_min = 4500, + .gain_max = 20500, + .gain_step = 253, + .num_channels = 2, + .pack_code = ad8366_pack_code, }; -static int ad8366_write(struct iio_dev *indio_dev, - unsigned char ch_a, unsigned char ch_b) +static const struct ad8366_info ada4961_chip_info = { + .name = "ada4961", + .gain_min = -6000, + .gain_max = 15000, + .gain_step = -1000, + .num_channels = 1, +}; + +static const struct ad8366_info adl5240_chip_info = { + .name = "adl5240", + .gain_min = -11500, + .gain_max = 20000, + .gain_step = 500, + .num_channels = 1, +}; + +static const struct ad8366_info adrf5702_chip_info = { + .name = "adrf5702", + .gain_min = -31875, + .gain_max = 0, + .gain_step = -125, + .num_channels = 1, +}; + +static const struct ad8366_info adrf5703_chip_info = { + .name = "adrf5703", + .gain_min = -31750, + .gain_max = 0, + .gain_step = -250, + .num_channels = 1, +}; + +static const struct ad8366_info adrf5720_chip_info = { + .name = "adrf5720", + .gain_min = -31500, + .gain_max = 0, + .gain_step = -500, + .num_channels = 1, +}; + +static const struct ad8366_info adrf5730_chip_info = { + .name = "adrf5730", + .gain_min = -31500, + .gain_max = 0, + .gain_step = -500, + .num_channels = 1, +}; + +static const struct ad8366_info adrf5731_chip_info = { + .name = "adrf5731", + .gain_min = -30000, + .gain_max = 0, + .gain_step = -2000, + .num_channels = 1, + .pack_code = adrf5731_pack_code, +}; + +static const struct ad8366_info hmc271_chip_info = { + .name = "hmc271a", + .gain_min = -31000, + .gain_max = 0, + .gain_step = 1000, + .num_channels = 1, + .pack_code = hmc271_pack_code, +}; + +static const struct ad8366_info hmc792_chip_info = { + .name = "hmc792a", + .gain_min = -15750, + .gain_max = 0, + .gain_step = 250, + .num_channels = 1, +}; + +static const struct ad8366_info hmc1018_chip_info = { + .name = "hmc1018a", + .gain_min = -31000, + .gain_max = 0, + .gain_step = 1000, + .num_channels = 1, +}; + +static const struct ad8366_info hmc1019_chip_info = { + .name = "hmc1019a", + .gain_min = -15500, + .gain_max = 0, + .gain_step = 500, + .num_channels = 1, +}; + +static const struct ad8366_info hmc1119_chip_info = { + .name = "hmc1119", + .gain_min = -31750, + .gain_max = 0, + .gain_step = -250, + .num_channels = 1, +}; + +static int ad8366_write_code(struct ad8366_state *st) { - struct ad8366_state *st = iio_priv(indio_dev); - int ret; + const struct ad8366_info *inf = st->info; + size_t len = 1; - switch (st->type) { - case ID_AD8366: - ch_a = bitrev8(ch_a & 0x3F); - ch_b = bitrev8(ch_b & 0x3F); + if (inf->pack_code) + len = inf->pack_code(st->ch, inf->num_channels, st->data); + else + st->data[0] = st->ch[0]; - st->data[0] = ch_b >> 4; - st->data[1] = (ch_b << 4) | (ch_a >> 2); - break; - case ID_ADA4961: - st->data[0] = ch_a & 0x1F; - break; - case ID_ADL5240: - st->data[0] = (ch_a & 0x3F); - break; - case ID_HMC792: - case ID_HMC1119: - st->data[0] = ch_a; - break; - } - - ret = spi_write(st->spi, st->data, indio_dev->num_channels); - if (ret < 0) - dev_err(&indio_dev->dev, "write failed (%d)", ret); - - return ret; + return spi_write(st->spi, st->data, len); } static int ad8366_read_raw(struct iio_dev *indio_dev, @@ -116,6 +210,7 @@ static int ad8366_read_raw(struct iio_dev *indio_dev, long m) { struct ad8366_state *st = iio_priv(indio_dev); + const struct ad8366_info *inf = st->info; int ret; int code, gain = 0; @@ -123,25 +218,8 @@ static int ad8366_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_HARDWAREGAIN: code = st->ch[chan->channel]; - - switch (st->type) { - case ID_AD8366: - gain = code * 253 + 4500; - break; - case ID_ADA4961: - gain = 15000 - code * 1000; - break; - case ID_ADL5240: - gain = 20000 - 31500 + code * 500; - break; - case ID_HMC792: - gain = -1 * code * 500; - break; - case ID_HMC1119: - gain = -1 * code * 250; - break; - } - + gain = inf->gain_step > 0 ? inf->gain_min : inf->gain_max; + gain += inf->gain_step * code; /* Values in dB */ *val = gain / 1000; *val2 = (gain % 1000) * 1000; @@ -176,29 +254,14 @@ static int ad8366_write_raw(struct iio_dev *indio_dev, if (gain > inf->gain_max || gain < inf->gain_min) return -EINVAL; - switch (st->type) { - case ID_AD8366: - code = (gain - 4500) / 253; - break; - case ID_ADA4961: - code = (15000 - gain) / 1000; - break; - case ID_ADL5240: - code = ((gain - 500 - 20000) / 500) & 0x3F; - break; - case ID_HMC792: - code = (abs(gain) / 500) & 0x3F; - break; - case ID_HMC1119: - code = (abs(gain) / 250) & 0x7F; - break; - } + gain -= inf->gain_step > 0 ? inf->gain_min : inf->gain_max; + code = DIV_ROUND_CLOSEST(gain, inf->gain_step); mutex_lock(&st->lock); switch (mask) { case IIO_CHAN_INFO_HARDWAREGAIN: st->ch[chan->channel] = code; - ret = ad8366_write(indio_dev, st->ch[0], st->ch[1]); + ret = ad8366_write_code(st); break; default: ret = -EINVAL; @@ -239,107 +302,97 @@ static const struct iio_chan_spec ad8366_channels[] = { AD8366_CHAN(1), }; -static const struct iio_chan_spec ada4961_channels[] = { - AD8366_CHAN(0), -}; - static int ad8366_probe(struct spi_device *spi) { + struct device *dev = &spi->dev; + struct gpio_desc *enable_gpio; + struct reset_control *rstc; struct iio_dev *indio_dev; struct ad8366_state *st; int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; st = iio_priv(indio_dev); - st->reg = devm_regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(st->reg)) { - ret = regulator_enable(st->reg); - if (ret) - return ret; - } + ret = devm_mutex_init(dev, &st->lock); + if (ret) + return ret; + + ret = devm_regulator_get_enable(dev, "vcc"); + if (ret) + return dev_err_probe(dev, ret, "Failed to get regulator\n"); - spi_set_drvdata(spi, indio_dev); - mutex_init(&st->lock); st->spi = spi; - st->type = spi_get_device_id(spi)->driver_data; + st->info = spi_get_device_match_data(spi); - switch (st->type) { - case ID_AD8366: - indio_dev->channels = ad8366_channels; - indio_dev->num_channels = ARRAY_SIZE(ad8366_channels); - break; - case ID_ADA4961: - case ID_ADL5240: - case ID_HMC792: - case ID_HMC1119: - st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(st->reset_gpio)) { - ret = PTR_ERR(st->reset_gpio); - goto error_disable_reg; - } - indio_dev->channels = ada4961_channels; - indio_dev->num_channels = ARRAY_SIZE(ada4961_channels); - break; - default: - dev_err(&spi->dev, "Invalid device ID\n"); - ret = -EINVAL; - goto error_disable_reg; - } + enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(enable_gpio)) + return dev_err_probe(dev, PTR_ERR(enable_gpio), + "Failed to get enable GPIO\n"); - st->info = &ad8366_infos[st->type]; - indio_dev->name = spi_get_device_id(spi)->name; + rstc = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL); + if (IS_ERR(rstc)) + return dev_err_probe(dev, PTR_ERR(rstc), + "Failed to get reset controller\n"); + + indio_dev->name = st->info->name; indio_dev->info = &ad8366_info; indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad8366_channels; + indio_dev->num_channels = st->info->num_channels; - ret = ad8366_write(indio_dev, 0, 0); + ret = ad8366_write_code(st); if (ret < 0) - goto error_disable_reg; + return dev_err_probe(dev, ret, "failed to write initial gain\n"); - ret = iio_device_register(indio_dev); - if (ret) - goto error_disable_reg; - - return 0; - -error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); - - return ret; -} - -static void ad8366_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad8366_state *st = iio_priv(indio_dev); - struct regulator *reg = st->reg; - - iio_device_unregister(indio_dev); - - if (!IS_ERR(reg)) - regulator_disable(reg); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id ad8366_id[] = { - {"ad8366", ID_AD8366}, - {"ada4961", ID_ADA4961}, - {"adl5240", ID_ADL5240}, - {"hmc792a", ID_HMC792}, - {"hmc1119", ID_HMC1119}, + { "ad8366", (kernel_ulong_t)&ad8366_chip_info }, + { "ada4961", (kernel_ulong_t)&ada4961_chip_info }, + { "adl5240", (kernel_ulong_t)&adl5240_chip_info }, + { "adrf5702", (kernel_ulong_t)&adrf5702_chip_info }, + { "adrf5703", (kernel_ulong_t)&adrf5703_chip_info }, + { "adrf5720", (kernel_ulong_t)&adrf5720_chip_info }, + { "adrf5730", (kernel_ulong_t)&adrf5730_chip_info }, + { "adrf5731", (kernel_ulong_t)&adrf5731_chip_info }, + { "hmc271a", (kernel_ulong_t)&hmc271_chip_info }, + { "hmc792a", (kernel_ulong_t)&hmc792_chip_info }, + { "hmc1018a", (kernel_ulong_t)&hmc1018_chip_info }, + { "hmc1019a", (kernel_ulong_t)&hmc1019_chip_info }, + { "hmc1119", (kernel_ulong_t)&hmc1119_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, ad8366_id); +static const struct of_device_id ad8366_of_match[] = { + { .compatible = "adi,ad8366", .data = &ad8366_chip_info }, + { .compatible = "adi,ada4961", .data = &ada4961_chip_info }, + { .compatible = "adi,adl5240", .data = &adl5240_chip_info }, + { .compatible = "adi,adrf5702", .data = &adrf5702_chip_info }, + { .compatible = "adi,adrf5703", .data = &adrf5703_chip_info }, + { .compatible = "adi,adrf5720", .data = &adrf5720_chip_info }, + { .compatible = "adi,adrf5730", .data = &adrf5730_chip_info }, + { .compatible = "adi,adrf5731", .data = &adrf5731_chip_info }, + { .compatible = "adi,hmc271a", .data = &hmc271_chip_info }, + { .compatible = "adi,hmc792a", .data = &hmc792_chip_info }, + { .compatible = "adi,hmc1018a", .data = &hmc1018_chip_info }, + { .compatible = "adi,hmc1019a", .data = &hmc1019_chip_info }, + { .compatible = "adi,hmc1119", .data = &hmc1119_chip_info }, + { } +}; +MODULE_DEVICE_TABLE(of, ad8366_of_match); + static struct spi_driver ad8366_driver = { .driver = { - .name = KBUILD_MODNAME, + .name = KBUILD_MODNAME, + .of_match_table = ad8366_of_match, }, .probe = ad8366_probe, - .remove = ad8366_remove, .id_table = ad8366_id, }; diff --git a/drivers/iio/amplifiers/ada4250.c b/drivers/iio/amplifiers/ada4250.c index 40f396ea9069..71e361af2074 100644 --- a/drivers/iio/amplifiers/ada4250.c +++ b/drivers/iio/amplifiers/ada4250.c @@ -109,7 +109,7 @@ static int ada4250_set_offset_uv(struct iio_dev *indio_dev, /* * Compute Range and Voltage per LSB for the Sensor Offset Calibration - * Example of computation for Range 1 and Range 2 (Curren Bias Set = AVDD): + * Example of computation for Range 1 and Range 2 (Current Bias Set = AVDD): * Range 1 Range 2 * Gain | Max Vos(mV) | LSB(mV) | Max Vos(mV) | LSB(mV) | * 2 | X1*127 | X1=0.126(AVDD-1) | X1*3*127 | X1*3 | diff --git a/drivers/iio/buffer/industrialio-hw-consumer.c b/drivers/iio/buffer/industrialio-hw-consumer.c index cb771ef8eeb3..24d7df603760 100644 --- a/drivers/iio/buffer/industrialio-hw-consumer.c +++ b/drivers/iio/buffer/industrialio-hw-consumer.c @@ -28,7 +28,6 @@ struct hw_consumer_buffer { struct list_head head; struct iio_dev *indio_dev; struct iio_buffer buffer; - long scan_mask[]; }; static struct hw_consumer_buffer *iio_buffer_to_hw_consumer_buffer( @@ -52,7 +51,6 @@ static const struct iio_buffer_access_funcs iio_hw_buf_access = { static struct hw_consumer_buffer *iio_hw_consumer_get_buffer( struct iio_hw_consumer *hwc, struct iio_dev *indio_dev) { - unsigned int mask_longs = BITS_TO_LONGS(iio_get_masklength(indio_dev)); struct hw_consumer_buffer *buf; list_for_each_entry(buf, &hwc->buffers, head) { @@ -60,13 +58,18 @@ static struct hw_consumer_buffer *iio_hw_consumer_get_buffer( return buf; } - buf = kzalloc_flex(*buf, scan_mask, mask_longs); + buf = kzalloc_obj(*buf); if (!buf) return NULL; buf->buffer.access = &iio_hw_buf_access; buf->indio_dev = indio_dev; - buf->buffer.scan_mask = buf->scan_mask; + buf->buffer.scan_mask = bitmap_zalloc(iio_get_masklength(indio_dev), + GFP_KERNEL); + if (!buf->buffer.scan_mask) { + kfree(buf); + return NULL; + } iio_buffer_init(&buf->buffer); list_add_tail(&buf->head, &hwc->buffers); diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c index a6ff9085b8a2..b67ea6468226 100644 --- a/drivers/iio/buffer/kfifo_buf.c +++ b/drivers/iio/buffer/kfifo_buf.c @@ -224,35 +224,9 @@ void iio_kfifo_free(struct iio_buffer *r) } EXPORT_SYMBOL(iio_kfifo_free); -static void devm_iio_kfifo_release(struct device *dev, void *res) +static void devm_iio_kfifo_release(void *buffer) { - iio_kfifo_free(*(struct iio_buffer **)res); -} - -/** - * devm_iio_kfifo_allocate - Resource-managed iio_kfifo_allocate() - * @dev: Device to allocate kfifo buffer for - * - * RETURNS: - * Pointer to allocated iio_buffer on success, NULL on failure. - */ -static struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev) -{ - struct iio_buffer **ptr, *r; - - ptr = devres_alloc(devm_iio_kfifo_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return NULL; - - r = iio_kfifo_allocate(); - if (r) { - *ptr = r; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } - - return r; + iio_kfifo_free(buffer); } /** @@ -262,10 +236,12 @@ static struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev) * @setup_ops: The setup_ops required to configure the HW part of the buffer (optional) * @buffer_attrs: Extra sysfs buffer attributes for this IIO buffer * - * This function allocates a kfifo buffer via devm_iio_kfifo_allocate() and + * This function allocates a kfifo buffer via iio_kfifo_allocate() and * attaches it to the IIO device via iio_device_attach_buffer(). * This is meant to be a bit of a short-hand/helper function as there are a few * drivers that seem to do this. + * + * Return: 0 on success, negative error code on failure. */ int devm_iio_kfifo_buffer_setup_ext(struct device *dev, struct iio_dev *indio_dev, @@ -273,11 +249,16 @@ int devm_iio_kfifo_buffer_setup_ext(struct device *dev, const struct iio_dev_attr **buffer_attrs) { struct iio_buffer *buffer; + int ret; - buffer = devm_iio_kfifo_allocate(dev); + buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; + ret = devm_add_action_or_reset(dev, devm_iio_kfifo_release, buffer); + if (ret) + return ret; + indio_dev->modes |= INDIO_BUFFER_SOFTWARE; indio_dev->setup_ops = setup_ops; diff --git a/drivers/iio/cdc/ad7150.c b/drivers/iio/cdc/ad7150.c index 427d32e398b3..8106a6a83561 100644 --- a/drivers/iio/cdc/ad7150.c +++ b/drivers/iio/cdc/ad7150.c @@ -306,7 +306,7 @@ static int ad7150_write_event_config(struct iio_dev *indio_dev, dir); if (ret) goto error_ret; - /* reenable any irq's we disabled whilst changing mode */ + /* re-enable any IRQs we disabled whilst changing mode */ enable_irq(chip->interrupts[0]); enable_irq(chip->interrupts[1]); } diff --git a/drivers/iio/cdc/ad7746.c b/drivers/iio/cdc/ad7746.c index 8a306d55c72a..cb97e3c978d8 100644 --- a/drivers/iio/cdc/ad7746.c +++ b/drivers/iio/cdc/ad7746.c @@ -606,7 +606,7 @@ static int ad7746_read_channel(struct iio_dev *indio_dev, return ret; /* - * Offset applied internally becaue the _offset userspace interface is + * Offset applied internally because the _offset userspace interface is * needed for the CAP DACs which apply a controllable offset. */ *val = get_unaligned_be24(data) - 0x800000; diff --git a/drivers/iio/chemical/bme680_core.c b/drivers/iio/chemical/bme680_core.c index 24e0b59e2fdf..6aeac132394c 100644 --- a/drivers/iio/chemical/bme680_core.c +++ b/drivers/iio/chemical/bme680_core.c @@ -807,7 +807,7 @@ static int bme680_read_gas(struct bme680_data *data, int *comp_gas_res) adc_gas_res = FIELD_GET(BME680_ADC_GAS_RES, gas_regs_val); /* - * occurs if either the gas heating duration was insuffient + * This may occur if either the gas heating duration was insufficient * to reach the target heater temperature or the target * heater temperature was too high for the heater sink to * reach. diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index 82cef4a12442..f34e2bbba2d1 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -106,7 +106,7 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev, switch (st->core.type) { case MOTIONSENSE_TYPE_ACCEL: /* - * EC returns data in g, iio exepects m/s^2. + * EC returns data in g, IIO expects m/s^2. * Do not use IIO_G_TO_M_S_2 to avoid precision loss. */ *val = div_s64(val64 * 980665, 10); diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index a61428bfdce3..c115a72832b2 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c @@ -346,7 +346,7 @@ int hid_sensor_write_raw_hyst_rel_value(struct hid_sensor_common *st, EXPORT_SYMBOL_NS(hid_sensor_write_raw_hyst_rel_value, "IIO_HID"); /* - * This fuction applies the unit exponent to the scale. + * This function applies the unit exponent to the scale. * For example: * 9.806650000 ->exp:2-> val0[980]val1[665000000] * 9.000806000 ->exp:2-> val0[900]val1[80600000] diff --git a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c index 97526ba87b93..e0b10366ed2b 100644 --- a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c +++ b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c @@ -154,7 +154,7 @@ void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts, valid = inv_update_chip_period(ts, period); } - /* no previous data, compute theoritical value from interrupt */ + /* no previous data, compute theoretical value from interrupt */ if (ts->timestamp == 0) { /* elapsed time: sensor period * sensor samples number */ interval = (int64_t)ts->period * (int64_t)sample_nb; @@ -185,7 +185,7 @@ void inv_sensors_timestamp_apply_odr(struct inv_sensors_timestamp *ts, /* * After ODR change the time interval with the previous sample is - * undertermined (depends when the change occures). So we compute the + * undertermined (depends when the change occurs). So we compute the * timestamp from the current interrupt using the new FIFO period, the * total number of samples and the current sample numero. */ diff --git a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c index 588470863681..1960a2ce82a8 100644 --- a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c +++ b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c @@ -96,7 +96,7 @@ EXPORT_SYMBOL_NS(ms_sensors_read_prom_word, "IIO_MEAS_SPEC_SENSORS"); * * Generic ADC conversion & read function for Measurement Specialties * devices. - * The function will issue conversion command, sleep appopriate delay, and + * The function will issue conversion command, sleep appropriate delay, and * issue command to read ADC. * * Return: 0 on success, negative errno otherwise. diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index dac593be5695..dbc5e16fbde4 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -501,14 +501,12 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev, byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits + ch->scan_type.shift, 8); - outdata = kmalloc(byte_for_channel, GFP_DMA | GFP_KERNEL); - if (!outdata) - return -ENOMEM; + outdata = sdata->buffer_data; err = regmap_bulk_read(sdata->regmap, ch->address, outdata, byte_for_channel); if (err < 0) - goto st_sensors_free_memory; + return err; if (byte_for_channel == 1) *data = (s8)*outdata; @@ -517,10 +515,7 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev, else if (byte_for_channel == 3) *data = (s32)sign_extend32(get_unaligned_le24(outdata), 23); -st_sensors_free_memory: - kfree(outdata); - - return err; + return 0; } int st_sensors_read_info_raw(struct iio_dev *indio_dev, diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index db9f5c711b3d..cd4870b65415 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -408,6 +408,7 @@ config DPOT_DAC config DS4424 tristate "Maxim Integrated DS4422/DS4424 DAC driver" depends on I2C + select REGMAP_I2C help If you say yes here you get support for Maxim chips DS4422, DS4424. diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c index bd32fa57b1d7..20316fd568e6 100644 --- a/drivers/iio/dac/ad5360.c +++ b/drivers/iio/dac/ad5360.c @@ -206,14 +206,10 @@ static int ad5360_write_unlocked(struct iio_dev *indio_dev, static int ad5360_write(struct iio_dev *indio_dev, unsigned int cmd, unsigned int addr, unsigned int val, unsigned int shift) { - int ret; struct ad5360_state *st = iio_priv(indio_dev); - mutex_lock(&st->lock); - ret = ad5360_write_unlocked(indio_dev, cmd, addr, val, shift); - mutex_unlock(&st->lock); - - return ret; + guard(mutex)(&st->lock); + return ad5360_write_unlocked(indio_dev, cmd, addr, val, shift); } static int ad5360_read(struct iio_dev *indio_dev, unsigned int type, @@ -232,7 +228,7 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type, }, }; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); st->data[0].d32 = cpu_to_be32(AD5360_CMD(AD5360_CMD_SPECIAL_FUNCTION) | AD5360_ADDR(AD5360_REG_SF_READBACK) | @@ -240,12 +236,10 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type, AD5360_READBACK_ADDR(addr)); ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); - if (ret >= 0) - ret = be32_to_cpu(st->data[1].d32) & 0xffff; + if (ret < 0) + return ret; - mutex_unlock(&st->lock); - - return ret; + return be32_to_cpu(st->data[1].d32) & 0xffff; } static ssize_t ad5360_read_dac_powerdown(struct device *dev, @@ -262,19 +256,14 @@ static int ad5360_update_ctrl(struct iio_dev *indio_dev, unsigned int set, unsigned int clr) { struct ad5360_state *st = iio_priv(indio_dev); - int ret; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); st->ctrl |= set; st->ctrl &= ~clr; - ret = ad5360_write_unlocked(indio_dev, AD5360_CMD_SPECIAL_FUNCTION, - AD5360_REG_SF_CTRL, st->ctrl, 0); - - mutex_unlock(&st->lock); - - return ret; + return ad5360_write_unlocked(indio_dev, AD5360_CMD_SPECIAL_FUNCTION, + AD5360_REG_SF_CTRL, st->ctrl, 0); } static ssize_t ad5360_write_dac_powerdown(struct device *dev, diff --git a/drivers/iio/dac/ad7293.c b/drivers/iio/dac/ad7293.c index c3797e40cdd9..df6f126abf05 100644 --- a/drivers/iio/dac/ad7293.c +++ b/drivers/iio/dac/ad7293.c @@ -776,27 +776,27 @@ static int ad7293_reset(struct ad7293_state *st) static int ad7293_properties_parse(struct ad7293_state *st) { - struct spi_device *spi = st->spi; + struct device *dev = &st->spi->dev; int ret; - ret = devm_regulator_get_enable(&spi->dev, "avdd"); + ret = devm_regulator_get_enable(dev, "avdd"); if (ret) - return dev_err_probe(&spi->dev, ret, "failed to enable AVDD\n"); + return dev_err_probe(dev, ret, "failed to enable AVDD\n"); - ret = devm_regulator_get_enable(&spi->dev, "vdrive"); + ret = devm_regulator_get_enable(dev, "vdrive"); if (ret) - return dev_err_probe(&spi->dev, ret, "failed to enable VDRIVE\n"); + return dev_err_probe(dev, ret, "failed to enable VDRIVE\n"); - ret = devm_regulator_get_enable_optional(&spi->dev, "vrefin"); + ret = devm_regulator_get_enable_optional(dev, "vrefin"); if (ret < 0 && ret != -ENODEV) - return dev_err_probe(&spi->dev, ret, "failed to enable VREFIN\n"); + return dev_err_probe(dev, ret, "failed to enable VREFIN\n"); st->vrefin_en = ret != -ENODEV; - st->gpio_reset = devm_gpiod_get_optional(&st->spi->dev, "reset", + st->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(st->gpio_reset)) - return dev_err_probe(&spi->dev, PTR_ERR(st->gpio_reset), + return dev_err_probe(dev, PTR_ERR(st->gpio_reset), "failed to get the reset GPIO\n"); return 0; @@ -806,7 +806,7 @@ static int ad7293_init(struct ad7293_state *st) { int ret; u16 chip_id; - struct spi_device *spi = st->spi; + struct device *dev = &st->spi->dev; ret = ad7293_properties_parse(st); if (ret) @@ -821,10 +821,8 @@ static int ad7293_init(struct ad7293_state *st) if (ret) return ret; - if (chip_id != AD7293_CHIP_ID) { - dev_err(&spi->dev, "Invalid Chip ID.\n"); - return -EINVAL; - } + if (chip_id != AD7293_CHIP_ID) + return dev_err_probe(dev, -EINVAL, "Invalid Chip ID.\n"); if (!st->vrefin_en) return __ad7293_spi_update_bits(st, AD7293_REG_GENERAL, @@ -845,9 +843,10 @@ static int ad7293_probe(struct spi_device *spi) { struct iio_dev *indio_dev; struct ad7293_state *st; + struct device *dev = &spi->dev; int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -867,7 +866,7 @@ static int ad7293_probe(struct spi_device *spi) if (ret) return ret; - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id ad7293_id[] = { diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c index 9cc895bbe51a..451fad34e7ee 100644 --- a/drivers/iio/dac/adi-axi-dac.c +++ b/drivers/iio/dac/adi-axi-dac.c @@ -114,7 +114,6 @@ struct axi_dac_state { const struct axi_dac_info *info; u64 dac_clk; u32 reg_config; - bool int_tone; int dac_clk_rate; }; @@ -869,11 +868,13 @@ static const struct iio_backend_ops axi_ad3552r_ops = { static const struct iio_backend_info axi_dac_generic = { .name = "axi-dac", .ops = &axi_dac_generic_ops, + .caps = IIO_BACKEND_CAP_BUFFER | IIO_BACKEND_CAP_ENABLE, }; static const struct iio_backend_info axi_ad3552r = { .name = "axi-ad3552r", .ops = &axi_ad3552r_ops, + .caps = IIO_BACKEND_CAP_BUFFER | IIO_BACKEND_CAP_ENABLE, }; static const struct regmap_config axi_dac_regmap_config = { diff --git a/drivers/iio/dac/ds4424.c b/drivers/iio/dac/ds4424.c index c61868f2de31..085f73de3f02 100644 --- a/drivers/iio/dac/ds4424.c +++ b/drivers/iio/dac/ds4424.c @@ -5,22 +5,31 @@ * Copyright (C) 2017 Maxim Integrated */ +#include +#include +#include +#include +#include #include #include -#include +#include +#include #include -#include -#include -#include +#include +#include + #include +#include #include #define DS4422_MAX_DAC_CHANNELS 2 #define DS4424_MAX_DAC_CHANNELS 4 +#define DS4424_DAC_MASK GENMASK(6, 0) +#define DS4404_DAC_MASK GENMASK(4, 0) +#define DS4424_DAC_SOURCE BIT(7) + #define DS4424_DAC_ADDR(chan) ((chan) + 0xf8) -#define DS4424_SOURCE_I 1 -#define DS4424_SINK_I 0 #define DS4424_CHANNEL(chan) { \ .type = IIO_CURRENT, \ @@ -30,33 +39,61 @@ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ } -/* - * DS4424 DAC control register 8 bits - * [7] 0: to sink; 1: to source - * [6:0] steps to sink/source - * bit[7] looks like a sign bit, but the value of the register is - * not a two's complement code considering the bit[6:0] is a absolute - * distance from the zero point. - */ -union ds4424_raw_data { - struct { - u8 dx:7; - u8 source_bit:1; - }; - u8 bits; +#define DS4424_CHANNEL_WITH_SCALE(chan) { \ + .type = IIO_CURRENT, \ + .indexed = 1, \ + .output = 1, \ + .channel = chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ +} + +struct ds4424_chip_info { + const char *name; + int vref_mV; + int scale_denom; + u8 result_mask; + u8 num_channels; }; -enum ds4424_device_ids { - ID_DS4422, - ID_DS4424, +static const struct ds4424_chip_info ds4402_info = { + .name = "ds4402", + .vref_mV = 1230, + .scale_denom = 4, + .result_mask = DS4404_DAC_MASK, + .num_channels = DS4422_MAX_DAC_CHANNELS, +}; + +static const struct ds4424_chip_info ds4404_info = { + .name = "ds4404", + .vref_mV = 1230, + .scale_denom = 4, + .result_mask = DS4404_DAC_MASK, + .num_channels = DS4424_MAX_DAC_CHANNELS, +}; + +static const struct ds4424_chip_info ds4422_info = { + .name = "ds4422", + .vref_mV = 976, + .scale_denom = 16, + .result_mask = DS4424_DAC_MASK, + .num_channels = DS4422_MAX_DAC_CHANNELS, +}; + +static const struct ds4424_chip_info ds4424_info = { + .name = "ds4424", + .vref_mV = 976, + .scale_denom = 16, + .result_mask = DS4424_DAC_MASK, + .num_channels = DS4424_MAX_DAC_CHANNELS, }; struct ds4424_data { - struct i2c_client *client; - struct mutex lock; - uint8_t save[DS4424_MAX_DAC_CHANNELS]; + struct regmap *regmap; struct regulator *vcc_reg; - uint8_t raw[DS4424_MAX_DAC_CHANNELS]; + const struct ds4424_chip_info *chip_info; + u32 rfs_ohms[DS4424_MAX_DAC_CHANNELS]; + bool has_rfs; }; static const struct iio_chan_spec ds4424_channels[] = { @@ -66,63 +103,114 @@ static const struct iio_chan_spec ds4424_channels[] = { DS4424_CHANNEL(3), }; -static int ds4424_get_value(struct iio_dev *indio_dev, - int *val, int channel) +static const struct iio_chan_spec ds4424_channels_with_scale[] = { + DS4424_CHANNEL_WITH_SCALE(0), + DS4424_CHANNEL_WITH_SCALE(1), + DS4424_CHANNEL_WITH_SCALE(2), + DS4424_CHANNEL_WITH_SCALE(3), +}; + +static const struct regmap_range ds44x2_ranges[] = { + regmap_reg_range(DS4424_DAC_ADDR(0), DS4424_DAC_ADDR(1)), +}; + +static const struct regmap_range ds44x4_ranges[] = { + regmap_reg_range(DS4424_DAC_ADDR(0), DS4424_DAC_ADDR(3)), +}; + +static const struct regmap_access_table ds44x2_table = { + .yes_ranges = ds44x2_ranges, + .n_yes_ranges = ARRAY_SIZE(ds44x2_ranges), +}; + +static const struct regmap_access_table ds44x4_table = { + .yes_ranges = ds44x4_ranges, + .n_yes_ranges = ARRAY_SIZE(ds44x4_ranges), +}; + +static const struct regmap_config ds44x2_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_MAPLE, + .max_register = DS4424_DAC_ADDR(1), + .rd_table = &ds44x2_table, + .wr_table = &ds44x2_table, +}; + +static const struct regmap_config ds44x4_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_MAPLE, + .max_register = DS4424_DAC_ADDR(3), + .rd_table = &ds44x4_table, + .wr_table = &ds44x4_table, +}; + +static int ds4424_init_regmap(struct i2c_client *client, + struct iio_dev *indio_dev) { struct ds4424_data *data = iio_priv(indio_dev); + const struct regmap_config *regmap_config; + u8 vals[DS4424_MAX_DAC_CHANNELS]; int ret; - mutex_lock(&data->lock); - ret = i2c_smbus_read_byte_data(data->client, DS4424_DAC_ADDR(channel)); - if (ret < 0) - goto fail; + if (indio_dev->num_channels == DS4424_MAX_DAC_CHANNELS) + regmap_config = &ds44x4_regmap_config; + else + regmap_config = &ds44x2_regmap_config; - *val = ret; + data->regmap = devm_regmap_init_i2c(client, regmap_config); + if (IS_ERR(data->regmap)) + return dev_err_probe(&client->dev, PTR_ERR(data->regmap), + "Failed to init regmap.\n"); -fail: - mutex_unlock(&data->lock); - return ret; -} + /* + * Prime the cache with the bootloader's configuration. + * regmap_bulk_read() will automatically populate the cache with + * the values read from the hardware. + */ + ret = regmap_bulk_read(data->regmap, DS4424_DAC_ADDR(0), vals, + indio_dev->num_channels); + if (ret) + return dev_err_probe(&client->dev, ret, + "Failed to read hardware values\n"); -static int ds4424_set_value(struct iio_dev *indio_dev, - int val, struct iio_chan_spec const *chan) -{ - struct ds4424_data *data = iio_priv(indio_dev); - int ret; - - mutex_lock(&data->lock); - ret = i2c_smbus_write_byte_data(data->client, - DS4424_DAC_ADDR(chan->channel), val); - if (ret < 0) - goto fail; - - data->raw[chan->channel] = val; - -fail: - mutex_unlock(&data->lock); - return ret; + return 0; } static int ds4424_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { - union ds4424_raw_data raw; + struct ds4424_data *data = iio_priv(indio_dev); + unsigned int regval; int ret; switch (mask) { case IIO_CHAN_INFO_RAW: - ret = ds4424_get_value(indio_dev, val, chan->channel); + ret = regmap_read(data->regmap, DS4424_DAC_ADDR(chan->channel), + ®val); if (ret < 0) { - pr_err("%s : ds4424_get_value returned %d\n", - __func__, ret); + dev_err_ratelimited(indio_dev->dev.parent, + "Failed to read channel %d: %pe\n", + chan->channel, ERR_PTR(ret)); return ret; } - raw.bits = *val; - *val = raw.dx; - if (raw.source_bit == DS4424_SINK_I) + + *val = regval & data->chip_info->result_mask; + if (!(regval & DS4424_DAC_SOURCE)) *val = -*val; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + if (!data->has_rfs) + return -EINVAL; + + /* SCALE is mA/step: mV / Ohm = mA. */ + *val = data->chip_info->vref_mV; + *val2 = data->rfs_ohms[chan->channel] * + data->chip_info->scale_denom; + return IIO_VAL_FRACTIONAL; default: return -EINVAL; @@ -133,107 +221,131 @@ static int ds4424_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { - union ds4424_raw_data raw; + struct ds4424_data *data = iio_priv(indio_dev); + unsigned int abs_val; if (val2 != 0) return -EINVAL; switch (mask) { case IIO_CHAN_INFO_RAW: - if (val <= S8_MIN || val > S8_MAX) + abs_val = abs(val); + if (abs_val > data->chip_info->result_mask) return -EINVAL; - if (val > 0) { - raw.source_bit = DS4424_SOURCE_I; - raw.dx = val; - } else { - raw.source_bit = DS4424_SINK_I; - raw.dx = -val; - } + /* + * Currents exiting the IC (Source) are positive. 0 is a valid + * value for no current flow; the direction bit (Source vs Sink) + * is treated as don't-care by the hardware at 0. + */ + if (val > 0) + abs_val |= DS4424_DAC_SOURCE; - return ds4424_set_value(indio_dev, raw.bits, chan); + return regmap_write(data->regmap, DS4424_DAC_ADDR(chan->channel), + abs_val); default: return -EINVAL; } } -static int ds4424_verify_chip(struct iio_dev *indio_dev) +static int ds4424_parse_rfs(struct i2c_client *client, + struct ds4424_data *data, + struct iio_dev *indio_dev) { - int ret, val; + struct device *dev = &client->dev; + int count, ret; - ret = ds4424_get_value(indio_dev, &val, 0); - if (ret < 0) - dev_err(&indio_dev->dev, - "%s failed. ret: %d\n", __func__, ret); + if (!device_property_present(dev, "maxim,rfs-ohms")) + return 0; - return ret; + count = device_property_count_u32(dev, "maxim,rfs-ohms"); + if (count < 0) + return dev_err_probe(dev, count, "Failed to count maxim,rfs-ohms entries\n"); + if (count != indio_dev->num_channels) + return dev_err_probe(dev, -EINVAL, "maxim,rfs-ohms must have %u entries\n", + indio_dev->num_channels); + + ret = device_property_read_u32_array(dev, "maxim,rfs-ohms", + data->rfs_ohms, + indio_dev->num_channels); + if (ret) + return dev_err_probe(dev, ret, "Failed to read maxim,rfs-ohms property\n"); + + for (unsigned int i = 0; i < indio_dev->num_channels; i++) { + if (!data->rfs_ohms[i]) + return dev_err_probe(dev, -EINVAL, "maxim,rfs-ohms entry %u is zero\n", i); + } + + data->has_rfs = true; + + return 0; } static int ds4424_suspend(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ds4424_data *data = iio_priv(indio_dev); - int ret = 0; - int i; + u8 zero_buf[DS4424_MAX_DAC_CHANNELS] = { }; + int ret; - for (i = 0; i < indio_dev->num_channels; i++) { - data->save[i] = data->raw[i]; - ret = ds4424_set_value(indio_dev, 0, - &indio_dev->channels[i]); - if (ret < 0) - return ret; + /* Disable all outputs, bypass cache so the '0' isn't saved */ + regcache_cache_bypass(data->regmap, true); + ret = regmap_bulk_write(data->regmap, DS4424_DAC_ADDR(0), + zero_buf, indio_dev->num_channels); + regcache_cache_bypass(data->regmap, false); + if (ret) { + dev_err(dev, "Failed to zero outputs: %pe\n", ERR_PTR(ret)); + return ret; } - return ret; + + regcache_cache_only(data->regmap, true); + regcache_mark_dirty(data->regmap); + + return 0; } static int ds4424_resume(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ds4424_data *data = iio_priv(indio_dev); - int ret = 0; - int i; - for (i = 0; i < indio_dev->num_channels; i++) { - ret = ds4424_set_value(indio_dev, data->save[i], - &indio_dev->channels[i]); - if (ret < 0) - return ret; - } - return ret; + regcache_cache_only(data->regmap, false); + return regcache_sync(data->regmap); } static DEFINE_SIMPLE_DEV_PM_OPS(ds4424_pm_ops, ds4424_suspend, ds4424_resume); -static const struct iio_info ds4424_info = { +static const struct iio_info ds4424_iio_info = { .read_raw = ds4424_read_raw, .write_raw = ds4424_write_raw, }; static int ds4424_probe(struct i2c_client *client) { - const struct i2c_device_id *id = i2c_client_get_device_id(client); + const struct ds4424_chip_info *chip_info; struct ds4424_data *data; struct iio_dev *indio_dev; int ret; + chip_info = i2c_get_match_data(client); + if (!chip_info) + return -ENODEV; + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); - data->client = client; - indio_dev->name = id->name; + indio_dev->name = chip_info->name; + data->chip_info = chip_info; data->vcc_reg = devm_regulator_get(&client->dev, "vcc"); if (IS_ERR(data->vcc_reg)) return dev_err_probe(&client->dev, PTR_ERR(data->vcc_reg), "Failed to get vcc-supply regulator.\n"); - mutex_init(&data->lock); ret = regulator_enable(data->vcc_reg); if (ret < 0) { dev_err(&client->dev, @@ -241,28 +353,29 @@ static int ds4424_probe(struct i2c_client *client) return ret; } - usleep_range(1000, 1200); - ret = ds4424_verify_chip(indio_dev); - if (ret < 0) - goto fail; + /* + * The datasheet does not specify a power-up to I2C ready time. + * Maintain the existing conservative 1ms delay to ensure the + * device is ready for communication. + */ + fsleep(1 * USEC_PER_MSEC); - switch (id->driver_data) { - case ID_DS4422: - indio_dev->num_channels = DS4422_MAX_DAC_CHANNELS; - break; - case ID_DS4424: - indio_dev->num_channels = DS4424_MAX_DAC_CHANNELS; - break; - default: - dev_err(&client->dev, - "ds4424: Invalid chip id.\n"); - ret = -ENXIO; - goto fail; - } - - indio_dev->channels = ds4424_channels; + indio_dev->num_channels = chip_info->num_channels; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->info = &ds4424_info; + indio_dev->info = &ds4424_iio_info; + + ret = ds4424_init_regmap(client, indio_dev); + if (ret) + goto fail; + + ret = ds4424_parse_rfs(client, data, indio_dev); + if (ret) + goto fail; + + if (data->has_rfs) + indio_dev->channels = ds4424_channels_with_scale; + else + indio_dev->channels = ds4424_channels; ret = iio_device_register(indio_dev); if (ret < 0) { @@ -288,16 +401,20 @@ static void ds4424_remove(struct i2c_client *client) } static const struct i2c_device_id ds4424_id[] = { - { "ds4422", ID_DS4422 }, - { "ds4424", ID_DS4424 }, + { "ds4402", (kernel_ulong_t)&ds4402_info }, + { "ds4404", (kernel_ulong_t)&ds4404_info }, + { "ds4422", (kernel_ulong_t)&ds4422_info }, + { "ds4424", (kernel_ulong_t)&ds4424_info }, { } }; MODULE_DEVICE_TABLE(i2c, ds4424_id); static const struct of_device_id ds4424_of_match[] = { - { .compatible = "maxim,ds4422" }, - { .compatible = "maxim,ds4424" }, + { .compatible = "maxim,ds4402", .data = &ds4402_info }, + { .compatible = "maxim,ds4404", .data = &ds4404_info }, + { .compatible = "maxim,ds4422", .data = &ds4422_info }, + { .compatible = "maxim,ds4424", .data = &ds4424_info }, { } }; diff --git a/drivers/iio/dac/ltc2632.c b/drivers/iio/dac/ltc2632.c index 105f939f7e54..d6a3d290e7a8 100644 --- a/drivers/iio/dac/ltc2632.c +++ b/drivers/iio/dac/ltc2632.c @@ -48,27 +48,6 @@ struct ltc2632_state { int vref_mv; }; -enum ltc2632_supported_device_ids { - ID_LTC2632L12, - ID_LTC2632L10, - ID_LTC2632L8, - ID_LTC2632H12, - ID_LTC2632H10, - ID_LTC2632H8, - ID_LTC2634L12, - ID_LTC2634L10, - ID_LTC2634L8, - ID_LTC2634H12, - ID_LTC2634H10, - ID_LTC2634H8, - ID_LTC2636L12, - ID_LTC2636L10, - ID_LTC2636L8, - ID_LTC2636H12, - ID_LTC2636H10, - ID_LTC2636H8, -}; - static int ltc2632_spi_write(struct spi_device *spi, u8 cmd, u8 addr, u16 val, u8 shift) { @@ -79,8 +58,9 @@ static int ltc2632_spi_write(struct spi_device *spi, * The input shift register is 24 bits wide. * The next four are the command bits, C3 to C0, * followed by the 4-bit DAC address, A3 to A0, and then the - * 12-, 10-, 8-bit data-word. The data-word comprises the 12-, - * 10-, 8-bit input code followed by 4, 6, or 8 don't care bits. + * 16-, 12-, 10-, 8-bit data-word. The data-word comprises the + * 16-, 12-, 10-, 8-bit input code followed by 0, 4, 6, or 8 + * don't care bits. */ data = (cmd << 20) | (addr << 16) | (val << shift); put_unaligned_be24(data, &msg[0]); @@ -206,101 +186,129 @@ static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = { LTC2632_CHANNEL(7, _bits), \ } +static DECLARE_LTC2632_CHANNELS(ltc2632x16, 16); static DECLARE_LTC2632_CHANNELS(ltc2632x12, 12); static DECLARE_LTC2632_CHANNELS(ltc2632x10, 10); static DECLARE_LTC2632_CHANNELS(ltc2632x8, 8); -static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = { - [ID_LTC2632L12] = { - .channels = ltc2632x12_channels, - .num_channels = 2, - .vref_mv = 2500, - }, - [ID_LTC2632L10] = { - .channels = ltc2632x10_channels, - .num_channels = 2, - .vref_mv = 2500, - }, - [ID_LTC2632L8] = { - .channels = ltc2632x8_channels, - .num_channels = 2, - .vref_mv = 2500, - }, - [ID_LTC2632H12] = { - .channels = ltc2632x12_channels, - .num_channels = 2, - .vref_mv = 4096, - }, - [ID_LTC2632H10] = { - .channels = ltc2632x10_channels, - .num_channels = 2, - .vref_mv = 4096, - }, - [ID_LTC2632H8] = { - .channels = ltc2632x8_channels, - .num_channels = 2, - .vref_mv = 4096, - }, - [ID_LTC2634L12] = { - .channels = ltc2632x12_channels, - .num_channels = 4, - .vref_mv = 2500, - }, - [ID_LTC2634L10] = { - .channels = ltc2632x10_channels, - .num_channels = 4, - .vref_mv = 2500, - }, - [ID_LTC2634L8] = { - .channels = ltc2632x8_channels, - .num_channels = 4, - .vref_mv = 2500, - }, - [ID_LTC2634H12] = { - .channels = ltc2632x12_channels, - .num_channels = 4, - .vref_mv = 4096, - }, - [ID_LTC2634H10] = { - .channels = ltc2632x10_channels, - .num_channels = 4, - .vref_mv = 4096, - }, - [ID_LTC2634H8] = { - .channels = ltc2632x8_channels, - .num_channels = 4, - .vref_mv = 4096, - }, - [ID_LTC2636L12] = { - .channels = ltc2632x12_channels, - .num_channels = 8, - .vref_mv = 2500, - }, - [ID_LTC2636L10] = { - .channels = ltc2632x10_channels, - .num_channels = 8, - .vref_mv = 2500, - }, - [ID_LTC2636L8] = { - .channels = ltc2632x8_channels, - .num_channels = 8, - .vref_mv = 2500, - }, - [ID_LTC2636H12] = { - .channels = ltc2632x12_channels, - .num_channels = 8, - .vref_mv = 4096, - }, - [ID_LTC2636H10] = { - .channels = ltc2632x10_channels, - .num_channels = 8, - .vref_mv = 4096, - }, - [ID_LTC2636H8] = { - .channels = ltc2632x8_channels, - .num_channels = 8, - .vref_mv = 4096, - }, +static const struct ltc2632_chip_info ltc2632l12_chip_info = { + .channels = ltc2632x12_channels, + .num_channels = 2, + .vref_mv = 2500, +}; + +static const struct ltc2632_chip_info ltc2632l10_chip_info = { + .channels = ltc2632x10_channels, + .num_channels = 2, + .vref_mv = 2500, +}; + +static const struct ltc2632_chip_info ltc2632l8_chip_info = { + .channels = ltc2632x8_channels, + .num_channels = 2, + .vref_mv = 2500, +}; + +static const struct ltc2632_chip_info ltc2632h12_chip_info = { + .channels = ltc2632x12_channels, + .num_channels = 2, + .vref_mv = 4096, +}; + +static const struct ltc2632_chip_info ltc2632h10_chip_info = { + .channels = ltc2632x10_channels, + .num_channels = 2, + .vref_mv = 4096, +}; + +static const struct ltc2632_chip_info ltc2632h8_chip_info = { + .channels = ltc2632x8_channels, + .num_channels = 2, + .vref_mv = 4096, +}; + +static const struct ltc2632_chip_info ltc2634l12_chip_info = { + .channels = ltc2632x12_channels, + .num_channels = 4, + .vref_mv = 2500, +}; + +static const struct ltc2632_chip_info ltc2634l10_chip_info = { + .channels = ltc2632x10_channels, + .num_channels = 4, + .vref_mv = 2500, +}; + +static const struct ltc2632_chip_info ltc2634l8_chip_info = { + .channels = ltc2632x8_channels, + .num_channels = 4, + .vref_mv = 2500, +}; + +static const struct ltc2632_chip_info ltc2634h12_chip_info = { + .channels = ltc2632x12_channels, + .num_channels = 4, + .vref_mv = 4096, +}; + +static const struct ltc2632_chip_info ltc2634h10_chip_info = { + .channels = ltc2632x10_channels, + .num_channels = 4, + .vref_mv = 4096, +}; + +static const struct ltc2632_chip_info ltc2634h8_chip_info = { + .channels = ltc2632x8_channels, + .num_channels = 4, + .vref_mv = 4096, +}; + +static const struct ltc2632_chip_info ltc2636l12_chip_info = { + .channels = ltc2632x12_channels, + .num_channels = 8, + .vref_mv = 2500, +}; + +static const struct ltc2632_chip_info ltc2636l10_chip_info = { + .channels = ltc2632x10_channels, + .num_channels = 8, + .vref_mv = 2500, +}; + +static const struct ltc2632_chip_info ltc2636l8_chip_info = { + .channels = ltc2632x8_channels, + .num_channels = 8, + .vref_mv = 2500, +}; + +static const struct ltc2632_chip_info ltc2636h12_chip_info = { + .channels = ltc2632x12_channels, + .num_channels = 8, + .vref_mv = 4096, +}; + +static const struct ltc2632_chip_info ltc2636h10_chip_info = { + .channels = ltc2632x10_channels, + .num_channels = 8, + .vref_mv = 4096, +}; + +static const struct ltc2632_chip_info ltc2636h8_chip_info = { + .channels = ltc2632x8_channels, + .num_channels = 8, + .vref_mv = 4096, +}; + +static const struct ltc2632_chip_info ltc2654l16_chip_info = { + .channels = ltc2632x16_channels, + .num_channels = 4, + .vref_mv = 2500, +}; + +static const struct ltc2632_chip_info ltc2654h16_chip_info = { + .channels = ltc2632x16_channels, + .num_channels = 4, + .vref_mv = 4096, }; static int ltc2632_probe(struct spi_device *spi) @@ -354,84 +362,53 @@ static int ltc2632_probe(struct spi_device *spi) } static const struct spi_device_id ltc2632_id[] = { - { "ltc2632-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L12] }, - { "ltc2632-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L10] }, - { "ltc2632-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632L8] }, - { "ltc2632-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H12] }, - { "ltc2632-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H10] }, - { "ltc2632-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2632H8] }, - { "ltc2634-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L12] }, - { "ltc2634-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L10] }, - { "ltc2634-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634L8] }, - { "ltc2634-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H12] }, - { "ltc2634-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H10] }, - { "ltc2634-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2634H8] }, - { "ltc2636-l12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L12] }, - { "ltc2636-l10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L10] }, - { "ltc2636-l8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636L8] }, - { "ltc2636-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H12] }, - { "ltc2636-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H10] }, - { "ltc2636-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H8] }, + { "ltc2632-l12", (kernel_ulong_t)<c2632l12_chip_info }, + { "ltc2632-l10", (kernel_ulong_t)<c2632l10_chip_info }, + { "ltc2632-l8", (kernel_ulong_t)<c2632l8_chip_info }, + { "ltc2632-h12", (kernel_ulong_t)<c2632h12_chip_info }, + { "ltc2632-h10", (kernel_ulong_t)<c2632h10_chip_info }, + { "ltc2632-h8", (kernel_ulong_t)<c2632h8_chip_info }, + { "ltc2634-l12", (kernel_ulong_t)<c2634l12_chip_info }, + { "ltc2634-l10", (kernel_ulong_t)<c2634l10_chip_info }, + { "ltc2634-l8", (kernel_ulong_t)<c2634l8_chip_info }, + { "ltc2634-h12", (kernel_ulong_t)<c2634h12_chip_info }, + { "ltc2634-h10", (kernel_ulong_t)<c2634h10_chip_info }, + { "ltc2634-h8", (kernel_ulong_t)<c2634h8_chip_info }, + { "ltc2636-l12", (kernel_ulong_t)<c2636l12_chip_info }, + { "ltc2636-l10", (kernel_ulong_t)<c2636l10_chip_info }, + { "ltc2636-l8", (kernel_ulong_t)<c2636l8_chip_info }, + { "ltc2636-h12", (kernel_ulong_t)<c2636h12_chip_info }, + { "ltc2636-h10", (kernel_ulong_t)<c2636h10_chip_info }, + { "ltc2636-h8", (kernel_ulong_t)<c2636h8_chip_info }, + { "ltc2654-l16", (kernel_ulong_t)<c2654l16_chip_info }, + { "ltc2654-l12", (kernel_ulong_t)<c2634l12_chip_info }, + { "ltc2654-h16", (kernel_ulong_t)<c2654h16_chip_info }, + { "ltc2654-h12", (kernel_ulong_t)<c2634h12_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, ltc2632_id); static const struct of_device_id ltc2632_of_match[] = { - { - .compatible = "lltc,ltc2632-l12", - .data = <c2632_chip_info_tbl[ID_LTC2632L12] - }, { - .compatible = "lltc,ltc2632-l10", - .data = <c2632_chip_info_tbl[ID_LTC2632L10] - }, { - .compatible = "lltc,ltc2632-l8", - .data = <c2632_chip_info_tbl[ID_LTC2632L8] - }, { - .compatible = "lltc,ltc2632-h12", - .data = <c2632_chip_info_tbl[ID_LTC2632H12] - }, { - .compatible = "lltc,ltc2632-h10", - .data = <c2632_chip_info_tbl[ID_LTC2632H10] - }, { - .compatible = "lltc,ltc2632-h8", - .data = <c2632_chip_info_tbl[ID_LTC2632H8] - }, { - .compatible = "lltc,ltc2634-l12", - .data = <c2632_chip_info_tbl[ID_LTC2634L12] - }, { - .compatible = "lltc,ltc2634-l10", - .data = <c2632_chip_info_tbl[ID_LTC2634L10] - }, { - .compatible = "lltc,ltc2634-l8", - .data = <c2632_chip_info_tbl[ID_LTC2634L8] - }, { - .compatible = "lltc,ltc2634-h12", - .data = <c2632_chip_info_tbl[ID_LTC2634H12] - }, { - .compatible = "lltc,ltc2634-h10", - .data = <c2632_chip_info_tbl[ID_LTC2634H10] - }, { - .compatible = "lltc,ltc2634-h8", - .data = <c2632_chip_info_tbl[ID_LTC2634H8] - }, { - .compatible = "lltc,ltc2636-l12", - .data = <c2632_chip_info_tbl[ID_LTC2636L12] - }, { - .compatible = "lltc,ltc2636-l10", - .data = <c2632_chip_info_tbl[ID_LTC2636L10] - }, { - .compatible = "lltc,ltc2636-l8", - .data = <c2632_chip_info_tbl[ID_LTC2636L8] - }, { - .compatible = "lltc,ltc2636-h12", - .data = <c2632_chip_info_tbl[ID_LTC2636H12] - }, { - .compatible = "lltc,ltc2636-h10", - .data = <c2632_chip_info_tbl[ID_LTC2636H10] - }, { - .compatible = "lltc,ltc2636-h8", - .data = <c2632_chip_info_tbl[ID_LTC2636H8] - }, + { .compatible = "lltc,ltc2632-l12", .data = <c2632l12_chip_info }, + { .compatible = "lltc,ltc2632-l10", .data = <c2632l10_chip_info }, + { .compatible = "lltc,ltc2632-l8", .data = <c2632l8_chip_info }, + { .compatible = "lltc,ltc2632-h12", .data = <c2632h12_chip_info }, + { .compatible = "lltc,ltc2632-h10", .data = <c2632h10_chip_info }, + { .compatible = "lltc,ltc2632-h8", .data = <c2632h8_chip_info }, + { .compatible = "lltc,ltc2634-l12", .data = <c2634l12_chip_info }, + { .compatible = "lltc,ltc2634-l10", .data = <c2634l10_chip_info }, + { .compatible = "lltc,ltc2634-l8", .data = <c2634l8_chip_info }, + { .compatible = "lltc,ltc2634-h12", .data = <c2634h12_chip_info }, + { .compatible = "lltc,ltc2634-h10", .data = <c2634h10_chip_info }, + { .compatible = "lltc,ltc2634-h8", .data = <c2634h8_chip_info }, + { .compatible = "lltc,ltc2636-l12", .data = <c2636l12_chip_info }, + { .compatible = "lltc,ltc2636-l10", .data = <c2636l10_chip_info }, + { .compatible = "lltc,ltc2636-l8", .data = <c2636l8_chip_info }, + { .compatible = "lltc,ltc2636-h12", .data = <c2636h12_chip_info }, + { .compatible = "lltc,ltc2636-h10", .data = <c2636h10_chip_info }, + { .compatible = "lltc,ltc2636-h8", .data = <c2636h8_chip_info }, + { .compatible = "lltc,ltc2654-l16", .data = <c2654l16_chip_info }, + { .compatible = "lltc,ltc2654-h16", .data = <c2654h16_chip_info }, { } }; MODULE_DEVICE_TABLE(of, ltc2632_of_match); @@ -447,5 +424,5 @@ static struct spi_driver ltc2632_driver = { module_spi_driver(ltc2632_driver); MODULE_AUTHOR("Maxime Roussin-Belanger "); -MODULE_DESCRIPTION("LTC2632 DAC SPI driver"); +MODULE_DESCRIPTION("LTC2632 and similar DAC SPI driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/dac/max5522.c b/drivers/iio/dac/max5522.c index 1b8fe6b8d26e..b52a9cc1da79 100644 --- a/drivers/iio/dac/max5522.c +++ b/drivers/iio/dac/max5522.c @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -34,7 +35,7 @@ struct max5522_state { struct regmap *regmap; const struct max5522_chip_info *chip_info; unsigned short dac_cache[2]; - struct regulator *vrefin_reg; + int vref_mV; }; #define MAX5522_CHANNEL(chan) { \ @@ -79,17 +80,13 @@ static int max5522_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long info) { struct max5522_state *state = iio_priv(indio_dev); - int ret; switch (info) { case IIO_CHAN_INFO_RAW: *val = state->dac_cache[chan->channel]; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - ret = regulator_get_voltage(state->vrefin_reg); - if (ret < 0) - return -EINVAL; - *val = ret / 1000; + *val = state->vref_mV; *val2 = 10; return IIO_VAL_FRACTIONAL_LOG2; default: @@ -147,16 +144,11 @@ static int max5522_spi_probe(struct spi_device *spi) if (!state->chip_info) return -EINVAL; - state->vrefin_reg = devm_regulator_get(&spi->dev, "vrefin"); - if (IS_ERR(state->vrefin_reg)) - return dev_err_probe(&spi->dev, PTR_ERR(state->vrefin_reg), - "Vrefin regulator not specified\n"); - - ret = regulator_enable(state->vrefin_reg); - if (ret) { + ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vrefin"); + if (ret < 0) return dev_err_probe(&spi->dev, ret, - "Failed to enable vref regulators\n"); - } + "Failed to get vrefin regulator\n"); + state->vref_mV = ret / (MICRO / MILLI); state->regmap = devm_regmap_init_spi(spi, &max5522_regmap_config); diff --git a/drivers/iio/dac/ti-dac5571.c b/drivers/iio/dac/ti-dac5571.c index bdc3f94aef98..455d61fc3f13 100644 --- a/drivers/iio/dac/ti-dac5571.c +++ b/drivers/iio/dac/ti-dac5571.c @@ -45,7 +45,6 @@ static const struct dac5571_spec dac5571_spec[] = { struct dac5571_data { struct i2c_client *client; - int id; struct mutex lock; struct regulator *vref; u16 val[4]; diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c index 19f823446cda..a4984b867248 100644 --- a/drivers/iio/filter/admv8818.c +++ b/drivers/iio/filter/admv8818.c @@ -657,56 +657,49 @@ static void admv8818_clk_disable(void *data) static int admv8818_init(struct admv8818_state *st) { int ret; - struct spi_device *spi = st->spi; + struct device *dev = &st->spi->dev; unsigned int chip_id; ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A, ADMV8818_SOFTRESET_N_MSK | ADMV8818_SOFTRESET_MSK); - if (ret) { - dev_err(&spi->dev, "ADMV8818 Soft Reset failed.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "ADMV8818 Soft Reset failed.\n"); ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A, ADMV8818_SDOACTIVE_N_MSK | ADMV8818_SDOACTIVE_MSK); - if (ret) { - dev_err(&spi->dev, "ADMV8818 SDO Enable failed.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "ADMV8818 SDO Enable failed.\n"); 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 (ret) + return dev_err_probe(dev, ret, + "ADMV8818 Chip ID read failed.\n"); - if (chip_id != 0x1) { - dev_err(&spi->dev, "ADMV8818 Invalid Chip ID.\n"); - return -EINVAL; - } + if (chip_id != 0x1) + return dev_err_probe(dev, -EINVAL, + "ADMV8818 Invalid Chip ID.\n"); 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 (ret) + return dev_err_probe(dev, ret, + "ADMV8818 Single Instruction failed.\n"); if (st->clkin) return admv8818_rfin_band_select(st); - else - return 0; + + return 0; } static int admv8818_clk_setup(struct admv8818_state *st) { - struct spi_device *spi = st->spi; + struct device *dev = &st->spi->dev; int ret; - st->clkin = devm_clk_get_optional(&spi->dev, "rf_in"); + st->clkin = devm_clk_get_optional(dev, "rf_in"); if (IS_ERR(st->clkin)) - return dev_err_probe(&spi->dev, PTR_ERR(st->clkin), + return dev_err_probe(dev, PTR_ERR(st->clkin), "failed to get the input clock\n"); else if (!st->clkin) return 0; @@ -715,7 +708,7 @@ static int admv8818_clk_setup(struct admv8818_state *st) if (ret) return ret; - ret = devm_add_action_or_reset(&spi->dev, admv8818_clk_disable, st); + ret = devm_add_action_or_reset(dev, admv8818_clk_disable, st); if (ret) return ret; @@ -724,16 +717,16 @@ static int admv8818_clk_setup(struct admv8818_state *st) if (ret < 0) return ret; - return devm_add_action_or_reset(&spi->dev, admv8818_clk_notifier_unreg, st); + return devm_add_action_or_reset(dev, admv8818_clk_notifier_unreg, st); } static int admv8818_read_properties(struct admv8818_state *st) { - struct spi_device *spi = st->spi; + struct device *dev = &st->spi->dev; u32 mhz; int ret; - ret = device_property_read_u32(&spi->dev, "adi,lpf-margin-mhz", &mhz); + ret = device_property_read_u32(dev, "adi,lpf-margin-mhz", &mhz); if (ret == 0) st->lpf_margin_hz = (u64)mhz * HZ_PER_MHZ; else if (ret == -EINVAL) @@ -742,7 +735,7 @@ static int admv8818_read_properties(struct admv8818_state *st) return ret; - ret = device_property_read_u32(&spi->dev, "adi,hpf-margin-mhz", &mhz); + ret = device_property_read_u32(dev, "adi,hpf-margin-mhz", &mhz); if (ret == 0) st->hpf_margin_hz = (u64)mhz * HZ_PER_MHZ; else if (ret == -EINVAL) @@ -758,9 +751,10 @@ static int admv8818_probe(struct spi_device *spi) struct iio_dev *indio_dev; struct regmap *regmap; struct admv8818_state *st; + struct device *dev = &spi->dev; int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -792,7 +786,7 @@ static int admv8818_probe(struct spi_device *spi) if (ret) return ret; - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id admv8818_id[] = { diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c index 63c485e9e44c..ea4d2763564a 100644 --- a/drivers/iio/frequency/ad9523.c +++ b/drivers/iio/frequency/ad9523.c @@ -167,9 +167,9 @@ /* AD9523_CHANNEL_CLOCK_DIST */ #define AD9523_CLK_DIST_DIV_PHASE(x) (((x) & 0x3F) << 18) -#define AD9523_CLK_DIST_DIV_PHASE_REV(x) ((ret >> 18) & 0x3F) +#define AD9523_CLK_DIST_DIV_PHASE_REV(x) (((x) >> 18) & 0x3F) #define AD9523_CLK_DIST_DIV(x) ((((x) - 1) & 0x3FF) << 8) -#define AD9523_CLK_DIST_DIV_REV(x) (((ret >> 8) & 0x3FF) + 1) +#define AD9523_CLK_DIST_DIV_REV(x) ((((x) >> 8) & 0x3FF) + 1) #define AD9523_CLK_DIST_INV_DIV_OUTPUT_EN (1 << 7) #define AD9523_CLK_DIST_IGNORE_SYNC_EN (1 << 6) #define AD9523_CLK_DIST_PWR_DOWN_EN (1 << 5) @@ -558,55 +558,35 @@ static ssize_t ad9523_show(struct device *dev, return ret; } -static IIO_DEVICE_ATTR(pll1_locked, S_IRUGO, - ad9523_show, - NULL, - AD9523_STAT_PLL1_LD); +static IIO_DEVICE_ATTR(pll1_locked, 0444, ad9523_show, NULL, + AD9523_STAT_PLL1_LD); -static IIO_DEVICE_ATTR(pll2_locked, S_IRUGO, - ad9523_show, - NULL, - AD9523_STAT_PLL2_LD); +static IIO_DEVICE_ATTR(pll2_locked, 0444, ad9523_show, NULL, + AD9523_STAT_PLL2_LD); -static IIO_DEVICE_ATTR(pll1_reference_clk_a_present, S_IRUGO, - ad9523_show, - NULL, - AD9523_STAT_REFA); +static IIO_DEVICE_ATTR(pll1_reference_clk_a_present, 0444, ad9523_show, NULL, + AD9523_STAT_REFA); -static IIO_DEVICE_ATTR(pll1_reference_clk_b_present, S_IRUGO, - ad9523_show, - NULL, - AD9523_STAT_REFB); +static IIO_DEVICE_ATTR(pll1_reference_clk_b_present, 0444, ad9523_show, NULL, + AD9523_STAT_REFB); -static IIO_DEVICE_ATTR(pll1_reference_clk_test_present, S_IRUGO, - ad9523_show, - NULL, - AD9523_STAT_REF_TEST); +static IIO_DEVICE_ATTR(pll1_reference_clk_test_present, 0444, ad9523_show, NULL, + AD9523_STAT_REF_TEST); -static IIO_DEVICE_ATTR(vcxo_clk_present, S_IRUGO, - ad9523_show, - NULL, - AD9523_STAT_VCXO); +static IIO_DEVICE_ATTR(vcxo_clk_present, 0444, ad9523_show, NULL, + AD9523_STAT_VCXO); -static IIO_DEVICE_ATTR(pll2_feedback_clk_present, S_IRUGO, - ad9523_show, - NULL, - AD9523_STAT_PLL2_FB_CLK); +static IIO_DEVICE_ATTR(pll2_feedback_clk_present, 0444, ad9523_show, NULL, + AD9523_STAT_PLL2_FB_CLK); -static IIO_DEVICE_ATTR(pll2_reference_clk_present, S_IRUGO, - ad9523_show, - NULL, - AD9523_STAT_PLL2_REF_CLK); +static IIO_DEVICE_ATTR(pll2_reference_clk_present, 0444, ad9523_show, NULL, + AD9523_STAT_PLL2_REF_CLK); -static IIO_DEVICE_ATTR(sync_dividers, S_IWUSR, - NULL, - ad9523_store, - AD9523_SYNC); +static IIO_DEVICE_ATTR(sync_dividers, 0200, NULL, ad9523_store, + AD9523_SYNC); -static IIO_DEVICE_ATTR(store_eeprom, S_IWUSR, - NULL, - ad9523_store, - AD9523_EEPROM); +static IIO_DEVICE_ATTR(store_eeprom, 0200, NULL, ad9523_store, + AD9523_EEPROM); static struct attribute *ad9523_attributes[] = { &iio_dev_attr_sync_dividers.dev_attr.attr, @@ -797,8 +777,7 @@ static int ad9523_setup(struct iio_dev *indio_dev) return ret; ret = ad9523_write(indio_dev, AD9523_PLL1_CHARGE_PUMP_CTRL, - AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(pdata-> - pll1_charge_pump_current_nA) | + AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(pdata->pll1_charge_pump_current_nA) | AD9523_PLL1_CHARGE_PUMP_MODE_NORMAL | AD9523_PLL1_BACKLASH_PW_MIN); if (ret < 0) @@ -842,8 +821,7 @@ static int ad9523_setup(struct iio_dev *indio_dev) */ ret = ad9523_write(indio_dev, AD9523_PLL2_CHARGE_PUMP, - AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(pdata-> - pll2_charge_pump_current_nA)); + AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(pdata->pll2_charge_pump_current_nA)); if (ret < 0) return ret; @@ -970,17 +948,17 @@ static int ad9523_setup(struct iio_dev *indio_dev) static int ad9523_probe(struct spi_device *spi) { - struct ad9523_platform_data *pdata = dev_get_platdata(&spi->dev); + struct device *dev = &spi->dev; + struct ad9523_platform_data *pdata; struct iio_dev *indio_dev; struct ad9523_state *st; int ret; - if (!pdata) { - dev_err(&spi->dev, "no platform data?\n"); - return -EINVAL; - } + pdata = dev_get_platdata(dev); + if (!pdata) + return dev_err_probe(dev, -EINVAL, "no platform data?\n"); - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (indio_dev == NULL) return -ENOMEM; @@ -988,16 +966,16 @@ static int ad9523_probe(struct spi_device *spi) mutex_init(&st->lock); - ret = devm_regulator_get_enable(&spi->dev, "vcc"); + ret = devm_regulator_get_enable(dev, "vcc"); if (ret) return ret; - st->pwrdown_gpio = devm_gpiod_get_optional(&spi->dev, "powerdown", + st->pwrdown_gpio = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); if (IS_ERR(st->pwrdown_gpio)) return PTR_ERR(st->pwrdown_gpio); - st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", + st->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(st->reset_gpio)) return PTR_ERR(st->reset_gpio); @@ -1007,7 +985,7 @@ static int ad9523_probe(struct spi_device *spi) gpiod_direction_output(st->reset_gpio, 1); } - st->sync_gpio = devm_gpiod_get_optional(&spi->dev, "sync", + st->sync_gpio = devm_gpiod_get_optional(dev, "sync", GPIOD_OUT_HIGH); if (IS_ERR(st->sync_gpio)) return PTR_ERR(st->sync_gpio); @@ -1027,7 +1005,7 @@ static int ad9523_probe(struct spi_device *spi) if (ret < 0) return ret; - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id ad9523_id[] = { diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index ed1741165f55..6bbb6a8dd9d0 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -152,10 +152,10 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) st->r4_rf_div_sel = 0; /* - * !\TODO: The below computation is making sure we get a power of 2 - * shift (st->r4_rf_div_sel) so that freq becomes higher or equal to - * ADF4350_MIN_VCO_FREQ. This might be simplified with fls()/fls_long() - * and friends. + * NOTE: This iteratively shifts freq by a power of 2 + * (st->r4_rf_div_sel) to meet or exceed ADF4350_MIN_VCO_FREQ. + * A constant-time approach using fls_long() was attempted but + * deemed more complex without meaningful benefit for init code. */ while (freq < ADF4350_MIN_VCO_FREQ) { freq <<= 1; @@ -607,7 +607,7 @@ static int adf4350_probe(struct spi_device *spi) if (dev_fwnode(&spi->dev)) { pdata = adf4350_parse_dt(&spi->dev); if (pdata == NULL) - return -EINVAL; + return -ENOMEM; } else { pdata = dev_get_platdata(&spi->dev); } diff --git a/drivers/iio/frequency/adf4377.c b/drivers/iio/frequency/adf4377.c index 8e2da218d48a..ff6077e29c73 100644 --- a/drivers/iio/frequency/adf4377.c +++ b/drivers/iio/frequency/adf4377.c @@ -706,23 +706,20 @@ static void adf4377_gpio_init(struct adf4377_state *st) static int adf4377_init(struct adf4377_state *st) { - struct spi_device *spi = st->spi; + struct device *dev = &st->spi->dev; int ret; adf4377_gpio_init(st); ret = adf4377_soft_reset(st); - if (ret) { - dev_err(&spi->dev, "Failed to soft reset.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to soft reset.\n"); ret = regmap_multi_reg_write(st->regmap, adf4377_reg_defaults, ARRAY_SIZE(adf4377_reg_defaults)); - if (ret) { - dev_err(&spi->dev, "Failed to set default registers.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "Failed to set default registers.\n"); ret = regmap_update_bits(st->regmap, 0x00, ADF4377_0000_SDO_ACTIVE_MSK | ADF4377_0000_SDO_ACTIVE_R_MSK, @@ -730,10 +727,9 @@ static int adf4377_init(struct adf4377_state *st) ADF4377_0000_SDO_ACTIVE_SPI_4W) | FIELD_PREP(ADF4377_0000_SDO_ACTIVE_R_MSK, ADF4377_0000_SDO_ACTIVE_SPI_4W)); - if (ret) { - dev_err(&spi->dev, "Failed to set 4-Wire Operation.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "Failed to set 4-Wire Operation.\n"); st->clkin_freq = clk_get_rate(st->clkin); @@ -747,10 +743,9 @@ static int adf4377_init(struct adf4377_state *st) FIELD_PREP(ADF4377_001A_PD_PFDCP_MSK, 0) | FIELD_PREP(ADF4377_001A_PD_CLKOUT1_MSK, 0) | FIELD_PREP(ADF4377_001A_PD_CLKOUT2_MSK, 0)); - if (ret) { - dev_err(&spi->dev, "Failed to set power down registers.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "Failed to set power down registers.\n"); /* Set Mux Output */ ret = regmap_update_bits(st->regmap, 0x1D, @@ -882,35 +877,35 @@ static const struct iio_chan_spec adf4377_channels[] = { static int adf4377_properties_parse(struct adf4377_state *st) { - struct spi_device *spi = st->spi; + struct device *dev = &st->spi->dev; int ret; - st->clkin = devm_clk_get_enabled(&spi->dev, "ref_in"); + st->clkin = devm_clk_get_enabled(dev, "ref_in"); if (IS_ERR(st->clkin)) - return dev_err_probe(&spi->dev, PTR_ERR(st->clkin), + return dev_err_probe(dev, PTR_ERR(st->clkin), "failed to get the reference input clock\n"); - st->gpio_ce = devm_gpiod_get_optional(&st->spi->dev, "chip-enable", + st->gpio_ce = devm_gpiod_get_optional(dev, "chip-enable", GPIOD_OUT_LOW); if (IS_ERR(st->gpio_ce)) - return dev_err_probe(&spi->dev, PTR_ERR(st->gpio_ce), + return dev_err_probe(dev, PTR_ERR(st->gpio_ce), "failed to get the CE GPIO\n"); - st->gpio_enclk1 = devm_gpiod_get_optional(&st->spi->dev, "clk1-enable", + st->gpio_enclk1 = devm_gpiod_get_optional(dev, "clk1-enable", GPIOD_OUT_LOW); if (IS_ERR(st->gpio_enclk1)) - return dev_err_probe(&spi->dev, PTR_ERR(st->gpio_enclk1), + return dev_err_probe(dev, PTR_ERR(st->gpio_enclk1), "failed to get the CE GPIO\n"); if (st->chip_info->has_gpio_enclk2) { - st->gpio_enclk2 = devm_gpiod_get_optional(&st->spi->dev, "clk2-enable", + st->gpio_enclk2 = devm_gpiod_get_optional(dev, "clk2-enable", GPIOD_OUT_LOW); if (IS_ERR(st->gpio_enclk2)) - return dev_err_probe(&spi->dev, PTR_ERR(st->gpio_enclk2), + return dev_err_probe(dev, PTR_ERR(st->gpio_enclk2), "failed to get the CE GPIO\n"); } - ret = device_property_match_property_string(&spi->dev, "adi,muxout-select", + ret = device_property_match_property_string(dev, "adi,muxout-select", adf4377_muxout_modes, ARRAY_SIZE(adf4377_muxout_modes)); if (ret >= 0) @@ -1055,9 +1050,10 @@ static int adf4377_probe(struct spi_device *spi) struct iio_dev *indio_dev; struct regmap *regmap; struct adf4377_state *st; + struct device *dev = &spi->dev; int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -1080,7 +1076,7 @@ static int adf4377_probe(struct spi_device *spi) return ret; st->nb.notifier_call = adf4377_freq_change; - ret = devm_clk_notifier_register(&spi->dev, st->clkin, &st->nb); + ret = devm_clk_notifier_register(dev, st->clkin, &st->nb); if (ret) return ret; @@ -1097,7 +1093,7 @@ static int adf4377_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(adf4377_channels); } - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id adf4377_id[] = { diff --git a/drivers/iio/frequency/admv1013.c b/drivers/iio/frequency/admv1013.c index d8e8d541990f..b852378b3f68 100644 --- a/drivers/iio/frequency/admv1013.c +++ b/drivers/iio/frequency/admv1013.c @@ -85,9 +85,9 @@ enum { }; enum { - ADMV1013_SE_MODE_POS = 6, - ADMV1013_SE_MODE_NEG = 9, - ADMV1013_SE_MODE_DIFF = 12 + ADMV1013_SE_MODE_POS, + ADMV1013_SE_MODE_NEG, + ADMV1013_SE_MODE_DIFF, }; struct admv1013_state { @@ -441,7 +441,7 @@ static int admv1013_init(struct admv1013_state *st, int vcm_uv) { int ret; unsigned int data; - struct spi_device *spi = st->spi; + struct device *dev = &st->spi->dev; /* Perform a software reset */ ret = __admv1013_spi_update_bits(st, ADMV1013_REG_SPI_CONTROL, @@ -461,19 +461,30 @@ static int admv1013_init(struct admv1013_state *st, int vcm_uv) return ret; data = FIELD_GET(ADMV1013_CHIP_ID_MSK, data); - if (data != ADMV1013_CHIP_ID) { - dev_err(&spi->dev, "Invalid Chip ID.\n"); - return -EINVAL; - } + if (data != ADMV1013_CHIP_ID) + return dev_err_probe(dev, -EINVAL, "Invalid Chip ID.\n"); ret = __admv1013_spi_write(st, ADMV1013_REG_VVA_TEMP_COMP, 0xE700); if (ret) return ret; - data = FIELD_PREP(ADMV1013_QUAD_SE_MODE_MSK, st->quad_se_mode); + switch (st->quad_se_mode) { + case ADMV1013_SE_MODE_POS: + data = 6; + break; + case ADMV1013_SE_MODE_NEG: + data = 9; + break; + case ADMV1013_SE_MODE_DIFF: + data = 12; + break; + default: + return -EINVAL; + } ret = __admv1013_spi_update_bits(st, ADMV1013_REG_QUAD, - ADMV1013_QUAD_SE_MODE_MSK, data); + ADMV1013_QUAD_SE_MODE_MSK, + FIELD_PREP(ADMV1013_QUAD_SE_MODE_MSK, data)); if (ret) return ret; @@ -514,43 +525,39 @@ static void admv1013_powerdown(void *data) admv1013_spi_update_bits(data, ADMV1013_REG_ENABLE, enable_reg_msk, enable_reg); } +static const char * const admv1013_input_modes[] = { + [ADMV1013_IQ_MODE] = "iq", + [ADMV1013_IF_MODE] = "if", +}; + +static const char * const admv1013_quad_se_modes[] = { + [ADMV1013_SE_MODE_POS] = "se-pos", + [ADMV1013_SE_MODE_NEG] = "se-neg", + [ADMV1013_SE_MODE_DIFF] = "diff", +}; + static int admv1013_properties_parse(struct admv1013_state *st) { int ret; - const char *str; - struct spi_device *spi = st->spi; + struct device *dev = &st->spi->dev; - st->det_en = device_property_read_bool(&spi->dev, "adi,detector-enable"); + st->det_en = device_property_read_bool(dev, "adi,detector-enable"); - ret = device_property_read_string(&spi->dev, "adi,input-mode", &str); - if (ret) - st->input_mode = ADMV1013_IQ_MODE; + ret = device_property_match_property_string(dev, "adi,input-mode", + admv1013_input_modes, + ARRAY_SIZE(admv1013_input_modes)); + st->input_mode = ret >= 0 ? ret : ADMV1013_IQ_MODE; - if (!strcmp(str, "iq")) - st->input_mode = ADMV1013_IQ_MODE; - else if (!strcmp(str, "if")) - st->input_mode = ADMV1013_IF_MODE; - else - return -EINVAL; + ret = device_property_match_property_string(dev, "adi,quad-se-mode", + admv1013_quad_se_modes, + ARRAY_SIZE(admv1013_quad_se_modes)); + st->quad_se_mode = ret >= 0 ? ret : ADMV1013_SE_MODE_DIFF; - ret = device_property_read_string(&spi->dev, "adi,quad-se-mode", &str); - if (ret) - st->quad_se_mode = ADMV1013_SE_MODE_DIFF; - - if (!strcmp(str, "diff")) - st->quad_se_mode = ADMV1013_SE_MODE_DIFF; - else if (!strcmp(str, "se-pos")) - st->quad_se_mode = ADMV1013_SE_MODE_POS; - else if (!strcmp(str, "se-neg")) - st->quad_se_mode = ADMV1013_SE_MODE_NEG; - else - return -EINVAL; - - ret = devm_regulator_bulk_get_enable(&st->spi->dev, + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(admv1013_vcc_regs), admv1013_vcc_regs); if (ret) { - dev_err_probe(&spi->dev, ret, + dev_err_probe(dev, ret, "Failed to request VCC regulators\n"); return ret; } @@ -562,9 +569,10 @@ static int admv1013_probe(struct spi_device *spi) { struct iio_dev *indio_dev; struct admv1013_state *st; + struct device *dev = &spi->dev; int ret, vcm_uv; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -581,36 +589,34 @@ static int admv1013_probe(struct spi_device *spi) if (ret) return ret; - ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcm"); + ret = devm_regulator_get_enable_read_voltage(dev, "vcm"); if (ret < 0) - return dev_err_probe(&spi->dev, ret, + return dev_err_probe(dev, ret, "failed to get the common-mode voltage\n"); vcm_uv = ret; - st->clkin = devm_clk_get_enabled(&spi->dev, "lo_in"); + st->clkin = devm_clk_get_enabled(dev, "lo_in"); if (IS_ERR(st->clkin)) - return dev_err_probe(&spi->dev, PTR_ERR(st->clkin), + return dev_err_probe(dev, PTR_ERR(st->clkin), "failed to get the LO input clock\n"); st->nb.notifier_call = admv1013_freq_change; - ret = devm_clk_notifier_register(&spi->dev, st->clkin, &st->nb); + ret = devm_clk_notifier_register(dev, st->clkin, &st->nb); if (ret) return ret; mutex_init(&st->lock); ret = admv1013_init(st, vcm_uv); - if (ret) { - dev_err(&spi->dev, "admv1013 init failed\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "admv1013 init failed\n"); - ret = devm_add_action_or_reset(&spi->dev, admv1013_powerdown, st); + ret = devm_add_action_or_reset(dev, admv1013_powerdown, st); if (ret) return ret; - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id admv1013_id[] = { diff --git a/drivers/iio/frequency/admv1014.c b/drivers/iio/frequency/admv1014.c index 7a8f92ec80a2..25e8cd8135ad 100644 --- a/drivers/iio/frequency/admv1014.c +++ b/drivers/iio/frequency/admv1014.c @@ -610,15 +610,14 @@ static int admv1014_init(struct admv1014_state *st) { unsigned int chip_id, enable_reg, enable_reg_msk; struct spi_device *spi = st->spi; + struct device *dev = &spi->dev; int ret; ret = regulator_bulk_enable(ADMV1014_NUM_REGULATORS, st->regulators); - if (ret) { - dev_err(&spi->dev, "Failed to enable regulators"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to enable regulators"); - ret = devm_add_action_or_reset(&spi->dev, admv1014_reg_disable, st->regulators); + ret = devm_add_action_or_reset(dev, admv1014_reg_disable, st->regulators); if (ret) return ret; @@ -626,16 +625,16 @@ static int admv1014_init(struct admv1014_state *st) if (ret) return ret; - ret = devm_add_action_or_reset(&spi->dev, admv1014_clk_disable, st->clkin); + ret = devm_add_action_or_reset(dev, admv1014_clk_disable, st->clkin); if (ret) return ret; st->nb.notifier_call = admv1014_freq_change; - ret = devm_clk_notifier_register(&spi->dev, st->clkin, &st->nb); + ret = devm_clk_notifier_register(dev, st->clkin, &st->nb); if (ret) return ret; - ret = devm_add_action_or_reset(&spi->dev, admv1014_powerdown, st); + ret = devm_add_action_or_reset(dev, admv1014_powerdown, st); if (ret) return ret; @@ -643,55 +642,47 @@ static int admv1014_init(struct admv1014_state *st) ret = __admv1014_spi_update_bits(st, ADMV1014_REG_SPI_CONTROL, ADMV1014_SPI_SOFT_RESET_MSK, FIELD_PREP(ADMV1014_SPI_SOFT_RESET_MSK, 1)); - if (ret) { - dev_err(&spi->dev, "ADMV1014 SPI software reset failed.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "ADMV1014 SPI software reset failed.\n"); ret = __admv1014_spi_update_bits(st, ADMV1014_REG_SPI_CONTROL, ADMV1014_SPI_SOFT_RESET_MSK, FIELD_PREP(ADMV1014_SPI_SOFT_RESET_MSK, 0)); - if (ret) { - dev_err(&spi->dev, "ADMV1014 SPI software reset disable failed.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "ADMV1014 SPI software reset disable failed.\n"); ret = __admv1014_spi_write(st, ADMV1014_REG_VVA_TEMP_COMP, 0x727C); - if (ret) { - dev_err(&spi->dev, "Writing default Temperature Compensation value failed.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "Writing default Temperature Compensation value failed.\n"); ret = __admv1014_spi_read(st, ADMV1014_REG_SPI_CONTROL, &chip_id); if (ret) return ret; chip_id = FIELD_GET(ADMV1014_CHIP_ID_MSK, chip_id); - if (chip_id != ADMV1014_CHIP_ID) { - dev_err(&spi->dev, "Invalid Chip ID.\n"); - return -EINVAL; - } + if (chip_id != ADMV1014_CHIP_ID) + return dev_err_probe(dev, -EINVAL, "Invalid Chip ID.\n"); ret = __admv1014_spi_update_bits(st, ADMV1014_REG_QUAD, ADMV1014_QUAD_SE_MODE_MSK, FIELD_PREP(ADMV1014_QUAD_SE_MODE_MSK, st->quad_se_mode)); - if (ret) { - dev_err(&spi->dev, "Writing Quad SE Mode failed.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "Writing Quad SE Mode failed.\n"); ret = admv1014_update_quad_filters(st); - if (ret) { - dev_err(&spi->dev, "Update Quad Filters failed.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "Update Quad Filters failed.\n"); ret = admv1014_update_vcm_settings(st); - if (ret) { - dev_err(&spi->dev, "Update VCM Settings failed.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "Update VCM Settings failed.\n"); enable_reg_msk = ADMV1014_P1DB_COMPENSATION_MSK | ADMV1014_IF_AMP_PD_MSK | @@ -712,13 +703,14 @@ static int admv1014_properties_parse(struct admv1014_state *st) { unsigned int i; struct spi_device *spi = st->spi; + struct device *dev = &spi->dev; int ret; - st->det_en = device_property_read_bool(&spi->dev, "adi,detector-enable"); + st->det_en = device_property_read_bool(dev, "adi,detector-enable"); - st->p1db_comp = device_property_read_bool(&spi->dev, "adi,p1db-compensation-enable"); + st->p1db_comp = device_property_read_bool(dev, "adi,p1db-compensation-enable"); - ret = device_property_match_property_string(&spi->dev, "adi,input-mode", + ret = device_property_match_property_string(dev, "adi,input-mode", input_mode_names, ARRAY_SIZE(input_mode_names)); if (ret >= 0) @@ -726,7 +718,7 @@ static int admv1014_properties_parse(struct admv1014_state *st) else st->input_mode = ADMV1014_IQ_MODE; - ret = device_property_match_property_string(&spi->dev, "adi,quad-se-mode", + ret = device_property_match_property_string(dev, "adi,quad-se-mode", quad_se_mode_names, ARRAY_SIZE(quad_se_mode_names)); if (ret >= 0) @@ -737,16 +729,14 @@ static int admv1014_properties_parse(struct admv1014_state *st) for (i = 0; i < ADMV1014_NUM_REGULATORS; ++i) st->regulators[i].supply = admv1014_reg_name[i]; - ret = devm_regulator_bulk_get(&st->spi->dev, ADMV1014_NUM_REGULATORS, + ret = devm_regulator_bulk_get(dev, ADMV1014_NUM_REGULATORS, st->regulators); - if (ret) { - dev_err(&spi->dev, "Failed to request regulators"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Failed to request regulators"); - st->clkin = devm_clk_get(&spi->dev, "lo_in"); + st->clkin = devm_clk_get(dev, "lo_in"); if (IS_ERR(st->clkin)) - return dev_err_probe(&spi->dev, PTR_ERR(st->clkin), + return dev_err_probe(dev, PTR_ERR(st->clkin), "failed to get the LO input clock\n"); return 0; @@ -756,9 +746,10 @@ static int admv1014_probe(struct spi_device *spi) { struct iio_dev *indio_dev; struct admv1014_state *st; + struct device *dev = &spi->dev; int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -787,7 +778,7 @@ static int admv1014_probe(struct spi_device *spi) if (ret) return ret; - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id admv1014_id[] = { diff --git a/drivers/iio/frequency/admv4420.c b/drivers/iio/frequency/admv4420.c index 3ae462b4f5c9..618511eddfb1 100644 --- a/drivers/iio/frequency/admv4420.c +++ b/drivers/iio/frequency/admv4420.c @@ -243,7 +243,7 @@ static int admv4420_calc_parameters(struct admv4420_state *st) st->n_counter.n_counter = 1; } if (!sol_found) - return -1; + return -EINVAL; st->n_counter.int_val = div_u64_rem(st->n_counter.n_counter, 10, &st->n_counter.frac_val); st->n_counter.mod_val = 10; @@ -279,10 +279,9 @@ static int admv4420_setup(struct iio_dev *indio_dev) if (ret) return ret; - if (val != ADMV4420_SCRATCH_PAD_VAL_1) { - dev_err(dev, "Failed ADMV4420 to read/write scratchpad %x ", val); - return -EIO; - } + if (val != ADMV4420_SCRATCH_PAD_VAL_1) + return dev_err_probe(dev, -EIO, + "Failed ADMV4420 to read/write scratchpad %x\n", val); ret = regmap_write(st->regmap, ADMV4420_SCRATCHPAD, @@ -294,10 +293,9 @@ static int admv4420_setup(struct iio_dev *indio_dev) if (ret) return ret; - if (val != ADMV4420_SCRATCH_PAD_VAL_2) { - dev_err(dev, "Failed to read/write scratchpad %x ", val); - return -EIO; - } + if (val != ADMV4420_SCRATCH_PAD_VAL_2) + return dev_err_probe(dev, -EIO, + "Failed to read/write scratchpad %x\n", val); st->mux_sel = ADMV4420_LOCK_DTCT; st->lo_freq_hz = ADMV4420_DEFAULT_LO_FREQ_HZ; @@ -305,10 +303,10 @@ static int admv4420_setup(struct iio_dev *indio_dev) admv4420_fw_parse(st); ret = admv4420_calc_parameters(st); - if (ret) { - dev_err(dev, "Failed calc parameters for %lld ", st->vco_freq_hz); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "Failed calc parameters for %llu\n", + st->vco_freq_hz); ret = regmap_write(st->regmap, ADMV4420_R_DIV_L, FIELD_GET(0xFF, st->ref_block.divider)); @@ -344,18 +342,19 @@ static int admv4420_setup(struct iio_dev *indio_dev) static int admv4420_probe(struct spi_device *spi) { + struct device *dev = &spi->dev; struct iio_dev *indio_dev; struct admv4420_state *st; struct regmap *regmap; int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; regmap = devm_regmap_init_spi(spi, &admv4420_regmap_config); if (IS_ERR(regmap)) - return dev_err_probe(&spi->dev, PTR_ERR(regmap), + return dev_err_probe(dev, PTR_ERR(regmap), "Failed to initializing spi regmap\n"); st = iio_priv(indio_dev); @@ -368,12 +367,10 @@ static int admv4420_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(admv4420_channels); ret = admv4420_setup(indio_dev); - if (ret) { - dev_err(&spi->dev, "Setup ADMV4420 failed (%d)\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Setup ADMV4420 failed\n"); - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct of_device_id admv4420_of_match[] = { diff --git a/drivers/iio/frequency/adrf6780.c b/drivers/iio/frequency/adrf6780.c index a7a21f929970..257fd31a0b0e 100644 --- a/drivers/iio/frequency/adrf6780.c +++ b/drivers/iio/frequency/adrf6780.c @@ -346,23 +346,21 @@ static const struct iio_chan_spec adrf6780_channels[] = { static int adrf6780_reset(struct adrf6780_state *st) { int ret; - struct spi_device *spi = st->spi; + struct device *dev = &st->spi->dev; ret = __adrf6780_spi_update_bits(st, ADRF6780_REG_CONTROL, ADRF6780_SOFT_RESET_MSK, FIELD_PREP(ADRF6780_SOFT_RESET_MSK, 1)); - if (ret) { - dev_err(&spi->dev, "ADRF6780 SPI software reset failed.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "ADRF6780 SPI software reset failed.\n"); ret = __adrf6780_spi_update_bits(st, ADRF6780_REG_CONTROL, ADRF6780_SOFT_RESET_MSK, FIELD_PREP(ADRF6780_SOFT_RESET_MSK, 0)); - if (ret) { - dev_err(&spi->dev, "ADRF6780 SPI software reset disable failed.\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "ADRF6780 SPI software reset disable failed.\n"); return 0; } @@ -371,7 +369,7 @@ static int adrf6780_init(struct adrf6780_state *st) { int ret; unsigned int chip_id, enable_reg, enable_reg_msk; - struct spi_device *spi = st->spi; + struct device *dev = &st->spi->dev; /* Perform a software reset */ ret = adrf6780_reset(st); @@ -383,10 +381,9 @@ static int adrf6780_init(struct adrf6780_state *st) return ret; chip_id = FIELD_GET(ADRF6780_CHIP_ID_MSK, chip_id); - if (chip_id != ADRF6780_CHIP_ID) { - dev_err(&spi->dev, "ADRF6780 Invalid Chip ID.\n"); - return -EINVAL; - } + if (chip_id != ADRF6780_CHIP_ID) + return dev_err_probe(dev, -EINVAL, + "ADRF6780 Invalid Chip ID.\n"); enable_reg_msk = ADRF6780_VGA_BUFFER_EN_MSK | ADRF6780_DETECTOR_EN_MSK | @@ -426,18 +423,18 @@ static int adrf6780_init(struct adrf6780_state *st) static void adrf6780_properties_parse(struct adrf6780_state *st) { - struct spi_device *spi = st->spi; + struct device *dev = &st->spi->dev; - st->vga_buff_en = device_property_read_bool(&spi->dev, "adi,vga-buff-en"); - st->lo_buff_en = device_property_read_bool(&spi->dev, "adi,lo-buff-en"); - st->if_mode_en = device_property_read_bool(&spi->dev, "adi,if-mode-en"); - st->iq_mode_en = device_property_read_bool(&spi->dev, "adi,iq-mode-en"); - st->lo_x2_en = device_property_read_bool(&spi->dev, "adi,lo-x2-en"); - st->lo_ppf_en = device_property_read_bool(&spi->dev, "adi,lo-ppf-en"); - st->lo_en = device_property_read_bool(&spi->dev, "adi,lo-en"); - st->uc_bias_en = device_property_read_bool(&spi->dev, "adi,uc-bias-en"); - st->lo_sideband = device_property_read_bool(&spi->dev, "adi,lo-sideband"); - st->vdet_out_en = device_property_read_bool(&spi->dev, "adi,vdet-out-en"); + st->vga_buff_en = device_property_read_bool(dev, "adi,vga-buff-en"); + st->lo_buff_en = device_property_read_bool(dev, "adi,lo-buff-en"); + st->if_mode_en = device_property_read_bool(dev, "adi,if-mode-en"); + st->iq_mode_en = device_property_read_bool(dev, "adi,iq-mode-en"); + st->lo_x2_en = device_property_read_bool(dev, "adi,lo-x2-en"); + st->lo_ppf_en = device_property_read_bool(dev, "adi,lo-ppf-en"); + st->lo_en = device_property_read_bool(dev, "adi,lo-en"); + st->uc_bias_en = device_property_read_bool(dev, "adi,uc-bias-en"); + st->lo_sideband = device_property_read_bool(dev, "adi,lo-sideband"); + st->vdet_out_en = device_property_read_bool(dev, "adi,vdet-out-en"); } static void adrf6780_powerdown(void *data) @@ -450,9 +447,10 @@ static int adrf6780_probe(struct spi_device *spi) { struct iio_dev *indio_dev; struct adrf6780_state *st; + struct device *dev = &spi->dev; int ret; - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -467,9 +465,9 @@ static int adrf6780_probe(struct spi_device *spi) adrf6780_properties_parse(st); - st->clkin = devm_clk_get_enabled(&spi->dev, "lo_in"); + st->clkin = devm_clk_get_enabled(dev, "lo_in"); if (IS_ERR(st->clkin)) - return dev_err_probe(&spi->dev, PTR_ERR(st->clkin), + return dev_err_probe(dev, PTR_ERR(st->clkin), "failed to get the LO input clock\n"); mutex_init(&st->lock); @@ -478,11 +476,11 @@ static int adrf6780_probe(struct spi_device *spi) if (ret) return ret; - ret = devm_add_action_or_reset(&spi->dev, adrf6780_powerdown, st); + ret = devm_add_action_or_reset(dev, adrf6780_powerdown, st); if (ret) return ret; - return devm_iio_device_register(&spi->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct spi_device_id adrf6780_id[] = { diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c index c43990c518f7..c340cc899a7c 100644 --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c @@ -42,7 +42,7 @@ static const u32 gyro_3d_addresses[GYRO_3D_CHANNEL_MAX] = { HID_USAGE_SENSOR_ANGL_VELOCITY_Z_AXIS }; -static const u32 gryo_3d_sensitivity_addresses[] = { +static const u32 gyro_3d_sensitivity_addresses[] = { HID_USAGE_SENSOR_DATA_ANGL_VELOCITY, }; @@ -297,8 +297,8 @@ static int hid_gyro_3d_probe(struct platform_device *pdev) ret = hid_sensor_parse_common_attributes(hsdev, HID_USAGE_SENSOR_GYRO_3D, &gyro_state->common_attributes, - gryo_3d_sensitivity_addresses, - ARRAY_SIZE(gryo_3d_sensitivity_addresses)); + gyro_3d_sensitivity_addresses, + ARRAY_SIZE(gyro_3d_sensitivity_addresses)); if (ret) { dev_err(&pdev->dev, "failed to setup common attributes\n"); return ret; diff --git a/drivers/iio/humidity/hdc2010.c b/drivers/iio/humidity/hdc2010.c index 894a8b4ab193..1a0f18251381 100644 --- a/drivers/iio/humidity/hdc2010.c +++ b/drivers/iio/humidity/hdc2010.c @@ -44,7 +44,6 @@ struct hdc2010_data { struct i2c_client *client; struct mutex lock; u8 measurement_config; - u8 interrupt_config; u8 drdy_config; }; diff --git a/drivers/iio/imu/bmi323/bmi323_core.c b/drivers/iio/imu/bmi323/bmi323_core.c index 6bcb9a436581..f3d499423399 100644 --- a/drivers/iio/imu/bmi323/bmi323_core.c +++ b/drivers/iio/imu/bmi323/bmi323_core.c @@ -156,7 +156,6 @@ struct bmi323_data { struct iio_mount_matrix orientation; enum bmi323_irq_pin irq_pin; struct iio_trigger *trig; - bool drdy_trigger_enabled; enum bmi323_state state; s64 fifo_tstamp, old_fifo_tstamp; u32 odrns[BMI323_SENSORS_CNT]; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c index 0ab6eddf0543..532d5fdffaf8 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -1211,7 +1211,7 @@ int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev) ssize_t i, size; unsigned int no; const void *accel, *gyro, *timestamp; - const int8_t *temp; + const s8 *temp; unsigned int odr; int64_t ts_val; /* buffer is copied to userspace, zeroing it to avoid any data leak */ diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c index 6aee6c989485..47394594d17a 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c @@ -125,7 +125,7 @@ static int inv_magn_init(struct inv_mpu6050_state *st) } /* - * Sensitivity adjustement and scale to Gauss + * Sensitivity adjustment and scale to Gauss * * Hadj = H * (((ASA - 128) * 0.5 / 128) + 1) * Factor simplification: diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c index 7c933218036b..b2a7c2eaf50d 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c @@ -144,6 +144,7 @@ MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match); static const struct acpi_device_id st_lsm6dsx_i2c_acpi_match[] = { { "SMO8B30", ST_LSM6DS3TRC_ID, }, + { "SMOCF00", ST_LSM6DSO_ID, }, { } }; MODULE_DEVICE_TABLE(acpi, st_lsm6dsx_i2c_acpi_match); diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c index 447b694d6d5f..10e689f49441 100644 --- a/drivers/iio/industrialio-backend.c +++ b/drivers/iio/industrialio-backend.c @@ -56,6 +56,7 @@ struct iio_backend { void *priv; const char *name; unsigned int cached_reg_addr; + u32 caps; /* * This index is relative to the frontend. Meaning that for * frontends with multiple backends, this will be the index of this @@ -774,6 +775,20 @@ int iio_backend_extend_chan_spec(struct iio_backend *back, } EXPORT_SYMBOL_NS_GPL(iio_backend_extend_chan_spec, "IIO_BACKEND"); +/** + * iio_backend_has_caps - Check if backend has specific capabilities + * @back: Backend device + * @caps: Capabilities to check + * + * RETURNS: + * True if backend has all the requested capabilities, false otherwise. + */ +bool iio_backend_has_caps(struct iio_backend *back, u32 caps) +{ + return (back->caps & caps) == caps; +} +EXPORT_SYMBOL_NS_GPL(iio_backend_has_caps, "IIO_BACKEND"); + static void iio_backend_release(void *arg) { struct iio_backend *back = arg; @@ -952,7 +967,6 @@ EXPORT_SYMBOL_NS_GPL(iio_backend_data_transfer_addr, "IIO_BACKEND"); static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, const char *name, struct fwnode_handle *fwnode) { - struct fwnode_handle *fwnode_back; struct iio_backend *back; unsigned int index; int ret; @@ -967,7 +981,8 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con index = 0; } - fwnode_back = fwnode_find_reference(fwnode, "io-backends", index); + struct fwnode_handle *fwnode_back __free(fwnode_handle) = + fwnode_find_reference(fwnode, "io-backends", index); if (IS_ERR(fwnode_back)) return dev_err_cast_probe(dev, fwnode_back, "Cannot get Firmware reference\n"); @@ -977,7 +992,6 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con if (!device_match_fwnode(back->dev, fwnode_back)) continue; - fwnode_handle_put(fwnode_back); ret = __devm_iio_backend_get(dev, back); if (ret) return ERR_PTR(ret); @@ -988,7 +1002,6 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con return back; } - fwnode_handle_put(fwnode_back); return ERR_PTR(-EPROBE_DEFER); } @@ -1114,6 +1127,7 @@ int devm_iio_backend_register(struct device *dev, back->ops = info->ops; back->name = info->name; + back->caps = info->caps; back->owner = dev->driver->owner; back->dev = dev; back->priv = priv; diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 4149efcd5539..a0d6fcf2a9c9 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -256,6 +256,7 @@ static const char * const iio_ev_info_text[] = { [IIO_EV_INFO_TAP2_MIN_DELAY] = "tap2_min_delay", [IIO_EV_INFO_RUNNING_PERIOD] = "runningperiod", [IIO_EV_INFO_RUNNING_COUNT] = "runningcount", + [IIO_EV_INFO_SCALE] = "scale", }; static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr) diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 7f34fe7bad07..17781c12bc85 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -561,10 +561,6 @@ struct iio_trigger *viio_trigger_alloc(struct device *parent, if (!trig) return NULL; - trig->dev.parent = 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); @@ -592,6 +588,11 @@ struct iio_trigger *viio_trigger_alloc(struct device *parent, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE); } + trig->dev.parent = parent; + trig->dev.type = &iio_trig_type; + trig->dev.bus = &iio_bus_type; + device_initialize(&trig->dev); + return trig; free_descs: @@ -634,9 +635,9 @@ void iio_trigger_free(struct iio_trigger *trig) } EXPORT_SYMBOL(iio_trigger_free); -static void devm_iio_trigger_release(struct device *dev, void *res) +static void devm_iio_trigger_release(void *trig) { - iio_trigger_free(*(struct iio_trigger **)res); + iio_trigger_free(trig); } /** @@ -658,24 +659,20 @@ struct iio_trigger *__devm_iio_trigger_alloc(struct device *parent, struct module *this_mod, const char *fmt, ...) { - struct iio_trigger **ptr, *trig; + struct iio_trigger *trig; va_list vargs; - - ptr = devres_alloc(devm_iio_trigger_release, sizeof(*ptr), - GFP_KERNEL); - if (!ptr) - return NULL; + int ret; /* use raw alloc_dr for kmalloc caller tracing */ va_start(vargs, fmt); trig = viio_trigger_alloc(parent, this_mod, fmt, vargs); va_end(vargs); - if (trig) { - *ptr = trig; - devres_add(parent, ptr); - } else { - devres_free(ptr); - } + if (!trig) + return NULL; + + ret = devm_add_action_or_reset(parent, devm_iio_trigger_release, trig); + if (ret) + return NULL; return trig; } diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index ac1408d374c9..eff33e456c70 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -359,7 +359,7 @@ config ROHM_BU27034 select IIO_KFIFO_BUF help Enable support for the ROHM BU27034 ambient light sensor. ROHM BU27034 - is an ambient light sesnor with 3 channels and 3 photo diodes capable + is an ambient light sensor with 3 channels and 3 photo diodes capable of detecting a very wide range of illuminance. Typical application is adjusting LCD and backlight power of TVs and mobile phones. diff --git a/drivers/iio/light/acpi-als.c b/drivers/iio/light/acpi-als.c index d5d1a8b9c035..ab229318dce9 100644 --- a/drivers/iio/light/acpi-als.c +++ b/drivers/iio/light/acpi-als.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -90,9 +91,9 @@ static int acpi_als_read_value(struct acpi_als *als, char *prop, s32 *val) return 0; } -static void acpi_als_notify(struct acpi_device *device, u32 event) +static void acpi_als_notify(acpi_handle handle, u32 event, void *data) { - struct iio_dev *indio_dev = acpi_driver_data(device); + struct iio_dev *indio_dev = data; struct acpi_als *als = iio_priv(indio_dev); if (iio_buffer_enabled(indio_dev) && iio_trigger_using_own(indio_dev)) { @@ -102,7 +103,7 @@ static void acpi_als_notify(struct acpi_device *device, u32 event) break; default: /* Unhandled event */ - dev_dbg(&device->dev, + dev_dbg(&als->device->dev, "Unhandled ACPI ALS event (%08x)!\n", event); } @@ -175,9 +176,10 @@ static irqreturn_t acpi_als_trigger_handler(int irq, void *p) return IRQ_HANDLED; } -static int acpi_als_add(struct acpi_device *device) +static int acpi_als_probe(struct platform_device *pdev) { - struct device *dev = &device->dev; + struct device *dev = &pdev->dev; + struct acpi_device *device = ACPI_COMPANION(dev); struct iio_dev *indio_dev; struct acpi_als *als; int ret; @@ -188,7 +190,6 @@ static int acpi_als_add(struct acpi_device *device) als = iio_priv(indio_dev); - device->driver_data = indio_dev; als->device = device; mutex_init(&als->lock); @@ -218,7 +219,18 @@ static int acpi_als_add(struct acpi_device *device) if (ret) return ret; - return devm_iio_device_register(dev, indio_dev); + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return ret; + + return acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY, + acpi_als_notify, indio_dev); +} + +static void acpi_als_remove(struct platform_device *pdev) +{ + acpi_dev_remove_notify_handler(ACPI_COMPANION(&pdev->dev), + ACPI_DEVICE_NOTIFY, acpi_als_notify); } static const struct acpi_device_id acpi_als_device_ids[] = { @@ -228,17 +240,15 @@ static const struct acpi_device_id acpi_als_device_ids[] = { MODULE_DEVICE_TABLE(acpi, acpi_als_device_ids); -static struct acpi_driver acpi_als_driver = { - .name = "acpi_als", - .class = ACPI_ALS_CLASS, - .ids = acpi_als_device_ids, - .ops = { - .add = acpi_als_add, - .notify = acpi_als_notify, +static struct platform_driver acpi_als_driver = { + .probe = acpi_als_probe, + .remove = acpi_als_remove, + .driver = { + .name = "acpi_als", + .acpi_match_table = acpi_als_device_ids, }, }; - -module_acpi_driver(acpi_als_driver); +module_platform_driver(acpi_als_driver); MODULE_AUTHOR("Zhang Rui "); MODULE_AUTHOR("Martin Liska "); diff --git a/drivers/iio/light/apds9160.c b/drivers/iio/light/apds9160.c index 9b8af11b7b67..3da0bdac04cf 100644 --- a/drivers/iio/light/apds9160.c +++ b/drivers/iio/light/apds9160.c @@ -620,7 +620,7 @@ static int apds9160_set_ps_gain(struct apds9160_chip *data, int val) /* * The PS intelligent cancellation level register allows - * for an on-chip substraction of the ADC count caused by + * for an on-chip subtraction of the ADC count caused by * unwanted reflected light from PS ADC output. */ static int apds9160_set_ps_cancellation_level(struct apds9160_chip *data, diff --git a/drivers/iio/light/apds9306.c b/drivers/iio/light/apds9306.c index 7e68cca0edfa..5ca4c87524fe 100644 --- a/drivers/iio/light/apds9306.c +++ b/drivers/iio/light/apds9306.c @@ -168,7 +168,6 @@ struct apds9306_regfields { * respectively. * @regmap: Regmap structure pointer * @rf: Regmap register fields structure - * @nlux_per_count: Nano lux per ADC count for a particular model * @read_data_available: Flag set by IRQ handler for ADC data available */ struct apds9306_data { @@ -180,7 +179,6 @@ struct apds9306_data { struct regmap *regmap; struct apds9306_regfields rf; - int nlux_per_count; int read_data_available; }; @@ -1176,7 +1174,7 @@ static int apds9306_init_iio_gts(struct apds9306_data *data) static void apds9306_powerdown(void *ptr) { - struct apds9306_data *data = (struct apds9306_data *)ptr; + struct apds9306_data *data = ptr; struct apds9306_regfields *rf = &data->rf; int ret; diff --git a/drivers/iio/light/as73211.c b/drivers/iio/light/as73211.c index 32719f584c47..9fe830dac679 100644 --- a/drivers/iio/light/as73211.c +++ b/drivers/iio/light/as73211.c @@ -677,9 +677,6 @@ static irqreturn_t as73211_trigger_handler(int irq __always_unused, void *p) (char *)&scan.chan[0], 3 * sizeof(scan.chan[0])); if (ret < 0) goto done; - - /* Avoid pushing uninitialized data */ - scan.chan[3] = 0; } if (data_result) { diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c index c7df4b258e2c..7e388319ee2e 100644 --- a/drivers/iio/light/gp2ap020a00f.c +++ b/drivers/iio/light/gp2ap020a00f.c @@ -31,12 +31,14 @@ * the other one. */ +#include #include #include #include #include #include #include +#include #include #include #include @@ -44,6 +46,7 @@ #include #include #include + #include #include #include @@ -52,8 +55,6 @@ #include #include -#define GP2A_I2C_NAME "gp2ap020a00f" - /* Registers */ #define GP2AP020A00F_OP_REG 0x00 /* Basic operations */ #define GP2AP020A00F_ALS_REG 0x01 /* ALS related settings */ @@ -174,10 +175,8 @@ #define GP2AP020A00F_CHAN_TIMESTAMP 3 #define GP2AP020A00F_DATA_READY_TIMEOUT msecs_to_jiffies(1000) -#define GP2AP020A00F_DATA_REG(chan) (GP2AP020A00F_D0_L_REG + \ - (chan) * 2) -#define GP2AP020A00F_THRESH_REG(th_val_id) (GP2AP020A00F_TL_L_REG + \ - (th_val_id) * 2) +#define GP2AP020A00F_DATA_REG(chan) (GP2AP020A00F_D0_L_REG + (chan) * 2) +#define GP2AP020A00F_THRESH_REG(th_val_id) (GP2AP020A00F_TL_L_REG + (th_val_id) * 2) #define GP2AP020A00F_THRESH_VAL_ID(reg_addr) ((reg_addr - 4) / 2) #define GP2AP020A00F_SUBTRACT_MODE 0 @@ -194,7 +193,7 @@ enum gp2ap020a00f_opmode { GP2AP020A00F_OPMODE_ALS_AND_PS, GP2AP020A00F_OPMODE_PROX_DETECT, GP2AP020A00F_OPMODE_SHUTDOWN, - GP2AP020A00F_NUM_OPMODES, + GP2AP020A00F_NUM_OPMODES }; enum gp2ap020a00f_cmd { @@ -246,7 +245,6 @@ struct gp2ap020a00f_data { struct iio_trigger *trig; struct regmap *regmap; unsigned int thresh_val[4]; - u8 debug_reg_addr; struct irq_work work; wait_queue_head_t data_ready_queue; }; @@ -389,20 +387,17 @@ static int gp2ap020a00f_set_operation_mode(struct gp2ap020a00f_data *data, } err = regmap_update_bits(data->regmap, GP2AP020A00F_ALS_REG, - GP2AP020A00F_PRST_MASK, opmode_regs_settings[op] - .als_reg); + GP2AP020A00F_PRST_MASK, opmode_regs_settings[op].als_reg); if (err < 0) return err; err = regmap_update_bits(data->regmap, GP2AP020A00F_PS_REG, - GP2AP020A00F_INTTYPE_MASK, opmode_regs_settings[op] - .ps_reg); + GP2AP020A00F_INTTYPE_MASK, opmode_regs_settings[op].ps_reg); if (err < 0) return err; err = regmap_update_bits(data->regmap, GP2AP020A00F_LED_REG, - GP2AP020A00F_PIN_MASK, opmode_regs_settings[op] - .led_reg); + GP2AP020A00F_PIN_MASK, opmode_regs_settings[op].led_reg); if (err < 0) return err; } @@ -453,15 +448,13 @@ static int gp2ap020a00f_write_event_threshold(struct gp2ap020a00f_data *data, */ thresh_reg_val = data->thresh_val[th_val_id] / 16; else - thresh_reg_val = data->thresh_val[th_val_id] > 16000 ? - 16000 : - data->thresh_val[th_val_id]; + thresh_reg_val = min(data->thresh_val[th_val_id], 16000U); thresh_buf = cpu_to_le16(thresh_reg_val); return regmap_bulk_write(data->regmap, GP2AP020A00F_THRESH_REG(th_val_id), - (u8 *)&thresh_buf, 2); + &thresh_buf, sizeof(thresh_buf)); } static int gp2ap020a00f_alter_opmode(struct gp2ap020a00f_data *data, @@ -493,27 +486,24 @@ static int gp2ap020a00f_alter_opmode(struct gp2ap020a00f_data *data, static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data, enum gp2ap020a00f_cmd cmd) { - int err = 0; + int err; switch (cmd) { case GP2AP020A00F_CMD_READ_RAW_CLEAR: if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN) return -EBUSY; - err = gp2ap020a00f_set_operation_mode(data, + return gp2ap020a00f_set_operation_mode(data, GP2AP020A00F_OPMODE_READ_RAW_CLEAR); - break; case GP2AP020A00F_CMD_READ_RAW_IR: if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN) return -EBUSY; - err = gp2ap020a00f_set_operation_mode(data, + return gp2ap020a00f_set_operation_mode(data, GP2AP020A00F_OPMODE_READ_RAW_IR); - break; case GP2AP020A00F_CMD_READ_RAW_PROXIMITY: if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN) return -EBUSY; - err = gp2ap020a00f_set_operation_mode(data, + return gp2ap020a00f_set_operation_mode(data, GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY); - break; case GP2AP020A00F_CMD_TRIGGER_CLEAR_EN: if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT) return -EBUSY; @@ -521,16 +511,17 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data, err = gp2ap020a00f_alter_opmode(data, GP2AP020A00F_OPMODE_ALS, GP2AP020A00F_ADD_MODE); + else + err = 0; set_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags); - break; + return err; case GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS: clear_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags); if (gp2ap020a00f_als_enabled(data)) break; - err = gp2ap020a00f_alter_opmode(data, + return gp2ap020a00f_alter_opmode(data, GP2AP020A00F_OPMODE_ALS, GP2AP020A00F_SUBTRACT_MODE); - break; case GP2AP020A00F_CMD_TRIGGER_IR_EN: if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT) return -EBUSY; @@ -538,16 +529,17 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data, err = gp2ap020a00f_alter_opmode(data, GP2AP020A00F_OPMODE_ALS, GP2AP020A00F_ADD_MODE); + else + err = 0; set_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags); - break; + return err; case GP2AP020A00F_CMD_TRIGGER_IR_DIS: clear_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags); if (gp2ap020a00f_als_enabled(data)) break; - err = gp2ap020a00f_alter_opmode(data, + return gp2ap020a00f_alter_opmode(data, GP2AP020A00F_OPMODE_ALS, GP2AP020A00F_SUBTRACT_MODE); - break; case GP2AP020A00F_CMD_TRIGGER_PROX_EN: if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT) return -EBUSY; @@ -555,13 +547,12 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data, GP2AP020A00F_OPMODE_PS, GP2AP020A00F_ADD_MODE); set_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &data->flags); - break; + return err; case GP2AP020A00F_CMD_TRIGGER_PROX_DIS: clear_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &data->flags); - err = gp2ap020a00f_alter_opmode(data, + return gp2ap020a00f_alter_opmode(data, GP2AP020A00F_OPMODE_PS, GP2AP020A00F_SUBTRACT_MODE); - break; case GP2AP020A00F_CMD_ALS_HIGH_EV_EN: if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags)) return 0; @@ -575,9 +566,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data, return err; } set_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags); - err = gp2ap020a00f_write_event_threshold(data, + return gp2ap020a00f_write_event_threshold(data, GP2AP020A00F_THRESH_TH, true); - break; case GP2AP020A00F_CMD_ALS_HIGH_EV_DIS: if (!test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags)) return 0; @@ -589,9 +579,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data, if (err < 0) return err; } - err = gp2ap020a00f_write_event_threshold(data, + return gp2ap020a00f_write_event_threshold(data, GP2AP020A00F_THRESH_TH, false); - break; case GP2AP020A00F_CMD_ALS_LOW_EV_EN: if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags)) return 0; @@ -605,9 +594,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data, return err; } set_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags); - err = gp2ap020a00f_write_event_threshold(data, + return gp2ap020a00f_write_event_threshold(data, GP2AP020A00F_THRESH_TL, true); - break; case GP2AP020A00F_CMD_ALS_LOW_EV_DIS: if (!test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags)) return 0; @@ -619,9 +607,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data, if (err < 0) return err; } - err = gp2ap020a00f_write_event_threshold(data, + return gp2ap020a00f_write_event_threshold(data, GP2AP020A00F_THRESH_TL, false); - break; case GP2AP020A00F_CMD_PROX_HIGH_EV_EN: if (test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags)) return 0; @@ -635,9 +622,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data, return err; } set_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags); - err = gp2ap020a00f_write_event_threshold(data, + return gp2ap020a00f_write_event_threshold(data, GP2AP020A00F_THRESH_PH, true); - break; case GP2AP020A00F_CMD_PROX_HIGH_EV_DIS: if (!test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags)) return 0; @@ -646,9 +632,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data, GP2AP020A00F_OPMODE_SHUTDOWN); if (err < 0) return err; - err = gp2ap020a00f_write_event_threshold(data, + return gp2ap020a00f_write_event_threshold(data, GP2AP020A00F_THRESH_PH, false); - break; case GP2AP020A00F_CMD_PROX_LOW_EV_EN: if (test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags)) return 0; @@ -662,9 +647,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data, return err; } set_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags); - err = gp2ap020a00f_write_event_threshold(data, + return gp2ap020a00f_write_event_threshold(data, GP2AP020A00F_THRESH_PL, true); - break; case GP2AP020A00F_CMD_PROX_LOW_EV_DIS: if (!test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags)) return 0; @@ -673,12 +657,11 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data, GP2AP020A00F_OPMODE_SHUTDOWN); if (err < 0) return err; - err = gp2ap020a00f_write_event_threshold(data, + return gp2ap020a00f_write_event_threshold(data, GP2AP020A00F_THRESH_PL, false); - break; } - return err; + return 0; } static int wait_conversion_complete_irq(struct gp2ap020a00f_data *data) @@ -697,18 +680,18 @@ static int wait_conversion_complete_irq(struct gp2ap020a00f_data *data) static int gp2ap020a00f_read_output(struct gp2ap020a00f_data *data, unsigned int output_reg, int *val) { - u8 reg_buf[2]; + __le16 reg_buf; int err; err = wait_conversion_complete_irq(data); if (err < 0) dev_dbg(&data->client->dev, "data ready timeout\n"); - err = regmap_bulk_read(data->regmap, output_reg, reg_buf, 2); + err = regmap_bulk_read(data->regmap, output_reg, ®_buf, sizeof(reg_buf)); if (err < 0) return err; - *val = le16_to_cpup((__le16 *)reg_buf); + *val = le16_to_cpu(reg_buf); return err; } @@ -866,13 +849,13 @@ static irqreturn_t gp2ap020a00f_thresh_event_handler(int irq, void *data) { struct iio_dev *indio_dev = data; struct gp2ap020a00f_data *priv = iio_priv(indio_dev); - u8 op_reg_flags, d0_reg_buf[2]; unsigned int output_val, op_reg_val; + __le16 d0_reg_buf; + u8 op_reg_flags; int thresh_val_id, ret; /* Read interrupt flags */ - ret = regmap_read(priv->regmap, GP2AP020A00F_OP_REG, - &op_reg_val); + ret = regmap_read(priv->regmap, GP2AP020A00F_OP_REG, &op_reg_val); if (ret < 0) goto done; @@ -884,8 +867,7 @@ static irqreturn_t gp2ap020a00f_thresh_event_handler(int irq, void *data) /* Clear interrupt flags (if not in INTTYPE_PULSE mode) */ if (priv->cur_opmode != GP2AP020A00F_OPMODE_PROX_DETECT) { - ret = regmap_write(priv->regmap, GP2AP020A00F_OP_REG, - op_reg_val); + ret = regmap_write(priv->regmap, GP2AP020A00F_OP_REG, op_reg_val); if (ret < 0) goto done; } @@ -895,11 +877,11 @@ static irqreturn_t gp2ap020a00f_thresh_event_handler(int irq, void *data) * transition is required. */ ret = regmap_bulk_read(priv->regmap, GP2AP020A00F_D0_L_REG, - d0_reg_buf, 2); + &d0_reg_buf, sizeof(d0_reg_buf)); if (ret < 0) goto done; - output_val = le16_to_cpup((__le16 *)d0_reg_buf); + output_val = le16_to_cpu(d0_reg_buf); if (gp2ap020a00f_adjust_lux_mode(priv, output_val)) goto done; @@ -966,17 +948,15 @@ static irqreturn_t gp2ap020a00f_trigger_handler(int irq, void *data) int i, out_val, ret; iio_for_each_active_channel(indio_dev, i) { - ret = regmap_bulk_read(priv->regmap, - GP2AP020A00F_DATA_REG(i), - &priv->buffer[d_size], 2); + ret = regmap_bulk_read(priv->regmap, GP2AP020A00F_DATA_REG(i), + &priv->buffer[d_size], 2); if (ret < 0) goto done; if (i == GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR || i == GP2AP020A00F_SCAN_MODE_LIGHT_IR) { - out_val = le16_to_cpup((__le16 *)&priv->buffer[d_size]); + out_val = get_unaligned_le16(&priv->buffer[d_size]); gp2ap020a00f_output_to_lux(priv, &out_val); - put_unaligned_le32(out_val, &priv->buffer[d_size]); d_size += 4; } else { @@ -984,16 +964,15 @@ static irqreturn_t gp2ap020a00f_trigger_handler(int irq, void *data) } } - iio_push_to_buffers_with_timestamp(indio_dev, priv->buffer, - pf->timestamp); + iio_push_to_buffers_with_timestamp(indio_dev, priv->buffer, pf->timestamp); done: iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; } -static u8 gp2ap020a00f_get_thresh_reg(const struct iio_chan_spec *chan, - enum iio_event_direction event_dir) +static int gp2ap020a00f_get_thresh_reg(const struct iio_chan_spec *chan, + enum iio_event_direction event_dir) { switch (chan->type) { case IIO_PROXIMITY: @@ -1007,10 +986,8 @@ static u8 gp2ap020a00f_get_thresh_reg(const struct iio_chan_spec *chan, else return GP2AP020A00F_TL_L_REG; default: - break; + return -EINVAL; } - - return -EINVAL; } static int gp2ap020a00f_write_event_val(struct iio_dev *indio_dev, @@ -1023,53 +1000,41 @@ static int gp2ap020a00f_write_event_val(struct iio_dev *indio_dev, struct gp2ap020a00f_data *data = iio_priv(indio_dev); bool event_en = false; u8 thresh_val_id; - u8 thresh_reg_l; - int err = 0; + int thresh_reg_l; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, dir); - thresh_val_id = GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l); + if (thresh_reg_l < 0) + return thresh_reg_l; - if (thresh_val_id > GP2AP020A00F_THRESH_PH) { - err = -EINVAL; - goto error_unlock; - } + thresh_val_id = GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l); + if (thresh_val_id > GP2AP020A00F_THRESH_PH) + return -EINVAL; switch (thresh_reg_l) { case GP2AP020A00F_TH_L_REG: - event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, - &data->flags); + event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags); break; case GP2AP020A00F_TL_L_REG: - event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, - &data->flags); + event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags); break; case GP2AP020A00F_PH_L_REG: - if (val == 0) { - err = -EINVAL; - goto error_unlock; - } - event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, - &data->flags); + if (val == 0) + return -EINVAL; + + event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags); break; case GP2AP020A00F_PL_L_REG: - if (val == 0) { - err = -EINVAL; - goto error_unlock; - } - event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, - &data->flags); + if (val == 0) + return -EINVAL; + + event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags); break; } data->thresh_val[thresh_val_id] = val; - err = gp2ap020a00f_write_event_threshold(data, thresh_val_id, - event_en); -error_unlock: - mutex_unlock(&data->lock); - - return err; + return gp2ap020a00f_write_event_threshold(data, thresh_val_id, event_en); } static int gp2ap020a00f_read_event_val(struct iio_dev *indio_dev, @@ -1080,24 +1045,19 @@ static int gp2ap020a00f_read_event_val(struct iio_dev *indio_dev, int *val, int *val2) { struct gp2ap020a00f_data *data = iio_priv(indio_dev); - u8 thresh_reg_l; - int err = IIO_VAL_INT; + int thresh_reg_l; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, dir); - - if (thresh_reg_l > GP2AP020A00F_PH_L_REG) { - err = -EINVAL; - goto error_unlock; - } + if (thresh_reg_l < 0) + return thresh_reg_l; + if (thresh_reg_l > GP2AP020A00F_PH_L_REG) + return -EINVAL; *val = data->thresh_val[GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l)]; -error_unlock: - mutex_unlock(&data->lock); - - return err; + return IIO_VAL_INT; } static int gp2ap020a00f_write_prox_event_config(struct iio_dev *indio_dev, @@ -1163,32 +1123,25 @@ static int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev, { struct gp2ap020a00f_data *data = iio_priv(indio_dev); enum gp2ap020a00f_cmd cmd; - int err; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); switch (chan->type) { case IIO_PROXIMITY: - err = gp2ap020a00f_write_prox_event_config(indio_dev, state); - break; + return gp2ap020a00f_write_prox_event_config(indio_dev, state); case IIO_LIGHT: if (dir == IIO_EV_DIR_RISING) { cmd = state ? GP2AP020A00F_CMD_ALS_HIGH_EV_EN : GP2AP020A00F_CMD_ALS_HIGH_EV_DIS; - err = gp2ap020a00f_exec_cmd(data, cmd); + return gp2ap020a00f_exec_cmd(data, cmd); } else { cmd = state ? GP2AP020A00F_CMD_ALS_LOW_EV_EN : GP2AP020A00F_CMD_ALS_LOW_EV_DIS; - err = gp2ap020a00f_exec_cmd(data, cmd); + return gp2ap020a00f_exec_cmd(data, cmd); } - break; default: - err = -EINVAL; + return -EINVAL; } - - mutex_unlock(&data->lock); - - return err; } static int gp2ap020a00f_read_event_config(struct iio_dev *indio_dev, @@ -1197,40 +1150,29 @@ static int gp2ap020a00f_read_event_config(struct iio_dev *indio_dev, enum iio_event_direction dir) { struct gp2ap020a00f_data *data = iio_priv(indio_dev); - int event_en = 0; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); switch (chan->type) { case IIO_PROXIMITY: if (dir == IIO_EV_DIR_RISING) - event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, - &data->flags); + return test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags); else - event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, - &data->flags); - break; + return test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags); case IIO_LIGHT: if (dir == IIO_EV_DIR_RISING) - event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, - &data->flags); + return test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags); else - event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, - &data->flags); - break; + return test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags); default: - event_en = -EINVAL; - break; + return -EINVAL; } - - mutex_unlock(&data->lock); - - return event_en; } static int gp2ap020a00f_read_channel(struct gp2ap020a00f_data *data, struct iio_chan_spec const *chan, int *val) { + struct device *dev = &data->client->dev; enum gp2ap020a00f_cmd cmd; int err; @@ -1250,27 +1192,23 @@ static int gp2ap020a00f_read_channel(struct gp2ap020a00f_data *data, err = gp2ap020a00f_exec_cmd(data, cmd); if (err < 0) { - dev_err(&data->client->dev, - "gp2ap020a00f_exec_cmd failed\n"); - goto error_ret; + dev_err(dev, "gp2ap020a00f_exec_cmd failed\n"); + return err; } err = gp2ap020a00f_read_output(data, chan->address, val); if (err < 0) - dev_err(&data->client->dev, - "gp2ap020a00f_read_output failed\n"); + dev_err(dev, "gp2ap020a00f_read_output failed\n"); err = gp2ap020a00f_set_operation_mode(data, GP2AP020A00F_OPMODE_SHUTDOWN); if (err < 0) - dev_err(&data->client->dev, - "Failed to shut down the device.\n"); + dev_err(dev, "Failed to shut down the device.\n"); if (cmd == GP2AP020A00F_CMD_READ_RAW_CLEAR || cmd == GP2AP020A00F_CMD_READ_RAW_IR) gp2ap020a00f_output_to_lux(data, val); -error_ret: return err; } @@ -1383,9 +1321,9 @@ static const struct iio_info gp2ap020a00f_info = { static int gp2ap020a00f_buffer_postenable(struct iio_dev *indio_dev) { struct gp2ap020a00f_data *data = iio_priv(indio_dev); - int i, err = 0; + int i, err; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); /* * Enable triggers according to the scan_mask. Enabling either @@ -1409,28 +1347,27 @@ static int gp2ap020a00f_buffer_postenable(struct iio_dev *indio_dev) err = gp2ap020a00f_exec_cmd(data, GP2AP020A00F_CMD_TRIGGER_PROX_EN); break; + default: + err = -EINVAL; + break; } + if (err) + return err; } - if (err < 0) - goto error_unlock; - data->buffer = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); if (!data->buffer) - err = -ENOMEM; + return -ENOMEM; -error_unlock: - mutex_unlock(&data->lock); - - return err; + return 0; } static int gp2ap020a00f_buffer_predisable(struct iio_dev *indio_dev) { struct gp2ap020a00f_data *data = iio_priv(indio_dev); - int i, err = 0; + int i, err; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); iio_for_each_active_channel(indio_dev, i) { switch (i) { @@ -1446,15 +1383,16 @@ static int gp2ap020a00f_buffer_predisable(struct iio_dev *indio_dev) err = gp2ap020a00f_exec_cmd(data, GP2AP020A00F_CMD_TRIGGER_PROX_DIS); break; + default: + err = -EINVAL; + break; } + if (err) + return err; } - if (err == 0) - kfree(data->buffer); - - mutex_unlock(&data->lock); - - return err; + kfree(data->buffer); + return 0; } static const struct iio_buffer_setup_ops gp2ap020a00f_buffer_setup_ops = { @@ -1465,18 +1403,19 @@ static const struct iio_buffer_setup_ops gp2ap020a00f_buffer_setup_ops = { static int gp2ap020a00f_probe(struct i2c_client *client) { const struct i2c_device_id *id = i2c_client_get_device_id(client); + struct device *dev = &client->dev; struct gp2ap020a00f_data *data; struct iio_dev *indio_dev; struct regmap *regmap; int err; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); - data->vled_reg = devm_regulator_get(&client->dev, "vled"); + data->vled_reg = devm_regulator_get(dev, "vled"); if (IS_ERR(data->vled_reg)) return PTR_ERR(data->vled_reg); @@ -1486,7 +1425,7 @@ static int gp2ap020a00f_probe(struct i2c_client *client) regmap = devm_regmap_init_i2c(client, &gp2ap020a00f_regmap_config); if (IS_ERR(regmap)) { - dev_err(&client->dev, "Regmap initialization failed.\n"); + dev_err(dev, "Regmap initialization failed.\n"); err = PTR_ERR(regmap); goto error_regulator_disable; } @@ -1497,7 +1436,7 @@ static int gp2ap020a00f_probe(struct i2c_client *client) ARRAY_SIZE(gp2ap020a00f_reg_init_tab)); if (err < 0) { - dev_err(&client->dev, "Device initialization failed.\n"); + dev_err(dev, "Device initialization failed.\n"); goto error_regulator_disable; } @@ -1522,11 +1461,10 @@ static int gp2ap020a00f_probe(struct i2c_client *client) goto error_regulator_disable; /* Allocate trigger */ - data->trig = devm_iio_trigger_alloc(&client->dev, "%s-trigger", - indio_dev->name); + data->trig = devm_iio_trigger_alloc(dev, "%s-trigger", indio_dev->name); if (data->trig == NULL) { err = -ENOMEM; - dev_err(&indio_dev->dev, "Failed to allocate iio trigger.\n"); + dev_err(dev, "Failed to allocate iio trigger.\n"); goto error_uninit_buffer; } @@ -1538,7 +1476,7 @@ static int gp2ap020a00f_probe(struct i2c_client *client) "gp2ap020a00f_als_event", indio_dev); if (err < 0) { - dev_err(&client->dev, "Irq request failed.\n"); + dev_err(dev, "Irq request failed.\n"); goto error_uninit_buffer; } @@ -1546,7 +1484,7 @@ static int gp2ap020a00f_probe(struct i2c_client *client) err = iio_trigger_register(data->trig); if (err < 0) { - dev_err(&client->dev, "Failed to register iio trigger.\n"); + dev_err(dev, "Failed to register iio trigger.\n"); goto error_free_irq; } @@ -1572,12 +1510,12 @@ static void gp2ap020a00f_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct gp2ap020a00f_data *data = iio_priv(indio_dev); + struct device *dev = &client->dev; int err; - err = gp2ap020a00f_set_operation_mode(data, - GP2AP020A00F_OPMODE_SHUTDOWN); + err = gp2ap020a00f_set_operation_mode(data, GP2AP020A00F_OPMODE_SHUTDOWN); if (err < 0) - dev_err(&indio_dev->dev, "Failed to power off the device.\n"); + dev_err(dev, "Failed to power off the device.\n"); iio_device_unregister(indio_dev); iio_trigger_unregister(data->trig); @@ -1587,10 +1525,9 @@ static void gp2ap020a00f_remove(struct i2c_client *client) } static const struct i2c_device_id gp2ap020a00f_id[] = { - { GP2A_I2C_NAME }, + { "gp2ap020a00f" }, { } }; - MODULE_DEVICE_TABLE(i2c, gp2ap020a00f_id); static const struct of_device_id gp2ap020a00f_of_match[] = { @@ -1601,14 +1538,13 @@ MODULE_DEVICE_TABLE(of, gp2ap020a00f_of_match); static struct i2c_driver gp2ap020a00f_driver = { .driver = { - .name = GP2A_I2C_NAME, + .name = "gp2ap020a00f", .of_match_table = gp2ap020a00f_of_match, }, .probe = gp2ap020a00f_probe, .remove = gp2ap020a00f_remove, .id_table = gp2ap020a00f_id, }; - module_i2c_driver(gp2ap020a00f_driver); MODULE_AUTHOR("Jacek Anaszewski "); diff --git a/drivers/iio/light/ltr390.c b/drivers/iio/light/ltr390.c index fc387426fa87..f1702aca582d 100644 --- a/drivers/iio/light/ltr390.c +++ b/drivers/iio/light/ltr390.c @@ -101,7 +101,7 @@ enum ltr390_meas_rate { struct ltr390_data { struct regmap *regmap; struct i2c_client *client; - /* Protects device from simulataneous reads */ + /* Protects device from simultaneous reads */ struct mutex lock; enum ltr390_mode mode; int gain; diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index 022e0693983b..4d99ae336f61 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -754,7 +754,7 @@ static int ltr501_get_gain_index(const struct ltr501_gain *gain, int size, if (val == gain[i].scale && val2 == gain[i].uscale) return i; - return -1; + return -EINVAL; } static int __ltr501_write_raw(struct iio_dev *indio_dev, @@ -773,7 +773,7 @@ static int __ltr501_write_raw(struct iio_dev *indio_dev, info->als_gain_tbl_size, val, val2); if (i < 0) - return -EINVAL; + return i; data->als_contr &= ~info->als_gain_mask; data->als_contr |= i << info->als_gain_shift; @@ -785,7 +785,7 @@ static int __ltr501_write_raw(struct iio_dev *indio_dev, info->ps_gain_tbl_size, val, val2); if (i < 0) - return -EINVAL; + return i; data->ps_contr &= ~LTR501_CONTR_PS_GAIN_MASK; data->ps_contr |= i << LTR501_CONTR_PS_GAIN_SHIFT; diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index 393a3d2fbe1d..53bc455b7bad 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -91,7 +91,7 @@ struct opt3001_chip_info { */ int factor_integer; /* - * Factor used to align decimal part of proccessed value to six decimal + * Factor used to align decimal part of processed value to six decimal * places. */ int factor_decimal; diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c index 0b171106441a..c8f15ba95267 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -190,7 +190,7 @@ struct tsl2772_chip { }; /* - * Different devices require different coefficents, and these numbers were + * Different devices require different coefficients, and these numbers were * derived from the 'Lux Equation' section of the various device datasheets. * All of these coefficients assume a Glass Attenuation (GA) factor of 1. * The coefficients are multiplied by 1000 to avoid floating point operations. diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index a36c23813679..9650dbc41f2b 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -18,12 +18,13 @@ */ #include -#include -#include -#include #include -#include +#include +#include #include +#include +#include +#include #include #include @@ -185,6 +186,7 @@ static const int vcnl4040_ps_oversampling_ratio[] = {1, 2, 4, 8}; #define VCNL4000_SLEEP_DELAY_MS 2000 /* before we enter pm_runtime_suspend */ enum vcnl4000_device_ids { + CM36672P, VCNL4000, VCNL4010, VCNL4040, @@ -235,6 +237,8 @@ struct vcnl4000_chip_spec { }; static const struct i2c_device_id vcnl4000_id[] = { + { "cm36672p", CM36672P }, + { "cm36686", VCNL4040 }, { "vcnl4000", VCNL4000 }, { "vcnl4010", VCNL4010 }, { "vcnl4020", VCNL4010 }, @@ -277,7 +281,7 @@ static int vcnl4000_init(struct vcnl4000_data *data) data->rev = ret & 0xf; data->al_scale = 250000; - return data->chip_spec->set_power_state(data, true); + return 0; }; static ssize_t vcnl4000_write_als_enable(struct vcnl4000_data *data, bool en) @@ -353,17 +357,19 @@ static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on) static int vcnl4200_init(struct vcnl4000_data *data) { + struct i2c_client *client = data->client; + struct device *dev = &client->dev; int ret, id; u16 regval; - ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID); + ret = i2c_smbus_read_word_data(client, VCNL4200_DEV_ID); if (ret < 0) return ret; id = ret & 0xff; if (id != VCNL4200_PROD_ID) { - ret = i2c_smbus_read_word_data(data->client, VCNL4040_DEV_ID); + ret = i2c_smbus_read_word_data(client, VCNL4040_DEV_ID); if (ret < 0) return ret; @@ -373,7 +379,7 @@ static int vcnl4200_init(struct vcnl4000_data *data) return -ENODEV; } - dev_dbg(&data->client->dev, "device id 0x%x", id); + dev_dbg(dev, "device id 0x%x", id); data->rev = (ret >> 8) & 0xf; data->ps_int = 0; @@ -397,32 +403,32 @@ static int vcnl4200_init(struct vcnl4000_data *data) } data->al_scale = data->chip_spec->ulux_step; data->ps_scale = 16; - mutex_init(&data->vcnl4200_al.lock); - mutex_init(&data->vcnl4200_ps.lock); + + ret = devm_mutex_init(dev, &data->vcnl4200_al.lock); + if (ret) + return ret; + + ret = devm_mutex_init(dev, &data->vcnl4200_ps.lock); + if (ret) + return ret; /* Use 16 bits proximity sensor readings */ - ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1); + ret = i2c_smbus_read_word_data(client, VCNL4200_PS_CONF1); if (ret < 0) return ret; regval = ret | VCNL4040_PS_CONF2_PS_HD; - ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, - regval); + ret = i2c_smbus_write_word_data(client, VCNL4200_PS_CONF1, regval); if (ret < 0) return ret; /* Align proximity sensor sample rate to 16 bits data width */ - ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3); + ret = i2c_smbus_read_word_data(client, VCNL4200_PS_CONF3); if (ret < 0) return ret; regval = ret | VCNL4040_CONF3_PS_SAMPLE_16BITS; - ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3, - regval); - if (ret < 0) - return ret; - - ret = data->chip_spec->set_power_state(data, true); + ret = i2c_smbus_write_word_data(client, VCNL4200_PS_CONF3, regval); if (ret < 0) return ret; @@ -1842,6 +1848,22 @@ static const struct iio_chan_spec vcnl4040_channels[] = { } }; +static const struct iio_chan_spec cm36672p_channels[] = { + { + .type = IIO_PROXIMITY, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | + BIT(IIO_CHAN_INFO_CALIBBIAS), + .info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | + BIT(IIO_CHAN_INFO_CALIBBIAS), + .ext_info = vcnl4000_ext_info, + .event_spec = vcnl4040_event_spec, + .num_event_specs = ARRAY_SIZE(vcnl4040_event_spec), + }, +}; + static const struct iio_info vcnl4000_info = { .read_raw = vcnl4000_read_raw, }; @@ -1867,6 +1889,19 @@ static const struct iio_info vcnl4040_info = { }; static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { + [CM36672P] = { + .prod = "CM36672P", + .init = vcnl4200_init, + .measure_proximity = vcnl4200_measure_proximity, + .set_power_state = vcnl4200_set_power_state, + .channels = cm36672p_channels, + .num_channels = ARRAY_SIZE(cm36672p_channels), + .info = &vcnl4040_info, + .irq_thread = vcnl4040_irq_thread, + .int_reg = VCNL4040_INT_FLAGS, + .ps_it_times = &vcnl4040_ps_it_times, + .num_ps_it_times = ARRAY_SIZE(vcnl4040_ps_it_times), + }, [VCNL4000] = { .prod = "VCNL4000", .init = vcnl4000_init, @@ -1951,11 +1986,13 @@ static int vcnl4010_probe_trigger(struct iio_dev *indio_dev) static int vcnl4000_probe(struct i2c_client *client) { const struct i2c_device_id *id = i2c_client_get_device_id(client); + const char * const regulator_names[] = { "vdd", "vio", "vled" }; + struct device *dev = &client->dev; struct vcnl4000_data *data; struct iio_dev *indio_dev; int ret; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; @@ -1965,18 +2002,27 @@ static int vcnl4000_probe(struct i2c_client *client) data->id = id->driver_data; data->chip_spec = &vcnl4000_chip_spec_cfg[data->id]; - mutex_init(&data->vcnl4000_lock); + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names), + regulator_names); + if (ret) + return ret; + + ret = devm_mutex_init(dev, &data->vcnl4000_lock); + if (ret) + return ret; ret = data->chip_spec->init(data); if (ret < 0) return ret; - dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n", + ret = data->chip_spec->set_power_state(data, true); + if (ret) + return ret; + + dev_dbg(dev, "%s Ambient light/proximity sensor, Rev: %02x\n", data->chip_spec->prod, data->rev); - if (device_property_read_u32(&client->dev, "proximity-near-level", - &data->near_level)) - data->near_level = 0; + device_property_read_u32(dev, "proximity-near-level", &data->near_level); indio_dev->info = data->chip_spec->info; indio_dev->channels = data->chip_spec->channels; @@ -1986,35 +2032,29 @@ static int vcnl4000_probe(struct i2c_client *client) if (data->chip_spec->trig_buffer_func && data->chip_spec->buffer_setup_ops) { - ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, - NULL, + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, data->chip_spec->trig_buffer_func, data->chip_spec->buffer_setup_ops); - if (ret < 0) { - dev_err(&client->dev, - "unable to setup iio triggered buffer\n"); + if (ret < 0) return ret; - } } if (client->irq && data->chip_spec->irq_thread) { - ret = devm_request_threaded_irq(&client->dev, client->irq, - NULL, data->chip_spec->irq_thread, + ret = devm_request_threaded_irq(dev, client->irq, NULL, + data->chip_spec->irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "vcnl4000_irq", indio_dev); - if (ret < 0) { - dev_err(&client->dev, "irq request failed\n"); + if (ret < 0) return ret; - } ret = vcnl4010_probe_trigger(indio_dev); if (ret < 0) return ret; } - ret = pm_runtime_set_active(&client->dev); + ret = pm_runtime_set_active(dev); if (ret < 0) goto fail_poweroff; @@ -2022,9 +2062,9 @@ static int vcnl4000_probe(struct i2c_client *client) if (ret < 0) goto fail_poweroff; - pm_runtime_enable(&client->dev); - pm_runtime_set_autosuspend_delay(&client->dev, VCNL4000_SLEEP_DELAY_MS); - pm_runtime_use_autosuspend(&client->dev); + pm_runtime_enable(dev); + pm_runtime_set_autosuspend_delay(dev, VCNL4000_SLEEP_DELAY_MS); + pm_runtime_use_autosuspend(dev); return 0; fail_poweroff: @@ -2033,6 +2073,15 @@ static int vcnl4000_probe(struct i2c_client *client) } static const struct of_device_id vcnl_4000_of_match[] = { + { + .compatible = "capella,cm36672p", + .data = (void *)CM36672P, + }, + /* Capella CM36686 is fully compatible with Vishay VCNL4040 */ + { + .compatible = "capella,cm36686", + .data = (void *)VCNL4040, + }, { .compatible = "vishay,vcnl4000", .data = (void *)VCNL4000, diff --git a/drivers/iio/light/zopt2201.c b/drivers/iio/light/zopt2201.c index 1dba1b949cc3..0990e4d266eb 100644 --- a/drivers/iio/light/zopt2201.c +++ b/drivers/iio/light/zopt2201.c @@ -10,17 +10,17 @@ * TODO: interrupt support, ALS/UVB raw mode */ -#include -#include -#include -#include +#include #include +#include +#include +#include +#include +#include #include #include -#include - #define ZOPT2201_DRV_NAME "zopt2201" /* Registers */ @@ -186,10 +186,10 @@ static int zopt2201_read(struct zopt2201_data *data, u8 reg) u8 buf[3]; int ret; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); ret = zopt2201_enable_mode(data, reg == ZOPT2201_UVB_DATA); if (ret < 0) - goto fail; + return ret; while (tries--) { unsigned long t = zopt2201_resolution[data->res].us; @@ -200,30 +200,25 @@ static int zopt2201_read(struct zopt2201_data *data, u8 reg) msleep(t / 1000); ret = i2c_smbus_read_byte_data(client, ZOPT2201_MAIN_STATUS); if (ret < 0) - goto fail; + return ret; if (ret & ZOPT2201_MAIN_STATUS_DRDY) break; } if (tries < 0) { ret = -ETIMEDOUT; - goto fail; + return ret; } ret = i2c_smbus_read_i2c_block_data(client, reg, sizeof(buf), buf); if (ret < 0) - goto fail; + return ret; ret = i2c_smbus_write_byte_data(client, ZOPT2201_MAIN_CTRL, 0x00); if (ret < 0) - goto fail; - mutex_unlock(&data->lock); + return ret; return get_unaligned_le24(&buf[0]); - -fail: - mutex_unlock(&data->lock); - return ret; } static const struct iio_chan_spec zopt2201_channels[] = { @@ -317,17 +312,15 @@ static int zopt2201_set_resolution(struct zopt2201_data *data, u8 res) static int zopt2201_write_resolution(struct zopt2201_data *data, int val, int val2) { - int i, ret; + int i; if (val != 0) return -EINVAL; for (i = 0; i < ARRAY_SIZE(zopt2201_resolution); i++) if (val2 == zopt2201_resolution[i].us) { - mutex_lock(&data->lock); - ret = zopt2201_set_resolution(data, i); - mutex_unlock(&data->lock); - return ret; + guard(mutex)(&data->lock); + return zopt2201_set_resolution(data, i); } return -EINVAL; @@ -351,16 +344,12 @@ static int zopt2201_write_scale_by_idx(struct zopt2201_data *data, int idx, { int ret; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); ret = zopt2201_set_resolution(data, zopt2201_scale_array[idx].res); if (ret < 0) - goto unlock; + return ret; - ret = zopt2201_set_gain(data, zopt2201_scale_array[idx].gain); - -unlock: - mutex_unlock(&data->lock); - return ret; + return zopt2201_set_gain(data, zopt2201_scale_array[idx].gain); } static int zopt2201_write_scale_als(struct zopt2201_data *data, diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index 68ece700c7ce..817b18257608 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -577,7 +577,7 @@ static int ak8974_measure_channel(struct ak8974 *ak8974, unsigned long address, /* * This explicit cast to (s16) is necessary as the measurement * is done in 2's complement with positive and negative values. - * The follwing assignment to *val will then convert the signed + * The following assignment to *val will then convert the signed * s16 value to a signed int value. */ *val = (s16)le16_to_cpu(hw_values[address]); diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index d30315ad85de..b648b0afa573 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -545,7 +545,7 @@ static int ak8975_set_mode(struct ak8975_data *data, enum ak_ctrl_mode mode) return ret; } data->cntl_cache = regval; - /* After mode change wait atleast 100us */ + /* After mode change wait at least 100us */ usleep_range(100, 500); return 0; @@ -697,7 +697,7 @@ static int wait_conversion_complete_polled(struct ak8975_data *data) return read_status; } -/* Returns 0 if the end of conversion interrupt occured or -ETIME otherwise */ +/* Returns 0 if the end of conversion interrupt occurred or -ETIME otherwise */ static int wait_conversion_complete_interrupt(struct ak8975_data *data) { int ret; @@ -759,7 +759,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) if (ret < 0) goto exit; - /* Read out ST2 for release lock on measurment data. */ + /* Read out ST2 for release lock on measurement data. */ ret = i2c_smbus_read_byte_data(client, data->def->ctrl_regs[ST2]); if (ret < 0) { dev_err(&client->dev, "Error in reading ST2\n"); diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c index a022e1805dff..bf2551988008 100644 --- a/drivers/iio/magnetometer/bmc150_magn.c +++ b/drivers/iio/magnetometer/bmc150_magn.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -148,14 +149,16 @@ struct bmc150_magn_data { static const struct { int freq; u8 reg_val; -} bmc150_magn_samp_freq_table[] = { {2, 0x01}, - {6, 0x02}, - {8, 0x03}, - {10, 0x00}, - {15, 0x04}, - {20, 0x05}, - {25, 0x06}, - {30, 0x07} }; +} bmc150_magn_samp_freq_table[] = { + { 2, 0x01 }, + { 6, 0x02 }, + { 8, 0x03 }, + { 10, 0x00 }, + { 15, 0x04 }, + { 20, 0x05 }, + { 25, 0x06 }, + { 30, 0x07 }, +}; enum bmc150_magn_presets { LOW_POWER_PRESET, @@ -169,10 +172,10 @@ static const struct bmc150_magn_preset { u8 rep_z; u8 odr; } bmc150_magn_presets_table[] = { - [LOW_POWER_PRESET] = {3, 3, 10}, - [REGULAR_PRESET] = {9, 15, 10}, - [ENHANCED_REGULAR_PRESET] = {15, 27, 10}, - [HIGH_ACCURACY_PRESET] = {47, 83, 20}, + [LOW_POWER_PRESET] = { 3, 3, 10 }, + [REGULAR_PRESET] = { 9, 15, 10 }, + [ENHANCED_REGULAR_PRESET] = { 15, 27, 10 }, + [HIGH_ACCURACY_PRESET] = { 47, 83, 20 }, }; #define BMC150_MAGN_DEFAULT_PRESET REGULAR_PRESET @@ -255,6 +258,13 @@ static int bmc150_magn_set_power_mode(struct bmc150_magn_data *data, return -EINVAL; } +static int bmc150_magn_set_power_mode_locked(struct bmc150_magn_data *data, + enum bmc150_magn_power_modes mode) +{ + guard(mutex)(&data->mutex); + return bmc150_magn_set_power_mode(data, mode, true); +} + static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on) { int ret = 0; @@ -453,33 +463,29 @@ static int bmc150_magn_read_raw(struct iio_dev *indio_dev, s32 values[AXIS_XYZ_MAX]; switch (mask) { - case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_RAW: { if (iio_buffer_enabled(indio_dev)) return -EBUSY; - mutex_lock(&data->mutex); + + guard(mutex)(&data->mutex); ret = bmc150_magn_set_power_state(data, true); - if (ret < 0) { - mutex_unlock(&data->mutex); + if (ret < 0) return ret; - } ret = bmc150_magn_read_xyz(data, values); if (ret < 0) { bmc150_magn_set_power_state(data, false); - mutex_unlock(&data->mutex); return ret; } *val = values[chan->scan_index]; ret = bmc150_magn_set_power_state(data, false); - if (ret < 0) { - mutex_unlock(&data->mutex); + if (ret < 0) return ret; - } - mutex_unlock(&data->mutex); return IIO_VAL_INT; + } case IIO_CHAN_INFO_SCALE: /* * The API/driver performs an off-chip temperature @@ -527,48 +533,39 @@ static int bmc150_magn_write_raw(struct iio_dev *indio_dev, int ret; switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: + case IIO_CHAN_INFO_SAMP_FREQ: { if (val > data->max_odr) return -EINVAL; - mutex_lock(&data->mutex); - ret = bmc150_magn_set_odr(data, val); - mutex_unlock(&data->mutex); - return ret; + guard(mutex)(&data->mutex); + return bmc150_magn_set_odr(data, val); + } case IIO_CHAN_INFO_OVERSAMPLING_RATIO: switch (chan->channel2) { case IIO_MOD_X: - case IIO_MOD_Y: + case IIO_MOD_Y: { if (val < 1 || val > 511) return -EINVAL; - mutex_lock(&data->mutex); + guard(mutex)(&data->mutex); ret = bmc150_magn_set_max_odr(data, val, 0, 0); - if (ret < 0) { - mutex_unlock(&data->mutex); + if (ret < 0) return ret; - } - ret = regmap_update_bits(data->regmap, + return regmap_update_bits(data->regmap, BMC150_MAGN_REG_REP_XY, BMC150_MAGN_REG_REP_DATAMASK, - BMC150_MAGN_REPXY_TO_REGVAL - (val)); - mutex_unlock(&data->mutex); - return ret; - case IIO_MOD_Z: + BMC150_MAGN_REPXY_TO_REGVAL(val)); + } + case IIO_MOD_Z: { if (val < 1 || val > 256) return -EINVAL; - mutex_lock(&data->mutex); + guard(mutex)(&data->mutex); ret = bmc150_magn_set_max_odr(data, 0, val, 0); - if (ret < 0) { - mutex_unlock(&data->mutex); + if (ret < 0) return ret; - } - ret = regmap_update_bits(data->regmap, + return regmap_update_bits(data->regmap, BMC150_MAGN_REG_REP_Z, BMC150_MAGN_REG_REP_DATAMASK, - BMC150_MAGN_REPZ_TO_REGVAL - (val)); - mutex_unlock(&data->mutex); - return ret; + BMC150_MAGN_REPZ_TO_REGVAL(val)); + } default: return -EINVAL; } @@ -655,8 +652,9 @@ static const struct iio_info bmc150_magn_info = { }; static const unsigned long bmc150_magn_scan_masks[] = { - BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z), - 0}; + BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z), + 0 +}; static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p) { @@ -695,7 +693,7 @@ static int bmc150_magn_init(struct bmc150_magn_data *data) * 3ms power-on time according to datasheet, let's better * be safe than sorry and set this delay to 5ms. */ - msleep(5); + fsleep(5 * USEC_PER_MSEC); ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, false); @@ -782,9 +780,8 @@ static void bmc150_magn_trig_reen(struct iio_trigger *trig) if (!data->dready_trigger_on) return; - mutex_lock(&data->mutex); + guard(mutex)(&data->mutex); ret = bmc150_magn_reset_intr(data); - mutex_unlock(&data->mutex); if (ret) dev_err(data->dev, "Failed to reset interrupt\n"); } @@ -794,32 +791,28 @@ static int bmc150_magn_data_rdy_trigger_set_state(struct iio_trigger *trig, { struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct bmc150_magn_data *data = iio_priv(indio_dev); - int ret = 0; + int ret; + + guard(mutex)(&data->mutex); - mutex_lock(&data->mutex); if (state == data->dready_trigger_on) - goto err_unlock; + return 0; ret = regmap_update_bits(data->regmap, BMC150_MAGN_REG_INT_DRDY, BMC150_MAGN_MASK_DRDY_EN, state << BMC150_MAGN_SHIFT_DRDY_EN); if (ret < 0) - goto err_unlock; + return ret; data->dready_trigger_on = state; if (state) { ret = bmc150_magn_reset_intr(data); if (ret < 0) - goto err_unlock; + return ret; } - mutex_unlock(&data->mutex); return 0; - -err_unlock: - mutex_unlock(&data->mutex); - return ret; } static const struct iio_trigger_ops bmc150_magn_trigger_ops = { @@ -977,9 +970,7 @@ void bmc150_magn_remove(struct device *dev) if (data->dready_trig) iio_trigger_unregister(data->dready_trig); - mutex_lock(&data->mutex); - bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, true); - mutex_unlock(&data->mutex); + bmc150_magn_set_power_mode_locked(data, BMC150_MAGN_POWER_MODE_SUSPEND); regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators); } @@ -992,10 +983,8 @@ static int bmc150_magn_runtime_suspend(struct device *dev) struct bmc150_magn_data *data = iio_priv(indio_dev); int ret; - mutex_lock(&data->mutex); - ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SLEEP, - true); - mutex_unlock(&data->mutex); + ret = bmc150_magn_set_power_mode_locked(data, + BMC150_MAGN_POWER_MODE_SLEEP); if (ret < 0) { dev_err(dev, "powering off device failed\n"); return ret; @@ -1021,28 +1010,18 @@ static int bmc150_magn_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct bmc150_magn_data *data = iio_priv(indio_dev); - int ret; - mutex_lock(&data->mutex); - ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SLEEP, - true); - mutex_unlock(&data->mutex); - - return ret; + return bmc150_magn_set_power_mode_locked(data, + BMC150_MAGN_POWER_MODE_SLEEP); } static int bmc150_magn_resume(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct bmc150_magn_data *data = iio_priv(indio_dev); - int ret; - mutex_lock(&data->mutex); - ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_NORMAL, - true); - mutex_unlock(&data->mutex); - - return ret; + return bmc150_magn_set_power_mode_locked(data, + BMC150_MAGN_POWER_MODE_NORMAL); } #endif diff --git a/drivers/iio/magnetometer/si7210.c b/drivers/iio/magnetometer/si7210.c index 27e3feba7a0f..2a36abd1c99d 100644 --- a/drivers/iio/magnetometer/si7210.c +++ b/drivers/iio/magnetometer/si7210.c @@ -128,8 +128,8 @@ static const struct regmap_config si7210_regmap_conf = { struct si7210_data { struct regmap *regmap; struct i2c_client *client; - struct regulator *vdd; struct mutex fetch_lock; /* lock for a single measurement fetch */ + unsigned int vdd_uV; s8 temp_offset; s8 temp_gain; s8 scale_20_a[A_REGS_COUNT]; @@ -221,12 +221,8 @@ static int si7210_read_raw(struct iio_dev *indio_dev, temp *= (1 + (data->temp_gain / 2048)); temp += (int)(MICRO / 16) * data->temp_offset; - ret = regulator_get_voltage(data->vdd); - if (ret < 0) - return ret; - /* temp -= 0.222 * VDD */ - temp -= 222 * div_s64(ret, MILLI); + temp -= 222 * (data->vdd_uV / MILLI); *val = div_s64(temp, MILLI); @@ -396,14 +392,11 @@ static int si7210_probe(struct i2c_client *client) return dev_err_probe(&client->dev, PTR_ERR(data->regmap), "failed to register regmap\n"); - data->vdd = devm_regulator_get(&client->dev, "vdd"); - if (IS_ERR(data->vdd)) - return dev_err_probe(&client->dev, PTR_ERR(data->vdd), - "failed to get VDD regulator\n"); - - ret = regulator_enable(data->vdd); - if (ret) - return ret; + ret = devm_regulator_get_enable_read_voltage(&client->dev, "vdd"); + if (ret < 0) + return dev_err_probe(&client->dev, ret, + "Failed to get vdd regulator\n"); + data->vdd_uV = ret; indio_dev->name = dev_name(&client->dev); indio_dev->modes = INDIO_DIRECT_MODE; diff --git a/drivers/iio/magnetometer/yamaha-yas530.c b/drivers/iio/magnetometer/yamaha-yas530.c index d49e37edcbed..140c422773f6 100644 --- a/drivers/iio/magnetometer/yamaha-yas530.c +++ b/drivers/iio/magnetometer/yamaha-yas530.c @@ -1223,7 +1223,7 @@ static int yas530_measure_offsets(struct yas5xx *yas5xx) * as the values for [x, y1, y2]. The value is +/-31 * but the effect on the raw values is much larger. * The effect of the offset is to bring the measure - * rougly to the center. + * roughly to the center. */ ox = 0; oy1 = 0; diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c index 3b90384f17d7..04bf2f5be5b1 100644 --- a/drivers/iio/pressure/bmp280-spi.c +++ b/drivers/iio/pressure/bmp280-spi.c @@ -47,7 +47,7 @@ static int bmp380_regmap_spi_read(void *context, const void *reg, return -EINVAL; /* - * According to the BMP3xx datasheets, for a basic SPI read opertion, + * According to the BMP3xx datasheets, for a basic SPI read operation, * the first byte needs to be dropped and the rest are the requested * data. */ diff --git a/drivers/iio/pressure/hsc030pa.c b/drivers/iio/pressure/hsc030pa.c index 2d00c0656259..d6b18a84f0ab 100644 --- a/drivers/iio/pressure/hsc030pa.c +++ b/drivers/iio/pressure/hsc030pa.c @@ -273,7 +273,7 @@ static const struct hsc_range_config hsc_range_config[HSC_VARIANTS_MAX] = { * @data: structure containing instantiated sensor data * Return: true only if both status bits are zero * - * the two MSB from the first transfered byte contain a status code + * The two MSB from the first transferred byte contain a status code * 00 - normal operation, valid data * 01 - device in factory programming mode * 10 - stale data diff --git a/drivers/iio/pressure/hsc030pa_i2c.c b/drivers/iio/pressure/hsc030pa_i2c.c index a34ef4653f34..3500bda03d75 100644 --- a/drivers/iio/pressure/hsc030pa_i2c.c +++ b/drivers/iio/pressure/hsc030pa_i2c.c @@ -34,8 +34,13 @@ static int hsc_i2c_recv(struct hsc_data *data) msg.buf = data->buffer; ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) + return ret; - return (ret == 2) ? 0 : ret; + if (ret != 1) + return -EIO; + + return 0; } static int hsc_i2c_probe(struct i2c_client *client) diff --git a/drivers/iio/pressure/rohm-bm1390.c b/drivers/iio/pressure/rohm-bm1390.c index dac27fd359ad..08146ca0f91d 100644 --- a/drivers/iio/pressure/rohm-bm1390.c +++ b/drivers/iio/pressure/rohm-bm1390.c @@ -440,7 +440,7 @@ static int bm1390_fifo_flush(struct iio_dev *idev, unsigned int samples) * the timestamps. If we are ran from IRQ, then the * IRQF_ONESHOT has us covered - but if we are ran by the * user-space read we need to disable the IRQ to be on a safe - * side. We do this usng synchronous disable so that if the + * side. We do this using synchronous disable so that if the * IRQ thread is being ran on other CPU we wait for it to be * finished. */ diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c index 4923a558a26a..2c68fdf2744e 100644 --- a/drivers/iio/pressure/zpa2326.c +++ b/drivers/iio/pressure/zpa2326.c @@ -840,7 +840,7 @@ static irqreturn_t zpa2326_handle_threaded_irq(int irq, void *data) complete: /* - * Wake up direct or externaly triggered buffer mode waiters: see + * Wake up direct or externally triggered buffer mode waiters: see * zpa2326_sample_oneshot() and zpa2326_trigger_handler(). */ complete(&priv->data_ready); diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index 6070974c2c85..bb77fad2a1b3 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig @@ -244,6 +244,21 @@ config VL53L0X_I2C To compile this driver as a module, choose M here: the module will be called vl53l0x-i2c. +config VL53L1X_I2C + tristate "STMicroelectronics VL53L1X ToF ranger sensor (I2C)" + depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + select REGMAP_I2C + select RESET_CONTROLLER + help + Say Y here to build a driver for STMicroelectronics VL53L1X + ToF ranger sensors with i2c interface. + This driver can be used to measure the distance of objects. + + To compile this driver as a module, choose M here: the + module will be called vl53l1x-i2c. + config AW96103 tristate "AW96103/AW96105 Awinic proximity sensor" select REGMAP_I2C diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile index 152034d38c49..4352833dd8a4 100644 --- a/drivers/iio/proximity/Makefile +++ b/drivers/iio/proximity/Makefile @@ -23,5 +23,6 @@ obj-$(CONFIG_SX_COMMON) += sx_common.o obj-$(CONFIG_SX9500) += sx9500.o obj-$(CONFIG_VCNL3020) += vcnl3020.o obj-$(CONFIG_VL53L0X_I2C) += vl53l0x-i2c.o +obj-$(CONFIG_VL53L1X_I2C) += vl53l1x-i2c.o obj-$(CONFIG_AW96103) += aw96103.o diff --git a/drivers/iio/proximity/hx9023s.c b/drivers/iio/proximity/hx9023s.c index 17e00ee2b6f8..9efaa5b6b5bd 100644 --- a/drivers/iio/proximity/hx9023s.c +++ b/drivers/iio/proximity/hx9023s.c @@ -1088,6 +1088,7 @@ static int hx9023s_probe(struct i2c_client *client) struct device *dev = &client->dev; struct iio_dev *indio_dev; struct hx9023s_data *data; + const char *fw_name; int ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); @@ -1125,7 +1126,9 @@ static int hx9023s_probe(struct i2c_client *client) if (ret) return dev_err_probe(dev, ret, "channel config failed\n"); - ret = request_firmware_nowait(THIS_MODULE, true, "hx9023s.bin", dev, + fw_name = "hx9023s.bin"; + device_property_read_string(dev, "firmware-name", &fw_name); + ret = request_firmware_nowait(THIS_MODULE, true, fw_name, dev, GFP_KERNEL, data, hx9023s_cfg_update); if (ret) return dev_err_probe(dev, ret, "reg config failed\n"); diff --git a/drivers/iio/proximity/sx9324.c b/drivers/iio/proximity/sx9324.c index c7b2d03c23bc..f61eff39751d 100644 --- a/drivers/iio/proximity/sx9324.c +++ b/drivers/iio/proximity/sx9324.c @@ -821,7 +821,7 @@ static const struct sx_common_reg_default sx9324_default_regs[] = { { SX9324_REG_ADV_CTRL10, 0x00, "adv_ctrl10" }, { SX9324_REG_ADV_CTRL11, 0x00, "adv_ctrl11" }, { SX9324_REG_ADV_CTRL12, 0x00, "adv_ctrl12" }, - /* TODO(gwendal): SAR currenly disabled */ + /* TODO(gwendal): SAR currently disabled */ { SX9324_REG_ADV_CTRL13, 0x00, "adv_ctrl13" }, { SX9324_REG_ADV_CTRL14, 0x00, "adv_ctrl14" }, { SX9324_REG_ADV_CTRL15, 0x00, "adv_ctrl15" }, diff --git a/drivers/iio/proximity/vl53l1x-i2c.c b/drivers/iio/proximity/vl53l1x-i2c.c new file mode 100644 index 000000000000..4d9cb3983dba --- /dev/null +++ b/drivers/iio/proximity/vl53l1x-i2c.c @@ -0,0 +1,756 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * Support for ST VL53L1X FlightSense ToF Ranging Sensor on a i2c bus. + * + * Copyright (C) 2026 Siratul Islam + * + * Datasheet available at + * + * + * Default 7-bit i2c slave address 0x29. + * + * The VL53L1X requires a firmware configuration blob to be loaded at boot. + * Register values for the default configuration are taken from + * ST's VL53L1X Ultra Lite Driver (STSW-IMG009). + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#define VL53L1X_REG_SOFT_RESET 0x0000 +#define VL53L1X_REG_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND 0x0008 +#define VL53L1X_REG_VHV_CONFIG__INIT 0x000B +#define VL53L1X_REG_GPIO_HV_MUX__CTRL 0x0030 +#define VL53L1X_REG_GPIO__TIO_HV_STATUS 0x0031 +#define VL53L1X_REG_SYSTEM__INTERRUPT_CONFIG_GPIO 0x0046 +#define VL53L1X_REG_PHASECAL_CONFIG__TIMEOUT_MACROP 0x004B +#define VL53L1X_REG_RANGE_CONFIG__TIMEOUT_MACROP_A 0x005E +#define VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_A 0x0060 +#define VL53L1X_REG_RANGE_CONFIG__TIMEOUT_MACROP_B 0x0061 +#define VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_B 0x0063 +#define VL53L1X_REG_RANGE_CONFIG__VALID_PHASE_HIGH 0x0069 +#define VL53L1X_REG_SYSTEM__INTERMEASUREMENT_PERIOD 0x006C +#define VL53L1X_REG_SD_CONFIG__WOI_SD0 0x0078 +#define VL53L1X_REG_SD_CONFIG__WOI_SD1 0x0079 +#define VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD0 0x007A +#define VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD1 0x007B +#define VL53L1X_REG_SYSTEM__INTERRUPT_CLEAR 0x0086 +#define VL53L1X_REG_SYSTEM__MODE_START 0x0087 +#define VL53L1X_REG_RESULT__RANGE_STATUS 0x0089 +#define VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 0x0096 +#define VL53L1X_REG_RESULT__OSC_CALIBRATE_VAL 0x00DE +#define VL53L1X_REG_FIRMWARE__SYSTEM_STATUS 0x00E5 +#define VL53L1X_REG_IDENTIFICATION__MODEL_ID 0x010F +#define VL53L1X_REG_DEFAULT_CONFIG 0x002D + +#define VL53L1X_MODEL_ID_VAL 0xEACC + +#define VL53L1X_MODE_START_TIMED 0x40 +#define VL53L1X_MODE_START_STOP 0x00 + +#define VL53L1X_INT_NEW_SAMPLE_READY 0x02 + +#define VL53L1X_GPIO_HV_MUX_POLARITY BIT(4) + +#define VL53L1X_VHV_LOOP_BOUND_TWO 0x09 + +#define VL53L1X_RANGE_STATUS_MASK GENMASK(4, 0) +#define VL53L1X_RANGE_STATUS_VALID 9 + +#define VL53L1X_OSC_CALIBRATE_MASK GENMASK(9, 0) + +/* Inter-measurement period uses PLL divider with 1.075 oscillator correction */ +static const struct u32_fract vl53l1x_osc_correction = { + .numerator = 1075, + .denominator = 1000, +}; + +enum vl53l1x_distance_mode { + VL53L1X_SHORT, + VL53L1X_LONG, +}; + +struct vl53l1x_data { + struct regmap *regmap; + struct completion completion; + struct reset_control *xshut_reset; + enum vl53l1x_distance_mode distance_mode; + u8 gpio_polarity; + int irq; +}; + +static const struct regmap_range vl53l1x_volatile_ranges[] = { + regmap_reg_range(VL53L1X_REG_GPIO__TIO_HV_STATUS, + VL53L1X_REG_GPIO__TIO_HV_STATUS), + regmap_reg_range(VL53L1X_REG_RESULT__RANGE_STATUS, + VL53L1X_REG_RESULT__RANGE_STATUS), + regmap_reg_range(VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0, + VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 + 1), + regmap_reg_range(VL53L1X_REG_RESULT__OSC_CALIBRATE_VAL, + VL53L1X_REG_RESULT__OSC_CALIBRATE_VAL + 1), + regmap_reg_range(VL53L1X_REG_FIRMWARE__SYSTEM_STATUS, + VL53L1X_REG_FIRMWARE__SYSTEM_STATUS), +}; + +static const struct regmap_access_table vl53l1x_volatile_table = { + .yes_ranges = vl53l1x_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(vl53l1x_volatile_ranges), +}; + +static const struct regmap_range vl53l1x_write_only_ranges[] = { + regmap_reg_range(VL53L1X_REG_SOFT_RESET, VL53L1X_REG_SOFT_RESET), + regmap_reg_range(VL53L1X_REG_SYSTEM__INTERRUPT_CLEAR, + VL53L1X_REG_SYSTEM__MODE_START), +}; + +static const struct regmap_access_table vl53l1x_readable_table = { + .no_ranges = vl53l1x_write_only_ranges, + .n_no_ranges = ARRAY_SIZE(vl53l1x_write_only_ranges), +}; + +static const struct regmap_config vl53l1x_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + /* MODEL_ID is 16-bit. +1 covers the second byte at 0x0110 */ + .max_register = VL53L1X_REG_IDENTIFICATION__MODEL_ID + 1, + .cache_type = REGCACHE_MAPLE, + .volatile_table = &vl53l1x_volatile_table, + .rd_table = &vl53l1x_readable_table, +}; + +static int vl53l1x_read_u16(struct vl53l1x_data *data, u16 reg, u16 *val) +{ + __be16 buf; + int ret; + + ret = regmap_bulk_read(data->regmap, reg, &buf, sizeof(buf)); + if (ret) + return ret; + + *val = be16_to_cpu(buf); + return 0; +} + +static int vl53l1x_write_u16(struct vl53l1x_data *data, u16 reg, u16 val) +{ + __be16 buf = cpu_to_be16(val); + + return regmap_bulk_write(data->regmap, reg, &buf, sizeof(buf)); +} + +static int vl53l1x_write_u32(struct vl53l1x_data *data, u16 reg, u32 val) +{ + __be32 buf = cpu_to_be32(val); + + return regmap_bulk_write(data->regmap, reg, &buf, sizeof(buf)); +} + +static int vl53l1x_clear_irq(struct vl53l1x_data *data) +{ + return regmap_write(data->regmap, VL53L1X_REG_SYSTEM__INTERRUPT_CLEAR, 0x01); +} + +static int vl53l1x_start_ranging(struct vl53l1x_data *data) +{ + int ret; + + ret = vl53l1x_clear_irq(data); + if (ret) + return ret; + + return regmap_write(data->regmap, VL53L1X_REG_SYSTEM__MODE_START, + VL53L1X_MODE_START_TIMED); +} + +static int vl53l1x_stop_ranging(struct vl53l1x_data *data) +{ + return regmap_write(data->regmap, VL53L1X_REG_SYSTEM__MODE_START, + VL53L1X_MODE_START_STOP); +} + +/* + * Default configuration blob from ST's VL53L1X Ultra Lite Driver + * (STSW-IMG009). + */ +static const u8 vl53l1x_default_config[] = { + 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 0x08, /* reg 0x2d..0x34 */ + 0x00, 0x08, 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, /* reg 0x35..0x3c */ + 0x00, 0xFF, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, /* reg 0x3d..0x44 */ + 0x00, 0x20, 0x0B, 0x00, 0x00, 0x02, 0x0A, 0x21, /* reg 0x45..0x4c */ + 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0xC8, /* reg 0x4d..0x54 */ + 0x00, 0x00, 0x38, 0xFF, 0x01, 0x00, 0x08, 0x00, /* reg 0x55..0x5c */ + 0x00, 0x01, 0xCC, 0x0F, 0x01, 0xF1, 0x0D, 0x01, /* reg 0x5d..0x64 */ + 0x68, 0x00, 0x80, 0x08, 0xB8, 0x00, 0x00, 0x00, /* reg 0x65..0x6c */ + 0x00, 0x0F, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg 0x6d..0x74 */ + 0x00, 0x00, 0x01, 0x0F, 0x0D, 0x0E, 0x0E, 0x00, /* reg 0x75..0x7c */ + 0x00, 0x02, 0xC7, 0xFF, 0x9B, 0x00, 0x00, 0x00, /* reg 0x7d..0x84 */ + 0x01, 0x00, 0x00, /* reg 0x85..0x87 */ +}; + +static int vl53l1x_chip_init(struct vl53l1x_data *data) +{ + struct device *dev = regmap_get_device(data->regmap); + unsigned int val; + u16 model_id; + int ret; + + if (!data->xshut_reset) { + ret = regmap_write(data->regmap, VL53L1X_REG_SOFT_RESET, 0x00); + if (ret) + return ret; + fsleep(100); /* conservative reset pulse, no spec */ + + ret = regmap_write(data->regmap, VL53L1X_REG_SOFT_RESET, 0x01); + if (ret) + return ret; + fsleep(1000); /* conservative boot wait, no spec */ + } + + ret = regmap_read_poll_timeout(data->regmap, + VL53L1X_REG_FIRMWARE__SYSTEM_STATUS, val, + val & BIT(0), + 1 * USEC_PER_MSEC, + 100 * USEC_PER_MSEC); + if (ret) + return dev_err_probe(dev, ret, "firmware boot timeout\n"); + + ret = vl53l1x_read_u16(data, VL53L1X_REG_IDENTIFICATION__MODEL_ID, + &model_id); + if (ret) + return ret; + + if (model_id != VL53L1X_MODEL_ID_VAL) + dev_info(dev, "unknown model id: 0x%04x, continuing\n", model_id); + + ret = regmap_bulk_write(data->regmap, VL53L1X_REG_DEFAULT_CONFIG, + vl53l1x_default_config, + sizeof(vl53l1x_default_config)); + if (ret) + return ret; + + ret = regmap_read(data->regmap, VL53L1X_REG_GPIO_HV_MUX__CTRL, &val); + if (ret) + return ret; + data->gpio_polarity = !!(val & VL53L1X_GPIO_HV_MUX_POLARITY); + + /* Initial ranging cycle for VHV calibration */ + ret = vl53l1x_start_ranging(data); + if (ret) + return ret; + + /* 1ms poll, 1s timeout covers max timing budgets (per ST Ultra Lite Driver) */ + ret = regmap_read_poll_timeout(data->regmap, + VL53L1X_REG_GPIO__TIO_HV_STATUS, val, + (val & 1) != data->gpio_polarity, + 1 * USEC_PER_MSEC, + 1000 * USEC_PER_MSEC); + if (ret) + return ret; + + ret = vl53l1x_clear_irq(data); + if (ret) + return ret; + + ret = vl53l1x_stop_ranging(data); + if (ret) + return ret; + + ret = regmap_write(data->regmap, + VL53L1X_REG_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND, + VL53L1X_VHV_LOOP_BOUND_TWO); + if (ret) + return ret; + + return regmap_write(data->regmap, VL53L1X_REG_VHV_CONFIG__INIT, 0x00); +} + +static const struct reg_sequence vl53l1x_mode_short[] = { + { VL53L1X_REG_PHASECAL_CONFIG__TIMEOUT_MACROP, 0x14 }, + { VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_A, 0x07 }, + { VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_B, 0x05 }, + { VL53L1X_REG_RANGE_CONFIG__VALID_PHASE_HIGH, 0x38 }, + { VL53L1X_REG_SD_CONFIG__WOI_SD0, 0x07 }, + { VL53L1X_REG_SD_CONFIG__WOI_SD1, 0x05 }, + { VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD0, 0x06 }, + { VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD1, 0x06 }, +}; + +static const struct reg_sequence vl53l1x_mode_long[] = { + { VL53L1X_REG_PHASECAL_CONFIG__TIMEOUT_MACROP, 0x0A }, + { VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_A, 0x0F }, + { VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_B, 0x0D }, + { VL53L1X_REG_RANGE_CONFIG__VALID_PHASE_HIGH, 0xB8 }, + { VL53L1X_REG_SD_CONFIG__WOI_SD0, 0x0F }, + { VL53L1X_REG_SD_CONFIG__WOI_SD1, 0x0D }, + { VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD0, 0x0E }, + { VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD1, 0x0E }, +}; + +static const struct { + const struct reg_sequence *regs; + size_t num_regs; +} vl53l1x_mode_configs[] = { + [VL53L1X_SHORT] = { vl53l1x_mode_short, ARRAY_SIZE(vl53l1x_mode_short) }, + [VL53L1X_LONG] = { vl53l1x_mode_long, ARRAY_SIZE(vl53l1x_mode_long) }, +}; + +static int vl53l1x_set_distance_mode(struct vl53l1x_data *data, + enum vl53l1x_distance_mode mode) +{ + int ret; + + if (mode >= ARRAY_SIZE(vl53l1x_mode_configs)) + return -EINVAL; + + ret = regmap_multi_reg_write(data->regmap, + vl53l1x_mode_configs[mode].regs, + vl53l1x_mode_configs[mode].num_regs); + if (ret) + return ret; + + data->distance_mode = mode; + return 0; +} + +/* + * The timing budget controls how long the sensor spends collecting + * a single range measurement. Pre-computed TIMEOUT_MACROP register + * values from ST's VL53L1X Ultra Lite Driver. + */ +static int vl53l1x_set_timing_budget(struct vl53l1x_data *data, u16 budget_ms) +{ + u16 timeout_a, timeout_b; + int ret; + + switch (data->distance_mode) { + case VL53L1X_SHORT: + switch (budget_ms) { + case 15: + timeout_a = 0x001D; + timeout_b = 0x0027; + break; + case 20: + timeout_a = 0x0051; + timeout_b = 0x006E; + break; + case 33: + timeout_a = 0x00D6; + timeout_b = 0x006E; + break; + case 50: + timeout_a = 0x01AE; + timeout_b = 0x01E8; + break; + case 100: + timeout_a = 0x02E1; + timeout_b = 0x0388; + break; + case 200: + timeout_a = 0x03E1; + timeout_b = 0x0496; + break; + case 500: + timeout_a = 0x0591; + timeout_b = 0x05C1; + break; + default: + return -EINVAL; + } + break; + case VL53L1X_LONG: + switch (budget_ms) { + case 20: + timeout_a = 0x001E; + timeout_b = 0x0022; + break; + case 33: + timeout_a = 0x0060; + timeout_b = 0x006E; + break; + case 50: + timeout_a = 0x00AD; + timeout_b = 0x00C6; + break; + case 100: + timeout_a = 0x01CC; + timeout_b = 0x01EA; + break; + case 200: + timeout_a = 0x02D9; + timeout_b = 0x02F8; + break; + case 500: + timeout_a = 0x048F; + timeout_b = 0x04A4; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + ret = vl53l1x_write_u16(data, VL53L1X_REG_RANGE_CONFIG__TIMEOUT_MACROP_A, + timeout_a); + if (ret) + return ret; + + return vl53l1x_write_u16(data, VL53L1X_REG_RANGE_CONFIG__TIMEOUT_MACROP_B, + timeout_b); +} + +static int vl53l1x_set_inter_measurement_ms(struct vl53l1x_data *data, + u16 period_ms) +{ + u16 osc_calibrate_val; + u16 clock_pll; + u32 inter_meas; + int ret; + + ret = vl53l1x_read_u16(data, VL53L1X_REG_RESULT__OSC_CALIBRATE_VAL, + &osc_calibrate_val); + if (ret) + return ret; + + clock_pll = osc_calibrate_val & VL53L1X_OSC_CALIBRATE_MASK; + inter_meas = (clock_pll * period_ms * vl53l1x_osc_correction.numerator) / + vl53l1x_osc_correction.denominator; + + return vl53l1x_write_u32(data, + VL53L1X_REG_SYSTEM__INTERMEASUREMENT_PERIOD, + inter_meas); +} + +static int vl53l1x_read_proximity(struct vl53l1x_data *data, int *val) +{ + unsigned int range_status; + u16 distance; + int ret; + + if (data->irq) { + reinit_completion(&data->completion); + + ret = vl53l1x_clear_irq(data); + if (ret) + return ret; + + if (!wait_for_completion_timeout(&data->completion, HZ)) + return -ETIMEDOUT; + } else { + unsigned int rdy; + + /* 1ms poll, 1s timeout covers max timing budgets (per ST Ultra Lite Driver) */ + ret = regmap_read_poll_timeout(data->regmap, + VL53L1X_REG_GPIO__TIO_HV_STATUS, rdy, + (rdy & 1) != data->gpio_polarity, + 1 * USEC_PER_MSEC, + 1000 * USEC_PER_MSEC); + if (ret) + return ret; + } + + ret = regmap_read(data->regmap, VL53L1X_REG_RESULT__RANGE_STATUS, + &range_status); + if (ret) + goto clear_irq; + + if (FIELD_GET(VL53L1X_RANGE_STATUS_MASK, range_status) != + VL53L1X_RANGE_STATUS_VALID) { + ret = -EIO; + goto clear_irq; + } + + ret = vl53l1x_read_u16(data, + VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0, + &distance); + if (ret) + goto clear_irq; + + *val = distance; + +clear_irq: + vl53l1x_clear_irq(data); + return ret; +} + +static const struct iio_chan_spec vl53l1x_channels[] = { + { + .type = IIO_DISTANCE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + +static int vl53l1x_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct vl53l1x_data *data = iio_priv(indio_dev); + int ret; + + if (chan->type != IIO_DISTANCE) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = vl53l1x_read_proximity(data, val); + iio_device_release_direct(indio_dev); + if (ret) + return ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = 1000; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static const struct iio_info vl53l1x_info = { + .read_raw = vl53l1x_read_raw, + .validate_trigger = iio_validate_own_trigger, +}; + +static irqreturn_t vl53l1x_trigger_handler(int irq, void *priv) +{ + struct iio_poll_func *pf = priv; + struct iio_dev *indio_dev = pf->indio_dev; + struct vl53l1x_data *data = iio_priv(indio_dev); + struct { + u16 distance; + aligned_s64 timestamp; + } scan = { }; + unsigned int range_status; + int ret; + + ret = regmap_read(data->regmap, VL53L1X_REG_RESULT__RANGE_STATUS, + &range_status); + if (ret) + goto notify_and_clear_irq; + if (FIELD_GET(VL53L1X_RANGE_STATUS_MASK, range_status) != + VL53L1X_RANGE_STATUS_VALID) + goto notify_and_clear_irq; + + ret = vl53l1x_read_u16(data, + VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0, + &scan.distance); + if (ret) + goto notify_and_clear_irq; + + iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan), + iio_get_time_ns(indio_dev)); + +notify_and_clear_irq: + iio_trigger_notify_done(indio_dev->trig); + vl53l1x_clear_irq(data); + + return IRQ_HANDLED; +} + +static irqreturn_t vl53l1x_irq_handler(int irq, void *priv) +{ + struct iio_dev *indio_dev = priv; + struct vl53l1x_data *data = iio_priv(indio_dev); + + if (iio_buffer_enabled(indio_dev)) + iio_trigger_poll(indio_dev->trig); + else + complete(&data->completion); + + return IRQ_HANDLED; +} + +static const struct iio_trigger_ops vl53l1x_trigger_ops = { + .validate_device = iio_trigger_validate_own_device, +}; + +static void vl53l1x_stop_ranging_action(void *priv) +{ + vl53l1x_stop_ranging(priv); +} + +static int vl53l1x_configure_irq(struct device *dev, int irq, + struct iio_dev *indio_dev) +{ + struct vl53l1x_data *data = iio_priv(indio_dev); + int ret; + + ret = devm_request_irq(dev, irq, vl53l1x_irq_handler, IRQF_NO_THREAD, + indio_dev->name, indio_dev); + if (ret) + return ret; + + ret = regmap_write(data->regmap, VL53L1X_REG_SYSTEM__INTERRUPT_CONFIG_GPIO, + VL53L1X_INT_NEW_SAMPLE_READY); + if (ret) + return dev_err_probe(dev, ret, "failed to configure IRQ\n"); + + return 0; +} + +static int vl53l1x_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct vl53l1x_data *data; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->irq = client->irq; + + data->regmap = devm_regmap_init_i2c(client, &vl53l1x_regmap_config); + if (IS_ERR(data->regmap)) + return dev_err_probe(dev, PTR_ERR(data->regmap), + "regmap initialization failed\n"); + + ret = devm_regulator_get_enable(dev, "vdd"); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable VDD regulator\n"); + + /* + * XSHUT held low puts the chip in hardware standby. All register + * state is lost on de-assert so this is functionally a reset. + */ + data->xshut_reset = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL); + if (IS_ERR(data->xshut_reset)) + return dev_err_probe(dev, PTR_ERR(data->xshut_reset), + "Cannot get reset control\n"); + + /* + * 1.2 ms max boot duration. + * Datasheet Section 3.6 "Power up and boot sequence". + */ + fsleep(1200); + + ret = vl53l1x_chip_init(data); + if (ret) + return ret; + + ret = vl53l1x_set_distance_mode(data, VL53L1X_LONG); + if (ret) + return ret; + + /* 50 ms timing budget (per ST Ultra Lite Driver) */ + ret = vl53l1x_set_timing_budget(data, 50); + if (ret) + return ret; + + /* 50 ms inter-measurement period (per ST Ultra Lite Driver) */ + ret = vl53l1x_set_inter_measurement_ms(data, 50); + if (ret) + return ret; + + /* + * The hardware only supports "autonomous" continuous ranging mode. + * Start ranging here and leave it running for the lifetime of + * the device. Both direct reads and the buffer path rely on this. + */ + ret = vl53l1x_start_ranging(data); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, vl53l1x_stop_ranging_action, data); + if (ret) + return ret; + + indio_dev->name = "vl53l1x"; + indio_dev->info = &vl53l1x_info; + indio_dev->channels = vl53l1x_channels; + indio_dev->num_channels = ARRAY_SIZE(vl53l1x_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + if (client->irq) { + struct iio_trigger *trig; + + init_completion(&data->completion); + + trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, + iio_device_id(indio_dev)); + if (!trig) + return -ENOMEM; + + trig->ops = &vl53l1x_trigger_ops; + iio_trigger_set_drvdata(trig, indio_dev); + ret = devm_iio_trigger_register(dev, trig); + if (ret) + return ret; + + indio_dev->trig = iio_trigger_get(trig); + + ret = vl53l1x_configure_irq(dev, client->irq, indio_dev); + if (ret) + return ret; + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, + &vl53l1x_trigger_handler, + NULL); + if (ret) + return ret; + } + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct i2c_device_id vl53l1x_id[] = { + { "vl53l1x" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, vl53l1x_id); + +static const struct of_device_id st_vl53l1x_dt_match[] = { + { .compatible = "st,vl53l1x" }, + { } +}; +MODULE_DEVICE_TABLE(of, st_vl53l1x_dt_match); + +static struct i2c_driver vl53l1x_driver = { + .driver = { + .name = "vl53l1x-i2c", + .of_match_table = st_vl53l1x_dt_match, + }, + .probe = vl53l1x_probe, + .id_table = vl53l1x_id, +}; +module_i2c_driver(vl53l1x_driver); + +MODULE_AUTHOR("Siratul Islam "); +MODULE_DESCRIPTION("ST VL53L1X ToF ranging sensor driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/iio/resolver/ad2s1210.c b/drivers/iio/resolver/ad2s1210.c index 06d9c784f93e..774728c804c0 100644 --- a/drivers/iio/resolver/ad2s1210.c +++ b/drivers/iio/resolver/ad2s1210.c @@ -896,14 +896,14 @@ static const struct iio_event_spec ad2s1210_monitor_signal_event_spec[] = { .mask_separate = BIT(IIO_EV_INFO_VALUE), }, { - /* Sine/cosine DOS overrange fault.*/ + /* Sine/cosine DOS overrange fault. */ .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_RISING, - /* Degredation of signal overrange threshold. */ + /* Degradation of signal overrange threshold. */ .mask_separate = BIT(IIO_EV_INFO_VALUE), }, { - /* Sine/cosine DOS mismatch fault.*/ + /* Sine/cosine DOS mismatch fault. */ .type = IIO_EV_TYPE_MAG, .dir = IIO_EV_DIR_RISING, .mask_separate = BIT(IIO_EV_INFO_VALUE), diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c index 7dd40d69cce6..38e6f8dfd3b8 100644 --- a/drivers/iio/temperature/ltc2983.c +++ b/drivers/iio/temperature/ltc2983.c @@ -709,7 +709,7 @@ ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data ret = fwnode_property_read_u32(ref, "reg", &thermo->cold_junction_chan); if (ret) /* - * This would be catched later but we can just return + * This would be caught later but we can just return * the error right away. */ return dev_err_ptr_probe(&st->spi->dev, ret, @@ -798,7 +798,7 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st, * For 4wire RTD with rotation, the channel selection cannot be * >=19 since the chann + 1 is used in this configuration. * For 4wire RTDs with kelvin rsense, the rsense channel cannot be - * <=1 since chanel - 1 and channel - 2 are used. + * <=1 since channel - 1 and channel - 2 are used. */ if (rtd->sensor_config & LTC2983_RTD_4_WIRE_MASK) { /* 4-wire */ diff --git a/drivers/iio/test/iio-test-gts.c b/drivers/iio/test/iio-test-gts.c index 11250bc905c9..6ffff85ba853 100644 --- a/drivers/iio/test/iio-test-gts.c +++ b/drivers/iio/test/iio-test-gts.c @@ -20,7 +20,7 @@ * * If yes, then adding a test is probably a good idea but please stop for a * moment and consider the effort of changing all the tests when code gets - * refactored. Eventually it neeeds to be. + * refactored. Eventually it needs to be. */ #define TEST_TSEL_50 1 diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c index 172acf135f3b..0e32a2295990 100644 --- a/drivers/staging/iio/adc/ad7816.c +++ b/drivers/staging/iio/adc/ad7816.c @@ -124,8 +124,8 @@ static ssize_t ad7816_show_mode(struct device *dev, struct ad7816_chip_info *chip = iio_priv(indio_dev); if (chip->mode) - return sprintf(buf, "power-save\n"); - return sprintf(buf, "full\n"); + return sysfs_emit(buf, "power-save\n"); + return sysfs_emit(buf, "full\n"); } static ssize_t ad7816_store_mode(struct device *dev, @@ -156,7 +156,7 @@ static ssize_t ad7816_show_available_modes(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "full\npower-save\n"); + return sysfs_emit(buf, "full\npower-save\n"); } static IIO_DEVICE_ATTR(available_modes, 0444, ad7816_show_available_modes, @@ -169,7 +169,7 @@ static ssize_t ad7816_show_channel(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7816_chip_info *chip = iio_priv(indio_dev); - return sprintf(buf, "%d\n", chip->channel_id); + return sysfs_emit(buf, "%d\n", chip->channel_id); } static ssize_t ad7816_store_channel(struct device *dev, @@ -231,9 +231,9 @@ static ssize_t ad7816_show_value(struct device *dev, data &= AD7816_TEMP_FLOAT_MASK; if (value < 0) data = BIT(AD7816_TEMP_FLOAT_OFFSET) - data; - return sprintf(buf, "%d.%.2d\n", value, data * 25); + return sysfs_emit(buf, "%d.%.2d\n", value, data * 25); } - return sprintf(buf, "%u\n", data); + return sysfs_emit(buf, "%u\n", data); } static IIO_DEVICE_ATTR(value, 0444, ad7816_show_value, NULL, 0); @@ -281,9 +281,9 @@ static ssize_t ad7816_show_oti(struct device *dev, value = AD7816_BOUND_VALUE_MIN + (chip->oti_data[chip->channel_id] - AD7816_BOUND_VALUE_BASE); - return sprintf(buf, "%d\n", value); + return sysfs_emit(buf, "%d\n", value); } - return sprintf(buf, "%u\n", chip->oti_data[chip->channel_id]); + return sysfs_emit(buf, "%u\n", chip->oti_data[chip->channel_id]); } static inline ssize_t ad7816_set_oti(struct device *dev, diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c index d339d5e8e043..bdb2580e29bf 100644 --- a/drivers/staging/iio/frequency/ad9834.c +++ b/drivers/staging/iio/frequency/ad9834.c @@ -281,16 +281,12 @@ ssize_t ad9834_show_out0_wavetype_available(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad9834_state *st = iio_priv(indio_dev); - char *str; if (st->devid == ID_AD9833 || st->devid == ID_AD9837) - str = "sine triangle square"; - else if (st->control & AD9834_OPBITEN) - str = "sine"; - else - str = "sine triangle"; - - return sprintf(buf, "%s\n", str); + return sysfs_emit(buf, "sine triangle square\n"); + if (st->control & AD9834_OPBITEN) + return sysfs_emit(buf, "sine\n"); + return sysfs_emit(buf, "sine triangle\n"); } static IIO_DEVICE_ATTR(out_altvoltage0_out0_wavetype_available, 0444, @@ -303,14 +299,10 @@ ssize_t ad9834_show_out1_wavetype_available(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad9834_state *st = iio_priv(indio_dev); - char *str; if (st->control & AD9834_MODE) - str = ""; - else - str = "square"; - - return sprintf(buf, "%s\n", str); + return sysfs_emit(buf, "\n"); + return sysfs_emit(buf, "square\n"); } static IIO_DEVICE_ATTR(out_altvoltage0_out1_wavetype_available, 0444, diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 85a4223295cd..dde2ec9d1f6a 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -5,6 +5,7 @@ * Copyright 2011 Analog Devices Inc. */ +#include #include #include #include @@ -194,8 +195,7 @@ static int ad5933_set_freq(struct ad5933_state *st, u8 d8[4]; } dat; - freqreg = (u64)freq * (u64)(1 << 27); - do_div(freqreg, st->mclk_hz / 4); + freqreg = div64_ul(BIT_ULL(27) * freq, st->mclk_hz / 4); switch (reg) { case AD5933_REG_FREQ_START: @@ -285,7 +285,7 @@ static ssize_t ad5933_show_frequency(struct device *dev, freqreg = (u64)freqreg * (u64)(st->mclk_hz / 4); do_div(freqreg, BIT(27)); - return sprintf(buf, "%d\n", (int)freqreg); + return sysfs_emit(buf, "%llu\n", freqreg); } static ssize_t ad5933_store_frequency(struct device *dev, @@ -338,27 +338,27 @@ static ssize_t ad5933_show(struct device *dev, mutex_lock(&st->lock); switch ((u32)this_attr->address) { case AD5933_OUT_RANGE: - len = sprintf(buf, "%u\n", - st->range_avail[(st->ctrl_hb >> 1) & 0x3]); + len = sysfs_emit(buf, "%u\n", + st->range_avail[(st->ctrl_hb >> 1) & 0x3]); break; case AD5933_OUT_RANGE_AVAIL: - len = sprintf(buf, "%u %u %u %u\n", st->range_avail[0], - st->range_avail[3], st->range_avail[2], - st->range_avail[1]); + len = sysfs_emit(buf, "%u %u %u %u\n", st->range_avail[0], + st->range_avail[3], st->range_avail[2], + st->range_avail[1]); break; case AD5933_OUT_SETTLING_CYCLES: - len = sprintf(buf, "%d\n", st->settling_cycles); + len = sysfs_emit(buf, "%d\n", st->settling_cycles); break; case AD5933_IN_PGA_GAIN: - len = sprintf(buf, "%s\n", - (st->ctrl_hb & AD5933_CTRL_PGA_GAIN_1) ? - "1" : "0.2"); + len = sysfs_emit(buf, "%s\n", + (st->ctrl_hb & AD5933_CTRL_PGA_GAIN_1) ? + "1" : "0.2"); break; case AD5933_IN_PGA_GAIN_AVAIL: - len = sprintf(buf, "1 0.2\n"); + len = sysfs_emit(buf, "1 0.2\n"); break; case AD5933_FREQ_POINTS: - len = sprintf(buf, "%d\n", st->freq_points); + len = sysfs_emit(buf, "%d\n", st->freq_points); break; default: ret = -EINVAL; diff --git a/include/linux/iio/adc/qcom-adc5-gen3-common.h b/include/linux/iio/adc/qcom-adc5-gen3-common.h new file mode 100644 index 000000000000..6303eaa6640b --- /dev/null +++ b/include/linux/iio/adc/qcom-adc5-gen3-common.h @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * Code used in the main and auxiliary Qualcomm PMIC voltage ADCs + * of type ADC5 Gen3. + */ + +#ifndef QCOM_ADC5_GEN3_COMMON_H +#define QCOM_ADC5_GEN3_COMMON_H + +#include +#include +#include +#include +#include +#include +#include + +#define ADC5_GEN3_HS 0x45 +#define ADC5_GEN3_HS_BUSY BIT(7) +#define ADC5_GEN3_HS_READY BIT(0) + +#define ADC5_GEN3_STATUS1 0x46 +#define ADC5_GEN3_STATUS1_CONV_FAULT BIT(7) +#define ADC5_GEN3_STATUS1_THR_CROSS BIT(6) +#define ADC5_GEN3_STATUS1_EOC BIT(0) + +#define ADC5_GEN3_TM_EN_STS 0x47 +#define ADC5_GEN3_TM_HIGH_STS 0x48 +#define ADC5_GEN3_TM_LOW_STS 0x49 + +#define ADC5_GEN3_EOC_STS 0x4a +#define ADC5_GEN3_EOC_CHAN_0 BIT(0) + +#define ADC5_GEN3_EOC_CLR 0x4b +#define ADC5_GEN3_TM_HIGH_STS_CLR 0x4c +#define ADC5_GEN3_TM_LOW_STS_CLR 0x4d +#define ADC5_GEN3_CONV_ERR_CLR 0x4e +#define ADC5_GEN3_CONV_ERR_CLR_REQ BIT(0) + +#define ADC5_GEN3_SID 0x4f +#define ADC5_GEN3_SID_MASK GENMASK(3, 0) + +#define ADC5_GEN3_PERPH_CH 0x50 +#define ADC5_GEN3_CHAN_CONV_REQ BIT(7) + +#define ADC5_GEN3_TIMER_SEL 0x51 +#define ADC5_GEN3_TIME_IMMEDIATE 0x1 + +#define ADC5_GEN3_DIG_PARAM 0x52 +#define ADC5_GEN3_DIG_PARAM_CAL_SEL_MASK GENMASK(5, 4) +#define ADC5_GEN3_DIG_PARAM_DEC_RATIO_SEL_MASK GENMASK(3, 2) + +#define ADC5_GEN3_FAST_AVG 0x53 +#define ADC5_GEN3_FAST_AVG_CTL_EN BIT(7) +#define ADC5_GEN3_FAST_AVG_CTL_SAMPLES_MASK GENMASK(2, 0) + +#define ADC5_GEN3_ADC_CH_SEL_CTL 0x54 +#define ADC5_GEN3_DELAY_CTL 0x55 +#define ADC5_GEN3_HW_SETTLE_DELAY_MASK GENMASK(3, 0) + +#define ADC5_GEN3_CH_EN 0x56 +#define ADC5_GEN3_HIGH_THR_INT_EN BIT(1) +#define ADC5_GEN3_LOW_THR_INT_EN BIT(0) + +#define ADC5_GEN3_LOW_THR0 0x57 +#define ADC5_GEN3_LOW_THR1 0x58 +#define ADC5_GEN3_HIGH_THR0 0x59 +#define ADC5_GEN3_HIGH_THR1 0x5a + +#define ADC5_GEN3_CH_DATA0(channel) (0x5c + (channel) * 2) +#define ADC5_GEN3_CH_DATA1(channel) (0x5d + (channel) * 2) + +#define ADC5_GEN3_CONV_REQ 0xe5 +#define ADC5_GEN3_CONV_REQ_REQ BIT(0) + +#define ADC5_GEN3_VIRTUAL_SID_MASK GENMASK(15, 8) +#define ADC5_GEN3_CHANNEL_MASK GENMASK(7, 0) +#define ADC5_GEN3_V_CHAN(x) \ + (FIELD_PREP(ADC5_GEN3_VIRTUAL_SID_MASK, (x).sid) | (x).channel) + +/* ADC channels for PMIC5 Gen3 */ +#define ADC5_GEN3_REF_GND 0x00 +#define ADC5_GEN3_1P25VREF 0x01 +#define ADC5_GEN3_DIE_TEMP 0x03 +#define ADC5_GEN3_USB_SNS_V_16 0x11 +#define ADC5_GEN3_VIN_DIV16_MUX 0x12 +#define ADC5_GEN3_VPH_PWR 0x8e +#define ADC5_GEN3_VBAT_SNS_QBG 0x8f +/* 100k pull-up channels */ +#define ADC5_GEN3_AMUX1_THM_100K_PU 0x44 +#define ADC5_GEN3_AMUX2_THM_100K_PU 0x45 +#define ADC5_GEN3_AMUX3_THM_100K_PU 0x46 +#define ADC5_GEN3_AMUX4_THM_100K_PU 0x47 +#define ADC5_GEN3_AMUX5_THM_100K_PU 0x48 +#define ADC5_GEN3_AMUX6_THM_100K_PU 0x49 +#define ADC5_GEN3_AMUX1_GPIO_100K_PU 0x4a +#define ADC5_GEN3_AMUX2_GPIO_100K_PU 0x4b +#define ADC5_GEN3_AMUX3_GPIO_100K_PU 0x4c +#define ADC5_GEN3_AMUX4_GPIO_100K_PU 0x4d + +#define ADC5_MAX_CHANNEL 0xc0 + +enum adc5_cal_method { + ADC5_NO_CAL = 0, + ADC5_RATIOMETRIC_CAL, + ADC5_ABSOLUTE_CAL, +}; + +enum adc5_time_select { + MEAS_INT_DISABLE = 0, + MEAS_INT_IMMEDIATE, + MEAS_INT_50MS, + MEAS_INT_100MS, + MEAS_INT_1S, + MEAS_INT_NONE, +}; + +/** + * struct adc5_sdam_data - data per SDAM allocated for adc usage + * @base_addr: base address for the ADC SDAM peripheral. + * @irq_name: ADC IRQ name. + * @irq: ADC IRQ number. + */ +struct adc5_sdam_data { + u16 base_addr; + const char *irq_name; + int irq; +}; + +/** + * struct adc5_device_data - Top-level ADC device data + * @regmap: ADC peripheral register map field. + * @base: array of SDAM data. + * @num_sdams: number of ADC SDAM peripherals. + */ +struct adc5_device_data { + struct regmap *regmap; + struct adc5_sdam_data *base; + int num_sdams; +}; + +/** + * struct adc5_channel_common_prop - ADC channel properties (common to ADC and TM). + * @channel: channel number, refer to the channel list. + * @cal_method: calibration method. + * @decimation: sampling rate supported for the channel. + * @sid: ID of PMIC owning the channel. + * @label: Channel name used in device tree. + * @prescale: channel scaling performed on the input signal. + * @hw_settle_time_us: the time between AMUX being configured and the + * start of conversion in uS. + * @avg_samples: ability to provide single result from the ADC + * that is an average of multiple measurements. + * @scale_fn_type: Represents the scaling function to convert voltage + * physical units desired by the client for the channel. + */ +struct adc5_channel_common_prop { + unsigned int channel; + enum adc5_cal_method cal_method; + unsigned int decimation; + unsigned int sid; + const char *label; + unsigned int prescale; + unsigned int hw_settle_time_us; + unsigned int avg_samples; + enum vadc_scale_fn_type scale_fn_type; +}; + +/** + * struct tm5_aux_dev_wrapper - wrapper structure around TM auxiliary device + * @aux_dev: TM auxiliary device structure. + * @dev_data: Top-level ADC device data. + * @tm_props: Array of common ADC channel properties for TM channels. + * @n_tm_channels: number of TM channels. + */ +struct tm5_aux_dev_wrapper { + struct auxiliary_device aux_dev; + struct adc5_device_data *dev_data; + struct adc5_channel_common_prop *tm_props; + unsigned int n_tm_channels; +}; + +int adc5_gen3_read(struct adc5_device_data *adc, unsigned int sdam_index, + u16 offset, u8 *data, int len); + +int adc5_gen3_write(struct adc5_device_data *adc, unsigned int sdam_index, + u16 offset, u8 *data, int len); + +int adc5_gen3_poll_wait_hs(struct adc5_device_data *adc, + unsigned int sdam_index); + +void adc5_gen3_update_dig_param(struct adc5_channel_common_prop *prop, + u8 *data); + +int adc5_gen3_status_clear(struct adc5_device_data *adc, + int sdam_index, u16 offset, u8 *val, int len); + +void adc5_gen3_mutex_lock(struct device *dev); +void adc5_gen3_mutex_unlock(struct device *dev); +int adc5_gen3_get_scaled_reading(struct device *dev, + struct adc5_channel_common_prop *common_props, + int *val); +int adc5_gen3_therm_code_to_temp(struct device *dev, + struct adc5_channel_common_prop *common_props, + u16 code, int *val); +void adc5_gen3_register_tm_event_notifier(struct device *dev, + void (*handler)(struct auxiliary_device *)); + +#endif /* QCOM_ADC5_GEN3_COMMON_H */ diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h index 7f815f3fed6a..4d15c2a9802c 100644 --- a/include/linux/iio/backend.h +++ b/include/linux/iio/backend.h @@ -84,6 +84,27 @@ enum iio_backend_filter_type { IIO_BACKEND_FILTER_TYPE_MAX }; +/** + * enum iio_backend_capabilities - Backend capabilities + * Backend capabilities can be used by frontends to check if a given + * functionality is supported by the backend. This is useful for frontend + * devices which are expected to work with alternative backend + * implementations. Capabilities are loosely coupled with operations, + * meaning that a capability requires certain operations to be implemented + * by the backend. A capability might be mapped to a single operation or + * multiple operations. + * + * @IIO_BACKEND_CAP_CALIBRATION: Backend supports digital interface + * calibration. Calibration procedure is device specific. + * @IIO_BACKEND_CAP_BUFFER: Support for IIO buffer interface. + * @IIO_BACKEND_CAP_ENABLE: Backend can be explicitly enabled/disabled. + */ +enum iio_backend_capabilities { + IIO_BACKEND_CAP_CALIBRATION = BIT(0), + IIO_BACKEND_CAP_BUFFER = BIT(1), + IIO_BACKEND_CAP_ENABLE = BIT(2), +}; + /** * struct iio_backend_ops - operations structure for an iio_backend * @enable: Enable backend. @@ -179,10 +200,12 @@ struct iio_backend_ops { * struct iio_backend_info - info structure for an iio_backend * @name: Backend name. * @ops: Backend operations. + * @caps: Backend capabilities. (bitmask of enum iio_backend_capabilities). */ struct iio_backend_info { const char *name; const struct iio_backend_ops *ops; + u32 caps; }; int iio_backend_chan_enable(struct iio_backend *back, unsigned int chan); @@ -235,6 +258,7 @@ int iio_backend_read_raw(struct iio_backend *back, long mask); int iio_backend_extend_chan_spec(struct iio_backend *back, struct iio_chan_spec *chan); +bool iio_backend_has_caps(struct iio_backend *back, u32 caps); void *iio_backend_get_priv(const struct iio_backend *conv); struct iio_backend *devm_iio_backend_get(struct device *dev, const char *name); struct iio_backend *devm_iio_backend_fwnode_get(struct device *dev, diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index f9ae5cdd884f..1ba496f0fea5 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -160,12 +160,12 @@ struct st_sensor_int_drdy { /** * struct st_sensor_data_ready_irq - ST sensor device data-ready interrupt - * struct int1 - data-ready configuration register for INT1 pin. - * struct int2 - data-ready configuration register for INT2 pin. + * @int1: data-ready configuration register for INT1 pin. + * @int2: data-ready configuration register for INT2 pin. * @addr_ihl: address to enable/disable active low on the INT lines. * @mask_ihl: mask to enable/disable active low on the INT lines. - * struct stat_drdy - status register of DRDY (data ready) interrupt. - * struct ig1 - represents the Interrupt Generator 1 of sensors. + * @stat_drdy: status register of DRDY (data ready) interrupt. + * @ig1: represents the Interrupt Generator 1 of sensors. * @en_addr: address of the enable ig1 register. * @en_mask: mask to write the on/off value for enable. */ @@ -190,6 +190,7 @@ struct st_sensor_data_ready_irq { * @wai_addr: The address of WhoAmI register. * @sensors_supported: List of supported sensors by struct itself. * @ch: IIO channels for the sensor. + * @num_ch: Number of IIO channels in @ch * @odr: Output data rate register and ODR list available. * @pw: Power register of the sensor. * @enable_axis: Enable one or more axis of the sensor. @@ -228,7 +229,7 @@ struct st_sensor_settings { * @regmap: Pointer to specific sensor regmap configuration. * @enabled: Status of the sensor (false->off, true->on). * @odr: Output data rate of the sensor [Hz]. - * num_data_channels: Number of data channels used in buffer. + * @num_data_channels: Number of data channels used in buffer. * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2). * @int_pin_open_drain: Set the interrupt/DRDY to open drain. * @irq: the IRQ number. diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 34eebad12d2c..4e3099defc1d 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -21,6 +21,7 @@ enum iio_event_info { IIO_EV_INFO_TAP2_MIN_DELAY, IIO_EV_INFO_RUNNING_PERIOD, IIO_EV_INFO_RUNNING_COUNT, + IIO_EV_INFO_SCALE, }; #define IIO_VAL_INT 1 diff --git a/include/linux/platform_data/tsl2772.h b/include/linux/platform_data/tsl2772.h index f8ade15a35e2..f042e82b39c3 100644 --- a/include/linux/platform_data/tsl2772.h +++ b/include/linux/platform_data/tsl2772.h @@ -61,9 +61,9 @@ struct tsl2772_lux { * @prox_pulse_count: Number if proximity emitter pulses. * @prox_max_samples_cal: The number of samples that are taken when performing * a proximity calibration. - * @prox_diode Which diode(s) to use for driving the external + * @prox_diode: Which diode(s) to use for driving the external * LED(s) for proximity sensing. - * @prox_power The amount of power to use for the external LED(s). + * @prox_power: The amount of power to use for the external LED(s). */ struct tsl2772_settings { int als_time;