Pull char/misc/IIO/whatever driver subsystem updates from Greg KH: "Here is the 'big and hairy' char/misc/iio and other small driver subsystem updates for 6.13-rc1. Loads of things in here, and even a fun merge conflict! - rust misc driver bindings and other rust changes to make misc drivers actually possible. I think this is the tipping point, expect to see way more rust drivers going forward now that these bindings are present. Next merge window hopefully we will have pci and platform drivers working, which will fully enable almost all driver subsystems to start accepting (or at least getting) rust drivers. This is the end result of a lot of work from a lot of people, congrats to all of them for getting this far, you've proved many of us wrong in the best way possible, working code :) - IIO driver updates, too many to list individually, that subsystem keeps growing and growing... - Interconnect driver updates - nvmem driver updates - pwm driver updates - platform_driver::remove() fixups, loads of them - counter driver updates - misc driver updates (keba?) - binder driver updates and fixes - loads of other small char/misc/etc driver updates and additions, full details in the shortlog. All of these have been in linux-next for a while, with no other reported issues other than that merge conflict" * tag 'char-misc-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (401 commits) mei: vsc: Fix typo "maintstepping" -> "mainstepping" firmware: Switch back to struct platform_driver::remove() misc: isl29020: Fix the wrong format specifier scripts/tags.sh: Don't tag usages of DEFINE_MUTEX fpga: Switch back to struct platform_driver::remove() mei: vsc: Improve error logging in vsc_identify_silicon() mei: vsc: Do not re-enable interrupt from vsc_tp_reset() dt-bindings: spmi: qcom,x1e80100-spmi-pmic-arb: Add SAR2130P compatible dt-bindings: spmi: spmi-mtk-pmif: Add compatible for MT8188 spmi: pmic-arb: fix return path in for_each_available_child_of_node() iio: Move __private marking before struct element priv in struct iio_dev docs: iio: ad7380: add adaq4370-4 and adaq4380-4 iio: adc: ad7380: add support for adaq4370-4 and adaq4380-4 iio: adc: ad7380: use local dev variable to shorten long lines iio: adc: ad7380: fix oversampling formula dt-bindings: iio: adc: ad7380: add adaq4370-4 and adaq4380-4 compatible parts bus: mhi: host: pci_generic: Use pcim_iomap_region() to request and map MHI BAR bus: mhi: host: Switch trace_mhi_gen_tre fields to native endian misc: atmel-ssc: Use of_property_present() for non-boolean properties misc: keba: Add hardware dependency ...
Unified · Split
| @@ -2268,6 +2268,30 @@ Description: · 2267 unmodified lines | |||
| 2268 | An example format is 16-bytes, 2-digits-per-byte, HEX-string | 2268 | An example format is 16-bytes, 2-digits-per-byte, HEX-string |
| 2269 | representing the sensor unique ID number. | 2269 | representing the sensor unique ID number. |
| 2270 | 2270 | ||
| 2271 | What: /sys/bus/iio/devices/iio:deviceX/filter_type_available | ||
| 2272 | What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_filter_mode_available | ||
| 2273 | KernelVersion: 6.1 | ||
| 2274 | Contact: linux-iio@vger.kernel.org | ||
| 2275 | Description: | ||
| 2276 | Reading returns a list with the possible filter modes. Options | ||
| 2277 | for the attribute: | ||
| 2278 | |||
| 2279 | * "sinc3" - The digital sinc3 filter. Moderate 1st | ||
| 2280 | conversion time. Good noise performance. | ||
| 2281 | * "sinc4" - Sinc 4. Excellent noise performance. Long | ||
| 2282 | 1st conversion time. | ||
| 2283 | * "sinc5" - The digital sinc5 filter. Excellent noise | ||
| 2284 | performance | ||
| 2285 | * "sinc4+sinc1" - Sinc4 + averaging by 8. Low 1st conversion | ||
| 2286 | time. | ||
| 2287 | * "sinc3+rej60" - Sinc3 + 60Hz rejection. | ||
| 2288 | * "sinc3+sinc1" - Sinc3 + averaging by 8. Low 1st conversion | ||
| 2289 | time. | ||
| 2290 | * "sinc3+pf1" - Sinc3 + device specific Post Filter 1. | ||
| 2291 | * "sinc3+pf2" - Sinc3 + device specific Post Filter 2. | ||
| 2292 | * "sinc3+pf3" - Sinc3 + device specific Post Filter 3. | ||
| 2293 | * "sinc3+pf4" - Sinc3 + device specific Post Filter 4. | ||
| 2294 | |||
| 2271 | What: /sys/.../events/in_proximity_thresh_either_runningperiod | 2295 | What: /sys/.../events/in_proximity_thresh_either_runningperiod |
| 2272 | KernelVersion: 6.6 | 2296 | KernelVersion: 6.6 |
| 2273 | Contact: linux-iio@vger.kernel.org | 2297 | Contact: linux-iio@vger.kernel.org |
| @@ -2339,3 +2363,11 @@ KernelVersion: 6.10 · 65 unmodified lines | |||
| 2339 | Contact: linux-iio@vger.kernel.org | 2363 | Contact: linux-iio@vger.kernel.org |
| 2340 | Description: | 2364 | Description: |
| 2341 | The value of current sense resistor in Ohms. | 2365 | The value of current sense resistor in Ohms. |
| 2366 | |||
| 2367 | What: /sys/.../iio:deviceX/in_attention_input | ||
| 2368 | KernelVersion: 6.13 | ||
| 2369 | Contact: linux-iio@vger.kernel.org | ||
| 2370 | Description: | ||
| 2371 | Value representing the user's attention to the system expressed | ||
| 2372 | in units as percentage. This usually means if the user is | ||
| 2373 | looking at the screen or not. | ||
| @@ -1,46 +0,0 @@ | |||
| 1 | What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_filter_mode_available | ||
| 2 | KernelVersion: 6.2 | ||
| 3 | Contact: linux-iio@vger.kernel.org | ||
| 4 | Description: | ||
| 5 | Reading returns a list with the possible filter modes. | ||
| 6 | |||
| 7 | * "sinc4" - Sinc 4. Excellent noise performance. Long | ||
| 8 | 1st conversion time. No natural 50/60Hz rejection. | ||
| 9 | |||
| 10 | * "sinc4+sinc1" - Sinc4 + averaging by 8. Low 1st conversion | ||
| 11 | time. | ||
| 12 | |||
| 13 | * "sinc3" - Sinc3. Moderate 1st conversion time. | ||
| 14 | Good noise performance. | ||
| 15 | |||
| 16 | * "sinc3+rej60" - Sinc3 + 60Hz rejection. At a sampling | ||
| 17 | frequency of 50Hz, achieves simultaneous 50Hz and 60Hz | ||
| 18 | rejection. | ||
| 19 | |||
| 20 | * "sinc3+sinc1" - Sinc3 + averaging by 8. Low 1st conversion | ||
| 21 | time. Best used with a sampling frequency of at least | ||
| 22 | 216.19Hz. | ||
| 23 | |||
| 24 | * "sinc3+pf1" - Sinc3 + Post Filter 1. 53dB rejection @ | ||
| 25 | 50Hz, 58dB rejection @ 60Hz. | ||
| 26 | |||
| 27 | * "sinc3+pf2" - Sinc3 + Post Filter 2. 70dB rejection @ | ||
| 28 | 50Hz, 70dB rejection @ 60Hz. | ||
| 29 | |||
| 30 | * "sinc3+pf3" - Sinc3 + Post Filter 3. 99dB rejection @ | ||
| 31 | 50Hz, 103dB rejection @ 60Hz. | ||
| 32 | |||
| 33 | * "sinc3+pf4" - Sinc3 + Post Filter 4. 103dB rejection @ | ||
| 34 | 50Hz, 109dB rejection @ 60Hz. | ||
| 35 | |||
| 36 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_filter_mode | ||
| 37 | KernelVersion: 6.2 | ||
| 38 | Contact: linux-iio@vger.kernel.org | ||
| 39 | Description: | ||
| 40 | Set the filter mode of the differential channel. When the filter | ||
| 41 | mode changes, the in_voltageY-voltageZ_sampling_frequency and | ||
| 42 | in_voltageY-voltageZ_sampling_frequency_available attributes | ||
| 43 | might also change to accommodate the new filter mode. | ||
| 44 | If the current sampling frequency is out of range for the new | ||
| 45 | filter mode, the sampling frequency will be changed to the | ||
| 46 | closest valid one. | ||
| @@ -37,6 +37,10 @@ properties: · 36 unmodified lines | |||
| 37 | to both the positive and negative inputs of a differential ADC. | 37 | to both the positive and negative inputs of a differential ADC. |
| 38 | The first value specifies the positive input pin, the second | 38 | The first value specifies the positive input pin, the second |
| 39 | specifies the negative input pin. | 39 | specifies the negative input pin. |
| 40 | There are also some ADCs, where the differential channel has dedicated | ||
| 41 | positive and negative inputs which can be used to measure differential | ||
| 42 | voltage levels. For those setups, this property can be configured with | ||
| 43 | the 'reg' property for both inputs (i.e. diff-channels = <reg reg>). | ||
| 40 | 44 | ||
| 41 | single-channel: | 45 | single-channel: |
| 42 | $ref: /schemas/types.yaml#/definitions/uint32 | 46 | $ref: /schemas/types.yaml#/definitions/uint32 |
| @@ -28,6 +28,7 @@ description: | · 27 unmodified lines | |||
| 28 | Datasheets for supported chips: | 28 | Datasheets for supported chips: |
| 29 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD4111.pdf | 29 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD4111.pdf |
| 30 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD4112.pdf | 30 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD4112.pdf |
| 31 | <AD4113: not released yet> | ||
| 31 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD4114.pdf | 32 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD4114.pdf |
| 32 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD4115.pdf | 33 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD4115.pdf |
| 33 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD4116.pdf | 34 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD4116.pdf |
| @@ -44,6 +45,7 @@ properties: · 10 unmodified lines | |||
| 44 | enum: | 45 | enum: |
| 45 | - adi,ad4111 | 46 | - adi,ad4111 |
| 46 | - adi,ad4112 | 47 | - adi,ad4112 |
| 48 | - adi,ad4113 | ||
| 47 | - adi,ad4114 | 49 | - adi,ad4114 |
| 48 | - adi,ad4115 | 50 | - adi,ad4115 |
| 49 | - adi,ad4116 | 51 | - adi,ad4116 |
| @@ -331,6 +333,7 @@ allOf: · 281 unmodified lines | |||
| 331 | enum: | 333 | enum: |
| 332 | - adi,ad4111 | 334 | - adi,ad4111 |
| 333 | - adi,ad4112 | 335 | - adi,ad4112 |
| 336 | - adi,ad4113 | ||
| 334 | - adi,ad4114 | 337 | - adi,ad4114 |
| 335 | - adi,ad4115 | 338 | - adi,ad4115 |
| 336 | - adi,ad4116 | 339 | - adi,ad4116 |
| @@ -25,6 +25,8 @@ description: | · 24 unmodified lines | |||
| 25 | * https://www.analog.com/en/products/ad7386-4.html | 25 | * https://www.analog.com/en/products/ad7386-4.html |
| 26 | * https://www.analog.com/en/products/ad7387-4.html | 26 | * https://www.analog.com/en/products/ad7387-4.html |
| 27 | * https://www.analog.com/en/products/ad7388-4.html | 27 | * https://www.analog.com/en/products/ad7388-4.html |
| 28 | * https://www.analog.com/en/products/adaq4370-4.html | ||
| 29 | * https://www.analog.com/en/products/adaq4380-4.html | ||
| 28 | 30 | ||
| 29 | 31 | ||
| 30 | $ref: /schemas/spi/spi-peripheral-props.yaml# | 32 | $ref: /schemas/spi/spi-peripheral-props.yaml# |
| @@ -46,6 +48,8 @@ properties: · 15 unmodified lines | |||
| 46 | - adi,ad7386-4 | 48 | - adi,ad7386-4 |
| 47 | - adi,ad7387-4 | 49 | - adi,ad7387-4 |
| 48 | - adi,ad7388-4 | 50 | - adi,ad7388-4 |
| 51 | - adi,adaq4370-4 | ||
| 52 | - adi,adaq4380-4 | ||
| 49 | 53 | ||
| 50 | reg: | 54 | reg: |
| 51 | maxItems: 1 | 55 | maxItems: 1 |
| @@ -70,6 +74,20 @@ properties: · 18 unmodified lines | |||
| 70 | refin-supply: | 74 | refin-supply: |
| 71 | description: | 75 | description: |
| 72 | A 2.5V to 3.3V supply for external reference voltage, for ad7380-4 only. | 76 | A 2.5V to 3.3V supply for external reference voltage, for ad7380-4 only. |
| 77 | For adaq devices, a 5V supply voltage. A 3.3V internal reference is | ||
| 78 | derived from it. Connect to vs-p-supply for normal operation. | ||
| 79 | |||
| 80 | vs-p-supply: | ||
| 81 | description: | ||
| 82 | Amplifiers positive supply. | ||
| 83 | |||
| 84 | vs-n-supply: | ||
| 85 | description: | ||
| 86 | Amplifiers negative supply. | ||
| 87 | |||
| 88 | ldo-supply: | ||
| 89 | description: | ||
| 90 | LDO supply. Connect to vs-p-supply or a 3.6 to 5.5 V supply. | ||
| 73 | 91 | ||
| 74 | aina-supply: | 92 | aina-supply: |
| 75 | description: | 93 | description: |
| @@ -97,12 +115,45 @@ properties: · 21 unmodified lines | |||
| 97 | specify the ALERT interrupt. | 115 | specify the ALERT interrupt. |
| 98 | maxItems: 1 | 116 | maxItems: 1 |
| 99 | 117 | ||
| 118 | "#address-cells": | ||
| 119 | const: 1 | ||
| 120 | |||
| 121 | "#size-cells": | ||
| 122 | const: 0 | ||
| 123 | |||
| 100 | required: | 124 | required: |
| 101 | - compatible | 125 | - compatible |
| 102 | - reg | 126 | - reg |
| 103 | - vcc-supply | 127 | - vcc-supply |
| 104 | - vlogic-supply | 128 | - vlogic-supply |
| 105 | 129 | ||
| 130 | patternProperties: | ||
| 131 | "^channel@[0-3]$": | ||
| 132 | $ref: adc.yaml | ||
| 133 | type: object | ||
| 134 | |||
| 135 | properties: | ||
| 136 | reg: | ||
| 137 | description: | ||
| 138 | The channel number. From 0 to 3 corresponding to channels A,B,C,D | ||
| 139 | minimum: 0 | ||
| 140 | maximum: 3 | ||
| 141 | |||
| 142 | adi,gain-milli: | ||
| 143 | description: | ||
| 144 | The hardware gain applied to the ADC input (in milli units). | ||
| 145 | If not present, default to 1000 (no actual gain applied). | ||
| 146 | Refer to the typical connection diagrams section of the datasheet for | ||
| 147 | pin wiring. | ||
| 148 | $ref: /schemas/types.yaml#/definitions/uint16 | ||
| 149 | enum: [300, 600, 1000, 1600] | ||
| 150 | default: 1000 | ||
| 151 | |||
| 152 | required: | ||
| 153 | - reg | ||
| 154 | |||
| 155 | additionalProperties: false | ||
| 156 | |||
| 106 | unevaluatedProperties: false | 157 | unevaluatedProperties: false |
| 107 | 158 | ||
| 108 | allOf: | 159 | allOf: |
| @@ -140,6 +191,7 @@ allOf: · 31 unmodified lines | |||
| 140 | aind-supply: false | 191 | aind-supply: false |
| 141 | 192 | ||
| 142 | # ad7380-4 uses refin-supply as external reference. | 193 | # ad7380-4 uses refin-supply as external reference. |
| 194 | # adaq devices use internal reference only, derived from refin-supply | ||
| 143 | # All other chips from ad738x family use refio as optional external reference. | 195 | # All other chips from ad738x family use refio as optional external reference. |
| 144 | # When refio-supply is omitted, internal reference is used. | 196 | # When refio-supply is omitted, internal reference is used. |
| 145 | - if: | 197 | - if: |
| @@ -147,6 +199,8 @@ allOf: · 1 unmodified line | |||
| 147 | compatible: | 199 | compatible: |
| 148 | enum: | 200 | enum: |
| 149 | - adi,ad7380-4 | 201 | - adi,ad7380-4 |
| 202 | - adi,adaq4370-4 | ||
| 203 | - adi,adaq4380-4 | ||
| 150 | then: | 204 | then: |
| 151 | properties: | 205 | properties: |
| 152 | refio-supply: false | 206 | refio-supply: false |
| @@ -156,6 +210,27 @@ allOf: · 3 unmodified lines | |||
| 156 | properties: | 210 | properties: |
| 157 | refin-supply: false | 211 | refin-supply: false |
| 158 | 212 | ||
| 213 | # adaq devices need more supplies and using channel to declare gain property | ||
| 214 | # only applies to adaq devices | ||
| 215 | - if: | ||
| 216 | properties: | ||
| 217 | compatible: | ||
| 218 | enum: | ||
| 219 | - adi,adaq4370-4 | ||
| 220 | - adi,adaq4380-4 | ||
| 221 | then: | ||
| 222 | required: | ||
| 223 | - vs-p-supply | ||
| 224 | - vs-n-supply | ||
| 225 | - ldo-supply | ||
| 226 | else: | ||
| 227 | properties: | ||
| 228 | vs-p-supply: false | ||
| 229 | vs-n-supply: false | ||
| 230 | ldo-supply: false | ||
| 231 | patternProperties: | ||
| 232 | "^channel@[0-3]$": false | ||
| 233 | |||
| 159 | examples: | 234 | examples: |
| 160 | - | | 235 | - | |
| 161 | #include <dt-bindings/interrupt-controller/irq.h> | 236 | #include <dt-bindings/interrupt-controller/irq.h> |
| @@ -180,3 +255,48 @@ examples: · 18 unmodified lines | |||
| 180 | refio-supply = <&supply_2_5V>; | 255 | refio-supply = <&supply_2_5V>; |
| 181 | }; | 256 | }; |
| 182 | }; | 257 | }; |
| 258 | |||
| 259 | - | | ||
| 260 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 261 | |||
| 262 | spi { | ||
| 263 | #address-cells = <1>; | ||
| 264 | #size-cells = <0>; | ||
| 265 | |||
| 266 | adc@0 { | ||
| 267 | compatible = "adi,adaq4380-4"; | ||
| 268 | reg = <0>; | ||
| 269 | |||
| 270 | spi-cpol; | ||
| 271 | spi-cpha; | ||
| 272 | spi-max-frequency = <80000000>; | ||
| 273 | |||
| 274 | interrupts = <27 IRQ_TYPE_EDGE_FALLING>; | ||
| 275 | interrupt-parent = <&gpio0>; | ||
| 276 | |||
| 277 | vcc-supply = <&supply_3_3V>; | ||
| 278 | vlogic-supply = <&supply_3_3V>; | ||
| 279 | refin-supply = <&supply_5V>; | ||
| 280 | vs-p-supply = <&supply_5V>; | ||
| 281 | vs-n-supply = <&supply_0V>; | ||
| 282 | ldo-supply = <&supply_5V>; | ||
| 283 | |||
| 284 | #address-cells = <1>; | ||
| 285 | #size-cells = <0>; | ||
| 286 | |||
| 287 | channel@0 { | ||
| 288 | reg = <0>; | ||
| 289 | adi,gain-milli = /bits/ 16 <300>; | ||
| 290 | }; | ||
| 291 | |||
| 292 | channel@2 { | ||
| 293 | reg = <2>; | ||
| 294 | adi,gain-milli = /bits/ 16 <600>; | ||
| 295 | }; | ||
| 296 | |||
| 297 | channel@3 { | ||
| 298 | reg = <3>; | ||
| 299 | adi,gain-milli = /bits/ 16 <1000>; | ||
| 300 | }; | ||
| 301 | }; | ||
| 302 | }; | ||
| @@ -14,6 +14,11 @@ description: | · 13 unmodified lines | |||
| 14 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD7605-4.pdf | 14 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD7605-4.pdf |
| 15 | https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606_7606-6_7606-4.pdf | 15 | https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606_7606-6_7606-4.pdf |
| 16 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD7606B.pdf | 16 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD7606B.pdf |
| 17 | https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606c-16.pdf | ||
| 18 | https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606c-18.pdf | ||
| 19 | https://www.analog.com/media/en/technical-documentation/data-sheets/ad7607.pdf | ||
| 20 | https://www.analog.com/media/en/technical-documentation/data-sheets/ad7608.pdf | ||
| 21 | https://www.analog.com/media/en/technical-documentation/data-sheets/ad7609.pdf | ||
| 17 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD7616.pdf | 22 | https://www.analog.com/media/en/technical-documentation/data-sheets/AD7616.pdf |
| 18 | 23 | ||
| 19 | properties: | 24 | properties: |
| @@ -24,11 +29,27 @@ properties: · 4 unmodified lines | |||
| 24 | - adi,ad7606-6 | 29 | - adi,ad7606-6 |
| 25 | - adi,ad7606-8 # Referred to as AD7606 (without -8) in the datasheet | 30 | - adi,ad7606-8 # Referred to as AD7606 (without -8) in the datasheet |
| 26 | - adi,ad7606b | 31 | - adi,ad7606b |
| 32 | - adi,ad7606c-16 | ||
| 33 | - adi,ad7606c-18 | ||
| 34 | - adi,ad7607 | ||
| 35 | - adi,ad7608 | ||
| 36 | - adi,ad7609 | ||
| 27 | - adi,ad7616 | 37 | - adi,ad7616 |
| 28 | 38 | ||
| 29 | reg: | 39 | reg: |
| 30 | maxItems: 1 | 40 | maxItems: 1 |
| 31 | 41 | ||
| 42 | "#address-cells": | ||
| 43 | const: 1 | ||
| 44 | |||
| 45 | "#size-cells": | ||
| 46 | const: 0 | ||
| 47 | |||
| 48 | # According to the datasheet, "Data is clocked in from SDI on the falling | ||
| 49 | # edge of SCLK, while data is clocked out on DOUTA on the rising edge of | ||
| 50 | # SCLK". Also, even if not stated textually in the datasheet, it is made | ||
| 51 | # clear on the diagrams that sclk idles at high. Subsequently, in case SPI | ||
| 52 | # interface is used, the correct way is to only set spi-cpol. | ||
| 32 | spi-cpha: true | 53 | spi-cpha: true |
| 33 | 54 | ||
| 34 | spi-cpol: true | 55 | spi-cpol: true |
| @@ -114,18 +135,91 @@ properties: · 79 unmodified lines | |||
| 114 | assumed that the pins are hardwired to VDD. | 135 | assumed that the pins are hardwired to VDD. |
| 115 | type: boolean | 136 | type: boolean |
| 116 | 137 | ||
| 138 | pwms: | ||
| 139 | description: | ||
| 140 | In case the conversion is triggered by a PWM instead of a GPIO plugged to | ||
| 141 | the CONVST pin, the PWM must be referenced. | ||
| 142 | The first is the PWM connected to CONVST or CONVST1 for the chips with the | ||
| 143 | 2nd PWM connected to CONVST2, if CONVST2 is available and not shorted to | ||
| 144 | CONVST1. | ||
| 145 | minItems: 1 | ||
| 146 | maxItems: 2 | ||
| 147 | |||
| 148 | pwm-names: | ||
| 149 | items: | ||
| 150 | - const: convst1 | ||
| 151 | - const: convst2 | ||
| 152 | |||
| 153 | io-backends: | ||
| 154 | description: | ||
| 155 | A reference to the iio-backend, which is responsible handling the BUSY | ||
| 156 | pin's falling edge and communication. | ||
| 157 | An example of backend can be found at | ||
| 158 | http://analogdevicesinc.github.io/hdl/library/axi_ad7606x/index.html | ||
| 159 | |||
| 160 | |||
| 161 | patternProperties: | ||
| 162 | "^channel@[1-8]$": | ||
| 163 | type: object | ||
| 164 | $ref: adc.yaml | ||
| 165 | unevaluatedProperties: false | ||
| 166 | |||
| 167 | properties: | ||
| 168 | reg: | ||
| 169 | description: | ||
| 170 | The channel number, as specified in the datasheet (from 1 to 8). | ||
| 171 | minimum: 1 | ||
| 172 | maximum: 8 | ||
| 173 | |||
| 174 | diff-channels: | ||
| 175 | description: | ||
| 176 | Each channel can be configured as a bipolar differential channel. | ||
| 177 | The ADC uses the same positive and negative inputs for this. | ||
| 178 | This property must be specified as 'reg' (or the channel number) for | ||
| 179 | both positive and negative inputs (i.e. diff-channels = <reg reg>). | ||
| 180 | Since the configuration is bipolar differential, the 'bipolar' | ||
| 181 | property is required. | ||
| 182 | items: | ||
| 183 | minimum: 1 | ||
| 184 | maximum: 8 | ||
| 185 | |||
| 186 | bipolar: | ||
| 187 | description: | ||
| 188 | The ADC channels can be configured as | ||
| 189 | * Bipolar single-ended | ||
| 190 | * Unipolar single-ended | ||
| 191 | * Bipolar differential | ||
| 192 | Therefore in the DT, if no channel node is specified, it is considered | ||
| 193 | 'unipolar single-ended'. So for the other configurations the 'bipolar' | ||
| 194 | property must be specified. If 'diff-channels' is specified, it is | ||
| 195 | considered a bipolar differential channel. Otherwise it is bipolar | ||
| 196 | single-ended. | ||
| 197 | |||
| 198 | required: | ||
| 199 | - reg | ||
| 200 | - bipolar | ||
| 201 | |||
| 117 | required: | 202 | required: |
| 118 | - compatible | 203 | - compatible |
| 119 | - reg | 204 | - reg |
| 120 | - spi-cpha | ||
| 121 | - avcc-supply | 205 | - avcc-supply |
| 122 | - vdrive-supply | 206 | - vdrive-supply |
| 123 | - interrupts | ||
| 124 | - adi,conversion-start-gpios | ||
| 125 | 207 | ||
| 126 | allOf: | 208 | allOf: |
| 127 | - $ref: /schemas/spi/spi-peripheral-props.yaml# | 209 | - $ref: /schemas/spi/spi-peripheral-props.yaml# |
| 128 | 210 | ||
| 211 | - oneOf: | ||
| 212 | - required: | ||
| 213 | - adi,conversion-start-gpios | ||
| 214 | - required: | ||
| 215 | - pwms | ||
| 216 | |||
| 217 | - oneOf: | ||
| 218 | - required: | ||
| 219 | - interrupts | ||
| 220 | - required: | ||
| 221 | - io-backends | ||
| 222 | |||
| 129 | - if: | 223 | - if: |
| 130 | properties: | 224 | properties: |
| 131 | compatible: | 225 | compatible: |
| @@ -162,17 +256,66 @@ allOf: · 30 unmodified lines | |||
| 162 | - adi,ad7606-4 | 256 | - adi,ad7606-4 |
| 163 | - adi,ad7606-6 | 257 | - adi,ad7606-6 |
| 164 | - adi,ad7606-8 | 258 | - adi,ad7606-8 |
| 259 | - adi,ad7607 | ||
| 260 | - adi,ad7608 | ||
| 261 | - adi,ad7609 | ||
| 165 | then: | 262 | then: |
| 166 | properties: | 263 | properties: |
| 167 | adi,sw-mode: false | 264 | adi,sw-mode: false |
| 168 | else: | 265 | else: |
| 169 | properties: | 266 | properties: |
| 267 | pwms: | ||
| 268 | maxItems: 1 | ||
| 269 | pwm-names: | ||
| 270 | maxItems: 1 | ||
| 170 | adi,conversion-start-gpios: | 271 | adi,conversion-start-gpios: |
| 171 | maxItems: 1 | 272 | maxItems: 1 |
| 172 | 273 | ||
| 274 | - if: | ||
| 275 | not: | ||
| 276 | required: | ||
| 277 | - adi,sw-mode | ||
| 278 | then: | ||
| 279 | patternProperties: | ||
| 280 | "^channel@[1-8]$": false | ||
| 281 | |||
| 282 | - if: | ||
| 283 | not: | ||
| 284 | properties: | ||
| 285 | compatible: | ||
| 286 | enum: | ||
| 287 | - adi,ad7606c-16 | ||
| 288 | - adi,ad7606c-18 | ||
| 289 | then: | ||
| 290 | patternProperties: | ||
| 291 | "^channel@[1-8]$": false | ||
| 292 | |||
| 173 | unevaluatedProperties: false | 293 | unevaluatedProperties: false |
| 174 | 294 | ||
| 175 | examples: | 295 | examples: |
| 296 | - | | ||
| 297 | #include <dt-bindings/gpio/gpio.h> | ||
| 298 | iio-backend { | ||
| 299 | #address-cells = <1>; | ||
| 300 | #size-cells = <0>; | ||
| 301 | adi_adc@0 { | ||
| 302 | compatible = "adi,ad7606b"; | ||
| 303 | reg = <0>; | ||
| 304 | pwms = <&axi_pwm_gen 0 0>; | ||
| 305 | |||
| 306 | avcc-supply = <&adc_vref>; | ||
| 307 | vdrive-supply = <&vdd_supply>; | ||
| 308 | |||
| 309 | reset-gpios = <&gpio0 91 GPIO_ACTIVE_HIGH>; | ||
| 310 | standby-gpios = <&gpio0 90 GPIO_ACTIVE_LOW>; | ||
| 311 | adi,range-gpios = <&gpio0 89 GPIO_ACTIVE_HIGH>; | ||
| 312 | adi,oversampling-ratio-gpios = <&gpio0 88 GPIO_ACTIVE_HIGH | ||
| 313 | &gpio0 87 GPIO_ACTIVE_HIGH | ||
| 314 | &gpio0 86 GPIO_ACTIVE_HIGH>; | ||
| 315 | io-backends = <&iio_backend>; | ||
| 316 | }; | ||
| 317 | }; | ||
| 318 | |||
| 176 | - | | 319 | - | |
| 177 | #include <dt-bindings/gpio/gpio.h> | 320 | #include <dt-bindings/gpio/gpio.h> |
| 178 | #include <dt-bindings/interrupt-controller/irq.h> | 321 | #include <dt-bindings/interrupt-controller/irq.h> |
| @@ -185,7 +328,6 @@ examples: · 6 unmodified lines | |||
| 185 | reg = <0>; | 328 | reg = <0>; |
| 186 | spi-max-frequency = <1000000>; | 329 | spi-max-frequency = <1000000>; |
| 187 | spi-cpol; | 330 | spi-cpol; |
| 188 | spi-cpha; | ||
| 189 | 331 | ||
| 190 | avcc-supply = <&adc_vref>; | 332 | avcc-supply = <&adc_vref>; |
| 191 | vdrive-supply = <&vdd_supply>; | 333 | vdrive-supply = <&vdd_supply>; |
| @@ -202,4 +344,53 @@ examples: · 10 unmodified lines | |||
| 202 | standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>; | 344 | standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>; |
| 203 | }; | 345 | }; |
| 204 | }; | 346 | }; |
| 347 | - | | ||
| 348 | #include <dt-bindings/gpio/gpio.h> | ||
| 349 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 350 | spi { | ||
| 351 | #address-cells = <1>; | ||
| 352 | #size-cells = <0>; | ||
| 353 | |||
| 354 | adc@0 { | ||
| 355 | compatible = "adi,ad7606c-18"; | ||
| 356 | reg = <0>; | ||
| 357 | |||
| 358 | #address-cells = <1>; | ||
| 359 | #size-cells = <0>; | ||
| 360 | |||
| 361 | spi-max-frequency = <1000000>; | ||
| 362 | spi-cpol; | ||
| 363 | |||
| 364 | avcc-supply = <&adc_vref>; | ||
| 365 | vdrive-supply = <&vdd_supply>; | ||
| 366 | |||
| 367 | interrupts = <25 IRQ_TYPE_EDGE_FALLING>; | ||
| 368 | interrupt-parent = <&gpio>; | ||
| 369 | |||
| 370 | adi,conversion-start-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; | ||
| 371 | reset-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>; | ||
| 372 | adi,first-data-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; | ||
| 373 | standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>; | ||
| 374 | |||
| 375 | adi,sw-mode; | ||
| 376 | |||
| 377 | channel@1 { | ||
| 378 | reg = <1>; | ||
| 379 | diff-channels = <1 1>; | ||
| 380 | bipolar; | ||
| 381 | }; | ||
| 382 | |||
| 383 | channel@3 { | ||
| 384 | reg = <3>; | ||
| 385 | bipolar; | ||
| 386 | }; | ||
| 387 | |||
| 388 | channel@8 { | ||
| 389 | reg = <8>; | ||
| 390 | diff-channels = <8 8>; | ||
| 391 | bipolar; | ||
| 392 | }; | ||
| 393 | |||
| 394 | }; | ||
| 395 | }; | ||
| 205 | ... | 396 | ... |
| @@ -0,0 +1,176 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/adc/adi,ad7625.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Analog Devices Fast PulSAR Analog to Digital Converters | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Michael Hennerich <Michael.Hennerich@analog.com> | ||
| 11 | - Nuno Sá <nuno.sa@analog.com> | ||
| 12 | |||
| 13 | description: | | ||
| 14 | A family of single channel differential analog to digital converters. | ||
| 15 | |||
| 16 | * https://www.analog.com/en/products/ad7625.html | ||
| 17 | * https://www.analog.com/en/products/ad7626.html | ||
| 18 | * https://www.analog.com/en/products/ad7960.html | ||
| 19 | * https://www.analog.com/en/products/ad7961.html | ||
| 20 | |||
| 21 | properties: | ||
| 22 | compatible: | ||
| 23 | enum: | ||
| 24 | - adi,ad7625 | ||
| 25 | - adi,ad7626 | ||
| 26 | - adi,ad7960 | ||
| 27 | - adi,ad7961 | ||
| 28 | |||
| 29 | vdd1-supply: true | ||
| 30 | vdd2-supply: true | ||
| 31 | vio-supply: true | ||
| 32 | |||
| 33 | ref-supply: | ||
| 34 | description: | ||
| 35 | Voltage regulator for the external reference voltage (REF). | ||
| 36 | |||
| 37 | refin-supply: | ||
| 38 | description: | ||
| 39 | Voltage regulator for the reference buffer input (REFIN). | ||
| 40 | |||
| 41 | clocks: | ||
| 42 | description: | ||
| 43 | The clock connected to the CLK pins, gated by the clk_gate PWM. | ||
| 44 | maxItems: 1 | ||
| 45 | |||
| 46 | pwms: | ||
| 47 | items: | ||
| 48 | - description: PWM connected to the CNV input on the ADC. | ||
| 49 | - description: PWM that gates the clock connected to the ADC's CLK input. | ||
| 50 | |||
| 51 | pwm-names: | ||
| 52 | items: | ||
| 53 | - const: cnv | ||
| 54 | - const: clk_gate | ||
| 55 | |||
| 56 | io-backends: | ||
| 57 | description: | ||
| 58 | The AXI ADC IP block connected to the D+/- and DCO+/- lines of the | ||
| 59 | ADC. An example backend can be found at | ||
| 60 | http://analogdevicesinc.github.io/hdl/projects/pulsar_lvds/index.html. | ||
| 61 | maxItems: 1 | ||
| 62 | |||
| 63 | adi,no-dco: | ||
| 64 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 65 | description: | ||
| 66 | Indicates the wiring of the DCO+/- lines. If true, then they are | ||
| 67 | grounded and the device is in self-clocked mode. If this is not | ||
| 68 | present, then the device is in echoed clock mode. | ||
| 69 | |||
| 70 | adi,en0-always-on: | ||
| 71 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 72 | description: | ||
| 73 | Indicates if EN0 is hard-wired to the high state. If neither this | ||
| 74 | nor en0-gpios are present, then EN0 is hard-wired low. | ||
| 75 | |||
| 76 | adi,en1-always-on: | ||
| 77 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 78 | description: | ||
| 79 | Indicates if EN1 is hard-wired to the high state. If neither this | ||
| 80 | nor en1-gpios are present, then EN1 is hard-wired low. | ||
| 81 | |||
| 82 | adi,en2-always-on: | ||
| 83 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 84 | description: | ||
| 85 | Indicates if EN2 is hard-wired to the high state. If neither this | ||
| 86 | nor en2-gpios are present, then EN2 is hard-wired low. | ||
| 87 | |||
| 88 | adi,en3-always-on: | ||
| 89 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 90 | description: | ||
| 91 | Indicates if EN3 is hard-wired to the high state. If neither this | ||
| 92 | nor en3-gpios are present, then EN3 is hard-wired low. | ||
| 93 | |||
| 94 | en0-gpios: | ||
| 95 | description: | ||
| 96 | Configurable EN0 pin. | ||
| 97 | |||
| 98 | en1-gpios: | ||
| 99 | description: | ||
| 100 | Configurable EN1 pin. | ||
| 101 | |||
| 102 | en2-gpios: | ||
| 103 | description: | ||
| 104 | Configurable EN2 pin. | ||
| 105 | |||
| 106 | en3-gpios: | ||
| 107 | description: | ||
| 108 | Configurable EN3 pin. | ||
| 109 | |||
| 110 | required: | ||
| 111 | - compatible | ||
| 112 | - vdd1-supply | ||
| 113 | - vdd2-supply | ||
| 114 | - vio-supply | ||
| 115 | - clocks | ||
| 116 | - pwms | ||
| 117 | - pwm-names | ||
| 118 | - io-backends | ||
| 119 | |||
| 120 | allOf: | ||
| 121 | - if: | ||
| 122 | required: | ||
| 123 | - ref-supply | ||
| 124 | then: | ||
| 125 | properties: | ||
| 126 | refin-supply: false | ||
| 127 | - if: | ||
| 128 | required: | ||
| 129 | - refin-supply | ||
| 130 | then: | ||
| 131 | properties: | ||
| 132 | ref-supply: false | ||
| 133 | - if: | ||
| 134 | properties: | ||
| 135 | compatible: | ||
| 136 | contains: | ||
| 137 | enum: | ||
| 138 | - adi,ad7625 | ||
| 139 | - adi,ad7626 | ||
| 140 | then: | ||
| 141 | properties: | ||
| 142 | en2-gpios: false | ||
| 143 | en3-gpios: false | ||
| 144 | adi,en2-always-on: false | ||
| 145 | adi,en3-always-on: false | ||
| 146 | |||
| 147 | - if: | ||
| 148 | properties: | ||
| 149 | compatible: | ||
| 150 | contains: | ||
| 151 | enum: | ||
| 152 | - adi,ad7960 | ||
| 153 | - adi,ad7961 | ||
| 154 | then: | ||
| 155 | # ad796x parts must have one of the two supplies | ||
| 156 | oneOf: | ||
| 157 | - required: [ref-supply] | ||
| 158 | - required: [refin-supply] | ||
| 159 | |||
| 160 | additionalProperties: false | ||
| 161 | |||
| 162 | examples: | ||
| 163 | - | | ||
| 164 | #include <dt-bindings/gpio/gpio.h> | ||
| 165 | adc { | ||
| 166 | compatible = "adi,ad7625"; | ||
| 167 | vdd1-supply = <&supply_5V>; | ||
| 168 | vdd2-supply = <&supply_2_5V>; | ||
| 169 | vio-supply = <&supply_2_5V>; | ||
| 170 | io-backends = <&axi_adc>; | ||
| 171 | clocks = <&ref_clk>; | ||
| 172 | pwms = <&axi_pwm_gen 0 0>, <&axi_pwm_gen 1 0>; | ||
| 173 | pwm-names = "cnv", "clk_gate"; | ||
| 174 | en0-gpios = <&gpio0 86 GPIO_ACTIVE_HIGH>; | ||
| 175 | en1-gpios = <&gpio0 87 GPIO_ACTIVE_HIGH>; | ||
| 176 | }; | ||
| @@ -0,0 +1,110 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/adc/adi,ad7779.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Analog Devices AD777X family 8-Channel, 24-Bit, Simultaneous Sampling ADCs | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Ramona Nechita <ramona.nechita@analog.com> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | The AD777X family consist of 8-channel, simultaneous sampling analog-to- | ||
| 14 | digital converter (ADC). Eight full Σ-Δ ADCs are on-chip. The | ||
| 15 | AD7771 provides an ultralow input current to allow direct sensor | ||
| 16 | connection. Each input channel has a programmable gain stage | ||
| 17 | allowing gains of 1, 2, 4, and 8 to map lower amplitude sensor | ||
| 18 | outputs into the full-scale ADC input range, maximizing the | ||
| 19 | dynamic range of the signal chain. | ||
| 20 | |||
| 21 | https://www.analog.com/media/en/technical-documentation/data-sheets/ad7770.pdf | ||
| 22 | https://www.analog.com/media/en/technical-documentation/data-sheets/ad7771.pdf | ||
| 23 | https://www.analog.com/media/en/technical-documentation/data-sheets/ad7779.pdf | ||
| 24 | |||
| 25 | $ref: /schemas/spi/spi-peripheral-props.yaml# | ||
| 26 | |||
| 27 | properties: | ||
| 28 | compatible: | ||
| 29 | enum: | ||
| 30 | - adi,ad7770 | ||
| 31 | - adi,ad7771 | ||
| 32 | - adi,ad7779 | ||
| 33 | |||
| 34 | reg: | ||
| 35 | maxItems: 1 | ||
| 36 | |||
| 37 | '#address-cells': | ||
| 38 | const: 1 | ||
| 39 | |||
| 40 | '#size-cells': | ||
| 41 | const: 0 | ||
| 42 | |||
| 43 | clocks: | ||
| 44 | maxItems: 1 | ||
| 45 | |||
| 46 | avdd1-supply: | ||
| 47 | description: Front-End analog supply AVDD1. Can be used as conversion ref. | ||
| 48 | |||
| 49 | avdd2-supply: | ||
| 50 | description: AVDD2 Analog Supply from 2.2 V to 3.6 V. | ||
| 51 | |||
| 52 | avdd4-supply: | ||
| 53 | description: AVDD4 SAR Analog Supply and Reference Source. | ||
| 54 | |||
| 55 | interrupts: | ||
| 56 | minItems: 1 | ||
| 57 | items: | ||
| 58 | - description: | | ||
| 59 | adc_rdy: Interrupt line for DRDY signal which indicates the end of | ||
| 60 | conversion independently of the interface selected to read back the | ||
| 61 | Σ-∆ conversion. | ||
| 62 | - description: | | ||
| 63 | Alert: The chip includes self diagnostic features to guarantee the | ||
| 64 | correct operation. If an error is detected, the ALERT pin is pulled | ||
| 65 | high to generate an external interruption to the controller. | ||
| 66 | |||
| 67 | interrupt-names: | ||
| 68 | minItems: 1 | ||
| 69 | maxItems: 2 | ||
| 70 | items: | ||
| 71 | enum: | ||
| 72 | - adc_rdy | ||
| 73 | - alert | ||
| 74 | |||
| 75 | start-gpios: | ||
| 76 | description: | ||
| 77 | Pin that controls start synchronization pulse. | ||
| 78 | maxItems: 1 | ||
| 79 | |||
| 80 | reset-gpios: | ||
| 81 | maxItems: 1 | ||
| 82 | |||
| 83 | required: | ||
| 84 | - compatible | ||
| 85 | - reg | ||
| 86 | - clocks | ||
| 87 | - interrupts | ||
| 88 | |||
| 89 | unevaluatedProperties: false | ||
| 90 | |||
| 91 | examples: | ||
| 92 | - | | ||
| 93 | #include <dt-bindings/gpio/gpio.h> | ||
| 94 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 95 | spi { | ||
| 96 | #address-cells = <1>; | ||
| 97 | #size-cells = <0>; | ||
| 98 | |||
| 99 | adc@0 { | ||
| 100 | compatible = "adi,ad7779"; | ||
| 101 | reg = <0>; | ||
| 102 | start-gpios = <&gpio0 87 GPIO_ACTIVE_LOW>; | ||
| 103 | reset-gpios = <&gpio0 93 GPIO_ACTIVE_LOW>; | ||
| 104 | interrupt-parent = <&intc>; | ||
| 105 | interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>; | ||
| 106 | interrupt-names = "adc_rdy"; | ||
| 107 | clocks = <&adc_clk>; | ||
| 108 | }; | ||
| 109 | }; | ||
| 110 | ... | ||
| @@ -98,6 +98,7 @@ allOf: · 97 unmodified lines | |||
| 98 | compatible: | 98 | compatible: |
| 99 | contains: | 99 | contains: |
| 100 | enum: | 100 | enum: |
| 101 | - amlogic,meson8-saradc | ||
| 101 | - amlogic,meson8b-saradc | 102 | - amlogic,meson8b-saradc |
| 102 | - amlogic,meson8m2-saradc | 103 | - amlogic,meson8m2-saradc |
| 103 | then: | 104 | then: |
| @@ -0,0 +1,86 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/adc/gehc,pmc-adc.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: GE HealthCare PMC Analog to Digital Converter (ADC) | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Herve Codina <herve.codina@bootlin.com> | ||
| 11 | |||
| 12 | description: | ||
| 13 | The GE HealthCare PMC ADC is a 16-Channel (voltage and current), 16-Bit ADC | ||
| 14 | with an I2C Interface. | ||
| 15 | |||
| 16 | properties: | ||
| 17 | compatible: | ||
| 18 | const: gehc,pmc-adc | ||
| 19 | |||
| 20 | reg: | ||
| 21 | maxItems: 1 | ||
| 22 | |||
| 23 | vdd-supply: | ||
| 24 | description: | ||
| 25 | Regulator for the VDD power supply. | ||
| 26 | |||
| 27 | vdda-supply: | ||
| 28 | description: | ||
| 29 | Regulator for the VDD analog (VDDA) power supply. | ||
| 30 | |||
| 31 | vddio-supply: | ||
| 32 | description: | ||
| 33 | Regulator for the VDD IO (VDDIO) power supply. | ||
| 34 | |||
| 35 | vref-supply: | ||
| 36 | description: | ||
| 37 | Regulator for the voltage reference power supply. | ||
| 38 | |||
| 39 | clocks: | ||
| 40 | maxItems: 1 | ||
| 41 | description: | ||
| 42 | The component uses an external oscillator (osc) if an external oscillator | ||
| 43 | is connected to its clock pins. Otherwise, it uses an internal reference | ||
| 44 | clock. | ||
| 45 | |||
| 46 | clock-names: | ||
| 47 | items: | ||
| 48 | - const: osc | ||
| 49 | |||
| 50 | "#io-channel-cells": | ||
| 51 | const: 2 | ||
| 52 | description: | | ||
| 53 | The first cell is the channel type (dt-bindings/iio/adc/gehc,pmc-adc.h | ||
| 54 | defines these values): | ||
| 55 | - 0: voltage | ||
| 56 | - 1: current | ||
| 57 | The second cell is the channel number from 0 to 15. | ||
| 58 | |||
| 59 | required: | ||
| 60 | - compatible | ||
| 61 | - reg | ||
| 62 | - vdd-supply | ||
| 63 | - vdda-supply | ||
| 64 | - vddio-supply | ||
| 65 | - vref-supply | ||
| 66 | - '#io-channel-cells' | ||
| 67 | |||
| 68 | additionalProperties: false | ||
| 69 | |||
| 70 | examples: | ||
| 71 | - | | ||
| 72 | i2c { | ||
| 73 | #address-cells = <1>; | ||
| 74 | #size-cells = <0>; | ||
| 75 | |||
| 76 | adc@14 { | ||
| 77 | compatible = "gehc,pmc-adc"; | ||
| 78 | reg = <0x14>; | ||
| 79 | vdd-supply = <®_vdd>; | ||
| 80 | vdda-supply = <®_vdda>; | ||
| 81 | vddio-supply = <®_vddio>; | ||
| 82 | vref-supply = <®_vref>; | ||
| 83 | #io-channel-cells = <2>; | ||
| 84 | }; | ||
| 85 | }; | ||
| 86 | ... | ||
| @@ -30,7 +30,7 @@ properties: · 29 unmodified lines | |||
| 30 | maxItems: 1 | 30 | maxItems: 1 |
| 31 | 31 | ||
| 32 | spi-max-frequency: | 32 | spi-max-frequency: |
| 33 | maximum: 30000000 | 33 | maximum: 66000000 |
| 34 | 34 | ||
| 35 | reset-gpios: | 35 | reset-gpios: |
| 36 | maxItems: 1 | 36 | maxItems: 1 |
| @@ -60,6 +60,12 @@ properties: · 23 unmodified lines | |||
| 60 | $ref: /schemas/types.yaml#/definitions/uint32 | 60 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 61 | enum: [0, 1, 2, 3] | 61 | enum: [0, 1, 2, 3] |
| 62 | 62 | ||
| 63 | io-backends: | ||
| 64 | description: The iio backend reference. | ||
| 65 | Device can be optionally connected to the "axi-ad3552r IP" fpga-based | ||
| 66 | QSPI + DDR (Double Data Rate) controller to reach high speed transfers. | ||
| 67 | maxItems: 1 | ||
| 68 | |||
| 63 | '#address-cells': | 69 | '#address-cells': |
| 64 | const: 1 | 70 | const: 1 |
| 65 | 71 | ||
| @@ -128,6 +134,7 @@ patternProperties: · 62 unmodified lines | |||
| 128 | - custom-output-range-config | 134 | - custom-output-range-config |
| 129 | 135 | ||
| 130 | allOf: | 136 | allOf: |
| 137 | - $ref: /schemas/spi/spi-peripheral-props.yaml# | ||
| 131 | - if: | 138 | - if: |
| 132 | properties: | 139 | properties: |
| 133 | compatible: | 140 | compatible: |
| @@ -26,16 +26,47 @@ properties: · 25 unmodified lines | |||
| 26 | vdd-supply: true | 26 | vdd-supply: true |
| 27 | vss-supply: true | 27 | vss-supply: true |
| 28 | 28 | ||
| 29 | vcc-supply: | ||
| 30 | description: | ||
| 31 | Supply that powers the chip. | ||
| 32 | |||
| 33 | iovcc-supply: | ||
| 34 | description: | ||
| 35 | Supply for the digital interface. | ||
| 36 | |||
| 37 | vrefp-supply: | ||
| 38 | description: | ||
| 39 | Positive referance input voltage range. From 5v to (vdd - 2.5) | ||
| 40 | |||
| 41 | vrefn-supply: | ||
| 42 | description: | ||
| 43 | Negative referance input voltage range. From (vss + 2.5) to 0. | ||
| 44 | |||
| 29 | adi,rbuf-gain2-en: | 45 | adi,rbuf-gain2-en: |
| 30 | description: Specify to allow an external amplifier to be connected in a | 46 | description: Specify to allow an external amplifier to be connected in a |
| 31 | gain of two configuration. | 47 | gain of two configuration. |
| 32 | type: boolean | 48 | type: boolean |
| 33 | 49 | ||
| 50 | reset-gpios: | ||
| 51 | maxItems: 1 | ||
| 52 | |||
| 53 | clear-gpios: | ||
| 54 | maxItems: 1 | ||
| 55 | |||
| 56 | ldac-gpios: | ||
| 57 | description: | ||
| 58 | LDAC pin to be used as a hardware trigger to update the DAC channels. | ||
| 59 | maxItems: 1 | ||
| 60 | |||
| 34 | required: | 61 | required: |
| 35 | - compatible | 62 | - compatible |
| 36 | - reg | 63 | - reg |
| 37 | - vdd-supply | 64 | - vdd-supply |
| 38 | - vss-supply | 65 | - vss-supply |
| 66 | - vcc-supply | ||
| 67 | - iovcc-supply | ||
| 68 | - vrefp-supply | ||
| 69 | - vrefn-supply | ||
| 39 | 70 | ||
| 40 | allOf: | 71 | allOf: |
| 41 | - $ref: /schemas/spi/spi-peripheral-props.yaml# | 72 | - $ref: /schemas/spi/spi-peripheral-props.yaml# |
| @@ -44,6 +75,7 @@ unevaluatedProperties: false · 2 unmodified lines | |||
| 44 | 75 | ||
| 45 | examples: | 76 | examples: |
| 46 | - | | 77 | - | |
| 78 | #include <dt-bindings/gpio/gpio.h> | ||
| 47 | spi { | 79 | spi { |
| 48 | #address-cells = <1>; | 80 | #address-cells = <1>; |
| 49 | #size-cells = <0>; | 81 | #size-cells = <0>; |
| @@ -53,6 +85,13 @@ examples: · 3 unmodified lines | |||
| 53 | reg = <0>; | 85 | reg = <0>; |
| 54 | vss-supply = <&dac_vss>; | 86 | vss-supply = <&dac_vss>; |
| 55 | vdd-supply = <&dac_vdd>; | 87 | vdd-supply = <&dac_vdd>; |
| 88 | vcc-supply = <&dac_vcc>; | ||
| 89 | iovcc-supply = <&dac_iovcc>; | ||
| 90 | vrefp-supply = <&dac_vrefp>; | ||
| 91 | vrefn-supply = <&dac_vrefn>; | ||
| 92 | reset-gpios = <&gpio_bd 16 GPIO_ACTIVE_LOW>; | ||
| 93 | clear-gpios = <&gpio_bd 17 GPIO_ACTIVE_LOW>; | ||
| 94 | ldac-gpios = <&gpio_bd 18 GPIO_ACTIVE_HIGH>; | ||
| 56 | }; | 95 | }; |
| 57 | }; | 96 | }; |
| 58 | ... | 97 | ... |
| @@ -0,0 +1,164 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | # Copyright 2024 Analog Devices Inc. | ||
| 3 | %YAML 1.2 | ||
| 4 | --- | ||
| 5 | $id: http://devicetree.org/schemas/iio/dac/adi,ad8460.yaml# | ||
| 6 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 7 | |||
| 8 | title: Analog Devices AD8460 DAC | ||
| 9 | |||
| 10 | maintainers: | ||
| 11 | - Mariel Tinaco <mariel.tinaco@analog.com> | ||
| 12 | |||
| 13 | description: | | ||
| 14 | Analog Devices AD8460 110 V High Voltage, 1 A High Current, | ||
| 15 | Arbitrary Waveform Generator with Integrated 14-Bit High Speed DAC | ||
| 16 | https://www.analog.com/media/en/technical-documentation/data-sheets/ad8460.pdf | ||
| 17 | |||
| 18 | properties: | ||
| 19 | compatible: | ||
| 20 | enum: | ||
| 21 | - adi,ad8460 | ||
| 22 | |||
| 23 | reg: | ||
| 24 | maxItems: 1 | ||
| 25 | |||
| 26 | clocks: | ||
| 27 | maxItems: 1 | ||
| 28 | |||
| 29 | dmas: | ||
| 30 | maxItems: 1 | ||
| 31 | |||
| 32 | dma-names: | ||
| 33 | items: | ||
| 34 | - const: tx | ||
| 35 | |||
| 36 | spi-max-frequency: | ||
| 37 | maximum: 20000000 | ||
| 38 | |||
| 39 | hvcc-supply: | ||
| 40 | description: Positive high voltage power supply line | ||
| 41 | |||
| 42 | hvee-supply: | ||
| 43 | description: Negative high voltage power supply line | ||
| 44 | |||
| 45 | vcc-5v-supply: | ||
| 46 | description: Low voltage power supply | ||
| 47 | |||
| 48 | vref-5v-supply: | ||
| 49 | description: Reference voltage for analog low voltage | ||
| 50 | |||
| 51 | dvdd-3p3v-supply: | ||
| 52 | description: Digital supply bypass | ||
| 53 | |||
| 54 | avdd-3p3v-supply: | ||
| 55 | description: Analog supply bypass | ||
| 56 | |||
| 57 | refio-1p2v-supply: | ||
| 58 | description: Drive voltage in the range of 1.2V maximum to as low as | ||
| 59 | low as 0.12V through the REF_IO pin to adjust full scale output span | ||
| 60 | |||
| 61 | adi,external-resistor-ohms: | ||
| 62 | description: Specify value of external resistor connected to FS_ADJ pin | ||
| 63 | to establish internal HVDAC's reference current I_REF | ||
| 64 | minimum: 2000 | ||
| 65 | maximum: 20000 | ||
| 66 | default: 2000 | ||
| 67 | |||
| 68 | adi,range-microvolt: | ||
| 69 | description: Voltage output range specified as <minimum, maximum> | ||
| 70 | items: | ||
| 71 | - minimum: -55000000 | ||
| 72 | maximum: 0 | ||
| 73 | default: 0 | ||
| 74 | - minimum: 0 | ||
| 75 | maximum: 55000000 | ||
| 76 | default: 0 | ||
| 77 | |||
| 78 | adi,range-microamp: | ||
| 79 | description: Current output range specified as <minimum, maximum> | ||
| 80 | items: | ||
| 81 | - minimum: -1000000 | ||
| 82 | maximum: 0 | ||
| 83 | default: 0 | ||
| 84 | - minimum: 0 | ||
| 85 | maximum: 1000000 | ||
| 86 | default: 0 | ||
| 87 | |||
| 88 | adi,max-millicelsius: | ||
| 89 | description: Overtemperature threshold | ||
| 90 | minimum: 0 | ||
| 91 | maximum: 150000 | ||
| 92 | default: 0 | ||
| 93 | |||
| 94 | shutdown-reset-gpios: | ||
| 95 | description: Corresponds to SDN_RESET pin. To exit shutdown | ||
| 96 | or sleep mode, pulse SDN_RESET HIGH, then leave LOW. | ||
| 97 | maxItems: 1 | ||
| 98 | |||
| 99 | reset-gpios: | ||
| 100 | description: Manual Power On Reset (POR). Pull this GPIO pin | ||
| 101 | LOW and then HIGH to reset all digital registers to default | ||
| 102 | maxItems: 1 | ||
| 103 | |||
| 104 | shutdown-gpios: | ||
| 105 | description: Corresponds to SDN_IO pin. Shutdown may be | ||
| 106 | initiated by the user, by pulsing SDN_IO high. To exit shutdown, | ||
| 107 | pulse SDN_IO low, then float. | ||
| 108 | maxItems: 1 | ||
| 109 | |||
| 110 | required: | ||
| 111 | - compatible | ||
| 112 | - reg | ||
| 113 | - clocks | ||
| 114 | - hvcc-supply | ||
| 115 | - hvee-supply | ||
| 116 | - vcc-5v-supply | ||
| 117 | - vref-5v-supply | ||
| 118 | - dvdd-3p3v-supply | ||
| 119 | - avdd-3p3v-supply | ||
| 120 | - refio-1p2v-supply | ||
| 121 | |||
| 122 | allOf: | ||
| 123 | - $ref: /schemas/spi/spi-peripheral-props.yaml# | ||
| 124 | |||
| 125 | unevaluatedProperties: false | ||
| 126 | |||
| 127 | examples: | ||
| 128 | - | | ||
| 129 | #include <dt-bindings/gpio/gpio.h> | ||
| 130 | |||
| 131 | spi { | ||
| 132 | #address-cells = <1>; | ||
| 133 | #size-cells = <0>; | ||
| 134 | |||
| 135 | dac@0 { | ||
| 136 | compatible = "adi,ad8460"; | ||
| 137 | reg = <0>; | ||
| 138 | spi-max-frequency = <8000000>; | ||
| 139 | |||
| 140 | dmas = <&tx_dma 0>; | ||
| 141 | dma-names = "tx"; | ||
| 142 | |||
| 143 | shutdown-reset-gpios = <&gpio 86 GPIO_ACTIVE_HIGH>; | ||
| 144 | reset-gpios = <&gpio 91 GPIO_ACTIVE_LOW>; | ||
| 145 | shutdown-gpios = <&gpio 88 GPIO_ACTIVE_HIGH>; | ||
| 146 | |||
| 147 | clocks = <&sync_ext_clk>; | ||
| 148 | |||
| 149 | hvcc-supply = <&hvcc>; | ||
| 150 | hvee-supply = <&hvee>; | ||
| 151 | vcc-5v-supply = <&vcc_5>; | ||
| 152 | vref-5v-supply = <&vref_5>; | ||
| 153 | dvdd-3p3v-supply = <&dvdd_3_3>; | ||
| 154 | avdd-3p3v-supply = <&avdd_3_3>; | ||
| 155 | refio-1p2v-supply = <&refio_1_2>; | ||
| 156 | |||
| 157 | adi,external-resistor-ohms = <2000>; | ||
| 158 | adi,range-microvolt = <(-40000000) 40000000>; | ||
| 159 | adi,range-microamp = <0 50000>; | ||
| 160 | adi,max-millicelsius = <50000>; | ||
| 161 | }; | ||
| 162 | }; | ||
| 163 | |||
| 164 | ... | ||
| @@ -19,11 +19,13 @@ description: | · 18 unmodified lines | |||
| 19 | memory via DMA into the DAC. | 19 | memory via DMA into the DAC. |
| 20 | 20 | ||
| 21 | https://wiki.analog.com/resources/fpga/docs/axi_dac_ip | 21 | https://wiki.analog.com/resources/fpga/docs/axi_dac_ip |
| 22 | https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html | ||
| 22 | 23 | ||
| 23 | properties: | 24 | properties: |
| 24 | compatible: | 25 | compatible: |
| 25 | enum: | 26 | enum: |
| 26 | - adi,axi-dac-9.1.b | 27 | - adi,axi-dac-9.1.b |
| 28 | - adi,axi-ad3552r | ||
| 27 | 29 | ||
| 28 | reg: | 30 | reg: |
| 29 | maxItems: 1 | 31 | maxItems: 1 |
| @@ -36,7 +38,14 @@ properties: · 6 unmodified lines | |||
| 36 | - const: tx | 38 | - const: tx |
| 37 | 39 | ||
| 38 | clocks: | 40 | clocks: |
| 39 | maxItems: 1 | 41 | minItems: 1 |
| 42 | maxItems: 2 | ||
| 43 | |||
| 44 | clock-names: | ||
| 45 | items: | ||
| 46 | - const: s_axi_aclk | ||
| 47 | - const: dac_clk | ||
| 48 | minItems: 1 | ||
| 40 | 49 | ||
| 41 | '#io-backend-cells': | 50 | '#io-backend-cells': |
| 42 | const: 0 | 51 | const: 0 |
| @@ -47,7 +56,29 @@ required: · 4 unmodified lines | |||
| 47 | - reg | 56 | - reg |
| 48 | - clocks | 57 | - clocks |
| 49 | 58 | ||
| 50 | additionalProperties: false | 59 | allOf: |
| 60 | - if: | ||
| 61 | properties: | ||
| 62 | compatible: | ||
| 63 | contains: | ||
| 64 | const: adi,axi-ad3552r | ||
| 65 | then: | ||
| 66 | $ref: /schemas/spi/spi-controller.yaml# | ||
| 67 | properties: | ||
| 68 | clocks: | ||
| 69 | minItems: 2 | ||
| 70 | clock-names: | ||
| 71 | minItems: 2 | ||
| 72 | required: | ||
| 73 | - clock-names | ||
| 74 | else: | ||
| 75 | properties: | ||
| 76 | clocks: | ||
| 77 | maxItems: 1 | ||
| 78 | clock-names: | ||
| 79 | maxItems: 1 | ||
| 80 | |||
| 81 | unevaluatedProperties: false | ||
| 51 | 82 | ||
| 52 | examples: | 83 | examples: |
| 53 | - | | 84 | - | |
| @@ -57,6 +88,38 @@ examples: · 3 unmodified lines | |||
| 57 | dmas = <&tx_dma 0>; | 88 | dmas = <&tx_dma 0>; |
| 58 | dma-names = "tx"; | 89 | dma-names = "tx"; |
| 59 | #io-backend-cells = <0>; | 90 | #io-backend-cells = <0>; |
| 60 | clocks = <&axi_clk>; | 91 | clocks = <&clkc 15>; |
| 92 | clock-names = "s_axi_aclk"; | ||
| 93 | }; | ||
| 94 | |||
| 95 | - | | ||
| 96 | #include <dt-bindings/gpio/gpio.h> | ||
| 97 | axi_dac: spi@44a70000 { | ||
| 98 | compatible = "adi,axi-ad3552r"; | ||
| 99 | reg = <0x44a70000 0x1000>; | ||
| 100 | dmas = <&dac_tx_dma 0>; | ||
| 101 | dma-names = "tx"; | ||
| 102 | #io-backend-cells = <0>; | ||
| 103 | clocks = <&clkc 15>, <&ref_clk>; | ||
| 104 | clock-names = "s_axi_aclk", "dac_clk"; | ||
| 105 | |||
| 106 | #address-cells = <1>; | ||
| 107 | #size-cells = <0>; | ||
| 108 | |||
| 109 | dac@0 { | ||
| 110 | compatible = "adi,ad3552r"; | ||
| 111 | reg = <0>; | ||
| 112 | reset-gpios = <&gpio0 92 GPIO_ACTIVE_HIGH>; | ||
| 113 | io-backends = <&axi_dac>; | ||
| 114 | spi-max-frequency = <20000000>; | ||
| 115 | |||
| 116 | #address-cells = <1>; | ||
| 117 | #size-cells = <0>; | ||
| 118 | |||
| 119 | channel@0 { | ||
| 120 | reg = <0>; | ||
| 121 | adi,output-range-microvolt = <(-10000000) (10000000)>; | ||
| 122 | }; | ||
| 123 | }; | ||
| 61 | }; | 124 | }; |
| 62 | ... | 125 | ... |
| @@ -0,0 +1,79 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/imu/bosch,bmi270.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Bosch BMI270 6-Axis IMU | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Alex Lanzano <lanzano.alex@gmail.com> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | BMI270 is a 6-axis inertial measurement unit that can measure acceleration and | ||
| 14 | angular velocity. The sensor also supports configurable interrupt events such | ||
| 15 | as motion, step counter, and wrist motion gestures. The sensor can communicate | ||
| 16 | I2C or SPI. | ||
| 17 | https://www.bosch-sensortec.com/products/motion-sensors/imus/bmi270/ | ||
| 18 | |||
| 19 | properties: | ||
| 20 | compatible: | ||
| 21 | enum: | ||
| 22 | - bosch,bmi260 | ||
| 23 | - bosch,bmi270 | ||
| 24 | |||
| 25 | reg: | ||
| 26 | maxItems: 1 | ||
| 27 | |||
| 28 | vdd-supply: true | ||
| 29 | vddio-supply: true | ||
| 30 | |||
| 31 | interrupts: | ||
| 32 | minItems: 1 | ||
| 33 | maxItems: 2 | ||
| 34 | |||
| 35 | interrupt-names: | ||
| 36 | minItems: 1 | ||
| 37 | maxItems: 2 | ||
| 38 | items: | ||
| 39 | enum: | ||
| 40 | - INT1 | ||
| 41 | - INT2 | ||
| 42 | |||
| 43 | drive-open-drain: | ||
| 44 | description: | ||
| 45 | set if the specified interrupt pins should be configured as | ||
| 46 | open drain. If not set, defaults to push-pull. | ||
| 47 | |||
| 48 | mount-matrix: | ||
| 49 | description: | ||
| 50 | an optional 3x3 mounting rotation matrix. | ||
| 51 | |||
| 52 | required: | ||
| 53 | - compatible | ||
| 54 | - reg | ||
| 55 | - vdd-supply | ||
| 56 | - vddio-supply | ||
| 57 | |||
| 58 | allOf: | ||
| 59 | - $ref: /schemas/spi/spi-peripheral-props.yaml# | ||
| 60 | |||
| 61 | unevaluatedProperties: false | ||
| 62 | |||
| 63 | examples: | ||
| 64 | - | | ||
| 65 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 66 | i2c { | ||
| 67 | #address-cells = <1>; | ||
| 68 | #size-cells = <0>; | ||
| 69 | |||
| 70 | imu@68 { | ||
| 71 | compatible = "bosch,bmi270"; | ||
| 72 | reg = <0x68>; | ||
| 73 | vdd-supply = <&vdd>; | ||
| 74 | vddio-supply = <&vddio>; | ||
| 75 | interrupt-parent = <&gpio1>; | ||
| 76 | interrupts = <16 IRQ_TYPE_EDGE_RISING>; | ||
| 77 | interrupt-names = "INT1"; | ||
| 78 | }; | ||
| 79 | }; | ||
| @@ -0,0 +1,51 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/imu/bosch,smi240.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Bosch smi240 imu | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Jianping Shen <Jianping.Shen@de.bosch.com> | ||
| 11 | |||
| 12 | description: | ||
| 13 | Inertial Measurement Unit with Accelerometer and Gyroscope | ||
| 14 | with a measurement range of +/-300°/s and up to 16g. | ||
| 15 | https://www.bosch-semiconductors.com/mems-sensors/highly-automated-driving/smi240/ | ||
| 16 | |||
| 17 | properties: | ||
| 18 | compatible: | ||
| 19 | const: bosch,smi240 | ||
| 20 | |||
| 21 | reg: | ||
| 22 | maxItems: 1 | ||
| 23 | |||
| 24 | vdd-supply: true | ||
| 25 | vddio-supply: true | ||
| 26 | |||
| 27 | required: | ||
| 28 | - compatible | ||
| 29 | - reg | ||
| 30 | - vdd-supply | ||
| 31 | - vddio-supply | ||
| 32 | |||
| 33 | allOf: | ||
| 34 | - $ref: /schemas/spi/spi-peripheral-props.yaml# | ||
| 35 | |||
| 36 | unevaluatedProperties: false | ||
| 37 | |||
| 38 | examples: | ||
| 39 | - | | ||
| 40 | spi { | ||
| 41 | #address-cells = <1>; | ||
| 42 | #size-cells = <0>; | ||
| 43 | |||
| 44 | imu@0 { | ||
| 45 | compatible = "bosch,smi240"; | ||
| 46 | reg = <0>; | ||
| 47 | vdd-supply = <&vdd>; | ||
| 48 | vddio-supply = <&vddio>; | ||
| 49 | spi-max-frequency = <10000000>; | ||
| 50 | }; | ||
| 51 | }; | ||
| @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 6 unmodified lines | |||
| 7 | title: InvenSense ICM-426xx Inertial Measurement Unit | 7 | title: InvenSense ICM-426xx Inertial Measurement Unit |
| 8 | 8 | ||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Jean-Baptiste Maneyrol <jmaneyrol@invensense.com> | 10 | - Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> |
| 11 | 11 | ||
| 12 | description: | | 12 | description: | |
| 13 | 6-axis MotionTracking device that combines a 3-axis gyroscope and a 3-axis | 13 | 6-axis MotionTracking device that combines a 3-axis gyroscope and a 3-axis |
| @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 6 unmodified lines | |||
| 7 | title: InvenSense MPU-6050 Six-Axis (Gyro + Accelerometer) MEMS MotionTracking Device | 7 | title: InvenSense MPU-6050 Six-Axis (Gyro + Accelerometer) MEMS MotionTracking Device |
| 8 | 8 | ||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Jean-Baptiste Maneyrol <jmaneyrol@invensense.com> | 10 | - Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> |
| 11 | 11 | ||
| 12 | description: | | 12 | description: | |
| 13 | These devices support both I2C and SPI bus interfaces. | 13 | These devices support both I2C and SPI bus interfaces. |
| @@ -36,6 +36,11 @@ properties: · 22 unmodified lines | |||
| 36 | - items: | 36 | - items: |
| 37 | - const: invensense,icm20608d | 37 | - const: invensense,icm20608d |
| 38 | - const: invensense,icm20608 | 38 | - const: invensense,icm20608 |
| 39 | - items: | ||
| 40 | - enum: | ||
| 41 | - invensense,iam20680hp | ||
| 42 | - invensense,iam20680ht | ||
| 43 | - const: invensense,iam20680 | ||
| 39 | 44 | ||
| 40 | reg: | 45 | reg: |
| 41 | maxItems: 1 | 46 | maxItems: 1 |
| @@ -15,7 +15,9 @@ description: | · 14 unmodified lines | |||
| 15 | 15 | ||
| 16 | properties: | 16 | properties: |
| 17 | compatible: | 17 | compatible: |
| 18 | const: ti,opt3001 | 18 | enum: |
| 19 | - ti,opt3001 | ||
| 20 | - ti,opt3002 | ||
| 19 | 21 | ||
| 20 | reg: | 22 | reg: |
| 21 | maxItems: 1 | 23 | maxItems: 1 |
| @@ -1,64 +0,0 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/light/veml6030.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: VEML6030 Ambient Light Sensor (ALS) | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Rishi Gupta <gupt21@gmail.com> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | Bindings for the ambient light sensor veml6030 from Vishay | ||
| 14 | Semiconductors over an i2c interface. | ||
| 15 | |||
| 16 | Irrespective of whether interrupt is used or not, application | ||
| 17 | can get the ALS and White channel reading from IIO raw interface. | ||
| 18 | |||
| 19 | If the interrupts are used, application will receive an IIO event | ||
| 20 | whenever configured threshold is crossed. | ||
| 21 | |||
| 22 | Specifications about the sensor can be found at: | ||
| 23 | https://www.vishay.com/docs/84366/veml6030.pdf | ||
| 24 | |||
| 25 | properties: | ||
| 26 | compatible: | ||
| 27 | enum: | ||
| 28 | - vishay,veml6030 | ||
| 29 | |||
| 30 | reg: | ||
| 31 | description: | ||
| 32 | I2C address of the device. | ||
| 33 | enum: | ||
| 34 | - 0x10 # ADDR pin pulled down | ||
| 35 | - 0x48 # ADDR pin pulled up | ||
| 36 | |||
| 37 | interrupts: | ||
| 38 | description: | ||
| 39 | interrupt mapping for IRQ. Configure with IRQ_TYPE_LEVEL_LOW. | ||
| 40 | Refer to interrupt-controller/interrupts.txt for generic | ||
| 41 | interrupt client node bindings. | ||
| 42 | maxItems: 1 | ||
| 43 | |||
| 44 | required: | ||
| 45 | - compatible | ||
| 46 | - reg | ||
| 47 | |||
| 48 | additionalProperties: false | ||
| 49 | |||
| 50 | examples: | ||
| 51 | - | | ||
| 52 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 53 | |||
| 54 | i2c { | ||
| 55 | #address-cells = <1>; | ||
| 56 | #size-cells = <0>; | ||
| 57 | |||
| 58 | light-sensor@10 { | ||
| 59 | compatible = "vishay,veml6030"; | ||
| 60 | reg = <0x10>; | ||
| 61 | interrupts = <12 IRQ_TYPE_LEVEL_LOW>; | ||
| 62 | }; | ||
| 63 | }; | ||
| 64 | ... | ||
| @@ -0,0 +1,107 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/light/vishay,veml6030.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: VEML3235, VEML6030, VEML6035 and VEML7700 Ambient Light Sensors (ALS) | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Rishi Gupta <gupt21@gmail.com> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | Bindings for the ambient light sensors veml6030 and veml6035 from | ||
| 14 | Vishay Semiconductors over an i2c interface. | ||
| 15 | |||
| 16 | Irrespective of whether interrupt is used or not, application | ||
| 17 | can get the ALS and White channel reading from IIO raw interface. | ||
| 18 | |||
| 19 | If the interrupts are used, application will receive an IIO event | ||
| 20 | whenever configured threshold is crossed. | ||
| 21 | |||
| 22 | Specifications about the sensors can be found at: | ||
| 23 | https://www.vishay.com/docs/80131/veml3235.pdf | ||
| 24 | https://www.vishay.com/docs/84366/veml6030.pdf | ||
| 25 | https://www.vishay.com/docs/84889/veml6035.pdf | ||
| 26 | https://www.vishay.com/docs/84286/veml7700.pdf | ||
| 27 | |||
| 28 | properties: | ||
| 29 | compatible: | ||
| 30 | enum: | ||
| 31 | - vishay,veml3235 | ||
| 32 | - vishay,veml6030 | ||
| 33 | - vishay,veml6035 | ||
| 34 | - vishay,veml7700 | ||
| 35 | |||
| 36 | reg: | ||
| 37 | maxItems: 1 | ||
| 38 | |||
| 39 | interrupts: | ||
| 40 | description: | ||
| 41 | interrupt mapping for IRQ. Configure with IRQ_TYPE_LEVEL_LOW. | ||
| 42 | Refer to interrupt-controller/interrupts.txt for generic | ||
| 43 | interrupt client node bindings. | ||
| 44 | maxItems: 1 | ||
| 45 | |||
| 46 | vdd-supply: true | ||
| 47 | |||
| 48 | required: | ||
| 49 | - compatible | ||
| 50 | - reg | ||
| 51 | - vdd-supply | ||
| 52 | |||
| 53 | allOf: | ||
| 54 | - if: | ||
| 55 | properties: | ||
| 56 | compatible: | ||
| 57 | enum: | ||
| 58 | - vishay,veml6030 | ||
| 59 | then: | ||
| 60 | properties: | ||
| 61 | reg: | ||
| 62 | enum: | ||
| 63 | - 0x10 # ADDR pin pulled down | ||
| 64 | - 0x48 # ADDR pin pulled up | ||
| 65 | |||
| 66 | - if: | ||
| 67 | properties: | ||
| 68 | compatible: | ||
| 69 | enum: | ||
| 70 | - vishay,veml6035 | ||
| 71 | then: | ||
| 72 | properties: | ||
| 73 | reg: | ||
| 74 | enum: | ||
| 75 | - 0x29 | ||
| 76 | |||
| 77 | - if: | ||
| 78 | properties: | ||
| 79 | compatible: | ||
| 80 | enum: | ||
| 81 | - vishay,veml3235 | ||
| 82 | - vishay,veml7700 | ||
| 83 | then: | ||
| 84 | properties: | ||
| 85 | reg: | ||
| 86 | enum: | ||
| 87 | - 0x10 | ||
| 88 | interrupts: false | ||
| 89 | |||
| 90 | additionalProperties: false | ||
| 91 | |||
| 92 | examples: | ||
| 93 | - | | ||
| 94 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 95 | |||
| 96 | i2c { | ||
| 97 | #address-cells = <1>; | ||
| 98 | #size-cells = <0>; | ||
| 99 | |||
| 100 | light-sensor@10 { | ||
| 101 | compatible = "vishay,veml6030"; | ||
| 102 | reg = <0x10>; | ||
| 103 | interrupts = <12 IRQ_TYPE_LEVEL_LOW>; | ||
| 104 | vdd-supply = <&vdd>; | ||
| 105 | }; | ||
| 106 | }; | ||
| 107 | ... | ||
| @@ -4,7 +4,7 @@ · 3 unmodified lines | |||
| 4 | $id: http://devicetree.org/schemas/iio/light/vishay,veml6075.yaml# | 4 | $id: http://devicetree.org/schemas/iio/light/vishay,veml6075.yaml# |
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# |
| 6 | 6 | ||
| 7 | title: Vishay VEML6075 UVA/B and VEML6040 RGBW sensors | 7 | title: Vishay VEML6070 UVA, VEML6075 UVA/B and VEML6040 RGBW sensors |
| 8 | 8 | ||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Javier Carrasco <javier.carrasco.cruz@gmail.com> | 10 | - Javier Carrasco <javier.carrasco.cruz@gmail.com> |
| @@ -16,11 +16,19 @@ properties: · 5 unmodified lines | |||
| 16 | compatible: | 16 | compatible: |
| 17 | enum: | 17 | enum: |
| 18 | - vishay,veml6040 | 18 | - vishay,veml6040 |
| 19 | - vishay,veml6070 | ||
| 19 | - vishay,veml6075 | 20 | - vishay,veml6075 |
| 20 | 21 | ||
| 21 | reg: | 22 | reg: |
| 22 | maxItems: 1 | 23 | maxItems: 1 |
| 23 | 24 | ||
| 25 | vishay,rset-ohms: | ||
| 26 | description: | ||
| 27 | Resistor used to select the integration time. | ||
| 28 | default: 270000 | ||
| 29 | minimum: 75000 | ||
| 30 | maximum: 1200000 | ||
| 31 | |||
| 24 | vdd-supply: true | 32 | vdd-supply: true |
| 25 | 33 | ||
| 26 | required: | 34 | required: |
| @@ -28,6 +36,17 @@ required: · 1 unmodified line | |||
| 28 | - reg | 36 | - reg |
| 29 | - vdd-supply | 37 | - vdd-supply |
| 30 | 38 | ||
| 39 | allOf: | ||
| 40 | - if: | ||
| 41 | properties: | ||
| 42 | compatible: | ||
| 43 | enum: | ||
| 44 | - vishay,veml6040 | ||
| 45 | - vishay,veml6075 | ||
| 46 | then: | ||
| 47 | properties: | ||
| 48 | vishay,rset-ohms: false | ||
| 49 | |||
| 31 | additionalProperties: false | 50 | additionalProperties: false |
| 32 | 51 | ||
| 33 | examples: | 52 | examples: |
| @@ -0,0 +1,46 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/magnetometer/allegromicro,als31300.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Allegro MicroSystems ALS31300 3-D Linear Hall Effect sensor | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Neil Armstrong <neil.armstrong@linaro.org> | ||
| 11 | |||
| 12 | properties: | ||
| 13 | $nodename: | ||
| 14 | pattern: '^magnetometer@[0-9a-f]+$' | ||
| 15 | |||
| 16 | compatible: | ||
| 17 | enum: | ||
| 18 | - allegromicro,als31300-500 # Factory configured at 500 Gauss input range | ||
| 19 | - allegromicro,als31300-1000 # Factory configured at 1000 Gauss input range | ||
| 20 | - allegromicro,als31300-2000 # Factory configured at 2000 Gauss input range | ||
| 21 | |||
| 22 | reg: | ||
| 23 | maxItems: 1 | ||
| 24 | |||
| 25 | vcc-supply: | ||
| 26 | description: 5.5V supply | ||
| 27 | |||
| 28 | interrupts: | ||
| 29 | maxItems: 1 | ||
| 30 | |||
| 31 | required: | ||
| 32 | - compatible | ||
| 33 | |||
| 34 | additionalProperties: false | ||
| 35 | |||
| 36 | examples: | ||
| 37 | - | | ||
| 38 | i2c { | ||
| 39 | #address-cells = <1>; | ||
| 40 | #size-cells = <0>; | ||
| 41 | magnetometer@61 { | ||
| 42 | compatible = "allegromicro,als31300-500"; | ||
| 43 | reg = <0x61>; | ||
| 44 | vcc-supply = <&hall_vcc>; | ||
| 45 | }; | ||
| 46 | }; | ||
| @@ -47,15 +47,33 @@ properties: · 46 unmodified lines | |||
| 47 | maxItems: 1 | 47 | maxItems: 1 |
| 48 | 48 | ||
| 49 | interrupts: | 49 | interrupts: |
| 50 | description: | ||
| 51 | interrupt mapping for IRQ (BMP085 only) | ||
| 52 | maxItems: 1 | 50 | maxItems: 1 |
| 53 | 51 | ||
| 52 | drive-open-drain: | ||
| 53 | description: | ||
| 54 | set if the interrupt pin should be configured as open drain. | ||
| 55 | If not set, defaults to push-pull configuration. | ||
| 56 | type: boolean | ||
| 57 | |||
| 54 | required: | 58 | required: |
| 55 | - compatible | 59 | - compatible |
| 56 | - vddd-supply | 60 | - vddd-supply |
| 57 | - vdda-supply | 61 | - vdda-supply |
| 58 | 62 | ||
| 63 | allOf: | ||
| 64 | - if: | ||
| 65 | properties: | ||
| 66 | compatible: | ||
| 67 | not: | ||
| 68 | contains: | ||
| 69 | enum: | ||
| 70 | - bosch,bmp085 | ||
| 71 | - bosch,bmp380 | ||
| 72 | - bosch,bmp580 | ||
| 73 | then: | ||
| 74 | properties: | ||
| 75 | interrupts: false | ||
| 76 | |||
| 59 | additionalProperties: false | 77 | additionalProperties: false |
| 60 | 78 | ||
| 61 | examples: | 79 | examples: |
| @@ -23,6 +23,9 @@ properties: · 22 unmodified lines | |||
| 23 | vdd-supply: | 23 | vdd-supply: |
| 24 | description: provide VDD power to the sensor. | 24 | description: provide VDD power to the sensor. |
| 25 | 25 | ||
| 26 | interrupts: | ||
| 27 | maxItems: 1 | ||
| 28 | |||
| 26 | required: | 29 | required: |
| 27 | - compatible | 30 | - compatible |
| 28 | - reg | 31 | - reg |
| @@ -31,6 +34,7 @@ additionalProperties: false · 2 unmodified lines | |||
| 31 | 34 | ||
| 32 | examples: | 35 | examples: |
| 33 | - | | 36 | - | |
| 37 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 34 | i2c { | 38 | i2c { |
| 35 | #address-cells = <1>; | 39 | #address-cells = <1>; |
| 36 | #size-cells = <0>; | 40 | #size-cells = <0>; |
| @@ -38,5 +42,7 @@ examples: · 1 unmodified line | |||
| 38 | compatible = "ti,tmp006"; | 42 | compatible = "ti,tmp006"; |
| 39 | reg = <0x40>; | 43 | reg = <0x40>; |
| 40 | vdd-supply = <&ldo4_reg>; | 44 | vdd-supply = <&ldo4_reg>; |
| 45 | interrupt-parent = <&gpio1>; | ||
| 46 | interrupts = <4 IRQ_TYPE_EDGE_FALLING>; | ||
| 41 | }; | 47 | }; |
| 42 | }; | 48 | }; |
| @@ -26,6 +26,7 @@ properties: · 25 unmodified lines | |||
| 26 | - items: | 26 | - items: |
| 27 | - enum: | 27 | - enum: |
| 28 | - qcom,qcm2290-cpu-bwmon | 28 | - qcom,qcm2290-cpu-bwmon |
| 29 | - qcom,qcs8300-cpu-bwmon | ||
| 29 | - qcom,sa8775p-cpu-bwmon | 30 | - qcom,sa8775p-cpu-bwmon |
| 30 | - qcom,sc7180-cpu-bwmon | 31 | - qcom,sc7180-cpu-bwmon |
| 31 | - qcom,sc7280-cpu-bwmon | 32 | - qcom,sc7280-cpu-bwmon |
| @@ -40,6 +41,7 @@ properties: · 8 unmodified lines | |||
| 40 | - const: qcom,sdm845-bwmon # BWMON v4, unified register space | 41 | - const: qcom,sdm845-bwmon # BWMON v4, unified register space |
| 41 | - items: | 42 | - items: |
| 42 | - enum: | 43 | - enum: |
| 44 | - qcom,qcs8300-llcc-bwmon | ||
| 43 | - qcom,sa8775p-llcc-bwmon | 45 | - qcom,sa8775p-llcc-bwmon |
| 44 | - qcom,sc7180-llcc-bwmon | 46 | - qcom,sc7180-llcc-bwmon |
| 45 | - qcom,sc8280xp-llcc-bwmon | 47 | - qcom,sc8280xp-llcc-bwmon |
| @@ -0,0 +1,73 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/interconnect/qcom,qcs615-rpmh.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Qualcomm RPMh Network-On-Chip Interconnect on QCS615 | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Raviteja Laggyshetty <quic_rlaggysh@quicinc.com> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | RPMh interconnect providers support system bandwidth requirements through | ||
| 14 | RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is | ||
| 15 | able to communicate with the BCM through the Resource State Coordinator (RSC) | ||
| 16 | associated with each execution environment. Provider nodes must point to at | ||
| 17 | least one RPMh device child node pertaining to their RSC and each provider | ||
| 18 | can map to multiple RPMh resources. | ||
| 19 | |||
| 20 | See also: include/dt-bindings/interconnect/qcom,qcs615-rpmh.h | ||
| 21 | |||
| 22 | properties: | ||
| 23 | compatible: | ||
| 24 | enum: | ||
| 25 | - qcom,qcs615-aggre1-noc | ||
| 26 | - qcom,qcs615-camnoc-virt | ||
| 27 | - qcom,qcs615-config-noc | ||
| 28 | - qcom,qcs615-dc-noc | ||
| 29 | - qcom,qcs615-gem-noc | ||
| 30 | - qcom,qcs615-ipa-virt | ||
| 31 | - qcom,qcs615-mc-virt | ||
| 32 | - qcom,qcs615-mmss-noc | ||
| 33 | - qcom,qcs615-system-noc | ||
| 34 | |||
| 35 | reg: | ||
| 36 | maxItems: 1 | ||
| 37 | |||
| 38 | required: | ||
| 39 | - compatible | ||
| 40 | |||
| 41 | allOf: | ||
| 42 | - $ref: qcom,rpmh-common.yaml# | ||
| 43 | - if: | ||
| 44 | properties: | ||
| 45 | compatible: | ||
| 46 | contains: | ||
| 47 | enum: | ||
| 48 | - qcom,qcs615-camnoc-virt | ||
| 49 | - qcom,qcs615-ipa-virt | ||
| 50 | - qcom,qcs615-mc-virt | ||
| 51 | then: | ||
| 52 | properties: | ||
| 53 | reg: false | ||
| 54 | else: | ||
| 55 | required: | ||
| 56 | - reg | ||
| 57 | |||
| 58 | unevaluatedProperties: false | ||
| 59 | |||
| 60 | examples: | ||
| 61 | - | | ||
| 62 | gem_noc: interconnect@9680000 { | ||
| 63 | compatible = "qcom,qcs615-gem-noc"; | ||
| 64 | reg = <0x9680000 0x3e200>; | ||
| 65 | #interconnect-cells = <2>; | ||
| 66 | qcom,bcm-voters = <&apps_bcm_voter>; | ||
| 67 | }; | ||
| 68 | |||
| 69 | mc_virt: interconnect-2 { | ||
| 70 | compatible = "qcom,qcs615-mc-virt"; | ||
| 71 | #interconnect-cells = <2>; | ||
| 72 | qcom,bcm-voters = <&apps_bcm_voter>; | ||
| 73 | }; | ||
| @@ -0,0 +1,72 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/interconnect/qcom,qcs8300-rpmh.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Qualcomm RPMh Network-On-Chip Interconnect on QCS8300 | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Raviteja Laggyshetty <quic_rlaggysh@quicinc.com> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | RPMh interconnect providers support system bandwidth requirements through | ||
| 14 | RPMh hardware accelerators known as Bus Clock Manager (BCM). | ||
| 15 | |||
| 16 | See also: include/dt-bindings/interconnect/qcom,qcs8300-rpmh.h | ||
| 17 | |||
| 18 | properties: | ||
| 19 | compatible: | ||
| 20 | enum: | ||
| 21 | - qcom,qcs8300-aggre1-noc | ||
| 22 | - qcom,qcs8300-aggre2-noc | ||
| 23 | - qcom,qcs8300-clk-virt | ||
| 24 | - qcom,qcs8300-config-noc | ||
| 25 | - qcom,qcs8300-dc-noc | ||
| 26 | - qcom,qcs8300-gem-noc | ||
| 27 | - qcom,qcs8300-gpdsp-anoc | ||
| 28 | - qcom,qcs8300-lpass-ag-noc | ||
| 29 | - qcom,qcs8300-mc-virt | ||
| 30 | - qcom,qcs8300-mmss-noc | ||
| 31 | - qcom,qcs8300-nspa-noc | ||
| 32 | - qcom,qcs8300-pcie-anoc | ||
| 33 | - qcom,qcs8300-system-noc | ||
| 34 | |||
| 35 | reg: | ||
| 36 | maxItems: 1 | ||
| 37 | |||
| 38 | required: | ||
| 39 | - compatible | ||
| 40 | |||
| 41 | allOf: | ||
| 42 | - $ref: qcom,rpmh-common.yaml# | ||
| 43 | - if: | ||
| 44 | properties: | ||
| 45 | compatible: | ||
| 46 | contains: | ||
| 47 | enum: | ||
| 48 | - qcom,qcs8300-clk-virt | ||
| 49 | - qcom,qcs8300-mc-virt | ||
| 50 | then: | ||
| 51 | properties: | ||
| 52 | reg: false | ||
| 53 | else: | ||
| 54 | required: | ||
| 55 | - reg | ||
| 56 | |||
| 57 | unevaluatedProperties: false | ||
| 58 | |||
| 59 | examples: | ||
| 60 | - | | ||
| 61 | gem_noc: interconnect@9100000 { | ||
| 62 | compatible = "qcom,qcs8300-gem-noc"; | ||
| 63 | reg = <0x9100000 0xf7080>; | ||
| 64 | #interconnect-cells = <2>; | ||
| 65 | qcom,bcm-voters = <&apps_bcm_voter>; | ||
| 66 | }; | ||
| 67 | |||
| 68 | clk_virt: interconnect-0 { | ||
| 69 | compatible = "qcom,qcs8300-clk-virt"; | ||
| 70 | #interconnect-cells = <2>; | ||
| 71 | qcom,bcm-voters = <&apps_bcm_voter>; | ||
| 72 | }; | ||
| @@ -0,0 +1,117 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/interconnect/qcom,sar2130p-rpmh.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Qualcomm RPMh Network-On-Chip Interconnect on SAR2130P | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Dmitry Baryshkov <dmitry.baryshkov@linaro.org> | ||
| 11 | - Georgi Djakov <djakov@kernel.org> | ||
| 12 | |||
| 13 | description: | | ||
| 14 | RPMh interconnect providers support system bandwidth requirements through | ||
| 15 | RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is | ||
| 16 | able to communicate with the BCM through the Resource State Coordinator (RSC) | ||
| 17 | associated with each execution environment. Provider nodes must point to at | ||
| 18 | least one RPMh device child node pertaining to their RSC and each provider | ||
| 19 | can map to multiple RPMh resources. | ||
| 20 | |||
| 21 | See also:: include/dt-bindings/interconnect/qcom,sar2130p-rpmh.h | ||
| 22 | |||
| 23 | properties: | ||
| 24 | compatible: | ||
| 25 | enum: | ||
| 26 | - qcom,sar2130p-clk-virt | ||
| 27 | - qcom,sar2130p-config-noc | ||
| 28 | - qcom,sar2130p-gem-noc | ||
| 29 | - qcom,sar2130p-lpass-ag-noc | ||
| 30 | - qcom,sar2130p-mc-virt | ||
| 31 | - qcom,sar2130p-mmss-noc | ||
| 32 | - qcom,sar2130p-nsp-noc | ||
| 33 | - qcom,sar2130p-pcie-anoc | ||
| 34 | - qcom,sar2130p-system-noc | ||
| 35 | |||
| 36 | reg: | ||
| 37 | maxItems: 1 | ||
| 38 | |||
| 39 | clocks: | ||
| 40 | minItems: 1 | ||
| 41 | maxItems: 2 | ||
| 42 | |||
| 43 | required: | ||
| 44 | - compatible | ||
| 45 | |||
| 46 | allOf: | ||
| 47 | - $ref: qcom,rpmh-common.yaml# | ||
| 48 | - if: | ||
| 49 | properties: | ||
| 50 | compatible: | ||
| 51 | contains: | ||
| 52 | enum: | ||
| 53 | - qcom,sar2130p-clk-virt | ||
| 54 | - qcom,sar2130p-mc-virt | ||
| 55 | then: | ||
| 56 | properties: | ||
| 57 | reg: false | ||
| 58 | else: | ||
| 59 | required: | ||
| 60 | - reg | ||
| 61 | |||
| 62 | - if: | ||
| 63 | properties: | ||
| 64 | compatible: | ||
| 65 | contains: | ||
| 66 | enum: | ||
| 67 | - qcom,sar2130p-pcie-anoc | ||
| 68 | then: | ||
| 69 | properties: | ||
| 70 | clocks: | ||
| 71 | items: | ||
| 72 | - description: aggre-NOC PCIe AXI clock | ||
| 73 | - description: cfg-NOC PCIe a-NOC AHB clock | ||
| 74 | |||
| 75 | - if: | ||
| 76 | properties: | ||
| 77 | compatible: | ||
| 78 | contains: | ||
| 79 | enum: | ||
| 80 | - qcom,sar2130p-system-noc | ||
| 81 | then: | ||
| 82 | properties: | ||
| 83 | clocks: | ||
| 84 | items: | ||
| 85 | - description: aggre USB3 PRIM AXI clock | ||
| 86 | |||
| 87 | - if: | ||
| 88 | properties: | ||
| 89 | compatible: | ||
| 90 | contains: | ||
| 91 | enum: | ||
| 92 | - qcom,sar2130p-system-noc | ||
| 93 | - qcom,sar2130p-pcie-anoc | ||
| 94 | then: | ||
| 95 | required: | ||
| 96 | - clocks | ||
| 97 | else: | ||
| 98 | properties: | ||
| 99 | clocks: false | ||
| 100 | |||
| 101 | unevaluatedProperties: false | ||
| 102 | |||
| 103 | examples: | ||
| 104 | - | | ||
| 105 | clk_virt: interconnect-0 { | ||
| 106 | compatible = "qcom,sar2130p-clk-virt"; | ||
| 107 | #interconnect-cells = <2>; | ||
| 108 | qcom,bcm-voters = <&apps_bcm_voter>; | ||
| 109 | }; | ||
| 110 | |||
| 111 | aggre1_noc: interconnect@1680000 { | ||
| 112 | compatible = "qcom,sar2130p-system-noc"; | ||
| 113 | reg = <0x01680000 0x29080>; | ||
| 114 | #interconnect-cells = <2>; | ||
| 115 | clocks = <&gcc_prim_axi_clk>; | ||
| 116 | qcom,bcm-voters = <&apps_bcm_voter>; | ||
| 117 | }; | ||
| @@ -1,7 +1,7 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | %YAML 1.2 | 2 | %YAML 1.2 |
| 3 | --- | 3 | --- |
| 4 | $id: http://devicetree.org/schemas/fuse/renesas,rcar-efuse.yaml# | 4 | $id: http://devicetree.org/schemas/nvmem/renesas,rcar-efuse.yaml# |
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# |
| 6 | 6 | ||
| 7 | title: R-Car E-FUSE connected to PFC | 7 | title: R-Car E-FUSE connected to PFC |
| @@ -13,6 +13,9 @@ description: · 5 unmodified lines | |||
| 13 | The E-FUSE is a type of non-volatile memory, which is accessible through the | 13 | The E-FUSE is a type of non-volatile memory, which is accessible through the |
| 14 | Pin Function Controller (PFC) on some R-Car Gen4 SoCs. | 14 | Pin Function Controller (PFC) on some R-Car Gen4 SoCs. |
| 15 | 15 | ||
| 16 | allOf: | ||
| 17 | - $ref: nvmem.yaml# | ||
| 18 | |||
| 16 | properties: | 19 | properties: |
| 17 | compatible: | 20 | compatible: |
| 18 | enum: | 21 | enum: |
| @@ -39,17 +42,27 @@ required: · 20 unmodified lines | |||
| 39 | - power-domains | 42 | - power-domains |
| 40 | - resets | 43 | - resets |
| 41 | 44 | ||
| 42 | additionalProperties: false | 45 | unevaluatedProperties: false |
| 43 | 46 | ||
| 44 | examples: | 47 | examples: |
| 45 | - | | 48 | - | |
| 46 | #include <dt-bindings/clock/r8a779a0-cpg-mssr.h> | 49 | #include <dt-bindings/clock/r8a779f0-cpg-mssr.h> |
| 47 | #include <dt-bindings/power/r8a779a0-sysc.h> | 50 | #include <dt-bindings/power/r8a779f0-sysc.h> |
| 48 | 51 | ||
| 49 | fuse: fuse@e6078800 { | 52 | fuse@e6078800 { |
| 50 | compatible = "renesas,r8a779a0-efuse"; | 53 | compatible = "renesas,r8a779f0-efuse"; |
| 51 | reg = <0xe6078800 0x100>; | 54 | reg = <0xe6078800 0x200>; |
| 52 | clocks = <&cpg CPG_MOD 916>; | 55 | clocks = <&cpg CPG_MOD 915>; |
| 53 | power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>; | 56 | power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>; |
| 54 | resets = <&cpg 916>; | 57 | resets = <&cpg 915>; |
| 58 | |||
| 59 | nvmem-layout { | ||
| 60 | compatible = "fixed-layout"; | ||
| 61 | #address-cells = <1>; | ||
| 62 | #size-cells = <1>; | ||
| 63 | |||
| 64 | calib@144 { | ||
| 65 | reg = <0x144 0x08>; | ||
| 66 | }; | ||
| 67 | }; | ||
| 55 | }; | 68 | }; |
| @@ -1,7 +1,7 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | %YAML 1.2 | 2 | %YAML 1.2 |
| 3 | --- | 3 | --- |
| 4 | $id: http://devicetree.org/schemas/fuse/renesas,rcar-otp.yaml# | 4 | $id: http://devicetree.org/schemas/nvmem/renesas,rcar-otp.yaml# |
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# |
| 6 | 6 | ||
| 7 | title: R-Car E-FUSE connected to OTP_MEM | 7 | title: R-Car E-FUSE connected to OTP_MEM |
| @@ -13,6 +13,9 @@ description: · 5 unmodified lines | |||
| 13 | The E-FUSE is a type of non-volatile memory, which is accessible through the | 13 | The E-FUSE is a type of non-volatile memory, which is accessible through the |
| 14 | One-Time Programmable Memory (OTP_MEM) module on some R-Car Gen4 SoCs. | 14 | One-Time Programmable Memory (OTP_MEM) module on some R-Car Gen4 SoCs. |
| 15 | 15 | ||
| 16 | allOf: | ||
| 17 | - $ref: nvmem.yaml# | ||
| 18 | |||
| 16 | properties: | 19 | properties: |
| 17 | compatible: | 20 | compatible: |
| 18 | enum: | 21 | enum: |
| @@ -22,17 +25,19 @@ properties: · 3 unmodified lines | |||
| 22 | reg: | 25 | reg: |
| 23 | items: | 26 | items: |
| 24 | - description: OTP_MEM_0 | 27 | - description: OTP_MEM_0 |
| 25 | - description: OTP_MEM_1 | 28 | - description: OTP_MEM_1. |
| 29 | The addresses of cells defined under the optional nvmem-layout | ||
| 30 | subnode are relative to this register bank. | ||
| 26 | 31 | ||
| 27 | required: | 32 | required: |
| 28 | - compatible | 33 | - compatible |
| 29 | - reg | 34 | - reg |
| 30 | 35 | ||
| 31 | additionalProperties: false | 36 | unevaluatedProperties: false |
| 32 | 37 | ||
| 33 | examples: | 38 | examples: |
| 34 | - | | 39 | - | |
| 35 | otp: otp@e61be000 { | 40 | otp@e61be000 { |
| 36 | compatible = "renesas,r8a779g0-otp"; | 41 | compatible = "renesas,r8a779g0-otp"; |
| 37 | reg = <0xe61be000 0x1000>, <0xe61bf000 0x1000>; | 42 | reg = <0xe61be000 0x1000>, <0xe61bf000 0x1000>; |
| 38 | }; | 43 | }; |
| @@ -1,52 +0,0 @@ | |||
| 1 | = Spreadtrum SC27XX PMIC eFuse device tree bindings = | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: Should be one of the following. | ||
| 5 | "sprd,sc2720-efuse" | ||
| 6 | "sprd,sc2721-efuse" | ||
| 7 | "sprd,sc2723-efuse" | ||
| 8 | "sprd,sc2730-efuse" | ||
| 9 | "sprd,sc2731-efuse" | ||
| 10 | - reg: Specify the address offset of efuse controller. | ||
| 11 | - hwlocks: Reference to a phandle of a hwlock provider node. | ||
| 12 | |||
| 13 | = Data cells = | ||
| 14 | Are child nodes of eFuse, bindings of which as described in | ||
| 15 | bindings/nvmem/nvmem.txt | ||
| 16 | |||
| 17 | Example: | ||
| 18 | |||
| 19 | sc2731_pmic: pmic@0 { | ||
| 20 | compatible = "sprd,sc2731"; | ||
| 21 | reg = <0>; | ||
| 22 | spi-max-frequency = <26000000>; | ||
| 23 | interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; | ||
| 24 | interrupt-controller; | ||
| 25 | #interrupt-cells = <2>; | ||
| 26 | #address-cells = <1>; | ||
| 27 | #size-cells = <0>; | ||
| 28 | |||
| 29 | efuse@380 { | ||
| 30 | compatible = "sprd,sc2731-efuse"; | ||
| 31 | reg = <0x380>; | ||
| 32 | #address-cells = <1>; | ||
| 33 | #size-cells = <1>; | ||
| 34 | hwlocks = <&hwlock 12>; | ||
| 35 | |||
| 36 | /* Data cells */ | ||
| 37 | thermal_calib: calib@10 { | ||
| 38 | reg = <0x10 0x2>; | ||
| 39 | }; | ||
| 40 | }; | ||
| 41 | }; | ||
| 42 | |||
| 43 | = Data consumers = | ||
| 44 | Are device nodes which consume nvmem data cells. | ||
| 45 | |||
| 46 | Example: | ||
| 47 | |||
| 48 | thermal { | ||
| 49 | ... | ||
| 50 | nvmem-cells = <&thermal_calib>; | ||
| 51 | nvmem-cell-names = "calibration"; | ||
| 52 | }; | ||
| @@ -0,0 +1,68 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/nvmem/sprd,sc2731-efuse.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Spreadtrum SC27XX PMIC eFuse | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Orson Zhai <orsonzhai@gmail.com> | ||
| 11 | - Baolin Wang <baolin.wang7@gmail.com> | ||
| 12 | - Chunyan Zhang <zhang.lyra@gmail.com> | ||
| 13 | |||
| 14 | properties: | ||
| 15 | compatible: | ||
| 16 | enum: | ||
| 17 | - sprd,sc2720-efuse | ||
| 18 | - sprd,sc2721-efuse | ||
| 19 | - sprd,sc2723-efuse | ||
| 20 | - sprd,sc2730-efuse | ||
| 21 | - sprd,sc2731-efuse | ||
| 22 | |||
| 23 | reg: | ||
| 24 | maxItems: 1 | ||
| 25 | |||
| 26 | hwlocks: | ||
| 27 | maxItems: 1 | ||
| 28 | |||
| 29 | required: | ||
| 30 | - compatible | ||
| 31 | - reg | ||
| 32 | - hwlocks | ||
| 33 | |||
| 34 | allOf: | ||
| 35 | - $ref: nvmem.yaml# | ||
| 36 | - $ref: nvmem-deprecated-cells.yaml# | ||
| 37 | |||
| 38 | unevaluatedProperties: false | ||
| 39 | |||
| 40 | examples: | ||
| 41 | - | | ||
| 42 | pmic { | ||
| 43 | #address-cells = <1>; | ||
| 44 | #size-cells = <0>; | ||
| 45 | |||
| 46 | efuse@380 { | ||
| 47 | compatible = "sprd,sc2731-efuse"; | ||
| 48 | reg = <0x380>; | ||
| 49 | hwlocks = <&hwlock 12>; | ||
| 50 | #address-cells = <1>; | ||
| 51 | #size-cells = <1>; | ||
| 52 | |||
| 53 | /* Data cells */ | ||
| 54 | fgu_calib: calib@6 { | ||
| 55 | reg = <0x6 0x2>; | ||
| 56 | bits = <0 9>; | ||
| 57 | }; | ||
| 58 | |||
| 59 | adc_big_scale: calib@24 { | ||
| 60 | reg = <0x24 0x2>; | ||
| 61 | }; | ||
| 62 | |||
| 63 | adc_small_scale: calib@26 { | ||
| 64 | reg = <0x26 0x2>; | ||
| 65 | }; | ||
| 66 | }; | ||
| 67 | }; | ||
| 68 | ... | ||
| @@ -0,0 +1,61 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/nvmem/sprd,ums312-efuse.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Spreadtrum UMS312 eFuse | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Orson Zhai <orsonzhai@gmail.com> | ||
| 11 | - Baolin Wang <baolin.wang7@gmail.com> | ||
| 12 | - Chunyan Zhang <zhang.lyra@gmail.com> | ||
| 13 | |||
| 14 | properties: | ||
| 15 | compatible: | ||
| 16 | const: sprd,ums312-efuse | ||
| 17 | |||
| 18 | reg: | ||
| 19 | maxItems: 1 | ||
| 20 | |||
| 21 | clocks: | ||
| 22 | maxItems: 1 | ||
| 23 | |||
| 24 | clock-names: | ||
| 25 | const: enable | ||
| 26 | |||
| 27 | hwlocks: | ||
| 28 | maxItems: 1 | ||
| 29 | |||
| 30 | required: | ||
| 31 | - compatible | ||
| 32 | - reg | ||
| 33 | - clocks | ||
| 34 | - clock-names | ||
| 35 | - hwlocks | ||
| 36 | |||
| 37 | allOf: | ||
| 38 | - $ref: nvmem.yaml# | ||
| 39 | - $ref: nvmem-deprecated-cells.yaml# | ||
| 40 | |||
| 41 | unevaluatedProperties: false | ||
| 42 | |||
| 43 | examples: | ||
| 44 | - | | ||
| 45 | #include <dt-bindings/clock/sprd,ums512-clk.h> | ||
| 46 | |||
| 47 | efuse@32240000 { | ||
| 48 | compatible = "sprd,ums312-efuse"; | ||
| 49 | reg = <0x32240000 0x10000>; | ||
| 50 | clocks = <&aonapb_gate CLK_EFUSE_EB>; | ||
| 51 | clock-names = "enable"; | ||
| 52 | hwlocks = <&hwlock 8>; | ||
| 53 | #address-cells = <1>; | ||
| 54 | #size-cells = <1>; | ||
| 55 | |||
| 56 | /* Data cells */ | ||
| 57 | thermal_calib: calib@10 { | ||
| 58 | reg = <0x10 0x2>; | ||
| 59 | }; | ||
| 60 | }; | ||
| 61 | ... | ||
| @@ -1,39 +0,0 @@ | |||
| 1 | = Spreadtrum eFuse device tree bindings = | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: Should be "sprd,ums312-efuse". | ||
| 5 | - reg: Specify the address offset of efuse controller. | ||
| 6 | - clock-names: Should be "enable". | ||
| 7 | - clocks: The phandle and specifier referencing the controller's clock. | ||
| 8 | - hwlocks: Reference to a phandle of a hwlock provider node. | ||
| 9 | |||
| 10 | = Data cells = | ||
| 11 | Are child nodes of eFuse, bindings of which as described in | ||
| 12 | bindings/nvmem/nvmem.txt | ||
| 13 | |||
| 14 | Example: | ||
| 15 | |||
| 16 | ap_efuse: efuse@32240000 { | ||
| 17 | compatible = "sprd,ums312-efuse"; | ||
| 18 | reg = <0 0x32240000 0 0x10000>; | ||
| 19 | clock-names = "enable"; | ||
| 20 | hwlocks = <&hwlock 8>; | ||
| 21 | clocks = <&aonapb_gate CLK_EFUSE_EB>; | ||
| 22 | |||
| 23 | /* Data cells */ | ||
| 24 | thermal_calib: calib@10 { | ||
| 25 | reg = <0x10 0x2>; | ||
| 26 | }; | ||
| 27 | }; | ||
| 28 | |||
| 29 | = Data consumers = | ||
| 30 | Are device nodes which consume nvmem data cells. | ||
| 31 | |||
| 32 | Example: | ||
| 33 | |||
| 34 | thermal { | ||
| 35 | ... | ||
| 36 | |||
| 37 | nvmem-cells = <&thermal_calib>; | ||
| 38 | nvmem-cell-names = "calibration"; | ||
| 39 | }; | ||
| @@ -1,40 +0,0 @@ | |||
| 1 | Zodiac Inflight Innovations RAVE EEPROM Bindings | ||
| 2 | |||
| 3 | RAVE SP EEPROM device is a "MFD cell" device exposing physical EEPROM | ||
| 4 | attached to RAVE Supervisory Processor. It is expected that its Device | ||
| 5 | Tree node is specified as a child of the node corresponding to the | ||
| 6 | parent RAVE SP device (as documented in | ||
| 7 | Documentation/devicetree/bindings/mfd/zii,rave-sp.txt) | ||
| 8 | |||
| 9 | Required properties: | ||
| 10 | |||
| 11 | - compatible: Should be "zii,rave-sp-eeprom" | ||
| 12 | |||
| 13 | Optional properties: | ||
| 14 | |||
| 15 | - zii,eeprom-name: Unique EEPROM identifier describing its function in the | ||
| 16 | system. Will be used as created NVMEM deivce's name. | ||
| 17 | |||
| 18 | Data cells: | ||
| 19 | |||
| 20 | Data cells are child nodes of eerpom node, bindings for which are | ||
| 21 | documented in Documentation/devicetree/bindings/nvmem/nvmem.txt | ||
| 22 | |||
| 23 | Example: | ||
| 24 | |||
| 25 | rave-sp { | ||
| 26 | compatible = "zii,rave-sp-rdu1"; | ||
| 27 | current-speed = <38400>; | ||
| 28 | |||
| 29 | eeprom@a4 { | ||
| 30 | compatible = "zii,rave-sp-eeprom"; | ||
| 31 | reg = <0xa4 0x4000>; | ||
| 32 | #address-cells = <1>; | ||
| 33 | #size-cells = <1>; | ||
| 34 | zii,eeprom-name = "main-eeprom"; | ||
| 35 | |||
| 36 | wdt_timeout: wdt-timeout@81 { | ||
| 37 | reg = <0x81 2>; | ||
| 38 | }; | ||
| 39 | }; | ||
| 40 | } | ||
| @@ -0,0 +1,54 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/nvmem/zii,rave-sp-eeprom.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Zodiac Inflight Innovations RAVE EEPROM | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Frank Li <Frank.Li@nxp.com> | ||
| 11 | |||
| 12 | description: | ||
| 13 | RAVE SP EEPROM device is a "MFD cell" device exposing physical EEPROM | ||
| 14 | attached to RAVE Supervisory Processor. It is expected that its Device | ||
| 15 | Tree node is specified as a child of the node corresponding to the | ||
| 16 | parent RAVE SP device (as documented in | ||
| 17 | Documentation/devicetree/bindings/mfd/zii,rave-sp.yaml) | ||
| 18 | |||
| 19 | properties: | ||
| 20 | compatible: | ||
| 21 | const: zii,rave-sp-eeprom | ||
| 22 | |||
| 23 | reg: | ||
| 24 | maxItems: 1 | ||
| 25 | |||
| 26 | zii,eeprom-name: | ||
| 27 | $ref: /schemas/types.yaml#/definitions/string | ||
| 28 | description: | ||
| 29 | Unique EEPROM identifier describing its function in the | ||
| 30 | system. Will be used as created NVMEM deivce's name. | ||
| 31 | |||
| 32 | required: | ||
| 33 | - compatible | ||
| 34 | |||
| 35 | allOf: | ||
| 36 | - $ref: nvmem.yaml# | ||
| 37 | - $ref: nvmem-deprecated-cells.yaml# | ||
| 38 | |||
| 39 | unevaluatedProperties: false | ||
| 40 | |||
| 41 | examples: | ||
| 42 | - | | ||
| 43 | eeprom@a4 { | ||
| 44 | compatible = "zii,rave-sp-eeprom"; | ||
| 45 | reg = <0xa4 0x4000>; | ||
| 46 | #address-cells = <1>; | ||
| 47 | #size-cells = <1>; | ||
| 48 | zii,eeprom-name = "main-eeprom"; | ||
| 49 | |||
| 50 | wdt-timeout@81 { | ||
| 51 | reg = <0x81 2>; | ||
| 52 | }; | ||
| 53 | }; | ||
| 54 | |||
| @@ -25,6 +25,7 @@ properties: · 24 unmodified lines | |||
| 25 | - items: | 25 | - items: |
| 26 | - enum: | 26 | - enum: |
| 27 | - mediatek,mt8186-spmi | 27 | - mediatek,mt8186-spmi |
| 28 | - mediatek,mt8188-spmi | ||
| 28 | - const: mediatek,mt8195-spmi | 29 | - const: mediatek,mt8195-spmi |
| 29 | 30 | ||
| 30 | reg: | 31 | reg: |
| @@ -19,7 +19,11 @@ description: | · 18 unmodified lines | |||
| 19 | 19 | ||
| 20 | properties: | 20 | properties: |
| 21 | compatible: | 21 | compatible: |
| 22 | const: qcom,x1e80100-spmi-pmic-arb | 22 | oneOf: |
| 23 | - items: | ||
| 24 | - const: qcom,sar2130p-spmi-pmic-arb | ||
| 25 | - const: qcom,x1e80100-spmi-pmic-arb | ||
| 26 | - const: qcom,x1e80100-spmi-pmic-arb | ||
| 23 | 27 | ||
| 24 | reg: | 28 | reg: |
| 25 | items: | 29 | items: |
| @@ -83,6 +83,8 @@ patternProperties: · 82 unmodified lines | |||
| 83 | description: ALFA Network Inc. | 83 | description: ALFA Network Inc. |
| 84 | "^allegro,.*": | 84 | "^allegro,.*": |
| 85 | description: Allegro DVT | 85 | description: Allegro DVT |
| 86 | "^allegromicro,.*": | ||
| 87 | description: Allegro MicroSystems, Inc. | ||
| 86 | "^alliedvision,.*": | 88 | "^alliedvision,.*": |
| 87 | description: Allied Vision Technologies GmbH | 89 | description: Allied Vision Technologies GmbH |
| 88 | "^allo,.*": | 90 | "^allo,.*": |
| @@ -565,6 +567,8 @@ patternProperties: · 476 unmodified lines | |||
| 565 | description: GE Fanuc Intelligent Platforms Embedded Systems, Inc. | 567 | description: GE Fanuc Intelligent Platforms Embedded Systems, Inc. |
| 566 | "^GEFanuc,.*": | 568 | "^GEFanuc,.*": |
| 567 | description: GE Fanuc Intelligent Platforms Embedded Systems, Inc. | 569 | description: GE Fanuc Intelligent Platforms Embedded Systems, Inc. |
| 570 | "^gehc,.*": | ||
| 571 | description: GE HealthCare | ||
| 568 | "^gemei,.*": | 572 | "^gemei,.*": |
| 569 | description: Gemei Digital Technology Co., Ltd. | 573 | description: Gemei Digital Technology Co., Ltd. |
| 570 | "^gemtek,.*": | 574 | "^gemtek,.*": |
| @@ -27,6 +27,8 @@ The following chips are supported by this driver: · 26 unmodified lines | |||
| 27 | * `AD7386-4 <https://www.analog.com/en/products/ad7386-4.html>`_ | 27 | * `AD7386-4 <https://www.analog.com/en/products/ad7386-4.html>`_ |
| 28 | * `AD7387-4 <https://www.analog.com/en/products/ad7387-4.html>`_ | 28 | * `AD7387-4 <https://www.analog.com/en/products/ad7387-4.html>`_ |
| 29 | * `AD7388-4 <https://www.analog.com/en/products/ad7388-4.html>`_ | 29 | * `AD7388-4 <https://www.analog.com/en/products/ad7388-4.html>`_ |
| 30 | * `ADAQ4370-4 <https://www.analog.com/en/products/adaq4370-4.html>`_ | ||
| 31 | * `ADAQ4380-4 <https://www.analog.com/en/products/adaq4380-4.html>`_ | ||
| 30 | 32 | ||
| 31 | 33 | ||
| 32 | Supported features | 34 | Supported features |
| @@ -47,6 +49,12 @@ ad7380-4 · 14 unmodified lines | |||
| 47 | ad7380-4 supports only an external reference voltage (2.5V to 3.3V). It must be | 49 | ad7380-4 supports only an external reference voltage (2.5V to 3.3V). It must be |
| 48 | declared in the device tree as ``refin-supply``. | 50 | declared in the device tree as ``refin-supply``. |
| 49 | 51 | ||
| 52 | ADAQ devices | ||
| 53 | ~~~~~~~~~~~~ | ||
| 54 | |||
| 55 | adaq4370-4 and adaq4380-4 don't have an external reference, but use a 3.3V | ||
| 56 | internal reference derived from one of its supplies (``refin-supply``) | ||
| 57 | |||
| 50 | All other devices from ad738x family | 58 | All other devices from ad738x family |
| 51 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 59 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 52 | 60 | ||
| @@ -121,6 +129,14 @@ Example for AD7386/7/8 (2 channels parts): · 68 unmodified lines | |||
| 121 | 129 | ||
| 122 | When enabling sequencer mode, the effective sampling rate is divided by two. | 130 | When enabling sequencer mode, the effective sampling rate is divided by two. |
| 123 | 131 | ||
| 132 | Gain (ADAQ devices only) | ||
| 133 | ~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 134 | |||
| 135 | ADAQ devices have a pin selectable gain in front of each ADC. The appropriate | ||
| 136 | gain is selectable from device tree using the ``adi,gain-milli`` property. | ||
| 137 | Refer to the typical connection diagrams section of the datasheet for pin | ||
| 138 | wiring. | ||
| 139 | |||
| 124 | Unimplemented features | 140 | Unimplemented features |
| 125 | ---------------------- | 141 | ---------------------- |
| 126 | 142 | ||
| @@ -0,0 +1,144 @@ | |||
| 1 | .. SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | |||
| 3 | ============= | ||
| 4 | AD7606 driver | ||
| 5 | ============= | ||
| 6 | |||
| 7 | ADC driver for Analog Devices Inc. AD7606 and similar devices. The module name | ||
| 8 | is ``ad7606``. | ||
| 9 | |||
| 10 | Supported devices | ||
| 11 | ================= | ||
| 12 | |||
| 13 | The following chips are supported by this driver: | ||
| 14 | |||
| 15 | * `AD7605 <https://www.analog.com/en/products/ad7605.html>`_ | ||
| 16 | * `AD7606 <https://www.analog.com/en/products/ad7606.html>`_ | ||
| 17 | * `AD7606B <https://www.analog.com/en/products/ad7606b.html>`_ | ||
| 18 | * `AD7616 <https://www.analog.com/en/products/ad7616.html>`_ | ||
| 19 | |||
| 20 | Supported features | ||
| 21 | ================== | ||
| 22 | |||
| 23 | SPI wiring modes | ||
| 24 | ---------------- | ||
| 25 | |||
| 26 | These ADCs can output data on several SDO lines (1/2/4/8). The driver | ||
| 27 | currently supports only 1 SDO line. | ||
| 28 | |||
| 29 | Parallel wiring mode | ||
| 30 | -------------------- | ||
| 31 | |||
| 32 | There is also a parallel interface, with 16 lines (that can be reduced to 8 in | ||
| 33 | byte mode). The parallel interface is selected by declaring the device as | ||
| 34 | platform in the device tree (with no io-backends node defined, see below). | ||
| 35 | |||
| 36 | IIO-backend mode | ||
| 37 | ---------------- | ||
| 38 | |||
| 39 | This mode allows to reach the best sample rates, but it requires an external | ||
| 40 | hardware (eg HDL or APU) to handle the low level communication. | ||
| 41 | The backend mode is enabled when through the definition of the "io-backends" | ||
| 42 | property in the device tree. | ||
| 43 | |||
| 44 | The reference configuration for the current implementation of IIO-backend mode | ||
| 45 | is the HDL reference provided by ADI: | ||
| 46 | https://wiki.analog.com/resources/eval/user-guides/ad7606x-fmc/hdl | ||
| 47 | |||
| 48 | This implementation embeds an IIO-backend compatible IP (adi-axi-adc) and a PWM | ||
| 49 | connected to the conversion trigger pin. | ||
| 50 | |||
| 51 | .. code-block:: | ||
| 52 | |||
| 53 | +---+ +---------------------------- | ||
| 54 | | | +-------+ |AD76xx | ||
| 55 | | A | controls | | | | ||
| 56 | | D |-------------->| PWM |-------------->| cnvst | ||
| 57 | | 7 | | | | | ||
| 58 | | 6 | +-------+ | | ||
| 59 | | 0 | controls +-----------+-----------+ | | ||
| 60 | | 6 |---------->| | |<--| frstdata | ||
| 61 | | | | Backend | Backend |<--| busy | ||
| 62 | | D | | Driver | | | | ||
| 63 | | R | | | |-->| clk | ||
| 64 | | I | requests |+---------+| DMA | | | ||
| 65 | | V |----------->| Buffer ||<---- |<=>| DATA | ||
| 66 | | E | |+---------+| | | | ||
| 67 | | R | +-----------+-----------+ | | ||
| 68 | | |-------------------------------------->| reset/configuration gpios | ||
| 69 | +---+ +----------------------------- | ||
| 70 | |||
| 71 | |||
| 72 | Software and hardware modes | ||
| 73 | --------------------------- | ||
| 74 | |||
| 75 | While all the AD7606/AD7616 series parts can be configured using GPIOs, some of | ||
| 76 | them can be configured using register. | ||
| 77 | |||
| 78 | The chips that support software mode have more values available for configuring | ||
| 79 | the device, as well as more settings, and allow to control the range and | ||
| 80 | calibration per channel. | ||
| 81 | |||
| 82 | The following settings are available per channel in software mode: | ||
| 83 | - Scale | ||
| 84 | |||
| 85 | Also, there is a broader choice of oversampling ratios in software mode. | ||
| 86 | |||
| 87 | Conversion triggering | ||
| 88 | --------------------- | ||
| 89 | |||
| 90 | The conversion can be triggered by two distinct ways: | ||
| 91 | |||
| 92 | - A GPIO is connected to the conversion trigger pin, and this GPIO is controlled | ||
| 93 | by the driver directly. In this configuration, the driver sets back the | ||
| 94 | conversion trigger pin to high as soon as it has read all the conversions. | ||
| 95 | |||
| 96 | - An external source is connected to the conversion trigger pin. In the | ||
| 97 | current implementation, it must be a PWM. In this configuration, the driver | ||
| 98 | does not control directly the conversion trigger pin. Instead, it can | ||
| 99 | control the PWM's frequency. This trigger is enabled only for iio-backend. | ||
| 100 | |||
| 101 | Reference voltage | ||
| 102 | ----------------- | ||
| 103 | |||
| 104 | 2 possible reference voltage sources are supported: | ||
| 105 | |||
| 106 | - Internal reference (2.5V) | ||
| 107 | - External reference (2.5V) | ||
| 108 | |||
| 109 | The source is determined by the device tree. If ``refin-supply`` is present, | ||
| 110 | then the external reference is used, otherwise the internal reference is used. | ||
| 111 | |||
| 112 | Oversampling | ||
| 113 | ------------ | ||
| 114 | |||
| 115 | This family supports oversampling to improve SNR. | ||
| 116 | In software mode, the following ratios are available: | ||
| 117 | 1 (oversampling disabled)/2/4/8/16/32/64/128/256. | ||
| 118 | |||
| 119 | Unimplemented features | ||
| 120 | ---------------------- | ||
| 121 | |||
| 122 | - 2/4/8 SDO lines | ||
| 123 | - CRC indication | ||
| 124 | - Calibration | ||
| 125 | |||
| 126 | Device buffers | ||
| 127 | ============== | ||
| 128 | |||
| 129 | IIO triggered buffer | ||
| 130 | -------------------- | ||
| 131 | |||
| 132 | This driver supports IIO triggered buffers, with a "built in" trigger, i.e the | ||
| 133 | trigger is allocated and linked by the driver, and a new conversion is triggered | ||
| 134 | as soon as the samples are transferred, and a timestamp channel is added to make | ||
| 135 | up for the potential jitter induced by the delays in the interrupt handling. | ||
| 136 | |||
| 137 | IIO backend buffer | ||
| 138 | ------------------ | ||
| 139 | |||
| 140 | When IIO backend is used, the trigger is not needed, and the sample rate is | ||
| 141 | considered as stable. There is no timestamp channel. The communication is | ||
| 142 | delegated to an external logic, called a backend, and the backend's driver | ||
| 143 | handles the buffer. When this mode is enabled, the driver cannot control the | ||
| 144 | conversion pin, because the busy pin is bound to the backend. | ||
| @@ -0,0 +1,91 @@ | |||
| 1 | .. SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | |||
| 3 | ==================== | ||
| 4 | AD7625 driver | ||
| 5 | ==================== | ||
| 6 | |||
| 7 | ADC driver for Analog Devices Inc. AD7625, AD7626, AD7960, and AD7961 | ||
| 8 | devices. The module name is ``ad7625``. | ||
| 9 | |||
| 10 | Supported devices | ||
| 11 | ================= | ||
| 12 | |||
| 13 | The following chips are supported by this driver: | ||
| 14 | |||
| 15 | * `AD7625 <https://www.analog.com/AD7625>`_ | ||
| 16 | * `AD7626 <https://www.analog.com/AD7626>`_ | ||
| 17 | * `AD7960 <https://www.analog.com/AD7960>`_ | ||
| 18 | * `AD7961 <https://www.analog.com/AD7961>`_ | ||
| 19 | |||
| 20 | The driver requires use of the Pulsar LVDS HDL project: | ||
| 21 | |||
| 22 | * `Pulsar LVDS HDL <http://analogdevicesinc.github.io/hdl/projects/pulsar_lvds/index.html>`_ | ||
| 23 | |||
| 24 | To trigger conversions and enable subsequent data transfer, the devices | ||
| 25 | require coupled PWM signals with a phase offset. | ||
| 26 | |||
| 27 | Supported features | ||
| 28 | ================== | ||
| 29 | |||
| 30 | Conversion control modes | ||
| 31 | ------------------------ | ||
| 32 | |||
| 33 | The driver currently supports one of two possible LVDS conversion control methods. | ||
| 34 | |||
| 35 | Echoed-Clock interface mode | ||
| 36 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| 37 | |||
| 38 | .. code-block:: | ||
| 39 | |||
| 40 | +----------------+ | ||
| 41 | +xxxxxxxxxxxxxxxxxxxxxxxxxx| CNV | | ||
| 42 | X | | | ||
| 43 | v | HOST | | ||
| 44 | +----------------------------+ | | | ||
| 45 | | CNV+/CNV- DCO+/DCO- |xxxxxxx>| CLK_IN | | ||
| 46 | | | | | | ||
| 47 | | | | | | ||
| 48 | | AD7625 D+/D- |xxxxxxx>| DATA_IN | | ||
| 49 | | | | | | ||
| 50 | | | | | | ||
| 51 | | CLK+/CLK- |<xxxxxxx| CLK & CLK_GATE | | ||
| 52 | +----------------------------+ | | | ||
| 53 | +----------------+ | ||
| 54 | |||
| 55 | Reference voltage | ||
| 56 | ----------------- | ||
| 57 | |||
| 58 | Three possible reference voltage sources are supported: | ||
| 59 | |||
| 60 | - Internal reference (only available on AD7625 and AD7626) | ||
| 61 | - External reference and internal buffer | ||
| 62 | - External reference | ||
| 63 | |||
| 64 | The source is determined by the device tree. If ``ref-supply`` is present, then | ||
| 65 | the external reference is used. If ``refin-supply`` is present, then the internal | ||
| 66 | buffer is used. If neither is present, then the internal reference is used. | ||
| 67 | |||
| 68 | Unimplemented features | ||
| 69 | ---------------------- | ||
| 70 | |||
| 71 | - Self-clocked mode | ||
| 72 | |||
| 73 | |||
| 74 | Device attributes | ||
| 75 | ================= | ||
| 76 | |||
| 77 | The AD762x is a fully-differential ADC and has the following attributes: | ||
| 78 | |||
| 79 | +---------------------------------------+--------------------------------------------------------------+ | ||
| 80 | | Attribute | Description | | ||
| 81 | +=======================================+==============================================================+ | ||
| 82 | | ``scale`` | Scale factor to convert raw value from buffered reads to mV. | | ||
| 83 | +---------------------------------------+--------------------------------------------------------------+ | ||
| 84 | |||
| 85 | |||
| 86 | Device buffers | ||
| 87 | ============== | ||
| 88 | |||
| 89 | This driver supports IIO triggered buffers. | ||
| 90 | |||
| 91 | See :doc:`iio_devbuf` for more information. | ||
| @@ -22,7 +22,7 @@ This driver supports also IIO buffers. · 21 unmodified lines | |||
| 22 | 22 | ||
| 23 | The IMU continuously performs an autocalibration procedure if (and only if) | 23 | The IMU continuously performs an autocalibration procedure if (and only if) |
| 24 | operating in fusion mode. The magnetometer autocalibration can however be | 24 | operating in fusion mode. The magnetometer autocalibration can however be |
| 25 | disabled writing 0 in the sysfs in_magn_calibration_fast_enable attribute. | 25 | disabled by writing 0 in the sysfs in_magn_calibration_fast_enable attribute. |
| 26 | 26 | ||
| 27 | The driver provides access to autocalibration flags (i.e. you can known if | 27 | The driver provides access to autocalibration flags (i.e. you can known if |
| 28 | the IMU has successfully autocalibrated) and to the calibration data blob. | 28 | the IMU has successfully autocalibrated) and to the calibration data blob. |
| @@ -21,6 +21,8 @@ Industrial I/O Kernel Drivers · 20 unmodified lines | |||
| 21 | ad4000 | 21 | ad4000 |
| 22 | ad4695 | 22 | ad4695 |
| 23 | ad7380 | 23 | ad7380 |
| 24 | ad7606 | ||
| 25 | ad7625 | ||
| 24 | ad7944 | 26 | ad7944 |
| 25 | adis16475 | 27 | adis16475 |
| 26 | adis16480 | 28 | adis16480 |
| @@ -1271,7 +1271,6 @@ M: Cosmin Tanislav <cosmin.tanislav@analog.com> · 1270 unmodified lines | |||
| 1271 | L: linux-iio@vger.kernel.org | 1271 | L: linux-iio@vger.kernel.org |
| 1272 | S: Supported | 1272 | S: Supported |
| 1273 | W: https://ez.analog.com/linux-software-drivers | 1273 | W: https://ez.analog.com/linux-software-drivers |
| 1274 | F: Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130 | ||
| 1275 | F: Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml | 1274 | F: Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml |
| 1276 | F: drivers/iio/adc/ad4130.c | 1275 | F: drivers/iio/adc/ad4130.c |
| 1277 | 1276 | ||
| @@ -1336,6 +1335,17 @@ F: Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml · 58 unmodified lines | |||
| 1336 | F: drivers/iio/addac/ad74413r.c | 1335 | F: drivers/iio/addac/ad74413r.c |
| 1337 | F: include/dt-bindings/iio/addac/adi,ad74413r.h | 1336 | F: include/dt-bindings/iio/addac/adi,ad74413r.h |
| 1338 | 1337 | ||
| 1338 | ANALOG DEVICES INC AD7625 DRIVER | ||
| 1339 | M: Michael Hennerich <Michael.Hennerich@analog.com> | ||
| 1340 | M: Nuno Sá <nuno.sa@analog.com> | ||
| 1341 | R: Trevor Gamblin <tgamblin@baylibre.com> | ||
| 1342 | S: Supported | ||
| 1343 | W: https://ez.analog.com/linux-software-drivers | ||
| 1344 | W: http://analogdevicesinc.github.io/hdl/projects/pulsar_lvds/index.html | ||
| 1345 | F: Documentation/devicetree/bindings/iio/adc/adi,ad7625.yaml | ||
| 1346 | F: Documentation/iio/ad7625.rst | ||
| 1347 | F: drivers/iio/adc/ad7625.c | ||
| 1348 | |||
| 1339 | ANALOG DEVICES INC AD7768-1 DRIVER | 1349 | ANALOG DEVICES INC AD7768-1 DRIVER |
| 1340 | M: Michael Hennerich <Michael.Hennerich@analog.com> | 1350 | M: Michael Hennerich <Michael.Hennerich@analog.com> |
| 1341 | L: linux-iio@vger.kernel.org | 1351 | L: linux-iio@vger.kernel.org |
| @@ -1363,6 +1373,14 @@ F: Documentation/ABI/testing/debugfs-iio-ad9467 · 21 unmodified lines | |||
| 1363 | F: Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml | 1373 | F: Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml |
| 1364 | F: drivers/iio/adc/ad9467.c | 1374 | F: drivers/iio/adc/ad9467.c |
| 1365 | 1375 | ||
| 1376 | ANALOG DEVICES INC AD8460 DRIVER | ||
| 1377 | M: Mariel Tinaco <Mariel.Tinaco@analog.com> | ||
| 1378 | L: linux-iio@vger.kernel.org | ||
| 1379 | S: Supported | ||
| 1380 | W: https://ez.analog.com/linux-software-drivers | ||
| 1381 | F: Documentation/devicetree/bindings/iio/dac/adi,ad8460.yaml | ||
| 1382 | F: drivers/iio/dac/ad8460.c | ||
| 1383 | |||
| 1366 | ANALOG DEVICES INC AD9739a DRIVER | 1384 | ANALOG DEVICES INC AD9739a DRIVER |
| 1367 | M: Nuno Sa <nuno.sa@analog.com> | 1385 | M: Nuno Sa <nuno.sa@analog.com> |
| 1368 | M: Dragos Bogdan <dragos.bogdan@analog.com> | 1386 | M: Dragos Bogdan <dragos.bogdan@analog.com> |
| @@ -1563,6 +1581,7 @@ F: Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350 · 194 unmodified lines | |||
| 1563 | F: Documentation/devicetree/bindings/iio/*/adi,* | 1581 | F: Documentation/devicetree/bindings/iio/*/adi,* |
| 1564 | F: Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml | 1582 | F: Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml |
| 1565 | F: Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml | 1583 | F: Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml |
| 1584 | F: Documentation/iio/ad7606.rst | ||
| 1566 | F: drivers/iio/*/ad* | 1585 | F: drivers/iio/*/ad* |
| 1567 | F: drivers/iio/adc/ltc249* | 1586 | F: drivers/iio/adc/ltc249* |
| 1568 | F: drivers/iio/amplifiers/hmc425a.c | 1587 | F: drivers/iio/amplifiers/hmc425a.c |
| @@ -2924,6 +2943,7 @@ Q: http://patchwork.kernel.org/project/linux-renesas-soc/list/ · 1355 unmodified lines | |||
| 2924 | C: irc://irc.libera.chat/renesas-soc | 2943 | C: irc://irc.libera.chat/renesas-soc |
| 2925 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git next | 2944 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git next |
| 2926 | F: Documentation/devicetree/bindings/hwinfo/renesas,prr.yaml | 2945 | F: Documentation/devicetree/bindings/hwinfo/renesas,prr.yaml |
| 2946 | F: Documentation/devicetree/bindings/nvmem/renesas,* | ||
| 2927 | F: Documentation/devicetree/bindings/soc/renesas/ | 2947 | F: Documentation/devicetree/bindings/soc/renesas/ |
| 2928 | F: arch/arm/boot/dts/renesas/ | 2948 | F: arch/arm/boot/dts/renesas/ |
| 2929 | F: arch/arm/configs/shmobile_defconfig | 2949 | F: arch/arm/configs/shmobile_defconfig |
| @@ -2931,6 +2951,7 @@ F: arch/arm/include/debug/renesas-scif.S · 1 unmodified line | |||
| 2931 | F: arch/arm/mach-shmobile/ | 2951 | F: arch/arm/mach-shmobile/ |
| 2932 | F: arch/arm64/boot/dts/renesas/ | 2952 | F: arch/arm64/boot/dts/renesas/ |
| 2933 | F: arch/riscv/boot/dts/renesas/ | 2953 | F: arch/riscv/boot/dts/renesas/ |
| 2954 | F: drivers/nvmem/rcar-efuse.c | ||
| 2934 | F: drivers/pmdomain/renesas/ | 2955 | F: drivers/pmdomain/renesas/ |
| 2935 | F: drivers/soc/renesas/ | 2956 | F: drivers/soc/renesas/ |
| 2936 | F: include/linux/soc/renesas/ | 2957 | F: include/linux/soc/renesas/ |
| @@ -4036,6 +4057,13 @@ S: Maintained · 1099 unmodified lines | |||
| 4036 | F: Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml | 4057 | F: Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml |
| 4037 | F: drivers/iio/accel/bma400* | 4058 | F: drivers/iio/accel/bma400* |
| 4038 | 4059 | ||
| 4060 | BOSCH SENSORTEC BMI270 IMU IIO DRIVER | ||
| 4061 | M: Alex Lanzano <lanzano.alex@gmail.com> | ||
| 4062 | L: linux-iio@vger.kernel.org | ||
| 4063 | S: Maintained | ||
| 4064 | F: Documentation/devicetree/bindings/iio/imu/bosch,bmi270.yaml | ||
| 4065 | F: drivers/iio/imu/bmi270/ | ||
| 4066 | |||
| 4039 | BOSCH SENSORTEC BMI323 IMU IIO DRIVER | 4067 | BOSCH SENSORTEC BMI323 IMU IIO DRIVER |
| 4040 | M: Jagath Jog J <jagathjog1996@gmail.com> | 4068 | M: Jagath Jog J <jagathjog1996@gmail.com> |
| 4041 | L: linux-iio@vger.kernel.org | 4069 | L: linux-iio@vger.kernel.org |
| @@ -9483,6 +9511,14 @@ M: Kieran Bingham <kbingham@kernel.org> · 5441 unmodified lines | |||
| 9483 | S: Supported | 9511 | S: Supported |
| 9484 | F: scripts/gdb/ | 9512 | F: scripts/gdb/ |
| 9485 | 9513 | ||
| 9514 | GE HEALTHCARE PMC ADC DRIVER | ||
| 9515 | M: Herve Codina <herve.codina@bootlin.com> | ||
| 9516 | L: linux-iio@vger.kernel.org | ||
| 9517 | S: Maintained | ||
| 9518 | F: Documentation/devicetree/bindings/iio/adc/gehc,pmc-adc.yaml | ||
| 9519 | F: drivers/iio/adc/gehc-pmc-adc.c | ||
| 9520 | F: include/dt-bindings/iio/adc/gehc,pmc-adc.h | ||
| 9521 | |||
| 9486 | GEMINI CRYPTO DRIVER | 9522 | GEMINI CRYPTO DRIVER |
| 9487 | M: Corentin Labbe <clabbe@baylibre.com> | 9523 | M: Corentin Labbe <clabbe@baylibre.com> |
| 9488 | L: linux-crypto@vger.kernel.org | 9524 | L: linux-crypto@vger.kernel.org |
| @@ -11646,7 +11682,7 @@ F: drivers/usb/misc/usb-ljca.c · 2157 unmodified lines | |||
| 11646 | F: include/linux/usb/ljca.h | 11682 | F: include/linux/usb/ljca.h |
| 11647 | 11683 | ||
| 11648 | INTEL MANAGEMENT ENGINE (mei) | 11684 | INTEL MANAGEMENT ENGINE (mei) |
| 11649 | M: Tomas Winkler <tomas.winkler@intel.com> | 11685 | M: Alexander Usyskin <alexander.usyskin@intel.com> |
| 11650 | L: linux-kernel@vger.kernel.org | 11686 | L: linux-kernel@vger.kernel.org |
| 11651 | S: Supported | 11687 | S: Supported |
| 11652 | F: Documentation/driver-api/mei/* | 11688 | F: Documentation/driver-api/mei/* |
| @@ -11927,7 +11963,7 @@ F: Documentation/devicetree/bindings/media/i2c/isil,isl79987.yaml · 274 unmodified lines | |||
| 11927 | F: drivers/media/i2c/isl7998x.c | 11963 | F: drivers/media/i2c/isl7998x.c |
| 11928 | 11964 | ||
| 11929 | INVENSENSE ICM-426xx IMU DRIVER | 11965 | INVENSENSE ICM-426xx IMU DRIVER |
| 11930 | M: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com> | 11966 | M: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> |
| 11931 | L: linux-iio@vger.kernel.org | 11967 | L: linux-iio@vger.kernel.org |
| 11932 | S: Maintained | 11968 | S: Maintained |
| 11933 | W: https://invensense.tdk.com/ | 11969 | W: https://invensense.tdk.com/ |
| @@ -11942,6 +11978,14 @@ S: Maintained · 8 unmodified lines | |||
| 11942 | F: Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml | 11978 | F: Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml |
| 11943 | F: drivers/iio/gyro/mpu3050* | 11979 | F: drivers/iio/gyro/mpu3050* |
| 11944 | 11980 | ||
| 11981 | INVENSENSE MPU-6050 IMU DRIVER | ||
| 11982 | M: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> | ||
| 11983 | L: linux-iio@vger.kernel.org | ||
| 11984 | S: Maintained | ||
| 11985 | W: https://invensense.tdk.com/ | ||
| 11986 | F: Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml | ||
| 11987 | F: drivers/iio/imu/inv_mpu6050/ | ||
| 11988 | |||
| 11945 | IOC3 ETHERNET DRIVER | 11989 | IOC3 ETHERNET DRIVER |
| 11946 | M: Thomas Bogendoerfer <tsbogend@alpha.franken.de> | 11990 | M: Thomas Bogendoerfer <tsbogend@alpha.franken.de> |
| 11947 | L: linux-mips@vger.kernel.org | 11991 | L: linux-mips@vger.kernel.org |
| @@ -24889,6 +24933,18 @@ S: Maintained · 12941 unmodified lines | |||
| 24889 | F: drivers/input/serio/userio.c | 24933 | F: drivers/input/serio/userio.c |
| 24890 | F: include/uapi/linux/userio.h | 24934 | F: include/uapi/linux/userio.h |
| 24891 | 24935 | ||
| 24936 | VISHAY VEML3235 AMBIENT LIGHT SENSOR DRIVER | ||
| 24937 | M: Javier Carrasco <javier.carrasco.cruz@gmail.com> | ||
| 24938 | S: Maintained | ||
| 24939 | F: Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml | ||
| 24940 | F: drivers/iio/light/veml3235.c | ||
| 24941 | |||
| 24942 | VISHAY VEML6030 AMBIENT LIGHT SENSOR DRIVER | ||
| 24943 | M: Javier Carrasco <javier.carrasco.cruz@gmail.com> | ||
| 24944 | S: Maintained | ||
| 24945 | F: Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml | ||
| 24946 | F: drivers/iio/light/veml6030.c | ||
| 24947 | |||
| 24892 | VISHAY VEML6075 UVA AND UVB LIGHT SENSOR DRIVER | 24948 | VISHAY VEML6075 UVA AND UVB LIGHT SENSOR DRIVER |
| 24893 | M: Javier Carrasco <javier.carrasco.cruz@gmail.com> | 24949 | M: Javier Carrasco <javier.carrasco.cruz@gmail.com> |
| 24894 | S: Maintained | 24950 | S: Maintained |
| @@ -1225,6 +1225,12 @@ static void binder_cleanup_ref_olocked(struct binder_ref *ref) · 1224 unmodified lines | |||
| 1225 | binder_dequeue_work(ref->proc, &ref->death->work); | 1225 | binder_dequeue_work(ref->proc, &ref->death->work); |
| 1226 | binder_stats_deleted(BINDER_STAT_DEATH); | 1226 | binder_stats_deleted(BINDER_STAT_DEATH); |
| 1227 | } | 1227 | } |
| 1228 | |||
| 1229 | if (ref->freeze) { | ||
| 1230 | binder_dequeue_work(ref->proc, &ref->freeze->work); | ||
| 1231 | binder_stats_deleted(BINDER_STAT_FREEZE); | ||
| 1232 | } | ||
| 1233 | |||
| 1228 | binder_stats_deleted(BINDER_STAT_REF); | 1234 | binder_stats_deleted(BINDER_STAT_REF); |
| 1229 | } | 1235 | } |
| 1230 | 1236 | ||
| @@ -3850,7 +3856,6 @@ binder_request_freeze_notification(struct binder_proc *proc, · 2619 unmodified lines | |||
| 3850 | { | 3856 | { |
| 3851 | struct binder_ref_freeze *freeze; | 3857 | struct binder_ref_freeze *freeze; |
| 3852 | struct binder_ref *ref; | 3858 | struct binder_ref *ref; |
| 3853 | bool is_frozen; | ||
| 3854 | 3859 | ||
| 3855 | freeze = kzalloc(sizeof(*freeze), GFP_KERNEL); | 3860 | freeze = kzalloc(sizeof(*freeze), GFP_KERNEL); |
| 3856 | if (!freeze) | 3861 | if (!freeze) |
| @@ -3866,32 +3871,31 @@ binder_request_freeze_notification(struct binder_proc *proc, · 9 unmodified lines | |||
| 3866 | } | 3871 | } |
| 3867 | 3872 | ||
| 3868 | binder_node_lock(ref->node); | 3873 | binder_node_lock(ref->node); |
| 3869 | 3874 | if (ref->freeze) { | |
| 3870 | if (ref->freeze || !ref->node->proc) { | 3875 | binder_user_error("%d:%d BC_REQUEST_FREEZE_NOTIFICATION already set\n", |
| 3871 | binder_user_error("%d:%d invalid BC_REQUEST_FREEZE_NOTIFICATION %s\n", | 3876 | proc->pid, thread->pid); |
| 3872 | proc->pid, thread->pid, | ||
| 3873 | ref->freeze ? "already set" : "dead node"); | ||
| 3874 | binder_node_unlock(ref->node); | 3877 | binder_node_unlock(ref->node); |
| 3875 | binder_proc_unlock(proc); | 3878 | binder_proc_unlock(proc); |
| 3876 | kfree(freeze); | 3879 | kfree(freeze); |
| 3877 | return -EINVAL; | 3880 | return -EINVAL; |
| 3878 | } | 3881 | } |
| 3879 | binder_inner_proc_lock(ref->node->proc); | ||
| 3880 | is_frozen = ref->node->proc->is_frozen; | ||
| 3881 | binder_inner_proc_unlock(ref->node->proc); | ||
| 3882 | 3882 | ||
| 3883 | binder_stats_created(BINDER_STAT_FREEZE); | 3883 | binder_stats_created(BINDER_STAT_FREEZE); |
| 3884 | INIT_LIST_HEAD(&freeze->work.entry); | 3884 | INIT_LIST_HEAD(&freeze->work.entry); |
| 3885 | freeze->cookie = handle_cookie->cookie; | 3885 | freeze->cookie = handle_cookie->cookie; |
| 3886 | freeze->work.type = BINDER_WORK_FROZEN_BINDER; | 3886 | freeze->work.type = BINDER_WORK_FROZEN_BINDER; |
| 3887 | freeze->is_frozen = is_frozen; | ||
| 3888 | |||
| 3889 | ref->freeze = freeze; | 3887 | ref->freeze = freeze; |
| 3890 | 3888 | ||
| 3891 | binder_inner_proc_lock(proc); | 3889 | if (ref->node->proc) { |
| 3892 | binder_enqueue_work_ilocked(&ref->freeze->work, &proc->todo); | 3890 | binder_inner_proc_lock(ref->node->proc); |
| 3893 | binder_wakeup_proc_ilocked(proc); | 3891 | freeze->is_frozen = ref->node->proc->is_frozen; |
| 3894 | binder_inner_proc_unlock(proc); | 3892 | binder_inner_proc_unlock(ref->node->proc); |
| 3893 | |||
| 3894 | binder_inner_proc_lock(proc); | ||
| 3895 | binder_enqueue_work_ilocked(&freeze->work, &proc->todo); | ||
| 3896 | binder_wakeup_proc_ilocked(proc); | ||
| 3897 | binder_inner_proc_unlock(proc); | ||
| 3898 | } | ||
| 3895 | 3899 | ||
| 3896 | binder_node_unlock(ref->node); | 3900 | binder_node_unlock(ref->node); |
| 3897 | binder_proc_unlock(proc); | 3901 | binder_proc_unlock(proc); |
| @@ -5151,6 +5155,16 @@ static void binder_release_work(struct binder_proc *proc, · 1253 unmodified lines | |||
| 5151 | } break; | 5155 | } break; |
| 5152 | case BINDER_WORK_NODE: | 5156 | case BINDER_WORK_NODE: |
| 5153 | break; | 5157 | break; |
| 5158 | case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION: { | ||
| 5159 | struct binder_ref_freeze *freeze; | ||
| 5160 | |||
| 5161 | freeze = container_of(w, struct binder_ref_freeze, work); | ||
| 5162 | binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, | ||
| 5163 | "undelivered freeze notification, %016llx\n", | ||
| 5164 | (u64)freeze->cookie); | ||
| 5165 | kfree(freeze); | ||
| 5166 | binder_stats_deleted(BINDER_STAT_FREEZE); | ||
| 5167 | } break; | ||
| 5154 | default: | 5168 | default: |
| 5155 | pr_err("unexpected work type, %d, not freed\n", | 5169 | pr_err("unexpected work type, %d, not freed\n", |
| 5156 | wtype); | 5170 | wtype); |
| @@ -5552,6 +5566,7 @@ static bool binder_txns_pending_ilocked(struct binder_proc *proc) · 395 unmodified lines | |||
| 5552 | 5566 | ||
| 5553 | static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen) | 5567 | static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen) |
| 5554 | { | 5568 | { |
| 5569 | struct binder_node *prev = NULL; | ||
| 5555 | struct rb_node *n; | 5570 | struct rb_node *n; |
| 5556 | struct binder_ref *ref; | 5571 | struct binder_ref *ref; |
| 5557 | 5572 | ||
| @@ -5560,7 +5575,10 @@ static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen) · 2 unmodified lines | |||
| 5560 | struct binder_node *node; | 5575 | struct binder_node *node; |
| 5561 | 5576 | ||
| 5562 | node = rb_entry(n, struct binder_node, rb_node); | 5577 | node = rb_entry(n, struct binder_node, rb_node); |
| 5578 | binder_inc_node_tmpref_ilocked(node); | ||
| 5563 | binder_inner_proc_unlock(proc); | 5579 | binder_inner_proc_unlock(proc); |
| 5580 | if (prev) | ||
| 5581 | binder_put_node(prev); | ||
| 5564 | binder_node_lock(node); | 5582 | binder_node_lock(node); |
| 5565 | hlist_for_each_entry(ref, &node->refs, node_entry) { | 5583 | hlist_for_each_entry(ref, &node->refs, node_entry) { |
| 5566 | /* | 5584 | /* |
| @@ -5586,10 +5604,15 @@ static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen) · 19 unmodified lines | |||
| 5586 | } | 5604 | } |
| 5587 | binder_inner_proc_unlock(ref->proc); | 5605 | binder_inner_proc_unlock(ref->proc); |
| 5588 | } | 5606 | } |
| 5607 | prev = node; | ||
| 5589 | binder_node_unlock(node); | 5608 | binder_node_unlock(node); |
| 5590 | binder_inner_proc_lock(proc); | 5609 | binder_inner_proc_lock(proc); |
| 5610 | if (proc->is_dead) | ||
| 5611 | break; | ||
| 5591 | } | 5612 | } |
| 5592 | binder_inner_proc_unlock(proc); | 5613 | binder_inner_proc_unlock(proc); |
| 5614 | if (prev) | ||
| 5615 | binder_put_node(prev); | ||
| 5593 | } | 5616 | } |
| 5594 | 5617 | ||
| 5595 | static int binder_ioctl_freeze(struct binder_freeze_info *info, | 5618 | static int binder_ioctl_freeze(struct binder_freeze_info *info, |
| @@ -6260,6 +6283,7 @@ static void binder_deferred_release(struct binder_proc *proc) · 664 unmodified lines | |||
| 6260 | 6283 | ||
| 6261 | binder_release_work(proc, &proc->todo); | 6284 | binder_release_work(proc, &proc->todo); |
| 6262 | binder_release_work(proc, &proc->delivered_death); | 6285 | binder_release_work(proc, &proc->delivered_death); |
| 6286 | binder_release_work(proc, &proc->delivered_freeze); | ||
| 6263 | 6287 | ||
| 6264 | binder_debug(BINDER_DEBUG_OPEN_CLOSE, | 6288 | binder_debug(BINDER_DEBUG_OPEN_CLOSE, |
| 6265 | "%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d\n", | 6289 | "%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d\n", |
| @@ -6393,6 +6417,12 @@ static void print_binder_work_ilocked(struct seq_file *m, · 127 unmodified lines | |||
| 6393 | case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: | 6417 | case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: |
| 6394 | seq_printf(m, "%shas cleared death notification\n", prefix); | 6418 | seq_printf(m, "%shas cleared death notification\n", prefix); |
| 6395 | break; | 6419 | break; |
| 6420 | case BINDER_WORK_FROZEN_BINDER: | ||
| 6421 | seq_printf(m, "%shas frozen binder\n", prefix); | ||
| 6422 | break; | ||
| 6423 | case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION: | ||
| 6424 | seq_printf(m, "%shas cleared freeze notification\n", prefix); | ||
| 6425 | break; | ||
| 6396 | default: | 6426 | default: |
| 6397 | seq_printf(m, "%sunknown work: type %d\n", prefix, w->type); | 6427 | seq_printf(m, "%sunknown work: type %d\n", prefix, w->type); |
| 6398 | break; | 6428 | break; |
| @@ -6539,6 +6569,10 @@ static void print_binder_proc(struct seq_file *m, · 140 unmodified lines | |||
| 6539 | seq_puts(m, " has delivered dead binder\n"); | 6569 | seq_puts(m, " has delivered dead binder\n"); |
| 6540 | break; | 6570 | break; |
| 6541 | } | 6571 | } |
| 6572 | list_for_each_entry(w, &proc->delivered_freeze, entry) { | ||
| 6573 | seq_puts(m, " has delivered freeze binder\n"); | ||
| 6574 | break; | ||
| 6575 | } | ||
| 6542 | binder_inner_proc_unlock(proc); | 6576 | binder_inner_proc_unlock(proc); |
| 6543 | if (!print_all && m->count == header_pos) | 6577 | if (!print_all && m->count == header_pos) |
| 6544 | m->count = start_pos; | 6578 | m->count = start_pos; |
| @@ -82,9 +82,9 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) · 81 unmodified lines | |||
| 82 | * other cores to shutdown while we're collecting RDDM buffer. After | 82 | * other cores to shutdown while we're collecting RDDM buffer. After |
| 83 | * returning from this function, we expect the device to reset. | 83 | * returning from this function, we expect the device to reset. |
| 84 | * | 84 | * |
| 85 | * Normaly, we read/write pm_state only after grabbing the | 85 | * Normally, we read/write pm_state only after grabbing the |
| 86 | * pm_lock, since we're in a panic, skipping it. Also there is no | 86 | * pm_lock, since we're in a panic, skipping it. Also there is no |
| 87 | * gurantee that this state change would take effect since | 87 | * guarantee that this state change would take effect since |
| 88 | * we're setting it w/o grabbing pm_lock | 88 | * we're setting it w/o grabbing pm_lock |
| 89 | */ | 89 | */ |
| 90 | mhi_cntrl->pm_state = MHI_PM_LD_ERR_FATAL_DETECT; | 90 | mhi_cntrl->pm_state = MHI_PM_LD_ERR_FATAL_DETECT; |
| @@ -255,7 +255,7 @@ struct mhi_chan { · 254 unmodified lines | |||
| 255 | /* | 255 | /* |
| 256 | * Important: When consuming, increment tre_ring first and when | 256 | * Important: When consuming, increment tre_ring first and when |
| 257 | * releasing, decrement buf_ring first. If tre_ring has space, buf_ring | 257 | * releasing, decrement buf_ring first. If tre_ring has space, buf_ring |
| 258 | * is guranteed to have space so we do not need to check both rings. | 258 | * is guaranteed to have space so we do not need to check both rings. |
| 259 | */ | 259 | */ |
| 260 | struct mhi_ring buf_ring; | 260 | struct mhi_ring buf_ring; |
| 261 | struct mhi_ring tre_ring; | 261 | struct mhi_ring tre_ring; |
| @@ -917,12 +917,12 @@ static int mhi_pci_claim(struct mhi_controller *mhi_cntrl, · 916 unmodified lines | |||
| 917 | return err; | 917 | return err; |
| 918 | } | 918 | } |
| 919 | 919 | ||
| 920 | err = pcim_iomap_regions(pdev, 1 << bar_num, pci_name(pdev)); | 920 | mhi_cntrl->regs = pcim_iomap_region(pdev, 1 << bar_num, pci_name(pdev)); |
| 921 | if (err) { | 921 | if (IS_ERR(mhi_cntrl->regs)) { |
| 922 | err = PTR_ERR(mhi_cntrl->regs); | ||
| 922 | dev_err(&pdev->dev, "failed to map pci region: %d\n", err); | 923 | dev_err(&pdev->dev, "failed to map pci region: %d\n", err); |
| 923 | return err; | 924 | return err; |
| 924 | } | 925 | } |
| 925 | mhi_cntrl->regs = pcim_iomap_table(pdev)[bar_num]; | ||
| 926 | mhi_cntrl->reg_len = pci_resource_len(pdev, bar_num); | 926 | mhi_cntrl->reg_len = pci_resource_len(pdev, bar_num); |
| 927 | 927 | ||
| 928 | err = dma_set_mask_and_coherent(&pdev->dev, dma_mask); | 928 | err = dma_set_mask_and_coherent(&pdev->dev, dma_mask); |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | #if !defined(_TRACE_EVENT_MHI_HOST_H) || defined(TRACE_HEADER_MULTI_READ) | 9 | #if !defined(_TRACE_EVENT_MHI_HOST_H) || defined(TRACE_HEADER_MULTI_READ) |
| 10 | #define _TRACE_EVENT_MHI_HOST_H | 10 | #define _TRACE_EVENT_MHI_HOST_H |
| 11 | 11 | ||
| 12 | #include <linux/byteorder/generic.h> | ||
| 12 | #include <linux/tracepoint.h> | 13 | #include <linux/tracepoint.h> |
| 13 | #include <linux/trace_seq.h> | 14 | #include <linux/trace_seq.h> |
| 14 | #include "../common.h" | 15 | #include "../common.h" |
| @@ -97,18 +98,18 @@ TRACE_EVENT(mhi_gen_tre, · 82 unmodified lines | |||
| 97 | __string(name, mhi_cntrl->mhi_dev->name) | 98 | __string(name, mhi_cntrl->mhi_dev->name) |
| 98 | __field(int, ch_num) | 99 | __field(int, ch_num) |
| 99 | __field(void *, wp) | 100 | __field(void *, wp) |
| 100 | __field(__le64, tre_ptr) | 101 | __field(uint64_t, tre_ptr) |
| 101 | __field(__le32, dword0) | 102 | __field(uint32_t, dword0) |
| 102 | __field(__le32, dword1) | 103 | __field(uint32_t, dword1) |
| 103 | ), | 104 | ), |
| 104 | 105 | ||
| 105 | TP_fast_assign( | 106 | TP_fast_assign( |
| 106 | __assign_str(name); | 107 | __assign_str(name); |
| 107 | __entry->ch_num = mhi_chan->chan; | 108 | __entry->ch_num = mhi_chan->chan; |
| 108 | __entry->wp = mhi_tre; | 109 | __entry->wp = mhi_tre; |
| 109 | __entry->tre_ptr = mhi_tre->ptr; | 110 | __entry->tre_ptr = le64_to_cpu(mhi_tre->ptr); |
| 110 | __entry->dword0 = mhi_tre->dword[0]; | 111 | __entry->dword0 = le32_to_cpu(mhi_tre->dword[0]); |
| 111 | __entry->dword1 = mhi_tre->dword[1]; | 112 | __entry->dword1 = le32_to_cpu(mhi_tre->dword[1]); |
| 112 | ), | 113 | ), |
| 113 | 114 | ||
| 114 | TP_printk("%s: Chan: %d TRE: 0x%p TRE buf: 0x%llx DWORD0: 0x%08x DWORD1: 0x%08x\n", | 115 | TP_printk("%s: Chan: %d TRE: 0x%p TRE buf: 0x%llx DWORD0: 0x%08x DWORD1: 0x%08x\n", |
| @@ -176,19 +177,19 @@ DECLARE_EVENT_CLASS(mhi_process_event_ring, · 61 unmodified lines | |||
| 176 | 177 | ||
| 177 | TP_STRUCT__entry( | 178 | TP_STRUCT__entry( |
| 178 | __string(name, mhi_cntrl->mhi_dev->name) | 179 | __string(name, mhi_cntrl->mhi_dev->name) |
| 179 | __field(__le32, dword0) | 180 | __field(uint32_t, dword0) |
| 180 | __field(__le32, dword1) | 181 | __field(uint32_t, dword1) |
| 181 | __field(int, state) | 182 | __field(int, state) |
| 182 | __field(__le64, ptr) | 183 | __field(uint64_t, ptr) |
| 183 | __field(void *, rp) | 184 | __field(void *, rp) |
| 184 | ), | 185 | ), |
| 185 | 186 | ||
| 186 | TP_fast_assign( | 187 | TP_fast_assign( |
| 187 | __assign_str(name); | 188 | __assign_str(name); |
| 188 | __entry->rp = rp; | 189 | __entry->rp = rp; |
| 189 | __entry->ptr = rp->ptr; | 190 | __entry->ptr = le64_to_cpu(rp->ptr); |
| 190 | __entry->dword0 = rp->dword[0]; | 191 | __entry->dword0 = le32_to_cpu(rp->dword[0]); |
| 191 | __entry->dword1 = rp->dword[1]; | 192 | __entry->dword1 = le32_to_cpu(rp->dword[1]); |
| 192 | __entry->state = MHI_TRE_GET_EV_STATE(rp); | 193 | __entry->state = MHI_TRE_GET_EV_STATE(rp); |
| 193 | ), | 194 | ), |
| 194 | 195 | ||
| @@ -213,7 +213,7 @@ static struct platform_driver oppanel_driver = { · 212 unmodified lines | |||
| 213 | .of_match_table = oppanel_match, | 213 | .of_match_table = oppanel_match, |
| 214 | }, | 214 | }, |
| 215 | .probe = oppanel_probe, | 215 | .probe = oppanel_probe, |
| 216 | .remove_new = oppanel_remove, | 216 | .remove = oppanel_remove, |
| 217 | }; | 217 | }; |
| 218 | 218 | ||
| 219 | module_platform_driver(oppanel_driver); | 219 | module_platform_driver(oppanel_driver); |
| @@ -1467,7 +1467,7 @@ static struct platform_driver sonypi_driver = { · 1466 unmodified lines | |||
| 1467 | .pm = SONYPI_PM, | 1467 | .pm = SONYPI_PM, |
| 1468 | }, | 1468 | }, |
| 1469 | .probe = sonypi_probe, | 1469 | .probe = sonypi_probe, |
| 1470 | .remove_new = sonypi_remove, | 1470 | .remove = sonypi_remove, |
| 1471 | .shutdown = sonypi_shutdown, | 1471 | .shutdown = sonypi_shutdown, |
| 1472 | }; | 1472 | }; |
| 1473 | 1473 | ||
| @@ -738,7 +738,7 @@ MODULE_DEVICE_TABLE(of, hwicap_of_match); · 737 unmodified lines | |||
| 738 | 738 | ||
| 739 | static struct platform_driver hwicap_platform_driver = { | 739 | static struct platform_driver hwicap_platform_driver = { |
| 740 | .probe = hwicap_drv_probe, | 740 | .probe = hwicap_drv_probe, |
| 741 | .remove_new = hwicap_drv_remove, | 741 | .remove = hwicap_drv_remove, |
| 742 | .driver = { | 742 | .driver = { |
| 743 | .name = DRIVER_NAME, | 743 | .name = DRIVER_NAME, |
| 744 | .of_match_table = hwicap_of_match, | 744 | .of_match_table = hwicap_of_match, |
| @@ -74,7 +74,7 @@ static void xilly_drv_remove(struct platform_device *op) · 73 unmodified lines | |||
| 74 | 74 | ||
| 75 | static struct platform_driver xillybus_platform_driver = { | 75 | static struct platform_driver xillybus_platform_driver = { |
| 76 | .probe = xilly_drv_probe, | 76 | .probe = xilly_drv_probe, |
| 77 | .remove_new = xilly_drv_remove, | 77 | .remove = xilly_drv_remove, |
| 78 | .driver = { | 78 | .driver = { |
| 79 | .name = xillyname, | 79 | .name = xillyname, |
| 80 | .of_match_table = xillybus_of_match, | 80 | .of_match_table = xillybus_of_match, |
| @@ -2407,6 +2407,18 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) · 2406 unmodified lines | |||
| 2407 | 2407 | ||
| 2408 | start += PAGE_SIZE; | 2408 | start += PAGE_SIZE; |
| 2409 | } | 2409 | } |
| 2410 | |||
| 2411 | #ifdef CONFIG_MMU | ||
| 2412 | /* | ||
| 2413 | * Leaving behind a partial mapping of a buffer we're about to | ||
| 2414 | * drop is unsafe, see remap_pfn_range_notrack(). | ||
| 2415 | * We need to zap the range here ourselves instead of relying | ||
| 2416 | * on the automatic zapping in remap_pfn_range() because we call | ||
| 2417 | * remap_pfn_range() in a loop. | ||
| 2418 | */ | ||
| 2419 | if (retval) | ||
| 2420 | zap_vma_ptes(vma, vma->vm_start, size); | ||
| 2421 | #endif | ||
| 2410 | } | 2422 | } |
| 2411 | 2423 | ||
| 2412 | if (retval == 0) { | 2424 | if (retval == 0) { |
| @@ -311,6 +311,7 @@ static const struct of_device_id ftm_quaddec_match[] = { · 310 unmodified lines | |||
| 311 | { .compatible = "fsl,ftm-quaddec" }, | 311 | { .compatible = "fsl,ftm-quaddec" }, |
| 312 | {}, | 312 | {}, |
| 313 | }; | 313 | }; |
| 314 | MODULE_DEVICE_TABLE(of, ftm_quaddec_match); | ||
| 314 | 315 | ||
| 315 | static struct platform_driver ftm_quaddec_driver = { | 316 | static struct platform_driver ftm_quaddec_driver = { |
| 316 | .driver = { | 317 | .driver = { |
| @@ -408,13 +408,9 @@ static int intel_qep_probe(struct pci_dev *pci, const struct pci_device_id *id) · 407 unmodified lines | |||
| 408 | 408 | ||
| 409 | pci_set_master(pci); | 409 | pci_set_master(pci); |
| 410 | 410 | ||
| 411 | ret = pcim_iomap_regions(pci, BIT(0), pci_name(pci)); | 411 | regs = pcim_iomap_region(pci, 0, pci_name(pci)); |
| 412 | if (ret) | 412 | if (IS_ERR(regs)) |
| 413 | return ret; | 413 | return PTR_ERR(regs); |
| 414 | |||
| 415 | regs = pcim_iomap_table(pci)[0]; | ||
| 416 | if (!regs) | ||
| 417 | return -ENOMEM; | ||
| 418 | 414 | ||
| 419 | qep->dev = dev; | 415 | qep->dev = dev; |
| 420 | qep->regs = regs; | 416 | qep->regs = regs; |
| @@ -214,11 +214,17 @@ static int stm32_count_enable_write(struct counter_device *counter, · 213 unmodified lines | |||
| 214 | { | 214 | { |
| 215 | struct stm32_timer_cnt *const priv = counter_priv(counter); | 215 | struct stm32_timer_cnt *const priv = counter_priv(counter); |
| 216 | u32 cr1; | 216 | u32 cr1; |
| 217 | int ret; | ||
| 217 | 218 | ||
| 218 | if (enable) { | 219 | if (enable) { |
| 219 | regmap_read(priv->regmap, TIM_CR1, &cr1); | 220 | regmap_read(priv->regmap, TIM_CR1, &cr1); |
| 220 | if (!(cr1 & TIM_CR1_CEN)) | 221 | if (!(cr1 & TIM_CR1_CEN)) { |
| 221 | clk_enable(priv->clk); | 222 | ret = clk_enable(priv->clk); |
| 223 | if (ret) { | ||
| 224 | dev_err(counter->parent, "Cannot enable clock %d\n", ret); | ||
| 225 | return ret; | ||
| 226 | } | ||
| 227 | } | ||
| 222 | 228 | ||
| 223 | regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, | 229 | regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, |
| 224 | TIM_CR1_CEN); | 230 | TIM_CR1_CEN); |
| @@ -694,6 +700,7 @@ static int stm32_timer_cnt_probe_encoder(struct device *dev, · 469 unmodified lines | |||
| 694 | } | 700 | } |
| 695 | 701 | ||
| 696 | ret = of_property_read_u32(tnode, "reg", &idx); | 702 | ret = of_property_read_u32(tnode, "reg", &idx); |
| 703 | of_node_put(tnode); | ||
| 697 | if (ret) { | 704 | if (ret) { |
| 698 | dev_err(dev, "Can't get index (%d)\n", ret); | 705 | dev_err(dev, "Can't get index (%d)\n", ret); |
| 699 | return ret; | 706 | return ret; |
| @@ -816,7 +823,11 @@ static int __maybe_unused stm32_timer_cnt_resume(struct device *dev) · 116 unmodified lines | |||
| 816 | return ret; | 823 | return ret; |
| 817 | 824 | ||
| 818 | if (priv->enabled) { | 825 | if (priv->enabled) { |
| 819 | clk_enable(priv->clk); | 826 | ret = clk_enable(priv->clk); |
| 827 | if (ret) { | ||
| 828 | dev_err(dev, "Cannot enable clock %d\n", ret); | ||
| 829 | return ret; | ||
| 830 | } | ||
| 820 | 831 | ||
| 821 | /* Restore registers that may have been lost */ | 832 | /* Restore registers that may have been lost */ |
| 822 | regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr); | 833 | regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr); |
| @@ -574,8 +574,13 @@ static int ecap_cnt_resume(struct device *dev) · 573 unmodified lines | |||
| 574 | { | 574 | { |
| 575 | struct counter_device *counter_dev = dev_get_drvdata(dev); | 575 | struct counter_device *counter_dev = dev_get_drvdata(dev); |
| 576 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev); | 576 | struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev); |
| 577 | int ret; | ||
| 577 | 578 | ||
| 578 | clk_enable(ecap_dev->clk); | 579 | ret = clk_enable(ecap_dev->clk); |
| 580 | if (ret) { | ||
| 581 | dev_err(dev, "Cannot enable clock %d\n", ret); | ||
| 582 | return ret; | ||
| 583 | } | ||
| 579 | 584 | ||
| 580 | ecap_cnt_capture_set_evmode(counter_dev, ecap_dev->pm_ctx.ev_mode); | 585 | ecap_cnt_capture_set_evmode(counter_dev, ecap_dev->pm_ctx.ev_mode); |
| 581 | 586 | ||
| @@ -3333,7 +3333,7 @@ static struct platform_driver scmi_driver = { · 3332 unmodified lines | |||
| 3333 | .dev_groups = versions_groups, | 3333 | .dev_groups = versions_groups, |
| 3334 | }, | 3334 | }, |
| 3335 | .probe = scmi_probe, | 3335 | .probe = scmi_probe, |
| 3336 | .remove_new = scmi_remove, | 3336 | .remove = scmi_remove, |
| 3337 | }; | 3337 | }; |
| 3338 | 3338 | ||
| 3339 | static struct dentry *scmi_debugfs_init(void) | 3339 | static struct dentry *scmi_debugfs_init(void) |
| @@ -1049,7 +1049,7 @@ static struct platform_driver scpi_driver = { · 1048 unmodified lines | |||
| 1049 | .dev_groups = versions_groups, | 1049 | .dev_groups = versions_groups, |
| 1050 | }, | 1050 | }, |
| 1051 | .probe = scpi_probe, | 1051 | .probe = scpi_probe, |
| 1052 | .remove_new = scpi_remove, | 1052 | .remove = scpi_remove, |
| 1053 | }; | 1053 | }; |
| 1054 | module_platform_driver(scpi_driver); | 1054 | module_platform_driver(scpi_driver); |
| 1055 | 1055 | ||
| @@ -220,7 +220,7 @@ MODULE_DEVICE_TABLE(of, coreboot_of_match); · 219 unmodified lines | |||
| 220 | 220 | ||
| 221 | static struct platform_driver coreboot_table_driver = { | 221 | static struct platform_driver coreboot_table_driver = { |
| 222 | .probe = coreboot_table_probe, | 222 | .probe = coreboot_table_probe, |
| 223 | .remove_new = coreboot_table_remove, | 223 | .remove = coreboot_table_remove, |
| 224 | .driver = { | 224 | .driver = { |
| 225 | .name = "coreboot_table", | 225 | .name = "coreboot_table", |
| 226 | .acpi_match_table = ACPI_PTR(cros_coreboot_acpi_match), | 226 | .acpi_match_table = ACPI_PTR(cros_coreboot_acpi_match), |
| @@ -180,7 +180,7 @@ static struct platform_driver imx_dsp_driver = { · 179 unmodified lines | |||
| 180 | .name = "imx-dsp", | 180 | .name = "imx-dsp", |
| 181 | }, | 181 | }, |
| 182 | .probe = imx_dsp_probe, | 182 | .probe = imx_dsp_probe, |
| 183 | .remove_new = imx_dsp_remove, | 183 | .remove = imx_dsp_remove, |
| 184 | }; | 184 | }; |
| 185 | builtin_platform_driver(imx_dsp_driver); | 185 | builtin_platform_driver(imx_dsp_driver); |
| 186 | 186 | ||
| @@ -116,7 +116,7 @@ static void __meminit release_firmware_map_entry(struct kobject *kobj) · 115 unmodified lines | |||
| 116 | kfree(entry); | 116 | kfree(entry); |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | static struct kobj_type __refdata memmap_ktype = { | 119 | static const struct kobj_type memmap_ktype = { |
| 120 | .release = release_firmware_map_entry, | 120 | .release = release_firmware_map_entry, |
| 121 | .sysfs_ops = &memmap_attr_ops, | 121 | .sysfs_ops = &memmap_attr_ops, |
| 122 | .default_groups = def_groups, | 122 | .default_groups = def_groups, |
| @@ -458,7 +458,7 @@ static struct platform_driver mpfs_auto_update_driver = { · 457 unmodified lines | |||
| 458 | .name = "mpfs-auto-update", | 458 | .name = "mpfs-auto-update", |
| 459 | }, | 459 | }, |
| 460 | .probe = mpfs_auto_update_probe, | 460 | .probe = mpfs_auto_update_probe, |
| 461 | .remove_new = mpfs_auto_update_remove, | 461 | .remove = mpfs_auto_update_remove, |
| 462 | }; | 462 | }; |
| 463 | module_platform_driver(mpfs_auto_update_driver); | 463 | module_platform_driver(mpfs_auto_update_driver); |
| 464 | 464 | ||
| @@ -95,10 +95,9 @@ static int mtk_adsp_ipc_probe(struct platform_device *pdev) · 94 unmodified lines | |||
| 95 | adsp_chan->idx = i; | 95 | adsp_chan->idx = i; |
| 96 | adsp_chan->ch = mbox_request_channel_byname(cl, adsp_mbox_ch_names[i]); | 96 | adsp_chan->ch = mbox_request_channel_byname(cl, adsp_mbox_ch_names[i]); |
| 97 | if (IS_ERR(adsp_chan->ch)) { | 97 | if (IS_ERR(adsp_chan->ch)) { |
| 98 | ret = PTR_ERR(adsp_chan->ch); | 98 | ret = dev_err_probe(dev, PTR_ERR(adsp_chan->ch), |
| 99 | if (ret != -EPROBE_DEFER) | 99 | "Failed to request mbox channel %s\n", |
| 100 | dev_err(dev, "Failed to request mbox chan %s ret %d\n", | 100 | adsp_mbox_ch_names[i]); |
| 101 | adsp_mbox_ch_names[i], ret); | ||
| 102 | 101 | ||
| 103 | for (j = 0; j < i; j++) { | 102 | for (j = 0; j < i; j++) { |
| 104 | adsp_chan = &adsp_ipc->chans[j]; | 103 | adsp_chan = &adsp_ipc->chans[j]; |
| @@ -133,7 +132,7 @@ static struct platform_driver mtk_adsp_ipc_driver = { · 28 unmodified lines | |||
| 133 | .name = "mtk-adsp-ipc", | 132 | .name = "mtk-adsp-ipc", |
| 134 | }, | 133 | }, |
| 135 | .probe = mtk_adsp_ipc_probe, | 134 | .probe = mtk_adsp_ipc_probe, |
| 136 | .remove_new = mtk_adsp_ipc_remove, | 135 | .remove = mtk_adsp_ipc_remove, |
| 137 | }; | 136 | }; |
| 138 | builtin_platform_driver(mtk_adsp_ipc_driver); | 137 | builtin_platform_driver(mtk_adsp_ipc_driver); |
| 139 | 138 | ||
| @@ -757,7 +757,7 @@ MODULE_DEVICE_TABLE(acpi, fw_cfg_sysfs_acpi_match); · 756 unmodified lines | |||
| 757 | 757 | ||
| 758 | static struct platform_driver fw_cfg_sysfs_driver = { | 758 | static struct platform_driver fw_cfg_sysfs_driver = { |
| 759 | .probe = fw_cfg_sysfs_probe, | 759 | .probe = fw_cfg_sysfs_probe, |
| 760 | .remove_new = fw_cfg_sysfs_remove, | 760 | .remove = fw_cfg_sysfs_remove, |
| 761 | .driver = { | 761 | .driver = { |
| 762 | .name = "fw_cfg", | 762 | .name = "fw_cfg", |
| 763 | .of_match_table = fw_cfg_sysfs_mmio_match, | 763 | .of_match_table = fw_cfg_sysfs_mmio_match, |
| @@ -406,7 +406,7 @@ static struct platform_driver rpi_firmware_driver = { · 405 unmodified lines | |||
| 406 | }, | 406 | }, |
| 407 | .probe = rpi_firmware_probe, | 407 | .probe = rpi_firmware_probe, |
| 408 | .shutdown = rpi_firmware_shutdown, | 408 | .shutdown = rpi_firmware_shutdown, |
| 409 | .remove_new = rpi_firmware_remove, | 409 | .remove = rpi_firmware_remove, |
| 410 | }; | 410 | }; |
| 411 | module_platform_driver(rpi_firmware_driver); | 411 | module_platform_driver(rpi_firmware_driver); |
| 412 | 412 | ||
| @@ -802,7 +802,7 @@ static void stratix10_rsu_remove(struct platform_device *pdev) · 801 unmodified lines | |||
| 802 | 802 | ||
| 803 | static struct platform_driver stratix10_rsu_driver = { | 803 | static struct platform_driver stratix10_rsu_driver = { |
| 804 | .probe = stratix10_rsu_probe, | 804 | .probe = stratix10_rsu_probe, |
| 805 | .remove_new = stratix10_rsu_remove, | 805 | .remove = stratix10_rsu_remove, |
| 806 | .driver = { | 806 | .driver = { |
| 807 | .name = "stratix10-rsu", | 807 | .name = "stratix10-rsu", |
| 808 | .dev_groups = rsu_groups, | 808 | .dev_groups = rsu_groups, |
| @@ -1271,7 +1271,7 @@ static void stratix10_svc_drv_remove(struct platform_device *pdev) · 1270 unmodified lines | |||
| 1271 | 1271 | ||
| 1272 | static struct platform_driver stratix10_svc_driver = { | 1272 | static struct platform_driver stratix10_svc_driver = { |
| 1273 | .probe = stratix10_svc_drv_probe, | 1273 | .probe = stratix10_svc_drv_probe, |
| 1274 | .remove_new = stratix10_svc_drv_remove, | 1274 | .remove = stratix10_svc_drv_remove, |
| 1275 | .driver = { | 1275 | .driver = { |
| 1276 | .name = "stratix10-svc", | 1276 | .name = "stratix10-svc", |
| 1277 | .of_match_table = stratix10_svc_drv_match, | 1277 | .of_match_table = stratix10_svc_drv_match, |
| @@ -2118,6 +2118,6 @@ static struct platform_driver zynqmp_firmware_driver = { · 2117 unmodified lines | |||
| 2118 | .dev_groups = zynqmp_firmware_groups, | 2118 | .dev_groups = zynqmp_firmware_groups, |
| 2119 | }, | 2119 | }, |
| 2120 | .probe = zynqmp_firmware_probe, | 2120 | .probe = zynqmp_firmware_probe, |
| 2121 | .remove_new = zynqmp_firmware_remove, | 2121 | .remove = zynqmp_firmware_remove, |
| 2122 | }; | 2122 | }; |
| 2123 | module_platform_driver(zynqmp_firmware_driver); | 2123 | module_platform_driver(zynqmp_firmware_driver); |
| @@ -152,7 +152,7 @@ MODULE_DEVICE_TABLE(of, altera_fpga_of_match); · 151 unmodified lines | |||
| 152 | 152 | ||
| 153 | static struct platform_driver altera_fpga_driver = { | 153 | static struct platform_driver altera_fpga_driver = { |
| 154 | .probe = alt_fpga_bridge_probe, | 154 | .probe = alt_fpga_bridge_probe, |
| 155 | .remove_new = alt_fpga_bridge_remove, | 155 | .remove = alt_fpga_bridge_remove, |
| 156 | .driver = { | 156 | .driver = { |
| 157 | .name = "altera_fpga2sdram_bridge", | 157 | .name = "altera_fpga2sdram_bridge", |
| 158 | .of_match_table = of_match_ptr(altera_fpga_of_match), | 158 | .of_match_table = of_match_ptr(altera_fpga_of_match), |
| @@ -262,7 +262,7 @@ static void altera_freeze_br_remove(struct platform_device *pdev) · 261 unmodified lines | |||
| 262 | 262 | ||
| 263 | static struct platform_driver altera_freeze_br_driver = { | 263 | static struct platform_driver altera_freeze_br_driver = { |
| 264 | .probe = altera_freeze_br_probe, | 264 | .probe = altera_freeze_br_probe, |
| 265 | .remove_new = altera_freeze_br_remove, | 265 | .remove = altera_freeze_br_remove, |
| 266 | .driver = { | 266 | .driver = { |
| 267 | .name = "altera_freeze_br", | 267 | .name = "altera_freeze_br", |
| 268 | .of_match_table = altera_freeze_br_of_match, | 268 | .of_match_table = altera_freeze_br_of_match, |
| @@ -205,7 +205,7 @@ MODULE_DEVICE_TABLE(of, altera_fpga_of_match); · 204 unmodified lines | |||
| 205 | 205 | ||
| 206 | static struct platform_driver alt_fpga_bridge_driver = { | 206 | static struct platform_driver alt_fpga_bridge_driver = { |
| 207 | .probe = alt_fpga_bridge_probe, | 207 | .probe = alt_fpga_bridge_probe, |
| 208 | .remove_new = alt_fpga_bridge_remove, | 208 | .remove = alt_fpga_bridge_remove, |
| 209 | .driver = { | 209 | .driver = { |
| 210 | .name = "altera_hps2fpga_bridge", | 210 | .name = "altera_hps2fpga_bridge", |
| 211 | .of_match_table = of_match_ptr(altera_fpga_of_match), | 211 | .of_match_table = of_match_ptr(altera_fpga_of_match), |
| @@ -947,12 +947,12 @@ static const struct attribute_group *afu_dev_groups[] = { · 946 unmodified lines | |||
| 947 | }; | 947 | }; |
| 948 | 948 | ||
| 949 | static struct platform_driver afu_driver = { | 949 | static struct platform_driver afu_driver = { |
| 950 | .driver = { | 950 | .driver = { |
| 951 | .name = DFL_FPGA_FEATURE_DEV_PORT, | 951 | .name = DFL_FPGA_FEATURE_DEV_PORT, |
| 952 | .dev_groups = afu_dev_groups, | 952 | .dev_groups = afu_dev_groups, |
| 953 | }, | 953 | }, |
| 954 | .probe = afu_probe, | 954 | .probe = afu_probe, |
| 955 | .remove_new = afu_remove, | 955 | .remove = afu_remove, |
| 956 | }; | 956 | }; |
| 957 | 957 | ||
| 958 | static int __init afu_init(void) | 958 | static int __init afu_init(void) |
| @@ -92,11 +92,11 @@ static void fme_br_remove(struct platform_device *pdev) · 91 unmodified lines | |||
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | static struct platform_driver fme_br_driver = { | 94 | static struct platform_driver fme_br_driver = { |
| 95 | .driver = { | 95 | .driver = { |
| 96 | .name = DFL_FPGA_FME_BRIDGE, | 96 | .name = DFL_FPGA_FME_BRIDGE, |
| 97 | }, | 97 | }, |
| 98 | .probe = fme_br_probe, | 98 | .probe = fme_br_probe, |
| 99 | .remove_new = fme_br_remove, | 99 | .remove = fme_br_remove, |
| 100 | }; | 100 | }; |
| 101 | 101 | ||
| 102 | module_platform_driver(fme_br_driver); | 102 | module_platform_driver(fme_br_driver); |
| @@ -742,12 +742,12 @@ static const struct attribute_group *fme_dev_groups[] = { · 741 unmodified lines | |||
| 742 | }; | 742 | }; |
| 743 | 743 | ||
| 744 | static struct platform_driver fme_driver = { | 744 | static struct platform_driver fme_driver = { |
| 745 | .driver = { | 745 | .driver = { |
| 746 | .name = DFL_FPGA_FEATURE_DEV_FME, | 746 | .name = DFL_FPGA_FEATURE_DEV_FME, |
| 747 | .dev_groups = fme_dev_groups, | 747 | .dev_groups = fme_dev_groups, |
| 748 | }, | 748 | }, |
| 749 | .probe = fme_probe, | 749 | .probe = fme_probe, |
| 750 | .remove_new = fme_remove, | 750 | .remove = fme_remove, |
| 751 | }; | 751 | }; |
| 752 | 752 | ||
| 753 | module_platform_driver(fme_driver); | 753 | module_platform_driver(fme_driver); |
| @@ -71,11 +71,11 @@ static void fme_region_remove(struct platform_device *pdev) · 70 unmodified lines | |||
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | static struct platform_driver fme_region_driver = { | 73 | static struct platform_driver fme_region_driver = { |
| 74 | .driver = { | 74 | .driver = { |
| 75 | .name = DFL_FPGA_FME_REGION, | 75 | .name = DFL_FPGA_FME_REGION, |
| 76 | }, | 76 | }, |
| 77 | .probe = fme_region_probe, | 77 | .probe = fme_region_probe, |
| 78 | .remove_new = fme_region_remove, | 78 | .remove = fme_region_remove, |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | module_platform_driver(fme_region_driver); | 81 | module_platform_driver(fme_region_driver); |
| @@ -759,7 +759,7 @@ MODULE_DEVICE_TABLE(platform, intel_m10bmc_sec_ids); · 758 unmodified lines | |||
| 759 | 759 | ||
| 760 | static struct platform_driver intel_m10bmc_sec_driver = { | 760 | static struct platform_driver intel_m10bmc_sec_driver = { |
| 761 | .probe = m10bmc_sec_probe, | 761 | .probe = m10bmc_sec_probe, |
| 762 | .remove_new = m10bmc_sec_remove, | 762 | .remove = m10bmc_sec_remove, |
| 763 | .driver = { | 763 | .driver = { |
| 764 | .name = "intel-m10bmc-sec-update", | 764 | .name = "intel-m10bmc-sec-update", |
| 765 | .dev_groups = m10bmc_sec_attr_groups, | 765 | .dev_groups = m10bmc_sec_attr_groups, |
| @@ -436,7 +436,7 @@ static void of_fpga_region_remove(struct platform_device *pdev) · 435 unmodified lines | |||
| 436 | 436 | ||
| 437 | static struct platform_driver of_fpga_region_driver = { | 437 | static struct platform_driver of_fpga_region_driver = { |
| 438 | .probe = of_fpga_region_probe, | 438 | .probe = of_fpga_region_probe, |
| 439 | .remove_new = of_fpga_region_remove, | 439 | .remove = of_fpga_region_remove, |
| 440 | .driver = { | 440 | .driver = { |
| 441 | .name = "of-fpga-region", | 441 | .name = "of-fpga-region", |
| 442 | .of_match_table = of_match_ptr(fpga_region_of_match), | 442 | .of_match_table = of_match_ptr(fpga_region_of_match), |
| @@ -535,7 +535,7 @@ MODULE_DEVICE_TABLE(of, socfpga_a10_fpga_of_match); · 534 unmodified lines | |||
| 535 | 535 | ||
| 536 | static struct platform_driver socfpga_a10_fpga_driver = { | 536 | static struct platform_driver socfpga_a10_fpga_driver = { |
| 537 | .probe = socfpga_a10_fpga_probe, | 537 | .probe = socfpga_a10_fpga_probe, |
| 538 | .remove_new = socfpga_a10_fpga_remove, | 538 | .remove = socfpga_a10_fpga_remove, |
| 539 | .driver = { | 539 | .driver = { |
| 540 | .name = "socfpga_a10_fpga_manager", | 540 | .name = "socfpga_a10_fpga_manager", |
| 541 | .of_match_table = socfpga_a10_fpga_of_match, | 541 | .of_match_table = socfpga_a10_fpga_of_match, |
| @@ -455,7 +455,7 @@ MODULE_DEVICE_TABLE(of, s10_of_match); · 454 unmodified lines | |||
| 455 | 455 | ||
| 456 | static struct platform_driver s10_driver = { | 456 | static struct platform_driver s10_driver = { |
| 457 | .probe = s10_probe, | 457 | .probe = s10_probe, |
| 458 | .remove_new = s10_remove, | 458 | .remove = s10_remove, |
| 459 | .driver = { | 459 | .driver = { |
| 460 | .name = "Stratix10 SoC FPGA manager", | 460 | .name = "Stratix10 SoC FPGA manager", |
| 461 | .of_match_table = of_match_ptr(s10_of_match), | 461 | .of_match_table = of_match_ptr(s10_of_match), |
| @@ -162,7 +162,7 @@ static void xlnx_pr_decoupler_remove(struct platform_device *pdev) · 161 unmodified lines | |||
| 162 | 162 | ||
| 163 | static struct platform_driver xlnx_pr_decoupler_driver = { | 163 | static struct platform_driver xlnx_pr_decoupler_driver = { |
| 164 | .probe = xlnx_pr_decoupler_probe, | 164 | .probe = xlnx_pr_decoupler_probe, |
| 165 | .remove_new = xlnx_pr_decoupler_remove, | 165 | .remove = xlnx_pr_decoupler_remove, |
| 166 | .driver = { | 166 | .driver = { |
| 167 | .name = "xlnx_pr_decoupler", | 167 | .name = "xlnx_pr_decoupler", |
| 168 | .of_match_table = xlnx_pr_decoupler_of_match, | 168 | .of_match_table = xlnx_pr_decoupler_of_match, |
| @@ -642,7 +642,7 @@ MODULE_DEVICE_TABLE(of, zynq_fpga_of_match); · 641 unmodified lines | |||
| 642 | 642 | ||
| 643 | static struct platform_driver zynq_fpga_driver = { | 643 | static struct platform_driver zynq_fpga_driver = { |
| 644 | .probe = zynq_fpga_probe, | 644 | .probe = zynq_fpga_probe, |
| 645 | .remove_new = zynq_fpga_remove, | 645 | .remove = zynq_fpga_remove, |
| 646 | .driver = { | 646 | .driver = { |
| 647 | .name = "zynq_fpga_manager", | 647 | .name = "zynq_fpga_manager", |
| 648 | .of_match_table = of_match_ptr(zynq_fpga_of_match), | 648 | .of_match_table = of_match_ptr(zynq_fpga_of_match), |
| @@ -780,7 +780,7 @@ const struct device_type greybus_interface_type = { · 779 unmodified lines | |||
| 780 | * The position of interface within the Endo is encoded in "interface_id" | 780 | * The position of interface within the Endo is encoded in "interface_id" |
| 781 | * argument. | 781 | * argument. |
| 782 | * | 782 | * |
| 783 | * Returns a pointer to the new interfce or a null pointer if a | 783 | * Returns a pointer to the new interface or a null pointer if a |
| 784 | * failure occurs due to memory exhaustion. | 784 | * failure occurs due to memory exhaustion. |
| 785 | */ | 785 | */ |
| 786 | struct gb_interface *gb_interface_create(struct gb_module *module, | 786 | struct gb_interface *gb_interface_create(struct gb_module *module, |
| @@ -643,7 +643,7 @@ static irqreturn_t adxl355_trigger_handler(int irq, void *p) · 642 unmodified lines | |||
| 643 | * The acceleration data is 24 bits and big endian. It has to be saved | 643 | * The acceleration data is 24 bits and big endian. It has to be saved |
| 644 | * in 32 bits, hence, it is saved in the 2nd byte of the 4 byte buffer. | 644 | * in 32 bits, hence, it is saved in the 2nd byte of the 4 byte buffer. |
| 645 | * The buf array is 14 bytes as it includes 3x4=12 bytes for | 645 | * The buf array is 14 bytes as it includes 3x4=12 bytes for |
| 646 | * accelaration data of x, y, and z axis. It also includes 2 bytes for | 646 | * acceleration data of x, y, and z axis. It also includes 2 bytes for |
| 647 | * temperature data. | 647 | * temperature data. |
| 648 | */ | 648 | */ |
| 649 | ret = regmap_bulk_read(data->regmap, ADXL355_XDATA3_REG, | 649 | ret = regmap_bulk_read(data->regmap, ADXL355_XDATA3_REG, |
| @@ -1073,7 +1073,7 @@ static int adxl367_write_event_config(struct iio_dev *indio_dev, · 1072 unmodified lines | |||
| 1073 | const struct iio_chan_spec *chan, | 1073 | const struct iio_chan_spec *chan, |
| 1074 | enum iio_event_type type, | 1074 | enum iio_event_type type, |
| 1075 | enum iio_event_direction dir, | 1075 | enum iio_event_direction dir, |
| 1076 | int state) | 1076 | bool state) |
| 1077 | { | 1077 | { |
| 1078 | enum adxl367_activity_type act; | 1078 | enum adxl367_activity_type act; |
| 1079 | 1079 | ||
| @@ -940,7 +940,7 @@ static int adxl372_read_event_config(struct iio_dev *indio_dev, const struct iio · 939 unmodified lines | |||
| 940 | 940 | ||
| 941 | static int adxl372_write_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, | 941 | static int adxl372_write_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, |
| 942 | enum iio_event_type type, enum iio_event_direction dir, | 942 | enum iio_event_type type, enum iio_event_direction dir, |
| 943 | int state) | 943 | bool state) |
| 944 | { | 944 | { |
| 945 | struct adxl372_state *st = iio_priv(indio_dev); | 945 | struct adxl372_state *st = iio_priv(indio_dev); |
| 946 | 946 | ||
| @@ -1181,7 +1181,7 @@ static int adxl380_read_raw(struct iio_dev *indio_dev, · 1180 unmodified lines | |||
| 1181 | 1181 | ||
| 1182 | ret = adxl380_read_chn(st, chan->address); | 1182 | ret = adxl380_read_chn(st, chan->address); |
| 1183 | iio_device_release_direct_mode(indio_dev); | 1183 | iio_device_release_direct_mode(indio_dev); |
| 1184 | if (ret) | 1184 | if (ret < 0) |
| 1185 | return ret; | 1185 | return ret; |
| 1186 | 1186 | ||
| 1187 | *val = sign_extend32(ret >> chan->scan_type.shift, | 1187 | *val = sign_extend32(ret >> chan->scan_type.shift, |
| @@ -1386,7 +1386,7 @@ static int adxl380_write_event_config(struct iio_dev *indio_dev, · 198 unmodified lines | |||
| 1386 | const struct iio_chan_spec *chan, | 1386 | const struct iio_chan_spec *chan, |
| 1387 | enum iio_event_type type, | 1387 | enum iio_event_type type, |
| 1388 | enum iio_event_direction dir, | 1388 | enum iio_event_direction dir, |
| 1389 | int state) | 1389 | bool state) |
| 1390 | { | 1390 | { |
| 1391 | struct adxl380_state *st = iio_priv(indio_dev); | 1391 | struct adxl380_state *st = iio_priv(indio_dev); |
| 1392 | enum adxl380_axis axis; | 1392 | enum adxl380_axis axis; |
| @@ -1719,7 +1719,6 @@ static int adxl380_config_irq(struct iio_dev *indio_dev) · 326 unmodified lines | |||
| 1719 | { | 1719 | { |
| 1720 | struct adxl380_state *st = iio_priv(indio_dev); | 1720 | struct adxl380_state *st = iio_priv(indio_dev); |
| 1721 | unsigned long irq_flag; | 1721 | unsigned long irq_flag; |
| 1722 | struct irq_data *desc; | ||
| 1723 | u32 irq_type; | 1722 | u32 irq_type; |
| 1724 | u8 polarity; | 1723 | u8 polarity; |
| 1725 | int ret; | 1724 | int ret; |
| @@ -1737,11 +1736,7 @@ static int adxl380_config_irq(struct iio_dev *indio_dev) · 11 unmodified lines | |||
| 1737 | st->int_map[1] = ADXL380_INT1_MAP1_REG; | 1736 | st->int_map[1] = ADXL380_INT1_MAP1_REG; |
| 1738 | } | 1737 | } |
| 1739 | 1738 | ||
| 1740 | desc = irq_get_irq_data(st->irq); | 1739 | irq_type = irq_get_trigger_type(st->irq); |
| 1741 | if (!desc) | ||
| 1742 | return dev_err_probe(st->dev, -EINVAL, "Could not find IRQ %d\n", st->irq); | ||
| 1743 | |||
| 1744 | irq_type = irqd_get_trigger_type(desc); | ||
| 1745 | if (irq_type == IRQ_TYPE_LEVEL_HIGH) { | 1740 | if (irq_type == IRQ_TYPE_LEVEL_HIGH) { |
| 1746 | polarity = 0; | 1741 | polarity = 0; |
| 1747 | irq_flag = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; | 1742 | irq_flag = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | |||
| 21 | #include <linux/regulator/consumer.h> | 21 | #include <linux/regulator/consumer.h> |
| 22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
| 24 | #include <linux/types.h> | ||
| 24 | #include <linux/iio/iio.h> | 25 | #include <linux/iio/iio.h> |
| 25 | #include <linux/iio/sysfs.h> | 26 | #include <linux/iio/sysfs.h> |
| 26 | #include <linux/iio/buffer.h> | 27 | #include <linux/iio/buffer.h> |
| @@ -144,7 +145,7 @@ struct bma180_data { · 117 unmodified lines | |||
| 144 | /* Ensure timestamp is naturally aligned */ | 145 | /* Ensure timestamp is naturally aligned */ |
| 145 | struct { | 146 | struct { |
| 146 | s16 chan[4]; | 147 | s16 chan[4]; |
| 147 | s64 timestamp __aligned(8); | 148 | aligned_s64 timestamp; |
| 148 | } scan; | 149 | } scan; |
| 149 | }; | 150 | }; |
| 150 | 151 | ||
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/mod_devicetable.h> | 10 | #include <linux/mod_devicetable.h> |
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/types.h> | ||
| 12 | #include <linux/spi/spi.h> | 13 | #include <linux/spi/spi.h> |
| 13 | 14 | ||
| 14 | #include <linux/iio/buffer.h> | 15 | #include <linux/iio/buffer.h> |
| @@ -115,7 +115,7 @@ struct bma400_data { · 114 unmodified lines | |||
| 115 | struct { | 115 | struct { |
| 116 | __le16 buff[3]; | 116 | __le16 buff[3]; |
| 117 | u8 temperature; | 117 | u8 temperature; |
| 118 | s64 ts __aligned(8); | 118 | aligned_s64 ts; |
| 119 | } buffer __aligned(IIO_DMA_MINALIGN); | 119 | } buffer __aligned(IIO_DMA_MINALIGN); |
| 120 | __le16 status; | 120 | __le16 status; |
| 121 | __be16 duration; | 121 | __be16 duration; |
| @@ -1293,7 +1293,7 @@ static int bma400_disable_adv_interrupt(struct bma400_data *data) · 1171 unmodified lines | |||
| 1293 | static int bma400_write_event_config(struct iio_dev *indio_dev, | 1293 | static int bma400_write_event_config(struct iio_dev *indio_dev, |
| 1294 | const struct iio_chan_spec *chan, | 1294 | const struct iio_chan_spec *chan, |
| 1295 | enum iio_event_type type, | 1295 | enum iio_event_type type, |
| 1296 | enum iio_event_direction dir, int state) | 1296 | enum iio_event_direction dir, bool state) |
| 1297 | { | 1297 | { |
| 1298 | struct bma400_data *data = iio_priv(indio_dev); | 1298 | struct bma400_data *data = iio_priv(indio_dev); |
| 1299 | int ret; | 1299 | int ret; |
| @@ -804,7 +804,7 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev, · 803 unmodified lines | |||
| 804 | const struct iio_chan_spec *chan, | 804 | const struct iio_chan_spec *chan, |
| 805 | enum iio_event_type type, | 805 | enum iio_event_type type, |
| 806 | enum iio_event_direction dir, | 806 | enum iio_event_direction dir, |
| 807 | int state) | 807 | bool state) |
| 808 | { | 808 | { |
| 809 | struct bmc150_accel_data *data = iio_priv(indio_dev); | 809 | struct bmc150_accel_data *data = iio_priv(indio_dev); |
| 810 | int ret; | 810 | int ret; |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | |||
| 6 | #include <linux/iio/iio.h> | 6 | #include <linux/iio/iio.h> |
| 7 | #include <linux/mutex.h> | 7 | #include <linux/mutex.h> |
| 8 | #include <linux/regulator/consumer.h> | 8 | #include <linux/regulator/consumer.h> |
| 9 | #include <linux/types.h> | ||
| 9 | #include <linux/workqueue.h> | 10 | #include <linux/workqueue.h> |
| 10 | 11 | ||
| 11 | struct regmap; | 12 | struct regmap; |
| @@ -69,7 +70,7 @@ struct bmc150_accel_data { · 57 unmodified lines | |||
| 69 | */ | 70 | */ |
| 70 | struct { | 71 | struct { |
| 71 | __le16 channels[3]; | 72 | __le16 channels[3]; |
| 72 | s64 ts __aligned(8); | 73 | aligned_s64 ts; |
| 73 | } scan; | 74 | } scan; |
| 74 | u8 bw_bits; | 75 | u8 bw_bits; |
| 75 | u32 slope_dur; | 76 | u32 slope_dur; |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | |||
| 22 | #include <linux/property.h> | 22 | #include <linux/property.h> |
| 23 | #include <linux/regulator/consumer.h> | 23 | #include <linux/regulator/consumer.h> |
| 24 | #include <linux/regmap.h> | 24 | #include <linux/regmap.h> |
| 25 | #include <linux/types.h> | ||
| 25 | 26 | ||
| 26 | #include <linux/iio/buffer.h> | 27 | #include <linux/iio/buffer.h> |
| 27 | #include <linux/iio/events.h> | 28 | #include <linux/iio/events.h> |
| @@ -163,7 +164,7 @@ struct fxls8962af_data { · 135 unmodified lines | |||
| 163 | const struct fxls8962af_chip_info *chip_info; | 164 | const struct fxls8962af_chip_info *chip_info; |
| 164 | struct { | 165 | struct { |
| 165 | __le16 channels[3]; | 166 | __le16 channels[3]; |
| 166 | s64 ts __aligned(8); | 167 | aligned_s64 ts; |
| 167 | } scan; | 168 | } scan; |
| 168 | int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */ | 169 | int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */ |
| 169 | struct iio_mount_matrix orientation; | 170 | struct iio_mount_matrix orientation; |
| @@ -616,7 +617,7 @@ static int · 446 unmodified lines | |||
| 616 | fxls8962af_write_event_config(struct iio_dev *indio_dev, | 617 | fxls8962af_write_event_config(struct iio_dev *indio_dev, |
| 617 | const struct iio_chan_spec *chan, | 618 | const struct iio_chan_spec *chan, |
| 618 | enum iio_event_type type, | 619 | enum iio_event_type type, |
| 619 | enum iio_event_direction dir, int state) | 620 | enum iio_event_direction dir, bool state) |
| 620 | { | 621 | { |
| 621 | struct fxls8962af_data *data = iio_priv(indio_dev); | 622 | struct fxls8962af_data *data = iio_priv(indio_dev); |
| 622 | u8 enable_event, enable_bits; | 623 | u8 enable_event, enable_bits; |
| @@ -1103,8 +1104,7 @@ static int fxls8962af_irq_setup(struct iio_dev *indio_dev, int irq) · 480 unmodified lines | |||
| 1103 | if (ret) | 1104 | if (ret) |
| 1104 | return ret; | 1105 | return ret; |
| 1105 | 1106 | ||
| 1106 | irq_type = irqd_get_trigger_type(irq_get_irq_data(irq)); | 1107 | irq_type = irq_get_trigger_type(irq); |
| 1107 | |||
| 1108 | switch (irq_type) { | 1108 | switch (irq_type) { |
| 1109 | case IRQF_TRIGGER_HIGH: | 1109 | case IRQF_TRIGGER_HIGH: |
| 1110 | case IRQF_TRIGGER_RISING: | 1110 | case IRQF_TRIGGER_RISING: |
| @@ -28,7 +28,7 @@ struct accel_3d_state { · 27 unmodified lines | |||
| 28 | /* Ensure timestamp is naturally aligned */ | 28 | /* Ensure timestamp is naturally aligned */ |
| 29 | struct { | 29 | struct { |
| 30 | u32 accel_val[3]; | 30 | u32 accel_val[3]; |
| 31 | s64 timestamp __aligned(8); | 31 | aligned_s64 timestamp; |
| 32 | } scan; | 32 | } scan; |
| 33 | int scale_pre_decml; | 33 | int scale_pre_decml; |
| 34 | int scale_post_decml; | 34 | int scale_post_decml; |
| @@ -328,6 +328,7 @@ static int accel_3d_parse_report(struct platform_device *pdev, · 293 unmodified lines | |||
| 328 | /* Function to initialize the processing for usage id */ | 328 | /* Function to initialize the processing for usage id */ |
| 329 | static int hid_accel_3d_probe(struct platform_device *pdev) | 329 | static int hid_accel_3d_probe(struct platform_device *pdev) |
| 330 | { | 330 | { |
| 331 | struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); | ||
| 331 | int ret = 0; | 332 | int ret = 0; |
| 332 | const char *name; | 333 | const char *name; |
| 333 | struct iio_dev *indio_dev; | 334 | struct iio_dev *indio_dev; |
| @@ -335,8 +336,6 @@ static int hid_accel_3d_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 335 | const struct iio_chan_spec *channel_spec; | 336 | const struct iio_chan_spec *channel_spec; |
| 336 | int channel_size; | 337 | int channel_size; |
| 337 | 338 | ||
| 338 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | ||
| 339 | |||
| 340 | indio_dev = devm_iio_device_alloc(&pdev->dev, | 339 | indio_dev = devm_iio_device_alloc(&pdev->dev, |
| 341 | sizeof(struct accel_3d_state)); | 340 | sizeof(struct accel_3d_state)); |
| 342 | if (indio_dev == NULL) | 341 | if (indio_dev == NULL) |
| @@ -424,7 +423,7 @@ error_remove_trigger: · 81 unmodified lines | |||
| 424 | /* Function to deinitialize the processing for usage id */ | 423 | /* Function to deinitialize the processing for usage id */ |
| 425 | static void hid_accel_3d_remove(struct platform_device *pdev) | 424 | static void hid_accel_3d_remove(struct platform_device *pdev) |
| 426 | { | 425 | { |
| 427 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | 426 | struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); |
| 428 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); | 427 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); |
| 429 | struct accel_3d_state *accel_state = iio_priv(indio_dev); | 428 | struct accel_3d_state *accel_state = iio_priv(indio_dev); |
| 430 | 429 | ||
| @@ -452,7 +451,7 @@ static struct platform_driver hid_accel_3d_platform_driver = { · 21 unmodified lines | |||
| 452 | .pm = &hid_sensor_pm_ops, | 451 | .pm = &hid_sensor_pm_ops, |
| 453 | }, | 452 | }, |
| 454 | .probe = hid_accel_3d_probe, | 453 | .probe = hid_accel_3d_probe, |
| 455 | .remove_new = hid_accel_3d_remove, | 454 | .remove = hid_accel_3d_remove, |
| 456 | }; | 455 | }; |
| 457 | module_platform_driver(hid_accel_3d_platform_driver); | 456 | module_platform_driver(hid_accel_3d_platform_driver); |
| 458 | 457 | ||
| @@ -16,6 +16,7 @@ · 15 unmodified lines | |||
| 16 | #include <linux/regulator/consumer.h> | 16 | #include <linux/regulator/consumer.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/string_choices.h> | 18 | #include <linux/string_choices.h> |
| 19 | #include <linux/types.h> | ||
| 19 | #include <linux/units.h> | 20 | #include <linux/units.h> |
| 20 | 21 | ||
| 21 | #include <linux/iio/iio.h> | 22 | #include <linux/iio/iio.h> |
| @@ -292,7 +293,7 @@ struct kx022a_data { · 270 unmodified lines | |||
| 292 | __le16 buffer[8] __aligned(IIO_DMA_MINALIGN); | 293 | __le16 buffer[8] __aligned(IIO_DMA_MINALIGN); |
| 293 | struct { | 294 | struct { |
| 294 | __le16 channels[3]; | 295 | __le16 channels[3]; |
| 295 | s64 ts __aligned(8); | 296 | aligned_s64 ts; |
| 296 | } scan; | 297 | } scan; |
| 297 | }; | 298 | }; |
| 298 | 299 | ||
| @@ -594,7 +595,7 @@ static int kx022a_get_axis(struct kx022a_data *data, · 295 unmodified lines | |||
| 594 | if (ret) | 595 | if (ret) |
| 595 | return ret; | 596 | return ret; |
| 596 | 597 | ||
| 597 | *val = le16_to_cpu(data->buffer[0]); | 598 | *val = (s16)le16_to_cpu(data->buffer[0]); |
| 598 | 599 | ||
| 599 | return IIO_VAL_INT; | 600 | return IIO_VAL_INT; |
| 600 | } | 601 | } |
| @@ -4,13 +4,15 @@ · 3 unmodified lines | |||
| 4 | * Copyright (c) 2014, Intel Corporation. | 4 | * Copyright (c) 2014, Intel Corporation. |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/i2c.h> | 7 | #include <linux/i2c.h> |
| 9 | #include <linux/interrupt.h> | 8 | #include <linux/interrupt.h> |
| 10 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
| 11 | #include <linux/bitops.h> | 10 | #include <linux/bitops.h> |
| 11 | #include <linux/mod_devicetable.h> | ||
| 12 | #include <linux/module.h> | ||
| 12 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
| 13 | #include <linux/string.h> | 14 | #include <linux/string.h> |
| 15 | #include <linux/types.h> | ||
| 14 | #include <linux/acpi.h> | 16 | #include <linux/acpi.h> |
| 15 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
| 16 | #include <linux/pm_runtime.h> | 18 | #include <linux/pm_runtime.h> |
| @@ -168,14 +170,73 @@ · 151 unmodified lines | |||
| 168 | 170 | ||
| 169 | #define KXCJK1013_DEFAULT_WAKE_THRES 1 | 171 | #define KXCJK1013_DEFAULT_WAKE_THRES 1 |
| 170 | 172 | ||
| 171 | enum kx_chipset { | 173 | /* Refer to section 4 of the specification */ |
| 172 | KXCJK1013, | 174 | struct kx_odr_start_up_time { |
| 173 | KXCJ91008, | 175 | int odr_bits; |
| 174 | KXTJ21009, | 176 | int usec; |
| 175 | KXTF9, | 177 | }; |
| 176 | KX0221020, | 178 | |
| 177 | KX0231025, | 179 | /* KXCJK-1013 */ |
| 178 | KX_MAX_CHIPS /* this must be last */ | 180 | static const struct kx_odr_start_up_time kxcjk1013_odr_start_up_times[] = { |
| 181 | { 0x08, 100000 }, | ||
| 182 | { 0x09, 100000 }, | ||
| 183 | { 0x0A, 100000 }, | ||
| 184 | { 0x0B, 100000 }, | ||
| 185 | { 0x00, 80000 }, | ||
| 186 | { 0x01, 41000 }, | ||
| 187 | { 0x02, 21000 }, | ||
| 188 | { 0x03, 11000 }, | ||
| 189 | { 0x04, 6400 }, | ||
| 190 | { 0x05, 3900 }, | ||
| 191 | { 0x06, 2700 }, | ||
| 192 | { 0x07, 2100 }, | ||
| 193 | { } | ||
| 194 | }; | ||
| 195 | |||
| 196 | /* KXCTJ2-1009 */ | ||
| 197 | static const struct kx_odr_start_up_time kxtj21009_odr_start_up_times[] = { | ||
| 198 | { 0x08, 1240000 }, | ||
| 199 | { 0x09, 621000 }, | ||
| 200 | { 0x0A, 309000 }, | ||
| 201 | { 0x0B, 151000 }, | ||
| 202 | { 0x00, 80000 }, | ||
| 203 | { 0x01, 41000 }, | ||
| 204 | { 0x02, 21000 }, | ||
| 205 | { 0x03, 11000 }, | ||
| 206 | { 0x04, 6000 }, | ||
| 207 | { 0x05, 4000 }, | ||
| 208 | { 0x06, 3000 }, | ||
| 209 | { 0x07, 2000 }, | ||
| 210 | { } | ||
| 211 | }; | ||
| 212 | |||
| 213 | /* KXTF9 */ | ||
| 214 | static const struct kx_odr_start_up_time kxtf9_odr_start_up_times[] = { | ||
| 215 | { 0x01, 81000 }, | ||
| 216 | { 0x02, 41000 }, | ||
| 217 | { 0x03, 21000 }, | ||
| 218 | { 0x04, 11000 }, | ||
| 219 | { 0x05, 5100 }, | ||
| 220 | { 0x06, 2700 }, | ||
| 221 | { } | ||
| 222 | }; | ||
| 223 | |||
| 224 | /* KX023-1025 */ | ||
| 225 | static const struct kx_odr_start_up_time kx0231025_odr_start_up_times[] = { | ||
| 226 | /* First 4 are not in datasheet, taken from KXCTJ2-1009 */ | ||
| 227 | { 0x08, 1240000 }, | ||
| 228 | { 0x09, 621000 }, | ||
| 229 | { 0x0A, 309000 }, | ||
| 230 | { 0x0B, 151000 }, | ||
| 231 | { 0x00, 81000 }, | ||
| 232 | { 0x01, 40000 }, | ||
| 233 | { 0x02, 22000 }, | ||
| 234 | { 0x03, 12000 }, | ||
| 235 | { 0x04, 7000 }, | ||
| 236 | { 0x05, 4400 }, | ||
| 237 | { 0x06, 3000 }, | ||
| 238 | { 0x07, 3000 }, | ||
| 239 | { } | ||
| 179 | }; | 240 | }; |
| 180 | 241 | ||
| 181 | enum kx_acpi_type { | 242 | enum kx_acpi_type { |
| @@ -234,6 +295,55 @@ static const struct kx_chipset_regs kx0231025_regs = { · 52 unmodified lines | |||
| 234 | .wake_thres = KX023_REG_ATH, | 295 | .wake_thres = KX023_REG_ATH, |
| 235 | }; | 296 | }; |
| 236 | 297 | ||
| 298 | struct kx_chipset_info { | ||
| 299 | const struct kx_chipset_regs *regs; | ||
| 300 | const struct kx_odr_start_up_time *times; | ||
| 301 | enum kx_acpi_type acpi_type; | ||
| 302 | }; | ||
| 303 | |||
| 304 | static const struct kx_chipset_info kxcjk1013_info = { | ||
| 305 | .regs = &kxcjk1013_regs, | ||
| 306 | .times = pm_ptr(kxcjk1013_odr_start_up_times), | ||
| 307 | }; | ||
| 308 | |||
| 309 | static const struct kx_chipset_info kxcj91008_info = { | ||
| 310 | .regs = &kxcjk1013_regs, | ||
| 311 | .times = pm_ptr(kxcjk1013_odr_start_up_times), | ||
| 312 | }; | ||
| 313 | |||
| 314 | static const struct kx_chipset_info kxcj91008_kiox010a_info = { | ||
| 315 | .regs = &kxcjk1013_regs, | ||
| 316 | .times = pm_ptr(kxcjk1013_odr_start_up_times), | ||
| 317 | .acpi_type = ACPI_KIOX010A, | ||
| 318 | }; | ||
| 319 | |||
| 320 | static const struct kx_chipset_info kxcj91008_kiox020a_info = { | ||
| 321 | .regs = &kxcjk1013_regs, | ||
| 322 | .times = pm_ptr(kxcjk1013_odr_start_up_times), | ||
| 323 | .acpi_type = ACPI_GENERIC, | ||
| 324 | }; | ||
| 325 | |||
| 326 | static const struct kx_chipset_info kxcj91008_smo8500_info = { | ||
| 327 | .regs = &kxcjk1013_regs, | ||
| 328 | .times = pm_ptr(kxcjk1013_odr_start_up_times), | ||
| 329 | .acpi_type = ACPI_SMO8500, | ||
| 330 | }; | ||
| 331 | |||
| 332 | static const struct kx_chipset_info kxtj21009_info = { | ||
| 333 | .regs = &kxcjk1013_regs, | ||
| 334 | .times = pm_ptr(kxtj21009_odr_start_up_times), | ||
| 335 | }; | ||
| 336 | |||
| 337 | static const struct kx_chipset_info kxtf9_info = { | ||
| 338 | .regs = &kxtf9_regs, | ||
| 339 | .times = pm_ptr(kxtf9_odr_start_up_times), | ||
| 340 | }; | ||
| 341 | |||
| 342 | static const struct kx_chipset_info kx0231025_info = { | ||
| 343 | .regs = &kx0231025_regs, | ||
| 344 | .times = pm_ptr(kx0231025_odr_start_up_times), | ||
| 345 | }; | ||
| 346 | |||
| 237 | enum kxcjk1013_axis { | 347 | enum kxcjk1013_axis { |
| 238 | AXIS_X, | 348 | AXIS_X, |
| 239 | AXIS_Y, | 349 | AXIS_Y, |
| @@ -250,7 +360,7 @@ struct kxcjk1013_data { · 10 unmodified lines | |||
| 250 | /* Ensure timestamp naturally aligned */ | 360 | /* Ensure timestamp naturally aligned */ |
| 251 | struct { | 361 | struct { |
| 252 | s16 chans[AXIS_MAX]; | 362 | s16 chans[AXIS_MAX]; |
| 253 | s64 timestamp __aligned(8); | 363 | aligned_s64 timestamp; |
| 254 | } scan; | 364 | } scan; |
| 255 | u8 odr_bits; | 365 | u8 odr_bits; |
| 256 | u8 range; | 366 | u8 range; |
| @@ -261,9 +371,7 @@ struct kxcjk1013_data { · 4 unmodified lines | |||
| 261 | int ev_enable_state; | 371 | int ev_enable_state; |
| 262 | bool motion_trigger_on; | 372 | bool motion_trigger_on; |
| 263 | int64_t timestamp; | 373 | int64_t timestamp; |
| 264 | enum kx_chipset chipset; | 374 | const struct kx_chipset_info *info; |
| 265 | enum kx_acpi_type acpi_type; | ||
| 266 | const struct kx_chipset_regs *regs; | ||
| 267 | }; | 375 | }; |
| 268 | 376 | ||
| 269 | enum kxcjk1013_mode { | 377 | enum kxcjk1013_mode { |
| @@ -314,83 +422,6 @@ static const struct kx_odr_map kxtf9_samp_freq_table[] = { · 44 unmodified lines | |||
| 314 | static const char *const kxtf9_samp_freq_avail = | 422 | static const char *const kxtf9_samp_freq_avail = |
| 315 | "25 50 100 200 400 800"; | 423 | "25 50 100 200 400 800"; |
| 316 | 424 | ||
| 317 | /* Refer to section 4 of the specification */ | ||
| 318 | static __maybe_unused const struct { | ||
| 319 | int odr_bits; | ||
| 320 | int usec; | ||
| 321 | } odr_start_up_times[KX_MAX_CHIPS][12] = { | ||
| 322 | /* KXCJK-1013 */ | ||
| 323 | { | ||
| 324 | {0x08, 100000}, | ||
| 325 | {0x09, 100000}, | ||
| 326 | {0x0A, 100000}, | ||
| 327 | {0x0B, 100000}, | ||
| 328 | {0, 80000}, | ||
| 329 | {0x01, 41000}, | ||
| 330 | {0x02, 21000}, | ||
| 331 | {0x03, 11000}, | ||
| 332 | {0x04, 6400}, | ||
| 333 | {0x05, 3900}, | ||
| 334 | {0x06, 2700}, | ||
| 335 | {0x07, 2100}, | ||
| 336 | }, | ||
| 337 | /* KXCJ9-1008 */ | ||
| 338 | { | ||
| 339 | {0x08, 100000}, | ||
| 340 | {0x09, 100000}, | ||
| 341 | {0x0A, 100000}, | ||
| 342 | {0x0B, 100000}, | ||
| 343 | {0, 80000}, | ||
| 344 | {0x01, 41000}, | ||
| 345 | {0x02, 21000}, | ||
| 346 | {0x03, 11000}, | ||
| 347 | {0x04, 6400}, | ||
| 348 | {0x05, 3900}, | ||
| 349 | {0x06, 2700}, | ||
| 350 | {0x07, 2100}, | ||
| 351 | }, | ||
| 352 | /* KXCTJ2-1009 */ | ||
| 353 | { | ||
| 354 | {0x08, 1240000}, | ||
| 355 | {0x09, 621000}, | ||
| 356 | {0x0A, 309000}, | ||
| 357 | {0x0B, 151000}, | ||
| 358 | {0, 80000}, | ||
| 359 | {0x01, 41000}, | ||
| 360 | {0x02, 21000}, | ||
| 361 | {0x03, 11000}, | ||
| 362 | {0x04, 6000}, | ||
| 363 | {0x05, 4000}, | ||
| 364 | {0x06, 3000}, | ||
| 365 | {0x07, 2000}, | ||
| 366 | }, | ||
| 367 | /* KXTF9 */ | ||
| 368 | { | ||
| 369 | {0x01, 81000}, | ||
| 370 | {0x02, 41000}, | ||
| 371 | {0x03, 21000}, | ||
| 372 | {0x04, 11000}, | ||
| 373 | {0x05, 5100}, | ||
| 374 | {0x06, 2700}, | ||
| 375 | }, | ||
| 376 | /* KX023-1025 */ | ||
| 377 | { | ||
| 378 | /* First 4 are not in datasheet, taken from KXCTJ2-1009 */ | ||
| 379 | {0x08, 1240000}, | ||
| 380 | {0x09, 621000}, | ||
| 381 | {0x0A, 309000}, | ||
| 382 | {0x0B, 151000}, | ||
| 383 | {0, 81000}, | ||
| 384 | {0x01, 40000}, | ||
| 385 | {0x02, 22000}, | ||
| 386 | {0x03, 12000}, | ||
| 387 | {0x04, 7000}, | ||
| 388 | {0x05, 4400}, | ||
| 389 | {0x06, 3000}, | ||
| 390 | {0x07, 3000}, | ||
| 391 | }, | ||
| 392 | }; | ||
| 393 | |||
| 394 | static const struct { | 425 | static const struct { |
| 395 | u16 scale; | 426 | u16 scale; |
| 396 | u8 gsel_0; | 427 | u8 gsel_0; |
| @@ -424,30 +455,15 @@ static int kiox010a_dsm(struct device *dev, int fn_index) · 27 unmodified lines | |||
| 424 | return 0; | 455 | return 0; |
| 425 | } | 456 | } |
| 426 | 457 | ||
| 427 | static const struct acpi_device_id kx_acpi_match[] = { | ||
| 428 | {"KXCJ1013", KXCJK1013}, | ||
| 429 | {"KXCJ1008", KXCJ91008}, | ||
| 430 | {"KXCJ9000", KXCJ91008}, | ||
| 431 | {"KIOX0008", KXCJ91008}, | ||
| 432 | {"KIOX0009", KXTJ21009}, | ||
| 433 | {"KIOX000A", KXCJ91008}, | ||
| 434 | {"KIOX010A", KXCJ91008}, /* KXCJ91008 in the display of a yoga 2-in-1 */ | ||
| 435 | {"KIOX020A", KXCJ91008}, /* KXCJ91008 in the base of a yoga 2-in-1 */ | ||
| 436 | {"KXTJ1009", KXTJ21009}, | ||
| 437 | {"KXJ2109", KXTJ21009}, | ||
| 438 | {"SMO8500", KXCJ91008}, | ||
| 439 | { } | ||
| 440 | }; | ||
| 441 | MODULE_DEVICE_TABLE(acpi, kx_acpi_match); | ||
| 442 | |||
| 443 | #endif | 458 | #endif |
| 444 | 459 | ||
| 445 | static int kxcjk1013_set_mode(struct kxcjk1013_data *data, | 460 | static int kxcjk1013_set_mode(struct kxcjk1013_data *data, |
| 446 | enum kxcjk1013_mode mode) | 461 | enum kxcjk1013_mode mode) |
| 447 | { | 462 | { |
| 463 | const struct kx_chipset_regs *regs = data->info->regs; | ||
| 448 | int ret; | 464 | int ret; |
| 449 | 465 | ||
| 450 | ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); | 466 | ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1); |
| 451 | if (ret < 0) { | 467 | if (ret < 0) { |
| 452 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | 468 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); |
| 453 | return ret; | 469 | return ret; |
| @@ -458,7 +474,7 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data, · 4 unmodified lines | |||
| 458 | else | 474 | else |
| 459 | ret |= KXCJK1013_REG_CTRL1_BIT_PC1; | 475 | ret |= KXCJK1013_REG_CTRL1_BIT_PC1; |
| 460 | 476 | ||
| 461 | ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); | 477 | ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret); |
| 462 | if (ret < 0) { | 478 | if (ret < 0) { |
| 463 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); | 479 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); |
| 464 | return ret; | 480 | return ret; |
| @@ -470,9 +486,10 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data, · 5 unmodified lines | |||
| 470 | static int kxcjk1013_get_mode(struct kxcjk1013_data *data, | 486 | static int kxcjk1013_get_mode(struct kxcjk1013_data *data, |
| 471 | enum kxcjk1013_mode *mode) | 487 | enum kxcjk1013_mode *mode) |
| 472 | { | 488 | { |
| 489 | const struct kx_chipset_regs *regs = data->info->regs; | ||
| 473 | int ret; | 490 | int ret; |
| 474 | 491 | ||
| 475 | ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); | 492 | ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1); |
| 476 | if (ret < 0) { | 493 | if (ret < 0) { |
| 477 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | 494 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); |
| 478 | return ret; | 495 | return ret; |
| @@ -488,9 +505,10 @@ static int kxcjk1013_get_mode(struct kxcjk1013_data *data, · 9 unmodified lines | |||
| 488 | 505 | ||
| 489 | static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index) | 506 | static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index) |
| 490 | { | 507 | { |
| 508 | const struct kx_chipset_regs *regs = data->info->regs; | ||
| 491 | int ret; | 509 | int ret; |
| 492 | 510 | ||
| 493 | ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); | 511 | ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1); |
| 494 | if (ret < 0) { | 512 | if (ret < 0) { |
| 495 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | 513 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); |
| 496 | return ret; | 514 | return ret; |
| @@ -501,7 +519,7 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index) · 4 unmodified lines | |||
| 501 | ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3); | 519 | ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3); |
| 502 | ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4); | 520 | ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4); |
| 503 | 521 | ||
| 504 | ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); | 522 | ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret); |
| 505 | if (ret < 0) { | 523 | if (ret < 0) { |
| 506 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); | 524 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); |
| 507 | return ret; | 525 | return ret; |
| @@ -514,10 +532,11 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index) · 6 unmodified lines | |||
| 514 | 532 | ||
| 515 | static int kxcjk1013_chip_init(struct kxcjk1013_data *data) | 533 | static int kxcjk1013_chip_init(struct kxcjk1013_data *data) |
| 516 | { | 534 | { |
| 535 | const struct kx_chipset_regs *regs = data->info->regs; | ||
| 517 | int ret; | 536 | int ret; |
| 518 | 537 | ||
| 519 | #ifdef CONFIG_ACPI | 538 | #ifdef CONFIG_ACPI |
| 520 | if (data->acpi_type == ACPI_KIOX010A) { | 539 | if (data->info->acpi_type == ACPI_KIOX010A) { |
| 521 | /* Make sure the kbd and touchpad on 2-in-1s using 2 KXCJ91008-s work */ | 540 | /* Make sure the kbd and touchpad on 2-in-1s using 2 KXCJ91008-s work */ |
| 522 | kiox010a_dsm(&data->client->dev, KIOX010A_SET_LAPTOP_MODE); | 541 | kiox010a_dsm(&data->client->dev, KIOX010A_SET_LAPTOP_MODE); |
| 523 | } | 542 | } |
| @@ -535,7 +554,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) · 11 unmodified lines | |||
| 535 | if (ret < 0) | 554 | if (ret < 0) |
| 536 | return ret; | 555 | return ret; |
| 537 | 556 | ||
| 538 | ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); | 557 | ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1); |
| 539 | if (ret < 0) { | 558 | if (ret < 0) { |
| 540 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | 559 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); |
| 541 | return ret; | 560 | return ret; |
| @@ -544,7 +563,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) · 2 unmodified lines | |||
| 544 | /* Set 12 bit mode */ | 563 | /* Set 12 bit mode */ |
| 545 | ret |= KXCJK1013_REG_CTRL1_BIT_RES; | 564 | ret |= KXCJK1013_REG_CTRL1_BIT_RES; |
| 546 | 565 | ||
| 547 | ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); | 566 | ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret); |
| 548 | if (ret < 0) { | 567 | if (ret < 0) { |
| 549 | dev_err(&data->client->dev, "Error reading reg_ctrl\n"); | 568 | dev_err(&data->client->dev, "Error reading reg_ctrl\n"); |
| 550 | return ret; | 569 | return ret; |
| @@ -555,7 +574,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) · 4 unmodified lines | |||
| 555 | if (ret < 0) | 574 | if (ret < 0) |
| 556 | return ret; | 575 | return ret; |
| 557 | 576 | ||
| 558 | ret = i2c_smbus_read_byte_data(data->client, data->regs->data_ctrl); | 577 | ret = i2c_smbus_read_byte_data(data->client, regs->data_ctrl); |
| 559 | if (ret < 0) { | 578 | if (ret < 0) { |
| 560 | dev_err(&data->client->dev, "Error reading reg_data_ctrl\n"); | 579 | dev_err(&data->client->dev, "Error reading reg_data_ctrl\n"); |
| 561 | return ret; | 580 | return ret; |
| @@ -564,7 +583,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) · 2 unmodified lines | |||
| 564 | data->odr_bits = ret; | 583 | data->odr_bits = ret; |
| 565 | 584 | ||
| 566 | /* Set up INT polarity */ | 585 | /* Set up INT polarity */ |
| 567 | ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1); | 586 | ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1); |
| 568 | if (ret < 0) { | 587 | if (ret < 0) { |
| 569 | dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); | 588 | dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); |
| 570 | return ret; | 589 | return ret; |
| @@ -575,14 +594,14 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) · 4 unmodified lines | |||
| 575 | else | 594 | else |
| 576 | ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEA; | 595 | ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEA; |
| 577 | 596 | ||
| 578 | ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret); | 597 | ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret); |
| 579 | if (ret < 0) { | 598 | if (ret < 0) { |
| 580 | dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); | 599 | dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); |
| 581 | return ret; | 600 | return ret; |
| 582 | } | 601 | } |
| 583 | 602 | ||
| 584 | /* On KX023 and KX022, route all used interrupts to INT1 for now */ | 603 | /* On KX023, route all used interrupts to INT1 for now */ |
| 585 | if ((data->chipset == KX0231025 || data->chipset == KX0221020) && data->client->irq > 0) { | 604 | if (data->info == &kx0231025_info && data->client->irq > 0) { |
| 586 | ret = i2c_smbus_write_byte_data(data->client, KX023_REG_INC4, | 605 | ret = i2c_smbus_write_byte_data(data->client, KX023_REG_INC4, |
| 587 | KX023_REG_INC4_DRDY1 | | 606 | KX023_REG_INC4_DRDY1 | |
| 588 | KX023_REG_INC4_WUFI1); | 607 | KX023_REG_INC4_WUFI1); |
| @@ -601,20 +620,17 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) · 12 unmodified lines | |||
| 601 | return 0; | 620 | return 0; |
| 602 | } | 621 | } |
| 603 | 622 | ||
| 604 | #ifdef CONFIG_PM | ||
| 605 | static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data) | 623 | static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data) |
| 606 | { | 624 | { |
| 607 | int i; | 625 | const struct kx_odr_start_up_time *times; |
| 608 | int idx = data->chipset; | ||
| 609 | 626 | ||
| 610 | for (i = 0; i < ARRAY_SIZE(odr_start_up_times[idx]); ++i) { | 627 | for (times = data->info->times; times->usec; times++) { |
| 611 | if (odr_start_up_times[idx][i].odr_bits == data->odr_bits) | 628 | if (times->odr_bits == data->odr_bits) |
| 612 | return odr_start_up_times[idx][i].usec; | 629 | return times->usec; |
| 613 | } | 630 | } |
| 614 | 631 | ||
| 615 | return KXCJK1013_MAX_STARTUP_TIME_US; | 632 | return KXCJK1013_MAX_STARTUP_TIME_US; |
| 616 | } | 633 | } |
| 617 | #endif | ||
| 618 | 634 | ||
| 619 | static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) | 635 | static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) |
| 620 | { | 636 | { |
| @@ -639,18 +655,17 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) · 18 unmodified lines | |||
| 639 | 655 | ||
| 640 | static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data) | 656 | static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data) |
| 641 | { | 657 | { |
| 658 | const struct kx_chipset_regs *regs = data->info->regs; | ||
| 642 | int ret; | 659 | int ret; |
| 643 | 660 | ||
| 644 | ret = i2c_smbus_write_byte_data(data->client, data->regs->wake_timer, | 661 | ret = i2c_smbus_write_byte_data(data->client, regs->wake_timer, data->wake_dur); |
| 645 | data->wake_dur); | ||
| 646 | if (ret < 0) { | 662 | if (ret < 0) { |
| 647 | dev_err(&data->client->dev, | 663 | dev_err(&data->client->dev, |
| 648 | "Error writing reg_wake_timer\n"); | 664 | "Error writing reg_wake_timer\n"); |
| 649 | return ret; | 665 | return ret; |
| 650 | } | 666 | } |
| 651 | 667 | ||
| 652 | ret = i2c_smbus_write_byte_data(data->client, data->regs->wake_thres, | 668 | ret = i2c_smbus_write_byte_data(data->client, regs->wake_thres, data->wake_thres); |
| 653 | data->wake_thres); | ||
| 654 | if (ret < 0) { | 669 | if (ret < 0) { |
| 655 | dev_err(&data->client->dev, "Error writing reg_wake_thres\n"); | 670 | dev_err(&data->client->dev, "Error writing reg_wake_thres\n"); |
| 656 | return ret; | 671 | return ret; |
| @@ -662,6 +677,7 @@ static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data) · 5 unmodified lines | |||
| 662 | static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, | 677 | static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, |
| 663 | bool status) | 678 | bool status) |
| 664 | { | 679 | { |
| 680 | const struct kx_chipset_regs *regs = data->info->regs; | ||
| 665 | int ret; | 681 | int ret; |
| 666 | enum kxcjk1013_mode store_mode; | 682 | enum kxcjk1013_mode store_mode; |
| 667 | 683 | ||
| @@ -678,7 +694,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, · 10 unmodified lines | |||
| 678 | if (ret < 0) | 694 | if (ret < 0) |
| 679 | return ret; | 695 | return ret; |
| 680 | 696 | ||
| 681 | ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1); | 697 | ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1); |
| 682 | if (ret < 0) { | 698 | if (ret < 0) { |
| 683 | dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); | 699 | dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); |
| 684 | return ret; | 700 | return ret; |
| @@ -689,13 +705,13 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, · 4 unmodified lines | |||
| 689 | else | 705 | else |
| 690 | ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; | 706 | ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; |
| 691 | 707 | ||
| 692 | ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret); | 708 | ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret); |
| 693 | if (ret < 0) { | 709 | if (ret < 0) { |
| 694 | dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); | 710 | dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); |
| 695 | return ret; | 711 | return ret; |
| 696 | } | 712 | } |
| 697 | 713 | ||
| 698 | ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); | 714 | ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1); |
| 699 | if (ret < 0) { | 715 | if (ret < 0) { |
| 700 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | 716 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); |
| 701 | return ret; | 717 | return ret; |
| @@ -706,7 +722,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, · 4 unmodified lines | |||
| 706 | else | 722 | else |
| 707 | ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE; | 723 | ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE; |
| 708 | 724 | ||
| 709 | ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); | 725 | ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret); |
| 710 | if (ret < 0) { | 726 | if (ret < 0) { |
| 711 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); | 727 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); |
| 712 | return ret; | 728 | return ret; |
| @@ -724,6 +740,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, · 11 unmodified lines | |||
| 724 | static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, | 740 | static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, |
| 725 | bool status) | 741 | bool status) |
| 726 | { | 742 | { |
| 743 | const struct kx_chipset_regs *regs = data->info->regs; | ||
| 727 | int ret; | 744 | int ret; |
| 728 | enum kxcjk1013_mode store_mode; | 745 | enum kxcjk1013_mode store_mode; |
| 729 | 746 | ||
| @@ -736,7 +753,7 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, · 6 unmodified lines | |||
| 736 | if (ret < 0) | 753 | if (ret < 0) |
| 737 | return ret; | 754 | return ret; |
| 738 | 755 | ||
| 739 | ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1); | 756 | ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1); |
| 740 | if (ret < 0) { | 757 | if (ret < 0) { |
| 741 | dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); | 758 | dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); |
| 742 | return ret; | 759 | return ret; |
| @@ -747,13 +764,13 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, · 4 unmodified lines | |||
| 747 | else | 764 | else |
| 748 | ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; | 765 | ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; |
| 749 | 766 | ||
| 750 | ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret); | 767 | ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret); |
| 751 | if (ret < 0) { | 768 | if (ret < 0) { |
| 752 | dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); | 769 | dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); |
| 753 | return ret; | 770 | return ret; |
| 754 | } | 771 | } |
| 755 | 772 | ||
| 756 | ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); | 773 | ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1); |
| 757 | if (ret < 0) { | 774 | if (ret < 0) { |
| 758 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | 775 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); |
| 759 | return ret; | 776 | return ret; |
| @@ -764,7 +781,7 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, · 4 unmodified lines | |||
| 764 | else | 781 | else |
| 765 | ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY; | 782 | ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY; |
| 766 | 783 | ||
| 767 | ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); | 784 | ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret); |
| 768 | if (ret < 0) { | 785 | if (ret < 0) { |
| 769 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); | 786 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); |
| 770 | return ret; | 787 | return ret; |
| @@ -811,6 +828,7 @@ static int kxcjk1013_convert_odr_value(const struct kx_odr_map *map, · 40 unmodified lines | |||
| 811 | 828 | ||
| 812 | static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2) | 829 | static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2) |
| 813 | { | 830 | { |
| 831 | const struct kx_chipset_regs *regs = data->info->regs; | ||
| 814 | int ret; | 832 | int ret; |
| 815 | enum kxcjk1013_mode store_mode; | 833 | enum kxcjk1013_mode store_mode; |
| 816 | const struct kx_odr_map *odr_setting; | 834 | const struct kx_odr_map *odr_setting; |
| @@ -819,7 +837,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2) · 2 unmodified lines | |||
| 819 | if (ret < 0) | 837 | if (ret < 0) |
| 820 | return ret; | 838 | return ret; |
| 821 | 839 | ||
| 822 | if (data->chipset == KXTF9) | 840 | if (data->info == &kxtf9_info) |
| 823 | odr_setting = kxcjk1013_find_odr_value(kxtf9_samp_freq_table, | 841 | odr_setting = kxcjk1013_find_odr_value(kxtf9_samp_freq_table, |
| 824 | ARRAY_SIZE(kxtf9_samp_freq_table), | 842 | ARRAY_SIZE(kxtf9_samp_freq_table), |
| 825 | val, val2); | 843 | val, val2); |
| @@ -836,7 +854,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2) · 10 unmodified lines | |||
| 836 | if (ret < 0) | 854 | if (ret < 0) |
| 837 | return ret; | 855 | return ret; |
| 838 | 856 | ||
| 839 | ret = i2c_smbus_write_byte_data(data->client, data->regs->data_ctrl, | 857 | ret = i2c_smbus_write_byte_data(data->client, regs->data_ctrl, |
| 840 | odr_setting->odr_bits); | 858 | odr_setting->odr_bits); |
| 841 | if (ret < 0) { | 859 | if (ret < 0) { |
| 842 | dev_err(&data->client->dev, "Error writing data_ctrl\n"); | 860 | dev_err(&data->client->dev, "Error writing data_ctrl\n"); |
| @@ -845,7 +863,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2) · 2 unmodified lines | |||
| 845 | 863 | ||
| 846 | data->odr_bits = odr_setting->odr_bits; | 864 | data->odr_bits = odr_setting->odr_bits; |
| 847 | 865 | ||
| 848 | ret = i2c_smbus_write_byte_data(data->client, data->regs->wuf_ctrl, | 866 | ret = i2c_smbus_write_byte_data(data->client, regs->wuf_ctrl, |
| 849 | odr_setting->wuf_bits); | 867 | odr_setting->wuf_bits); |
| 850 | if (ret < 0) { | 868 | if (ret < 0) { |
| 851 | dev_err(&data->client->dev, "Error writing reg_ctrl2\n"); | 869 | dev_err(&data->client->dev, "Error writing reg_ctrl2\n"); |
| @@ -863,7 +881,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2) · 11 unmodified lines | |||
| 863 | 881 | ||
| 864 | static int kxcjk1013_get_odr(struct kxcjk1013_data *data, int *val, int *val2) | 882 | static int kxcjk1013_get_odr(struct kxcjk1013_data *data, int *val, int *val2) |
| 865 | { | 883 | { |
| 866 | if (data->chipset == KXTF9) | 884 | if (data->info == &kxtf9_info) |
| 867 | return kxcjk1013_convert_odr_value(kxtf9_samp_freq_table, | 885 | return kxcjk1013_convert_odr_value(kxtf9_samp_freq_table, |
| 868 | ARRAY_SIZE(kxtf9_samp_freq_table), | 886 | ARRAY_SIZE(kxtf9_samp_freq_table), |
| 869 | data->odr_bits, val, val2); | 887 | data->odr_bits, val, val2); |
| @@ -1063,7 +1081,7 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev, · 193 unmodified lines | |||
| 1063 | const struct iio_chan_spec *chan, | 1081 | const struct iio_chan_spec *chan, |
| 1064 | enum iio_event_type type, | 1082 | enum iio_event_type type, |
| 1065 | enum iio_event_direction dir, | 1083 | enum iio_event_direction dir, |
| 1066 | int state) | 1084 | bool state) |
| 1067 | { | 1085 | { |
| 1068 | struct kxcjk1013_data *data = iio_priv(indio_dev); | 1086 | struct kxcjk1013_data *data = iio_priv(indio_dev); |
| 1069 | int ret; | 1087 | int ret; |
| @@ -1130,7 +1148,7 @@ static ssize_t kxcjk1013_get_samp_freq_avail(struct device *dev, · 60 unmodified lines | |||
| 1130 | struct kxcjk1013_data *data = iio_priv(indio_dev); | 1148 | struct kxcjk1013_data *data = iio_priv(indio_dev); |
| 1131 | const char *str; | 1149 | const char *str; |
| 1132 | 1150 | ||
| 1133 | if (data->chipset == KXTF9) | 1151 | if (data->info == &kxtf9_info) |
| 1134 | str = kxtf9_samp_freq_avail; | 1152 | str = kxtf9_samp_freq_avail; |
| 1135 | else | 1153 | else |
| 1136 | str = kxcjk1013_samp_freq_avail; | 1154 | str = kxcjk1013_samp_freq_avail; |
| @@ -1207,7 +1225,7 @@ static const struct iio_buffer_setup_ops kxcjk1013_buffer_setup_ops = { · 70 unmodified lines | |||
| 1207 | .postdisable = kxcjk1013_buffer_postdisable, | 1225 | .postdisable = kxcjk1013_buffer_postdisable, |
| 1208 | }; | 1226 | }; |
| 1209 | 1227 | ||
| 1210 | static const struct iio_info kxcjk1013_info = { | 1228 | static const struct iio_info kxcjk1013_iio_info = { |
| 1211 | .attrs = &kxcjk1013_attrs_group, | 1229 | .attrs = &kxcjk1013_attrs_group, |
| 1212 | .read_raw = kxcjk1013_read_raw, | 1230 | .read_raw = kxcjk1013_read_raw, |
| 1213 | .write_raw = kxcjk1013_write_raw, | 1231 | .write_raw = kxcjk1013_write_raw, |
| @@ -1247,9 +1265,10 @@ static void kxcjk1013_trig_reen(struct iio_trigger *trig) · 33 unmodified lines | |||
| 1247 | { | 1265 | { |
| 1248 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | 1266 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); |
| 1249 | struct kxcjk1013_data *data = iio_priv(indio_dev); | 1267 | struct kxcjk1013_data *data = iio_priv(indio_dev); |
| 1268 | const struct kx_chipset_regs *regs = data->info->regs; | ||
| 1250 | int ret; | 1269 | int ret; |
| 1251 | 1270 | ||
| 1252 | ret = i2c_smbus_read_byte_data(data->client, data->regs->int_rel); | 1271 | ret = i2c_smbus_read_byte_data(data->client, regs->int_rel); |
| 1253 | if (ret < 0) | 1272 | if (ret < 0) |
| 1254 | dev_err(&data->client->dev, "Error reading reg_int_rel\n"); | 1273 | dev_err(&data->client->dev, "Error reading reg_int_rel\n"); |
| 1255 | } | 1274 | } |
| @@ -1301,8 +1320,9 @@ static const struct iio_trigger_ops kxcjk1013_trigger_ops = { · 45 unmodified lines | |||
| 1301 | static void kxcjk1013_report_motion_event(struct iio_dev *indio_dev) | 1320 | static void kxcjk1013_report_motion_event(struct iio_dev *indio_dev) |
| 1302 | { | 1321 | { |
| 1303 | struct kxcjk1013_data *data = iio_priv(indio_dev); | 1322 | struct kxcjk1013_data *data = iio_priv(indio_dev); |
| 1323 | const struct kx_chipset_regs *regs = data->info->regs; | ||
| 1304 | 1324 | ||
| 1305 | int ret = i2c_smbus_read_byte_data(data->client, data->regs->int_src2); | 1325 | int ret = i2c_smbus_read_byte_data(data->client, regs->int_src2); |
| 1306 | if (ret < 0) { | 1326 | if (ret < 0) { |
| 1307 | dev_err(&data->client->dev, "Error reading reg_int_src2\n"); | 1327 | dev_err(&data->client->dev, "Error reading reg_int_src2\n"); |
| 1308 | return; | 1328 | return; |
| @@ -1367,16 +1387,17 @@ static irqreturn_t kxcjk1013_event_handler(int irq, void *private) · 58 unmodified lines | |||
| 1367 | { | 1387 | { |
| 1368 | struct iio_dev *indio_dev = private; | 1388 | struct iio_dev *indio_dev = private; |
| 1369 | struct kxcjk1013_data *data = iio_priv(indio_dev); | 1389 | struct kxcjk1013_data *data = iio_priv(indio_dev); |
| 1390 | const struct kx_chipset_regs *regs = data->info->regs; | ||
| 1370 | int ret; | 1391 | int ret; |
| 1371 | 1392 | ||
| 1372 | ret = i2c_smbus_read_byte_data(data->client, data->regs->int_src1); | 1393 | ret = i2c_smbus_read_byte_data(data->client, regs->int_src1); |
| 1373 | if (ret < 0) { | 1394 | if (ret < 0) { |
| 1374 | dev_err(&data->client->dev, "Error reading reg_int_src1\n"); | 1395 | dev_err(&data->client->dev, "Error reading reg_int_src1\n"); |
| 1375 | goto ack_intr; | 1396 | goto ack_intr; |
| 1376 | } | 1397 | } |
| 1377 | 1398 | ||
| 1378 | if (ret & KXCJK1013_REG_INT_SRC1_BIT_WUFS) { | 1399 | if (ret & KXCJK1013_REG_INT_SRC1_BIT_WUFS) { |
| 1379 | if (data->chipset == KXTF9) | 1400 | if (data->info == &kxtf9_info) |
| 1380 | iio_push_event(indio_dev, | 1401 | iio_push_event(indio_dev, |
| 1381 | IIO_MOD_EVENT_CODE(IIO_ACCEL, | 1402 | IIO_MOD_EVENT_CODE(IIO_ACCEL, |
| 1382 | 0, | 1403 | 0, |
| @@ -1392,7 +1413,7 @@ ack_intr: · 9 unmodified lines | |||
| 1392 | if (data->dready_trigger_on) | 1413 | if (data->dready_trigger_on) |
| 1393 | return IRQ_HANDLED; | 1414 | return IRQ_HANDLED; |
| 1394 | 1415 | ||
| 1395 | ret = i2c_smbus_read_byte_data(data->client, data->regs->int_rel); | 1416 | ret = i2c_smbus_read_byte_data(data->client, regs->int_rel); |
| 1396 | if (ret < 0) | 1417 | if (ret < 0) |
| 1397 | dev_err(&data->client->dev, "Error reading reg_int_rel\n"); | 1418 | dev_err(&data->client->dev, "Error reading reg_int_rel\n"); |
| 1398 | 1419 | ||
| @@ -1417,31 +1438,6 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private) · 18 unmodified lines | |||
| 1417 | return IRQ_HANDLED; | 1438 | return IRQ_HANDLED; |
| 1418 | } | 1439 | } |
| 1419 | 1440 | ||
| 1420 | static const char *kxcjk1013_match_acpi_device(struct device *dev, | ||
| 1421 | enum kx_chipset *chipset, | ||
| 1422 | enum kx_acpi_type *acpi_type, | ||
| 1423 | const char **label) | ||
| 1424 | { | ||
| 1425 | const struct acpi_device_id *id; | ||
| 1426 | |||
| 1427 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
| 1428 | if (!id) | ||
| 1429 | return NULL; | ||
| 1430 | |||
| 1431 | if (strcmp(id->id, "SMO8500") == 0) { | ||
| 1432 | *acpi_type = ACPI_SMO8500; | ||
| 1433 | } else if (strcmp(id->id, "KIOX010A") == 0) { | ||
| 1434 | *acpi_type = ACPI_KIOX010A; | ||
| 1435 | *label = "accel-display"; | ||
| 1436 | } else if (strcmp(id->id, "KIOX020A") == 0) { | ||
| 1437 | *label = "accel-base"; | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | *chipset = (enum kx_chipset)id->driver_data; | ||
| 1441 | |||
| 1442 | return dev_name(dev); | ||
| 1443 | } | ||
| 1444 | |||
| 1445 | static int kxcjk1013_probe(struct i2c_client *client) | 1441 | static int kxcjk1013_probe(struct i2c_client *client) |
| 1446 | { | 1442 | { |
| 1447 | const struct i2c_device_id *id = i2c_client_get_device_id(client); | 1443 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
| @@ -1449,6 +1445,7 @@ static int kxcjk1013_probe(struct i2c_client *client) · 1 unmodified line | |||
| 1449 | struct kxcjk1013_data *data; | 1445 | struct kxcjk1013_data *data; |
| 1450 | struct iio_dev *indio_dev; | 1446 | struct iio_dev *indio_dev; |
| 1451 | struct kxcjk_1013_platform_data *pdata; | 1447 | struct kxcjk_1013_platform_data *pdata; |
| 1448 | const void *ddata = NULL; | ||
| 1452 | const char *name; | 1449 | const char *name; |
| 1453 | int ret; | 1450 | int ret; |
| 1454 | 1451 | ||
| @@ -1489,32 +1486,18 @@ static int kxcjk1013_probe(struct i2c_client *client) · 34 unmodified lines | |||
| 1489 | msleep(20); | 1486 | msleep(20); |
| 1490 | 1487 | ||
| 1491 | if (id) { | 1488 | if (id) { |
| 1492 | data->chipset = (enum kx_chipset)(id->driver_data); | ||
| 1493 | name = id->name; | 1489 | name = id->name; |
| 1494 | } else if (ACPI_HANDLE(&client->dev)) { | 1490 | data->info = (const struct kx_chipset_info *)(id->driver_data); |
| 1495 | name = kxcjk1013_match_acpi_device(&client->dev, | 1491 | } else { |
| 1496 | &data->chipset, | 1492 | name = iio_get_acpi_device_name_and_data(&client->dev, &ddata); |
| 1497 | &data->acpi_type, | 1493 | data->info = ddata; |
| 1498 | &indio_dev->label); | 1494 | if (data->info == &kxcj91008_kiox010a_info) |
| 1499 | } else | 1495 | indio_dev->label = "accel-display"; |
| 1500 | return -ENODEV; | 1496 | else if (data->info == &kxcj91008_kiox020a_info) |
| 1501 | 1497 | indio_dev->label = "accel-base"; | |
| 1502 | switch (data->chipset) { | ||
| 1503 | case KXCJK1013: | ||
| 1504 | case KXCJ91008: | ||
| 1505 | case KXTJ21009: | ||
| 1506 | data->regs = &kxcjk1013_regs; | ||
| 1507 | break; | ||
| 1508 | case KXTF9: | ||
| 1509 | data->regs = &kxtf9_regs; | ||
| 1510 | break; | ||
| 1511 | case KX0221020: | ||
| 1512 | case KX0231025: | ||
| 1513 | data->regs = &kx0231025_regs; | ||
| 1514 | break; | ||
| 1515 | default: | ||
| 1516 | return -EINVAL; | ||
| 1517 | } | 1498 | } |
| 1499 | if (!name) | ||
| 1500 | return -ENODEV; | ||
| 1518 | 1501 | ||
| 1519 | ret = kxcjk1013_chip_init(data); | 1502 | ret = kxcjk1013_chip_init(data); |
| 1520 | if (ret < 0) | 1503 | if (ret < 0) |
| @@ -1527,9 +1510,9 @@ static int kxcjk1013_probe(struct i2c_client *client) · 6 unmodified lines | |||
| 1527 | indio_dev->available_scan_masks = kxcjk1013_scan_masks; | 1510 | indio_dev->available_scan_masks = kxcjk1013_scan_masks; |
| 1528 | indio_dev->name = name; | 1511 | indio_dev->name = name; |
| 1529 | indio_dev->modes = INDIO_DIRECT_MODE; | 1512 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 1530 | indio_dev->info = &kxcjk1013_info; | 1513 | indio_dev->info = &kxcjk1013_iio_info; |
| 1531 | 1514 | ||
| 1532 | if (client->irq > 0 && data->acpi_type != ACPI_SMO8500) { | 1515 | if (client->irq > 0 && data->info->acpi_type != ACPI_SMO8500) { |
| 1533 | ret = devm_request_threaded_irq(&client->dev, client->irq, | 1516 | ret = devm_request_threaded_irq(&client->dev, client->irq, |
| 1534 | kxcjk1013_data_rdy_trig_poll, | 1517 | kxcjk1013_data_rdy_trig_poll, |
| 1535 | kxcjk1013_event_handler, | 1518 | kxcjk1013_event_handler, |
| @@ -1637,7 +1620,6 @@ static void kxcjk1013_remove(struct i2c_client *client) · 101 unmodified lines | |||
| 1637 | mutex_unlock(&data->mutex); | 1620 | mutex_unlock(&data->mutex); |
| 1638 | } | 1621 | } |
| 1639 | 1622 | ||
| 1640 | #ifdef CONFIG_PM_SLEEP | ||
| 1641 | static int kxcjk1013_suspend(struct device *dev) | 1623 | static int kxcjk1013_suspend(struct device *dev) |
| 1642 | { | 1624 | { |
| 1643 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | 1625 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); |
| @@ -1665,9 +1647,7 @@ static int kxcjk1013_resume(struct device *dev) · 21 unmodified lines | |||
| 1665 | 1647 | ||
| 1666 | return ret; | 1648 | return ret; |
| 1667 | } | 1649 | } |
| 1668 | #endif | ||
| 1669 | 1650 | ||
| 1670 | #ifdef CONFIG_PM | ||
| 1671 | static int kxcjk1013_runtime_suspend(struct device *dev) | 1651 | static int kxcjk1013_runtime_suspend(struct device *dev) |
| 1672 | { | 1652 | { |
| 1673 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | 1653 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); |
| @@ -1701,44 +1681,56 @@ static int kxcjk1013_runtime_resume(struct device *dev) · 27 unmodified lines | |||
| 1701 | 1681 | ||
| 1702 | return 0; | 1682 | return 0; |
| 1703 | } | 1683 | } |
| 1704 | #endif | ||
| 1705 | 1684 | ||
| 1706 | static const struct dev_pm_ops kxcjk1013_pm_ops = { | 1685 | static const struct dev_pm_ops kxcjk1013_pm_ops = { |
| 1707 | SET_SYSTEM_SLEEP_PM_OPS(kxcjk1013_suspend, kxcjk1013_resume) | 1686 | SYSTEM_SLEEP_PM_OPS(kxcjk1013_suspend, kxcjk1013_resume) |
| 1708 | SET_RUNTIME_PM_OPS(kxcjk1013_runtime_suspend, | 1687 | RUNTIME_PM_OPS(kxcjk1013_runtime_suspend, kxcjk1013_runtime_resume, NULL) |
| 1709 | kxcjk1013_runtime_resume, NULL) | ||
| 1710 | }; | 1688 | }; |
| 1711 | 1689 | ||
| 1712 | static const struct i2c_device_id kxcjk1013_id[] = { | 1690 | static const struct i2c_device_id kxcjk1013_id[] = { |
| 1713 | {"kxcjk1013", KXCJK1013}, | 1691 | { "kxcjk1013", (kernel_ulong_t)&kxcjk1013_info }, |
| 1714 | {"kxcj91008", KXCJ91008}, | 1692 | { "kxcj91008", (kernel_ulong_t)&kxcj91008_info }, |
| 1715 | {"kxtj21009", KXTJ21009}, | 1693 | { "kxtj21009", (kernel_ulong_t)&kxtj21009_info }, |
| 1716 | {"kxtf9", KXTF9}, | 1694 | { "kxtf9", (kernel_ulong_t)&kxtf9_info }, |
| 1717 | {"kx022-1020", KX0221020}, | 1695 | { "kx023-1025", (kernel_ulong_t)&kx0231025_info }, |
| 1718 | {"kx023-1025", KX0231025}, | 1696 | { } |
| 1719 | {"SMO8500", KXCJ91008}, | ||
| 1720 | {} | ||
| 1721 | }; | 1697 | }; |
| 1722 | |||
| 1723 | MODULE_DEVICE_TABLE(i2c, kxcjk1013_id); | 1698 | MODULE_DEVICE_TABLE(i2c, kxcjk1013_id); |
| 1724 | 1699 | ||
| 1725 | static const struct of_device_id kxcjk1013_of_match[] = { | 1700 | static const struct of_device_id kxcjk1013_of_match[] = { |
| 1726 | { .compatible = "kionix,kxcjk1013", }, | 1701 | { .compatible = "kionix,kxcjk1013", &kxcjk1013_info }, |
| 1727 | { .compatible = "kionix,kxcj91008", }, | 1702 | { .compatible = "kionix,kxcj91008", &kxcj91008_info }, |
| 1728 | { .compatible = "kionix,kxtj21009", }, | 1703 | { .compatible = "kionix,kxtj21009", &kxtj21009_info }, |
| 1729 | { .compatible = "kionix,kxtf9", }, | 1704 | { .compatible = "kionix,kxtf9", &kxtf9_info }, |
| 1730 | { .compatible = "kionix,kx022-1020", }, | 1705 | { .compatible = "kionix,kx023-1025", &kx0231025_info }, |
| 1731 | { .compatible = "kionix,kx023-1025", }, | ||
| 1732 | { } | 1706 | { } |
| 1733 | }; | 1707 | }; |
| 1734 | MODULE_DEVICE_TABLE(of, kxcjk1013_of_match); | 1708 | MODULE_DEVICE_TABLE(of, kxcjk1013_of_match); |
| 1735 | 1709 | ||
| 1710 | static const struct acpi_device_id kx_acpi_match[] = { | ||
| 1711 | { "KIOX0008", (kernel_ulong_t)&kxcj91008_info }, | ||
| 1712 | { "KIOX0009", (kernel_ulong_t)&kxtj21009_info }, | ||
| 1713 | { "KIOX000A", (kernel_ulong_t)&kxcj91008_info }, | ||
| 1714 | /* KXCJ91008 in the display of a yoga 2-in-1 */ | ||
| 1715 | { "KIOX010A", (kernel_ulong_t)&kxcj91008_kiox010a_info }, | ||
| 1716 | /* KXCJ91008 in the base of a yoga 2-in-1 */ | ||
| 1717 | { "KIOX020A", (kernel_ulong_t)&kxcj91008_kiox020a_info }, | ||
| 1718 | { "KXCJ1008", (kernel_ulong_t)&kxcj91008_info }, | ||
| 1719 | { "KXCJ1013", (kernel_ulong_t)&kxcjk1013_info }, | ||
| 1720 | { "KXCJ9000", (kernel_ulong_t)&kxcj91008_info }, | ||
| 1721 | { "KXJ2109", (kernel_ulong_t)&kxtj21009_info }, | ||
| 1722 | { "KXTJ1009", (kernel_ulong_t)&kxtj21009_info }, | ||
| 1723 | { "SMO8500", (kernel_ulong_t)&kxcj91008_smo8500_info }, | ||
| 1724 | { } | ||
| 1725 | }; | ||
| 1726 | MODULE_DEVICE_TABLE(acpi, kx_acpi_match); | ||
| 1727 | |||
| 1736 | static struct i2c_driver kxcjk1013_driver = { | 1728 | static struct i2c_driver kxcjk1013_driver = { |
| 1737 | .driver = { | 1729 | .driver = { |
| 1738 | .name = KXCJK1013_DRV_NAME, | 1730 | .name = KXCJK1013_DRV_NAME, |
| 1739 | .acpi_match_table = ACPI_PTR(kx_acpi_match), | 1731 | .acpi_match_table = kx_acpi_match, |
| 1740 | .of_match_table = kxcjk1013_of_match, | 1732 | .of_match_table = kxcjk1013_of_match, |
| 1741 | .pm = &kxcjk1013_pm_ops, | 1733 | .pm = pm_ptr(&kxcjk1013_pm_ops), |
| 1742 | }, | 1734 | }, |
| 1743 | .probe = kxcjk1013_probe, | 1735 | .probe = kxcjk1013_probe, |
| 1744 | .remove = kxcjk1013_remove, | 1736 | .remove = kxcjk1013_remove, |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | |||
| 15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 16 | #include <linux/sysfs.h> | 16 | #include <linux/sysfs.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/types.h> | ||
| 18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 19 | #include <linux/regmap.h> | 20 | #include <linux/regmap.h> |
| 20 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
| @@ -215,7 +216,7 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p) · 194 unmodified lines | |||
| 215 | */ | 216 | */ |
| 216 | struct { | 217 | struct { |
| 217 | __be16 chan[4]; | 218 | __be16 chan[4]; |
| 218 | s64 ts __aligned(8); | 219 | aligned_s64 ts; |
| 219 | } hw_values; | 220 | } hw_values; |
| 220 | int ret; | 221 | int ret; |
| 221 | 222 | ||
| @@ -19,6 +19,7 @@ · 18 unmodified lines | |||
| 19 | #include <linux/iio/triggered_buffer.h> | 19 | #include <linux/iio/triggered_buffer.h> |
| 20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 21 | #include <linux/regmap.h> | 21 | #include <linux/regmap.h> |
| 22 | #include <linux/types.h> | ||
| 22 | 23 | ||
| 23 | #include "mma7455.h" | 24 | #include "mma7455.h" |
| 24 | 25 | ||
| @@ -58,7 +59,7 @@ struct mma7455_data { · 33 unmodified lines | |||
| 58 | */ | 59 | */ |
| 59 | struct { | 60 | struct { |
| 60 | __le16 channels[3]; | 61 | __le16 channels[3]; |
| 61 | s64 ts __aligned(8); | 62 | aligned_s64 ts; |
| 62 | } scan; | 63 | } scan; |
| 63 | }; | 64 | }; |
| 64 | 65 | ||
| @@ -32,6 +32,7 @@ · 31 unmodified lines | |||
| 32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
| 33 | #include <linux/pm_runtime.h> | 33 | #include <linux/pm_runtime.h> |
| 34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
| 35 | #include <linux/types.h> | ||
| 35 | 36 | ||
| 36 | #define MMA8452_STATUS 0x00 | 37 | #define MMA8452_STATUS 0x00 |
| 37 | #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) | 38 | #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) |
| @@ -115,7 +116,7 @@ struct mma8452_data { · 77 unmodified lines | |||
| 115 | /* Ensure correct alignment of time stamp when present */ | 116 | /* Ensure correct alignment of time stamp when present */ |
| 116 | struct { | 117 | struct { |
| 117 | __be16 channels[3]; | 118 | __be16 channels[3]; |
| 118 | s64 ts __aligned(8); | 119 | aligned_s64 ts; |
| 119 | } buffer; | 120 | } buffer; |
| 120 | }; | 121 | }; |
| 121 | 122 | ||
| @@ -973,7 +974,7 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev, · 851 unmodified lines | |||
| 973 | const struct iio_chan_spec *chan, | 974 | const struct iio_chan_spec *chan, |
| 974 | enum iio_event_type type, | 975 | enum iio_event_type type, |
| 975 | enum iio_event_direction dir, | 976 | enum iio_event_direction dir, |
| 976 | int state) | 977 | bool state) |
| 977 | { | 978 | { |
| 978 | struct mma8452_data *data = iio_priv(indio_dev); | 979 | struct mma8452_data *data = iio_priv(indio_dev); |
| 979 | int val, ret; | 980 | int val, ret; |
| @@ -4,11 +4,11 @@ · 3 unmodified lines | |||
| 4 | * Copyright (c) 2014, Intel Corporation. | 4 | * Copyright (c) 2014, Intel Corporation. |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/i2c.h> | 7 | #include <linux/i2c.h> |
| 9 | #include <linux/interrupt.h> | 8 | #include <linux/interrupt.h> |
| 9 | #include <linux/mod_devicetable.h> | ||
| 10 | #include <linux/module.h> | ||
| 10 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
| 11 | #include <linux/acpi.h> | ||
| 12 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
| 13 | #include <linux/gpio/consumer.h> | 13 | #include <linux/gpio/consumer.h> |
| 14 | #include <linux/iio/iio.h> | 14 | #include <linux/iio/iio.h> |
| @@ -45,7 +45,7 @@ enum mma9551_tilt_axis { · 30 unmodified lines | |||
| 45 | struct mma9551_data { | 45 | struct mma9551_data { |
| 46 | struct i2c_client *client; | 46 | struct i2c_client *client; |
| 47 | struct mutex mutex; | 47 | struct mutex mutex; |
| 48 | int event_enabled[3]; | 48 | bool event_enabled[3]; |
| 49 | int irqs[MMA9551_GPIO_COUNT]; | 49 | int irqs[MMA9551_GPIO_COUNT]; |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| @@ -162,7 +162,7 @@ static int mma9551_read_event_config(struct iio_dev *indio_dev, · 110 unmodified lines | |||
| 162 | 162 | ||
| 163 | static int mma9551_config_incli_event(struct iio_dev *indio_dev, | 163 | static int mma9551_config_incli_event(struct iio_dev *indio_dev, |
| 164 | enum iio_modifier axis, | 164 | enum iio_modifier axis, |
| 165 | int state) | 165 | bool state) |
| 166 | { | 166 | { |
| 167 | struct mma9551_data *data = iio_priv(indio_dev); | 167 | struct mma9551_data *data = iio_priv(indio_dev); |
| 168 | enum mma9551_tilt_axis mma_axis; | 168 | enum mma9551_tilt_axis mma_axis; |
| @@ -174,7 +174,7 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev, · 5 unmodified lines | |||
| 174 | if (data->event_enabled[mma_axis] == state) | 174 | if (data->event_enabled[mma_axis] == state) |
| 175 | return 0; | 175 | return 0; |
| 176 | 176 | ||
| 177 | if (state == 0) { | 177 | if (!state) { |
| 178 | ret = mma9551_gpio_config(data->client, | 178 | ret = mma9551_gpio_config(data->client, |
| 179 | (enum mma9551_gpio_pin)mma_axis, | 179 | (enum mma9551_gpio_pin)mma_axis, |
| 180 | MMA9551_APPID_NONE, 0, 0); | 180 | MMA9551_APPID_NONE, 0, 0); |
| @@ -225,7 +225,7 @@ static int mma9551_write_event_config(struct iio_dev *indio_dev, · 44 unmodified lines | |||
| 225 | const struct iio_chan_spec *chan, | 225 | const struct iio_chan_spec *chan, |
| 226 | enum iio_event_type type, | 226 | enum iio_event_type type, |
| 227 | enum iio_event_direction dir, | 227 | enum iio_event_direction dir, |
| 228 | int state) | 228 | bool state) |
| 229 | { | 229 | { |
| 230 | struct mma9551_data *data = iio_priv(indio_dev); | 230 | struct mma9551_data *data = iio_priv(indio_dev); |
| 231 | int ret; | 231 | int ret; |
| @@ -435,17 +435,6 @@ static int mma9551_gpio_probe(struct iio_dev *indio_dev) · 203 unmodified lines | |||
| 435 | return 0; | 435 | return 0; |
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | static const char *mma9551_match_acpi_device(struct device *dev) | ||
| 439 | { | ||
| 440 | const struct acpi_device_id *id; | ||
| 441 | |||
| 442 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
| 443 | if (!id) | ||
| 444 | return NULL; | ||
| 445 | |||
| 446 | return dev_name(dev); | ||
| 447 | } | ||
| 448 | |||
| 449 | static int mma9551_probe(struct i2c_client *client) | 438 | static int mma9551_probe(struct i2c_client *client) |
| 450 | { | 439 | { |
| 451 | const struct i2c_device_id *id = i2c_client_get_device_id(client); | 440 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
| @@ -464,8 +453,8 @@ static int mma9551_probe(struct i2c_client *client) · 12 unmodified lines | |||
| 464 | 453 | ||
| 465 | if (id) | 454 | if (id) |
| 466 | name = id->name; | 455 | name = id->name; |
| 467 | else if (ACPI_HANDLE(&client->dev)) | 456 | else |
| 468 | name = mma9551_match_acpi_device(&client->dev); | 457 | name = iio_get_acpi_device_name(&client->dev); |
| 469 | 458 | ||
| 470 | ret = mma9551_init(data); | 459 | ret = mma9551_init(data); |
| 471 | if (ret < 0) | 460 | if (ret < 0) |
| @@ -4,11 +4,11 @@ · 3 unmodified lines | |||
| 4 | * Copyright (c) 2014, Intel Corporation. | 4 | * Copyright (c) 2014, Intel Corporation. |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/i2c.h> | 7 | #include <linux/i2c.h> |
| 9 | #include <linux/interrupt.h> | 8 | #include <linux/interrupt.h> |
| 9 | #include <linux/mod_devicetable.h> | ||
| 10 | #include <linux/module.h> | ||
| 10 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
| 11 | #include <linux/acpi.h> | ||
| 12 | #include <linux/iio/iio.h> | 12 | #include <linux/iio/iio.h> |
| 13 | #include <linux/iio/sysfs.h> | 13 | #include <linux/iio/sysfs.h> |
| 14 | #include <linux/iio/events.h> | 14 | #include <linux/iio/events.h> |
| @@ -725,7 +725,8 @@ static int mma9553_read_event_config(struct iio_dev *indio_dev, · 710 unmodified lines | |||
| 725 | static int mma9553_write_event_config(struct iio_dev *indio_dev, | 725 | static int mma9553_write_event_config(struct iio_dev *indio_dev, |
| 726 | const struct iio_chan_spec *chan, | 726 | const struct iio_chan_spec *chan, |
| 727 | enum iio_event_type type, | 727 | enum iio_event_type type, |
| 728 | enum iio_event_direction dir, int state) | 728 | enum iio_event_direction dir, |
| 729 | bool state) | ||
| 729 | { | 730 | { |
| 730 | struct mma9553_data *data = iio_priv(indio_dev); | 731 | struct mma9553_data *data = iio_priv(indio_dev); |
| 731 | struct mma9553_event *event; | 732 | struct mma9553_event *event; |
| @@ -1030,9 +1031,9 @@ static irqreturn_t mma9553_event_handler(int irq, void *private) · 298 unmodified lines | |||
| 1030 | if (ev_step_detect->enabled && (stepcnt != data->stepcnt)) { | 1031 | if (ev_step_detect->enabled && (stepcnt != data->stepcnt)) { |
| 1031 | data->stepcnt = stepcnt; | 1032 | data->stepcnt = stepcnt; |
| 1032 | iio_push_event(indio_dev, | 1033 | iio_push_event(indio_dev, |
| 1033 | IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD, | 1034 | IIO_UNMOD_EVENT_CODE(IIO_STEPS, 0, |
| 1034 | IIO_EV_DIR_NONE, | 1035 | IIO_EV_TYPE_CHANGE, |
| 1035 | IIO_EV_TYPE_CHANGE, 0, 0, 0), | 1036 | IIO_EV_DIR_NONE), |
| 1036 | data->timestamp); | 1037 | data->timestamp); |
| 1037 | } | 1038 | } |
| 1038 | 1039 | ||
| @@ -1041,20 +1042,18 @@ static irqreturn_t mma9553_event_handler(int irq, void *private) · 2 unmodified lines | |||
| 1041 | /* ev_activity can be NULL if activity == ACTIVITY_UNKNOWN */ | 1042 | /* ev_activity can be NULL if activity == ACTIVITY_UNKNOWN */ |
| 1042 | if (ev_prev_activity && ev_prev_activity->enabled) | 1043 | if (ev_prev_activity && ev_prev_activity->enabled) |
| 1043 | iio_push_event(indio_dev, | 1044 | iio_push_event(indio_dev, |
| 1044 | IIO_EVENT_CODE(IIO_ACTIVITY, 0, | 1045 | IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0, |
| 1045 | ev_prev_activity->info->mod, | 1046 | ev_prev_activity->info->mod, |
| 1046 | IIO_EV_DIR_FALLING, | 1047 | IIO_EV_TYPE_THRESH, |
| 1047 | IIO_EV_TYPE_THRESH, 0, 0, | 1048 | IIO_EV_DIR_FALLING), |
| 1048 | 0), | ||
| 1049 | data->timestamp); | 1049 | data->timestamp); |
| 1050 | 1050 | ||
| 1051 | if (ev_activity && ev_activity->enabled) | 1051 | if (ev_activity && ev_activity->enabled) |
| 1052 | iio_push_event(indio_dev, | 1052 | iio_push_event(indio_dev, |
| 1053 | IIO_EVENT_CODE(IIO_ACTIVITY, 0, | 1053 | IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0, |
| 1054 | ev_activity->info->mod, | 1054 | ev_activity->info->mod, |
| 1055 | IIO_EV_DIR_RISING, | 1055 | IIO_EV_TYPE_THRESH, |
| 1056 | IIO_EV_TYPE_THRESH, 0, 0, | 1056 | IIO_EV_DIR_RISING), |
| 1057 | 0), | ||
| 1058 | data->timestamp); | 1057 | data->timestamp); |
| 1059 | } | 1058 | } |
| 1060 | mutex_unlock(&data->mutex); | 1059 | mutex_unlock(&data->mutex); |
| @@ -1062,17 +1061,6 @@ static irqreturn_t mma9553_event_handler(int irq, void *private) · 1 unmodified line | |||
| 1062 | return IRQ_HANDLED; | 1061 | return IRQ_HANDLED; |
| 1063 | } | 1062 | } |
| 1064 | 1063 | ||
| 1065 | static const char *mma9553_match_acpi_device(struct device *dev) | ||
| 1066 | { | ||
| 1067 | const struct acpi_device_id *id; | ||
| 1068 | |||
| 1069 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
| 1070 | if (!id) | ||
| 1071 | return NULL; | ||
| 1072 | |||
| 1073 | return dev_name(dev); | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | static int mma9553_probe(struct i2c_client *client) | 1064 | static int mma9553_probe(struct i2c_client *client) |
| 1077 | { | 1065 | { |
| 1078 | const struct i2c_device_id *id = i2c_client_get_device_id(client); | 1066 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
| @@ -1091,9 +1079,9 @@ static int mma9553_probe(struct i2c_client *client) · 12 unmodified lines | |||
| 1091 | 1079 | ||
| 1092 | if (id) | 1080 | if (id) |
| 1093 | name = id->name; | 1081 | name = id->name; |
| 1094 | else if (ACPI_HANDLE(&client->dev)) | ||
| 1095 | name = mma9553_match_acpi_device(&client->dev); | ||
| 1096 | else | 1082 | else |
| 1083 | name = iio_get_acpi_device_name(&client->dev); | ||
| 1084 | if (!name) | ||
| 1097 | return -ENOSYS; | 1085 | return -ENOSYS; |
| 1098 | 1086 | ||
| 1099 | mutex_init(&data->mutex); | 1087 | mutex_init(&data->mutex); |
| @@ -34,6 +34,7 @@ · 33 unmodified lines | |||
| 34 | #include <linux/pm_runtime.h> | 34 | #include <linux/pm_runtime.h> |
| 35 | #include <linux/regmap.h> | 35 | #include <linux/regmap.h> |
| 36 | #include <linux/string_choices.h> | 36 | #include <linux/string_choices.h> |
| 37 | #include <linux/types.h> | ||
| 37 | #include <linux/units.h> | 38 | #include <linux/units.h> |
| 38 | 39 | ||
| 39 | #include <linux/iio/buffer.h> | 40 | #include <linux/iio/buffer.h> |
| @@ -893,7 +894,7 @@ static irqreturn_t msa311_buffer_thread(int irq, void *p) · 853 unmodified lines | |||
| 893 | __le16 axis; | 894 | __le16 axis; |
| 894 | struct { | 895 | struct { |
| 895 | __le16 channels[MSA311_SI_Z + 1]; | 896 | __le16 channels[MSA311_SI_Z + 1]; |
| 896 | s64 ts __aligned(8); | 897 | aligned_s64 ts; |
| 897 | } buf; | 898 | } buf; |
| 898 | 899 | ||
| 899 | memset(&buf, 0, sizeof(buf)); | 900 | memset(&buf, 0, sizeof(buf)); |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | |||
| 11 | #include <linux/iio/iio.h> | 11 | #include <linux/iio/iio.h> |
| 12 | #include <linux/mod_devicetable.h> | 12 | #include <linux/mod_devicetable.h> |
| 13 | #include <linux/regmap.h> | 13 | #include <linux/regmap.h> |
| 14 | #include <linux/types.h> | ||
| 14 | #include <linux/iio/sysfs.h> | 15 | #include <linux/iio/sysfs.h> |
| 15 | #include <linux/iio/trigger.h> | 16 | #include <linux/iio/trigger.h> |
| 16 | #include <linux/iio/buffer.h> | 17 | #include <linux/iio/buffer.h> |
| @@ -69,7 +70,7 @@ struct mxc4005_data { · 52 unmodified lines | |||
| 69 | /* Ensure timestamp is naturally aligned */ | 70 | /* Ensure timestamp is naturally aligned */ |
| 70 | struct { | 71 | struct { |
| 71 | __be16 chans[3]; | 72 | __be16 chans[3]; |
| 72 | s64 timestamp __aligned(8); | 73 | aligned_s64 timestamp; |
| 73 | } scan; | 74 | } scan; |
| 74 | bool trigger_enabled; | 75 | bool trigger_enabled; |
| 75 | unsigned int control; | 76 | unsigned int control; |
| @@ -1158,7 +1158,7 @@ error_ret: · 1157 unmodified lines | |||
| 1158 | return ret; | 1158 | return ret; |
| 1159 | } | 1159 | } |
| 1160 | 1160 | ||
| 1161 | static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state) | 1161 | static int sca3000_freefall_set_state(struct iio_dev *indio_dev, bool state) |
| 1162 | { | 1162 | { |
| 1163 | struct sca3000_state *st = iio_priv(indio_dev); | 1163 | struct sca3000_state *st = iio_priv(indio_dev); |
| 1164 | int ret; | 1164 | int ret; |
| @@ -1181,7 +1181,7 @@ static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state) · 16 unmodified lines | |||
| 1181 | } | 1181 | } |
| 1182 | 1182 | ||
| 1183 | static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis, | 1183 | static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis, |
| 1184 | int state) | 1184 | bool state) |
| 1185 | { | 1185 | { |
| 1186 | struct sca3000_state *st = iio_priv(indio_dev); | 1186 | struct sca3000_state *st = iio_priv(indio_dev); |
| 1187 | int ret, ctrlval; | 1187 | int ret, ctrlval; |
| @@ -1253,7 +1253,7 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev, · 65 unmodified lines | |||
| 1253 | const struct iio_chan_spec *chan, | 1253 | const struct iio_chan_spec *chan, |
| 1254 | enum iio_event_type type, | 1254 | enum iio_event_type type, |
| 1255 | enum iio_event_direction dir, | 1255 | enum iio_event_direction dir, |
| 1256 | int state) | 1256 | bool state) |
| 1257 | { | 1257 | { |
| 1258 | struct sca3000_state *st = iio_priv(indio_dev); | 1258 | struct sca3000_state *st = iio_priv(indio_dev); |
| 1259 | int ret; | 1259 | int ret; |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
| 15 | #include <linux/types.h> | ||
| 15 | #include <linux/iio/buffer.h> | 16 | #include <linux/iio/buffer.h> |
| 16 | #include <linux/iio/iio.h> | 17 | #include <linux/iio/iio.h> |
| 17 | #include <linux/iio/sysfs.h> | 18 | #include <linux/iio/sysfs.h> |
| @@ -105,7 +106,7 @@ struct stk8312_data { · 87 unmodified lines | |||
| 105 | /* Ensure timestamp is naturally aligned */ | 106 | /* Ensure timestamp is naturally aligned */ |
| 106 | struct { | 107 | struct { |
| 107 | s8 chans[3]; | 108 | s8 chans[3]; |
| 108 | s64 timestamp __aligned(8); | 109 | aligned_s64 timestamp; |
| 109 | } scan; | 110 | } scan; |
| 110 | }; | 111 | }; |
| 111 | 112 | ||
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/mod_devicetable.h> | 14 | #include <linux/mod_devicetable.h> |
| 15 | #include <linux/types.h> | ||
| 15 | #include <linux/iio/buffer.h> | 16 | #include <linux/iio/buffer.h> |
| 16 | #include <linux/iio/iio.h> | 17 | #include <linux/iio/iio.h> |
| 17 | #include <linux/iio/sysfs.h> | 18 | #include <linux/iio/sysfs.h> |
| @@ -94,7 +95,7 @@ struct stk8ba50_data { · 76 unmodified lines | |||
| 94 | /* Ensure timestamp is naturally aligned */ | 95 | /* Ensure timestamp is naturally aligned */ |
| 95 | struct { | 96 | struct { |
| 96 | s16 chans[3]; | 97 | s16 chans[3]; |
| 97 | s64 timetamp __aligned(8); | 98 | aligned_s64 timetamp; |
| 98 | } scan; | 99 | } scan; |
| 99 | }; | 100 | }; |
| 100 | 101 | ||
| @@ -226,12 +226,14 @@ config AD7606_IFACE_PARALLEL · 225 unmodified lines | |||
| 226 | tristate "Analog Devices AD7606 ADC driver with parallel interface support" | 226 | tristate "Analog Devices AD7606 ADC driver with parallel interface support" |
| 227 | depends on HAS_IOPORT | 227 | depends on HAS_IOPORT |
| 228 | select AD7606 | 228 | select AD7606 |
| 229 | select IIO_BACKEND | ||
| 229 | help | 230 | help |
| 230 | Say yes here to build parallel interface support for Analog Devices: | 231 | Say yes here to build parallel interface support for Analog Devices: |
| 231 | ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). | 232 | ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). |
| 233 | It also support iio_backended devices for AD7606B. | ||
| 232 | 234 | ||
| 233 | To compile this driver as a module, choose M here: the | 235 | To compile this driver as a module, choose M here: the |
| 234 | module will be called ad7606_parallel. | 236 | module will be called ad7606_par. |
| 235 | 237 | ||
| 236 | config AD7606_IFACE_SPI | 238 | config AD7606_IFACE_SPI |
| 237 | tristate "Analog Devices AD7606 ADC driver with spi interface support" | 239 | tristate "Analog Devices AD7606 ADC driver with spi interface support" |
| @@ -244,6 +246,22 @@ config AD7606_IFACE_SPI · 6 unmodified lines | |||
| 244 | To compile this driver as a module, choose M here: the | 246 | To compile this driver as a module, choose M here: the |
| 245 | module will be called ad7606_spi. | 247 | module will be called ad7606_spi. |
| 246 | 248 | ||
| 249 | config AD7625 | ||
| 250 | tristate "Analog Devices AD7625/AD7626 High Speed ADC driver" | ||
| 251 | depends on PWM | ||
| 252 | select IIO_BACKEND | ||
| 253 | help | ||
| 254 | Say yes here to build support for Analog Devices: | ||
| 255 | * AD7625 16-Bit, 6 MSPS PulSAR Analog-to-Digital Converter | ||
| 256 | * AD7626 16-Bit, 10 MSPS PulSAR Analog-to-Digital Converter | ||
| 257 | * AD7960 18-Bit, 5 MSPS PulSAR Analog-to-Digital Converter | ||
| 258 | * AD7961 16-Bit, 5 MSPS PulSAR Analog-to-Digital Converter | ||
| 259 | |||
| 260 | The driver requires the assistance of the AXI ADC IP core to operate. | ||
| 261 | |||
| 262 | To compile this driver as a module, choose M here: the module will be | ||
| 263 | called ad7625. | ||
| 264 | |||
| 247 | config AD7766 | 265 | config AD7766 |
| 248 | tristate "Analog Devices AD7766/AD7767 ADC driver" | 266 | tristate "Analog Devices AD7766/AD7767 ADC driver" |
| 249 | depends on SPI_MASTER | 267 | depends on SPI_MASTER |
| @@ -269,6 +287,18 @@ config AD7768_1 · 19 unmodified lines | |||
| 269 | To compile this driver as a module, choose M here: the module will be | 287 | To compile this driver as a module, choose M here: the module will be |
| 270 | called ad7768-1. | 288 | called ad7768-1. |
| 271 | 289 | ||
| 290 | config AD7779 | ||
| 291 | tristate "Analog Devices AD7779 ADC driver" | ||
| 292 | depends on SPI | ||
| 293 | select CRC8 | ||
| 294 | select IIO_BUFFER | ||
| 295 | help | ||
| 296 | Say yes here to build support for Analog Devices AD777X family | ||
| 297 | (AD7770, AD7771, AD7779) analog to digital converter (ADC). | ||
| 298 | |||
| 299 | To compile this driver as a module, choose M here: the module will be | ||
| 300 | called ad7779. | ||
| 301 | |||
| 272 | config AD7780 | 302 | config AD7780 |
| 273 | tristate "Analog Devices AD7780 and similar ADCs driver" | 303 | tristate "Analog Devices AD7780 and similar ADCs driver" |
| 274 | depends on SPI | 304 | depends on SPI |
| @@ -575,6 +605,16 @@ config FSL_MX25_ADC · 300 unmodified lines | |||
| 575 | Generic Conversion Queue driver used for general purpose ADC in the | 605 | Generic Conversion Queue driver used for general purpose ADC in the |
| 576 | MX25. This driver supports single measurements using the MX25 ADC. | 606 | MX25. This driver supports single measurements using the MX25 ADC. |
| 577 | 607 | ||
| 608 | config GEHC_PMC_ADC | ||
| 609 | tristate "GE HealthCare PMC ADC driver" | ||
| 610 | depends on I2C | ||
| 611 | help | ||
| 612 | Say yes here to build support for the GE HealthCare PMC 16-bit | ||
| 613 | 16-Channel ADC. | ||
| 614 | |||
| 615 | To compile this driver as a module, choose M here: the module will be | ||
| 616 | called gehc-pmc-adc. | ||
| 617 | |||
| 578 | config HI8435 | 618 | config HI8435 |
| 579 | tristate "Holt Integrated Circuits HI-8435 threshold detector" | 619 | tristate "Holt Integrated Circuits HI-8435 threshold detector" |
| 580 | select IIO_TRIGGERED_EVENT | 620 | select IIO_TRIGGERED_EVENT |
| @@ -1580,7 +1620,6 @@ config TWL4030_MADC · 999 unmodified lines | |||
| 1580 | config TWL6030_GPADC | 1620 | config TWL6030_GPADC |
| 1581 | tristate "TWL6030 GPADC (General Purpose A/D Converter) Support" | 1621 | tristate "TWL6030 GPADC (General Purpose A/D Converter) Support" |
| 1582 | depends on TWL4030_CORE | 1622 | depends on TWL4030_CORE |
| 1583 | default n | ||
| 1584 | help | 1623 | help |
| 1585 | Say yes here if you want support for the TWL6030/TWL6032 General | 1624 | Say yes here if you want support for the TWL6030/TWL6032 General |
| 1586 | Purpose A/D Converter. This will add support for battery type | 1625 | Purpose A/D Converter. This will add support for battery type |
| @@ -25,8 +25,10 @@ obj-$(CONFIG_AD7476) += ad7476.o · 24 unmodified lines | |||
| 25 | obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o | 25 | obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o |
| 26 | obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o | 26 | obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o |
| 27 | obj-$(CONFIG_AD7606) += ad7606.o | 27 | obj-$(CONFIG_AD7606) += ad7606.o |
| 28 | obj-$(CONFIG_AD7625) += ad7625.o | ||
| 28 | obj-$(CONFIG_AD7766) += ad7766.o | 29 | obj-$(CONFIG_AD7766) += ad7766.o |
| 29 | obj-$(CONFIG_AD7768_1) += ad7768-1.o | 30 | obj-$(CONFIG_AD7768_1) += ad7768-1.o |
| 31 | obj-$(CONFIG_AD7779) += ad7779.o | ||
| 30 | obj-$(CONFIG_AD7780) += ad7780.o | 32 | obj-$(CONFIG_AD7780) += ad7780.o |
| 31 | obj-$(CONFIG_AD7791) += ad7791.o | 33 | obj-$(CONFIG_AD7791) += ad7791.o |
| 32 | obj-$(CONFIG_AD7793) += ad7793.o | 34 | obj-$(CONFIG_AD7793) += ad7793.o |
| @@ -52,6 +54,7 @@ obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o · 19 unmodified lines | |||
| 52 | obj-$(CONFIG_EP93XX_ADC) += ep93xx_adc.o | 54 | obj-$(CONFIG_EP93XX_ADC) += ep93xx_adc.o |
| 53 | obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o | 55 | obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o |
| 54 | obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o | 56 | obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o |
| 57 | obj-$(CONFIG_GEHC_PMC_ADC) += gehc-pmc-adc.o | ||
| 55 | obj-$(CONFIG_HI8435) += hi8435.o | 58 | obj-$(CONFIG_HI8435) += hi8435.o |
| 56 | obj-$(CONFIG_HX711) += hx711.o | 59 | obj-$(CONFIG_HX711) += hx711.o |
| 57 | obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o | 60 | obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o |
| @@ -1194,7 +1194,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(ab8500_gpadc_pm_ops, · 1193 unmodified lines | |||
| 1194 | 1194 | ||
| 1195 | static struct platform_driver ab8500_gpadc_driver = { | 1195 | static struct platform_driver ab8500_gpadc_driver = { |
| 1196 | .probe = ab8500_gpadc_probe, | 1196 | .probe = ab8500_gpadc_probe, |
| 1197 | .remove_new = ab8500_gpadc_remove, | 1197 | .remove = ab8500_gpadc_remove, |
| 1198 | .driver = { | 1198 | .driver = { |
| 1199 | .name = "ab8500-gpadc", | 1199 | .name = "ab8500-gpadc", |
| 1200 | .pm = pm_ptr(&ab8500_gpadc_pm_ops), | 1200 | .pm = pm_ptr(&ab8500_gpadc_pm_ops), |
| @@ -344,6 +344,8 @@ static int ad4000_single_conversion(struct iio_dev *indio_dev, · 343 unmodified lines | |||
| 344 | 344 | ||
| 345 | if (chan->scan_type.sign == 's') | 345 | if (chan->scan_type.sign == 's') |
| 346 | *val = sign_extend32(sample, chan->scan_type.realbits - 1); | 346 | *val = sign_extend32(sample, chan->scan_type.realbits - 1); |
| 347 | else | ||
| 348 | *val = sample; | ||
| 347 | 349 | ||
| 348 | return IIO_VAL_INT; | 350 | return IIO_VAL_INT; |
| 349 | } | 351 | } |
| @@ -637,7 +639,9 @@ static int ad4000_probe(struct spi_device *spi) · 287 unmodified lines | |||
| 637 | indio_dev->name = chip->dev_name; | 639 | indio_dev->name = chip->dev_name; |
| 638 | indio_dev->num_channels = 1; | 640 | indio_dev->num_channels = 1; |
| 639 | 641 | ||
| 640 | devm_mutex_init(dev, &st->lock); | 642 | ret = devm_mutex_init(dev, &st->lock); |
| 643 | if (ret) | ||
| 644 | return ret; | ||
| 641 | 645 | ||
| 642 | st->gain_milli = 1000; | 646 | st->gain_milli = 1000; |
| 643 | if (chip->has_hardware_gain) { | 647 | if (chip->has_hardware_gain) { |
| @@ -150,7 +150,8 @@ static int ad7091r_read_event_config(struct iio_dev *indio_dev, · 149 unmodified lines | |||
| 150 | static int ad7091r_write_event_config(struct iio_dev *indio_dev, | 150 | static int ad7091r_write_event_config(struct iio_dev *indio_dev, |
| 151 | const struct iio_chan_spec *chan, | 151 | const struct iio_chan_spec *chan, |
| 152 | enum iio_event_type type, | 152 | enum iio_event_type type, |
| 153 | enum iio_event_direction dir, int state) | 153 | enum iio_event_direction dir, |
| 154 | bool state) | ||
| 154 | { | 155 | { |
| 155 | struct ad7091r_state *st = iio_priv(indio_dev); | 156 | struct ad7091r_state *st = iio_priv(indio_dev); |
| 156 | 157 | ||
| @@ -65,7 +65,7 @@ struct ad7091r_state { · 64 unmodified lines | |||
| 65 | struct regulator *vref; | 65 | struct regulator *vref; |
| 66 | const struct ad7091r_chip_info *chip_info; | 66 | const struct ad7091r_chip_info *chip_info; |
| 67 | enum ad7091r_mode mode; | 67 | enum ad7091r_mode mode; |
| 68 | struct mutex lock; /*lock to prevent concurent reads */ | 68 | struct mutex lock; /*lock to prevent concurrent reads */ |
| 69 | __be16 tx_buf __aligned(IIO_DMA_MINALIGN); | 69 | __be16 tx_buf __aligned(IIO_DMA_MINALIGN); |
| 70 | __be16 rx_buf; | 70 | __be16 rx_buf; |
| 71 | }; | 71 | }; |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | |||
| 3 | * AD717x and AD411x family SPI ADC driver | 3 | * AD717x and AD411x family SPI ADC driver |
| 4 | * | 4 | * |
| 5 | * Supported devices: | 5 | * Supported devices: |
| 6 | * AD4111/AD4112/AD4114/AD4115/AD4116 | 6 | * AD4111/AD4112/AD4113/AD4114/AD4115/AD4116 |
| 7 | * AD7172-2/AD7172-4/AD7173-8/AD7175-2 | 7 | * AD7172-2/AD7172-4/AD7173-8/AD7175-2 |
| 8 | * AD7175-8/AD7176-2/AD7177-2 | 8 | * AD7175-8/AD7176-2/AD7177-2 |
| 9 | * | 9 | * |
| @@ -76,14 +76,15 @@ · 66 unmodified lines | |||
| 76 | (x) == AD7173_AIN_REF_NEG) | 76 | (x) == AD7173_AIN_REF_NEG) |
| 77 | 77 | ||
| 78 | #define AD7172_2_ID 0x00d0 | 78 | #define AD7172_2_ID 0x00d0 |
| 79 | #define AD7175_ID 0x0cd0 | ||
| 80 | #define AD7176_ID 0x0c90 | 79 | #define AD7176_ID 0x0c90 |
| 80 | #define AD7175_ID 0x0cd0 | ||
| 81 | #define AD7175_2_ID 0x0cd0 | 81 | #define AD7175_2_ID 0x0cd0 |
| 82 | #define AD7172_4_ID 0x2050 | 82 | #define AD7172_4_ID 0x2050 |
| 83 | #define AD7173_ID 0x30d0 | 83 | #define AD7173_ID 0x30d0 |
| 84 | #define AD4111_ID AD7173_ID | 84 | #define AD4111_ID AD7173_ID |
| 85 | #define AD4112_ID AD7173_ID | 85 | #define AD4112_ID AD7173_ID |
| 86 | #define AD4114_ID AD7173_ID | 86 | #define AD4114_ID AD7173_ID |
| 87 | #define AD4113_ID 0x31d0 | ||
| 87 | #define AD4116_ID 0x34d0 | 88 | #define AD4116_ID 0x34d0 |
| 88 | #define AD4115_ID 0x38d0 | 89 | #define AD4115_ID 0x38d0 |
| 89 | #define AD7175_8_ID 0x3cd0 | 90 | #define AD7175_8_ID 0x3cd0 |
| @@ -170,6 +171,7 @@ struct ad7173_device_info { · 80 unmodified lines | |||
| 170 | bool has_temp; | 171 | bool has_temp; |
| 171 | /* ((AVDD1 − AVSS)/5) */ | 172 | /* ((AVDD1 − AVSS)/5) */ |
| 172 | bool has_pow_supply_monitoring; | 173 | bool has_pow_supply_monitoring; |
| 174 | bool data_reg_only_16bit; | ||
| 173 | bool has_input_buf; | 175 | bool has_input_buf; |
| 174 | bool has_int_ref; | 176 | bool has_int_ref; |
| 175 | bool has_ref2; | 177 | bool has_ref2; |
| @@ -294,6 +296,24 @@ static const struct ad7173_device_info ad4112_device_info = { · 118 unmodified lines | |||
| 294 | .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates), | 296 | .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates), |
| 295 | }; | 297 | }; |
| 296 | 298 | ||
| 299 | static const struct ad7173_device_info ad4113_device_info = { | ||
| 300 | .name = "ad4113", | ||
| 301 | .id = AD4113_ID, | ||
| 302 | .num_voltage_in_div = 8, | ||
| 303 | .num_channels = 16, | ||
| 304 | .num_configs = 8, | ||
| 305 | .num_voltage_in = 8, | ||
| 306 | .num_gpios = 2, | ||
| 307 | .data_reg_only_16bit = true, | ||
| 308 | .higher_gpio_bits = true, | ||
| 309 | .has_vincom_input = true, | ||
| 310 | .has_input_buf = true, | ||
| 311 | .has_int_ref = true, | ||
| 312 | .clock = 2 * HZ_PER_MHZ, | ||
| 313 | .sinc5_data_rates = ad7173_sinc5_data_rates, | ||
| 314 | .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates), | ||
| 315 | }; | ||
| 316 | |||
| 297 | static const struct ad7173_device_info ad4114_device_info = { | 317 | static const struct ad7173_device_info ad4114_device_info = { |
| 298 | .name = "ad4114", | 318 | .name = "ad4114", |
| 299 | .id = AD4114_ID, | 319 | .id = AD4114_ID, |
| @@ -985,6 +1005,13 @@ static const struct iio_info ad7173_info = { · 685 unmodified lines | |||
| 985 | .update_scan_mode = ad7173_update_scan_mode, | 1005 | .update_scan_mode = ad7173_update_scan_mode, |
| 986 | }; | 1006 | }; |
| 987 | 1007 | ||
| 1008 | static const struct iio_scan_type ad4113_scan_type = { | ||
| 1009 | .sign = 'u', | ||
| 1010 | .realbits = 16, | ||
| 1011 | .storagebits = 16, | ||
| 1012 | .endianness = IIO_BE, | ||
| 1013 | }; | ||
| 1014 | |||
| 988 | static const struct iio_chan_spec ad7173_channel_template = { | 1015 | static const struct iio_chan_spec ad7173_channel_template = { |
| 989 | .type = IIO_VOLTAGE, | 1016 | .type = IIO_VOLTAGE, |
| 990 | .indexed = 1, | 1017 | .indexed = 1, |
| @@ -1226,6 +1253,8 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev) · 235 unmodified lines | |||
| 1226 | chan_st_priv->cfg.input_buf = st->info->has_input_buf; | 1253 | chan_st_priv->cfg.input_buf = st->info->has_input_buf; |
| 1227 | chan_st_priv->cfg.ref_sel = AD7173_SETUP_REF_SEL_INT_REF; | 1254 | chan_st_priv->cfg.ref_sel = AD7173_SETUP_REF_SEL_INT_REF; |
| 1228 | st->adc_mode |= AD7173_ADC_MODE_REF_EN; | 1255 | st->adc_mode |= AD7173_ADC_MODE_REF_EN; |
| 1256 | if (st->info->data_reg_only_16bit) | ||
| 1257 | chan_arr[chan_index].scan_type = ad4113_scan_type; | ||
| 1229 | 1258 | ||
| 1230 | chan_index++; | 1259 | chan_index++; |
| 1231 | } | 1260 | } |
| @@ -1306,6 +1335,9 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev) · 74 unmodified lines | |||
| 1306 | chan_st_priv->ain = AD7173_CH_ADDRESS(ain[0], ain[1]); | 1335 | chan_st_priv->ain = AD7173_CH_ADDRESS(ain[0], ain[1]); |
| 1307 | } | 1336 | } |
| 1308 | 1337 | ||
| 1338 | if (st->info->data_reg_only_16bit) | ||
| 1339 | chan_arr[chan_index].scan_type = ad4113_scan_type; | ||
| 1340 | |||
| 1309 | chan_index++; | 1341 | chan_index++; |
| 1310 | } | 1342 | } |
| 1311 | return 0; | 1343 | return 0; |
| @@ -1434,6 +1466,7 @@ static int ad7173_probe(struct spi_device *spi) · 122 unmodified lines | |||
| 1434 | static const struct of_device_id ad7173_of_match[] = { | 1466 | static const struct of_device_id ad7173_of_match[] = { |
| 1435 | { .compatible = "adi,ad4111", .data = &ad4111_device_info }, | 1467 | { .compatible = "adi,ad4111", .data = &ad4111_device_info }, |
| 1436 | { .compatible = "adi,ad4112", .data = &ad4112_device_info }, | 1468 | { .compatible = "adi,ad4112", .data = &ad4112_device_info }, |
| 1469 | { .compatible = "adi,ad4113", .data = &ad4113_device_info }, | ||
| 1437 | { .compatible = "adi,ad4114", .data = &ad4114_device_info }, | 1470 | { .compatible = "adi,ad4114", .data = &ad4114_device_info }, |
| 1438 | { .compatible = "adi,ad4115", .data = &ad4115_device_info }, | 1471 | { .compatible = "adi,ad4115", .data = &ad4115_device_info }, |
| 1439 | { .compatible = "adi,ad4116", .data = &ad4116_device_info }, | 1472 | { .compatible = "adi,ad4116", .data = &ad4116_device_info }, |
| @@ -1451,6 +1484,7 @@ MODULE_DEVICE_TABLE(of, ad7173_of_match); · 11 unmodified lines | |||
| 1451 | static const struct spi_device_id ad7173_id_table[] = { | 1484 | static const struct spi_device_id ad7173_id_table[] = { |
| 1452 | { "ad4111", (kernel_ulong_t)&ad4111_device_info }, | 1485 | { "ad4111", (kernel_ulong_t)&ad4111_device_info }, |
| 1453 | { "ad4112", (kernel_ulong_t)&ad4112_device_info }, | 1486 | { "ad4112", (kernel_ulong_t)&ad4112_device_info }, |
| 1487 | { "ad4113", (kernel_ulong_t)&ad4113_device_info }, | ||
| 1454 | { "ad4114", (kernel_ulong_t)&ad4114_device_info }, | 1488 | { "ad4114", (kernel_ulong_t)&ad4114_device_info }, |
| 1455 | { "ad4115", (kernel_ulong_t)&ad4115_device_info }, | 1489 | { "ad4115", (kernel_ulong_t)&ad4115_device_info }, |
| 1456 | { "ad4116", (kernel_ulong_t)&ad4116_device_info }, | 1490 | { "ad4116", (kernel_ulong_t)&ad4116_device_info }, |
| @@ -1394,6 +1394,9 @@ static int ad7192_probe(struct spi_device *spi) · 1393 unmodified lines | |||
| 1394 | st->int_vref_mv = ret == -ENODEV ? avdd_mv : ret / MILLI; | 1394 | st->int_vref_mv = ret == -ENODEV ? avdd_mv : ret / MILLI; |
| 1395 | 1395 | ||
| 1396 | st->chip_info = spi_get_device_match_data(spi); | 1396 | st->chip_info = spi_get_device_match_data(spi); |
| 1397 | if (!st->chip_info) | ||
| 1398 | return -ENODEV; | ||
| 1399 | |||
| 1397 | indio_dev->name = st->chip_info->name; | 1400 | indio_dev->name = st->chip_info->name; |
| 1398 | indio_dev->modes = INDIO_DIRECT_MODE; | 1401 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 1399 | indio_dev->info = st->chip_info->info; | 1402 | indio_dev->info = st->chip_info->info; |
| @@ -383,7 +383,7 @@ static const char * const ad7266_gpio_labels[] = { · 382 unmodified lines | |||
| 383 | 383 | ||
| 384 | static int ad7266_probe(struct spi_device *spi) | 384 | static int ad7266_probe(struct spi_device *spi) |
| 385 | { | 385 | { |
| 386 | struct ad7266_platform_data *pdata = spi->dev.platform_data; | 386 | const struct ad7266_platform_data *pdata = dev_get_platdata(&spi->dev); |
| 387 | struct iio_dev *indio_dev; | 387 | struct iio_dev *indio_dev; |
| 388 | struct ad7266_state *st; | 388 | struct ad7266_state *st; |
| 389 | unsigned int i; | 389 | unsigned int i; |
| @@ -822,17 +822,15 @@ static irqreturn_t ad7280_event_handler(int irq, void *private) · 821 unmodified lines | |||
| 822 | if (FIELD_GET(AD7280A_TRANS_READ_CONV_CHANADDR_MSK, channels[i]) <= | 822 | if (FIELD_GET(AD7280A_TRANS_READ_CONV_CHANADDR_MSK, channels[i]) <= |
| 823 | AD7280A_CELL_VOLTAGE_6_REG) { | 823 | AD7280A_CELL_VOLTAGE_6_REG) { |
| 824 | if (val >= st->cell_threshhigh) { | 824 | if (val >= st->cell_threshhigh) { |
| 825 | u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0, | 825 | u64 tmp = IIO_DIFF_EVENT_CODE(IIO_VOLTAGE, 0, 0, |
| 826 | IIO_EV_DIR_RISING, | 826 | IIO_EV_TYPE_THRESH, |
| 827 | IIO_EV_TYPE_THRESH, | 827 | IIO_EV_DIR_RISING); |
| 828 | 0, 0, 0); | ||
| 829 | iio_push_event(indio_dev, tmp, | 828 | iio_push_event(indio_dev, tmp, |
| 830 | iio_get_time_ns(indio_dev)); | 829 | iio_get_time_ns(indio_dev)); |
| 831 | } else if (val <= st->cell_threshlow) { | 830 | } else if (val <= st->cell_threshlow) { |
| 832 | u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0, | 831 | u64 tmp = IIO_DIFF_EVENT_CODE(IIO_VOLTAGE, 0, 0, |
| 833 | IIO_EV_DIR_FALLING, | 832 | IIO_EV_TYPE_THRESH, |
| 834 | IIO_EV_TYPE_THRESH, | 833 | IIO_EV_DIR_FALLING); |
| 835 | 0, 0, 0); | ||
| 836 | iio_push_event(indio_dev, tmp, | 834 | iio_push_event(indio_dev, tmp, |
| 837 | iio_get_time_ns(indio_dev)); | 835 | iio_get_time_ns(indio_dev)); |
| 838 | } | 836 | } |
| @@ -269,7 +269,7 @@ static int ad7291_write_event_config(struct iio_dev *indio_dev, · 268 unmodified lines | |||
| 269 | const struct iio_chan_spec *chan, | 269 | const struct iio_chan_spec *chan, |
| 270 | enum iio_event_type type, | 270 | enum iio_event_type type, |
| 271 | enum iio_event_direction dir, | 271 | enum iio_event_direction dir, |
| 272 | int state) | 272 | bool state) |
| 273 | { | 273 | { |
| 274 | int ret = 0; | 274 | int ret = 0; |
| 275 | struct ad7291_chip_info *chip = iio_priv(indio_dev); | 275 | struct ad7291_chip_info *chip = iio_priv(indio_dev); |
| @@ -13,6 +13,8 @@ · 12 unmodified lines | |||
| 13 | * ad7381-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7381-4.pdf | 13 | * ad7381-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7381-4.pdf |
| 14 | * ad7383/4-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-4-ad7384-4.pdf | 14 | * ad7383/4-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-4-ad7384-4.pdf |
| 15 | * ad7386/7/8-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7386-4-7387-4-7388-4.pdf | 15 | * ad7386/7/8-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7386-4-7387-4-7388-4.pdf |
| 16 | * adaq4370-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4370-4.pdf | ||
| 17 | * adaq4380-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4380-4.pdf | ||
| 16 | */ | 18 | */ |
| 17 | 19 | ||
| 18 | #include <linux/align.h> | 20 | #include <linux/align.h> |
| @@ -22,11 +24,14 @@ · 3 unmodified lines | |||
| 22 | #include <linux/device.h> | 24 | #include <linux/device.h> |
| 23 | #include <linux/err.h> | 25 | #include <linux/err.h> |
| 24 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 27 | #include <linux/math.h> | ||
| 25 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 26 | #include <linux/regmap.h> | 29 | #include <linux/regmap.h> |
| 27 | #include <linux/regulator/consumer.h> | 30 | #include <linux/regulator/consumer.h> |
| 28 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
| 29 | #include <linux/spi/spi.h> | 32 | #include <linux/spi/spi.h> |
| 33 | #include <linux/units.h> | ||
| 34 | #include <linux/util_macros.h> | ||
| 30 | 35 | ||
| 31 | #include <linux/iio/buffer.h> | 36 | #include <linux/iio/buffer.h> |
| 32 | #include <linux/iio/iio.h> | 37 | #include <linux/iio/iio.h> |
| @@ -36,6 +41,8 @@ · 3 unmodified lines | |||
| 36 | #define MAX_NUM_CHANNELS 8 | 41 | #define MAX_NUM_CHANNELS 8 |
| 37 | /* 2.5V internal reference voltage */ | 42 | /* 2.5V internal reference voltage */ |
| 38 | #define AD7380_INTERNAL_REF_MV 2500 | 43 | #define AD7380_INTERNAL_REF_MV 2500 |
| 44 | /* 3.3V internal reference voltage for ADAQ */ | ||
| 45 | #define ADAQ4380_INTERNAL_REF_MV 3300 | ||
| 39 | 46 | ||
| 40 | /* reading and writing registers is more reliable at lower than max speed */ | 47 | /* reading and writing registers is more reliable at lower than max speed */ |
| 41 | #define AD7380_REG_WR_SPEED_HZ 10000000 | 48 | #define AD7380_REG_WR_SPEED_HZ 10000000 |
| @@ -77,6 +84,13 @@ · 35 unmodified lines | |||
| 77 | #define T_CONVERT_X_NS 500 /* xth conversion start time (oversampling) */ | 84 | #define T_CONVERT_X_NS 500 /* xth conversion start time (oversampling) */ |
| 78 | #define T_POWERUP_US 5000 /* Power up */ | 85 | #define T_POWERUP_US 5000 /* Power up */ |
| 79 | 86 | ||
| 87 | /* | ||
| 88 | * AD738x support several SDO lines to increase throughput, but driver currently | ||
| 89 | * supports only 1 SDO line (standard SPI transaction) | ||
| 90 | */ | ||
| 91 | #define AD7380_NUM_SDO_LINES 1 | ||
| 92 | #define AD7380_DEFAULT_GAIN_MILLI 1000 | ||
| 93 | |||
| 80 | struct ad7380_timing_specs { | 94 | struct ad7380_timing_specs { |
| 81 | const unsigned int t_csh_ns; /* CS minimum high time */ | 95 | const unsigned int t_csh_ns; /* CS minimum high time */ |
| 82 | }; | 96 | }; |
| @@ -86,10 +100,12 @@ struct ad7380_chip_info { · 3 unmodified lines | |||
| 86 | const struct iio_chan_spec *channels; | 100 | const struct iio_chan_spec *channels; |
| 87 | unsigned int num_channels; | 101 | unsigned int num_channels; |
| 88 | unsigned int num_simult_channels; | 102 | unsigned int num_simult_channels; |
| 103 | bool has_hardware_gain; | ||
| 89 | bool has_mux; | 104 | bool has_mux; |
| 90 | const char * const *supplies; | 105 | const char * const *supplies; |
| 91 | unsigned int num_supplies; | 106 | unsigned int num_supplies; |
| 92 | bool external_ref_only; | 107 | bool external_ref_only; |
| 108 | bool adaq_internal_ref_only; | ||
| 93 | const char * const *vcm_supplies; | 109 | const char * const *vcm_supplies; |
| 94 | unsigned int num_vcm_supplies; | 110 | unsigned int num_vcm_supplies; |
| 95 | const unsigned long *available_scan_masks; | 111 | const unsigned long *available_scan_masks; |
| @@ -181,11 +197,12 @@ static const struct iio_scan_type ad7380_scan_type_16_u[] = { · 85 unmodified lines | |||
| 181 | }, | 197 | }, |
| 182 | }; | 198 | }; |
| 183 | 199 | ||
| 184 | #define AD7380_CHANNEL(index, bits, diff, sign) { \ | 200 | #define _AD7380_CHANNEL(index, bits, diff, sign, gain) { \ |
| 185 | .type = IIO_VOLTAGE, \ | 201 | .type = IIO_VOLTAGE, \ |
| 186 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | 202 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
| 203 | ((gain) ? BIT(IIO_CHAN_INFO_SCALE) : 0) | \ | ||
| 187 | ((diff) ? 0 : BIT(IIO_CHAN_INFO_OFFSET)), \ | 204 | ((diff) ? 0 : BIT(IIO_CHAN_INFO_OFFSET)), \ |
| 188 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ | 205 | .info_mask_shared_by_type = ((gain) ? 0 : BIT(IIO_CHAN_INFO_SCALE)) | \ |
| 189 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ | 206 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ |
| 190 | .info_mask_shared_by_type_available = \ | 207 | .info_mask_shared_by_type_available = \ |
| 191 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ | 208 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ |
| @@ -199,6 +216,12 @@ static const struct iio_scan_type ad7380_scan_type_16_u[] = { · 7 unmodified lines | |||
| 199 | .num_ext_scan_type = ARRAY_SIZE(ad7380_scan_type_##bits##_##sign), \ | 216 | .num_ext_scan_type = ARRAY_SIZE(ad7380_scan_type_##bits##_##sign), \ |
| 200 | } | 217 | } |
| 201 | 218 | ||
| 219 | #define AD7380_CHANNEL(index, bits, diff, sign) \ | ||
| 220 | _AD7380_CHANNEL(index, bits, diff, sign, false) | ||
| 221 | |||
| 222 | #define ADAQ4380_CHANNEL(index, bits, diff, sign) \ | ||
| 223 | _AD7380_CHANNEL(index, bits, diff, sign, true) | ||
| 224 | |||
| 202 | #define DEFINE_AD7380_2_CHANNEL(name, bits, diff, sign) \ | 225 | #define DEFINE_AD7380_2_CHANNEL(name, bits, diff, sign) \ |
| 203 | static const struct iio_chan_spec name[] = { \ | 226 | static const struct iio_chan_spec name[] = { \ |
| 204 | AD7380_CHANNEL(0, bits, diff, sign), \ | 227 | AD7380_CHANNEL(0, bits, diff, sign), \ |
| @@ -215,6 +238,15 @@ static const struct iio_chan_spec name[] = { \ · 10 unmodified lines | |||
| 215 | IIO_CHAN_SOFT_TIMESTAMP(4), \ | 238 | IIO_CHAN_SOFT_TIMESTAMP(4), \ |
| 216 | } | 239 | } |
| 217 | 240 | ||
| 241 | #define DEFINE_ADAQ4380_4_CHANNEL(name, bits, diff, sign) \ | ||
| 242 | static const struct iio_chan_spec name[] = { \ | ||
| 243 | ADAQ4380_CHANNEL(0, bits, diff, sign), \ | ||
| 244 | ADAQ4380_CHANNEL(1, bits, diff, sign), \ | ||
| 245 | ADAQ4380_CHANNEL(2, bits, diff, sign), \ | ||
| 246 | ADAQ4380_CHANNEL(3, bits, diff, sign), \ | ||
| 247 | IIO_CHAN_SOFT_TIMESTAMP(4), \ | ||
| 248 | } | ||
| 249 | |||
| 218 | #define DEFINE_AD7380_8_CHANNEL(name, bits, diff, sign) \ | 250 | #define DEFINE_AD7380_8_CHANNEL(name, bits, diff, sign) \ |
| 219 | static const struct iio_chan_spec name[] = { \ | 251 | static const struct iio_chan_spec name[] = { \ |
| 220 | AD7380_CHANNEL(0, bits, diff, sign), \ | 252 | AD7380_CHANNEL(0, bits, diff, sign), \ |
| @@ -233,6 +265,7 @@ DEFINE_AD7380_2_CHANNEL(ad7380_channels, 16, 1, s); · 12 unmodified lines | |||
| 233 | DEFINE_AD7380_2_CHANNEL(ad7381_channels, 14, 1, s); | 265 | DEFINE_AD7380_2_CHANNEL(ad7381_channels, 14, 1, s); |
| 234 | DEFINE_AD7380_4_CHANNEL(ad7380_4_channels, 16, 1, s); | 266 | DEFINE_AD7380_4_CHANNEL(ad7380_4_channels, 16, 1, s); |
| 235 | DEFINE_AD7380_4_CHANNEL(ad7381_4_channels, 14, 1, s); | 267 | DEFINE_AD7380_4_CHANNEL(ad7381_4_channels, 14, 1, s); |
| 268 | DEFINE_ADAQ4380_4_CHANNEL(adaq4380_4_channels, 16, 1, s); | ||
| 236 | /* pseudo differential */ | 269 | /* pseudo differential */ |
| 237 | DEFINE_AD7380_2_CHANNEL(ad7383_channels, 16, 0, s); | 270 | DEFINE_AD7380_2_CHANNEL(ad7383_channels, 16, 0, s); |
| 238 | DEFINE_AD7380_2_CHANNEL(ad7384_channels, 14, 0, s); | 271 | DEFINE_AD7380_2_CHANNEL(ad7384_channels, 14, 0, s); |
| @@ -251,6 +284,10 @@ static const char * const ad7380_supplies[] = { · 12 unmodified lines | |||
| 251 | "vcc", "vlogic", | 284 | "vcc", "vlogic", |
| 252 | }; | 285 | }; |
| 253 | 286 | ||
| 287 | static const char * const adaq4380_supplies[] = { | ||
| 288 | "ldo", "vcc", "vlogic", "vs-p", "vs-n", "refin", | ||
| 289 | }; | ||
| 290 | |||
| 254 | static const char * const ad7380_2_channel_vcm_supplies[] = { | 291 | static const char * const ad7380_2_channel_vcm_supplies[] = { |
| 255 | "aina", "ainb", | 292 | "aina", "ainb", |
| 256 | }; | 293 | }; |
| @@ -341,6 +378,11 @@ static const int ad7380_oversampling_ratios[] = { · 84 unmodified lines | |||
| 341 | 1, 2, 4, 8, 16, 32, | 378 | 1, 2, 4, 8, 16, 32, |
| 342 | }; | 379 | }; |
| 343 | 380 | ||
| 381 | /* Gains stored as fractions of 1000 so they can be expressed by integers. */ | ||
| 382 | static const int ad7380_gains[] = { | ||
| 383 | 300, 600, 1000, 1600, | ||
| 384 | }; | ||
| 385 | |||
| 344 | static const struct ad7380_chip_info ad7380_chip_info = { | 386 | static const struct ad7380_chip_info ad7380_chip_info = { |
| 345 | .name = "ad7380", | 387 | .name = "ad7380", |
| 346 | .channels = ad7380_channels, | 388 | .channels = ad7380_channels, |
| @@ -510,6 +552,32 @@ static const struct ad7380_chip_info ad7388_4_chip_info = { · 163 unmodified lines | |||
| 510 | .timing_specs = &ad7380_4_timing, | 552 | .timing_specs = &ad7380_4_timing, |
| 511 | }; | 553 | }; |
| 512 | 554 | ||
| 555 | static const struct ad7380_chip_info adaq4370_4_chip_info = { | ||
| 556 | .name = "adaq4370-4", | ||
| 557 | .channels = adaq4380_4_channels, | ||
| 558 | .num_channels = ARRAY_SIZE(adaq4380_4_channels), | ||
| 559 | .num_simult_channels = 4, | ||
| 560 | .supplies = adaq4380_supplies, | ||
| 561 | .num_supplies = ARRAY_SIZE(adaq4380_supplies), | ||
| 562 | .adaq_internal_ref_only = true, | ||
| 563 | .has_hardware_gain = true, | ||
| 564 | .available_scan_masks = ad7380_4_channel_scan_masks, | ||
| 565 | .timing_specs = &ad7380_4_timing, | ||
| 566 | }; | ||
| 567 | |||
| 568 | static const struct ad7380_chip_info adaq4380_4_chip_info = { | ||
| 569 | .name = "adaq4380-4", | ||
| 570 | .channels = adaq4380_4_channels, | ||
| 571 | .num_channels = ARRAY_SIZE(adaq4380_4_channels), | ||
| 572 | .num_simult_channels = 4, | ||
| 573 | .supplies = adaq4380_supplies, | ||
| 574 | .num_supplies = ARRAY_SIZE(adaq4380_supplies), | ||
| 575 | .adaq_internal_ref_only = true, | ||
| 576 | .has_hardware_gain = true, | ||
| 577 | .available_scan_masks = ad7380_4_channel_scan_masks, | ||
| 578 | .timing_specs = &ad7380_4_timing, | ||
| 579 | }; | ||
| 580 | |||
| 513 | struct ad7380_state { | 581 | struct ad7380_state { |
| 514 | const struct ad7380_chip_info *chip_info; | 582 | const struct ad7380_chip_info *chip_info; |
| 515 | struct spi_device *spi; | 583 | struct spi_device *spi; |
| @@ -520,6 +588,7 @@ struct ad7380_state { · 4 unmodified lines | |||
| 520 | bool seq; | 588 | bool seq; |
| 521 | unsigned int vref_mv; | 589 | unsigned int vref_mv; |
| 522 | unsigned int vcm_mv[MAX_NUM_CHANNELS]; | 590 | unsigned int vcm_mv[MAX_NUM_CHANNELS]; |
| 591 | unsigned int gain_milli[MAX_NUM_CHANNELS]; | ||
| 523 | /* xfers, message an buffer for reading sample data */ | 592 | /* xfers, message an buffer for reading sample data */ |
| 524 | struct spi_transfer normal_xfer[2]; | 593 | struct spi_transfer normal_xfer[2]; |
| 525 | struct spi_message normal_msg; | 594 | struct spi_message normal_msg; |
| @@ -649,7 +718,8 @@ static int ad7380_set_ch(struct ad7380_state *st, unsigned int ch) · 123 unmodified lines | |||
| 649 | 718 | ||
| 650 | if (st->oversampling_ratio > 1) | 719 | if (st->oversampling_ratio > 1) |
| 651 | xfer.delay.value = T_CONVERT_0_NS + | 720 | xfer.delay.value = T_CONVERT_0_NS + |
| 652 | T_CONVERT_X_NS * (st->oversampling_ratio - 1); | 721 | T_CONVERT_X_NS * (st->oversampling_ratio - 1) * |
| 722 | st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES; | ||
| 653 | 723 | ||
| 654 | return spi_sync_transfer(st->spi, &xfer, 1); | 724 | return spi_sync_transfer(st->spi, &xfer, 1); |
| 655 | } | 725 | } |
| @@ -672,7 +742,8 @@ static void ad7380_update_xfers(struct ad7380_state *st, · 16 unmodified lines | |||
| 672 | */ | 742 | */ |
| 673 | if (st->oversampling_ratio > 1) | 743 | if (st->oversampling_ratio > 1) |
| 674 | t_convert = T_CONVERT_0_NS + T_CONVERT_X_NS * | 744 | t_convert = T_CONVERT_0_NS + T_CONVERT_X_NS * |
| 675 | (st->oversampling_ratio - 1); | 745 | (st->oversampling_ratio - 1) * |
| 746 | st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES; | ||
| 676 | 747 | ||
| 677 | if (st->seq) { | 748 | if (st->seq) { |
| 678 | xfer[0].delay.value = xfer[1].delay.value = t_convert; | 749 | xfer[0].delay.value = xfer[1].delay.value = t_convert; |
| @@ -868,8 +939,15 @@ static int ad7380_read_raw(struct iio_dev *indio_dev, · 189 unmodified lines | |||
| 868 | * * (2 × VREF) / 2^N, for differential chips | 939 | * * (2 × VREF) / 2^N, for differential chips |
| 869 | * * VREF / 2^N, for pseudo-differential chips | 940 | * * VREF / 2^N, for pseudo-differential chips |
| 870 | * where N is the ADC resolution (i.e realbits) | 941 | * where N is the ADC resolution (i.e realbits) |
| 942 | * | ||
| 943 | * The gain is stored as a fraction of 1000 and, as we need to | ||
| 944 | * divide vref_mv by the gain, we invert the gain/1000 fraction. | ||
| 871 | */ | 945 | */ |
| 872 | *val = st->vref_mv; | 946 | if (st->chip_info->has_hardware_gain) |
| 947 | *val = mult_frac(st->vref_mv, MILLI, | ||
| 948 | st->gain_milli[chan->scan_index]); | ||
| 949 | else | ||
| 950 | *val = st->vref_mv; | ||
| 873 | *val2 = scan_type->realbits - chan->differential; | 951 | *val2 = scan_type->realbits - chan->differential; |
| 874 | 952 | ||
| 875 | return IIO_VAL_FRACTIONAL_LOG2; | 953 | return IIO_VAL_FRACTIONAL_LOG2; |
| @@ -1021,17 +1099,19 @@ static int ad7380_init(struct ad7380_state *st, bool external_ref_en) · 145 unmodified lines | |||
| 1021 | /* SPI 1-wire mode */ | 1099 | /* SPI 1-wire mode */ |
| 1022 | return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2, | 1100 | return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2, |
| 1023 | AD7380_CONFIG2_SDO, | 1101 | AD7380_CONFIG2_SDO, |
| 1024 | FIELD_PREP(AD7380_CONFIG2_SDO, 1)); | 1102 | FIELD_PREP(AD7380_CONFIG2_SDO, |
| 1103 | AD7380_NUM_SDO_LINES)); | ||
| 1025 | } | 1104 | } |
| 1026 | 1105 | ||
| 1027 | static int ad7380_probe(struct spi_device *spi) | 1106 | static int ad7380_probe(struct spi_device *spi) |
| 1028 | { | 1107 | { |
| 1108 | struct device *dev = &spi->dev; | ||
| 1029 | struct iio_dev *indio_dev; | 1109 | struct iio_dev *indio_dev; |
| 1030 | struct ad7380_state *st; | 1110 | struct ad7380_state *st; |
| 1031 | bool external_ref_en; | 1111 | bool external_ref_en; |
| 1032 | int ret, i; | 1112 | int ret, i; |
| 1033 | 1113 | ||
| 1034 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); | 1114 | indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); |
| 1035 | if (!indio_dev) | 1115 | if (!indio_dev) |
| 1036 | return -ENOMEM; | 1116 | return -ENOMEM; |
| 1037 | 1117 | ||
| @@ -1039,21 +1119,32 @@ static int ad7380_probe(struct spi_device *spi) · 1 unmodified line | |||
| 1039 | st->spi = spi; | 1119 | st->spi = spi; |
| 1040 | st->chip_info = spi_get_device_match_data(spi); | 1120 | st->chip_info = spi_get_device_match_data(spi); |
| 1041 | if (!st->chip_info) | 1121 | if (!st->chip_info) |
| 1042 | return dev_err_probe(&spi->dev, -EINVAL, "missing match data\n"); | 1122 | return dev_err_probe(dev, -EINVAL, "missing match data\n"); |
| 1043 | 1123 | ||
| 1044 | ret = devm_regulator_bulk_get_enable(&spi->dev, st->chip_info->num_supplies, | 1124 | ret = devm_regulator_bulk_get_enable(dev, st->chip_info->num_supplies, |
| 1045 | st->chip_info->supplies); | 1125 | st->chip_info->supplies); |
| 1046 | 1126 | ||
| 1047 | if (ret) | 1127 | if (ret) |
| 1048 | return dev_err_probe(&spi->dev, ret, | 1128 | return dev_err_probe(dev, ret, |
| 1049 | "Failed to enable power supplies\n"); | 1129 | "Failed to enable power supplies\n"); |
| 1050 | fsleep(T_POWERUP_US); | 1130 | fsleep(T_POWERUP_US); |
| 1051 | 1131 | ||
| 1052 | if (st->chip_info->external_ref_only) { | 1132 | if (st->chip_info->adaq_internal_ref_only) { |
| 1053 | ret = devm_regulator_get_enable_read_voltage(&spi->dev, | 1133 | /* |
| 1054 | "refin"); | 1134 | * ADAQ chips use fixed internal reference but still |
| 1135 | * require a specific reference supply to power it. | ||
| 1136 | * "refin" is already enabled with other power supplies | ||
| 1137 | * in bulk_get_enable(). | ||
| 1138 | */ | ||
| 1139 | |||
| 1140 | st->vref_mv = ADAQ4380_INTERNAL_REF_MV; | ||
| 1141 | |||
| 1142 | /* these chips don't have a register bit for this */ | ||
| 1143 | external_ref_en = false; | ||
| 1144 | } else if (st->chip_info->external_ref_only) { | ||
| 1145 | ret = devm_regulator_get_enable_read_voltage(dev, "refin"); | ||
| 1055 | if (ret < 0) | 1146 | if (ret < 0) |
| 1056 | return dev_err_probe(&spi->dev, ret, | 1147 | return dev_err_probe(dev, ret, |
| 1057 | "Failed to get refin regulator\n"); | 1148 | "Failed to get refin regulator\n"); |
| 1058 | 1149 | ||
| 1059 | st->vref_mv = ret / 1000; | 1150 | st->vref_mv = ret / 1000; |
| @@ -1065,10 +1156,9 @@ static int ad7380_probe(struct spi_device *spi) · 5 unmodified lines | |||
| 1065 | * If there is no REFIO supply, then it means that we are using | 1156 | * If there is no REFIO supply, then it means that we are using |
| 1066 | * the internal reference, otherwise REFIO is reference voltage. | 1157 | * the internal reference, otherwise REFIO is reference voltage. |
| 1067 | */ | 1158 | */ |
| 1068 | ret = devm_regulator_get_enable_read_voltage(&spi->dev, | 1159 | ret = devm_regulator_get_enable_read_voltage(dev, "refio"); |
| 1069 | "refio"); | ||
| 1070 | if (ret < 0 && ret != -ENODEV) | 1160 | if (ret < 0 && ret != -ENODEV) |
| 1071 | return dev_err_probe(&spi->dev, ret, | 1161 | return dev_err_probe(dev, ret, |
| 1072 | "Failed to get refio regulator\n"); | 1162 | "Failed to get refio regulator\n"); |
| 1073 | 1163 | ||
| 1074 | external_ref_en = ret != -ENODEV; | 1164 | external_ref_en = ret != -ENODEV; |
| @@ -1076,7 +1166,7 @@ static int ad7380_probe(struct spi_device *spi) · 1 unmodified line | |||
| 1076 | } | 1166 | } |
| 1077 | 1167 | ||
| 1078 | if (st->chip_info->num_vcm_supplies > ARRAY_SIZE(st->vcm_mv)) | 1168 | if (st->chip_info->num_vcm_supplies > ARRAY_SIZE(st->vcm_mv)) |
| 1079 | return dev_err_probe(&spi->dev, -EINVAL, | 1169 | return dev_err_probe(dev, -EINVAL, |
| 1080 | "invalid number of VCM supplies\n"); | 1170 | "invalid number of VCM supplies\n"); |
| 1081 | 1171 | ||
| 1082 | /* | 1172 | /* |
| @@ -1086,18 +1176,54 @@ static int ad7380_probe(struct spi_device *spi) · 3 unmodified lines | |||
| 1086 | for (i = 0; i < st->chip_info->num_vcm_supplies; i++) { | 1176 | for (i = 0; i < st->chip_info->num_vcm_supplies; i++) { |
| 1087 | const char *vcm = st->chip_info->vcm_supplies[i]; | 1177 | const char *vcm = st->chip_info->vcm_supplies[i]; |
| 1088 | 1178 | ||
| 1089 | ret = devm_regulator_get_enable_read_voltage(&spi->dev, vcm); | 1179 | ret = devm_regulator_get_enable_read_voltage(dev, vcm); |
| 1090 | if (ret < 0) | 1180 | if (ret < 0) |
| 1091 | return dev_err_probe(&spi->dev, ret, | 1181 | return dev_err_probe(dev, ret, |
| 1092 | "Failed to get %s regulator\n", | 1182 | "Failed to get %s regulator\n", |
| 1093 | vcm); | 1183 | vcm); |
| 1094 | 1184 | ||
| 1095 | st->vcm_mv[i] = ret / 1000; | 1185 | st->vcm_mv[i] = ret / 1000; |
| 1096 | } | 1186 | } |
| 1097 | 1187 | ||
| 1098 | st->regmap = devm_regmap_init(&spi->dev, NULL, st, &ad7380_regmap_config); | 1188 | for (i = 0; i < MAX_NUM_CHANNELS; i++) |
| 1189 | st->gain_milli[i] = AD7380_DEFAULT_GAIN_MILLI; | ||
| 1190 | |||
| 1191 | if (st->chip_info->has_hardware_gain) { | ||
| 1192 | device_for_each_child_node_scoped(dev, node) { | ||
| 1193 | unsigned int channel, gain; | ||
| 1194 | int gain_idx; | ||
| 1195 | |||
| 1196 | ret = fwnode_property_read_u32(node, "reg", &channel); | ||
| 1197 | if (ret) | ||
| 1198 | return dev_err_probe(dev, ret, | ||
| 1199 | "Failed to read reg property\n"); | ||
| 1200 | |||
| 1201 | if (channel >= st->chip_info->num_channels - 1) | ||
| 1202 | return dev_err_probe(dev, -EINVAL, | ||
| 1203 | "Invalid channel number %i\n", | ||
| 1204 | channel); | ||
| 1205 | |||
| 1206 | ret = fwnode_property_read_u32(node, "adi,gain-milli", | ||
| 1207 | &gain); | ||
| 1208 | if (ret && ret != -EINVAL) | ||
| 1209 | return dev_err_probe(dev, ret, | ||
| 1210 | "Failed to read gain for channel %i\n", | ||
| 1211 | channel); | ||
| 1212 | if (ret != -EINVAL) { | ||
| 1213 | /* | ||
| 1214 | * Match gain value from dt to one of supported | ||
| 1215 | * gains | ||
| 1216 | */ | ||
| 1217 | gain_idx = find_closest(gain, ad7380_gains, | ||
| 1218 | ARRAY_SIZE(ad7380_gains)); | ||
| 1219 | st->gain_milli[channel] = ad7380_gains[gain_idx]; | ||
| 1220 | } | ||
| 1221 | } | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | st->regmap = devm_regmap_init(dev, NULL, st, &ad7380_regmap_config); | ||
| 1099 | if (IS_ERR(st->regmap)) | 1225 | if (IS_ERR(st->regmap)) |
| 1100 | return dev_err_probe(&spi->dev, PTR_ERR(st->regmap), | 1226 | return dev_err_probe(dev, PTR_ERR(st->regmap), |
| 1101 | "failed to allocate register map\n"); | 1227 | "failed to allocate register map\n"); |
| 1102 | 1228 | ||
| 1103 | /* | 1229 | /* |
| @@ -1148,7 +1274,7 @@ static int ad7380_probe(struct spi_device *spi) · 44 unmodified lines | |||
| 1148 | indio_dev->modes = INDIO_DIRECT_MODE; | 1274 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 1149 | indio_dev->available_scan_masks = st->chip_info->available_scan_masks; | 1275 | indio_dev->available_scan_masks = st->chip_info->available_scan_masks; |
| 1150 | 1276 | ||
| 1151 | ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, | 1277 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, |
| 1152 | iio_pollfunc_store_time, | 1278 | iio_pollfunc_store_time, |
| 1153 | ad7380_trigger_handler, | 1279 | ad7380_trigger_handler, |
| 1154 | &ad7380_buffer_setup_ops); | 1280 | &ad7380_buffer_setup_ops); |
| @@ -1159,7 +1285,7 @@ static int ad7380_probe(struct spi_device *spi) · 4 unmodified lines | |||
| 1159 | if (ret) | 1285 | if (ret) |
| 1160 | return ret; | 1286 | return ret; |
| 1161 | 1287 | ||
| 1162 | return devm_iio_device_register(&spi->dev, indio_dev); | 1288 | return devm_iio_device_register(dev, indio_dev); |
| 1163 | } | 1289 | } |
| 1164 | 1290 | ||
| 1165 | static const struct of_device_id ad7380_of_match_table[] = { | 1291 | static const struct of_device_id ad7380_of_match_table[] = { |
| @@ -1177,6 +1303,8 @@ static const struct of_device_id ad7380_of_match_table[] = { · 11 unmodified lines | |||
| 1177 | { .compatible = "adi,ad7386-4", .data = &ad7386_4_chip_info }, | 1303 | { .compatible = "adi,ad7386-4", .data = &ad7386_4_chip_info }, |
| 1178 | { .compatible = "adi,ad7387-4", .data = &ad7387_4_chip_info }, | 1304 | { .compatible = "adi,ad7387-4", .data = &ad7387_4_chip_info }, |
| 1179 | { .compatible = "adi,ad7388-4", .data = &ad7388_4_chip_info }, | 1305 | { .compatible = "adi,ad7388-4", .data = &ad7388_4_chip_info }, |
| 1306 | { .compatible = "adi,adaq4370-4", .data = &adaq4370_4_chip_info }, | ||
| 1307 | { .compatible = "adi,adaq4380-4", .data = &adaq4380_4_chip_info }, | ||
| 1180 | { } | 1308 | { } |
| 1181 | }; | 1309 | }; |
| 1182 | 1310 | ||
| @@ -1195,6 +1323,8 @@ static const struct spi_device_id ad7380_id_table[] = { · 12 unmodified lines | |||
| 1195 | { "ad7386-4", (kernel_ulong_t)&ad7386_4_chip_info }, | 1323 | { "ad7386-4", (kernel_ulong_t)&ad7386_4_chip_info }, |
| 1196 | { "ad7387-4", (kernel_ulong_t)&ad7387_4_chip_info }, | 1324 | { "ad7387-4", (kernel_ulong_t)&ad7387_4_chip_info }, |
| 1197 | { "ad7388-4", (kernel_ulong_t)&ad7388_4_chip_info }, | 1325 | { "ad7388-4", (kernel_ulong_t)&ad7388_4_chip_info }, |
| 1326 | { "adaq4370-4", (kernel_ulong_t)&adaq4370_4_chip_info }, | ||
| 1327 | { "adaq4380-4", (kernel_ulong_t)&adaq4380_4_chip_info }, | ||
| 1198 | { } | 1328 | { } |
| 1199 | }; | 1329 | }; |
| 1200 | MODULE_DEVICE_TABLE(spi, ad7380_id_table); | 1330 | MODULE_DEVICE_TABLE(spi, ad7380_id_table); |
| @@ -13,14 +13,17 @@ · 12 unmodified lines | |||
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/property.h> | 15 | #include <linux/property.h> |
| 16 | #include <linux/pwm.h> | ||
| 16 | #include <linux/regulator/consumer.h> | 17 | #include <linux/regulator/consumer.h> |
| 17 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
| 18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 19 | #include <linux/sysfs.h> | 20 | #include <linux/sysfs.h> |
| 21 | #include <linux/units.h> | ||
| 20 | #include <linux/util_macros.h> | 22 | #include <linux/util_macros.h> |
| 21 | 23 | ||
| 22 | #include <linux/iio/iio.h> | 24 | #include <linux/iio/backend.h> |
| 23 | #include <linux/iio/buffer.h> | 25 | #include <linux/iio/buffer.h> |
| 26 | #include <linux/iio/iio.h> | ||
| 24 | #include <linux/iio/sysfs.h> | 27 | #include <linux/iio/sysfs.h> |
| 25 | #include <linux/iio/trigger.h> | 28 | #include <linux/iio/trigger.h> |
| 26 | #include <linux/iio/triggered_buffer.h> | 29 | #include <linux/iio/triggered_buffer.h> |
| @@ -30,15 +33,52 @@ · 3 unmodified lines | |||
| 30 | 33 | ||
| 31 | /* | 34 | /* |
| 32 | * Scales are computed as 5000/32768 and 10000/32768 respectively, | 35 | * Scales are computed as 5000/32768 and 10000/32768 respectively, |
| 33 | * so that when applied to the raw values they provide mV values | 36 | * so that when applied to the raw values they provide mV values. |
| 37 | * The scale arrays are kept as IIO_VAL_INT_PLUS_MICRO, so index | ||
| 38 | * X is the integer part and X + 1 is the fractional part. | ||
| 34 | */ | 39 | */ |
| 35 | static const unsigned int ad7606_scale_avail[2] = { | 40 | static const unsigned int ad7606_16bit_hw_scale_avail[2][2] = { |
| 36 | 152588, 305176 | 41 | { 0, 152588 }, { 0, 305176 } |
| 42 | }; | ||
| 43 | |||
| 44 | static const unsigned int ad7606_18bit_hw_scale_avail[2][2] = { | ||
| 45 | { 0, 38147 }, { 0, 76294 } | ||
| 46 | }; | ||
| 47 | |||
| 48 | static const unsigned int ad7606c_16bit_single_ended_unipolar_scale_avail[3][2] = { | ||
| 49 | { 0, 76294 }, { 0, 152588 }, { 0, 190735 } | ||
| 50 | }; | ||
| 51 | |||
| 52 | static const unsigned int ad7606c_16bit_single_ended_bipolar_scale_avail[5][2] = { | ||
| 53 | { 0, 76294 }, { 0, 152588 }, { 0, 190735 }, { 0, 305176 }, { 0, 381470 } | ||
| 54 | }; | ||
| 55 | |||
| 56 | static const unsigned int ad7606c_16bit_differential_bipolar_scale_avail[4][2] = { | ||
| 57 | { 0, 152588 }, { 0, 305176 }, { 0, 381470 }, { 0, 610352 } | ||
| 58 | }; | ||
| 59 | |||
| 60 | static const unsigned int ad7606c_18bit_single_ended_unipolar_scale_avail[3][2] = { | ||
| 61 | { 0, 19073 }, { 0, 38147 }, { 0, 47684 } | ||
| 62 | }; | ||
| 63 | |||
| 64 | static const unsigned int ad7606c_18bit_single_ended_bipolar_scale_avail[5][2] = { | ||
| 65 | { 0, 19073 }, { 0, 38147 }, { 0, 47684 }, { 0, 76294 }, { 0, 95367 } | ||
| 37 | }; | 66 | }; |
| 38 | 67 | ||
| 68 | static const unsigned int ad7606c_18bit_differential_bipolar_scale_avail[4][2] = { | ||
| 69 | { 0, 38147 }, { 0, 76294 }, { 0, 95367 }, { 0, 152588 } | ||
| 70 | }; | ||
| 71 | |||
| 72 | static const unsigned int ad7606_16bit_sw_scale_avail[3][2] = { | ||
| 73 | { 0, 76293 }, { 0, 152588 }, { 0, 305176 } | ||
| 74 | }; | ||
| 39 | 75 | ||
| 40 | static const unsigned int ad7616_sw_scale_avail[3] = { | 76 | static const unsigned int ad7607_hw_scale_avail[2][2] = { |
| 41 | 76293, 152588, 305176 | 77 | { 0, 610352 }, { 1, 220703 } |
| 78 | }; | ||
| 79 | |||
| 80 | static const unsigned int ad7609_hw_scale_avail[2][2] = { | ||
| 81 | { 0, 152588 }, { 0, 305176 } | ||
| 42 | }; | 82 | }; |
| 43 | 83 | ||
| 44 | static const unsigned int ad7606_oversampling_avail[7] = { | 84 | static const unsigned int ad7606_oversampling_avail[7] = { |
| @@ -49,6 +89,227 @@ static const unsigned int ad7616_oversampling_avail[8] = { · 4 unmodified lines | |||
| 49 | 1, 2, 4, 8, 16, 32, 64, 128, | 89 | 1, 2, 4, 8, 16, 32, 64, 128, |
| 50 | }; | 90 | }; |
| 51 | 91 | ||
| 92 | static const struct iio_chan_spec ad7605_channels[] = { | ||
| 93 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
| 94 | AD7605_CHANNEL(0), | ||
| 95 | AD7605_CHANNEL(1), | ||
| 96 | AD7605_CHANNEL(2), | ||
| 97 | AD7605_CHANNEL(3), | ||
| 98 | }; | ||
| 99 | |||
| 100 | static const struct iio_chan_spec ad7606_channels_16bit[] = { | ||
| 101 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
| 102 | AD7606_CHANNEL(0, 16), | ||
| 103 | AD7606_CHANNEL(1, 16), | ||
| 104 | AD7606_CHANNEL(2, 16), | ||
| 105 | AD7606_CHANNEL(3, 16), | ||
| 106 | AD7606_CHANNEL(4, 16), | ||
| 107 | AD7606_CHANNEL(5, 16), | ||
| 108 | AD7606_CHANNEL(6, 16), | ||
| 109 | AD7606_CHANNEL(7, 16), | ||
| 110 | }; | ||
| 111 | |||
| 112 | static const struct iio_chan_spec ad7606_channels_18bit[] = { | ||
| 113 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
| 114 | AD7606_CHANNEL(0, 18), | ||
| 115 | AD7606_CHANNEL(1, 18), | ||
| 116 | AD7606_CHANNEL(2, 18), | ||
| 117 | AD7606_CHANNEL(3, 18), | ||
| 118 | AD7606_CHANNEL(4, 18), | ||
| 119 | AD7606_CHANNEL(5, 18), | ||
| 120 | AD7606_CHANNEL(6, 18), | ||
| 121 | AD7606_CHANNEL(7, 18), | ||
| 122 | }; | ||
| 123 | |||
| 124 | static const struct iio_chan_spec ad7607_channels[] = { | ||
| 125 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
| 126 | AD7606_CHANNEL(0, 14), | ||
| 127 | AD7606_CHANNEL(1, 14), | ||
| 128 | AD7606_CHANNEL(2, 14), | ||
| 129 | AD7606_CHANNEL(3, 14), | ||
| 130 | AD7606_CHANNEL(4, 14), | ||
| 131 | AD7606_CHANNEL(5, 14), | ||
| 132 | AD7606_CHANNEL(6, 14), | ||
| 133 | AD7606_CHANNEL(7, 14), | ||
| 134 | }; | ||
| 135 | |||
| 136 | static const struct iio_chan_spec ad7608_channels[] = { | ||
| 137 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
| 138 | AD7606_CHANNEL(0, 18), | ||
| 139 | AD7606_CHANNEL(1, 18), | ||
| 140 | AD7606_CHANNEL(2, 18), | ||
| 141 | AD7606_CHANNEL(3, 18), | ||
| 142 | AD7606_CHANNEL(4, 18), | ||
| 143 | AD7606_CHANNEL(5, 18), | ||
| 144 | AD7606_CHANNEL(6, 18), | ||
| 145 | AD7606_CHANNEL(7, 18), | ||
| 146 | }; | ||
| 147 | |||
| 148 | /* | ||
| 149 | * The current assumption that this driver makes for AD7616, is that it's | ||
| 150 | * working in Hardware Mode with Serial, Burst and Sequencer modes activated. | ||
| 151 | * To activate them, following pins must be pulled high: | ||
| 152 | * -SER/PAR | ||
| 153 | * -SEQEN | ||
| 154 | * And following pins must be pulled low: | ||
| 155 | * -WR/BURST | ||
| 156 | * -DB4/SER1W | ||
| 157 | */ | ||
| 158 | static const struct iio_chan_spec ad7616_channels[] = { | ||
| 159 | IIO_CHAN_SOFT_TIMESTAMP(16), | ||
| 160 | AD7606_CHANNEL(0, 16), | ||
| 161 | AD7606_CHANNEL(1, 16), | ||
| 162 | AD7606_CHANNEL(2, 16), | ||
| 163 | AD7606_CHANNEL(3, 16), | ||
| 164 | AD7606_CHANNEL(4, 16), | ||
| 165 | AD7606_CHANNEL(5, 16), | ||
| 166 | AD7606_CHANNEL(6, 16), | ||
| 167 | AD7606_CHANNEL(7, 16), | ||
| 168 | AD7606_CHANNEL(8, 16), | ||
| 169 | AD7606_CHANNEL(9, 16), | ||
| 170 | AD7606_CHANNEL(10, 16), | ||
| 171 | AD7606_CHANNEL(11, 16), | ||
| 172 | AD7606_CHANNEL(12, 16), | ||
| 173 | AD7606_CHANNEL(13, 16), | ||
| 174 | AD7606_CHANNEL(14, 16), | ||
| 175 | AD7606_CHANNEL(15, 16), | ||
| 176 | }; | ||
| 177 | |||
| 178 | static int ad7606c_18bit_chan_scale_setup(struct ad7606_state *st, | ||
| 179 | struct iio_chan_spec *chan, int ch); | ||
| 180 | static int ad7606c_16bit_chan_scale_setup(struct ad7606_state *st, | ||
| 181 | struct iio_chan_spec *chan, int ch); | ||
| 182 | static int ad7606_16bit_chan_scale_setup(struct ad7606_state *st, | ||
| 183 | struct iio_chan_spec *chan, int ch); | ||
| 184 | static int ad7607_chan_scale_setup(struct ad7606_state *st, | ||
| 185 | struct iio_chan_spec *chan, int ch); | ||
| 186 | static int ad7608_chan_scale_setup(struct ad7606_state *st, | ||
| 187 | struct iio_chan_spec *chan, int ch); | ||
| 188 | static int ad7609_chan_scale_setup(struct ad7606_state *st, | ||
| 189 | struct iio_chan_spec *chan, int ch); | ||
| 190 | |||
| 191 | const struct ad7606_chip_info ad7605_4_info = { | ||
| 192 | .channels = ad7605_channels, | ||
| 193 | .name = "ad7605-4", | ||
| 194 | .num_adc_channels = 4, | ||
| 195 | .num_channels = 5, | ||
| 196 | .scale_setup_cb = ad7606_16bit_chan_scale_setup, | ||
| 197 | }; | ||
| 198 | EXPORT_SYMBOL_NS_GPL(ad7605_4_info, IIO_AD7606); | ||
| 199 | |||
| 200 | const struct ad7606_chip_info ad7606_8_info = { | ||
| 201 | .channels = ad7606_channels_16bit, | ||
| 202 | .name = "ad7606-8", | ||
| 203 | .num_adc_channels = 8, | ||
| 204 | .num_channels = 9, | ||
| 205 | .oversampling_avail = ad7606_oversampling_avail, | ||
| 206 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | ||
| 207 | .scale_setup_cb = ad7606_16bit_chan_scale_setup, | ||
| 208 | }; | ||
| 209 | EXPORT_SYMBOL_NS_GPL(ad7606_8_info, IIO_AD7606); | ||
| 210 | |||
| 211 | const struct ad7606_chip_info ad7606_6_info = { | ||
| 212 | .channels = ad7606_channels_16bit, | ||
| 213 | .name = "ad7606-6", | ||
| 214 | .num_adc_channels = 6, | ||
| 215 | .num_channels = 7, | ||
| 216 | .oversampling_avail = ad7606_oversampling_avail, | ||
| 217 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | ||
| 218 | .scale_setup_cb = ad7606_16bit_chan_scale_setup, | ||
| 219 | }; | ||
| 220 | EXPORT_SYMBOL_NS_GPL(ad7606_6_info, IIO_AD7606); | ||
| 221 | |||
| 222 | const struct ad7606_chip_info ad7606_4_info = { | ||
| 223 | .channels = ad7606_channels_16bit, | ||
| 224 | .name = "ad7606-4", | ||
| 225 | .num_adc_channels = 4, | ||
| 226 | .num_channels = 5, | ||
| 227 | .oversampling_avail = ad7606_oversampling_avail, | ||
| 228 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | ||
| 229 | .scale_setup_cb = ad7606_16bit_chan_scale_setup, | ||
| 230 | }; | ||
| 231 | EXPORT_SYMBOL_NS_GPL(ad7606_4_info, IIO_AD7606); | ||
| 232 | |||
| 233 | const struct ad7606_chip_info ad7606b_info = { | ||
| 234 | .channels = ad7606_channels_16bit, | ||
| 235 | .max_samplerate = 800 * KILO, | ||
| 236 | .name = "ad7606b", | ||
| 237 | .num_adc_channels = 8, | ||
| 238 | .num_channels = 9, | ||
| 239 | .oversampling_avail = ad7606_oversampling_avail, | ||
| 240 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | ||
| 241 | .scale_setup_cb = ad7606_16bit_chan_scale_setup, | ||
| 242 | }; | ||
| 243 | EXPORT_SYMBOL_NS_GPL(ad7606b_info, IIO_AD7606); | ||
| 244 | |||
| 245 | const struct ad7606_chip_info ad7606c_16_info = { | ||
| 246 | .channels = ad7606_channels_16bit, | ||
| 247 | .name = "ad7606c16", | ||
| 248 | .num_adc_channels = 8, | ||
| 249 | .num_channels = 9, | ||
| 250 | .oversampling_avail = ad7606_oversampling_avail, | ||
| 251 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | ||
| 252 | .scale_setup_cb = ad7606c_16bit_chan_scale_setup, | ||
| 253 | }; | ||
| 254 | EXPORT_SYMBOL_NS_GPL(ad7606c_16_info, IIO_AD7606); | ||
| 255 | |||
| 256 | const struct ad7606_chip_info ad7607_info = { | ||
| 257 | .channels = ad7607_channels, | ||
| 258 | .name = "ad7607", | ||
| 259 | .num_adc_channels = 8, | ||
| 260 | .num_channels = 9, | ||
| 261 | .oversampling_avail = ad7606_oversampling_avail, | ||
| 262 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | ||
| 263 | .scale_setup_cb = ad7607_chan_scale_setup, | ||
| 264 | }; | ||
| 265 | EXPORT_SYMBOL_NS_GPL(ad7607_info, IIO_AD7606); | ||
| 266 | |||
| 267 | const struct ad7606_chip_info ad7608_info = { | ||
| 268 | .channels = ad7608_channels, | ||
| 269 | .name = "ad7608", | ||
| 270 | .num_adc_channels = 8, | ||
| 271 | .num_channels = 9, | ||
| 272 | .oversampling_avail = ad7606_oversampling_avail, | ||
| 273 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | ||
| 274 | .scale_setup_cb = ad7608_chan_scale_setup, | ||
| 275 | }; | ||
| 276 | EXPORT_SYMBOL_NS_GPL(ad7608_info, IIO_AD7606); | ||
| 277 | |||
| 278 | const struct ad7606_chip_info ad7609_info = { | ||
| 279 | .channels = ad7608_channels, | ||
| 280 | .name = "ad7609", | ||
| 281 | .num_adc_channels = 8, | ||
| 282 | .num_channels = 9, | ||
| 283 | .oversampling_avail = ad7606_oversampling_avail, | ||
| 284 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | ||
| 285 | .scale_setup_cb = ad7609_chan_scale_setup, | ||
| 286 | }; | ||
| 287 | EXPORT_SYMBOL_NS_GPL(ad7609_info, IIO_AD7606); | ||
| 288 | |||
| 289 | const struct ad7606_chip_info ad7606c_18_info = { | ||
| 290 | .channels = ad7606_channels_18bit, | ||
| 291 | .name = "ad7606c18", | ||
| 292 | .num_adc_channels = 8, | ||
| 293 | .num_channels = 9, | ||
| 294 | .oversampling_avail = ad7606_oversampling_avail, | ||
| 295 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | ||
| 296 | .scale_setup_cb = ad7606c_18bit_chan_scale_setup, | ||
| 297 | }; | ||
| 298 | EXPORT_SYMBOL_NS_GPL(ad7606c_18_info, IIO_AD7606); | ||
| 299 | |||
| 300 | const struct ad7606_chip_info ad7616_info = { | ||
| 301 | .channels = ad7616_channels, | ||
| 302 | .init_delay_ms = 15, | ||
| 303 | .name = "ad7616", | ||
| 304 | .num_adc_channels = 16, | ||
| 305 | .num_channels = 17, | ||
| 306 | .oversampling_avail = ad7616_oversampling_avail, | ||
| 307 | .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail), | ||
| 308 | .os_req_reset = true, | ||
| 309 | .scale_setup_cb = ad7606_16bit_chan_scale_setup, | ||
| 310 | }; | ||
| 311 | EXPORT_SYMBOL_NS_GPL(ad7616_info, IIO_AD7606); | ||
| 312 | |||
| 52 | int ad7606_reset(struct ad7606_state *st) | 313 | int ad7606_reset(struct ad7606_state *st) |
| 53 | { | 314 | { |
| 54 | if (st->gpio_reset) { | 315 | if (st->gpio_reset) { |
| @@ -62,6 +323,228 @@ int ad7606_reset(struct ad7606_state *st) · 7 unmodified lines | |||
| 62 | } | 323 | } |
| 63 | EXPORT_SYMBOL_NS_GPL(ad7606_reset, IIO_AD7606); | 324 | EXPORT_SYMBOL_NS_GPL(ad7606_reset, IIO_AD7606); |
| 64 | 325 | ||
| 326 | static int ad7606_16bit_chan_scale_setup(struct ad7606_state *st, | ||
| 327 | struct iio_chan_spec *chan, int ch) | ||
| 328 | { | ||
| 329 | struct ad7606_chan_scale *cs = &st->chan_scales[ch]; | ||
| 330 | |||
| 331 | if (!st->sw_mode_en) { | ||
| 332 | /* tied to logic low, analog input range is +/- 5V */ | ||
| 333 | cs->range = 0; | ||
| 334 | cs->scale_avail = ad7606_16bit_hw_scale_avail; | ||
| 335 | cs->num_scales = ARRAY_SIZE(ad7606_16bit_hw_scale_avail); | ||
| 336 | return 0; | ||
| 337 | } | ||
| 338 | |||
| 339 | /* Scale of 0.076293 is only available in sw mode */ | ||
| 340 | /* After reset, in software mode, ±10 V is set by default */ | ||
| 341 | cs->range = 2; | ||
| 342 | cs->scale_avail = ad7606_16bit_sw_scale_avail; | ||
| 343 | cs->num_scales = ARRAY_SIZE(ad7606_16bit_sw_scale_avail); | ||
| 344 | |||
| 345 | return 0; | ||
| 346 | } | ||
| 347 | |||
| 348 | static int ad7606_get_chan_config(struct ad7606_state *st, int ch, | ||
| 349 | bool *bipolar, bool *differential) | ||
| 350 | { | ||
| 351 | unsigned int num_channels = st->chip_info->num_channels - 1; | ||
| 352 | struct device *dev = st->dev; | ||
| 353 | int ret; | ||
| 354 | |||
| 355 | *bipolar = false; | ||
| 356 | *differential = false; | ||
| 357 | |||
| 358 | device_for_each_child_node_scoped(dev, child) { | ||
| 359 | u32 pins[2]; | ||
| 360 | int reg; | ||
| 361 | |||
| 362 | ret = fwnode_property_read_u32(child, "reg", ®); | ||
| 363 | if (ret) | ||
| 364 | continue; | ||
| 365 | |||
| 366 | /* channel number (here) is from 1 to num_channels */ | ||
| 367 | if (reg == 0 || reg > num_channels) { | ||
| 368 | dev_warn(dev, | ||
| 369 | "Invalid channel number (ignoring): %d\n", reg); | ||
| 370 | continue; | ||
| 371 | } | ||
| 372 | |||
| 373 | if (reg != (ch + 1)) | ||
| 374 | continue; | ||
| 375 | |||
| 376 | *bipolar = fwnode_property_read_bool(child, "bipolar"); | ||
| 377 | |||
| 378 | ret = fwnode_property_read_u32_array(child, "diff-channels", | ||
| 379 | pins, ARRAY_SIZE(pins)); | ||
| 380 | /* Channel is differential, if pins are the same as 'reg' */ | ||
| 381 | if (ret == 0 && (pins[0] != reg || pins[1] != reg)) { | ||
| 382 | dev_err(dev, | ||
| 383 | "Differential pins must be the same as 'reg'"); | ||
| 384 | return -EINVAL; | ||
| 385 | } | ||
| 386 | |||
| 387 | *differential = (ret == 0); | ||
| 388 | |||
| 389 | if (*differential && !*bipolar) { | ||
| 390 | dev_err(dev, | ||
| 391 | "'bipolar' must be added for diff channel %d\n", | ||
| 392 | reg); | ||
| 393 | return -EINVAL; | ||
| 394 | } | ||
| 395 | |||
| 396 | return 0; | ||
| 397 | } | ||
| 398 | |||
| 399 | return 0; | ||
| 400 | } | ||
| 401 | |||
| 402 | static int ad7606c_18bit_chan_scale_setup(struct ad7606_state *st, | ||
| 403 | struct iio_chan_spec *chan, int ch) | ||
| 404 | { | ||
| 405 | struct ad7606_chan_scale *cs = &st->chan_scales[ch]; | ||
| 406 | bool bipolar, differential; | ||
| 407 | int ret; | ||
| 408 | |||
| 409 | if (!st->sw_mode_en) { | ||
| 410 | cs->range = 0; | ||
| 411 | cs->scale_avail = ad7606_18bit_hw_scale_avail; | ||
| 412 | cs->num_scales = ARRAY_SIZE(ad7606_18bit_hw_scale_avail); | ||
| 413 | return 0; | ||
| 414 | } | ||
| 415 | |||
| 416 | ret = ad7606_get_chan_config(st, ch, &bipolar, &differential); | ||
| 417 | if (ret) | ||
| 418 | return ret; | ||
| 419 | |||
| 420 | if (differential) { | ||
| 421 | cs->scale_avail = ad7606c_18bit_differential_bipolar_scale_avail; | ||
| 422 | cs->num_scales = | ||
| 423 | ARRAY_SIZE(ad7606c_18bit_differential_bipolar_scale_avail); | ||
| 424 | /* Bipolar differential ranges start at 8 (b1000) */ | ||
| 425 | cs->reg_offset = 8; | ||
| 426 | cs->range = 1; | ||
| 427 | chan->differential = 1; | ||
| 428 | chan->channel2 = chan->channel; | ||
| 429 | |||
| 430 | return 0; | ||
| 431 | } | ||
| 432 | |||
| 433 | chan->differential = 0; | ||
| 434 | |||
| 435 | if (bipolar) { | ||
| 436 | cs->scale_avail = ad7606c_18bit_single_ended_bipolar_scale_avail; | ||
| 437 | cs->num_scales = | ||
| 438 | ARRAY_SIZE(ad7606c_18bit_single_ended_bipolar_scale_avail); | ||
| 439 | /* Bipolar single-ended ranges start at 0 (b0000) */ | ||
| 440 | cs->reg_offset = 0; | ||
| 441 | cs->range = 3; | ||
| 442 | chan->scan_type.sign = 's'; | ||
| 443 | |||
| 444 | return 0; | ||
| 445 | } | ||
| 446 | |||
| 447 | cs->scale_avail = ad7606c_18bit_single_ended_unipolar_scale_avail; | ||
| 448 | cs->num_scales = | ||
| 449 | ARRAY_SIZE(ad7606c_18bit_single_ended_unipolar_scale_avail); | ||
| 450 | /* Unipolar single-ended ranges start at 5 (b0101) */ | ||
| 451 | cs->reg_offset = 5; | ||
| 452 | cs->range = 1; | ||
| 453 | chan->scan_type.sign = 'u'; | ||
| 454 | |||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 458 | static int ad7606c_16bit_chan_scale_setup(struct ad7606_state *st, | ||
| 459 | struct iio_chan_spec *chan, int ch) | ||
| 460 | { | ||
| 461 | struct ad7606_chan_scale *cs = &st->chan_scales[ch]; | ||
| 462 | bool bipolar, differential; | ||
| 463 | int ret; | ||
| 464 | |||
| 465 | if (!st->sw_mode_en) { | ||
| 466 | cs->range = 0; | ||
| 467 | cs->scale_avail = ad7606_16bit_hw_scale_avail; | ||
| 468 | cs->num_scales = ARRAY_SIZE(ad7606_16bit_hw_scale_avail); | ||
| 469 | return 0; | ||
| 470 | } | ||
| 471 | |||
| 472 | ret = ad7606_get_chan_config(st, ch, &bipolar, &differential); | ||
| 473 | if (ret) | ||
| 474 | return ret; | ||
| 475 | |||
| 476 | if (differential) { | ||
| 477 | cs->scale_avail = ad7606c_16bit_differential_bipolar_scale_avail; | ||
| 478 | cs->num_scales = | ||
| 479 | ARRAY_SIZE(ad7606c_16bit_differential_bipolar_scale_avail); | ||
| 480 | /* Bipolar differential ranges start at 8 (b1000) */ | ||
| 481 | cs->reg_offset = 8; | ||
| 482 | cs->range = 1; | ||
| 483 | chan->differential = 1; | ||
| 484 | chan->channel2 = chan->channel; | ||
| 485 | chan->scan_type.sign = 's'; | ||
| 486 | |||
| 487 | return 0; | ||
| 488 | } | ||
| 489 | |||
| 490 | chan->differential = 0; | ||
| 491 | |||
| 492 | if (bipolar) { | ||
| 493 | cs->scale_avail = ad7606c_16bit_single_ended_bipolar_scale_avail; | ||
| 494 | cs->num_scales = | ||
| 495 | ARRAY_SIZE(ad7606c_16bit_single_ended_bipolar_scale_avail); | ||
| 496 | /* Bipolar single-ended ranges start at 0 (b0000) */ | ||
| 497 | cs->reg_offset = 0; | ||
| 498 | cs->range = 3; | ||
| 499 | chan->scan_type.sign = 's'; | ||
| 500 | |||
| 501 | return 0; | ||
| 502 | } | ||
| 503 | |||
| 504 | cs->scale_avail = ad7606c_16bit_single_ended_unipolar_scale_avail; | ||
| 505 | cs->num_scales = | ||
| 506 | ARRAY_SIZE(ad7606c_16bit_single_ended_unipolar_scale_avail); | ||
| 507 | /* Unipolar single-ended ranges start at 5 (b0101) */ | ||
| 508 | cs->reg_offset = 5; | ||
| 509 | cs->range = 1; | ||
| 510 | chan->scan_type.sign = 'u'; | ||
| 511 | |||
| 512 | return 0; | ||
| 513 | } | ||
| 514 | |||
| 515 | static int ad7607_chan_scale_setup(struct ad7606_state *st, | ||
| 516 | struct iio_chan_spec *chan, int ch) | ||
| 517 | { | ||
| 518 | struct ad7606_chan_scale *cs = &st->chan_scales[ch]; | ||
| 519 | |||
| 520 | cs->range = 0; | ||
| 521 | cs->scale_avail = ad7607_hw_scale_avail; | ||
| 522 | cs->num_scales = ARRAY_SIZE(ad7607_hw_scale_avail); | ||
| 523 | return 0; | ||
| 524 | } | ||
| 525 | |||
| 526 | static int ad7608_chan_scale_setup(struct ad7606_state *st, | ||
| 527 | struct iio_chan_spec *chan, int ch) | ||
| 528 | { | ||
| 529 | struct ad7606_chan_scale *cs = &st->chan_scales[ch]; | ||
| 530 | |||
| 531 | cs->range = 0; | ||
| 532 | cs->scale_avail = ad7606_18bit_hw_scale_avail; | ||
| 533 | cs->num_scales = ARRAY_SIZE(ad7606_18bit_hw_scale_avail); | ||
| 534 | return 0; | ||
| 535 | } | ||
| 536 | |||
| 537 | static int ad7609_chan_scale_setup(struct ad7606_state *st, | ||
| 538 | struct iio_chan_spec *chan, int ch) | ||
| 539 | { | ||
| 540 | struct ad7606_chan_scale *cs = &st->chan_scales[ch]; | ||
| 541 | |||
| 542 | cs->range = 0; | ||
| 543 | cs->scale_avail = ad7609_hw_scale_avail; | ||
| 544 | cs->num_scales = ARRAY_SIZE(ad7609_hw_scale_avail); | ||
| 545 | return 0; | ||
| 546 | } | ||
| 547 | |||
| 65 | static int ad7606_reg_access(struct iio_dev *indio_dev, | 548 | static int ad7606_reg_access(struct iio_dev *indio_dev, |
| 66 | unsigned int reg, | 549 | unsigned int reg, |
| 67 | unsigned int writeval, | 550 | unsigned int writeval, |
| @@ -83,12 +566,85 @@ static int ad7606_reg_access(struct iio_dev *indio_dev, · 15 unmodified lines | |||
| 83 | } | 566 | } |
| 84 | } | 567 | } |
| 85 | 568 | ||
| 569 | static int ad7606_pwm_set_high(struct ad7606_state *st) | ||
| 570 | { | ||
| 571 | struct pwm_state cnvst_pwm_state; | ||
| 572 | int ret; | ||
| 573 | |||
| 574 | pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state); | ||
| 575 | cnvst_pwm_state.enabled = true; | ||
| 576 | cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period; | ||
| 577 | |||
| 578 | ret = pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state); | ||
| 579 | |||
| 580 | return ret; | ||
| 581 | } | ||
| 582 | |||
| 583 | static int ad7606_pwm_set_low(struct ad7606_state *st) | ||
| 584 | { | ||
| 585 | struct pwm_state cnvst_pwm_state; | ||
| 586 | int ret; | ||
| 587 | |||
| 588 | pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state); | ||
| 589 | cnvst_pwm_state.enabled = true; | ||
| 590 | cnvst_pwm_state.duty_cycle = 0; | ||
| 591 | |||
| 592 | ret = pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state); | ||
| 593 | |||
| 594 | return ret; | ||
| 595 | } | ||
| 596 | |||
| 597 | static int ad7606_pwm_set_swing(struct ad7606_state *st) | ||
| 598 | { | ||
| 599 | struct pwm_state cnvst_pwm_state; | ||
| 600 | |||
| 601 | pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state); | ||
| 602 | cnvst_pwm_state.enabled = true; | ||
| 603 | cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period / 2; | ||
| 604 | |||
| 605 | return pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state); | ||
| 606 | } | ||
| 607 | |||
| 608 | static bool ad7606_pwm_is_swinging(struct ad7606_state *st) | ||
| 609 | { | ||
| 610 | struct pwm_state cnvst_pwm_state; | ||
| 611 | |||
| 612 | pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state); | ||
| 613 | |||
| 614 | return cnvst_pwm_state.duty_cycle != cnvst_pwm_state.period && | ||
| 615 | cnvst_pwm_state.duty_cycle != 0; | ||
| 616 | } | ||
| 617 | |||
| 618 | static int ad7606_set_sampling_freq(struct ad7606_state *st, unsigned long freq) | ||
| 619 | { | ||
| 620 | struct pwm_state cnvst_pwm_state; | ||
| 621 | bool is_swinging = ad7606_pwm_is_swinging(st); | ||
| 622 | bool is_high; | ||
| 623 | |||
| 624 | if (freq == 0) | ||
| 625 | return -EINVAL; | ||
| 626 | |||
| 627 | /* Retrieve the previous state. */ | ||
| 628 | pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state); | ||
| 629 | is_high = cnvst_pwm_state.duty_cycle == cnvst_pwm_state.period; | ||
| 630 | |||
| 631 | cnvst_pwm_state.period = DIV_ROUND_UP_ULL(NSEC_PER_SEC, freq); | ||
| 632 | cnvst_pwm_state.polarity = PWM_POLARITY_NORMAL; | ||
| 633 | if (is_high) | ||
| 634 | cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period; | ||
| 635 | else if (is_swinging) | ||
| 636 | cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period / 2; | ||
| 637 | else | ||
| 638 | cnvst_pwm_state.duty_cycle = 0; | ||
| 639 | |||
| 640 | return pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state); | ||
| 641 | } | ||
| 642 | |||
| 86 | static int ad7606_read_samples(struct ad7606_state *st) | 643 | static int ad7606_read_samples(struct ad7606_state *st) |
| 87 | { | 644 | { |
| 88 | unsigned int num = st->chip_info->num_channels - 1; | 645 | unsigned int num = st->chip_info->num_adc_channels; |
| 89 | u16 *data = st->data; | ||
| 90 | 646 | ||
| 91 | return st->bops->read_block(st->dev, num, data); | 647 | return st->bops->read_block(st->dev, num, &st->data); |
| 92 | } | 648 | } |
| 93 | 649 | ||
| 94 | static irqreturn_t ad7606_trigger_handler(int irq, void *p) | 650 | static irqreturn_t ad7606_trigger_handler(int irq, void *p) |
| @@ -104,7 +660,7 @@ static irqreturn_t ad7606_trigger_handler(int irq, void *p) · 9 unmodified lines | |||
| 104 | if (ret) | 660 | if (ret) |
| 105 | goto error_ret; | 661 | goto error_ret; |
| 106 | 662 | ||
| 107 | iio_push_to_buffers_with_timestamp(indio_dev, st->data, | 663 | iio_push_to_buffers_with_timestamp(indio_dev, &st->data, |
| 108 | iio_get_time_ns(indio_dev)); | 664 | iio_get_time_ns(indio_dev)); |
| 109 | error_ret: | 665 | error_ret: |
| 110 | iio_trigger_notify_done(indio_dev->trig); | 666 | iio_trigger_notify_done(indio_dev->trig); |
| @@ -114,24 +670,62 @@ error_ret: · 3 unmodified lines | |||
| 114 | return IRQ_HANDLED; | 670 | return IRQ_HANDLED; |
| 115 | } | 671 | } |
| 116 | 672 | ||
| 117 | static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch) | 673 | static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch, |
| 674 | int *val) | ||
| 118 | { | 675 | { |
| 119 | struct ad7606_state *st = iio_priv(indio_dev); | 676 | struct ad7606_state *st = iio_priv(indio_dev); |
| 677 | unsigned int realbits = st->chip_info->channels[1].scan_type.realbits; | ||
| 678 | const struct iio_chan_spec *chan; | ||
| 120 | int ret; | 679 | int ret; |
| 121 | 680 | ||
| 122 | gpiod_set_value(st->gpio_convst, 1); | 681 | if (st->gpio_convst) { |
| 123 | ret = wait_for_completion_timeout(&st->completion, | 682 | gpiod_set_value(st->gpio_convst, 1); |
| 124 | msecs_to_jiffies(1000)); | 683 | } else { |
| 125 | if (!ret) { | 684 | ret = ad7606_pwm_set_high(st); |
| 126 | ret = -ETIMEDOUT; | 685 | if (ret < 0) |
| 127 | goto error_ret; | 686 | return ret; |
| 687 | } | ||
| 688 | |||
| 689 | /* | ||
| 690 | * If no backend, wait for the interruption on busy pin, otherwise just add | ||
| 691 | * a delay to leave time for the data to be available. For now, the latter | ||
| 692 | * will not happen because IIO_CHAN_INFO_RAW is not supported for the backend. | ||
| 693 | * TODO: Add support for reading a single value when the backend is used. | ||
| 694 | */ | ||
| 695 | if (!st->back) { | ||
| 696 | ret = wait_for_completion_timeout(&st->completion, | ||
| 697 | msecs_to_jiffies(1000)); | ||
| 698 | if (!ret) { | ||
| 699 | ret = -ETIMEDOUT; | ||
| 700 | goto error_ret; | ||
| 701 | } | ||
| 702 | } else { | ||
| 703 | fsleep(1); | ||
| 128 | } | 704 | } |
| 129 | 705 | ||
| 130 | ret = ad7606_read_samples(st); | 706 | ret = ad7606_read_samples(st); |
| 131 | if (ret == 0) | 707 | if (ret) |
| 132 | ret = st->data[ch]; | 708 | goto error_ret; |
| 709 | |||
| 710 | chan = &indio_dev->channels[ch + 1]; | ||
| 711 | if (chan->scan_type.sign == 'u') { | ||
| 712 | if (realbits > 16) | ||
| 713 | *val = st->data.buf32[ch]; | ||
| 714 | else | ||
| 715 | *val = st->data.buf16[ch]; | ||
| 716 | } else { | ||
| 717 | if (realbits > 16) | ||
| 718 | *val = sign_extend32(st->data.buf32[ch], realbits - 1); | ||
| 719 | else | ||
| 720 | *val = sign_extend32(st->data.buf16[ch], realbits - 1); | ||
| 721 | } | ||
| 133 | 722 | ||
| 134 | error_ret: | 723 | error_ret: |
| 724 | if (!st->gpio_convst) { | ||
| 725 | ret = ad7606_pwm_set_low(st); | ||
| 726 | if (ret < 0) | ||
| 727 | return ret; | ||
| 728 | } | ||
| 135 | gpiod_set_value(st->gpio_convst, 0); | 729 | gpiod_set_value(st->gpio_convst, 0); |
| 136 | 730 | ||
| 137 | return ret; | 731 | return ret; |
| @@ -145,53 +739,57 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, · 7 unmodified lines | |||
| 145 | { | 739 | { |
| 146 | int ret, ch = 0; | 740 | int ret, ch = 0; |
| 147 | struct ad7606_state *st = iio_priv(indio_dev); | 741 | struct ad7606_state *st = iio_priv(indio_dev); |
| 742 | struct ad7606_chan_scale *cs; | ||
| 743 | struct pwm_state cnvst_pwm_state; | ||
| 148 | 744 | ||
| 149 | switch (m) { | 745 | switch (m) { |
| 150 | case IIO_CHAN_INFO_RAW: | 746 | case IIO_CHAN_INFO_RAW: |
| 151 | iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { | 747 | iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { |
| 152 | ret = ad7606_scan_direct(indio_dev, chan->address); | 748 | ret = ad7606_scan_direct(indio_dev, chan->address, val); |
| 153 | if (ret < 0) | 749 | if (ret < 0) |
| 154 | return ret; | 750 | return ret; |
| 155 | *val = (short) ret; | ||
| 156 | return IIO_VAL_INT; | 751 | return IIO_VAL_INT; |
| 157 | } | 752 | } |
| 158 | unreachable(); | 753 | unreachable(); |
| 159 | case IIO_CHAN_INFO_SCALE: | 754 | case IIO_CHAN_INFO_SCALE: |
| 160 | if (st->sw_mode_en) | 755 | if (st->sw_mode_en) |
| 161 | ch = chan->address; | 756 | ch = chan->address; |
| 162 | *val = 0; | 757 | cs = &st->chan_scales[ch]; |
| 163 | *val2 = st->scale_avail[st->range[ch]]; | 758 | *val = cs->scale_avail[cs->range][0]; |
| 759 | *val2 = cs->scale_avail[cs->range][1]; | ||
| 164 | return IIO_VAL_INT_PLUS_MICRO; | 760 | return IIO_VAL_INT_PLUS_MICRO; |
| 165 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | 761 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
| 166 | *val = st->oversampling; | 762 | *val = st->oversampling; |
| 167 | return IIO_VAL_INT; | 763 | return IIO_VAL_INT; |
| 764 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 765 | /* | ||
| 766 | * TODO: return the real frequency intead of the requested one once | ||
| 767 | * pwm_get_state_hw comes upstream. | ||
| 768 | */ | ||
| 769 | pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state); | ||
| 770 | *val = DIV_ROUND_CLOSEST_ULL(NSEC_PER_SEC, cnvst_pwm_state.period); | ||
| 771 | return IIO_VAL_INT; | ||
| 168 | } | 772 | } |
| 169 | return -EINVAL; | 773 | return -EINVAL; |
| 170 | } | 774 | } |
| 171 | 775 | ||
| 172 | static ssize_t ad7606_show_avail(char *buf, const unsigned int *vals, | ||
| 173 | unsigned int n, bool micros) | ||
| 174 | { | ||
| 175 | size_t len = 0; | ||
| 176 | int i; | ||
| 177 | |||
| 178 | for (i = 0; i < n; i++) { | ||
| 179 | len += scnprintf(buf + len, PAGE_SIZE - len, | ||
| 180 | micros ? "0.%06u " : "%u ", vals[i]); | ||
| 181 | } | ||
| 182 | buf[len - 1] = '\n'; | ||
| 183 | |||
| 184 | return len; | ||
| 185 | } | ||
| 186 | |||
| 187 | static ssize_t in_voltage_scale_available_show(struct device *dev, | 776 | static ssize_t in_voltage_scale_available_show(struct device *dev, |
| 188 | struct device_attribute *attr, | 777 | struct device_attribute *attr, |
| 189 | char *buf) | 778 | char *buf) |
| 190 | { | 779 | { |
| 191 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 780 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 192 | struct ad7606_state *st = iio_priv(indio_dev); | 781 | struct ad7606_state *st = iio_priv(indio_dev); |
| 782 | struct ad7606_chan_scale *cs = &st->chan_scales[0]; | ||
| 783 | const unsigned int (*vals)[2] = cs->scale_avail; | ||
| 784 | unsigned int i; | ||
| 785 | size_t len = 0; | ||
| 786 | |||
| 787 | for (i = 0; i < cs->num_scales; i++) | ||
| 788 | len += scnprintf(buf + len, PAGE_SIZE - len, "%u.%06u ", | ||
| 789 | vals[i][0], vals[i][1]); | ||
| 790 | buf[len - 1] = '\n'; | ||
| 193 | 791 | ||
| 194 | return ad7606_show_avail(buf, st->scale_avail, st->num_scales, true); | 792 | return len; |
| 195 | } | 793 | } |
| 196 | 794 | ||
| 197 | static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0); | 795 | static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0); |
| @@ -229,19 +827,27 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, · 31 unmodified lines | |||
| 229 | long mask) | 827 | long mask) |
| 230 | { | 828 | { |
| 231 | struct ad7606_state *st = iio_priv(indio_dev); | 829 | struct ad7606_state *st = iio_priv(indio_dev); |
| 830 | unsigned int scale_avail_uv[AD760X_MAX_SCALES]; | ||
| 831 | struct ad7606_chan_scale *cs; | ||
| 232 | int i, ret, ch = 0; | 832 | int i, ret, ch = 0; |
| 233 | 833 | ||
| 234 | guard(mutex)(&st->lock); | 834 | guard(mutex)(&st->lock); |
| 235 | 835 | ||
| 236 | switch (mask) { | 836 | switch (mask) { |
| 237 | case IIO_CHAN_INFO_SCALE: | 837 | case IIO_CHAN_INFO_SCALE: |
| 238 | i = find_closest(val2, st->scale_avail, st->num_scales); | ||
| 239 | if (st->sw_mode_en) | 838 | if (st->sw_mode_en) |
| 240 | ch = chan->address; | 839 | ch = chan->address; |
| 241 | ret = st->write_scale(indio_dev, ch, i); | 840 | cs = &st->chan_scales[ch]; |
| 841 | for (i = 0; i < cs->num_scales; i++) { | ||
| 842 | scale_avail_uv[i] = cs->scale_avail[i][0] * MICRO + | ||
| 843 | cs->scale_avail[i][1]; | ||
| 844 | } | ||
| 845 | val = (val * MICRO) + val2; | ||
| 846 | i = find_closest(val, scale_avail_uv, cs->num_scales); | ||
| 847 | ret = st->write_scale(indio_dev, ch, i + cs->reg_offset); | ||
| 242 | if (ret < 0) | 848 | if (ret < 0) |
| 243 | return ret; | 849 | return ret; |
| 244 | st->range[ch] = i; | 850 | cs->range = i; |
| 245 | 851 | ||
| 246 | return 0; | 852 | return 0; |
| 247 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | 853 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
| @@ -252,8 +858,13 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, · 4 unmodified lines | |||
| 252 | ret = st->write_os(indio_dev, i); | 858 | ret = st->write_os(indio_dev, i); |
| 253 | if (ret < 0) | 859 | if (ret < 0) |
| 254 | return ret; | 860 | return ret; |
| 861 | st->oversampling = st->oversampling_avail[i]; | ||
| 255 | 862 | ||
| 256 | return 0; | 863 | return 0; |
| 864 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 865 | if (val < 0 && val2 != 0) | ||
| 866 | return -EINVAL; | ||
| 867 | return ad7606_set_sampling_freq(st, val); | ||
| 257 | default: | 868 | default: |
| 258 | return -EINVAL; | 869 | return -EINVAL; |
| 259 | } | 870 | } |
| @@ -265,9 +876,15 @@ static ssize_t ad7606_oversampling_ratio_avail(struct device *dev, · 5 unmodified lines | |||
| 265 | { | 876 | { |
| 266 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 877 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 267 | struct ad7606_state *st = iio_priv(indio_dev); | 878 | struct ad7606_state *st = iio_priv(indio_dev); |
| 879 | const unsigned int *vals = st->oversampling_avail; | ||
| 880 | unsigned int i; | ||
| 881 | size_t len = 0; | ||
| 268 | 882 | ||
| 269 | return ad7606_show_avail(buf, st->oversampling_avail, | 883 | for (i = 0; i < st->num_os_ratios; i++) |
| 270 | st->num_os_ratios, false); | 884 | len += scnprintf(buf + len, PAGE_SIZE - len, "%u ", vals[i]); |
| 885 | buf[len - 1] = '\n'; | ||
| 886 | |||
| 887 | return len; | ||
| 271 | } | 888 | } |
| 272 | 889 | ||
| 273 | static IIO_DEVICE_ATTR(oversampling_ratio_available, 0444, | 890 | static IIO_DEVICE_ATTR(oversampling_ratio_available, 0444, |
| @@ -301,102 +918,13 @@ static const struct attribute_group ad7606_attribute_group_range = { · 27 unmodified lines | |||
| 301 | .attrs = ad7606_attributes_range, | 918 | .attrs = ad7606_attributes_range, |
| 302 | }; | 919 | }; |
| 303 | 920 | ||
| 304 | static const struct iio_chan_spec ad7605_channels[] = { | ||
| 305 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
| 306 | AD7605_CHANNEL(0), | ||
| 307 | AD7605_CHANNEL(1), | ||
| 308 | AD7605_CHANNEL(2), | ||
| 309 | AD7605_CHANNEL(3), | ||
| 310 | }; | ||
| 311 | |||
| 312 | static const struct iio_chan_spec ad7606_channels[] = { | ||
| 313 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
| 314 | AD7606_CHANNEL(0), | ||
| 315 | AD7606_CHANNEL(1), | ||
| 316 | AD7606_CHANNEL(2), | ||
| 317 | AD7606_CHANNEL(3), | ||
| 318 | AD7606_CHANNEL(4), | ||
| 319 | AD7606_CHANNEL(5), | ||
| 320 | AD7606_CHANNEL(6), | ||
| 321 | AD7606_CHANNEL(7), | ||
| 322 | }; | ||
| 323 | |||
| 324 | /* | ||
| 325 | * The current assumption that this driver makes for AD7616, is that it's | ||
| 326 | * working in Hardware Mode with Serial, Burst and Sequencer modes activated. | ||
| 327 | * To activate them, following pins must be pulled high: | ||
| 328 | * -SER/PAR | ||
| 329 | * -SEQEN | ||
| 330 | * And following pins must be pulled low: | ||
| 331 | * -WR/BURST | ||
| 332 | * -DB4/SER1W | ||
| 333 | */ | ||
| 334 | static const struct iio_chan_spec ad7616_channels[] = { | ||
| 335 | IIO_CHAN_SOFT_TIMESTAMP(16), | ||
| 336 | AD7606_CHANNEL(0), | ||
| 337 | AD7606_CHANNEL(1), | ||
| 338 | AD7606_CHANNEL(2), | ||
| 339 | AD7606_CHANNEL(3), | ||
| 340 | AD7606_CHANNEL(4), | ||
| 341 | AD7606_CHANNEL(5), | ||
| 342 | AD7606_CHANNEL(6), | ||
| 343 | AD7606_CHANNEL(7), | ||
| 344 | AD7606_CHANNEL(8), | ||
| 345 | AD7606_CHANNEL(9), | ||
| 346 | AD7606_CHANNEL(10), | ||
| 347 | AD7606_CHANNEL(11), | ||
| 348 | AD7606_CHANNEL(12), | ||
| 349 | AD7606_CHANNEL(13), | ||
| 350 | AD7606_CHANNEL(14), | ||
| 351 | AD7606_CHANNEL(15), | ||
| 352 | }; | ||
| 353 | |||
| 354 | static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { | ||
| 355 | /* More devices added in future */ | ||
| 356 | [ID_AD7605_4] = { | ||
| 357 | .channels = ad7605_channels, | ||
| 358 | .num_channels = 5, | ||
| 359 | }, | ||
| 360 | [ID_AD7606_8] = { | ||
| 361 | .channels = ad7606_channels, | ||
| 362 | .num_channels = 9, | ||
| 363 | .oversampling_avail = ad7606_oversampling_avail, | ||
| 364 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | ||
| 365 | }, | ||
| 366 | [ID_AD7606_6] = { | ||
| 367 | .channels = ad7606_channels, | ||
| 368 | .num_channels = 7, | ||
| 369 | .oversampling_avail = ad7606_oversampling_avail, | ||
| 370 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | ||
| 371 | }, | ||
| 372 | [ID_AD7606_4] = { | ||
| 373 | .channels = ad7606_channels, | ||
| 374 | .num_channels = 5, | ||
| 375 | .oversampling_avail = ad7606_oversampling_avail, | ||
| 376 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | ||
| 377 | }, | ||
| 378 | [ID_AD7606B] = { | ||
| 379 | .channels = ad7606_channels, | ||
| 380 | .num_channels = 9, | ||
| 381 | .oversampling_avail = ad7606_oversampling_avail, | ||
| 382 | .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), | ||
| 383 | }, | ||
| 384 | [ID_AD7616] = { | ||
| 385 | .channels = ad7616_channels, | ||
| 386 | .num_channels = 17, | ||
| 387 | .oversampling_avail = ad7616_oversampling_avail, | ||
| 388 | .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail), | ||
| 389 | .os_req_reset = true, | ||
| 390 | .init_delay_ms = 15, | ||
| 391 | }, | ||
| 392 | }; | ||
| 393 | |||
| 394 | static int ad7606_request_gpios(struct ad7606_state *st) | 921 | static int ad7606_request_gpios(struct ad7606_state *st) |
| 395 | { | 922 | { |
| 396 | struct device *dev = st->dev; | 923 | struct device *dev = st->dev; |
| 397 | 924 | ||
| 398 | st->gpio_convst = devm_gpiod_get(dev, "adi,conversion-start", | 925 | st->gpio_convst = devm_gpiod_get_optional(dev, "adi,conversion-start", |
| 399 | GPIOD_OUT_LOW); | 926 | GPIOD_OUT_LOW); |
| 927 | |||
| 400 | if (IS_ERR(st->gpio_convst)) | 928 | if (IS_ERR(st->gpio_convst)) |
| 401 | return PTR_ERR(st->gpio_convst); | 929 | return PTR_ERR(st->gpio_convst); |
| 402 | 930 | ||
| @@ -438,14 +966,24 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id) · 35 unmodified lines | |||
| 438 | { | 966 | { |
| 439 | struct iio_dev *indio_dev = dev_id; | 967 | struct iio_dev *indio_dev = dev_id; |
| 440 | struct ad7606_state *st = iio_priv(indio_dev); | 968 | struct ad7606_state *st = iio_priv(indio_dev); |
| 969 | int ret; | ||
| 441 | 970 | ||
| 442 | if (iio_buffer_enabled(indio_dev)) { | 971 | if (iio_buffer_enabled(indio_dev)) { |
| 443 | gpiod_set_value(st->gpio_convst, 0); | 972 | if (st->gpio_convst) { |
| 973 | gpiod_set_value(st->gpio_convst, 0); | ||
| 974 | } else { | ||
| 975 | ret = ad7606_pwm_set_low(st); | ||
| 976 | if (ret < 0) { | ||
| 977 | dev_err(st->dev, "PWM set low failed"); | ||
| 978 | goto done; | ||
| 979 | } | ||
| 980 | } | ||
| 444 | iio_trigger_poll_nested(st->trig); | 981 | iio_trigger_poll_nested(st->trig); |
| 445 | } else { | 982 | } else { |
| 446 | complete(&st->completion); | 983 | complete(&st->completion); |
| 447 | } | 984 | } |
| 448 | 985 | ||
| 986 | done: | ||
| 449 | return IRQ_HANDLED; | 987 | return IRQ_HANDLED; |
| 450 | }; | 988 | }; |
| 451 | 989 | ||
| @@ -478,14 +1016,81 @@ static int ad7606_buffer_predisable(struct iio_dev *indio_dev) · 26 unmodified lines | |||
| 478 | return 0; | 1016 | return 0; |
| 479 | } | 1017 | } |
| 480 | 1018 | ||
| 1019 | static int ad7606_read_avail(struct iio_dev *indio_dev, | ||
| 1020 | struct iio_chan_spec const *chan, | ||
| 1021 | const int **vals, int *type, int *length, | ||
| 1022 | long info) | ||
| 1023 | { | ||
| 1024 | struct ad7606_state *st = iio_priv(indio_dev); | ||
| 1025 | struct ad7606_chan_scale *cs; | ||
| 1026 | unsigned int ch = 0; | ||
| 1027 | |||
| 1028 | switch (info) { | ||
| 1029 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | ||
| 1030 | *vals = st->oversampling_avail; | ||
| 1031 | *length = st->num_os_ratios; | ||
| 1032 | *type = IIO_VAL_INT; | ||
| 1033 | |||
| 1034 | return IIO_AVAIL_LIST; | ||
| 1035 | |||
| 1036 | case IIO_CHAN_INFO_SCALE: | ||
| 1037 | if (st->sw_mode_en) | ||
| 1038 | ch = chan->address; | ||
| 1039 | |||
| 1040 | cs = &st->chan_scales[ch]; | ||
| 1041 | *vals = (int *)cs->scale_avail; | ||
| 1042 | *length = cs->num_scales; | ||
| 1043 | *type = IIO_VAL_INT_PLUS_MICRO; | ||
| 1044 | |||
| 1045 | return IIO_AVAIL_LIST; | ||
| 1046 | } | ||
| 1047 | return -EINVAL; | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | static int ad7606_backend_buffer_postenable(struct iio_dev *indio_dev) | ||
| 1051 | { | ||
| 1052 | struct ad7606_state *st = iio_priv(indio_dev); | ||
| 1053 | |||
| 1054 | return ad7606_pwm_set_swing(st); | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | static int ad7606_backend_buffer_predisable(struct iio_dev *indio_dev) | ||
| 1058 | { | ||
| 1059 | struct ad7606_state *st = iio_priv(indio_dev); | ||
| 1060 | |||
| 1061 | return ad7606_pwm_set_low(st); | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | static int ad7606_update_scan_mode(struct iio_dev *indio_dev, | ||
| 1065 | const unsigned long *scan_mask) | ||
| 1066 | { | ||
| 1067 | struct ad7606_state *st = iio_priv(indio_dev); | ||
| 1068 | |||
| 1069 | /* | ||
| 1070 | * The update scan mode is only for iio backend compatible drivers. | ||
| 1071 | * If the specific update_scan_mode is not defined in the bus ops, | ||
| 1072 | * just do nothing and return 0. | ||
| 1073 | */ | ||
| 1074 | if (!st->bops->update_scan_mode) | ||
| 1075 | return 0; | ||
| 1076 | |||
| 1077 | return st->bops->update_scan_mode(indio_dev, scan_mask); | ||
| 1078 | } | ||
| 1079 | |||
| 481 | static const struct iio_buffer_setup_ops ad7606_buffer_ops = { | 1080 | static const struct iio_buffer_setup_ops ad7606_buffer_ops = { |
| 482 | .postenable = &ad7606_buffer_postenable, | 1081 | .postenable = &ad7606_buffer_postenable, |
| 483 | .predisable = &ad7606_buffer_predisable, | 1082 | .predisable = &ad7606_buffer_predisable, |
| 484 | }; | 1083 | }; |
| 485 | 1084 | ||
| 1085 | static const struct iio_buffer_setup_ops ad7606_backend_buffer_ops = { | ||
| 1086 | .postenable = &ad7606_backend_buffer_postenable, | ||
| 1087 | .predisable = &ad7606_backend_buffer_predisable, | ||
| 1088 | }; | ||
| 1089 | |||
| 486 | static const struct iio_info ad7606_info_no_os_or_range = { | 1090 | static const struct iio_info ad7606_info_no_os_or_range = { |
| 487 | .read_raw = &ad7606_read_raw, | 1091 | .read_raw = &ad7606_read_raw, |
| 488 | .validate_trigger = &ad7606_validate_trigger, | 1092 | .validate_trigger = &ad7606_validate_trigger, |
| 1093 | .update_scan_mode = &ad7606_update_scan_mode, | ||
| 489 | }; | 1094 | }; |
| 490 | 1095 | ||
| 491 | static const struct iio_info ad7606_info_os_and_range = { | 1096 | static const struct iio_info ad7606_info_os_and_range = { |
| @@ -493,14 +1098,16 @@ static const struct iio_info ad7606_info_os_and_range = { · 1 unmodified line | |||
| 493 | .write_raw = &ad7606_write_raw, | 1098 | .write_raw = &ad7606_write_raw, |
| 494 | .attrs = &ad7606_attribute_group_os_and_range, | 1099 | .attrs = &ad7606_attribute_group_os_and_range, |
| 495 | .validate_trigger = &ad7606_validate_trigger, | 1100 | .validate_trigger = &ad7606_validate_trigger, |
| 1101 | .update_scan_mode = &ad7606_update_scan_mode, | ||
| 496 | }; | 1102 | }; |
| 497 | 1103 | ||
| 498 | static const struct iio_info ad7606_info_os_range_and_debug = { | 1104 | static const struct iio_info ad7606_info_sw_mode = { |
| 499 | .read_raw = &ad7606_read_raw, | 1105 | .read_raw = &ad7606_read_raw, |
| 500 | .write_raw = &ad7606_write_raw, | 1106 | .write_raw = &ad7606_write_raw, |
| 1107 | .read_avail = &ad7606_read_avail, | ||
| 501 | .debugfs_reg_access = &ad7606_reg_access, | 1108 | .debugfs_reg_access = &ad7606_reg_access, |
| 502 | .attrs = &ad7606_attribute_group_os_and_range, | ||
| 503 | .validate_trigger = &ad7606_validate_trigger, | 1109 | .validate_trigger = &ad7606_validate_trigger, |
| 1110 | .update_scan_mode = &ad7606_update_scan_mode, | ||
| 504 | }; | 1111 | }; |
| 505 | 1112 | ||
| 506 | static const struct iio_info ad7606_info_os = { | 1113 | static const struct iio_info ad7606_info_os = { |
| @@ -508,6 +1115,7 @@ static const struct iio_info ad7606_info_os = { · 1 unmodified line | |||
| 508 | .write_raw = &ad7606_write_raw, | 1115 | .write_raw = &ad7606_write_raw, |
| 509 | .attrs = &ad7606_attribute_group_os, | 1116 | .attrs = &ad7606_attribute_group_os, |
| 510 | .validate_trigger = &ad7606_validate_trigger, | 1117 | .validate_trigger = &ad7606_validate_trigger, |
| 1118 | .update_scan_mode = &ad7606_update_scan_mode, | ||
| 511 | }; | 1119 | }; |
| 512 | 1120 | ||
| 513 | static const struct iio_info ad7606_info_range = { | 1121 | static const struct iio_info ad7606_info_range = { |
| @@ -515,14 +1123,60 @@ static const struct iio_info ad7606_info_range = { · 1 unmodified line | |||
| 515 | .write_raw = &ad7606_write_raw, | 1123 | .write_raw = &ad7606_write_raw, |
| 516 | .attrs = &ad7606_attribute_group_range, | 1124 | .attrs = &ad7606_attribute_group_range, |
| 517 | .validate_trigger = &ad7606_validate_trigger, | 1125 | .validate_trigger = &ad7606_validate_trigger, |
| 1126 | .update_scan_mode = &ad7606_update_scan_mode, | ||
| 518 | }; | 1127 | }; |
| 519 | 1128 | ||
| 520 | static const struct iio_trigger_ops ad7606_trigger_ops = { | 1129 | static const struct iio_trigger_ops ad7606_trigger_ops = { |
| 521 | .validate_device = iio_trigger_validate_own_device, | 1130 | .validate_device = iio_trigger_validate_own_device, |
| 522 | }; | 1131 | }; |
| 523 | 1132 | ||
| 1133 | static int ad7606_sw_mode_setup(struct iio_dev *indio_dev) | ||
| 1134 | { | ||
| 1135 | struct ad7606_state *st = iio_priv(indio_dev); | ||
| 1136 | |||
| 1137 | st->sw_mode_en = st->bops->sw_mode_config && | ||
| 1138 | device_property_present(st->dev, "adi,sw-mode"); | ||
| 1139 | if (!st->sw_mode_en) | ||
| 1140 | return 0; | ||
| 1141 | |||
| 1142 | indio_dev->info = &ad7606_info_sw_mode; | ||
| 1143 | |||
| 1144 | return st->bops->sw_mode_config(indio_dev); | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | static int ad7606_chan_scales_setup(struct iio_dev *indio_dev) | ||
| 1148 | { | ||
| 1149 | unsigned int num_channels = indio_dev->num_channels - 1; | ||
| 1150 | struct ad7606_state *st = iio_priv(indio_dev); | ||
| 1151 | struct iio_chan_spec *chans; | ||
| 1152 | size_t size; | ||
| 1153 | int ch, ret; | ||
| 1154 | |||
| 1155 | /* Clone IIO channels, since some may be differential */ | ||
| 1156 | size = indio_dev->num_channels * sizeof(*indio_dev->channels); | ||
| 1157 | chans = devm_kzalloc(st->dev, size, GFP_KERNEL); | ||
| 1158 | if (!chans) | ||
| 1159 | return -ENOMEM; | ||
| 1160 | |||
| 1161 | memcpy(chans, indio_dev->channels, size); | ||
| 1162 | indio_dev->channels = chans; | ||
| 1163 | |||
| 1164 | for (ch = 0; ch < num_channels; ch++) { | ||
| 1165 | ret = st->chip_info->scale_setup_cb(st, &chans[ch + 1], ch); | ||
| 1166 | if (ret) | ||
| 1167 | return ret; | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | return 0; | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | static void ad7606_pwm_disable(void *data) | ||
| 1174 | { | ||
| 1175 | pwm_disable(data); | ||
| 1176 | } | ||
| 1177 | |||
| 524 | int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, | 1178 | int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, |
| 525 | const char *name, unsigned int id, | 1179 | const struct ad7606_chip_info *chip_info, |
| 526 | const struct ad7606_bus_ops *bops) | 1180 | const struct ad7606_bus_ops *bops) |
| 527 | { | 1181 | { |
| 528 | struct ad7606_state *st; | 1182 | struct ad7606_state *st; |
| @@ -540,18 +1194,14 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, · 11 unmodified lines | |||
| 540 | mutex_init(&st->lock); | 1194 | mutex_init(&st->lock); |
| 541 | st->bops = bops; | 1195 | st->bops = bops; |
| 542 | st->base_address = base_address; | 1196 | st->base_address = base_address; |
| 543 | /* tied to logic low, analog input range is +/- 5V */ | ||
| 544 | st->range[0] = 0; | ||
| 545 | st->oversampling = 1; | 1197 | st->oversampling = 1; |
| 546 | st->scale_avail = ad7606_scale_avail; | ||
| 547 | st->num_scales = ARRAY_SIZE(ad7606_scale_avail); | ||
| 548 | 1198 | ||
| 549 | ret = devm_regulator_get_enable(dev, "avcc"); | 1199 | ret = devm_regulator_get_enable(dev, "avcc"); |
| 550 | if (ret) | 1200 | if (ret) |
| 551 | return dev_err_probe(dev, ret, | 1201 | return dev_err_probe(dev, ret, |
| 552 | "Failed to enable specified AVcc supply\n"); | 1202 | "Failed to enable specified AVcc supply\n"); |
| 553 | 1203 | ||
| 554 | st->chip_info = &ad7606_chip_info_tbl[id]; | 1204 | st->chip_info = chip_info; |
| 555 | 1205 | ||
| 556 | if (st->chip_info->oversampling_num) { | 1206 | if (st->chip_info->oversampling_num) { |
| 557 | st->oversampling_avail = st->chip_info->oversampling_avail; | 1207 | st->oversampling_avail = st->chip_info->oversampling_avail; |
| @@ -574,12 +1224,10 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, · 16 unmodified lines | |||
| 574 | indio_dev->info = &ad7606_info_no_os_or_range; | 1224 | indio_dev->info = &ad7606_info_no_os_or_range; |
| 575 | } | 1225 | } |
| 576 | indio_dev->modes = INDIO_DIRECT_MODE; | 1226 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 577 | indio_dev->name = name; | 1227 | indio_dev->name = chip_info->name; |
| 578 | indio_dev->channels = st->chip_info->channels; | 1228 | indio_dev->channels = st->chip_info->channels; |
| 579 | indio_dev->num_channels = st->chip_info->num_channels; | 1229 | indio_dev->num_channels = st->chip_info->num_channels; |
| 580 | 1230 | ||
| 581 | init_completion(&st->completion); | ||
| 582 | |||
| 583 | ret = ad7606_reset(st); | 1231 | ret = ad7606_reset(st); |
| 584 | if (ret) | 1232 | if (ret) |
| 585 | dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); | 1233 | dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); |
| @@ -593,52 +1241,90 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, · 7 unmodified lines | |||
| 593 | st->write_scale = ad7606_write_scale_hw; | 1241 | st->write_scale = ad7606_write_scale_hw; |
| 594 | st->write_os = ad7606_write_os_hw; | 1242 | st->write_os = ad7606_write_os_hw; |
| 595 | 1243 | ||
| 596 | if (st->bops->sw_mode_config) | 1244 | ret = ad7606_sw_mode_setup(indio_dev); |
| 597 | st->sw_mode_en = device_property_present(st->dev, | 1245 | if (ret) |
| 598 | "adi,sw-mode"); | 1246 | return ret; |
| 1247 | |||
| 1248 | ret = ad7606_chan_scales_setup(indio_dev); | ||
| 1249 | if (ret) | ||
| 1250 | return ret; | ||
| 1251 | |||
| 1252 | /* If convst pin is not defined, setup PWM. */ | ||
| 1253 | if (!st->gpio_convst) { | ||
| 1254 | st->cnvst_pwm = devm_pwm_get(dev, NULL); | ||
| 1255 | if (IS_ERR(st->cnvst_pwm)) | ||
| 1256 | return PTR_ERR(st->cnvst_pwm); | ||
| 599 | 1257 | ||
| 600 | if (st->sw_mode_en) { | 1258 | /* The PWM is initialized at 1MHz to have a fast enough GPIO emulation. */ |
| 601 | /* Scale of 0.076293 is only available in sw mode */ | 1259 | ret = ad7606_set_sampling_freq(st, 1 * MEGA); |
| 602 | st->scale_avail = ad7616_sw_scale_avail; | 1260 | if (ret) |
| 603 | st->num_scales = ARRAY_SIZE(ad7616_sw_scale_avail); | 1261 | return ret; |
| 604 | 1262 | ||
| 605 | /* After reset, in software mode, ±10 V is set by default */ | 1263 | ret = ad7606_pwm_set_low(st); |
| 606 | memset32(st->range, 2, ARRAY_SIZE(st->range)); | 1264 | if (ret) |
| 607 | indio_dev->info = &ad7606_info_os_range_and_debug; | 1265 | return ret; |
| 608 | 1266 | ||
| 609 | ret = st->bops->sw_mode_config(indio_dev); | 1267 | /* |
| 610 | if (ret < 0) | 1268 | * PWM is not disabled when sampling stops, but instead its duty cycle is set |
| 1269 | * to 0% to be sure we have a "low" state. After we unload the driver, let's | ||
| 1270 | * disable the PWM. | ||
| 1271 | */ | ||
| 1272 | ret = devm_add_action_or_reset(dev, ad7606_pwm_disable, | ||
| 1273 | st->cnvst_pwm); | ||
| 1274 | if (ret) | ||
| 611 | return ret; | 1275 | return ret; |
| 612 | } | 1276 | } |
| 613 | 1277 | ||
| 614 | st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", | 1278 | if (st->bops->iio_backend_config) { |
| 615 | indio_dev->name, | 1279 | /* |
| 616 | iio_device_id(indio_dev)); | 1280 | * If there is a backend, the PWM should not overpass the maximum sampling |
| 617 | if (!st->trig) | 1281 | * frequency the chip supports. |
| 618 | return -ENOMEM; | 1282 | */ |
| 1283 | ret = ad7606_set_sampling_freq(st, | ||
| 1284 | chip_info->max_samplerate ? : 2 * KILO); | ||
| 1285 | if (ret) | ||
| 1286 | return ret; | ||
| 619 | 1287 | ||
| 620 | st->trig->ops = &ad7606_trigger_ops; | 1288 | ret = st->bops->iio_backend_config(dev, indio_dev); |
| 621 | iio_trigger_set_drvdata(st->trig, indio_dev); | 1289 | if (ret) |
| 622 | ret = devm_iio_trigger_register(dev, st->trig); | 1290 | return ret; |
| 623 | if (ret) | ||
| 624 | return ret; | ||
| 625 | 1291 | ||
| 626 | indio_dev->trig = iio_trigger_get(st->trig); | 1292 | indio_dev->setup_ops = &ad7606_backend_buffer_ops; |
| 1293 | } else { | ||
| 627 | 1294 | ||
| 628 | ret = devm_request_threaded_irq(dev, irq, | 1295 | /* Reserve the PWM use only for backend (force gpio_convst definition) */ |
| 629 | NULL, | 1296 | if (!st->gpio_convst) |
| 630 | &ad7606_interrupt, | 1297 | return dev_err_probe(dev, -EINVAL, |
| 631 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 1298 | "No backend, connect convst to a GPIO"); |
| 632 | name, indio_dev); | 1299 | |
| 633 | if (ret) | 1300 | init_completion(&st->completion); |
| 634 | return ret; | 1301 | st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", |
| 1302 | indio_dev->name, | ||
| 1303 | iio_device_id(indio_dev)); | ||
| 1304 | if (!st->trig) | ||
| 1305 | return -ENOMEM; | ||
| 1306 | |||
| 1307 | st->trig->ops = &ad7606_trigger_ops; | ||
| 1308 | iio_trigger_set_drvdata(st->trig, indio_dev); | ||
| 1309 | ret = devm_iio_trigger_register(dev, st->trig); | ||
| 1310 | if (ret) | ||
| 1311 | return ret; | ||
| 635 | 1312 | ||
| 636 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, | 1313 | indio_dev->trig = iio_trigger_get(st->trig); |
| 637 | &iio_pollfunc_store_time, | 1314 | |
| 638 | &ad7606_trigger_handler, | 1315 | ret = devm_request_threaded_irq(dev, irq, NULL, &ad7606_interrupt, |
| 639 | &ad7606_buffer_ops); | 1316 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
| 640 | if (ret) | 1317 | chip_info->name, indio_dev); |
| 641 | return ret; | 1318 | if (ret) |
| 1319 | return ret; | ||
| 1320 | |||
| 1321 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, | ||
| 1322 | &iio_pollfunc_store_time, | ||
| 1323 | &ad7606_trigger_handler, | ||
| 1324 | &ad7606_buffer_ops); | ||
| 1325 | if (ret) | ||
| 1326 | return ret; | ||
| 1327 | } | ||
| 642 | 1328 | ||
| 643 | return devm_iio_device_register(dev, indio_dev); | 1329 | return devm_iio_device_register(dev, indio_dev); |
| 644 | } | 1330 | } |
| @@ -665,7 +1351,7 @@ static int ad7606_resume(struct device *dev) · 20 unmodified lines | |||
| 665 | struct ad7606_state *st = iio_priv(indio_dev); | 1351 | struct ad7606_state *st = iio_priv(indio_dev); |
| 666 | 1352 | ||
| 667 | if (st->gpio_standby) { | 1353 | if (st->gpio_standby) { |
| 668 | gpiod_set_value(st->gpio_range, st->range[0]); | 1354 | gpiod_set_value(st->gpio_range, st->chan_scales[0].range); |
| 669 | gpiod_set_value(st->gpio_standby, 1); | 1355 | gpiod_set_value(st->gpio_standby, 1); |
| 670 | ad7606_reset(st); | 1356 | ad7606_reset(st); |
| 671 | } | 1357 | } |
| @@ -8,7 +8,9 @@ · 7 unmodified lines | |||
| 8 | #ifndef IIO_ADC_AD7606_H_ | 8 | #ifndef IIO_ADC_AD7606_H_ |
| 9 | #define IIO_ADC_AD7606_H_ | 9 | #define IIO_ADC_AD7606_H_ |
| 10 | 10 | ||
| 11 | #define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all) { \ | 11 | #define AD760X_MAX_CHANNELS 16 |
| 12 | |||
| 13 | #define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all, bits) { \ | ||
| 12 | .type = IIO_VOLTAGE, \ | 14 | .type = IIO_VOLTAGE, \ |
| 13 | .indexed = 1, \ | 15 | .indexed = 1, \ |
| 14 | .channel = num, \ | 16 | .channel = num, \ |
| @@ -19,56 +21,111 @@ · 4 unmodified lines | |||
| 19 | .scan_index = num, \ | 21 | .scan_index = num, \ |
| 20 | .scan_type = { \ | 22 | .scan_type = { \ |
| 21 | .sign = 's', \ | 23 | .sign = 's', \ |
| 22 | .realbits = 16, \ | 24 | .realbits = (bits), \ |
| 23 | .storagebits = 16, \ | 25 | .storagebits = (bits) > 16 ? 32 : 16, \ |
| 26 | .endianness = IIO_CPU, \ | ||
| 27 | }, \ | ||
| 28 | } | ||
| 29 | |||
| 30 | #define AD7606_SW_CHANNEL(num, bits) { \ | ||
| 31 | .type = IIO_VOLTAGE, \ | ||
| 32 | .indexed = 1, \ | ||
| 33 | .channel = num, \ | ||
| 34 | .address = num, \ | ||
| 35 | .info_mask_separate = \ | ||
| 36 | BIT(IIO_CHAN_INFO_RAW) | \ | ||
| 37 | BIT(IIO_CHAN_INFO_SCALE), \ | ||
| 38 | .info_mask_separate_available = \ | ||
| 39 | BIT(IIO_CHAN_INFO_SCALE), \ | ||
| 40 | .info_mask_shared_by_all = \ | ||
| 41 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ | ||
| 42 | .info_mask_shared_by_all_available = \ | ||
| 43 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ | ||
| 44 | .scan_index = num, \ | ||
| 45 | .scan_type = { \ | ||
| 46 | .sign = 's', \ | ||
| 47 | .realbits = (bits), \ | ||
| 48 | .storagebits = (bits) > 16 ? 32 : 16, \ | ||
| 24 | .endianness = IIO_CPU, \ | 49 | .endianness = IIO_CPU, \ |
| 25 | }, \ | 50 | }, \ |
| 26 | } | 51 | } |
| 27 | 52 | ||
| 28 | #define AD7605_CHANNEL(num) \ | 53 | #define AD7605_CHANNEL(num) \ |
| 29 | AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ | 54 | AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ |
| 30 | BIT(IIO_CHAN_INFO_SCALE), 0) | 55 | BIT(IIO_CHAN_INFO_SCALE), 0, 16) |
| 31 | 56 | ||
| 32 | #define AD7606_CHANNEL(num) \ | 57 | #define AD7606_CHANNEL(num, bits) \ |
| 33 | AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ | 58 | AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ |
| 34 | BIT(IIO_CHAN_INFO_SCALE), \ | 59 | BIT(IIO_CHAN_INFO_SCALE), \ |
| 35 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) | 60 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), bits) |
| 61 | |||
| 62 | #define AD7616_CHANNEL(num) AD7606_SW_CHANNEL(num, 16) | ||
| 63 | |||
| 64 | #define AD7606_BI_CHANNEL(num) \ | ||
| 65 | AD760X_CHANNEL(num, 0, \ | ||
| 66 | BIT(IIO_CHAN_INFO_SCALE), \ | ||
| 67 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | ||
| 68 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), 16) | ||
| 36 | 69 | ||
| 37 | #define AD7616_CHANNEL(num) \ | 70 | struct ad7606_state; |
| 38 | AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),\ | 71 | |
| 39 | 0, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) | 72 | typedef int (*ad7606_scale_setup_cb_t)(struct ad7606_state *st, |
| 73 | struct iio_chan_spec *chan, int ch); | ||
| 40 | 74 | ||
| 41 | /** | 75 | /** |
| 42 | * struct ad7606_chip_info - chip specific information | 76 | * struct ad7606_chip_info - chip specific information |
| 43 | * @channels: channel specification | 77 | * @channels: channel specification |
| 78 | * @max_samplerate: maximum supported samplerate | ||
| 79 | * @name device name | ||
| 44 | * @num_channels: number of channels | 80 | * @num_channels: number of channels |
| 81 | * @num_adc_channels the number of channels the ADC actually inputs. | ||
| 82 | * @scale_setup_cb: callback to setup the scales for each channel | ||
| 45 | * @oversampling_avail pointer to the array which stores the available | 83 | * @oversampling_avail pointer to the array which stores the available |
| 46 | * oversampling ratios. | 84 | * oversampling ratios. |
| 47 | * @oversampling_num number of elements stored in oversampling_avail array | 85 | * @oversampling_num number of elements stored in oversampling_avail array |
| 48 | * @os_req_reset some devices require a reset to update oversampling | 86 | * @os_req_reset some devices require a reset to update oversampling |
| 49 | * @init_delay_ms required delay in miliseconds for initialization | 87 | * @init_delay_ms required delay in milliseconds for initialization |
| 50 | * after a restart | 88 | * after a restart |
| 51 | */ | 89 | */ |
| 52 | struct ad7606_chip_info { | 90 | struct ad7606_chip_info { |
| 53 | const struct iio_chan_spec *channels; | 91 | const struct iio_chan_spec *channels; |
| 92 | unsigned int max_samplerate; | ||
| 93 | const char *name; | ||
| 94 | unsigned int num_adc_channels; | ||
| 54 | unsigned int num_channels; | 95 | unsigned int num_channels; |
| 96 | ad7606_scale_setup_cb_t scale_setup_cb; | ||
| 55 | const unsigned int *oversampling_avail; | 97 | const unsigned int *oversampling_avail; |
| 56 | unsigned int oversampling_num; | 98 | unsigned int oversampling_num; |
| 57 | bool os_req_reset; | 99 | bool os_req_reset; |
| 58 | unsigned long init_delay_ms; | 100 | unsigned long init_delay_ms; |
| 59 | }; | 101 | }; |
| 60 | 102 | ||
| 103 | /** | ||
| 104 | * struct ad7606_chan_scale - channel scale configuration | ||
| 105 | * @scale_avail pointer to the array which stores the available scales | ||
| 106 | * @num_scales number of elements stored in the scale_avail array | ||
| 107 | * @range voltage range selection, selects which scale to apply | ||
| 108 | * @reg_offset offset for the register value, to be applied when | ||
| 109 | * writing the value of 'range' to the register value | ||
| 110 | */ | ||
| 111 | struct ad7606_chan_scale { | ||
| 112 | #define AD760X_MAX_SCALES 16 | ||
| 113 | const unsigned int (*scale_avail)[2]; | ||
| 114 | unsigned int num_scales; | ||
| 115 | unsigned int range; | ||
| 116 | unsigned int reg_offset; | ||
| 117 | }; | ||
| 118 | |||
| 61 | /** | 119 | /** |
| 62 | * struct ad7606_state - driver instance specific data | 120 | * struct ad7606_state - driver instance specific data |
| 63 | * @dev pointer to kernel device | 121 | * @dev pointer to kernel device |
| 64 | * @chip_info entry in the table of chips that describes this device | 122 | * @chip_info entry in the table of chips that describes this device |
| 65 | * @bops bus operations (SPI or parallel) | 123 | * @bops bus operations (SPI or parallel) |
| 66 | * @range voltage range selection, selects which scale to apply | 124 | * @chan_scales scale configuration for channels |
| 67 | * @oversampling oversampling selection | 125 | * @oversampling oversampling selection |
| 126 | * @cnvst_pwm pointer to the PWM device connected to the cnvst pin | ||
| 68 | * @base_address address from where to read data in parallel operation | 127 | * @base_address address from where to read data in parallel operation |
| 69 | * @sw_mode_en software mode enabled | 128 | * @sw_mode_en software mode enabled |
| 70 | * @scale_avail pointer to the array which stores the available scales | ||
| 71 | * @num_scales number of elements stored in the scale_avail array | ||
| 72 | * @oversampling_avail pointer to the array which stores the available | 129 | * @oversampling_avail pointer to the array which stores the available |
| 73 | * oversampling ratios. | 130 | * oversampling ratios. |
| 74 | * @num_os_ratios number of elements stored in oversampling_avail array | 131 | * @num_os_ratios number of elements stored in oversampling_avail array |
| @@ -92,14 +149,14 @@ struct ad7606_state { · 17 unmodified lines | |||
| 92 | struct device *dev; | 149 | struct device *dev; |
| 93 | const struct ad7606_chip_info *chip_info; | 150 | const struct ad7606_chip_info *chip_info; |
| 94 | const struct ad7606_bus_ops *bops; | 151 | const struct ad7606_bus_ops *bops; |
| 95 | unsigned int range[16]; | 152 | struct ad7606_chan_scale chan_scales[AD760X_MAX_CHANNELS]; |
| 96 | unsigned int oversampling; | 153 | unsigned int oversampling; |
| 154 | struct pwm_device *cnvst_pwm; | ||
| 97 | void __iomem *base_address; | 155 | void __iomem *base_address; |
| 98 | bool sw_mode_en; | 156 | bool sw_mode_en; |
| 99 | const unsigned int *scale_avail; | ||
| 100 | unsigned int num_scales; | ||
| 101 | const unsigned int *oversampling_avail; | 157 | const unsigned int *oversampling_avail; |
| 102 | unsigned int num_os_ratios; | 158 | unsigned int num_os_ratios; |
| 159 | struct iio_backend *back; | ||
| 103 | int (*write_scale)(struct iio_dev *indio_dev, int ch, int val); | 160 | int (*write_scale)(struct iio_dev *indio_dev, int ch, int val); |
| 104 | int (*write_os)(struct iio_dev *indio_dev, int val); | 161 | int (*write_os)(struct iio_dev *indio_dev, int val); |
| 105 | 162 | ||
| @@ -116,24 +173,33 @@ struct ad7606_state { · 10 unmodified lines | |||
| 116 | /* | 173 | /* |
| 117 | * DMA (thus cache coherency maintenance) may require the | 174 | * DMA (thus cache coherency maintenance) may require the |
| 118 | * transfer buffers to live in their own cache lines. | 175 | * transfer buffers to live in their own cache lines. |
| 119 | * 16 * 16-bit samples + 64-bit timestamp | 176 | * 16 * 16-bit samples + 64-bit timestamp - for AD7616 |
| 177 | * 8 * 32-bit samples + 64-bit timestamp - for AD7616C-18 (and similar) | ||
| 120 | */ | 178 | */ |
| 121 | unsigned short data[20] __aligned(IIO_DMA_MINALIGN); | 179 | union { |
| 180 | u16 buf16[20]; | ||
| 181 | u32 buf32[10]; | ||
| 182 | } data __aligned(IIO_DMA_MINALIGN); | ||
| 122 | __be16 d16[2]; | 183 | __be16 d16[2]; |
| 123 | }; | 184 | }; |
| 124 | 185 | ||
| 125 | /** | 186 | /** |
| 126 | * struct ad7606_bus_ops - driver bus operations | 187 | * struct ad7606_bus_ops - driver bus operations |
| 188 | * @iio_backend_config function pointer for configuring the iio_backend for | ||
| 189 | * the compatibles that use it | ||
| 127 | * @read_block function pointer for reading blocks of data | 190 | * @read_block function pointer for reading blocks of data |
| 128 | * @sw_mode_config: pointer to a function which configured the device | 191 | * @sw_mode_config: pointer to a function which configured the device |
| 129 | * for software mode | 192 | * for software mode |
| 130 | * @reg_read function pointer for reading spi register | 193 | * @reg_read function pointer for reading spi register |
| 131 | * @reg_write function pointer for writing spi register | 194 | * @reg_write function pointer for writing spi register |
| 132 | * @write_mask function pointer for write spi register with mask | 195 | * @write_mask function pointer for write spi register with mask |
| 196 | * @update_scan_mode function pointer for handling the calls to iio_info's update_scan | ||
| 197 | * mode when enabling/disabling channels. | ||
| 133 | * @rd_wr_cmd pointer to the function which calculates the spi address | 198 | * @rd_wr_cmd pointer to the function which calculates the spi address |
| 134 | */ | 199 | */ |
| 135 | struct ad7606_bus_ops { | 200 | struct ad7606_bus_ops { |
| 136 | /* more methods added in future? */ | 201 | /* more methods added in future? */ |
| 202 | int (*iio_backend_config)(struct device *dev, struct iio_dev *indio_dev); | ||
| 137 | int (*read_block)(struct device *dev, int num, void *data); | 203 | int (*read_block)(struct device *dev, int num, void *data); |
| 138 | int (*sw_mode_config)(struct iio_dev *indio_dev); | 204 | int (*sw_mode_config)(struct iio_dev *indio_dev); |
| 139 | int (*reg_read)(struct ad7606_state *st, unsigned int addr); | 205 | int (*reg_read)(struct ad7606_state *st, unsigned int addr); |
| @@ -144,23 +210,37 @@ struct ad7606_bus_ops { · 4 unmodified lines | |||
| 144 | unsigned int addr, | 210 | unsigned int addr, |
| 145 | unsigned long mask, | 211 | unsigned long mask, |
| 146 | unsigned int val); | 212 | unsigned int val); |
| 213 | int (*update_scan_mode)(struct iio_dev *indio_dev, const unsigned long *scan_mask); | ||
| 147 | u16 (*rd_wr_cmd)(int addr, char isWriteOp); | 214 | u16 (*rd_wr_cmd)(int addr, char isWriteOp); |
| 148 | }; | 215 | }; |
| 149 | 216 | ||
| 217 | /** | ||
| 218 | * struct ad7606_bus_info - agregate ad7606_chip_info and ad7606_bus_ops | ||
| 219 | * @chip_info entry in the table of chips that describes this device | ||
| 220 | * @bops bus operations (SPI or parallel) | ||
| 221 | */ | ||
| 222 | struct ad7606_bus_info { | ||
| 223 | const struct ad7606_chip_info *chip_info; | ||
| 224 | const struct ad7606_bus_ops *bops; | ||
| 225 | }; | ||
| 226 | |||
| 150 | int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, | 227 | int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, |
| 151 | const char *name, unsigned int id, | 228 | const struct ad7606_chip_info *info, |
| 152 | const struct ad7606_bus_ops *bops); | 229 | const struct ad7606_bus_ops *bops); |
| 153 | 230 | ||
| 154 | int ad7606_reset(struct ad7606_state *st); | 231 | int ad7606_reset(struct ad7606_state *st); |
| 155 | 232 | ||
| 156 | enum ad7606_supported_device_ids { | 233 | extern const struct ad7606_chip_info ad7605_4_info; |
| 157 | ID_AD7605_4, | 234 | extern const struct ad7606_chip_info ad7606_8_info; |
| 158 | ID_AD7606_8, | 235 | extern const struct ad7606_chip_info ad7606_6_info; |
| 159 | ID_AD7606_6, | 236 | extern const struct ad7606_chip_info ad7606_4_info; |
| 160 | ID_AD7606_4, | 237 | extern const struct ad7606_chip_info ad7606b_info; |
| 161 | ID_AD7606B, | 238 | extern const struct ad7606_chip_info ad7606c_16_info; |
| 162 | ID_AD7616, | 239 | extern const struct ad7606_chip_info ad7606c_18_info; |
| 163 | }; | 240 | extern const struct ad7606_chip_info ad7607_info; |
| 241 | extern const struct ad7606_chip_info ad7608_info; | ||
| 242 | extern const struct ad7606_chip_info ad7609_info; | ||
| 243 | extern const struct ad7606_chip_info ad7616_info; | ||
| 164 | 244 | ||
| 165 | #ifdef CONFIG_PM_SLEEP | 245 | #ifdef CONFIG_PM_SLEEP |
| 166 | extern const struct dev_pm_ops ad7606_pm_ops; | 246 | extern const struct dev_pm_ops ad7606_pm_ops; |
| @@ -2,20 +2,95 @@ · 1 unmodified line | |||
| 2 | /* | 2 | /* |
| 3 | * AD7606 Parallel Interface ADC driver | 3 | * AD7606 Parallel Interface ADC driver |
| 4 | * | 4 | * |
| 5 | * Copyright 2011 Analog Devices Inc. | 5 | * Copyright 2011 - 2024 Analog Devices Inc. |
| 6 | * Copyright 2024 BayLibre SAS. | ||
| 6 | */ | 7 | */ |
| 7 | 8 | ||
| 9 | #include <linux/err.h> | ||
| 10 | #include <linux/gpio/consumer.h> | ||
| 11 | #include <linux/io.h> | ||
| 8 | #include <linux/mod_devicetable.h> | 12 | #include <linux/mod_devicetable.h> |
| 9 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 10 | #include <linux/gpio/consumer.h> | ||
| 11 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
| 15 | #include <linux/property.h> | ||
| 12 | #include <linux/types.h> | 16 | #include <linux/types.h> |
| 13 | #include <linux/err.h> | ||
| 14 | #include <linux/io.h> | ||
| 15 | 17 | ||
| 18 | #include <linux/iio/backend.h> | ||
| 16 | #include <linux/iio/iio.h> | 19 | #include <linux/iio/iio.h> |
| 20 | |||
| 17 | #include "ad7606.h" | 21 | #include "ad7606.h" |
| 18 | 22 | ||
| 23 | static const struct iio_chan_spec ad7606b_bi_channels[] = { | ||
| 24 | AD7606_BI_CHANNEL(0), | ||
| 25 | AD7606_BI_CHANNEL(1), | ||
| 26 | AD7606_BI_CHANNEL(2), | ||
| 27 | AD7606_BI_CHANNEL(3), | ||
| 28 | AD7606_BI_CHANNEL(4), | ||
| 29 | AD7606_BI_CHANNEL(5), | ||
| 30 | AD7606_BI_CHANNEL(6), | ||
| 31 | AD7606_BI_CHANNEL(7), | ||
| 32 | }; | ||
| 33 | |||
| 34 | static int ad7606_bi_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *scan_mask) | ||
| 35 | { | ||
| 36 | struct ad7606_state *st = iio_priv(indio_dev); | ||
| 37 | unsigned int c, ret; | ||
| 38 | |||
| 39 | for (c = 0; c < indio_dev->num_channels; c++) { | ||
| 40 | if (test_bit(c, scan_mask)) | ||
| 41 | ret = iio_backend_chan_enable(st->back, c); | ||
| 42 | else | ||
| 43 | ret = iio_backend_chan_disable(st->back, c); | ||
| 44 | if (ret) | ||
| 45 | return ret; | ||
| 46 | } | ||
| 47 | |||
| 48 | return 0; | ||
| 49 | } | ||
| 50 | |||
| 51 | static int ad7606_bi_setup_iio_backend(struct device *dev, struct iio_dev *indio_dev) | ||
| 52 | { | ||
| 53 | struct ad7606_state *st = iio_priv(indio_dev); | ||
| 54 | unsigned int ret, c; | ||
| 55 | struct iio_backend_data_fmt data = { | ||
| 56 | .sign_extend = true, | ||
| 57 | .enable = true, | ||
| 58 | }; | ||
| 59 | |||
| 60 | st->back = devm_iio_backend_get(dev, NULL); | ||
| 61 | if (IS_ERR(st->back)) | ||
| 62 | return PTR_ERR(st->back); | ||
| 63 | |||
| 64 | /* If the device is iio_backend powered the PWM is mandatory */ | ||
| 65 | if (!st->cnvst_pwm) | ||
| 66 | return dev_err_probe(st->dev, -EINVAL, | ||
| 67 | "A PWM is mandatory when using backend.\n"); | ||
| 68 | |||
| 69 | ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev); | ||
| 70 | if (ret) | ||
| 71 | return ret; | ||
| 72 | |||
| 73 | ret = devm_iio_backend_enable(dev, st->back); | ||
| 74 | if (ret) | ||
| 75 | return ret; | ||
| 76 | |||
| 77 | for (c = 0; c < indio_dev->num_channels; c++) { | ||
| 78 | ret = iio_backend_data_format_set(st->back, c, &data); | ||
| 79 | if (ret) | ||
| 80 | return ret; | ||
| 81 | } | ||
| 82 | |||
| 83 | indio_dev->channels = ad7606b_bi_channels; | ||
| 84 | indio_dev->num_channels = 8; | ||
| 85 | |||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | static const struct ad7606_bus_ops ad7606_bi_bops = { | ||
| 90 | .iio_backend_config = ad7606_bi_setup_iio_backend, | ||
| 91 | .update_scan_mode = ad7606_bi_update_scan_mode, | ||
| 92 | }; | ||
| 93 | |||
| 19 | static int ad7606_par16_read_block(struct device *dev, | 94 | static int ad7606_par16_read_block(struct device *dev, |
| 20 | int count, void *buf) | 95 | int count, void *buf) |
| 21 | { | 96 | { |
| @@ -89,12 +164,32 @@ static const struct ad7606_bus_ops ad7606_par8_bops = { · 67 unmodified lines | |||
| 89 | 164 | ||
| 90 | static int ad7606_par_probe(struct platform_device *pdev) | 165 | static int ad7606_par_probe(struct platform_device *pdev) |
| 91 | { | 166 | { |
| 92 | const struct platform_device_id *id = platform_get_device_id(pdev); | 167 | const struct ad7606_chip_info *chip_info; |
| 168 | const struct platform_device_id *id; | ||
| 93 | struct resource *res; | 169 | struct resource *res; |
| 94 | void __iomem *addr; | 170 | void __iomem *addr; |
| 95 | resource_size_t remap_size; | 171 | resource_size_t remap_size; |
| 96 | int irq; | 172 | int irq; |
| 97 | 173 | ||
| 174 | /* | ||
| 175 | * If a firmware node is available (ACPI or DT), platform_device_id is null | ||
| 176 | * and we must use get_match_data. | ||
| 177 | */ | ||
| 178 | if (dev_fwnode(&pdev->dev)) { | ||
| 179 | chip_info = device_get_match_data(&pdev->dev); | ||
| 180 | if (device_property_present(&pdev->dev, "io-backends")) | ||
| 181 | /* | ||
| 182 | * If a backend is available ,call the core probe with backend | ||
| 183 | * bops, otherwise use the former bops. | ||
| 184 | */ | ||
| 185 | return ad7606_probe(&pdev->dev, 0, NULL, | ||
| 186 | chip_info, | ||
| 187 | &ad7606_bi_bops); | ||
| 188 | } else { | ||
| 189 | id = platform_get_device_id(pdev); | ||
| 190 | chip_info = (const struct ad7606_chip_info *)id->driver_data; | ||
| 191 | } | ||
| 192 | |||
| 98 | irq = platform_get_irq(pdev, 0); | 193 | irq = platform_get_irq(pdev, 0); |
| 99 | if (irq < 0) | 194 | if (irq < 0) |
| 100 | return irq; | 195 | return irq; |
| @@ -105,26 +200,33 @@ static int ad7606_par_probe(struct platform_device *pdev) · 4 unmodified lines | |||
| 105 | 200 | ||
| 106 | remap_size = resource_size(res); | 201 | remap_size = resource_size(res); |
| 107 | 202 | ||
| 108 | return ad7606_probe(&pdev->dev, irq, addr, | 203 | return ad7606_probe(&pdev->dev, irq, addr, chip_info, |
| 109 | id->name, id->driver_data, | ||
| 110 | remap_size > 1 ? &ad7606_par16_bops : | 204 | remap_size > 1 ? &ad7606_par16_bops : |
| 111 | &ad7606_par8_bops); | 205 | &ad7606_par8_bops); |
| 112 | } | 206 | } |
| 113 | 207 | ||
| 114 | static const struct platform_device_id ad7606_driver_ids[] = { | 208 | static const struct platform_device_id ad7606_driver_ids[] = { |
| 115 | { .name = "ad7605-4", .driver_data = ID_AD7605_4, }, | 209 | { .name = "ad7605-4", .driver_data = (kernel_ulong_t)&ad7605_4_info, }, |
| 116 | { .name = "ad7606-4", .driver_data = ID_AD7606_4, }, | 210 | { .name = "ad7606-4", .driver_data = (kernel_ulong_t)&ad7606_4_info, }, |
| 117 | { .name = "ad7606-6", .driver_data = ID_AD7606_6, }, | 211 | { .name = "ad7606-6", .driver_data = (kernel_ulong_t)&ad7606_6_info, }, |
| 118 | { .name = "ad7606-8", .driver_data = ID_AD7606_8, }, | 212 | { .name = "ad7606-8", .driver_data = (kernel_ulong_t)&ad7606_8_info, }, |
| 213 | { .name = "ad7606b", .driver_data = (kernel_ulong_t)&ad7606b_info, }, | ||
| 214 | { .name = "ad7607", .driver_data = (kernel_ulong_t)&ad7607_info, }, | ||
| 215 | { .name = "ad7608", .driver_data = (kernel_ulong_t)&ad7608_info, }, | ||
| 216 | { .name = "ad7609", .driver_data = (kernel_ulong_t)&ad7609_info, }, | ||
| 119 | { } | 217 | { } |
| 120 | }; | 218 | }; |
| 121 | MODULE_DEVICE_TABLE(platform, ad7606_driver_ids); | 219 | MODULE_DEVICE_TABLE(platform, ad7606_driver_ids); |
| 122 | 220 | ||
| 123 | static const struct of_device_id ad7606_of_match[] = { | 221 | static const struct of_device_id ad7606_of_match[] = { |
| 124 | { .compatible = "adi,ad7605-4" }, | 222 | { .compatible = "adi,ad7605-4", .data = &ad7605_4_info }, |
| 125 | { .compatible = "adi,ad7606-4" }, | 223 | { .compatible = "adi,ad7606-4", .data = &ad7606_4_info }, |
| 126 | { .compatible = "adi,ad7606-6" }, | 224 | { .compatible = "adi,ad7606-6", .data = &ad7606_6_info }, |
| 127 | { .compatible = "adi,ad7606-8" }, | 225 | { .compatible = "adi,ad7606-8", .data = &ad7606_8_info }, |
| 226 | { .compatible = "adi,ad7606b", .data = &ad7606b_info }, | ||
| 227 | { .compatible = "adi,ad7607", .data = &ad7607_info }, | ||
| 228 | { .compatible = "adi,ad7608", .data = &ad7608_info }, | ||
| 229 | { .compatible = "adi,ad7609", .data = &ad7609_info }, | ||
| 128 | { } | 230 | { } |
| 129 | }; | 231 | }; |
| 130 | MODULE_DEVICE_TABLE(of, ad7606_of_match); | 232 | MODULE_DEVICE_TABLE(of, ad7606_of_match); |
| @@ -144,3 +246,4 @@ MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); · 13 unmodified lines | |||
| 144 | MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); | 246 | MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); |
| 145 | MODULE_LICENSE("GPL v2"); | 247 | MODULE_LICENSE("GPL v2"); |
| 146 | MODULE_IMPORT_NS(IIO_AD7606); | 248 | MODULE_IMPORT_NS(IIO_AD7606); |
| 249 | MODULE_IMPORT_NS(IIO_BACKEND); | ||
| @@ -5,10 +5,10 @@ · 4 unmodified lines | |||
| 5 | * Copyright 2011 Analog Devices Inc. | 5 | * Copyright 2011 Analog Devices Inc. |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include <linux/err.h> | ||
| 8 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 9 | #include <linux/spi/spi.h> | 10 | #include <linux/spi/spi.h> |
| 10 | #include <linux/types.h> | 11 | #include <linux/types.h> |
| 11 | #include <linux/err.h> | ||
| 12 | 12 | ||
| 13 | #include <linux/iio/iio.h> | 13 | #include <linux/iio/iio.h> |
| 14 | #include "ad7606.h" | 14 | #include "ad7606.h" |
| @@ -67,14 +67,26 @@ static const struct iio_chan_spec ad7616_sw_channels[] = { · 52 unmodified lines | |||
| 67 | 67 | ||
| 68 | static const struct iio_chan_spec ad7606b_sw_channels[] = { | 68 | static const struct iio_chan_spec ad7606b_sw_channels[] = { |
| 69 | IIO_CHAN_SOFT_TIMESTAMP(8), | 69 | IIO_CHAN_SOFT_TIMESTAMP(8), |
| 70 | AD7616_CHANNEL(0), | 70 | AD7606_SW_CHANNEL(0, 16), |
| 71 | AD7616_CHANNEL(1), | 71 | AD7606_SW_CHANNEL(1, 16), |
| 72 | AD7616_CHANNEL(2), | 72 | AD7606_SW_CHANNEL(2, 16), |
| 73 | AD7616_CHANNEL(3), | 73 | AD7606_SW_CHANNEL(3, 16), |
| 74 | AD7616_CHANNEL(4), | 74 | AD7606_SW_CHANNEL(4, 16), |
| 75 | AD7616_CHANNEL(5), | 75 | AD7606_SW_CHANNEL(5, 16), |
| 76 | AD7616_CHANNEL(6), | 76 | AD7606_SW_CHANNEL(6, 16), |
| 77 | AD7616_CHANNEL(7), | 77 | AD7606_SW_CHANNEL(7, 16), |
| 78 | }; | ||
| 79 | |||
| 80 | static const struct iio_chan_spec ad7606c_18_sw_channels[] = { | ||
| 81 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
| 82 | AD7606_SW_CHANNEL(0, 18), | ||
| 83 | AD7606_SW_CHANNEL(1, 18), | ||
| 84 | AD7606_SW_CHANNEL(2, 18), | ||
| 85 | AD7606_SW_CHANNEL(3, 18), | ||
| 86 | AD7606_SW_CHANNEL(4, 18), | ||
| 87 | AD7606_SW_CHANNEL(5, 18), | ||
| 88 | AD7606_SW_CHANNEL(6, 18), | ||
| 89 | AD7606_SW_CHANNEL(7, 18), | ||
| 78 | }; | 90 | }; |
| 79 | 91 | ||
| 80 | static const unsigned int ad7606B_oversampling_avail[9] = { | 92 | static const unsigned int ad7606B_oversampling_avail[9] = { |
| @@ -120,6 +132,32 @@ static int ad7606_spi_read_block(struct device *dev, · 39 unmodified lines | |||
| 120 | return 0; | 132 | return 0; |
| 121 | } | 133 | } |
| 122 | 134 | ||
| 135 | static int ad7606_spi_read_block14to16(struct device *dev, | ||
| 136 | int count, void *buf) | ||
| 137 | { | ||
| 138 | struct spi_device *spi = to_spi_device(dev); | ||
| 139 | struct spi_transfer xfer = { | ||
| 140 | .bits_per_word = 14, | ||
| 141 | .len = count * sizeof(u16), | ||
| 142 | .rx_buf = buf, | ||
| 143 | }; | ||
| 144 | |||
| 145 | return spi_sync_transfer(spi, &xfer, 1); | ||
| 146 | } | ||
| 147 | |||
| 148 | static int ad7606_spi_read_block18to32(struct device *dev, | ||
| 149 | int count, void *buf) | ||
| 150 | { | ||
| 151 | struct spi_device *spi = to_spi_device(dev); | ||
| 152 | struct spi_transfer xfer = { | ||
| 153 | .bits_per_word = 18, | ||
| 154 | .len = count * sizeof(u32), | ||
| 155 | .rx_buf = buf, | ||
| 156 | }; | ||
| 157 | |||
| 158 | return spi_sync_transfer(spi, &xfer, 1); | ||
| 159 | } | ||
| 160 | |||
| 123 | static int ad7606_spi_reg_read(struct ad7606_state *st, unsigned int addr) | 161 | static int ad7606_spi_reg_read(struct ad7606_state *st, unsigned int addr) |
| 124 | { | 162 | { |
| 125 | struct spi_device *spi = to_spi_device(st->dev); | 163 | struct spi_device *spi = to_spi_device(st->dev); |
| @@ -283,10 +321,31 @@ static int ad7606B_sw_mode_config(struct iio_dev *indio_dev) · 157 unmodified lines | |||
| 283 | return 0; | 321 | return 0; |
| 284 | } | 322 | } |
| 285 | 323 | ||
| 324 | static int ad7606c_18_sw_mode_config(struct iio_dev *indio_dev) | ||
| 325 | { | ||
| 326 | int ret; | ||
| 327 | |||
| 328 | ret = ad7606B_sw_mode_config(indio_dev); | ||
| 329 | if (ret) | ||
| 330 | return ret; | ||
| 331 | |||
| 332 | indio_dev->channels = ad7606c_18_sw_channels; | ||
| 333 | |||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 286 | static const struct ad7606_bus_ops ad7606_spi_bops = { | 337 | static const struct ad7606_bus_ops ad7606_spi_bops = { |
| 287 | .read_block = ad7606_spi_read_block, | 338 | .read_block = ad7606_spi_read_block, |
| 288 | }; | 339 | }; |
| 289 | 340 | ||
| 341 | static const struct ad7606_bus_ops ad7607_spi_bops = { | ||
| 342 | .read_block = ad7606_spi_read_block14to16, | ||
| 343 | }; | ||
| 344 | |||
| 345 | static const struct ad7606_bus_ops ad7608_spi_bops = { | ||
| 346 | .read_block = ad7606_spi_read_block18to32, | ||
| 347 | }; | ||
| 348 | |||
| 290 | static const struct ad7606_bus_ops ad7616_spi_bops = { | 349 | static const struct ad7606_bus_ops ad7616_spi_bops = { |
| 291 | .read_block = ad7606_spi_read_block, | 350 | .read_block = ad7606_spi_read_block, |
| 292 | .reg_read = ad7606_spi_reg_read, | 351 | .reg_read = ad7606_spi_reg_read, |
| @@ -296,7 +355,7 @@ static const struct ad7606_bus_ops ad7616_spi_bops = { · 3 unmodified lines | |||
| 296 | .sw_mode_config = ad7616_sw_mode_config, | 355 | .sw_mode_config = ad7616_sw_mode_config, |
| 297 | }; | 356 | }; |
| 298 | 357 | ||
| 299 | static const struct ad7606_bus_ops ad7606B_spi_bops = { | 358 | static const struct ad7606_bus_ops ad7606b_spi_bops = { |
| 300 | .read_block = ad7606_spi_read_block, | 359 | .read_block = ad7606_spi_read_block, |
| 301 | .reg_read = ad7606_spi_reg_read, | 360 | .reg_read = ad7606_spi_reg_read, |
| 302 | .reg_write = ad7606_spi_reg_write, | 361 | .reg_write = ad7606_spi_reg_write, |
| @@ -305,46 +364,106 @@ static const struct ad7606_bus_ops ad7606B_spi_bops = { · 2 unmodified lines | |||
| 305 | .sw_mode_config = ad7606B_sw_mode_config, | 364 | .sw_mode_config = ad7606B_sw_mode_config, |
| 306 | }; | 365 | }; |
| 307 | 366 | ||
| 367 | static const struct ad7606_bus_ops ad7606c_18_spi_bops = { | ||
| 368 | .read_block = ad7606_spi_read_block18to32, | ||
| 369 | .reg_read = ad7606_spi_reg_read, | ||
| 370 | .reg_write = ad7606_spi_reg_write, | ||
| 371 | .write_mask = ad7606_spi_write_mask, | ||
| 372 | .rd_wr_cmd = ad7606B_spi_rd_wr_cmd, | ||
| 373 | .sw_mode_config = ad7606c_18_sw_mode_config, | ||
| 374 | }; | ||
| 375 | |||
| 376 | static const struct ad7606_bus_info ad7605_4_bus_info = { | ||
| 377 | .chip_info = &ad7605_4_info, | ||
| 378 | .bops = &ad7606_spi_bops, | ||
| 379 | }; | ||
| 380 | |||
| 381 | static const struct ad7606_bus_info ad7606_8_bus_info = { | ||
| 382 | .chip_info = &ad7606_8_info, | ||
| 383 | .bops = &ad7606_spi_bops, | ||
| 384 | }; | ||
| 385 | |||
| 386 | static const struct ad7606_bus_info ad7606_6_bus_info = { | ||
| 387 | .chip_info = &ad7606_6_info, | ||
| 388 | .bops = &ad7606_spi_bops, | ||
| 389 | }; | ||
| 390 | |||
| 391 | static const struct ad7606_bus_info ad7606_4_bus_info = { | ||
| 392 | .chip_info = &ad7606_4_info, | ||
| 393 | .bops = &ad7606_spi_bops, | ||
| 394 | }; | ||
| 395 | |||
| 396 | static const struct ad7606_bus_info ad7606b_bus_info = { | ||
| 397 | .chip_info = &ad7606b_info, | ||
| 398 | .bops = &ad7606b_spi_bops, | ||
| 399 | }; | ||
| 400 | |||
| 401 | static const struct ad7606_bus_info ad7606c_16_bus_info = { | ||
| 402 | .chip_info = &ad7606c_16_info, | ||
| 403 | .bops = &ad7606b_spi_bops, | ||
| 404 | }; | ||
| 405 | |||
| 406 | static const struct ad7606_bus_info ad7606c_18_bus_info = { | ||
| 407 | .chip_info = &ad7606c_18_info, | ||
| 408 | .bops = &ad7606c_18_spi_bops, | ||
| 409 | }; | ||
| 410 | |||
| 411 | static const struct ad7606_bus_info ad7607_bus_info = { | ||
| 412 | .chip_info = &ad7607_info, | ||
| 413 | .bops = &ad7607_spi_bops, | ||
| 414 | }; | ||
| 415 | |||
| 416 | static const struct ad7606_bus_info ad7608_bus_info = { | ||
| 417 | .chip_info = &ad7608_info, | ||
| 418 | .bops = &ad7608_spi_bops, | ||
| 419 | }; | ||
| 420 | |||
| 421 | static const struct ad7606_bus_info ad7609_bus_info = { | ||
| 422 | .chip_info = &ad7609_info, | ||
| 423 | .bops = &ad7608_spi_bops, | ||
| 424 | }; | ||
| 425 | |||
| 426 | static const struct ad7606_bus_info ad7616_bus_info = { | ||
| 427 | .chip_info = &ad7616_info, | ||
| 428 | .bops = &ad7616_spi_bops, | ||
| 429 | }; | ||
| 430 | |||
| 308 | static int ad7606_spi_probe(struct spi_device *spi) | 431 | static int ad7606_spi_probe(struct spi_device *spi) |
| 309 | { | 432 | { |
| 310 | const struct spi_device_id *id = spi_get_device_id(spi); | 433 | const struct ad7606_bus_info *bus_info = spi_get_device_match_data(spi); |
| 311 | const struct ad7606_bus_ops *bops; | ||
| 312 | |||
| 313 | switch (id->driver_data) { | ||
| 314 | case ID_AD7616: | ||
| 315 | bops = &ad7616_spi_bops; | ||
| 316 | break; | ||
| 317 | case ID_AD7606B: | ||
| 318 | bops = &ad7606B_spi_bops; | ||
| 319 | break; | ||
| 320 | default: | ||
| 321 | bops = &ad7606_spi_bops; | ||
| 322 | break; | ||
| 323 | } | ||
| 324 | 434 | ||
| 325 | return ad7606_probe(&spi->dev, spi->irq, NULL, | 435 | return ad7606_probe(&spi->dev, spi->irq, NULL, |
| 326 | id->name, id->driver_data, | 436 | bus_info->chip_info, bus_info->bops); |
| 327 | bops); | ||
| 328 | } | 437 | } |
| 329 | 438 | ||
| 330 | static const struct spi_device_id ad7606_id_table[] = { | 439 | static const struct spi_device_id ad7606_id_table[] = { |
| 331 | { "ad7605-4", ID_AD7605_4 }, | 440 | { "ad7605-4", (kernel_ulong_t)&ad7605_4_bus_info }, |
| 332 | { "ad7606-4", ID_AD7606_4 }, | 441 | { "ad7606-4", (kernel_ulong_t)&ad7606_4_bus_info }, |
| 333 | { "ad7606-6", ID_AD7606_6 }, | 442 | { "ad7606-6", (kernel_ulong_t)&ad7606_6_bus_info }, |
| 334 | { "ad7606-8", ID_AD7606_8 }, | 443 | { "ad7606-8", (kernel_ulong_t)&ad7606_8_bus_info }, |
| 335 | { "ad7606b", ID_AD7606B }, | 444 | { "ad7606b", (kernel_ulong_t)&ad7606b_bus_info }, |
| 336 | { "ad7616", ID_AD7616 }, | 445 | { "ad7606c-16", (kernel_ulong_t)&ad7606c_16_bus_info }, |
| 446 | { "ad7606c-18", (kernel_ulong_t)&ad7606c_18_bus_info }, | ||
| 447 | { "ad7607", (kernel_ulong_t)&ad7607_bus_info }, | ||
| 448 | { "ad7608", (kernel_ulong_t)&ad7608_bus_info }, | ||
| 449 | { "ad7609", (kernel_ulong_t)&ad7609_bus_info }, | ||
| 450 | { "ad7616", (kernel_ulong_t)&ad7616_bus_info }, | ||
| 337 | { } | 451 | { } |
| 338 | }; | 452 | }; |
| 339 | MODULE_DEVICE_TABLE(spi, ad7606_id_table); | 453 | MODULE_DEVICE_TABLE(spi, ad7606_id_table); |
| 340 | 454 | ||
| 341 | static const struct of_device_id ad7606_of_match[] = { | 455 | static const struct of_device_id ad7606_of_match[] = { |
| 342 | { .compatible = "adi,ad7605-4" }, | 456 | { .compatible = "adi,ad7605-4", .data = &ad7605_4_bus_info }, |
| 343 | { .compatible = "adi,ad7606-4" }, | 457 | { .compatible = "adi,ad7606-4", .data = &ad7606_4_bus_info }, |
| 344 | { .compatible = "adi,ad7606-6" }, | 458 | { .compatible = "adi,ad7606-6", .data = &ad7606_6_bus_info }, |
| 345 | { .compatible = "adi,ad7606-8" }, | 459 | { .compatible = "adi,ad7606-8", .data = &ad7606_8_bus_info }, |
| 346 | { .compatible = "adi,ad7606b" }, | 460 | { .compatible = "adi,ad7606b", .data = &ad7606b_bus_info }, |
| 347 | { .compatible = "adi,ad7616" }, | 461 | { .compatible = "adi,ad7606c-16", .data = &ad7606c_16_bus_info }, |
| 462 | { .compatible = "adi,ad7606c-18", .data = &ad7606c_18_bus_info }, | ||
| 463 | { .compatible = "adi,ad7607", .data = &ad7607_bus_info }, | ||
| 464 | { .compatible = "adi,ad7608", .data = &ad7608_bus_info }, | ||
| 465 | { .compatible = "adi,ad7609", .data = &ad7609_bus_info }, | ||
| 466 | { .compatible = "adi,ad7616", .data = &ad7616_bus_info }, | ||
| 348 | { } | 467 | { } |
| 349 | }; | 468 | }; |
| 350 | MODULE_DEVICE_TABLE(of, ad7606_of_match); | 469 | MODULE_DEVICE_TABLE(of, ad7606_of_match); |
| @@ -0,0 +1,684 @@ | |||
| 1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) | ||
| 2 | /* | ||
| 3 | * Analog Devices Inc. AD7625 ADC driver | ||
| 4 | * | ||
| 5 | * Copyright 2024 Analog Devices Inc. | ||
| 6 | * Copyright 2024 BayLibre, SAS | ||
| 7 | * | ||
| 8 | * Note that this driver requires the AXI ADC IP block configured for | ||
| 9 | * LVDS to function. See Documentation/iio/ad7625.rst for more | ||
| 10 | * information. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/clk.h> | ||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/gpio/consumer.h> | ||
| 17 | #include <linux/iio/backend.h> | ||
| 18 | #include <linux/iio/iio.h> | ||
| 19 | #include <linux/kernel.h> | ||
| 20 | #include <linux/mod_devicetable.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/platform_device.h> | ||
| 23 | #include <linux/pwm.h> | ||
| 24 | #include <linux/regulator/consumer.h> | ||
| 25 | #include <linux/units.h> | ||
| 26 | |||
| 27 | #define AD7625_INTERNAL_REF_MV 4096 | ||
| 28 | #define AD7960_MAX_NBW_FREQ (2 * MEGA) | ||
| 29 | |||
| 30 | struct ad7625_timing_spec { | ||
| 31 | /* Max conversion high time (t_{CNVH}). */ | ||
| 32 | unsigned int conv_high_ns; | ||
| 33 | /* Max conversion to MSB delay (t_{MSB}). */ | ||
| 34 | unsigned int conv_msb_ns; | ||
| 35 | }; | ||
| 36 | |||
| 37 | struct ad7625_chip_info { | ||
| 38 | const char *name; | ||
| 39 | const unsigned int max_sample_freq_hz; | ||
| 40 | const struct ad7625_timing_spec *timing_spec; | ||
| 41 | const struct iio_chan_spec chan_spec; | ||
| 42 | const bool has_power_down_state; | ||
| 43 | const bool has_bandwidth_control; | ||
| 44 | const bool has_internal_vref; | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* AD7625_CHAN_SPEC - Define a chan spec structure for a specific chip */ | ||
| 48 | #define AD7625_CHAN_SPEC(_bits) { \ | ||
| 49 | .type = IIO_VOLTAGE, \ | ||
| 50 | .indexed = 1, \ | ||
| 51 | .differential = 1, \ | ||
| 52 | .channel = 0, \ | ||
| 53 | .channel2 = 1, \ | ||
| 54 | .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE), \ | ||
| 55 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | ||
| 56 | .scan_index = 0, \ | ||
| 57 | .scan_type.sign = 's', \ | ||
| 58 | .scan_type.storagebits = (_bits) > 16 ? 32 : 16, \ | ||
| 59 | .scan_type.realbits = (_bits), \ | ||
| 60 | } | ||
| 61 | |||
| 62 | struct ad7625_state { | ||
| 63 | const struct ad7625_chip_info *info; | ||
| 64 | struct iio_backend *back; | ||
| 65 | /* rate of the clock gated by the "clk_gate" PWM */ | ||
| 66 | u32 ref_clk_rate_hz; | ||
| 67 | /* PWM burst signal for transferring acquired data to the host */ | ||
| 68 | struct pwm_device *clk_gate_pwm; | ||
| 69 | /* | ||
| 70 | * PWM control signal for initiating data conversion. Analog | ||
| 71 | * inputs are sampled beginning on this signal's rising edge. | ||
| 72 | */ | ||
| 73 | struct pwm_device *cnv_pwm; | ||
| 74 | /* | ||
| 75 | * Waveforms containing the last-requested and rounded | ||
| 76 | * properties for the clk_gate and cnv PWMs | ||
| 77 | */ | ||
| 78 | struct pwm_waveform clk_gate_wf; | ||
| 79 | struct pwm_waveform cnv_wf; | ||
| 80 | unsigned int vref_mv; | ||
| 81 | u32 sampling_freq_hz; | ||
| 82 | /* | ||
| 83 | * Optional GPIOs for controlling device state. EN0 and EN1 | ||
| 84 | * determine voltage reference configuration and on/off state. | ||
| 85 | * EN2 controls the device -3dB bandwidth (and by extension, max | ||
| 86 | * sample rate). EN3 controls the VCM reference output. EN2 and | ||
| 87 | * EN3 are only present for the AD796x devices. | ||
| 88 | */ | ||
| 89 | struct gpio_desc *en_gpios[4]; | ||
| 90 | bool can_power_down; | ||
| 91 | bool can_refin; | ||
| 92 | bool can_ref_4v096; | ||
| 93 | /* | ||
| 94 | * Indicate whether the bandwidth can be narrow (9MHz). | ||
| 95 | * When true, device sample rate must also be < 2MSPS. | ||
| 96 | */ | ||
| 97 | bool can_narrow_bandwidth; | ||
| 98 | /* Indicate whether the bandwidth can be wide (28MHz). */ | ||
| 99 | bool can_wide_bandwidth; | ||
| 100 | bool can_ref_5v; | ||
| 101 | bool can_snooze; | ||
| 102 | bool can_test_pattern; | ||
| 103 | /* Indicate whether there is a REFIN supply connected */ | ||
| 104 | bool have_refin; | ||
| 105 | }; | ||
| 106 | |||
| 107 | static const struct ad7625_timing_spec ad7625_timing_spec = { | ||
| 108 | .conv_high_ns = 40, | ||
| 109 | .conv_msb_ns = 145, | ||
| 110 | }; | ||
| 111 | |||
| 112 | static const struct ad7625_timing_spec ad7626_timing_spec = { | ||
| 113 | .conv_high_ns = 40, | ||
| 114 | .conv_msb_ns = 80, | ||
| 115 | }; | ||
| 116 | |||
| 117 | /* | ||
| 118 | * conv_msb_ns is set to 0 instead of the datasheet maximum of 200ns to | ||
| 119 | * avoid exceeding the minimum conversion time, i.e. it is effectively | ||
| 120 | * modulo 200 and offset by a full period. Values greater than or equal | ||
| 121 | * to the period would be rejected by the PWM API. | ||
| 122 | */ | ||
| 123 | static const struct ad7625_timing_spec ad7960_timing_spec = { | ||
| 124 | .conv_high_ns = 80, | ||
| 125 | .conv_msb_ns = 0, | ||
| 126 | }; | ||
| 127 | |||
| 128 | static const struct ad7625_chip_info ad7625_chip_info = { | ||
| 129 | .name = "ad7625", | ||
| 130 | .max_sample_freq_hz = 6 * MEGA, | ||
| 131 | .timing_spec = &ad7625_timing_spec, | ||
| 132 | .chan_spec = AD7625_CHAN_SPEC(16), | ||
| 133 | .has_power_down_state = false, | ||
| 134 | .has_bandwidth_control = false, | ||
| 135 | .has_internal_vref = true, | ||
| 136 | }; | ||
| 137 | |||
| 138 | static const struct ad7625_chip_info ad7626_chip_info = { | ||
| 139 | .name = "ad7626", | ||
| 140 | .max_sample_freq_hz = 10 * MEGA, | ||
| 141 | .timing_spec = &ad7626_timing_spec, | ||
| 142 | .chan_spec = AD7625_CHAN_SPEC(16), | ||
| 143 | .has_power_down_state = true, | ||
| 144 | .has_bandwidth_control = false, | ||
| 145 | .has_internal_vref = true, | ||
| 146 | }; | ||
| 147 | |||
| 148 | static const struct ad7625_chip_info ad7960_chip_info = { | ||
| 149 | .name = "ad7960", | ||
| 150 | .max_sample_freq_hz = 5 * MEGA, | ||
| 151 | .timing_spec = &ad7960_timing_spec, | ||
| 152 | .chan_spec = AD7625_CHAN_SPEC(18), | ||
| 153 | .has_power_down_state = true, | ||
| 154 | .has_bandwidth_control = true, | ||
| 155 | .has_internal_vref = false, | ||
| 156 | }; | ||
| 157 | |||
| 158 | static const struct ad7625_chip_info ad7961_chip_info = { | ||
| 159 | .name = "ad7961", | ||
| 160 | .max_sample_freq_hz = 5 * MEGA, | ||
| 161 | .timing_spec = &ad7960_timing_spec, | ||
| 162 | .chan_spec = AD7625_CHAN_SPEC(16), | ||
| 163 | .has_power_down_state = true, | ||
| 164 | .has_bandwidth_control = true, | ||
| 165 | .has_internal_vref = false, | ||
| 166 | }; | ||
| 167 | |||
| 168 | enum ad7960_mode { | ||
| 169 | AD7960_MODE_POWER_DOWN, | ||
| 170 | AD7960_MODE_SNOOZE, | ||
| 171 | AD7960_MODE_NARROW_BANDWIDTH, | ||
| 172 | AD7960_MODE_WIDE_BANDWIDTH, | ||
| 173 | AD7960_MODE_TEST_PATTERN, | ||
| 174 | }; | ||
| 175 | |||
| 176 | static int ad7625_set_sampling_freq(struct ad7625_state *st, u32 freq) | ||
| 177 | { | ||
| 178 | u32 target; | ||
| 179 | struct pwm_waveform clk_gate_wf = { }, cnv_wf = { }; | ||
| 180 | int ret; | ||
| 181 | |||
| 182 | target = DIV_ROUND_UP(NSEC_PER_SEC, freq); | ||
| 183 | cnv_wf.period_length_ns = clamp(target, 100, 10 * KILO); | ||
| 184 | |||
| 185 | /* | ||
| 186 | * Use the maximum conversion time t_CNVH from the datasheet as | ||
| 187 | * the duty_cycle for ref_clk, cnv, and clk_gate | ||
| 188 | */ | ||
| 189 | cnv_wf.duty_length_ns = st->info->timing_spec->conv_high_ns; | ||
| 190 | |||
| 191 | ret = pwm_round_waveform_might_sleep(st->cnv_pwm, &cnv_wf); | ||
| 192 | if (ret) | ||
| 193 | return ret; | ||
| 194 | |||
| 195 | /* | ||
| 196 | * Set up the burst signal for transferring data. period and | ||
| 197 | * offset should mirror the CNV signal | ||
| 198 | */ | ||
| 199 | clk_gate_wf.period_length_ns = cnv_wf.period_length_ns; | ||
| 200 | |||
| 201 | clk_gate_wf.duty_length_ns = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * | ||
| 202 | st->info->chan_spec.scan_type.realbits, | ||
| 203 | st->ref_clk_rate_hz); | ||
| 204 | |||
| 205 | /* max t_MSB from datasheet */ | ||
| 206 | clk_gate_wf.duty_offset_ns = st->info->timing_spec->conv_msb_ns; | ||
| 207 | |||
| 208 | ret = pwm_round_waveform_might_sleep(st->clk_gate_pwm, &clk_gate_wf); | ||
| 209 | if (ret) | ||
| 210 | return ret; | ||
| 211 | |||
| 212 | st->cnv_wf = cnv_wf; | ||
| 213 | st->clk_gate_wf = clk_gate_wf; | ||
| 214 | |||
| 215 | /* TODO: Add a rounding API for PWMs that can simplify this */ | ||
| 216 | target = DIV_ROUND_CLOSEST(st->ref_clk_rate_hz, freq); | ||
| 217 | st->sampling_freq_hz = DIV_ROUND_CLOSEST(st->ref_clk_rate_hz, | ||
| 218 | target); | ||
| 219 | |||
| 220 | return 0; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int ad7625_read_raw(struct iio_dev *indio_dev, | ||
| 224 | const struct iio_chan_spec *chan, | ||
| 225 | int *val, int *val2, long info) | ||
| 226 | { | ||
| 227 | struct ad7625_state *st = iio_priv(indio_dev); | ||
| 228 | |||
| 229 | switch (info) { | ||
| 230 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 231 | *val = st->sampling_freq_hz; | ||
| 232 | |||
| 233 | return IIO_VAL_INT; | ||
| 234 | |||
| 235 | case IIO_CHAN_INFO_SCALE: | ||
| 236 | *val = st->vref_mv; | ||
| 237 | *val2 = chan->scan_type.realbits - 1; | ||
| 238 | |||
| 239 | return IIO_VAL_FRACTIONAL_LOG2; | ||
| 240 | |||
| 241 | default: | ||
| 242 | return -EINVAL; | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | static int ad7625_write_raw(struct iio_dev *indio_dev, | ||
| 247 | struct iio_chan_spec const *chan, | ||
| 248 | int val, int val2, long info) | ||
| 249 | { | ||
| 250 | struct ad7625_state *st = iio_priv(indio_dev); | ||
| 251 | |||
| 252 | switch (info) { | ||
| 253 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 254 | iio_device_claim_direct_scoped(return -EBUSY, indio_dev) | ||
| 255 | return ad7625_set_sampling_freq(st, val); | ||
| 256 | unreachable(); | ||
| 257 | default: | ||
| 258 | return -EINVAL; | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | static int ad7625_parse_mode(struct device *dev, struct ad7625_state *st, | ||
| 263 | int num_gpios) | ||
| 264 | { | ||
| 265 | bool en_always_on[4], en_always_off[4]; | ||
| 266 | bool en_may_be_on[4], en_may_be_off[4]; | ||
| 267 | char en_gpio_buf[4]; | ||
| 268 | char always_on_buf[18]; | ||
| 269 | int i; | ||
| 270 | |||
| 271 | for (i = 0; i < num_gpios; i++) { | ||
| 272 | snprintf(en_gpio_buf, sizeof(en_gpio_buf), "en%d", i); | ||
| 273 | snprintf(always_on_buf, sizeof(always_on_buf), | ||
| 274 | "adi,en%d-always-on", i); | ||
| 275 | /* Set the device to 0b0000 (power-down mode) by default */ | ||
| 276 | st->en_gpios[i] = devm_gpiod_get_optional(dev, en_gpio_buf, | ||
| 277 | GPIOD_OUT_LOW); | ||
| 278 | if (IS_ERR(st->en_gpios[i])) | ||
| 279 | return dev_err_probe(dev, PTR_ERR(st->en_gpios[i]), | ||
| 280 | "failed to get EN%d GPIO\n", i); | ||
| 281 | |||
| 282 | en_always_on[i] = device_property_read_bool(dev, always_on_buf); | ||
| 283 | if (st->en_gpios[i] && en_always_on[i]) | ||
| 284 | return dev_err_probe(dev, -EINVAL, | ||
| 285 | "cannot have adi,en%d-always-on and en%d-gpios\n", i, i); | ||
| 286 | |||
| 287 | en_may_be_off[i] = !en_always_on[i]; | ||
| 288 | en_may_be_on[i] = en_always_on[i] || st->en_gpios[i]; | ||
| 289 | en_always_off[i] = !en_always_on[i] && !st->en_gpios[i]; | ||
| 290 | } | ||
| 291 | |||
| 292 | /* | ||
| 293 | * Power down is mode 0bXX00, but not all devices have a valid | ||
| 294 | * power down state. | ||
| 295 | */ | ||
| 296 | st->can_power_down = en_may_be_off[1] && en_may_be_off[0] && | ||
| 297 | st->info->has_power_down_state; | ||
| 298 | /* | ||
| 299 | * The REFIN pin can take a 1.2V (AD762x) or 2.048V (AD796x) | ||
| 300 | * external reference when the mode is 0bXX01. | ||
| 301 | */ | ||
| 302 | st->can_refin = en_may_be_off[1] && en_may_be_on[0]; | ||
| 303 | /* 4.096V can be applied to REF when the EN mode is 0bXX10. */ | ||
| 304 | st->can_ref_4v096 = en_may_be_on[1] && en_may_be_off[0]; | ||
| 305 | |||
| 306 | /* Avoid AD796x-specific setup if the part is an AD762x */ | ||
| 307 | if (num_gpios == 2) | ||
| 308 | return 0; | ||
| 309 | |||
| 310 | /* mode 0b1100 (AD796x) is invalid */ | ||
| 311 | if (en_always_on[3] && en_always_on[2] && | ||
| 312 | en_always_off[1] && en_always_off[0]) | ||
| 313 | return dev_err_probe(dev, -EINVAL, | ||
| 314 | "EN GPIOs set to invalid mode 0b1100\n"); | ||
| 315 | /* | ||
| 316 | * 5V can be applied to the AD796x REF pin when the EN mode is | ||
| 317 | * the same (0bX001 or 0bX101) as for can_refin, and REFIN is | ||
| 318 | * 0V. | ||
| 319 | */ | ||
| 320 | st->can_ref_5v = st->can_refin; | ||
| 321 | /* | ||
| 322 | * Bandwidth (AD796x) is controlled solely by EN2. If it's | ||
| 323 | * specified and not hard-wired, then we can configure it to | ||
| 324 | * change the bandwidth between 28MHz and 9MHz. | ||
| 325 | */ | ||
| 326 | st->can_narrow_bandwidth = en_may_be_on[2]; | ||
| 327 | /* Wide bandwidth mode is possible if EN2 can be 0. */ | ||
| 328 | st->can_wide_bandwidth = en_may_be_off[2]; | ||
| 329 | /* Snooze mode (AD796x) is 0bXX11 when REFIN = 0V. */ | ||
| 330 | st->can_snooze = en_may_be_on[1] && en_may_be_on[0]; | ||
| 331 | /* Test pattern mode (AD796x) is 0b0100. */ | ||
| 332 | st->can_test_pattern = en_may_be_off[3] && en_may_be_on[2] && | ||
| 333 | en_may_be_off[1] && en_may_be_off[0]; | ||
| 334 | |||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | /* Set EN1 and EN0 based on reference voltage source */ | ||
| 339 | static void ad7625_set_en_gpios_for_vref(struct ad7625_state *st, | ||
| 340 | bool have_refin, int ref_mv) | ||
| 341 | { | ||
| 342 | if (have_refin || ref_mv == 5000) { | ||
| 343 | gpiod_set_value_cansleep(st->en_gpios[1], 0); | ||
| 344 | gpiod_set_value_cansleep(st->en_gpios[0], 1); | ||
| 345 | } else if (ref_mv == 4096) { | ||
| 346 | gpiod_set_value_cansleep(st->en_gpios[1], 1); | ||
| 347 | gpiod_set_value_cansleep(st->en_gpios[0], 0); | ||
| 348 | } else { | ||
| 349 | /* | ||
| 350 | * Unreachable by AD796x, since the driver will error if | ||
| 351 | * neither REF nor REFIN is provided | ||
| 352 | */ | ||
| 353 | gpiod_set_value_cansleep(st->en_gpios[1], 1); | ||
| 354 | gpiod_set_value_cansleep(st->en_gpios[0], 1); | ||
| 355 | } | ||
| 356 | } | ||
| 357 | |||
| 358 | static int ad7960_set_mode(struct ad7625_state *st, enum ad7960_mode mode, | ||
| 359 | bool have_refin, int ref_mv) | ||
| 360 | { | ||
| 361 | switch (mode) { | ||
| 362 | case AD7960_MODE_POWER_DOWN: | ||
| 363 | if (!st->can_power_down) | ||
| 364 | return -EINVAL; | ||
| 365 | |||
| 366 | gpiod_set_value_cansleep(st->en_gpios[2], 0); | ||
| 367 | gpiod_set_value_cansleep(st->en_gpios[1], 0); | ||
| 368 | gpiod_set_value_cansleep(st->en_gpios[0], 0); | ||
| 369 | |||
| 370 | return 0; | ||
| 371 | |||
| 372 | case AD7960_MODE_SNOOZE: | ||
| 373 | if (!st->can_snooze) | ||
| 374 | return -EINVAL; | ||
| 375 | |||
| 376 | gpiod_set_value_cansleep(st->en_gpios[1], 1); | ||
| 377 | gpiod_set_value_cansleep(st->en_gpios[0], 1); | ||
| 378 | |||
| 379 | return 0; | ||
| 380 | |||
| 381 | case AD7960_MODE_NARROW_BANDWIDTH: | ||
| 382 | if (!st->can_narrow_bandwidth) | ||
| 383 | return -EINVAL; | ||
| 384 | |||
| 385 | gpiod_set_value_cansleep(st->en_gpios[2], 1); | ||
| 386 | ad7625_set_en_gpios_for_vref(st, have_refin, ref_mv); | ||
| 387 | |||
| 388 | return 0; | ||
| 389 | |||
| 390 | case AD7960_MODE_WIDE_BANDWIDTH: | ||
| 391 | if (!st->can_wide_bandwidth) | ||
| 392 | return -EINVAL; | ||
| 393 | |||
| 394 | gpiod_set_value_cansleep(st->en_gpios[2], 0); | ||
| 395 | ad7625_set_en_gpios_for_vref(st, have_refin, ref_mv); | ||
| 396 | |||
| 397 | return 0; | ||
| 398 | |||
| 399 | case AD7960_MODE_TEST_PATTERN: | ||
| 400 | if (!st->can_test_pattern) | ||
| 401 | return -EINVAL; | ||
| 402 | |||
| 403 | gpiod_set_value_cansleep(st->en_gpios[3], 0); | ||
| 404 | gpiod_set_value_cansleep(st->en_gpios[2], 1); | ||
| 405 | gpiod_set_value_cansleep(st->en_gpios[1], 0); | ||
| 406 | gpiod_set_value_cansleep(st->en_gpios[0], 0); | ||
| 407 | |||
| 408 | return 0; | ||
| 409 | |||
| 410 | default: | ||
| 411 | return -EINVAL; | ||
| 412 | } | ||
| 413 | } | ||
| 414 | |||
| 415 | static int ad7625_buffer_preenable(struct iio_dev *indio_dev) | ||
| 416 | { | ||
| 417 | struct ad7625_state *st = iio_priv(indio_dev); | ||
| 418 | int ret; | ||
| 419 | |||
| 420 | ret = pwm_set_waveform_might_sleep(st->cnv_pwm, &st->cnv_wf, false); | ||
| 421 | if (ret) | ||
| 422 | return ret; | ||
| 423 | |||
| 424 | ret = pwm_set_waveform_might_sleep(st->clk_gate_pwm, | ||
| 425 | &st->clk_gate_wf, false); | ||
| 426 | if (ret) { | ||
| 427 | /* Disable cnv PWM if clk_gate setup failed */ | ||
| 428 | pwm_disable(st->cnv_pwm); | ||
| 429 | return ret; | ||
| 430 | } | ||
| 431 | |||
| 432 | return 0; | ||
| 433 | } | ||
| 434 | |||
| 435 | static int ad7625_buffer_postdisable(struct iio_dev *indio_dev) | ||
| 436 | { | ||
| 437 | struct ad7625_state *st = iio_priv(indio_dev); | ||
| 438 | |||
| 439 | pwm_disable(st->clk_gate_pwm); | ||
| 440 | pwm_disable(st->cnv_pwm); | ||
| 441 | |||
| 442 | return 0; | ||
| 443 | } | ||
| 444 | |||
| 445 | static const struct iio_info ad7625_info = { | ||
| 446 | .read_raw = ad7625_read_raw, | ||
| 447 | .write_raw = ad7625_write_raw, | ||
| 448 | }; | ||
| 449 | |||
| 450 | static const struct iio_buffer_setup_ops ad7625_buffer_setup_ops = { | ||
| 451 | .preenable = &ad7625_buffer_preenable, | ||
| 452 | .postdisable = &ad7625_buffer_postdisable, | ||
| 453 | }; | ||
| 454 | |||
| 455 | static int devm_ad7625_pwm_get(struct device *dev, | ||
| 456 | struct ad7625_state *st) | ||
| 457 | { | ||
| 458 | struct clk *ref_clk; | ||
| 459 | u32 ref_clk_rate_hz; | ||
| 460 | |||
| 461 | st->cnv_pwm = devm_pwm_get(dev, "cnv"); | ||
| 462 | if (IS_ERR(st->cnv_pwm)) | ||
| 463 | return dev_err_probe(dev, PTR_ERR(st->cnv_pwm), | ||
| 464 | "failed to get cnv pwm\n"); | ||
| 465 | |||
| 466 | /* Preemptively disable the PWM in case it was enabled at boot */ | ||
| 467 | pwm_disable(st->cnv_pwm); | ||
| 468 | |||
| 469 | st->clk_gate_pwm = devm_pwm_get(dev, "clk_gate"); | ||
| 470 | if (IS_ERR(st->clk_gate_pwm)) | ||
| 471 | return dev_err_probe(dev, PTR_ERR(st->clk_gate_pwm), | ||
| 472 | "failed to get clk_gate pwm\n"); | ||
| 473 | |||
| 474 | /* Preemptively disable the PWM in case it was enabled at boot */ | ||
| 475 | pwm_disable(st->clk_gate_pwm); | ||
| 476 | |||
| 477 | ref_clk = devm_clk_get_enabled(dev, NULL); | ||
| 478 | if (IS_ERR(ref_clk)) | ||
| 479 | return dev_err_probe(dev, PTR_ERR(ref_clk), | ||
| 480 | "failed to get ref_clk"); | ||
| 481 | |||
| 482 | ref_clk_rate_hz = clk_get_rate(ref_clk); | ||
| 483 | if (!ref_clk_rate_hz) | ||
| 484 | return dev_err_probe(dev, -EINVAL, | ||
| 485 | "failed to get ref_clk rate"); | ||
| 486 | |||
| 487 | st->ref_clk_rate_hz = ref_clk_rate_hz; | ||
| 488 | |||
| 489 | return 0; | ||
| 490 | } | ||
| 491 | |||
| 492 | /* | ||
| 493 | * There are three required input voltages for each device, plus two | ||
| 494 | * conditionally-optional (depending on part) REF and REFIN voltages | ||
| 495 | * where their validity depends upon the EN pin configuration. | ||
| 496 | * | ||
| 497 | * Power-up info for the device says to bring up vio, then vdd2, then | ||
| 498 | * vdd1, so list them in that order in the regulator_names array. | ||
| 499 | * | ||
| 500 | * The reference voltage source is determined like so: | ||
| 501 | * - internal reference: neither REF or REFIN is connected (invalid for | ||
| 502 | * AD796x) | ||
| 503 | * - internal buffer, external reference: REF not connected, REFIN | ||
| 504 | * connected | ||
| 505 | * - external reference: REF connected, REFIN not connected | ||
| 506 | */ | ||
| 507 | static int devm_ad7625_regulator_setup(struct device *dev, | ||
| 508 | struct ad7625_state *st) | ||
| 509 | { | ||
| 510 | static const char * const regulator_names[] = { "vio", "vdd2", "vdd1" }; | ||
| 511 | int ret, ref_mv; | ||
| 512 | |||
| 513 | ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names), | ||
| 514 | regulator_names); | ||
| 515 | if (ret) | ||
| 516 | return ret; | ||
| 517 | |||
| 518 | ret = devm_regulator_get_enable_read_voltage(dev, "ref"); | ||
| 519 | if (ret < 0 && ret != -ENODEV) | ||
| 520 | return dev_err_probe(dev, ret, "failed to get REF voltage\n"); | ||
| 521 | |||
| 522 | ref_mv = ret == -ENODEV ? 0 : ret / 1000; | ||
| 523 | |||
| 524 | ret = devm_regulator_get_enable_optional(dev, "refin"); | ||
| 525 | if (ret < 0 && ret != -ENODEV) | ||
| 526 | return dev_err_probe(dev, ret, "failed to get REFIN voltage\n"); | ||
| 527 | |||
| 528 | st->have_refin = ret != -ENODEV; | ||
| 529 | |||
| 530 | if (st->have_refin && !st->can_refin) | ||
| 531 | return dev_err_probe(dev, -EINVAL, | ||
| 532 | "REFIN provided in unsupported mode\n"); | ||
| 533 | |||
| 534 | if (!st->info->has_internal_vref && !st->have_refin && !ref_mv) | ||
| 535 | return dev_err_probe(dev, -EINVAL, | ||
| 536 | "Need either REFIN or REF"); | ||
| 537 | |||
| 538 | if (st->have_refin && ref_mv) | ||
| 539 | return dev_err_probe(dev, -EINVAL, | ||
| 540 | "cannot have both REFIN and REF supplies\n"); | ||
| 541 | |||
| 542 | if (ref_mv == 4096 && !st->can_ref_4v096) | ||
| 543 | return dev_err_probe(dev, -EINVAL, | ||
| 544 | "REF is 4.096V in unsupported mode\n"); | ||
| 545 | |||
| 546 | if (ref_mv == 5000 && !st->can_ref_5v) | ||
| 547 | return dev_err_probe(dev, -EINVAL, | ||
| 548 | "REF is 5V in unsupported mode\n"); | ||
| 549 | |||
| 550 | st->vref_mv = ref_mv ?: AD7625_INTERNAL_REF_MV; | ||
| 551 | |||
| 552 | return 0; | ||
| 553 | } | ||
| 554 | |||
| 555 | static int ad7625_probe(struct platform_device *pdev) | ||
| 556 | { | ||
| 557 | struct device *dev = &pdev->dev; | ||
| 558 | struct iio_dev *indio_dev; | ||
| 559 | struct ad7625_state *st; | ||
| 560 | int ret; | ||
| 561 | u32 default_sample_freq; | ||
| 562 | |||
| 563 | indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); | ||
| 564 | if (!indio_dev) | ||
| 565 | return -ENOMEM; | ||
| 566 | |||
| 567 | st = iio_priv(indio_dev); | ||
| 568 | |||
| 569 | st->info = device_get_match_data(dev); | ||
| 570 | if (!st->info) | ||
| 571 | return dev_err_probe(dev, -EINVAL, "no chip info\n"); | ||
| 572 | |||
| 573 | if (device_property_read_bool(dev, "adi,no-dco")) | ||
| 574 | return dev_err_probe(dev, -EINVAL, | ||
| 575 | "self-clocked mode not supported\n"); | ||
| 576 | |||
| 577 | if (st->info->has_bandwidth_control) | ||
| 578 | ret = ad7625_parse_mode(dev, st, 4); | ||
| 579 | else | ||
| 580 | ret = ad7625_parse_mode(dev, st, 2); | ||
| 581 | |||
| 582 | if (ret) | ||
| 583 | return ret; | ||
| 584 | |||
| 585 | ret = devm_ad7625_regulator_setup(dev, st); | ||
| 586 | if (ret) | ||
| 587 | return ret; | ||
| 588 | |||
| 589 | /* Set the device mode based on detected EN configuration. */ | ||
| 590 | if (!st->info->has_bandwidth_control) { | ||
| 591 | ad7625_set_en_gpios_for_vref(st, st->have_refin, st->vref_mv); | ||
| 592 | } else { | ||
| 593 | /* | ||
| 594 | * If neither sampling mode is available, then report an error, | ||
| 595 | * since the other modes are not useful defaults. | ||
| 596 | */ | ||
| 597 | if (st->can_wide_bandwidth) { | ||
| 598 | ret = ad7960_set_mode(st, AD7960_MODE_WIDE_BANDWIDTH, | ||
| 599 | st->have_refin, st->vref_mv); | ||
| 600 | } else if (st->can_narrow_bandwidth) { | ||
| 601 | ret = ad7960_set_mode(st, AD7960_MODE_NARROW_BANDWIDTH, | ||
| 602 | st->have_refin, st->vref_mv); | ||
| 603 | } else { | ||
| 604 | return dev_err_probe(dev, -EINVAL, | ||
| 605 | "couldn't set device to wide or narrow bandwidth modes\n"); | ||
| 606 | } | ||
| 607 | |||
| 608 | if (ret) | ||
| 609 | return dev_err_probe(dev, -EINVAL, | ||
| 610 | "failed to set EN pins\n"); | ||
| 611 | } | ||
| 612 | |||
| 613 | ret = devm_ad7625_pwm_get(dev, st); | ||
| 614 | if (ret) | ||
| 615 | return ret; | ||
| 616 | |||
| 617 | indio_dev->channels = &st->info->chan_spec; | ||
| 618 | indio_dev->num_channels = 1; | ||
| 619 | indio_dev->name = st->info->name; | ||
| 620 | indio_dev->info = &ad7625_info; | ||
| 621 | indio_dev->setup_ops = &ad7625_buffer_setup_ops; | ||
| 622 | |||
| 623 | st->back = devm_iio_backend_get(dev, NULL); | ||
| 624 | if (IS_ERR(st->back)) | ||
| 625 | return dev_err_probe(dev, PTR_ERR(st->back), | ||
| 626 | "failed to get IIO backend"); | ||
| 627 | |||
| 628 | ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev); | ||
| 629 | if (ret) | ||
| 630 | return ret; | ||
| 631 | |||
| 632 | ret = devm_iio_backend_enable(dev, st->back); | ||
| 633 | if (ret) | ||
| 634 | return ret; | ||
| 635 | |||
| 636 | /* | ||
| 637 | * Set the initial sampling frequency to the maximum, unless the | ||
| 638 | * AD796x device is limited to narrow bandwidth by EN2 == 1, in | ||
| 639 | * which case the sampling frequency should be limited to 2MSPS | ||
| 640 | */ | ||
| 641 | default_sample_freq = st->info->max_sample_freq_hz; | ||
| 642 | if (st->info->has_bandwidth_control && !st->can_wide_bandwidth) | ||
| 643 | default_sample_freq = AD7960_MAX_NBW_FREQ; | ||
| 644 | |||
| 645 | ret = ad7625_set_sampling_freq(st, default_sample_freq); | ||
| 646 | if (ret) | ||
| 647 | dev_err_probe(dev, ret, | ||
| 648 | "failed to set valid sampling frequency\n"); | ||
| 649 | |||
| 650 | return devm_iio_device_register(dev, indio_dev); | ||
| 651 | } | ||
| 652 | |||
| 653 | static const struct of_device_id ad7625_of_match[] = { | ||
| 654 | { .compatible = "adi,ad7625", .data = &ad7625_chip_info }, | ||
| 655 | { .compatible = "adi,ad7626", .data = &ad7626_chip_info }, | ||
| 656 | { .compatible = "adi,ad7960", .data = &ad7960_chip_info }, | ||
| 657 | { .compatible = "adi,ad7961", .data = &ad7961_chip_info }, | ||
| 658 | { } | ||
| 659 | }; | ||
| 660 | MODULE_DEVICE_TABLE(of, ad7625_of_match); | ||
| 661 | |||
| 662 | static const struct platform_device_id ad7625_device_ids[] = { | ||
| 663 | { .name = "ad7625", .driver_data = (kernel_ulong_t)&ad7625_chip_info }, | ||
| 664 | { .name = "ad7626", .driver_data = (kernel_ulong_t)&ad7626_chip_info }, | ||
| 665 | { .name = "ad7960", .driver_data = (kernel_ulong_t)&ad7960_chip_info }, | ||
| 666 | { .name = "ad7961", .driver_data = (kernel_ulong_t)&ad7961_chip_info }, | ||
| 667 | { } | ||
| 668 | }; | ||
| 669 | MODULE_DEVICE_TABLE(platform, ad7625_device_ids); | ||
| 670 | |||
| 671 | static struct platform_driver ad7625_driver = { | ||
| 672 | .probe = ad7625_probe, | ||
| 673 | .driver = { | ||
| 674 | .name = "ad7625", | ||
| 675 | .of_match_table = ad7625_of_match, | ||
| 676 | }, | ||
| 677 | .id_table = ad7625_device_ids, | ||
| 678 | }; | ||
| 679 | module_platform_driver(ad7625_driver); | ||
| 680 | |||
| 681 | MODULE_AUTHOR("Trevor Gamblin <tgamblin@baylibre.com>"); | ||
| 682 | MODULE_DESCRIPTION("Analog Devices AD7625 ADC"); | ||
| 683 | MODULE_LICENSE("Dual BSD/GPL"); | ||
| 684 | MODULE_IMPORT_NS(IIO_BACKEND); | ||
| @@ -0,0 +1,914 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | /* | ||
| 3 | * AD7770, AD7771, AD7779 ADC | ||
| 4 | * | ||
| 5 | * Copyright 2023-2024 Analog Devices Inc. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/bitfield.h> | ||
| 9 | #include <linux/bitmap.h> | ||
| 10 | #include <linux/clk.h> | ||
| 11 | #include <linux/crc8.h> | ||
| 12 | #include <linux/delay.h> | ||
| 13 | #include <linux/err.h> | ||
| 14 | #include <linux/gpio/consumer.h> | ||
| 15 | #include <linux/interrupt.h> | ||
| 16 | #include <linux/irq.h> | ||
| 17 | #include <linux/math.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/mod_devicetable.h> | ||
| 20 | #include <linux/regulator/consumer.h> | ||
| 21 | #include <linux/spi/spi.h> | ||
| 22 | #include <linux/string.h> | ||
| 23 | #include <linux/types.h> | ||
| 24 | #include <linux/unaligned.h> | ||
| 25 | #include <linux/units.h> | ||
| 26 | |||
| 27 | #include <linux/iio/iio.h> | ||
| 28 | #include <linux/iio/buffer.h> | ||
| 29 | #include <linux/iio/sysfs.h> | ||
| 30 | #include <linux/iio/trigger.h> | ||
| 31 | #include <linux/iio/triggered_buffer.h> | ||
| 32 | #include <linux/iio/trigger_consumer.h> | ||
| 33 | |||
| 34 | #define AD7779_SPI_READ_CMD BIT(7) | ||
| 35 | |||
| 36 | #define AD7779_DISABLE_SD BIT(7) | ||
| 37 | |||
| 38 | #define AD7779_REG_CH_DISABLE 0x08 | ||
| 39 | #define AD7779_REG_CH_SYNC_OFFSET(ch) (0x09 + (ch)) | ||
| 40 | #define AD7779_REG_CH_CONFIG(ch) (0x00 + (ch)) | ||
| 41 | #define AD7779_REG_GENERAL_USER_CONFIG_1 0x11 | ||
| 42 | #define AD7779_REG_GENERAL_USER_CONFIG_2 0x12 | ||
| 43 | #define AD7779_REG_GENERAL_USER_CONFIG_3 0x13 | ||
| 44 | #define AD7779_REG_DOUT_FORMAT 0x14 | ||
| 45 | #define AD7779_REG_ADC_MUX_CONFIG 0x15 | ||
| 46 | #define AD7779_REG_GPIO_CONFIG 0x17 | ||
| 47 | #define AD7779_REG_BUFFER_CONFIG_1 0x19 | ||
| 48 | #define AD7779_REG_GLOBAL_MUX_CONFIG 0x16 | ||
| 49 | #define AD7779_REG_BUFFER_CONFIG_2 0x1A | ||
| 50 | #define AD7779_REG_GPIO_DATA 0x18 | ||
| 51 | #define AD7779_REG_CH_OFFSET_UPPER_BYTE(ch) (0x1C + (ch) * 6) | ||
| 52 | #define AD7779_REG_CH_OFFSET_LOWER_BYTE(ch) (0x1E + (ch) * 6) | ||
| 53 | #define AD7779_REG_CH_GAIN_UPPER_BYTE(ch) (0x1F + (ch) * 6) | ||
| 54 | #define AD7779_REG_CH_OFFSET_MID_BYTE(ch) (0x1D + (ch) * 6) | ||
| 55 | #define AD7779_REG_CH_GAIN_MID_BYTE(ch) (0x20 + (ch) * 6) | ||
| 56 | #define AD7779_REG_CH_ERR_REG(ch) (0x4C + (ch)) | ||
| 57 | #define AD7779_REG_CH0_1_SAT_ERR 0x54 | ||
| 58 | #define AD7779_REG_CH_GAIN_LOWER_BYTE(ch) (0x21 + (ch) * 6) | ||
| 59 | #define AD7779_REG_CH2_3_SAT_ERR 0x55 | ||
| 60 | #define AD7779_REG_CH4_5_SAT_ERR 0x56 | ||
| 61 | #define AD7779_REG_CH6_7_SAT_ERR 0x57 | ||
| 62 | #define AD7779_REG_CHX_ERR_REG_EN 0x58 | ||
| 63 | #define AD7779_REG_GEN_ERR_REG_1 0x59 | ||
| 64 | #define AD7779_REG_GEN_ERR_REG_1_EN 0x5A | ||
| 65 | #define AD7779_REG_GEN_ERR_REG_2 0x5B | ||
| 66 | #define AD7779_REG_GEN_ERR_REG_2_EN 0x5C | ||
| 67 | #define AD7779_REG_STATUS_REG_1 0x5D | ||
| 68 | #define AD7779_REG_STATUS_REG_2 0x5E | ||
| 69 | #define AD7779_REG_STATUS_REG_3 0x5F | ||
| 70 | #define AD7779_REG_SRC_N_MSB 0x60 | ||
| 71 | #define AD7779_REG_SRC_N_LSB 0x61 | ||
| 72 | #define AD7779_REG_SRC_IF_MSB 0x62 | ||
| 73 | #define AD7779_REG_SRC_IF_LSB 0x63 | ||
| 74 | #define AD7779_REG_SRC_UPDATE 0x64 | ||
| 75 | |||
| 76 | #define AD7779_FILTER_MSK BIT(6) | ||
| 77 | #define AD7779_MOD_POWERMODE_MSK BIT(6) | ||
| 78 | #define AD7779_MOD_PDB_REFOUT_MSK BIT(4) | ||
| 79 | #define AD7779_MOD_SPI_EN_MSK BIT(4) | ||
| 80 | #define AD7779_USRMOD_INIT_MSK GENMASK(6, 4) | ||
| 81 | |||
| 82 | /* AD7779_REG_DOUT_FORMAT */ | ||
| 83 | #define AD7779_DOUT_FORMAT_MSK GENMASK(7, 6) | ||
| 84 | #define AD7779_DOUT_HEADER_FORMAT BIT(5) | ||
| 85 | #define AD7779_DCLK_CLK_DIV_MSK GENMASK(3, 1) | ||
| 86 | |||
| 87 | #define AD7779_REFMUX_CTRL_MSK GENMASK(7, 6) | ||
| 88 | #define AD7779_SPI_CRC_EN_MSK BIT(0) | ||
| 89 | |||
| 90 | #define AD7779_MAXCLK_LOWPOWER (4096 * HZ_PER_KHZ) | ||
| 91 | #define AD7779_NUM_CHANNELS 8 | ||
| 92 | #define AD7779_RESET_BUF_SIZE 8 | ||
| 93 | #define AD7779_CHAN_DATA_SIZE 4 | ||
| 94 | |||
| 95 | #define AD7779_LOWPOWER_DIV 512 | ||
| 96 | #define AD7779_HIGHPOWER_DIV 2048 | ||
| 97 | |||
| 98 | #define AD7779_SINC3_MAXFREQ (16 * HZ_PER_KHZ) | ||
| 99 | #define AD7779_SINC5_MAXFREQ (128 * HZ_PER_KHZ) | ||
| 100 | |||
| 101 | #define AD7779_DEFAULT_SAMPLING_FREQ (8 * HZ_PER_KHZ) | ||
| 102 | #define AD7779_DEFAULT_SAMPLING_2LINE (4 * HZ_PER_KHZ) | ||
| 103 | #define AD7779_DEFAULT_SAMPLING_1LINE (2 * HZ_PER_KHZ) | ||
| 104 | |||
| 105 | #define AD7779_SPIMODE_MAX_SAMP_FREQ (16 * HZ_PER_KHZ) | ||
| 106 | |||
| 107 | #define GAIN_REL 0x555555 | ||
| 108 | #define AD7779_FREQ_MSB_MSK GENMASK(15, 8) | ||
| 109 | #define AD7779_FREQ_LSB_MSK GENMASK(7, 0) | ||
| 110 | #define AD7779_UPPER GENMASK(23, 16) | ||
| 111 | #define AD7779_MID GENMASK(15, 8) | ||
| 112 | #define AD7779_LOWER GENMASK(7, 0) | ||
| 113 | |||
| 114 | #define AD7779_REG_MSK GENMASK(6, 0) | ||
| 115 | |||
| 116 | #define AD7779_CRC8_POLY 0x07 | ||
| 117 | DECLARE_CRC8_TABLE(ad7779_crc8_table); | ||
| 118 | |||
| 119 | enum ad7779_filter { | ||
| 120 | AD7779_SINC3, | ||
| 121 | AD7779_SINC5, | ||
| 122 | }; | ||
| 123 | |||
| 124 | enum ad7779_variant { | ||
| 125 | ad7770, | ||
| 126 | ad7771, | ||
| 127 | ad7779, | ||
| 128 | }; | ||
| 129 | |||
| 130 | enum ad7779_power_mode { | ||
| 131 | AD7779_LOW_POWER, | ||
| 132 | AD7779_HIGH_POWER, | ||
| 133 | }; | ||
| 134 | |||
| 135 | struct ad7779_chip_info { | ||
| 136 | const char *name; | ||
| 137 | struct iio_chan_spec const *channels; | ||
| 138 | }; | ||
| 139 | |||
| 140 | struct ad7779_state { | ||
| 141 | struct spi_device *spi; | ||
| 142 | const struct ad7779_chip_info *chip_info; | ||
| 143 | struct clk *mclk; | ||
| 144 | struct iio_trigger *trig; | ||
| 145 | struct completion completion; | ||
| 146 | unsigned int sampling_freq; | ||
| 147 | enum ad7779_filter filter_enabled; | ||
| 148 | /* | ||
| 149 | * DMA (thus cache coherency maintenance) requires the | ||
| 150 | * transfer buffers to live in their own cache lines. | ||
| 151 | */ | ||
| 152 | struct { | ||
| 153 | u32 chans[8]; | ||
| 154 | aligned_s64 timestamp; | ||
| 155 | } data __aligned(IIO_DMA_MINALIGN); | ||
| 156 | u32 spidata_tx[8]; | ||
| 157 | u8 reg_rx_buf[3]; | ||
| 158 | u8 reg_tx_buf[3]; | ||
| 159 | u8 reset_buf[8]; | ||
| 160 | }; | ||
| 161 | |||
| 162 | static const char * const ad7779_filter_type[] = { | ||
| 163 | [AD7779_SINC3] = "sinc3", | ||
| 164 | [AD7779_SINC5] = "sinc5", | ||
| 165 | }; | ||
| 166 | |||
| 167 | static const char * const ad7779_power_supplies[] = { | ||
| 168 | "avdd1", "avdd2", "avdd4", | ||
| 169 | }; | ||
| 170 | |||
| 171 | static int ad7779_spi_read(struct ad7779_state *st, u8 reg, u8 *rbuf) | ||
| 172 | { | ||
| 173 | int ret; | ||
| 174 | u8 crc_buf[2]; | ||
| 175 | u8 exp_crc; | ||
| 176 | struct spi_transfer t = { | ||
| 177 | .tx_buf = st->reg_tx_buf, | ||
| 178 | .rx_buf = st->reg_rx_buf, | ||
| 179 | }; | ||
| 180 | |||
| 181 | st->reg_tx_buf[0] = AD7779_SPI_READ_CMD | FIELD_GET(AD7779_REG_MSK, reg); | ||
| 182 | st->reg_tx_buf[1] = 0; | ||
| 183 | |||
| 184 | if (reg == AD7779_REG_GEN_ERR_REG_1_EN) { | ||
| 185 | t.len = 2; | ||
| 186 | } else { | ||
| 187 | t.len = 3; | ||
| 188 | st->reg_tx_buf[2] = crc8(ad7779_crc8_table, st->reg_tx_buf, | ||
| 189 | t.len - 1, 0); | ||
| 190 | } | ||
| 191 | |||
| 192 | ret = spi_sync_transfer(st->spi, &t, 1); | ||
| 193 | if (ret) | ||
| 194 | return ret; | ||
| 195 | |||
| 196 | crc_buf[0] = AD7779_SPI_READ_CMD | FIELD_GET(AD7779_REG_MSK, reg); | ||
| 197 | crc_buf[1] = st->reg_rx_buf[1]; | ||
| 198 | exp_crc = crc8(ad7779_crc8_table, crc_buf, ARRAY_SIZE(crc_buf), 0); | ||
| 199 | if (reg != AD7779_REG_GEN_ERR_REG_1_EN && exp_crc != st->reg_rx_buf[2]) { | ||
| 200 | dev_err(&st->spi->dev, "Bad CRC %x, expected %x", | ||
| 201 | st->reg_rx_buf[2], exp_crc); | ||
| 202 | return -EINVAL; | ||
| 203 | } | ||
| 204 | *rbuf = st->reg_rx_buf[1]; | ||
| 205 | |||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | static int ad7779_spi_write(struct ad7779_state *st, u8 reg, u8 val) | ||
| 210 | { | ||
| 211 | u8 length = 3; | ||
| 212 | |||
| 213 | st->reg_tx_buf[0] = FIELD_GET(AD7779_REG_MSK, reg); | ||
| 214 | st->reg_tx_buf[1] = val; | ||
| 215 | if (reg == AD7779_REG_GEN_ERR_REG_1_EN) | ||
| 216 | length = 2; | ||
| 217 | else | ||
| 218 | st->reg_tx_buf[2] = crc8(ad7779_crc8_table, st->reg_tx_buf, | ||
| 219 | length - 1, 0); | ||
| 220 | |||
| 221 | return spi_write(st->spi, st->reg_tx_buf, length); | ||
| 222 | } | ||
| 223 | |||
| 224 | static int ad7779_spi_write_mask(struct ad7779_state *st, u8 reg, u8 mask, | ||
| 225 | u8 val) | ||
| 226 | { | ||
| 227 | int ret; | ||
| 228 | u8 regval, data; | ||
| 229 | |||
| 230 | ret = ad7779_spi_read(st, reg, &data); | ||
| 231 | if (ret) | ||
| 232 | return ret; | ||
| 233 | |||
| 234 | regval = (data & ~mask) | (val & mask); | ||
| 235 | |||
| 236 | if (regval == data) | ||
| 237 | return 0; | ||
| 238 | |||
| 239 | return ad7779_spi_write(st, reg, regval); | ||
| 240 | } | ||
| 241 | |||
| 242 | static int ad7779_reg_access(struct iio_dev *indio_dev, | ||
| 243 | unsigned int reg, | ||
| 244 | unsigned int writeval, | ||
| 245 | unsigned int *readval) | ||
| 246 | { | ||
| 247 | struct ad7779_state *st = iio_priv(indio_dev); | ||
| 248 | u8 rval; | ||
| 249 | int ret; | ||
| 250 | |||
| 251 | if (readval) { | ||
| 252 | ret = ad7779_spi_read(st, reg, &rval); | ||
| 253 | *readval = rval; | ||
| 254 | return ret; | ||
| 255 | } | ||
| 256 | |||
| 257 | return ad7779_spi_write(st, reg, writeval); | ||
| 258 | } | ||
| 259 | |||
| 260 | static int ad7779_set_sampling_frequency(struct ad7779_state *st, | ||
| 261 | unsigned int sampling_freq) | ||
| 262 | { | ||
| 263 | int ret; | ||
| 264 | unsigned int dec; | ||
| 265 | unsigned int frac; | ||
| 266 | unsigned int div; | ||
| 267 | unsigned int decimal; | ||
| 268 | unsigned int freq_khz; | ||
| 269 | |||
| 270 | if (st->filter_enabled == AD7779_SINC3 && | ||
| 271 | sampling_freq > AD7779_SINC3_MAXFREQ) | ||
| 272 | return -EINVAL; | ||
| 273 | |||
| 274 | if (st->filter_enabled == AD7779_SINC5 && | ||
| 275 | sampling_freq > AD7779_SINC5_MAXFREQ) | ||
| 276 | return -EINVAL; | ||
| 277 | |||
| 278 | if (sampling_freq > AD7779_SPIMODE_MAX_SAMP_FREQ) | ||
| 279 | return -EINVAL; | ||
| 280 | |||
| 281 | div = AD7779_HIGHPOWER_DIV; | ||
| 282 | |||
| 283 | freq_khz = sampling_freq / HZ_PER_KHZ; | ||
| 284 | dec = div / freq_khz; | ||
| 285 | frac = div % freq_khz; | ||
| 286 | |||
| 287 | ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB, | ||
| 288 | FIELD_GET(AD7779_FREQ_MSB_MSK, dec)); | ||
| 289 | if (ret) | ||
| 290 | return ret; | ||
| 291 | ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB, | ||
| 292 | FIELD_GET(AD7779_FREQ_LSB_MSK, dec)); | ||
| 293 | if (ret) | ||
| 294 | return ret; | ||
| 295 | |||
| 296 | if (frac) { | ||
| 297 | /* | ||
| 298 | * In order to obtain the first three decimals of the decimation | ||
| 299 | * the initial number is multiplied with 10^3 prior to the | ||
| 300 | * division, then the original division result is subtracted and | ||
| 301 | * the number is divided by 10^3. | ||
| 302 | */ | ||
| 303 | decimal = ((mult_frac(div, KILO, freq_khz) - dec * KILO) << 16) | ||
| 304 | / KILO; | ||
| 305 | ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB, | ||
| 306 | FIELD_GET(AD7779_FREQ_MSB_MSK, decimal)); | ||
| 307 | if (ret) | ||
| 308 | return ret; | ||
| 309 | ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB, | ||
| 310 | FIELD_GET(AD7779_FREQ_LSB_MSK, decimal)); | ||
| 311 | if (ret) | ||
| 312 | return ret; | ||
| 313 | } else { | ||
| 314 | ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB, | ||
| 315 | FIELD_GET(AD7779_FREQ_MSB_MSK, 0x0)); | ||
| 316 | if (ret) | ||
| 317 | return ret; | ||
| 318 | ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB, | ||
| 319 | FIELD_GET(AD7779_FREQ_LSB_MSK, 0x0)); | ||
| 320 | if (ret) | ||
| 321 | return ret; | ||
| 322 | } | ||
| 323 | ret = ad7779_spi_write(st, AD7779_REG_SRC_UPDATE, BIT(0)); | ||
| 324 | if (ret) | ||
| 325 | return ret; | ||
| 326 | |||
| 327 | /* SRC update settling time */ | ||
| 328 | fsleep(15); | ||
| 329 | |||
| 330 | ret = ad7779_spi_write(st, AD7779_REG_SRC_UPDATE, 0x0); | ||
| 331 | if (ret) | ||
| 332 | return ret; | ||
| 333 | |||
| 334 | /* SRC update settling time */ | ||
| 335 | fsleep(15); | ||
| 336 | |||
| 337 | st->sampling_freq = sampling_freq; | ||
| 338 | |||
| 339 | return 0; | ||
| 340 | } | ||
| 341 | |||
| 342 | static int ad7779_get_filter(struct iio_dev *indio_dev, | ||
| 343 | struct iio_chan_spec const *chan) | ||
| 344 | { | ||
| 345 | struct ad7779_state *st = iio_priv(indio_dev); | ||
| 346 | u8 temp; | ||
| 347 | int ret; | ||
| 348 | |||
| 349 | ret = ad7779_spi_read(st, AD7779_REG_GENERAL_USER_CONFIG_2, &temp); | ||
| 350 | if (ret) | ||
| 351 | return ret; | ||
| 352 | |||
| 353 | return FIELD_GET(AD7779_FILTER_MSK, temp); | ||
| 354 | } | ||
| 355 | |||
| 356 | static int ad7779_set_filter(struct iio_dev *indio_dev, | ||
| 357 | struct iio_chan_spec const *chan, | ||
| 358 | unsigned int mode) | ||
| 359 | { | ||
| 360 | struct ad7779_state *st = iio_priv(indio_dev); | ||
| 361 | int ret; | ||
| 362 | |||
| 363 | ret = ad7779_spi_write_mask(st, | ||
| 364 | AD7779_REG_GENERAL_USER_CONFIG_2, | ||
| 365 | AD7779_FILTER_MSK, | ||
| 366 | FIELD_PREP(AD7779_FILTER_MSK, mode)); | ||
| 367 | if (ret) | ||
| 368 | return ret; | ||
| 369 | |||
| 370 | ret = ad7779_set_sampling_frequency(st, st->sampling_freq); | ||
| 371 | if (ret) | ||
| 372 | return ret; | ||
| 373 | |||
| 374 | st->filter_enabled = mode; | ||
| 375 | |||
| 376 | return 0; | ||
| 377 | } | ||
| 378 | |||
| 379 | static int ad7779_get_calibscale(struct ad7779_state *st, int channel) | ||
| 380 | { | ||
| 381 | int ret; | ||
| 382 | u8 calibscale[3]; | ||
| 383 | |||
| 384 | ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_LOWER_BYTE(channel), | ||
| 385 | &calibscale[0]); | ||
| 386 | if (ret) | ||
| 387 | return ret; | ||
| 388 | |||
| 389 | ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_MID_BYTE(channel), | ||
| 390 | &calibscale[1]); | ||
| 391 | if (ret) | ||
| 392 | return ret; | ||
| 393 | |||
| 394 | ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_UPPER_BYTE(channel), | ||
| 395 | &calibscale[2]); | ||
| 396 | if (ret) | ||
| 397 | return ret; | ||
| 398 | |||
| 399 | return get_unaligned_be24(calibscale); | ||
| 400 | } | ||
| 401 | |||
| 402 | static int ad7779_set_calibscale(struct ad7779_state *st, int channel, int val) | ||
| 403 | { | ||
| 404 | int ret; | ||
| 405 | unsigned int gain; | ||
| 406 | u8 gain_bytes[3]; | ||
| 407 | |||
| 408 | /* | ||
| 409 | * The gain value is relative to 0x555555, which represents a gain of 1 | ||
| 410 | */ | ||
| 411 | gain = DIV_ROUND_CLOSEST_ULL((u64)val * 5592405LL, MEGA); | ||
| 412 | put_unaligned_be24(gain, gain_bytes); | ||
| 413 | ret = ad7779_spi_write(st, AD7779_REG_CH_GAIN_UPPER_BYTE(channel), | ||
| 414 | gain_bytes[0]); | ||
| 415 | if (ret) | ||
| 416 | return ret; | ||
| 417 | |||
| 418 | ret = ad7779_spi_write(st, AD7779_REG_CH_GAIN_MID_BYTE(channel), | ||
| 419 | gain_bytes[1]); | ||
| 420 | if (ret) | ||
| 421 | return ret; | ||
| 422 | |||
| 423 | return ad7779_spi_write(st, AD7779_REG_CH_GAIN_LOWER_BYTE(channel), | ||
| 424 | gain_bytes[2]); | ||
| 425 | } | ||
| 426 | |||
| 427 | static int ad7779_get_calibbias(struct ad7779_state *st, int channel) | ||
| 428 | { | ||
| 429 | int ret; | ||
| 430 | u8 calibbias[3]; | ||
| 431 | |||
| 432 | ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_LOWER_BYTE(channel), | ||
| 433 | &calibbias[0]); | ||
| 434 | if (ret) | ||
| 435 | return ret; | ||
| 436 | |||
| 437 | ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_MID_BYTE(channel), | ||
| 438 | &calibbias[1]); | ||
| 439 | if (ret) | ||
| 440 | return ret; | ||
| 441 | |||
| 442 | ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_UPPER_BYTE(channel), | ||
| 443 | &calibbias[2]); | ||
| 444 | if (ret) | ||
| 445 | return ret; | ||
| 446 | |||
| 447 | return get_unaligned_be24(calibbias); | ||
| 448 | } | ||
| 449 | |||
| 450 | static int ad7779_set_calibbias(struct ad7779_state *st, int channel, int val) | ||
| 451 | { | ||
| 452 | int ret; | ||
| 453 | u8 calibbias[3]; | ||
| 454 | |||
| 455 | put_unaligned_be24(val, calibbias); | ||
| 456 | ret = ad7779_spi_write(st, AD7779_REG_CH_OFFSET_UPPER_BYTE(channel), | ||
| 457 | calibbias[0]); | ||
| 458 | if (ret) | ||
| 459 | return ret; | ||
| 460 | |||
| 461 | ret = ad7779_spi_write(st, AD7779_REG_CH_OFFSET_MID_BYTE(channel), | ||
| 462 | calibbias[1]); | ||
| 463 | if (ret) | ||
| 464 | return ret; | ||
| 465 | |||
| 466 | return ad7779_spi_write(st, AD7779_REG_CH_OFFSET_LOWER_BYTE(channel), | ||
| 467 | calibbias[2]); | ||
| 468 | } | ||
| 469 | |||
| 470 | static int ad7779_read_raw(struct iio_dev *indio_dev, | ||
| 471 | struct iio_chan_spec const *chan, int *val, | ||
| 472 | int *val2, long mask) | ||
| 473 | { | ||
| 474 | struct ad7779_state *st = iio_priv(indio_dev); | ||
| 475 | int ret; | ||
| 476 | |||
| 477 | iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { | ||
| 478 | switch (mask) { | ||
| 479 | case IIO_CHAN_INFO_CALIBSCALE: | ||
| 480 | ret = ad7779_get_calibscale(st, chan->channel); | ||
| 481 | if (ret < 0) | ||
| 482 | return ret; | ||
| 483 | *val = ret; | ||
| 484 | *val2 = GAIN_REL; | ||
| 485 | return IIO_VAL_FRACTIONAL; | ||
| 486 | case IIO_CHAN_INFO_CALIBBIAS: | ||
| 487 | ret = ad7779_get_calibbias(st, chan->channel); | ||
| 488 | if (ret < 0) | ||
| 489 | return ret; | ||
| 490 | *val = ret; | ||
| 491 | return IIO_VAL_INT; | ||
| 492 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 493 | *val = st->sampling_freq; | ||
| 494 | if (*val < 0) | ||
| 495 | return -EINVAL; | ||
| 496 | return IIO_VAL_INT; | ||
| 497 | default: | ||
| 498 | return -EINVAL; | ||
| 499 | } | ||
| 500 | } | ||
| 501 | unreachable(); | ||
| 502 | } | ||
| 503 | |||
| 504 | static int ad7779_write_raw(struct iio_dev *indio_dev, | ||
| 505 | struct iio_chan_spec const *chan, int val, int val2, | ||
| 506 | long mask) | ||
| 507 | { | ||
| 508 | struct ad7779_state *st = iio_priv(indio_dev); | ||
| 509 | |||
| 510 | iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { | ||
| 511 | switch (mask) { | ||
| 512 | case IIO_CHAN_INFO_CALIBSCALE: | ||
| 513 | return ad7779_set_calibscale(st, chan->channel, val2); | ||
| 514 | case IIO_CHAN_INFO_CALIBBIAS: | ||
| 515 | return ad7779_set_calibbias(st, chan->channel, val); | ||
| 516 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 517 | return ad7779_set_sampling_frequency(st, val); | ||
| 518 | default: | ||
| 519 | return -EINVAL; | ||
| 520 | } | ||
| 521 | } | ||
| 522 | unreachable(); | ||
| 523 | } | ||
| 524 | |||
| 525 | static int ad7779_buffer_preenable(struct iio_dev *indio_dev) | ||
| 526 | { | ||
| 527 | int ret; | ||
| 528 | struct ad7779_state *st = iio_priv(indio_dev); | ||
| 529 | |||
| 530 | ret = ad7779_spi_write_mask(st, | ||
| 531 | AD7779_REG_GENERAL_USER_CONFIG_3, | ||
| 532 | AD7779_MOD_SPI_EN_MSK, | ||
| 533 | FIELD_PREP(AD7779_MOD_SPI_EN_MSK, 1)); | ||
| 534 | if (ret) | ||
| 535 | return ret; | ||
| 536 | |||
| 537 | /* | ||
| 538 | * DRDY output cannot be disabled at device level therefore we mask | ||
| 539 | * the irq at host end. | ||
| 540 | */ | ||
| 541 | enable_irq(st->spi->irq); | ||
| 542 | |||
| 543 | return 0; | ||
| 544 | } | ||
| 545 | |||
| 546 | static int ad7779_buffer_postdisable(struct iio_dev *indio_dev) | ||
| 547 | { | ||
| 548 | struct ad7779_state *st = iio_priv(indio_dev); | ||
| 549 | |||
| 550 | disable_irq(st->spi->irq); | ||
| 551 | |||
| 552 | return ad7779_spi_write(st, AD7779_REG_GENERAL_USER_CONFIG_3, | ||
| 553 | AD7779_DISABLE_SD); | ||
| 554 | } | ||
| 555 | |||
| 556 | static irqreturn_t ad7779_trigger_handler(int irq, void *p) | ||
| 557 | { | ||
| 558 | struct iio_poll_func *pf = p; | ||
| 559 | struct iio_dev *indio_dev = pf->indio_dev; | ||
| 560 | struct ad7779_state *st = iio_priv(indio_dev); | ||
| 561 | int ret; | ||
| 562 | struct spi_transfer t = { | ||
| 563 | .rx_buf = st->data.chans, | ||
| 564 | .tx_buf = st->spidata_tx, | ||
| 565 | .len = AD7779_NUM_CHANNELS * AD7779_CHAN_DATA_SIZE, | ||
| 566 | }; | ||
| 567 | |||
| 568 | st->spidata_tx[0] = AD7779_SPI_READ_CMD; | ||
| 569 | ret = spi_sync_transfer(st->spi, &t, 1); | ||
| 570 | if (ret) { | ||
| 571 | dev_err(&st->spi->dev, "SPI transfer error in IRQ handler"); | ||
| 572 | goto exit_handler; | ||
| 573 | } | ||
| 574 | |||
| 575 | iio_push_to_buffers_with_timestamp(indio_dev, &st->data, pf->timestamp); | ||
| 576 | |||
| 577 | exit_handler: | ||
| 578 | iio_trigger_notify_done(indio_dev->trig); | ||
| 579 | return IRQ_HANDLED; | ||
| 580 | } | ||
| 581 | |||
| 582 | static int ad7779_reset(struct iio_dev *indio_dev, struct gpio_desc *reset_gpio) | ||
| 583 | { | ||
| 584 | struct ad7779_state *st = iio_priv(indio_dev); | ||
| 585 | int ret; | ||
| 586 | struct spi_transfer t = { | ||
| 587 | .tx_buf = st->reset_buf, | ||
| 588 | .len = 8, | ||
| 589 | }; | ||
| 590 | |||
| 591 | if (reset_gpio) { | ||
| 592 | gpiod_set_value(reset_gpio, 1); | ||
| 593 | /* Delay for reset to occur is 225 microseconds */ | ||
| 594 | fsleep(230); | ||
| 595 | ret = 0; | ||
| 596 | } else { | ||
| 597 | memset(st->reset_buf, 0xff, sizeof(st->reset_buf)); | ||
| 598 | ret = spi_sync_transfer(st->spi, &t, 1); | ||
| 599 | if (ret) | ||
| 600 | return ret; | ||
| 601 | } | ||
| 602 | |||
| 603 | /* Delay for reset to occur is 225 microseconds */ | ||
| 604 | fsleep(230); | ||
| 605 | |||
| 606 | return ret; | ||
| 607 | } | ||
| 608 | |||
| 609 | static const struct iio_info ad7779_info = { | ||
| 610 | .read_raw = ad7779_read_raw, | ||
| 611 | .write_raw = ad7779_write_raw, | ||
| 612 | .debugfs_reg_access = &ad7779_reg_access, | ||
| 613 | }; | ||
| 614 | |||
| 615 | static const struct iio_enum ad7779_filter_enum = { | ||
| 616 | .items = ad7779_filter_type, | ||
| 617 | .num_items = ARRAY_SIZE(ad7779_filter_type), | ||
| 618 | .get = ad7779_get_filter, | ||
| 619 | .set = ad7779_set_filter, | ||
| 620 | }; | ||
| 621 | |||
| 622 | static const struct iio_chan_spec_ext_info ad7779_ext_filter[] = { | ||
| 623 | IIO_ENUM("filter_type", IIO_SHARED_BY_ALL, &ad7779_filter_enum), | ||
| 624 | IIO_ENUM_AVAILABLE("filter_type", IIO_SHARED_BY_ALL, | ||
| 625 | &ad7779_filter_enum), | ||
| 626 | { } | ||
| 627 | }; | ||
| 628 | |||
| 629 | #define AD777x_CHAN_S(index, _ext_info) \ | ||
| 630 | { \ | ||
| 631 | .type = IIO_VOLTAGE, \ | ||
| 632 | .info_mask_separate = BIT(IIO_CHAN_INFO_CALIBSCALE) | \ | ||
| 633 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ | ||
| 634 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ | ||
| 635 | .address = (index), \ | ||
| 636 | .indexed = 1, \ | ||
| 637 | .channel = (index), \ | ||
| 638 | .scan_index = (index), \ | ||
| 639 | .ext_info = (_ext_info), \ | ||
| 640 | .scan_type = { \ | ||
| 641 | .sign = 's', \ | ||
| 642 | .realbits = 24, \ | ||
| 643 | .storagebits = 32, \ | ||
| 644 | .endianness = IIO_BE, \ | ||
| 645 | }, \ | ||
| 646 | } | ||
| 647 | |||
| 648 | #define AD777x_CHAN_NO_FILTER_S(index) \ | ||
| 649 | AD777x_CHAN_S(index, NULL) | ||
| 650 | |||
| 651 | #define AD777x_CHAN_FILTER_S(index) \ | ||
| 652 | AD777x_CHAN_S(index, ad7779_ext_filter) | ||
| 653 | static const struct iio_chan_spec ad7779_channels[] = { | ||
| 654 | AD777x_CHAN_NO_FILTER_S(0), | ||
| 655 | AD777x_CHAN_NO_FILTER_S(1), | ||
| 656 | AD777x_CHAN_NO_FILTER_S(2), | ||
| 657 | AD777x_CHAN_NO_FILTER_S(3), | ||
| 658 | AD777x_CHAN_NO_FILTER_S(4), | ||
| 659 | AD777x_CHAN_NO_FILTER_S(5), | ||
| 660 | AD777x_CHAN_NO_FILTER_S(6), | ||
| 661 | AD777x_CHAN_NO_FILTER_S(7), | ||
| 662 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
| 663 | }; | ||
| 664 | |||
| 665 | static const struct iio_chan_spec ad7779_channels_filter[] = { | ||
| 666 | AD777x_CHAN_FILTER_S(0), | ||
| 667 | AD777x_CHAN_FILTER_S(1), | ||
| 668 | AD777x_CHAN_FILTER_S(2), | ||
| 669 | AD777x_CHAN_FILTER_S(3), | ||
| 670 | AD777x_CHAN_FILTER_S(4), | ||
| 671 | AD777x_CHAN_FILTER_S(5), | ||
| 672 | AD777x_CHAN_FILTER_S(6), | ||
| 673 | AD777x_CHAN_FILTER_S(7), | ||
| 674 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
| 675 | }; | ||
| 676 | |||
| 677 | static const struct iio_buffer_setup_ops ad7779_buffer_setup_ops = { | ||
| 678 | .preenable = ad7779_buffer_preenable, | ||
| 679 | .postdisable = ad7779_buffer_postdisable, | ||
| 680 | }; | ||
| 681 | |||
| 682 | static const struct iio_trigger_ops ad7779_trigger_ops = { | ||
| 683 | .validate_device = iio_trigger_validate_own_device, | ||
| 684 | }; | ||
| 685 | |||
| 686 | static int ad7779_conf(struct ad7779_state *st, struct gpio_desc *start_gpio) | ||
| 687 | { | ||
| 688 | int ret; | ||
| 689 | |||
| 690 | ret = ad7779_spi_write_mask(st, AD7779_REG_GEN_ERR_REG_1_EN, | ||
| 691 | AD7779_SPI_CRC_EN_MSK, | ||
| 692 | FIELD_PREP(AD7779_SPI_CRC_EN_MSK, 1)); | ||
| 693 | if (ret) | ||
| 694 | return ret; | ||
| 695 | |||
| 696 | ret = ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1, | ||
| 697 | AD7779_USRMOD_INIT_MSK, | ||
| 698 | FIELD_PREP(AD7779_USRMOD_INIT_MSK, 5)); | ||
| 699 | if (ret) | ||
| 700 | return ret; | ||
| 701 | |||
| 702 | ret = ad7779_spi_write_mask(st, AD7779_REG_DOUT_FORMAT, | ||
| 703 | AD7779_DCLK_CLK_DIV_MSK, | ||
| 704 | FIELD_PREP(AD7779_DCLK_CLK_DIV_MSK, 1)); | ||
| 705 | if (ret) | ||
| 706 | return ret; | ||
| 707 | |||
| 708 | ret = ad7779_spi_write_mask(st, AD7779_REG_ADC_MUX_CONFIG, | ||
| 709 | AD7779_REFMUX_CTRL_MSK, | ||
| 710 | FIELD_PREP(AD7779_REFMUX_CTRL_MSK, 1)); | ||
| 711 | if (ret) | ||
| 712 | return ret; | ||
| 713 | |||
| 714 | ret = ad7779_set_sampling_frequency(st, AD7779_DEFAULT_SAMPLING_FREQ); | ||
| 715 | if (ret) | ||
| 716 | return ret; | ||
| 717 | |||
| 718 | gpiod_set_value(start_gpio, 0); | ||
| 719 | /* Start setup time */ | ||
| 720 | fsleep(15); | ||
| 721 | gpiod_set_value(start_gpio, 1); | ||
| 722 | /* Start setup time */ | ||
| 723 | fsleep(15); | ||
| 724 | gpiod_set_value(start_gpio, 0); | ||
| 725 | /* Start setup time */ | ||
| 726 | fsleep(15); | ||
| 727 | |||
| 728 | return 0; | ||
| 729 | } | ||
| 730 | |||
| 731 | static int ad7779_probe(struct spi_device *spi) | ||
| 732 | { | ||
| 733 | struct iio_dev *indio_dev; | ||
| 734 | struct ad7779_state *st; | ||
| 735 | struct gpio_desc *reset_gpio, *start_gpio; | ||
| 736 | struct device *dev = &spi->dev; | ||
| 737 | int ret = -EINVAL; | ||
| 738 | |||
| 739 | if (!spi->irq) | ||
| 740 | return dev_err_probe(dev, ret, "DRDY irq not present\n"); | ||
| 741 | |||
| 742 | indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); | ||
| 743 | if (!indio_dev) | ||
| 744 | return -ENOMEM; | ||
| 745 | |||
| 746 | st = iio_priv(indio_dev); | ||
| 747 | |||
| 748 | ret = devm_regulator_bulk_get_enable(dev, | ||
| 749 | ARRAY_SIZE(ad7779_power_supplies), | ||
| 750 | ad7779_power_supplies); | ||
| 751 | if (ret) | ||
| 752 | return dev_err_probe(dev, ret, | ||
| 753 | "failed to get and enable supplies\n"); | ||
| 754 | |||
| 755 | st->mclk = devm_clk_get_enabled(dev, "mclk"); | ||
| 756 | if (IS_ERR(st->mclk)) | ||
| 757 | return PTR_ERR(st->mclk); | ||
| 758 | |||
| 759 | reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); | ||
| 760 | if (IS_ERR(reset_gpio)) | ||
| 761 | return PTR_ERR(reset_gpio); | ||
| 762 | |||
| 763 | start_gpio = devm_gpiod_get(dev, "start", GPIOD_OUT_HIGH); | ||
| 764 | if (IS_ERR(start_gpio)) | ||
| 765 | return PTR_ERR(start_gpio); | ||
| 766 | |||
| 767 | crc8_populate_msb(ad7779_crc8_table, AD7779_CRC8_POLY); | ||
| 768 | st->spi = spi; | ||
| 769 | |||
| 770 | st->chip_info = spi_get_device_match_data(spi); | ||
| 771 | if (!st->chip_info) | ||
| 772 | return -ENODEV; | ||
| 773 | |||
| 774 | ret = ad7779_reset(indio_dev, reset_gpio); | ||
| 775 | if (ret) | ||
| 776 | return ret; | ||
| 777 | |||
| 778 | ret = ad7779_conf(st, start_gpio); | ||
| 779 | if (ret) | ||
| 780 | return ret; | ||
| 781 | |||
| 782 | indio_dev->name = st->chip_info->name; | ||
| 783 | indio_dev->info = &ad7779_info; | ||
| 784 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
| 785 | indio_dev->channels = st->chip_info->channels; | ||
| 786 | indio_dev->num_channels = ARRAY_SIZE(ad7779_channels); | ||
| 787 | |||
| 788 | st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, | ||
| 789 | iio_device_id(indio_dev)); | ||
| 790 | if (!st->trig) | ||
| 791 | return -ENOMEM; | ||
| 792 | |||
| 793 | st->trig->ops = &ad7779_trigger_ops; | ||
| 794 | |||
| 795 | iio_trigger_set_drvdata(st->trig, st); | ||
| 796 | |||
| 797 | ret = devm_request_irq(dev, spi->irq, iio_trigger_generic_data_rdy_poll, | ||
| 798 | IRQF_ONESHOT | IRQF_NO_AUTOEN, indio_dev->name, | ||
| 799 | st->trig); | ||
| 800 | if (ret) | ||
| 801 | return dev_err_probe(dev, ret, "request IRQ %d failed\n", | ||
| 802 | st->spi->irq); | ||
| 803 | |||
| 804 | ret = devm_iio_trigger_register(dev, st->trig); | ||
| 805 | if (ret) | ||
| 806 | return ret; | ||
| 807 | |||
| 808 | indio_dev->trig = iio_trigger_get(st->trig); | ||
| 809 | |||
| 810 | init_completion(&st->completion); | ||
| 811 | |||
| 812 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, | ||
| 813 | &iio_pollfunc_store_time, | ||
| 814 | &ad7779_trigger_handler, | ||
| 815 | &ad7779_buffer_setup_ops); | ||
| 816 | if (ret) | ||
| 817 | return ret; | ||
| 818 | |||
| 819 | ret = ad7779_spi_write_mask(st, AD7779_REG_DOUT_FORMAT, | ||
| 820 | AD7779_DCLK_CLK_DIV_MSK, | ||
| 821 | FIELD_PREP(AD7779_DCLK_CLK_DIV_MSK, 7)); | ||
| 822 | if (ret) | ||
| 823 | return ret; | ||
| 824 | |||
| 825 | return devm_iio_device_register(dev, indio_dev); | ||
| 826 | } | ||
| 827 | |||
| 828 | static int ad7779_suspend(struct device *dev) | ||
| 829 | { | ||
| 830 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
| 831 | struct ad7779_state *st = iio_priv(indio_dev); | ||
| 832 | |||
| 833 | return ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1, | ||
| 834 | AD7779_MOD_POWERMODE_MSK, | ||
| 835 | FIELD_PREP(AD7779_MOD_POWERMODE_MSK, | ||
| 836 | AD7779_LOW_POWER)); | ||
| 837 | } | ||
| 838 | |||
| 839 | static int ad7779_resume(struct device *dev) | ||
| 840 | { | ||
| 841 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
| 842 | struct ad7779_state *st = iio_priv(indio_dev); | ||
| 843 | |||
| 844 | return ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1, | ||
| 845 | AD7779_MOD_POWERMODE_MSK, | ||
| 846 | FIELD_PREP(AD7779_MOD_POWERMODE_MSK, | ||
| 847 | AD7779_HIGH_POWER)); | ||
| 848 | } | ||
| 849 | |||
| 850 | static DEFINE_SIMPLE_DEV_PM_OPS(ad7779_pm_ops, ad7779_suspend, ad7779_resume); | ||
| 851 | |||
| 852 | static const struct ad7779_chip_info ad7770_chip_info = { | ||
| 853 | .name = "ad7770", | ||
| 854 | .channels = ad7779_channels, | ||
| 855 | }; | ||
| 856 | |||
| 857 | static const struct ad7779_chip_info ad7771_chip_info = { | ||
| 858 | .name = "ad7771", | ||
| 859 | .channels = ad7779_channels_filter, | ||
| 860 | }; | ||
| 861 | |||
| 862 | static const struct ad7779_chip_info ad7779_chip_info = { | ||
| 863 | .name = "ad7779", | ||
| 864 | .channels = ad7779_channels, | ||
| 865 | }; | ||
| 866 | |||
| 867 | static const struct spi_device_id ad7779_id[] = { | ||
| 868 | { | ||
| 869 | .name = "ad7770", | ||
| 870 | .driver_data = (kernel_ulong_t)&ad7770_chip_info, | ||
| 871 | }, | ||
| 872 | { | ||
| 873 | .name = "ad7771", | ||
| 874 | .driver_data = (kernel_ulong_t)&ad7771_chip_info, | ||
| 875 | }, | ||
| 876 | { | ||
| 877 | .name = "ad7779", | ||
| 878 | .driver_data = (kernel_ulong_t)&ad7779_chip_info, | ||
| 879 | }, | ||
| 880 | { } | ||
| 881 | }; | ||
| 882 | MODULE_DEVICE_TABLE(spi, ad7779_id); | ||
| 883 | |||
| 884 | static const struct of_device_id ad7779_of_table[] = { | ||
| 885 | { | ||
| 886 | .compatible = "adi,ad7770", | ||
| 887 | .data = &ad7770_chip_info, | ||
| 888 | }, | ||
| 889 | { | ||
| 890 | .compatible = "adi,ad7771", | ||
| 891 | .data = &ad7771_chip_info, | ||
| 892 | }, | ||
| 893 | { | ||
| 894 | .compatible = "adi,ad7779", | ||
| 895 | .data = &ad7779_chip_info, | ||
| 896 | }, | ||
| 897 | { } | ||
| 898 | }; | ||
| 899 | MODULE_DEVICE_TABLE(of, ad7779_of_table); | ||
| 900 | |||
| 901 | static struct spi_driver ad7779_driver = { | ||
| 902 | .driver = { | ||
| 903 | .name = "ad7779", | ||
| 904 | .pm = pm_sleep_ptr(&ad7779_pm_ops), | ||
| 905 | .of_match_table = ad7779_of_table, | ||
| 906 | }, | ||
| 907 | .probe = ad7779_probe, | ||
| 908 | .id_table = ad7779_id, | ||
| 909 | }; | ||
| 910 | module_spi_driver(ad7779_driver); | ||
| 911 | |||
| 912 | MODULE_AUTHOR("Ramona Alexandra Nechita <ramona.nechita@analog.com>"); | ||
| 913 | MODULE_DESCRIPTION("Analog Devices AD7779 ADC"); | ||
| 914 | MODULE_LICENSE("GPL"); | ||
| @@ -152,7 +152,7 @@ static int ad7780_write_raw(struct iio_dev *indio_dev, · 151 unmodified lines | |||
| 152 | 152 | ||
| 153 | switch (m) { | 153 | switch (m) { |
| 154 | case IIO_CHAN_INFO_SCALE: | 154 | case IIO_CHAN_INFO_SCALE: |
| 155 | if (val != 0) | 155 | if (val != 0 || val2 == 0) |
| 156 | return -EINVAL; | 156 | return -EINVAL; |
| 157 | 157 | ||
| 158 | vref = st->int_vref_mv * 1000000LL; | 158 | vref = st->int_vref_mv * 1000000LL; |
| @@ -371,7 +371,7 @@ static const struct iio_info ad7791_no_filter_info = { · 370 unmodified lines | |||
| 371 | }; | 371 | }; |
| 372 | 372 | ||
| 373 | static int ad7791_setup(struct ad7791_state *st, | 373 | static int ad7791_setup(struct ad7791_state *st, |
| 374 | struct ad7791_platform_data *pdata) | 374 | const struct ad7791_platform_data *pdata) |
| 375 | { | 375 | { |
| 376 | /* Set to poweron-reset default values */ | 376 | /* Set to poweron-reset default values */ |
| 377 | st->mode = AD7791_MODE_BUFFER; | 377 | st->mode = AD7791_MODE_BUFFER; |
| @@ -401,7 +401,7 @@ static void ad7791_reg_disable(void *reg) · 23 unmodified lines | |||
| 401 | 401 | ||
| 402 | static int ad7791_probe(struct spi_device *spi) | 402 | static int ad7791_probe(struct spi_device *spi) |
| 403 | { | 403 | { |
| 404 | struct ad7791_platform_data *pdata = spi->dev.platform_data; | 404 | const struct ad7791_platform_data *pdata = dev_get_platdata(&spi->dev); |
| 405 | struct iio_dev *indio_dev; | 405 | struct iio_dev *indio_dev; |
| 406 | struct ad7791_state *st; | 406 | struct ad7791_state *st; |
| 407 | int ret; | 407 | int ret; |
| @@ -770,7 +770,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { · 769 unmodified lines | |||
| 770 | 770 | ||
| 771 | static int ad7793_probe(struct spi_device *spi) | 771 | static int ad7793_probe(struct spi_device *spi) |
| 772 | { | 772 | { |
| 773 | const struct ad7793_platform_data *pdata = spi->dev.platform_data; | 773 | const struct ad7793_platform_data *pdata = dev_get_platdata(&spi->dev); |
| 774 | struct ad7793_state *st; | 774 | struct ad7793_state *st; |
| 775 | struct iio_dev *indio_dev; | 775 | struct iio_dev *indio_dev; |
| 776 | int ret, vref_mv = 0; | 776 | int ret, vref_mv = 0; |
| @@ -41,7 +41,7 @@ enum ad7887_channels { · 40 unmodified lines | |||
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| 44 | * struct ad7887_chip_info - chip specifc information | 44 | * struct ad7887_chip_info - chip specific information |
| 45 | * @int_vref_mv: the internal reference voltage | 45 | * @int_vref_mv: the internal reference voltage |
| 46 | * @channels: channels specification | 46 | * @channels: channels specification |
| 47 | * @num_channels: number of channels | 47 | * @num_channels: number of channels |
| @@ -234,7 +234,7 @@ static void ad7887_reg_disable(void *data) · 186 unmodified lines | |||
| 234 | 234 | ||
| 235 | static int ad7887_probe(struct spi_device *spi) | 235 | static int ad7887_probe(struct spi_device *spi) |
| 236 | { | 236 | { |
| 237 | struct ad7887_platform_data *pdata = spi->dev.platform_data; | 237 | const struct ad7887_platform_data *pdata = dev_get_platdata(&spi->dev); |
| 238 | struct ad7887_state *st; | 238 | struct ad7887_state *st; |
| 239 | struct iio_dev *indio_dev; | 239 | struct iio_dev *indio_dev; |
| 240 | uint8_t mode; | 240 | uint8_t mode; |
| @@ -48,7 +48,7 @@ · 47 unmodified lines | |||
| 48 | 48 | ||
| 49 | struct ad7923_state { | 49 | struct ad7923_state { |
| 50 | struct spi_device *spi; | 50 | struct spi_device *spi; |
| 51 | struct spi_transfer ring_xfer[5]; | 51 | struct spi_transfer ring_xfer[9]; |
| 52 | struct spi_transfer scan_single_xfer[2]; | 52 | struct spi_transfer scan_single_xfer[2]; |
| 53 | struct spi_message ring_msg; | 53 | struct spi_message ring_msg; |
| 54 | struct spi_message scan_single_msg; | 54 | struct spi_message scan_single_msg; |
| @@ -64,7 +64,7 @@ struct ad7923_state { · 9 unmodified lines | |||
| 64 | * Length = 8 channels + 4 extra for 8 byte timestamp | 64 | * Length = 8 channels + 4 extra for 8 byte timestamp |
| 65 | */ | 65 | */ |
| 66 | __be16 rx_buf[12] __aligned(IIO_DMA_MINALIGN); | 66 | __be16 rx_buf[12] __aligned(IIO_DMA_MINALIGN); |
| 67 | __be16 tx_buf[4]; | 67 | __be16 tx_buf[8]; |
| 68 | }; | 68 | }; |
| 69 | 69 | ||
| 70 | struct ad7923_chip_info { | 70 | struct ad7923_chip_info { |
| @@ -80,7 +80,7 @@ struct ad7944_adc { · 79 unmodified lines | |||
| 80 | }; | 80 | }; |
| 81 | 81 | ||
| 82 | /* quite time before CNV rising edge */ | 82 | /* quite time before CNV rising edge */ |
| 83 | #define T_QUIET_NS 20 | 83 | #define AD7944_T_QUIET_NS 20 |
| 84 | 84 | ||
| 85 | static const struct ad7944_timing_spec ad7944_timing_spec = { | 85 | static const struct ad7944_timing_spec ad7944_timing_spec = { |
| 86 | .conv_ns = 420, | 86 | .conv_ns = 420, |
| @@ -150,7 +150,7 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc * · 63 unmodified lines | |||
| 150 | * CS is tied to CNV and we need a low to high transition to start the | 150 | * CS is tied to CNV and we need a low to high transition to start the |
| 151 | * conversion, so place CNV low for t_QUIET to prepare for this. | 151 | * conversion, so place CNV low for t_QUIET to prepare for this. |
| 152 | */ | 152 | */ |
| 153 | xfers[0].delay.value = T_QUIET_NS; | 153 | xfers[0].delay.value = AD7944_T_QUIET_NS; |
| 154 | xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS; | 154 | xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS; |
| 155 | 155 | ||
| 156 | /* | 156 | /* |
| @@ -406,7 +406,7 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev, · 405 unmodified lines | |||
| 406 | const struct iio_chan_spec *chan, | 406 | const struct iio_chan_spec *chan, |
| 407 | enum iio_event_type type, | 407 | enum iio_event_type type, |
| 408 | enum iio_event_direction dir, | 408 | enum iio_event_direction dir, |
| 409 | int state) | 409 | bool state) |
| 410 | { | 410 | { |
| 411 | struct ad799x_state *st = iio_priv(indio_dev); | 411 | struct ad799x_state *st = iio_priv(indio_dev); |
| 412 | int ret; | 412 | int ret; |
| @@ -469,7 +469,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p) · 468 unmodified lines | |||
| 469 | /* | 469 | /* |
| 470 | * Data array after transfer will look like (if status is appended): | 470 | * Data array after transfer will look like (if status is appended): |
| 471 | * data[] = { [0][sample][sample][sample][status] } | 471 | * data[] = { [0][sample][sample][sample][status] } |
| 472 | * Keeping the first byte 0 shifts the status postion by 1 byte to the right. | 472 | * Keeping the first byte 0 shifts the status position by 1 byte to the right. |
| 473 | */ | 473 | */ |
| 474 | status_pos = reg_size + 1; | 474 | status_pos = reg_size + 1; |
| 475 | 475 | ||
| @@ -656,7 +656,7 @@ int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev, · 180 unmodified lines | |||
| 656 | sigma_delta->spi = spi; | 656 | sigma_delta->spi = spi; |
| 657 | sigma_delta->info = info; | 657 | sigma_delta->info = info; |
| 658 | 658 | ||
| 659 | /* If the field is unset in ad_sigma_delta_info, asume there can only be 1 slot. */ | 659 | /* If the field is unset in ad_sigma_delta_info, assume there can only be 1 slot. */ |
| 660 | if (!info->num_slots) | 660 | if (!info->num_slots) |
| 661 | sigma_delta->num_slots = 1; | 661 | sigma_delta->num_slots = 1; |
| 662 | else | 662 | else |
| @@ -2625,7 +2625,7 @@ MODULE_DEVICE_TABLE(of, at91_adc_dt_match); · 2624 unmodified lines | |||
| 2625 | 2625 | ||
| 2626 | static struct platform_driver at91_adc_driver = { | 2626 | static struct platform_driver at91_adc_driver = { |
| 2627 | .probe = at91_adc_probe, | 2627 | .probe = at91_adc_probe, |
| 2628 | .remove_new = at91_adc_remove, | 2628 | .remove = at91_adc_remove, |
| 2629 | .driver = { | 2629 | .driver = { |
| 2630 | .name = "at91-sama5d2_adc", | 2630 | .name = "at91-sama5d2_adc", |
| 2631 | .of_match_table = at91_adc_dt_match, | 2631 | .of_match_table = at91_adc_dt_match, |
| @@ -1341,7 +1341,7 @@ MODULE_DEVICE_TABLE(of, at91_adc_dt_ids); · 1340 unmodified lines | |||
| 1341 | 1341 | ||
| 1342 | static struct platform_driver at91_adc_driver = { | 1342 | static struct platform_driver at91_adc_driver = { |
| 1343 | .probe = at91_adc_probe, | 1343 | .probe = at91_adc_probe, |
| 1344 | .remove_new = at91_adc_remove, | 1344 | .remove = at91_adc_remove, |
| 1345 | .driver = { | 1345 | .driver = { |
| 1346 | .name = DRIVER_NAME, | 1346 | .name = DRIVER_NAME, |
| 1347 | .of_match_table = at91_adc_dt_ids, | 1347 | .of_match_table = at91_adc_dt_ids, |
| @@ -155,52 +155,22 @@ enum axp813_adc_channel_v { · 154 unmodified lines | |||
| 155 | AXP813_BATT_V, | 155 | AXP813_BATT_V, |
| 156 | }; | 156 | }; |
| 157 | 157 | ||
| 158 | static struct iio_map axp20x_maps[] = { | 158 | static const struct iio_map axp20x_maps[] = { |
| 159 | { | 159 | IIO_MAP("vbus_v", "axp20x-usb-power-supply", "vbus_v"), |
| 160 | .consumer_dev_name = "axp20x-usb-power-supply", | 160 | IIO_MAP("vbus_i", "axp20x-usb-power-supply", "vbus_i"), |
| 161 | .consumer_channel = "vbus_v", | 161 | IIO_MAP("acin_v", "axp20x-ac-power-supply", "acin_v"), |
| 162 | .adc_channel_label = "vbus_v", | 162 | IIO_MAP("acin_i", "axp20x-ac-power-supply", "acin_i"), |
| 163 | }, { | 163 | IIO_MAP("batt_v", "axp20x-battery-power-supply", "batt_v"), |
| 164 | .consumer_dev_name = "axp20x-usb-power-supply", | 164 | IIO_MAP("batt_chrg_i", "axp20x-battery-power-supply", "batt_chrg_i"), |
| 165 | .consumer_channel = "vbus_i", | 165 | IIO_MAP("batt_dischrg_i", "axp20x-battery-power-supply", "batt_dischrg_i"), |
| 166 | .adc_channel_label = "vbus_i", | 166 | { /* sentinel */ } |
| 167 | }, { | ||
| 168 | .consumer_dev_name = "axp20x-ac-power-supply", | ||
| 169 | .consumer_channel = "acin_v", | ||
| 170 | .adc_channel_label = "acin_v", | ||
| 171 | }, { | ||
| 172 | .consumer_dev_name = "axp20x-ac-power-supply", | ||
| 173 | .consumer_channel = "acin_i", | ||
| 174 | .adc_channel_label = "acin_i", | ||
| 175 | }, { | ||
| 176 | .consumer_dev_name = "axp20x-battery-power-supply", | ||
| 177 | .consumer_channel = "batt_v", | ||
| 178 | .adc_channel_label = "batt_v", | ||
| 179 | }, { | ||
| 180 | .consumer_dev_name = "axp20x-battery-power-supply", | ||
| 181 | .consumer_channel = "batt_chrg_i", | ||
| 182 | .adc_channel_label = "batt_chrg_i", | ||
| 183 | }, { | ||
| 184 | .consumer_dev_name = "axp20x-battery-power-supply", | ||
| 185 | .consumer_channel = "batt_dischrg_i", | ||
| 186 | .adc_channel_label = "batt_dischrg_i", | ||
| 187 | }, { /* sentinel */ } | ||
| 188 | }; | 167 | }; |
| 189 | 168 | ||
| 190 | static struct iio_map axp22x_maps[] = { | 169 | static const struct iio_map axp22x_maps[] = { |
| 191 | { | 170 | IIO_MAP("batt_v", "axp20x-battery-power-supply", "batt_v"), |
| 192 | .consumer_dev_name = "axp20x-battery-power-supply", | 171 | IIO_MAP("batt_chrg_i", "axp20x-battery-power-supply", "batt_chrg_i"), |
| 193 | .consumer_channel = "batt_v", | 172 | IIO_MAP("batt_dischrg_i", "axp20x-battery-power-supply", "batt_dischrg_i"), |
| 194 | .adc_channel_label = "batt_v", | 173 | { /* sentinel */ } |
| 195 | }, { | ||
| 196 | .consumer_dev_name = "axp20x-battery-power-supply", | ||
| 197 | .consumer_channel = "batt_chrg_i", | ||
| 198 | .adc_channel_label = "batt_chrg_i", | ||
| 199 | }, { | ||
| 200 | .consumer_dev_name = "axp20x-battery-power-supply", | ||
| 201 | .consumer_channel = "batt_dischrg_i", | ||
| 202 | .adc_channel_label = "batt_dischrg_i", | ||
| 203 | }, { /* sentinel */ } | ||
| 204 | }; | 174 | }; |
| 205 | 175 | ||
| 206 | static struct iio_map axp717_maps[] = { | 176 | static struct iio_map axp717_maps[] = { |
| @@ -1044,7 +1014,7 @@ struct axp_data { · 837 unmodified lines | |||
| 1044 | unsigned long adc_en2_mask; | 1014 | unsigned long adc_en2_mask; |
| 1045 | int (*adc_rate)(struct axp20x_adc_iio *info, | 1015 | int (*adc_rate)(struct axp20x_adc_iio *info, |
| 1046 | int rate); | 1016 | int rate); |
| 1047 | struct iio_map *maps; | 1017 | const struct iio_map *maps; |
| 1048 | }; | 1018 | }; |
| 1049 | 1019 | ||
| 1050 | static const struct axp_data axp192_data = { | 1020 | static const struct axp_data axp192_data = { |
| @@ -1212,7 +1182,7 @@ static struct platform_driver axp20x_adc_driver = { · 161 unmodified lines | |||
| 1212 | }, | 1182 | }, |
| 1213 | .id_table = axp20x_adc_id_match, | 1183 | .id_table = axp20x_adc_id_match, |
| 1214 | .probe = axp20x_probe, | 1184 | .probe = axp20x_probe, |
| 1215 | .remove_new = axp20x_remove, | 1185 | .remove = axp20x_remove, |
| 1216 | }; | 1186 | }; |
| 1217 | 1187 | ||
| 1218 | module_platform_driver(axp20x_adc_driver); | 1188 | module_platform_driver(axp20x_adc_driver); |
| @@ -103,7 +103,7 @@ static const struct iio_chan_spec axp288_adc_channels[] = { · 102 unmodified lines | |||
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | /* for consumer drivers */ | 105 | /* for consumer drivers */ |
| 106 | static struct iio_map axp288_adc_default_maps[] = { | 106 | static const struct iio_map axp288_adc_default_maps[] = { |
| 107 | IIO_MAP("TS_PIN", "axp288-batt", "axp288-batt-temp"), | 107 | IIO_MAP("TS_PIN", "axp288-batt", "axp288-batt-temp"), |
| 108 | IIO_MAP("PMIC_TEMP", "axp288-pmic", "axp288-pmic-temp"), | 108 | IIO_MAP("PMIC_TEMP", "axp288-pmic", "axp288-pmic-temp"), |
| 109 | IIO_MAP("GPADC", "axp288-gpadc", "axp288-system-temp"), | 109 | IIO_MAP("GPADC", "axp288-gpadc", "axp288-system-temp"), |
| @@ -611,10 +611,10 @@ static const struct of_device_id iproc_adc_of_match[] = { · 610 unmodified lines | |||
| 611 | MODULE_DEVICE_TABLE(of, iproc_adc_of_match); | 611 | MODULE_DEVICE_TABLE(of, iproc_adc_of_match); |
| 612 | 612 | ||
| 613 | static struct platform_driver iproc_adc_driver = { | 613 | static struct platform_driver iproc_adc_driver = { |
| 614 | .probe = iproc_adc_probe, | 614 | .probe = iproc_adc_probe, |
| 615 | .remove_new = iproc_adc_remove, | 615 | .remove = iproc_adc_remove, |
| 616 | .driver = { | 616 | .driver = { |
| 617 | .name = "iproc-static-adc", | 617 | .name = "iproc-static-adc", |
| 618 | .of_match_table = iproc_adc_of_match, | 618 | .of_match_table = iproc_adc_of_match, |
| 619 | }, | 619 | }, |
| 620 | }; | 620 | }; |
| @@ -291,27 +291,11 @@ static const struct iio_chan_spec da9150_gpadc_channels[] = { · 290 unmodified lines | |||
| 291 | }; | 291 | }; |
| 292 | 292 | ||
| 293 | /* Default maps used by da9150-charger */ | 293 | /* Default maps used by da9150-charger */ |
| 294 | static struct iio_map da9150_gpadc_default_maps[] = { | 294 | static const struct iio_map da9150_gpadc_default_maps[] = { |
| 295 | { | 295 | IIO_MAP("IBUS", "da9150-charger", "CHAN_IBUS"), |
| 296 | .consumer_dev_name = "da9150-charger", | 296 | IIO_MAP("VBUS", "da9150-charger", "CHAN_VBUS"), |
| 297 | .consumer_channel = "CHAN_IBUS", | 297 | IIO_MAP("TJUNC_CORE", "da9150-charger", "CHAN_TJUNC"), |
| 298 | .adc_channel_label = "IBUS", | 298 | IIO_MAP("VBAT", "da9150-charger", "CHAN_VBAT"), |
| 299 | }, | ||
| 300 | { | ||
| 301 | .consumer_dev_name = "da9150-charger", | ||
| 302 | .consumer_channel = "CHAN_VBUS", | ||
| 303 | .adc_channel_label = "VBUS", | ||
| 304 | }, | ||
| 305 | { | ||
| 306 | .consumer_dev_name = "da9150-charger", | ||
| 307 | .consumer_channel = "CHAN_TJUNC", | ||
| 308 | .adc_channel_label = "TJUNC_CORE", | ||
| 309 | }, | ||
| 310 | { | ||
| 311 | .consumer_dev_name = "da9150-charger", | ||
| 312 | .consumer_channel = "CHAN_VBAT", | ||
| 313 | .adc_channel_label = "VBAT", | ||
| 314 | }, | ||
| 315 | {}, | 299 | {}, |
| 316 | }; | 300 | }; |
| 317 | 301 | ||
| @@ -700,7 +700,7 @@ static void dln2_adc_remove(struct platform_device *pdev) · 699 unmodified lines | |||
| 700 | static struct platform_driver dln2_adc_driver = { | 700 | static struct platform_driver dln2_adc_driver = { |
| 701 | .driver.name = DLN2_ADC_MOD_NAME, | 701 | .driver.name = DLN2_ADC_MOD_NAME, |
| 702 | .probe = dln2_adc_probe, | 702 | .probe = dln2_adc_probe, |
| 703 | .remove_new = dln2_adc_remove, | 703 | .remove = dln2_adc_remove, |
| 704 | }; | 704 | }; |
| 705 | 705 | ||
| 706 | module_platform_driver(dln2_adc_driver); | 706 | module_platform_driver(dln2_adc_driver); |
| @@ -238,7 +238,7 @@ static struct platform_driver ep93xx_adc_driver = { · 237 unmodified lines | |||
| 238 | .of_match_table = ep93xx_adc_of_ids, | 238 | .of_match_table = ep93xx_adc_of_ids, |
| 239 | }, | 239 | }, |
| 240 | .probe = ep93xx_adc_probe, | 240 | .probe = ep93xx_adc_probe, |
| 241 | .remove_new = ep93xx_adc_remove, | 241 | .remove = ep93xx_adc_remove, |
| 242 | }; | 242 | }; |
| 243 | module_platform_driver(ep93xx_adc_driver); | 243 | module_platform_driver(ep93xx_adc_driver); |
| 244 | 244 | ||
| @@ -1008,7 +1008,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(exynos_adc_pm_ops, exynos_adc_suspend, · 1007 unmodified lines | |||
| 1008 | 1008 | ||
| 1009 | static struct platform_driver exynos_adc_driver = { | 1009 | static struct platform_driver exynos_adc_driver = { |
| 1010 | .probe = exynos_adc_probe, | 1010 | .probe = exynos_adc_probe, |
| 1011 | .remove_new = exynos_adc_remove, | 1011 | .remove = exynos_adc_remove, |
| 1012 | .driver = { | 1012 | .driver = { |
| 1013 | .name = "exynos-adc", | 1013 | .name = "exynos-adc", |
| 1014 | .of_match_table = exynos_adc_match, | 1014 | .of_match_table = exynos_adc_match, |
| @@ -0,0 +1,228 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * The GE HealthCare PMC ADC is a 16-Channel (Voltage and current), 16-Bit | ||
| 4 | * ADC with an I2C Interface. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2024, GE HealthCare | ||
| 7 | * | ||
| 8 | * Authors: | ||
| 9 | * Herve Codina <herve.codina@bootlin.com> | ||
| 10 | */ | ||
| 11 | #include <dt-bindings/iio/adc/gehc,pmc-adc.h> | ||
| 12 | #include <linux/bitops.h> | ||
| 13 | #include <linux/clk.h> | ||
| 14 | #include <linux/i2c.h> | ||
| 15 | #include <linux/iio/iio.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/regulator/consumer.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | |||
| 20 | struct pmc_adc { | ||
| 21 | struct i2c_client *client; | ||
| 22 | }; | ||
| 23 | |||
| 24 | #define PMC_ADC_CMD_REQUEST_PROTOCOL_VERSION 0x01 | ||
| 25 | #define PMC_ADC_CMD_READ_VOLTAGE(_ch) (0x10 | (_ch)) | ||
| 26 | #define PMC_ADC_CMD_READ_CURRENT(_ch) (0x20 | (_ch)) | ||
| 27 | |||
| 28 | #define PMC_ADC_VOLTAGE_CHANNEL(_ch, _ds_name) { \ | ||
| 29 | .type = IIO_VOLTAGE, \ | ||
| 30 | .indexed = 1, \ | ||
| 31 | .channel = (_ch), \ | ||
| 32 | .address = PMC_ADC_CMD_READ_VOLTAGE(_ch), \ | ||
| 33 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ | ||
| 34 | .datasheet_name = (_ds_name), \ | ||
| 35 | } | ||
| 36 | |||
| 37 | #define PMC_ADC_CURRENT_CHANNEL(_ch, _ds_name) { \ | ||
| 38 | .type = IIO_CURRENT, \ | ||
| 39 | .indexed = 1, \ | ||
| 40 | .channel = (_ch), \ | ||
| 41 | .address = PMC_ADC_CMD_READ_CURRENT(_ch), \ | ||
| 42 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ | ||
| 43 | .datasheet_name = (_ds_name), \ | ||
| 44 | } | ||
| 45 | |||
| 46 | static const struct iio_chan_spec pmc_adc_channels[] = { | ||
| 47 | PMC_ADC_VOLTAGE_CHANNEL(0, "CH0_V"), | ||
| 48 | PMC_ADC_VOLTAGE_CHANNEL(1, "CH1_V"), | ||
| 49 | PMC_ADC_VOLTAGE_CHANNEL(2, "CH2_V"), | ||
| 50 | PMC_ADC_VOLTAGE_CHANNEL(3, "CH3_V"), | ||
| 51 | PMC_ADC_VOLTAGE_CHANNEL(4, "CH4_V"), | ||
| 52 | PMC_ADC_VOLTAGE_CHANNEL(5, "CH5_V"), | ||
| 53 | PMC_ADC_VOLTAGE_CHANNEL(6, "CH6_V"), | ||
| 54 | PMC_ADC_VOLTAGE_CHANNEL(7, "CH7_V"), | ||
| 55 | PMC_ADC_VOLTAGE_CHANNEL(8, "CH8_V"), | ||
| 56 | PMC_ADC_VOLTAGE_CHANNEL(9, "CH9_V"), | ||
| 57 | PMC_ADC_VOLTAGE_CHANNEL(10, "CH10_V"), | ||
| 58 | PMC_ADC_VOLTAGE_CHANNEL(11, "CH11_V"), | ||
| 59 | PMC_ADC_VOLTAGE_CHANNEL(12, "CH12_V"), | ||
| 60 | PMC_ADC_VOLTAGE_CHANNEL(13, "CH13_V"), | ||
| 61 | PMC_ADC_VOLTAGE_CHANNEL(14, "CH14_V"), | ||
| 62 | PMC_ADC_VOLTAGE_CHANNEL(15, "CH15_V"), | ||
| 63 | |||
| 64 | PMC_ADC_CURRENT_CHANNEL(0, "CH0_I"), | ||
| 65 | PMC_ADC_CURRENT_CHANNEL(1, "CH1_I"), | ||
| 66 | PMC_ADC_CURRENT_CHANNEL(2, "CH2_I"), | ||
| 67 | PMC_ADC_CURRENT_CHANNEL(3, "CH3_I"), | ||
| 68 | PMC_ADC_CURRENT_CHANNEL(4, "CH4_I"), | ||
| 69 | PMC_ADC_CURRENT_CHANNEL(5, "CH5_I"), | ||
| 70 | PMC_ADC_CURRENT_CHANNEL(6, "CH6_I"), | ||
| 71 | PMC_ADC_CURRENT_CHANNEL(7, "CH7_I"), | ||
| 72 | PMC_ADC_CURRENT_CHANNEL(8, "CH8_I"), | ||
| 73 | PMC_ADC_CURRENT_CHANNEL(9, "CH9_I"), | ||
| 74 | PMC_ADC_CURRENT_CHANNEL(10, "CH10_I"), | ||
| 75 | PMC_ADC_CURRENT_CHANNEL(11, "CH11_I"), | ||
| 76 | PMC_ADC_CURRENT_CHANNEL(12, "CH12_I"), | ||
| 77 | PMC_ADC_CURRENT_CHANNEL(13, "CH13_I"), | ||
| 78 | PMC_ADC_CURRENT_CHANNEL(14, "CH14_I"), | ||
| 79 | PMC_ADC_CURRENT_CHANNEL(15, "CH15_I"), | ||
| 80 | }; | ||
| 81 | |||
| 82 | static int pmc_adc_read_raw_ch(struct pmc_adc *pmc_adc, u8 cmd, int *val) | ||
| 83 | { | ||
| 84 | s32 ret; | ||
| 85 | |||
| 86 | ret = i2c_smbus_read_word_swapped(pmc_adc->client, cmd); | ||
| 87 | if (ret < 0) { | ||
| 88 | dev_err(&pmc_adc->client->dev, "i2c read word failed (%d)\n", ret); | ||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | |||
| 92 | *val = sign_extend32(ret, 15); | ||
| 93 | return 0; | ||
| 94 | } | ||
| 95 | |||
| 96 | static int pmc_adc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, | ||
| 97 | int *val, int *val2, long mask) | ||
| 98 | { | ||
| 99 | struct pmc_adc *pmc_adc = iio_priv(indio_dev); | ||
| 100 | int ret; | ||
| 101 | |||
| 102 | switch (mask) { | ||
| 103 | case IIO_CHAN_INFO_PROCESSED: | ||
| 104 | /* Values are directly read in mV or mA */ | ||
| 105 | ret = pmc_adc_read_raw_ch(pmc_adc, chan->address, val); | ||
| 106 | if (ret) | ||
| 107 | return ret; | ||
| 108 | return IIO_VAL_INT; | ||
| 109 | } | ||
| 110 | |||
| 111 | return -EINVAL; | ||
| 112 | } | ||
| 113 | |||
| 114 | static int pmc_adc_fwnode_xlate(struct iio_dev *indio_dev, | ||
| 115 | const struct fwnode_reference_args *iiospec) | ||
| 116 | { | ||
| 117 | enum iio_chan_type expected_type; | ||
| 118 | unsigned int i; | ||
| 119 | |||
| 120 | /* | ||
| 121 | * args[0]: Acquisition type (i.e. voltage or current) | ||
| 122 | * args[1]: PMC ADC channel number | ||
| 123 | */ | ||
| 124 | if (iiospec->nargs != 2) | ||
| 125 | return -EINVAL; | ||
| 126 | |||
| 127 | switch (iiospec->args[0]) { | ||
| 128 | case GEHC_PMC_ADC_VOLTAGE: | ||
| 129 | expected_type = IIO_VOLTAGE; | ||
| 130 | break; | ||
| 131 | case GEHC_PMC_ADC_CURRENT: | ||
| 132 | expected_type = IIO_CURRENT; | ||
| 133 | break; | ||
| 134 | default: | ||
| 135 | dev_err(&indio_dev->dev, "Invalid channel type %llu\n", | ||
| 136 | iiospec->args[0]); | ||
| 137 | return -EINVAL; | ||
| 138 | } | ||
| 139 | |||
| 140 | for (i = 0; i < indio_dev->num_channels; i++) | ||
| 141 | if (indio_dev->channels[i].type == expected_type && | ||
| 142 | indio_dev->channels[i].channel == iiospec->args[1]) | ||
| 143 | return i; | ||
| 144 | |||
| 145 | dev_err(&indio_dev->dev, "Invalid channel type %llu number %llu\n", | ||
| 146 | iiospec->args[0], iiospec->args[1]); | ||
| 147 | return -EINVAL; | ||
| 148 | } | ||
| 149 | |||
| 150 | static const struct iio_info pmc_adc_info = { | ||
| 151 | .read_raw = pmc_adc_read_raw, | ||
| 152 | .fwnode_xlate = pmc_adc_fwnode_xlate, | ||
| 153 | }; | ||
| 154 | |||
| 155 | static const char *const pmc_adc_regulator_names[] = { | ||
| 156 | "vdd", | ||
| 157 | "vdda", | ||
| 158 | "vddio", | ||
| 159 | "vref", | ||
| 160 | }; | ||
| 161 | |||
| 162 | static int pmc_adc_probe(struct i2c_client *client) | ||
| 163 | { | ||
| 164 | struct iio_dev *indio_dev; | ||
| 165 | struct pmc_adc *pmc_adc; | ||
| 166 | struct clk *clk; | ||
| 167 | s32 val; | ||
| 168 | int ret; | ||
| 169 | |||
| 170 | ret = devm_regulator_bulk_get_enable(&client->dev, ARRAY_SIZE(pmc_adc_regulator_names), | ||
| 171 | pmc_adc_regulator_names); | ||
| 172 | if (ret) | ||
| 173 | return dev_err_probe(&client->dev, ret, "Failed to get regulators\n"); | ||
| 174 | |||
| 175 | clk = devm_clk_get_optional_enabled(&client->dev, "osc"); | ||
| 176 | if (IS_ERR(clk)) | ||
| 177 | return dev_err_probe(&client->dev, PTR_ERR(clk), "Failed to get osc clock\n"); | ||
| 178 | |||
| 179 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*pmc_adc)); | ||
| 180 | if (!indio_dev) | ||
| 181 | return -ENOMEM; | ||
| 182 | |||
| 183 | pmc_adc = iio_priv(indio_dev); | ||
| 184 | pmc_adc->client = client; | ||
| 185 | |||
| 186 | val = i2c_smbus_read_byte_data(pmc_adc->client, PMC_ADC_CMD_REQUEST_PROTOCOL_VERSION); | ||
| 187 | if (val < 0) | ||
| 188 | return dev_err_probe(&client->dev, val, "Failed to get protocol version\n"); | ||
| 189 | |||
| 190 | if (val != 0x01) | ||
| 191 | return dev_err_probe(&client->dev, -EINVAL, | ||
| 192 | "Unsupported protocol version 0x%02x\n", val); | ||
| 193 | |||
| 194 | indio_dev->name = "pmc_adc"; | ||
| 195 | indio_dev->info = &pmc_adc_info; | ||
| 196 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
| 197 | indio_dev->channels = pmc_adc_channels; | ||
| 198 | indio_dev->num_channels = ARRAY_SIZE(pmc_adc_channels); | ||
| 199 | |||
| 200 | return devm_iio_device_register(&client->dev, indio_dev); | ||
| 201 | } | ||
| 202 | |||
| 203 | static const struct of_device_id pmc_adc_of_match[] = { | ||
| 204 | { .compatible = "gehc,pmc-adc"}, | ||
| 205 | { } | ||
| 206 | }; | ||
| 207 | MODULE_DEVICE_TABLE(of, pmc_adc_of_match); | ||
| 208 | |||
| 209 | static const struct i2c_device_id pmc_adc_id_table[] = { | ||
| 210 | { "pmc-adc" }, | ||
| 211 | { } | ||
| 212 | }; | ||
| 213 | MODULE_DEVICE_TABLE(i2c, pmc_adc_id_table); | ||
| 214 | |||
| 215 | static struct i2c_driver pmc_adc_i2c_driver = { | ||
| 216 | .driver = { | ||
| 217 | .name = "pmc-adc", | ||
| 218 | .of_match_table = pmc_adc_of_match, | ||
| 219 | }, | ||
| 220 | .id_table = pmc_adc_id_table, | ||
| 221 | .probe = pmc_adc_probe, | ||
| 222 | }; | ||
| 223 | |||
| 224 | module_i2c_driver(pmc_adc_i2c_driver); | ||
| 225 | |||
| 226 | MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>"); | ||
| 227 | MODULE_DESCRIPTION("GE HealthCare PMC ADC driver"); | ||
| 228 | MODULE_LICENSE("GPL"); | ||
| @@ -132,7 +132,7 @@ static int hi8435_read_event_config(struct iio_dev *idev, · 131 unmodified lines | |||
| 132 | static int hi8435_write_event_config(struct iio_dev *idev, | 132 | static int hi8435_write_event_config(struct iio_dev *idev, |
| 133 | const struct iio_chan_spec *chan, | 133 | const struct iio_chan_spec *chan, |
| 134 | enum iio_event_type type, | 134 | enum iio_event_type type, |
| 135 | enum iio_event_direction dir, int state) | 135 | enum iio_event_direction dir, bool state) |
| 136 | { | 136 | { |
| 137 | struct hi8435_priv *priv = iio_priv(idev); | 137 | struct hi8435_priv *priv = iio_priv(idev); |
| 138 | int ret; | 138 | int ret; |
| @@ -487,7 +487,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_adc_match); · 486 unmodified lines | |||
| 487 | 487 | ||
| 488 | static struct platform_driver imx8qxp_adc_driver = { | 488 | static struct platform_driver imx8qxp_adc_driver = { |
| 489 | .probe = imx8qxp_adc_probe, | 489 | .probe = imx8qxp_adc_probe, |
| 490 | .remove_new = imx8qxp_adc_remove, | 490 | .remove = imx8qxp_adc_remove, |
| 491 | .driver = { | 491 | .driver = { |
| 492 | .name = ADC_DRIVER_NAME, | 492 | .name = ADC_DRIVER_NAME, |
| 493 | .of_match_table = imx8qxp_adc_match, | 493 | .of_match_table = imx8qxp_adc_match, |
| @@ -470,7 +470,7 @@ MODULE_DEVICE_TABLE(of, imx93_adc_match); · 469 unmodified lines | |||
| 470 | 470 | ||
| 471 | static struct platform_driver imx93_adc_driver = { | 471 | static struct platform_driver imx93_adc_driver = { |
| 472 | .probe = imx93_adc_probe, | 472 | .probe = imx93_adc_probe, |
| 473 | .remove_new = imx93_adc_remove, | 473 | .remove = imx93_adc_remove, |
| 474 | .driver = { | 474 | .driver = { |
| 475 | .name = IMX93_ADC_DRIVER_NAME, | 475 | .name = IMX93_ADC_DRIVER_NAME, |
| 476 | .of_match_table = imx93_adc_match, | 476 | .of_match_table = imx93_adc_match, |
| @@ -164,7 +164,7 @@ static const struct iio_chan_spec mrfld_adc_channels[] = { · 163 unmodified lines | |||
| 164 | BCOVE_ADC_CHANNEL(IIO_TEMP, 8, "CH8", 0xC6), | 164 | BCOVE_ADC_CHANNEL(IIO_TEMP, 8, "CH8", 0xC6), |
| 165 | }; | 165 | }; |
| 166 | 166 | ||
| 167 | static struct iio_map iio_maps[] = { | 167 | static const struct iio_map iio_maps[] = { |
| 168 | IIO_MAP("CH0", "bcove-battery", "VBATRSLT"), | 168 | IIO_MAP("CH0", "bcove-battery", "VBATRSLT"), |
| 169 | IIO_MAP("CH1", "bcove-battery", "BATTID"), | 169 | IIO_MAP("CH1", "bcove-battery", "BATTID"), |
| 170 | IIO_MAP("CH2", "bcove-battery", "IBATRSLT"), | 170 | IIO_MAP("CH2", "bcove-battery", "IBATRSLT"), |
| @@ -26,7 +26,7 @@ · 25 unmodified lines | |||
| 26 | 26 | ||
| 27 | struct lp8788_adc { | 27 | struct lp8788_adc { |
| 28 | struct lp8788 *lp; | 28 | struct lp8788 *lp; |
| 29 | struct iio_map *map; | 29 | const struct iio_map *map; |
| 30 | struct mutex lock; | 30 | struct mutex lock; |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| @@ -149,17 +149,9 @@ static const struct iio_chan_spec lp8788_adc_channels[] = { · 116 unmodified lines | |||
| 149 | }; | 149 | }; |
| 150 | 150 | ||
| 151 | /* default maps used by iio consumer (lp8788-charger driver) */ | 151 | /* default maps used by iio consumer (lp8788-charger driver) */ |
| 152 | static struct iio_map lp8788_default_iio_maps[] = { | 152 | static const struct iio_map lp8788_default_iio_maps[] = { |
| 153 | { | 153 | IIO_MAP("VBATT_5P0", "lp8788-charger", "lp8788_vbatt_5p0"), |
| 154 | .consumer_dev_name = "lp8788-charger", | 154 | IIO_MAP("ADC1", "lp8788-charger", "lp8788_adc1"), |
| 155 | .consumer_channel = "lp8788_vbatt_5p0", | ||
| 156 | .adc_channel_label = "VBATT_5P0", | ||
| 157 | }, | ||
| 158 | { | ||
| 159 | .consumer_dev_name = "lp8788-charger", | ||
| 160 | .consumer_channel = "lp8788_adc1", | ||
| 161 | .adc_channel_label = "ADC1", | ||
| 162 | }, | ||
| 163 | { } | 155 | { } |
| 164 | }; | 156 | }; |
| 165 | 157 | ||
| @@ -168,7 +160,7 @@ static int lp8788_iio_map_register(struct device *dev, · 2 unmodified lines | |||
| 168 | struct lp8788_platform_data *pdata, | 160 | struct lp8788_platform_data *pdata, |
| 169 | struct lp8788_adc *adc) | 161 | struct lp8788_adc *adc) |
| 170 | { | 162 | { |
| 171 | struct iio_map *map; | 163 | const struct iio_map *map; |
| 172 | int ret; | 164 | int ret; |
| 173 | 165 | ||
| 174 | map = (!pdata || !pdata->adc_pdata) ? | 166 | map = (!pdata || !pdata->adc_pdata) ? |
| @@ -168,6 +168,7 @@ static const struct iio_info ltc2497core_info = { · 167 unmodified lines | |||
| 168 | int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev) | 168 | int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev) |
| 169 | { | 169 | { |
| 170 | struct ltc2497core_driverdata *ddata = iio_priv(indio_dev); | 170 | struct ltc2497core_driverdata *ddata = iio_priv(indio_dev); |
| 171 | struct iio_map *plat_data = dev_get_platdata(dev); | ||
| 171 | int ret; | 172 | int ret; |
| 172 | 173 | ||
| 173 | /* | 174 | /* |
| @@ -200,16 +201,10 @@ int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev) · 26 unmodified lines | |||
| 200 | return ret; | 201 | return ret; |
| 201 | } | 202 | } |
| 202 | 203 | ||
| 203 | if (dev->platform_data) { | 204 | ret = iio_map_array_register(indio_dev, plat_data); |
| 204 | struct iio_map *plat_data; | 205 | if (ret) { |
| 205 | 206 | dev_err(&indio_dev->dev, "iio map err: %d\n", ret); | |
| 206 | plat_data = (struct iio_map *)dev->platform_data; | 207 | goto err_regulator_disable; |
| 207 | |||
| 208 | ret = iio_map_array_register(indio_dev, plat_data); | ||
| 209 | if (ret) { | ||
| 210 | dev_err(&indio_dev->dev, "iio map err: %d\n", ret); | ||
| 211 | goto err_regulator_disable; | ||
| 212 | } | ||
| 213 | } | 208 | } |
| 214 | 209 | ||
| 215 | ddata->addr_prev = LTC2497_CONFIG_DEFAULT; | 210 | ddata->addr_prev = LTC2497_CONFIG_DEFAULT; |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | |||
| 25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
| 26 | #include <linux/mod_devicetable.h> | 26 | #include <linux/mod_devicetable.h> |
| 27 | #include <linux/property.h> | 27 | #include <linux/property.h> |
| 28 | #include <linux/unaligned.h> | ||
| 28 | 29 | ||
| 29 | #include <linux/iio/iio.h> | 30 | #include <linux/iio/iio.h> |
| 30 | #include <linux/iio/sysfs.h> | 31 | #include <linux/iio/sysfs.h> |
| @@ -392,7 +393,7 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev, · 361 unmodified lines | |||
| 392 | if (data < 0) | 393 | if (data < 0) |
| 393 | return data; | 394 | return data; |
| 394 | 395 | ||
| 395 | data = (rxbuf[1] | rxbuf[0] << 8) & | 396 | data = get_unaligned_be16(rxbuf) & |
| 396 | ((1 << st->chip_info->bits) - 1); | 397 | ((1 << st->chip_info->bits) - 1); |
| 397 | } else { | 398 | } else { |
| 398 | /* Get reading */ | 399 | /* Get reading */ |
| @@ -943,7 +944,7 @@ error_ret: · 544 unmodified lines | |||
| 943 | 944 | ||
| 944 | static int max1363_write_event_config(struct iio_dev *indio_dev, | 945 | static int max1363_write_event_config(struct iio_dev *indio_dev, |
| 945 | const struct iio_chan_spec *chan, enum iio_event_type type, | 946 | const struct iio_chan_spec *chan, enum iio_event_type type, |
| 946 | enum iio_event_direction dir, int state) | 947 | enum iio_event_direction dir, bool state) |
| 947 | { | 948 | { |
| 948 | struct max1363_state *st = iio_priv(indio_dev); | 949 | struct max1363_state *st = iio_priv(indio_dev); |
| 949 | 950 | ||
| @@ -161,7 +161,7 @@ static int max34408_read_raw(struct iio_dev *indio_dev, · 160 unmodified lines | |||
| 161 | return IIO_VAL_INT; | 161 | return IIO_VAL_INT; |
| 162 | case IIO_CHAN_INFO_SCALE: | 162 | case IIO_CHAN_INFO_SCALE: |
| 163 | /* | 163 | /* |
| 164 | * calcluate current for 8bit ADC with Rsense | 164 | * calculate current for 8bit ADC with Rsense |
| 165 | * value. | 165 | * value. |
| 166 | * 10 mV * 1000 / Rsense uOhm = max current | 166 | * 10 mV * 1000 / Rsense uOhm = max current |
| 167 | * (max current * adc val * 1000) / (2^8 - 1) mA | 167 | * (max current * adc val * 1000) / (2^8 - 1) mA |
| @@ -1483,7 +1483,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops, · 1482 unmodified lines | |||
| 1483 | 1483 | ||
| 1484 | static struct platform_driver meson_sar_adc_driver = { | 1484 | static struct platform_driver meson_sar_adc_driver = { |
| 1485 | .probe = meson_sar_adc_probe, | 1485 | .probe = meson_sar_adc_probe, |
| 1486 | .remove_new = meson_sar_adc_remove, | 1486 | .remove = meson_sar_adc_remove, |
| 1487 | .driver = { | 1487 | .driver = { |
| 1488 | .name = "meson-saradc", | 1488 | .name = "meson-saradc", |
| 1489 | .of_match_table = meson_sar_adc_of_match, | 1489 | .of_match_table = meson_sar_adc_of_match, |
| @@ -52,7 +52,7 @@ static struct iio_chan_spec mp2629_channels[] = { · 51 unmodified lines | |||
| 52 | MP2629_ADC_CHAN(INPUT_CURRENT, IIO_CURRENT) | 52 | MP2629_ADC_CHAN(INPUT_CURRENT, IIO_CURRENT) |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | static struct iio_map mp2629_adc_maps[] = { | 55 | static const struct iio_map mp2629_adc_maps[] = { |
| 56 | MP2629_MAP(BATT_VOLT, "batt-volt"), | 56 | MP2629_MAP(BATT_VOLT, "batt-volt"), |
| 57 | MP2629_MAP(SYSTEM_VOLT, "system-volt"), | 57 | MP2629_MAP(SYSTEM_VOLT, "system-volt"), |
| 58 | MP2629_MAP(INPUT_VOLT, "input-volt"), | 58 | MP2629_MAP(INPUT_VOLT, "input-volt"), |
| @@ -195,7 +195,7 @@ static struct platform_driver mp2629_adc_driver = { · 136 unmodified lines | |||
| 195 | .of_match_table = mp2629_adc_of_match, | 195 | .of_match_table = mp2629_adc_of_match, |
| 196 | }, | 196 | }, |
| 197 | .probe = mp2629_adc_probe, | 197 | .probe = mp2629_adc_probe, |
| 198 | .remove_new = mp2629_adc_remove, | 198 | .remove = mp2629_adc_remove, |
| 199 | }; | 199 | }; |
| 200 | module_platform_driver(mp2629_adc_driver); | 200 | module_platform_driver(mp2629_adc_driver); |
| 201 | 201 | ||
| @@ -124,7 +124,7 @@ static int mt6360_adc_read_channel(struct mt6360_adc_data *mad, int channel, int · 123 unmodified lines | |||
| 124 | usleep_range(ADC_LOOP_TIME_US / 2, ADC_LOOP_TIME_US); | 124 | usleep_range(ADC_LOOP_TIME_US / 2, ADC_LOOP_TIME_US); |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | *val = rpt[1] << 8 | rpt[2]; | 127 | *val = get_unaligned_be16(&rpt[1]); |
| 128 | ret = IIO_VAL_INT; | 128 | ret = IIO_VAL_INT; |
| 129 | 129 | ||
| 130 | out_adc_conv: | 130 | out_adc_conv: |
| @@ -819,10 +819,10 @@ static void mxs_lradc_adc_remove(struct platform_device *pdev) · 818 unmodified lines | |||
| 819 | 819 | ||
| 820 | static struct platform_driver mxs_lradc_adc_driver = { | 820 | static struct platform_driver mxs_lradc_adc_driver = { |
| 821 | .driver = { | 821 | .driver = { |
| 822 | .name = "mxs-lradc-adc", | 822 | .name = "mxs-lradc-adc", |
| 823 | }, | 823 | }, |
| 824 | .probe = mxs_lradc_adc_probe, | 824 | .probe = mxs_lradc_adc_probe, |
| 825 | .remove_new = mxs_lradc_adc_remove, | 825 | .remove = mxs_lradc_adc_remove, |
| 826 | }; | 826 | }; |
| 827 | module_platform_driver(mxs_lradc_adc_driver); | 827 | module_platform_driver(mxs_lradc_adc_driver); |
| 828 | 828 | ||
| @@ -337,7 +337,7 @@ static void npcm_adc_remove(struct platform_device *pdev) · 336 unmodified lines | |||
| 337 | 337 | ||
| 338 | static struct platform_driver npcm_adc_driver = { | 338 | static struct platform_driver npcm_adc_driver = { |
| 339 | .probe = npcm_adc_probe, | 339 | .probe = npcm_adc_probe, |
| 340 | .remove_new = npcm_adc_remove, | 340 | .remove = npcm_adc_remove, |
| 341 | .driver = { | 341 | .driver = { |
| 342 | .name = "npcm_adc", | 342 | .name = "npcm_adc", |
| 343 | .of_match_table = npcm_adc_match, | 343 | .of_match_table = npcm_adc_match, |
| @@ -241,7 +241,7 @@ static inline void pac1921_calc_scale(int dividend, int divisor, int *val, · 240 unmodified lines | |||
| 241 | s64 tmp; | 241 | s64 tmp; |
| 242 | 242 | ||
| 243 | tmp = div_s64(dividend * (s64)NANO, divisor); | 243 | tmp = div_s64(dividend * (s64)NANO, divisor); |
| 244 | *val = (int)div_s64_rem(tmp, NANO, val2); | 244 | *val = div_s64_rem(tmp, NANO, val2); |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | /* | 247 | /* |
| @@ -260,7 +260,7 @@ static void pac1921_calc_current_scales(struct pac1921_priv *priv) · 12 unmodified lines | |||
| 260 | int max = (PAC1921_MAX_VSENSE_MV * MICRO) >> i; | 260 | int max = (PAC1921_MAX_VSENSE_MV * MICRO) >> i; |
| 261 | int vsense_lsb = DIV_ROUND_CLOSEST(max, PAC1921_RES_RESOLUTION); | 261 | int vsense_lsb = DIV_ROUND_CLOSEST(max, PAC1921_RES_RESOLUTION); |
| 262 | 262 | ||
| 263 | pac1921_calc_scale(vsense_lsb, (int)priv->rshunt_uohm, | 263 | pac1921_calc_scale(vsense_lsb, priv->rshunt_uohm, |
| 264 | &priv->current_scales[i][0], | 264 | &priv->current_scales[i][0], |
| 265 | &priv->current_scales[i][1]); | 265 | &priv->current_scales[i][1]); |
| 266 | } | 266 | } |
| @@ -314,7 +314,7 @@ static int pac1921_check_push_overflow(struct iio_dev *indio_dev, s64 timestamp) · 47 unmodified lines | |||
| 314 | timestamp); | 314 | timestamp); |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | priv->prev_ovf_flags = (u8)flags; | 317 | priv->prev_ovf_flags = flags; |
| 318 | 318 | ||
| 319 | return 0; | 319 | return 0; |
| 320 | } | 320 | } |
| @@ -329,8 +329,7 @@ static int pac1921_check_push_overflow(struct iio_dev *indio_dev, s64 timestamp) · 8 unmodified lines | |||
| 329 | static int pac1921_read_res(struct pac1921_priv *priv, unsigned long reg, | 329 | static int pac1921_read_res(struct pac1921_priv *priv, unsigned long reg, |
| 330 | u16 *val) | 330 | u16 *val) |
| 331 | { | 331 | { |
| 332 | int ret = regmap_bulk_read(priv->regmap, (unsigned int)reg, val, | 332 | int ret = regmap_bulk_read(priv->regmap, reg, val, sizeof(*val)); |
| 333 | sizeof(*val)); | ||
| 334 | if (ret) | 333 | if (ret) |
| 335 | return ret; | 334 | return ret; |
| 336 | 335 | ||
| @@ -366,7 +365,7 @@ static int pac1921_read_raw(struct iio_dev *indio_dev, · 29 unmodified lines | |||
| 366 | if (ret) | 365 | if (ret) |
| 367 | return ret; | 366 | return ret; |
| 368 | 367 | ||
| 369 | *val = (int)res_val; | 368 | *val = res_val; |
| 370 | 369 | ||
| 371 | return IIO_VAL_INT; | 370 | return IIO_VAL_INT; |
| 372 | } | 371 | } |
| @@ -400,10 +399,10 @@ static int pac1921_read_raw(struct iio_dev *indio_dev, · 27 unmodified lines | |||
| 400 | s64 tmp = curr_scale[0] * (s64)NANO + curr_scale[1]; | 399 | s64 tmp = curr_scale[0] * (s64)NANO + curr_scale[1]; |
| 401 | 400 | ||
| 402 | /* Multiply by max_vbus (V) / dv_gain */ | 401 | /* Multiply by max_vbus (V) / dv_gain */ |
| 403 | tmp *= PAC1921_MAX_VBUS_V >> (int)priv->dv_gain; | 402 | tmp *= PAC1921_MAX_VBUS_V >> priv->dv_gain; |
| 404 | 403 | ||
| 405 | /* Convert back to INT_PLUS_NANO */ | 404 | /* Convert back to INT_PLUS_NANO */ |
| 406 | *val = (int)div_s64_rem(tmp, NANO, val2); | 405 | *val = div_s64_rem(tmp, NANO, val2); |
| 407 | 406 | ||
| 408 | return IIO_VAL_INT_PLUS_NANO; | 407 | return IIO_VAL_INT_PLUS_NANO; |
| 409 | } | 408 | } |
| @@ -426,7 +425,7 @@ static int pac1921_read_raw(struct iio_dev *indio_dev, · 16 unmodified lines | |||
| 426 | * 1/(integr_period_usecs/MICRO) = MICRO/integr_period_usecs | 425 | * 1/(integr_period_usecs/MICRO) = MICRO/integr_period_usecs |
| 427 | */ | 426 | */ |
| 428 | *val = MICRO; | 427 | *val = MICRO; |
| 429 | *val2 = (int)priv->integr_period_usecs; | 428 | *val2 = priv->integr_period_usecs; |
| 430 | return IIO_VAL_FRACTIONAL; | 429 | return IIO_VAL_FRACTIONAL; |
| 431 | 430 | ||
| 432 | default: | 431 | default: |
| @@ -503,7 +502,7 @@ static int pac1921_lookup_scale(const int (*const scales_tbl)[2], size_t size, · 70 unmodified lines | |||
| 503 | for (unsigned int i = 0; i < size; i++) | 502 | for (unsigned int i = 0; i < size; i++) |
| 504 | if (scales_tbl[i][0] == scale_val && | 503 | if (scales_tbl[i][0] == scale_val && |
| 505 | scales_tbl[i][1] == scale_val2) | 504 | scales_tbl[i][1] == scale_val2) |
| 506 | return (int)i; | 505 | return i; |
| 507 | 506 | ||
| 508 | return -EINVAL; | 507 | return -EINVAL; |
| 509 | } | 508 | } |
| @@ -553,7 +552,7 @@ static int pac1921_update_gain_from_scale(struct pac1921_priv *priv, · 43 unmodified lines | |||
| 553 | if (ret < 0) | 552 | if (ret < 0) |
| 554 | return ret; | 553 | return ret; |
| 555 | 554 | ||
| 556 | return pac1921_update_gain(priv, &priv->dv_gain, (u8)ret, | 555 | return pac1921_update_gain(priv, &priv->dv_gain, ret, |
| 557 | PAC1921_GAIN_DV_GAIN_MASK); | 556 | PAC1921_GAIN_DV_GAIN_MASK); |
| 558 | case PAC1921_CHAN_VSENSE: | 557 | case PAC1921_CHAN_VSENSE: |
| 559 | ret = pac1921_lookup_scale(pac1921_vsense_scales, | 558 | ret = pac1921_lookup_scale(pac1921_vsense_scales, |
| @@ -562,7 +561,7 @@ static int pac1921_update_gain_from_scale(struct pac1921_priv *priv, · 2 unmodified lines | |||
| 562 | if (ret < 0) | 561 | if (ret < 0) |
| 563 | return ret; | 562 | return ret; |
| 564 | 563 | ||
| 565 | return pac1921_update_gain(priv, &priv->di_gain, (u8)ret, | 564 | return pac1921_update_gain(priv, &priv->di_gain, ret, |
| 566 | PAC1921_GAIN_DI_GAIN_MASK); | 565 | PAC1921_GAIN_DI_GAIN_MASK); |
| 567 | case PAC1921_CHAN_CURRENT: | 566 | case PAC1921_CHAN_CURRENT: |
| 568 | ret = pac1921_lookup_scale(priv->current_scales, | 567 | ret = pac1921_lookup_scale(priv->current_scales, |
| @@ -571,7 +570,7 @@ static int pac1921_update_gain_from_scale(struct pac1921_priv *priv, · 2 unmodified lines | |||
| 571 | if (ret < 0) | 570 | if (ret < 0) |
| 572 | return ret; | 571 | return ret; |
| 573 | 572 | ||
| 574 | return pac1921_update_gain(priv, &priv->di_gain, (u8)ret, | 573 | return pac1921_update_gain(priv, &priv->di_gain, ret, |
| 575 | PAC1921_GAIN_DI_GAIN_MASK); | 574 | PAC1921_GAIN_DI_GAIN_MASK); |
| 576 | default: | 575 | default: |
| 577 | return -EINVAL; | 576 | return -EINVAL; |
| @@ -586,7 +585,7 @@ static int pac1921_lookup_int_num_samples(int num_samples) · 8 unmodified lines | |||
| 586 | { | 585 | { |
| 587 | for (unsigned int i = 0; i < ARRAY_SIZE(pac1921_int_num_samples); i++) | 586 | for (unsigned int i = 0; i < ARRAY_SIZE(pac1921_int_num_samples); i++) |
| 588 | if (pac1921_int_num_samples[i] == num_samples) | 587 | if (pac1921_int_num_samples[i] == num_samples) |
| 589 | return (int)i; | 588 | return i; |
| 590 | 589 | ||
| 591 | return -EINVAL; | 590 | return -EINVAL; |
| 592 | } | 591 | } |
| @@ -607,7 +606,7 @@ static int pac1921_update_int_num_samples(struct pac1921_priv *priv, · 14 unmodified lines | |||
| 607 | if (ret < 0) | 606 | if (ret < 0) |
| 608 | return ret; | 607 | return ret; |
| 609 | 608 | ||
| 610 | n_samples = (u8)ret; | 609 | n_samples = ret; |
| 611 | 610 | ||
| 612 | if (priv->n_samples == n_samples) | 611 | if (priv->n_samples == n_samples) |
| 613 | return 0; | 612 | return 0; |
| @@ -700,7 +699,8 @@ static int pac1921_read_event_config(struct iio_dev *indio_dev, · 86 unmodified lines | |||
| 700 | static int pac1921_write_event_config(struct iio_dev *indio_dev, | 699 | static int pac1921_write_event_config(struct iio_dev *indio_dev, |
| 701 | const struct iio_chan_spec *chan, | 700 | const struct iio_chan_spec *chan, |
| 702 | enum iio_event_type type, | 701 | enum iio_event_type type, |
| 703 | enum iio_event_direction dir, int state) | 702 | enum iio_event_direction dir, |
| 703 | bool state) | ||
| 704 | { | 704 | { |
| 705 | struct pac1921_priv *priv = iio_priv(indio_dev); | 705 | struct pac1921_priv *priv = iio_priv(indio_dev); |
| 706 | u8 ovf_bit; | 706 | u8 ovf_bit; |
| @@ -770,7 +770,7 @@ static ssize_t pac1921_read_shunt_resistor(struct iio_dev *indio_dev, · 63 unmodified lines | |||
| 770 | 770 | ||
| 771 | guard(mutex)(&priv->lock); | 771 | guard(mutex)(&priv->lock); |
| 772 | 772 | ||
| 773 | vals[0] = (int)priv->rshunt_uohm; | 773 | vals[0] = priv->rshunt_uohm; |
| 774 | vals[1] = MICRO; | 774 | vals[1] = MICRO; |
| 775 | 775 | ||
| 776 | return iio_format_value(buf, IIO_VAL_FRACTIONAL, 1, vals); | 776 | return iio_format_value(buf, IIO_VAL_FRACTIONAL, 1, vals); |
| @@ -793,13 +793,13 @@ static ssize_t pac1921_write_shunt_resistor(struct iio_dev *indio_dev, · 16 unmodified lines | |||
| 793 | if (ret) | 793 | if (ret) |
| 794 | return ret; | 794 | return ret; |
| 795 | 795 | ||
| 796 | rshunt_uohm = (u32)val * MICRO + (u32)val_fract; | 796 | rshunt_uohm = val * MICRO + val_fract; |
| 797 | if (rshunt_uohm == 0 || rshunt_uohm > INT_MAX) | 797 | if (rshunt_uohm == 0 || rshunt_uohm > INT_MAX) |
| 798 | return -EINVAL; | 798 | return -EINVAL; |
| 799 | 799 | ||
| 800 | guard(mutex)(&priv->lock); | 800 | guard(mutex)(&priv->lock); |
| 801 | 801 | ||
| 802 | priv->rshunt_uohm = (u32)rshunt_uohm; | 802 | priv->rshunt_uohm = rshunt_uohm; |
| 803 | 803 | ||
| 804 | pac1921_calc_current_scales(priv); | 804 | pac1921_calc_current_scales(priv); |
| 805 | 805 | ||
| @@ -1077,7 +1077,7 @@ static int pac1921_init(struct pac1921_priv *priv) · 271 unmodified lines | |||
| 1077 | /* | 1077 | /* |
| 1078 | * Init control register: | 1078 | * Init control register: |
| 1079 | * - VPower free run integration mode | 1079 | * - VPower free run integration mode |
| 1080 | * - OUT pin full scale range: 3V (HW detault) | 1080 | * - OUT pin full scale range: 3V (HW default) |
| 1081 | * - no timeout, no sleep, no sleep override, no recalc (HW defaults) | 1081 | * - no timeout, no sleep, no sleep override, no recalc (HW defaults) |
| 1082 | */ | 1082 | */ |
| 1083 | val = FIELD_PREP(PAC1921_CONTROL_MXSL_MASK, | 1083 | val = FIELD_PREP(PAC1921_CONTROL_MXSL_MASK, |
| @@ -1168,10 +1168,12 @@ static int pac1921_probe(struct i2c_client *client) · 84 unmodified lines | |||
| 1168 | 1168 | ||
| 1169 | priv->regmap = devm_regmap_init_i2c(client, &pac1921_regmap_config); | 1169 | priv->regmap = devm_regmap_init_i2c(client, &pac1921_regmap_config); |
| 1170 | if (IS_ERR(priv->regmap)) | 1170 | if (IS_ERR(priv->regmap)) |
| 1171 | return dev_err_probe(dev, (int)PTR_ERR(priv->regmap), | 1171 | return dev_err_probe(dev, PTR_ERR(priv->regmap), |
| 1172 | "Cannot initialize register map\n"); | 1172 | "Cannot initialize register map\n"); |
| 1173 | 1173 | ||
| 1174 | devm_mutex_init(dev, &priv->lock); | 1174 | ret = devm_mutex_init(dev, &priv->lock); |
| 1175 | if (ret) | ||
| 1176 | return ret; | ||
| 1175 | 1177 | ||
| 1176 | priv->dv_gain = PAC1921_DEFAULT_DV_GAIN; | 1178 | priv->dv_gain = PAC1921_DEFAULT_DV_GAIN; |
| 1177 | priv->di_gain = PAC1921_DEFAULT_DI_GAIN; | 1179 | priv->di_gain = PAC1921_DEFAULT_DI_GAIN; |
| @@ -1191,7 +1193,7 @@ static int pac1921_probe(struct i2c_client *client) · 13 unmodified lines | |||
| 1191 | 1193 | ||
| 1192 | priv->vdd = devm_regulator_get(dev, "vdd"); | 1194 | priv->vdd = devm_regulator_get(dev, "vdd"); |
| 1193 | if (IS_ERR(priv->vdd)) | 1195 | if (IS_ERR(priv->vdd)) |
| 1194 | return dev_err_probe(dev, (int)PTR_ERR(priv->vdd), | 1196 | return dev_err_probe(dev, PTR_ERR(priv->vdd), |
| 1195 | "Cannot get vdd regulator\n"); | 1197 | "Cannot get vdd regulator\n"); |
| 1196 | 1198 | ||
| 1197 | ret = regulator_enable(priv->vdd); | 1199 | ret = regulator_enable(priv->vdd); |
| @@ -1507,7 +1507,7 @@ static int pac1934_probe(struct i2c_client *client) · 1506 unmodified lines | |||
| 1507 | indio_dev->name = pac1934_chip_config[ret].name; | 1507 | indio_dev->name = pac1934_chip_config[ret].name; |
| 1508 | } | 1508 | } |
| 1509 | 1509 | ||
| 1510 | if (acpi_match_device(dev->driver->acpi_match_table, dev)) | 1510 | if (is_acpi_device_node(dev_fwnode(dev))) |
| 1511 | ret = pac1934_acpi_parse_channel_config(client, info); | 1511 | ret = pac1934_acpi_parse_channel_config(client, info); |
| 1512 | else | 1512 | else |
| 1513 | /* | 1513 | /* |
| @@ -456,7 +456,7 @@ static int palmas_gpadc_get_calibrated_code(struct palmas_gpadc *adc, · 455 unmodified lines | |||
| 456 | * raw high threshold = (ideal threshold + INL) * gain error + offset error | 456 | * raw high threshold = (ideal threshold + INL) * gain error + offset error |
| 457 | * | 457 | * |
| 458 | * The gain error include both gain error, as specified in the datasheet, and | 458 | * The gain error include both gain error, as specified in the datasheet, and |
| 459 | * the gain error drift. These paramenters vary depending on device and whether | 459 | * the gain error drift. These parameters vary depending on device and whether |
| 460 | * the channel is calibrated (trimmed) or not. | 460 | * the channel is calibrated (trimmed) or not. |
| 461 | */ | 461 | */ |
| 462 | static int palmas_gpadc_threshold_with_tolerance(int val, const int INL, | 462 | static int palmas_gpadc_threshold_with_tolerance(int val, const int INL, |
| @@ -676,7 +676,7 @@ static int palmas_gpadc_write_event_config(struct iio_dev *indio_dev, · 213 unmodified lines | |||
| 676 | const struct iio_chan_spec *chan, | 676 | const struct iio_chan_spec *chan, |
| 677 | enum iio_event_type type, | 677 | enum iio_event_type type, |
| 678 | enum iio_event_direction dir, | 678 | enum iio_event_direction dir, |
| 679 | int state) | 679 | bool state) |
| 680 | { | 680 | { |
| 681 | struct palmas_gpadc *adc = iio_priv(indio_dev); | 681 | struct palmas_gpadc *adc = iio_priv(indio_dev); |
| 682 | int adc_chan = chan->channel; | 682 | int adc_chan = chan->channel; |
| @@ -821,7 +821,6 @@ static int pm8xxx_xoadc_parse_channel(struct device *dev, · 820 unmodified lines | |||
| 821 | 821 | ||
| 822 | static int pm8xxx_xoadc_parse_channels(struct pm8xxx_xoadc *adc) | 822 | static int pm8xxx_xoadc_parse_channels(struct pm8xxx_xoadc *adc) |
| 823 | { | 823 | { |
| 824 | struct fwnode_handle *child; | ||
| 825 | struct pm8xxx_chan_info *ch; | 824 | struct pm8xxx_chan_info *ch; |
| 826 | int ret; | 825 | int ret; |
| 827 | int i; | 826 | int i; |
| @@ -844,16 +843,15 @@ static int pm8xxx_xoadc_parse_channels(struct pm8xxx_xoadc *adc) · 16 unmodified lines | |||
| 844 | return -ENOMEM; | 843 | return -ENOMEM; |
| 845 | 844 | ||
| 846 | i = 0; | 845 | i = 0; |
| 847 | device_for_each_child_node(adc->dev, child) { | 846 | device_for_each_child_node_scoped(adc->dev, child) { |
| 848 | ch = &adc->chans[i]; | 847 | ch = &adc->chans[i]; |
| 849 | ret = pm8xxx_xoadc_parse_channel(adc->dev, child, | 848 | ret = pm8xxx_xoadc_parse_channel(adc->dev, child, |
| 850 | adc->variant->channels, | 849 | adc->variant->channels, |
| 851 | &adc->iio_chans[i], | 850 | &adc->iio_chans[i], |
| 852 | ch); | 851 | ch); |
| 853 | if (ret) { | 852 | if (ret) |
| 854 | fwnode_handle_put(child); | ||
| 855 | return ret; | 853 | return ret; |
| 856 | } | 854 | |
| 857 | i++; | 855 | i++; |
| 858 | } | 856 | } |
| 859 | 857 | ||
| @@ -1016,7 +1014,7 @@ static struct platform_driver pm8xxx_xoadc_driver = { · 156 unmodified lines | |||
| 1016 | .of_match_table = pm8xxx_xoadc_id_table, | 1014 | .of_match_table = pm8xxx_xoadc_id_table, |
| 1017 | }, | 1015 | }, |
| 1018 | .probe = pm8xxx_xoadc_probe, | 1016 | .probe = pm8xxx_xoadc_probe, |
| 1019 | .remove_new = pm8xxx_xoadc_remove, | 1017 | .remove = pm8xxx_xoadc_remove, |
| 1020 | }; | 1018 | }; |
| 1021 | module_platform_driver(pm8xxx_xoadc_driver); | 1019 | module_platform_driver(pm8xxx_xoadc_driver); |
| 1022 | 1020 | ||
| @@ -830,7 +830,7 @@ static int adc5_get_fw_data(struct adc5_chip *adc) · 829 unmodified lines | |||
| 830 | 830 | ||
| 831 | adc->nchannels = device_get_child_node_count(adc->dev); | 831 | adc->nchannels = device_get_child_node_count(adc->dev); |
| 832 | if (!adc->nchannels) | 832 | if (!adc->nchannels) |
| 833 | return -EINVAL; | 833 | return dev_err_probe(adc->dev, -EINVAL, "no channels defined\n"); |
| 834 | 834 | ||
| 835 | adc->iio_chans = devm_kcalloc(adc->dev, adc->nchannels, | 835 | adc->iio_chans = devm_kcalloc(adc->dev, adc->nchannels, |
| 836 | sizeof(*adc->iio_chans), GFP_KERNEL); | 836 | sizeof(*adc->iio_chans), GFP_KERNEL); |
| @@ -903,7 +903,7 @@ static int adc5_probe(struct platform_device *pdev) · 66 unmodified lines | |||
| 903 | 903 | ||
| 904 | ret = adc5_get_fw_data(adc); | 904 | ret = adc5_get_fw_data(adc); |
| 905 | if (ret) | 905 | if (ret) |
| 906 | return dev_err_probe(dev, ret, "adc get dt data failed\n"); | 906 | return ret; |
| 907 | 907 | ||
| 908 | irq_eoc = platform_get_irq(pdev, 0); | 908 | irq_eoc = platform_get_irq(pdev, 0); |
| 909 | if (irq_eoc < 0) { | 909 | if (irq_eoc < 0) { |
| @@ -754,7 +754,6 @@ static int vadc_get_fw_data(struct vadc_priv *vadc) · 753 unmodified lines | |||
| 754 | const struct vadc_channels *vadc_chan; | 754 | const struct vadc_channels *vadc_chan; |
| 755 | struct iio_chan_spec *iio_chan; | 755 | struct iio_chan_spec *iio_chan; |
| 756 | struct vadc_channel_prop prop; | 756 | struct vadc_channel_prop prop; |
| 757 | struct fwnode_handle *child; | ||
| 758 | unsigned int index = 0; | 757 | unsigned int index = 0; |
| 759 | int ret; | 758 | int ret; |
| 760 | 759 | ||
| @@ -774,12 +773,10 @@ static int vadc_get_fw_data(struct vadc_priv *vadc) · 13 unmodified lines | |||
| 774 | 773 | ||
| 775 | iio_chan = vadc->iio_chans; | 774 | iio_chan = vadc->iio_chans; |
| 776 | 775 | ||
| 777 | device_for_each_child_node(vadc->dev, child) { | 776 | device_for_each_child_node_scoped(vadc->dev, child) { |
| 778 | ret = vadc_get_fw_channel_data(vadc->dev, &prop, child); | 777 | ret = vadc_get_fw_channel_data(vadc->dev, &prop, child); |
| 779 | if (ret) { | 778 | if (ret) |
| 780 | fwnode_handle_put(child); | ||
| 781 | return ret; | 779 | return ret; |
| 782 | } | ||
| 783 | 780 | ||
| 784 | prop.scale_fn_type = vadc_chans[prop.channel].scale_fn_type; | 781 | prop.scale_fn_type = vadc_chans[prop.channel].scale_fn_type; |
| 785 | vadc->chan_props[index] = prop; | 782 | vadc->chan_props[index] = prop; |
| @@ -592,7 +592,7 @@ static const struct dev_pm_ops rcar_gyroadc_pm_ops = { · 591 unmodified lines | |||
| 592 | 592 | ||
| 593 | static struct platform_driver rcar_gyroadc_driver = { | 593 | static struct platform_driver rcar_gyroadc_driver = { |
| 594 | .probe = rcar_gyroadc_probe, | 594 | .probe = rcar_gyroadc_probe, |
| 595 | .remove_new = rcar_gyroadc_remove, | 595 | .remove = rcar_gyroadc_remove, |
| 596 | .driver = { | 596 | .driver = { |
| 597 | .name = DRIVER_NAME, | 597 | .name = DRIVER_NAME, |
| 598 | .of_match_table = rcar_gyroadc_match, | 598 | .of_match_table = rcar_gyroadc_match, |
| @@ -185,7 +185,7 @@ static const struct iio_chan_spec rn5t618_adc_iio_channels[] = { · 184 unmodified lines | |||
| 185 | RN5T618_ADC_CHANNEL(AIN0, IIO_VOLTAGE, "AIN0") | 185 | RN5T618_ADC_CHANNEL(AIN0, IIO_VOLTAGE, "AIN0") |
| 186 | }; | 186 | }; |
| 187 | 187 | ||
| 188 | static struct iio_map rn5t618_maps[] = { | 188 | static const struct iio_map rn5t618_maps[] = { |
| 189 | IIO_MAP("VADP", "rn5t618-power", "vadp"), | 189 | IIO_MAP("VADP", "rn5t618-power", "vadp"), |
| 190 | IIO_MAP("VUSB", "rn5t618-power", "vusb"), | 190 | IIO_MAP("VUSB", "rn5t618-power", "vusb"), |
| 191 | { /* sentinel */ } | 191 | { /* sentinel */ } |
| @@ -906,7 +906,7 @@ MODULE_DEVICE_TABLE(of, stm32_adc_of_match); · 905 unmodified lines | |||
| 906 | 906 | ||
| 907 | static struct platform_driver stm32_adc_driver = { | 907 | static struct platform_driver stm32_adc_driver = { |
| 908 | .probe = stm32_adc_probe, | 908 | .probe = stm32_adc_probe, |
| 909 | .remove_new = stm32_adc_remove, | 909 | .remove = stm32_adc_remove, |
| 910 | .driver = { | 910 | .driver = { |
| 911 | .name = "stm32-adc-core", | 911 | .name = "stm32-adc-core", |
| 912 | .of_match_table = stm32_adc_of_match, | 912 | .of_match_table = stm32_adc_of_match, |
| @@ -2644,7 +2644,7 @@ MODULE_DEVICE_TABLE(of, stm32_adc_of_match); · 2643 unmodified lines | |||
| 2644 | 2644 | ||
| 2645 | static struct platform_driver stm32_adc_driver = { | 2645 | static struct platform_driver stm32_adc_driver = { |
| 2646 | .probe = stm32_adc_probe, | 2646 | .probe = stm32_adc_probe, |
| 2647 | .remove_new = stm32_adc_remove, | 2647 | .remove = stm32_adc_remove, |
| 2648 | .driver = { | 2648 | .driver = { |
| 2649 | .name = "stm32-adc", | 2649 | .name = "stm32-adc", |
| 2650 | .of_match_table = stm32_adc_of_match, | 2650 | .of_match_table = stm32_adc_of_match, |
| @@ -1890,7 +1890,7 @@ static struct platform_driver stm32_dfsdm_adc_driver = { · 1889 unmodified lines | |||
| 1890 | .pm = pm_sleep_ptr(&stm32_dfsdm_adc_pm_ops), | 1890 | .pm = pm_sleep_ptr(&stm32_dfsdm_adc_pm_ops), |
| 1891 | }, | 1891 | }, |
| 1892 | .probe = stm32_dfsdm_adc_probe, | 1892 | .probe = stm32_dfsdm_adc_probe, |
| 1893 | .remove_new = stm32_dfsdm_adc_remove, | 1893 | .remove = stm32_dfsdm_adc_remove, |
| 1894 | }; | 1894 | }; |
| 1895 | module_platform_driver(stm32_dfsdm_adc_driver); | 1895 | module_platform_driver(stm32_dfsdm_adc_driver); |
| 1896 | 1896 | ||
| @@ -506,7 +506,7 @@ static const struct dev_pm_ops stm32_dfsdm_core_pm_ops = { · 505 unmodified lines | |||
| 506 | 506 | ||
| 507 | static struct platform_driver stm32_dfsdm_driver = { | 507 | static struct platform_driver stm32_dfsdm_driver = { |
| 508 | .probe = stm32_dfsdm_probe, | 508 | .probe = stm32_dfsdm_probe, |
| 509 | .remove_new = stm32_dfsdm_core_remove, | 509 | .remove = stm32_dfsdm_core_remove, |
| 510 | .driver = { | 510 | .driver = { |
| 511 | .name = "stm32-dfsdm", | 511 | .name = "stm32-dfsdm", |
| 512 | .of_match_table = stm32_dfsdm_of_match, | 512 | .of_match_table = stm32_dfsdm_of_match, |
| @@ -155,7 +155,6 @@ static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev, · 154 unmodified lines | |||
| 155 | unsigned int channel; | 155 | unsigned int channel; |
| 156 | int num_channels, i, ret; | 156 | int num_channels, i, ret; |
| 157 | struct iio_chan_spec *channels; | 157 | struct iio_chan_spec *channels; |
| 158 | struct fwnode_handle *node; | ||
| 159 | 158 | ||
| 160 | num_channels = device_get_child_node_count(dev); | 159 | num_channels = device_get_child_node_count(dev); |
| 161 | if (num_channels == 0) | 160 | if (num_channels == 0) |
| @@ -167,12 +166,10 @@ static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev, · 5 unmodified lines | |||
| 167 | return -ENOMEM; | 166 | return -ENOMEM; |
| 168 | 167 | ||
| 169 | i = 0; | 168 | i = 0; |
| 170 | device_for_each_child_node(dev, node) { | 169 | device_for_each_child_node_scoped(dev, node) { |
| 171 | ret = fwnode_property_read_u32(node, "reg", &channel); | 170 | ret = fwnode_property_read_u32(node, "reg", &channel); |
| 172 | if (ret) { | 171 | if (ret) |
| 173 | fwnode_handle_put(node); | ||
| 174 | return dev_err_probe(dev, ret, "invalid channel number\n"); | 172 | return dev_err_probe(dev, ret, "invalid channel number\n"); |
| 175 | } | ||
| 176 | 173 | ||
| 177 | channels[i].type = IIO_VOLTAGE; | 174 | channels[i].type = IIO_VOLTAGE; |
| 178 | channels[i].indexed = 1; | 175 | channels[i].indexed = 1; |
| @@ -114,11 +114,8 @@ struct sun4i_gpadc_iio { · 113 unmodified lines | |||
| 114 | .datasheet_name = _name, \ | 114 | .datasheet_name = _name, \ |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | static struct iio_map sun4i_gpadc_hwmon_maps[] = { | 117 | static const struct iio_map sun4i_gpadc_hwmon_maps[] = { |
| 118 | { | 118 | IIO_MAP("temp_adc", "iio_hwmon.0", NULL), |
| 119 | .adc_channel_label = "temp_adc", | ||
| 120 | .consumer_dev_name = "iio_hwmon.0", | ||
| 121 | }, | ||
| 122 | { /* sentinel */ }, | 119 | { /* sentinel */ }, |
| 123 | }; | 120 | }; |
| 124 | 121 | ||
| @@ -700,7 +697,7 @@ static struct platform_driver sun4i_gpadc_driver = { · 575 unmodified lines | |||
| 700 | }, | 697 | }, |
| 701 | .id_table = sun4i_gpadc_id, | 698 | .id_table = sun4i_gpadc_id, |
| 702 | .probe = sun4i_gpadc_probe, | 699 | .probe = sun4i_gpadc_probe, |
| 703 | .remove_new = sun4i_gpadc_remove, | 700 | .remove = sun4i_gpadc_remove, |
| 704 | }; | 701 | }; |
| 705 | MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_id); | 702 | MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_id); |
| 706 | 703 | ||
| @@ -806,7 +806,7 @@ static int ads1015_disable_event_config(struct ads1015_data *data, · 805 unmodified lines | |||
| 806 | 806 | ||
| 807 | static int ads1015_write_event_config(struct iio_dev *indio_dev, | 807 | static int ads1015_write_event_config(struct iio_dev *indio_dev, |
| 808 | const struct iio_chan_spec *chan, enum iio_event_type type, | 808 | const struct iio_chan_spec *chan, enum iio_event_type type, |
| 809 | enum iio_event_direction dir, int state) | 809 | enum iio_event_direction dir, bool state) |
| 810 | { | 810 | { |
| 811 | struct ads1015_data *data = iio_priv(indio_dev); | 811 | struct ads1015_data *data = iio_priv(indio_dev); |
| 812 | int ret; | 812 | int ret; |
| @@ -1032,8 +1032,7 @@ static int ads1015_probe(struct i2c_client *client) · 219 unmodified lines | |||
| 1032 | } | 1032 | } |
| 1033 | 1033 | ||
| 1034 | if (client->irq && chip->has_comparator) { | 1034 | if (client->irq && chip->has_comparator) { |
| 1035 | unsigned long irq_trig = | 1035 | unsigned long irq_trig = irq_get_trigger_type(client->irq); |
| 1036 | irqd_get_trigger_type(irq_get_irq_data(client->irq)); | ||
| 1037 | unsigned int cfg_comp_mask = ADS1015_CFG_COMP_QUE_MASK | | 1036 | unsigned int cfg_comp_mask = ADS1015_CFG_COMP_QUE_MASK | |
| 1038 | ADS1015_CFG_COMP_LAT_MASK | ADS1015_CFG_COMP_POL_MASK; | 1037 | ADS1015_CFG_COMP_LAT_MASK | ADS1015_CFG_COMP_POL_MASK; |
| 1039 | unsigned int cfg_comp = | 1038 | unsigned int cfg_comp = |
| @@ -804,7 +804,7 @@ static const struct of_device_id __maybe_unused ads1119_of_match[] = { · 803 unmodified lines | |||
| 804 | MODULE_DEVICE_TABLE(of, ads1119_of_match); | 804 | MODULE_DEVICE_TABLE(of, ads1119_of_match); |
| 805 | 805 | ||
| 806 | static const struct i2c_device_id ads1119_id[] = { | 806 | static const struct i2c_device_id ads1119_id[] = { |
| 807 | { "ads1119", 0 }, | 807 | { "ads1119" }, |
| 808 | { } | 808 | { } |
| 809 | }; | 809 | }; |
| 810 | MODULE_DEVICE_TABLE(i2c, ads1119_id); | 810 | MODULE_DEVICE_TABLE(i2c, ads1119_id); |
| @@ -294,7 +294,7 @@ static int ads1298_get_scale(struct ads1298_private *priv, · 293 unmodified lines | |||
| 294 | if (ret) | 294 | if (ret) |
| 295 | return ret; | 295 | return ret; |
| 296 | 296 | ||
| 297 | /* Refererence in millivolts */ | 297 | /* Reference in millivolts */ |
| 298 | *val = regval & ADS1298_MASK_CONFIG3_VREF_4V ? 4000 : 2400; | 298 | *val = regval & ADS1298_MASK_CONFIG3_VREF_4V ? 4000 : 2400; |
| 299 | } | 299 | } |
| 300 | 300 | ||
| @@ -494,7 +494,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, · 493 unmodified lines | |||
| 494 | /* | 494 | /* |
| 495 | * We check the complete FIFO. We programmed just one entry but in case | 495 | * We check the complete FIFO. We programmed just one entry but in case |
| 496 | * something went wrong we left empty handed (-EAGAIN previously) and | 496 | * something went wrong we left empty handed (-EAGAIN previously) and |
| 497 | * then the value apeared somehow in the FIFO we would have two entries. | 497 | * then the value appeared somehow in the FIFO we would have two entries. |
| 498 | * Therefore we read every item and keep only the latest version of the | 498 | * Therefore we read every item and keep only the latest version of the |
| 499 | * requested channel. | 499 | * requested channel. |
| 500 | */ | 500 | */ |
| @@ -740,12 +740,12 @@ MODULE_DEVICE_TABLE(of, ti_adc_dt_ids); · 239 unmodified lines | |||
| 740 | 740 | ||
| 741 | static struct platform_driver tiadc_driver = { | 741 | static struct platform_driver tiadc_driver = { |
| 742 | .driver = { | 742 | .driver = { |
| 743 | .name = "TI-am335x-adc", | 743 | .name = "TI-am335x-adc", |
| 744 | .pm = pm_sleep_ptr(&tiadc_pm_ops), | 744 | .pm = pm_sleep_ptr(&tiadc_pm_ops), |
| 745 | .of_match_table = ti_adc_dt_ids, | 745 | .of_match_table = ti_adc_dt_ids, |
| 746 | }, | 746 | }, |
| 747 | .probe = tiadc_probe, | 747 | .probe = tiadc_probe, |
| 748 | .remove_new = tiadc_remove, | 748 | .remove = tiadc_remove, |
| 749 | }; | 749 | }; |
| 750 | module_platform_driver(tiadc_driver); | 750 | module_platform_driver(tiadc_driver); |
| 751 | 751 | ||
| @@ -248,7 +248,7 @@ static const struct s16_fract twl4030_divider_ratios[16] = { · 247 unmodified lines | |||
| 248 | {15, 100}, /* CHANNEL 11 */ | 248 | {15, 100}, /* CHANNEL 11 */ |
| 249 | {1, 4}, /* CHANNEL 12 */ | 249 | {1, 4}, /* CHANNEL 12 */ |
| 250 | {1, 1}, /* CHANNEL 13 Reserved channels */ | 250 | {1, 1}, /* CHANNEL 13 Reserved channels */ |
| 251 | {1, 1}, /* CHANNEL 14 Reseved channels */ | 251 | {1, 1}, /* CHANNEL 14 Reserved channels */ |
| 252 | {5, 11}, /* CHANNEL 15 */ | 252 | {5, 11}, /* CHANNEL 15 */ |
| 253 | }; | 253 | }; |
| 254 | 254 | ||
| @@ -914,7 +914,7 @@ MODULE_DEVICE_TABLE(of, twl_madc_of_match); · 659 unmodified lines | |||
| 914 | 914 | ||
| 915 | static struct platform_driver twl4030_madc_driver = { | 915 | static struct platform_driver twl4030_madc_driver = { |
| 916 | .probe = twl4030_madc_probe, | 916 | .probe = twl4030_madc_probe, |
| 917 | .remove_new = twl4030_madc_remove, | 917 | .remove = twl4030_madc_remove, |
| 918 | .driver = { | 918 | .driver = { |
| 919 | .name = "twl4030_madc", | 919 | .name = "twl4030_madc", |
| 920 | .of_match_table = twl_madc_of_match, | 920 | .of_match_table = twl_madc_of_match, |
| @@ -1003,7 +1003,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(twl6030_gpadc_pm_ops, twl6030_gpadc_suspend, · 1002 unmodified lines | |||
| 1003 | 1003 | ||
| 1004 | static struct platform_driver twl6030_gpadc_driver = { | 1004 | static struct platform_driver twl6030_gpadc_driver = { |
| 1005 | .probe = twl6030_gpadc_probe, | 1005 | .probe = twl6030_gpadc_probe, |
| 1006 | .remove_new = twl6030_gpadc_remove, | 1006 | .remove = twl6030_gpadc_remove, |
| 1007 | .driver = { | 1007 | .driver = { |
| 1008 | .name = DRIVER_NAME, | 1008 | .name = DRIVER_NAME, |
| 1009 | .pm = pm_sleep_ptr(&twl6030_gpadc_pm_ops), | 1009 | .pm = pm_sleep_ptr(&twl6030_gpadc_pm_ops), |
| @@ -972,7 +972,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(vf610_adc_pm_ops, vf610_adc_suspend, · 971 unmodified lines | |||
| 972 | 972 | ||
| 973 | static struct platform_driver vf610_adc_driver = { | 973 | static struct platform_driver vf610_adc_driver = { |
| 974 | .probe = vf610_adc_probe, | 974 | .probe = vf610_adc_probe, |
| 975 | .remove_new = vf610_adc_remove, | 975 | .remove = vf610_adc_remove, |
| 976 | .driver = { | 976 | .driver = { |
| 977 | .name = DRIVER_NAME, | 977 | .name = DRIVER_NAME, |
| 978 | .of_match_table = vf610_adc_match, | 978 | .of_match_table = vf610_adc_match, |
| @@ -905,7 +905,7 @@ static int ams_write_event_config(struct iio_dev *indio_dev, · 904 unmodified lines | |||
| 905 | const struct iio_chan_spec *chan, | 905 | const struct iio_chan_spec *chan, |
| 906 | enum iio_event_type type, | 906 | enum iio_event_type type, |
| 907 | enum iio_event_direction dir, | 907 | enum iio_event_direction dir, |
| 908 | int state) | 908 | bool state) |
| 909 | { | 909 | { |
| 910 | struct ams *ams = iio_priv(indio_dev); | 910 | struct ams *ams = iio_priv(indio_dev); |
| 911 | unsigned int alarm; | 911 | unsigned int alarm; |
| @@ -121,7 +121,7 @@ int xadc_read_event_config(struct iio_dev *indio_dev, · 120 unmodified lines | |||
| 121 | 121 | ||
| 122 | int xadc_write_event_config(struct iio_dev *indio_dev, | 122 | int xadc_write_event_config(struct iio_dev *indio_dev, |
| 123 | const struct iio_chan_spec *chan, enum iio_event_type type, | 123 | const struct iio_chan_spec *chan, enum iio_event_type type, |
| 124 | enum iio_event_direction dir, int state) | 124 | enum iio_event_direction dir, bool state) |
| 125 | { | 125 | { |
| 126 | unsigned int alarm = xadc_get_alarm_mask(chan); | 126 | unsigned int alarm = xadc_get_alarm_mask(chan); |
| 127 | struct xadc *xadc = iio_priv(indio_dev); | 127 | struct xadc *xadc = iio_priv(indio_dev); |
| @@ -220,7 +220,7 @@ int xadc_write_event_value(struct iio_dev *indio_dev, · 92 unmodified lines | |||
| 220 | /* | 220 | /* |
| 221 | * Since we store the hysteresis as relative (to the threshold) | 221 | * Since we store the hysteresis as relative (to the threshold) |
| 222 | * value, but the hardware expects an absolute value we need to | 222 | * value, but the hardware expects an absolute value we need to |
| 223 | * recalcualte this value whenever the hysteresis or the | 223 | * recalculate this value whenever the hysteresis or the |
| 224 | * threshold changes. | 224 | * threshold changes. |
| 225 | */ | 225 | */ |
| 226 | if (xadc->threshold[offset] < xadc->temp_hysteresis) | 226 | if (xadc->threshold[offset] < xadc->temp_hysteresis) |
| @@ -25,7 +25,7 @@ int xadc_read_event_config(struct iio_dev *indio_dev, · 24 unmodified lines | |||
| 25 | enum iio_event_direction dir); | 25 | enum iio_event_direction dir); |
| 26 | int xadc_write_event_config(struct iio_dev *indio_dev, | 26 | int xadc_write_event_config(struct iio_dev *indio_dev, |
| 27 | const struct iio_chan_spec *chan, enum iio_event_type type, | 27 | const struct iio_chan_spec *chan, enum iio_event_type type, |
| 28 | enum iio_event_direction dir, int state); | 28 | enum iio_event_direction dir, bool state); |
| 29 | int xadc_read_event_value(struct iio_dev *indio_dev, | 29 | int xadc_read_event_value(struct iio_dev *indio_dev, |
| 30 | const struct iio_chan_spec *chan, enum iio_event_type type, | 30 | const struct iio_chan_spec *chan, enum iio_event_type type, |
| 31 | enum iio_event_direction dir, enum iio_event_info info, | 31 | enum iio_event_direction dir, enum iio_event_info info, |
| @@ -191,7 +191,7 @@ enum ad74115_gpio_mode { · 190 unmodified lines | |||
| 191 | }; | 191 | }; |
| 192 | 192 | ||
| 193 | struct ad74115_channels { | 193 | struct ad74115_channels { |
| 194 | struct iio_chan_spec *channels; | 194 | const struct iio_chan_spec *channels; |
| 195 | unsigned int num_channels; | 195 | unsigned int num_channels; |
| 196 | }; | 196 | }; |
| 197 | 197 | ||
| @@ -1295,46 +1295,46 @@ static const struct iio_info ad74115_info = { · 1097 unmodified lines | |||
| 1295 | _AD74115_ADC_CHANNEL(_type, index, BIT(IIO_CHAN_INFO_SCALE) \ | 1295 | _AD74115_ADC_CHANNEL(_type, index, BIT(IIO_CHAN_INFO_SCALE) \ |
| 1296 | | BIT(IIO_CHAN_INFO_OFFSET)) | 1296 | | BIT(IIO_CHAN_INFO_OFFSET)) |
| 1297 | 1297 | ||
| 1298 | static struct iio_chan_spec ad74115_voltage_input_channels[] = { | 1298 | static const struct iio_chan_spec ad74115_voltage_input_channels[] = { |
| 1299 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1), | 1299 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1), |
| 1300 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), | 1300 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), |
| 1301 | }; | 1301 | }; |
| 1302 | 1302 | ||
| 1303 | static struct iio_chan_spec ad74115_voltage_output_channels[] = { | 1303 | static const struct iio_chan_spec ad74115_voltage_output_channels[] = { |
| 1304 | AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_MAIN), | 1304 | AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_MAIN), |
| 1305 | AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1), | 1305 | AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1), |
| 1306 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), | 1306 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), |
| 1307 | }; | 1307 | }; |
| 1308 | 1308 | ||
| 1309 | static struct iio_chan_spec ad74115_current_input_channels[] = { | 1309 | static const struct iio_chan_spec ad74115_current_input_channels[] = { |
| 1310 | AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1), | 1310 | AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1), |
| 1311 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), | 1311 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), |
| 1312 | }; | 1312 | }; |
| 1313 | 1313 | ||
| 1314 | static struct iio_chan_spec ad74115_current_output_channels[] = { | 1314 | static const struct iio_chan_spec ad74115_current_output_channels[] = { |
| 1315 | AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN), | 1315 | AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN), |
| 1316 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1), | 1316 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1), |
| 1317 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), | 1317 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), |
| 1318 | }; | 1318 | }; |
| 1319 | 1319 | ||
| 1320 | static struct iio_chan_spec ad74115_2_wire_resistance_input_channels[] = { | 1320 | static const struct iio_chan_spec ad74115_2_wire_resistance_input_channels[] = { |
| 1321 | _AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1, | 1321 | _AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1, |
| 1322 | BIT(IIO_CHAN_INFO_PROCESSED)), | 1322 | BIT(IIO_CHAN_INFO_PROCESSED)), |
| 1323 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), | 1323 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), |
| 1324 | }; | 1324 | }; |
| 1325 | 1325 | ||
| 1326 | static struct iio_chan_spec ad74115_3_4_wire_resistance_input_channels[] = { | 1326 | static const struct iio_chan_spec ad74115_3_4_wire_resistance_input_channels[] = { |
| 1327 | AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1), | 1327 | AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1), |
| 1328 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), | 1328 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), |
| 1329 | }; | 1329 | }; |
| 1330 | 1330 | ||
| 1331 | static struct iio_chan_spec ad74115_digital_input_logic_channels[] = { | 1331 | static const struct iio_chan_spec ad74115_digital_input_logic_channels[] = { |
| 1332 | AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR), | 1332 | AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR), |
| 1333 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1), | 1333 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1), |
| 1334 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), | 1334 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2), |
| 1335 | }; | 1335 | }; |
| 1336 | 1336 | ||
| 1337 | static struct iio_chan_spec ad74115_digital_input_loop_channels[] = { | 1337 | static const struct iio_chan_spec ad74115_digital_input_loop_channels[] = { |
| 1338 | AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN), | 1338 | AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN), |
| 1339 | AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR), | 1339 | AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR), |
| 1340 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1), | 1340 | AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1), |
| @@ -6,9 +6,11 @@ · 5 unmodified lines | |||
| 6 | 6 | ||
| 7 | #include <linux/unaligned.h> | 7 | #include <linux/unaligned.h> |
| 8 | #include <linux/bitfield.h> | 8 | #include <linux/bitfield.h> |
| 9 | #include <linux/cleanup.h> | ||
| 9 | #include <linux/crc8.h> | 10 | #include <linux/crc8.h> |
| 10 | #include <linux/device.h> | 11 | #include <linux/device.h> |
| 11 | #include <linux/err.h> | 12 | #include <linux/err.h> |
| 13 | #include <linux/gpio/consumer.h> | ||
| 12 | #include <linux/gpio/driver.h> | 14 | #include <linux/gpio/driver.h> |
| 13 | #include <linux/iio/buffer.h> | 15 | #include <linux/iio/buffer.h> |
| 14 | #include <linux/iio/iio.h> | 16 | #include <linux/iio/iio.h> |
| @@ -45,8 +47,8 @@ struct ad74413r_channel_config { · 30 unmodified lines | |||
| 45 | }; | 47 | }; |
| 46 | 48 | ||
| 47 | struct ad74413r_channels { | 49 | struct ad74413r_channels { |
| 48 | struct iio_chan_spec *channels; | 50 | const struct iio_chan_spec *channels; |
| 49 | unsigned int num_channels; | 51 | unsigned int num_channels; |
| 50 | }; | 52 | }; |
| 51 | 53 | ||
| 52 | struct ad74413r_state { | 54 | struct ad74413r_state { |
| @@ -59,7 +61,7 @@ struct ad74413r_state { · 6 unmodified lines | |||
| 59 | unsigned int num_gpo_gpios; | 61 | unsigned int num_gpo_gpios; |
| 60 | unsigned int num_comparator_gpios; | 62 | unsigned int num_comparator_gpios; |
| 61 | u32 sense_resistor_ohms; | 63 | u32 sense_resistor_ohms; |
| 62 | 64 | int refin_reg_uv; | |
| 63 | /* | 65 | /* |
| 64 | * Synchronize consecutive operations when doing a one-shot | 66 | * Synchronize consecutive operations when doing a one-shot |
| 65 | * conversion and when updating the ADC samples SPI message. | 67 | * conversion and when updating the ADC samples SPI message. |
| @@ -68,11 +70,9 @@ struct ad74413r_state { · 2 unmodified lines | |||
| 68 | 70 | ||
| 69 | const struct ad74413r_chip_info *chip_info; | 71 | const struct ad74413r_chip_info *chip_info; |
| 70 | struct spi_device *spi; | 72 | struct spi_device *spi; |
| 71 | struct regulator *refin_reg; | ||
| 72 | struct regmap *regmap; | 73 | struct regmap *regmap; |
| 73 | struct device *dev; | 74 | struct device *dev; |
| 74 | struct iio_trigger *trig; | 75 | struct iio_trigger *trig; |
| 75 | struct gpio_desc *reset_gpio; | ||
| 76 | 76 | ||
| 77 | size_t adc_active_channels; | 77 | size_t adc_active_channels; |
| 78 | struct spi_message adc_samples_msg; | 78 | struct spi_message adc_samples_msg; |
| @@ -407,12 +407,16 @@ static int ad74413r_gpio_set_comp_config(struct gpio_chip *chip, · 328 unmodified lines | |||
| 407 | 407 | ||
| 408 | static int ad74413r_reset(struct ad74413r_state *st) | 408 | static int ad74413r_reset(struct ad74413r_state *st) |
| 409 | { | 409 | { |
| 410 | struct gpio_desc *reset_gpio; | ||
| 410 | int ret; | 411 | int ret; |
| 411 | 412 | ||
| 412 | if (st->reset_gpio) { | 413 | reset_gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_HIGH); |
| 413 | gpiod_set_value_cansleep(st->reset_gpio, 1); | 414 | if (IS_ERR(reset_gpio)) |
| 415 | return PTR_ERR(reset_gpio); | ||
| 416 | |||
| 417 | if (reset_gpio) { | ||
| 414 | fsleep(50); | 418 | fsleep(50); |
| 415 | gpiod_set_value_cansleep(st->reset_gpio, 0); | 419 | gpiod_set_value_cansleep(reset_gpio, 0); |
| 416 | return 0; | 420 | return 0; |
| 417 | } | 421 | } |
| 418 | 422 | ||
| @@ -660,7 +664,7 @@ static int ad74413r_get_output_voltage_scale(struct ad74413r_state *st, · 241 unmodified lines | |||
| 660 | static int ad74413r_get_output_current_scale(struct ad74413r_state *st, | 664 | static int ad74413r_get_output_current_scale(struct ad74413r_state *st, |
| 661 | int *val, int *val2) | 665 | int *val, int *val2) |
| 662 | { | 666 | { |
| 663 | *val = regulator_get_voltage(st->refin_reg); | 667 | *val = st->refin_reg_uv; |
| 664 | *val2 = st->sense_resistor_ohms * AD74413R_DAC_CODE_MAX * 1000; | 668 | *val2 = st->sense_resistor_ohms * AD74413R_DAC_CODE_MAX * 1000; |
| 665 | 669 | ||
| 666 | return IIO_VAL_FRACTIONAL; | 670 | return IIO_VAL_FRACTIONAL; |
| @@ -861,19 +865,12 @@ static int ad74413r_get_single_adc_result(struct iio_dev *indio_dev, · 194 unmodified lines | |||
| 861 | unsigned int channel, int *val) | 865 | unsigned int channel, int *val) |
| 862 | { | 866 | { |
| 863 | struct ad74413r_state *st = iio_priv(indio_dev); | 867 | struct ad74413r_state *st = iio_priv(indio_dev); |
| 864 | int ret; | ||
| 865 | |||
| 866 | ret = iio_device_claim_direct_mode(indio_dev); | ||
| 867 | if (ret) | ||
| 868 | return ret; | ||
| 869 | |||
| 870 | mutex_lock(&st->lock); | ||
| 871 | ret = _ad74413r_get_single_adc_result(st, channel, val); | ||
| 872 | mutex_unlock(&st->lock); | ||
| 873 | |||
| 874 | iio_device_release_direct_mode(indio_dev); | ||
| 875 | 868 | ||
| 876 | return ret; | 869 | iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { |
| 870 | guard(mutex)(&st->lock); | ||
| 871 | return _ad74413r_get_single_adc_result(st, channel, val); | ||
| 872 | } | ||
| 873 | unreachable(); | ||
| 877 | } | 874 | } |
| 878 | 875 | ||
| 879 | static void ad74413r_adc_to_resistance_result(int adc_result, int *val) | 876 | static void ad74413r_adc_to_resistance_result(int adc_result, int *val) |
| @@ -895,7 +892,7 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev, · 15 unmodified lines | |||
| 895 | unsigned int channel; | 892 | unsigned int channel; |
| 896 | int ret = -EINVAL; | 893 | int ret = -EINVAL; |
| 897 | 894 | ||
| 898 | mutex_lock(&st->lock); | 895 | guard(mutex)(&st->lock); |
| 899 | 896 | ||
| 900 | spi_message_init(&st->adc_samples_msg); | 897 | spi_message_init(&st->adc_samples_msg); |
| 901 | st->adc_active_channels = 0; | 898 | st->adc_active_channels = 0; |
| @@ -903,11 +900,11 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev, · 1 unmodified line | |||
| 903 | for_each_clear_bit(channel, active_scan_mask, AD74413R_CHANNEL_MAX) { | 900 | for_each_clear_bit(channel, active_scan_mask, AD74413R_CHANNEL_MAX) { |
| 904 | ret = ad74413r_set_adc_channel_enable(st, channel, false); | 901 | ret = ad74413r_set_adc_channel_enable(st, channel, false); |
| 905 | if (ret) | 902 | if (ret) |
| 906 | goto out; | 903 | return ret; |
| 907 | } | 904 | } |
| 908 | 905 | ||
| 909 | if (*active_scan_mask == 0) | 906 | if (*active_scan_mask == 0) |
| 910 | goto out; | 907 | return ret; |
| 911 | 908 | ||
| 912 | /* | 909 | /* |
| 913 | * The read select register is used to select which register's value | 910 | * The read select register is used to select which register's value |
| @@ -925,7 +922,7 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev, · 11 unmodified lines | |||
| 925 | for_each_set_bit(channel, active_scan_mask, AD74413R_CHANNEL_MAX) { | 922 | for_each_set_bit(channel, active_scan_mask, AD74413R_CHANNEL_MAX) { |
| 926 | ret = ad74413r_set_adc_channel_enable(st, channel, true); | 923 | ret = ad74413r_set_adc_channel_enable(st, channel, true); |
| 927 | if (ret) | 924 | if (ret) |
| 928 | goto out; | 925 | return ret; |
| 929 | 926 | ||
| 930 | st->adc_active_channels++; | 927 | st->adc_active_channels++; |
| 931 | 928 | ||
| @@ -956,11 +953,7 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev, · 24 unmodified lines | |||
| 956 | xfer->cs_change = 0; | 953 | xfer->cs_change = 0; |
| 957 | 954 | ||
| 958 | spi_message_add_tail(xfer, &st->adc_samples_msg); | 955 | spi_message_add_tail(xfer, &st->adc_samples_msg); |
| 959 | 956 | return 0; | |
| 960 | out: | ||
| 961 | mutex_unlock(&st->lock); | ||
| 962 | |||
| 963 | return ret; | ||
| 964 | } | 957 | } |
| 965 | 958 | ||
| 966 | static int ad74413r_buffer_postenable(struct iio_dev *indio_dev) | 959 | static int ad74413r_buffer_postenable(struct iio_dev *indio_dev) |
| @@ -1138,34 +1131,34 @@ static const struct iio_info ad74413r_info = { · 171 unmodified lines | |||
| 1138 | AD74413R_ADC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE) \ | 1131 | AD74413R_ADC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE) \ |
| 1139 | | BIT(IIO_CHAN_INFO_OFFSET)) | 1132 | | BIT(IIO_CHAN_INFO_OFFSET)) |
| 1140 | 1133 | ||
| 1141 | static struct iio_chan_spec ad74413r_voltage_output_channels[] = { | 1134 | static const struct iio_chan_spec ad74413r_voltage_output_channels[] = { |
| 1142 | AD74413R_DAC_CHANNEL(IIO_VOLTAGE, BIT(IIO_CHAN_INFO_SCALE)), | 1135 | AD74413R_DAC_CHANNEL(IIO_VOLTAGE, BIT(IIO_CHAN_INFO_SCALE)), |
| 1143 | AD74413R_ADC_CURRENT_CHANNEL, | 1136 | AD74413R_ADC_CURRENT_CHANNEL, |
| 1144 | }; | 1137 | }; |
| 1145 | 1138 | ||
| 1146 | static struct iio_chan_spec ad74413r_current_output_channels[] = { | 1139 | static const struct iio_chan_spec ad74413r_current_output_channels[] = { |
| 1147 | AD74413R_DAC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE)), | 1140 | AD74413R_DAC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE)), |
| 1148 | AD74413R_ADC_VOLTAGE_CHANNEL, | 1141 | AD74413R_ADC_VOLTAGE_CHANNEL, |
| 1149 | }; | 1142 | }; |
| 1150 | 1143 | ||
| 1151 | static struct iio_chan_spec ad74413r_voltage_input_channels[] = { | 1144 | static const struct iio_chan_spec ad74413r_voltage_input_channels[] = { |
| 1152 | AD74413R_ADC_VOLTAGE_CHANNEL, | 1145 | AD74413R_ADC_VOLTAGE_CHANNEL, |
| 1153 | }; | 1146 | }; |
| 1154 | 1147 | ||
| 1155 | static struct iio_chan_spec ad74413r_current_input_channels[] = { | 1148 | static const struct iio_chan_spec ad74413r_current_input_channels[] = { |
| 1156 | AD74413R_ADC_CURRENT_CHANNEL, | 1149 | AD74413R_ADC_CURRENT_CHANNEL, |
| 1157 | }; | 1150 | }; |
| 1158 | 1151 | ||
| 1159 | static struct iio_chan_spec ad74413r_current_input_loop_channels[] = { | 1152 | static const struct iio_chan_spec ad74413r_current_input_loop_channels[] = { |
| 1160 | AD74413R_DAC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE)), | 1153 | AD74413R_DAC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE)), |
| 1161 | AD74413R_ADC_CURRENT_CHANNEL, | 1154 | AD74413R_ADC_CURRENT_CHANNEL, |
| 1162 | }; | 1155 | }; |
| 1163 | 1156 | ||
| 1164 | static struct iio_chan_spec ad74413r_resistance_input_channels[] = { | 1157 | static const struct iio_chan_spec ad74413r_resistance_input_channels[] = { |
| 1165 | AD74413R_ADC_CHANNEL(IIO_RESISTANCE, BIT(IIO_CHAN_INFO_PROCESSED)), | 1158 | AD74413R_ADC_CHANNEL(IIO_RESISTANCE, BIT(IIO_CHAN_INFO_PROCESSED)), |
| 1166 | }; | 1159 | }; |
| 1167 | 1160 | ||
| 1168 | static struct iio_chan_spec ad74413r_digital_input_channels[] = { | 1161 | static const struct iio_chan_spec ad74413r_digital_input_channels[] = { |
| 1169 | AD74413R_ADC_VOLTAGE_CHANNEL, | 1162 | AD74413R_ADC_VOLTAGE_CHANNEL, |
| 1170 | }; | 1163 | }; |
| 1171 | 1164 | ||
| @@ -1270,7 +1263,8 @@ static int ad74413r_setup_channels(struct iio_dev *indio_dev) · 98 unmodified lines | |||
| 1270 | { | 1263 | { |
| 1271 | struct ad74413r_state *st = iio_priv(indio_dev); | 1264 | struct ad74413r_state *st = iio_priv(indio_dev); |
| 1272 | struct ad74413r_channel_config *config; | 1265 | struct ad74413r_channel_config *config; |
| 1273 | struct iio_chan_spec *channels, *chans; | 1266 | const struct iio_chan_spec *chans; |
| 1267 | struct iio_chan_spec *channels; | ||
| 1274 | unsigned int i, num_chans, chan_i; | 1268 | unsigned int i, num_chans, chan_i; |
| 1275 | int ret; | 1269 | int ret; |
| 1276 | 1270 | ||
| @@ -1346,11 +1340,6 @@ static int ad74413r_setup_gpios(struct ad74413r_state *st) · 69 unmodified lines | |||
| 1346 | return 0; | 1340 | return 0; |
| 1347 | } | 1341 | } |
| 1348 | 1342 | ||
| 1349 | static void ad74413r_regulator_disable(void *regulator) | ||
| 1350 | { | ||
| 1351 | regulator_disable(regulator); | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | static int ad74413r_probe(struct spi_device *spi) | 1343 | static int ad74413r_probe(struct spi_device *spi) |
| 1355 | { | 1344 | { |
| 1356 | struct ad74413r_state *st; | 1345 | struct ad74413r_state *st; |
| @@ -1369,7 +1358,10 @@ static int ad74413r_probe(struct spi_device *spi) · 12 unmodified lines | |||
| 1369 | if (!st->chip_info) | 1358 | if (!st->chip_info) |
| 1370 | return -EINVAL; | 1359 | return -EINVAL; |
| 1371 | 1360 | ||
| 1372 | mutex_init(&st->lock); | 1361 | ret = devm_mutex_init(st->dev, &st->lock); |
| 1362 | if (ret) | ||
| 1363 | return ret; | ||
| 1364 | |||
| 1373 | init_completion(&st->adc_data_completion); | 1365 | init_completion(&st->adc_data_completion); |
| 1374 | 1366 | ||
| 1375 | st->regmap = devm_regmap_init(st->dev, NULL, st, | 1367 | st->regmap = devm_regmap_init(st->dev, NULL, st, |
| @@ -1377,23 +1369,11 @@ static int ad74413r_probe(struct spi_device *spi) · 1 unmodified line | |||
| 1377 | if (IS_ERR(st->regmap)) | 1369 | if (IS_ERR(st->regmap)) |
| 1378 | return PTR_ERR(st->regmap); | 1370 | return PTR_ERR(st->regmap); |
| 1379 | 1371 | ||
| 1380 | st->reset_gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW); | 1372 | ret = devm_regulator_get_enable_read_voltage(st->dev, "refin"); |
| 1381 | if (IS_ERR(st->reset_gpio)) | 1373 | if (ret < 0) |
| 1382 | return PTR_ERR(st->reset_gpio); | 1374 | return dev_err_probe(st->dev, ret, |
| 1383 | 1375 | "Failed to get refin regulator voltage\n"); | |
| 1384 | st->refin_reg = devm_regulator_get(st->dev, "refin"); | 1376 | st->refin_reg_uv = ret; |
| 1385 | if (IS_ERR(st->refin_reg)) | ||
| 1386 | return dev_err_probe(st->dev, PTR_ERR(st->refin_reg), | ||
| 1387 | "Failed to get refin regulator\n"); | ||
| 1388 | |||
| 1389 | ret = regulator_enable(st->refin_reg); | ||
| 1390 | if (ret) | ||
| 1391 | return ret; | ||
| 1392 | |||
| 1393 | ret = devm_add_action_or_reset(st->dev, ad74413r_regulator_disable, | ||
| 1394 | st->refin_reg); | ||
| 1395 | if (ret) | ||
| 1396 | return ret; | ||
| 1397 | 1377 | ||
| 1398 | st->sense_resistor_ohms = 100000000; | 1378 | st->sense_resistor_ohms = 100000000; |
| 1399 | device_property_read_u32(st->dev, "shunt-resistor-micro-ohms", | 1379 | device_property_read_u32(st->dev, "shunt-resistor-micro-ohms", |
| @@ -232,7 +232,7 @@ static int ad7150_write_event_params(struct iio_dev *indio_dev, · 231 unmodified lines | |||
| 232 | static int ad7150_write_event_config(struct iio_dev *indio_dev, | 232 | static int ad7150_write_event_config(struct iio_dev *indio_dev, |
| 233 | const struct iio_chan_spec *chan, | 233 | const struct iio_chan_spec *chan, |
| 234 | enum iio_event_type type, | 234 | enum iio_event_type type, |
| 235 | enum iio_event_direction dir, int state) | 235 | enum iio_event_direction dir, bool state) |
| 236 | { | 236 | { |
| 237 | struct ad7150_chip_info *chip = iio_priv(indio_dev); | 237 | struct ad7150_chip_info *chip = iio_priv(indio_dev); |
| 238 | int ret = 0; | 238 | int ret = 0; |
| @@ -50,6 +50,8 @@ config BME680 · 49 unmodified lines | |||
| 50 | select REGMAP | 50 | select REGMAP |
| 51 | select BME680_I2C if I2C | 51 | select BME680_I2C if I2C |
| 52 | select BME680_SPI if SPI | 52 | select BME680_SPI if SPI |
| 53 | select IIO_BUFFER | ||
| 54 | select IIO_TRIGGERED_BUFFER | ||
| 53 | help | 55 | help |
| 54 | Say yes here to build support for Bosch Sensortec BME680 sensor with | 56 | Say yes here to build support for Bosch Sensortec BME680 sensor with |
| 55 | temperature, pressure, humidity and gas sensing capability. | 57 | temperature, pressure, humidity and gas sensing capability. |
| @@ -2,6 +2,8 @@ · 1 unmodified line | |||
| 2 | #ifndef BME680_H_ | 2 | #ifndef BME680_H_ |
| 3 | #define BME680_H_ | 3 | #define BME680_H_ |
| 4 | 4 | ||
| 5 | #include <linux/regmap.h> | ||
| 6 | |||
| 5 | #define BME680_REG_CHIP_ID 0xD0 | 7 | #define BME680_REG_CHIP_ID 0xD0 |
| 6 | #define BME680_CHIP_ID_VAL 0x61 | 8 | #define BME680_CHIP_ID_VAL 0x61 |
| 7 | #define BME680_REG_SOFT_RESET 0xE0 | 9 | #define BME680_REG_SOFT_RESET 0xE0 |
| @@ -25,8 +27,6 @@ · 17 unmodified lines | |||
| 25 | #define BME680_OSRS_TEMP_MASK GENMASK(7, 5) | 27 | #define BME680_OSRS_TEMP_MASK GENMASK(7, 5) |
| 26 | #define BME680_OSRS_PRESS_MASK GENMASK(4, 2) | 28 | #define BME680_OSRS_PRESS_MASK GENMASK(4, 2) |
| 27 | #define BME680_MODE_MASK GENMASK(1, 0) | 29 | #define BME680_MODE_MASK GENMASK(1, 0) |
| 28 | #define BME680_MODE_FORCED 1 | ||
| 29 | #define BME680_MODE_SLEEP 0 | ||
| 30 | 30 | ||
| 31 | #define BME680_REG_CONFIG 0x75 | 31 | #define BME680_REG_CONFIG 0x75 |
| 32 | #define BME680_FILTER_MASK GENMASK(4, 2) | 32 | #define BME680_FILTER_MASK GENMASK(4, 2) |
| @@ -42,6 +42,7 @@ · 9 unmodified lines | |||
| 42 | #define BME680_RHRANGE_MASK GENMASK(5, 4) | 42 | #define BME680_RHRANGE_MASK GENMASK(5, 4) |
| 43 | #define BME680_REG_RES_HEAT_VAL 0x00 | 43 | #define BME680_REG_RES_HEAT_VAL 0x00 |
| 44 | #define BME680_RSERROR_MASK GENMASK(7, 4) | 44 | #define BME680_RSERROR_MASK GENMASK(7, 4) |
| 45 | #define BME680_REG_IDAC_HEAT_0 0x50 | ||
| 45 | #define BME680_REG_RES_HEAT_0 0x5A | 46 | #define BME680_REG_RES_HEAT_0 0x5A |
| 46 | #define BME680_REG_GAS_WAIT_0 0x64 | 47 | #define BME680_REG_GAS_WAIT_0 0x64 |
| 47 | #define BME680_ADC_GAS_RES GENMASK(15, 6) | 48 | #define BME680_ADC_GAS_RES GENMASK(15, 6) |
| @@ -63,7 +64,11 @@ · 15 unmodified lines | |||
| 63 | 64 | ||
| 64 | #define BME680_MEAS_TRIM_MASK GENMASK(24, 4) | 65 | #define BME680_MEAS_TRIM_MASK GENMASK(24, 4) |
| 65 | 66 | ||
| 66 | #define BME680_STARTUP_TIME_US 5000 | 67 | /* Datasheet Section 1.1, Table 1 */ |
| 68 | #define BME680_STARTUP_TIME_US 2000 | ||
| 69 | |||
| 70 | #define BME680_NUM_CHANNELS 4 | ||
| 71 | #define BME680_NUM_BULK_READ_REGS 15 | ||
| 67 | 72 | ||
| 68 | /* Calibration Parameters */ | 73 | /* Calibration Parameters */ |
| 69 | #define BME680_T2_LSB_REG 0x8A | 74 | #define BME680_T2_LSB_REG 0x8A |
| @@ -16,8 +16,11 @@ · 15 unmodified lines | |||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/regmap.h> | 17 | #include <linux/regmap.h> |
| 18 | 18 | ||
| 19 | #include <linux/iio/buffer.h> | ||
| 19 | #include <linux/iio/iio.h> | 20 | #include <linux/iio/iio.h> |
| 20 | #include <linux/iio/sysfs.h> | 21 | #include <linux/iio/sysfs.h> |
| 22 | #include <linux/iio/trigger_consumer.h> | ||
| 23 | #include <linux/iio/triggered_buffer.h> | ||
| 21 | 24 | ||
| 22 | #include <linux/unaligned.h> | 25 | #include <linux/unaligned.h> |
| 23 | 26 | ||
| @@ -95,6 +98,19 @@ struct bme680_calib { · 71 unmodified lines | |||
| 95 | s8 range_sw_err; | 98 | s8 range_sw_err; |
| 96 | }; | 99 | }; |
| 97 | 100 | ||
| 101 | /* values of CTRL_MEAS register */ | ||
| 102 | enum bme680_op_mode { | ||
| 103 | BME680_MODE_SLEEP = 0, | ||
| 104 | BME680_MODE_FORCED = 1, | ||
| 105 | }; | ||
| 106 | |||
| 107 | enum bme680_scan { | ||
| 108 | BME680_TEMP, | ||
| 109 | BME680_PRESS, | ||
| 110 | BME680_HUMID, | ||
| 111 | BME680_GAS, | ||
| 112 | }; | ||
| 113 | |||
| 98 | struct bme680_data { | 114 | struct bme680_data { |
| 99 | struct regmap *regmap; | 115 | struct regmap *regmap; |
| 100 | struct bme680_calib bme680; | 116 | struct bme680_calib bme680; |
| @@ -102,11 +118,17 @@ struct bme680_data { · 1 unmodified line | |||
| 102 | u8 oversampling_temp; | 118 | u8 oversampling_temp; |
| 103 | u8 oversampling_press; | 119 | u8 oversampling_press; |
| 104 | u8 oversampling_humid; | 120 | u8 oversampling_humid; |
| 121 | u8 preheat_curr_mA; | ||
| 105 | u16 heater_dur; | 122 | u16 heater_dur; |
| 106 | u16 heater_temp; | 123 | u16 heater_temp; |
| 107 | 124 | ||
| 125 | struct { | ||
| 126 | s32 chan[4]; | ||
| 127 | aligned_s64 ts; | ||
| 128 | } scan; | ||
| 129 | |||
| 108 | union { | 130 | union { |
| 109 | u8 buf[3]; | 131 | u8 buf[BME680_NUM_BULK_READ_REGS]; |
| 110 | unsigned int check; | 132 | unsigned int check; |
| 111 | __be16 be16; | 133 | __be16 be16; |
| 112 | u8 bme680_cal_buf_1[BME680_CALIB_RANGE_1_LEN]; | 134 | u8 bme680_cal_buf_1[BME680_CALIB_RANGE_1_LEN]; |
| @@ -138,22 +160,66 @@ EXPORT_SYMBOL_NS(bme680_regmap_config, IIO_BME680); · 25 unmodified lines | |||
| 138 | static const struct iio_chan_spec bme680_channels[] = { | 160 | static const struct iio_chan_spec bme680_channels[] = { |
| 139 | { | 161 | { |
| 140 | .type = IIO_TEMP, | 162 | .type = IIO_TEMP, |
| 163 | /* PROCESSED maintained for ABI backwards compatibility */ | ||
| 141 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | | 164 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | |
| 165 | BIT(IIO_CHAN_INFO_RAW) | | ||
| 166 | BIT(IIO_CHAN_INFO_SCALE) | | ||
| 142 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), | 167 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), |
| 168 | .scan_index = 0, | ||
| 169 | .scan_type = { | ||
| 170 | .sign = 's', | ||
| 171 | .realbits = 16, | ||
| 172 | .storagebits = 16, | ||
| 173 | .endianness = IIO_CPU, | ||
| 174 | }, | ||
| 143 | }, | 175 | }, |
| 144 | { | 176 | { |
| 145 | .type = IIO_PRESSURE, | 177 | .type = IIO_PRESSURE, |
| 178 | /* PROCESSED maintained for ABI backwards compatibility */ | ||
| 146 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | | 179 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | |
| 180 | BIT(IIO_CHAN_INFO_RAW) | | ||
| 181 | BIT(IIO_CHAN_INFO_SCALE) | | ||
| 147 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), | 182 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), |
| 183 | .scan_index = 1, | ||
| 184 | .scan_type = { | ||
| 185 | .sign = 'u', | ||
| 186 | .realbits = 32, | ||
| 187 | .storagebits = 32, | ||
| 188 | .endianness = IIO_CPU, | ||
| 189 | }, | ||
| 148 | }, | 190 | }, |
| 149 | { | 191 | { |
| 150 | .type = IIO_HUMIDITYRELATIVE, | 192 | .type = IIO_HUMIDITYRELATIVE, |
| 193 | /* PROCESSED maintained for ABI backwards compatibility */ | ||
| 151 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | | 194 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | |
| 195 | BIT(IIO_CHAN_INFO_RAW) | | ||
| 196 | BIT(IIO_CHAN_INFO_SCALE) | | ||
| 152 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), | 197 | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), |
| 198 | .scan_index = 2, | ||
| 199 | .scan_type = { | ||
| 200 | .sign = 'u', | ||
| 201 | .realbits = 32, | ||
| 202 | .storagebits = 32, | ||
| 203 | .endianness = IIO_CPU, | ||
| 204 | }, | ||
| 153 | }, | 205 | }, |
| 154 | { | 206 | { |
| 155 | .type = IIO_RESISTANCE, | 207 | .type = IIO_RESISTANCE, |
| 156 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), | 208 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), |
| 209 | .scan_index = 3, | ||
| 210 | .scan_type = { | ||
| 211 | .sign = 'u', | ||
| 212 | .realbits = 32, | ||
| 213 | .storagebits = 32, | ||
| 214 | .endianness = IIO_CPU, | ||
| 215 | }, | ||
| 216 | }, | ||
| 217 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
| 218 | { | ||
| 219 | .type = IIO_CURRENT, | ||
| 220 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), | ||
| 221 | .output = 1, | ||
| 222 | .scan_index = -1, | ||
| 157 | }, | 223 | }, |
| 158 | }; | 224 | }; |
| 159 | 225 | ||
| @@ -224,7 +290,7 @@ static int bme680_read_calib(struct bme680_data *data, · 64 unmodified lines | |||
| 224 | calib->res_heat_val = data->bme680_cal_buf_3[RES_HEAT_VAL]; | 290 | calib->res_heat_val = data->bme680_cal_buf_3[RES_HEAT_VAL]; |
| 225 | 291 | ||
| 226 | calib->res_heat_range = FIELD_GET(BME680_RHRANGE_MASK, | 292 | calib->res_heat_range = FIELD_GET(BME680_RHRANGE_MASK, |
| 227 | data->bme680_cal_buf_3[RES_HEAT_RANGE]); | 293 | data->bme680_cal_buf_3[RES_HEAT_RANGE]); |
| 228 | 294 | ||
| 229 | calib->range_sw_err = FIELD_GET(BME680_RSERROR_MASK, | 295 | calib->range_sw_err = FIELD_GET(BME680_RSERROR_MASK, |
| 230 | data->bme680_cal_buf_3[RANGE_SW_ERR]); | 296 | data->bme680_cal_buf_3[RANGE_SW_ERR]); |
| @@ -438,19 +504,19 @@ static u32 bme680_compensate_gas(struct bme680_data *data, u16 gas_res_adc, · 207 unmodified lines | |||
| 438 | u32 calc_gas_res; | 504 | u32 calc_gas_res; |
| 439 | 505 | ||
| 440 | /* Look up table for the possible gas range values */ | 506 | /* Look up table for the possible gas range values */ |
| 441 | static const u32 lookupTable[16] = {2147483647u, 2147483647u, | 507 | static const u32 lookup_table[16] = { |
| 442 | 2147483647u, 2147483647u, 2147483647u, | 508 | 2147483647u, 2147483647u, 2147483647u, 2147483647u, |
| 443 | 2126008810u, 2147483647u, 2130303777u, | 509 | 2147483647u, 2126008810u, 2147483647u, 2130303777u, |
| 444 | 2147483647u, 2147483647u, 2143188679u, | 510 | 2147483647u, 2147483647u, 2143188679u, 2136746228u, |
| 445 | 2136746228u, 2147483647u, 2126008810u, | 511 | 2147483647u, 2126008810u, 2147483647u, 2147483647u |
| 446 | 2147483647u, 2147483647u}; | 512 | }; |
| 447 | 513 | ||
| 448 | var1 = ((1340 + (5 * (s64) calib->range_sw_err)) * | 514 | var1 = ((1340LL + (5 * calib->range_sw_err)) * |
| 449 | ((s64) lookupTable[gas_range])) >> 16; | 515 | (lookup_table[gas_range])) >> 16; |
| 450 | var2 = ((gas_res_adc << 15) - 16777216) + var1; | 516 | var2 = ((gas_res_adc << 15) - 16777216) + var1; |
| 451 | var3 = ((125000 << (15 - gas_range)) * var1) >> 9; | 517 | var3 = ((125000 << (15 - gas_range)) * var1) >> 9; |
| 452 | var3 += (var2 >> 1); | 518 | var3 += (var2 >> 1); |
| 453 | calc_gas_res = div64_s64(var3, (s64) var2); | 519 | calc_gas_res = div64_s64(var3, (s64)var2); |
| 454 | 520 | ||
| 455 | return calc_gas_res; | 521 | return calc_gas_res; |
| 456 | } | 522 | } |
| @@ -468,7 +534,7 @@ static u8 bme680_calc_heater_res(struct bme680_data *data, u16 temp) · 11 unmodified lines | |||
| 468 | if (temp > 400) /* Cap temperature */ | 534 | if (temp > 400) /* Cap temperature */ |
| 469 | temp = 400; | 535 | temp = 400; |
| 470 | 536 | ||
| 471 | var1 = (((s32) BME680_AMB_TEMP * calib->par_gh3) / 1000) * 256; | 537 | var1 = (((s32)BME680_AMB_TEMP * calib->par_gh3) / 1000) * 256; |
| 472 | var2 = (calib->par_gh1 + 784) * (((((calib->par_gh2 + 154009) * | 538 | var2 = (calib->par_gh1 + 784) * (((((calib->par_gh2 + 154009) * |
| 473 | temp * 5) / 100) | 539 | temp * 5) / 100) |
| 474 | + 3276800) / 10); | 540 | + 3276800) / 10); |
| @@ -502,23 +568,22 @@ static u8 bme680_calc_heater_dur(u16 dur) · 27 unmodified lines | |||
| 502 | return durval; | 568 | return durval; |
| 503 | } | 569 | } |
| 504 | 570 | ||
| 505 | static int bme680_set_mode(struct bme680_data *data, bool mode) | 571 | /* Taken from datasheet, section 5.3.3 */ |
| 572 | static u8 bme680_calc_heater_preheat_current(u8 curr) | ||
| 573 | { | ||
| 574 | return 8 * curr - 1; | ||
| 575 | } | ||
| 576 | |||
| 577 | static int bme680_set_mode(struct bme680_data *data, enum bme680_op_mode mode) | ||
| 506 | { | 578 | { |
| 507 | struct device *dev = regmap_get_device(data->regmap); | 579 | struct device *dev = regmap_get_device(data->regmap); |
| 508 | int ret; | 580 | int ret; |
| 509 | 581 | ||
| 510 | if (mode) { | 582 | ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS, |
| 511 | ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS, | 583 | BME680_MODE_MASK, mode); |
| 512 | BME680_MODE_MASK, BME680_MODE_FORCED); | 584 | if (ret < 0) { |
| 513 | if (ret < 0) | 585 | dev_err(dev, "failed to set ctrl_meas register\n"); |
| 514 | dev_err(dev, "failed to set forced mode\n"); | 586 | return ret; |
| 515 | |||
| 516 | } else { | ||
| 517 | ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS, | ||
| 518 | BME680_MODE_MASK, BME680_MODE_SLEEP); | ||
| 519 | if (ret < 0) | ||
| 520 | dev_err(dev, "failed to set sleep mode\n"); | ||
| 521 | |||
| 522 | } | 587 | } |
| 523 | 588 | ||
| 524 | return ret; | 589 | return ret; |
| @@ -546,7 +611,7 @@ static int bme680_wait_for_eoc(struct bme680_data *data) · 21 unmodified lines | |||
| 546 | data->oversampling_humid) * 1936) + (477 * 4) + | 611 | data->oversampling_humid) * 1936) + (477 * 4) + |
| 547 | (477 * 5) + 1000 + (data->heater_dur * 1000); | 612 | (477 * 5) + 1000 + (data->heater_dur * 1000); |
| 548 | 613 | ||
| 549 | usleep_range(wait_eoc_us, wait_eoc_us + 100); | 614 | fsleep(wait_eoc_us); |
| 550 | 615 | ||
| 551 | ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &data->check); | 616 | ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &data->check); |
| 552 | if (ret) { | 617 | if (ret) { |
| @@ -571,9 +636,8 @@ static int bme680_chip_config(struct bme680_data *data) · 18 unmodified lines | |||
| 571 | int ret; | 636 | int ret; |
| 572 | u8 osrs; | 637 | u8 osrs; |
| 573 | 638 | ||
| 574 | osrs = FIELD_PREP( | 639 | osrs = FIELD_PREP(BME680_OSRS_HUMIDITY_MASK, |
| 575 | BME680_OSRS_HUMIDITY_MASK, | 640 | bme680_oversampling_to_reg(data->oversampling_humid)); |
| 576 | bme680_oversampling_to_reg(data->oversampling_humid)); | ||
| 577 | /* | 641 | /* |
| 578 | * Highly recommended to set oversampling of humidity before | 642 | * Highly recommended to set oversampling of humidity before |
| 579 | * temperature/pressure oversampling. | 643 | * temperature/pressure oversampling. |
| @@ -587,8 +651,7 @@ static int bme680_chip_config(struct bme680_data *data) · 7 unmodified lines | |||
| 587 | 651 | ||
| 588 | /* IIR filter settings */ | 652 | /* IIR filter settings */ |
| 589 | ret = regmap_update_bits(data->regmap, BME680_REG_CONFIG, | 653 | ret = regmap_update_bits(data->regmap, BME680_REG_CONFIG, |
| 590 | BME680_FILTER_MASK, | 654 | BME680_FILTER_MASK, BME680_FILTER_COEFF_VAL); |
| 591 | BME680_FILTER_COEFF_VAL); | ||
| 592 | if (ret < 0) { | 655 | if (ret < 0) { |
| 593 | dev_err(dev, "failed to write config register\n"); | 656 | dev_err(dev, "failed to write config register\n"); |
| 594 | return ret; | 657 | return ret; |
| @@ -609,14 +672,27 @@ static int bme680_chip_config(struct bme680_data *data) · 14 unmodified lines | |||
| 609 | return 0; | 672 | return 0; |
| 610 | } | 673 | } |
| 611 | 674 | ||
| 675 | static int bme680_preheat_curr_config(struct bme680_data *data, u8 val) | ||
| 676 | { | ||
| 677 | struct device *dev = regmap_get_device(data->regmap); | ||
| 678 | u8 heatr_curr; | ||
| 679 | int ret; | ||
| 680 | |||
| 681 | heatr_curr = bme680_calc_heater_preheat_current(val); | ||
| 682 | ret = regmap_write(data->regmap, BME680_REG_IDAC_HEAT_0, heatr_curr); | ||
| 683 | if (ret < 0) | ||
| 684 | dev_err(dev, "failed to write idac_heat_0 register\n"); | ||
| 685 | |||
| 686 | return ret; | ||
| 687 | } | ||
| 688 | |||
| 612 | static int bme680_gas_config(struct bme680_data *data) | 689 | static int bme680_gas_config(struct bme680_data *data) |
| 613 | { | 690 | { |
| 614 | struct device *dev = regmap_get_device(data->regmap); | 691 | struct device *dev = regmap_get_device(data->regmap); |
| 615 | int ret; | 692 | int ret; |
| 616 | u8 heatr_res, heatr_dur; | 693 | u8 heatr_res, heatr_dur; |
| 617 | 694 | ||
| 618 | /* Go to sleep */ | 695 | ret = bme680_set_mode(data, BME680_MODE_SLEEP); |
| 619 | ret = bme680_set_mode(data, false); | ||
| 620 | if (ret < 0) | 696 | if (ret < 0) |
| 621 | return ret; | 697 | return ret; |
| 622 | 698 | ||
| @@ -638,6 +714,10 @@ static int bme680_gas_config(struct bme680_data *data) · 15 unmodified lines | |||
| 638 | return ret; | 714 | return ret; |
| 639 | } | 715 | } |
| 640 | 716 | ||
| 717 | ret = bme680_preheat_curr_config(data, data->preheat_curr_mA); | ||
| 718 | if (ret) | ||
| 719 | return ret; | ||
| 720 | |||
| 641 | /* Enable the gas sensor and select heater profile set-point 0 */ | 721 | /* Enable the gas sensor and select heater profile set-point 0 */ |
| 642 | ret = regmap_update_bits(data->regmap, BME680_REG_CTRL_GAS_1, | 722 | ret = regmap_update_bits(data->regmap, BME680_REG_CTRL_GAS_1, |
| 643 | BME680_RUN_GAS_MASK | BME680_NB_CONV_MASK, | 723 | BME680_RUN_GAS_MASK | BME680_NB_CONV_MASK, |
| @@ -649,23 +729,20 @@ static int bme680_gas_config(struct bme680_data *data) · 5 unmodified lines | |||
| 649 | return ret; | 729 | return ret; |
| 650 | } | 730 | } |
| 651 | 731 | ||
| 652 | static int bme680_read_temp(struct bme680_data *data, int *val) | 732 | static int bme680_read_temp(struct bme680_data *data, s16 *comp_temp) |
| 653 | { | 733 | { |
| 654 | int ret; | 734 | int ret; |
| 655 | u32 adc_temp; | 735 | u32 adc_temp; |
| 656 | s16 comp_temp; | ||
| 657 | 736 | ||
| 658 | ret = bme680_read_temp_adc(data, &adc_temp); | 737 | ret = bme680_read_temp_adc(data, &adc_temp); |
| 659 | if (ret) | 738 | if (ret) |
| 660 | return ret; | 739 | return ret; |
| 661 | 740 | ||
| 662 | comp_temp = bme680_compensate_temp(data, adc_temp); | 741 | *comp_temp = bme680_compensate_temp(data, adc_temp); |
| 663 | *val = comp_temp * 10; /* Centidegrees to millidegrees */ | 742 | return 0; |
| 664 | return IIO_VAL_INT; | ||
| 665 | } | 743 | } |
| 666 | 744 | ||
| 667 | static int bme680_read_press(struct bme680_data *data, | 745 | static int bme680_read_press(struct bme680_data *data, u32 *comp_press) |
| 668 | int *val, int *val2) | ||
| 669 | { | 746 | { |
| 670 | int ret; | 747 | int ret; |
| 671 | u32 adc_press; | 748 | u32 adc_press; |
| @@ -679,16 +756,14 @@ static int bme680_read_press(struct bme680_data *data, · 7 unmodified lines | |||
| 679 | if (ret) | 756 | if (ret) |
| 680 | return ret; | 757 | return ret; |
| 681 | 758 | ||
| 682 | *val = bme680_compensate_press(data, adc_press, t_fine); | 759 | *comp_press = bme680_compensate_press(data, adc_press, t_fine); |
| 683 | *val2 = 1000; | 760 | return 0; |
| 684 | return IIO_VAL_FRACTIONAL; | ||
| 685 | } | 761 | } |
| 686 | 762 | ||
| 687 | static int bme680_read_humid(struct bme680_data *data, | 763 | static int bme680_read_humid(struct bme680_data *data, u32 *comp_humidity) |
| 688 | int *val, int *val2) | ||
| 689 | { | 764 | { |
| 690 | int ret; | 765 | int ret; |
| 691 | u32 adc_humidity, comp_humidity; | 766 | u32 adc_humidity; |
| 692 | s32 t_fine; | 767 | s32 t_fine; |
| 693 | 768 | ||
| 694 | ret = bme680_get_t_fine(data, &t_fine); | 769 | ret = bme680_get_t_fine(data, &t_fine); |
| @@ -699,15 +774,11 @@ static int bme680_read_humid(struct bme680_data *data, · 4 unmodified lines | |||
| 699 | if (ret) | 774 | if (ret) |
| 700 | return ret; | 775 | return ret; |
| 701 | 776 | ||
| 702 | comp_humidity = bme680_compensate_humid(data, adc_humidity, t_fine); | 777 | *comp_humidity = bme680_compensate_humid(data, adc_humidity, t_fine); |
| 703 | 778 | return 0; | |
| 704 | *val = comp_humidity; | ||
| 705 | *val2 = 1000; | ||
| 706 | return IIO_VAL_FRACTIONAL; | ||
| 707 | } | 779 | } |
| 708 | 780 | ||
| 709 | static int bme680_read_gas(struct bme680_data *data, | 781 | static int bme680_read_gas(struct bme680_data *data, int *comp_gas_res) |
| 710 | int *val) | ||
| 711 | { | 782 | { |
| 712 | struct device *dev = regmap_get_device(data->regmap); | 783 | struct device *dev = regmap_get_device(data->regmap); |
| 713 | int ret; | 784 | int ret; |
| @@ -742,9 +813,8 @@ static int bme680_read_gas(struct bme680_data *data, · 28 unmodified lines | |||
| 742 | } | 813 | } |
| 743 | 814 | ||
| 744 | gas_range = FIELD_GET(BME680_GAS_RANGE_MASK, gas_regs_val); | 815 | gas_range = FIELD_GET(BME680_GAS_RANGE_MASK, gas_regs_val); |
| 745 | 816 | *comp_gas_res = bme680_compensate_gas(data, adc_gas_res, gas_range); | |
| 746 | *val = bme680_compensate_gas(data, adc_gas_res, gas_range); | 817 | return 0; |
| 747 | return IIO_VAL_INT; | ||
| 748 | } | 818 | } |
| 749 | 819 | ||
| 750 | static int bme680_read_raw(struct iio_dev *indio_dev, | 820 | static int bme680_read_raw(struct iio_dev *indio_dev, |
| @@ -752,12 +822,12 @@ static int bme680_read_raw(struct iio_dev *indio_dev, · 1 unmodified line | |||
| 752 | int *val, int *val2, long mask) | 822 | int *val, int *val2, long mask) |
| 753 | { | 823 | { |
| 754 | struct bme680_data *data = iio_priv(indio_dev); | 824 | struct bme680_data *data = iio_priv(indio_dev); |
| 755 | int ret; | 825 | int chan_val, ret; |
| 826 | s16 temp_chan_val; | ||
| 756 | 827 | ||
| 757 | guard(mutex)(&data->lock); | 828 | guard(mutex)(&data->lock); |
| 758 | 829 | ||
| 759 | /* set forced mode to trigger measurement */ | 830 | ret = bme680_set_mode(data, BME680_MODE_FORCED); |
| 760 | ret = bme680_set_mode(data, true); | ||
| 761 | if (ret < 0) | 831 | if (ret < 0) |
| 762 | return ret; | 832 | return ret; |
| 763 | 833 | ||
| @@ -769,13 +839,77 @@ static int bme680_read_raw(struct iio_dev *indio_dev, · 5 unmodified lines | |||
| 769 | case IIO_CHAN_INFO_PROCESSED: | 839 | case IIO_CHAN_INFO_PROCESSED: |
| 770 | switch (chan->type) { | 840 | switch (chan->type) { |
| 771 | case IIO_TEMP: | 841 | case IIO_TEMP: |
| 772 | return bme680_read_temp(data, val); | 842 | ret = bme680_read_temp(data, &temp_chan_val); |
| 843 | if (ret) | ||
| 844 | return ret; | ||
| 845 | |||
| 846 | *val = temp_chan_val * 10; | ||
| 847 | return IIO_VAL_INT; | ||
| 773 | case IIO_PRESSURE: | 848 | case IIO_PRESSURE: |
| 774 | return bme680_read_press(data, val, val2); | 849 | ret = bme680_read_press(data, &chan_val); |
| 850 | if (ret) | ||
| 851 | return ret; | ||
| 852 | |||
| 853 | *val = chan_val; | ||
| 854 | *val2 = 1000; | ||
| 855 | return IIO_VAL_FRACTIONAL; | ||
| 775 | case IIO_HUMIDITYRELATIVE: | 856 | case IIO_HUMIDITYRELATIVE: |
| 776 | return bme680_read_humid(data, val, val2); | 857 | ret = bme680_read_humid(data, &chan_val); |
| 858 | if (ret) | ||
| 859 | return ret; | ||
| 860 | |||
| 861 | *val = chan_val; | ||
| 862 | *val2 = 1000; | ||
| 863 | return IIO_VAL_FRACTIONAL; | ||
| 777 | case IIO_RESISTANCE: | 864 | case IIO_RESISTANCE: |
| 778 | return bme680_read_gas(data, val); | 865 | ret = bme680_read_gas(data, &chan_val); |
| 866 | if (ret) | ||
| 867 | return ret; | ||
| 868 | |||
| 869 | *val = chan_val; | ||
| 870 | return IIO_VAL_INT; | ||
| 871 | default: | ||
| 872 | return -EINVAL; | ||
| 873 | } | ||
| 874 | case IIO_CHAN_INFO_RAW: | ||
| 875 | switch (chan->type) { | ||
| 876 | case IIO_TEMP: | ||
| 877 | ret = bme680_read_temp(data, (s16 *)&chan_val); | ||
| 878 | if (ret) | ||
| 879 | return ret; | ||
| 880 | |||
| 881 | *val = chan_val; | ||
| 882 | return IIO_VAL_INT; | ||
| 883 | case IIO_PRESSURE: | ||
| 884 | ret = bme680_read_press(data, &chan_val); | ||
| 885 | if (ret) | ||
| 886 | return ret; | ||
| 887 | |||
| 888 | *val = chan_val; | ||
| 889 | return IIO_VAL_INT; | ||
| 890 | case IIO_HUMIDITYRELATIVE: | ||
| 891 | ret = bme680_read_humid(data, &chan_val); | ||
| 892 | if (ret) | ||
| 893 | return ret; | ||
| 894 | |||
| 895 | *val = chan_val; | ||
| 896 | return IIO_VAL_INT; | ||
| 897 | default: | ||
| 898 | return -EINVAL; | ||
| 899 | } | ||
| 900 | case IIO_CHAN_INFO_SCALE: | ||
| 901 | switch (chan->type) { | ||
| 902 | case IIO_TEMP: | ||
| 903 | *val = 10; | ||
| 904 | return IIO_VAL_INT; | ||
| 905 | case IIO_PRESSURE: | ||
| 906 | *val = 1; | ||
| 907 | *val2 = 1000; | ||
| 908 | return IIO_VAL_FRACTIONAL; | ||
| 909 | case IIO_HUMIDITYRELATIVE: | ||
| 910 | *val = 1; | ||
| 911 | *val2 = 1000; | ||
| 912 | return IIO_VAL_FRACTIONAL; | ||
| 779 | default: | 913 | default: |
| 780 | return -EINVAL; | 914 | return -EINVAL; |
| 781 | } | 915 | } |
| @@ -836,6 +970,15 @@ static int bme680_write_raw(struct iio_dev *indio_dev, · 54 unmodified lines | |||
| 836 | 970 | ||
| 837 | return bme680_chip_config(data); | 971 | return bme680_chip_config(data); |
| 838 | } | 972 | } |
| 973 | case IIO_CHAN_INFO_PROCESSED: | ||
| 974 | { | ||
| 975 | switch (chan->type) { | ||
| 976 | case IIO_CURRENT: | ||
| 977 | return bme680_preheat_curr_config(data, (u8)val); | ||
| 978 | default: | ||
| 979 | return -EINVAL; | ||
| 980 | } | ||
| 981 | } | ||
| 839 | default: | 982 | default: |
| 840 | return -EINVAL; | 983 | return -EINVAL; |
| 841 | } | 984 | } |
| @@ -861,6 +1004,86 @@ static const struct iio_info bme680_info = { · 19 unmodified lines | |||
| 861 | .attrs = &bme680_attribute_group, | 1004 | .attrs = &bme680_attribute_group, |
| 862 | }; | 1005 | }; |
| 863 | 1006 | ||
| 1007 | static const unsigned long bme680_avail_scan_masks[] = { | ||
| 1008 | BIT(BME680_GAS) | BIT(BME680_HUMID) | BIT(BME680_PRESS) | BIT(BME680_TEMP), | ||
| 1009 | 0 | ||
| 1010 | }; | ||
| 1011 | |||
| 1012 | static irqreturn_t bme680_trigger_handler(int irq, void *p) | ||
| 1013 | { | ||
| 1014 | struct iio_poll_func *pf = p; | ||
| 1015 | struct iio_dev *indio_dev = pf->indio_dev; | ||
| 1016 | struct bme680_data *data = iio_priv(indio_dev); | ||
| 1017 | struct device *dev = regmap_get_device(data->regmap); | ||
| 1018 | u32 adc_temp, adc_press, adc_humid; | ||
| 1019 | u16 adc_gas_res, gas_regs_val; | ||
| 1020 | u8 gas_range; | ||
| 1021 | s32 t_fine; | ||
| 1022 | int ret; | ||
| 1023 | |||
| 1024 | guard(mutex)(&data->lock); | ||
| 1025 | |||
| 1026 | ret = bme680_set_mode(data, BME680_MODE_FORCED); | ||
| 1027 | if (ret < 0) | ||
| 1028 | goto out; | ||
| 1029 | |||
| 1030 | ret = bme680_wait_for_eoc(data); | ||
| 1031 | if (ret) | ||
| 1032 | goto out; | ||
| 1033 | |||
| 1034 | ret = regmap_bulk_read(data->regmap, BME680_REG_MEAS_STAT_0, | ||
| 1035 | data->buf, sizeof(data->buf)); | ||
| 1036 | if (ret) { | ||
| 1037 | dev_err(dev, "failed to burst read sensor data\n"); | ||
| 1038 | goto out; | ||
| 1039 | } | ||
| 1040 | if (data->buf[0] & BME680_GAS_MEAS_BIT) { | ||
| 1041 | dev_err(dev, "gas measurement incomplete\n"); | ||
| 1042 | goto out; | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | /* Temperature calculations */ | ||
| 1046 | adc_temp = FIELD_GET(BME680_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[5])); | ||
| 1047 | if (adc_temp == BME680_MEAS_SKIPPED) { | ||
| 1048 | dev_err(dev, "reading temperature skipped\n"); | ||
| 1049 | goto out; | ||
| 1050 | } | ||
| 1051 | data->scan.chan[0] = bme680_compensate_temp(data, adc_temp); | ||
| 1052 | t_fine = bme680_calc_t_fine(data, adc_temp); | ||
| 1053 | |||
| 1054 | /* Pressure calculations */ | ||
| 1055 | adc_press = FIELD_GET(BME680_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[2])); | ||
| 1056 | if (adc_press == BME680_MEAS_SKIPPED) { | ||
| 1057 | dev_err(dev, "reading pressure skipped\n"); | ||
| 1058 | goto out; | ||
| 1059 | } | ||
| 1060 | data->scan.chan[1] = bme680_compensate_press(data, adc_press, t_fine); | ||
| 1061 | |||
| 1062 | /* Humidity calculations */ | ||
| 1063 | adc_humid = get_unaligned_be16(&data->buf[8]); | ||
| 1064 | if (adc_humid == BME680_MEAS_SKIPPED) { | ||
| 1065 | dev_err(dev, "reading humidity skipped\n"); | ||
| 1066 | goto out; | ||
| 1067 | } | ||
| 1068 | data->scan.chan[2] = bme680_compensate_humid(data, adc_humid, t_fine); | ||
| 1069 | |||
| 1070 | /* Gas calculations */ | ||
| 1071 | gas_regs_val = get_unaligned_be16(&data->buf[13]); | ||
| 1072 | adc_gas_res = FIELD_GET(BME680_ADC_GAS_RES, gas_regs_val); | ||
| 1073 | if ((gas_regs_val & BME680_GAS_STAB_BIT) == 0) { | ||
| 1074 | dev_err(dev, "heater failed to reach the target temperature\n"); | ||
| 1075 | goto out; | ||
| 1076 | } | ||
| 1077 | gas_range = FIELD_GET(BME680_GAS_RANGE_MASK, gas_regs_val); | ||
| 1078 | data->scan.chan[3] = bme680_compensate_gas(data, adc_gas_res, gas_range); | ||
| 1079 | |||
| 1080 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, | ||
| 1081 | iio_get_time_ns(indio_dev)); | ||
| 1082 | out: | ||
| 1083 | iio_trigger_notify_done(indio_dev->trig); | ||
| 1084 | return IRQ_HANDLED; | ||
| 1085 | } | ||
| 1086 | |||
| 864 | int bme680_core_probe(struct device *dev, struct regmap *regmap, | 1087 | int bme680_core_probe(struct device *dev, struct regmap *regmap, |
| 865 | const char *name) | 1088 | const char *name) |
| 866 | { | 1089 | { |
| @@ -879,6 +1102,7 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap, · 12 unmodified lines | |||
| 879 | indio_dev->name = name; | 1102 | indio_dev->name = name; |
| 880 | indio_dev->channels = bme680_channels; | 1103 | indio_dev->channels = bme680_channels; |
| 881 | indio_dev->num_channels = ARRAY_SIZE(bme680_channels); | 1104 | indio_dev->num_channels = ARRAY_SIZE(bme680_channels); |
| 1105 | indio_dev->available_scan_masks = bme680_avail_scan_masks; | ||
| 882 | indio_dev->info = &bme680_info; | 1106 | indio_dev->info = &bme680_info; |
| 883 | indio_dev->modes = INDIO_DIRECT_MODE; | 1107 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 884 | 1108 | ||
| @@ -888,13 +1112,13 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap, · 3 unmodified lines | |||
| 888 | data->oversampling_temp = 8; /* 8X oversampling rate */ | 1112 | data->oversampling_temp = 8; /* 8X oversampling rate */ |
| 889 | data->heater_temp = 320; /* degree Celsius */ | 1113 | data->heater_temp = 320; /* degree Celsius */ |
| 890 | data->heater_dur = 150; /* milliseconds */ | 1114 | data->heater_dur = 150; /* milliseconds */ |
| 1115 | data->preheat_curr_mA = 0; | ||
| 891 | 1116 | ||
| 892 | ret = regmap_write(regmap, BME680_REG_SOFT_RESET, | 1117 | ret = regmap_write(regmap, BME680_REG_SOFT_RESET, BME680_CMD_SOFTRESET); |
| 893 | BME680_CMD_SOFTRESET); | ||
| 894 | if (ret < 0) | 1118 | if (ret < 0) |
| 895 | return dev_err_probe(dev, ret, "Failed to reset chip\n"); | 1119 | return dev_err_probe(dev, ret, "Failed to reset chip\n"); |
| 896 | 1120 | ||
| 897 | usleep_range(BME680_STARTUP_TIME_US, BME680_STARTUP_TIME_US + 1000); | 1121 | fsleep(BME680_STARTUP_TIME_US); |
| 898 | 1122 | ||
| 899 | ret = regmap_read(regmap, BME680_REG_CHIP_ID, &data->check); | 1123 | ret = regmap_read(regmap, BME680_REG_CHIP_ID, &data->check); |
| 900 | if (ret < 0) | 1124 | if (ret < 0) |
| @@ -922,6 +1146,14 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap, · 21 unmodified lines | |||
| 922 | return dev_err_probe(dev, ret, | 1146 | return dev_err_probe(dev, ret, |
| 923 | "failed to set gas config data\n"); | 1147 | "failed to set gas config data\n"); |
| 924 | 1148 | ||
| 1149 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, | ||
| 1150 | iio_pollfunc_store_time, | ||
| 1151 | bme680_trigger_handler, | ||
| 1152 | NULL); | ||
| 1153 | if (ret) | ||
| 1154 | return dev_err_probe(dev, ret, | ||
| 1155 | "iio triggered buffer setup failed\n"); | ||
| 1156 | |||
| 925 | return devm_iio_device_register(dev, indio_dev); | 1157 | return devm_iio_device_register(dev, indio_dev); |
| 926 | } | 1158 | } |
| 927 | EXPORT_SYMBOL_NS_GPL(bme680_core_probe, IIO_BME680); | 1159 | EXPORT_SYMBOL_NS_GPL(bme680_core_probe, IIO_BME680); |
| @@ -70,6 +70,10 @@ int inv_sensors_timestamp_update_odr(struct inv_sensors_timestamp *ts, · 69 unmodified lines | |||
| 70 | if (mult != ts->mult) | 70 | if (mult != ts->mult) |
| 71 | ts->new_mult = mult; | 71 | ts->new_mult = mult; |
| 72 | 72 | ||
| 73 | /* When FIFO is off, directly apply the new ODR */ | ||
| 74 | if (!fifo) | ||
| 75 | inv_sensors_timestamp_apply_odr(ts, 0, 0, 0); | ||
| 76 | |||
| 73 | return 0; | 77 | return 0; |
| 74 | } | 78 | } |
| 75 | EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_update_odr, IIO_INV_SENSORS_TIMESTAMP); | 79 | EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_update_odr, IIO_INV_SENSORS_TIMESTAMP); |
| @@ -134,11 +134,11 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, · 133 unmodified lines | |||
| 134 | iio_trigger_set_drvdata(sdata->trig, indio_dev); | 134 | iio_trigger_set_drvdata(sdata->trig, indio_dev); |
| 135 | sdata->trig->ops = trigger_ops; | 135 | sdata->trig->ops = trigger_ops; |
| 136 | 136 | ||
| 137 | irq_trig = irqd_get_trigger_type(irq_get_irq_data(sdata->irq)); | ||
| 138 | /* | 137 | /* |
| 139 | * If the IRQ is triggered on falling edge, we need to mark the | 138 | * If the IRQ is triggered on falling edge, we need to mark the |
| 140 | * interrupt as active low, if the hardware supports this. | 139 | * interrupt as active low, if the hardware supports this. |
| 141 | */ | 140 | */ |
| 141 | irq_trig = irq_get_trigger_type(sdata->irq); | ||
| 142 | switch(irq_trig) { | 142 | switch(irq_trig) { |
| 143 | case IRQF_TRIGGER_FALLING: | 143 | case IRQF_TRIGGER_FALLING: |
| 144 | case IRQF_TRIGGER_LOW: | 144 | case IRQF_TRIGGER_LOW: |
| @@ -6,9 +6,28 @@ · 5 unmodified lines | |||
| 6 | 6 | ||
| 7 | menu "Digital to analog converters" | 7 | menu "Digital to analog converters" |
| 8 | 8 | ||
| 9 | config AD3552R_HS | ||
| 10 | tristate "Analog Devices AD3552R DAC High Speed driver" | ||
| 11 | select AD3552R_LIB | ||
| 12 | select IIO_BACKEND | ||
| 13 | help | ||
| 14 | Say yes here to build support for Analog Devices AD3552R | ||
| 15 | Digital to Analog Converter High Speed driver. | ||
| 16 | |||
| 17 | The driver requires the assistance of an IP core to operate, | ||
| 18 | since data is streamed into target device via DMA, sent over a | ||
| 19 | QSPI + DDR (Double Data Rate) bus. | ||
| 20 | |||
| 21 | To compile this driver as a module, choose M here: the | ||
| 22 | module will be called ad3552r-hs. | ||
| 23 | |||
| 24 | config AD3552R_LIB | ||
| 25 | tristate | ||
| 26 | |||
| 9 | config AD3552R | 27 | config AD3552R |
| 10 | tristate "Analog Devices AD3552R DAC driver" | 28 | tristate "Analog Devices AD3552R DAC driver" |
| 11 | depends on SPI_MASTER | 29 | depends on SPI_MASTER |
| 30 | select AD3552R_LIB | ||
| 12 | select IIO_BUFFER | 31 | select IIO_BUFFER |
| 13 | select IIO_TRIGGERED_BUFFER | 32 | select IIO_TRIGGERED_BUFFER |
| 14 | help | 33 | help |
| @@ -306,6 +325,19 @@ config AD7303 · 291 unmodified lines | |||
| 306 | To compile this driver as module choose M here: the module will be called | 325 | To compile this driver as module choose M here: the module will be called |
| 307 | ad7303. | 326 | ad7303. |
| 308 | 327 | ||
| 328 | config AD8460 | ||
| 329 | tristate "Analog Devices AD8460 DAC driver" | ||
| 330 | depends on SPI | ||
| 331 | select REGMAP_SPI | ||
| 332 | select IIO_BUFFER | ||
| 333 | select IIO_BUFFER_DMAENGINE | ||
| 334 | help | ||
| 335 | Say yes here to build support for Analog Devices AD8460 Digital to | ||
| 336 | Analog Converters (DAC). | ||
| 337 | |||
| 338 | To compile this driver as a module choose M here: the module will be called | ||
| 339 | ad8460. | ||
| 340 | |||
| 309 | config AD8801 | 341 | config AD8801 |
| 310 | tristate "Analog Devices AD8801/AD8803 DAC driver" | 342 | tristate "Analog Devices AD8801/AD8803 DAC driver" |
| 311 | depends on SPI_MASTER | 343 | depends on SPI_MASTER |
| @@ -4,6 +4,8 @@ · 3 unmodified lines | |||
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | # When adding new entries keep the list in alphabetical order | 6 | # When adding new entries keep the list in alphabetical order |
| 7 | obj-$(CONFIG_AD3552R_HS) += ad3552r-hs.o | ||
| 8 | obj-$(CONFIG_AD3552R_LIB) += ad3552r-common.o | ||
| 7 | obj-$(CONFIG_AD3552R) += ad3552r.o | 9 | obj-$(CONFIG_AD3552R) += ad3552r.o |
| 8 | obj-$(CONFIG_AD5360) += ad5360.o | 10 | obj-$(CONFIG_AD5360) += ad5360.o |
| 9 | obj-$(CONFIG_AD5380) += ad5380.o | 11 | obj-$(CONFIG_AD5380) += ad5380.o |
| @@ -28,6 +30,7 @@ obj-$(CONFIG_AD5686_SPI) += ad5686-spi.o · 18 unmodified lines | |||
| 28 | obj-$(CONFIG_AD5696_I2C) += ad5696-i2c.o | 30 | obj-$(CONFIG_AD5696_I2C) += ad5696-i2c.o |
| 29 | obj-$(CONFIG_AD7293) += ad7293.o | 31 | obj-$(CONFIG_AD7293) += ad7293.o |
| 30 | obj-$(CONFIG_AD7303) += ad7303.o | 32 | obj-$(CONFIG_AD7303) += ad7303.o |
| 33 | obj-$(CONFIG_AD8460) += ad8460.o | ||
| 31 | obj-$(CONFIG_AD8801) += ad8801.o | 34 | obj-$(CONFIG_AD8801) += ad8801.o |
| 32 | obj-$(CONFIG_AD9739A) += ad9739a.o | 35 | obj-$(CONFIG_AD9739A) += ad9739a.o |
| 33 | obj-$(CONFIG_ADI_AXI_DAC) += adi-axi-dac.o | 36 | obj-$(CONFIG_ADI_AXI_DAC) += adi-axi-dac.o |
| @@ -0,0 +1,249 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | // | ||
| 3 | // Copyright (c) 2010-2024 Analog Devices Inc. | ||
| 4 | // Copyright (c) 2024 Baylibre, SAS | ||
| 5 | |||
| 6 | #include <linux/bitfield.h> | ||
| 7 | #include <linux/device.h> | ||
| 8 | #include <linux/module.h> | ||
| 9 | #include <linux/property.h> | ||
| 10 | #include <linux/regulator/consumer.h> | ||
| 11 | |||
| 12 | #include "ad3552r.h" | ||
| 13 | |||
| 14 | const s32 ad3552r_ch_ranges[AD3552R_MAX_RANGES][2] = { | ||
| 15 | [AD3552R_CH_OUTPUT_RANGE_0__2P5V] = { 0, 2500 }, | ||
| 16 | [AD3552R_CH_OUTPUT_RANGE_0__5V] = { 0, 5000 }, | ||
| 17 | [AD3552R_CH_OUTPUT_RANGE_0__10V] = { 0, 10000 }, | ||
| 18 | [AD3552R_CH_OUTPUT_RANGE_NEG_5__5V] = { -5000, 5000 }, | ||
| 19 | [AD3552R_CH_OUTPUT_RANGE_NEG_10__10V] = { -10000, 10000 } | ||
| 20 | }; | ||
| 21 | EXPORT_SYMBOL_NS_GPL(ad3552r_ch_ranges, IIO_AD3552R); | ||
| 22 | |||
| 23 | const s32 ad3542r_ch_ranges[AD3542R_MAX_RANGES][2] = { | ||
| 24 | [AD3542R_CH_OUTPUT_RANGE_0__2P5V] = { 0, 2500 }, | ||
| 25 | [AD3542R_CH_OUTPUT_RANGE_0__3V] = { 0, 3000 }, | ||
| 26 | [AD3542R_CH_OUTPUT_RANGE_0__5V] = { 0, 5000 }, | ||
| 27 | [AD3542R_CH_OUTPUT_RANGE_0__10V] = { 0, 10000 }, | ||
| 28 | [AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V] = { -2500, 7500 }, | ||
| 29 | [AD3542R_CH_OUTPUT_RANGE_NEG_5__5V] = { -5000, 5000 } | ||
| 30 | }; | ||
| 31 | EXPORT_SYMBOL_NS_GPL(ad3542r_ch_ranges, IIO_AD3552R); | ||
| 32 | |||
| 33 | /* Gain * AD3552R_GAIN_SCALE */ | ||
| 34 | static const s32 gains_scaling_table[] = { | ||
| 35 | [AD3552R_CH_GAIN_SCALING_1] = 1000, | ||
| 36 | [AD3552R_CH_GAIN_SCALING_0_5] = 500, | ||
| 37 | [AD3552R_CH_GAIN_SCALING_0_25] = 250, | ||
| 38 | [AD3552R_CH_GAIN_SCALING_0_125] = 125 | ||
| 39 | }; | ||
| 40 | |||
| 41 | u16 ad3552r_calc_custom_gain(u8 p, u8 n, s16 goffs) | ||
| 42 | { | ||
| 43 | return FIELD_PREP(AD3552R_MASK_CH_RANGE_OVERRIDE, 1) | | ||
| 44 | FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_P, p) | | ||
| 45 | FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_N, n) | | ||
| 46 | FIELD_PREP(AD3552R_MASK_CH_OFFSET_BIT_8, abs(goffs)) | | ||
| 47 | FIELD_PREP(AD3552R_MASK_CH_OFFSET_POLARITY, goffs < 0); | ||
| 48 | } | ||
| 49 | EXPORT_SYMBOL_NS_GPL(ad3552r_calc_custom_gain, IIO_AD3552R); | ||
| 50 | |||
| 51 | static void ad3552r_get_custom_range(struct ad3552r_ch_data *ch_data, | ||
| 52 | s32 *v_min, s32 *v_max) | ||
| 53 | { | ||
| 54 | s64 vref, tmp, common, offset, gn, gp; | ||
| 55 | /* | ||
| 56 | * From datasheet formula (In Volts): | ||
| 57 | * Vmin = 2.5 + [(GainN + Offset / 1024) * 2.5 * Rfb * 1.03] | ||
| 58 | * Vmax = 2.5 - [(GainP + Offset / 1024) * 2.5 * Rfb * 1.03] | ||
| 59 | * Calculus are converted to milivolts | ||
| 60 | */ | ||
| 61 | vref = 2500; | ||
| 62 | /* 2.5 * 1.03 * 1000 (To mV) */ | ||
| 63 | common = 2575 * ch_data->rfb; | ||
| 64 | offset = ch_data->gain_offset; | ||
| 65 | |||
| 66 | gn = gains_scaling_table[ch_data->n]; | ||
| 67 | tmp = (1024 * gn + AD3552R_GAIN_SCALE * offset) * common; | ||
| 68 | tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE); | ||
| 69 | *v_max = vref + tmp; | ||
| 70 | |||
| 71 | gp = gains_scaling_table[ch_data->p]; | ||
| 72 | tmp = (1024 * gp - AD3552R_GAIN_SCALE * offset) * common; | ||
| 73 | tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE); | ||
| 74 | *v_min = vref - tmp; | ||
| 75 | } | ||
| 76 | |||
| 77 | void ad3552r_calc_gain_and_offset(struct ad3552r_ch_data *ch_data, | ||
| 78 | const struct ad3552r_model_data *model_data) | ||
| 79 | { | ||
| 80 | s32 idx, v_max, v_min, span, rem; | ||
| 81 | s64 tmp; | ||
| 82 | |||
| 83 | if (ch_data->range_override) { | ||
| 84 | ad3552r_get_custom_range(ch_data, &v_min, &v_max); | ||
| 85 | } else { | ||
| 86 | /* Normal range */ | ||
| 87 | idx = ch_data->range; | ||
| 88 | v_min = model_data->ranges_table[idx][0]; | ||
| 89 | v_max = model_data->ranges_table[idx][1]; | ||
| 90 | } | ||
| 91 | |||
| 92 | /* | ||
| 93 | * From datasheet formula: | ||
| 94 | * Vout = Span * (D / 65536) + Vmin | ||
| 95 | * Converted to scale and offset: | ||
| 96 | * Scale = Span / 65536 | ||
| 97 | * Offset = 65536 * Vmin / Span | ||
| 98 | * | ||
| 99 | * Reminders are in micros in order to be printed as | ||
| 100 | * IIO_VAL_INT_PLUS_MICRO | ||
| 101 | */ | ||
| 102 | span = v_max - v_min; | ||
| 103 | ch_data->scale_int = div_s64_rem(span, 65536, &rem); | ||
| 104 | /* Do operations in microvolts */ | ||
| 105 | ch_data->scale_dec = DIV_ROUND_CLOSEST((s64)rem * 1000000, 65536); | ||
| 106 | |||
| 107 | ch_data->offset_int = div_s64_rem(v_min * 65536, span, &rem); | ||
| 108 | tmp = (s64)rem * 1000000; | ||
| 109 | ch_data->offset_dec = div_s64(tmp, span); | ||
| 110 | } | ||
| 111 | EXPORT_SYMBOL_NS_GPL(ad3552r_calc_gain_and_offset, IIO_AD3552R); | ||
| 112 | |||
| 113 | int ad3552r_get_ref_voltage(struct device *dev, u32 *val) | ||
| 114 | { | ||
| 115 | int voltage; | ||
| 116 | int delta = 100000; | ||
| 117 | |||
| 118 | voltage = devm_regulator_get_enable_read_voltage(dev, "vref"); | ||
| 119 | if (voltage < 0 && voltage != -ENODEV) | ||
| 120 | return dev_err_probe(dev, voltage, | ||
| 121 | "Error getting vref voltage\n"); | ||
| 122 | |||
| 123 | if (voltage == -ENODEV) { | ||
| 124 | if (device_property_read_bool(dev, "adi,vref-out-en")) | ||
| 125 | *val = AD3552R_INTERNAL_VREF_PIN_2P5V; | ||
| 126 | else | ||
| 127 | *val = AD3552R_INTERNAL_VREF_PIN_FLOATING; | ||
| 128 | |||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | if (voltage > 2500000 + delta || voltage < 2500000 - delta) { | ||
| 133 | dev_warn(dev, "vref-supply must be 2.5V"); | ||
| 134 | return -EINVAL; | ||
| 135 | } | ||
| 136 | |||
| 137 | *val = AD3552R_EXTERNAL_VREF_PIN_INPUT; | ||
| 138 | |||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | EXPORT_SYMBOL_NS_GPL(ad3552r_get_ref_voltage, IIO_AD3552R); | ||
| 142 | |||
| 143 | int ad3552r_get_drive_strength(struct device *dev, u32 *val) | ||
| 144 | { | ||
| 145 | int err; | ||
| 146 | u32 drive_strength; | ||
| 147 | |||
| 148 | err = device_property_read_u32(dev, "adi,sdo-drive-strength", | ||
| 149 | &drive_strength); | ||
| 150 | if (err) | ||
| 151 | return err; | ||
| 152 | |||
| 153 | if (drive_strength > 3) { | ||
| 154 | dev_err_probe(dev, -EINVAL, | ||
| 155 | "adi,sdo-drive-strength must be less than 4\n"); | ||
| 156 | return -EINVAL; | ||
| 157 | } | ||
| 158 | |||
| 159 | *val = drive_strength; | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | EXPORT_SYMBOL_NS_GPL(ad3552r_get_drive_strength, IIO_AD3552R); | ||
| 164 | |||
| 165 | int ad3552r_get_custom_gain(struct device *dev, struct fwnode_handle *child, | ||
| 166 | u8 *gs_p, u8 *gs_n, u16 *rfb, s16 *goffs) | ||
| 167 | { | ||
| 168 | int err; | ||
| 169 | u32 val; | ||
| 170 | struct fwnode_handle *gain_child __free(fwnode_handle) = | ||
| 171 | fwnode_get_named_child_node(child, | ||
| 172 | "custom-output-range-config"); | ||
| 173 | |||
| 174 | if (!gain_child) | ||
| 175 | return dev_err_probe(dev, -EINVAL, | ||
| 176 | "custom-output-range-config mandatory\n"); | ||
| 177 | |||
| 178 | err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val); | ||
| 179 | if (err) | ||
| 180 | return dev_err_probe(dev, err, | ||
| 181 | "adi,gain-scaling-p mandatory\n"); | ||
| 182 | *gs_p = val; | ||
| 183 | |||
| 184 | err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val); | ||
| 185 | if (err) | ||
| 186 | return dev_err_probe(dev, err, | ||
| 187 | "adi,gain-scaling-n property mandatory\n"); | ||
| 188 | *gs_n = val; | ||
| 189 | |||
| 190 | err = fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val); | ||
| 191 | if (err) | ||
| 192 | return dev_err_probe(dev, err, | ||
| 193 | "adi,rfb-ohms mandatory\n"); | ||
| 194 | *rfb = val; | ||
| 195 | |||
| 196 | err = fwnode_property_read_u32(gain_child, "adi,gain-offset", &val); | ||
| 197 | if (err) | ||
| 198 | return dev_err_probe(dev, err, | ||
| 199 | "adi,gain-offset mandatory\n"); | ||
| 200 | *goffs = val; | ||
| 201 | |||
| 202 | return 0; | ||
| 203 | } | ||
| 204 | EXPORT_SYMBOL_NS_GPL(ad3552r_get_custom_gain, IIO_AD3552R); | ||
| 205 | |||
| 206 | static int ad3552r_find_range(const struct ad3552r_model_data *model_info, | ||
| 207 | s32 *vals) | ||
| 208 | { | ||
| 209 | int i; | ||
| 210 | |||
| 211 | for (i = 0; i < model_info->num_ranges; i++) | ||
| 212 | if (vals[0] == model_info->ranges_table[i][0] * 1000 && | ||
| 213 | vals[1] == model_info->ranges_table[i][1] * 1000) | ||
| 214 | return i; | ||
| 215 | |||
| 216 | return -EINVAL; | ||
| 217 | } | ||
| 218 | |||
| 219 | int ad3552r_get_output_range(struct device *dev, | ||
| 220 | const struct ad3552r_model_data *model_info, | ||
| 221 | struct fwnode_handle *child, u32 *val) | ||
| 222 | { | ||
| 223 | int ret; | ||
| 224 | s32 vals[2]; | ||
| 225 | |||
| 226 | /* This property is optional, so returning -ENOENT if missing */ | ||
| 227 | if (!fwnode_property_present(child, "adi,output-range-microvolt")) | ||
| 228 | return -ENOENT; | ||
| 229 | |||
| 230 | ret = fwnode_property_read_u32_array(child, | ||
| 231 | "adi,output-range-microvolt", | ||
| 232 | vals, 2); | ||
| 233 | if (ret) | ||
| 234 | return dev_err_probe(dev, ret, | ||
| 235 | "invalid adi,output-range-microvolt\n"); | ||
| 236 | |||
| 237 | ret = ad3552r_find_range(model_info, vals); | ||
| 238 | if (ret < 0) | ||
| 239 | return dev_err_probe(dev, ret, | ||
| 240 | "invalid adi,output-range-microvolt value\n"); | ||
| 241 | |||
| 242 | *val = ret; | ||
| 243 | |||
| 244 | return 0; | ||
| 245 | } | ||
| 246 | EXPORT_SYMBOL_NS_GPL(ad3552r_get_output_range, IIO_AD3552R); | ||
| 247 | |||
| 248 | MODULE_DESCRIPTION("ad3552r common functions"); | ||
| 249 | MODULE_LICENSE("GPL"); | ||
| @@ -0,0 +1,529 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Analog Devices AD3552R | ||
| 4 | * Digital to Analog converter driver, High Speed version | ||
| 5 | * | ||
| 6 | * Copyright 2024 Analog Devices Inc. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/bitfield.h> | ||
| 10 | #include <linux/delay.h> | ||
| 11 | #include <linux/gpio/consumer.h> | ||
| 12 | #include <linux/iio/backend.h> | ||
| 13 | #include <linux/iio/buffer.h> | ||
| 14 | #include <linux/mod_devicetable.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/property.h> | ||
| 17 | #include <linux/units.h> | ||
| 18 | |||
| 19 | #include "ad3552r.h" | ||
| 20 | #include "ad3552r-hs.h" | ||
| 21 | |||
| 22 | struct ad3552r_hs_state { | ||
| 23 | const struct ad3552r_model_data *model_data; | ||
| 24 | struct gpio_desc *reset_gpio; | ||
| 25 | struct device *dev; | ||
| 26 | struct iio_backend *back; | ||
| 27 | bool single_channel; | ||
| 28 | struct ad3552r_ch_data ch_data[AD3552R_MAX_CH]; | ||
| 29 | struct ad3552r_hs_platform_data *data; | ||
| 30 | }; | ||
| 31 | |||
| 32 | static int ad3552r_qspi_update_reg_bits(struct ad3552r_hs_state *st, | ||
| 33 | u32 reg, u32 mask, u32 val, | ||
| 34 | size_t xfer_size) | ||
| 35 | { | ||
| 36 | u32 rval; | ||
| 37 | int ret; | ||
| 38 | |||
| 39 | ret = st->data->bus_reg_read(st->back, reg, &rval, xfer_size); | ||
| 40 | if (ret) | ||
| 41 | return ret; | ||
| 42 | |||
| 43 | rval = (rval & ~mask) | val; | ||
| 44 | |||
| 45 | return st->data->bus_reg_write(st->back, reg, rval, xfer_size); | ||
| 46 | } | ||
| 47 | |||
| 48 | static int ad3552r_hs_read_raw(struct iio_dev *indio_dev, | ||
| 49 | struct iio_chan_spec const *chan, | ||
| 50 | int *val, int *val2, long mask) | ||
| 51 | { | ||
| 52 | struct ad3552r_hs_state *st = iio_priv(indio_dev); | ||
| 53 | int ret; | ||
| 54 | int ch = chan->channel; | ||
| 55 | |||
| 56 | switch (mask) { | ||
| 57 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 58 | /* | ||
| 59 | * Using 4 lanes (QSPI), then using 2 as DDR mode is | ||
| 60 | * considered always on (considering buffering mode always). | ||
| 61 | */ | ||
| 62 | *val = DIV_ROUND_CLOSEST(st->data->bus_sample_data_clock_hz * | ||
| 63 | 4 * 2, chan->scan_type.realbits); | ||
| 64 | |||
| 65 | return IIO_VAL_INT; | ||
| 66 | |||
| 67 | case IIO_CHAN_INFO_RAW: | ||
| 68 | ret = st->data->bus_reg_read(st->back, | ||
| 69 | AD3552R_REG_ADDR_CH_DAC_16B(chan->channel), | ||
| 70 | val, 2); | ||
| 71 | if (ret) | ||
| 72 | return ret; | ||
| 73 | |||
| 74 | return IIO_VAL_INT; | ||
| 75 | case IIO_CHAN_INFO_SCALE: | ||
| 76 | *val = st->ch_data[ch].scale_int; | ||
| 77 | *val2 = st->ch_data[ch].scale_dec; | ||
| 78 | return IIO_VAL_INT_PLUS_MICRO; | ||
| 79 | case IIO_CHAN_INFO_OFFSET: | ||
| 80 | *val = st->ch_data[ch].offset_int; | ||
| 81 | *val2 = st->ch_data[ch].offset_dec; | ||
| 82 | return IIO_VAL_INT_PLUS_MICRO; | ||
| 83 | default: | ||
| 84 | return -EINVAL; | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | static int ad3552r_hs_write_raw(struct iio_dev *indio_dev, | ||
| 89 | struct iio_chan_spec const *chan, | ||
| 90 | int val, int val2, long mask) | ||
| 91 | { | ||
| 92 | struct ad3552r_hs_state *st = iio_priv(indio_dev); | ||
| 93 | |||
| 94 | switch (mask) { | ||
| 95 | case IIO_CHAN_INFO_RAW: | ||
| 96 | iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { | ||
| 97 | return st->data->bus_reg_write(st->back, | ||
| 98 | AD3552R_REG_ADDR_CH_DAC_16B(chan->channel), | ||
| 99 | val, 2); | ||
| 100 | } | ||
| 101 | unreachable(); | ||
| 102 | default: | ||
| 103 | return -EINVAL; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | static int ad3552r_hs_buffer_postenable(struct iio_dev *indio_dev) | ||
| 108 | { | ||
| 109 | struct ad3552r_hs_state *st = iio_priv(indio_dev); | ||
| 110 | struct iio_backend_data_fmt fmt = { | ||
| 111 | .type = IIO_BACKEND_DATA_UNSIGNED | ||
| 112 | }; | ||
| 113 | int loop_len, val, ret; | ||
| 114 | |||
| 115 | switch (*indio_dev->active_scan_mask) { | ||
| 116 | case AD3552R_CH0_ACTIVE: | ||
| 117 | st->single_channel = true; | ||
| 118 | loop_len = 2; | ||
| 119 | val = AD3552R_REG_ADDR_CH_DAC_16B(0); | ||
| 120 | break; | ||
| 121 | case AD3552R_CH1_ACTIVE: | ||
| 122 | st->single_channel = true; | ||
| 123 | loop_len = 2; | ||
| 124 | val = AD3552R_REG_ADDR_CH_DAC_16B(1); | ||
| 125 | break; | ||
| 126 | case AD3552R_CH0_ACTIVE | AD3552R_CH1_ACTIVE: | ||
| 127 | st->single_channel = false; | ||
| 128 | loop_len = 4; | ||
| 129 | val = AD3552R_REG_ADDR_CH_DAC_16B(1); | ||
| 130 | break; | ||
| 131 | default: | ||
| 132 | return -EINVAL; | ||
| 133 | } | ||
| 134 | |||
| 135 | ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_STREAM_MODE, | ||
| 136 | loop_len, 1); | ||
| 137 | if (ret) | ||
| 138 | return ret; | ||
| 139 | |||
| 140 | /* Inform DAC chip to switch into DDR mode */ | ||
| 141 | ret = ad3552r_qspi_update_reg_bits(st, | ||
| 142 | AD3552R_REG_ADDR_INTERFACE_CONFIG_D, | ||
| 143 | AD3552R_MASK_SPI_CONFIG_DDR, | ||
| 144 | AD3552R_MASK_SPI_CONFIG_DDR, 1); | ||
| 145 | if (ret) | ||
| 146 | return ret; | ||
| 147 | |||
| 148 | /* Inform DAC IP to go for DDR mode from now on */ | ||
| 149 | ret = iio_backend_ddr_enable(st->back); | ||
| 150 | if (ret) { | ||
| 151 | dev_err(st->dev, "could not set DDR mode, not streaming"); | ||
| 152 | goto exit_err; | ||
| 153 | } | ||
| 154 | |||
| 155 | ret = iio_backend_data_transfer_addr(st->back, val); | ||
| 156 | if (ret) | ||
| 157 | goto exit_err; | ||
| 158 | |||
| 159 | ret = iio_backend_data_format_set(st->back, 0, &fmt); | ||
| 160 | if (ret) | ||
| 161 | goto exit_err; | ||
| 162 | |||
| 163 | ret = iio_backend_data_stream_enable(st->back); | ||
| 164 | if (ret) | ||
| 165 | goto exit_err; | ||
| 166 | |||
| 167 | return 0; | ||
| 168 | |||
| 169 | exit_err: | ||
| 170 | ad3552r_qspi_update_reg_bits(st, | ||
| 171 | AD3552R_REG_ADDR_INTERFACE_CONFIG_D, | ||
| 172 | AD3552R_MASK_SPI_CONFIG_DDR, | ||
| 173 | 0, 1); | ||
| 174 | |||
| 175 | iio_backend_ddr_disable(st->back); | ||
| 176 | |||
| 177 | return ret; | ||
| 178 | } | ||
| 179 | |||
| 180 | static int ad3552r_hs_buffer_predisable(struct iio_dev *indio_dev) | ||
| 181 | { | ||
| 182 | struct ad3552r_hs_state *st = iio_priv(indio_dev); | ||
| 183 | int ret; | ||
| 184 | |||
| 185 | ret = iio_backend_data_stream_disable(st->back); | ||
| 186 | if (ret) | ||
| 187 | return ret; | ||
| 188 | |||
| 189 | /* Inform DAC to set in SDR mode */ | ||
| 190 | ret = ad3552r_qspi_update_reg_bits(st, | ||
| 191 | AD3552R_REG_ADDR_INTERFACE_CONFIG_D, | ||
| 192 | AD3552R_MASK_SPI_CONFIG_DDR, | ||
| 193 | 0, 1); | ||
| 194 | if (ret) | ||
| 195 | return ret; | ||
| 196 | |||
| 197 | ret = iio_backend_ddr_disable(st->back); | ||
| 198 | if (ret) | ||
| 199 | return ret; | ||
| 200 | |||
| 201 | return 0; | ||
| 202 | } | ||
| 203 | |||
| 204 | static inline int ad3552r_hs_set_output_range(struct ad3552r_hs_state *st, | ||
| 205 | int ch, unsigned int mode) | ||
| 206 | { | ||
| 207 | int val; | ||
| 208 | |||
| 209 | if (ch == 0) | ||
| 210 | val = FIELD_PREP(AD3552R_MASK_CH0_RANGE, mode); | ||
| 211 | else | ||
| 212 | val = FIELD_PREP(AD3552R_MASK_CH1_RANGE, mode); | ||
| 213 | |||
| 214 | return ad3552r_qspi_update_reg_bits(st, | ||
| 215 | AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE, | ||
| 216 | AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch), | ||
| 217 | val, 1); | ||
| 218 | } | ||
| 219 | |||
| 220 | static int ad3552r_hs_reset(struct ad3552r_hs_state *st) | ||
| 221 | { | ||
| 222 | int ret; | ||
| 223 | |||
| 224 | st->reset_gpio = devm_gpiod_get_optional(st->dev, | ||
| 225 | "reset", GPIOD_OUT_HIGH); | ||
| 226 | if (IS_ERR(st->reset_gpio)) | ||
| 227 | return PTR_ERR(st->reset_gpio); | ||
| 228 | |||
| 229 | if (st->reset_gpio) { | ||
| 230 | fsleep(10); | ||
| 231 | gpiod_set_value_cansleep(st->reset_gpio, 0); | ||
| 232 | } else { | ||
| 233 | ret = ad3552r_qspi_update_reg_bits(st, | ||
| 234 | AD3552R_REG_ADDR_INTERFACE_CONFIG_A, | ||
| 235 | AD3552R_MASK_SOFTWARE_RESET, | ||
| 236 | AD3552R_MASK_SOFTWARE_RESET, 1); | ||
| 237 | if (ret) | ||
| 238 | return ret; | ||
| 239 | } | ||
| 240 | msleep(100); | ||
| 241 | |||
| 242 | return 0; | ||
| 243 | } | ||
| 244 | |||
| 245 | static int ad3552r_hs_scratch_pad_test(struct ad3552r_hs_state *st) | ||
| 246 | { | ||
| 247 | int ret, val; | ||
| 248 | |||
| 249 | ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD, | ||
| 250 | AD3552R_SCRATCH_PAD_TEST_VAL1, 1); | ||
| 251 | if (ret) | ||
| 252 | return ret; | ||
| 253 | |||
| 254 | ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD, | ||
| 255 | &val, 1); | ||
| 256 | if (ret) | ||
| 257 | return ret; | ||
| 258 | |||
| 259 | if (val != AD3552R_SCRATCH_PAD_TEST_VAL1) | ||
| 260 | return dev_err_probe(st->dev, -EIO, | ||
| 261 | "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n", | ||
| 262 | AD3552R_SCRATCH_PAD_TEST_VAL1, val); | ||
| 263 | |||
| 264 | ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD, | ||
| 265 | AD3552R_SCRATCH_PAD_TEST_VAL2, 1); | ||
| 266 | if (ret) | ||
| 267 | return ret; | ||
| 268 | |||
| 269 | ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD, | ||
| 270 | &val, 1); | ||
| 271 | if (ret) | ||
| 272 | return ret; | ||
| 273 | |||
| 274 | if (val != AD3552R_SCRATCH_PAD_TEST_VAL2) | ||
| 275 | return dev_err_probe(st->dev, -EIO, | ||
| 276 | "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n", | ||
| 277 | AD3552R_SCRATCH_PAD_TEST_VAL2, val); | ||
| 278 | |||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | static int ad3552r_hs_setup_custom_gain(struct ad3552r_hs_state *st, | ||
| 283 | int ch, u16 gain, u16 offset) | ||
| 284 | { | ||
| 285 | int ret; | ||
| 286 | |||
| 287 | ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_CH_OFFSET(ch), | ||
| 288 | offset, 1); | ||
| 289 | if (ret) | ||
| 290 | return ret; | ||
| 291 | |||
| 292 | return st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_CH_GAIN(ch), | ||
| 293 | gain, 1); | ||
| 294 | } | ||
| 295 | |||
| 296 | static int ad3552r_hs_setup(struct ad3552r_hs_state *st) | ||
| 297 | { | ||
| 298 | u16 id; | ||
| 299 | u16 gain = 0, offset = 0; | ||
| 300 | u32 ch, val, range; | ||
| 301 | int ret; | ||
| 302 | |||
| 303 | ret = ad3552r_hs_reset(st); | ||
| 304 | if (ret) | ||
| 305 | return ret; | ||
| 306 | |||
| 307 | ret = iio_backend_ddr_disable(st->back); | ||
| 308 | if (ret) | ||
| 309 | return ret; | ||
| 310 | |||
| 311 | ret = ad3552r_hs_scratch_pad_test(st); | ||
| 312 | if (ret) | ||
| 313 | return ret; | ||
| 314 | |||
| 315 | ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_L, | ||
| 316 | &val, 1); | ||
| 317 | if (ret) | ||
| 318 | return ret; | ||
| 319 | |||
| 320 | id = val; | ||
| 321 | |||
| 322 | ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_H, | ||
| 323 | &val, 1); | ||
| 324 | if (ret) | ||
| 325 | return ret; | ||
| 326 | |||
| 327 | id |= val << 8; | ||
| 328 | if (id != st->model_data->chip_id) | ||
| 329 | dev_info(st->dev, "Chip ID error. Expected 0x%x, Read 0x%x\n", | ||
| 330 | AD3552R_ID, id); | ||
| 331 | |||
| 332 | ret = st->data->bus_reg_write(st->back, | ||
| 333 | AD3552R_REG_ADDR_SH_REFERENCE_CONFIG, | ||
| 334 | 0, 1); | ||
| 335 | if (ret) | ||
| 336 | return ret; | ||
| 337 | |||
| 338 | ret = st->data->bus_reg_write(st->back, | ||
| 339 | AD3552R_REG_ADDR_TRANSFER_REGISTER, | ||
| 340 | FIELD_PREP(AD3552R_MASK_MULTI_IO_MODE, | ||
| 341 | AD3552R_QUAD_SPI) | | ||
| 342 | AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE, 1); | ||
| 343 | if (ret) | ||
| 344 | return ret; | ||
| 345 | |||
| 346 | ret = iio_backend_data_source_set(st->back, 0, IIO_BACKEND_EXTERNAL); | ||
| 347 | if (ret) | ||
| 348 | return ret; | ||
| 349 | |||
| 350 | ret = iio_backend_data_source_set(st->back, 1, IIO_BACKEND_EXTERNAL); | ||
| 351 | if (ret) | ||
| 352 | return ret; | ||
| 353 | |||
| 354 | ret = ad3552r_get_ref_voltage(st->dev, &val); | ||
| 355 | if (ret < 0) | ||
| 356 | return ret; | ||
| 357 | |||
| 358 | val = ret; | ||
| 359 | |||
| 360 | ret = ad3552r_qspi_update_reg_bits(st, | ||
| 361 | AD3552R_REG_ADDR_SH_REFERENCE_CONFIG, | ||
| 362 | AD3552R_MASK_REFERENCE_VOLTAGE_SEL, | ||
| 363 | val, 1); | ||
| 364 | if (ret) | ||
| 365 | return ret; | ||
| 366 | |||
| 367 | ret = ad3552r_get_drive_strength(st->dev, &val); | ||
| 368 | if (!ret) { | ||
| 369 | ret = ad3552r_qspi_update_reg_bits(st, | ||
| 370 | AD3552R_REG_ADDR_INTERFACE_CONFIG_D, | ||
| 371 | AD3552R_MASK_SDO_DRIVE_STRENGTH, | ||
| 372 | val, 1); | ||
| 373 | if (ret) | ||
| 374 | return ret; | ||
| 375 | } | ||
| 376 | |||
| 377 | device_for_each_child_node_scoped(st->dev, child) { | ||
| 378 | ret = fwnode_property_read_u32(child, "reg", &ch); | ||
| 379 | if (ret) | ||
| 380 | return dev_err_probe(st->dev, ret, | ||
| 381 | "reg property missing\n"); | ||
| 382 | |||
| 383 | ret = ad3552r_get_output_range(st->dev, st->model_data, child, | ||
| 384 | &range); | ||
| 385 | if (ret && ret != -ENOENT) | ||
| 386 | return ret; | ||
| 387 | if (ret == -ENOENT) { | ||
| 388 | ret = ad3552r_get_custom_gain(st->dev, child, | ||
| 389 | &st->ch_data[ch].p, | ||
| 390 | &st->ch_data[ch].n, | ||
| 391 | &st->ch_data[ch].rfb, | ||
| 392 | &st->ch_data[ch].gain_offset); | ||
| 393 | if (ret) | ||
| 394 | return ret; | ||
| 395 | |||
| 396 | gain = ad3552r_calc_custom_gain(st->ch_data[ch].p, | ||
| 397 | st->ch_data[ch].n, | ||
| 398 | st->ch_data[ch].gain_offset); | ||
| 399 | offset = abs(st->ch_data[ch].gain_offset); | ||
| 400 | |||
| 401 | st->ch_data[ch].range_override = 1; | ||
| 402 | |||
| 403 | ret = ad3552r_hs_setup_custom_gain(st, ch, gain, | ||
| 404 | offset); | ||
| 405 | if (ret) | ||
| 406 | return ret; | ||
| 407 | } else { | ||
| 408 | st->ch_data[ch].range = range; | ||
| 409 | |||
| 410 | ret = ad3552r_hs_set_output_range(st, ch, range); | ||
| 411 | if (ret) | ||
| 412 | return ret; | ||
| 413 | } | ||
| 414 | |||
| 415 | ad3552r_calc_gain_and_offset(&st->ch_data[ch], st->model_data); | ||
| 416 | } | ||
| 417 | |||
| 418 | return 0; | ||
| 419 | } | ||
| 420 | |||
| 421 | static const struct iio_buffer_setup_ops ad3552r_hs_buffer_setup_ops = { | ||
| 422 | .postenable = ad3552r_hs_buffer_postenable, | ||
| 423 | .predisable = ad3552r_hs_buffer_predisable, | ||
| 424 | }; | ||
| 425 | |||
| 426 | #define AD3552R_CHANNEL(ch) { \ | ||
| 427 | .type = IIO_VOLTAGE, \ | ||
| 428 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | ||
| 429 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | ||
| 430 | BIT(IIO_CHAN_INFO_SCALE) | \ | ||
| 431 | BIT(IIO_CHAN_INFO_OFFSET), \ | ||
| 432 | .output = 1, \ | ||
| 433 | .indexed = 1, \ | ||
| 434 | .channel = (ch), \ | ||
| 435 | .scan_index = (ch), \ | ||
| 436 | .scan_type = { \ | ||
| 437 | .sign = 'u', \ | ||
| 438 | .realbits = 16, \ | ||
| 439 | .storagebits = 16, \ | ||
| 440 | .endianness = IIO_BE, \ | ||
| 441 | } \ | ||
| 442 | } | ||
| 443 | |||
| 444 | static const struct iio_chan_spec ad3552r_hs_channels[] = { | ||
| 445 | AD3552R_CHANNEL(0), | ||
| 446 | AD3552R_CHANNEL(1), | ||
| 447 | }; | ||
| 448 | |||
| 449 | static const struct iio_info ad3552r_hs_info = { | ||
| 450 | .read_raw = &ad3552r_hs_read_raw, | ||
| 451 | .write_raw = &ad3552r_hs_write_raw, | ||
| 452 | }; | ||
| 453 | |||
| 454 | static int ad3552r_hs_probe(struct platform_device *pdev) | ||
| 455 | { | ||
| 456 | struct ad3552r_hs_state *st; | ||
| 457 | struct iio_dev *indio_dev; | ||
| 458 | int ret; | ||
| 459 | |||
| 460 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); | ||
| 461 | if (!indio_dev) | ||
| 462 | return -ENOMEM; | ||
| 463 | |||
| 464 | st = iio_priv(indio_dev); | ||
| 465 | st->dev = &pdev->dev; | ||
| 466 | |||
| 467 | st->data = dev_get_platdata(st->dev); | ||
| 468 | if (!st->data) | ||
| 469 | return dev_err_probe(st->dev, -ENODEV, "No platform data !"); | ||
| 470 | |||
| 471 | st->back = devm_iio_backend_get(&pdev->dev, NULL); | ||
| 472 | if (IS_ERR(st->back)) | ||
| 473 | return PTR_ERR(st->back); | ||
| 474 | |||
| 475 | ret = devm_iio_backend_enable(&pdev->dev, st->back); | ||
| 476 | if (ret) | ||
| 477 | return ret; | ||
| 478 | |||
| 479 | st->model_data = device_get_match_data(&pdev->dev); | ||
| 480 | if (!st->model_data) | ||
| 481 | return -ENODEV; | ||
| 482 | |||
| 483 | indio_dev->name = "ad3552r"; | ||
| 484 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
| 485 | indio_dev->setup_ops = &ad3552r_hs_buffer_setup_ops; | ||
| 486 | indio_dev->channels = ad3552r_hs_channels; | ||
| 487 | indio_dev->num_channels = ARRAY_SIZE(ad3552r_hs_channels); | ||
| 488 | indio_dev->info = &ad3552r_hs_info; | ||
| 489 | |||
| 490 | ret = devm_iio_backend_request_buffer(&pdev->dev, st->back, indio_dev); | ||
| 491 | if (ret) | ||
| 492 | return ret; | ||
| 493 | |||
| 494 | ret = ad3552r_hs_setup(st); | ||
| 495 | if (ret) | ||
| 496 | return ret; | ||
| 497 | |||
| 498 | return devm_iio_device_register(&pdev->dev, indio_dev); | ||
| 499 | } | ||
| 500 | |||
| 501 | static const struct ad3552r_model_data ad3552r_model_data = { | ||
| 502 | .model_name = "ad3552r", | ||
| 503 | .chip_id = AD3552R_ID, | ||
| 504 | .num_hw_channels = 2, | ||
| 505 | .ranges_table = ad3552r_ch_ranges, | ||
| 506 | .num_ranges = ARRAY_SIZE(ad3552r_ch_ranges), | ||
| 507 | }; | ||
| 508 | |||
| 509 | static const struct of_device_id ad3552r_hs_of_id[] = { | ||
| 510 | { .compatible = "adi,ad3552r", .data = &ad3552r_model_data }, | ||
| 511 | { } | ||
| 512 | }; | ||
| 513 | MODULE_DEVICE_TABLE(of, ad3552r_hs_of_id); | ||
| 514 | |||
| 515 | static struct platform_driver ad3552r_hs_driver = { | ||
| 516 | .driver = { | ||
| 517 | .name = "ad3552r-hs", | ||
| 518 | .of_match_table = ad3552r_hs_of_id, | ||
| 519 | }, | ||
| 520 | .probe = ad3552r_hs_probe, | ||
| 521 | }; | ||
| 522 | module_platform_driver(ad3552r_hs_driver); | ||
| 523 | |||
| 524 | MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>"); | ||
| 525 | MODULE_AUTHOR("Angelo Dureghello <adueghello@baylibre.com>"); | ||
| 526 | MODULE_DESCRIPTION("AD3552R Driver - High Speed version"); | ||
| 527 | MODULE_LICENSE("GPL"); | ||
| 528 | MODULE_IMPORT_NS(IIO_BACKEND); | ||
| 529 | MODULE_IMPORT_NS(IIO_AD3552R); | ||
| @@ -0,0 +1,19 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2024 Analog Devices Inc. | ||
| 4 | * Copyright (c) 2024 Baylibre, SAS | ||
| 5 | */ | ||
| 6 | #ifndef __LINUX_PLATFORM_DATA_AD3552R_HS_H__ | ||
| 7 | #define __LINUX_PLATFORM_DATA_AD3552R_HS_H__ | ||
| 8 | |||
| 9 | struct iio_backend; | ||
| 10 | |||
| 11 | struct ad3552r_hs_platform_data { | ||
| 12 | int (*bus_reg_read)(struct iio_backend *back, u32 reg, u32 *val, | ||
| 13 | size_t data_size); | ||
| 14 | int (*bus_reg_write)(struct iio_backend *back, u32 reg, u32 val, | ||
| 15 | size_t data_size); | ||
| 16 | u32 bus_sample_data_clock_hz; | ||
| 17 | }; | ||
| 18 | |||
| 19 | #endif /* __LINUX_PLATFORM_DATA_AD3552R_HS_H__ */ | ||
| @@ -6,271 +6,15 @@ · 5 unmodified lines | |||
| 6 | * Copyright 2021 Analog Devices Inc. | 6 | * Copyright 2021 Analog Devices Inc. |
| 7 | */ | 7 | */ |
| 8 | #include <linux/unaligned.h> | 8 | #include <linux/unaligned.h> |
| 9 | #include <linux/bitfield.h> | ||
| 9 | #include <linux/device.h> | 10 | #include <linux/device.h> |
| 10 | #include <linux/iio/triggered_buffer.h> | 11 | #include <linux/iio/triggered_buffer.h> |
| 11 | #include <linux/iio/trigger_consumer.h> | 12 | #include <linux/iio/trigger_consumer.h> |
| 12 | #include <linux/iopoll.h> | 13 | #include <linux/iopoll.h> |
| 13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 14 | #include <linux/regulator/consumer.h> | ||
| 15 | #include <linux/spi/spi.h> | 15 | #include <linux/spi/spi.h> |
| 16 | 16 | ||
| 17 | /* Register addresses */ | 17 | #include "ad3552r.h" |
| 18 | /* Primary address space */ | ||
| 19 | #define AD3552R_REG_ADDR_INTERFACE_CONFIG_A 0x00 | ||
| 20 | #define AD3552R_MASK_SOFTWARE_RESET (BIT(7) | BIT(0)) | ||
| 21 | #define AD3552R_MASK_ADDR_ASCENSION BIT(5) | ||
| 22 | #define AD3552R_MASK_SDO_ACTIVE BIT(4) | ||
| 23 | #define AD3552R_REG_ADDR_INTERFACE_CONFIG_B 0x01 | ||
| 24 | #define AD3552R_MASK_SINGLE_INST BIT(7) | ||
| 25 | #define AD3552R_MASK_SHORT_INSTRUCTION BIT(3) | ||
| 26 | #define AD3552R_REG_ADDR_DEVICE_CONFIG 0x02 | ||
| 27 | #define AD3552R_MASK_DEVICE_STATUS(n) BIT(4 + (n)) | ||
| 28 | #define AD3552R_MASK_CUSTOM_MODES GENMASK(3, 2) | ||
| 29 | #define AD3552R_MASK_OPERATING_MODES GENMASK(1, 0) | ||
| 30 | #define AD3552R_REG_ADDR_CHIP_TYPE 0x03 | ||
| 31 | #define AD3552R_MASK_CLASS GENMASK(7, 0) | ||
| 32 | #define AD3552R_REG_ADDR_PRODUCT_ID_L 0x04 | ||
| 33 | #define AD3552R_REG_ADDR_PRODUCT_ID_H 0x05 | ||
| 34 | #define AD3552R_REG_ADDR_CHIP_GRADE 0x06 | ||
| 35 | #define AD3552R_MASK_GRADE GENMASK(7, 4) | ||
| 36 | #define AD3552R_MASK_DEVICE_REVISION GENMASK(3, 0) | ||
| 37 | #define AD3552R_REG_ADDR_SCRATCH_PAD 0x0A | ||
| 38 | #define AD3552R_REG_ADDR_SPI_REVISION 0x0B | ||
| 39 | #define AD3552R_REG_ADDR_VENDOR_L 0x0C | ||
| 40 | #define AD3552R_REG_ADDR_VENDOR_H 0x0D | ||
| 41 | #define AD3552R_REG_ADDR_STREAM_MODE 0x0E | ||
| 42 | #define AD3552R_MASK_LENGTH GENMASK(7, 0) | ||
| 43 | #define AD3552R_REG_ADDR_TRANSFER_REGISTER 0x0F | ||
| 44 | #define AD3552R_MASK_MULTI_IO_MODE GENMASK(7, 6) | ||
| 45 | #define AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE BIT(2) | ||
| 46 | #define AD3552R_REG_ADDR_INTERFACE_CONFIG_C 0x10 | ||
| 47 | #define AD3552R_MASK_CRC_ENABLE (GENMASK(7, 6) |\ | ||
| 48 | GENMASK(1, 0)) | ||
| 49 | #define AD3552R_MASK_STRICT_REGISTER_ACCESS BIT(5) | ||
| 50 | #define AD3552R_REG_ADDR_INTERFACE_STATUS_A 0x11 | ||
| 51 | #define AD3552R_MASK_INTERFACE_NOT_READY BIT(7) | ||
| 52 | #define AD3552R_MASK_CLOCK_COUNTING_ERROR BIT(5) | ||
| 53 | #define AD3552R_MASK_INVALID_OR_NO_CRC BIT(3) | ||
| 54 | #define AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER BIT(2) | ||
| 55 | #define AD3552R_MASK_PARTIAL_REGISTER_ACCESS BIT(1) | ||
| 56 | #define AD3552R_MASK_REGISTER_ADDRESS_INVALID BIT(0) | ||
| 57 | #define AD3552R_REG_ADDR_INTERFACE_CONFIG_D 0x14 | ||
| 58 | #define AD3552R_MASK_ALERT_ENABLE_PULLUP BIT(6) | ||
| 59 | #define AD3552R_MASK_MEM_CRC_EN BIT(4) | ||
| 60 | #define AD3552R_MASK_SDO_DRIVE_STRENGTH GENMASK(3, 2) | ||
| 61 | #define AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN BIT(1) | ||
| 62 | #define AD3552R_MASK_SPI_CONFIG_DDR BIT(0) | ||
| 63 | #define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG 0x15 | ||
| 64 | #define AD3552R_MASK_IDUMP_FAST_MODE BIT(6) | ||
| 65 | #define AD3552R_MASK_SAMPLE_HOLD_DIFFERENTIAL_USER_EN BIT(5) | ||
| 66 | #define AD3552R_MASK_SAMPLE_HOLD_USER_TRIM GENMASK(4, 3) | ||
| 67 | #define AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE BIT(2) | ||
| 68 | #define AD3552R_MASK_REFERENCE_VOLTAGE_SEL GENMASK(1, 0) | ||
| 69 | #define AD3552R_REG_ADDR_ERR_ALARM_MASK 0x16 | ||
| 70 | #define AD3552R_MASK_REF_RANGE_ALARM BIT(6) | ||
| 71 | #define AD3552R_MASK_CLOCK_COUNT_ERR_ALARM BIT(5) | ||
| 72 | #define AD3552R_MASK_MEM_CRC_ERR_ALARM BIT(4) | ||
| 73 | #define AD3552R_MASK_SPI_CRC_ERR_ALARM BIT(3) | ||
| 74 | #define AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM BIT(2) | ||
| 75 | #define AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM BIT(1) | ||
| 76 | #define AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM BIT(0) | ||
| 77 | #define AD3552R_REG_ADDR_ERR_STATUS 0x17 | ||
| 78 | #define AD3552R_MASK_REF_RANGE_ERR_STATUS BIT(6) | ||
| 79 | #define AD3552R_MASK_DUAL_SPI_STREAM_EXCEEDS_DAC_ERR_STATUS BIT(5) | ||
| 80 | #define AD3552R_MASK_MEM_CRC_ERR_STATUS BIT(4) | ||
| 81 | #define AD3552R_MASK_RESET_STATUS BIT(0) | ||
| 82 | #define AD3552R_REG_ADDR_POWERDOWN_CONFIG 0x18 | ||
| 83 | #define AD3552R_MASK_CH_DAC_POWERDOWN(ch) BIT(4 + (ch)) | ||
| 84 | #define AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch) BIT(ch) | ||
| 85 | #define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE 0x19 | ||
| 86 | #define AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch) ((ch) ? GENMASK(7, 4) :\ | ||
| 87 | GENMASK(3, 0)) | ||
| 88 | #define AD3552R_REG_ADDR_CH_OFFSET(ch) (0x1B + (ch) * 2) | ||
| 89 | #define AD3552R_MASK_CH_OFFSET_BITS_0_7 GENMASK(7, 0) | ||
| 90 | #define AD3552R_REG_ADDR_CH_GAIN(ch) (0x1C + (ch) * 2) | ||
| 91 | #define AD3552R_MASK_CH_RANGE_OVERRIDE BIT(7) | ||
| 92 | #define AD3552R_MASK_CH_GAIN_SCALING_N GENMASK(6, 5) | ||
| 93 | #define AD3552R_MASK_CH_GAIN_SCALING_P GENMASK(4, 3) | ||
| 94 | #define AD3552R_MASK_CH_OFFSET_POLARITY BIT(2) | ||
| 95 | #define AD3552R_MASK_CH_OFFSET_BIT_8 BIT(0) | ||
| 96 | /* | ||
| 97 | * Secondary region | ||
| 98 | * For multibyte registers specify the highest address because the access is | ||
| 99 | * done in descending order | ||
| 100 | */ | ||
| 101 | #define AD3552R_SECONDARY_REGION_START 0x28 | ||
| 102 | #define AD3552R_REG_ADDR_HW_LDAC_16B 0x28 | ||
| 103 | #define AD3552R_REG_ADDR_CH_DAC_16B(ch) (0x2C - (1 - ch) * 2) | ||
| 104 | #define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B 0x2E | ||
| 105 | #define AD3552R_REG_ADDR_CH_SELECT_16B 0x2F | ||
| 106 | #define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B 0x31 | ||
| 107 | #define AD3552R_REG_ADDR_SW_LDAC_16B 0x32 | ||
| 108 | #define AD3552R_REG_ADDR_CH_INPUT_16B(ch) (0x36 - (1 - ch) * 2) | ||
| 109 | /* 3 bytes registers */ | ||
| 110 | #define AD3552R_REG_START_24B 0x37 | ||
| 111 | #define AD3552R_REG_ADDR_HW_LDAC_24B 0x37 | ||
| 112 | #define AD3552R_REG_ADDR_CH_DAC_24B(ch) (0x3D - (1 - ch) * 3) | ||
| 113 | #define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B 0x40 | ||
| 114 | #define AD3552R_REG_ADDR_CH_SELECT_24B 0x41 | ||
| 115 | #define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B 0x44 | ||
| 116 | #define AD3552R_REG_ADDR_SW_LDAC_24B 0x45 | ||
| 117 | #define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - ch) * 3) | ||
| 118 | |||
| 119 | /* Useful defines */ | ||
| 120 | #define AD3552R_MAX_CH 2 | ||
| 121 | #define AD3552R_MASK_CH(ch) BIT(ch) | ||
| 122 | #define AD3552R_MASK_ALL_CH GENMASK(1, 0) | ||
| 123 | #define AD3552R_MAX_REG_SIZE 3 | ||
| 124 | #define AD3552R_READ_BIT BIT(7) | ||
| 125 | #define AD3552R_ADDR_MASK GENMASK(6, 0) | ||
| 126 | #define AD3552R_MASK_DAC_12B 0xFFF0 | ||
| 127 | #define AD3552R_DEFAULT_CONFIG_B_VALUE 0x8 | ||
| 128 | #define AD3552R_SCRATCH_PAD_TEST_VAL1 0x34 | ||
| 129 | #define AD3552R_SCRATCH_PAD_TEST_VAL2 0xB2 | ||
| 130 | #define AD3552R_GAIN_SCALE 1000 | ||
| 131 | #define AD3552R_LDAC_PULSE_US 100 | ||
| 132 | |||
| 133 | enum ad3552r_ch_vref_select { | ||
| 134 | /* Internal source with Vref I/O floating */ | ||
| 135 | AD3552R_INTERNAL_VREF_PIN_FLOATING, | ||
| 136 | /* Internal source with Vref I/O at 2.5V */ | ||
| 137 | AD3552R_INTERNAL_VREF_PIN_2P5V, | ||
| 138 | /* External source with Vref I/O as input */ | ||
| 139 | AD3552R_EXTERNAL_VREF_PIN_INPUT | ||
| 140 | }; | ||
| 141 | |||
| 142 | enum ad3552r_id { | ||
| 143 | AD3541R_ID = 0x400b, | ||
| 144 | AD3542R_ID = 0x4009, | ||
| 145 | AD3551R_ID = 0x400a, | ||
| 146 | AD3552R_ID = 0x4008, | ||
| 147 | }; | ||
| 148 | |||
| 149 | enum ad3552r_ch_output_range { | ||
| 150 | /* Range from 0 V to 2.5 V. Requires Rfb1x connection */ | ||
| 151 | AD3552R_CH_OUTPUT_RANGE_0__2P5V, | ||
| 152 | /* Range from 0 V to 5 V. Requires Rfb1x connection */ | ||
| 153 | AD3552R_CH_OUTPUT_RANGE_0__5V, | ||
| 154 | /* Range from 0 V to 10 V. Requires Rfb2x connection */ | ||
| 155 | AD3552R_CH_OUTPUT_RANGE_0__10V, | ||
| 156 | /* Range from -5 V to 5 V. Requires Rfb2x connection */ | ||
| 157 | AD3552R_CH_OUTPUT_RANGE_NEG_5__5V, | ||
| 158 | /* Range from -10 V to 10 V. Requires Rfb4x connection */ | ||
| 159 | AD3552R_CH_OUTPUT_RANGE_NEG_10__10V, | ||
| 160 | }; | ||
| 161 | |||
| 162 | static const s32 ad3552r_ch_ranges[][2] = { | ||
| 163 | [AD3552R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500}, | ||
| 164 | [AD3552R_CH_OUTPUT_RANGE_0__5V] = {0, 5000}, | ||
| 165 | [AD3552R_CH_OUTPUT_RANGE_0__10V] = {0, 10000}, | ||
| 166 | [AD3552R_CH_OUTPUT_RANGE_NEG_5__5V] = {-5000, 5000}, | ||
| 167 | [AD3552R_CH_OUTPUT_RANGE_NEG_10__10V] = {-10000, 10000} | ||
| 168 | }; | ||
| 169 | |||
| 170 | enum ad3542r_ch_output_range { | ||
| 171 | /* Range from 0 V to 2.5 V. Requires Rfb1x connection */ | ||
| 172 | AD3542R_CH_OUTPUT_RANGE_0__2P5V, | ||
| 173 | /* Range from 0 V to 3 V. Requires Rfb1x connection */ | ||
| 174 | AD3542R_CH_OUTPUT_RANGE_0__3V, | ||
| 175 | /* Range from 0 V to 5 V. Requires Rfb1x connection */ | ||
| 176 | AD3542R_CH_OUTPUT_RANGE_0__5V, | ||
| 177 | /* Range from 0 V to 10 V. Requires Rfb2x connection */ | ||
| 178 | AD3542R_CH_OUTPUT_RANGE_0__10V, | ||
| 179 | /* Range from -2.5 V to 7.5 V. Requires Rfb2x connection */ | ||
| 180 | AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V, | ||
| 181 | /* Range from -5 V to 5 V. Requires Rfb2x connection */ | ||
| 182 | AD3542R_CH_OUTPUT_RANGE_NEG_5__5V, | ||
| 183 | }; | ||
| 184 | |||
| 185 | static const s32 ad3542r_ch_ranges[][2] = { | ||
| 186 | [AD3542R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500}, | ||
| 187 | [AD3542R_CH_OUTPUT_RANGE_0__3V] = {0, 3000}, | ||
| 188 | [AD3542R_CH_OUTPUT_RANGE_0__5V] = {0, 5000}, | ||
| 189 | [AD3542R_CH_OUTPUT_RANGE_0__10V] = {0, 10000}, | ||
| 190 | [AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V] = {-2500, 7500}, | ||
| 191 | [AD3542R_CH_OUTPUT_RANGE_NEG_5__5V] = {-5000, 5000} | ||
| 192 | }; | ||
| 193 | |||
| 194 | enum ad3552r_ch_gain_scaling { | ||
| 195 | /* Gain scaling of 1 */ | ||
| 196 | AD3552R_CH_GAIN_SCALING_1, | ||
| 197 | /* Gain scaling of 0.5 */ | ||
| 198 | AD3552R_CH_GAIN_SCALING_0_5, | ||
| 199 | /* Gain scaling of 0.25 */ | ||
| 200 | AD3552R_CH_GAIN_SCALING_0_25, | ||
| 201 | /* Gain scaling of 0.125 */ | ||
| 202 | AD3552R_CH_GAIN_SCALING_0_125, | ||
| 203 | }; | ||
| 204 | |||
| 205 | /* Gain * AD3552R_GAIN_SCALE */ | ||
| 206 | static const s32 gains_scaling_table[] = { | ||
| 207 | [AD3552R_CH_GAIN_SCALING_1] = 1000, | ||
| 208 | [AD3552R_CH_GAIN_SCALING_0_5] = 500, | ||
| 209 | [AD3552R_CH_GAIN_SCALING_0_25] = 250, | ||
| 210 | [AD3552R_CH_GAIN_SCALING_0_125] = 125 | ||
| 211 | }; | ||
| 212 | |||
| 213 | enum ad3552r_dev_attributes { | ||
| 214 | /* - Direct register values */ | ||
| 215 | /* From 0-3 */ | ||
| 216 | AD3552R_SDO_DRIVE_STRENGTH, | ||
| 217 | /* | ||
| 218 | * 0 -> Internal Vref, vref_io pin floating (default) | ||
| 219 | * 1 -> Internal Vref, vref_io driven by internal vref | ||
| 220 | * 2 or 3 -> External Vref | ||
| 221 | */ | ||
| 222 | AD3552R_VREF_SELECT, | ||
| 223 | /* Read registers in ascending order if set. Else descending */ | ||
| 224 | AD3552R_ADDR_ASCENSION, | ||
| 225 | }; | ||
| 226 | |||
| 227 | enum ad3552r_ch_attributes { | ||
| 228 | /* DAC powerdown */ | ||
| 229 | AD3552R_CH_DAC_POWERDOWN, | ||
| 230 | /* DAC amplifier powerdown */ | ||
| 231 | AD3552R_CH_AMPLIFIER_POWERDOWN, | ||
| 232 | /* Select the output range. Select from enum ad3552r_ch_output_range */ | ||
| 233 | AD3552R_CH_OUTPUT_RANGE_SEL, | ||
| 234 | /* | ||
| 235 | * Over-rider the range selector in order to manually set the output | ||
| 236 | * voltage range | ||
| 237 | */ | ||
| 238 | AD3552R_CH_RANGE_OVERRIDE, | ||
| 239 | /* Manually set the offset voltage */ | ||
| 240 | AD3552R_CH_GAIN_OFFSET, | ||
| 241 | /* Sets the polarity of the offset. */ | ||
| 242 | AD3552R_CH_GAIN_OFFSET_POLARITY, | ||
| 243 | /* PDAC gain scaling */ | ||
| 244 | AD3552R_CH_GAIN_SCALING_P, | ||
| 245 | /* NDAC gain scaling */ | ||
| 246 | AD3552R_CH_GAIN_SCALING_N, | ||
| 247 | /* Rfb value */ | ||
| 248 | AD3552R_CH_RFB, | ||
| 249 | /* Channel select. When set allow Input -> DAC and Mask -> DAC */ | ||
| 250 | AD3552R_CH_SELECT, | ||
| 251 | }; | ||
| 252 | |||
| 253 | struct ad3552r_ch_data { | ||
| 254 | s32 scale_int; | ||
| 255 | s32 scale_dec; | ||
| 256 | s32 offset_int; | ||
| 257 | s32 offset_dec; | ||
| 258 | s16 gain_offset; | ||
| 259 | u16 rfb; | ||
| 260 | u8 n; | ||
| 261 | u8 p; | ||
| 262 | u8 range; | ||
| 263 | bool range_override; | ||
| 264 | }; | ||
| 265 | |||
| 266 | struct ad3552r_model_data { | ||
| 267 | const char *model_name; | ||
| 268 | enum ad3552r_id chip_id; | ||
| 269 | unsigned int num_hw_channels; | ||
| 270 | const s32 (*ranges_table)[2]; | ||
| 271 | int num_ranges; | ||
| 272 | bool requires_output_range; | ||
| 273 | }; | ||
| 274 | 18 | ||
| 275 | struct ad3552r_desc { | 19 | struct ad3552r_desc { |
| 276 | const struct ad3552r_model_data *model_data; | 20 | const struct ad3552r_model_data *model_data; |
| @@ -285,45 +29,6 @@ struct ad3552r_desc { · 8 unmodified lines | |||
| 285 | unsigned int num_ch; | 29 | unsigned int num_ch; |
| 286 | }; | 30 | }; |
| 287 | 31 | ||
| 288 | static const u16 addr_mask_map[][2] = { | ||
| 289 | [AD3552R_ADDR_ASCENSION] = { | ||
| 290 | AD3552R_REG_ADDR_INTERFACE_CONFIG_A, | ||
| 291 | AD3552R_MASK_ADDR_ASCENSION | ||
| 292 | }, | ||
| 293 | [AD3552R_SDO_DRIVE_STRENGTH] = { | ||
| 294 | AD3552R_REG_ADDR_INTERFACE_CONFIG_D, | ||
| 295 | AD3552R_MASK_SDO_DRIVE_STRENGTH | ||
| 296 | }, | ||
| 297 | [AD3552R_VREF_SELECT] = { | ||
| 298 | AD3552R_REG_ADDR_SH_REFERENCE_CONFIG, | ||
| 299 | AD3552R_MASK_REFERENCE_VOLTAGE_SEL | ||
| 300 | }, | ||
| 301 | }; | ||
| 302 | |||
| 303 | /* 0 -> reg addr, 1->ch0 mask, 2->ch1 mask */ | ||
| 304 | static const u16 addr_mask_map_ch[][3] = { | ||
| 305 | [AD3552R_CH_DAC_POWERDOWN] = { | ||
| 306 | AD3552R_REG_ADDR_POWERDOWN_CONFIG, | ||
| 307 | AD3552R_MASK_CH_DAC_POWERDOWN(0), | ||
| 308 | AD3552R_MASK_CH_DAC_POWERDOWN(1) | ||
| 309 | }, | ||
| 310 | [AD3552R_CH_AMPLIFIER_POWERDOWN] = { | ||
| 311 | AD3552R_REG_ADDR_POWERDOWN_CONFIG, | ||
| 312 | AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(0), | ||
| 313 | AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(1) | ||
| 314 | }, | ||
| 315 | [AD3552R_CH_OUTPUT_RANGE_SEL] = { | ||
| 316 | AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE, | ||
| 317 | AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0), | ||
| 318 | AD3552R_MASK_CH_OUTPUT_RANGE_SEL(1) | ||
| 319 | }, | ||
| 320 | [AD3552R_CH_SELECT] = { | ||
| 321 | AD3552R_REG_ADDR_CH_SELECT_16B, | ||
| 322 | AD3552R_MASK_CH(0), | ||
| 323 | AD3552R_MASK_CH(1) | ||
| 324 | } | ||
| 325 | }; | ||
| 326 | |||
| 327 | static u8 _ad3552r_reg_len(u8 addr) | 32 | static u8 _ad3552r_reg_len(u8 addr) |
| 328 | { | 33 | { |
| 329 | switch (addr) { | 34 | switch (addr) { |
| @@ -399,11 +104,6 @@ static int ad3552r_read_reg(struct ad3552r_desc *dac, u8 addr, u16 *val) · 69 unmodified lines | |||
| 399 | return 0; | 104 | return 0; |
| 400 | } | 105 | } |
| 401 | 106 | ||
| 402 | static u16 ad3552r_field_prep(u16 val, u16 mask) | ||
| 403 | { | ||
| 404 | return (val << __ffs(mask)) & mask; | ||
| 405 | } | ||
| 406 | |||
| 407 | /* Update field of a register, shift val if needed */ | 107 | /* Update field of a register, shift val if needed */ |
| 408 | static int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask, | 108 | static int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask, |
| 409 | u16 val) | 109 | u16 val) |
| @@ -416,21 +116,11 @@ static int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask, · 6 unmodified lines | |||
| 416 | return ret; | 116 | return ret; |
| 417 | 117 | ||
| 418 | reg &= ~mask; | 118 | reg &= ~mask; |
| 419 | reg |= ad3552r_field_prep(val, mask); | 119 | reg |= val; |
| 420 | 120 | ||
| 421 | return ad3552r_write_reg(dac, addr, reg); | 121 | return ad3552r_write_reg(dac, addr, reg); |
| 422 | } | 122 | } |
| 423 | 123 | ||
| 424 | static int ad3552r_set_ch_value(struct ad3552r_desc *dac, | ||
| 425 | enum ad3552r_ch_attributes attr, | ||
| 426 | u8 ch, | ||
| 427 | u16 val) | ||
| 428 | { | ||
| 429 | /* Update register related to attributes in chip */ | ||
| 430 | return ad3552r_update_reg_field(dac, addr_mask_map_ch[attr][0], | ||
| 431 | addr_mask_map_ch[attr][ch + 1], val); | ||
| 432 | } | ||
| 433 | |||
| 434 | #define AD3552R_CH_DAC(_idx) ((struct iio_chan_spec) { \ | 124 | #define AD3552R_CH_DAC(_idx) ((struct iio_chan_spec) { \ |
| 435 | .type = IIO_VOLTAGE, \ | 125 | .type = IIO_VOLTAGE, \ |
| 436 | .output = true, \ | 126 | .output = true, \ |
| @@ -510,8 +200,14 @@ static int ad3552r_write_raw(struct iio_dev *indio_dev, · 73 unmodified lines | |||
| 510 | val); | 200 | val); |
| 511 | break; | 201 | break; |
| 512 | case IIO_CHAN_INFO_ENABLE: | 202 | case IIO_CHAN_INFO_ENABLE: |
| 513 | err = ad3552r_set_ch_value(dac, AD3552R_CH_DAC_POWERDOWN, | 203 | if (chan->channel == 0) |
| 514 | chan->channel, !val); | 204 | val = FIELD_PREP(AD3552R_MASK_CH_DAC_POWERDOWN(0), !val); |
| 205 | else | ||
| 206 | val = FIELD_PREP(AD3552R_MASK_CH_DAC_POWERDOWN(1), !val); | ||
| 207 | |||
| 208 | err = ad3552r_update_reg_field(dac, AD3552R_REG_ADDR_POWERDOWN_CONFIG, | ||
| 209 | AD3552R_MASK_CH_DAC_POWERDOWN(chan->channel), | ||
| 210 | val); | ||
| 515 | break; | 211 | break; |
| 516 | default: | 212 | default: |
| 517 | err = -EINVAL; | 213 | err = -EINVAL; |
| @@ -715,83 +411,9 @@ static int ad3552r_reset(struct ad3552r_desc *dac) · 197 unmodified lines | |||
| 715 | } | 411 | } |
| 716 | 412 | ||
| 717 | return ad3552r_update_reg_field(dac, | 413 | return ad3552r_update_reg_field(dac, |
| 718 | addr_mask_map[AD3552R_ADDR_ASCENSION][0], | 414 | AD3552R_REG_ADDR_INTERFACE_CONFIG_A, |
| 719 | addr_mask_map[AD3552R_ADDR_ASCENSION][1], | 415 | AD3552R_MASK_ADDR_ASCENSION, |
| 720 | val); | 416 | FIELD_PREP(AD3552R_MASK_ADDR_ASCENSION, val)); |
| 721 | } | ||
| 722 | |||
| 723 | static void ad3552r_get_custom_range(struct ad3552r_desc *dac, s32 i, s32 *v_min, | ||
| 724 | s32 *v_max) | ||
| 725 | { | ||
| 726 | s64 vref, tmp, common, offset, gn, gp; | ||
| 727 | /* | ||
| 728 | * From datasheet formula (In Volts): | ||
| 729 | * Vmin = 2.5 + [(GainN + Offset / 1024) * 2.5 * Rfb * 1.03] | ||
| 730 | * Vmax = 2.5 - [(GainP + Offset / 1024) * 2.5 * Rfb * 1.03] | ||
| 731 | * Calculus are converted to milivolts | ||
| 732 | */ | ||
| 733 | vref = 2500; | ||
| 734 | /* 2.5 * 1.03 * 1000 (To mV) */ | ||
| 735 | common = 2575 * dac->ch_data[i].rfb; | ||
| 736 | offset = dac->ch_data[i].gain_offset; | ||
| 737 | |||
| 738 | gn = gains_scaling_table[dac->ch_data[i].n]; | ||
| 739 | tmp = (1024 * gn + AD3552R_GAIN_SCALE * offset) * common; | ||
| 740 | tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE); | ||
| 741 | *v_max = vref + tmp; | ||
| 742 | |||
| 743 | gp = gains_scaling_table[dac->ch_data[i].p]; | ||
| 744 | tmp = (1024 * gp - AD3552R_GAIN_SCALE * offset) * common; | ||
| 745 | tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE); | ||
| 746 | *v_min = vref - tmp; | ||
| 747 | } | ||
| 748 | |||
| 749 | static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch) | ||
| 750 | { | ||
| 751 | s32 idx, v_max, v_min, span, rem; | ||
| 752 | s64 tmp; | ||
| 753 | |||
| 754 | if (dac->ch_data[ch].range_override) { | ||
| 755 | ad3552r_get_custom_range(dac, ch, &v_min, &v_max); | ||
| 756 | } else { | ||
| 757 | /* Normal range */ | ||
| 758 | idx = dac->ch_data[ch].range; | ||
| 759 | v_min = dac->model_data->ranges_table[idx][0]; | ||
| 760 | v_max = dac->model_data->ranges_table[idx][1]; | ||
| 761 | } | ||
| 762 | |||
| 763 | /* | ||
| 764 | * From datasheet formula: | ||
| 765 | * Vout = Span * (D / 65536) + Vmin | ||
| 766 | * Converted to scale and offset: | ||
| 767 | * Scale = Span / 65536 | ||
| 768 | * Offset = 65536 * Vmin / Span | ||
| 769 | * | ||
| 770 | * Reminders are in micros in order to be printed as | ||
| 771 | * IIO_VAL_INT_PLUS_MICRO | ||
| 772 | */ | ||
| 773 | span = v_max - v_min; | ||
| 774 | dac->ch_data[ch].scale_int = div_s64_rem(span, 65536, &rem); | ||
| 775 | /* Do operations in microvolts */ | ||
| 776 | dac->ch_data[ch].scale_dec = DIV_ROUND_CLOSEST((s64)rem * 1000000, | ||
| 777 | 65536); | ||
| 778 | |||
| 779 | dac->ch_data[ch].offset_int = div_s64_rem(v_min * 65536, span, &rem); | ||
| 780 | tmp = (s64)rem * 1000000; | ||
| 781 | dac->ch_data[ch].offset_dec = div_s64(tmp, span); | ||
| 782 | } | ||
| 783 | |||
| 784 | static int ad3552r_find_range(const struct ad3552r_model_data *model_data, | ||
| 785 | s32 *vals) | ||
| 786 | { | ||
| 787 | int i; | ||
| 788 | |||
| 789 | for (i = 0; i < model_data->num_ranges; i++) | ||
| 790 | if (vals[0] == model_data->ranges_table[i][0] * 1000 && | ||
| 791 | vals[1] == model_data->ranges_table[i][1] * 1000) | ||
| 792 | return i; | ||
| 793 | |||
| 794 | return -EINVAL; | ||
| 795 | } | 417 | } |
| 796 | 418 | ||
| 797 | static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac, | 419 | static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac, |
| @@ -799,57 +421,30 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac, · 1 unmodified line | |||
| 799 | u32 ch) | 421 | u32 ch) |
| 800 | { | 422 | { |
| 801 | struct device *dev = &dac->spi->dev; | 423 | struct device *dev = &dac->spi->dev; |
| 802 | u32 val; | ||
| 803 | int err; | 424 | int err; |
| 804 | u8 addr; | 425 | u8 addr; |
| 805 | u16 reg = 0, offset; | 426 | u16 reg; |
| 806 | |||
| 807 | struct fwnode_handle *gain_child __free(fwnode_handle) | ||
| 808 | = fwnode_get_named_child_node(child, | ||
| 809 | "custom-output-range-config"); | ||
| 810 | if (!gain_child) | ||
| 811 | return dev_err_probe(dev, -EINVAL, | ||
| 812 | "mandatory custom-output-range-config property missing\n"); | ||
| 813 | |||
| 814 | dac->ch_data[ch].range_override = 1; | ||
| 815 | reg |= ad3552r_field_prep(1, AD3552R_MASK_CH_RANGE_OVERRIDE); | ||
| 816 | |||
| 817 | err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val); | ||
| 818 | if (err) | ||
| 819 | return dev_err_probe(dev, err, | ||
| 820 | "mandatory adi,gain-scaling-p property missing\n"); | ||
| 821 | reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_P); | ||
| 822 | dac->ch_data[ch].p = val; | ||
| 823 | |||
| 824 | err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val); | ||
| 825 | if (err) | ||
| 826 | return dev_err_probe(dev, err, | ||
| 827 | "mandatory adi,gain-scaling-n property missing\n"); | ||
| 828 | reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_N); | ||
| 829 | dac->ch_data[ch].n = val; | ||
| 830 | |||
| 831 | err = fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val); | ||
| 832 | if (err) | ||
| 833 | return dev_err_probe(dev, err, | ||
| 834 | "mandatory adi,rfb-ohms property missing\n"); | ||
| 835 | dac->ch_data[ch].rfb = val; | ||
| 836 | 427 | ||
| 837 | err = fwnode_property_read_u32(gain_child, "adi,gain-offset", &val); | 428 | err = ad3552r_get_custom_gain(dev, child, |
| 429 | &dac->ch_data[ch].p, | ||
| 430 | &dac->ch_data[ch].n, | ||
| 431 | &dac->ch_data[ch].rfb, | ||
| 432 | &dac->ch_data[ch].gain_offset); | ||
| 838 | if (err) | 433 | if (err) |
| 839 | return dev_err_probe(dev, err, | 434 | return err; |
| 840 | "mandatory adi,gain-offset property missing\n"); | ||
| 841 | dac->ch_data[ch].gain_offset = val; | ||
| 842 | 435 | ||
| 843 | offset = abs((s32)val); | 436 | dac->ch_data[ch].range_override = 1; |
| 844 | reg |= ad3552r_field_prep((offset >> 8), AD3552R_MASK_CH_OFFSET_BIT_8); | ||
| 845 | 437 | ||
| 846 | reg |= ad3552r_field_prep((s32)val < 0, AD3552R_MASK_CH_OFFSET_POLARITY); | ||
| 847 | addr = AD3552R_REG_ADDR_CH_GAIN(ch); | 438 | addr = AD3552R_REG_ADDR_CH_GAIN(ch); |
| 848 | err = ad3552r_write_reg(dac, addr, | 439 | err = ad3552r_write_reg(dac, addr, |
| 849 | offset & AD3552R_MASK_CH_OFFSET_BITS_0_7); | 440 | abs((s32)dac->ch_data[ch].gain_offset) & |
| 441 | AD3552R_MASK_CH_OFFSET_BITS_0_7); | ||
| 850 | if (err) | 442 | if (err) |
| 851 | return dev_err_probe(dev, err, "Error writing register\n"); | 443 | return dev_err_probe(dev, err, "Error writing register\n"); |
| 852 | 444 | ||
| 445 | reg = ad3552r_calc_custom_gain(dac->ch_data[ch].p, dac->ch_data[ch].n, | ||
| 446 | dac->ch_data[ch].gain_offset); | ||
| 447 | |||
| 853 | err = ad3552r_write_reg(dac, addr, reg); | 448 | err = ad3552r_write_reg(dac, addr, reg); |
| 854 | if (err) | 449 | if (err) |
| 855 | return dev_err_probe(dev, err, "Error writing register\n"); | 450 | return dev_err_probe(dev, err, "Error writing register\n"); |
| @@ -860,49 +455,31 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac, · 4 unmodified lines | |||
| 860 | static int ad3552r_configure_device(struct ad3552r_desc *dac) | 455 | static int ad3552r_configure_device(struct ad3552r_desc *dac) |
| 861 | { | 456 | { |
| 862 | struct device *dev = &dac->spi->dev; | 457 | struct device *dev = &dac->spi->dev; |
| 863 | int err, cnt = 0, voltage, delta = 100000; | 458 | int err, cnt = 0; |
| 864 | u32 vals[2], val, ch; | 459 | u32 val, ch; |
| 865 | 460 | ||
| 866 | dac->gpio_ldac = devm_gpiod_get_optional(dev, "ldac", GPIOD_OUT_HIGH); | 461 | dac->gpio_ldac = devm_gpiod_get_optional(dev, "ldac", GPIOD_OUT_HIGH); |
| 867 | if (IS_ERR(dac->gpio_ldac)) | 462 | if (IS_ERR(dac->gpio_ldac)) |
| 868 | return dev_err_probe(dev, PTR_ERR(dac->gpio_ldac), | 463 | return dev_err_probe(dev, PTR_ERR(dac->gpio_ldac), |
| 869 | "Error getting gpio ldac"); | 464 | "Error getting gpio ldac"); |
| 870 | 465 | ||
| 871 | voltage = devm_regulator_get_enable_read_voltage(dev, "vref"); | 466 | err = ad3552r_get_ref_voltage(dev, &val); |
| 872 | if (voltage < 0 && voltage != -ENODEV) | 467 | if (err < 0) |
| 873 | return dev_err_probe(dev, voltage, "Error getting vref voltage\n"); | 468 | return err; |
| 874 | |||
| 875 | if (voltage == -ENODEV) { | ||
| 876 | if (device_property_read_bool(dev, "adi,vref-out-en")) | ||
| 877 | val = AD3552R_INTERNAL_VREF_PIN_2P5V; | ||
| 878 | else | ||
| 879 | val = AD3552R_INTERNAL_VREF_PIN_FLOATING; | ||
| 880 | } else { | ||
| 881 | if (voltage > 2500000 + delta || voltage < 2500000 - delta) { | ||
| 882 | dev_warn(dev, "vref-supply must be 2.5V"); | ||
| 883 | return -EINVAL; | ||
| 884 | } | ||
| 885 | val = AD3552R_EXTERNAL_VREF_PIN_INPUT; | ||
| 886 | } | ||
| 887 | 469 | ||
| 888 | err = ad3552r_update_reg_field(dac, | 470 | err = ad3552r_update_reg_field(dac, |
| 889 | addr_mask_map[AD3552R_VREF_SELECT][0], | 471 | AD3552R_REG_ADDR_SH_REFERENCE_CONFIG, |
| 890 | addr_mask_map[AD3552R_VREF_SELECT][1], | 472 | AD3552R_MASK_REFERENCE_VOLTAGE_SEL, |
| 891 | val); | 473 | FIELD_PREP(AD3552R_MASK_REFERENCE_VOLTAGE_SEL, val)); |
| 892 | if (err) | 474 | if (err) |
| 893 | return err; | 475 | return err; |
| 894 | 476 | ||
| 895 | err = device_property_read_u32(dev, "adi,sdo-drive-strength", &val); | 477 | err = ad3552r_get_drive_strength(dev, &val); |
| 896 | if (!err) { | 478 | if (!err) { |
| 897 | if (val > 3) { | ||
| 898 | dev_err(dev, "adi,sdo-drive-strength must be less than 4\n"); | ||
| 899 | return -EINVAL; | ||
| 900 | } | ||
| 901 | |||
| 902 | err = ad3552r_update_reg_field(dac, | 479 | err = ad3552r_update_reg_field(dac, |
| 903 | addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][0], | 480 | AD3552R_REG_ADDR_INTERFACE_CONFIG_D, |
| 904 | addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][1], | 481 | AD3552R_MASK_SDO_DRIVE_STRENGTH, |
| 905 | val); | 482 | FIELD_PREP(AD3552R_MASK_SDO_DRIVE_STRENGTH, val)); |
| 906 | if (err) | 483 | if (err) |
| 907 | return err; | 484 | return err; |
| 908 | } | 485 | } |
| @@ -923,24 +500,21 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) · 14 unmodified lines | |||
| 923 | "reg must be less than %d\n", | 500 | "reg must be less than %d\n", |
| 924 | dac->model_data->num_hw_channels); | 501 | dac->model_data->num_hw_channels); |
| 925 | 502 | ||
| 926 | if (fwnode_property_present(child, "adi,output-range-microvolt")) { | 503 | err = ad3552r_get_output_range(dev, dac->model_data, |
| 927 | err = fwnode_property_read_u32_array(child, | 504 | child, &val); |
| 928 | "adi,output-range-microvolt", | 505 | if (err && err != -ENOENT) |
| 929 | vals, | 506 | return err; |
| 930 | 2); | 507 | |
| 931 | if (err) | 508 | if (!err) { |
| 932 | return dev_err_probe(dev, err, | 509 | if (ch == 0) |
| 933 | "adi,output-range-microvolt property could not be parsed\n"); | 510 | val = FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0), val); |
| 934 | 511 | else | |
| 935 | err = ad3552r_find_range(dac->model_data, vals); | 512 | val = FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(1), val); |
| 936 | if (err < 0) | 513 | |
| 937 | return dev_err_probe(dev, err, | 514 | err = ad3552r_update_reg_field(dac, |
| 938 | "Invalid adi,output-range-microvolt value\n"); | 515 | AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE, |
| 939 | 516 | AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch), | |
| 940 | val = err; | 517 | val); |
| 941 | err = ad3552r_set_ch_value(dac, | ||
| 942 | AD3552R_CH_OUTPUT_RANGE_SEL, | ||
| 943 | ch, val); | ||
| 944 | if (err) | 518 | if (err) |
| 945 | return err; | 519 | return err; |
| 946 | 520 | ||
| @@ -955,10 +529,17 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) · 8 unmodified lines | |||
| 955 | return err; | 529 | return err; |
| 956 | } | 530 | } |
| 957 | 531 | ||
| 958 | ad3552r_calc_gain_and_offset(dac, ch); | 532 | ad3552r_calc_gain_and_offset(&dac->ch_data[ch], dac->model_data); |
| 959 | dac->enabled_ch |= BIT(ch); | 533 | dac->enabled_ch |= BIT(ch); |
| 960 | 534 | ||
| 961 | err = ad3552r_set_ch_value(dac, AD3552R_CH_SELECT, ch, 1); | 535 | if (ch == 0) |
| 536 | val = FIELD_PREP(AD3552R_MASK_CH(0), 1); | ||
| 537 | else | ||
| 538 | val = FIELD_PREP(AD3552R_MASK_CH(1), 1); | ||
| 539 | |||
| 540 | err = ad3552r_update_reg_field(dac, | ||
| 541 | AD3552R_REG_ADDR_CH_SELECT_16B, | ||
| 542 | AD3552R_MASK_CH(ch), val); | ||
| 962 | if (err < 0) | 543 | if (err < 0) |
| 963 | return err; | 544 | return err; |
| 964 | 545 | ||
| @@ -970,8 +551,15 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac) · 5 unmodified lines | |||
| 970 | /* Disable unused channels */ | 551 | /* Disable unused channels */ |
| 971 | for_each_clear_bit(ch, &dac->enabled_ch, | 552 | for_each_clear_bit(ch, &dac->enabled_ch, |
| 972 | dac->model_data->num_hw_channels) { | 553 | dac->model_data->num_hw_channels) { |
| 973 | err = ad3552r_set_ch_value(dac, AD3552R_CH_AMPLIFIER_POWERDOWN, | 554 | if (ch == 0) |
| 974 | ch, 1); | 555 | val = FIELD_PREP(AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(0), 1); |
| 556 | else | ||
| 557 | val = FIELD_PREP(AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(1), 1); | ||
| 558 | |||
| 559 | err = ad3552r_update_reg_field(dac, | ||
| 560 | AD3552R_REG_ADDR_POWERDOWN_CONFIG, | ||
| 561 | AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch), | ||
| 562 | val); | ||
| 975 | if (err) | 563 | if (err) |
| 976 | return err; | 564 | return err; |
| 977 | } | 565 | } |
| @@ -1140,3 +728,4 @@ module_spi_driver(ad3552r_driver); · 162 unmodified lines | |||
| 1140 | MODULE_AUTHOR("Mihail Chindris <mihail.chindris@analog.com>"); | 728 | MODULE_AUTHOR("Mihail Chindris <mihail.chindris@analog.com>"); |
| 1141 | MODULE_DESCRIPTION("Analog Device AD3552R DAC"); | 729 | MODULE_DESCRIPTION("Analog Device AD3552R DAC"); |
| 1142 | MODULE_LICENSE("GPL v2"); | 730 | MODULE_LICENSE("GPL v2"); |
| 731 | MODULE_IMPORT_NS(IIO_AD3552R); | ||
| @@ -0,0 +1,228 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * AD3552R Digital <-> Analog converters common header | ||
| 4 | * | ||
| 5 | * Copyright 2021-2024 Analog Devices Inc. | ||
| 6 | * Author: Angelo Dureghello <adureghello@baylibre.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef __DRIVERS_IIO_DAC_AD3552R_H__ | ||
| 10 | #define __DRIVERS_IIO_DAC_AD3552R_H__ | ||
| 11 | |||
| 12 | /* Register addresses */ | ||
| 13 | /* Primary address space */ | ||
| 14 | #define AD3552R_REG_ADDR_INTERFACE_CONFIG_A 0x00 | ||
| 15 | #define AD3552R_MASK_SOFTWARE_RESET (BIT(7) | BIT(0)) | ||
| 16 | #define AD3552R_MASK_ADDR_ASCENSION BIT(5) | ||
| 17 | #define AD3552R_MASK_SDO_ACTIVE BIT(4) | ||
| 18 | #define AD3552R_REG_ADDR_INTERFACE_CONFIG_B 0x01 | ||
| 19 | #define AD3552R_MASK_SINGLE_INST BIT(7) | ||
| 20 | #define AD3552R_MASK_SHORT_INSTRUCTION BIT(3) | ||
| 21 | #define AD3552R_REG_ADDR_DEVICE_CONFIG 0x02 | ||
| 22 | #define AD3552R_MASK_DEVICE_STATUS(n) BIT(4 + (n)) | ||
| 23 | #define AD3552R_MASK_CUSTOM_MODES GENMASK(3, 2) | ||
| 24 | #define AD3552R_MASK_OPERATING_MODES GENMASK(1, 0) | ||
| 25 | #define AD3552R_REG_ADDR_CHIP_TYPE 0x03 | ||
| 26 | #define AD3552R_MASK_CLASS GENMASK(7, 0) | ||
| 27 | #define AD3552R_REG_ADDR_PRODUCT_ID_L 0x04 | ||
| 28 | #define AD3552R_REG_ADDR_PRODUCT_ID_H 0x05 | ||
| 29 | #define AD3552R_REG_ADDR_CHIP_GRADE 0x06 | ||
| 30 | #define AD3552R_MASK_GRADE GENMASK(7, 4) | ||
| 31 | #define AD3552R_MASK_DEVICE_REVISION GENMASK(3, 0) | ||
| 32 | #define AD3552R_REG_ADDR_SCRATCH_PAD 0x0A | ||
| 33 | #define AD3552R_REG_ADDR_SPI_REVISION 0x0B | ||
| 34 | #define AD3552R_REG_ADDR_VENDOR_L 0x0C | ||
| 35 | #define AD3552R_REG_ADDR_VENDOR_H 0x0D | ||
| 36 | #define AD3552R_REG_ADDR_STREAM_MODE 0x0E | ||
| 37 | #define AD3552R_MASK_LENGTH GENMASK(7, 0) | ||
| 38 | #define AD3552R_REG_ADDR_TRANSFER_REGISTER 0x0F | ||
| 39 | #define AD3552R_MASK_MULTI_IO_MODE GENMASK(7, 6) | ||
| 40 | #define AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE BIT(2) | ||
| 41 | #define AD3552R_REG_ADDR_INTERFACE_CONFIG_C 0x10 | ||
| 42 | #define AD3552R_MASK_CRC_ENABLE \ | ||
| 43 | (GENMASK(7, 6) | GENMASK(1, 0)) | ||
| 44 | #define AD3552R_MASK_STRICT_REGISTER_ACCESS BIT(5) | ||
| 45 | #define AD3552R_REG_ADDR_INTERFACE_STATUS_A 0x11 | ||
| 46 | #define AD3552R_MASK_INTERFACE_NOT_READY BIT(7) | ||
| 47 | #define AD3552R_MASK_CLOCK_COUNTING_ERROR BIT(5) | ||
| 48 | #define AD3552R_MASK_INVALID_OR_NO_CRC BIT(3) | ||
| 49 | #define AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER BIT(2) | ||
| 50 | #define AD3552R_MASK_PARTIAL_REGISTER_ACCESS BIT(1) | ||
| 51 | #define AD3552R_MASK_REGISTER_ADDRESS_INVALID BIT(0) | ||
| 52 | #define AD3552R_REG_ADDR_INTERFACE_CONFIG_D 0x14 | ||
| 53 | #define AD3552R_MASK_ALERT_ENABLE_PULLUP BIT(6) | ||
| 54 | #define AD3552R_MASK_MEM_CRC_EN BIT(4) | ||
| 55 | #define AD3552R_MASK_SDO_DRIVE_STRENGTH GENMASK(3, 2) | ||
| 56 | #define AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN BIT(1) | ||
| 57 | #define AD3552R_MASK_SPI_CONFIG_DDR BIT(0) | ||
| 58 | #define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG 0x15 | ||
| 59 | #define AD3552R_MASK_IDUMP_FAST_MODE BIT(6) | ||
| 60 | #define AD3552R_MASK_SAMPLE_HOLD_DIFF_USER_EN BIT(5) | ||
| 61 | #define AD3552R_MASK_SAMPLE_HOLD_USER_TRIM GENMASK(4, 3) | ||
| 62 | #define AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE BIT(2) | ||
| 63 | #define AD3552R_MASK_REFERENCE_VOLTAGE_SEL GENMASK(1, 0) | ||
| 64 | #define AD3552R_REG_ADDR_ERR_ALARM_MASK 0x16 | ||
| 65 | #define AD3552R_MASK_REF_RANGE_ALARM BIT(6) | ||
| 66 | #define AD3552R_MASK_CLOCK_COUNT_ERR_ALARM BIT(5) | ||
| 67 | #define AD3552R_MASK_MEM_CRC_ERR_ALARM BIT(4) | ||
| 68 | #define AD3552R_MASK_SPI_CRC_ERR_ALARM BIT(3) | ||
| 69 | #define AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM BIT(2) | ||
| 70 | #define AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM BIT(1) | ||
| 71 | #define AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM BIT(0) | ||
| 72 | #define AD3552R_REG_ADDR_ERR_STATUS 0x17 | ||
| 73 | #define AD3552R_MASK_REF_RANGE_ERR_STATUS BIT(6) | ||
| 74 | #define AD3552R_MASK_STREAM_EXCEEDS_DAC_ERR_STATUS BIT(5) | ||
| 75 | #define AD3552R_MASK_MEM_CRC_ERR_STATUS BIT(4) | ||
| 76 | #define AD3552R_MASK_RESET_STATUS BIT(0) | ||
| 77 | #define AD3552R_REG_ADDR_POWERDOWN_CONFIG 0x18 | ||
| 78 | #define AD3552R_MASK_CH_DAC_POWERDOWN(ch) BIT(4 + (ch)) | ||
| 79 | #define AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch) BIT(ch) | ||
| 80 | #define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE 0x19 | ||
| 81 | #define AD3552R_MASK_CH0_RANGE GENMASK(2, 0) | ||
| 82 | #define AD3552R_MASK_CH1_RANGE GENMASK(6, 4) | ||
| 83 | #define AD3552R_MASK_CH_OUTPUT_RANGE GENMASK(7, 0) | ||
| 84 | #define AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch) \ | ||
| 85 | ((ch) ? GENMASK(7, 4) : GENMASK(3, 0)) | ||
| 86 | #define AD3552R_REG_ADDR_CH_OFFSET(ch) (0x1B + (ch) * 2) | ||
| 87 | #define AD3552R_MASK_CH_OFFSET_BITS_0_7 GENMASK(7, 0) | ||
| 88 | #define AD3552R_REG_ADDR_CH_GAIN(ch) (0x1C + (ch) * 2) | ||
| 89 | #define AD3552R_MASK_CH_RANGE_OVERRIDE BIT(7) | ||
| 90 | #define AD3552R_MASK_CH_GAIN_SCALING_N GENMASK(6, 5) | ||
| 91 | #define AD3552R_MASK_CH_GAIN_SCALING_P GENMASK(4, 3) | ||
| 92 | #define AD3552R_MASK_CH_OFFSET_POLARITY BIT(2) | ||
| 93 | #define AD3552R_MASK_CH_OFFSET_BIT_8 BIT(8) | ||
| 94 | /* | ||
| 95 | * Secondary region | ||
| 96 | * For multibyte registers specify the highest address because the access is | ||
| 97 | * done in descending order | ||
| 98 | */ | ||
| 99 | #define AD3552R_SECONDARY_REGION_START 0x28 | ||
| 100 | #define AD3552R_REG_ADDR_HW_LDAC_16B 0x28 | ||
| 101 | #define AD3552R_REG_ADDR_CH_DAC_16B(ch) (0x2C - (1 - (ch)) * 2) | ||
| 102 | #define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B 0x2E | ||
| 103 | #define AD3552R_REG_ADDR_CH_SELECT_16B 0x2F | ||
| 104 | #define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B 0x31 | ||
| 105 | #define AD3552R_REG_ADDR_SW_LDAC_16B 0x32 | ||
| 106 | #define AD3552R_REG_ADDR_CH_INPUT_16B(ch) (0x36 - (1 - (ch)) * 2) | ||
| 107 | /* 3 bytes registers */ | ||
| 108 | #define AD3552R_REG_START_24B 0x37 | ||
| 109 | #define AD3552R_REG_ADDR_HW_LDAC_24B 0x37 | ||
| 110 | #define AD3552R_REG_ADDR_CH_DAC_24B(ch) (0x3D - (1 - (ch)) * 3) | ||
| 111 | #define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B 0x40 | ||
| 112 | #define AD3552R_REG_ADDR_CH_SELECT_24B 0x41 | ||
| 113 | #define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B 0x44 | ||
| 114 | #define AD3552R_REG_ADDR_SW_LDAC_24B 0x45 | ||
| 115 | #define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - (ch)) * 3) | ||
| 116 | |||
| 117 | #define AD3552R_MAX_CH 2 | ||
| 118 | #define AD3552R_MASK_CH(ch) BIT(ch) | ||
| 119 | #define AD3552R_MASK_ALL_CH GENMASK(1, 0) | ||
| 120 | #define AD3552R_MAX_REG_SIZE 3 | ||
| 121 | #define AD3552R_READ_BIT BIT(7) | ||
| 122 | #define AD3552R_ADDR_MASK GENMASK(6, 0) | ||
| 123 | #define AD3552R_MASK_DAC_12B GENMASK(15, 4) | ||
| 124 | #define AD3552R_DEFAULT_CONFIG_B_VALUE 0x8 | ||
| 125 | #define AD3552R_SCRATCH_PAD_TEST_VAL1 0x34 | ||
| 126 | #define AD3552R_SCRATCH_PAD_TEST_VAL2 0xB2 | ||
| 127 | #define AD3552R_GAIN_SCALE 1000 | ||
| 128 | #define AD3552R_LDAC_PULSE_US 100 | ||
| 129 | |||
| 130 | #define AD3552R_CH0_ACTIVE BIT(0) | ||
| 131 | #define AD3552R_CH1_ACTIVE BIT(1) | ||
| 132 | |||
| 133 | #define AD3552R_MAX_RANGES 5 | ||
| 134 | #define AD3542R_MAX_RANGES 6 | ||
| 135 | #define AD3552R_QUAD_SPI 2 | ||
| 136 | |||
| 137 | extern const s32 ad3552r_ch_ranges[AD3552R_MAX_RANGES][2]; | ||
| 138 | extern const s32 ad3542r_ch_ranges[AD3542R_MAX_RANGES][2]; | ||
| 139 | |||
| 140 | enum ad3552r_id { | ||
| 141 | AD3541R_ID = 0x400b, | ||
| 142 | AD3542R_ID = 0x4009, | ||
| 143 | AD3551R_ID = 0x400a, | ||
| 144 | AD3552R_ID = 0x4008, | ||
| 145 | }; | ||
| 146 | |||
| 147 | struct ad3552r_model_data { | ||
| 148 | const char *model_name; | ||
| 149 | enum ad3552r_id chip_id; | ||
| 150 | unsigned int num_hw_channels; | ||
| 151 | const s32 (*ranges_table)[2]; | ||
| 152 | int num_ranges; | ||
| 153 | bool requires_output_range; | ||
| 154 | }; | ||
| 155 | |||
| 156 | struct ad3552r_ch_data { | ||
| 157 | s32 scale_int; | ||
| 158 | s32 scale_dec; | ||
| 159 | s32 offset_int; | ||
| 160 | s32 offset_dec; | ||
| 161 | s16 gain_offset; | ||
| 162 | u16 rfb; | ||
| 163 | u8 n; | ||
| 164 | u8 p; | ||
| 165 | u8 range; | ||
| 166 | bool range_override; | ||
| 167 | }; | ||
| 168 | |||
| 169 | enum ad3552r_ch_gain_scaling { | ||
| 170 | /* Gain scaling of 1 */ | ||
| 171 | AD3552R_CH_GAIN_SCALING_1, | ||
| 172 | /* Gain scaling of 0.5 */ | ||
| 173 | AD3552R_CH_GAIN_SCALING_0_5, | ||
| 174 | /* Gain scaling of 0.25 */ | ||
| 175 | AD3552R_CH_GAIN_SCALING_0_25, | ||
| 176 | /* Gain scaling of 0.125 */ | ||
| 177 | AD3552R_CH_GAIN_SCALING_0_125, | ||
| 178 | }; | ||
| 179 | |||
| 180 | enum ad3552r_ch_vref_select { | ||
| 181 | /* Internal source with Vref I/O floating */ | ||
| 182 | AD3552R_INTERNAL_VREF_PIN_FLOATING, | ||
| 183 | /* Internal source with Vref I/O at 2.5V */ | ||
| 184 | AD3552R_INTERNAL_VREF_PIN_2P5V, | ||
| 185 | /* External source with Vref I/O as input */ | ||
| 186 | AD3552R_EXTERNAL_VREF_PIN_INPUT | ||
| 187 | }; | ||
| 188 | |||
| 189 | enum ad3542r_ch_output_range { | ||
| 190 | /* Range from 0 V to 2.5 V. Requires Rfb1x connection */ | ||
| 191 | AD3542R_CH_OUTPUT_RANGE_0__2P5V, | ||
| 192 | /* Range from 0 V to 3 V. Requires Rfb1x connection */ | ||
| 193 | AD3542R_CH_OUTPUT_RANGE_0__3V, | ||
| 194 | /* Range from 0 V to 5 V. Requires Rfb1x connection */ | ||
| 195 | AD3542R_CH_OUTPUT_RANGE_0__5V, | ||
| 196 | /* Range from 0 V to 10 V. Requires Rfb2x connection */ | ||
| 197 | AD3542R_CH_OUTPUT_RANGE_0__10V, | ||
| 198 | /* Range from -2.5 V to 7.5 V. Requires Rfb2x connection */ | ||
| 199 | AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V, | ||
| 200 | /* Range from -5 V to 5 V. Requires Rfb2x connection */ | ||
| 201 | AD3542R_CH_OUTPUT_RANGE_NEG_5__5V, | ||
| 202 | }; | ||
| 203 | |||
| 204 | enum ad3552r_ch_output_range { | ||
| 205 | /* Range from 0 V to 2.5 V. Requires Rfb1x connection */ | ||
| 206 | AD3552R_CH_OUTPUT_RANGE_0__2P5V, | ||
| 207 | /* Range from 0 V to 5 V. Requires Rfb1x connection */ | ||
| 208 | AD3552R_CH_OUTPUT_RANGE_0__5V, | ||
| 209 | /* Range from 0 V to 10 V. Requires Rfb2x connection */ | ||
| 210 | AD3552R_CH_OUTPUT_RANGE_0__10V, | ||
| 211 | /* Range from -5 V to 5 V. Requires Rfb2x connection */ | ||
| 212 | AD3552R_CH_OUTPUT_RANGE_NEG_5__5V, | ||
| 213 | /* Range from -10 V to 10 V. Requires Rfb4x connection */ | ||
| 214 | AD3552R_CH_OUTPUT_RANGE_NEG_10__10V, | ||
| 215 | }; | ||
| 216 | |||
| 217 | int ad3552r_get_output_range(struct device *dev, | ||
| 218 | const struct ad3552r_model_data *model_info, | ||
| 219 | struct fwnode_handle *child, u32 *val); | ||
| 220 | int ad3552r_get_custom_gain(struct device *dev, struct fwnode_handle *child, | ||
| 221 | u8 *gs_p, u8 *gs_n, u16 *rfb, s16 *goffs); | ||
| 222 | u16 ad3552r_calc_custom_gain(u8 p, u8 n, s16 goffs); | ||
| 223 | int ad3552r_get_ref_voltage(struct device *dev, u32 *val); | ||
| 224 | int ad3552r_get_drive_strength(struct device *dev, u32 *val); | ||
| 225 | void ad3552r_calc_gain_and_offset(struct ad3552r_ch_data *ch_data, | ||
| 226 | const struct ad3552r_model_data *model_data); | ||
| 227 | |||
| 228 | #endif /* __DRIVERS_IIO_DAC_AD3552R_H__ */ | ||
| @@ -47,7 +47,6 @@ struct ad5380_chip_info { · 46 unmodified lines | |||
| 47 | * struct ad5380_state - driver instance specific data | 47 | * struct ad5380_state - driver instance specific data |
| 48 | * @regmap: regmap instance used by the device | 48 | * @regmap: regmap instance used by the device |
| 49 | * @chip_info: chip model specific constants, available modes etc | 49 | * @chip_info: chip model specific constants, available modes etc |
| 50 | * @vref_reg: vref supply regulator | ||
| 51 | * @vref: actual reference voltage used in uA | 50 | * @vref: actual reference voltage used in uA |
| 52 | * @pwr_down: whether the chip is currently in power down mode | 51 | * @pwr_down: whether the chip is currently in power down mode |
| 53 | * @lock: lock to protect the data buffer during regmap ops | 52 | * @lock: lock to protect the data buffer during regmap ops |
| @@ -55,7 +54,6 @@ struct ad5380_chip_info { · 1 unmodified line | |||
| 55 | struct ad5380_state { | 54 | struct ad5380_state { |
| 56 | struct regmap *regmap; | 55 | struct regmap *regmap; |
| 57 | const struct ad5380_chip_info *chip_info; | 56 | const struct ad5380_chip_info *chip_info; |
| 58 | struct regulator *vref_reg; | ||
| 59 | int vref; | 57 | int vref; |
| 60 | bool pwr_down; | 58 | bool pwr_down; |
| 61 | struct mutex lock; | 59 | struct mutex lock; |
| @@ -341,14 +339,14 @@ static const struct ad5380_chip_info ad5380_chip_info_tbl[] = { · 279 unmodified lines | |||
| 341 | }, | 339 | }, |
| 342 | }; | 340 | }; |
| 343 | 341 | ||
| 344 | static int ad5380_alloc_channels(struct iio_dev *indio_dev) | 342 | static int ad5380_alloc_channels(struct device *dev, struct iio_dev *indio_dev) |
| 345 | { | 343 | { |
| 346 | struct ad5380_state *st = iio_priv(indio_dev); | 344 | struct ad5380_state *st = iio_priv(indio_dev); |
| 347 | struct iio_chan_spec *channels; | 345 | struct iio_chan_spec *channels; |
| 348 | unsigned int i; | 346 | unsigned int i; |
| 349 | 347 | ||
| 350 | channels = kcalloc(st->chip_info->num_channels, | 348 | channels = devm_kcalloc(dev, st->chip_info->num_channels, |
| 351 | sizeof(struct iio_chan_spec), GFP_KERNEL); | 349 | sizeof(struct iio_chan_spec), GFP_KERNEL); |
| 352 | 350 | ||
| 353 | if (!channels) | 351 | if (!channels) |
| 354 | return -ENOMEM; | 352 | return -ENOMEM; |
| @@ -379,7 +377,6 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap, · 24 unmodified lines | |||
| 379 | } | 377 | } |
| 380 | 378 | ||
| 381 | st = iio_priv(indio_dev); | 379 | st = iio_priv(indio_dev); |
| 382 | dev_set_drvdata(dev, indio_dev); | ||
| 383 | 380 | ||
| 384 | st->chip_info = &ad5380_chip_info_tbl[type]; | 381 | st->chip_info = &ad5380_chip_info_tbl[type]; |
| 385 | st->regmap = regmap; | 382 | st->regmap = regmap; |
| @@ -391,68 +388,32 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap, · 5 unmodified lines | |||
| 391 | 388 | ||
| 392 | mutex_init(&st->lock); | 389 | mutex_init(&st->lock); |
| 393 | 390 | ||
| 394 | ret = ad5380_alloc_channels(indio_dev); | 391 | ret = ad5380_alloc_channels(dev, indio_dev); |
| 395 | if (ret) { | 392 | if (ret) |
| 396 | dev_err(dev, "Failed to allocate channel spec: %d\n", ret); | 393 | return dev_err_probe(dev, ret, "Failed to allocate channel spec\n"); |
| 397 | return ret; | ||
| 398 | } | ||
| 399 | 394 | ||
| 400 | if (st->chip_info->int_vref == 2500) | 395 | if (st->chip_info->int_vref == 2500) |
| 401 | ctrl |= AD5380_CTRL_INT_VREF_2V5; | 396 | ctrl |= AD5380_CTRL_INT_VREF_2V5; |
| 402 | 397 | ||
| 403 | st->vref_reg = devm_regulator_get(dev, "vref"); | 398 | ret = devm_regulator_get_enable_read_voltage(dev, "vref"); |
| 404 | if (!IS_ERR(st->vref_reg)) { | 399 | if (ret < 0 && ret != -ENODEV) |
| 405 | ret = regulator_enable(st->vref_reg); | 400 | return dev_err_probe(dev, ret, "Failed to get vref voltage\n"); |
| 406 | if (ret) { | 401 | if (ret == -ENODEV) { |
| 407 | dev_err(dev, "Failed to enable vref regulators: %d\n", | ||
| 408 | ret); | ||
| 409 | goto error_free_reg; | ||
| 410 | } | ||
| 411 | |||
| 412 | ret = regulator_get_voltage(st->vref_reg); | ||
| 413 | if (ret < 0) | ||
| 414 | goto error_disable_reg; | ||
| 415 | |||
| 416 | st->vref = ret / 1000; | ||
| 417 | } else { | ||
| 418 | st->vref = st->chip_info->int_vref; | 402 | st->vref = st->chip_info->int_vref; |
| 419 | ctrl |= AD5380_CTRL_INT_VREF_EN; | 403 | ctrl |= AD5380_CTRL_INT_VREF_EN; |
| 404 | } else { | ||
| 405 | st->vref = ret / 1000; | ||
| 420 | } | 406 | } |
| 421 | 407 | ||
| 422 | ret = regmap_write(st->regmap, AD5380_REG_SF_CTRL, ctrl); | 408 | ret = regmap_write(st->regmap, AD5380_REG_SF_CTRL, ctrl); |
| 423 | if (ret) { | 409 | if (ret) |
| 424 | dev_err(dev, "Failed to write to device: %d\n", ret); | 410 | return dev_err_probe(dev, ret, "Failed to write to device\n"); |
| 425 | goto error_disable_reg; | ||
| 426 | } | ||
| 427 | 411 | ||
| 428 | ret = iio_device_register(indio_dev); | 412 | ret = devm_iio_device_register(dev, indio_dev); |
| 429 | if (ret) { | 413 | if (ret) |
| 430 | dev_err(dev, "Failed to register iio device: %d\n", ret); | 414 | return dev_err_probe(dev, ret, "Failed to register iio device\n"); |
| 431 | goto error_disable_reg; | ||
| 432 | } | ||
| 433 | 415 | ||
| 434 | return 0; | 416 | return 0; |
| 435 | |||
| 436 | error_disable_reg: | ||
| 437 | if (!IS_ERR(st->vref_reg)) | ||
| 438 | regulator_disable(st->vref_reg); | ||
| 439 | error_free_reg: | ||
| 440 | kfree(indio_dev->channels); | ||
| 441 | |||
| 442 | return ret; | ||
| 443 | } | ||
| 444 | |||
| 445 | static void ad5380_remove(struct device *dev) | ||
| 446 | { | ||
| 447 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
| 448 | struct ad5380_state *st = iio_priv(indio_dev); | ||
| 449 | |||
| 450 | iio_device_unregister(indio_dev); | ||
| 451 | |||
| 452 | kfree(indio_dev->channels); | ||
| 453 | |||
| 454 | if (!IS_ERR(st->vref_reg)) | ||
| 455 | regulator_disable(st->vref_reg); | ||
| 456 | } | 417 | } |
| 457 | 418 | ||
| 458 | static bool ad5380_reg_false(struct device *dev, unsigned int reg) | 419 | static bool ad5380_reg_false(struct device *dev, unsigned int reg) |
| @@ -486,11 +447,6 @@ static int ad5380_spi_probe(struct spi_device *spi) · 27 unmodified lines | |||
| 486 | return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name); | 447 | return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name); |
| 487 | } | 448 | } |
| 488 | 449 | ||
| 489 | static void ad5380_spi_remove(struct spi_device *spi) | ||
| 490 | { | ||
| 491 | ad5380_remove(&spi->dev); | ||
| 492 | } | ||
| 493 | |||
| 494 | static const struct spi_device_id ad5380_spi_ids[] = { | 450 | static const struct spi_device_id ad5380_spi_ids[] = { |
| 495 | { "ad5380-3", ID_AD5380_3 }, | 451 | { "ad5380-3", ID_AD5380_3 }, |
| 496 | { "ad5380-5", ID_AD5380_5 }, | 452 | { "ad5380-5", ID_AD5380_5 }, |
| @@ -517,7 +473,6 @@ static struct spi_driver ad5380_spi_driver = { · 20 unmodified lines | |||
| 517 | .name = "ad5380", | 473 | .name = "ad5380", |
| 518 | }, | 474 | }, |
| 519 | .probe = ad5380_spi_probe, | 475 | .probe = ad5380_spi_probe, |
| 520 | .remove = ad5380_spi_remove, | ||
| 521 | .id_table = ad5380_spi_ids, | 476 | .id_table = ad5380_spi_ids, |
| 522 | }; | 477 | }; |
| 523 | 478 | ||
| @@ -559,11 +514,6 @@ static int ad5380_i2c_probe(struct i2c_client *i2c) · 35 unmodified lines | |||
| 559 | return ad5380_probe(&i2c->dev, regmap, id->driver_data, id->name); | 514 | return ad5380_probe(&i2c->dev, regmap, id->driver_data, id->name); |
| 560 | } | 515 | } |
| 561 | 516 | ||
| 562 | static void ad5380_i2c_remove(struct i2c_client *i2c) | ||
| 563 | { | ||
| 564 | ad5380_remove(&i2c->dev); | ||
| 565 | } | ||
| 566 | |||
| 567 | static const struct i2c_device_id ad5380_i2c_ids[] = { | 517 | static const struct i2c_device_id ad5380_i2c_ids[] = { |
| 568 | { "ad5380-3", ID_AD5380_3 }, | 518 | { "ad5380-3", ID_AD5380_3 }, |
| 569 | { "ad5380-5", ID_AD5380_5 }, | 519 | { "ad5380-5", ID_AD5380_5 }, |
| @@ -590,7 +540,6 @@ static struct i2c_driver ad5380_i2c_driver = { · 20 unmodified lines | |||
| 590 | .name = "ad5380", | 540 | .name = "ad5380", |
| 591 | }, | 541 | }, |
| 592 | .probe = ad5380_i2c_probe, | 542 | .probe = ad5380_i2c_probe, |
| 593 | .remove = ad5380_i2c_remove, | ||
| 594 | .id_table = ad5380_i2c_ids, | 543 | .id_table = ad5380_i2c_ids, |
| 595 | }; | 544 | }; |
| 596 | 545 | ||
| @@ -384,7 +384,7 @@ static int ad5421_write_raw(struct iio_dev *indio_dev, · 383 unmodified lines | |||
| 384 | 384 | ||
| 385 | static int ad5421_write_event_config(struct iio_dev *indio_dev, | 385 | static int ad5421_write_event_config(struct iio_dev *indio_dev, |
| 386 | const struct iio_chan_spec *chan, enum iio_event_type type, | 386 | const struct iio_chan_spec *chan, enum iio_event_type type, |
| 387 | enum iio_event_direction dir, int state) | 387 | enum iio_event_direction dir, bool state) |
| 388 | { | 388 | { |
| 389 | struct ad5421_state *st = iio_priv(indio_dev); | 389 | struct ad5421_state *st = iio_priv(indio_dev); |
| 390 | unsigned int mask; | 390 | unsigned int mask; |
| @@ -32,7 +32,6 @@ · 31 unmodified lines | |||
| 32 | * struct ad5446_state - driver instance specific data | 32 | * struct ad5446_state - driver instance specific data |
| 33 | * @dev: this device | 33 | * @dev: this device |
| 34 | * @chip_info: chip model specific constants, available modes etc | 34 | * @chip_info: chip model specific constants, available modes etc |
| 35 | * @reg: supply regulator | ||
| 36 | * @vref_mv: actual reference voltage used | 35 | * @vref_mv: actual reference voltage used |
| 37 | * @cached_val: store/retrieve values during power down | 36 | * @cached_val: store/retrieve values during power down |
| 38 | * @pwr_down_mode: power down mode (1k, 100k or tristate) | 37 | * @pwr_down_mode: power down mode (1k, 100k or tristate) |
| @@ -43,7 +42,6 @@ · 4 unmodified lines | |||
| 43 | struct ad5446_state { | 42 | struct ad5446_state { |
| 44 | struct device *dev; | 43 | struct device *dev; |
| 45 | const struct ad5446_chip_info *chip_info; | 44 | const struct ad5446_chip_info *chip_info; |
| 46 | struct regulator *reg; | ||
| 47 | unsigned short vref_mv; | 45 | unsigned short vref_mv; |
| 48 | unsigned cached_val; | 46 | unsigned cached_val; |
| 49 | unsigned pwr_down_mode; | 47 | unsigned pwr_down_mode; |
| @@ -226,32 +224,15 @@ static int ad5446_probe(struct device *dev, const char *name, · 176 unmodified lines | |||
| 226 | { | 224 | { |
| 227 | struct ad5446_state *st; | 225 | struct ad5446_state *st; |
| 228 | struct iio_dev *indio_dev; | 226 | struct iio_dev *indio_dev; |
| 229 | struct regulator *reg; | 227 | int ret; |
| 230 | int ret, voltage_uv = 0; | ||
| 231 | |||
| 232 | reg = devm_regulator_get(dev, "vcc"); | ||
| 233 | if (!IS_ERR(reg)) { | ||
| 234 | ret = regulator_enable(reg); | ||
| 235 | if (ret) | ||
| 236 | return ret; | ||
| 237 | |||
| 238 | ret = regulator_get_voltage(reg); | ||
| 239 | if (ret < 0) | ||
| 240 | goto error_disable_reg; | ||
| 241 | |||
| 242 | voltage_uv = ret; | ||
| 243 | } | ||
| 244 | 228 | ||
| 245 | indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); | 229 | indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); |
| 246 | if (indio_dev == NULL) { | 230 | if (!indio_dev) |
| 247 | ret = -ENOMEM; | 231 | return -ENOMEM; |
| 248 | goto error_disable_reg; | 232 | |
| 249 | } | ||
| 250 | st = iio_priv(indio_dev); | 233 | st = iio_priv(indio_dev); |
| 251 | st->chip_info = chip_info; | 234 | st->chip_info = chip_info; |
| 252 | 235 | ||
| 253 | dev_set_drvdata(dev, indio_dev); | ||
| 254 | st->reg = reg; | ||
| 255 | st->dev = dev; | 236 | st->dev = dev; |
| 256 | 237 | ||
| 257 | indio_dev->name = name; | 238 | indio_dev->name = name; |
| @@ -264,33 +245,19 @@ static int ad5446_probe(struct device *dev, const char *name, · 6 unmodified lines | |||
| 264 | 245 | ||
| 265 | st->pwr_down_mode = MODE_PWRDWN_1k; | 246 | st->pwr_down_mode = MODE_PWRDWN_1k; |
| 266 | 247 | ||
| 267 | if (st->chip_info->int_vref_mv) | 248 | ret = devm_regulator_get_enable_read_voltage(dev, "vcc"); |
| 268 | st->vref_mv = st->chip_info->int_vref_mv; | 249 | if (ret < 0 && ret != -ENODEV) |
| 269 | else if (voltage_uv) | 250 | return ret; |
| 270 | st->vref_mv = voltage_uv / 1000; | 251 | if (ret == -ENODEV) { |
| 271 | else | 252 | if (chip_info->int_vref_mv) |
| 272 | dev_warn(dev, "reference voltage unspecified\n"); | 253 | st->vref_mv = chip_info->int_vref_mv; |
| 273 | 254 | else | |
| 274 | ret = iio_device_register(indio_dev); | 255 | dev_warn(dev, "reference voltage unspecified\n"); |
| 275 | if (ret) | 256 | } else { |
| 276 | goto error_disable_reg; | 257 | st->vref_mv = ret / 1000; |
| 277 | 258 | } | |
| 278 | return 0; | ||
| 279 | |||
| 280 | error_disable_reg: | ||
| 281 | if (!IS_ERR(reg)) | ||
| 282 | regulator_disable(reg); | ||
| 283 | return ret; | ||
| 284 | } | ||
| 285 | |||
| 286 | static void ad5446_remove(struct device *dev) | ||
| 287 | { | ||
| 288 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
| 289 | struct ad5446_state *st = iio_priv(indio_dev); | ||
| 290 | 259 | ||
| 291 | iio_device_unregister(indio_dev); | 260 | return devm_iio_device_register(dev, indio_dev); |
| 292 | if (!IS_ERR(st->reg)) | ||
| 293 | regulator_disable(st->reg); | ||
| 294 | } | 261 | } |
| 295 | 262 | ||
| 296 | #if IS_ENABLED(CONFIG_SPI_MASTER) | 263 | #if IS_ENABLED(CONFIG_SPI_MASTER) |
| @@ -491,18 +458,12 @@ static int ad5446_spi_probe(struct spi_device *spi) · 194 unmodified lines | |||
| 491 | &ad5446_spi_chip_info[id->driver_data]); | 458 | &ad5446_spi_chip_info[id->driver_data]); |
| 492 | } | 459 | } |
| 493 | 460 | ||
| 494 | static void ad5446_spi_remove(struct spi_device *spi) | ||
| 495 | { | ||
| 496 | ad5446_remove(&spi->dev); | ||
| 497 | } | ||
| 498 | |||
| 499 | static struct spi_driver ad5446_spi_driver = { | 461 | static struct spi_driver ad5446_spi_driver = { |
| 500 | .driver = { | 462 | .driver = { |
| 501 | .name = "ad5446", | 463 | .name = "ad5446", |
| 502 | .of_match_table = ad5446_of_ids, | 464 | .of_match_table = ad5446_of_ids, |
| 503 | }, | 465 | }, |
| 504 | .probe = ad5446_spi_probe, | 466 | .probe = ad5446_spi_probe, |
| 505 | .remove = ad5446_spi_remove, | ||
| 506 | .id_table = ad5446_spi_ids, | 467 | .id_table = ad5446_spi_ids, |
| 507 | }; | 468 | }; |
| 508 | 469 | ||
| @@ -575,11 +536,6 @@ static int ad5446_i2c_probe(struct i2c_client *i2c) · 66 unmodified lines | |||
| 575 | &ad5446_i2c_chip_info[id->driver_data]); | 536 | &ad5446_i2c_chip_info[id->driver_data]); |
| 576 | } | 537 | } |
| 577 | 538 | ||
| 578 | static void ad5446_i2c_remove(struct i2c_client *i2c) | ||
| 579 | { | ||
| 580 | ad5446_remove(&i2c->dev); | ||
| 581 | } | ||
| 582 | |||
| 583 | static const struct i2c_device_id ad5446_i2c_ids[] = { | 539 | static const struct i2c_device_id ad5446_i2c_ids[] = { |
| 584 | {"ad5301", ID_AD5602}, | 540 | {"ad5301", ID_AD5602}, |
| 585 | {"ad5311", ID_AD5612}, | 541 | {"ad5311", ID_AD5612}, |
| @@ -596,7 +552,6 @@ static struct i2c_driver ad5446_i2c_driver = { · 10 unmodified lines | |||
| 596 | .name = "ad5446", | 552 | .name = "ad5446", |
| 597 | }, | 553 | }, |
| 598 | .probe = ad5446_i2c_probe, | 554 | .probe = ad5446_i2c_probe, |
| 599 | .remove = ad5446_i2c_remove, | ||
| 600 | .id_table = ad5446_i2c_ids, | 555 | .id_table = ad5446_i2c_ids, |
| 601 | }; | 556 | }; |
| 602 | 557 | ||
| @@ -270,38 +270,29 @@ static const struct iio_chan_spec ad5504_channels[] = { · 269 unmodified lines | |||
| 270 | 270 | ||
| 271 | static int ad5504_probe(struct spi_device *spi) | 271 | static int ad5504_probe(struct spi_device *spi) |
| 272 | { | 272 | { |
| 273 | struct ad5504_platform_data *pdata = spi->dev.platform_data; | 273 | const struct ad5504_platform_data *pdata = dev_get_platdata(&spi->dev); |
| 274 | struct iio_dev *indio_dev; | 274 | struct iio_dev *indio_dev; |
| 275 | struct ad5504_state *st; | 275 | struct ad5504_state *st; |
| 276 | struct regulator *reg; | 276 | int ret; |
| 277 | int ret, voltage_uv = 0; | ||
| 278 | 277 | ||
| 279 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); | 278 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); |
| 280 | if (!indio_dev) | 279 | if (!indio_dev) |
| 281 | return -ENOMEM; | 280 | return -ENOMEM; |
| 282 | reg = devm_regulator_get(&spi->dev, "vcc"); | ||
| 283 | if (!IS_ERR(reg)) { | ||
| 284 | ret = regulator_enable(reg); | ||
| 285 | if (ret) | ||
| 286 | return ret; | ||
| 287 | 281 | ||
| 288 | ret = regulator_get_voltage(reg); | 282 | st = iio_priv(indio_dev); |
| 289 | if (ret < 0) | ||
| 290 | goto error_disable_reg; | ||
| 291 | 283 | ||
| 292 | voltage_uv = ret; | 284 | ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcc"); |
| 285 | if (ret < 0 && ret != -ENODEV) | ||
| 286 | return ret; | ||
| 287 | if (ret == -ENODEV) { | ||
| 288 | if (pdata->vref_mv) | ||
| 289 | st->vref_mv = pdata->vref_mv; | ||
| 290 | else | ||
| 291 | dev_warn(&spi->dev, "reference voltage unspecified\n"); | ||
| 292 | } else { | ||
| 293 | st->vref_mv = ret / 1000; | ||
| 293 | } | 294 | } |
| 294 | 295 | ||
| 295 | spi_set_drvdata(spi, indio_dev); | ||
| 296 | st = iio_priv(indio_dev); | ||
| 297 | if (voltage_uv) | ||
| 298 | st->vref_mv = voltage_uv / 1000; | ||
| 299 | else if (pdata) | ||
| 300 | st->vref_mv = pdata->vref_mv; | ||
| 301 | else | ||
| 302 | dev_warn(&spi->dev, "reference voltage unspecified\n"); | ||
| 303 | |||
| 304 | st->reg = reg; | ||
| 305 | st->spi = spi; | 296 | st->spi = spi; |
| 306 | indio_dev->name = spi_get_device_id(st->spi)->name; | 297 | indio_dev->name = spi_get_device_id(st->spi)->name; |
| 307 | indio_dev->info = &ad5504_info; | 298 | indio_dev->info = &ad5504_info; |
| @@ -320,31 +311,10 @@ static int ad5504_probe(struct spi_device *spi) · 12 unmodified lines | |||
| 320 | spi_get_device_id(st->spi)->name, | 311 | spi_get_device_id(st->spi)->name, |
| 321 | indio_dev); | 312 | indio_dev); |
| 322 | if (ret) | 313 | if (ret) |
| 323 | goto error_disable_reg; | 314 | return ret; |
| 324 | } | 315 | } |
| 325 | 316 | ||
| 326 | ret = iio_device_register(indio_dev); | 317 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 327 | if (ret) | ||
| 328 | goto error_disable_reg; | ||
| 329 | |||
| 330 | return 0; | ||
| 331 | |||
| 332 | error_disable_reg: | ||
| 333 | if (!IS_ERR(reg)) | ||
| 334 | regulator_disable(reg); | ||
| 335 | |||
| 336 | return ret; | ||
| 337 | } | ||
| 338 | |||
| 339 | static void ad5504_remove(struct spi_device *spi) | ||
| 340 | { | ||
| 341 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 342 | struct ad5504_state *st = iio_priv(indio_dev); | ||
| 343 | |||
| 344 | iio_device_unregister(indio_dev); | ||
| 345 | |||
| 346 | if (!IS_ERR(st->reg)) | ||
| 347 | regulator_disable(st->reg); | ||
| 348 | } | 318 | } |
| 349 | 319 | ||
| 350 | static const struct spi_device_id ad5504_id[] = { | 320 | static const struct spi_device_id ad5504_id[] = { |
| @@ -359,7 +329,6 @@ static struct spi_driver ad5504_driver = { · 8 unmodified lines | |||
| 359 | .name = "ad5504", | 329 | .name = "ad5504", |
| 360 | }, | 330 | }, |
| 361 | .probe = ad5504_probe, | 331 | .probe = ad5504_probe, |
| 362 | .remove = ad5504_remove, | ||
| 363 | .id_table = ad5504_id, | 332 | .id_table = ad5504_id, |
| 364 | }; | 333 | }; |
| 365 | module_spi_driver(ad5504_driver); | 334 | module_spi_driver(ad5504_driver); |
| @@ -54,7 +54,6 @@ struct ad5624r_chip_info { · 53 unmodified lines | |||
| 54 | struct ad5624r_state { | 54 | struct ad5624r_state { |
| 55 | struct spi_device *us; | 55 | struct spi_device *us; |
| 56 | const struct ad5624r_chip_info *chip_info; | 56 | const struct ad5624r_chip_info *chip_info; |
| 57 | struct regulator *reg; | ||
| 58 | unsigned short vref_mv; | 57 | unsigned short vref_mv; |
| 59 | unsigned pwr_down_mask; | 58 | unsigned pwr_down_mask; |
| 60 | unsigned pwr_down_mode; | 59 | unsigned pwr_down_mode; |
| @@ -223,50 +223,26 @@ static int ad5624r_probe(struct spi_device *spi) · 222 unmodified lines | |||
| 223 | { | 223 | { |
| 224 | struct ad5624r_state *st; | 224 | struct ad5624r_state *st; |
| 225 | struct iio_dev *indio_dev; | 225 | struct iio_dev *indio_dev; |
| 226 | int ret, voltage_uv = 0; | 226 | bool external_vref; |
| 227 | int ret; | ||
| 227 | 228 | ||
| 228 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); | 229 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); |
| 229 | if (!indio_dev) | 230 | if (!indio_dev) |
| 230 | return -ENOMEM; | 231 | return -ENOMEM; |
| 231 | st = iio_priv(indio_dev); | 232 | st = iio_priv(indio_dev); |
| 232 | st->reg = devm_regulator_get_optional(&spi->dev, "vref"); | 233 | ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref"); |
| 233 | if (!IS_ERR(st->reg)) { | 234 | if (ret == -ENODEV) |
| 234 | ret = regulator_enable(st->reg); | ||
| 235 | if (ret) | ||
| 236 | return ret; | ||
| 237 | |||
| 238 | ret = regulator_get_voltage(st->reg); | ||
| 239 | if (ret < 0) | ||
| 240 | goto error_disable_reg; | ||
| 241 | |||
| 242 | voltage_uv = ret; | ||
| 243 | } else { | ||
| 244 | if (PTR_ERR(st->reg) != -ENODEV) | ||
| 245 | return PTR_ERR(st->reg); | ||
| 246 | /* Backwards compatibility. This naming is not correct */ | 235 | /* Backwards compatibility. This naming is not correct */ |
| 247 | st->reg = devm_regulator_get_optional(&spi->dev, "vcc"); | 236 | ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcc"); |
| 248 | if (!IS_ERR(st->reg)) { | 237 | if (ret < 0 && ret != -ENODEV) |
| 249 | ret = regulator_enable(st->reg); | 238 | return ret; |
| 250 | if (ret) | 239 | |
| 251 | return ret; | 240 | external_vref = ret != -ENODEV; |
| 252 | 241 | st->vref_mv = external_vref ? ret / 1000 : st->chip_info->int_vref_mv; | |
| 253 | ret = regulator_get_voltage(st->reg); | ||
| 254 | if (ret < 0) | ||
| 255 | goto error_disable_reg; | ||
| 256 | |||
| 257 | voltage_uv = ret; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | 242 | ||
| 261 | spi_set_drvdata(spi, indio_dev); | ||
| 262 | st->chip_info = | 243 | st->chip_info = |
| 263 | &ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | 244 | &ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data]; |
| 264 | 245 | ||
| 265 | if (voltage_uv) | ||
| 266 | st->vref_mv = voltage_uv / 1000; | ||
| 267 | else | ||
| 268 | st->vref_mv = st->chip_info->int_vref_mv; | ||
| 269 | |||
| 270 | st->us = spi; | 246 | st->us = spi; |
| 271 | 247 | ||
| 272 | indio_dev->name = spi_get_device_id(spi)->name; | 248 | indio_dev->name = spi_get_device_id(spi)->name; |
| @@ -276,31 +252,11 @@ static int ad5624r_probe(struct spi_device *spi) · 3 unmodified lines | |||
| 276 | indio_dev->num_channels = AD5624R_DAC_CHANNELS; | 252 | indio_dev->num_channels = AD5624R_DAC_CHANNELS; |
| 277 | 253 | ||
| 278 | ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0, | 254 | ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0, |
| 279 | !!voltage_uv, 16); | 255 | external_vref, 16); |
| 280 | if (ret) | ||
| 281 | goto error_disable_reg; | ||
| 282 | |||
| 283 | ret = iio_device_register(indio_dev); | ||
| 284 | if (ret) | 256 | if (ret) |
| 285 | goto error_disable_reg; | 257 | return ret; |
| 286 | |||
| 287 | return 0; | ||
| 288 | |||
| 289 | error_disable_reg: | ||
| 290 | if (!IS_ERR(st->reg)) | ||
| 291 | regulator_disable(st->reg); | ||
| 292 | |||
| 293 | return ret; | ||
| 294 | } | ||
| 295 | |||
| 296 | static void ad5624r_remove(struct spi_device *spi) | ||
| 297 | { | ||
| 298 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 299 | struct ad5624r_state *st = iio_priv(indio_dev); | ||
| 300 | 258 | ||
| 301 | iio_device_unregister(indio_dev); | 259 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 302 | if (!IS_ERR(st->reg)) | ||
| 303 | regulator_disable(st->reg); | ||
| 304 | } | 260 | } |
| 305 | 261 | ||
| 306 | static const struct spi_device_id ad5624r_id[] = { | 262 | static const struct spi_device_id ad5624r_id[] = { |
| @@ -319,7 +275,6 @@ static struct spi_driver ad5624r_driver = { · 12 unmodified lines | |||
| 319 | .name = "ad5624r", | 275 | .name = "ad5624r", |
| 320 | }, | 276 | }, |
| 321 | .probe = ad5624r_probe, | 277 | .probe = ad5624r_probe, |
| 322 | .remove = ad5624r_remove, | ||
| 323 | .id_table = ad5624r_id, | 278 | .id_table = ad5624r_id, |
| 324 | }; | 279 | }; |
| 325 | module_spi_driver(ad5624r_driver); | 280 | module_spi_driver(ad5624r_driver); |
| @@ -699,7 +699,6 @@ static const struct ad5755_platform_data ad5755_default_pdata = { · 698 unmodified lines | |||
| 699 | 699 | ||
| 700 | static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev) | 700 | static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev) |
| 701 | { | 701 | { |
| 702 | struct fwnode_handle *pp; | ||
| 703 | struct ad5755_platform_data *pdata; | 702 | struct ad5755_platform_data *pdata; |
| 704 | unsigned int tmp; | 703 | unsigned int tmp; |
| 705 | unsigned int tmparray[3]; | 704 | unsigned int tmparray[3]; |
| @@ -746,11 +745,12 @@ static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev) · 40 unmodified lines | |||
| 746 | } | 745 | } |
| 747 | 746 | ||
| 748 | devnr = 0; | 747 | devnr = 0; |
| 749 | device_for_each_child_node(dev, pp) { | 748 | device_for_each_child_node_scoped(dev, pp) { |
| 750 | if (devnr >= AD5755_NUM_CHANNELS) { | 749 | if (devnr >= AD5755_NUM_CHANNELS) { |
| 751 | dev_err(dev, | 750 | dev_err(dev, |
| 752 | "There are too many channels defined in DT\n"); | 751 | "There are too many channels defined in DT\n"); |
| 753 | goto error_out; | 752 | devm_kfree(dev, pdata); |
| 753 | return NULL; | ||
| 754 | } | 754 | } |
| 755 | 755 | ||
| 756 | pdata->dac[devnr].mode = AD5755_MODE_CURRENT_4mA_20mA; | 756 | pdata->dac[devnr].mode = AD5755_MODE_CURRENT_4mA_20mA; |
| @@ -800,11 +800,6 @@ static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev) · 43 unmodified lines | |||
| 800 | } | 800 | } |
| 801 | 801 | ||
| 802 | return pdata; | 802 | return pdata; |
| 803 | |||
| 804 | error_out: | ||
| 805 | fwnode_handle_put(pp); | ||
| 806 | devm_kfree(dev, pdata); | ||
| 807 | return NULL; | ||
| 808 | } | 803 | } |
| 809 | 804 | ||
| 810 | static int ad5755_probe(struct spi_device *spi) | 805 | static int ad5755_probe(struct spi_device *spi) |
| @@ -53,7 +53,6 @@ enum ad5761_supported_device_ids { · 52 unmodified lines | |||
| 53 | /** | 53 | /** |
| 54 | * struct ad5761_state - driver instance specific data | 54 | * struct ad5761_state - driver instance specific data |
| 55 | * @spi: spi_device | 55 | * @spi: spi_device |
| 56 | * @vref_reg: reference voltage regulator | ||
| 57 | * @use_intref: true when the internal voltage reference is used | 56 | * @use_intref: true when the internal voltage reference is used |
| 58 | * @vref: actual voltage reference in mVolts | 57 | * @vref: actual voltage reference in mVolts |
| 59 | * @range: output range mode used | 58 | * @range: output range mode used |
| @@ -62,7 +61,6 @@ enum ad5761_supported_device_ids { · 2 unmodified lines | |||
| 62 | */ | 61 | */ |
| 63 | struct ad5761_state { | 62 | struct ad5761_state { |
| 64 | struct spi_device *spi; | 63 | struct spi_device *spi; |
| 65 | struct regulator *vref_reg; | ||
| 66 | struct mutex lock; | 64 | struct mutex lock; |
| 67 | 65 | ||
| 68 | bool use_intref; | 66 | bool use_intref; |
| @@ -287,63 +285,6 @@ static const struct ad5761_chip_info ad5761_chip_infos[] = { · 218 unmodified lines | |||
| 287 | }, | 285 | }, |
| 288 | }; | 286 | }; |
| 289 | 287 | ||
| 290 | static int ad5761_get_vref(struct ad5761_state *st, | ||
| 291 | const struct ad5761_chip_info *chip_info) | ||
| 292 | { | ||
| 293 | int ret; | ||
| 294 | |||
| 295 | st->vref_reg = devm_regulator_get_optional(&st->spi->dev, "vref"); | ||
| 296 | if (PTR_ERR(st->vref_reg) == -ENODEV) { | ||
| 297 | /* Use Internal regulator */ | ||
| 298 | if (!chip_info->int_vref) { | ||
| 299 | dev_err(&st->spi->dev, | ||
| 300 | "Voltage reference not found\n"); | ||
| 301 | return -EIO; | ||
| 302 | } | ||
| 303 | |||
| 304 | st->use_intref = true; | ||
| 305 | st->vref = chip_info->int_vref; | ||
| 306 | return 0; | ||
| 307 | } | ||
| 308 | |||
| 309 | if (IS_ERR(st->vref_reg)) { | ||
| 310 | dev_err(&st->spi->dev, | ||
| 311 | "Error getting voltage reference regulator\n"); | ||
| 312 | return PTR_ERR(st->vref_reg); | ||
| 313 | } | ||
| 314 | |||
| 315 | ret = regulator_enable(st->vref_reg); | ||
| 316 | if (ret) { | ||
| 317 | dev_err(&st->spi->dev, | ||
| 318 | "Failed to enable voltage reference\n"); | ||
| 319 | return ret; | ||
| 320 | } | ||
| 321 | |||
| 322 | ret = regulator_get_voltage(st->vref_reg); | ||
| 323 | if (ret < 0) { | ||
| 324 | dev_err(&st->spi->dev, | ||
| 325 | "Failed to get voltage reference value\n"); | ||
| 326 | goto disable_regulator_vref; | ||
| 327 | } | ||
| 328 | |||
| 329 | if (ret < 2000000 || ret > 3000000) { | ||
| 330 | dev_warn(&st->spi->dev, | ||
| 331 | "Invalid external voltage ref. value %d uV\n", ret); | ||
| 332 | ret = -EIO; | ||
| 333 | goto disable_regulator_vref; | ||
| 334 | } | ||
| 335 | |||
| 336 | st->vref = ret / 1000; | ||
| 337 | st->use_intref = false; | ||
| 338 | |||
| 339 | return 0; | ||
| 340 | |||
| 341 | disable_regulator_vref: | ||
| 342 | regulator_disable(st->vref_reg); | ||
| 343 | st->vref_reg = NULL; | ||
| 344 | return ret; | ||
| 345 | } | ||
| 346 | |||
| 347 | static int ad5761_probe(struct spi_device *spi) | 288 | static int ad5761_probe(struct spi_device *spi) |
| 348 | { | 289 | { |
| 349 | struct iio_dev *iio_dev; | 290 | struct iio_dev *iio_dev; |
| @@ -361,11 +302,28 @@ static int ad5761_probe(struct spi_device *spi) · 11 unmodified lines | |||
| 361 | st = iio_priv(iio_dev); | 302 | st = iio_priv(iio_dev); |
| 362 | 303 | ||
| 363 | st->spi = spi; | 304 | st->spi = spi; |
| 364 | spi_set_drvdata(spi, iio_dev); | ||
| 365 | 305 | ||
| 366 | ret = ad5761_get_vref(st, chip_info); | 306 | ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref"); |
| 367 | if (ret) | 307 | if (ret < 0 && ret != -ENODEV) |
| 368 | return ret; | 308 | return dev_err_probe(&spi->dev, ret, |
| 309 | "Failed to get voltage reference value\n"); | ||
| 310 | if (ret == -ENODEV) { | ||
| 311 | /* Use Internal regulator */ | ||
| 312 | if (!chip_info->int_vref) | ||
| 313 | return dev_err_probe(&spi->dev, -EIO, | ||
| 314 | "Voltage reference not found\n"); | ||
| 315 | |||
| 316 | st->use_intref = true; | ||
| 317 | st->vref = chip_info->int_vref; | ||
| 318 | } else { | ||
| 319 | if (ret < 2000000 || ret > 3000000) | ||
| 320 | return dev_err_probe(&spi->dev, -EIO, | ||
| 321 | "Invalid external voltage ref. value %d uV\n", | ||
| 322 | ret); | ||
| 323 | |||
| 324 | st->use_intref = false; | ||
| 325 | st->vref = ret / 1000; | ||
| 326 | } | ||
| 369 | 327 | ||
| 370 | if (pdata) | 328 | if (pdata) |
| 371 | voltage_range = pdata->voltage_range; | 329 | voltage_range = pdata->voltage_range; |
| @@ -374,35 +332,15 @@ static int ad5761_probe(struct spi_device *spi) · 2 unmodified lines | |||
| 374 | 332 | ||
| 375 | ret = ad5761_spi_set_range(st, voltage_range); | 333 | ret = ad5761_spi_set_range(st, voltage_range); |
| 376 | if (ret) | 334 | if (ret) |
| 377 | goto disable_regulator_err; | 335 | return ret; |
| 378 | 336 | ||
| 379 | iio_dev->info = &ad5761_info; | 337 | iio_dev->info = &ad5761_info; |
| 380 | iio_dev->modes = INDIO_DIRECT_MODE; | 338 | iio_dev->modes = INDIO_DIRECT_MODE; |
| 381 | iio_dev->channels = &chip_info->channel; | 339 | iio_dev->channels = &chip_info->channel; |
| 382 | iio_dev->num_channels = 1; | 340 | iio_dev->num_channels = 1; |
| 383 | iio_dev->name = spi_get_device_id(st->spi)->name; | 341 | iio_dev->name = spi_get_device_id(st->spi)->name; |
| 384 | ret = iio_device_register(iio_dev); | ||
| 385 | if (ret) | ||
| 386 | goto disable_regulator_err; | ||
| 387 | |||
| 388 | return 0; | ||
| 389 | |||
| 390 | disable_regulator_err: | ||
| 391 | if (!IS_ERR_OR_NULL(st->vref_reg)) | ||
| 392 | regulator_disable(st->vref_reg); | ||
| 393 | |||
| 394 | return ret; | ||
| 395 | } | ||
| 396 | |||
| 397 | static void ad5761_remove(struct spi_device *spi) | ||
| 398 | { | ||
| 399 | struct iio_dev *iio_dev = spi_get_drvdata(spi); | ||
| 400 | struct ad5761_state *st = iio_priv(iio_dev); | ||
| 401 | |||
| 402 | iio_device_unregister(iio_dev); | ||
| 403 | 342 | ||
| 404 | if (!IS_ERR_OR_NULL(st->vref_reg)) | 343 | return devm_iio_device_register(&spi->dev, iio_dev); |
| 405 | regulator_disable(st->vref_reg); | ||
| 406 | } | 344 | } |
| 407 | 345 | ||
| 408 | static const struct spi_device_id ad5761_id[] = { | 346 | static const struct spi_device_id ad5761_id[] = { |
| @@ -419,7 +357,6 @@ static struct spi_driver ad5761_driver = { · 10 unmodified lines | |||
| 419 | .name = "ad5761", | 357 | .name = "ad5761", |
| 420 | }, | 358 | }, |
| 421 | .probe = ad5761_probe, | 359 | .probe = ad5761_probe, |
| 422 | .remove = ad5761_remove, | ||
| 423 | .id_table = ad5761_id, | 360 | .id_table = ad5761_id, |
| 424 | }; | 361 | }; |
| 425 | module_spi_driver(ad5761_driver); | 362 | module_spi_driver(ad5761_driver); |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | |||
| 17 | #include <linux/regmap.h> | 17 | #include <linux/regmap.h> |
| 18 | #include <linux/regulator/consumer.h> | 18 | #include <linux/regulator/consumer.h> |
| 19 | #include <linux/spi/spi.h> | 19 | #include <linux/spi/spi.h> |
| 20 | #include <linux/unaligned.h> | ||
| 20 | 21 | ||
| 21 | #define ADI_SPI_IF_CONFIG_A 0x00 | 22 | #define ADI_SPI_IF_CONFIG_A 0x00 |
| 22 | #define ADI_SPI_IF_CONFIG_B 0x01 | 23 | #define ADI_SPI_IF_CONFIG_B 0x01 |
| @@ -121,7 +122,6 @@ struct ad5770r_out_range { · 98 unmodified lines | |||
| 121 | * struct ad5770r_state - driver instance specific data | 122 | * struct ad5770r_state - driver instance specific data |
| 122 | * @spi: spi_device | 123 | * @spi: spi_device |
| 123 | * @regmap: regmap | 124 | * @regmap: regmap |
| 124 | * @vref_reg: fixed regulator for reference configuration | ||
| 125 | * @gpio_reset: gpio descriptor | 125 | * @gpio_reset: gpio descriptor |
| 126 | * @output_mode: array contains channels output ranges | 126 | * @output_mode: array contains channels output ranges |
| 127 | * @vref: reference value | 127 | * @vref: reference value |
| @@ -133,7 +133,6 @@ struct ad5770r_out_range { · 5 unmodified lines | |||
| 133 | struct ad5770r_state { | 133 | struct ad5770r_state { |
| 134 | struct spi_device *spi; | 134 | struct spi_device *spi; |
| 135 | struct regmap *regmap; | 135 | struct regmap *regmap; |
| 136 | struct regulator *vref_reg; | ||
| 137 | struct gpio_desc *gpio_reset; | 136 | struct gpio_desc *gpio_reset; |
| 138 | struct ad5770r_out_range output_mode[AD5770R_MAX_CHANNELS]; | 137 | struct ad5770r_out_range output_mode[AD5770R_MAX_CHANNELS]; |
| 139 | int vref; | 138 | int vref; |
| @@ -325,7 +324,7 @@ static int ad5770r_read_raw(struct iio_dev *indio_dev, · 185 unmodified lines | |||
| 325 | if (ret) | 324 | if (ret) |
| 326 | return 0; | 325 | return 0; |
| 327 | 326 | ||
| 328 | buf16 = st->transf_buf[0] + (st->transf_buf[1] << 8); | 327 | buf16 = get_unaligned_le16(st->transf_buf); |
| 329 | *val = buf16 >> 2; | 328 | *val = buf16 >> 2; |
| 330 | return IIO_VAL_INT; | 329 | return IIO_VAL_INT; |
| 331 | case IIO_CHAN_INFO_SCALE: | 330 | case IIO_CHAN_INFO_SCALE: |
| @@ -590,13 +589,6 @@ static int ad5770r_init(struct ad5770r_state *st) · 258 unmodified lines | |||
| 590 | return ret; | 589 | return ret; |
| 591 | } | 590 | } |
| 592 | 591 | ||
| 593 | static void ad5770r_disable_regulator(void *data) | ||
| 594 | { | ||
| 595 | struct ad5770r_state *st = data; | ||
| 596 | |||
| 597 | regulator_disable(st->vref_reg); | ||
| 598 | } | ||
| 599 | |||
| 600 | static int ad5770r_probe(struct spi_device *spi) | 592 | static int ad5770r_probe(struct spi_device *spi) |
| 601 | { | 593 | { |
| 602 | struct ad5770r_state *st; | 594 | struct ad5770r_state *st; |
| @@ -621,34 +613,12 @@ static int ad5770r_probe(struct spi_device *spi) · 18 unmodified lines | |||
| 621 | } | 613 | } |
| 622 | st->regmap = regmap; | 614 | st->regmap = regmap; |
| 623 | 615 | ||
| 624 | st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref"); | 616 | ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref"); |
| 625 | if (!IS_ERR(st->vref_reg)) { | 617 | if (ret < 0 && ret != -ENODEV) |
| 626 | ret = regulator_enable(st->vref_reg); | 618 | return dev_err_probe(&spi->dev, ret, "Failed to get vref voltage\n"); |
| 627 | if (ret) { | ||
| 628 | dev_err(&spi->dev, | ||
| 629 | "Failed to enable vref regulators: %d\n", ret); | ||
| 630 | return ret; | ||
| 631 | } | ||
| 632 | 619 | ||
| 633 | ret = devm_add_action_or_reset(&spi->dev, | 620 | st->internal_ref = ret == -ENODEV; |
| 634 | ad5770r_disable_regulator, | 621 | st->vref = st->internal_ref ? AD5770R_LOW_VREF_mV : ret / 1000; |
| 635 | st); | ||
| 636 | if (ret < 0) | ||
| 637 | return ret; | ||
| 638 | |||
| 639 | ret = regulator_get_voltage(st->vref_reg); | ||
| 640 | if (ret < 0) | ||
| 641 | return ret; | ||
| 642 | |||
| 643 | st->vref = ret / 1000; | ||
| 644 | } else { | ||
| 645 | if (PTR_ERR(st->vref_reg) == -ENODEV) { | ||
| 646 | st->vref = AD5770R_LOW_VREF_mV; | ||
| 647 | st->internal_ref = true; | ||
| 648 | } else { | ||
| 649 | return PTR_ERR(st->vref_reg); | ||
| 650 | } | ||
| 651 | } | ||
| 652 | 622 | ||
| 653 | indio_dev->name = spi_get_device_id(spi)->name; | 623 | indio_dev->name = spi_get_device_id(spi)->name; |
| 654 | indio_dev->info = &ad5770r_info; | 624 | indio_dev->info = &ad5770r_info; |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
| 10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
| 11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
| 12 | #include <linux/delay.h> | ||
| 12 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 13 | #include <linux/spi/spi.h> | 14 | #include <linux/spi/spi.h> |
| 14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| @@ -61,11 +62,14 @@ · 46 unmodified lines | |||
| 61 | 62 | ||
| 62 | /** | 63 | /** |
| 63 | * struct ad5791_chip_info - chip specific information | 64 | * struct ad5791_chip_info - chip specific information |
| 65 | * @name: name of the dac chip | ||
| 66 | * @channel: channel specification | ||
| 64 | * @get_lin_comp: function pointer to the device specific function | 67 | * @get_lin_comp: function pointer to the device specific function |
| 65 | */ | 68 | */ |
| 66 | |||
| 67 | struct ad5791_chip_info { | 69 | struct ad5791_chip_info { |
| 68 | int (*get_lin_comp) (unsigned int span); | 70 | const char *name; |
| 71 | const struct iio_chan_spec channel; | ||
| 72 | int (*get_lin_comp)(unsigned int span); | ||
| 69 | }; | 73 | }; |
| 70 | 74 | ||
| 71 | /** | 75 | /** |
| @@ -73,6 +77,9 @@ struct ad5791_chip_info { · 1 unmodified line | |||
| 73 | * @spi: spi_device | 77 | * @spi: spi_device |
| 74 | * @reg_vdd: positive supply regulator | 78 | * @reg_vdd: positive supply regulator |
| 75 | * @reg_vss: negative supply regulator | 79 | * @reg_vss: negative supply regulator |
| 80 | * @gpio_reset: reset gpio | ||
| 81 | * @gpio_clear: clear gpio | ||
| 82 | * @gpio_ldac: load dac gpio | ||
| 76 | * @chip_info: chip model specific constants | 83 | * @chip_info: chip model specific constants |
| 77 | * @vref_mv: actual reference voltage used | 84 | * @vref_mv: actual reference voltage used |
| 78 | * @vref_neg_mv: voltage of the negative supply | 85 | * @vref_neg_mv: voltage of the negative supply |
| @@ -85,6 +92,9 @@ struct ad5791_state { · 6 unmodified lines | |||
| 85 | struct spi_device *spi; | 92 | struct spi_device *spi; |
| 86 | struct regulator *reg_vdd; | 93 | struct regulator *reg_vdd; |
| 87 | struct regulator *reg_vss; | 94 | struct regulator *reg_vss; |
| 95 | struct gpio_desc *gpio_reset; | ||
| 96 | struct gpio_desc *gpio_clear; | ||
| 97 | struct gpio_desc *gpio_ldac; | ||
| 88 | const struct ad5791_chip_info *chip_info; | 98 | const struct ad5791_chip_info *chip_info; |
| 89 | unsigned short vref_mv; | 99 | unsigned short vref_mv; |
| 90 | unsigned int vref_neg_mv; | 100 | unsigned int vref_neg_mv; |
| @@ -98,13 +108,6 @@ struct ad5791_state { · 7 unmodified lines | |||
| 98 | } data[3] __aligned(IIO_DMA_MINALIGN); | 108 | } data[3] __aligned(IIO_DMA_MINALIGN); |
| 99 | }; | 109 | }; |
| 100 | 110 | ||
| 101 | enum ad5791_supported_device_ids { | ||
| 102 | ID_AD5760, | ||
| 103 | ID_AD5780, | ||
| 104 | ID_AD5781, | ||
| 105 | ID_AD5791, | ||
| 106 | }; | ||
| 107 | |||
| 108 | static int ad5791_spi_write(struct ad5791_state *st, u8 addr, u32 val) | 111 | static int ad5791_spi_write(struct ad5791_state *st, u8 addr, u32 val) |
| 109 | { | 112 | { |
| 110 | st->data[0].d32 = cpu_to_be32(AD5791_CMD_WRITE | | 113 | st->data[0].d32 = cpu_to_be32(AD5791_CMD_WRITE | |
| @@ -228,20 +231,6 @@ static int ad5780_get_lin_comp(unsigned int span) · 117 unmodified lines | |||
| 228 | else | 231 | else |
| 229 | return AD5780_LINCOMP_10_20; | 232 | return AD5780_LINCOMP_10_20; |
| 230 | } | 233 | } |
| 231 | static const struct ad5791_chip_info ad5791_chip_info_tbl[] = { | ||
| 232 | [ID_AD5760] = { | ||
| 233 | .get_lin_comp = ad5780_get_lin_comp, | ||
| 234 | }, | ||
| 235 | [ID_AD5780] = { | ||
| 236 | .get_lin_comp = ad5780_get_lin_comp, | ||
| 237 | }, | ||
| 238 | [ID_AD5781] = { | ||
| 239 | .get_lin_comp = ad5791_get_lin_comp, | ||
| 240 | }, | ||
| 241 | [ID_AD5791] = { | ||
| 242 | .get_lin_comp = ad5791_get_lin_comp, | ||
| 243 | }, | ||
| 244 | }; | ||
| 245 | 234 | ||
| 246 | static int ad5791_read_raw(struct iio_dev *indio_dev, | 235 | static int ad5791_read_raw(struct iio_dev *indio_dev, |
| 247 | struct iio_chan_spec const *chan, | 236 | struct iio_chan_spec const *chan, |
| @@ -289,30 +278,34 @@ static const struct iio_chan_spec_ext_info ad5791_ext_info[] = { · 41 unmodified lines | |||
| 289 | { }, | 278 | { }, |
| 290 | }; | 279 | }; |
| 291 | 280 | ||
| 292 | #define AD5791_CHAN(bits, _shift) { \ | 281 | #define AD5791_DEFINE_CHIP_INFO(_name, bits, _shift, _lin_comp) \ |
| 293 | .type = IIO_VOLTAGE, \ | 282 | static const struct ad5791_chip_info _name##_chip_info = { \ |
| 294 | .output = 1, \ | 283 | .name = #_name, \ |
| 295 | .indexed = 1, \ | 284 | .get_lin_comp = &(_lin_comp), \ |
| 296 | .address = AD5791_ADDR_DAC0, \ | 285 | .channel = { \ |
| 297 | .channel = 0, \ | 286 | .type = IIO_VOLTAGE, \ |
| 298 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | 287 | .output = 1, \ |
| 299 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ | 288 | .indexed = 1, \ |
| 300 | BIT(IIO_CHAN_INFO_OFFSET), \ | 289 | .address = AD5791_ADDR_DAC0, \ |
| 301 | .scan_type = { \ | 290 | .channel = 0, \ |
| 302 | .sign = 'u', \ | 291 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
| 303 | .realbits = (bits), \ | 292 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ |
| 304 | .storagebits = 24, \ | 293 | BIT(IIO_CHAN_INFO_OFFSET), \ |
| 305 | .shift = (_shift), \ | 294 | .scan_type = { \ |
| 306 | }, \ | 295 | .sign = 'u', \ |
| 307 | .ext_info = ad5791_ext_info, \ | 296 | .realbits = (bits), \ |
| 297 | .storagebits = 24, \ | ||
| 298 | .shift = (_shift), \ | ||
| 299 | }, \ | ||
| 300 | .ext_info = ad5791_ext_info, \ | ||
| 301 | }, \ | ||
| 308 | } | 302 | } |
| 309 | 303 | ||
| 310 | static const struct iio_chan_spec ad5791_channels[] = { | 304 | AD5791_DEFINE_CHIP_INFO(ad5760, 16, 4, ad5780_get_lin_comp); |
| 311 | [ID_AD5760] = AD5791_CHAN(16, 4), | 305 | AD5791_DEFINE_CHIP_INFO(ad5780, 18, 2, ad5780_get_lin_comp); |
| 312 | [ID_AD5780] = AD5791_CHAN(18, 2), | 306 | AD5791_DEFINE_CHIP_INFO(ad5781, 18, 2, ad5791_get_lin_comp); |
| 313 | [ID_AD5781] = AD5791_CHAN(18, 2), | 307 | AD5791_DEFINE_CHIP_INFO(ad5790, 20, 0, ad5791_get_lin_comp); |
| 314 | [ID_AD5791] = AD5791_CHAN(20, 0) | 308 | AD5791_DEFINE_CHIP_INFO(ad5791, 20, 0, ad5791_get_lin_comp); |
| 315 | }; | ||
| 316 | 309 | ||
| 317 | static int ad5791_write_raw(struct iio_dev *indio_dev, | 310 | static int ad5791_write_raw(struct iio_dev *indio_dev, |
| 318 | struct iio_chan_spec const *chan, | 311 | struct iio_chan_spec const *chan, |
| @@ -341,7 +334,7 @@ static const struct iio_info ad5791_info = { · 22 unmodified lines | |||
| 341 | 334 | ||
| 342 | static int ad5791_probe(struct spi_device *spi) | 335 | static int ad5791_probe(struct spi_device *spi) |
| 343 | { | 336 | { |
| 344 | struct ad5791_platform_data *pdata = spi->dev.platform_data; | 337 | const struct ad5791_platform_data *pdata = dev_get_platdata(&spi->dev); |
| 345 | struct iio_dev *indio_dev; | 338 | struct iio_dev *indio_dev; |
| 346 | struct ad5791_state *st; | 339 | struct ad5791_state *st; |
| 347 | int ret, pos_voltage_uv = 0, neg_voltage_uv = 0; | 340 | int ret, pos_voltage_uv = 0, neg_voltage_uv = 0; |
| @@ -351,31 +344,21 @@ static int ad5791_probe(struct spi_device *spi) · 3 unmodified lines | |||
| 351 | if (!indio_dev) | 344 | if (!indio_dev) |
| 352 | return -ENOMEM; | 345 | return -ENOMEM; |
| 353 | st = iio_priv(indio_dev); | 346 | st = iio_priv(indio_dev); |
| 354 | st->reg_vdd = devm_regulator_get(&spi->dev, "vdd"); | ||
| 355 | if (!IS_ERR(st->reg_vdd)) { | ||
| 356 | ret = regulator_enable(st->reg_vdd); | ||
| 357 | if (ret) | ||
| 358 | return ret; | ||
| 359 | |||
| 360 | ret = regulator_get_voltage(st->reg_vdd); | ||
| 361 | if (ret < 0) | ||
| 362 | goto error_disable_reg_pos; | ||
| 363 | |||
| 364 | pos_voltage_uv = ret; | ||
| 365 | } | ||
| 366 | 347 | ||
| 367 | st->reg_vss = devm_regulator_get(&spi->dev, "vss"); | 348 | st->gpio_reset = devm_gpiod_get_optional(&spi->dev, "reset", |
| 368 | if (!IS_ERR(st->reg_vss)) { | 349 | GPIOD_OUT_HIGH); |
| 369 | ret = regulator_enable(st->reg_vss); | 350 | if (IS_ERR(st->gpio_reset)) |
| 370 | if (ret) | 351 | return PTR_ERR(st->gpio_reset); |
| 371 | goto error_disable_reg_pos; | ||
| 372 | 352 | ||
| 373 | ret = regulator_get_voltage(st->reg_vss); | 353 | st->gpio_clear = devm_gpiod_get_optional(&spi->dev, "clear", |
| 374 | if (ret < 0) | 354 | GPIOD_OUT_LOW); |
| 375 | goto error_disable_reg_neg; | 355 | if (IS_ERR(st->gpio_clear)) |
| 356 | return PTR_ERR(st->gpio_clear); | ||
| 376 | 357 | ||
| 377 | neg_voltage_uv = ret; | 358 | st->gpio_ldac = devm_gpiod_get_optional(&spi->dev, "ldac", |
| 378 | } | 359 | GPIOD_OUT_HIGH); |
| 360 | if (IS_ERR(st->gpio_ldac)) | ||
| 361 | return PTR_ERR(st->gpio_ldac); | ||
| 379 | 362 | ||
| 380 | st->pwr_down = true; | 363 | st->pwr_down = true; |
| 381 | st->spi = spi; | 364 | st->spi = spi; |
| @@ -386,7 +369,17 @@ static int ad5791_probe(struct spi_device *spi) · 4 unmodified lines | |||
| 386 | use_rbuf_gain2 = device_property_read_bool(&spi->dev, | 369 | use_rbuf_gain2 = device_property_read_bool(&spi->dev, |
| 387 | "adi,rbuf-gain2-en"); | 370 | "adi,rbuf-gain2-en"); |
| 388 | 371 | ||
| 389 | if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd)) { | 372 | pos_voltage_uv = devm_regulator_get_enable_read_voltage(&spi->dev, "vdd"); |
| 373 | if (pos_voltage_uv < 0 && pos_voltage_uv != -ENODEV) | ||
| 374 | return dev_err_probe(&spi->dev, pos_voltage_uv, | ||
| 375 | "failed to get vdd voltage\n"); | ||
| 376 | |||
| 377 | neg_voltage_uv = devm_regulator_get_enable_read_voltage(&spi->dev, "vss"); | ||
| 378 | if (neg_voltage_uv < 0 && neg_voltage_uv != -ENODEV) | ||
| 379 | return dev_err_probe(&spi->dev, neg_voltage_uv, | ||
| 380 | "failed to get vss voltage\n"); | ||
| 381 | |||
| 382 | if (neg_voltage_uv >= 0 && pos_voltage_uv >= 0) { | ||
| 390 | st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000; | 383 | st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000; |
| 391 | st->vref_neg_mv = neg_voltage_uv / 1000; | 384 | st->vref_neg_mv = neg_voltage_uv / 1000; |
| 392 | } else if (pdata) { | 385 | } else if (pdata) { |
| @@ -396,13 +389,18 @@ static int ad5791_probe(struct spi_device *spi) · 3 unmodified lines | |||
| 396 | dev_warn(&spi->dev, "reference voltage unspecified\n"); | 389 | dev_warn(&spi->dev, "reference voltage unspecified\n"); |
| 397 | } | 390 | } |
| 398 | 391 | ||
| 399 | ret = ad5791_spi_write(st, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET); | 392 | if (st->gpio_reset) { |
| 400 | if (ret) | 393 | fsleep(20); |
| 401 | goto error_disable_reg_neg; | 394 | gpiod_set_value_cansleep(st->gpio_reset, 0); |
| 402 | 395 | } else { | |
| 403 | st->chip_info = &ad5791_chip_info_tbl[spi_get_device_id(spi) | 396 | ret = ad5791_spi_write(st, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET); |
| 404 | ->driver_data]; | 397 | if (ret) |
| 398 | return dev_err_probe(&spi->dev, ret, "fail to reset\n"); | ||
| 399 | } | ||
| 405 | 400 | ||
| 401 | st->chip_info = spi_get_device_match_data(spi); | ||
| 402 | if (!st->chip_info) | ||
| 403 | return dev_err_probe(&spi->dev, -EINVAL, "no chip info\n"); | ||
| 406 | 404 | ||
| 407 | st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv)) | 405 | st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv)) |
| 408 | | (use_rbuf_gain2 ? 0 : AD5791_CTRL_RBUF) | | 406 | | (use_rbuf_gain2 ? 0 : AD5791_CTRL_RBUF) | |
| @@ -411,59 +409,42 @@ static int ad5791_probe(struct spi_device *spi) · 2 unmodified lines | |||
| 411 | ret = ad5791_spi_write(st, AD5791_ADDR_CTRL, st->ctrl | | 409 | ret = ad5791_spi_write(st, AD5791_ADDR_CTRL, st->ctrl | |
| 412 | AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); | 410 | AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); |
| 413 | if (ret) | 411 | if (ret) |
| 414 | goto error_disable_reg_neg; | 412 | return dev_err_probe(&spi->dev, ret, "fail to write ctrl register\n"); |
| 415 | 413 | ||
| 416 | spi_set_drvdata(spi, indio_dev); | ||
| 417 | indio_dev->info = &ad5791_info; | 414 | indio_dev->info = &ad5791_info; |
| 418 | indio_dev->modes = INDIO_DIRECT_MODE; | 415 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 419 | indio_dev->channels | 416 | indio_dev->channels = &st->chip_info->channel; |
| 420 | = &ad5791_channels[spi_get_device_id(spi)->driver_data]; | ||
| 421 | indio_dev->num_channels = 1; | 417 | indio_dev->num_channels = 1; |
| 422 | indio_dev->name = spi_get_device_id(st->spi)->name; | 418 | indio_dev->name = st->chip_info->name; |
| 423 | ret = iio_device_register(indio_dev); | 419 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 424 | if (ret) | ||
| 425 | goto error_disable_reg_neg; | ||
| 426 | |||
| 427 | return 0; | ||
| 428 | |||
| 429 | error_disable_reg_neg: | ||
| 430 | if (!IS_ERR(st->reg_vss)) | ||
| 431 | regulator_disable(st->reg_vss); | ||
| 432 | error_disable_reg_pos: | ||
| 433 | if (!IS_ERR(st->reg_vdd)) | ||
| 434 | regulator_disable(st->reg_vdd); | ||
| 435 | return ret; | ||
| 436 | } | 420 | } |
| 437 | 421 | ||
| 438 | static void ad5791_remove(struct spi_device *spi) | 422 | static const struct of_device_id ad5791_of_match[] = { |
| 439 | { | 423 | { .compatible = "adi,ad5760", .data = &ad5760_chip_info }, |
| 440 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | 424 | { .compatible = "adi,ad5780", .data = &ad5780_chip_info }, |
| 441 | struct ad5791_state *st = iio_priv(indio_dev); | 425 | { .compatible = "adi,ad5781", .data = &ad5781_chip_info }, |
| 442 | 426 | { .compatible = "adi,ad5790", .data = &ad5790_chip_info }, | |
| 443 | iio_device_unregister(indio_dev); | 427 | { .compatible = "adi,ad5791", .data = &ad5791_chip_info }, |
| 444 | if (!IS_ERR(st->reg_vdd)) | 428 | { } |
| 445 | regulator_disable(st->reg_vdd); | 429 | }; |
| 446 | 430 | MODULE_DEVICE_TABLE(of, ad5791_of_match); | |
| 447 | if (!IS_ERR(st->reg_vss)) | ||
| 448 | regulator_disable(st->reg_vss); | ||
| 449 | } | ||
| 450 | 431 | ||
| 451 | static const struct spi_device_id ad5791_id[] = { | 432 | static const struct spi_device_id ad5791_id[] = { |
| 452 | {"ad5760", ID_AD5760}, | 433 | { "ad5760", (kernel_ulong_t)&ad5760_chip_info }, |
| 453 | {"ad5780", ID_AD5780}, | 434 | { "ad5780", (kernel_ulong_t)&ad5780_chip_info }, |
| 454 | {"ad5781", ID_AD5781}, | 435 | { "ad5781", (kernel_ulong_t)&ad5781_chip_info }, |
| 455 | {"ad5790", ID_AD5791}, | 436 | { "ad5790", (kernel_ulong_t)&ad5790_chip_info }, |
| 456 | {"ad5791", ID_AD5791}, | 437 | { "ad5791", (kernel_ulong_t)&ad5791_chip_info }, |
| 457 | {} | 438 | { } |
| 458 | }; | 439 | }; |
| 459 | MODULE_DEVICE_TABLE(spi, ad5791_id); | 440 | MODULE_DEVICE_TABLE(spi, ad5791_id); |
| 460 | 441 | ||
| 461 | static struct spi_driver ad5791_driver = { | 442 | static struct spi_driver ad5791_driver = { |
| 462 | .driver = { | 443 | .driver = { |
| 463 | .name = "ad5791", | 444 | .name = "ad5791", |
| 445 | .of_match_table = ad5791_of_match, | ||
| 464 | }, | 446 | }, |
| 465 | .probe = ad5791_probe, | 447 | .probe = ad5791_probe, |
| 466 | .remove = ad5791_remove, | ||
| 467 | .id_table = ad5791_id, | 448 | .id_table = ad5791_id, |
| 468 | }; | 449 | }; |
| 469 | module_spi_driver(ad5791_driver); | 450 | module_spi_driver(ad5791_driver); |
| @@ -0,0 +1,951 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * AD8460 Waveform generator DAC Driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2024 Analog Devices, Inc. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/bitfield.h> | ||
| 9 | #include <linux/cleanup.h> | ||
| 10 | #include <linux/clk.h> | ||
| 11 | #include <linux/debugfs.h> | ||
| 12 | #include <linux/delay.h> | ||
| 13 | #include <linux/dmaengine.h> | ||
| 14 | #include <linux/gpio/consumer.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/mod_devicetable.h> | ||
| 18 | #include <linux/regmap.h> | ||
| 19 | #include <linux/regulator/consumer.h> | ||
| 20 | #include <linux/spi/spi.h> | ||
| 21 | |||
| 22 | #include <linux/iio/buffer.h> | ||
| 23 | #include <linux/iio/buffer-dma.h> | ||
| 24 | #include <linux/iio/buffer-dmaengine.h> | ||
| 25 | #include <linux/iio/consumer.h> | ||
| 26 | #include <linux/iio/events.h> | ||
| 27 | #include <linux/iio/iio.h> | ||
| 28 | |||
| 29 | #define AD8460_CTRL_REG(x) (x) | ||
| 30 | #define AD8460_HVDAC_DATA_WORD(x) (0x60 + (2 * (x))) | ||
| 31 | |||
| 32 | #define AD8460_HV_RESET_MSK BIT(7) | ||
| 33 | #define AD8460_HV_SLEEP_MSK BIT(4) | ||
| 34 | #define AD8460_WAVE_GEN_MODE_MSK BIT(0) | ||
| 35 | |||
| 36 | #define AD8460_HVDAC_SLEEP_MSK BIT(3) | ||
| 37 | |||
| 38 | #define AD8460_FAULT_ARM_MSK BIT(7) | ||
| 39 | #define AD8460_FAULT_LIMIT_MSK GENMASK(6, 0) | ||
| 40 | |||
| 41 | #define AD8460_APG_MODE_ENABLE_MSK BIT(5) | ||
| 42 | #define AD8460_PATTERN_DEPTH_MSK GENMASK(3, 0) | ||
| 43 | |||
| 44 | #define AD8460_QUIESCENT_CURRENT_MSK GENMASK(7, 0) | ||
| 45 | |||
| 46 | #define AD8460_SHUTDOWN_FLAG_MSK BIT(7) | ||
| 47 | |||
| 48 | #define AD8460_DATA_BYTE_LOW_MSK GENMASK(7, 0) | ||
| 49 | #define AD8460_DATA_BYTE_HIGH_MSK GENMASK(5, 0) | ||
| 50 | #define AD8460_DATA_BYTE_FULL_MSK GENMASK(13, 0) | ||
| 51 | |||
| 52 | #define AD8460_DEFAULT_FAULT_PROTECT 0x00 | ||
| 53 | #define AD8460_DATA_BYTE_WORD_LENGTH 2 | ||
| 54 | #define AD8460_NUM_DATA_WORDS 16 | ||
| 55 | #define AD8460_NOMINAL_VOLTAGE_SPAN 80 | ||
| 56 | #define AD8460_MIN_EXT_RESISTOR_OHMS 2000 | ||
| 57 | #define AD8460_MAX_EXT_RESISTOR_OHMS 20000 | ||
| 58 | #define AD8460_MIN_VREFIO_UV 120000 | ||
| 59 | #define AD8460_MAX_VREFIO_UV 1200000 | ||
| 60 | #define AD8460_ABS_MAX_OVERVOLTAGE_UV 55000000 | ||
| 61 | #define AD8460_ABS_MAX_OVERCURRENT_UA 1000000 | ||
| 62 | #define AD8460_MAX_OVERTEMPERATURE_MC 150000 | ||
| 63 | #define AD8460_MIN_OVERTEMPERATURE_MC 20000 | ||
| 64 | #define AD8460_CURRENT_LIMIT_CONV(x) ((x) / 15625) | ||
| 65 | #define AD8460_VOLTAGE_LIMIT_CONV(x) ((x) / 1953000) | ||
| 66 | #define AD8460_TEMP_LIMIT_CONV(x) (((x) + 266640) / 6510) | ||
| 67 | |||
| 68 | enum ad8460_fault_type { | ||
| 69 | AD8460_OVERCURRENT_SRC, | ||
| 70 | AD8460_OVERCURRENT_SNK, | ||
| 71 | AD8460_OVERVOLTAGE_POS, | ||
| 72 | AD8460_OVERVOLTAGE_NEG, | ||
| 73 | AD8460_OVERTEMPERATURE, | ||
| 74 | }; | ||
| 75 | |||
| 76 | struct ad8460_state { | ||
| 77 | struct spi_device *spi; | ||
| 78 | struct regmap *regmap; | ||
| 79 | struct iio_channel *tmp_adc_channel; | ||
| 80 | struct clk *sync_clk; | ||
| 81 | /* lock to protect against multiple access to the device and shared data */ | ||
| 82 | struct mutex lock; | ||
| 83 | int refio_1p2v_mv; | ||
| 84 | u32 ext_resistor_ohms; | ||
| 85 | /* | ||
| 86 | * DMA (thus cache coherency maintenance) requires the | ||
| 87 | * transfer buffers to live in their own cache lines. | ||
| 88 | */ | ||
| 89 | __le16 spi_tx_buf __aligned(IIO_DMA_MINALIGN); | ||
| 90 | }; | ||
| 91 | |||
| 92 | static int ad8460_hv_reset(struct ad8460_state *state) | ||
| 93 | { | ||
| 94 | int ret; | ||
| 95 | |||
| 96 | ret = regmap_set_bits(state->regmap, AD8460_CTRL_REG(0x00), | ||
| 97 | AD8460_HV_RESET_MSK); | ||
| 98 | if (ret) | ||
| 99 | return ret; | ||
| 100 | |||
| 101 | fsleep(20); | ||
| 102 | |||
| 103 | return regmap_clear_bits(state->regmap, AD8460_CTRL_REG(0x00), | ||
| 104 | AD8460_HV_RESET_MSK); | ||
| 105 | } | ||
| 106 | |||
| 107 | static int ad8460_reset(const struct ad8460_state *state) | ||
| 108 | { | ||
| 109 | struct device *dev = &state->spi->dev; | ||
| 110 | struct gpio_desc *reset; | ||
| 111 | |||
| 112 | reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); | ||
| 113 | if (IS_ERR(reset)) | ||
| 114 | return dev_err_probe(dev, PTR_ERR(reset), | ||
| 115 | "Failed to get reset gpio"); | ||
| 116 | if (reset) { | ||
| 117 | /* minimum duration of 10ns */ | ||
| 118 | ndelay(10); | ||
| 119 | gpiod_set_value_cansleep(reset, 1); | ||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* bring all registers to their default state */ | ||
| 124 | return regmap_write(state->regmap, AD8460_CTRL_REG(0x03), 1); | ||
| 125 | } | ||
| 126 | |||
| 127 | static int ad8460_enable_apg_mode(struct ad8460_state *state, int val) | ||
| 128 | { | ||
| 129 | int ret; | ||
| 130 | |||
| 131 | ret = regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x02), | ||
| 132 | AD8460_APG_MODE_ENABLE_MSK, | ||
| 133 | FIELD_PREP(AD8460_APG_MODE_ENABLE_MSK, val)); | ||
| 134 | if (ret) | ||
| 135 | return ret; | ||
| 136 | |||
| 137 | return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x00), | ||
| 138 | AD8460_WAVE_GEN_MODE_MSK, | ||
| 139 | FIELD_PREP(AD8460_WAVE_GEN_MODE_MSK, val)); | ||
| 140 | } | ||
| 141 | |||
| 142 | static int ad8460_read_shutdown_flag(struct ad8460_state *state, u64 *flag) | ||
| 143 | { | ||
| 144 | int ret, val; | ||
| 145 | |||
| 146 | ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x0E), &val); | ||
| 147 | if (ret) | ||
| 148 | return ret; | ||
| 149 | |||
| 150 | *flag = FIELD_GET(AD8460_SHUTDOWN_FLAG_MSK, val); | ||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | static int ad8460_get_hvdac_word(struct ad8460_state *state, int index, int *val) | ||
| 155 | { | ||
| 156 | int ret; | ||
| 157 | |||
| 158 | ret = regmap_bulk_read(state->regmap, AD8460_HVDAC_DATA_WORD(index), | ||
| 159 | &state->spi_tx_buf, AD8460_DATA_BYTE_WORD_LENGTH); | ||
| 160 | if (ret) | ||
| 161 | return ret; | ||
| 162 | |||
| 163 | *val = le16_to_cpu(state->spi_tx_buf); | ||
| 164 | |||
| 165 | return ret; | ||
| 166 | } | ||
| 167 | |||
| 168 | static int ad8460_set_hvdac_word(struct ad8460_state *state, int index, int val) | ||
| 169 | { | ||
| 170 | state->spi_tx_buf = cpu_to_le16(FIELD_PREP(AD8460_DATA_BYTE_FULL_MSK, val)); | ||
| 171 | |||
| 172 | return regmap_bulk_write(state->regmap, AD8460_HVDAC_DATA_WORD(index), | ||
| 173 | &state->spi_tx_buf, AD8460_DATA_BYTE_WORD_LENGTH); | ||
| 174 | } | ||
| 175 | |||
| 176 | static ssize_t ad8460_dac_input_read(struct iio_dev *indio_dev, uintptr_t private, | ||
| 177 | const struct iio_chan_spec *chan, char *buf) | ||
| 178 | { | ||
| 179 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 180 | unsigned int reg; | ||
| 181 | int ret; | ||
| 182 | |||
| 183 | ret = ad8460_get_hvdac_word(state, private, ®); | ||
| 184 | if (ret) | ||
| 185 | return ret; | ||
| 186 | |||
| 187 | return sysfs_emit(buf, "%u\n", reg); | ||
| 188 | } | ||
| 189 | |||
| 190 | static ssize_t ad8460_dac_input_write(struct iio_dev *indio_dev, uintptr_t private, | ||
| 191 | const struct iio_chan_spec *chan, | ||
| 192 | const char *buf, size_t len) | ||
| 193 | { | ||
| 194 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 195 | unsigned int reg; | ||
| 196 | int ret; | ||
| 197 | |||
| 198 | ret = kstrtou32(buf, 10, ®); | ||
| 199 | if (ret) | ||
| 200 | return ret; | ||
| 201 | |||
| 202 | guard(mutex)(&state->lock); | ||
| 203 | |||
| 204 | return ad8460_set_hvdac_word(state, private, reg); | ||
| 205 | } | ||
| 206 | |||
| 207 | static ssize_t ad8460_read_symbol(struct iio_dev *indio_dev, uintptr_t private, | ||
| 208 | const struct iio_chan_spec *chan, char *buf) | ||
| 209 | { | ||
| 210 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 211 | unsigned int reg; | ||
| 212 | int ret; | ||
| 213 | |||
| 214 | ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x02), ®); | ||
| 215 | if (ret) | ||
| 216 | return ret; | ||
| 217 | |||
| 218 | return sysfs_emit(buf, "%lu\n", FIELD_GET(AD8460_PATTERN_DEPTH_MSK, reg)); | ||
| 219 | } | ||
| 220 | |||
| 221 | static ssize_t ad8460_write_symbol(struct iio_dev *indio_dev, uintptr_t private, | ||
| 222 | const struct iio_chan_spec *chan, | ||
| 223 | const char *buf, size_t len) | ||
| 224 | { | ||
| 225 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 226 | uint16_t sym; | ||
| 227 | int ret; | ||
| 228 | |||
| 229 | ret = kstrtou16(buf, 10, &sym); | ||
| 230 | if (ret) | ||
| 231 | return ret; | ||
| 232 | |||
| 233 | guard(mutex)(&state->lock); | ||
| 234 | |||
| 235 | return regmap_update_bits(state->regmap, | ||
| 236 | AD8460_CTRL_REG(0x02), | ||
| 237 | AD8460_PATTERN_DEPTH_MSK, | ||
| 238 | FIELD_PREP(AD8460_PATTERN_DEPTH_MSK, sym)); | ||
| 239 | } | ||
| 240 | |||
| 241 | static ssize_t ad8460_read_toggle_en(struct iio_dev *indio_dev, uintptr_t private, | ||
| 242 | const struct iio_chan_spec *chan, char *buf) | ||
| 243 | { | ||
| 244 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 245 | unsigned int reg; | ||
| 246 | int ret; | ||
| 247 | |||
| 248 | ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x02), ®); | ||
| 249 | if (ret) | ||
| 250 | return ret; | ||
| 251 | |||
| 252 | return sysfs_emit(buf, "%ld\n", FIELD_GET(AD8460_APG_MODE_ENABLE_MSK, reg)); | ||
| 253 | } | ||
| 254 | |||
| 255 | static ssize_t ad8460_write_toggle_en(struct iio_dev *indio_dev, uintptr_t private, | ||
| 256 | const struct iio_chan_spec *chan, | ||
| 257 | const char *buf, size_t len) | ||
| 258 | { | ||
| 259 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 260 | bool toggle_en; | ||
| 261 | int ret; | ||
| 262 | |||
| 263 | ret = kstrtobool(buf, &toggle_en); | ||
| 264 | if (ret) | ||
| 265 | return ret; | ||
| 266 | |||
| 267 | iio_device_claim_direct_scoped(return -EBUSY, indio_dev) | ||
| 268 | return ad8460_enable_apg_mode(state, toggle_en); | ||
| 269 | unreachable(); | ||
| 270 | } | ||
| 271 | |||
| 272 | static ssize_t ad8460_read_powerdown(struct iio_dev *indio_dev, uintptr_t private, | ||
| 273 | const struct iio_chan_spec *chan, char *buf) | ||
| 274 | { | ||
| 275 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 276 | unsigned int reg; | ||
| 277 | int ret; | ||
| 278 | |||
| 279 | ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x01), ®); | ||
| 280 | if (ret) | ||
| 281 | return ret; | ||
| 282 | |||
| 283 | return sysfs_emit(buf, "%ld\n", FIELD_GET(AD8460_HVDAC_SLEEP_MSK, reg)); | ||
| 284 | } | ||
| 285 | |||
| 286 | static ssize_t ad8460_write_powerdown(struct iio_dev *indio_dev, uintptr_t private, | ||
| 287 | const struct iio_chan_spec *chan, | ||
| 288 | const char *buf, size_t len) | ||
| 289 | { | ||
| 290 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 291 | bool pwr_down; | ||
| 292 | u64 sdn_flag; | ||
| 293 | int ret; | ||
| 294 | |||
| 295 | ret = kstrtobool(buf, &pwr_down); | ||
| 296 | if (ret) | ||
| 297 | return ret; | ||
| 298 | |||
| 299 | guard(mutex)(&state->lock); | ||
| 300 | |||
| 301 | /* | ||
| 302 | * If powerdown is set, HVDAC is enabled and the HV driver is | ||
| 303 | * enabled via HV_RESET in case it is in shutdown mode, | ||
| 304 | * If powerdown is cleared, HVDAC is set to shutdown state | ||
| 305 | * as well as the HV driver. Quiescent current decreases and ouput is | ||
| 306 | * floating (high impedance). | ||
| 307 | */ | ||
| 308 | |||
| 309 | ret = regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x01), | ||
| 310 | AD8460_HVDAC_SLEEP_MSK, | ||
| 311 | FIELD_PREP(AD8460_HVDAC_SLEEP_MSK, pwr_down)); | ||
| 312 | if (ret) | ||
| 313 | return ret; | ||
| 314 | |||
| 315 | if (!pwr_down) { | ||
| 316 | ret = ad8460_read_shutdown_flag(state, &sdn_flag); | ||
| 317 | if (ret) | ||
| 318 | return ret; | ||
| 319 | |||
| 320 | if (sdn_flag) { | ||
| 321 | ret = ad8460_hv_reset(state); | ||
| 322 | if (ret) | ||
| 323 | return ret; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | ret = regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x00), | ||
| 328 | AD8460_HV_SLEEP_MSK, | ||
| 329 | FIELD_PREP(AD8460_HV_SLEEP_MSK, !pwr_down)); | ||
| 330 | if (ret) | ||
| 331 | return ret; | ||
| 332 | |||
| 333 | return len; | ||
| 334 | } | ||
| 335 | |||
| 336 | static const char * const ad8460_powerdown_modes[] = { | ||
| 337 | "three_state", | ||
| 338 | }; | ||
| 339 | |||
| 340 | static int ad8460_get_powerdown_mode(struct iio_dev *indio_dev, | ||
| 341 | const struct iio_chan_spec *chan) | ||
| 342 | { | ||
| 343 | return 0; | ||
| 344 | } | ||
| 345 | |||
| 346 | static int ad8460_set_powerdown_mode(struct iio_dev *indio_dev, | ||
| 347 | const struct iio_chan_spec *chan, | ||
| 348 | unsigned int type) | ||
| 349 | { | ||
| 350 | return 0; | ||
| 351 | } | ||
| 352 | |||
| 353 | static int ad8460_set_sample(struct ad8460_state *state, int val) | ||
| 354 | { | ||
| 355 | int ret; | ||
| 356 | |||
| 357 | ret = ad8460_enable_apg_mode(state, 1); | ||
| 358 | if (ret) | ||
| 359 | return ret; | ||
| 360 | |||
| 361 | guard(mutex)(&state->lock); | ||
| 362 | ret = ad8460_set_hvdac_word(state, 0, val); | ||
| 363 | if (ret) | ||
| 364 | return ret; | ||
| 365 | |||
| 366 | return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x02), | ||
| 367 | AD8460_PATTERN_DEPTH_MSK, | ||
| 368 | FIELD_PREP(AD8460_PATTERN_DEPTH_MSK, 0)); | ||
| 369 | } | ||
| 370 | |||
| 371 | static int ad8460_set_fault_threshold(struct ad8460_state *state, | ||
| 372 | enum ad8460_fault_type fault, | ||
| 373 | unsigned int threshold) | ||
| 374 | { | ||
| 375 | return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x08 + fault), | ||
| 376 | AD8460_FAULT_LIMIT_MSK, | ||
| 377 | FIELD_PREP(AD8460_FAULT_LIMIT_MSK, threshold)); | ||
| 378 | } | ||
| 379 | |||
| 380 | static int ad8460_get_fault_threshold(struct ad8460_state *state, | ||
| 381 | enum ad8460_fault_type fault, | ||
| 382 | unsigned int *threshold) | ||
| 383 | { | ||
| 384 | unsigned int val; | ||
| 385 | int ret; | ||
| 386 | |||
| 387 | ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x08 + fault), &val); | ||
| 388 | if (ret) | ||
| 389 | return ret; | ||
| 390 | |||
| 391 | *threshold = FIELD_GET(AD8460_FAULT_LIMIT_MSK, val); | ||
| 392 | |||
| 393 | return ret; | ||
| 394 | } | ||
| 395 | |||
| 396 | static int ad8460_set_fault_threshold_en(struct ad8460_state *state, | ||
| 397 | enum ad8460_fault_type fault, bool en) | ||
| 398 | { | ||
| 399 | return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x08 + fault), | ||
| 400 | AD8460_FAULT_ARM_MSK, | ||
| 401 | FIELD_PREP(AD8460_FAULT_ARM_MSK, en)); | ||
| 402 | } | ||
| 403 | |||
| 404 | static int ad8460_get_fault_threshold_en(struct ad8460_state *state, | ||
| 405 | enum ad8460_fault_type fault, bool *en) | ||
| 406 | { | ||
| 407 | unsigned int val; | ||
| 408 | int ret; | ||
| 409 | |||
| 410 | ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x08 + fault), &val); | ||
| 411 | if (ret) | ||
| 412 | return ret; | ||
| 413 | |||
| 414 | *en = FIELD_GET(AD8460_FAULT_ARM_MSK, val); | ||
| 415 | |||
| 416 | return 0; | ||
| 417 | } | ||
| 418 | |||
| 419 | static int ad8460_write_raw(struct iio_dev *indio_dev, | ||
| 420 | struct iio_chan_spec const *chan, int val, int val2, | ||
| 421 | long mask) | ||
| 422 | { | ||
| 423 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 424 | |||
| 425 | switch (mask) { | ||
| 426 | case IIO_CHAN_INFO_RAW: | ||
| 427 | switch (chan->type) { | ||
| 428 | case IIO_VOLTAGE: | ||
| 429 | iio_device_claim_direct_scoped(return -EBUSY, indio_dev) | ||
| 430 | return ad8460_set_sample(state, val); | ||
| 431 | unreachable(); | ||
| 432 | case IIO_CURRENT: | ||
| 433 | return regmap_write(state->regmap, AD8460_CTRL_REG(0x04), | ||
| 434 | FIELD_PREP(AD8460_QUIESCENT_CURRENT_MSK, val)); | ||
| 435 | default: | ||
| 436 | return -EINVAL; | ||
| 437 | } | ||
| 438 | default: | ||
| 439 | return -EINVAL; | ||
| 440 | } | ||
| 441 | } | ||
| 442 | |||
| 443 | static int ad8460_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, | ||
| 444 | int *val, int *val2, long mask) | ||
| 445 | { | ||
| 446 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 447 | int data, ret; | ||
| 448 | |||
| 449 | switch (mask) { | ||
| 450 | case IIO_CHAN_INFO_RAW: | ||
| 451 | switch (chan->type) { | ||
| 452 | case IIO_VOLTAGE: | ||
| 453 | scoped_guard(mutex, &state->lock) { | ||
| 454 | ret = ad8460_get_hvdac_word(state, 0, &data); | ||
| 455 | if (ret) | ||
| 456 | return ret; | ||
| 457 | } | ||
| 458 | *val = data; | ||
| 459 | return IIO_VAL_INT; | ||
| 460 | case IIO_CURRENT: | ||
| 461 | ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x04), | ||
| 462 | &data); | ||
| 463 | if (ret) | ||
| 464 | return ret; | ||
| 465 | *val = data; | ||
| 466 | return IIO_VAL_INT; | ||
| 467 | case IIO_TEMP: | ||
| 468 | ret = iio_read_channel_raw(state->tmp_adc_channel, &data); | ||
| 469 | if (ret) | ||
| 470 | return ret; | ||
| 471 | *val = data; | ||
| 472 | return IIO_VAL_INT; | ||
| 473 | default: | ||
| 474 | return -EINVAL; | ||
| 475 | } | ||
| 476 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 477 | *val = clk_get_rate(state->sync_clk); | ||
| 478 | return IIO_VAL_INT; | ||
| 479 | case IIO_CHAN_INFO_SCALE: | ||
| 480 | /* | ||
| 481 | * vCONV = vNOMINAL_SPAN * (DAC_CODE / 2**14) - 40V | ||
| 482 | * vMAX = vNOMINAL_SPAN * (2**14 / 2**14) - 40V | ||
| 483 | * vMIN = vNOMINAL_SPAN * (0 / 2**14) - 40V | ||
| 484 | * vADJ = vCONV * (2000 / rSET) * (vREF / 1.2) | ||
| 485 | * vSPAN = vADJ_MAX - vADJ_MIN | ||
| 486 | * See datasheet page 49, section FULL-SCALE REDUCTION | ||
| 487 | */ | ||
| 488 | *val = AD8460_NOMINAL_VOLTAGE_SPAN * 2000 * state->refio_1p2v_mv; | ||
| 489 | *val2 = state->ext_resistor_ohms * 1200; | ||
| 490 | return IIO_VAL_FRACTIONAL; | ||
| 491 | default: | ||
| 492 | return -EINVAL; | ||
| 493 | } | ||
| 494 | } | ||
| 495 | |||
| 496 | static int ad8460_select_fault_type(int chan_type, enum iio_event_direction dir) | ||
| 497 | { | ||
| 498 | switch (chan_type) { | ||
| 499 | case IIO_VOLTAGE: | ||
| 500 | switch (dir) { | ||
| 501 | case IIO_EV_DIR_RISING: | ||
| 502 | return AD8460_OVERVOLTAGE_POS; | ||
| 503 | case IIO_EV_DIR_FALLING: | ||
| 504 | return AD8460_OVERVOLTAGE_NEG; | ||
| 505 | default: | ||
| 506 | return -EINVAL; | ||
| 507 | } | ||
| 508 | case IIO_CURRENT: | ||
| 509 | switch (dir) { | ||
| 510 | case IIO_EV_DIR_RISING: | ||
| 511 | return AD8460_OVERCURRENT_SRC; | ||
| 512 | case IIO_EV_DIR_FALLING: | ||
| 513 | return AD8460_OVERCURRENT_SNK; | ||
| 514 | default: | ||
| 515 | return -EINVAL; | ||
| 516 | } | ||
| 517 | case IIO_TEMP: | ||
| 518 | switch (dir) { | ||
| 519 | case IIO_EV_DIR_RISING: | ||
| 520 | return AD8460_OVERTEMPERATURE; | ||
| 521 | default: | ||
| 522 | return -EINVAL; | ||
| 523 | } | ||
| 524 | default: | ||
| 525 | return -EINVAL; | ||
| 526 | } | ||
| 527 | } | ||
| 528 | |||
| 529 | static int ad8460_write_event_value(struct iio_dev *indio_dev, | ||
| 530 | const struct iio_chan_spec *chan, | ||
| 531 | enum iio_event_type type, | ||
| 532 | enum iio_event_direction dir, | ||
| 533 | enum iio_event_info info, int val, int val2) | ||
| 534 | { | ||
| 535 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 536 | int fault; | ||
| 537 | |||
| 538 | if (type != IIO_EV_TYPE_THRESH) | ||
| 539 | return -EINVAL; | ||
| 540 | |||
| 541 | if (info != IIO_EV_INFO_VALUE) | ||
| 542 | return -EINVAL; | ||
| 543 | |||
| 544 | fault = ad8460_select_fault_type(chan->type, dir); | ||
| 545 | if (fault < 0) | ||
| 546 | return fault; | ||
| 547 | |||
| 548 | return ad8460_set_fault_threshold(state, fault, val); | ||
| 549 | } | ||
| 550 | |||
| 551 | static int ad8460_read_event_value(struct iio_dev *indio_dev, | ||
| 552 | const struct iio_chan_spec *chan, | ||
| 553 | enum iio_event_type type, | ||
| 554 | enum iio_event_direction dir, | ||
| 555 | enum iio_event_info info, int *val, int *val2) | ||
| 556 | { | ||
| 557 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 558 | int fault; | ||
| 559 | |||
| 560 | if (type != IIO_EV_TYPE_THRESH) | ||
| 561 | return -EINVAL; | ||
| 562 | |||
| 563 | if (info != IIO_EV_INFO_VALUE) | ||
| 564 | return -EINVAL; | ||
| 565 | |||
| 566 | fault = ad8460_select_fault_type(chan->type, dir); | ||
| 567 | if (fault < 0) | ||
| 568 | return fault; | ||
| 569 | |||
| 570 | return ad8460_get_fault_threshold(state, fault, val); | ||
| 571 | } | ||
| 572 | |||
| 573 | static int ad8460_write_event_config(struct iio_dev *indio_dev, | ||
| 574 | const struct iio_chan_spec *chan, | ||
| 575 | enum iio_event_type type, | ||
| 576 | enum iio_event_direction dir, bool val) | ||
| 577 | { | ||
| 578 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 579 | int fault; | ||
| 580 | |||
| 581 | if (type != IIO_EV_TYPE_THRESH) | ||
| 582 | return -EINVAL; | ||
| 583 | |||
| 584 | fault = ad8460_select_fault_type(chan->type, dir); | ||
| 585 | if (fault < 0) | ||
| 586 | return fault; | ||
| 587 | |||
| 588 | return ad8460_set_fault_threshold_en(state, fault, val); | ||
| 589 | } | ||
| 590 | |||
| 591 | static int ad8460_read_event_config(struct iio_dev *indio_dev, | ||
| 592 | const struct iio_chan_spec *chan, | ||
| 593 | enum iio_event_type type, | ||
| 594 | enum iio_event_direction dir) | ||
| 595 | { | ||
| 596 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 597 | int fault, ret; | ||
| 598 | bool en; | ||
| 599 | |||
| 600 | if (type != IIO_EV_TYPE_THRESH) | ||
| 601 | return -EINVAL; | ||
| 602 | |||
| 603 | fault = ad8460_select_fault_type(chan->type, dir); | ||
| 604 | if (fault < 0) | ||
| 605 | return fault; | ||
| 606 | |||
| 607 | ret = ad8460_get_fault_threshold_en(state, fault, &en); | ||
| 608 | if (ret) | ||
| 609 | return ret; | ||
| 610 | |||
| 611 | return en; | ||
| 612 | } | ||
| 613 | |||
| 614 | static int ad8460_reg_access(struct iio_dev *indio_dev, unsigned int reg, | ||
| 615 | unsigned int writeval, unsigned int *readval) | ||
| 616 | { | ||
| 617 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 618 | |||
| 619 | if (readval) | ||
| 620 | return regmap_read(state->regmap, reg, readval); | ||
| 621 | |||
| 622 | return regmap_write(state->regmap, reg, writeval); | ||
| 623 | } | ||
| 624 | |||
| 625 | static int ad8460_buffer_preenable(struct iio_dev *indio_dev) | ||
| 626 | { | ||
| 627 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 628 | |||
| 629 | return ad8460_enable_apg_mode(state, 0); | ||
| 630 | } | ||
| 631 | |||
| 632 | static int ad8460_buffer_postdisable(struct iio_dev *indio_dev) | ||
| 633 | { | ||
| 634 | struct ad8460_state *state = iio_priv(indio_dev); | ||
| 635 | |||
| 636 | return ad8460_enable_apg_mode(state, 1); | ||
| 637 | } | ||
| 638 | |||
| 639 | static const struct iio_buffer_setup_ops ad8460_buffer_setup_ops = { | ||
| 640 | .preenable = &ad8460_buffer_preenable, | ||
| 641 | .postdisable = &ad8460_buffer_postdisable, | ||
| 642 | }; | ||
| 643 | |||
| 644 | static const struct iio_info ad8460_info = { | ||
| 645 | .read_raw = &ad8460_read_raw, | ||
| 646 | .write_raw = &ad8460_write_raw, | ||
| 647 | .write_event_value = &ad8460_write_event_value, | ||
| 648 | .read_event_value = &ad8460_read_event_value, | ||
| 649 | .write_event_config = &ad8460_write_event_config, | ||
| 650 | .read_event_config = &ad8460_read_event_config, | ||
| 651 | .debugfs_reg_access = &ad8460_reg_access, | ||
| 652 | }; | ||
| 653 | |||
| 654 | static const struct iio_enum ad8460_powerdown_mode_enum = { | ||
| 655 | .items = ad8460_powerdown_modes, | ||
| 656 | .num_items = ARRAY_SIZE(ad8460_powerdown_modes), | ||
| 657 | .get = ad8460_get_powerdown_mode, | ||
| 658 | .set = ad8460_set_powerdown_mode, | ||
| 659 | }; | ||
| 660 | |||
| 661 | #define AD8460_CHAN_EXT_INFO(_name, _what, _read, _write) { \ | ||
| 662 | .name = (_name), \ | ||
| 663 | .read = (_read), \ | ||
| 664 | .write = (_write), \ | ||
| 665 | .private = (_what), \ | ||
| 666 | .shared = IIO_SEPARATE, \ | ||
| 667 | } | ||
| 668 | |||
| 669 | static const struct iio_chan_spec_ext_info ad8460_ext_info[] = { | ||
| 670 | AD8460_CHAN_EXT_INFO("raw0", 0, ad8460_dac_input_read, | ||
| 671 | ad8460_dac_input_write), | ||
| 672 | AD8460_CHAN_EXT_INFO("raw1", 1, ad8460_dac_input_read, | ||
| 673 | ad8460_dac_input_write), | ||
| 674 | AD8460_CHAN_EXT_INFO("raw2", 2, ad8460_dac_input_read, | ||
| 675 | ad8460_dac_input_write), | ||
| 676 | AD8460_CHAN_EXT_INFO("raw3", 3, ad8460_dac_input_read, | ||
| 677 | ad8460_dac_input_write), | ||
| 678 | AD8460_CHAN_EXT_INFO("raw4", 4, ad8460_dac_input_read, | ||
| 679 | ad8460_dac_input_write), | ||
| 680 | AD8460_CHAN_EXT_INFO("raw5", 5, ad8460_dac_input_read, | ||
| 681 | ad8460_dac_input_write), | ||
| 682 | AD8460_CHAN_EXT_INFO("raw6", 6, ad8460_dac_input_read, | ||
| 683 | ad8460_dac_input_write), | ||
| 684 | AD8460_CHAN_EXT_INFO("raw7", 7, ad8460_dac_input_read, | ||
| 685 | ad8460_dac_input_write), | ||
| 686 | AD8460_CHAN_EXT_INFO("raw8", 8, ad8460_dac_input_read, | ||
| 687 | ad8460_dac_input_write), | ||
| 688 | AD8460_CHAN_EXT_INFO("raw9", 9, ad8460_dac_input_read, | ||
| 689 | ad8460_dac_input_write), | ||
| 690 | AD8460_CHAN_EXT_INFO("raw10", 10, ad8460_dac_input_read, | ||
| 691 | ad8460_dac_input_write), | ||
| 692 | AD8460_CHAN_EXT_INFO("raw11", 11, ad8460_dac_input_read, | ||
| 693 | ad8460_dac_input_write), | ||
| 694 | AD8460_CHAN_EXT_INFO("raw12", 12, ad8460_dac_input_read, | ||
| 695 | ad8460_dac_input_write), | ||
| 696 | AD8460_CHAN_EXT_INFO("raw13", 13, ad8460_dac_input_read, | ||
| 697 | ad8460_dac_input_write), | ||
| 698 | AD8460_CHAN_EXT_INFO("raw14", 14, ad8460_dac_input_read, | ||
| 699 | ad8460_dac_input_write), | ||
| 700 | AD8460_CHAN_EXT_INFO("raw15", 15, ad8460_dac_input_read, | ||
| 701 | ad8460_dac_input_write), | ||
| 702 | AD8460_CHAN_EXT_INFO("toggle_en", 0, ad8460_read_toggle_en, | ||
| 703 | ad8460_write_toggle_en), | ||
| 704 | AD8460_CHAN_EXT_INFO("symbol", 0, ad8460_read_symbol, | ||
| 705 | ad8460_write_symbol), | ||
| 706 | AD8460_CHAN_EXT_INFO("powerdown", 0, ad8460_read_powerdown, | ||
| 707 | ad8460_write_powerdown), | ||
| 708 | IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad8460_powerdown_mode_enum), | ||
| 709 | IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, | ||
| 710 | &ad8460_powerdown_mode_enum), | ||
| 711 | { } | ||
| 712 | }; | ||
| 713 | |||
| 714 | static const struct iio_event_spec ad8460_events[] = { | ||
| 715 | { | ||
| 716 | .type = IIO_EV_TYPE_THRESH, | ||
| 717 | .dir = IIO_EV_DIR_RISING, | ||
| 718 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | | ||
| 719 | BIT(IIO_EV_INFO_ENABLE), | ||
| 720 | }, | ||
| 721 | { | ||
| 722 | .type = IIO_EV_TYPE_THRESH, | ||
| 723 | .dir = IIO_EV_DIR_FALLING, | ||
| 724 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | | ||
| 725 | BIT(IIO_EV_INFO_ENABLE), | ||
| 726 | }, | ||
| 727 | }; | ||
| 728 | |||
| 729 | #define AD8460_VOLTAGE_CHAN { \ | ||
| 730 | .type = IIO_VOLTAGE, \ | ||
| 731 | .info_mask_separate = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | ||
| 732 | BIT(IIO_CHAN_INFO_RAW) | \ | ||
| 733 | BIT(IIO_CHAN_INFO_SCALE), \ | ||
| 734 | .output = 1, \ | ||
| 735 | .indexed = 1, \ | ||
| 736 | .channel = 0, \ | ||
| 737 | .scan_index = 0, \ | ||
| 738 | .scan_type = { \ | ||
| 739 | .sign = 'u', \ | ||
| 740 | .realbits = 14, \ | ||
| 741 | .storagebits = 16, \ | ||
| 742 | .endianness = IIO_CPU, \ | ||
| 743 | }, \ | ||
| 744 | .ext_info = ad8460_ext_info, \ | ||
| 745 | .event_spec = ad8460_events, \ | ||
| 746 | .num_event_specs = ARRAY_SIZE(ad8460_events), \ | ||
| 747 | } | ||
| 748 | |||
| 749 | #define AD8460_CURRENT_CHAN { \ | ||
| 750 | .type = IIO_CURRENT, \ | ||
| 751 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
| 752 | .output = 1, \ | ||
| 753 | .indexed = 1, \ | ||
| 754 | .channel = 0, \ | ||
| 755 | .scan_index = -1, \ | ||
| 756 | .event_spec = ad8460_events, \ | ||
| 757 | .num_event_specs = ARRAY_SIZE(ad8460_events), \ | ||
| 758 | } | ||
| 759 | |||
| 760 | #define AD8460_TEMP_CHAN { \ | ||
| 761 | .type = IIO_TEMP, \ | ||
| 762 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
| 763 | .indexed = 1, \ | ||
| 764 | .channel = 0, \ | ||
| 765 | .scan_index = -1, \ | ||
| 766 | .event_spec = ad8460_events, \ | ||
| 767 | .num_event_specs = 1, \ | ||
| 768 | } | ||
| 769 | |||
| 770 | static const struct iio_chan_spec ad8460_channels[] = { | ||
| 771 | AD8460_VOLTAGE_CHAN, | ||
| 772 | AD8460_CURRENT_CHAN, | ||
| 773 | }; | ||
| 774 | |||
| 775 | static const struct iio_chan_spec ad8460_channels_with_tmp_adc[] = { | ||
| 776 | AD8460_VOLTAGE_CHAN, | ||
| 777 | AD8460_CURRENT_CHAN, | ||
| 778 | AD8460_TEMP_CHAN, | ||
| 779 | }; | ||
| 780 | |||
| 781 | static const struct regmap_config ad8460_regmap_config = { | ||
| 782 | .reg_bits = 8, | ||
| 783 | .val_bits = 8, | ||
| 784 | .max_register = 0x7F, | ||
| 785 | }; | ||
| 786 | |||
| 787 | static const char * const ad8460_supplies[] = { | ||
| 788 | "avdd_3p3v", "dvdd_3p3v", "vcc_5v", "hvcc", "hvee", "vref_5v" | ||
| 789 | }; | ||
| 790 | |||
| 791 | static int ad8460_probe(struct spi_device *spi) | ||
| 792 | { | ||
| 793 | struct device *dev = &spi->dev; | ||
| 794 | struct ad8460_state *state; | ||
| 795 | struct iio_dev *indio_dev; | ||
| 796 | u32 tmp[2], temp; | ||
| 797 | int ret; | ||
| 798 | |||
| 799 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state)); | ||
| 800 | if (!indio_dev) | ||
| 801 | return -ENOMEM; | ||
| 802 | |||
| 803 | state = iio_priv(indio_dev); | ||
| 804 | |||
| 805 | indio_dev->name = "ad8460"; | ||
| 806 | indio_dev->info = &ad8460_info; | ||
| 807 | |||
| 808 | state->spi = spi; | ||
| 809 | |||
| 810 | state->regmap = devm_regmap_init_spi(spi, &ad8460_regmap_config); | ||
| 811 | if (IS_ERR(state->regmap)) | ||
| 812 | return dev_err_probe(dev, PTR_ERR(state->regmap), | ||
| 813 | "Failed to initialize regmap"); | ||
| 814 | |||
| 815 | ret = devm_mutex_init(dev, &state->lock); | ||
| 816 | if (ret) | ||
| 817 | return ret; | ||
| 818 | |||
| 819 | state->sync_clk = devm_clk_get_enabled(dev, NULL); | ||
| 820 | if (IS_ERR(state->sync_clk)) | ||
| 821 | return dev_err_probe(dev, PTR_ERR(state->sync_clk), | ||
| 822 | "Failed to get sync clk\n"); | ||
| 823 | |||
| 824 | state->tmp_adc_channel = devm_iio_channel_get(dev, "ad8460-tmp"); | ||
| 825 | if (IS_ERR(state->tmp_adc_channel)) { | ||
| 826 | if (PTR_ERR(state->tmp_adc_channel) == -EPROBE_DEFER) | ||
| 827 | return -EPROBE_DEFER; | ||
| 828 | indio_dev->channels = ad8460_channels; | ||
| 829 | indio_dev->num_channels = ARRAY_SIZE(ad8460_channels); | ||
| 830 | } else { | ||
| 831 | indio_dev->channels = ad8460_channels_with_tmp_adc; | ||
| 832 | indio_dev->num_channels = ARRAY_SIZE(ad8460_channels_with_tmp_adc); | ||
| 833 | } | ||
| 834 | |||
| 835 | ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad8460_supplies), | ||
| 836 | ad8460_supplies); | ||
| 837 | if (ret) | ||
| 838 | return dev_err_probe(dev, ret, | ||
| 839 | "Failed to enable power supplies\n"); | ||
| 840 | |||
| 841 | ret = devm_regulator_get_enable_read_voltage(dev, "refio_1p2v"); | ||
| 842 | if (ret < 0 && ret != -ENODEV) | ||
| 843 | return dev_err_probe(dev, ret, "Failed to get reference voltage\n"); | ||
| 844 | |||
| 845 | state->refio_1p2v_mv = ret == -ENODEV ? 1200 : ret / 1000; | ||
| 846 | |||
| 847 | if (!in_range(state->refio_1p2v_mv, AD8460_MIN_VREFIO_UV / 1000, | ||
| 848 | AD8460_MAX_VREFIO_UV / 1000)) | ||
| 849 | return dev_err_probe(dev, -EINVAL, | ||
| 850 | "Invalid ref voltage range(%u mV) [%u mV, %u mV]\n", | ||
| 851 | state->refio_1p2v_mv, | ||
| 852 | AD8460_MIN_VREFIO_UV / 1000, | ||
| 853 | AD8460_MAX_VREFIO_UV / 1000); | ||
| 854 | |||
| 855 | ret = device_property_read_u32(dev, "adi,external-resistor-ohms", | ||
| 856 | &state->ext_resistor_ohms); | ||
| 857 | if (ret) | ||
| 858 | state->ext_resistor_ohms = 2000; | ||
| 859 | else if (!in_range(state->ext_resistor_ohms, AD8460_MIN_EXT_RESISTOR_OHMS, | ||
| 860 | AD8460_MAX_EXT_RESISTOR_OHMS)) | ||
| 861 | return dev_err_probe(dev, -EINVAL, | ||
| 862 | "Invalid resistor set range(%u) [%u, %u]\n", | ||
| 863 | state->ext_resistor_ohms, | ||
| 864 | AD8460_MIN_EXT_RESISTOR_OHMS, | ||
| 865 | AD8460_MAX_EXT_RESISTOR_OHMS); | ||
| 866 | |||
| 867 | ret = device_property_read_u32_array(dev, "adi,range-microamp", | ||
| 868 | tmp, ARRAY_SIZE(tmp)); | ||
| 869 | if (!ret) { | ||
| 870 | if (in_range(tmp[1], 0, AD8460_ABS_MAX_OVERCURRENT_UA)) | ||
| 871 | regmap_write(state->regmap, AD8460_CTRL_REG(0x08), | ||
| 872 | FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) | | ||
| 873 | AD8460_CURRENT_LIMIT_CONV(tmp[1])); | ||
| 874 | |||
| 875 | if (in_range(tmp[0], -AD8460_ABS_MAX_OVERCURRENT_UA, 0)) | ||
| 876 | regmap_write(state->regmap, AD8460_CTRL_REG(0x09), | ||
| 877 | FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) | | ||
| 878 | AD8460_CURRENT_LIMIT_CONV(abs(tmp[0]))); | ||
| 879 | } | ||
| 880 | |||
| 881 | ret = device_property_read_u32_array(dev, "adi,range-microvolt", | ||
| 882 | tmp, ARRAY_SIZE(tmp)); | ||
| 883 | if (!ret) { | ||
| 884 | if (in_range(tmp[1], 0, AD8460_ABS_MAX_OVERVOLTAGE_UV)) | ||
| 885 | regmap_write(state->regmap, AD8460_CTRL_REG(0x0A), | ||
| 886 | FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) | | ||
| 887 | AD8460_VOLTAGE_LIMIT_CONV(tmp[1])); | ||
| 888 | |||
| 889 | if (in_range(tmp[0], -AD8460_ABS_MAX_OVERVOLTAGE_UV, 0)) | ||
| 890 | regmap_write(state->regmap, AD8460_CTRL_REG(0x0B), | ||
| 891 | FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) | | ||
| 892 | AD8460_VOLTAGE_LIMIT_CONV(abs(tmp[0]))); | ||
| 893 | } | ||
| 894 | |||
| 895 | ret = device_property_read_u32(dev, "adi,max-millicelsius", &temp); | ||
| 896 | if (!ret) { | ||
| 897 | if (in_range(temp, AD8460_MIN_OVERTEMPERATURE_MC, | ||
| 898 | AD8460_MAX_OVERTEMPERATURE_MC)) | ||
| 899 | regmap_write(state->regmap, AD8460_CTRL_REG(0x0C), | ||
| 900 | FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) | | ||
| 901 | AD8460_TEMP_LIMIT_CONV(abs(temp))); | ||
| 902 | } | ||
| 903 | |||
| 904 | ret = ad8460_reset(state); | ||
| 905 | if (ret) | ||
| 906 | return ret; | ||
| 907 | |||
| 908 | /* Enables DAC by default */ | ||
| 909 | ret = regmap_clear_bits(state->regmap, AD8460_CTRL_REG(0x01), | ||
| 910 | AD8460_HVDAC_SLEEP_MSK); | ||
| 911 | if (ret) | ||
| 912 | return ret; | ||
| 913 | |||
| 914 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
| 915 | indio_dev->setup_ops = &ad8460_buffer_setup_ops; | ||
| 916 | |||
| 917 | ret = devm_iio_dmaengine_buffer_setup_ext(dev, indio_dev, "tx", | ||
| 918 | IIO_BUFFER_DIRECTION_OUT); | ||
| 919 | if (ret) | ||
| 920 | return dev_err_probe(dev, ret, | ||
| 921 | "Failed to get DMA buffer\n"); | ||
| 922 | |||
| 923 | return devm_iio_device_register(dev, indio_dev); | ||
| 924 | } | ||
| 925 | |||
| 926 | static const struct of_device_id ad8460_of_match[] = { | ||
| 927 | { .compatible = "adi,ad8460" }, | ||
| 928 | { } | ||
| 929 | }; | ||
| 930 | MODULE_DEVICE_TABLE(of, ad8460_of_match); | ||
| 931 | |||
| 932 | static const struct spi_device_id ad8460_spi_match[] = { | ||
| 933 | { .name = "ad8460" }, | ||
| 934 | { } | ||
| 935 | }; | ||
| 936 | MODULE_DEVICE_TABLE(spi, ad8460_spi_match); | ||
| 937 | |||
| 938 | static struct spi_driver ad8460_driver = { | ||
| 939 | .driver = { | ||
| 940 | .name = "ad8460", | ||
| 941 | .of_match_table = ad8460_of_match, | ||
| 942 | }, | ||
| 943 | .probe = ad8460_probe, | ||
| 944 | .id_table = ad8460_spi_match, | ||
| 945 | }; | ||
| 946 | module_spi_driver(ad8460_driver); | ||
| 947 | |||
| 948 | MODULE_AUTHOR("Mariel Tinaco <mariel.tinaco@analog.com"); | ||
| 949 | MODULE_DESCRIPTION("AD8460 DAC driver"); | ||
| 950 | MODULE_LICENSE("GPL"); | ||
| 951 | MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER); | ||
| @@ -29,44 +29,77 @@ · 28 unmodified lines | |||
| 29 | #include <linux/iio/buffer.h> | 29 | #include <linux/iio/buffer.h> |
| 30 | #include <linux/iio/iio.h> | 30 | #include <linux/iio/iio.h> |
| 31 | 31 | ||
| 32 | #include "ad3552r-hs.h" | ||
| 33 | |||
| 32 | /* | 34 | /* |
| 33 | * Register definitions: | 35 | * Register definitions: |
| 34 | * https://wiki.analog.com/resources/fpga/docs/axi_dac_ip#register_map | 36 | * https://wiki.analog.com/resources/fpga/docs/axi_dac_ip#register_map |
| 35 | */ | 37 | */ |
| 36 | 38 | ||
| 37 | /* Base controls */ | 39 | /* Base controls */ |
| 38 | #define AXI_DAC_REG_CONFIG 0x0c | 40 | #define AXI_DAC_CONFIG_REG 0x0c |
| 39 | #define AXI_DDS_DISABLE BIT(6) | 41 | #define AXI_DAC_CONFIG_DDS_DISABLE BIT(6) |
| 40 | 42 | ||
| 41 | /* DAC controls */ | 43 | /* DAC controls */ |
| 42 | #define AXI_DAC_REG_RSTN 0x0040 | 44 | #define AXI_DAC_RSTN_REG 0x0040 |
| 43 | #define AXI_DAC_RSTN_CE_N BIT(2) | 45 | #define AXI_DAC_RSTN_CE_N BIT(2) |
| 44 | #define AXI_DAC_RSTN_MMCM_RSTN BIT(1) | 46 | #define AXI_DAC_RSTN_MMCM_RSTN BIT(1) |
| 45 | #define AXI_DAC_RSTN_RSTN BIT(0) | 47 | #define AXI_DAC_RSTN_RSTN BIT(0) |
| 46 | #define AXI_DAC_REG_CNTRL_1 0x0044 | 48 | #define AXI_DAC_CNTRL_1_REG 0x0044 |
| 47 | #define AXI_DAC_SYNC BIT(0) | 49 | #define AXI_DAC_CNTRL_1_SYNC BIT(0) |
| 48 | #define AXI_DAC_REG_CNTRL_2 0x0048 | 50 | #define AXI_DAC_CNTRL_2_REG 0x0048 |
| 49 | #define ADI_DAC_R1_MODE BIT(4) | 51 | #define AXI_DAC_CNTRL_2_SDR_DDR_N BIT(16) |
| 50 | #define AXI_DAC_DRP_STATUS 0x0074 | 52 | #define AXI_DAC_CNTRL_2_SYMB_8B BIT(14) |
| 51 | #define AXI_DAC_DRP_LOCKED BIT(17) | 53 | #define ADI_DAC_CNTRL_2_R1_MODE BIT(5) |
| 54 | #define AXI_DAC_CNTRL_2_UNSIGNED_DATA BIT(4) | ||
| 55 | #define AXI_DAC_STATUS_1_REG 0x0054 | ||
| 56 | #define AXI_DAC_STATUS_2_REG 0x0058 | ||
| 57 | #define AXI_DAC_DRP_STATUS_REG 0x0074 | ||
| 58 | #define AXI_DAC_DRP_STATUS_DRP_LOCKED BIT(17) | ||
| 59 | #define AXI_DAC_CUSTOM_RD_REG 0x0080 | ||
| 60 | #define AXI_DAC_CUSTOM_WR_REG 0x0084 | ||
| 61 | #define AXI_DAC_CUSTOM_WR_DATA_8 GENMASK(23, 16) | ||
| 62 | #define AXI_DAC_CUSTOM_WR_DATA_16 GENMASK(23, 8) | ||
| 63 | #define AXI_DAC_UI_STATUS_REG 0x0088 | ||
| 64 | #define AXI_DAC_UI_STATUS_IF_BUSY BIT(4) | ||
| 65 | #define AXI_DAC_CUSTOM_CTRL_REG 0x008C | ||
| 66 | #define AXI_DAC_CUSTOM_CTRL_ADDRESS GENMASK(31, 24) | ||
| 67 | #define AXI_DAC_CUSTOM_CTRL_SYNCED_TRANSFER BIT(2) | ||
| 68 | #define AXI_DAC_CUSTOM_CTRL_STREAM BIT(1) | ||
| 69 | #define AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA BIT(0) | ||
| 70 | |||
| 71 | #define AXI_DAC_CUSTOM_CTRL_STREAM_ENABLE (AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA | \ | ||
| 72 | AXI_DAC_CUSTOM_CTRL_STREAM) | ||
| 73 | |||
| 52 | /* DAC Channel controls */ | 74 | /* DAC Channel controls */ |
| 53 | #define AXI_DAC_REG_CHAN_CNTRL_1(c) (0x0400 + (c) * 0x40) | 75 | #define AXI_DAC_CHAN_CNTRL_1_REG(c) (0x0400 + (c) * 0x40) |
| 54 | #define AXI_DAC_REG_CHAN_CNTRL_3(c) (0x0408 + (c) * 0x40) | 76 | #define AXI_DAC_CHAN_CNTRL_3_REG(c) (0x0408 + (c) * 0x40) |
| 55 | #define AXI_DAC_SCALE_SIGN BIT(15) | 77 | #define AXI_DAC_CHAN_CNTRL_3_SCALE_SIGN BIT(15) |
| 56 | #define AXI_DAC_SCALE_INT BIT(14) | 78 | #define AXI_DAC_CHAN_CNTRL_3_SCALE_INT BIT(14) |
| 57 | #define AXI_DAC_SCALE GENMASK(14, 0) | 79 | #define AXI_DAC_CHAN_CNTRL_3_SCALE GENMASK(14, 0) |
| 58 | #define AXI_DAC_REG_CHAN_CNTRL_2(c) (0x0404 + (c) * 0x40) | 80 | #define AXI_DAC_CHAN_CNTRL_2_REG(c) (0x0404 + (c) * 0x40) |
| 59 | #define AXI_DAC_REG_CHAN_CNTRL_4(c) (0x040c + (c) * 0x40) | 81 | #define AXI_DAC_CHAN_CNTRL_2_PHASE GENMASK(31, 16) |
| 60 | #define AXI_DAC_PHASE GENMASK(31, 16) | 82 | #define AXI_DAC_CHAN_CNTRL_2_FREQUENCY GENMASK(15, 0) |
| 61 | #define AXI_DAC_FREQUENCY GENMASK(15, 0) | 83 | #define AXI_DAC_CHAN_CNTRL_4_REG(c) (0x040c + (c) * 0x40) |
| 62 | #define AXI_DAC_REG_CHAN_CNTRL_7(c) (0x0418 + (c) * 0x40) | 84 | #define AXI_DAC_CHAN_CNTRL_7_REG(c) (0x0418 + (c) * 0x40) |
| 63 | #define AXI_DAC_DATA_SEL GENMASK(3, 0) | 85 | #define AXI_DAC_CHAN_CNTRL_7_DATA_SEL GENMASK(3, 0) |
| 86 | |||
| 87 | #define AXI_DAC_RD_ADDR(x) (BIT(7) | (x)) | ||
| 64 | 88 | ||
| 65 | /* 360 degrees in rad */ | 89 | /* 360 degrees in rad */ |
| 66 | #define AXI_DAC_2_PI_MEGA 6283190 | 90 | #define AXI_DAC_2_PI_MEGA 6283190 |
| 91 | |||
| 67 | enum { | 92 | enum { |
| 68 | AXI_DAC_DATA_INTERNAL_TONE, | 93 | AXI_DAC_DATA_INTERNAL_TONE, |
| 69 | AXI_DAC_DATA_DMA = 2, | 94 | AXI_DAC_DATA_DMA = 2, |
| 95 | AXI_DAC_DATA_INTERNAL_RAMP_16BIT = 11, | ||
| 96 | }; | ||
| 97 | |||
| 98 | struct axi_dac_info { | ||
| 99 | unsigned int version; | ||
| 100 | const struct iio_backend_info *backend_info; | ||
| 101 | bool has_dac_clk; | ||
| 102 | bool has_child_nodes; | ||
| 70 | }; | 103 | }; |
| 71 | 104 | ||
| 72 | struct axi_dac_state { | 105 | struct axi_dac_state { |
| @@ -77,9 +110,11 @@ struct axi_dac_state { · 4 unmodified lines | |||
| 77 | * data/variables. | 110 | * data/variables. |
| 78 | */ | 111 | */ |
| 79 | struct mutex lock; | 112 | struct mutex lock; |
| 113 | const struct axi_dac_info *info; | ||
| 80 | u64 dac_clk; | 114 | u64 dac_clk; |
| 81 | u32 reg_config; | 115 | u32 reg_config; |
| 82 | bool int_tone; | 116 | bool int_tone; |
| 117 | int dac_clk_rate; | ||
| 83 | }; | 118 | }; |
| 84 | 119 | ||
| 85 | static int axi_dac_enable(struct iio_backend *back) | 120 | static int axi_dac_enable(struct iio_backend *back) |
| @@ -89,7 +124,7 @@ static int axi_dac_enable(struct iio_backend *back) · 3 unmodified lines | |||
| 89 | int ret; | 124 | int ret; |
| 90 | 125 | ||
| 91 | guard(mutex)(&st->lock); | 126 | guard(mutex)(&st->lock); |
| 92 | ret = regmap_set_bits(st->regmap, AXI_DAC_REG_RSTN, | 127 | ret = regmap_set_bits(st->regmap, AXI_DAC_RSTN_REG, |
| 93 | AXI_DAC_RSTN_MMCM_RSTN); | 128 | AXI_DAC_RSTN_MMCM_RSTN); |
| 94 | if (ret) | 129 | if (ret) |
| 95 | return ret; | 130 | return ret; |
| @@ -98,12 +133,14 @@ static int axi_dac_enable(struct iio_backend *back) · 2 unmodified lines | |||
| 98 | * designs really use it but if they don't we still get the lock bit | 133 | * designs really use it but if they don't we still get the lock bit |
| 99 | * set. So let's do it all the time so the code is generic. | 134 | * set. So let's do it all the time so the code is generic. |
| 100 | */ | 135 | */ |
| 101 | ret = regmap_read_poll_timeout(st->regmap, AXI_DAC_DRP_STATUS, __val, | 136 | ret = regmap_read_poll_timeout(st->regmap, AXI_DAC_DRP_STATUS_REG, |
| 102 | __val & AXI_DAC_DRP_LOCKED, 100, 1000); | 137 | __val, |
| 138 | __val & AXI_DAC_DRP_STATUS_DRP_LOCKED, | ||
| 139 | 100, 1000); | ||
| 103 | if (ret) | 140 | if (ret) |
| 104 | return ret; | 141 | return ret; |
| 105 | 142 | ||
| 106 | return regmap_set_bits(st->regmap, AXI_DAC_REG_RSTN, | 143 | return regmap_set_bits(st->regmap, AXI_DAC_RSTN_REG, |
| 107 | AXI_DAC_RSTN_RSTN | AXI_DAC_RSTN_MMCM_RSTN); | 144 | AXI_DAC_RSTN_RSTN | AXI_DAC_RSTN_MMCM_RSTN); |
| 108 | } | 145 | } |
| 109 | 146 | ||
| @@ -112,7 +149,7 @@ static void axi_dac_disable(struct iio_backend *back) · 2 unmodified lines | |||
| 112 | struct axi_dac_state *st = iio_backend_get_priv(back); | 149 | struct axi_dac_state *st = iio_backend_get_priv(back); |
| 113 | 150 | ||
| 114 | guard(mutex)(&st->lock); | 151 | guard(mutex)(&st->lock); |
| 115 | regmap_write(st->regmap, AXI_DAC_REG_RSTN, 0); | 152 | regmap_write(st->regmap, AXI_DAC_RSTN_REG, 0); |
| 116 | } | 153 | } |
| 117 | 154 | ||
| 118 | static struct iio_buffer *axi_dac_request_buffer(struct iio_backend *back, | 155 | static struct iio_buffer *axi_dac_request_buffer(struct iio_backend *back, |
| @@ -155,15 +192,15 @@ static int __axi_dac_frequency_get(struct axi_dac_state *st, unsigned int chan, · 36 unmodified lines | |||
| 155 | } | 192 | } |
| 156 | 193 | ||
| 157 | if (tone_2) | 194 | if (tone_2) |
| 158 | reg = AXI_DAC_REG_CHAN_CNTRL_4(chan); | 195 | reg = AXI_DAC_CHAN_CNTRL_4_REG(chan); |
| 159 | else | 196 | else |
| 160 | reg = AXI_DAC_REG_CHAN_CNTRL_2(chan); | 197 | reg = AXI_DAC_CHAN_CNTRL_2_REG(chan); |
| 161 | 198 | ||
| 162 | ret = regmap_read(st->regmap, reg, &raw); | 199 | ret = regmap_read(st->regmap, reg, &raw); |
| 163 | if (ret) | 200 | if (ret) |
| 164 | return ret; | 201 | return ret; |
| 165 | 202 | ||
| 166 | raw = FIELD_GET(AXI_DAC_FREQUENCY, raw); | 203 | raw = FIELD_GET(AXI_DAC_CHAN_CNTRL_2_FREQUENCY, raw); |
| 167 | *freq = DIV_ROUND_CLOSEST_ULL(raw * st->dac_clk, BIT(16)); | 204 | *freq = DIV_ROUND_CLOSEST_ULL(raw * st->dac_clk, BIT(16)); |
| 168 | 205 | ||
| 169 | return 0; | 206 | return 0; |
| @@ -194,17 +231,18 @@ static int axi_dac_scale_get(struct axi_dac_state *st, · 24 unmodified lines | |||
| 194 | u32 reg, raw; | 231 | u32 reg, raw; |
| 195 | 232 | ||
| 196 | if (tone_2) | 233 | if (tone_2) |
| 197 | reg = AXI_DAC_REG_CHAN_CNTRL_3(chan->channel); | 234 | reg = AXI_DAC_CHAN_CNTRL_3_REG(chan->channel); |
| 198 | else | 235 | else |
| 199 | reg = AXI_DAC_REG_CHAN_CNTRL_1(chan->channel); | 236 | reg = AXI_DAC_CHAN_CNTRL_1_REG(chan->channel); |
| 200 | 237 | ||
| 201 | ret = regmap_read(st->regmap, reg, &raw); | 238 | ret = regmap_read(st->regmap, reg, &raw); |
| 202 | if (ret) | 239 | if (ret) |
| 203 | return ret; | 240 | return ret; |
| 204 | 241 | ||
| 205 | sign = FIELD_GET(AXI_DAC_SCALE_SIGN, raw); | 242 | sign = FIELD_GET(AXI_DAC_CHAN_CNTRL_3_SCALE_SIGN, raw); |
| 206 | raw = FIELD_GET(AXI_DAC_SCALE, raw); | 243 | raw = FIELD_GET(AXI_DAC_CHAN_CNTRL_3_SCALE, raw); |
| 207 | scale = DIV_ROUND_CLOSEST_ULL((u64)raw * MEGA, AXI_DAC_SCALE_INT); | 244 | scale = DIV_ROUND_CLOSEST_ULL((u64)raw * MEGA, |
| 245 | AXI_DAC_CHAN_CNTRL_3_SCALE_INT); | ||
| 208 | 246 | ||
| 209 | vals[0] = scale / MEGA; | 247 | vals[0] = scale / MEGA; |
| 210 | vals[1] = scale % MEGA; | 248 | vals[1] = scale % MEGA; |
| @@ -227,15 +265,15 @@ static int axi_dac_phase_get(struct axi_dac_state *st, · 16 unmodified lines | |||
| 227 | int ret, vals[2]; | 265 | int ret, vals[2]; |
| 228 | 266 | ||
| 229 | if (tone_2) | 267 | if (tone_2) |
| 230 | reg = AXI_DAC_REG_CHAN_CNTRL_4(chan->channel); | 268 | reg = AXI_DAC_CHAN_CNTRL_4_REG(chan->channel); |
| 231 | else | 269 | else |
| 232 | reg = AXI_DAC_REG_CHAN_CNTRL_2(chan->channel); | 270 | reg = AXI_DAC_CHAN_CNTRL_2_REG(chan->channel); |
| 233 | 271 | ||
| 234 | ret = regmap_read(st->regmap, reg, &raw); | 272 | ret = regmap_read(st->regmap, reg, &raw); |
| 235 | if (ret) | 273 | if (ret) |
| 236 | return ret; | 274 | return ret; |
| 237 | 275 | ||
| 238 | raw = FIELD_GET(AXI_DAC_PHASE, raw); | 276 | raw = FIELD_GET(AXI_DAC_CHAN_CNTRL_2_PHASE, raw); |
| 239 | phase = DIV_ROUND_CLOSEST_ULL((u64)raw * AXI_DAC_2_PI_MEGA, U16_MAX); | 277 | phase = DIV_ROUND_CLOSEST_ULL((u64)raw * AXI_DAC_2_PI_MEGA, U16_MAX); |
| 240 | 278 | ||
| 241 | vals[0] = phase / MEGA; | 279 | vals[0] = phase / MEGA; |
| @@ -260,18 +298,20 @@ static int __axi_dac_frequency_set(struct axi_dac_state *st, unsigned int chan, · 18 unmodified lines | |||
| 260 | } | 298 | } |
| 261 | 299 | ||
| 262 | if (tone_2) | 300 | if (tone_2) |
| 263 | reg = AXI_DAC_REG_CHAN_CNTRL_4(chan); | 301 | reg = AXI_DAC_CHAN_CNTRL_4_REG(chan); |
| 264 | else | 302 | else |
| 265 | reg = AXI_DAC_REG_CHAN_CNTRL_2(chan); | 303 | reg = AXI_DAC_CHAN_CNTRL_2_REG(chan); |
| 266 | 304 | ||
| 267 | raw = DIV64_U64_ROUND_CLOSEST((u64)freq * BIT(16), sample_rate); | 305 | raw = DIV64_U64_ROUND_CLOSEST((u64)freq * BIT(16), sample_rate); |
| 268 | 306 | ||
| 269 | ret = regmap_update_bits(st->regmap, reg, AXI_DAC_FREQUENCY, raw); | 307 | ret = regmap_update_bits(st->regmap, reg, |
| 308 | AXI_DAC_CHAN_CNTRL_2_FREQUENCY, raw); | ||
| 270 | if (ret) | 309 | if (ret) |
| 271 | return ret; | 310 | return ret; |
| 272 | 311 | ||
| 273 | /* synchronize channels */ | 312 | /* synchronize channels */ |
| 274 | return regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC); | 313 | return regmap_set_bits(st->regmap, AXI_DAC_CNTRL_1_REG, |
| 314 | AXI_DAC_CNTRL_1_SYNC); | ||
| 275 | } | 315 | } |
| 276 | 316 | ||
| 277 | static int axi_dac_frequency_set(struct axi_dac_state *st, | 317 | static int axi_dac_frequency_set(struct axi_dac_state *st, |
| @@ -312,16 +352,16 @@ static int axi_dac_scale_set(struct axi_dac_state *st, · 34 unmodified lines | |||
| 312 | 352 | ||
| 313 | /* format is 1.1.14 (sign, integer and fractional bits) */ | 353 | /* format is 1.1.14 (sign, integer and fractional bits) */ |
| 314 | if (scale < 0) { | 354 | if (scale < 0) { |
| 315 | raw = FIELD_PREP(AXI_DAC_SCALE_SIGN, 1); | 355 | raw = FIELD_PREP(AXI_DAC_CHAN_CNTRL_3_SCALE_SIGN, 1); |
| 316 | scale *= -1; | 356 | scale *= -1; |
| 317 | } | 357 | } |
| 318 | 358 | ||
| 319 | raw |= div_u64((u64)scale * AXI_DAC_SCALE_INT, MEGA); | 359 | raw |= div_u64((u64)scale * AXI_DAC_CHAN_CNTRL_3_SCALE_INT, MEGA); |
| 320 | 360 | ||
| 321 | if (tone_2) | 361 | if (tone_2) |
| 322 | reg = AXI_DAC_REG_CHAN_CNTRL_3(chan->channel); | 362 | reg = AXI_DAC_CHAN_CNTRL_3_REG(chan->channel); |
| 323 | else | 363 | else |
| 324 | reg = AXI_DAC_REG_CHAN_CNTRL_1(chan->channel); | 364 | reg = AXI_DAC_CHAN_CNTRL_1_REG(chan->channel); |
| 325 | 365 | ||
| 326 | guard(mutex)(&st->lock); | 366 | guard(mutex)(&st->lock); |
| 327 | ret = regmap_write(st->regmap, reg, raw); | 367 | ret = regmap_write(st->regmap, reg, raw); |
| @@ -329,7 +369,8 @@ static int axi_dac_scale_set(struct axi_dac_state *st, · 1 unmodified line | |||
| 329 | return ret; | 369 | return ret; |
| 330 | 370 | ||
| 331 | /* synchronize channels */ | 371 | /* synchronize channels */ |
| 332 | ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC); | 372 | ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_1_REG, |
| 373 | AXI_DAC_CNTRL_1_SYNC); | ||
| 333 | if (ret) | 374 | if (ret) |
| 334 | return ret; | 375 | return ret; |
| 335 | 376 | ||
| @@ -355,18 +396,19 @@ static int axi_dac_phase_set(struct axi_dac_state *st, · 19 unmodified lines | |||
| 355 | raw = DIV_ROUND_CLOSEST_ULL((u64)phase * U16_MAX, AXI_DAC_2_PI_MEGA); | 396 | raw = DIV_ROUND_CLOSEST_ULL((u64)phase * U16_MAX, AXI_DAC_2_PI_MEGA); |
| 356 | 397 | ||
| 357 | if (tone_2) | 398 | if (tone_2) |
| 358 | reg = AXI_DAC_REG_CHAN_CNTRL_4(chan->channel); | 399 | reg = AXI_DAC_CHAN_CNTRL_4_REG(chan->channel); |
| 359 | else | 400 | else |
| 360 | reg = AXI_DAC_REG_CHAN_CNTRL_2(chan->channel); | 401 | reg = AXI_DAC_CHAN_CNTRL_2_REG(chan->channel); |
| 361 | 402 | ||
| 362 | guard(mutex)(&st->lock); | 403 | guard(mutex)(&st->lock); |
| 363 | ret = regmap_update_bits(st->regmap, reg, AXI_DAC_PHASE, | 404 | ret = regmap_update_bits(st->regmap, reg, AXI_DAC_CHAN_CNTRL_2_PHASE, |
| 364 | FIELD_PREP(AXI_DAC_PHASE, raw)); | 405 | FIELD_PREP(AXI_DAC_CHAN_CNTRL_2_PHASE, raw)); |
| 365 | if (ret) | 406 | if (ret) |
| 366 | return ret; | 407 | return ret; |
| 367 | 408 | ||
| 368 | /* synchronize channels */ | 409 | /* synchronize channels */ |
| 369 | ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC); | 410 | ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_1_REG, |
| 411 | AXI_DAC_CNTRL_1_SYNC); | ||
| 370 | if (ret) | 412 | if (ret) |
| 371 | return ret; | 413 | return ret; |
| 372 | 414 | ||
| @@ -437,7 +479,7 @@ static int axi_dac_extend_chan(struct iio_backend *back, · 64 unmodified lines | |||
| 437 | 479 | ||
| 438 | if (chan->type != IIO_ALTVOLTAGE) | 480 | if (chan->type != IIO_ALTVOLTAGE) |
| 439 | return -EINVAL; | 481 | return -EINVAL; |
| 440 | if (st->reg_config & AXI_DDS_DISABLE) | 482 | if (st->reg_config & AXI_DAC_CONFIG_DDS_DISABLE) |
| 441 | /* nothing to extend */ | 483 | /* nothing to extend */ |
| 442 | return 0; | 484 | return 0; |
| 443 | 485 | ||
| @@ -454,13 +496,19 @@ static int axi_dac_data_source_set(struct iio_backend *back, unsigned int chan, · 10 unmodified lines | |||
| 454 | switch (data) { | 496 | switch (data) { |
| 455 | case IIO_BACKEND_INTERNAL_CONTINUOUS_WAVE: | 497 | case IIO_BACKEND_INTERNAL_CONTINUOUS_WAVE: |
| 456 | return regmap_update_bits(st->regmap, | 498 | return regmap_update_bits(st->regmap, |
| 457 | AXI_DAC_REG_CHAN_CNTRL_7(chan), | 499 | AXI_DAC_CHAN_CNTRL_7_REG(chan), |
| 458 | AXI_DAC_DATA_SEL, | 500 | AXI_DAC_CHAN_CNTRL_7_DATA_SEL, |
| 459 | AXI_DAC_DATA_INTERNAL_TONE); | 501 | AXI_DAC_DATA_INTERNAL_TONE); |
| 460 | case IIO_BACKEND_EXTERNAL: | 502 | case IIO_BACKEND_EXTERNAL: |
| 461 | return regmap_update_bits(st->regmap, | 503 | return regmap_update_bits(st->regmap, |
| 462 | AXI_DAC_REG_CHAN_CNTRL_7(chan), | 504 | AXI_DAC_CHAN_CNTRL_7_REG(chan), |
| 463 | AXI_DAC_DATA_SEL, AXI_DAC_DATA_DMA); | 505 | AXI_DAC_CHAN_CNTRL_7_DATA_SEL, |
| 506 | AXI_DAC_DATA_DMA); | ||
| 507 | case IIO_BACKEND_INTERNAL_RAMP_16BIT: | ||
| 508 | return regmap_update_bits(st->regmap, | ||
| 509 | AXI_DAC_CHAN_CNTRL_7_REG(chan), | ||
| 510 | AXI_DAC_CHAN_CNTRL_7_DATA_SEL, | ||
| 511 | AXI_DAC_DATA_INTERNAL_RAMP_16BIT); | ||
| 464 | default: | 512 | default: |
| 465 | return -EINVAL; | 513 | return -EINVAL; |
| 466 | } | 514 | } |
| @@ -475,7 +523,7 @@ static int axi_dac_set_sample_rate(struct iio_backend *back, unsigned int chan, · 8 unmodified lines | |||
| 475 | 523 | ||
| 476 | if (!sample_rate) | 524 | if (!sample_rate) |
| 477 | return -EINVAL; | 525 | return -EINVAL; |
| 478 | if (st->reg_config & AXI_DDS_DISABLE) | 526 | if (st->reg_config & AXI_DAC_CONFIG_DDS_DISABLE) |
| 479 | /* sample_rate has no meaning if DDS is disabled */ | 527 | /* sample_rate has no meaning if DDS is disabled */ |
| 480 | return 0; | 528 | return 0; |
| 481 | 529 | ||
| @@ -518,6 +566,184 @@ static int axi_dac_reg_access(struct iio_backend *back, unsigned int reg, · 36 unmodified lines | |||
| 518 | return regmap_write(st->regmap, reg, writeval); | 566 | return regmap_write(st->regmap, reg, writeval); |
| 519 | } | 567 | } |
| 520 | 568 | ||
| 569 | static int axi_dac_ddr_enable(struct iio_backend *back) | ||
| 570 | { | ||
| 571 | struct axi_dac_state *st = iio_backend_get_priv(back); | ||
| 572 | |||
| 573 | return regmap_clear_bits(st->regmap, AXI_DAC_CNTRL_2_REG, | ||
| 574 | AXI_DAC_CNTRL_2_SDR_DDR_N); | ||
| 575 | } | ||
| 576 | |||
| 577 | static int axi_dac_ddr_disable(struct iio_backend *back) | ||
| 578 | { | ||
| 579 | struct axi_dac_state *st = iio_backend_get_priv(back); | ||
| 580 | |||
| 581 | return regmap_set_bits(st->regmap, AXI_DAC_CNTRL_2_REG, | ||
| 582 | AXI_DAC_CNTRL_2_SDR_DDR_N); | ||
| 583 | } | ||
| 584 | |||
| 585 | static int axi_dac_data_stream_enable(struct iio_backend *back) | ||
| 586 | { | ||
| 587 | struct axi_dac_state *st = iio_backend_get_priv(back); | ||
| 588 | |||
| 589 | return regmap_set_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG, | ||
| 590 | AXI_DAC_CUSTOM_CTRL_STREAM_ENABLE); | ||
| 591 | } | ||
| 592 | |||
| 593 | static int axi_dac_data_stream_disable(struct iio_backend *back) | ||
| 594 | { | ||
| 595 | struct axi_dac_state *st = iio_backend_get_priv(back); | ||
| 596 | |||
| 597 | return regmap_clear_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG, | ||
| 598 | AXI_DAC_CUSTOM_CTRL_STREAM_ENABLE); | ||
| 599 | } | ||
| 600 | |||
| 601 | static int axi_dac_data_transfer_addr(struct iio_backend *back, u32 address) | ||
| 602 | { | ||
| 603 | struct axi_dac_state *st = iio_backend_get_priv(back); | ||
| 604 | |||
| 605 | if (address > FIELD_MAX(AXI_DAC_CUSTOM_CTRL_ADDRESS)) | ||
| 606 | return -EINVAL; | ||
| 607 | |||
| 608 | /* | ||
| 609 | * Sample register address, when the DAC is configured, or stream | ||
| 610 | * start address when the FSM is in stream state. | ||
| 611 | */ | ||
| 612 | return regmap_update_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG, | ||
| 613 | AXI_DAC_CUSTOM_CTRL_ADDRESS, | ||
| 614 | FIELD_PREP(AXI_DAC_CUSTOM_CTRL_ADDRESS, | ||
| 615 | address)); | ||
| 616 | } | ||
| 617 | |||
| 618 | static int axi_dac_data_format_set(struct iio_backend *back, unsigned int ch, | ||
| 619 | const struct iio_backend_data_fmt *data) | ||
| 620 | { | ||
| 621 | struct axi_dac_state *st = iio_backend_get_priv(back); | ||
| 622 | |||
| 623 | switch (data->type) { | ||
| 624 | case IIO_BACKEND_DATA_UNSIGNED: | ||
| 625 | return regmap_clear_bits(st->regmap, AXI_DAC_CNTRL_2_REG, | ||
| 626 | AXI_DAC_CNTRL_2_UNSIGNED_DATA); | ||
| 627 | default: | ||
| 628 | return -EINVAL; | ||
| 629 | } | ||
| 630 | } | ||
| 631 | |||
| 632 | static int __axi_dac_bus_reg_write(struct iio_backend *back, u32 reg, | ||
| 633 | u32 val, size_t data_size) | ||
| 634 | { | ||
| 635 | struct axi_dac_state *st = iio_backend_get_priv(back); | ||
| 636 | int ret; | ||
| 637 | u32 ival; | ||
| 638 | |||
| 639 | /* | ||
| 640 | * Both AXI_DAC_CNTRL_2_REG and AXI_DAC_CUSTOM_WR_REG need to know | ||
| 641 | * the data size. So keeping data size control here only, | ||
| 642 | * since data size is mandatory for the current transfer. | ||
| 643 | * DDR state handled separately by specific backend calls, | ||
| 644 | * generally all raw register writes are SDR. | ||
| 645 | */ | ||
| 646 | if (data_size == sizeof(u16)) | ||
| 647 | ival = FIELD_PREP(AXI_DAC_CUSTOM_WR_DATA_16, val); | ||
| 648 | else | ||
| 649 | ival = FIELD_PREP(AXI_DAC_CUSTOM_WR_DATA_8, val); | ||
| 650 | |||
| 651 | ret = regmap_write(st->regmap, AXI_DAC_CUSTOM_WR_REG, ival); | ||
| 652 | if (ret) | ||
| 653 | return ret; | ||
| 654 | |||
| 655 | if (data_size == sizeof(u8)) | ||
| 656 | ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_2_REG, | ||
| 657 | AXI_DAC_CNTRL_2_SYMB_8B); | ||
| 658 | else | ||
| 659 | ret = regmap_clear_bits(st->regmap, AXI_DAC_CNTRL_2_REG, | ||
| 660 | AXI_DAC_CNTRL_2_SYMB_8B); | ||
| 661 | if (ret) | ||
| 662 | return ret; | ||
| 663 | |||
| 664 | ret = regmap_update_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG, | ||
| 665 | AXI_DAC_CUSTOM_CTRL_ADDRESS, | ||
| 666 | FIELD_PREP(AXI_DAC_CUSTOM_CTRL_ADDRESS, reg)); | ||
| 667 | if (ret) | ||
| 668 | return ret; | ||
| 669 | |||
| 670 | ret = regmap_update_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG, | ||
| 671 | AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA, | ||
| 672 | AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA); | ||
| 673 | if (ret) | ||
| 674 | return ret; | ||
| 675 | |||
| 676 | ret = regmap_read_poll_timeout(st->regmap, | ||
| 677 | AXI_DAC_UI_STATUS_REG, ival, | ||
| 678 | FIELD_GET(AXI_DAC_UI_STATUS_IF_BUSY, ival) == 0, | ||
| 679 | 10, 100 * KILO); | ||
| 680 | if (ret == -ETIMEDOUT) | ||
| 681 | dev_err(st->dev, "AXI read timeout\n"); | ||
| 682 | |||
| 683 | /* Cleaning always AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA */ | ||
| 684 | return regmap_clear_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG, | ||
| 685 | AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA); | ||
| 686 | } | ||
| 687 | |||
| 688 | static int axi_dac_bus_reg_write(struct iio_backend *back, u32 reg, | ||
| 689 | u32 val, size_t data_size) | ||
| 690 | { | ||
| 691 | struct axi_dac_state *st = iio_backend_get_priv(back); | ||
| 692 | |||
| 693 | guard(mutex)(&st->lock); | ||
| 694 | return __axi_dac_bus_reg_write(back, reg, val, data_size); | ||
| 695 | } | ||
| 696 | |||
| 697 | static int axi_dac_bus_reg_read(struct iio_backend *back, u32 reg, u32 *val, | ||
| 698 | size_t data_size) | ||
| 699 | { | ||
| 700 | struct axi_dac_state *st = iio_backend_get_priv(back); | ||
| 701 | int ret; | ||
| 702 | |||
| 703 | guard(mutex)(&st->lock); | ||
| 704 | |||
| 705 | /* | ||
| 706 | * SPI, we write with read flag, then we read just at the AXI | ||
| 707 | * io address space to get data read. | ||
| 708 | */ | ||
| 709 | ret = __axi_dac_bus_reg_write(back, AXI_DAC_RD_ADDR(reg), 0, | ||
| 710 | data_size); | ||
| 711 | if (ret) | ||
| 712 | return ret; | ||
| 713 | |||
| 714 | return regmap_read(st->regmap, AXI_DAC_CUSTOM_RD_REG, val); | ||
| 715 | } | ||
| 716 | |||
| 717 | static void axi_dac_child_remove(void *data) | ||
| 718 | { | ||
| 719 | platform_device_unregister(data); | ||
| 720 | } | ||
| 721 | |||
| 722 | static int axi_dac_create_platform_device(struct axi_dac_state *st, | ||
| 723 | struct fwnode_handle *child) | ||
| 724 | { | ||
| 725 | struct ad3552r_hs_platform_data pdata = { | ||
| 726 | .bus_reg_read = axi_dac_bus_reg_read, | ||
| 727 | .bus_reg_write = axi_dac_bus_reg_write, | ||
| 728 | .bus_sample_data_clock_hz = st->dac_clk_rate, | ||
| 729 | }; | ||
| 730 | struct platform_device_info pi = { | ||
| 731 | .parent = st->dev, | ||
| 732 | .name = fwnode_get_name(child), | ||
| 733 | .id = PLATFORM_DEVID_AUTO, | ||
| 734 | .fwnode = child, | ||
| 735 | .data = &pdata, | ||
| 736 | .size_data = sizeof(pdata), | ||
| 737 | }; | ||
| 738 | struct platform_device *pdev; | ||
| 739 | |||
| 740 | pdev = platform_device_register_full(&pi); | ||
| 741 | if (IS_ERR(pdev)) | ||
| 742 | return PTR_ERR(pdev); | ||
| 743 | |||
| 744 | return devm_add_action_or_reset(st->dev, axi_dac_child_remove, pdev); | ||
| 745 | } | ||
| 746 | |||
| 521 | static const struct iio_backend_ops axi_dac_generic_ops = { | 747 | static const struct iio_backend_ops axi_dac_generic_ops = { |
| 522 | .enable = axi_dac_enable, | 748 | .enable = axi_dac_enable, |
| 523 | .disable = axi_dac_disable, | 749 | .disable = axi_dac_disable, |
| @@ -531,11 +757,30 @@ static const struct iio_backend_ops axi_dac_generic_ops = { · 7 unmodified lines | |||
| 531 | .debugfs_reg_access = iio_backend_debugfs_ptr(axi_dac_reg_access), | 757 | .debugfs_reg_access = iio_backend_debugfs_ptr(axi_dac_reg_access), |
| 532 | }; | 758 | }; |
| 533 | 759 | ||
| 760 | static const struct iio_backend_ops axi_ad3552r_ops = { | ||
| 761 | .enable = axi_dac_enable, | ||
| 762 | .disable = axi_dac_disable, | ||
| 763 | .request_buffer = axi_dac_request_buffer, | ||
| 764 | .free_buffer = axi_dac_free_buffer, | ||
| 765 | .data_source_set = axi_dac_data_source_set, | ||
| 766 | .ddr_enable = axi_dac_ddr_enable, | ||
| 767 | .ddr_disable = axi_dac_ddr_disable, | ||
| 768 | .data_stream_enable = axi_dac_data_stream_enable, | ||
| 769 | .data_stream_disable = axi_dac_data_stream_disable, | ||
| 770 | .data_format_set = axi_dac_data_format_set, | ||
| 771 | .data_transfer_addr = axi_dac_data_transfer_addr, | ||
| 772 | }; | ||
| 773 | |||
| 534 | static const struct iio_backend_info axi_dac_generic = { | 774 | static const struct iio_backend_info axi_dac_generic = { |
| 535 | .name = "axi-dac", | 775 | .name = "axi-dac", |
| 536 | .ops = &axi_dac_generic_ops, | 776 | .ops = &axi_dac_generic_ops, |
| 537 | }; | 777 | }; |
| 538 | 778 | ||
| 779 | static const struct iio_backend_info axi_ad3552r = { | ||
| 780 | .name = "axi-ad3552r", | ||
| 781 | .ops = &axi_ad3552r_ops, | ||
| 782 | }; | ||
| 783 | |||
| 539 | static const struct regmap_config axi_dac_regmap_config = { | 784 | static const struct regmap_config axi_dac_regmap_config = { |
| 540 | .val_bits = 32, | 785 | .val_bits = 32, |
| 541 | .reg_bits = 32, | 786 | .reg_bits = 32, |
| @@ -545,7 +790,6 @@ static const struct regmap_config axi_dac_regmap_config = { · 3 unmodified lines | |||
| 545 | 790 | ||
| 546 | static int axi_dac_probe(struct platform_device *pdev) | 791 | static int axi_dac_probe(struct platform_device *pdev) |
| 547 | { | 792 | { |
| 548 | const unsigned int *expected_ver; | ||
| 549 | struct axi_dac_state *st; | 793 | struct axi_dac_state *st; |
| 550 | void __iomem *base; | 794 | void __iomem *base; |
| 551 | unsigned int ver; | 795 | unsigned int ver; |
| @@ -556,14 +800,29 @@ static int axi_dac_probe(struct platform_device *pdev) · 4 unmodified lines | |||
| 556 | if (!st) | 800 | if (!st) |
| 557 | return -ENOMEM; | 801 | return -ENOMEM; |
| 558 | 802 | ||
| 559 | expected_ver = device_get_match_data(&pdev->dev); | 803 | st->info = device_get_match_data(&pdev->dev); |
| 560 | if (!expected_ver) | 804 | if (!st->info) |
| 561 | return -ENODEV; | 805 | return -ENODEV; |
| 806 | clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk"); | ||
| 807 | if (IS_ERR(clk)) { | ||
| 808 | /* Backward compat., old fdt versions without clock-names. */ | ||
| 809 | clk = devm_clk_get_enabled(&pdev->dev, NULL); | ||
| 810 | if (IS_ERR(clk)) | ||
| 811 | return dev_err_probe(&pdev->dev, PTR_ERR(clk), | ||
| 812 | "failed to get clock\n"); | ||
| 813 | } | ||
| 562 | 814 | ||
| 563 | clk = devm_clk_get_enabled(&pdev->dev, NULL); | 815 | if (st->info->has_dac_clk) { |
| 564 | if (IS_ERR(clk)) | 816 | struct clk *dac_clk; |
| 565 | return dev_err_probe(&pdev->dev, PTR_ERR(clk), | 817 | |
| 566 | "failed to get clock\n"); | 818 | dac_clk = devm_clk_get_enabled(&pdev->dev, "dac_clk"); |
| 819 | if (IS_ERR(dac_clk)) | ||
| 820 | return dev_err_probe(&pdev->dev, PTR_ERR(dac_clk), | ||
| 821 | "failed to get dac_clk clock\n"); | ||
| 822 | |||
| 823 | /* We only care about the streaming mode rate */ | ||
| 824 | st->dac_clk_rate = clk_get_rate(dac_clk) / 2; | ||
| 825 | } | ||
| 567 | 826 | ||
| 568 | base = devm_platform_ioremap_resource(pdev, 0); | 827 | base = devm_platform_ioremap_resource(pdev, 0); |
| 569 | if (IS_ERR(base)) | 828 | if (IS_ERR(base)) |
| @@ -580,7 +839,7 @@ static int axi_dac_probe(struct platform_device *pdev) · 10 unmodified lines | |||
| 580 | * Force disable the core. Up to the frontend to enable us. And we can | 839 | * Force disable the core. Up to the frontend to enable us. And we can |
| 581 | * still read/write registers... | 840 | * still read/write registers... |
| 582 | */ | 841 | */ |
| 583 | ret = regmap_write(st->regmap, AXI_DAC_REG_RSTN, 0); | 842 | ret = regmap_write(st->regmap, AXI_DAC_RSTN_REG, 0); |
| 584 | if (ret) | 843 | if (ret) |
| 585 | return ret; | 844 | return ret; |
| 586 | 845 | ||
| @@ -588,12 +847,13 @@ static int axi_dac_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 588 | if (ret) | 847 | if (ret) |
| 589 | return ret; | 848 | return ret; |
| 590 | 849 | ||
| 591 | if (ADI_AXI_PCORE_VER_MAJOR(ver) != ADI_AXI_PCORE_VER_MAJOR(*expected_ver)) { | 850 | if (ADI_AXI_PCORE_VER_MAJOR(ver) != |
| 851 | ADI_AXI_PCORE_VER_MAJOR(st->info->version)) { | ||
| 592 | dev_err(&pdev->dev, | 852 | dev_err(&pdev->dev, |
| 593 | "Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n", | 853 | "Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n", |
| 594 | ADI_AXI_PCORE_VER_MAJOR(*expected_ver), | 854 | ADI_AXI_PCORE_VER_MAJOR(st->info->version), |
| 595 | ADI_AXI_PCORE_VER_MINOR(*expected_ver), | 855 | ADI_AXI_PCORE_VER_MINOR(st->info->version), |
| 596 | ADI_AXI_PCORE_VER_PATCH(*expected_ver), | 856 | ADI_AXI_PCORE_VER_PATCH(st->info->version), |
| 597 | ADI_AXI_PCORE_VER_MAJOR(ver), | 857 | ADI_AXI_PCORE_VER_MAJOR(ver), |
| 598 | ADI_AXI_PCORE_VER_MINOR(ver), | 858 | ADI_AXI_PCORE_VER_MINOR(ver), |
| 599 | ADI_AXI_PCORE_VER_PATCH(ver)); | 859 | ADI_AXI_PCORE_VER_PATCH(ver)); |
| @@ -601,7 +861,7 @@ static int axi_dac_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 601 | } | 861 | } |
| 602 | 862 | ||
| 603 | /* Let's get the core read only configuration */ | 863 | /* Let's get the core read only configuration */ |
| 604 | ret = regmap_read(st->regmap, AXI_DAC_REG_CONFIG, &st->reg_config); | 864 | ret = regmap_read(st->regmap, AXI_DAC_CONFIG_REG, &st->reg_config); |
| 605 | if (ret) | 865 | if (ret) |
| 606 | return ret; | 866 | return ret; |
| 607 | 867 | ||
| @@ -613,16 +873,40 @@ static int axi_dac_probe(struct platform_device *pdev) · 5 unmodified lines | |||
| 613 | * want independent channels let's override the core's default value and | 873 | * want independent channels let's override the core's default value and |
| 614 | * set the R1_MODE bit. | 874 | * set the R1_MODE bit. |
| 615 | */ | 875 | */ |
| 616 | ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_2, ADI_DAC_R1_MODE); | 876 | ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_2_REG, |
| 877 | ADI_DAC_CNTRL_2_R1_MODE); | ||
| 617 | if (ret) | 878 | if (ret) |
| 618 | return ret; | 879 | return ret; |
| 619 | 880 | ||
| 620 | mutex_init(&st->lock); | 881 | mutex_init(&st->lock); |
| 621 | ret = devm_iio_backend_register(&pdev->dev, &axi_dac_generic, st); | 882 | |
| 883 | ret = devm_iio_backend_register(&pdev->dev, st->info->backend_info, st); | ||
| 622 | if (ret) | 884 | if (ret) |
| 623 | return dev_err_probe(&pdev->dev, ret, | 885 | return dev_err_probe(&pdev->dev, ret, |
| 624 | "failed to register iio backend\n"); | 886 | "failed to register iio backend\n"); |
| 625 | 887 | ||
| 888 | device_for_each_child_node_scoped(&pdev->dev, child) { | ||
| 889 | int val; | ||
| 890 | |||
| 891 | if (!st->info->has_child_nodes) | ||
| 892 | return dev_err_probe(&pdev->dev, -EINVAL, | ||
| 893 | "invalid fdt axi-dac compatible."); | ||
| 894 | |||
| 895 | /* Processing only reg 0 node */ | ||
| 896 | ret = fwnode_property_read_u32(child, "reg", &val); | ||
| 897 | if (ret) | ||
| 898 | return dev_err_probe(&pdev->dev, ret, | ||
| 899 | "invalid reg property."); | ||
| 900 | if (val != 0) | ||
| 901 | return dev_err_probe(&pdev->dev, -EINVAL, | ||
| 902 | "invalid node address."); | ||
| 903 | |||
| 904 | ret = axi_dac_create_platform_device(st, child); | ||
| 905 | if (ret) | ||
| 906 | return dev_err_probe(&pdev->dev, -EINVAL, | ||
| 907 | "cannot create device."); | ||
| 908 | } | ||
| 909 | |||
| 626 | dev_info(&pdev->dev, "AXI DAC IP core (%d.%.2d.%c) probed\n", | 910 | dev_info(&pdev->dev, "AXI DAC IP core (%d.%.2d.%c) probed\n", |
| 627 | ADI_AXI_PCORE_VER_MAJOR(ver), | 911 | ADI_AXI_PCORE_VER_MAJOR(ver), |
| 628 | ADI_AXI_PCORE_VER_MINOR(ver), | 912 | ADI_AXI_PCORE_VER_MINOR(ver), |
| @@ -631,10 +915,21 @@ static int axi_dac_probe(struct platform_device *pdev) · 2 unmodified lines | |||
| 631 | return 0; | 915 | return 0; |
| 632 | } | 916 | } |
| 633 | 917 | ||
| 634 | static unsigned int axi_dac_9_1_b_info = ADI_AXI_PCORE_VER(9, 1, 'b'); | 918 | static const struct axi_dac_info dac_generic = { |
| 919 | .version = ADI_AXI_PCORE_VER(9, 1, 'b'), | ||
| 920 | .backend_info = &axi_dac_generic, | ||
| 921 | }; | ||
| 922 | |||
| 923 | static const struct axi_dac_info dac_ad3552r = { | ||
| 924 | .version = ADI_AXI_PCORE_VER(9, 1, 'b'), | ||
| 925 | .backend_info = &axi_ad3552r, | ||
| 926 | .has_dac_clk = true, | ||
| 927 | .has_child_nodes = true, | ||
| 928 | }; | ||
| 635 | 929 | ||
| 636 | static const struct of_device_id axi_dac_of_match[] = { | 930 | static const struct of_device_id axi_dac_of_match[] = { |
| 637 | { .compatible = "adi,axi-dac-9.1.b", .data = &axi_dac_9_1_b_info }, | 931 | { .compatible = "adi,axi-dac-9.1.b", .data = &dac_generic }, |
| 932 | { .compatible = "adi,axi-ad3552r", .data = &dac_ad3552r }, | ||
| 638 | {} | 933 | {} |
| 639 | }; | 934 | }; |
| 640 | MODULE_DEVICE_TABLE(of, axi_dac_of_match); | 935 | MODULE_DEVICE_TABLE(of, axi_dac_of_match); |
| @@ -243,7 +243,7 @@ MODULE_DEVICE_TABLE(of, dpot_dac_match); · 242 unmodified lines | |||
| 243 | 243 | ||
| 244 | static struct platform_driver dpot_dac_driver = { | 244 | static struct platform_driver dpot_dac_driver = { |
| 245 | .probe = dpot_dac_probe, | 245 | .probe = dpot_dac_probe, |
| 246 | .remove_new = dpot_dac_remove, | 246 | .remove = dpot_dac_remove, |
| 247 | .driver = { | 247 | .driver = { |
| 248 | .name = "iio-dpot-dac", | 248 | .name = "iio-dpot-dac", |
| 249 | .of_match_table = dpot_dac_match, | 249 | .of_match_table = dpot_dac_match, |
| @@ -184,9 +184,9 @@ static const struct of_device_id lpc18xx_dac_match[] = { · 183 unmodified lines | |||
| 184 | MODULE_DEVICE_TABLE(of, lpc18xx_dac_match); | 184 | MODULE_DEVICE_TABLE(of, lpc18xx_dac_match); |
| 185 | 185 | ||
| 186 | static struct platform_driver lpc18xx_dac_driver = { | 186 | static struct platform_driver lpc18xx_dac_driver = { |
| 187 | .probe = lpc18xx_dac_probe, | 187 | .probe = lpc18xx_dac_probe, |
| 188 | .remove_new = lpc18xx_dac_remove, | 188 | .remove = lpc18xx_dac_remove, |
| 189 | .driver = { | 189 | .driver = { |
| 190 | .name = "lpc18xx-dac", | 190 | .name = "lpc18xx-dac", |
| 191 | .of_match_table = lpc18xx_dac_match, | 191 | .of_match_table = lpc18xx_dac_match, |
| 192 | }, | 192 | }, |
| @@ -201,7 +201,7 @@ static int m62332_probe(struct i2c_client *client) · 200 unmodified lines | |||
| 201 | indio_dev->modes = INDIO_DIRECT_MODE; | 201 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 202 | indio_dev->info = &m62332_info; | 202 | indio_dev->info = &m62332_info; |
| 203 | 203 | ||
| 204 | ret = iio_map_array_register(indio_dev, client->dev.platform_data); | 204 | ret = iio_map_array_register(indio_dev, dev_get_platdata(&client->dev)); |
| 205 | if (ret < 0) | 205 | if (ret < 0) |
| 206 | return ret; | 206 | return ret; |
| 207 | 207 | ||
| @@ -143,10 +143,10 @@ static const struct iio_chan_spec max517_channels[] = { · 142 unmodified lines | |||
| 143 | 143 | ||
| 144 | static int max517_probe(struct i2c_client *client) | 144 | static int max517_probe(struct i2c_client *client) |
| 145 | { | 145 | { |
| 146 | const struct max517_platform_data *platform_data = dev_get_platdata(&client->dev); | ||
| 146 | const struct i2c_device_id *id = i2c_client_get_device_id(client); | 147 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
| 147 | struct max517_data *data; | 148 | struct max517_data *data; |
| 148 | struct iio_dev *indio_dev; | 149 | struct iio_dev *indio_dev; |
| 149 | struct max517_platform_data *platform_data = client->dev.platform_data; | ||
| 150 | int chan; | 150 | int chan; |
| 151 | 151 | ||
| 152 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | 152 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); |
| @@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match); · 244 unmodified lines | |||
| 245 | 245 | ||
| 246 | static struct platform_driver stm32_dac_driver = { | 246 | static struct platform_driver stm32_dac_driver = { |
| 247 | .probe = stm32_dac_probe, | 247 | .probe = stm32_dac_probe, |
| 248 | .remove_new = stm32_dac_remove, | 248 | .remove = stm32_dac_remove, |
| 249 | .driver = { | 249 | .driver = { |
| 250 | .name = "stm32-dac-core", | 250 | .name = "stm32-dac-core", |
| 251 | .of_match_table = stm32_dac_of_match, | 251 | .of_match_table = stm32_dac_of_match, |
| @@ -398,7 +398,7 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match); · 397 unmodified lines | |||
| 398 | 398 | ||
| 399 | static struct platform_driver stm32_dac_driver = { | 399 | static struct platform_driver stm32_dac_driver = { |
| 400 | .probe = stm32_dac_probe, | 400 | .probe = stm32_dac_probe, |
| 401 | .remove_new = stm32_dac_remove, | 401 | .remove = stm32_dac_remove, |
| 402 | .driver = { | 402 | .driver = { |
| 403 | .name = "stm32-dac", | 403 | .name = "stm32-dac", |
| 404 | .of_match_table = stm32_dac_of_match, | 404 | .of_match_table = stm32_dac_of_match, |
| @@ -272,7 +272,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(vf610_dac_pm_ops, vf610_dac_suspend, · 271 unmodified lines | |||
| 272 | 272 | ||
| 273 | static struct platform_driver vf610_dac_driver = { | 273 | static struct platform_driver vf610_dac_driver = { |
| 274 | .probe = vf610_dac_probe, | 274 | .probe = vf610_dac_probe, |
| 275 | .remove_new = vf610_dac_remove, | 275 | .remove = vf610_dac_remove, |
| 276 | .driver = { | 276 | .driver = { |
| 277 | .name = "vf610-dac", | 277 | .name = "vf610-dac", |
| 278 | .of_match_table = vf610_dac_match, | 278 | .of_match_table = vf610_dac_match, |
| @@ -60,7 +60,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, · 59 unmodified lines | |||
| 60 | const struct iio_chan_spec *chan, | 60 | const struct iio_chan_spec *chan, |
| 61 | enum iio_event_type type, | 61 | enum iio_event_type type, |
| 62 | enum iio_event_direction dir, | 62 | enum iio_event_direction dir, |
| 63 | int state); | 63 | bool state); |
| 64 | 64 | ||
| 65 | int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev, | 65 | int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev, |
| 66 | const struct iio_chan_spec *chan, | 66 | const struct iio_chan_spec *chan, |
| @@ -53,7 +53,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, · 52 unmodified lines | |||
| 53 | const struct iio_chan_spec *chan, | 53 | const struct iio_chan_spec *chan, |
| 54 | enum iio_event_type type, | 54 | enum iio_event_type type, |
| 55 | enum iio_event_direction dir, | 55 | enum iio_event_direction dir, |
| 56 | int state) | 56 | bool state) |
| 57 | { | 57 | { |
| 58 | struct iio_dummy_state *st = iio_priv(indio_dev); | 58 | struct iio_dummy_state *st = iio_priv(indio_dev); |
| 59 | 59 | ||
| @@ -183,36 +183,34 @@ static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) · 123 unmodified lines | |||
| 183 | switch (st->regs->reg_data) { | 183 | switch (st->regs->reg_data) { |
| 184 | case 0: | 184 | case 0: |
| 185 | iio_push_event(indio_dev, | 185 | iio_push_event(indio_dev, |
| 186 | IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, | 186 | IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0, |
| 187 | IIO_EV_DIR_RISING, | 187 | IIO_EV_TYPE_THRESH, |
| 188 | IIO_EV_TYPE_THRESH, 0, 0, 0), | 188 | IIO_EV_DIR_RISING), |
| 189 | st->event_timestamp); | 189 | st->event_timestamp); |
| 190 | break; | 190 | break; |
| 191 | case 1: | 191 | case 1: |
| 192 | if (st->activity_running > st->event_val) | 192 | if (st->activity_running > st->event_val) |
| 193 | iio_push_event(indio_dev, | 193 | iio_push_event(indio_dev, |
| 194 | IIO_EVENT_CODE(IIO_ACTIVITY, 0, | 194 | IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0, |
| 195 | IIO_MOD_RUNNING, | 195 | IIO_MOD_RUNNING, |
| 196 | IIO_EV_DIR_RISING, | 196 | IIO_EV_TYPE_THRESH, |
| 197 | IIO_EV_TYPE_THRESH, | 197 | IIO_EV_DIR_RISING), |
| 198 | 0, 0, 0), | ||
| 199 | st->event_timestamp); | 198 | st->event_timestamp); |
| 200 | break; | 199 | break; |
| 201 | case 2: | 200 | case 2: |
| 202 | if (st->activity_walking < st->event_val) | 201 | if (st->activity_walking < st->event_val) |
| 203 | iio_push_event(indio_dev, | 202 | iio_push_event(indio_dev, |
| 204 | IIO_EVENT_CODE(IIO_ACTIVITY, 0, | 203 | IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0, |
| 205 | IIO_MOD_WALKING, | 204 | IIO_MOD_WALKING, |
| 206 | IIO_EV_DIR_FALLING, | 205 | IIO_EV_TYPE_THRESH, |
| 207 | IIO_EV_TYPE_THRESH, | 206 | IIO_EV_DIR_FALLING), |
| 208 | 0, 0, 0), | ||
| 209 | st->event_timestamp); | 207 | st->event_timestamp); |
| 210 | break; | 208 | break; |
| 211 | case 3: | 209 | case 3: |
| 212 | iio_push_event(indio_dev, | 210 | iio_push_event(indio_dev, |
| 213 | IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD, | 211 | IIO_UNMOD_EVENT_CODE(IIO_STEPS, 0, |
| 214 | IIO_EV_DIR_NONE, | 212 | IIO_EV_TYPE_CHANGE, |
| 215 | IIO_EV_TYPE_CHANGE, 0, 0, 0), | 213 | IIO_EV_DIR_NONE), |
| 216 | st->event_timestamp); | 214 | st->event_timestamp); |
| 217 | break; | 215 | break; |
| 218 | default: | 216 | default: |
| @@ -970,7 +970,7 @@ static int ad9523_setup(struct iio_dev *indio_dev) · 969 unmodified lines | |||
| 970 | 970 | ||
| 971 | static int ad9523_probe(struct spi_device *spi) | 971 | static int ad9523_probe(struct spi_device *spi) |
| 972 | { | 972 | { |
| 973 | struct ad9523_platform_data *pdata = spi->dev.platform_data; | 973 | struct ad9523_platform_data *pdata = dev_get_platdata(&spi->dev); |
| 974 | struct iio_dev *indio_dev; | 974 | struct iio_dev *indio_dev; |
| 975 | struct ad9523_state *st; | 975 | struct ad9523_state *st; |
| 976 | int ret; | 976 | int ret; |
| @@ -603,7 +603,7 @@ static int adf4350_probe(struct spi_device *spi) · 602 unmodified lines | |||
| 603 | if (pdata == NULL) | 603 | if (pdata == NULL) |
| 604 | return -EINVAL; | 604 | return -EINVAL; |
| 605 | } else { | 605 | } else { |
| 606 | pdata = spi->dev.platform_data; | 606 | pdata = dev_get_platdata(&spi->dev); |
| 607 | } | 607 | } |
| 608 | 608 | ||
| 609 | if (!pdata) { | 609 | if (!pdata) { |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | * | 4 | * |
| 5 | * Copyright 2019 Analog Devices Inc. | 5 | * Copyright 2019 Analog Devices Inc. |
| 6 | */ | 6 | */ |
| 7 | #include "linux/dev_printk.h" | ||
| 7 | #include <linux/bitfield.h> | 8 | #include <linux/bitfield.h> |
| 8 | #include <linux/clk.h> | 9 | #include <linux/clk.h> |
| 9 | #include <linux/device.h> | 10 | #include <linux/device.h> |
| @@ -150,6 +151,7 @@ static const struct regmap_config adf4371_regmap_config = { · 140 unmodified lines | |||
| 150 | }; | 151 | }; |
| 151 | 152 | ||
| 152 | struct adf4371_chip_info { | 153 | struct adf4371_chip_info { |
| 154 | const char *name; | ||
| 153 | unsigned int num_channels; | 155 | unsigned int num_channels; |
| 154 | const struct iio_chan_spec *channels; | 156 | const struct iio_chan_spec *channels; |
| 155 | }; | 157 | }; |
| @@ -157,7 +159,6 @@ struct adf4371_chip_info { · 1 unmodified line | |||
| 157 | struct adf4371_state { | 159 | struct adf4371_state { |
| 158 | struct spi_device *spi; | 160 | struct spi_device *spi; |
| 159 | struct regmap *regmap; | 161 | struct regmap *regmap; |
| 160 | struct clk *clkin; | ||
| 161 | /* | 162 | /* |
| 162 | * Lock for accessing device registers. Some operations require | 163 | * Lock for accessing device registers. Some operations require |
| 163 | * multiple consecutive R/W operations, during which the device | 164 | * multiple consecutive R/W operations, during which the device |
| @@ -444,15 +445,16 @@ static const struct iio_chan_spec adf4371_chan[] = { · 280 unmodified lines | |||
| 444 | ADF4371_CHANNEL(ADF4371_CH_RF32), | 445 | ADF4371_CHANNEL(ADF4371_CH_RF32), |
| 445 | }; | 446 | }; |
| 446 | 447 | ||
| 447 | static const struct adf4371_chip_info adf4371_chip_info[] = { | 448 | static const struct adf4371_chip_info adf4371_chip_info = { |
| 448 | [ADF4371] = { | 449 | .name = "adf4371", |
| 449 | .channels = adf4371_chan, | 450 | .channels = adf4371_chan, |
| 450 | .num_channels = 4, | 451 | .num_channels = 4, |
| 451 | }, | 452 | }; |
| 452 | [ADF4372] = { | 453 | |
| 453 | .channels = adf4371_chan, | 454 | static const struct adf4371_chip_info adf4372_chip_info = { |
| 454 | .num_channels = 3, | 455 | .name = "adf4372", |
| 455 | } | 456 | .channels = adf4371_chan, |
| 457 | .num_channels = 3, | ||
| 456 | }; | 458 | }; |
| 457 | 459 | ||
| 458 | static int adf4371_reg_access(struct iio_dev *indio_dev, | 460 | static int adf4371_reg_access(struct iio_dev *indio_dev, |
| @@ -542,10 +544,10 @@ static int adf4371_setup(struct adf4371_state *st) · 83 unmodified lines | |||
| 542 | 544 | ||
| 543 | static int adf4371_probe(struct spi_device *spi) | 545 | static int adf4371_probe(struct spi_device *spi) |
| 544 | { | 546 | { |
| 545 | const struct spi_device_id *id = spi_get_device_id(spi); | ||
| 546 | struct iio_dev *indio_dev; | 547 | struct iio_dev *indio_dev; |
| 547 | struct adf4371_state *st; | 548 | struct adf4371_state *st; |
| 548 | struct regmap *regmap; | 549 | struct regmap *regmap; |
| 550 | struct clk *clkin; | ||
| 549 | int ret; | 551 | int ret; |
| 550 | 552 | ||
| 551 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); | 553 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); |
| @@ -553,50 +555,49 @@ static int adf4371_probe(struct spi_device *spi) · 1 unmodified line | |||
| 553 | return -ENOMEM; | 555 | return -ENOMEM; |
| 554 | 556 | ||
| 555 | regmap = devm_regmap_init_spi(spi, &adf4371_regmap_config); | 557 | regmap = devm_regmap_init_spi(spi, &adf4371_regmap_config); |
| 556 | if (IS_ERR(regmap)) { | 558 | if (IS_ERR(regmap)) |
| 557 | dev_err(&spi->dev, "Error initializing spi regmap: %ld\n", | 559 | return dev_err_probe(&spi->dev, PTR_ERR(regmap), |
| 558 | PTR_ERR(regmap)); | 560 | "Error initializing spi regmap\n"); |
| 559 | return PTR_ERR(regmap); | ||
| 560 | } | ||
| 561 | 561 | ||
| 562 | st = iio_priv(indio_dev); | 562 | st = iio_priv(indio_dev); |
| 563 | spi_set_drvdata(spi, indio_dev); | ||
| 564 | st->spi = spi; | 563 | st->spi = spi; |
| 565 | st->regmap = regmap; | 564 | st->regmap = regmap; |
| 566 | mutex_init(&st->lock); | 565 | mutex_init(&st->lock); |
| 567 | 566 | ||
| 568 | st->chip_info = &adf4371_chip_info[id->driver_data]; | 567 | st->chip_info = spi_get_device_match_data(spi); |
| 569 | indio_dev->name = id->name; | 568 | if (!st->chip_info) |
| 569 | return -ENODEV; | ||
| 570 | |||
| 571 | indio_dev->name = st->chip_info->name; | ||
| 570 | indio_dev->info = &adf4371_info; | 572 | indio_dev->info = &adf4371_info; |
| 571 | indio_dev->modes = INDIO_DIRECT_MODE; | 573 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 572 | indio_dev->channels = st->chip_info->channels; | 574 | indio_dev->channels = st->chip_info->channels; |
| 573 | indio_dev->num_channels = st->chip_info->num_channels; | 575 | indio_dev->num_channels = st->chip_info->num_channels; |
| 574 | 576 | ||
| 575 | st->clkin = devm_clk_get_enabled(&spi->dev, "clkin"); | 577 | clkin = devm_clk_get_enabled(&spi->dev, "clkin"); |
| 576 | if (IS_ERR(st->clkin)) | 578 | if (IS_ERR(clkin)) |
| 577 | return PTR_ERR(st->clkin); | 579 | return dev_err_probe(&spi->dev, PTR_ERR(clkin), |
| 580 | "Failed to get clkin\n"); | ||
| 578 | 581 | ||
| 579 | st->clkin_freq = clk_get_rate(st->clkin); | 582 | st->clkin_freq = clk_get_rate(clkin); |
| 580 | 583 | ||
| 581 | ret = adf4371_setup(st); | 584 | ret = adf4371_setup(st); |
| 582 | if (ret < 0) { | 585 | if (ret < 0) |
| 583 | dev_err(&spi->dev, "ADF4371 setup failed\n"); | 586 | return dev_err_probe(&spi->dev, ret, "ADF4371 setup failed\n"); |
| 584 | return ret; | ||
| 585 | } | ||
| 586 | 587 | ||
| 587 | return devm_iio_device_register(&spi->dev, indio_dev); | 588 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 588 | } | 589 | } |
| 589 | 590 | ||
| 590 | static const struct spi_device_id adf4371_id_table[] = { | 591 | static const struct spi_device_id adf4371_id_table[] = { |
| 591 | { "adf4371", ADF4371 }, | 592 | { "adf4371", (kernel_ulong_t)&adf4371_chip_info }, |
| 592 | { "adf4372", ADF4372 }, | 593 | { "adf4372", (kernel_ulong_t)&adf4372_chip_info }, |
| 593 | {} | 594 | {} |
| 594 | }; | 595 | }; |
| 595 | MODULE_DEVICE_TABLE(spi, adf4371_id_table); | 596 | MODULE_DEVICE_TABLE(spi, adf4371_id_table); |
| 596 | 597 | ||
| 597 | static const struct of_device_id adf4371_of_match[] = { | 598 | static const struct of_device_id adf4371_of_match[] = { |
| 598 | { .compatible = "adi,adf4371" }, | 599 | { .compatible = "adi,adf4371", .data = &adf4371_chip_info }, |
| 599 | { .compatible = "adi,adf4372" }, | 600 | { .compatible = "adi,adf4372", .data = &adf4372_chip_info}, |
| 600 | { }, | 601 | { }, |
| 601 | }; | 602 | }; |
| 602 | MODULE_DEVICE_TABLE(of, adf4371_of_match); | 603 | MODULE_DEVICE_TABLE(of, adf4371_of_match); |
| @@ -27,7 +27,7 @@ config ADIS16136 · 26 unmodified lines | |||
| 27 | select IIO_ADIS_LIB_BUFFER if IIO_BUFFER | 27 | select IIO_ADIS_LIB_BUFFER if IIO_BUFFER |
| 28 | help | 28 | help |
| 29 | Say yes here to build support for the Analog Devices ADIS16133, ADIS16135, | 29 | Say yes here to build support for the Analog Devices ADIS16133, ADIS16135, |
| 30 | ADIS16136 gyroscope devices. | 30 | ADIS16136, ADIS16137 gyroscope devices. |
| 31 | 31 | ||
| 32 | config ADIS16260 | 32 | config ADIS16260 |
| 33 | tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver" | 33 | tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver" |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | |||
| 8 | #include <linux/interrupt.h> | 8 | #include <linux/interrupt.h> |
| 9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
| 10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
| 11 | #include <linux/acpi.h> | ||
| 12 | #include <linux/pm.h> | 11 | #include <linux/pm.h> |
| 13 | #include <linux/pm_runtime.h> | 12 | #include <linux/pm_runtime.h> |
| 14 | #include <linux/iio/iio.h> | 13 | #include <linux/iio/iio.h> |
| @@ -444,7 +443,7 @@ static int bmg160_setup_new_data_interrupt(struct bmg160_data *data, · 429 unmodified lines | |||
| 444 | 443 | ||
| 445 | static int bmg160_get_bw(struct bmg160_data *data, int *val) | 444 | static int bmg160_get_bw(struct bmg160_data *data, int *val) |
| 446 | { | 445 | { |
| 447 | struct device *dev = regmap_get_device(data->regmap); | 446 | struct device *dev = regmap_get_device(data->regmap); |
| 448 | int i; | 447 | int i; |
| 449 | unsigned int bw_bits; | 448 | unsigned int bw_bits; |
| 450 | int ret; | 449 | int ret; |
| @@ -749,7 +748,7 @@ static int bmg160_write_event_config(struct iio_dev *indio_dev, · 298 unmodified lines | |||
| 749 | const struct iio_chan_spec *chan, | 748 | const struct iio_chan_spec *chan, |
| 750 | enum iio_event_type type, | 749 | enum iio_event_type type, |
| 751 | enum iio_event_direction dir, | 750 | enum iio_event_direction dir, |
| 752 | int state) | 751 | bool state) |
| 753 | { | 752 | { |
| 754 | struct bmg160_data *data = iio_priv(indio_dev); | 753 | struct bmg160_data *data = iio_priv(indio_dev); |
| 755 | int ret; | 754 | int ret; |
| @@ -1055,17 +1054,6 @@ static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = { · 299 unmodified lines | |||
| 1055 | .postdisable = bmg160_buffer_postdisable, | 1054 | .postdisable = bmg160_buffer_postdisable, |
| 1056 | }; | 1055 | }; |
| 1057 | 1056 | ||
| 1058 | static const char *bmg160_match_acpi_device(struct device *dev) | ||
| 1059 | { | ||
| 1060 | const struct acpi_device_id *id; | ||
| 1061 | |||
| 1062 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
| 1063 | if (!id) | ||
| 1064 | return NULL; | ||
| 1065 | |||
| 1066 | return dev_name(dev); | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, | 1057 | int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, |
| 1070 | const char *name) | 1058 | const char *name) |
| 1071 | { | 1059 | { |
| @@ -1098,9 +1086,6 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, · 26 unmodified lines | |||
| 1098 | 1086 | ||
| 1099 | mutex_init(&data->mutex); | 1087 | mutex_init(&data->mutex); |
| 1100 | 1088 | ||
| 1101 | if (ACPI_HANDLE(dev)) | ||
| 1102 | name = bmg160_match_acpi_device(dev); | ||
| 1103 | |||
| 1104 | indio_dev->channels = bmg160_channels; | 1089 | indio_dev->channels = bmg160_channels; |
| 1105 | indio_dev->num_channels = ARRAY_SIZE(bmg160_channels); | 1090 | indio_dev->num_channels = ARRAY_SIZE(bmg160_channels); |
| 1106 | indio_dev->name = name; | 1091 | indio_dev->name = name; |
| @@ -17,7 +17,7 @@ static int bmg160_i2c_probe(struct i2c_client *client) · 16 unmodified lines | |||
| 17 | { | 17 | { |
| 18 | const struct i2c_device_id *id = i2c_client_get_device_id(client); | 18 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
| 19 | struct regmap *regmap; | 19 | struct regmap *regmap; |
| 20 | const char *name = NULL; | 20 | const char *name; |
| 21 | 21 | ||
| 22 | regmap = devm_regmap_init_i2c(client, &bmg160_regmap_i2c_conf); | 22 | regmap = devm_regmap_init_i2c(client, &bmg160_regmap_i2c_conf); |
| 23 | if (IS_ERR(regmap)) { | 23 | if (IS_ERR(regmap)) { |
| @@ -28,6 +28,8 @@ static int bmg160_i2c_probe(struct i2c_client *client) · 4 unmodified lines | |||
| 28 | 28 | ||
| 29 | if (id) | 29 | if (id) |
| 30 | name = id->name; | 30 | name = id->name; |
| 31 | else | ||
| 32 | name = iio_get_acpi_device_name(&client->dev); | ||
| 31 | 33 | ||
| 32 | return bmg160_core_probe(&client->dev, regmap, client->irq, name); | 34 | return bmg160_core_probe(&client->dev, regmap, client->irq, name); |
| 33 | } | 35 | } |
| @@ -39,8 +41,6 @@ static void bmg160_i2c_remove(struct i2c_client *client) · 5 unmodified lines | |||
| 39 | 41 | ||
| 40 | static const struct acpi_device_id bmg160_acpi_match[] = { | 42 | static const struct acpi_device_id bmg160_acpi_match[] = { |
| 41 | {"BMG0160", 0}, | 43 | {"BMG0160", 0}, |
| 42 | {"BMI055B", 0}, | ||
| 43 | {"BMI088B", 0}, | ||
| 44 | {}, | 44 | {}, |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| @@ -849,8 +849,7 @@ static int fxas21002c_trigger_probe(struct fxas21002c_data *data) · 848 unmodified lines | |||
| 849 | if (!data->dready_trig) | 849 | if (!data->dready_trig) |
| 850 | return -ENOMEM; | 850 | return -ENOMEM; |
| 851 | 851 | ||
| 852 | irq_trig = irqd_get_trigger_type(irq_get_irq_data(data->irq)); | 852 | irq_trig = irq_get_trigger_type(data->irq); |
| 853 | |||
| 854 | if (irq_trig == IRQF_TRIGGER_RISING) { | 853 | if (irq_trig == IRQF_TRIGGER_RISING) { |
| 855 | ret = regmap_field_write(data->regmap_fields[F_IPOL], 1); | 854 | ret = regmap_field_write(data->regmap_fields[F_IPOL], 1); |
| 856 | if (ret < 0) | 855 | if (ret < 0) |
| @@ -27,7 +27,7 @@ struct gyro_3d_state { · 26 unmodified lines | |||
| 27 | struct hid_sensor_hub_attribute_info gyro[GYRO_3D_CHANNEL_MAX]; | 27 | struct hid_sensor_hub_attribute_info gyro[GYRO_3D_CHANNEL_MAX]; |
| 28 | struct { | 28 | struct { |
| 29 | u32 gyro_val[GYRO_3D_CHANNEL_MAX]; | 29 | u32 gyro_val[GYRO_3D_CHANNEL_MAX]; |
| 30 | u64 timestamp __aligned(8); | 30 | aligned_s64 timestamp; |
| 31 | } scan; | 31 | } scan; |
| 32 | int scale_pre_decml; | 32 | int scale_pre_decml; |
| 33 | int scale_post_decml; | 33 | int scale_post_decml; |
| @@ -279,11 +279,11 @@ static int gyro_3d_parse_report(struct platform_device *pdev, · 245 unmodified lines | |||
| 279 | /* Function to initialize the processing for usage id */ | 279 | /* Function to initialize the processing for usage id */ |
| 280 | static int hid_gyro_3d_probe(struct platform_device *pdev) | 280 | static int hid_gyro_3d_probe(struct platform_device *pdev) |
| 281 | { | 281 | { |
| 282 | struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); | ||
| 282 | int ret = 0; | 283 | int ret = 0; |
| 283 | static const char *name = "gyro_3d"; | 284 | static const char *name = "gyro_3d"; |
| 284 | struct iio_dev *indio_dev; | 285 | struct iio_dev *indio_dev; |
| 285 | struct gyro_3d_state *gyro_state; | 286 | struct gyro_3d_state *gyro_state; |
| 286 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | ||
| 287 | 287 | ||
| 288 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*gyro_state)); | 288 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*gyro_state)); |
| 289 | if (!indio_dev) | 289 | if (!indio_dev) |
| @@ -361,7 +361,7 @@ error_remove_trigger: · 71 unmodified lines | |||
| 361 | /* Function to deinitialize the processing for usage id */ | 361 | /* Function to deinitialize the processing for usage id */ |
| 362 | static void hid_gyro_3d_remove(struct platform_device *pdev) | 362 | static void hid_gyro_3d_remove(struct platform_device *pdev) |
| 363 | { | 363 | { |
| 364 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | 364 | struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); |
| 365 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); | 365 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); |
| 366 | struct gyro_3d_state *gyro_state = iio_priv(indio_dev); | 366 | struct gyro_3d_state *gyro_state = iio_priv(indio_dev); |
| 367 | 367 | ||
| @@ -386,7 +386,7 @@ static struct platform_driver hid_gyro_3d_platform_driver = { · 18 unmodified lines | |||
| 386 | .pm = &hid_sensor_pm_ops, | 386 | .pm = &hid_sensor_pm_ops, |
| 387 | }, | 387 | }, |
| 388 | .probe = hid_gyro_3d_probe, | 388 | .probe = hid_gyro_3d_probe, |
| 389 | .remove_new = hid_gyro_3d_remove, | 389 | .remove = hid_gyro_3d_remove, |
| 390 | }; | 390 | }; |
| 391 | module_platform_driver(hid_gyro_3d_platform_driver); | 391 | module_platform_driver(hid_gyro_3d_platform_driver); |
| 392 | 392 | ||
| @@ -1059,12 +1059,12 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq) · 1058 unmodified lines | |||
| 1059 | /* Check if IRQ is open drain */ | 1059 | /* Check if IRQ is open drain */ |
| 1060 | mpu3050->irq_opendrain = device_property_read_bool(dev, "drive-open-drain"); | 1060 | mpu3050->irq_opendrain = device_property_read_bool(dev, "drive-open-drain"); |
| 1061 | 1061 | ||
| 1062 | irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); | ||
| 1063 | /* | 1062 | /* |
| 1064 | * Configure the interrupt generator hardware to supply whatever | 1063 | * Configure the interrupt generator hardware to supply whatever |
| 1065 | * the interrupt is configured for, edges low/high level low/high, | 1064 | * the interrupt is configured for, edges low/high level low/high, |
| 1066 | * we can provide it all. | 1065 | * we can provide it all. |
| 1067 | */ | 1066 | */ |
| 1067 | irq_trig = irq_get_trigger_type(irq); | ||
| 1068 | switch (irq_trig) { | 1068 | switch (irq_trig) { |
| 1069 | case IRQF_TRIGGER_RISING: | 1069 | case IRQF_TRIGGER_RISING: |
| 1070 | dev_info(&indio_dev->dev, | 1070 | dev_info(&indio_dev->dev, |
| @@ -18,7 +18,7 @@ struct hid_humidity_state { · 17 unmodified lines | |||
| 18 | struct hid_sensor_hub_attribute_info humidity_attr; | 18 | struct hid_sensor_hub_attribute_info humidity_attr; |
| 19 | struct { | 19 | struct { |
| 20 | s32 humidity_data; | 20 | s32 humidity_data; |
| 21 | u64 timestamp __aligned(8); | 21 | aligned_s64 timestamp; |
| 22 | } scan; | 22 | } scan; |
| 23 | int scale_pre_decml; | 23 | int scale_pre_decml; |
| 24 | int scale_post_decml; | 24 | int scale_post_decml; |
| @@ -287,7 +287,7 @@ static struct platform_driver hid_humidity_platform_driver = { · 262 unmodified lines | |||
| 287 | .pm = &hid_sensor_pm_ops, | 287 | .pm = &hid_sensor_pm_ops, |
| 288 | }, | 288 | }, |
| 289 | .probe = hid_humidity_probe, | 289 | .probe = hid_humidity_probe, |
| 290 | .remove_new = hid_humidity_remove, | 290 | .remove = hid_humidity_remove, |
| 291 | }; | 291 | }; |
| 292 | module_platform_driver(hid_humidity_platform_driver); | 292 | module_platform_driver(hid_humidity_platform_driver); |
| 293 | 293 | ||
| @@ -81,8 +81,7 @@ int hts221_allocate_trigger(struct iio_dev *iio_dev) · 80 unmodified lines | |||
| 81 | unsigned long irq_type; | 81 | unsigned long irq_type; |
| 82 | int err; | 82 | int err; |
| 83 | 83 | ||
| 84 | irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq)); | 84 | irq_type = irq_get_trigger_type(hw->irq); |
| 85 | |||
| 86 | switch (irq_type) { | 85 | switch (irq_type) { |
| 87 | case IRQF_TRIGGER_HIGH: | 86 | case IRQF_TRIGGER_HIGH: |
| 88 | case IRQF_TRIGGER_RISING: | 87 | case IRQF_TRIGGER_RISING: |
| @@ -53,6 +53,7 @@ config ADIS16480 · 52 unmodified lines | |||
| 53 | ADIS16485, ADIS16488 inertial sensors. | 53 | ADIS16485, ADIS16488 inertial sensors. |
| 54 | 54 | ||
| 55 | source "drivers/iio/imu/bmi160/Kconfig" | 55 | source "drivers/iio/imu/bmi160/Kconfig" |
| 56 | source "drivers/iio/imu/bmi270/Kconfig" | ||
| 56 | source "drivers/iio/imu/bmi323/Kconfig" | 57 | source "drivers/iio/imu/bmi323/Kconfig" |
| 57 | source "drivers/iio/imu/bno055/Kconfig" | 58 | source "drivers/iio/imu/bno055/Kconfig" |
| 58 | 59 | ||
| @@ -96,6 +97,20 @@ config KMX61 · 37 unmodified lines | |||
| 96 | 97 | ||
| 97 | source "drivers/iio/imu/inv_icm42600/Kconfig" | 98 | source "drivers/iio/imu/inv_icm42600/Kconfig" |
| 98 | source "drivers/iio/imu/inv_mpu6050/Kconfig" | 99 | source "drivers/iio/imu/inv_mpu6050/Kconfig" |
| 100 | |||
| 101 | config SMI240 | ||
| 102 | tristate "Bosch Sensor SMI240 Inertial Measurement Unit" | ||
| 103 | depends on SPI | ||
| 104 | select REGMAP_SPI | ||
| 105 | select IIO_BUFFER | ||
| 106 | select IIO_TRIGGERED_BUFFER | ||
| 107 | help | ||
| 108 | If you say yes here you get support for SMI240 IMU on SPI with | ||
| 109 | accelerometer and gyroscope. | ||
| 110 | |||
| 111 | This driver can also be built as a module. If so, the module will be | ||
| 112 | called smi240. | ||
| 113 | |||
| 99 | source "drivers/iio/imu/st_lsm6dsx/Kconfig" | 114 | source "drivers/iio/imu/st_lsm6dsx/Kconfig" |
| 100 | source "drivers/iio/imu/st_lsm9ds0/Kconfig" | 115 | source "drivers/iio/imu/st_lsm9ds0/Kconfig" |
| 101 | 116 | ||
| @@ -15,6 +15,7 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o · 14 unmodified lines | |||
| 15 | obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o | 15 | obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o |
| 16 | 16 | ||
| 17 | obj-y += bmi160/ | 17 | obj-y += bmi160/ |
| 18 | obj-y += bmi270/ | ||
| 18 | obj-y += bmi323/ | 19 | obj-y += bmi323/ |
| 19 | obj-y += bno055/ | 20 | obj-y += bno055/ |
| 20 | 21 | ||
| @@ -27,5 +28,7 @@ obj-y += inv_mpu6050/ · 6 unmodified lines | |||
| 27 | 28 | ||
| 28 | obj-$(CONFIG_KMX61) += kmx61.o | 29 | obj-$(CONFIG_KMX61) += kmx61.o |
| 29 | 30 | ||
| 31 | obj-$(CONFIG_SMI240) += smi240.o | ||
| 32 | |||
| 30 | obj-y += st_lsm6dsx/ | 33 | obj-y += st_lsm6dsx/ |
| 31 | obj-y += st_lsm9ds0/ | 34 | obj-y += st_lsm9ds0/ |
| @@ -690,18 +690,9 @@ static int bmi160_config_device_irq(struct iio_dev *indio_dev, int irq_type, · 689 unmodified lines | |||
| 690 | static int bmi160_setup_irq(struct iio_dev *indio_dev, int irq, | 690 | static int bmi160_setup_irq(struct iio_dev *indio_dev, int irq, |
| 691 | enum bmi160_int_pin pin) | 691 | enum bmi160_int_pin pin) |
| 692 | { | 692 | { |
| 693 | struct irq_data *desc; | 693 | u32 irq_type = irq_get_trigger_type(irq); |
| 694 | u32 irq_type; | ||
| 695 | int ret; | 694 | int ret; |
| 696 | 695 | ||
| 697 | desc = irq_get_irq_data(irq); | ||
| 698 | if (!desc) { | ||
| 699 | dev_err(&indio_dev->dev, "Could not find IRQ %d\n", irq); | ||
| 700 | return -EINVAL; | ||
| 701 | } | ||
| 702 | |||
| 703 | irq_type = irqd_get_trigger_type(desc); | ||
| 704 | |||
| 705 | ret = bmi160_config_device_irq(indio_dev, irq_type, pin); | 696 | ret = bmi160_config_device_irq(indio_dev, irq_type, pin); |
| 706 | if (ret) | 697 | if (ret) |
| 707 | return ret; | 698 | return ret; |
| @@ -0,0 +1,33 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | # | ||
| 3 | # BMI270 IMU driver | ||
| 4 | # | ||
| 5 | |||
| 6 | config BMI270 | ||
| 7 | tristate | ||
| 8 | select IIO_BUFFER | ||
| 9 | select IIO_TRIGGERED_BUFFER | ||
| 10 | |||
| 11 | config BMI270_I2C | ||
| 12 | tristate "Bosch BMI270 I2C driver" | ||
| 13 | depends on I2C | ||
| 14 | select BMI270 | ||
| 15 | select REGMAP_I2C | ||
| 16 | help | ||
| 17 | Enable support for the Bosch BMI270 6-Axis IMU connected to I2C | ||
| 18 | interface. | ||
| 19 | |||
| 20 | This driver can also be built as a module. If so, the module will be | ||
| 21 | called bmi270_i2c. | ||
| 22 | |||
| 23 | config BMI270_SPI | ||
| 24 | tristate "Bosch BMI270 SPI driver" | ||
| 25 | depends on SPI | ||
| 26 | select BMI270 | ||
| 27 | select REGMAP_SPI | ||
| 28 | help | ||
| 29 | Enable support for the Bosch BMI270 6-Axis IMU connected to SPI | ||
| 30 | interface. | ||
| 31 | |||
| 32 | This driver can also be built as a module. If so, the module will be | ||
| 33 | called bmi270_spi. | ||
| @@ -0,0 +1,7 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | # | ||
| 3 | # Makefile for Bosch BMI270 IMU | ||
| 4 | # | ||
| 5 | obj-$(CONFIG_BMI270) += bmi270_core.o | ||
| 6 | obj-$(CONFIG_BMI270_I2C) += bmi270_i2c.o | ||
| 7 | obj-$(CONFIG_BMI270_SPI) += bmi270_spi.o | ||
| @@ -0,0 +1,38 @@ | |||
| 1 | /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ | ||
| 2 | |||
| 3 | #ifndef BMI270_H_ | ||
| 4 | #define BMI270_H_ | ||
| 5 | |||
| 6 | #include <linux/regmap.h> | ||
| 7 | #include <linux/iio/iio.h> | ||
| 8 | |||
| 9 | struct device; | ||
| 10 | struct bmi270_data { | ||
| 11 | struct device *dev; | ||
| 12 | struct regmap *regmap; | ||
| 13 | const struct bmi270_chip_info *chip_info; | ||
| 14 | |||
| 15 | /* | ||
| 16 | * Where IIO_DMA_MINALIGN may be larger than 8 bytes, align to | ||
| 17 | * that to ensure a DMA safe buffer. | ||
| 18 | */ | ||
| 19 | struct { | ||
| 20 | __le16 channels[6]; | ||
| 21 | aligned_s64 timestamp; | ||
| 22 | } data __aligned(IIO_DMA_MINALIGN); | ||
| 23 | }; | ||
| 24 | |||
| 25 | struct bmi270_chip_info { | ||
| 26 | const char *name; | ||
| 27 | int chip_id; | ||
| 28 | const char *fw_name; | ||
| 29 | }; | ||
| 30 | |||
| 31 | extern const struct regmap_config bmi270_regmap_config; | ||
| 32 | extern const struct bmi270_chip_info bmi260_chip_info; | ||
| 33 | extern const struct bmi270_chip_info bmi270_chip_info; | ||
| 34 | |||
| 35 | int bmi270_core_probe(struct device *dev, struct regmap *regmap, | ||
| 36 | const struct bmi270_chip_info *chip_info); | ||
| 37 | |||
| 38 | #endif /* BMI270_H_ */ | ||
| @@ -0,0 +1,734 @@ | |||
| 1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | |||
| 3 | #include <linux/bitfield.h> | ||
| 4 | #include <linux/firmware.h> | ||
| 5 | #include <linux/i2c.h> | ||
| 6 | #include <linux/module.h> | ||
| 7 | #include <linux/regmap.h> | ||
| 8 | |||
| 9 | #include <linux/iio/iio.h> | ||
| 10 | #include <linux/iio/sysfs.h> | ||
| 11 | #include <linux/iio/triggered_buffer.h> | ||
| 12 | #include <linux/iio/trigger_consumer.h> | ||
| 13 | |||
| 14 | #include "bmi270.h" | ||
| 15 | |||
| 16 | #define BMI270_CHIP_ID_REG 0x00 | ||
| 17 | |||
| 18 | /* Checked to prevent sending incompatible firmware to BMI160 devices */ | ||
| 19 | #define BMI160_CHIP_ID_VAL 0xD1 | ||
| 20 | |||
| 21 | #define BMI260_CHIP_ID_VAL 0x27 | ||
| 22 | #define BMI270_CHIP_ID_VAL 0x24 | ||
| 23 | #define BMI270_CHIP_ID_MSK GENMASK(7, 0) | ||
| 24 | |||
| 25 | #define BMI270_ACCEL_X_REG 0x0c | ||
| 26 | #define BMI270_ANG_VEL_X_REG 0x12 | ||
| 27 | |||
| 28 | #define BMI270_INTERNAL_STATUS_REG 0x21 | ||
| 29 | #define BMI270_INTERNAL_STATUS_MSG_MSK GENMASK(3, 0) | ||
| 30 | #define BMI270_INTERNAL_STATUS_MSG_INIT_OK 0x01 | ||
| 31 | |||
| 32 | #define BMI270_INTERNAL_STATUS_AXES_REMAP_ERR_MSK BIT(5) | ||
| 33 | #define BMI270_INTERNAL_STATUS_ODR_50HZ_ERR_MSK BIT(6) | ||
| 34 | |||
| 35 | #define BMI270_ACC_CONF_REG 0x40 | ||
| 36 | #define BMI270_ACC_CONF_ODR_MSK GENMASK(3, 0) | ||
| 37 | #define BMI270_ACC_CONF_ODR_100HZ 0x08 | ||
| 38 | #define BMI270_ACC_CONF_BWP_MSK GENMASK(6, 4) | ||
| 39 | #define BMI270_ACC_CONF_BWP_NORMAL_MODE 0x02 | ||
| 40 | #define BMI270_ACC_CONF_FILTER_PERF_MSK BIT(7) | ||
| 41 | |||
| 42 | #define BMI270_ACC_CONF_RANGE_REG 0x41 | ||
| 43 | #define BMI270_ACC_CONF_RANGE_MSK GENMASK(1, 0) | ||
| 44 | |||
| 45 | #define BMI270_GYR_CONF_REG 0x42 | ||
| 46 | #define BMI270_GYR_CONF_ODR_MSK GENMASK(3, 0) | ||
| 47 | #define BMI270_GYR_CONF_ODR_200HZ 0x09 | ||
| 48 | #define BMI270_GYR_CONF_BWP_MSK GENMASK(5, 4) | ||
| 49 | #define BMI270_GYR_CONF_BWP_NORMAL_MODE 0x02 | ||
| 50 | #define BMI270_GYR_CONF_NOISE_PERF_MSK BIT(6) | ||
| 51 | #define BMI270_GYR_CONF_FILTER_PERF_MSK BIT(7) | ||
| 52 | |||
| 53 | #define BMI270_GYR_CONF_RANGE_REG 0x43 | ||
| 54 | #define BMI270_GYR_CONF_RANGE_MSK GENMASK(2, 0) | ||
| 55 | |||
| 56 | #define BMI270_INIT_CTRL_REG 0x59 | ||
| 57 | #define BMI270_INIT_CTRL_LOAD_DONE_MSK BIT(0) | ||
| 58 | |||
| 59 | #define BMI270_INIT_DATA_REG 0x5e | ||
| 60 | |||
| 61 | #define BMI270_PWR_CONF_REG 0x7c | ||
| 62 | #define BMI270_PWR_CONF_ADV_PWR_SAVE_MSK BIT(0) | ||
| 63 | #define BMI270_PWR_CONF_FIFO_WKUP_MSK BIT(1) | ||
| 64 | #define BMI270_PWR_CONF_FUP_EN_MSK BIT(2) | ||
| 65 | |||
| 66 | #define BMI270_PWR_CTRL_REG 0x7d | ||
| 67 | #define BMI270_PWR_CTRL_AUX_EN_MSK BIT(0) | ||
| 68 | #define BMI270_PWR_CTRL_GYR_EN_MSK BIT(1) | ||
| 69 | #define BMI270_PWR_CTRL_ACCEL_EN_MSK BIT(2) | ||
| 70 | #define BMI270_PWR_CTRL_TEMP_EN_MSK BIT(3) | ||
| 71 | |||
| 72 | #define BMI260_INIT_DATA_FILE "bmi260-init-data.fw" | ||
| 73 | #define BMI270_INIT_DATA_FILE "bmi270-init-data.fw" | ||
| 74 | |||
| 75 | enum bmi270_scan { | ||
| 76 | BMI270_SCAN_ACCEL_X, | ||
| 77 | BMI270_SCAN_ACCEL_Y, | ||
| 78 | BMI270_SCAN_ACCEL_Z, | ||
| 79 | BMI270_SCAN_GYRO_X, | ||
| 80 | BMI270_SCAN_GYRO_Y, | ||
| 81 | BMI270_SCAN_GYRO_Z, | ||
| 82 | BMI270_SCAN_TIMESTAMP, | ||
| 83 | }; | ||
| 84 | |||
| 85 | static const unsigned long bmi270_avail_scan_masks[] = { | ||
| 86 | (BIT(BMI270_SCAN_ACCEL_X) | | ||
| 87 | BIT(BMI270_SCAN_ACCEL_Y) | | ||
| 88 | BIT(BMI270_SCAN_ACCEL_Z) | | ||
| 89 | BIT(BMI270_SCAN_GYRO_X) | | ||
| 90 | BIT(BMI270_SCAN_GYRO_Y) | | ||
| 91 | BIT(BMI270_SCAN_GYRO_Z)), | ||
| 92 | 0 | ||
| 93 | }; | ||
| 94 | |||
| 95 | const struct bmi270_chip_info bmi260_chip_info = { | ||
| 96 | .name = "bmi260", | ||
| 97 | .chip_id = BMI260_CHIP_ID_VAL, | ||
| 98 | .fw_name = BMI260_INIT_DATA_FILE, | ||
| 99 | }; | ||
| 100 | EXPORT_SYMBOL_NS_GPL(bmi260_chip_info, IIO_BMI270); | ||
| 101 | |||
| 102 | const struct bmi270_chip_info bmi270_chip_info = { | ||
| 103 | .name = "bmi270", | ||
| 104 | .chip_id = BMI270_CHIP_ID_VAL, | ||
| 105 | .fw_name = BMI270_INIT_DATA_FILE, | ||
| 106 | }; | ||
| 107 | EXPORT_SYMBOL_NS_GPL(bmi270_chip_info, IIO_BMI270); | ||
| 108 | |||
| 109 | enum bmi270_sensor_type { | ||
| 110 | BMI270_ACCEL = 0, | ||
| 111 | BMI270_GYRO, | ||
| 112 | }; | ||
| 113 | |||
| 114 | struct bmi270_scale { | ||
| 115 | int scale; | ||
| 116 | int uscale; | ||
| 117 | }; | ||
| 118 | |||
| 119 | struct bmi270_odr { | ||
| 120 | int odr; | ||
| 121 | int uodr; | ||
| 122 | }; | ||
| 123 | |||
| 124 | static const struct bmi270_scale bmi270_accel_scale[] = { | ||
| 125 | { 0, 598 }, | ||
| 126 | { 0, 1197 }, | ||
| 127 | { 0, 2394 }, | ||
| 128 | { 0, 4788 }, | ||
| 129 | }; | ||
| 130 | |||
| 131 | static const struct bmi270_scale bmi270_gyro_scale[] = { | ||
| 132 | { 0, 1065 }, | ||
| 133 | { 0, 532 }, | ||
| 134 | { 0, 266 }, | ||
| 135 | { 0, 133 }, | ||
| 136 | { 0, 66 }, | ||
| 137 | }; | ||
| 138 | |||
| 139 | struct bmi270_scale_item { | ||
| 140 | const struct bmi270_scale *tbl; | ||
| 141 | int num; | ||
| 142 | }; | ||
| 143 | |||
| 144 | static const struct bmi270_scale_item bmi270_scale_table[] = { | ||
| 145 | [BMI270_ACCEL] = { | ||
| 146 | .tbl = bmi270_accel_scale, | ||
| 147 | .num = ARRAY_SIZE(bmi270_accel_scale), | ||
| 148 | }, | ||
| 149 | [BMI270_GYRO] = { | ||
| 150 | .tbl = bmi270_gyro_scale, | ||
| 151 | .num = ARRAY_SIZE(bmi270_gyro_scale), | ||
| 152 | }, | ||
| 153 | }; | ||
| 154 | |||
| 155 | static const struct bmi270_odr bmi270_accel_odr[] = { | ||
| 156 | { 0, 781250 }, | ||
| 157 | { 1, 562500 }, | ||
| 158 | { 3, 125000 }, | ||
| 159 | { 6, 250000 }, | ||
| 160 | { 12, 500000 }, | ||
| 161 | { 25, 0 }, | ||
| 162 | { 50, 0 }, | ||
| 163 | { 100, 0 }, | ||
| 164 | { 200, 0 }, | ||
| 165 | { 400, 0 }, | ||
| 166 | { 800, 0 }, | ||
| 167 | { 1600, 0 }, | ||
| 168 | }; | ||
| 169 | |||
| 170 | static const u8 bmi270_accel_odr_vals[] = { | ||
| 171 | 0x01, | ||
| 172 | 0x02, | ||
| 173 | 0x03, | ||
| 174 | 0x04, | ||
| 175 | 0x05, | ||
| 176 | 0x06, | ||
| 177 | 0x07, | ||
| 178 | 0x08, | ||
| 179 | 0x09, | ||
| 180 | 0x0A, | ||
| 181 | 0x0B, | ||
| 182 | 0x0C, | ||
| 183 | }; | ||
| 184 | |||
| 185 | static const struct bmi270_odr bmi270_gyro_odr[] = { | ||
| 186 | { 25, 0 }, | ||
| 187 | { 50, 0 }, | ||
| 188 | { 100, 0 }, | ||
| 189 | { 200, 0 }, | ||
| 190 | { 400, 0 }, | ||
| 191 | { 800, 0 }, | ||
| 192 | { 1600, 0 }, | ||
| 193 | { 3200, 0 }, | ||
| 194 | }; | ||
| 195 | |||
| 196 | static const u8 bmi270_gyro_odr_vals[] = { | ||
| 197 | 0x06, | ||
| 198 | 0x07, | ||
| 199 | 0x08, | ||
| 200 | 0x09, | ||
| 201 | 0x0A, | ||
| 202 | 0x0B, | ||
| 203 | 0x0C, | ||
| 204 | 0x0D, | ||
| 205 | }; | ||
| 206 | |||
| 207 | struct bmi270_odr_item { | ||
| 208 | const struct bmi270_odr *tbl; | ||
| 209 | const u8 *vals; | ||
| 210 | int num; | ||
| 211 | }; | ||
| 212 | |||
| 213 | static const struct bmi270_odr_item bmi270_odr_table[] = { | ||
| 214 | [BMI270_ACCEL] = { | ||
| 215 | .tbl = bmi270_accel_odr, | ||
| 216 | .vals = bmi270_accel_odr_vals, | ||
| 217 | .num = ARRAY_SIZE(bmi270_accel_odr), | ||
| 218 | }, | ||
| 219 | [BMI270_GYRO] = { | ||
| 220 | .tbl = bmi270_gyro_odr, | ||
| 221 | .vals = bmi270_gyro_odr_vals, | ||
| 222 | .num = ARRAY_SIZE(bmi270_gyro_odr), | ||
| 223 | }, | ||
| 224 | }; | ||
| 225 | |||
| 226 | static int bmi270_set_scale(struct bmi270_data *data, int chan_type, int uscale) | ||
| 227 | { | ||
| 228 | int i; | ||
| 229 | int reg, mask; | ||
| 230 | struct bmi270_scale_item bmi270_scale_item; | ||
| 231 | |||
| 232 | switch (chan_type) { | ||
| 233 | case IIO_ACCEL: | ||
| 234 | reg = BMI270_ACC_CONF_RANGE_REG; | ||
| 235 | mask = BMI270_ACC_CONF_RANGE_MSK; | ||
| 236 | bmi270_scale_item = bmi270_scale_table[BMI270_ACCEL]; | ||
| 237 | break; | ||
| 238 | case IIO_ANGL_VEL: | ||
| 239 | reg = BMI270_GYR_CONF_RANGE_REG; | ||
| 240 | mask = BMI270_GYR_CONF_RANGE_MSK; | ||
| 241 | bmi270_scale_item = bmi270_scale_table[BMI270_GYRO]; | ||
| 242 | break; | ||
| 243 | default: | ||
| 244 | return -EINVAL; | ||
| 245 | } | ||
| 246 | |||
| 247 | for (i = 0; i < bmi270_scale_item.num; i++) { | ||
| 248 | if (bmi270_scale_item.tbl[i].uscale != uscale) | ||
| 249 | continue; | ||
| 250 | |||
| 251 | return regmap_update_bits(data->regmap, reg, mask, i); | ||
| 252 | } | ||
| 253 | |||
| 254 | return -EINVAL; | ||
| 255 | } | ||
| 256 | |||
| 257 | static int bmi270_get_scale(struct bmi270_data *bmi270_device, int chan_type, | ||
| 258 | int *uscale) | ||
| 259 | { | ||
| 260 | int ret; | ||
| 261 | unsigned int val; | ||
| 262 | struct bmi270_scale_item bmi270_scale_item; | ||
| 263 | |||
| 264 | switch (chan_type) { | ||
| 265 | case IIO_ACCEL: | ||
| 266 | ret = regmap_read(bmi270_device->regmap, | ||
| 267 | BMI270_ACC_CONF_RANGE_REG, &val); | ||
| 268 | if (ret) | ||
| 269 | return ret; | ||
| 270 | |||
| 271 | val = FIELD_GET(BMI270_ACC_CONF_RANGE_MSK, val); | ||
| 272 | bmi270_scale_item = bmi270_scale_table[BMI270_ACCEL]; | ||
| 273 | break; | ||
| 274 | case IIO_ANGL_VEL: | ||
| 275 | ret = regmap_read(bmi270_device->regmap, | ||
| 276 | BMI270_GYR_CONF_RANGE_REG, &val); | ||
| 277 | if (ret) | ||
| 278 | return ret; | ||
| 279 | |||
| 280 | val = FIELD_GET(BMI270_GYR_CONF_RANGE_MSK, val); | ||
| 281 | bmi270_scale_item = bmi270_scale_table[BMI270_GYRO]; | ||
| 282 | break; | ||
| 283 | default: | ||
| 284 | return -EINVAL; | ||
| 285 | } | ||
| 286 | |||
| 287 | if (val >= bmi270_scale_item.num) | ||
| 288 | return -EINVAL; | ||
| 289 | |||
| 290 | *uscale = bmi270_scale_item.tbl[val].uscale; | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | static int bmi270_set_odr(struct bmi270_data *data, int chan_type, int odr, | ||
| 295 | int uodr) | ||
| 296 | { | ||
| 297 | int i; | ||
| 298 | int reg, mask; | ||
| 299 | struct bmi270_odr_item bmi270_odr_item; | ||
| 300 | |||
| 301 | switch (chan_type) { | ||
| 302 | case IIO_ACCEL: | ||
| 303 | reg = BMI270_ACC_CONF_REG; | ||
| 304 | mask = BMI270_ACC_CONF_ODR_MSK; | ||
| 305 | bmi270_odr_item = bmi270_odr_table[BMI270_ACCEL]; | ||
| 306 | break; | ||
| 307 | case IIO_ANGL_VEL: | ||
| 308 | reg = BMI270_GYR_CONF_REG; | ||
| 309 | mask = BMI270_GYR_CONF_ODR_MSK; | ||
| 310 | bmi270_odr_item = bmi270_odr_table[BMI270_GYRO]; | ||
| 311 | break; | ||
| 312 | default: | ||
| 313 | return -EINVAL; | ||
| 314 | } | ||
| 315 | |||
| 316 | for (i = 0; i < bmi270_odr_item.num; i++) { | ||
| 317 | if (bmi270_odr_item.tbl[i].odr != odr || | ||
| 318 | bmi270_odr_item.tbl[i].uodr != uodr) | ||
| 319 | continue; | ||
| 320 | |||
| 321 | return regmap_update_bits(data->regmap, reg, mask, | ||
| 322 | bmi270_odr_item.vals[i]); | ||
| 323 | } | ||
| 324 | |||
| 325 | return -EINVAL; | ||
| 326 | } | ||
| 327 | |||
| 328 | static int bmi270_get_odr(struct bmi270_data *data, int chan_type, int *odr, | ||
| 329 | int *uodr) | ||
| 330 | { | ||
| 331 | int i, val, ret; | ||
| 332 | struct bmi270_odr_item bmi270_odr_item; | ||
| 333 | |||
| 334 | switch (chan_type) { | ||
| 335 | case IIO_ACCEL: | ||
| 336 | ret = regmap_read(data->regmap, BMI270_ACC_CONF_REG, &val); | ||
| 337 | if (ret) | ||
| 338 | return ret; | ||
| 339 | |||
| 340 | val = FIELD_GET(BMI270_ACC_CONF_ODR_MSK, val); | ||
| 341 | bmi270_odr_item = bmi270_odr_table[BMI270_ACCEL]; | ||
| 342 | break; | ||
| 343 | case IIO_ANGL_VEL: | ||
| 344 | ret = regmap_read(data->regmap, BMI270_GYR_CONF_REG, &val); | ||
| 345 | if (ret) | ||
| 346 | return ret; | ||
| 347 | |||
| 348 | val = FIELD_GET(BMI270_GYR_CONF_ODR_MSK, val); | ||
| 349 | bmi270_odr_item = bmi270_odr_table[BMI270_GYRO]; | ||
| 350 | break; | ||
| 351 | default: | ||
| 352 | return -EINVAL; | ||
| 353 | } | ||
| 354 | |||
| 355 | for (i = 0; i < bmi270_odr_item.num; i++) { | ||
| 356 | if (val != bmi270_odr_item.vals[i]) | ||
| 357 | continue; | ||
| 358 | |||
| 359 | *odr = bmi270_odr_item.tbl[i].odr; | ||
| 360 | *uodr = bmi270_odr_item.tbl[i].uodr; | ||
| 361 | return 0; | ||
| 362 | } | ||
| 363 | |||
| 364 | return -EINVAL; | ||
| 365 | } | ||
| 366 | |||
| 367 | static irqreturn_t bmi270_trigger_handler(int irq, void *p) | ||
| 368 | { | ||
| 369 | struct iio_poll_func *pf = p; | ||
| 370 | struct iio_dev *indio_dev = pf->indio_dev; | ||
| 371 | struct bmi270_data *bmi270_device = iio_priv(indio_dev); | ||
| 372 | int ret; | ||
| 373 | |||
| 374 | ret = regmap_bulk_read(bmi270_device->regmap, BMI270_ACCEL_X_REG, | ||
| 375 | &bmi270_device->data.channels, | ||
| 376 | sizeof(bmi270_device->data.channels)); | ||
| 377 | |||
| 378 | if (ret) | ||
| 379 | goto done; | ||
| 380 | |||
| 381 | iio_push_to_buffers_with_timestamp(indio_dev, &bmi270_device->data, | ||
| 382 | pf->timestamp); | ||
| 383 | done: | ||
| 384 | iio_trigger_notify_done(indio_dev->trig); | ||
| 385 | return IRQ_HANDLED; | ||
| 386 | } | ||
| 387 | |||
| 388 | static int bmi270_get_data(struct bmi270_data *bmi270_device, | ||
| 389 | int chan_type, int axis, int *val) | ||
| 390 | { | ||
| 391 | __le16 sample; | ||
| 392 | int reg; | ||
| 393 | int ret; | ||
| 394 | |||
| 395 | switch (chan_type) { | ||
| 396 | case IIO_ACCEL: | ||
| 397 | reg = BMI270_ACCEL_X_REG + (axis - IIO_MOD_X) * 2; | ||
| 398 | break; | ||
| 399 | case IIO_ANGL_VEL: | ||
| 400 | reg = BMI270_ANG_VEL_X_REG + (axis - IIO_MOD_X) * 2; | ||
| 401 | break; | ||
| 402 | default: | ||
| 403 | return -EINVAL; | ||
| 404 | } | ||
| 405 | |||
| 406 | ret = regmap_bulk_read(bmi270_device->regmap, reg, &sample, sizeof(sample)); | ||
| 407 | if (ret) | ||
| 408 | return ret; | ||
| 409 | |||
| 410 | *val = sign_extend32(le16_to_cpu(sample), 15); | ||
| 411 | |||
| 412 | return 0; | ||
| 413 | } | ||
| 414 | |||
| 415 | static int bmi270_read_raw(struct iio_dev *indio_dev, | ||
| 416 | struct iio_chan_spec const *chan, | ||
| 417 | int *val, int *val2, long mask) | ||
| 418 | { | ||
| 419 | int ret; | ||
| 420 | struct bmi270_data *bmi270_device = iio_priv(indio_dev); | ||
| 421 | |||
| 422 | switch (mask) { | ||
| 423 | case IIO_CHAN_INFO_RAW: | ||
| 424 | ret = bmi270_get_data(bmi270_device, chan->type, chan->channel2, val); | ||
| 425 | if (ret) | ||
| 426 | return ret; | ||
| 427 | |||
| 428 | return IIO_VAL_INT; | ||
| 429 | case IIO_CHAN_INFO_SCALE: | ||
| 430 | *val = 0; | ||
| 431 | ret = bmi270_get_scale(bmi270_device, chan->type, val2); | ||
| 432 | return ret ? ret : IIO_VAL_INT_PLUS_MICRO; | ||
| 433 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 434 | ret = bmi270_get_odr(bmi270_device, chan->type, val, val2); | ||
| 435 | return ret ? ret : IIO_VAL_INT_PLUS_MICRO; | ||
| 436 | default: | ||
| 437 | return -EINVAL; | ||
| 438 | } | ||
| 439 | } | ||
| 440 | |||
| 441 | static int bmi270_write_raw(struct iio_dev *indio_dev, | ||
| 442 | struct iio_chan_spec const *chan, | ||
| 443 | int val, int val2, long mask) | ||
| 444 | { | ||
| 445 | struct bmi270_data *data = iio_priv(indio_dev); | ||
| 446 | |||
| 447 | switch (mask) { | ||
| 448 | case IIO_CHAN_INFO_SCALE: | ||
| 449 | return bmi270_set_scale(data, chan->type, val2); | ||
| 450 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 451 | return bmi270_set_odr(data, chan->type, val, val2); | ||
| 452 | default: | ||
| 453 | return -EINVAL; | ||
| 454 | } | ||
| 455 | } | ||
| 456 | |||
| 457 | static int bmi270_read_avail(struct iio_dev *indio_dev, | ||
| 458 | struct iio_chan_spec const *chan, | ||
| 459 | const int **vals, int *type, int *length, | ||
| 460 | long mask) | ||
| 461 | { | ||
| 462 | switch (mask) { | ||
| 463 | case IIO_CHAN_INFO_SCALE: | ||
| 464 | *type = IIO_VAL_INT_PLUS_MICRO; | ||
| 465 | switch (chan->type) { | ||
| 466 | case IIO_ANGL_VEL: | ||
| 467 | *vals = (const int *)bmi270_gyro_scale; | ||
| 468 | *length = ARRAY_SIZE(bmi270_gyro_scale) * 2; | ||
| 469 | return IIO_AVAIL_LIST; | ||
| 470 | case IIO_ACCEL: | ||
| 471 | *vals = (const int *)bmi270_accel_scale; | ||
| 472 | *length = ARRAY_SIZE(bmi270_accel_scale) * 2; | ||
| 473 | return IIO_AVAIL_LIST; | ||
| 474 | default: | ||
| 475 | return -EINVAL; | ||
| 476 | } | ||
| 477 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 478 | *type = IIO_VAL_INT_PLUS_MICRO; | ||
| 479 | switch (chan->type) { | ||
| 480 | case IIO_ANGL_VEL: | ||
| 481 | *vals = (const int *)bmi270_gyro_odr; | ||
| 482 | *length = ARRAY_SIZE(bmi270_gyro_odr) * 2; | ||
| 483 | return IIO_AVAIL_LIST; | ||
| 484 | case IIO_ACCEL: | ||
| 485 | *vals = (const int *)bmi270_accel_odr; | ||
| 486 | *length = ARRAY_SIZE(bmi270_accel_odr) * 2; | ||
| 487 | return IIO_AVAIL_LIST; | ||
| 488 | default: | ||
| 489 | return -EINVAL; | ||
| 490 | } | ||
| 491 | default: | ||
| 492 | return -EINVAL; | ||
| 493 | } | ||
| 494 | } | ||
| 495 | |||
| 496 | static const struct iio_info bmi270_info = { | ||
| 497 | .read_raw = bmi270_read_raw, | ||
| 498 | .write_raw = bmi270_write_raw, | ||
| 499 | .read_avail = bmi270_read_avail, | ||
| 500 | }; | ||
| 501 | |||
| 502 | #define BMI270_ACCEL_CHANNEL(_axis) { \ | ||
| 503 | .type = IIO_ACCEL, \ | ||
| 504 | .modified = 1, \ | ||
| 505 | .channel2 = IIO_MOD_##_axis, \ | ||
| 506 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
| 507 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ | ||
| 508 | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | ||
| 509 | .info_mask_shared_by_type_available = \ | ||
| 510 | BIT(IIO_CHAN_INFO_SCALE) | \ | ||
| 511 | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | ||
| 512 | .scan_index = BMI270_SCAN_ACCEL_##_axis, \ | ||
| 513 | .scan_type = { \ | ||
| 514 | .sign = 's', \ | ||
| 515 | .realbits = 16, \ | ||
| 516 | .storagebits = 16, \ | ||
| 517 | .endianness = IIO_LE, \ | ||
| 518 | }, \ | ||
| 519 | } | ||
| 520 | |||
| 521 | #define BMI270_ANG_VEL_CHANNEL(_axis) { \ | ||
| 522 | .type = IIO_ANGL_VEL, \ | ||
| 523 | .modified = 1, \ | ||
| 524 | .channel2 = IIO_MOD_##_axis, \ | ||
| 525 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
| 526 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ | ||
| 527 | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | ||
| 528 | .info_mask_shared_by_type_available = \ | ||
| 529 | BIT(IIO_CHAN_INFO_SCALE) | \ | ||
| 530 | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | ||
| 531 | .scan_index = BMI270_SCAN_GYRO_##_axis, \ | ||
| 532 | .scan_type = { \ | ||
| 533 | .sign = 's', \ | ||
| 534 | .realbits = 16, \ | ||
| 535 | .storagebits = 16, \ | ||
| 536 | .endianness = IIO_LE, \ | ||
| 537 | }, \ | ||
| 538 | } | ||
| 539 | |||
| 540 | static const struct iio_chan_spec bmi270_channels[] = { | ||
| 541 | BMI270_ACCEL_CHANNEL(X), | ||
| 542 | BMI270_ACCEL_CHANNEL(Y), | ||
| 543 | BMI270_ACCEL_CHANNEL(Z), | ||
| 544 | BMI270_ANG_VEL_CHANNEL(X), | ||
| 545 | BMI270_ANG_VEL_CHANNEL(Y), | ||
| 546 | BMI270_ANG_VEL_CHANNEL(Z), | ||
| 547 | IIO_CHAN_SOFT_TIMESTAMP(BMI270_SCAN_TIMESTAMP), | ||
| 548 | }; | ||
| 549 | |||
| 550 | static int bmi270_validate_chip_id(struct bmi270_data *bmi270_device) | ||
| 551 | { | ||
| 552 | int chip_id; | ||
| 553 | int ret; | ||
| 554 | struct device *dev = bmi270_device->dev; | ||
| 555 | struct regmap *regmap = bmi270_device->regmap; | ||
| 556 | |||
| 557 | ret = regmap_read(regmap, BMI270_CHIP_ID_REG, &chip_id); | ||
| 558 | if (ret) | ||
| 559 | return dev_err_probe(dev, ret, "Failed to read chip id"); | ||
| 560 | |||
| 561 | /* | ||
| 562 | * Some manufacturers use "BMI0160" for both the BMI160 and | ||
| 563 | * BMI260. If the device is actually a BMI160, the bmi160 | ||
| 564 | * driver should handle it and this driver should not. | ||
| 565 | */ | ||
| 566 | if (chip_id == BMI160_CHIP_ID_VAL) | ||
| 567 | return -ENODEV; | ||
| 568 | |||
| 569 | if (chip_id != bmi270_device->chip_info->chip_id) | ||
| 570 | dev_info(dev, "Unexpected chip id 0x%x", chip_id); | ||
| 571 | |||
| 572 | if (chip_id == bmi260_chip_info.chip_id) | ||
| 573 | bmi270_device->chip_info = &bmi260_chip_info; | ||
| 574 | else if (chip_id == bmi270_chip_info.chip_id) | ||
| 575 | bmi270_device->chip_info = &bmi270_chip_info; | ||
| 576 | |||
| 577 | return 0; | ||
| 578 | } | ||
| 579 | |||
| 580 | static int bmi270_write_calibration_data(struct bmi270_data *bmi270_device) | ||
| 581 | { | ||
| 582 | int ret; | ||
| 583 | int status = 0; | ||
| 584 | const struct firmware *init_data; | ||
| 585 | struct device *dev = bmi270_device->dev; | ||
| 586 | struct regmap *regmap = bmi270_device->regmap; | ||
| 587 | |||
| 588 | ret = regmap_clear_bits(regmap, BMI270_PWR_CONF_REG, | ||
| 589 | BMI270_PWR_CONF_ADV_PWR_SAVE_MSK); | ||
| 590 | if (ret) | ||
| 591 | return dev_err_probe(dev, ret, | ||
| 592 | "Failed to write power configuration"); | ||
| 593 | |||
| 594 | /* | ||
| 595 | * After disabling advanced power save, all registers are accessible | ||
| 596 | * after a 450us delay. This delay is specified in table A of the | ||
| 597 | * datasheet. | ||
| 598 | */ | ||
| 599 | usleep_range(450, 1000); | ||
| 600 | |||
| 601 | ret = regmap_clear_bits(regmap, BMI270_INIT_CTRL_REG, | ||
| 602 | BMI270_INIT_CTRL_LOAD_DONE_MSK); | ||
| 603 | if (ret) | ||
| 604 | return dev_err_probe(dev, ret, | ||
| 605 | "Failed to prepare device to load init data"); | ||
| 606 | |||
| 607 | ret = request_firmware(&init_data, | ||
| 608 | bmi270_device->chip_info->fw_name, dev); | ||
| 609 | if (ret) | ||
| 610 | return dev_err_probe(dev, ret, "Failed to load init data file"); | ||
| 611 | |||
| 612 | ret = regmap_bulk_write(regmap, BMI270_INIT_DATA_REG, | ||
| 613 | init_data->data, init_data->size); | ||
| 614 | release_firmware(init_data); | ||
| 615 | if (ret) | ||
| 616 | return dev_err_probe(dev, ret, "Failed to write init data"); | ||
| 617 | |||
| 618 | ret = regmap_set_bits(regmap, BMI270_INIT_CTRL_REG, | ||
| 619 | BMI270_INIT_CTRL_LOAD_DONE_MSK); | ||
| 620 | if (ret) | ||
| 621 | return dev_err_probe(dev, ret, | ||
| 622 | "Failed to stop device initialization"); | ||
| 623 | |||
| 624 | /* | ||
| 625 | * Wait at least 140ms for the device to complete configuration. | ||
| 626 | * This delay is specified in table C of the datasheet. | ||
| 627 | */ | ||
| 628 | usleep_range(140000, 160000); | ||
| 629 | |||
| 630 | ret = regmap_read(regmap, BMI270_INTERNAL_STATUS_REG, &status); | ||
| 631 | if (ret) | ||
| 632 | return dev_err_probe(dev, ret, "Failed to read internal status"); | ||
| 633 | |||
| 634 | if (status != BMI270_INTERNAL_STATUS_MSG_INIT_OK) | ||
| 635 | return dev_err_probe(dev, -ENODEV, "Device failed to initialize"); | ||
| 636 | |||
| 637 | return 0; | ||
| 638 | } | ||
| 639 | |||
| 640 | static int bmi270_configure_imu(struct bmi270_data *bmi270_device) | ||
| 641 | { | ||
| 642 | int ret; | ||
| 643 | struct device *dev = bmi270_device->dev; | ||
| 644 | struct regmap *regmap = bmi270_device->regmap; | ||
| 645 | |||
| 646 | ret = regmap_set_bits(regmap, BMI270_PWR_CTRL_REG, | ||
| 647 | BMI270_PWR_CTRL_AUX_EN_MSK | | ||
| 648 | BMI270_PWR_CTRL_GYR_EN_MSK | | ||
| 649 | BMI270_PWR_CTRL_ACCEL_EN_MSK); | ||
| 650 | if (ret) | ||
| 651 | return dev_err_probe(dev, ret, "Failed to enable accelerometer and gyroscope"); | ||
| 652 | |||
| 653 | ret = regmap_set_bits(regmap, BMI270_ACC_CONF_REG, | ||
| 654 | FIELD_PREP(BMI270_ACC_CONF_ODR_MSK, | ||
| 655 | BMI270_ACC_CONF_ODR_100HZ) | | ||
| 656 | FIELD_PREP(BMI270_ACC_CONF_BWP_MSK, | ||
| 657 | BMI270_ACC_CONF_BWP_NORMAL_MODE) | | ||
| 658 | BMI270_PWR_CONF_ADV_PWR_SAVE_MSK); | ||
| 659 | if (ret) | ||
| 660 | return dev_err_probe(dev, ret, "Failed to configure accelerometer"); | ||
| 661 | |||
| 662 | ret = regmap_set_bits(regmap, BMI270_GYR_CONF_REG, | ||
| 663 | FIELD_PREP(BMI270_GYR_CONF_ODR_MSK, | ||
| 664 | BMI270_GYR_CONF_ODR_200HZ) | | ||
| 665 | FIELD_PREP(BMI270_GYR_CONF_BWP_MSK, | ||
| 666 | BMI270_GYR_CONF_BWP_NORMAL_MODE) | | ||
| 667 | BMI270_PWR_CONF_ADV_PWR_SAVE_MSK); | ||
| 668 | if (ret) | ||
| 669 | return dev_err_probe(dev, ret, "Failed to configure gyroscope"); | ||
| 670 | |||
| 671 | /* Enable FIFO_WKUP, Disable ADV_PWR_SAVE and FUP_EN */ | ||
| 672 | ret = regmap_write(regmap, BMI270_PWR_CONF_REG, | ||
| 673 | BMI270_PWR_CONF_FIFO_WKUP_MSK); | ||
| 674 | if (ret) | ||
| 675 | return dev_err_probe(dev, ret, "Failed to set power configuration"); | ||
| 676 | |||
| 677 | return 0; | ||
| 678 | } | ||
| 679 | |||
| 680 | static int bmi270_chip_init(struct bmi270_data *bmi270_device) | ||
| 681 | { | ||
| 682 | int ret; | ||
| 683 | |||
| 684 | ret = bmi270_validate_chip_id(bmi270_device); | ||
| 685 | if (ret) | ||
| 686 | return ret; | ||
| 687 | |||
| 688 | ret = bmi270_write_calibration_data(bmi270_device); | ||
| 689 | if (ret) | ||
| 690 | return ret; | ||
| 691 | |||
| 692 | return bmi270_configure_imu(bmi270_device); | ||
| 693 | } | ||
| 694 | |||
| 695 | int bmi270_core_probe(struct device *dev, struct regmap *regmap, | ||
| 696 | const struct bmi270_chip_info *chip_info) | ||
| 697 | { | ||
| 698 | int ret; | ||
| 699 | struct bmi270_data *bmi270_device; | ||
| 700 | struct iio_dev *indio_dev; | ||
| 701 | |||
| 702 | indio_dev = devm_iio_device_alloc(dev, sizeof(*bmi270_device)); | ||
| 703 | if (!indio_dev) | ||
| 704 | return -ENOMEM; | ||
| 705 | |||
| 706 | bmi270_device = iio_priv(indio_dev); | ||
| 707 | bmi270_device->dev = dev; | ||
| 708 | bmi270_device->regmap = regmap; | ||
| 709 | bmi270_device->chip_info = chip_info; | ||
| 710 | |||
| 711 | ret = bmi270_chip_init(bmi270_device); | ||
| 712 | if (ret) | ||
| 713 | return ret; | ||
| 714 | |||
| 715 | indio_dev->channels = bmi270_channels; | ||
| 716 | indio_dev->num_channels = ARRAY_SIZE(bmi270_channels); | ||
| 717 | indio_dev->name = chip_info->name; | ||
| 718 | indio_dev->available_scan_masks = bmi270_avail_scan_masks; | ||
| 719 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
| 720 | indio_dev->info = &bmi270_info; | ||
| 721 | |||
| 722 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, | ||
| 723 | iio_pollfunc_store_time, | ||
| 724 | bmi270_trigger_handler, NULL); | ||
| 725 | if (ret) | ||
| 726 | return ret; | ||
| 727 | |||
| 728 | return devm_iio_device_register(dev, indio_dev); | ||
| 729 | } | ||
| 730 | EXPORT_SYMBOL_NS_GPL(bmi270_core_probe, IIO_BMI270); | ||
| 731 | |||
| 732 | MODULE_AUTHOR("Alex Lanzano"); | ||
| 733 | MODULE_DESCRIPTION("BMI270 driver"); | ||
| 734 | MODULE_LICENSE("GPL"); | ||
| @@ -0,0 +1,66 @@ | |||
| 1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | |||
| 3 | #include <linux/i2c.h> | ||
| 4 | #include <linux/iio/iio.h> | ||
| 5 | #include <linux/module.h> | ||
| 6 | #include <linux/mod_devicetable.h> | ||
| 7 | #include <linux/regmap.h> | ||
| 8 | |||
| 9 | #include "bmi270.h" | ||
| 10 | |||
| 11 | static const struct regmap_config bmi270_i2c_regmap_config = { | ||
| 12 | .reg_bits = 8, | ||
| 13 | .val_bits = 8, | ||
| 14 | }; | ||
| 15 | |||
| 16 | static int bmi270_i2c_probe(struct i2c_client *client) | ||
| 17 | { | ||
| 18 | struct regmap *regmap; | ||
| 19 | struct device *dev = &client->dev; | ||
| 20 | const struct bmi270_chip_info *chip_info; | ||
| 21 | |||
| 22 | chip_info = i2c_get_match_data(client); | ||
| 23 | if (!chip_info) | ||
| 24 | return -ENODEV; | ||
| 25 | |||
| 26 | regmap = devm_regmap_init_i2c(client, &bmi270_i2c_regmap_config); | ||
| 27 | if (IS_ERR(regmap)) | ||
| 28 | return dev_err_probe(dev, PTR_ERR(regmap), | ||
| 29 | "Failed to init i2c regmap"); | ||
| 30 | |||
| 31 | return bmi270_core_probe(dev, regmap, chip_info); | ||
| 32 | } | ||
| 33 | |||
| 34 | static const struct i2c_device_id bmi270_i2c_id[] = { | ||
| 35 | { "bmi260", (kernel_ulong_t)&bmi260_chip_info }, | ||
| 36 | { "bmi270", (kernel_ulong_t)&bmi270_chip_info }, | ||
| 37 | { } | ||
| 38 | }; | ||
| 39 | |||
| 40 | static const struct acpi_device_id bmi270_acpi_match[] = { | ||
| 41 | /* GPD Win Mini, Aya Neo AIR Pro, OXP Mini Pro, etc. */ | ||
| 42 | { "BMI0160", (kernel_ulong_t)&bmi260_chip_info }, | ||
| 43 | { } | ||
| 44 | }; | ||
| 45 | |||
| 46 | static const struct of_device_id bmi270_of_match[] = { | ||
| 47 | { .compatible = "bosch,bmi260", .data = &bmi260_chip_info }, | ||
| 48 | { .compatible = "bosch,bmi270", .data = &bmi270_chip_info }, | ||
| 49 | { } | ||
| 50 | }; | ||
| 51 | |||
| 52 | static struct i2c_driver bmi270_i2c_driver = { | ||
| 53 | .driver = { | ||
| 54 | .name = "bmi270_i2c", | ||
| 55 | .acpi_match_table = bmi270_acpi_match, | ||
| 56 | .of_match_table = bmi270_of_match, | ||
| 57 | }, | ||
| 58 | .probe = bmi270_i2c_probe, | ||
| 59 | .id_table = bmi270_i2c_id, | ||
| 60 | }; | ||
| 61 | module_i2c_driver(bmi270_i2c_driver); | ||
| 62 | |||
| 63 | MODULE_AUTHOR("Alex Lanzano"); | ||
| 64 | MODULE_DESCRIPTION("BMI270 driver"); | ||
| 65 | MODULE_LICENSE("GPL"); | ||
| 66 | MODULE_IMPORT_NS(IIO_BMI270); | ||
| @@ -0,0 +1,92 @@ | |||
| 1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | |||
| 3 | #include <linux/iio/iio.h> | ||
| 4 | #include <linux/mod_devicetable.h> | ||
| 5 | #include <linux/module.h> | ||
| 6 | #include <linux/regmap.h> | ||
| 7 | #include <linux/spi/spi.h> | ||
| 8 | |||
| 9 | #include "bmi270.h" | ||
| 10 | |||
| 11 | /* | ||
| 12 | * The following two functions are taken from the BMI323 spi driver code. | ||
| 13 | * In section 6.4 of the BMI270 data it specifies that after a read | ||
| 14 | * operation the first data byte from the device is a dummy byte | ||
| 15 | */ | ||
| 16 | static int bmi270_regmap_spi_read(void *spi, const void *reg_buf, | ||
| 17 | size_t reg_size, void *val_buf, | ||
| 18 | size_t val_size) | ||
| 19 | { | ||
| 20 | return spi_write_then_read(spi, reg_buf, reg_size, val_buf, val_size); | ||
| 21 | } | ||
| 22 | |||
| 23 | static int bmi270_regmap_spi_write(void *spi, const void *data, | ||
| 24 | size_t count) | ||
| 25 | { | ||
| 26 | u8 *data_buff = (u8 *)data; | ||
| 27 | |||
| 28 | /* | ||
| 29 | * Remove the extra pad byte since its only needed for the read | ||
| 30 | * operation | ||
| 31 | */ | ||
| 32 | data_buff[1] = data_buff[0]; | ||
| 33 | return spi_write_then_read(spi, data_buff + 1, count - 1, NULL, 0); | ||
| 34 | } | ||
| 35 | |||
| 36 | static const struct regmap_bus bmi270_regmap_bus = { | ||
| 37 | .read = bmi270_regmap_spi_read, | ||
| 38 | .write = bmi270_regmap_spi_write, | ||
| 39 | }; | ||
| 40 | |||
| 41 | static const struct regmap_config bmi270_spi_regmap_config = { | ||
| 42 | .reg_bits = 8, | ||
| 43 | .val_bits = 8, | ||
| 44 | .pad_bits = 8, | ||
| 45 | .read_flag_mask = BIT(7), | ||
| 46 | }; | ||
| 47 | |||
| 48 | static int bmi270_spi_probe(struct spi_device *spi) | ||
| 49 | { | ||
| 50 | struct regmap *regmap; | ||
| 51 | struct device *dev = &spi->dev; | ||
| 52 | const struct bmi270_chip_info *chip_info; | ||
| 53 | |||
| 54 | chip_info = spi_get_device_match_data(spi); | ||
| 55 | if (!chip_info) | ||
| 56 | return -ENODEV; | ||
| 57 | |||
| 58 | regmap = devm_regmap_init(dev, &bmi270_regmap_bus, dev, | ||
| 59 | &bmi270_spi_regmap_config); | ||
| 60 | if (IS_ERR(regmap)) | ||
| 61 | return dev_err_probe(dev, PTR_ERR(regmap), | ||
| 62 | "Failed to init i2c regmap"); | ||
| 63 | |||
| 64 | return bmi270_core_probe(dev, regmap, chip_info); | ||
| 65 | } | ||
| 66 | |||
| 67 | static const struct spi_device_id bmi270_spi_id[] = { | ||
| 68 | { "bmi260", (kernel_ulong_t)&bmi260_chip_info }, | ||
| 69 | { "bmi270", (kernel_ulong_t)&bmi270_chip_info }, | ||
| 70 | { } | ||
| 71 | }; | ||
| 72 | |||
| 73 | static const struct of_device_id bmi270_of_match[] = { | ||
| 74 | { .compatible = "bosch,bmi260", .data = &bmi260_chip_info }, | ||
| 75 | { .compatible = "bosch,bmi270", .data = &bmi270_chip_info }, | ||
| 76 | { } | ||
| 77 | }; | ||
| 78 | |||
| 79 | static struct spi_driver bmi270_spi_driver = { | ||
| 80 | .driver = { | ||
| 81 | .name = "bmi270", | ||
| 82 | .of_match_table = bmi270_of_match, | ||
| 83 | }, | ||
| 84 | .probe = bmi270_spi_probe, | ||
| 85 | .id_table = bmi270_spi_id, | ||
| 86 | }; | ||
| 87 | module_spi_driver(bmi270_spi_driver); | ||
| 88 | |||
| 89 | MODULE_AUTHOR("Alex Lanzano"); | ||
| 90 | MODULE_DESCRIPTION("BMI270 driver"); | ||
| 91 | MODULE_LICENSE("GPL"); | ||
| 92 | MODULE_IMPORT_NS(IIO_BMI270); | ||
| @@ -141,7 +141,6 @@ · 140 unmodified lines | |||
| 141 | #define BMI323_STEP_SC1_REG 0x10 | 141 | #define BMI323_STEP_SC1_REG 0x10 |
| 142 | #define BMI323_STEP_SC1_WTRMRK_MSK GENMASK(9, 0) | 142 | #define BMI323_STEP_SC1_WTRMRK_MSK GENMASK(9, 0) |
| 143 | #define BMI323_STEP_SC1_RST_CNT_MSK BIT(10) | 143 | #define BMI323_STEP_SC1_RST_CNT_MSK BIT(10) |
| 144 | #define BMI323_STEP_SC1_REG 0x10 | ||
| 145 | #define BMI323_STEP_LEN 2 | 144 | #define BMI323_STEP_LEN 2 |
| 146 | 145 | ||
| 147 | /* Tap gesture config registers */ | 146 | /* Tap gesture config registers */ |
| @@ -467,7 +467,7 @@ static int bmi323_feature_engine_events(struct bmi323_data *data, · 466 unmodified lines | |||
| 467 | BMI323_FEAT_IO_STATUS_MSK); | 467 | BMI323_FEAT_IO_STATUS_MSK); |
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | static int bmi323_step_wtrmrk_en(struct bmi323_data *data, int state) | 470 | static int bmi323_step_wtrmrk_en(struct bmi323_data *data, bool state) |
| 471 | { | 471 | { |
| 472 | enum bmi323_irq_pin step_irq; | 472 | enum bmi323_irq_pin step_irq; |
| 473 | int ret; | 473 | int ret; |
| @@ -484,7 +484,7 @@ static int bmi323_step_wtrmrk_en(struct bmi323_data *data, int state) · 10 unmodified lines | |||
| 484 | ret = bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG, | 484 | ret = bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG, |
| 485 | BMI323_STEP_SC1_WTRMRK_MSK, | 485 | BMI323_STEP_SC1_WTRMRK_MSK, |
| 486 | FIELD_PREP(BMI323_STEP_SC1_WTRMRK_MSK, | 486 | FIELD_PREP(BMI323_STEP_SC1_WTRMRK_MSK, |
| 487 | state ? 1 : 0)); | 487 | state)); |
| 488 | if (ret) | 488 | if (ret) |
| 489 | return ret; | 489 | return ret; |
| 490 | 490 | ||
| @@ -506,7 +506,7 @@ static int bmi323_motion_config_reg(enum iio_event_direction dir) · 15 unmodified lines | |||
| 506 | } | 506 | } |
| 507 | 507 | ||
| 508 | static int bmi323_motion_event_en(struct bmi323_data *data, | 508 | static int bmi323_motion_event_en(struct bmi323_data *data, |
| 509 | enum iio_event_direction dir, int state) | 509 | enum iio_event_direction dir, bool state) |
| 510 | { | 510 | { |
| 511 | unsigned int state_value = state ? BMI323_FEAT_XYZ_MSK : 0; | 511 | unsigned int state_value = state ? BMI323_FEAT_XYZ_MSK : 0; |
| 512 | int config, ret, msk, raw, field_value; | 512 | int config, ret, msk, raw, field_value; |
| @@ -570,7 +570,7 @@ static int bmi323_motion_event_en(struct bmi323_data *data, · 57 unmodified lines | |||
| 570 | } | 570 | } |
| 571 | 571 | ||
| 572 | static int bmi323_tap_event_en(struct bmi323_data *data, | 572 | static int bmi323_tap_event_en(struct bmi323_data *data, |
| 573 | enum iio_event_direction dir, int state) | 573 | enum iio_event_direction dir, bool state) |
| 574 | { | 574 | { |
| 575 | enum bmi323_irq_pin tap_irq; | 575 | enum bmi323_irq_pin tap_irq; |
| 576 | int ret, tap_enabled; | 576 | int ret, tap_enabled; |
| @@ -785,7 +785,7 @@ static const struct attribute_group bmi323_event_attribute_group = { · 208 unmodified lines | |||
| 785 | static int bmi323_write_event_config(struct iio_dev *indio_dev, | 785 | static int bmi323_write_event_config(struct iio_dev *indio_dev, |
| 786 | const struct iio_chan_spec *chan, | 786 | const struct iio_chan_spec *chan, |
| 787 | enum iio_event_type type, | 787 | enum iio_event_type type, |
| 788 | enum iio_event_direction dir, int state) | 788 | enum iio_event_direction dir, bool state) |
| 789 | { | 789 | { |
| 790 | struct bmi323_data *data = iio_priv(indio_dev); | 790 | struct bmi323_data *data = iio_priv(indio_dev); |
| 791 | 791 | ||
| @@ -1881,7 +1881,6 @@ static int bmi323_trigger_probe(struct bmi323_data *data, · 1089 unmodified lines | |||
| 1881 | struct fwnode_handle *fwnode; | 1881 | struct fwnode_handle *fwnode; |
| 1882 | enum bmi323_irq_pin irq_pin; | 1882 | enum bmi323_irq_pin irq_pin; |
| 1883 | int ret, irq, irq_type; | 1883 | int ret, irq, irq_type; |
| 1884 | struct irq_data *desc; | ||
| 1885 | 1884 | ||
| 1886 | fwnode = dev_fwnode(data->dev); | 1885 | fwnode = dev_fwnode(data->dev); |
| 1887 | if (!fwnode) | 1886 | if (!fwnode) |
| @@ -1898,12 +1897,7 @@ static int bmi323_trigger_probe(struct bmi323_data *data, · 10 unmodified lines | |||
| 1898 | irq_pin = BMI323_IRQ_INT2; | 1897 | irq_pin = BMI323_IRQ_INT2; |
| 1899 | } | 1898 | } |
| 1900 | 1899 | ||
| 1901 | desc = irq_get_irq_data(irq); | 1900 | irq_type = irq_get_trigger_type(irq); |
| 1902 | if (!desc) | ||
| 1903 | return dev_err_probe(data->dev, -EINVAL, | ||
| 1904 | "Could not find IRQ %d\n", irq); | ||
| 1905 | |||
| 1906 | irq_type = irqd_get_trigger_type(desc); | ||
| 1907 | switch (irq_type) { | 1901 | switch (irq_type) { |
| 1908 | case IRQF_TRIGGER_RISING: | 1902 | case IRQF_TRIGGER_RISING: |
| 1909 | latch = false; | 1903 | latch = false; |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | |||
| 8 | */ | 8 | */ |
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/regmap.h> | 10 | #include <linux/regmap.h> |
| 11 | #include <linux/acpi.h> | ||
| 12 | #include <linux/bitops.h> | 11 | #include <linux/bitops.h> |
| 13 | #include <linux/bitfield.h> | 12 | #include <linux/bitfield.h> |
| 14 | 13 | ||
| @@ -200,7 +200,6 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev, · 199 unmodified lines | |||
| 200 | { | 200 | { |
| 201 | struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); | 201 | struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); |
| 202 | struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev); | 202 | struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev); |
| 203 | struct inv_sensors_timestamp *ts = &accel_st->ts; | ||
| 204 | struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; | 203 | struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; |
| 205 | unsigned int fifo_en = 0; | 204 | unsigned int fifo_en = 0; |
| 206 | unsigned int sleep_temp = 0; | 205 | unsigned int sleep_temp = 0; |
| @@ -229,7 +228,6 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev, · 22 unmodified lines | |||
| 229 | } | 228 | } |
| 230 | 229 | ||
| 231 | /* update data FIFO write */ | 230 | /* update data FIFO write */ |
| 232 | inv_sensors_timestamp_apply_odr(ts, 0, 0, 0); | ||
| 233 | ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en); | 231 | ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en); |
| 234 | 232 | ||
| 235 | out_unlock: | 233 | out_unlock: |
| @@ -673,7 +673,6 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, · 672 unmodified lines | |||
| 673 | { | 673 | { |
| 674 | struct device *dev = regmap_get_device(regmap); | 674 | struct device *dev = regmap_get_device(regmap); |
| 675 | struct inv_icm42600_state *st; | 675 | struct inv_icm42600_state *st; |
| 676 | struct irq_data *irq_desc; | ||
| 677 | int irq_type; | 676 | int irq_type; |
| 678 | bool open_drain; | 677 | bool open_drain; |
| 679 | int ret; | 678 | int ret; |
| @@ -683,14 +682,7 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, · 3 unmodified lines | |||
| 683 | return -ENODEV; | 682 | return -ENODEV; |
| 684 | } | 683 | } |
| 685 | 684 | ||
| 686 | /* get irq properties, set trigger falling by default */ | 685 | irq_type = irq_get_trigger_type(irq); |
| 687 | irq_desc = irq_get_irq_data(irq); | ||
| 688 | if (!irq_desc) { | ||
| 689 | dev_err(dev, "could not find IRQ %d\n", irq); | ||
| 690 | return -EINVAL; | ||
| 691 | } | ||
| 692 | |||
| 693 | irq_type = irqd_get_trigger_type(irq_desc); | ||
| 694 | if (!irq_type) | 686 | if (!irq_type) |
| 695 | irq_type = IRQF_TRIGGER_FALLING; | 687 | irq_type = IRQF_TRIGGER_FALLING; |
| 696 | 688 | ||
| @@ -99,8 +99,6 @@ static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev, · 98 unmodified lines | |||
| 99 | const unsigned long *scan_mask) | 99 | const unsigned long *scan_mask) |
| 100 | { | 100 | { |
| 101 | struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); | 101 | struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); |
| 102 | struct inv_icm42600_sensor_state *gyro_st = iio_priv(indio_dev); | ||
| 103 | struct inv_sensors_timestamp *ts = &gyro_st->ts; | ||
| 104 | struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; | 102 | struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; |
| 105 | unsigned int fifo_en = 0; | 103 | unsigned int fifo_en = 0; |
| 106 | unsigned int sleep_gyro = 0; | 104 | unsigned int sleep_gyro = 0; |
| @@ -128,7 +126,6 @@ static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev, · 21 unmodified lines | |||
| 128 | } | 126 | } |
| 129 | 127 | ||
| 130 | /* update data FIFO write */ | 128 | /* update data FIFO write */ |
| 131 | inv_sensors_timestamp_apply_odr(ts, 0, 0, 0); | ||
| 132 | ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en); | 129 | ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en); |
| 133 | 130 | ||
| 134 | out_unlock: | 131 | out_unlock: |
| @@ -71,6 +71,22 @@ static int inv_icm42600_probe(struct i2c_client *client) · 70 unmodified lines | |||
| 71 | inv_icm42600_i2c_bus_setup); | 71 | inv_icm42600_i2c_bus_setup); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | /* | ||
| 75 | * device id table is used to identify what device can be | ||
| 76 | * supported by this driver | ||
| 77 | */ | ||
| 78 | static const struct i2c_device_id inv_icm42600_id[] = { | ||
| 79 | { "icm42600", INV_CHIP_ICM42600 }, | ||
| 80 | { "icm42602", INV_CHIP_ICM42602 }, | ||
| 81 | { "icm42605", INV_CHIP_ICM42605 }, | ||
| 82 | { "icm42686", INV_CHIP_ICM42686 }, | ||
| 83 | { "icm42622", INV_CHIP_ICM42622 }, | ||
| 84 | { "icm42688", INV_CHIP_ICM42688 }, | ||
| 85 | { "icm42631", INV_CHIP_ICM42631 }, | ||
| 86 | { } | ||
| 87 | }; | ||
| 88 | MODULE_DEVICE_TABLE(i2c, inv_icm42600_id); | ||
| 89 | |||
| 74 | static const struct of_device_id inv_icm42600_of_matches[] = { | 90 | static const struct of_device_id inv_icm42600_of_matches[] = { |
| 75 | { | 91 | { |
| 76 | .compatible = "invensense,icm42600", | 92 | .compatible = "invensense,icm42600", |
| @@ -104,6 +120,7 @@ static struct i2c_driver inv_icm42600_driver = { · 27 unmodified lines | |||
| 104 | .of_match_table = inv_icm42600_of_matches, | 120 | .of_match_table = inv_icm42600_of_matches, |
| 105 | .pm = pm_ptr(&inv_icm42600_pm_ops), | 121 | .pm = pm_ptr(&inv_icm42600_pm_ops), |
| 106 | }, | 122 | }, |
| 123 | .id_table = inv_icm42600_id, | ||
| 107 | .probe = inv_icm42600_probe, | 124 | .probe = inv_icm42600_probe, |
| 108 | }; | 125 | }; |
| 109 | module_i2c_driver(inv_icm42600_driver); | 126 | module_i2c_driver(inv_icm42600_driver); |
| @@ -67,6 +67,22 @@ static int inv_icm42600_probe(struct spi_device *spi) · 66 unmodified lines | |||
| 67 | inv_icm42600_spi_bus_setup); | 67 | inv_icm42600_spi_bus_setup); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | /* | ||
| 71 | * device id table is used to identify what device can be | ||
| 72 | * supported by this driver | ||
| 73 | */ | ||
| 74 | static const struct spi_device_id inv_icm42600_id[] = { | ||
| 75 | { "icm42600", INV_CHIP_ICM42600 }, | ||
| 76 | { "icm42602", INV_CHIP_ICM42602 }, | ||
| 77 | { "icm42605", INV_CHIP_ICM42605 }, | ||
| 78 | { "icm42686", INV_CHIP_ICM42686 }, | ||
| 79 | { "icm42622", INV_CHIP_ICM42622 }, | ||
| 80 | { "icm42688", INV_CHIP_ICM42688 }, | ||
| 81 | { "icm42631", INV_CHIP_ICM42631 }, | ||
| 82 | { } | ||
| 83 | }; | ||
| 84 | MODULE_DEVICE_TABLE(spi, inv_icm42600_id); | ||
| 85 | |||
| 70 | static const struct of_device_id inv_icm42600_of_matches[] = { | 86 | static const struct of_device_id inv_icm42600_of_matches[] = { |
| 71 | { | 87 | { |
| 72 | .compatible = "invensense,icm42600", | 88 | .compatible = "invensense,icm42600", |
| @@ -100,6 +116,7 @@ static struct spi_driver inv_icm42600_driver = { · 27 unmodified lines | |||
| 100 | .of_match_table = inv_icm42600_of_matches, | 116 | .of_match_table = inv_icm42600_of_matches, |
| 101 | .pm = pm_ptr(&inv_icm42600_pm_ops), | 117 | .pm = pm_ptr(&inv_icm42600_pm_ops), |
| 102 | }, | 118 | }, |
| 119 | .id_table = inv_icm42600_id, | ||
| 103 | .probe = inv_icm42600_probe, | 120 | .probe = inv_icm42600_probe, |
| 104 | }; | 121 | }; |
| 105 | module_spi_driver(inv_icm42600_driver); | 122 | module_spi_driver(inv_icm42600_driver); |
| @@ -10,6 +10,8 @@ · 9 unmodified lines | |||
| 10 | #include <linux/i2c.h> | 10 | #include <linux/i2c.h> |
| 11 | #include <linux/dmi.h> | 11 | #include <linux/dmi.h> |
| 12 | #include <linux/acpi.h> | 12 | #include <linux/acpi.h> |
| 13 | #include <linux/wordpart.h> | ||
| 14 | |||
| 13 | #include "inv_mpu_iio.h" | 15 | #include "inv_mpu_iio.h" |
| 14 | 16 | ||
| 15 | enum inv_mpu_product_name { | 17 | enum inv_mpu_product_name { |
| @@ -102,14 +104,11 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client, · 86 unmodified lines | |||
| 102 | unsigned short *secondary_addr) | 104 | unsigned short *secondary_addr) |
| 103 | { | 105 | { |
| 104 | struct acpi_device *adev = ACPI_COMPANION(&client->dev); | 106 | struct acpi_device *adev = ACPI_COMPANION(&client->dev); |
| 105 | const struct acpi_device_id *id; | ||
| 106 | u32 i2c_addr = 0; | 107 | u32 i2c_addr = 0; |
| 107 | LIST_HEAD(resources); | 108 | LIST_HEAD(resources); |
| 108 | int ret; | 109 | int ret; |
| 109 | 110 | ||
| 110 | id = acpi_match_device(client->dev.driver->acpi_match_table, | 111 | if (!is_acpi_device_node(dev_fwnode(&client->dev))) |
| 111 | &client->dev); | ||
| 112 | if (!id) | ||
| 113 | return -ENODEV; | 112 | return -ENODEV; |
| 114 | 113 | ||
| 115 | ret = acpi_dev_get_resources(adev, &resources, | 114 | ret = acpi_dev_get_resources(adev, &resources, |
| @@ -118,8 +117,8 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client, · 2 unmodified lines | |||
| 118 | return ret; | 117 | return ret; |
| 119 | 118 | ||
| 120 | acpi_dev_free_resource_list(&resources); | 119 | acpi_dev_free_resource_list(&resources); |
| 121 | *primary_addr = i2c_addr & 0x0000ffff; | 120 | *primary_addr = lower_16_bits(i2c_addr); |
| 122 | *secondary_addr = (i2c_addr & 0xffff0000) >> 16; | 121 | *secondary_addr = upper_16_bits(i2c_addr); |
| 123 | 122 | ||
| 124 | return 0; | 123 | return 0; |
| 125 | } | 124 | } |
| @@ -286,6 +286,24 @@ static const struct inv_mpu6050_hw hw_info[] = { · 285 unmodified lines | |||
| 286 | .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, | 286 | .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, |
| 287 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, | 287 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, |
| 288 | }, | 288 | }, |
| 289 | { | ||
| 290 | .whoami = INV_IAM20680HP_WHOAMI_VALUE, | ||
| 291 | .name = "IAM20680HP", | ||
| 292 | .reg = ®_set_6500, | ||
| 293 | .config = &chip_config_6500, | ||
| 294 | .fifo_size = 4 * 1024, | ||
| 295 | .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, | ||
| 296 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, | ||
| 297 | }, | ||
| 298 | { | ||
| 299 | .whoami = INV_IAM20680HT_WHOAMI_VALUE, | ||
| 300 | .name = "IAM20680HT", | ||
| 301 | .reg = ®_set_6500, | ||
| 302 | .config = &chip_config_6500, | ||
| 303 | .fifo_size = 4 * 1024, | ||
| 304 | .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, | ||
| 305 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, | ||
| 306 | }, | ||
| 289 | }; | 307 | }; |
| 290 | 308 | ||
| 291 | static int inv_mpu6050_pwr_mgmt_1_write(struct inv_mpu6050_state *st, bool sleep, | 309 | static int inv_mpu6050_pwr_mgmt_1_write(struct inv_mpu6050_state *st, bool sleep, |
| @@ -510,6 +528,8 @@ static int inv_mpu6050_set_accel_lpf_regs(struct inv_mpu6050_state *st, · 218 unmodified lines | |||
| 510 | return 0; | 528 | return 0; |
| 511 | case INV_ICM20689: | 529 | case INV_ICM20689: |
| 512 | case INV_ICM20690: | 530 | case INV_ICM20690: |
| 531 | case INV_IAM20680HT: | ||
| 532 | case INV_IAM20680HP: | ||
| 513 | /* set FIFO size to maximum value */ | 533 | /* set FIFO size to maximum value */ |
| 514 | val |= INV_ICM20689_BITS_FIFO_SIZE_MAX; | 534 | val |= INV_ICM20689_BITS_FIFO_SIZE_MAX; |
| 515 | break; | 535 | break; |
| @@ -1153,24 +1173,21 @@ static int inv_mpu6050_write_event_config(struct iio_dev *indio_dev, · 637 unmodified lines | |||
| 1153 | const struct iio_chan_spec *chan, | 1173 | const struct iio_chan_spec *chan, |
| 1154 | enum iio_event_type type, | 1174 | enum iio_event_type type, |
| 1155 | enum iio_event_direction dir, | 1175 | enum iio_event_direction dir, |
| 1156 | int state) | 1176 | bool state) |
| 1157 | { | 1177 | { |
| 1158 | struct inv_mpu6050_state *st = iio_priv(indio_dev); | 1178 | struct inv_mpu6050_state *st = iio_priv(indio_dev); |
| 1159 | int enable; | ||
| 1160 | 1179 | ||
| 1161 | /* support only WoM (accel roc rising) event */ | 1180 | /* support only WoM (accel roc rising) event */ |
| 1162 | if (chan->type != IIO_ACCEL || type != IIO_EV_TYPE_ROC || | 1181 | if (chan->type != IIO_ACCEL || type != IIO_EV_TYPE_ROC || |
| 1163 | dir != IIO_EV_DIR_RISING) | 1182 | dir != IIO_EV_DIR_RISING) |
| 1164 | return -EINVAL; | 1183 | return -EINVAL; |
| 1165 | 1184 | ||
| 1166 | enable = !!state; | ||
| 1167 | |||
| 1168 | guard(mutex)(&st->lock); | 1185 | guard(mutex)(&st->lock); |
| 1169 | 1186 | ||
| 1170 | if (st->chip_config.wom_en == enable) | 1187 | if (st->chip_config.wom_en == state) |
| 1171 | return 0; | 1188 | return 0; |
| 1172 | 1189 | ||
| 1173 | return inv_mpu6050_enable_wom(st, enable); | 1190 | return inv_mpu6050_enable_wom(st, state); |
| 1174 | } | 1191 | } |
| 1175 | 1192 | ||
| 1176 | static int inv_mpu6050_read_event_value(struct iio_dev *indio_dev, | 1193 | static int inv_mpu6050_read_event_value(struct iio_dev *indio_dev, |
| @@ -1859,7 +1876,6 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, · 682 unmodified lines | |||
| 1859 | struct inv_mpu6050_platform_data *pdata; | 1876 | struct inv_mpu6050_platform_data *pdata; |
| 1860 | struct device *dev = regmap_get_device(regmap); | 1877 | struct device *dev = regmap_get_device(regmap); |
| 1861 | int result; | 1878 | int result; |
| 1862 | struct irq_data *desc; | ||
| 1863 | int irq_type; | 1879 | int irq_type; |
| 1864 | 1880 | ||
| 1865 | indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); | 1881 | indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); |
| @@ -1893,13 +1909,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, · 27 unmodified lines | |||
| 1893 | } | 1909 | } |
| 1894 | 1910 | ||
| 1895 | if (irq > 0) { | 1911 | if (irq > 0) { |
| 1896 | desc = irq_get_irq_data(irq); | 1912 | irq_type = irq_get_trigger_type(irq); |
| 1897 | if (!desc) { | ||
| 1898 | dev_err(dev, "Could not find IRQ %d\n", irq); | ||
| 1899 | return -EINVAL; | ||
| 1900 | } | ||
| 1901 | |||
| 1902 | irq_type = irqd_get_trigger_type(desc); | ||
| 1903 | if (!irq_type) | 1913 | if (!irq_type) |
| 1904 | irq_type = IRQF_TRIGGER_RISING; | 1914 | irq_type = IRQF_TRIGGER_RISING; |
| 1905 | } else { | 1915 | } else { |
| @@ -188,6 +188,8 @@ static const struct i2c_device_id inv_mpu_id[] = { · 187 unmodified lines | |||
| 188 | {"icm20602", INV_ICM20602}, | 188 | {"icm20602", INV_ICM20602}, |
| 189 | {"icm20690", INV_ICM20690}, | 189 | {"icm20690", INV_ICM20690}, |
| 190 | {"iam20680", INV_IAM20680}, | 190 | {"iam20680", INV_IAM20680}, |
| 191 | {"iam20680hp", INV_IAM20680HP}, | ||
| 192 | {"iam20680ht", INV_IAM20680HT}, | ||
| 191 | {} | 193 | {} |
| 192 | }; | 194 | }; |
| 193 | 195 | ||
| @@ -254,6 +256,14 @@ static const struct of_device_id inv_of_match[] = { · 60 unmodified lines | |||
| 254 | .compatible = "invensense,iam20680", | 256 | .compatible = "invensense,iam20680", |
| 255 | .data = (void *)INV_IAM20680 | 257 | .data = (void *)INV_IAM20680 |
| 256 | }, | 258 | }, |
| 259 | { | ||
| 260 | .compatible = "invensense,iam20680hp", | ||
| 261 | .data = (void *)INV_IAM20680HP | ||
| 262 | }, | ||
| 263 | { | ||
| 264 | .compatible = "invensense,iam20680ht", | ||
| 265 | .data = (void *)INV_IAM20680HT | ||
| 266 | }, | ||
| 257 | { } | 267 | { } |
| 258 | }; | 268 | }; |
| 259 | MODULE_DEVICE_TABLE(of, inv_of_match); | 269 | MODULE_DEVICE_TABLE(of, inv_of_match); |
| @@ -85,6 +85,8 @@ enum inv_devices { · 84 unmodified lines | |||
| 85 | INV_ICM20602, | 85 | INV_ICM20602, |
| 86 | INV_ICM20690, | 86 | INV_ICM20690, |
| 87 | INV_IAM20680, | 87 | INV_IAM20680, |
| 88 | INV_IAM20680HP, | ||
| 89 | INV_IAM20680HT, | ||
| 88 | INV_NUM_PARTS | 90 | INV_NUM_PARTS |
| 89 | }; | 91 | }; |
| 90 | 92 | ||
| @@ -424,6 +426,8 @@ struct inv_mpu6050_state { · 333 unmodified lines | |||
| 424 | #define INV_ICM20602_WHOAMI_VALUE 0x12 | 426 | #define INV_ICM20602_WHOAMI_VALUE 0x12 |
| 425 | #define INV_ICM20690_WHOAMI_VALUE 0x20 | 427 | #define INV_ICM20690_WHOAMI_VALUE 0x20 |
| 426 | #define INV_IAM20680_WHOAMI_VALUE 0xA9 | 428 | #define INV_IAM20680_WHOAMI_VALUE 0xA9 |
| 429 | #define INV_IAM20680HP_WHOAMI_VALUE 0xF8 | ||
| 430 | #define INV_IAM20680HT_WHOAMI_VALUE 0xFA | ||
| 427 | 431 | ||
| 428 | /* scan element definition for generic MPU6xxx devices */ | 432 | /* scan element definition for generic MPU6xxx devices */ |
| 429 | enum inv_mpu6050_scan { | 433 | enum inv_mpu6050_scan { |
| @@ -80,6 +80,8 @@ static const struct spi_device_id inv_mpu_id[] = { · 79 unmodified lines | |||
| 80 | {"icm20602", INV_ICM20602}, | 80 | {"icm20602", INV_ICM20602}, |
| 81 | {"icm20690", INV_ICM20690}, | 81 | {"icm20690", INV_ICM20690}, |
| 82 | {"iam20680", INV_IAM20680}, | 82 | {"iam20680", INV_IAM20680}, |
| 83 | {"iam20680hp", INV_IAM20680HP}, | ||
| 84 | {"iam20680ht", INV_IAM20680HT}, | ||
| 83 | {} | 85 | {} |
| 84 | }; | 86 | }; |
| 85 | 87 | ||
| @@ -142,6 +144,14 @@ static const struct of_device_id inv_of_match[] = { · 56 unmodified lines | |||
| 142 | .compatible = "invensense,iam20680", | 144 | .compatible = "invensense,iam20680", |
| 143 | .data = (void *)INV_IAM20680 | 145 | .data = (void *)INV_IAM20680 |
| 144 | }, | 146 | }, |
| 147 | { | ||
| 148 | .compatible = "invensense,iam20680hp", | ||
| 149 | .data = (void *)INV_IAM20680HP | ||
| 150 | }, | ||
| 151 | { | ||
| 152 | .compatible = "invensense,iam20680ht", | ||
| 153 | .data = (void *)INV_IAM20680HT | ||
| 154 | }, | ||
| 145 | { } | 155 | { } |
| 146 | }; | 156 | }; |
| 147 | MODULE_DEVICE_TABLE(of, inv_of_match); | 157 | MODULE_DEVICE_TABLE(of, inv_of_match); |
| @@ -112,7 +112,6 @@ int inv_mpu6050_prepare_fifo(struct inv_mpu6050_state *st, bool enable) · 111 unmodified lines | |||
| 112 | if (enable) { | 112 | if (enable) { |
| 113 | /* reset timestamping */ | 113 | /* reset timestamping */ |
| 114 | inv_sensors_timestamp_reset(&st->timestamp); | 114 | inv_sensors_timestamp_reset(&st->timestamp); |
| 115 | inv_sensors_timestamp_apply_odr(&st->timestamp, 0, 0, 0); | ||
| 116 | /* reset FIFO */ | 115 | /* reset FIFO */ |
| 117 | d = st->chip_config.user_ctrl | INV_MPU6050_BIT_FIFO_RST; | 116 | d = st->chip_config.user_ctrl | INV_MPU6050_BIT_FIFO_RST; |
| 118 | ret = regmap_write(st->map, st->reg->user_ctrl, d); | 117 | ret = regmap_write(st->map, st->reg->user_ctrl, d); |
| @@ -7,12 +7,13 @@ · 6 unmodified lines | |||
| 7 | * IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F). | 7 | * IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F). |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/i2c.h> | 10 | #include <linux/i2c.h> |
| 12 | #include <linux/acpi.h> | ||
| 13 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
| 12 | #include <linux/mod_devicetable.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/pm.h> | 14 | #include <linux/pm.h> |
| 15 | #include <linux/pm_runtime.h> | 15 | #include <linux/pm_runtime.h> |
| 16 | |||
| 16 | #include <linux/iio/iio.h> | 17 | #include <linux/iio/iio.h> |
| 17 | #include <linux/iio/sysfs.h> | 18 | #include <linux/iio/sysfs.h> |
| 18 | #include <linux/iio/events.h> | 19 | #include <linux/iio/events.h> |
| @@ -941,7 +942,7 @@ static int kmx61_write_event_config(struct iio_dev *indio_dev, · 922 unmodified lines | |||
| 941 | const struct iio_chan_spec *chan, | 942 | const struct iio_chan_spec *chan, |
| 942 | enum iio_event_type type, | 943 | enum iio_event_type type, |
| 943 | enum iio_event_direction dir, | 944 | enum iio_event_direction dir, |
| 944 | int state) | 945 | bool state) |
| 945 | { | 946 | { |
| 946 | struct kmx61_data *data = kmx61_get_data(indio_dev); | 947 | struct kmx61_data *data = kmx61_get_data(indio_dev); |
| 947 | int ret = 0; | 948 | int ret = 0; |
| @@ -1217,16 +1218,6 @@ err: · 269 unmodified lines | |||
| 1217 | return IRQ_HANDLED; | 1218 | return IRQ_HANDLED; |
| 1218 | } | 1219 | } |
| 1219 | 1220 | ||
| 1220 | static const char *kmx61_match_acpi_device(struct device *dev) | ||
| 1221 | { | ||
| 1222 | const struct acpi_device_id *id; | ||
| 1223 | |||
| 1224 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
| 1225 | if (!id) | ||
| 1226 | return NULL; | ||
| 1227 | return dev_name(dev); | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data, | 1221 | static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data, |
| 1231 | const struct iio_info *info, | 1222 | const struct iio_info *info, |
| 1232 | const struct iio_chan_spec *chan, | 1223 | const struct iio_chan_spec *chan, |
| @@ -1293,8 +1284,6 @@ static int kmx61_probe(struct i2c_client *client) · 60 unmodified lines | |||
| 1293 | 1284 | ||
| 1294 | if (id) | 1285 | if (id) |
| 1295 | name = id->name; | 1286 | name = id->name; |
| 1296 | else if (ACPI_HANDLE(&client->dev)) | ||
| 1297 | name = kmx61_match_acpi_device(&client->dev); | ||
| 1298 | else | 1287 | else |
| 1299 | return -ENODEV; | 1288 | return -ENODEV; |
| 1300 | 1289 | ||
| @@ -1496,13 +1485,6 @@ static const struct dev_pm_ops kmx61_pm_ops = { · 195 unmodified lines | |||
| 1496 | RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL) | 1485 | RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL) |
| 1497 | }; | 1486 | }; |
| 1498 | 1487 | ||
| 1499 | static const struct acpi_device_id kmx61_acpi_match[] = { | ||
| 1500 | {"KMX61021", 0}, | ||
| 1501 | {} | ||
| 1502 | }; | ||
| 1503 | |||
| 1504 | MODULE_DEVICE_TABLE(acpi, kmx61_acpi_match); | ||
| 1505 | |||
| 1506 | static const struct i2c_device_id kmx61_id[] = { | 1488 | static const struct i2c_device_id kmx61_id[] = { |
| 1507 | { "kmx611021" }, | 1489 | { "kmx611021" }, |
| 1508 | {} | 1490 | {} |
| @@ -1513,7 +1495,6 @@ MODULE_DEVICE_TABLE(i2c, kmx61_id); · 4 unmodified lines | |||
| 1513 | static struct i2c_driver kmx61_driver = { | 1495 | static struct i2c_driver kmx61_driver = { |
| 1514 | .driver = { | 1496 | .driver = { |
| 1515 | .name = KMX61_DRV_NAME, | 1497 | .name = KMX61_DRV_NAME, |
| 1516 | .acpi_match_table = kmx61_acpi_match, | ||
| 1517 | .pm = pm_ptr(&kmx61_pm_ops), | 1498 | .pm = pm_ptr(&kmx61_pm_ops), |
| 1518 | }, | 1499 | }, |
| 1519 | .probe = kmx61_probe, | 1500 | .probe = kmx61_probe, |
| @@ -0,0 +1,621 @@ | |||
| 1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2024 Robert Bosch GmbH. | ||
| 4 | */ | ||
| 5 | #include <linux/bitfield.h> | ||
| 6 | #include <linux/bits.h> | ||
| 7 | #include <linux/delay.h> | ||
| 8 | #include <linux/device.h> | ||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/regmap.h> | ||
| 11 | #include <linux/spi/spi.h> | ||
| 12 | #include <linux/unaligned.h> | ||
| 13 | #include <linux/units.h> | ||
| 14 | |||
| 15 | #include <linux/iio/buffer.h> | ||
| 16 | #include <linux/iio/iio.h> | ||
| 17 | #include <linux/iio/trigger.h> | ||
| 18 | #include <linux/iio/trigger_consumer.h> | ||
| 19 | #include <linux/iio/triggered_buffer.h> | ||
| 20 | |||
| 21 | #define SMI240_CHIP_ID 0x0024 | ||
| 22 | |||
| 23 | #define SMI240_SOFT_CONFIG_EOC_MASK BIT(0) | ||
| 24 | #define SMI240_SOFT_CONFIG_GYR_BW_MASK BIT(1) | ||
| 25 | #define SMI240_SOFT_CONFIG_ACC_BW_MASK BIT(2) | ||
| 26 | #define SMI240_SOFT_CONFIG_BITE_AUTO_MASK BIT(3) | ||
| 27 | #define SMI240_SOFT_CONFIG_BITE_REP_MASK GENMASK(6, 4) | ||
| 28 | |||
| 29 | #define SMI240_CHIP_ID_REG 0x00 | ||
| 30 | #define SMI240_SOFT_CONFIG_REG 0x0A | ||
| 31 | #define SMI240_TEMP_CUR_REG 0x10 | ||
| 32 | #define SMI240_ACCEL_X_CUR_REG 0x11 | ||
| 33 | #define SMI240_GYRO_X_CUR_REG 0x14 | ||
| 34 | #define SMI240_DATA_CAP_FIRST_REG 0x17 | ||
| 35 | #define SMI240_CMD_REG 0x2F | ||
| 36 | |||
| 37 | #define SMI240_SOFT_RESET_CMD 0xB6 | ||
| 38 | |||
| 39 | #define SMI240_BITE_SEQUENCE_DELAY_US 140000 | ||
| 40 | #define SMI240_FILTER_FLUSH_DELAY_US 60000 | ||
| 41 | #define SMI240_DIGITAL_STARTUP_DELAY_US 120000 | ||
| 42 | #define SMI240_MECH_STARTUP_DELAY_US 100000 | ||
| 43 | |||
| 44 | #define SMI240_BUS_ID 0x00 | ||
| 45 | #define SMI240_CRC_INIT 0x05 | ||
| 46 | #define SMI240_CRC_POLY 0x0B | ||
| 47 | #define SMI240_CRC_MASK GENMASK(2, 0) | ||
| 48 | |||
| 49 | #define SMI240_READ_SD_BIT_MASK BIT(31) | ||
| 50 | #define SMI240_READ_DATA_MASK GENMASK(19, 4) | ||
| 51 | #define SMI240_READ_CS_BIT_MASK BIT(3) | ||
| 52 | |||
| 53 | #define SMI240_WRITE_BUS_ID_MASK GENMASK(31, 30) | ||
| 54 | #define SMI240_WRITE_ADDR_MASK GENMASK(29, 22) | ||
| 55 | #define SMI240_WRITE_BIT_MASK BIT(21) | ||
| 56 | #define SMI240_WRITE_CAP_BIT_MASK BIT(20) | ||
| 57 | #define SMI240_WRITE_DATA_MASK GENMASK(18, 3) | ||
| 58 | |||
| 59 | /* T°C = (temp / 256) + 25 */ | ||
| 60 | #define SMI240_TEMP_OFFSET 6400 /* 25 * 256 */ | ||
| 61 | #define SMI240_TEMP_SCALE 3906250 /* (1 / 256) * 1e9 */ | ||
| 62 | |||
| 63 | #define SMI240_ACCEL_SCALE 500 /* (1 / 2000) * 1e6 */ | ||
| 64 | #define SMI240_GYRO_SCALE 10000 /* (1 / 100) * 1e6 */ | ||
| 65 | |||
| 66 | #define SMI240_LOW_BANDWIDTH_HZ 50 | ||
| 67 | #define SMI240_HIGH_BANDWIDTH_HZ 400 | ||
| 68 | |||
| 69 | #define SMI240_BUILT_IN_SELF_TEST_COUNT 3 | ||
| 70 | |||
| 71 | #define SMI240_DATA_CHANNEL(_type, _axis, _index) { \ | ||
| 72 | .type = _type, \ | ||
| 73 | .modified = 1, \ | ||
| 74 | .channel2 = IIO_MOD_##_axis, \ | ||
| 75 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
| 76 | .info_mask_shared_by_type = \ | ||
| 77 | BIT(IIO_CHAN_INFO_SCALE) | \ | ||
| 78 | BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ | ||
| 79 | .info_mask_shared_by_type_available = \ | ||
| 80 | BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ | ||
| 81 | .scan_index = _index, \ | ||
| 82 | .scan_type = { \ | ||
| 83 | .sign = 's', \ | ||
| 84 | .realbits = 16, \ | ||
| 85 | .storagebits = 16, \ | ||
| 86 | .endianness = IIO_CPU, \ | ||
| 87 | }, \ | ||
| 88 | } | ||
| 89 | |||
| 90 | #define SMI240_TEMP_CHANNEL(_index) { \ | ||
| 91 | .type = IIO_TEMP, \ | ||
| 92 | .modified = 1, \ | ||
| 93 | .channel2 = IIO_MOD_TEMP_OBJECT, \ | ||
| 94 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | ||
| 95 | BIT(IIO_CHAN_INFO_OFFSET) | \ | ||
| 96 | BIT(IIO_CHAN_INFO_SCALE), \ | ||
| 97 | .scan_index = _index, \ | ||
| 98 | .scan_type = { \ | ||
| 99 | .sign = 's', \ | ||
| 100 | .realbits = 16, \ | ||
| 101 | .storagebits = 16, \ | ||
| 102 | .endianness = IIO_CPU, \ | ||
| 103 | }, \ | ||
| 104 | } | ||
| 105 | |||
| 106 | enum capture_mode { SMI240_CAPTURE_OFF = 0, SMI240_CAPTURE_ON = 1 }; | ||
| 107 | |||
| 108 | struct smi240_data { | ||
| 109 | struct regmap *regmap; | ||
| 110 | u16 accel_filter_freq; | ||
| 111 | u16 anglvel_filter_freq; | ||
| 112 | u8 built_in_self_test_count; | ||
| 113 | enum capture_mode capture; | ||
| 114 | /* | ||
| 115 | * Ensure natural alignment for timestamp if present. | ||
| 116 | * Channel size: 2 bytes. | ||
| 117 | * Max length needed: 2 * 3 channels + temp channel + 2 bytes padding + 8 byte ts. | ||
| 118 | * If fewer channels are enabled, less space may be needed, as | ||
| 119 | * long as the timestamp is still aligned to 8 bytes. | ||
| 120 | */ | ||
| 121 | s16 buf[12] __aligned(8); | ||
| 122 | |||
| 123 | __be32 spi_buf __aligned(IIO_DMA_MINALIGN); | ||
| 124 | }; | ||
| 125 | |||
| 126 | enum { | ||
| 127 | SMI240_TEMP_OBJECT, | ||
| 128 | SMI240_SCAN_ACCEL_X, | ||
| 129 | SMI240_SCAN_ACCEL_Y, | ||
| 130 | SMI240_SCAN_ACCEL_Z, | ||
| 131 | SMI240_SCAN_GYRO_X, | ||
| 132 | SMI240_SCAN_GYRO_Y, | ||
| 133 | SMI240_SCAN_GYRO_Z, | ||
| 134 | SMI240_SCAN_TIMESTAMP, | ||
| 135 | }; | ||
| 136 | |||
| 137 | static const struct iio_chan_spec smi240_channels[] = { | ||
| 138 | SMI240_TEMP_CHANNEL(SMI240_TEMP_OBJECT), | ||
| 139 | SMI240_DATA_CHANNEL(IIO_ACCEL, X, SMI240_SCAN_ACCEL_X), | ||
| 140 | SMI240_DATA_CHANNEL(IIO_ACCEL, Y, SMI240_SCAN_ACCEL_Y), | ||
| 141 | SMI240_DATA_CHANNEL(IIO_ACCEL, Z, SMI240_SCAN_ACCEL_Z), | ||
| 142 | SMI240_DATA_CHANNEL(IIO_ANGL_VEL, X, SMI240_SCAN_GYRO_X), | ||
| 143 | SMI240_DATA_CHANNEL(IIO_ANGL_VEL, Y, SMI240_SCAN_GYRO_Y), | ||
| 144 | SMI240_DATA_CHANNEL(IIO_ANGL_VEL, Z, SMI240_SCAN_GYRO_Z), | ||
| 145 | IIO_CHAN_SOFT_TIMESTAMP(SMI240_SCAN_TIMESTAMP), | ||
| 146 | }; | ||
| 147 | |||
| 148 | static const int smi240_low_pass_freqs[] = { SMI240_LOW_BANDWIDTH_HZ, | ||
| 149 | SMI240_HIGH_BANDWIDTH_HZ }; | ||
| 150 | |||
| 151 | static u8 smi240_crc3(u32 data, u8 init, u8 poly) | ||
| 152 | { | ||
| 153 | u8 crc = init; | ||
| 154 | u8 do_xor; | ||
| 155 | s8 i = 31; | ||
| 156 | |||
| 157 | do { | ||
| 158 | do_xor = crc & 0x04; | ||
| 159 | crc <<= 1; | ||
| 160 | crc |= 0x01 & (data >> i); | ||
| 161 | if (do_xor) | ||
| 162 | crc ^= poly; | ||
| 163 | |||
| 164 | crc &= SMI240_CRC_MASK; | ||
| 165 | } while (--i >= 0); | ||
| 166 | |||
| 167 | return crc; | ||
| 168 | } | ||
| 169 | |||
| 170 | static bool smi240_sensor_data_is_valid(u32 data) | ||
| 171 | { | ||
| 172 | if (smi240_crc3(data, SMI240_CRC_INIT, SMI240_CRC_POLY) != 0) | ||
| 173 | return false; | ||
| 174 | |||
| 175 | if (FIELD_GET(SMI240_READ_SD_BIT_MASK, data) & | ||
| 176 | FIELD_GET(SMI240_READ_CS_BIT_MASK, data)) | ||
| 177 | return false; | ||
| 178 | |||
| 179 | return true; | ||
| 180 | } | ||
| 181 | |||
| 182 | static int smi240_regmap_spi_read(void *context, const void *reg_buf, | ||
| 183 | size_t reg_size, void *val_buf, | ||
| 184 | size_t val_size) | ||
| 185 | { | ||
| 186 | int ret; | ||
| 187 | u32 request, response; | ||
| 188 | u16 *val = val_buf; | ||
| 189 | struct spi_device *spi = context; | ||
| 190 | struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev); | ||
| 191 | struct smi240_data *iio_priv_data = iio_priv(indio_dev); | ||
| 192 | |||
| 193 | if (reg_size != 1 || val_size != 2) | ||
| 194 | return -EINVAL; | ||
| 195 | |||
| 196 | request = FIELD_PREP(SMI240_WRITE_BUS_ID_MASK, SMI240_BUS_ID); | ||
| 197 | request |= FIELD_PREP(SMI240_WRITE_CAP_BIT_MASK, iio_priv_data->capture); | ||
| 198 | request |= FIELD_PREP(SMI240_WRITE_ADDR_MASK, *(u8 *)reg_buf); | ||
| 199 | request |= smi240_crc3(request, SMI240_CRC_INIT, SMI240_CRC_POLY); | ||
| 200 | |||
| 201 | iio_priv_data->spi_buf = cpu_to_be32(request); | ||
| 202 | |||
| 203 | /* | ||
| 204 | * SMI240 module consists of a 32Bit Out Of Frame (OOF) | ||
| 205 | * SPI protocol, where the slave interface responds to | ||
| 206 | * the Master request in the next frame. | ||
| 207 | * CS signal must toggle (> 700 ns) between the frames. | ||
| 208 | */ | ||
| 209 | ret = spi_write(spi, &iio_priv_data->spi_buf, sizeof(request)); | ||
| 210 | if (ret) | ||
| 211 | return ret; | ||
| 212 | |||
| 213 | ret = spi_read(spi, &iio_priv_data->spi_buf, sizeof(response)); | ||
| 214 | if (ret) | ||
| 215 | return ret; | ||
| 216 | |||
| 217 | response = be32_to_cpu(iio_priv_data->spi_buf); | ||
| 218 | |||
| 219 | if (!smi240_sensor_data_is_valid(response)) | ||
| 220 | return -EIO; | ||
| 221 | |||
| 222 | *val = FIELD_GET(SMI240_READ_DATA_MASK, response); | ||
| 223 | |||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | static int smi240_regmap_spi_write(void *context, const void *data, | ||
| 228 | size_t count) | ||
| 229 | { | ||
| 230 | u8 reg_addr; | ||
| 231 | u16 reg_data; | ||
| 232 | u32 request; | ||
| 233 | const u8 *data_ptr = data; | ||
| 234 | struct spi_device *spi = context; | ||
| 235 | struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev); | ||
| 236 | struct smi240_data *iio_priv_data = iio_priv(indio_dev); | ||
| 237 | |||
| 238 | if (count < 2) | ||
| 239 | return -EINVAL; | ||
| 240 | |||
| 241 | reg_addr = data_ptr[0]; | ||
| 242 | memcpy(®_data, &data_ptr[1], sizeof(reg_data)); | ||
| 243 | |||
| 244 | request = FIELD_PREP(SMI240_WRITE_BUS_ID_MASK, SMI240_BUS_ID); | ||
| 245 | request |= FIELD_PREP(SMI240_WRITE_BIT_MASK, 1); | ||
| 246 | request |= FIELD_PREP(SMI240_WRITE_ADDR_MASK, reg_addr); | ||
| 247 | request |= FIELD_PREP(SMI240_WRITE_DATA_MASK, reg_data); | ||
| 248 | request |= smi240_crc3(request, SMI240_CRC_INIT, SMI240_CRC_POLY); | ||
| 249 | |||
| 250 | iio_priv_data->spi_buf = cpu_to_be32(request); | ||
| 251 | |||
| 252 | return spi_write(spi, &iio_priv_data->spi_buf, sizeof(request)); | ||
| 253 | } | ||
| 254 | |||
| 255 | static const struct regmap_bus smi240_regmap_bus = { | ||
| 256 | .read = smi240_regmap_spi_read, | ||
| 257 | .write = smi240_regmap_spi_write, | ||
| 258 | }; | ||
| 259 | |||
| 260 | static const struct regmap_config smi240_regmap_config = { | ||
| 261 | .reg_bits = 8, | ||
| 262 | .val_bits = 16, | ||
| 263 | .val_format_endian = REGMAP_ENDIAN_NATIVE, | ||
| 264 | }; | ||
| 265 | |||
| 266 | static int smi240_soft_reset(struct smi240_data *data) | ||
| 267 | { | ||
| 268 | int ret; | ||
| 269 | |||
| 270 | ret = regmap_write(data->regmap, SMI240_CMD_REG, SMI240_SOFT_RESET_CMD); | ||
| 271 | if (ret) | ||
| 272 | return ret; | ||
| 273 | fsleep(SMI240_DIGITAL_STARTUP_DELAY_US); | ||
| 274 | |||
| 275 | return 0; | ||
| 276 | } | ||
| 277 | |||
| 278 | static int smi240_soft_config(struct smi240_data *data) | ||
| 279 | { | ||
| 280 | int ret; | ||
| 281 | u8 acc_bw, gyr_bw; | ||
| 282 | u16 request; | ||
| 283 | |||
| 284 | switch (data->accel_filter_freq) { | ||
| 285 | case SMI240_LOW_BANDWIDTH_HZ: | ||
| 286 | acc_bw = 0x1; | ||
| 287 | break; | ||
| 288 | case SMI240_HIGH_BANDWIDTH_HZ: | ||
| 289 | acc_bw = 0x0; | ||
| 290 | break; | ||
| 291 | default: | ||
| 292 | return -EINVAL; | ||
| 293 | } | ||
| 294 | |||
| 295 | switch (data->anglvel_filter_freq) { | ||
| 296 | case SMI240_LOW_BANDWIDTH_HZ: | ||
| 297 | gyr_bw = 0x1; | ||
| 298 | break; | ||
| 299 | case SMI240_HIGH_BANDWIDTH_HZ: | ||
| 300 | gyr_bw = 0x0; | ||
| 301 | break; | ||
| 302 | default: | ||
| 303 | return -EINVAL; | ||
| 304 | } | ||
| 305 | |||
| 306 | request = FIELD_PREP(SMI240_SOFT_CONFIG_EOC_MASK, 1); | ||
| 307 | request |= FIELD_PREP(SMI240_SOFT_CONFIG_GYR_BW_MASK, gyr_bw); | ||
| 308 | request |= FIELD_PREP(SMI240_SOFT_CONFIG_ACC_BW_MASK, acc_bw); | ||
| 309 | request |= FIELD_PREP(SMI240_SOFT_CONFIG_BITE_AUTO_MASK, 1); | ||
| 310 | request |= FIELD_PREP(SMI240_SOFT_CONFIG_BITE_REP_MASK, | ||
| 311 | data->built_in_self_test_count - 1); | ||
| 312 | |||
| 313 | ret = regmap_write(data->regmap, SMI240_SOFT_CONFIG_REG, request); | ||
| 314 | if (ret) | ||
| 315 | return ret; | ||
| 316 | |||
| 317 | fsleep(SMI240_MECH_STARTUP_DELAY_US + | ||
| 318 | data->built_in_self_test_count * SMI240_BITE_SEQUENCE_DELAY_US + | ||
| 319 | SMI240_FILTER_FLUSH_DELAY_US); | ||
| 320 | |||
| 321 | return 0; | ||
| 322 | } | ||
| 323 | |||
| 324 | static int smi240_get_low_pass_filter_freq(struct smi240_data *data, | ||
| 325 | int chan_type, int *val) | ||
| 326 | { | ||
| 327 | switch (chan_type) { | ||
| 328 | case IIO_ACCEL: | ||
| 329 | *val = data->accel_filter_freq; | ||
| 330 | return 0; | ||
| 331 | case IIO_ANGL_VEL: | ||
| 332 | *val = data->anglvel_filter_freq; | ||
| 333 | return 0; | ||
| 334 | default: | ||
| 335 | return -EINVAL; | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 339 | static int smi240_get_data(struct smi240_data *data, int chan_type, int axis, | ||
| 340 | int *val) | ||
| 341 | { | ||
| 342 | u8 reg; | ||
| 343 | int ret, sample; | ||
| 344 | |||
| 345 | switch (chan_type) { | ||
| 346 | case IIO_TEMP: | ||
| 347 | reg = SMI240_TEMP_CUR_REG; | ||
| 348 | break; | ||
| 349 | case IIO_ACCEL: | ||
| 350 | reg = SMI240_ACCEL_X_CUR_REG + (axis - IIO_MOD_X); | ||
| 351 | break; | ||
| 352 | case IIO_ANGL_VEL: | ||
| 353 | reg = SMI240_GYRO_X_CUR_REG + (axis - IIO_MOD_X); | ||
| 354 | break; | ||
| 355 | default: | ||
| 356 | return -EINVAL; | ||
| 357 | } | ||
| 358 | |||
| 359 | ret = regmap_read(data->regmap, reg, &sample); | ||
| 360 | if (ret) | ||
| 361 | return ret; | ||
| 362 | |||
| 363 | *val = sign_extend32(sample, 15); | ||
| 364 | |||
| 365 | return 0; | ||
| 366 | } | ||
| 367 | |||
| 368 | static irqreturn_t smi240_trigger_handler(int irq, void *p) | ||
| 369 | { | ||
| 370 | struct iio_poll_func *pf = p; | ||
| 371 | struct iio_dev *indio_dev = pf->indio_dev; | ||
| 372 | struct smi240_data *data = iio_priv(indio_dev); | ||
| 373 | int base = SMI240_DATA_CAP_FIRST_REG, i = 0; | ||
| 374 | int ret, chan, sample; | ||
| 375 | |||
| 376 | data->capture = SMI240_CAPTURE_ON; | ||
| 377 | |||
| 378 | iio_for_each_active_channel(indio_dev, chan) { | ||
| 379 | ret = regmap_read(data->regmap, base + chan, &sample); | ||
| 380 | data->capture = SMI240_CAPTURE_OFF; | ||
| 381 | if (ret) | ||
| 382 | goto out; | ||
| 383 | data->buf[i++] = sample; | ||
| 384 | } | ||
| 385 | |||
| 386 | iio_push_to_buffers_with_timestamp(indio_dev, data->buf, pf->timestamp); | ||
| 387 | |||
| 388 | out: | ||
| 389 | iio_trigger_notify_done(indio_dev->trig); | ||
| 390 | return IRQ_HANDLED; | ||
| 391 | } | ||
| 392 | |||
| 393 | static int smi240_read_avail(struct iio_dev *indio_dev, | ||
| 394 | struct iio_chan_spec const *chan, const int **vals, | ||
| 395 | int *type, int *length, long mask) | ||
| 396 | { | ||
| 397 | switch (mask) { | ||
| 398 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | ||
| 399 | *vals = smi240_low_pass_freqs; | ||
| 400 | *length = ARRAY_SIZE(smi240_low_pass_freqs); | ||
| 401 | *type = IIO_VAL_INT; | ||
| 402 | return IIO_AVAIL_LIST; | ||
| 403 | default: | ||
| 404 | return -EINVAL; | ||
| 405 | } | ||
| 406 | } | ||
| 407 | |||
| 408 | static int smi240_read_raw(struct iio_dev *indio_dev, | ||
| 409 | struct iio_chan_spec const *chan, int *val, | ||
| 410 | int *val2, long mask) | ||
| 411 | { | ||
| 412 | int ret; | ||
| 413 | struct smi240_data *data = iio_priv(indio_dev); | ||
| 414 | |||
| 415 | switch (mask) { | ||
| 416 | case IIO_CHAN_INFO_RAW: | ||
| 417 | ret = iio_device_claim_direct_mode(indio_dev); | ||
| 418 | if (ret) | ||
| 419 | return ret; | ||
| 420 | ret = smi240_get_data(data, chan->type, chan->channel2, val); | ||
| 421 | iio_device_release_direct_mode(indio_dev); | ||
| 422 | if (ret) | ||
| 423 | return ret; | ||
| 424 | return IIO_VAL_INT; | ||
| 425 | |||
| 426 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | ||
| 427 | ret = smi240_get_low_pass_filter_freq(data, chan->type, val); | ||
| 428 | if (ret) | ||
| 429 | return ret; | ||
| 430 | return IIO_VAL_INT; | ||
| 431 | |||
| 432 | case IIO_CHAN_INFO_SCALE: | ||
| 433 | switch (chan->type) { | ||
| 434 | case IIO_TEMP: | ||
| 435 | *val = SMI240_TEMP_SCALE / GIGA; | ||
| 436 | *val2 = SMI240_TEMP_SCALE % GIGA; | ||
| 437 | return IIO_VAL_INT_PLUS_NANO; | ||
| 438 | case IIO_ACCEL: | ||
| 439 | *val = 0; | ||
| 440 | *val2 = SMI240_ACCEL_SCALE; | ||
| 441 | return IIO_VAL_INT_PLUS_MICRO; | ||
| 442 | case IIO_ANGL_VEL: | ||
| 443 | *val = 0; | ||
| 444 | *val2 = SMI240_GYRO_SCALE; | ||
| 445 | return IIO_VAL_INT_PLUS_MICRO; | ||
| 446 | default: | ||
| 447 | return -EINVAL; | ||
| 448 | } | ||
| 449 | |||
| 450 | case IIO_CHAN_INFO_OFFSET: | ||
| 451 | if (chan->type == IIO_TEMP) { | ||
| 452 | *val = SMI240_TEMP_OFFSET; | ||
| 453 | return IIO_VAL_INT; | ||
| 454 | } else { | ||
| 455 | return -EINVAL; | ||
| 456 | } | ||
| 457 | |||
| 458 | default: | ||
| 459 | return -EINVAL; | ||
| 460 | } | ||
| 461 | } | ||
| 462 | |||
| 463 | static int smi240_write_raw(struct iio_dev *indio_dev, | ||
| 464 | struct iio_chan_spec const *chan, int val, int val2, | ||
| 465 | long mask) | ||
| 466 | { | ||
| 467 | int ret, i; | ||
| 468 | struct smi240_data *data = iio_priv(indio_dev); | ||
| 469 | |||
| 470 | switch (mask) { | ||
| 471 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | ||
| 472 | for (i = 0; i < ARRAY_SIZE(smi240_low_pass_freqs); i++) { | ||
| 473 | if (val == smi240_low_pass_freqs[i]) | ||
| 474 | break; | ||
| 475 | } | ||
| 476 | |||
| 477 | if (i == ARRAY_SIZE(smi240_low_pass_freqs)) | ||
| 478 | return -EINVAL; | ||
| 479 | |||
| 480 | switch (chan->type) { | ||
| 481 | case IIO_ACCEL: | ||
| 482 | data->accel_filter_freq = val; | ||
| 483 | break; | ||
| 484 | case IIO_ANGL_VEL: | ||
| 485 | data->anglvel_filter_freq = val; | ||
| 486 | break; | ||
| 487 | default: | ||
| 488 | return -EINVAL; | ||
| 489 | } | ||
| 490 | break; | ||
| 491 | default: | ||
| 492 | return -EINVAL; | ||
| 493 | } | ||
| 494 | |||
| 495 | /* Write access to soft config is locked until hard/soft reset */ | ||
| 496 | ret = smi240_soft_reset(data); | ||
| 497 | if (ret) | ||
| 498 | return ret; | ||
| 499 | |||
| 500 | return smi240_soft_config(data); | ||
| 501 | } | ||
| 502 | |||
| 503 | static int smi240_write_raw_get_fmt(struct iio_dev *indio_dev, | ||
| 504 | struct iio_chan_spec const *chan, long info) | ||
| 505 | { | ||
| 506 | switch (info) { | ||
| 507 | case IIO_CHAN_INFO_SCALE: | ||
| 508 | switch (chan->type) { | ||
| 509 | case IIO_TEMP: | ||
| 510 | return IIO_VAL_INT_PLUS_NANO; | ||
| 511 | default: | ||
| 512 | return IIO_VAL_INT_PLUS_MICRO; | ||
| 513 | } | ||
| 514 | default: | ||
| 515 | return IIO_VAL_INT_PLUS_MICRO; | ||
| 516 | } | ||
| 517 | } | ||
| 518 | |||
| 519 | static int smi240_init(struct smi240_data *data) | ||
| 520 | { | ||
| 521 | int ret; | ||
| 522 | |||
| 523 | data->accel_filter_freq = SMI240_HIGH_BANDWIDTH_HZ; | ||
| 524 | data->anglvel_filter_freq = SMI240_HIGH_BANDWIDTH_HZ; | ||
| 525 | data->built_in_self_test_count = SMI240_BUILT_IN_SELF_TEST_COUNT; | ||
| 526 | |||
| 527 | ret = smi240_soft_reset(data); | ||
| 528 | if (ret) | ||
| 529 | return ret; | ||
| 530 | |||
| 531 | return smi240_soft_config(data); | ||
| 532 | } | ||
| 533 | |||
| 534 | static const struct iio_info smi240_info = { | ||
| 535 | .read_avail = smi240_read_avail, | ||
| 536 | .read_raw = smi240_read_raw, | ||
| 537 | .write_raw = smi240_write_raw, | ||
| 538 | .write_raw_get_fmt = smi240_write_raw_get_fmt, | ||
| 539 | }; | ||
| 540 | |||
| 541 | static int smi240_probe(struct spi_device *spi) | ||
| 542 | { | ||
| 543 | struct device *dev = &spi->dev; | ||
| 544 | struct iio_dev *indio_dev; | ||
| 545 | struct regmap *regmap; | ||
| 546 | struct smi240_data *data; | ||
| 547 | int ret, response; | ||
| 548 | |||
| 549 | indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); | ||
| 550 | if (!indio_dev) | ||
| 551 | return -ENOMEM; | ||
| 552 | |||
| 553 | regmap = devm_regmap_init(dev, &smi240_regmap_bus, dev, | ||
| 554 | &smi240_regmap_config); | ||
| 555 | if (IS_ERR(regmap)) | ||
| 556 | return dev_err_probe(dev, PTR_ERR(regmap), | ||
| 557 | "Failed to initialize SPI Regmap\n"); | ||
| 558 | |||
| 559 | data = iio_priv(indio_dev); | ||
| 560 | dev_set_drvdata(dev, indio_dev); | ||
| 561 | data->regmap = regmap; | ||
| 562 | data->capture = SMI240_CAPTURE_OFF; | ||
| 563 | |||
| 564 | ret = regmap_read(data->regmap, SMI240_CHIP_ID_REG, &response); | ||
| 565 | if (ret) | ||
| 566 | return dev_err_probe(dev, ret, "Read chip id failed\n"); | ||
| 567 | |||
| 568 | if (response != SMI240_CHIP_ID) | ||
| 569 | dev_info(dev, "Unknown chip id: 0x%04x\n", response); | ||
| 570 | |||
| 571 | ret = smi240_init(data); | ||
| 572 | if (ret) | ||
| 573 | return dev_err_probe(dev, ret, | ||
| 574 | "Device initialization failed\n"); | ||
| 575 | |||
| 576 | indio_dev->channels = smi240_channels; | ||
| 577 | indio_dev->num_channels = ARRAY_SIZE(smi240_channels); | ||
| 578 | indio_dev->name = "smi240"; | ||
| 579 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
| 580 | indio_dev->info = &smi240_info; | ||
| 581 | |||
| 582 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, | ||
| 583 | iio_pollfunc_store_time, | ||
| 584 | smi240_trigger_handler, NULL); | ||
| 585 | if (ret) | ||
| 586 | return dev_err_probe(dev, ret, | ||
| 587 | "Setup triggered buffer failed\n"); | ||
| 588 | |||
| 589 | ret = devm_iio_device_register(dev, indio_dev); | ||
| 590 | if (ret) | ||
| 591 | return dev_err_probe(dev, ret, "Register IIO device failed\n"); | ||
| 592 | |||
| 593 | return 0; | ||
| 594 | } | ||
| 595 | |||
| 596 | static const struct spi_device_id smi240_spi_id[] = { | ||
| 597 | { "smi240" }, | ||
| 598 | { } | ||
| 599 | }; | ||
| 600 | MODULE_DEVICE_TABLE(spi, smi240_spi_id); | ||
| 601 | |||
| 602 | static const struct of_device_id smi240_of_match[] = { | ||
| 603 | { .compatible = "bosch,smi240" }, | ||
| 604 | { } | ||
| 605 | }; | ||
| 606 | MODULE_DEVICE_TABLE(of, smi240_of_match); | ||
| 607 | |||
| 608 | static struct spi_driver smi240_spi_driver = { | ||
| 609 | .probe = smi240_probe, | ||
| 610 | .id_table = smi240_spi_id, | ||
| 611 | .driver = { | ||
| 612 | .of_match_table = smi240_of_match, | ||
| 613 | .name = "smi240", | ||
| 614 | }, | ||
| 615 | }; | ||
| 616 | module_spi_driver(smi240_spi_driver); | ||
| 617 | |||
| 618 | MODULE_AUTHOR("Markus Lochmann <markus.lochmann@de.bosch.com>"); | ||
| 619 | MODULE_AUTHOR("Stefan Gutmann <stefan.gutmann@de.bosch.com>"); | ||
| 620 | MODULE_DESCRIPTION("Bosch SMI240 SPI driver"); | ||
| 621 | MODULE_LICENSE("Dual BSD/GPL"); | ||
| @@ -447,7 +447,7 @@ struct st_lsm6dsx_hw { · 446 unmodified lines | |||
| 447 | /* Ensure natural alignment of buffer elements */ | 447 | /* Ensure natural alignment of buffer elements */ |
| 448 | struct { | 448 | struct { |
| 449 | __le16 channels[3]; | 449 | __le16 channels[3]; |
| 450 | s64 ts __aligned(8); | 450 | aligned_s64 ts; |
| 451 | } scan[ST_LSM6DSX_ID_MAX]; | 451 | } scan[ST_LSM6DSX_ID_MAX]; |
| 452 | }; | 452 | }; |
| 453 | 453 | ||
| @@ -1865,7 +1865,7 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev, · 1864 unmodified lines | |||
| 1865 | return err; | 1865 | return err; |
| 1866 | } | 1866 | } |
| 1867 | 1867 | ||
| 1868 | static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, int state) | 1868 | static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, bool state) |
| 1869 | { | 1869 | { |
| 1870 | const struct st_lsm6dsx_reg *reg; | 1870 | const struct st_lsm6dsx_reg *reg; |
| 1871 | unsigned int data; | 1871 | unsigned int data; |
| @@ -1959,7 +1959,7 @@ static int · 87 unmodified lines | |||
| 1959 | st_lsm6dsx_write_event_config(struct iio_dev *iio_dev, | 1959 | st_lsm6dsx_write_event_config(struct iio_dev *iio_dev, |
| 1960 | const struct iio_chan_spec *chan, | 1960 | const struct iio_chan_spec *chan, |
| 1961 | enum iio_event_type type, | 1961 | enum iio_event_type type, |
| 1962 | enum iio_event_direction dir, int state) | 1962 | enum iio_event_direction dir, bool state) |
| 1963 | { | 1963 | { |
| 1964 | struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); | 1964 | struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); |
| 1965 | struct st_lsm6dsx_hw *hw = sensor->hw; | 1965 | struct st_lsm6dsx_hw *hw = sensor->hw; |
| @@ -2132,14 +2132,11 @@ st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, · 166 unmodified lines | |||
| 2132 | const struct st_lsm6dsx_reg **drdy_reg) | 2132 | const struct st_lsm6dsx_reg **drdy_reg) |
| 2133 | { | 2133 | { |
| 2134 | struct device *dev = hw->dev; | 2134 | struct device *dev = hw->dev; |
| 2135 | const struct st_sensors_platform_data *pdata = dev_get_platdata(dev); | ||
| 2135 | int err = 0, drdy_pin; | 2136 | int err = 0, drdy_pin; |
| 2136 | 2137 | ||
| 2137 | if (device_property_read_u32(dev, "st,drdy-int-pin", &drdy_pin) < 0) { | 2138 | if (device_property_read_u32(dev, "st,drdy-int-pin", &drdy_pin) < 0) |
| 2138 | struct st_sensors_platform_data *pdata; | ||
| 2139 | |||
| 2140 | pdata = (struct st_sensors_platform_data *)dev->platform_data; | ||
| 2141 | drdy_pin = pdata ? pdata->drdy_int_pin : 1; | 2139 | drdy_pin = pdata ? pdata->drdy_int_pin : 1; |
| 2142 | } | ||
| 2143 | 2140 | ||
| 2144 | switch (drdy_pin) { | 2141 | switch (drdy_pin) { |
| 2145 | case 1: | 2142 | case 1: |
| @@ -2162,14 +2159,13 @@ st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, · 16 unmodified lines | |||
| 2162 | static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw) | 2159 | static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw) |
| 2163 | { | 2160 | { |
| 2164 | const struct st_lsm6dsx_shub_settings *hub_settings; | 2161 | const struct st_lsm6dsx_shub_settings *hub_settings; |
| 2165 | struct st_sensors_platform_data *pdata; | ||
| 2166 | struct device *dev = hw->dev; | 2162 | struct device *dev = hw->dev; |
| 2163 | const struct st_sensors_platform_data *pdata = dev_get_platdata(dev); | ||
| 2167 | unsigned int data; | 2164 | unsigned int data; |
| 2168 | int err = 0; | 2165 | int err = 0; |
| 2169 | 2166 | ||
| 2170 | hub_settings = &hw->settings->shub_settings; | 2167 | hub_settings = &hw->settings->shub_settings; |
| 2171 | 2168 | ||
| 2172 | pdata = (struct st_sensors_platform_data *)dev->platform_data; | ||
| 2173 | if (device_property_read_bool(dev, "st,pullups") || | 2169 | if (device_property_read_bool(dev, "st,pullups") || |
| 2174 | (pdata && pdata->pullups)) { | 2170 | (pdata && pdata->pullups)) { |
| 2175 | if (hub_settings->pullup_en.sec_page) { | 2171 | if (hub_settings->pullup_en.sec_page) { |
| @@ -2524,15 +2520,14 @@ static irqreturn_t st_lsm6dsx_sw_trigger_handler_thread(int irq, · 348 unmodified lines | |||
| 2524 | 2520 | ||
| 2525 | static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw) | 2521 | static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw) |
| 2526 | { | 2522 | { |
| 2527 | struct st_sensors_platform_data *pdata; | ||
| 2528 | const struct st_lsm6dsx_reg *reg; | 2523 | const struct st_lsm6dsx_reg *reg; |
| 2529 | struct device *dev = hw->dev; | 2524 | struct device *dev = hw->dev; |
| 2525 | const struct st_sensors_platform_data *pdata = dev_get_platdata(dev); | ||
| 2530 | unsigned long irq_type; | 2526 | unsigned long irq_type; |
| 2531 | bool irq_active_low; | 2527 | bool irq_active_low; |
| 2532 | int err; | 2528 | int err; |
| 2533 | 2529 | ||
| 2534 | irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq)); | 2530 | irq_type = irq_get_trigger_type(hw->irq); |
| 2535 | |||
| 2536 | switch (irq_type) { | 2531 | switch (irq_type) { |
| 2537 | case IRQF_TRIGGER_HIGH: | 2532 | case IRQF_TRIGGER_HIGH: |
| 2538 | case IRQF_TRIGGER_RISING: | 2533 | case IRQF_TRIGGER_RISING: |
| @@ -2554,7 +2549,6 @@ static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw) · 15 unmodified lines | |||
| 2554 | if (err < 0) | 2549 | if (err < 0) |
| 2555 | return err; | 2550 | return err; |
| 2556 | 2551 | ||
| 2557 | pdata = (struct st_sensors_platform_data *)dev->platform_data; | ||
| 2558 | if (device_property_read_bool(dev, "drive-open-drain") || | 2552 | if (device_property_read_bool(dev, "drive-open-drain") || |
| 2559 | (pdata && pdata->open_drain)) { | 2553 | (pdata && pdata->open_drain)) { |
| 2560 | reg = &hw->settings->irq_config.od; | 2554 | reg = &hw->settings->irq_config.od; |
| @@ -2639,7 +2633,7 @@ static int st_lsm6dsx_init_regulators(struct device *dev) · 78 unmodified lines | |||
| 2639 | int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, | 2633 | int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, |
| 2640 | struct regmap *regmap) | 2634 | struct regmap *regmap) |
| 2641 | { | 2635 | { |
| 2642 | struct st_sensors_platform_data *pdata = dev->platform_data; | 2636 | const struct st_sensors_platform_data *pdata = dev_get_platdata(dev); |
| 2643 | const struct st_lsm6dsx_shub_settings *hub_settings; | 2637 | const struct st_lsm6dsx_shub_settings *hub_settings; |
| 2644 | struct st_lsm6dsx_hw *hw; | 2638 | struct st_lsm6dsx_hw *hw; |
| 2645 | const char *name = NULL; | 2639 | const char *name = NULL; |
| @@ -2,7 +2,8 @@ · 1 unmodified line | |||
| 2 | /* IIO ACPI helper functions */ | 2 | /* IIO ACPI helper functions */ |
| 3 | 3 | ||
| 4 | #include <linux/acpi.h> | 4 | #include <linux/acpi.h> |
| 5 | #include <linux/dev_printk.h> | 5 | #include <linux/device.h> |
| 6 | #include <linux/export.h> | ||
| 6 | #include <linux/iio/iio.h> | 7 | #include <linux/iio/iio.h> |
| 7 | #include <linux/sprintf.h> | 8 | #include <linux/sprintf.h> |
| 8 | 9 | ||
| @@ -28,17 +29,21 @@ bool iio_read_acpi_mount_matrix(struct device *dev, · 19 unmodified lines | |||
| 28 | char *acpi_method) | 29 | char *acpi_method) |
| 29 | { | 30 | { |
| 30 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 31 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 31 | struct acpi_device *adev = ACPI_COMPANION(dev); | ||
| 32 | char *str; | 32 | char *str; |
| 33 | union acpi_object *obj, *elements; | 33 | union acpi_object *obj, *elements; |
| 34 | acpi_handle handle; | ||
| 34 | acpi_status status; | 35 | acpi_status status; |
| 35 | int i, j, val[3]; | 36 | int i, j, val[3]; |
| 36 | bool ret = false; | 37 | bool ret = false; |
| 37 | 38 | ||
| 38 | if (!adev || !acpi_has_method(adev->handle, acpi_method)) | 39 | handle = ACPI_HANDLE(dev); |
| 40 | if (!handle) | ||
| 39 | return false; | 41 | return false; |
| 40 | 42 | ||
| 41 | status = acpi_evaluate_object(adev->handle, acpi_method, NULL, &buffer); | 43 | if (!acpi_has_method(handle, acpi_method)) |
| 44 | return false; | ||
| 45 | |||
| 46 | status = acpi_evaluate_object(handle, acpi_method, NULL, &buffer); | ||
| 42 | if (ACPI_FAILURE(status)) { | 47 | if (ACPI_FAILURE(status)) { |
| 43 | dev_err(dev, "Failed to get ACPI mount matrix: %d\n", status); | 48 | dev_err(dev, "Failed to get ACPI mount matrix: %d\n", status); |
| 44 | return false; | 49 | return false; |
| @@ -83,3 +88,38 @@ out_free_buffer: · 38 unmodified lines | |||
| 83 | return ret; | 88 | return ret; |
| 84 | } | 89 | } |
| 85 | EXPORT_SYMBOL_GPL(iio_read_acpi_mount_matrix); | 90 | EXPORT_SYMBOL_GPL(iio_read_acpi_mount_matrix); |
| 91 | |||
| 92 | /** | ||
| 93 | * iio_get_acpi_device_name_and_data() - Return ACPI device instance name and driver data | ||
| 94 | * @dev: Device structure | ||
| 95 | * @data: Optional pointer to return driver data | ||
| 96 | * | ||
| 97 | * When device was enumerated by ACPI ID matching, the user might | ||
| 98 | * want to set description for the physical chip. In such cases | ||
| 99 | * the ACPI device instance name might be used. This call may be | ||
| 100 | * performed to retrieve this information. | ||
| 101 | * | ||
| 102 | * NOTE: This helper function exists only for backward compatibility, | ||
| 103 | * do not use in a new code! | ||
| 104 | * | ||
| 105 | * Returns: ACPI device instance name or %NULL. | ||
| 106 | */ | ||
| 107 | const char *iio_get_acpi_device_name_and_data(struct device *dev, const void **data) | ||
| 108 | { | ||
| 109 | const struct acpi_device_id *id; | ||
| 110 | acpi_handle handle; | ||
| 111 | |||
| 112 | handle = ACPI_HANDLE(dev); | ||
| 113 | if (!handle) | ||
| 114 | return NULL; | ||
| 115 | |||
| 116 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
| 117 | if (!id) | ||
| 118 | return NULL; | ||
| 119 | |||
| 120 | if (data) | ||
| 121 | *data = (const void *)id->driver_data; | ||
| 122 | |||
| 123 | return dev_name(dev); | ||
| 124 | } | ||
| 125 | EXPORT_SYMBOL_GPL(iio_get_acpi_device_name_and_data); | ||
| @@ -718,6 +718,84 @@ static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back) · 717 unmodified lines | |||
| 718 | return 0; | 718 | return 0; |
| 719 | } | 719 | } |
| 720 | 720 | ||
| 721 | /** | ||
| 722 | * iio_backend_ddr_enable - Enable interface DDR (Double Data Rate) mode | ||
| 723 | * @back: Backend device | ||
| 724 | * | ||
| 725 | * Enable DDR, data is generated by the IP at each front (raising and falling) | ||
| 726 | * of the bus clock signal. | ||
| 727 | * | ||
| 728 | * RETURNS: | ||
| 729 | * 0 on success, negative error number on failure. | ||
| 730 | */ | ||
| 731 | int iio_backend_ddr_enable(struct iio_backend *back) | ||
| 732 | { | ||
| 733 | return iio_backend_op_call(back, ddr_enable); | ||
| 734 | } | ||
| 735 | EXPORT_SYMBOL_NS_GPL(iio_backend_ddr_enable, IIO_BACKEND); | ||
| 736 | |||
| 737 | /** | ||
| 738 | * iio_backend_ddr_disable - Disable interface DDR (Double Data Rate) mode | ||
| 739 | * @back: Backend device | ||
| 740 | * | ||
| 741 | * Disable DDR, setting into SDR mode (Single Data Rate). | ||
| 742 | * | ||
| 743 | * RETURNS: | ||
| 744 | * 0 on success, negative error number on failure. | ||
| 745 | */ | ||
| 746 | int iio_backend_ddr_disable(struct iio_backend *back) | ||
| 747 | { | ||
| 748 | return iio_backend_op_call(back, ddr_disable); | ||
| 749 | } | ||
| 750 | EXPORT_SYMBOL_NS_GPL(iio_backend_ddr_disable, IIO_BACKEND); | ||
| 751 | |||
| 752 | /** | ||
| 753 | * iio_backend_data_stream_enable - Enable data stream | ||
| 754 | * @back: Backend device | ||
| 755 | * | ||
| 756 | * Enable data stream over the bus interface. | ||
| 757 | * | ||
| 758 | * RETURNS: | ||
| 759 | * 0 on success, negative error number on failure. | ||
| 760 | */ | ||
| 761 | int iio_backend_data_stream_enable(struct iio_backend *back) | ||
| 762 | { | ||
| 763 | return iio_backend_op_call(back, data_stream_enable); | ||
| 764 | } | ||
| 765 | EXPORT_SYMBOL_NS_GPL(iio_backend_data_stream_enable, IIO_BACKEND); | ||
| 766 | |||
| 767 | /** | ||
| 768 | * iio_backend_data_stream_disable - Disable data stream | ||
| 769 | * @back: Backend device | ||
| 770 | * | ||
| 771 | * Disable data stream over the bus interface. | ||
| 772 | * | ||
| 773 | * RETURNS: | ||
| 774 | * 0 on success, negative error number on failure. | ||
| 775 | */ | ||
| 776 | int iio_backend_data_stream_disable(struct iio_backend *back) | ||
| 777 | { | ||
| 778 | return iio_backend_op_call(back, data_stream_disable); | ||
| 779 | } | ||
| 780 | EXPORT_SYMBOL_NS_GPL(iio_backend_data_stream_disable, IIO_BACKEND); | ||
| 781 | |||
| 782 | /** | ||
| 783 | * iio_backend_data_transfer_addr - Set data address. | ||
| 784 | * @back: Backend device | ||
| 785 | * @address: Data register address | ||
| 786 | * | ||
| 787 | * Some devices may need to inform the backend about an address | ||
| 788 | * where to read or write the data. | ||
| 789 | * | ||
| 790 | * RETURNS: | ||
| 791 | * 0 on success, negative error number on failure. | ||
| 792 | */ | ||
| 793 | int iio_backend_data_transfer_addr(struct iio_backend *back, u32 address) | ||
| 794 | { | ||
| 795 | return iio_backend_op_call(back, data_transfer_addr, address); | ||
| 796 | } | ||
| 797 | EXPORT_SYMBOL_NS_GPL(iio_backend_data_transfer_addr, IIO_BACKEND); | ||
| 798 | |||
| 721 | static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, const char *name, | 799 | static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, const char *name, |
| 722 | struct fwnode_handle *fwnode) | 800 | struct fwnode_handle *fwnode) |
| 723 | { | 801 | { |
| @@ -737,8 +815,8 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con · 13 unmodified lines | |||
| 737 | } | 815 | } |
| 738 | 816 | ||
| 739 | fwnode_back = fwnode_find_reference(fwnode, "io-backends", index); | 817 | fwnode_back = fwnode_find_reference(fwnode, "io-backends", index); |
| 740 | if (IS_ERR(fwnode)) | 818 | if (IS_ERR(fwnode_back)) |
| 741 | return dev_err_cast_probe(dev, fwnode, | 819 | return dev_err_cast_probe(dev, fwnode_back, |
| 742 | "Cannot get Firmware reference\n"); | 820 | "Cannot get Firmware reference\n"); |
| 743 | 821 | ||
| 744 | guard(mutex)(&iio_back_lock); | 822 | guard(mutex)(&iio_back_lock); |
| @@ -95,6 +95,7 @@ static const char * const iio_chan_type_name_spec[] = { · 94 unmodified lines | |||
| 95 | [IIO_DELTA_VELOCITY] = "deltavelocity", | 95 | [IIO_DELTA_VELOCITY] = "deltavelocity", |
| 96 | [IIO_COLORTEMP] = "colortemp", | 96 | [IIO_COLORTEMP] = "colortemp", |
| 97 | [IIO_CHROMATICITY] = "chromaticity", | 97 | [IIO_CHROMATICITY] = "chromaticity", |
| 98 | [IIO_ATTENTION] = "attention", | ||
| 98 | }; | 99 | }; |
| 99 | 100 | ||
| 100 | static const char * const iio_modifier_names[] = { | 101 | static const char * const iio_modifier_names[] = { |
| @@ -1665,7 +1666,7 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) · 1564 unmodified lines | |||
| 1665 | indio_dev = &iio_dev_opaque->indio_dev; | 1666 | indio_dev = &iio_dev_opaque->indio_dev; |
| 1666 | 1667 | ||
| 1667 | if (sizeof_priv) | 1668 | if (sizeof_priv) |
| 1668 | indio_dev->priv = (char *)iio_dev_opaque + | 1669 | ACCESS_PRIVATE(indio_dev, priv) = (char *)iio_dev_opaque + |
| 1669 | ALIGN(sizeof(*iio_dev_opaque), IIO_DMA_MINALIGN); | 1670 | ALIGN(sizeof(*iio_dev_opaque), IIO_DMA_MINALIGN); |
| 1670 | 1671 | ||
| 1671 | indio_dev->dev.parent = parent; | 1672 | indio_dev->dev.parent = parent; |
| @@ -167,7 +167,7 @@ static int iio_gts_gain_cmp(const void *a, const void *b) · 166 unmodified lines | |||
| 167 | 167 | ||
| 168 | static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales) | 168 | static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales) |
| 169 | { | 169 | { |
| 170 | int ret, i, j, new_idx, time_idx; | 170 | int i, j, new_idx, time_idx, ret = 0; |
| 171 | int *all_gains; | 171 | int *all_gains; |
| 172 | size_t gain_bytes; | 172 | size_t gain_bytes; |
| 173 | 173 | ||
| @@ -205,7 +205,7 @@ static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales) · 31 unmodified lines | |||
| 205 | memcpy(all_gains, gains[time_idx], gain_bytes); | 205 | memcpy(all_gains, gains[time_idx], gain_bytes); |
| 206 | new_idx = gts->num_hwgain; | 206 | new_idx = gts->num_hwgain; |
| 207 | 207 | ||
| 208 | while (time_idx--) { | 208 | while (time_idx-- > 0) { |
| 209 | for (j = 0; j < gts->num_hwgain; j++) { | 209 | for (j = 0; j < gts->num_hwgain; j++) { |
| 210 | int candidate = gains[time_idx][j]; | 210 | int candidate = gains[time_idx][j]; |
| 211 | int chk; | 211 | int chk; |
| @@ -20,7 +20,7 @@ · 19 unmodified lines | |||
| 20 | 20 | ||
| 21 | struct iio_map_internal { | 21 | struct iio_map_internal { |
| 22 | struct iio_dev *indio_dev; | 22 | struct iio_dev *indio_dev; |
| 23 | struct iio_map *map; | 23 | const struct iio_map *map; |
| 24 | struct list_head l; | 24 | struct list_head l; |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| @@ -42,7 +42,7 @@ static int iio_map_array_unregister_locked(struct iio_dev *indio_dev) · 15 unmodified lines | |||
| 42 | return ret; | 42 | return ret; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps) | 45 | int iio_map_array_register(struct iio_dev *indio_dev, const struct iio_map *maps) |
| 46 | { | 46 | { |
| 47 | struct iio_map_internal *mapi; | 47 | struct iio_map_internal *mapi; |
| 48 | int i = 0; | 48 | int i = 0; |
| @@ -86,7 +86,8 @@ static void iio_map_array_unregister_cb(void *indio_dev) · 37 unmodified lines | |||
| 86 | iio_map_array_unregister(indio_dev); | 86 | iio_map_array_unregister(indio_dev); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | int devm_iio_map_array_register(struct device *dev, struct iio_dev *indio_dev, struct iio_map *maps) | 89 | int devm_iio_map_array_register(struct device *dev, struct iio_dev *indio_dev, |
| 90 | const struct iio_map *maps) | ||
| 90 | { | 91 | { |
| 91 | int ret; | 92 | int ret; |
| 92 | 93 | ||
| @@ -269,7 +270,7 @@ struct iio_channel *fwnode_iio_channel_get_by_name(struct fwnode_handle *fwnode, · 176 unmodified lines | |||
| 269 | return ERR_PTR(-ENODEV); | 270 | return ERR_PTR(-ENODEV); |
| 270 | } | 271 | } |
| 271 | 272 | ||
| 272 | chan = __fwnode_iio_channel_get_by_name(fwnode, name); | 273 | chan = __fwnode_iio_channel_get_by_name(parent, name); |
| 273 | if (!IS_ERR(chan) || PTR_ERR(chan) != -ENODEV) { | 274 | if (!IS_ERR(chan) || PTR_ERR(chan) != -ENODEV) { |
| 274 | fwnode_handle_put(parent); | 275 | fwnode_handle_put(parent); |
| 275 | return chan; | 276 | return chan; |
| @@ -248,7 +248,6 @@ config SENSORS_ISL29018 · 247 unmodified lines | |||
| 248 | tristate "Intersil 29018 light and proximity sensor" | 248 | tristate "Intersil 29018 light and proximity sensor" |
| 249 | depends on I2C | 249 | depends on I2C |
| 250 | select REGMAP_I2C | 250 | select REGMAP_I2C |
| 251 | default n | ||
| 252 | help | 251 | help |
| 253 | If you say yes here you get support for ambient light sensing and | 252 | If you say yes here you get support for ambient light sensing and |
| 254 | proximity infrared sensing from Intersil ISL29018. | 253 | proximity infrared sensing from Intersil ISL29018. |
| @@ -476,7 +475,7 @@ config OPT3001 · 221 unmodified lines | |||
| 476 | depends on I2C | 475 | depends on I2C |
| 477 | help | 476 | help |
| 478 | If you say Y or M here, you get support for Texas Instruments | 477 | If you say Y or M here, you get support for Texas Instruments |
| 479 | OPT3001 Ambient Light Sensor. | 478 | OPT3001 Ambient Light Sensor, OPT3002 Light-to-Digital Sensor. |
| 480 | 479 | ||
| 481 | If built as a dynamically linked module, it will be called | 480 | If built as a dynamically linked module, it will be called |
| 482 | opt3001. | 481 | opt3001. |
| @@ -670,13 +669,24 @@ config VCNL4035 · 187 unmodified lines | |||
| 670 | To compile this driver as a module, choose M here: the | 669 | To compile this driver as a module, choose M here: the |
| 671 | module will be called vcnl4035. | 670 | module will be called vcnl4035. |
| 672 | 671 | ||
| 672 | config VEML3235 | ||
| 673 | tristate "VEML3235 ambient light sensor" | ||
| 674 | select REGMAP_I2C | ||
| 675 | depends on I2C | ||
| 676 | help | ||
| 677 | Say Y here if you want to build a driver for the Vishay VEML3235 | ||
| 678 | ambient light sensor. | ||
| 679 | |||
| 680 | To compile this driver as a module, choose M here: the | ||
| 681 | module will be called veml3235. | ||
| 682 | |||
| 673 | config VEML6030 | 683 | config VEML6030 |
| 674 | tristate "VEML6030 ambient light sensor" | 684 | tristate "VEML6030 and VEML6035 ambient light sensors" |
| 675 | select REGMAP_I2C | 685 | select REGMAP_I2C |
| 676 | depends on I2C | 686 | depends on I2C |
| 677 | help | 687 | help |
| 678 | Say Y here if you want to build a driver for the Vishay VEML6030 | 688 | Say Y here if you want to build a driver for the Vishay VEML6030 |
| 679 | ambient light sensor (ALS). | 689 | and VEML6035 ambient light sensors (ALS). |
| 680 | 690 | ||
| 681 | To compile this driver as a module, choose M here: the | 691 | To compile this driver as a module, choose M here: the |
| 682 | module will be called veml6030. | 692 | module will be called veml6030. |
| @@ -62,6 +62,7 @@ obj-$(CONFIG_TSL4531) += tsl4531.o · 61 unmodified lines | |||
| 62 | obj-$(CONFIG_US5182D) += us5182d.o | 62 | obj-$(CONFIG_US5182D) += us5182d.o |
| 63 | obj-$(CONFIG_VCNL4000) += vcnl4000.o | 63 | obj-$(CONFIG_VCNL4000) += vcnl4000.o |
| 64 | obj-$(CONFIG_VCNL4035) += vcnl4035.o | 64 | obj-$(CONFIG_VCNL4035) += vcnl4035.o |
| 65 | obj-$(CONFIG_VEML3235) += veml3235.o | ||
| 65 | obj-$(CONFIG_VEML6030) += veml6030.o | 66 | obj-$(CONFIG_VEML6030) += veml6030.o |
| 66 | obj-$(CONFIG_VEML6040) += veml6040.o | 67 | obj-$(CONFIG_VEML6040) += veml6040.o |
| 67 | obj-$(CONFIG_VEML6070) += veml6070.o | 68 | obj-$(CONFIG_VEML6070) += veml6070.o |
| @@ -502,7 +502,8 @@ fail: · 501 unmodified lines | |||
| 502 | static int adux1020_write_event_config(struct iio_dev *indio_dev, | 502 | static int adux1020_write_event_config(struct iio_dev *indio_dev, |
| 503 | const struct iio_chan_spec *chan, | 503 | const struct iio_chan_spec *chan, |
| 504 | enum iio_event_type type, | 504 | enum iio_event_type type, |
| 505 | enum iio_event_direction dir, int state) | 505 | enum iio_event_direction dir, |
| 506 | bool state) | ||
| 506 | { | 507 | { |
| 507 | struct adux1020_data *data = iio_priv(indio_dev); | 508 | struct adux1020_data *data = iio_priv(indio_dev); |
| 508 | int ret, mask; | 509 | int ret, mask; |
| @@ -526,12 +527,11 @@ static int adux1020_write_event_config(struct iio_dev *indio_dev, · 17 unmodified lines | |||
| 526 | mask = ADUX1020_PROX_OFF1_INT; | 527 | mask = ADUX1020_PROX_OFF1_INT; |
| 527 | 528 | ||
| 528 | if (state) | 529 | if (state) |
| 529 | state = 0; | 530 | ret = regmap_clear_bits(data->regmap, |
| 531 | ADUX1020_REG_INT_MASK, mask); | ||
| 530 | else | 532 | else |
| 531 | state = mask; | 533 | ret = regmap_set_bits(data->regmap, |
| 532 | 534 | ADUX1020_REG_INT_MASK, mask); | |
| 533 | ret = regmap_update_bits(data->regmap, ADUX1020_REG_INT_MASK, | ||
| 534 | mask, state); | ||
| 535 | if (ret < 0) | 535 | if (ret < 0) |
| 536 | goto fail; | 536 | goto fail; |
| 537 | 537 | ||
| @@ -87,7 +87,12 @@ static int al3010_init(struct al3010_data *data) · 86 unmodified lines | |||
| 87 | int ret; | 87 | int ret; |
| 88 | 88 | ||
| 89 | ret = al3010_set_pwr(data->client, true); | 89 | ret = al3010_set_pwr(data->client, true); |
| 90 | if (ret < 0) | ||
| 91 | return ret; | ||
| 90 | 92 | ||
| 93 | ret = devm_add_action_or_reset(&data->client->dev, | ||
| 94 | al3010_set_pwr_off, | ||
| 95 | data); | ||
| 91 | if (ret < 0) | 96 | if (ret < 0) |
| 92 | return ret; | 97 | return ret; |
| 93 | 98 | ||
| @@ -190,12 +195,6 @@ static int al3010_probe(struct i2c_client *client) · 96 unmodified lines | |||
| 190 | return ret; | 195 | return ret; |
| 191 | } | 196 | } |
| 192 | 197 | ||
| 193 | ret = devm_add_action_or_reset(&client->dev, | ||
| 194 | al3010_set_pwr_off, | ||
| 195 | data); | ||
| 196 | if (ret < 0) | ||
| 197 | return ret; | ||
| 198 | |||
| 199 | return devm_iio_device_register(&client->dev, indio_dev); | 198 | return devm_iio_device_register(&client->dev, indio_dev); |
| 200 | } | 199 | } |
| 201 | 200 | ||
| @@ -46,10 +46,10 @@ · 45 unmodified lines | |||
| 46 | struct apds9300_data { | 46 | struct apds9300_data { |
| 47 | struct i2c_client *client; | 47 | struct i2c_client *client; |
| 48 | struct mutex mutex; | 48 | struct mutex mutex; |
| 49 | int power_state; | 49 | bool power_state; |
| 50 | int thresh_low; | 50 | int thresh_low; |
| 51 | int thresh_hi; | 51 | int thresh_hi; |
| 52 | int intr_en; | 52 | bool intr_en; |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | /* Lux calculation */ | 55 | /* Lux calculation */ |
| @@ -148,7 +148,7 @@ static int apds9300_set_thresh_hi(struct apds9300_data *data, int value) · 92 unmodified lines | |||
| 148 | return 0; | 148 | return 0; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | static int apds9300_set_intr_state(struct apds9300_data *data, int state) | 151 | static int apds9300_set_intr_state(struct apds9300_data *data, bool state) |
| 152 | { | 152 | { |
| 153 | int ret; | 153 | int ret; |
| 154 | u8 cmd; | 154 | u8 cmd; |
| @@ -169,7 +169,7 @@ static int apds9300_set_intr_state(struct apds9300_data *data, int state) · 14 unmodified lines | |||
| 169 | return 0; | 169 | return 0; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | static int apds9300_set_power_state(struct apds9300_data *data, int state) | 172 | static int apds9300_set_power_state(struct apds9300_data *data, bool state) |
| 173 | { | 173 | { |
| 174 | int ret; | 174 | int ret; |
| 175 | u8 cmd; | 175 | u8 cmd; |
| @@ -221,7 +221,7 @@ static int apds9300_chip_init(struct apds9300_data *data) · 45 unmodified lines | |||
| 221 | * Disable interrupt to ensure thai it is doesn't enable | 221 | * Disable interrupt to ensure thai it is doesn't enable |
| 222 | * i.e. after device soft reset | 222 | * i.e. after device soft reset |
| 223 | */ | 223 | */ |
| 224 | ret = apds9300_set_intr_state(data, 0); | 224 | ret = apds9300_set_intr_state(data, false); |
| 225 | if (ret < 0) | 225 | if (ret < 0) |
| 226 | goto err; | 226 | goto err; |
| 227 | 227 | ||
| @@ -321,7 +321,7 @@ static int apds9300_read_interrupt_config(struct iio_dev *indio_dev, · 93 unmodified lines | |||
| 321 | 321 | ||
| 322 | static int apds9300_write_interrupt_config(struct iio_dev *indio_dev, | 322 | static int apds9300_write_interrupt_config(struct iio_dev *indio_dev, |
| 323 | const struct iio_chan_spec *chan, enum iio_event_type type, | 323 | const struct iio_chan_spec *chan, enum iio_event_type type, |
| 324 | enum iio_event_direction dir, int state) | 324 | enum iio_event_direction dir, bool state) |
| 325 | { | 325 | { |
| 326 | struct apds9300_data *data = iio_priv(indio_dev); | 326 | struct apds9300_data *data = iio_priv(indio_dev); |
| 327 | int ret; | 327 | int ret; |
| @@ -459,8 +459,8 @@ static void apds9300_remove(struct i2c_client *client) · 131 unmodified lines | |||
| 459 | iio_device_unregister(indio_dev); | 459 | iio_device_unregister(indio_dev); |
| 460 | 460 | ||
| 461 | /* Ensure that power off and interrupts are disabled */ | 461 | /* Ensure that power off and interrupts are disabled */ |
| 462 | apds9300_set_intr_state(data, 0); | 462 | apds9300_set_intr_state(data, false); |
| 463 | apds9300_set_power_state(data, 0); | 463 | apds9300_set_power_state(data, false); |
| 464 | } | 464 | } |
| 465 | 465 | ||
| 466 | static int apds9300_suspend(struct device *dev) | 466 | static int apds9300_suspend(struct device *dev) |
| @@ -470,7 +470,7 @@ static int apds9300_suspend(struct device *dev) · 3 unmodified lines | |||
| 470 | int ret; | 470 | int ret; |
| 471 | 471 | ||
| 472 | mutex_lock(&data->mutex); | 472 | mutex_lock(&data->mutex); |
| 473 | ret = apds9300_set_power_state(data, 0); | 473 | ret = apds9300_set_power_state(data, false); |
| 474 | mutex_unlock(&data->mutex); | 474 | mutex_unlock(&data->mutex); |
| 475 | 475 | ||
| 476 | return ret; | 476 | return ret; |
| @@ -483,7 +483,7 @@ static int apds9300_resume(struct device *dev) · 6 unmodified lines | |||
| 483 | int ret; | 483 | int ret; |
| 484 | 484 | ||
| 485 | mutex_lock(&data->mutex); | 485 | mutex_lock(&data->mutex); |
| 486 | ret = apds9300_set_power_state(data, 1); | 486 | ret = apds9300_set_power_state(data, true); |
| 487 | mutex_unlock(&data->mutex); | 487 | mutex_unlock(&data->mutex); |
| 488 | 488 | ||
| 489 | return ret; | 489 | return ret; |
| @@ -1071,7 +1071,7 @@ static int apds9306_write_event_config(struct iio_dev *indio_dev, · 1070 unmodified lines | |||
| 1071 | const struct iio_chan_spec *chan, | 1071 | const struct iio_chan_spec *chan, |
| 1072 | enum iio_event_type type, | 1072 | enum iio_event_type type, |
| 1073 | enum iio_event_direction dir, | 1073 | enum iio_event_direction dir, |
| 1074 | int state) | 1074 | bool state) |
| 1075 | { | 1075 | { |
| 1076 | struct apds9306_data *data = iio_priv(indio_dev); | 1076 | struct apds9306_data *data = iio_priv(indio_dev); |
| 1077 | struct apds9306_regfields *rf = &data->rf; | 1077 | struct apds9306_regfields *rf = &data->rf; |
| @@ -1125,10 +1125,7 @@ static int apds9306_write_event_config(struct iio_dev *indio_dev, · 47 unmodified lines | |||
| 1125 | } | 1125 | } |
| 1126 | } | 1126 | } |
| 1127 | case IIO_EV_TYPE_THRESH_ADAPTIVE: | 1127 | case IIO_EV_TYPE_THRESH_ADAPTIVE: |
| 1128 | if (state) | 1128 | return regmap_field_write(rf->int_thresh_var_en, state); |
| 1129 | return regmap_field_write(rf->int_thresh_var_en, 1); | ||
| 1130 | else | ||
| 1131 | return regmap_field_write(rf->int_thresh_var_en, 0); | ||
| 1132 | default: | 1129 | default: |
| 1133 | return -EINVAL; | 1130 | return -EINVAL; |
| 1134 | } | 1131 | } |
| @@ -133,8 +133,8 @@ struct apds9960_data { · 132 unmodified lines | |||
| 133 | struct regmap_field *reg_enable_pxs; | 133 | struct regmap_field *reg_enable_pxs; |
| 134 | 134 | ||
| 135 | /* state */ | 135 | /* state */ |
| 136 | int als_int; | 136 | bool als_int; |
| 137 | int pxs_int; | 137 | bool pxs_int; |
| 138 | int gesture_mode_running; | 138 | int gesture_mode_running; |
| 139 | 139 | ||
| 140 | /* gain values */ | 140 | /* gain values */ |
| @@ -749,21 +749,17 @@ static int apds9960_read_event_config(struct iio_dev *indio_dev, · 608 unmodified lines | |||
| 749 | default: | 749 | default: |
| 750 | return -EINVAL; | 750 | return -EINVAL; |
| 751 | } | 751 | } |
| 752 | |||
| 753 | return 0; | ||
| 754 | } | 752 | } |
| 755 | 753 | ||
| 756 | static int apds9960_write_event_config(struct iio_dev *indio_dev, | 754 | static int apds9960_write_event_config(struct iio_dev *indio_dev, |
| 757 | const struct iio_chan_spec *chan, | 755 | const struct iio_chan_spec *chan, |
| 758 | enum iio_event_type type, | 756 | enum iio_event_type type, |
| 759 | enum iio_event_direction dir, | 757 | enum iio_event_direction dir, |
| 760 | int state) | 758 | bool state) |
| 761 | { | 759 | { |
| 762 | struct apds9960_data *data = iio_priv(indio_dev); | 760 | struct apds9960_data *data = iio_priv(indio_dev); |
| 763 | int ret; | 761 | int ret; |
| 764 | 762 | ||
| 765 | state = !!state; | ||
| 766 | |||
| 767 | switch (chan->type) { | 763 | switch (chan->type) { |
| 768 | case IIO_PROXIMITY: | 764 | case IIO_PROXIMITY: |
| 769 | if (data->pxs_int == state) | 765 | if (data->pxs_int == state) |
| @@ -638,46 +638,42 @@ static int bh1745_read_event_config(struct iio_dev *indio_dev, · 637 unmodified lines | |||
| 638 | static int bh1745_write_event_config(struct iio_dev *indio_dev, | 638 | static int bh1745_write_event_config(struct iio_dev *indio_dev, |
| 639 | const struct iio_chan_spec *chan, | 639 | const struct iio_chan_spec *chan, |
| 640 | enum iio_event_type type, | 640 | enum iio_event_type type, |
| 641 | enum iio_event_direction dir, int state) | 641 | enum iio_event_direction dir, bool state) |
| 642 | { | 642 | { |
| 643 | struct bh1745_data *data = iio_priv(indio_dev); | 643 | struct bh1745_data *data = iio_priv(indio_dev); |
| 644 | int value; | 644 | int value; |
| 645 | 645 | ||
| 646 | if (state == 0) | 646 | if (!state) |
| 647 | return regmap_clear_bits(data->regmap, | 647 | return regmap_clear_bits(data->regmap, |
| 648 | BH1745_INTR, BH1745_INTR_ENABLE); | 648 | BH1745_INTR, BH1745_INTR_ENABLE); |
| 649 | 649 | ||
| 650 | if (state == 1) { | 650 | /* Latch is always enabled when enabling interrupt */ |
| 651 | /* Latch is always enabled when enabling interrupt */ | 651 | value = BH1745_INTR_ENABLE; |
| 652 | value = BH1745_INTR_ENABLE; | ||
| 653 | 652 | ||
| 654 | switch (chan->channel2) { | 653 | switch (chan->channel2) { |
| 655 | case IIO_MOD_LIGHT_RED: | 654 | case IIO_MOD_LIGHT_RED: |
| 656 | return regmap_write(data->regmap, BH1745_INTR, | 655 | return regmap_write(data->regmap, BH1745_INTR, |
| 657 | value | FIELD_PREP(BH1745_INTR_SOURCE_MASK, | 656 | value | FIELD_PREP(BH1745_INTR_SOURCE_MASK, |
| 658 | BH1745_INTR_SOURCE_RED)); | 657 | BH1745_INTR_SOURCE_RED)); |
| 659 | 658 | ||
| 660 | case IIO_MOD_LIGHT_GREEN: | 659 | case IIO_MOD_LIGHT_GREEN: |
| 661 | return regmap_write(data->regmap, BH1745_INTR, | 660 | return regmap_write(data->regmap, BH1745_INTR, |
| 662 | value | FIELD_PREP(BH1745_INTR_SOURCE_MASK, | 661 | value | FIELD_PREP(BH1745_INTR_SOURCE_MASK, |
| 663 | BH1745_INTR_SOURCE_GREEN)); | 662 | BH1745_INTR_SOURCE_GREEN)); |
| 664 | 663 | ||
| 665 | case IIO_MOD_LIGHT_BLUE: | 664 | case IIO_MOD_LIGHT_BLUE: |
| 666 | return regmap_write(data->regmap, BH1745_INTR, | 665 | return regmap_write(data->regmap, BH1745_INTR, |
| 667 | value | FIELD_PREP(BH1745_INTR_SOURCE_MASK, | 666 | value | FIELD_PREP(BH1745_INTR_SOURCE_MASK, |
| 668 | BH1745_INTR_SOURCE_BLUE)); | 667 | BH1745_INTR_SOURCE_BLUE)); |
| 669 | 668 | ||
| 670 | case IIO_MOD_LIGHT_CLEAR: | 669 | case IIO_MOD_LIGHT_CLEAR: |
| 671 | return regmap_write(data->regmap, BH1745_INTR, | 670 | return regmap_write(data->regmap, BH1745_INTR, |
| 672 | value | FIELD_PREP(BH1745_INTR_SOURCE_MASK, | 671 | value | FIELD_PREP(BH1745_INTR_SOURCE_MASK, |
| 673 | BH1745_INTR_SOURCE_CLEAR)); | 672 | BH1745_INTR_SOURCE_CLEAR)); |
| 674 | 673 | ||
| 675 | default: | 674 | default: |
| 676 | return -EINVAL; | 675 | return -EINVAL; |
| 677 | } | ||
| 678 | } | 676 | } |
| 679 | |||
| 680 | return -EINVAL; | ||
| 681 | } | 677 | } |
| 682 | 678 | ||
| 683 | static int bh1745_read_avail(struct iio_dev *indio_dev, | 679 | static int bh1745_read_avail(struct iio_dev *indio_dev, |
| @@ -217,8 +217,7 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181) · 216 unmodified lines | |||
| 217 | cm32181->lux_per_bit = CM32181_LUX_PER_BIT; | 217 | cm32181->lux_per_bit = CM32181_LUX_PER_BIT; |
| 218 | cm32181->lux_per_bit_base_it = CM32181_LUX_PER_BIT_BASE_IT; | 218 | cm32181->lux_per_bit_base_it = CM32181_LUX_PER_BIT_BASE_IT; |
| 219 | 219 | ||
| 220 | if (ACPI_HANDLE(cm32181->dev)) | 220 | cm32181_acpi_parse_cpm_tables(cm32181); |
| 221 | cm32181_acpi_parse_cpm_tables(cm32181); | ||
| 222 | 221 | ||
| 223 | /* Initialize registers*/ | 222 | /* Initialize registers*/ |
| 224 | for_each_set_bit(i, &cm32181->init_regs_bitmap, CM32181_CONF_REG_NUM) { | 223 | for_each_set_bit(i, &cm32181->init_regs_bitmap, CM32181_CONF_REG_NUM) { |
| @@ -318,7 +318,7 @@ static struct platform_driver cm3605_driver = { · 317 unmodified lines | |||
| 318 | .pm = pm_sleep_ptr(&cm3605_dev_pm_ops), | 318 | .pm = pm_sleep_ptr(&cm3605_dev_pm_ops), |
| 319 | }, | 319 | }, |
| 320 | .probe = cm3605_probe, | 320 | .probe = cm3605_probe, |
| 321 | .remove_new = cm3605_remove, | 321 | .remove = cm3605_remove, |
| 322 | }; | 322 | }; |
| 323 | module_platform_driver(cm3605_driver); | 323 | module_platform_driver(cm3605_driver); |
| 324 | 324 | ||
| @@ -529,7 +529,7 @@ static int cm36651_write_prox_event_config(struct iio_dev *indio_dev, · 528 unmodified lines | |||
| 529 | const struct iio_chan_spec *chan, | 529 | const struct iio_chan_spec *chan, |
| 530 | enum iio_event_type type, | 530 | enum iio_event_type type, |
| 531 | enum iio_event_direction dir, | 531 | enum iio_event_direction dir, |
| 532 | int state) | 532 | bool state) |
| 533 | { | 533 | { |
| 534 | struct cm36651_data *cm36651 = iio_priv(indio_dev); | 534 | struct cm36651_data *cm36651 = iio_priv(indio_dev); |
| 535 | int cmd, ret; | 535 | int cmd, ret; |
| @@ -340,7 +340,7 @@ static int gp2ap002_write_event_config(struct iio_dev *indio_dev, · 339 unmodified lines | |||
| 340 | const struct iio_chan_spec *chan, | 340 | const struct iio_chan_spec *chan, |
| 341 | enum iio_event_type type, | 341 | enum iio_event_type type, |
| 342 | enum iio_event_direction dir, | 342 | enum iio_event_direction dir, |
| 343 | int state) | 343 | bool state) |
| 344 | { | 344 | { |
| 345 | struct gp2ap002 *gp2ap002 = iio_priv(indio_dev); | 345 | struct gp2ap002 *gp2ap002 = iio_priv(indio_dev); |
| 346 | 346 | ||
| @@ -1159,7 +1159,7 @@ static int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev, · 1158 unmodified lines | |||
| 1159 | const struct iio_chan_spec *chan, | 1159 | const struct iio_chan_spec *chan, |
| 1160 | enum iio_event_type type, | 1160 | enum iio_event_type type, |
| 1161 | enum iio_event_direction dir, | 1161 | enum iio_event_direction dir, |
| 1162 | int state) | 1162 | bool state) |
| 1163 | { | 1163 | { |
| 1164 | struct gp2ap020a00f_data *data = iio_priv(indio_dev); | 1164 | struct gp2ap020a00f_data *data = iio_priv(indio_dev); |
| 1165 | enum gp2ap020a00f_cmd cmd; | 1165 | enum gp2ap020a00f_cmd cmd; |
| @@ -31,7 +31,7 @@ struct als_state { · 30 unmodified lines | |||
| 31 | struct iio_chan_spec channels[CHANNEL_SCAN_INDEX_MAX + 1]; | 31 | struct iio_chan_spec channels[CHANNEL_SCAN_INDEX_MAX + 1]; |
| 32 | struct { | 32 | struct { |
| 33 | u32 illum[CHANNEL_SCAN_INDEX_MAX]; | 33 | u32 illum[CHANNEL_SCAN_INDEX_MAX]; |
| 34 | u64 timestamp __aligned(8); | 34 | aligned_s64 timestamp; |
| 35 | } scan; | 35 | } scan; |
| 36 | int scale_pre_decml; | 36 | int scale_pre_decml; |
| 37 | int scale_post_decml; | 37 | int scale_post_decml; |
| @@ -356,11 +356,11 @@ static int als_parse_report(struct platform_device *pdev, · 318 unmodified lines | |||
| 356 | /* Function to initialize the processing for usage id */ | 356 | /* Function to initialize the processing for usage id */ |
| 357 | static int hid_als_probe(struct platform_device *pdev) | 357 | static int hid_als_probe(struct platform_device *pdev) |
| 358 | { | 358 | { |
| 359 | struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); | ||
| 359 | int ret = 0; | 360 | int ret = 0; |
| 360 | static const char *name = "als"; | 361 | static const char *name = "als"; |
| 361 | struct iio_dev *indio_dev; | 362 | struct iio_dev *indio_dev; |
| 362 | struct als_state *als_state; | 363 | struct als_state *als_state; |
| 363 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | ||
| 364 | 364 | ||
| 365 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct als_state)); | 365 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct als_state)); |
| 366 | if (!indio_dev) | 366 | if (!indio_dev) |
| @@ -438,7 +438,7 @@ error_remove_trigger: · 71 unmodified lines | |||
| 438 | /* Function to deinitialize the processing for usage id */ | 438 | /* Function to deinitialize the processing for usage id */ |
| 439 | static void hid_als_remove(struct platform_device *pdev) | 439 | static void hid_als_remove(struct platform_device *pdev) |
| 440 | { | 440 | { |
| 441 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | 441 | struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); |
| 442 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); | 442 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); |
| 443 | struct als_state *als_state = iio_priv(indio_dev); | 443 | struct als_state *als_state = iio_priv(indio_dev); |
| 444 | 444 | ||
| @@ -467,7 +467,7 @@ static struct platform_driver hid_als_platform_driver = { · 22 unmodified lines | |||
| 467 | .pm = &hid_sensor_pm_ops, | 467 | .pm = &hid_sensor_pm_ops, |
| 468 | }, | 468 | }, |
| 469 | .probe = hid_als_probe, | 469 | .probe = hid_als_probe, |
| 470 | .remove_new = hid_als_remove, | 470 | .remove = hid_als_remove, |
| 471 | }; | 471 | }; |
| 472 | module_platform_driver(hid_als_platform_driver); | 472 | module_platform_driver(hid_als_platform_driver); |
| 473 | 473 | ||
| @@ -13,16 +13,32 @@ · 12 unmodified lines | |||
| 13 | #include <linux/iio/buffer.h> | 13 | #include <linux/iio/buffer.h> |
| 14 | #include "../common/hid-sensors/hid-sensor-trigger.h" | 14 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 15 | 15 | ||
| 16 | #define CHANNEL_SCAN_INDEX_PRESENCE 0 | 16 | static const u32 prox_usage_ids[] = { |
| 17 | HID_USAGE_SENSOR_HUMAN_PRESENCE, | ||
| 18 | HID_USAGE_SENSOR_HUMAN_PROXIMITY, | ||
| 19 | HID_USAGE_SENSOR_HUMAN_ATTENTION, | ||
| 20 | }; | ||
| 21 | |||
| 22 | #define MAX_CHANNELS ARRAY_SIZE(prox_usage_ids) | ||
| 23 | |||
| 24 | enum { | ||
| 25 | HID_HUMAN_PRESENCE, | ||
| 26 | HID_HUMAN_PROXIMITY, | ||
| 27 | HID_HUMAN_ATTENTION, | ||
| 28 | }; | ||
| 17 | 29 | ||
| 18 | struct prox_state { | 30 | struct prox_state { |
| 19 | struct hid_sensor_hub_callbacks callbacks; | 31 | struct hid_sensor_hub_callbacks callbacks; |
| 20 | struct hid_sensor_common common_attributes; | 32 | struct hid_sensor_common common_attributes; |
| 21 | struct hid_sensor_hub_attribute_info prox_attr; | 33 | struct hid_sensor_hub_attribute_info prox_attr[MAX_CHANNELS]; |
| 22 | u32 human_presence; | 34 | struct iio_chan_spec channels[MAX_CHANNELS]; |
| 35 | u32 channel2usage[MAX_CHANNELS]; | ||
| 36 | u32 human_presence[MAX_CHANNELS]; | ||
| 23 | int scale_pre_decml; | 37 | int scale_pre_decml; |
| 24 | int scale_post_decml; | 38 | int scale_post_decml; |
| 25 | int scale_precision; | 39 | int scale_precision; |
| 40 | unsigned long scan_mask[2]; /* One entry plus one terminator. */ | ||
| 41 | int num_channels; | ||
| 26 | }; | 42 | }; |
| 27 | 43 | ||
| 28 | static const u32 prox_sensitivity_addresses[] = { | 44 | static const u32 prox_sensitivity_addresses[] = { |
| @@ -30,17 +46,24 @@ static const u32 prox_sensitivity_addresses[] = { · 1 unmodified line | |||
| 30 | HID_USAGE_SENSOR_DATA_PRESENCE, | 46 | HID_USAGE_SENSOR_DATA_PRESENCE, |
| 31 | }; | 47 | }; |
| 32 | 48 | ||
| 33 | /* Channel definitions */ | 49 | #define PROX_CHANNEL(_is_proximity, _channel) \ |
| 34 | static const struct iio_chan_spec prox_channels[] = { | 50 | {\ |
| 35 | { | 51 | .type = _is_proximity ? IIO_PROXIMITY : IIO_ATTENTION,\ |
| 36 | .type = IIO_PROXIMITY, | 52 | .info_mask_separate = _is_proximity ? BIT(IIO_CHAN_INFO_RAW) :\ |
| 37 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | 53 | BIT(IIO_CHAN_INFO_PROCESSED),\ |
| 38 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 54 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |\ |
| 39 | BIT(IIO_CHAN_INFO_SCALE) | | 55 | BIT(IIO_CHAN_INFO_SCALE) |\ |
| 40 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 56 | BIT(IIO_CHAN_INFO_SAMP_FREQ) |\ |
| 41 | BIT(IIO_CHAN_INFO_HYSTERESIS), | 57 | BIT(IIO_CHAN_INFO_HYSTERESIS),\ |
| 42 | .scan_index = CHANNEL_SCAN_INDEX_PRESENCE, | 58 | .indexed = _is_proximity,\ |
| 59 | .channel = _channel,\ | ||
| 43 | } | 60 | } |
| 61 | |||
| 62 | /* Channel definitions (same order as prox_usage_ids) */ | ||
| 63 | static const struct iio_chan_spec prox_channels[] = { | ||
| 64 | PROX_CHANNEL(true, HID_HUMAN_PRESENCE), | ||
| 65 | PROX_CHANNEL(true, HID_HUMAN_PROXIMITY), | ||
| 66 | PROX_CHANNEL(false, 0), | ||
| 44 | }; | 67 | }; |
| 45 | 68 | ||
| 46 | /* Adjust channel real bits based on report descriptor */ | 69 | /* Adjust channel real bits based on report descriptor */ |
| @@ -62,7 +85,7 @@ static int prox_read_raw(struct iio_dev *indio_dev, · 15 unmodified lines | |||
| 62 | { | 85 | { |
| 63 | struct prox_state *prox_state = iio_priv(indio_dev); | 86 | struct prox_state *prox_state = iio_priv(indio_dev); |
| 64 | struct hid_sensor_hub_device *hsdev; | 87 | struct hid_sensor_hub_device *hsdev; |
| 65 | int report_id = -1; | 88 | int report_id; |
| 66 | u32 address; | 89 | u32 address; |
| 67 | int ret_type; | 90 | int ret_type; |
| 68 | s32 min; | 91 | s32 min; |
| @@ -71,29 +94,23 @@ static int prox_read_raw(struct iio_dev *indio_dev, · 2 unmodified lines | |||
| 71 | *val2 = 0; | 94 | *val2 = 0; |
| 72 | switch (mask) { | 95 | switch (mask) { |
| 73 | case IIO_CHAN_INFO_RAW: | 96 | case IIO_CHAN_INFO_RAW: |
| 74 | switch (chan->scan_index) { | 97 | if (chan->scan_index >= prox_state->num_channels) |
| 75 | case CHANNEL_SCAN_INDEX_PRESENCE: | ||
| 76 | report_id = prox_state->prox_attr.report_id; | ||
| 77 | min = prox_state->prox_attr.logical_minimum; | ||
| 78 | address = HID_USAGE_SENSOR_HUMAN_PRESENCE; | ||
| 79 | hsdev = prox_state->common_attributes.hsdev; | ||
| 80 | break; | ||
| 81 | default: | ||
| 82 | report_id = -1; | ||
| 83 | break; | ||
| 84 | } | ||
| 85 | if (report_id >= 0) { | ||
| 86 | hid_sensor_power_state(&prox_state->common_attributes, | ||
| 87 | true); | ||
| 88 | *val = sensor_hub_input_attr_get_raw_value( | ||
| 89 | hsdev, hsdev->usage, address, report_id, | ||
| 90 | SENSOR_HUB_SYNC, min < 0); | ||
| 91 | hid_sensor_power_state(&prox_state->common_attributes, | ||
| 92 | false); | ||
| 93 | } else { | ||
| 94 | *val = 0; | ||
| 95 | return -EINVAL; | 98 | return -EINVAL; |
| 96 | } | 99 | address = prox_state->channel2usage[chan->scan_index]; |
| 100 | report_id = prox_state->prox_attr[chan->scan_index].report_id; | ||
| 101 | hsdev = prox_state->common_attributes.hsdev; | ||
| 102 | min = prox_state->prox_attr[chan->scan_index].logical_minimum; | ||
| 103 | hid_sensor_power_state(&prox_state->common_attributes, true); | ||
| 104 | *val = sensor_hub_input_attr_get_raw_value(hsdev, | ||
| 105 | hsdev->usage, | ||
| 106 | address, | ||
| 107 | report_id, | ||
| 108 | SENSOR_HUB_SYNC, | ||
| 109 | min < 0); | ||
| 110 | if (prox_state->channel2usage[chan->scan_index] == | ||
| 111 | HID_USAGE_SENSOR_HUMAN_ATTENTION) | ||
| 112 | *val *= 100; | ||
| 113 | hid_sensor_power_state(&prox_state->common_attributes, false); | ||
| 97 | ret_type = IIO_VAL_INT; | 114 | ret_type = IIO_VAL_INT; |
| 98 | break; | 115 | break; |
| 99 | case IIO_CHAN_INFO_SCALE: | 116 | case IIO_CHAN_INFO_SCALE: |
| @@ -103,7 +120,7 @@ static int prox_read_raw(struct iio_dev *indio_dev, · 3 unmodified lines | |||
| 103 | break; | 120 | break; |
| 104 | case IIO_CHAN_INFO_OFFSET: | 121 | case IIO_CHAN_INFO_OFFSET: |
| 105 | *val = hid_sensor_convert_exponent( | 122 | *val = hid_sensor_convert_exponent( |
| 106 | prox_state->prox_attr.unit_expo); | 123 | prox_state->prox_attr[chan->scan_index].unit_expo); |
| 107 | ret_type = IIO_VAL_INT; | 124 | ret_type = IIO_VAL_INT; |
| 108 | break; | 125 | break; |
| 109 | case IIO_CHAN_INFO_SAMP_FREQ: | 126 | case IIO_CHAN_INFO_SAMP_FREQ: |
| @@ -153,14 +170,6 @@ static const struct iio_info prox_info = { · 43 unmodified lines | |||
| 153 | .write_raw = &prox_write_raw, | 170 | .write_raw = &prox_write_raw, |
| 154 | }; | 171 | }; |
| 155 | 172 | ||
| 156 | /* Function to push data to buffer */ | ||
| 157 | static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data, | ||
| 158 | int len) | ||
| 159 | { | ||
| 160 | dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); | ||
| 161 | iio_push_to_buffers(indio_dev, data); | ||
| 162 | } | ||
| 163 | |||
| 164 | /* Callback handler to send event after all samples are received and captured */ | 173 | /* Callback handler to send event after all samples are received and captured */ |
| 165 | static int prox_proc_event(struct hid_sensor_hub_device *hsdev, | 174 | static int prox_proc_event(struct hid_sensor_hub_device *hsdev, |
| 166 | unsigned usage_id, | 175 | unsigned usage_id, |
| @@ -170,10 +179,10 @@ static int prox_proc_event(struct hid_sensor_hub_device *hsdev, · 3 unmodified lines | |||
| 170 | struct prox_state *prox_state = iio_priv(indio_dev); | 179 | struct prox_state *prox_state = iio_priv(indio_dev); |
| 171 | 180 | ||
| 172 | dev_dbg(&indio_dev->dev, "prox_proc_event\n"); | 181 | dev_dbg(&indio_dev->dev, "prox_proc_event\n"); |
| 173 | if (atomic_read(&prox_state->common_attributes.data_ready)) | 182 | if (atomic_read(&prox_state->common_attributes.data_ready)) { |
| 174 | hid_sensor_push_data(indio_dev, | 183 | dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); |
| 175 | &prox_state->human_presence, | 184 | iio_push_to_buffers(indio_dev, &prox_state->human_presence); |
| 176 | sizeof(prox_state->human_presence)); | 185 | } |
| 177 | 186 | ||
| 178 | return 0; | 187 | return 0; |
| 179 | } | 188 | } |
| @@ -186,58 +195,77 @@ static int prox_capture_sample(struct hid_sensor_hub_device *hsdev, · 6 unmodified lines | |||
| 186 | { | 195 | { |
| 187 | struct iio_dev *indio_dev = platform_get_drvdata(priv); | 196 | struct iio_dev *indio_dev = platform_get_drvdata(priv); |
| 188 | struct prox_state *prox_state = iio_priv(indio_dev); | 197 | struct prox_state *prox_state = iio_priv(indio_dev); |
| 189 | int ret = -EINVAL; | 198 | int multiplier = 1; |
| 190 | 199 | int chan; | |
| 191 | switch (usage_id) { | 200 | |
| 192 | case HID_USAGE_SENSOR_HUMAN_PRESENCE: | 201 | for (chan = 0; chan < prox_state->num_channels; chan++) |
| 193 | switch (raw_len) { | 202 | if (prox_state->channel2usage[chan] == usage_id) |
| 194 | case 1: | ||
| 195 | prox_state->human_presence = *(u8 *)raw_data; | ||
| 196 | return 0; | ||
| 197 | case 4: | ||
| 198 | prox_state->human_presence = *(u32 *)raw_data; | ||
| 199 | return 0; | ||
| 200 | default: | ||
| 201 | break; | 203 | break; |
| 202 | } | 204 | if (chan == prox_state->num_channels) |
| 203 | break; | 205 | return -EINVAL; |
| 206 | |||
| 207 | if (usage_id == HID_USAGE_SENSOR_HUMAN_ATTENTION) | ||
| 208 | multiplier = 100; | ||
| 209 | |||
| 210 | switch (raw_len) { | ||
| 211 | case 1: | ||
| 212 | prox_state->human_presence[chan] = *(u8 *)raw_data * multiplier; | ||
| 213 | return 0; | ||
| 214 | case 4: | ||
| 215 | prox_state->human_presence[chan] = *(u32 *)raw_data * multiplier; | ||
| 216 | return 0; | ||
| 204 | } | 217 | } |
| 205 | 218 | ||
| 206 | return ret; | 219 | return -EINVAL; |
| 207 | } | 220 | } |
| 208 | 221 | ||
| 209 | /* Parse report which is specific to an usage id*/ | 222 | /* Parse report which is specific to an usage id*/ |
| 210 | static int prox_parse_report(struct platform_device *pdev, | 223 | static int prox_parse_report(struct platform_device *pdev, |
| 211 | struct hid_sensor_hub_device *hsdev, | 224 | struct hid_sensor_hub_device *hsdev, |
| 212 | struct iio_chan_spec *channels, | ||
| 213 | unsigned usage_id, | ||
| 214 | struct prox_state *st) | 225 | struct prox_state *st) |
| 215 | { | 226 | { |
| 227 | struct iio_chan_spec *channels = st->channels; | ||
| 228 | int index = 0; | ||
| 216 | int ret; | 229 | int ret; |
| 230 | int i; | ||
| 231 | |||
| 232 | for (i = 0; i < MAX_CHANNELS; i++) { | ||
| 233 | u32 usage_id = prox_usage_ids[i]; | ||
| 234 | |||
| 235 | ret = sensor_hub_input_get_attribute_info(hsdev, | ||
| 236 | HID_INPUT_REPORT, | ||
| 237 | hsdev->usage, | ||
| 238 | usage_id, | ||
| 239 | &st->prox_attr[index]); | ||
| 240 | if (ret < 0) | ||
| 241 | continue; | ||
| 242 | st->channel2usage[index] = usage_id; | ||
| 243 | st->scan_mask[0] |= BIT(index); | ||
| 244 | channels[index] = prox_channels[i]; | ||
| 245 | channels[index].scan_index = index; | ||
| 246 | prox_adjust_channel_bit_mask(channels, index, | ||
| 247 | st->prox_attr[index].size); | ||
| 248 | dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr[index].index, | ||
| 249 | st->prox_attr[index].report_id); | ||
| 250 | index++; | ||
| 251 | } | ||
| 217 | 252 | ||
| 218 | ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT, | 253 | if (!index) |
| 219 | usage_id, | ||
| 220 | HID_USAGE_SENSOR_HUMAN_PRESENCE, | ||
| 221 | &st->prox_attr); | ||
| 222 | if (ret < 0) | ||
| 223 | return ret; | 254 | return ret; |
| 224 | prox_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_PRESENCE, | ||
| 225 | st->prox_attr.size); | ||
| 226 | 255 | ||
| 227 | dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr.index, | 256 | st->num_channels = index; |
| 228 | st->prox_attr.report_id); | ||
| 229 | 257 | ||
| 230 | return ret; | 258 | return 0; |
| 231 | } | 259 | } |
| 232 | 260 | ||
| 233 | /* Function to initialize the processing for usage id */ | 261 | /* Function to initialize the processing for usage id */ |
| 234 | static int hid_prox_probe(struct platform_device *pdev) | 262 | static int hid_prox_probe(struct platform_device *pdev) |
| 235 | { | 263 | { |
| 264 | struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); | ||
| 236 | int ret = 0; | 265 | int ret = 0; |
| 237 | static const char *name = "prox"; | 266 | static const char *name = "prox"; |
| 238 | struct iio_dev *indio_dev; | 267 | struct iio_dev *indio_dev; |
| 239 | struct prox_state *prox_state; | 268 | struct prox_state *prox_state; |
| 240 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | ||
| 241 | 269 | ||
| 242 | indio_dev = devm_iio_device_alloc(&pdev->dev, | 270 | indio_dev = devm_iio_device_alloc(&pdev->dev, |
| 243 | sizeof(struct prox_state)); | 271 | sizeof(struct prox_state)); |
| @@ -258,22 +286,15 @@ static int hid_prox_probe(struct platform_device *pdev) · 14 unmodified lines | |||
| 258 | return ret; | 286 | return ret; |
| 259 | } | 287 | } |
| 260 | 288 | ||
| 261 | indio_dev->channels = devm_kmemdup(&pdev->dev, prox_channels, | 289 | ret = prox_parse_report(pdev, hsdev, prox_state); |
| 262 | sizeof(prox_channels), GFP_KERNEL); | ||
| 263 | if (!indio_dev->channels) { | ||
| 264 | dev_err(&pdev->dev, "failed to duplicate channels\n"); | ||
| 265 | return -ENOMEM; | ||
| 266 | } | ||
| 267 | |||
| 268 | ret = prox_parse_report(pdev, hsdev, | ||
| 269 | (struct iio_chan_spec *)indio_dev->channels, | ||
| 270 | hsdev->usage, prox_state); | ||
| 271 | if (ret) { | 290 | if (ret) { |
| 272 | dev_err(&pdev->dev, "failed to setup attributes\n"); | 291 | dev_err(&pdev->dev, "failed to setup attributes\n"); |
| 273 | return ret; | 292 | return ret; |
| 274 | } | 293 | } |
| 275 | 294 | ||
| 276 | indio_dev->num_channels = ARRAY_SIZE(prox_channels); | 295 | indio_dev->num_channels = prox_state->num_channels; |
| 296 | indio_dev->channels = prox_state->channels; | ||
| 297 | indio_dev->available_scan_masks = prox_state->scan_mask; | ||
| 277 | indio_dev->info = &prox_info; | 298 | indio_dev->info = &prox_info; |
| 278 | indio_dev->name = name; | 299 | indio_dev->name = name; |
| 279 | indio_dev->modes = INDIO_DIRECT_MODE; | 300 | indio_dev->modes = INDIO_DIRECT_MODE; |
| @@ -315,7 +336,7 @@ error_remove_trigger: · 35 unmodified lines | |||
| 315 | /* Function to deinitialize the processing for usage id */ | 336 | /* Function to deinitialize the processing for usage id */ |
| 316 | static void hid_prox_remove(struct platform_device *pdev) | 337 | static void hid_prox_remove(struct platform_device *pdev) |
| 317 | { | 338 | { |
| 318 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | 339 | struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev); |
| 319 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); | 340 | struct iio_dev *indio_dev = platform_get_drvdata(pdev); |
| 320 | struct prox_state *prox_state = iio_priv(indio_dev); | 341 | struct prox_state *prox_state = iio_priv(indio_dev); |
| 321 | 342 | ||
| @@ -344,7 +365,7 @@ static struct platform_driver hid_prox_platform_driver = { · 22 unmodified lines | |||
| 344 | .pm = &hid_sensor_pm_ops, | 365 | .pm = &hid_sensor_pm_ops, |
| 345 | }, | 366 | }, |
| 346 | .probe = hid_prox_probe, | 367 | .probe = hid_prox_probe, |
| 347 | .remove_new = hid_prox_remove, | 368 | .remove = hid_prox_remove, |
| 348 | }; | 369 | }; |
| 349 | module_platform_driver(hid_prox_platform_driver); | 370 | module_platform_driver(hid_prox_platform_driver); |
| 350 | 371 | ||
| @@ -271,7 +271,7 @@ static int iqs621_als_write_event_config(struct iio_dev *indio_dev, · 270 unmodified lines | |||
| 271 | const struct iio_chan_spec *chan, | 271 | const struct iio_chan_spec *chan, |
| 272 | enum iio_event_type type, | 272 | enum iio_event_type type, |
| 273 | enum iio_event_direction dir, | 273 | enum iio_event_direction dir, |
| 274 | int state) | 274 | bool state) |
| 275 | { | 275 | { |
| 276 | struct iqs621_als_private *iqs621_als = iio_priv(indio_dev); | 276 | struct iqs621_als_private *iqs621_als = iio_priv(indio_dev); |
| 277 | struct iqs62x_core *iqs62x = iqs621_als->iqs62x; | 277 | struct iqs62x_core *iqs62x = iqs621_als->iqs62x; |
| @@ -8,17 +8,18 @@ · 7 unmodified lines | |||
| 8 | * Copyright (c) 2010, NVIDIA Corporation. | 8 | * Copyright (c) 2010, NVIDIA Corporation. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/i2c.h> | 11 | #include <linux/i2c.h> |
| 13 | #include <linux/err.h> | 12 | #include <linux/err.h> |
| 13 | #include <linux/mod_devicetable.h> | ||
| 14 | #include <linux/module.h> | ||
| 14 | #include <linux/mutex.h> | 15 | #include <linux/mutex.h> |
| 15 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
| 16 | #include <linux/regmap.h> | 17 | #include <linux/regmap.h> |
| 17 | #include <linux/regulator/consumer.h> | 18 | #include <linux/regulator/consumer.h> |
| 18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 20 | |||
| 19 | #include <linux/iio/iio.h> | 21 | #include <linux/iio/iio.h> |
| 20 | #include <linux/iio/sysfs.h> | 22 | #include <linux/iio/sysfs.h> |
| 21 | #include <linux/acpi.h> | ||
| 22 | 23 | ||
| 23 | #define ISL29018_CONV_TIME_MS 100 | 24 | #define ISL29018_CONV_TIME_MS 100 |
| 24 | 25 | ||
| @@ -687,20 +688,6 @@ static const struct isl29018_chip_info isl29018_chip_info_tbl[] = { · 662 unmodified lines | |||
| 687 | }, | 688 | }, |
| 688 | }; | 689 | }; |
| 689 | 690 | ||
| 690 | static const char *isl29018_match_acpi_device(struct device *dev, int *data) | ||
| 691 | { | ||
| 692 | const struct acpi_device_id *id; | ||
| 693 | |||
| 694 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
| 695 | |||
| 696 | if (!id) | ||
| 697 | return NULL; | ||
| 698 | |||
| 699 | *data = (int)id->driver_data; | ||
| 700 | |||
| 701 | return dev_name(dev); | ||
| 702 | } | ||
| 703 | |||
| 704 | static void isl29018_disable_regulator_action(void *_data) | 691 | static void isl29018_disable_regulator_action(void *_data) |
| 705 | { | 692 | { |
| 706 | struct isl29018_chip *chip = _data; | 693 | struct isl29018_chip *chip = _data; |
| @@ -716,9 +703,10 @@ static int isl29018_probe(struct i2c_client *client) · 9 unmodified lines | |||
| 716 | const struct i2c_device_id *id = i2c_client_get_device_id(client); | 703 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
| 717 | struct isl29018_chip *chip; | 704 | struct isl29018_chip *chip; |
| 718 | struct iio_dev *indio_dev; | 705 | struct iio_dev *indio_dev; |
| 706 | const void *ddata = NULL; | ||
| 707 | const char *name; | ||
| 708 | int dev_id; | ||
| 719 | int err; | 709 | int err; |
| 720 | const char *name = NULL; | ||
| 721 | int dev_id = 0; | ||
| 722 | 710 | ||
| 723 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); | 711 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); |
| 724 | if (!indio_dev) | 712 | if (!indio_dev) |
| @@ -731,11 +719,11 @@ static int isl29018_probe(struct i2c_client *client) · 6 unmodified lines | |||
| 731 | if (id) { | 719 | if (id) { |
| 732 | name = id->name; | 720 | name = id->name; |
| 733 | dev_id = id->driver_data; | 721 | dev_id = id->driver_data; |
| 722 | } else { | ||
| 723 | name = iio_get_acpi_device_name_and_data(&client->dev, &ddata); | ||
| 724 | dev_id = (intptr_t)ddata; | ||
| 734 | } | 725 | } |
| 735 | 726 | ||
| 736 | if (ACPI_HANDLE(&client->dev)) | ||
| 737 | name = isl29018_match_acpi_device(&client->dev, &dev_id); | ||
| 738 | |||
| 739 | mutex_init(&chip->lock); | 727 | mutex_init(&chip->lock); |
| 740 | 728 | ||
| 741 | chip->type = dev_id; | 729 | chip->type = dev_id; |
| @@ -832,15 +820,13 @@ static int isl29018_resume(struct device *dev) · 90 unmodified lines | |||
| 832 | static DEFINE_SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend, | 820 | static DEFINE_SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend, |
| 833 | isl29018_resume); | 821 | isl29018_resume); |
| 834 | 822 | ||
| 835 | #ifdef CONFIG_ACPI | ||
| 836 | static const struct acpi_device_id isl29018_acpi_match[] = { | 823 | static const struct acpi_device_id isl29018_acpi_match[] = { |
| 837 | {"ISL29018", isl29018}, | 824 | {"ISL29018", isl29018}, |
| 838 | {"ISL29023", isl29023}, | 825 | {"ISL29023", isl29023}, |
| 839 | {"ISL29035", isl29035}, | 826 | {"ISL29035", isl29035}, |
| 840 | {}, | 827 | {} |
| 841 | }; | 828 | }; |
| 842 | MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match); | 829 | MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match); |
| 843 | #endif | ||
| 844 | 830 | ||
| 845 | static const struct i2c_device_id isl29018_id[] = { | 831 | static const struct i2c_device_id isl29018_id[] = { |
| 846 | {"isl29018", isl29018}, | 832 | {"isl29018", isl29018}, |
| @@ -854,14 +840,14 @@ static const struct of_device_id isl29018_of_match[] = { · 7 unmodified lines | |||
| 854 | { .compatible = "isil,isl29018", }, | 840 | { .compatible = "isil,isl29018", }, |
| 855 | { .compatible = "isil,isl29023", }, | 841 | { .compatible = "isil,isl29023", }, |
| 856 | { .compatible = "isil,isl29035", }, | 842 | { .compatible = "isil,isl29035", }, |
| 857 | { }, | 843 | { } |
| 858 | }; | 844 | }; |
| 859 | MODULE_DEVICE_TABLE(of, isl29018_of_match); | 845 | MODULE_DEVICE_TABLE(of, isl29018_of_match); |
| 860 | 846 | ||
| 861 | static struct i2c_driver isl29018_driver = { | 847 | static struct i2c_driver isl29018_driver = { |
| 862 | .driver = { | 848 | .driver = { |
| 863 | .name = "isl29018", | 849 | .name = "isl29018", |
| 864 | .acpi_match_table = ACPI_PTR(isl29018_acpi_match), | 850 | .acpi_match_table = isl29018_acpi_match, |
| 865 | .pm = pm_sleep_ptr(&isl29018_pm_ops), | 851 | .pm = pm_sleep_ptr(&isl29018_pm_ops), |
| 866 | .of_match_table = isl29018_of_match, | 852 | .of_match_table = isl29018_of_match, |
| 867 | }, | 853 | }, |
| @@ -754,7 +754,7 @@ static int lm3533_als_set_resistor(struct lm3533_als *als, u8 val) · 753 unmodified lines | |||
| 754 | } | 754 | } |
| 755 | 755 | ||
| 756 | static int lm3533_als_setup(struct lm3533_als *als, | 756 | static int lm3533_als_setup(struct lm3533_als *als, |
| 757 | struct lm3533_als_platform_data *pdata) | 757 | const struct lm3533_als_platform_data *pdata) |
| 758 | { | 758 | { |
| 759 | int ret; | 759 | int ret; |
| 760 | 760 | ||
| @@ -828,8 +828,8 @@ static const struct iio_info lm3533_als_info = { · 67 unmodified lines | |||
| 828 | 828 | ||
| 829 | static int lm3533_als_probe(struct platform_device *pdev) | 829 | static int lm3533_als_probe(struct platform_device *pdev) |
| 830 | { | 830 | { |
| 831 | const struct lm3533_als_platform_data *pdata; | ||
| 831 | struct lm3533 *lm3533; | 832 | struct lm3533 *lm3533; |
| 832 | struct lm3533_als_platform_data *pdata; | ||
| 833 | struct lm3533_als *als; | 833 | struct lm3533_als *als; |
| 834 | struct iio_dev *indio_dev; | 834 | struct iio_dev *indio_dev; |
| 835 | int ret; | 835 | int ret; |
| @@ -838,7 +838,7 @@ static int lm3533_als_probe(struct platform_device *pdev) · 2 unmodified lines | |||
| 838 | if (!lm3533) | 838 | if (!lm3533) |
| 839 | return -EINVAL; | 839 | return -EINVAL; |
| 840 | 840 | ||
| 841 | pdata = pdev->dev.platform_data; | 841 | pdata = dev_get_platdata(&pdev->dev); |
| 842 | if (!pdata) { | 842 | if (!pdata) { |
| 843 | dev_err(&pdev->dev, "no platform data\n"); | 843 | dev_err(&pdev->dev, "no platform data\n"); |
| 844 | return -EINVAL; | 844 | return -EINVAL; |
| @@ -912,7 +912,7 @@ static struct platform_driver lm3533_als_driver = { · 67 unmodified lines | |||
| 912 | .name = "lm3533-als", | 912 | .name = "lm3533-als", |
| 913 | }, | 913 | }, |
| 914 | .probe = lm3533_als_probe, | 914 | .probe = lm3533_als_probe, |
| 915 | .remove_new = lm3533_als_remove, | 915 | .remove = lm3533_als_remove, |
| 916 | }; | 916 | }; |
| 917 | module_platform_driver(lm3533_als_driver); | 917 | module_platform_driver(lm3533_als_driver); |
| 918 | 918 | ||
| @@ -18,14 +18,18 @@ · 17 unmodified lines | |||
| 18 | * - Interrupt support | 18 | * - Interrupt support |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #include <linux/bitfield.h> | ||
| 22 | #include <linux/device.h> | ||
| 21 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
| 24 | #include <linux/irq.h> | ||
| 25 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/math.h> | 26 | #include <linux/math.h> |
| 23 | #include <linux/module.h> | 27 | #include <linux/module.h> |
| 24 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
| 25 | #include <linux/regmap.h> | 29 | #include <linux/regmap.h> |
| 26 | #include <linux/bitfield.h> | ||
| 27 | 30 | ||
| 28 | #include <linux/iio/iio.h> | 31 | #include <linux/iio/iio.h> |
| 32 | #include <linux/iio/events.h> | ||
| 29 | 33 | ||
| 30 | #include <linux/unaligned.h> | 34 | #include <linux/unaligned.h> |
| 31 | 35 | ||
| @@ -33,18 +37,27 @@ · 1 unmodified line | |||
| 33 | #define LTR390_ALS_UVS_MEAS_RATE 0x04 | 37 | #define LTR390_ALS_UVS_MEAS_RATE 0x04 |
| 34 | #define LTR390_ALS_UVS_GAIN 0x05 | 38 | #define LTR390_ALS_UVS_GAIN 0x05 |
| 35 | #define LTR390_PART_ID 0x06 | 39 | #define LTR390_PART_ID 0x06 |
| 40 | #define LTR390_MAIN_STATUS 0x07 | ||
| 36 | #define LTR390_ALS_DATA 0x0D | 41 | #define LTR390_ALS_DATA 0x0D |
| 37 | #define LTR390_UVS_DATA 0x10 | 42 | #define LTR390_UVS_DATA 0x10 |
| 38 | #define LTR390_INT_CFG 0x19 | 43 | #define LTR390_INT_CFG 0x19 |
| 44 | #define LTR390_INT_PST 0x1A | ||
| 45 | #define LTR390_THRESH_UP 0x21 | ||
| 46 | #define LTR390_THRESH_LOW 0x24 | ||
| 39 | 47 | ||
| 40 | #define LTR390_PART_NUMBER_ID 0xb | 48 | #define LTR390_PART_NUMBER_ID 0xb |
| 41 | #define LTR390_ALS_UVS_GAIN_MASK 0x07 | 49 | #define LTR390_ALS_UVS_GAIN_MASK GENMASK(2, 0) |
| 42 | #define LTR390_ALS_UVS_INT_TIME_MASK 0x70 | 50 | #define LTR390_ALS_UVS_MEAS_RATE_MASK GENMASK(2, 0) |
| 51 | #define LTR390_ALS_UVS_INT_TIME_MASK GENMASK(6, 4) | ||
| 43 | #define LTR390_ALS_UVS_INT_TIME(x) FIELD_PREP(LTR390_ALS_UVS_INT_TIME_MASK, (x)) | 52 | #define LTR390_ALS_UVS_INT_TIME(x) FIELD_PREP(LTR390_ALS_UVS_INT_TIME_MASK, (x)) |
| 53 | #define LTR390_INT_PST_MASK GENMASK(7, 4) | ||
| 54 | #define LTR390_INT_PST_VAL(x) FIELD_PREP(LTR390_INT_PST_MASK, (x)) | ||
| 44 | 55 | ||
| 45 | #define LTR390_SW_RESET BIT(4) | 56 | #define LTR390_SW_RESET BIT(4) |
| 46 | #define LTR390_UVS_MODE BIT(3) | 57 | #define LTR390_UVS_MODE BIT(3) |
| 47 | #define LTR390_SENSOR_ENABLE BIT(1) | 58 | #define LTR390_SENSOR_ENABLE BIT(1) |
| 59 | #define LTR390_LS_INT_EN BIT(2) | ||
| 60 | #define LTR390_LS_INT_SEL_UVS BIT(5) | ||
441 more lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 338 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 496 lines aren’t shown here.
This diff is large: its 762 lines aren’t shown here.
This diff is large: its 323 lines aren’t shown here.
This diff is large: its 370 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 495 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 1069 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 141 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 279 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 217 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 1564 lines aren’t shown here.
This diff is large: its 129 lines aren’t shown here.
This diff is large: its 2089 lines aren’t shown here.
This diff is large: its 178 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 1931 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 721 lines aren’t shown here.
This diff is large: its 360 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 919 lines aren’t shown here.
This diff is large: its 840 lines aren’t shown here.
This diff is large: its 157 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 143 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 137 lines aren’t shown here.
This diff is large: its 190 lines aren’t shown here.
This diff is large: its 138 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 337 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 257 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.