Pull staging / IIO driver updates from Greg KH: "Here is the big set of IIO and staging driver patches for 5.14-rc1. Loads of IIO driver updates and additions in here, the shortlog has the full details. For the staging side, we moved a few drivers out of staging, and deleted the kpc2000 drivers as the original developer asked us to because no one was working on them anymore. Also in here are loads of coding style cleanups due to different intern projects focusing on the staging tree to try to get experience doing kernel development. All of these have been in the linux-next tree for a while with no reported problems" * tag 'staging-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (744 commits) staging: hi6421-spmi-pmic: cleanup some macros staging: hi6421-spmi-pmic: change identation of a table staging: hi6421-spmi-pmic: change a return code staging: hi6421-spmi-pmic: better name IRQs staging: hi6421-spmi-pmic: use devm_request_threaded_irq() staging: hisilicon,hi6421-spmi-pmic.yaml: cleanup descriptions spmi: hisi-spmi-controller: move driver from staging phy: phy-hi3670-usb3: move driver from staging into phy staging: rtl8188eu: remove include/rtw_debug.h header staging: rtl8188eu: remove GlobalDebugLevel variable staging: rtl8188eu: remove DRIVER_PREFIX preprocessor definition staging: rtl8188eu: remove RT_TRACE macro staging: rtl8188eu: remove all RT_TRACE calls from hal/rtl8188eu_recv.c staging: rtl8188eu: remove all RT_TRACE calls from hal/hal_intf.c staging: rtl8188eu: remove all RT_TRACE calls from hal/rtl8188eu_xmit.c staging: rtl8188eu: remove all RT_TRACE calls from core/rtw_xmit.c staging: rtl8188eu: remove all RT_TRACE calls from core/rtw_pwrctrl.c staging: rtl8188eu: remove all RT_TRACE calls from core/rtw_recv.c staging: rtl8188eu: remove all RT_TRACE calls from core/rtw_ioctl_set.c staging: rtl8188eu: remove all RT_TRACE calls from core/rtw_ieee80211.c ...
Unified · Split
| @@ -0,0 +1,182 @@ | |||
| 1 | What: /sys/bus/iio/devices/iio:deviceX/buffer/length | ||
| 2 | KernelVersion: 2.6.35 | ||
| 3 | Contact: linux-iio@vger.kernel.org | ||
| 4 | Description: | ||
| 5 | Number of scans contained by the buffer. | ||
| 6 | |||
| 7 | Since Kernel 5.11, multiple buffers are supported. | ||
| 8 | so, it is better to use, instead: | ||
| 9 | /sys/bus/iio/devices/iio:deviceX/bufferY/length | ||
| 10 | |||
| 11 | What: /sys/bus/iio/devices/iio:deviceX/buffer/enable | ||
| 12 | KernelVersion: 2.6.35 | ||
| 13 | Contact: linux-iio@vger.kernel.org | ||
| 14 | Description: | ||
| 15 | Actually start the buffer capture up. Will start trigger | ||
| 16 | if first device and appropriate. | ||
| 17 | |||
| 18 | Since Kernel 5.11, multiple buffers are supported. | ||
| 19 | so, it is better to use, instead: | ||
| 20 | /sys/bus/iio/devices/iio:deviceX/bufferY/enable | ||
| 21 | |||
| 22 | What: /sys/bus/iio/devices/iio:deviceX/scan_elements | ||
| 23 | KernelVersion: 2.6.37 | ||
| 24 | Contact: linux-iio@vger.kernel.org | ||
| 25 | Description: | ||
| 26 | Directory containing interfaces for elements that will be | ||
| 27 | captured for a single triggered sample set in the buffer. | ||
| 28 | |||
| 29 | Since kernel 5.11 the scan_elements attributes are merged into | ||
| 30 | the bufferY directory, to be configurable per buffer. | ||
| 31 | |||
| 32 | What: /sys/.../iio:deviceX/scan_elements/in_accel_x_en | ||
| 33 | What: /sys/.../iio:deviceX/scan_elements/in_accel_y_en | ||
| 34 | What: /sys/.../iio:deviceX/scan_elements/in_accel_z_en | ||
| 35 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_x_en | ||
| 36 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_y_en | ||
| 37 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_z_en | ||
| 38 | What: /sys/.../iio:deviceX/scan_elements/in_magn_x_en | ||
| 39 | What: /sys/.../iio:deviceX/scan_elements/in_magn_y_en | ||
| 40 | What: /sys/.../iio:deviceX/scan_elements/in_magn_z_en | ||
| 41 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_en | ||
| 42 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_en | ||
| 43 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_tilt_comp_en | ||
| 44 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_tilt_comp_en | ||
| 45 | What: /sys/.../iio:deviceX/scan_elements/in_timestamp_en | ||
| 46 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_en | ||
| 47 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_en | ||
| 48 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY-voltageZ_en | ||
| 49 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_i_en | ||
| 50 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_q_en | ||
| 51 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_i_en | ||
| 52 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_q_en | ||
| 53 | What: /sys/.../iio:deviceX/scan_elements/in_incli_x_en | ||
| 54 | What: /sys/.../iio:deviceX/scan_elements/in_incli_y_en | ||
| 55 | What: /sys/.../iio:deviceX/scan_elements/in_pressureY_en | ||
| 56 | What: /sys/.../iio:deviceX/scan_elements/in_pressure_en | ||
| 57 | What: /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_en | ||
| 58 | What: /sys/.../iio:deviceX/scan_elements/in_proximity_en | ||
| 59 | KernelVersion: 2.6.37 | ||
| 60 | Contact: linux-iio@vger.kernel.org | ||
| 61 | Description: | ||
| 62 | Scan element control for triggered data capture. | ||
| 63 | |||
| 64 | Since kernel 5.11 the scan_elements attributes are merged into | ||
| 65 | the bufferY directory, to be configurable per buffer. | ||
| 66 | |||
| 67 | What: /sys/.../iio:deviceX/scan_elements/in_accel_type | ||
| 68 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_type | ||
| 69 | What: /sys/.../iio:deviceX/scan_elements/in_magn_type | ||
| 70 | What: /sys/.../iio:deviceX/scan_elements/in_incli_type | ||
| 71 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_type | ||
| 72 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_type | ||
| 73 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_type | ||
| 74 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_i_type | ||
| 75 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_q_type | ||
| 76 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_i_type | ||
| 77 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_q_type | ||
| 78 | What: /sys/.../iio:deviceX/scan_elements/in_timestamp_type | ||
| 79 | What: /sys/.../iio:deviceX/scan_elements/in_pressureY_type | ||
| 80 | What: /sys/.../iio:deviceX/scan_elements/in_pressure_type | ||
| 81 | What: /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_type | ||
| 82 | What: /sys/.../iio:deviceX/scan_elements/in_proximity_type | ||
| 83 | KernelVersion: 2.6.37 | ||
| 84 | Contact: linux-iio@vger.kernel.org | ||
| 85 | Description: | ||
| 86 | Description of the scan element data storage within the buffer | ||
| 87 | and hence the form in which it is read from user-space. | ||
| 88 | Form is [be|le]:[s|u]bits/storagebits[>>shift]. | ||
| 89 | be or le specifies big or little endian. s or u specifies if | ||
| 90 | signed (2's complement) or unsigned. bits is the number of bits | ||
| 91 | of data and storagebits is the space (after padding) that it | ||
| 92 | occupies in the buffer. shift if specified, is the shift that | ||
| 93 | needs to be applied prior to masking out unused bits. Some | ||
| 94 | devices put their data in the middle of the transferred elements | ||
| 95 | with additional information on both sides. Note that some | ||
| 96 | devices will have additional information in the unused bits | ||
| 97 | so to get a clean value, the bits value must be used to mask | ||
| 98 | the buffer output value appropriately. The storagebits value | ||
| 99 | also specifies the data alignment. So s48/64>>2 will be a | ||
| 100 | signed 48 bit integer stored in a 64 bit location aligned to | ||
| 101 | a 64 bit boundary. To obtain the clean value, shift right 2 | ||
| 102 | and apply a mask to zero the top 16 bits of the result. | ||
| 103 | For other storage combinations this attribute will be extended | ||
| 104 | appropriately. | ||
| 105 | |||
| 106 | Since kernel 5.11 the scan_elements attributes are merged into | ||
| 107 | the bufferY directory, to be configurable per buffer. | ||
| 108 | |||
| 109 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_index | ||
| 110 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_index | ||
| 111 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_i_index | ||
| 112 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_q_index | ||
| 113 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_i_index | ||
| 114 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_q_index | ||
| 115 | What: /sys/.../iio:deviceX/scan_elements/in_accel_x_index | ||
| 116 | What: /sys/.../iio:deviceX/scan_elements/in_accel_y_index | ||
| 117 | What: /sys/.../iio:deviceX/scan_elements/in_accel_z_index | ||
| 118 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_x_index | ||
| 119 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_y_index | ||
| 120 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_z_index | ||
| 121 | What: /sys/.../iio:deviceX/scan_elements/in_magn_x_index | ||
| 122 | What: /sys/.../iio:deviceX/scan_elements/in_magn_y_index | ||
| 123 | What: /sys/.../iio:deviceX/scan_elements/in_magn_z_index | ||
| 124 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_index | ||
| 125 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_index | ||
| 126 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_tilt_comp_index | ||
| 127 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_tilt_comp_index | ||
| 128 | What: /sys/.../iio:deviceX/scan_elements/in_incli_x_index | ||
| 129 | What: /sys/.../iio:deviceX/scan_elements/in_incli_y_index | ||
| 130 | What: /sys/.../iio:deviceX/scan_elements/in_timestamp_index | ||
| 131 | What: /sys/.../iio:deviceX/scan_elements/in_pressureY_index | ||
| 132 | What: /sys/.../iio:deviceX/scan_elements/in_pressure_index | ||
| 133 | What: /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_index | ||
| 134 | What: /sys/.../iio:deviceX/scan_elements/in_proximity_index | ||
| 135 | KernelVersion: 2.6.37 | ||
| 136 | Description: | ||
| 137 | A single positive integer specifying the position of this | ||
| 138 | scan element in the buffer. Note these are not dependent on | ||
| 139 | what is enabled and may not be contiguous. Thus for user-space | ||
| 140 | to establish the full layout these must be used in conjunction | ||
| 141 | with all _en attributes to establish which channels are present, | ||
| 142 | and the relevant _type attributes to establish the data storage | ||
| 143 | format. | ||
| 144 | |||
| 145 | Since kernel 5.11 the scan_elements attributes are merged into | ||
| 146 | the bufferY directory, to be configurable per buffer. | ||
| 147 | |||
| 148 | What: /sys/bus/iio/devices/iio:deviceX/buffer/watermark | ||
| 149 | KernelVersion: 4.2 | ||
| 150 | Contact: linux-iio@vger.kernel.org | ||
| 151 | Description: | ||
| 152 | A single positive integer specifying the maximum number of scan | ||
| 153 | elements to wait for. | ||
| 154 | |||
| 155 | Poll will block until the watermark is reached. | ||
| 156 | |||
| 157 | Blocking read will wait until the minimum between the requested | ||
| 158 | read amount or the low water mark is available. | ||
| 159 | |||
| 160 | Non-blocking read will retrieve the available samples from the | ||
| 161 | buffer even if there are less samples then watermark level. This | ||
| 162 | allows the application to block on poll with a timeout and read | ||
| 163 | the available samples after the timeout expires and thus have a | ||
| 164 | maximum delay guarantee. | ||
| 165 | |||
| 166 | Since Kernel 5.11, multiple buffers are supported. | ||
| 167 | so, it is better to use, instead: | ||
| 168 | /sys/bus/iio/devices/iio:deviceX/bufferY/watermark | ||
| 169 | |||
| 170 | What: /sys/bus/iio/devices/iio:deviceX/buffer/data_available | ||
| 171 | KernelVersion: 4.16 | ||
| 172 | Contact: linux-iio@vger.kernel.org | ||
| 173 | Description: | ||
| 174 | A read-only value indicating the bytes of data available in the | ||
| 175 | buffer. In the case of an output buffer, this indicates the | ||
| 176 | amount of empty space available to write data to. In the case of | ||
| 177 | an input buffer, this indicates the amount of data available for | ||
| 178 | reading. | ||
| 179 | |||
| 180 | Since Kernel 5.11, multiple buffers are supported. | ||
| 181 | so, it is better to use, instead: | ||
| 182 | /sys/bus/iio/devices/iio:deviceX/bufferY/data_available | ||
| @@ -57,6 +57,7 @@ Description: · 56 unmodified lines | |||
| 57 | What: /sys/bus/counter/devices/counterX/countY/count_mode_available | 57 | What: /sys/bus/counter/devices/counterX/countY/count_mode_available |
| 58 | What: /sys/bus/counter/devices/counterX/countY/error_noise_available | 58 | What: /sys/bus/counter/devices/counterX/countY/error_noise_available |
| 59 | What: /sys/bus/counter/devices/counterX/countY/function_available | 59 | What: /sys/bus/counter/devices/counterX/countY/function_available |
| 60 | What: /sys/bus/counter/devices/counterX/countY/prescaler_available | ||
| 60 | What: /sys/bus/counter/devices/counterX/countY/signalZ_action_available | 61 | What: /sys/bus/counter/devices/counterX/countY/signalZ_action_available |
| 61 | KernelVersion: 5.2 | 62 | KernelVersion: 5.2 |
| 62 | Contact: linux-iio@vger.kernel.org | 63 | Contact: linux-iio@vger.kernel.org |
| @@ -154,6 +155,15 @@ Description: · 91 unmodified lines | |||
| 154 | Count Y. If possible, this should match the name of the | 155 | Count Y. If possible, this should match the name of the |
| 155 | respective channel as it appears in the device datasheet. | 156 | respective channel as it appears in the device datasheet. |
| 156 | 157 | ||
| 158 | What: /sys/bus/counter/devices/counterX/countY/prescaler | ||
| 159 | KernelVersion: 5.2 | ||
| 160 | Contact: linux-iio@vger.kernel.org | ||
| 161 | Description: | ||
| 162 | Configure the prescaler value associated with Count Y. | ||
| 163 | On the FlexTimer, the counter clock source passes through a | ||
| 164 | prescaler (i.e. a counter). This acts like a clock | ||
| 165 | divider. | ||
| 166 | |||
| 157 | What: /sys/bus/counter/devices/counterX/countY/preset | 167 | What: /sys/bus/counter/devices/counterX/countY/preset |
| 158 | KernelVersion: 5.2 | 168 | KernelVersion: 5.2 |
| 159 | Contact: linux-iio@vger.kernel.org | 169 | Contact: linux-iio@vger.kernel.org |
| @@ -193,6 +203,15 @@ Description: · 33 unmodified lines | |||
| 193 | both edges: | 203 | both edges: |
| 194 | Any state transition. | 204 | Any state transition. |
| 195 | 205 | ||
| 206 | What: /sys/bus/counter/devices/counterX/countY/spike_filter_ns | ||
| 207 | KernelVersion: 5.14 | ||
| 208 | Contact: linux-iio@vger.kernel.org | ||
| 209 | Description: | ||
| 210 | If the counter device supports programmable spike filter this | ||
| 211 | attribute indicates the value in nanoseconds where noise pulses | ||
| 212 | shorter or equal to configured value are ignored. Value 0 means | ||
| 213 | filter is disabled. | ||
| 214 | |||
| 196 | What: /sys/bus/counter/devices/counterX/name | 215 | What: /sys/bus/counter/devices/counterX/name |
| 197 | KernelVersion: 5.2 | 216 | KernelVersion: 5.2 |
| 198 | Contact: linux-iio@vger.kernel.org | 217 | Contact: linux-iio@vger.kernel.org |
| @@ -215,11 +234,45 @@ Description: · 16 unmodified lines | |||
| 215 | Read-only attribute that indicates the total number of Signals | 234 | Read-only attribute that indicates the total number of Signals |
| 216 | belonging to the Counter. | 235 | belonging to the Counter. |
| 217 | 236 | ||
| 218 | What: /sys/bus/counter/devices/counterX/signalY/signal | 237 | What: /sys/bus/counter/devices/counterX/signalY/cable_fault |
| 238 | KernelVersion: 5.7 | ||
| 239 | Contact: linux-iio@vger.kernel.org | ||
| 240 | Description: | ||
| 241 | Read-only attribute that indicates whether a differential | ||
| 242 | encoder cable fault (not connected or loose wires) is detected | ||
| 243 | for the respective channel of Signal Y. Valid attribute values | ||
| 244 | are boolean. Detection must first be enabled via the | ||
| 245 | corresponding cable_fault_enable attribute. | ||
| 246 | |||
| 247 | What: /sys/bus/counter/devices/counterX/signalY/cable_fault_enable | ||
| 248 | KernelVersion: 5.7 | ||
| 249 | Contact: linux-iio@vger.kernel.org | ||
| 250 | Description: | ||
| 251 | Whether detection of differential encoder cable faults for the | ||
| 252 | respective channel of Signal Y is enabled. Valid attribute | ||
| 253 | values are boolean. | ||
| 254 | |||
| 255 | What: /sys/bus/counter/devices/counterX/signalY/filter_clock_prescaler | ||
| 256 | KernelVersion: 5.7 | ||
| 257 | Contact: linux-iio@vger.kernel.org | ||
| 258 | Description: | ||
| 259 | Filter clock factor for input Signal Y. This prescaler value | ||
| 260 | affects the inputs of both quadrature pair signals. | ||
| 261 | |||
| 262 | What: /sys/bus/counter/devices/counterX/signalY/index_polarity | ||
| 219 | KernelVersion: 5.2 | 263 | KernelVersion: 5.2 |
| 220 | Contact: linux-iio@vger.kernel.org | 264 | Contact: linux-iio@vger.kernel.org |
| 221 | Description: | 265 | Description: |
| 222 | Signal data of Signal Y represented as a string. | 266 | Active level of index input Signal Y; irrelevant in |
| 267 | non-synchronous load mode. | ||
| 268 | |||
| 269 | What: /sys/bus/counter/devices/counterX/signalY/index_polarity_available | ||
| 270 | What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode_available | ||
| 271 | KernelVersion: 5.2 | ||
| 272 | Contact: linux-iio@vger.kernel.org | ||
| 273 | Description: | ||
| 274 | Discrete set of available values for the respective Signal Y | ||
| 275 | configuration are listed in this file. | ||
| 223 | 276 | ||
| 224 | What: /sys/bus/counter/devices/counterX/signalY/name | 277 | What: /sys/bus/counter/devices/counterX/signalY/name |
| 225 | KernelVersion: 5.2 | 278 | KernelVersion: 5.2 |
| @@ -228,3 +281,31 @@ Description: · 2 unmodified lines | |||
| 228 | Read-only attribute that indicates the device-specific name of | 281 | Read-only attribute that indicates the device-specific name of |
| 229 | Signal Y. If possible, this should match the name of the | 282 | Signal Y. If possible, this should match the name of the |
| 230 | respective signal as it appears in the device datasheet. | 283 | respective signal as it appears in the device datasheet. |
| 284 | |||
| 285 | What: /sys/bus/counter/devices/counterX/signalY/signal | ||
| 286 | KernelVersion: 5.2 | ||
| 287 | Contact: linux-iio@vger.kernel.org | ||
| 288 | Description: | ||
| 289 | Signal data of Signal Y represented as a string. | ||
| 290 | |||
| 291 | What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode | ||
| 292 | KernelVersion: 5.2 | ||
| 293 | Contact: linux-iio@vger.kernel.org | ||
| 294 | Description: | ||
| 295 | Configure the counter associated with Signal Y for | ||
| 296 | non-synchronous or synchronous load mode. Synchronous load mode | ||
| 297 | cannot be selected in non-quadrature (Pulse-Direction) clock | ||
| 298 | mode. | ||
| 299 | |||
| 300 | non-synchronous: | ||
| 301 | A logic low level is the active level at this index | ||
| 302 | input. The index function (as enabled via preset_enable) | ||
| 303 | is performed directly on the active level of the index | ||
| 304 | input. | ||
| 305 | |||
| 306 | synchronous: | ||
| 307 | Intended for interfacing with encoder Index output in | ||
| 308 | quadrature clock mode. The active level is configured | ||
| 309 | via index_polarity. The index function (as enabled via | ||
| 310 | preset_enable) is performed synchronously with the | ||
| 311 | quadrature clock on the active level of the index input. | ||
| @@ -1,61 +0,0 @@ | |||
| 1 | What: /sys/bus/counter/devices/counterX/signalY/cable_fault | ||
| 2 | KernelVersion: 5.7 | ||
| 3 | Contact: linux-iio@vger.kernel.org | ||
| 4 | Description: | ||
| 5 | Read-only attribute that indicates whether a differential | ||
| 6 | encoder cable fault (not connected or loose wires) is detected | ||
| 7 | for the respective channel of Signal Y. Valid attribute values | ||
| 8 | are boolean. Detection must first be enabled via the | ||
| 9 | corresponding cable_fault_enable attribute. | ||
| 10 | |||
| 11 | What: /sys/bus/counter/devices/counterX/signalY/cable_fault_enable | ||
| 12 | KernelVersion: 5.7 | ||
| 13 | Contact: linux-iio@vger.kernel.org | ||
| 14 | Description: | ||
| 15 | Whether detection of differential encoder cable faults for the | ||
| 16 | respective channel of Signal Y is enabled. Valid attribute | ||
| 17 | values are boolean. | ||
| 18 | |||
| 19 | What: /sys/bus/counter/devices/counterX/signalY/filter_clock_prescaler | ||
| 20 | KernelVersion: 5.7 | ||
| 21 | Contact: linux-iio@vger.kernel.org | ||
| 22 | Description: | ||
| 23 | Filter clock factor for input Signal Y. This prescaler value | ||
| 24 | affects the inputs of both quadrature pair signals. | ||
| 25 | |||
| 26 | What: /sys/bus/counter/devices/counterX/signalY/index_polarity | ||
| 27 | KernelVersion: 5.2 | ||
| 28 | Contact: linux-iio@vger.kernel.org | ||
| 29 | Description: | ||
| 30 | Active level of index input Signal Y; irrelevant in | ||
| 31 | non-synchronous load mode. | ||
| 32 | |||
| 33 | What: /sys/bus/counter/devices/counterX/signalY/index_polarity_available | ||
| 34 | What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode_available | ||
| 35 | KernelVersion: 5.2 | ||
| 36 | Contact: linux-iio@vger.kernel.org | ||
| 37 | Description: | ||
| 38 | Discrete set of available values for the respective Signal Y | ||
| 39 | configuration are listed in this file. | ||
| 40 | |||
| 41 | What: /sys/bus/counter/devices/counterX/signalY/synchronous_mode | ||
| 42 | KernelVersion: 5.2 | ||
| 43 | Contact: linux-iio@vger.kernel.org | ||
| 44 | Description: | ||
| 45 | Configure the counter associated with Signal Y for | ||
| 46 | non-synchronous or synchronous load mode. Synchronous load mode | ||
| 47 | cannot be selected in non-quadrature (Pulse-Direction) clock | ||
| 48 | mode. | ||
| 49 | |||
| 50 | non-synchronous: | ||
| 51 | A logic low level is the active level at this index | ||
| 52 | input. The index function (as enabled via preset_enable) | ||
| 53 | is performed directly on the active level of the index | ||
| 54 | input. | ||
| 55 | |||
| 56 | synchronous: | ||
| 57 | Intended for interfacing with encoder Index output in | ||
| 58 | quadrature clock mode. The active level is configured | ||
| 59 | via index_polarity. The index function (as enabled via | ||
| 60 | preset_enable) is performed synchronously with the | ||
| 61 | quadrature clock on the active level of the index input. | ||
| @@ -1,16 +0,0 @@ | |||
| 1 | What: /sys/bus/counter/devices/counterX/countY/prescaler_available | ||
| 2 | KernelVersion: 5.2 | ||
| 3 | Contact: linux-iio@vger.kernel.org | ||
| 4 | Description: | ||
| 5 | Discrete set of available values for the respective Count Y | ||
| 6 | configuration are listed in this file. Values are delimited by | ||
| 7 | newline characters. | ||
| 8 | |||
| 9 | What: /sys/bus/counter/devices/counterX/countY/prescaler | ||
| 10 | KernelVersion: 5.2 | ||
| 11 | Contact: linux-iio@vger.kernel.org | ||
| 12 | Description: | ||
| 13 | Configure the prescaler value associated with Count Y. | ||
| 14 | On the FlexTimer, the counter clock source passes through a | ||
| 15 | prescaler (i.e. a counter). This acts like a clock | ||
| 16 | divider. | ||
| @@ -455,6 +455,19 @@ Contact: linux-iio@vger.kernel.org · 454 unmodified lines | |||
| 455 | Description: | 455 | Description: |
| 456 | Hardware applied calibration offset (assumed to fix production | 456 | Hardware applied calibration offset (assumed to fix production |
| 457 | inaccuracies). | 457 | inaccuracies). |
| 458 | icm42600: For this device values are real physical offsets | ||
| 459 | expressed in SI units (m/s^2 for accelerometers and rad/s | ||
| 460 | for gyroscope)/ | ||
| 461 | |||
| 462 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_calibbias_available | ||
| 463 | What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_calibbias_available | ||
| 464 | KernelVersion: 5.8 | ||
| 465 | Contact: linux-iio@vger.kernel.org | ||
| 466 | Description: | ||
| 467 | Available values of calibbias. Maybe expressed as either of: | ||
| 468 | |||
| 469 | - a small discrete set of values like "0 2 4 6 8" | ||
| 470 | - a range specified as "[min step max]" | ||
| 458 | 471 | ||
| 459 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale | 472 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale |
| 460 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_calibscale | 473 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_calibscale |
| @@ -652,6 +665,25 @@ Description: · 191 unmodified lines | |||
| 652 | Output frequency for channel Y in Hz. The number must always be | 665 | Output frequency for channel Y in Hz. The number must always be |
| 653 | specified and unique if the output corresponds to a single | 666 | specified and unique if the output corresponds to a single |
| 654 | channel. | 667 | channel. |
| 668 | Some drivers have additional constraints: | ||
| 669 | ADF4371 has an integrated VCO with fundamendal output | ||
| 670 | frequency ranging from 4000000000 Hz 8000000000 Hz. | ||
| 671 | |||
| 672 | out_altvoltage0_frequency: | ||
| 673 | A divide by 1, 2, 4, 8, 16, 32 or circuit generates | ||
| 674 | frequencies from 62500000 Hz to 8000000000 Hz. | ||
| 675 | out_altvoltage1_frequency: | ||
| 676 | This channel duplicates the channel 0 frequency | ||
| 677 | out_altvoltage2_frequency: | ||
| 678 | A frequency doubler generates frequencies from | ||
| 679 | 8000000000 Hz to 16000000000 Hz. | ||
| 680 | out_altvoltage3_frequency: | ||
| 681 | A frequency quadrupler generates frequencies from | ||
| 682 | 16000000000 Hz to 32000000000 Hz. | ||
| 683 | |||
| 684 | Note: writes to one of the channels will affect the frequency of | ||
| 685 | all the other channels, since it involves changing the VCO | ||
| 686 | fundamental output frequency. | ||
| 655 | 687 | ||
| 656 | What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_phase | 688 | What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_phase |
| 657 | KernelVersion: 3.4.0 | 689 | KernelVersion: 3.4.0 |
| @@ -663,6 +695,17 @@ Description: · 5 unmodified lines | |||
| 663 | specified and unique if the output corresponds to a single | 695 | specified and unique if the output corresponds to a single |
| 664 | channel. | 696 | channel. |
| 665 | 697 | ||
| 698 | What: /sys/bus/iio/devices/iio:deviceX/out_currentY_raw | ||
| 699 | Date: May 2012 | ||
| 700 | KernelVersion: 3.5 | ||
| 701 | Contact: Johan Hovold <jhovold@gmail.com> | ||
| 702 | Description: | ||
| 703 | Set/get output current for channel Y. Units after application | ||
| 704 | of scale and offset are milliamps. | ||
| 705 | For some devices current channels are used to specify | ||
| 706 | current supplied to elements used in taking a measurement | ||
| 707 | of a different type. E.g. LED currents. | ||
| 708 | |||
| 666 | What: /sys/bus/iio/devices/iio:deviceX/events | 709 | What: /sys/bus/iio/devices/iio:deviceX/events |
| 667 | KernelVersion: 2.6.35 | 710 | KernelVersion: 2.6.35 |
| 668 | Contact: linux-iio@vger.kernel.org | 711 | Contact: linux-iio@vger.kernel.org |
| @@ -1195,16 +1238,12 @@ Description: · 526 unmodified lines | |||
| 1195 | The name of the trigger source being used, as per string given | 1238 | The name of the trigger source being used, as per string given |
| 1196 | in /sys/class/iio/triggerY/name. | 1239 | in /sys/class/iio/triggerY/name. |
| 1197 | 1240 | ||
| 1198 | What: /sys/bus/iio/devices/iio:deviceX/buffer/length | ||
| 1199 | KernelVersion: 2.6.35 | ||
| 1200 | What: /sys/bus/iio/devices/iio:deviceX/bufferY/length | 1241 | What: /sys/bus/iio/devices/iio:deviceX/bufferY/length |
| 1201 | KernelVersion: 5.11 | 1242 | KernelVersion: 5.11 |
| 1202 | Contact: linux-iio@vger.kernel.org | 1243 | Contact: linux-iio@vger.kernel.org |
| 1203 | Description: | 1244 | Description: |
| 1204 | Number of scans contained by the buffer. | 1245 | Number of scans contained by the buffer. |
| 1205 | 1246 | ||
| 1206 | What: /sys/bus/iio/devices/iio:deviceX/buffer/enable | ||
| 1207 | KernelVersion: 2.6.35 | ||
| 1208 | What: /sys/bus/iio/devices/iio:deviceX/bufferY/enable | 1247 | What: /sys/bus/iio/devices/iio:deviceX/bufferY/enable |
| 1209 | KernelVersion: 5.11 | 1248 | KernelVersion: 5.11 |
| 1210 | Contact: linux-iio@vger.kernel.org | 1249 | Contact: linux-iio@vger.kernel.org |
| @@ -1212,8 +1251,6 @@ Description: · 1 unmodified line | |||
| 1212 | Actually start the buffer capture up. Will start trigger | 1251 | Actually start the buffer capture up. Will start trigger |
| 1213 | if first device and appropriate. | 1252 | if first device and appropriate. |
| 1214 | 1253 | ||
| 1215 | What: /sys/bus/iio/devices/iio:deviceX/scan_elements | ||
| 1216 | KernelVersion: 2.6.37 | ||
| 1217 | What: /sys/bus/iio/devices/iio:deviceX/bufferY | 1254 | What: /sys/bus/iio/devices/iio:deviceX/bufferY |
| 1218 | KernelVersion: 5.11 | 1255 | KernelVersion: 5.11 |
| 1219 | Contact: linux-iio@vger.kernel.org | 1256 | Contact: linux-iio@vger.kernel.org |
| @@ -1224,34 +1261,6 @@ Description: · 4 unmodified lines | |||
| 1224 | Since kernel 5.11 the scan_elements attributes are merged into | 1261 | Since kernel 5.11 the scan_elements attributes are merged into |
| 1225 | the bufferY directory, to be configurable per buffer. | 1262 | the bufferY directory, to be configurable per buffer. |
| 1226 | 1263 | ||
| 1227 | What: /sys/.../iio:deviceX/scan_elements/in_accel_x_en | ||
| 1228 | What: /sys/.../iio:deviceX/scan_elements/in_accel_y_en | ||
| 1229 | What: /sys/.../iio:deviceX/scan_elements/in_accel_z_en | ||
| 1230 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_x_en | ||
| 1231 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_y_en | ||
| 1232 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_z_en | ||
| 1233 | What: /sys/.../iio:deviceX/scan_elements/in_magn_x_en | ||
| 1234 | What: /sys/.../iio:deviceX/scan_elements/in_magn_y_en | ||
| 1235 | What: /sys/.../iio:deviceX/scan_elements/in_magn_z_en | ||
| 1236 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_en | ||
| 1237 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_en | ||
| 1238 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_tilt_comp_en | ||
| 1239 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_tilt_comp_en | ||
| 1240 | What: /sys/.../iio:deviceX/scan_elements/in_timestamp_en | ||
| 1241 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_en | ||
| 1242 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_en | ||
| 1243 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY-voltageZ_en | ||
| 1244 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_i_en | ||
| 1245 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_q_en | ||
| 1246 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_i_en | ||
| 1247 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_q_en | ||
| 1248 | What: /sys/.../iio:deviceX/scan_elements/in_incli_x_en | ||
| 1249 | What: /sys/.../iio:deviceX/scan_elements/in_incli_y_en | ||
| 1250 | What: /sys/.../iio:deviceX/scan_elements/in_pressureY_en | ||
| 1251 | What: /sys/.../iio:deviceX/scan_elements/in_pressure_en | ||
| 1252 | What: /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_en | ||
| 1253 | What: /sys/.../iio:deviceX/scan_elements/in_proximity_en | ||
| 1254 | KernelVersion: 2.6.37 | ||
| 1255 | What: /sys/.../iio:deviceX/bufferY/in_accel_x_en | 1264 | What: /sys/.../iio:deviceX/bufferY/in_accel_x_en |
| 1256 | What: /sys/.../iio:deviceX/bufferY/in_accel_y_en | 1265 | What: /sys/.../iio:deviceX/bufferY/in_accel_y_en |
| 1257 | What: /sys/.../iio:deviceX/bufferY/in_accel_z_en | 1266 | What: /sys/.../iio:deviceX/bufferY/in_accel_z_en |
| @@ -1284,23 +1293,6 @@ Contact: linux-iio@vger.kernel.org · 26 unmodified lines | |||
| 1284 | Description: | 1293 | Description: |
| 1285 | Scan element control for triggered data capture. | 1294 | Scan element control for triggered data capture. |
| 1286 | 1295 | ||
| 1287 | What: /sys/.../iio:deviceX/scan_elements/in_accel_type | ||
| 1288 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_type | ||
| 1289 | What: /sys/.../iio:deviceX/scan_elements/in_magn_type | ||
| 1290 | What: /sys/.../iio:deviceX/scan_elements/in_incli_type | ||
| 1291 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_type | ||
| 1292 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_type | ||
| 1293 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_type | ||
| 1294 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_i_type | ||
| 1295 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_q_type | ||
| 1296 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_i_type | ||
| 1297 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_q_type | ||
| 1298 | What: /sys/.../iio:deviceX/scan_elements/in_timestamp_type | ||
| 1299 | What: /sys/.../iio:deviceX/scan_elements/in_pressureY_type | ||
| 1300 | What: /sys/.../iio:deviceX/scan_elements/in_pressure_type | ||
| 1301 | What: /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_type | ||
| 1302 | What: /sys/.../iio:deviceX/scan_elements/in_proximity_type | ||
| 1303 | KernelVersion: 2.6.37 | ||
| 1304 | What: /sys/.../iio:deviceX/bufferY/in_accel_type | 1296 | What: /sys/.../iio:deviceX/bufferY/in_accel_type |
| 1305 | What: /sys/.../iio:deviceX/bufferY/in_anglvel_type | 1297 | What: /sys/.../iio:deviceX/bufferY/in_anglvel_type |
| 1306 | What: /sys/.../iio:deviceX/bufferY/in_magn_type | 1298 | What: /sys/.../iio:deviceX/bufferY/in_magn_type |
| @@ -1347,33 +1339,6 @@ Description: · 40 unmodified lines | |||
| 1347 | If the type parameter can take one of a small set of values, | 1339 | If the type parameter can take one of a small set of values, |
| 1348 | this attribute lists them. | 1340 | this attribute lists them. |
| 1349 | 1341 | ||
| 1350 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_index | ||
| 1351 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_index | ||
| 1352 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_i_index | ||
| 1353 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_q_index | ||
| 1354 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_i_index | ||
| 1355 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_q_index | ||
| 1356 | What: /sys/.../iio:deviceX/scan_elements/in_accel_x_index | ||
| 1357 | What: /sys/.../iio:deviceX/scan_elements/in_accel_y_index | ||
| 1358 | What: /sys/.../iio:deviceX/scan_elements/in_accel_z_index | ||
| 1359 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_x_index | ||
| 1360 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_y_index | ||
| 1361 | What: /sys/.../iio:deviceX/scan_elements/in_anglvel_z_index | ||
| 1362 | What: /sys/.../iio:deviceX/scan_elements/in_magn_x_index | ||
| 1363 | What: /sys/.../iio:deviceX/scan_elements/in_magn_y_index | ||
| 1364 | What: /sys/.../iio:deviceX/scan_elements/in_magn_z_index | ||
| 1365 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_index | ||
| 1366 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_index | ||
| 1367 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_tilt_comp_index | ||
| 1368 | What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_tilt_comp_index | ||
| 1369 | What: /sys/.../iio:deviceX/scan_elements/in_incli_x_index | ||
| 1370 | What: /sys/.../iio:deviceX/scan_elements/in_incli_y_index | ||
| 1371 | What: /sys/.../iio:deviceX/scan_elements/in_timestamp_index | ||
| 1372 | What: /sys/.../iio:deviceX/scan_elements/in_pressureY_index | ||
| 1373 | What: /sys/.../iio:deviceX/scan_elements/in_pressure_index | ||
| 1374 | What: /sys/.../iio:deviceX/scan_elements/in_rot_quaternion_index | ||
| 1375 | What: /sys/.../iio:deviceX/scan_elements/in_proximity_index | ||
| 1376 | KernelVersion: 2.6.37 | ||
| 1377 | What: /sys/.../iio:deviceX/bufferY/in_voltageY_index | 1342 | What: /sys/.../iio:deviceX/bufferY/in_voltageY_index |
| 1378 | What: /sys/.../iio:deviceX/bufferY/in_voltageY_supply_index | 1343 | What: /sys/.../iio:deviceX/bufferY/in_voltageY_supply_index |
| 1379 | What: /sys/.../iio:deviceX/bufferY/in_voltageY_i_index | 1344 | What: /sys/.../iio:deviceX/bufferY/in_voltageY_i_index |
| @@ -1613,8 +1578,6 @@ Description: · 233 unmodified lines | |||
| 1613 | Specifies number of seconds in which we compute the steps | 1578 | Specifies number of seconds in which we compute the steps |
| 1614 | that occur in order to decide if the consumer is making steps. | 1579 | that occur in order to decide if the consumer is making steps. |
| 1615 | 1580 | ||
| 1616 | What: /sys/bus/iio/devices/iio:deviceX/buffer/watermark | ||
| 1617 | KernelVersion: 4.2 | ||
| 1618 | What: /sys/bus/iio/devices/iio:deviceX/bufferY/watermark | 1581 | What: /sys/bus/iio/devices/iio:deviceX/bufferY/watermark |
| 1619 | KernelVersion: 5.11 | 1582 | KernelVersion: 5.11 |
| 1620 | Contact: linux-iio@vger.kernel.org | 1583 | Contact: linux-iio@vger.kernel.org |
| @@ -1633,8 +1596,6 @@ Description: · 12 unmodified lines | |||
| 1633 | the available samples after the timeout expires and thus have a | 1596 | the available samples after the timeout expires and thus have a |
| 1634 | maximum delay guarantee. | 1597 | maximum delay guarantee. |
| 1635 | 1598 | ||
| 1636 | What: /sys/bus/iio/devices/iio:deviceX/buffer/data_available | ||
| 1637 | KernelVersion: 4.16 | ||
| 1638 | What: /sys/bus/iio/devices/iio:deviceX/bufferY/data_available | 1599 | What: /sys/bus/iio/devices/iio:deviceX/bufferY/data_available |
| 1639 | KernelVersion: 5.11 | 1600 | KernelVersion: 5.11 |
| 1640 | Contact: linux-iio@vger.kernel.org | 1601 | Contact: linux-iio@vger.kernel.org |
| @@ -1,28 +1,3 @@ | |||
| 1 | What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_frequency | ||
| 2 | KernelVersion: | ||
| 3 | Contact: linux-iio@vger.kernel.org | ||
| 4 | Description: | ||
| 5 | Stores the PLL frequency in Hz for channel Y. | ||
| 6 | Reading returns the actual frequency in Hz. | ||
| 7 | The ADF4371 has an integrated VCO with fundamendal output | ||
| 8 | frequency ranging from 4000000000 Hz 8000000000 Hz. | ||
| 9 | |||
| 10 | out_altvoltage0_frequency: | ||
| 11 | A divide by 1, 2, 4, 8, 16, 32 or circuit generates | ||
| 12 | frequencies from 62500000 Hz to 8000000000 Hz. | ||
| 13 | out_altvoltage1_frequency: | ||
| 14 | This channel duplicates the channel 0 frequency | ||
| 15 | out_altvoltage2_frequency: | ||
| 16 | A frequency doubler generates frequencies from | ||
| 17 | 8000000000 Hz to 16000000000 Hz. | ||
| 18 | out_altvoltage3_frequency: | ||
| 19 | A frequency quadrupler generates frequencies from | ||
| 20 | 16000000000 Hz to 32000000000 Hz. | ||
| 21 | |||
| 22 | Note: writes to one of the channels will affect the frequency of | ||
| 23 | all the other channels, since it involves changing the VCO | ||
| 24 | fundamental output frequency. | ||
| 25 | |||
| 26 | What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_name | 1 | What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_name |
| 27 | KernelVersion: | 2 | KernelVersion: |
| 28 | Contact: linux-iio@vger.kernel.org | 3 | Contact: linux-iio@vger.kernel.org |
| @@ -34,11 +9,3 @@ Description: · 5 unmodified lines | |||
| 34 | out_altvoltage2_name: RF16x | 9 | out_altvoltage2_name: RF16x |
| 35 | out_altvoltage3_name: RF32x | 10 | out_altvoltage3_name: RF32x |
| 36 | 11 | ||
| 37 | What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_powerdown | ||
| 38 | KernelVersion: | ||
| 39 | Contact: linux-iio@vger.kernel.org | ||
| 40 | Description: | ||
| 41 | This attribute allows the user to power down the PLL and it's | ||
| 42 | RFOut buffers. | ||
| 43 | Writing 1 causes the specified channel to power down. | ||
| 44 | Clearing returns to normal operation. | ||
| @@ -18,6 +18,8 @@ Description: · 17 unmodified lines | |||
| 18 | respectively which simply helper channels containing the | 18 | respectively which simply helper channels containing the |
| 19 | calculated difference in the value of stage 1 - 2 and 3 - 4. | 19 | calculated difference in the value of stage 1 - 2 and 3 - 4. |
| 20 | The values are expressed in 24-bit twos complement. | 20 | The values are expressed in 24-bit twos complement. |
| 21 | The LED current for the stage is controlled via | ||
| 22 | out_currentY_raw. | ||
| 21 | 23 | ||
| 22 | What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_offset | 24 | What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_offset |
| 23 | Date: May 2016 | 25 | Date: May 2016 |
| @@ -35,11 +37,3 @@ Contact: Andrew F. Davis <afd@ti.com> · 11 unmodified lines | |||
| 35 | Description: | 37 | Description: |
| 36 | Get and set the resistance and the capacitance settings for the | 38 | Get and set the resistance and the capacitance settings for the |
| 37 | Transimpedance Amplifier during the associated stage. | 39 | Transimpedance Amplifier during the associated stage. |
| 38 | |||
| 39 | What: /sys/bus/iio/devices/iio:deviceX/out_currentY_raw | ||
| 40 | Date: May 2016 | ||
| 41 | KernelVersion: | ||
| 42 | Contact: Andrew F. Davis <afd@ti.com> | ||
| 43 | Description: | ||
| 44 | Get and set the LED current for the specified LED active during | ||
| 45 | this stage. Y is the specific stage number. | ||
| @@ -1,20 +0,0 @@ | |||
| 1 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibbias | ||
| 2 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibbias | ||
| 3 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias | ||
| 4 | What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias | ||
| 5 | What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias | ||
| 6 | What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias | ||
| 7 | KernelVersion: 5.8 | ||
| 8 | Contact: linux-iio@vger.kernel.org | ||
| 9 | Description: | ||
| 10 | Hardware applied calibration offset (assumed to fix production | ||
| 11 | inaccuracies). Values represent a real physical offset expressed | ||
| 12 | in SI units (m/s^2 for accelerometer and rad/s for gyroscope). | ||
| 13 | |||
| 14 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_calibbias_available | ||
| 15 | What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_calibbias_available | ||
| 16 | KernelVersion: 5.8 | ||
| 17 | Contact: linux-iio@vger.kernel.org | ||
| 18 | Description: | ||
| 19 | Range of available values for hardware offset. Values in SI | ||
| 20 | units (m/s^2 for accelerometer and rad/s for gyroscope). | ||
| @@ -41,14 +41,6 @@ Description: · 40 unmodified lines | |||
| 41 | Get the current light zone (0..4) as defined by the | 41 | Get the current light zone (0..4) as defined by the |
| 42 | in_illuminance0_threshY_{falling,rising} thresholds. | 42 | in_illuminance0_threshY_{falling,rising} thresholds. |
| 43 | 43 | ||
| 44 | What: /sys/bus/iio/devices/iio:deviceX/out_currentY_raw | ||
| 45 | Date: May 2012 | ||
| 46 | KernelVersion: 3.5 | ||
| 47 | Contact: Johan Hovold <jhovold@gmail.com> | ||
| 48 | Description: | ||
| 49 | Get output current for channel Y (0..255), that is, | ||
| 50 | out_currentY_currentZ_raw, where Z is the current zone. | ||
| 51 | |||
| 52 | What: /sys/bus/iio/devices/iio:deviceX/out_currentY_currentZ_raw | 44 | What: /sys/bus/iio/devices/iio:deviceX/out_currentY_currentZ_raw |
| 53 | Date: May 2012 | 45 | Date: May 2012 |
| 54 | KernelVersion: 3.5 | 46 | KernelVersion: 3.5 |
| @@ -59,3 +51,6 @@ Description: · 4 unmodified lines | |||
| 59 | 51 | ||
| 60 | These values correspond to the ALS-mapper target registers for | 52 | These values correspond to the ALS-mapper target registers for |
| 61 | ALS-mapper Y + 1. | 53 | ALS-mapper Y + 1. |
| 54 | |||
| 55 | Note that out_currentY_raw provides the current for the | ||
| 56 | current zone. | ||
| @@ -0,0 +1,55 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/accel/adi,adis16201.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: ADIS16201 Dual Axis Inclinometer and similar | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Jonathan Cameron <Jonathan.Cameron@huawei.com> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | Two similar parts from external interface point of view. | ||
| 14 | SPI interface. | ||
| 15 | https://www.analog.com/en/products/adis16201.html | ||
| 16 | https://www.analog.com/en/products/adis16209.html | ||
| 17 | |||
| 18 | properties: | ||
| 19 | compatible: | ||
| 20 | enum: | ||
| 21 | - adi,adis16201 | ||
| 22 | - adi,adis16209 | ||
| 23 | |||
| 24 | reg: | ||
| 25 | maxItems: 1 | ||
| 26 | |||
| 27 | interrupts: | ||
| 28 | maxItems: 1 | ||
| 29 | |||
| 30 | spi-max-frequency: true | ||
| 31 | |||
| 32 | vdd-supply: true | ||
| 33 | |||
| 34 | required: | ||
| 35 | - compatible | ||
| 36 | - reg | ||
| 37 | |||
| 38 | additionalProperties: false | ||
| 39 | |||
| 40 | examples: | ||
| 41 | - | | ||
| 42 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 43 | spi0 { | ||
| 44 | #address-cells = <1>; | ||
| 45 | #size-cells = <0>; | ||
| 46 | |||
| 47 | accelerometer@0 { | ||
| 48 | compatible = "adi,adis16201"; | ||
| 49 | reg = <0>; | ||
| 50 | spi-max-frequency = <2500000>; | ||
| 51 | interrupt-parent = <&gpio0>; | ||
| 52 | interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; | ||
| 53 | }; | ||
| 54 | }; | ||
| 55 | ... | ||
| @@ -4,7 +4,7 @@ · 3 unmodified lines | |||
| 4 | $id: http://devicetree.org/schemas/iio/accel/bosch,bma180.yaml# | 4 | $id: http://devicetree.org/schemas/iio/accel/bosch,bma180.yaml# |
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# |
| 6 | 6 | ||
| 7 | title: Bosch BMA023 / BMA150/ BMA180 / BMA25x / SMB380 triaxial accelerometers | 7 | title: Bosch BMA023 / BMA150/ BMA180 / BMA250 / SMB380 triaxial accelerometers |
| 8 | 8 | ||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Jonathan Cameron <jic23@kernel.org> | 10 | - Jonathan Cameron <jic23@kernel.org> |
| @@ -21,7 +21,6 @@ properties: · 10 unmodified lines | |||
| 21 | - bosch,bma150 | 21 | - bosch,bma150 |
| 22 | - bosch,bma180 | 22 | - bosch,bma180 |
| 23 | - bosch,bma250 | 23 | - bosch,bma250 |
| 24 | - bosch,bma254 | ||
| 25 | - bosch,smb380 | 24 | - bosch,smb380 |
| 26 | 25 | ||
| 27 | reg: | 26 | reg: |
| @@ -0,0 +1,50 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/accel/bosch,bma220.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Bosch BMA220 Trixial Acceleration Sensor | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Jonathan Cameron <Jonathan.Cameron@huawei.com> | ||
| 11 | |||
| 12 | properties: | ||
| 13 | compatible: | ||
| 14 | enum: | ||
| 15 | - bosch,bma220 | ||
| 16 | |||
| 17 | reg: | ||
| 18 | maxItems: 1 | ||
| 19 | |||
| 20 | interrupts: | ||
| 21 | maxItems: 1 | ||
| 22 | |||
| 23 | spi-max-frequency: true | ||
| 24 | |||
| 25 | vdda-supply: true | ||
| 26 | vddd-supply: true | ||
| 27 | vddio-supply: true | ||
| 28 | |||
| 29 | required: | ||
| 30 | - compatible | ||
| 31 | - reg | ||
| 32 | |||
| 33 | additionalProperties: false | ||
| 34 | |||
| 35 | examples: | ||
| 36 | - | | ||
| 37 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 38 | spi0 { | ||
| 39 | #address-cells = <1>; | ||
| 40 | #size-cells = <0>; | ||
| 41 | |||
| 42 | accelerometer@0 { | ||
| 43 | compatible = "bosch,bma220"; | ||
| 44 | reg = <0>; | ||
| 45 | spi-max-frequency = <2500000>; | ||
| 46 | interrupt-parent = <&gpio0>; | ||
| 47 | interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; | ||
| 48 | }; | ||
| 49 | }; | ||
| 50 | ... | ||
| @@ -18,6 +18,8 @@ properties: · 17 unmodified lines | |||
| 18 | enum: | 18 | enum: |
| 19 | - bosch,bmc150_accel | 19 | - bosch,bmc150_accel |
| 20 | - bosch,bmi055_accel | 20 | - bosch,bmi055_accel |
| 21 | - bosch,bma253 | ||
| 22 | - bosch,bma254 | ||
| 21 | - bosch,bma255 | 23 | - bosch,bma255 |
| 22 | - bosch,bma250e | 24 | - bosch,bma250e |
| 23 | - bosch,bma222 | 25 | - bosch,bma222 |
| @@ -31,7 +33,12 @@ properties: · 7 unmodified lines | |||
| 31 | vddio-supply: true | 33 | vddio-supply: true |
| 32 | 34 | ||
| 33 | interrupts: | 35 | interrupts: |
| 34 | maxItems: 1 | 36 | minItems: 1 |
| 37 | maxItems: 2 | ||
| 38 | description: | | ||
| 39 | The first interrupt listed must be the one connected to the INT1 pin, | ||
| 40 | the second (optional) interrupt listed must be the one connected to the | ||
| 41 | INT2 pin (if available). | ||
| 35 | 42 | ||
| 36 | mount-matrix: | 43 | mount-matrix: |
| 37 | description: an optional 3x3 mounting rotation matrix. | 44 | description: an optional 3x3 mounting rotation matrix. |
| @@ -0,0 +1,82 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/accel/fsl,mma7455.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Freescale MMA7455 and MMA7456 three axis accelerometers | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Joachim Eastwood <manabian@gmail.com> | ||
| 11 | - Jonathan Cameron <jic23@kernel.org> | ||
| 12 | |||
| 13 | description: | ||
| 14 | Devices support both SPI and I2C interfaces. | ||
| 15 | |||
| 16 | properties: | ||
| 17 | compatible: | ||
| 18 | enum: | ||
| 19 | - fsl,mma7455 | ||
| 20 | - fsl,mma7456 | ||
| 21 | reg: | ||
| 22 | maxItems: 1 | ||
| 23 | |||
| 24 | avdd-supply: true | ||
| 25 | vddio-supply: true | ||
| 26 | |||
| 27 | interrupts: | ||
| 28 | minItems: 1 | ||
| 29 | maxItems: 2 | ||
| 30 | |||
| 31 | interrupt-names: | ||
| 32 | description: | ||
| 33 | Data ready is only available on INT1, but events can use either or | ||
| 34 | both pins. If not specified, first element assumed to correspond | ||
| 35 | to INT1 and second (where present) to INT2. | ||
| 36 | minItems: 1 | ||
| 37 | maxItems: 2 | ||
| 38 | items: | ||
| 39 | enum: | ||
| 40 | - "INT1" | ||
| 41 | - "INT2" | ||
| 42 | |||
| 43 | spi-max-frequency: true | ||
| 44 | |||
| 45 | required: | ||
| 46 | - compatible | ||
| 47 | - reg | ||
| 48 | |||
| 49 | additionalProperties: false | ||
| 50 | |||
| 51 | examples: | ||
| 52 | - | | ||
| 53 | # include <dt-bindings/interrupt-controller/irq.h> | ||
| 54 | i2c { | ||
| 55 | #address-cells = <1>; | ||
| 56 | #size-cells = <0>; | ||
| 57 | |||
| 58 | accelerometer@18 { | ||
| 59 | compatible = "fsl,mma7455"; | ||
| 60 | reg = <0x18>; | ||
| 61 | vddio-supply = <&iovdd>; | ||
| 62 | avdd-supply = <&avdd>; | ||
| 63 | interrupts = <57 IRQ_TYPE_EDGE_FALLING>, <58 IRQ_TYPE_EDGE_FALLING>; | ||
| 64 | interrupt-names = "INT2", "INT1"; | ||
| 65 | }; | ||
| 66 | }; | ||
| 67 | - | | ||
| 68 | # include <dt-bindings/interrupt-controller/irq.h> | ||
| 69 | spi { | ||
| 70 | #address-cells = <1>; | ||
| 71 | #size-cells = <0>; | ||
| 72 | accelerometer@0 { | ||
| 73 | compatible = "fsl,mma7456"; | ||
| 74 | reg = <0>; | ||
| 75 | spi-max-frequency = <10000000>; | ||
| 76 | vddio-supply = <&iovdd>; | ||
| 77 | avdd-supply = <&avdd>; | ||
| 78 | interrupts = <57 IRQ_TYPE_EDGE_FALLING>; | ||
| 79 | interrupt-names = "INT1"; | ||
| 80 | }; | ||
| 81 | }; | ||
| 82 | ... | ||
| @@ -16,6 +16,7 @@ properties: · 15 unmodified lines | |||
| 16 | - kionix,kxcj91008 | 16 | - kionix,kxcj91008 |
| 17 | - kionix,kxtj21009 | 17 | - kionix,kxtj21009 |
| 18 | - kionix,kxtf9 | 18 | - kionix,kxtf9 |
| 19 | - kionix,kx023-1025 | ||
| 19 | 20 | ||
| 20 | reg: | 21 | reg: |
| 21 | maxItems: 1 | 22 | maxItems: 1 |
| @@ -0,0 +1,44 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/accel/murata,sca3300.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Murata SCA3300 Accelerometer | ||
| 8 | |||
| 9 | description: | | ||
| 10 | 3-axis industrial accelerometer with digital SPI interface | ||
| 11 | https://www.murata.com/en-global/products/sensor/accel/sca3300 | ||
| 12 | |||
| 13 | maintainers: | ||
| 14 | - Tomas Melin <tomas.melin@vaisala.com> | ||
| 15 | |||
| 16 | properties: | ||
| 17 | compatible: | ||
| 18 | enum: | ||
| 19 | - murata,sca3300 | ||
| 20 | |||
| 21 | reg: | ||
| 22 | maxItems: 1 | ||
| 23 | |||
| 24 | spi-max-frequency: | ||
| 25 | maximum: 8000000 | ||
| 26 | |||
| 27 | required: | ||
| 28 | - compatible | ||
| 29 | - reg | ||
| 30 | |||
| 31 | additionalProperties: false | ||
| 32 | |||
| 33 | examples: | ||
| 34 | - | | ||
| 35 | spi { | ||
| 36 | #address-cells = <1>; | ||
| 37 | #size-cells = <0>; | ||
| 38 | accelerometer@0 { | ||
| 39 | compatible = "murata,sca3300"; | ||
| 40 | reg = <0x0>; | ||
| 41 | spi-max-frequency = <4000000>; | ||
| 42 | }; | ||
| 43 | }; | ||
| 44 | ... | ||
| @@ -0,0 +1,80 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/accel/nxp,fxls8962af.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: NXP FXLS8962AF/FXLS8964AF Accelerometer driver | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Sean Nyekjaer <sean@geanix.com> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | NXP FXLS8962AF/FXLS8964AF Accelerometer driver that supports | ||
| 14 | SPI and I2C interface. | ||
| 15 | https://www.nxp.com/docs/en/data-sheet/FXLS8962AF.pdf | ||
| 16 | https://www.nxp.com/docs/en/data-sheet/FXLS8964AF.pdf | ||
| 17 | |||
| 18 | properties: | ||
| 19 | compatible: | ||
| 20 | enum: | ||
| 21 | - nxp,fxls8962af | ||
| 22 | - nxp,fxls8964af | ||
| 23 | |||
| 24 | reg: | ||
| 25 | maxItems: 1 | ||
| 26 | |||
| 27 | vdd-supply: | ||
| 28 | description: phandle to the regulator that provides power to the accelerometer | ||
| 29 | |||
| 30 | spi-max-frequency: true | ||
| 31 | |||
| 32 | interrupts: | ||
| 33 | maxItems: 1 | ||
| 34 | |||
| 35 | interrupt-names: | ||
| 36 | enum: | ||
| 37 | - INT1 | ||
| 38 | - INT2 | ||
| 39 | |||
| 40 | drive-open-drain: | ||
| 41 | type: boolean | ||
| 42 | |||
| 43 | required: | ||
| 44 | - compatible | ||
| 45 | - reg | ||
| 46 | |||
| 47 | additionalProperties: false | ||
| 48 | |||
| 49 | examples: | ||
| 50 | - | | ||
| 51 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 52 | i2c0 { | ||
| 53 | #address-cells = <1>; | ||
| 54 | #size-cells = <0>; | ||
| 55 | |||
| 56 | /* Example for a I2C device node */ | ||
| 57 | accelerometer@62 { | ||
| 58 | compatible = "nxp,fxls8962af"; | ||
| 59 | reg = <0x62>; | ||
| 60 | interrupt-parent = <&gpio0>; | ||
| 61 | interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; | ||
| 62 | interrupt-names = "INT1"; | ||
| 63 | }; | ||
| 64 | }; | ||
| 65 | - | | ||
| 66 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 67 | spi0 { | ||
| 68 | #address-cells = <1>; | ||
| 69 | #size-cells = <0>; | ||
| 70 | |||
| 71 | /* Example for a SPI device node */ | ||
| 72 | accelerometer@0 { | ||
| 73 | compatible = "nxp,fxls8962af"; | ||
| 74 | reg = <0>; | ||
| 75 | spi-max-frequency = <4000000>; | ||
| 76 | interrupt-parent = <&gpio0>; | ||
| 77 | interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; | ||
| 78 | interrupt-names = "INT1"; | ||
| 79 | }; | ||
| 80 | }; | ||
| @@ -39,4 +39,16 @@ properties: · 38 unmodified lines | |||
| 39 | The first value specifies the positive input pin, the second | 39 | The first value specifies the positive input pin, the second |
| 40 | specifies the negative input pin. | 40 | specifies the negative input pin. |
| 41 | 41 | ||
| 42 | settling-time-us: | ||
| 43 | description: | ||
| 44 | Time between enabling the channel and first stable readings. | ||
| 45 | |||
| 46 | oversampling-ratio: | ||
| 47 | $ref: /schemas/types.yaml#/definitions/uint32 | ||
| 48 | description: | ||
| 49 | Oversampling is used as replacement of or addition to the low-pass filter. | ||
| 50 | In some cases, the desired filtering characteristics are a function the | ||
| 51 | device design and can interact with other characteristics such as | ||
| 52 | settling time. | ||
| 53 | |||
| 42 | additionalProperties: true | 54 | additionalProperties: true |
| @@ -0,0 +1,48 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | # Copyright 2019 Analog Devices Inc. | ||
| 3 | %YAML 1.2 | ||
| 4 | --- | ||
| 5 | $id: http://devicetree.org/schemas/iio/adc/adi,ad7298.yaml# | ||
| 6 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 7 | |||
| 8 | title: Analog Devices AD7298 ADC | ||
| 9 | |||
| 10 | maintainers: | ||
| 11 | - Michael Hennerich <michael.hennerich@analog.com> | ||
| 12 | |||
| 13 | description: | | ||
| 14 | Bindings for the Analog Devices AD7298 ADC device. Datasheet can be | ||
| 15 | found here: | ||
| 16 | https://www.analog.com/en/products/ad7298.html | ||
| 17 | |||
| 18 | properties: | ||
| 19 | compatible: | ||
| 20 | const: adi,ad7298 | ||
| 21 | |||
| 22 | reg: | ||
| 23 | maxItems: 1 | ||
| 24 | |||
| 25 | vref-supply: true | ||
| 26 | vdd-supply: true | ||
| 27 | spi-max-frequency: true | ||
| 28 | |||
| 29 | required: | ||
| 30 | - compatible | ||
| 31 | - reg | ||
| 32 | |||
| 33 | additionalProperties: false | ||
| 34 | |||
| 35 | examples: | ||
| 36 | - | | ||
| 37 | spi { | ||
| 38 | #address-cells = <1>; | ||
| 39 | #size-cells = <0>; | ||
| 40 | |||
| 41 | adc@0 { | ||
| 42 | compatible = "adi,ad7298"; | ||
| 43 | reg = <0>; | ||
| 44 | spi-max-frequency = <5000000>; | ||
| 45 | vref-supply = <&adc_vref>; | ||
| 46 | }; | ||
| 47 | }; | ||
| 48 | ... | ||
| @@ -0,0 +1,174 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | # Copyright 2019 Analog Devices Inc. | ||
| 3 | %YAML 1.2 | ||
| 4 | --- | ||
| 5 | $id: http://devicetree.org/schemas/iio/adc/adi,ad7476.yaml# | ||
| 6 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 7 | |||
| 8 | title: AD7476 and similar simple SPI ADCs from multiple manufacturers. | ||
| 9 | |||
| 10 | maintainers: | ||
| 11 | - Michael Hennerich <michael.hennerich@analog.com> | ||
| 12 | |||
| 13 | description: | | ||
| 14 | A lot of simple SPI ADCs have very straight forward interfaces. | ||
| 15 | They typically don't provide a MOSI pin, simply reading out data | ||
| 16 | on MISO when the clock toggles. | ||
| 17 | |||
| 18 | properties: | ||
| 19 | compatible: | ||
| 20 | enum: | ||
| 21 | - adi,ad7091 | ||
| 22 | - adi,ad7091r | ||
| 23 | - adi,ad7273 | ||
| 24 | - adi,ad7274 | ||
| 25 | - adi,ad7276 | ||
| 26 | - adi,ad7277 | ||
| 27 | - adi,ad7278 | ||
| 28 | - adi,ad7466 | ||
| 29 | - adi,ad7467 | ||
| 30 | - adi,ad7468 | ||
| 31 | - adi,ad7475 | ||
| 32 | - adi,ad7476 | ||
| 33 | - adi,ad7476a | ||
| 34 | - adi,ad7477 | ||
| 35 | - adi,ad7477a | ||
| 36 | - adi,ad7478 | ||
| 37 | - adi,ad7478a | ||
| 38 | - adi,ad7495 | ||
| 39 | - adi,ad7910 | ||
| 40 | - adi,ad7920 | ||
| 41 | - adi,ad7940 | ||
| 42 | - ti,adc081s | ||
| 43 | - ti,adc101s | ||
| 44 | - ti,adc121s | ||
| 45 | - ti,ads7866 | ||
| 46 | - ti,ads7867 | ||
| 47 | - ti,ads7868 | ||
| 48 | - lltc,ltc2314-14 | ||
| 49 | |||
| 50 | reg: | ||
| 51 | maxItems: 1 | ||
| 52 | |||
| 53 | vcc-supply: | ||
| 54 | description: | ||
| 55 | Main powersupply voltage for the chips, sometimes referred to as VDD on | ||
| 56 | datasheets. If there is no separate vref-supply, then this is needed | ||
| 57 | to establish channel scaling. | ||
| 58 | |||
| 59 | vdrive-supply: | ||
| 60 | description: | ||
| 61 | Some devices have separate supply for their digital control side. | ||
| 62 | |||
| 63 | vref-supply: | ||
| 64 | description: | ||
| 65 | Some devices have a specific reference voltage supplied on a different pin | ||
| 66 | to the other supplies. Needed to be able to establish channel scaling | ||
| 67 | unless there is also an internal reference available (e.g. ad7091r) | ||
| 68 | |||
| 69 | spi-max-frequency: true | ||
| 70 | |||
| 71 | adi,conversion-start-gpios: | ||
| 72 | description: A GPIO used to trigger the start of a conversion | ||
| 73 | maxItems: 1 | ||
| 74 | |||
| 75 | required: | ||
| 76 | - compatible | ||
| 77 | - reg | ||
| 78 | |||
| 79 | additionalProperties: false | ||
| 80 | |||
| 81 | allOf: | ||
| 82 | # Devices where reference is vcc | ||
| 83 | - if: | ||
| 84 | properties: | ||
| 85 | compatible: | ||
| 86 | contains: | ||
| 87 | enum: | ||
| 88 | - adi,ad7091 | ||
| 89 | - adi,ad7276 | ||
| 90 | - adi,ad7277 | ||
| 91 | - adi,ad7278 | ||
| 92 | - adi,ad7466 | ||
| 93 | - adi,ad7467 | ||
| 94 | - adi,ad7468 | ||
| 95 | - adi,ad7940 | ||
| 96 | - ti,adc081s | ||
| 97 | - ti,adc101s | ||
| 98 | - ti,adc121s | ||
| 99 | - ti,ads7866 | ||
| 100 | - ti,ads7868 | ||
| 101 | required: | ||
| 102 | - vcc-supply | ||
| 103 | # Devices with a vref | ||
| 104 | - if: | ||
| 105 | properties: | ||
| 106 | compatible: | ||
| 107 | contains: | ||
| 108 | enum: | ||
| 109 | - adi,ad7091r | ||
| 110 | - adi,ad7273 | ||
| 111 | - adi,ad7274 | ||
| 112 | - adi,ad7475 | ||
| 113 | - lltc,ltc2314-14 | ||
| 114 | then: | ||
| 115 | properties: | ||
| 116 | vref-supply: true | ||
| 117 | else: | ||
| 118 | properties: | ||
| 119 | vref-supply: false | ||
| 120 | # Devices with a vref where it is not optional | ||
| 121 | - if: | ||
| 122 | properties: | ||
| 123 | compatible: | ||
| 124 | contains: | ||
| 125 | enum: | ||
| 126 | - adi,ad7273 | ||
| 127 | - adi,ad7274 | ||
| 128 | - adi,ad7475 | ||
| 129 | - lltc,ltc2314-14 | ||
| 130 | then: | ||
| 131 | required: | ||
| 132 | - vref-supply | ||
| 133 | - if: | ||
| 134 | properties: | ||
| 135 | compatible: | ||
| 136 | contains: | ||
| 137 | enum: | ||
| 138 | - adi,ad7475 | ||
| 139 | - adi,ad7495 | ||
| 140 | then: | ||
| 141 | properties: | ||
| 142 | vdrive-supply: true | ||
| 143 | else: | ||
| 144 | properties: | ||
| 145 | vdrive-supply: false | ||
| 146 | - if: | ||
| 147 | properties: | ||
| 148 | compatible: | ||
| 149 | contains: | ||
| 150 | enum: | ||
| 151 | - adi,ad7091 | ||
| 152 | - adi,ad7091r | ||
| 153 | then: | ||
| 154 | properties: | ||
| 155 | adi,conversion-start-gpios: true | ||
| 156 | else: | ||
| 157 | properties: | ||
| 158 | adi,conversion-start-gpios: false | ||
| 159 | |||
| 160 | examples: | ||
| 161 | - | | ||
| 162 | spi { | ||
| 163 | #address-cells = <1>; | ||
| 164 | #size-cells = <0>; | ||
| 165 | |||
| 166 | adc@0 { | ||
| 167 | compatible = "adi,ad7091r"; | ||
| 168 | reg = <0>; | ||
| 169 | spi-max-frequency = <5000000>; | ||
| 170 | vcc-supply = <&adc_vcc>; | ||
| 171 | vref-supply = <&adc_vref>; | ||
| 172 | }; | ||
| 173 | }; | ||
| 174 | ... | ||
| @@ -0,0 +1,115 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/adc/ti,tsc2046.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Texas Instruments TSC2046 touch screen controller. | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Oleksij Rempel <o.rempel@pengutronix.de> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | TSC2046 is a touch screen controller with 8 channels ADC. | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | enum: | ||
| 18 | - ti,tsc2046e-adc | ||
| 19 | |||
| 20 | reg: | ||
| 21 | maxItems: 1 | ||
| 22 | |||
| 23 | interrupts: | ||
| 24 | maxItems: 1 | ||
| 25 | |||
| 26 | spi-max-frequency: true | ||
| 27 | |||
| 28 | "#io-channel-cells": | ||
| 29 | const: 1 | ||
| 30 | |||
| 31 | '#address-cells': | ||
| 32 | const: 1 | ||
| 33 | |||
| 34 | '#size-cells': | ||
| 35 | const: 0 | ||
| 36 | |||
| 37 | required: | ||
| 38 | - compatible | ||
| 39 | - reg | ||
| 40 | |||
| 41 | patternProperties: | ||
| 42 | "^channel@[0-7]$": | ||
| 43 | $ref: "adc.yaml" | ||
| 44 | type: object | ||
| 45 | |||
| 46 | properties: | ||
| 47 | reg: | ||
| 48 | description: | | ||
| 49 | The channel number. It can have up to 8 channels | ||
| 50 | items: | ||
| 51 | minimum: 0 | ||
| 52 | maximum: 7 | ||
| 53 | |||
| 54 | settling-time-us: true | ||
| 55 | oversampling-ratio: true | ||
| 56 | |||
| 57 | required: | ||
| 58 | - reg | ||
| 59 | |||
| 60 | additionalProperties: false | ||
| 61 | |||
| 62 | additionalProperties: false | ||
| 63 | |||
| 64 | examples: | ||
| 65 | - | | ||
| 66 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 67 | spi { | ||
| 68 | #address-cells = <1>; | ||
| 69 | #size-cells = <0>; | ||
| 70 | |||
| 71 | adc@0 { | ||
| 72 | compatible = "ti,tsc2046e-adc"; | ||
| 73 | reg = <0>; | ||
| 74 | spi-max-frequency = <1000000>; | ||
| 75 | interrupts-extended = <&gpio3 20 IRQ_TYPE_LEVEL_LOW>; | ||
| 76 | #io-channel-cells = <1>; | ||
| 77 | |||
| 78 | #address-cells = <1>; | ||
| 79 | #size-cells = <0>; | ||
| 80 | |||
| 81 | channel@0 { | ||
| 82 | reg = <0>; | ||
| 83 | }; | ||
| 84 | channel@1 { | ||
| 85 | reg = <1>; | ||
| 86 | settling-time-us = <700>; | ||
| 87 | oversampling-ratio = <5>; | ||
| 88 | }; | ||
| 89 | channel@2 { | ||
| 90 | reg = <2>; | ||
| 91 | }; | ||
| 92 | channel@3 { | ||
| 93 | reg = <3>; | ||
| 94 | settling-time-us = <700>; | ||
| 95 | oversampling-ratio = <5>; | ||
| 96 | }; | ||
| 97 | channel@4 { | ||
| 98 | reg = <4>; | ||
| 99 | settling-time-us = <700>; | ||
| 100 | oversampling-ratio = <5>; | ||
| 101 | }; | ||
| 102 | channel@5 { | ||
| 103 | reg = <5>; | ||
| 104 | settling-time-us = <700>; | ||
| 105 | oversampling-ratio = <5>; | ||
| 106 | }; | ||
| 107 | channel@6 { | ||
| 108 | reg = <6>; | ||
| 109 | }; | ||
| 110 | channel@7 { | ||
| 111 | reg = <7>; | ||
| 112 | }; | ||
| 113 | }; | ||
| 114 | }; | ||
| 115 | ... | ||
| @@ -24,6 +24,9 @@ properties: · 23 unmodified lines | |||
| 24 | description: | | 24 | description: | |
| 25 | Channel node of a voltage io-channel. | 25 | Channel node of a voltage io-channel. |
| 26 | 26 | ||
| 27 | "#io-channel-cells": | ||
| 28 | const: 0 | ||
| 29 | |||
| 27 | shunt-resistor-micro-ohms: | 30 | shunt-resistor-micro-ohms: |
| 28 | description: The shunt resistance. | 31 | description: The shunt resistance. |
| 29 | 32 | ||
| @@ -57,6 +60,7 @@ examples: · 27 unmodified lines | |||
| 57 | sysi { | 60 | sysi { |
| 58 | compatible = "current-sense-shunt"; | 61 | compatible = "current-sense-shunt"; |
| 59 | io-channels = <&tiadc 0>; | 62 | io-channels = <&tiadc 0>; |
| 63 | #io-channel-cells = <0>; | ||
| 60 | 64 | ||
| 61 | /* Divide the voltage by 3300000/1000000 (or 3.3) for the current. */ | 65 | /* Divide the voltage by 3300000/1000000 (or 3.3) for the current. */ |
| 62 | shunt-resistor-micro-ohms = <3300000>; | 66 | shunt-resistor-micro-ohms = <3300000>; |
| @@ -0,0 +1,77 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/cdc/adi,ad7746.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: AD7746 24-Bit Capacitance-to-Digital Converter with Temperature Sensor | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Michael Hennerich <michael.hennerich@analog.com> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | AD7746 24-Bit Capacitance-to-Digital Converter with Temperature Sensor | ||
| 14 | |||
| 15 | Specifications about the part can be found at: | ||
| 16 | https://www.analog.com/media/en/technical-documentation/data-sheets/ad7291.pdf | ||
| 17 | |||
| 18 | properties: | ||
| 19 | compatible: | ||
| 20 | enum: | ||
| 21 | - adi,ad7745 | ||
| 22 | - adi,ad7746 | ||
| 23 | - adi,ad7747 | ||
| 24 | |||
| 25 | reg: | ||
| 26 | maxItems: 1 | ||
| 27 | |||
| 28 | adi,excitation-vdd-permille: | ||
| 29 | description: | | ||
| 30 | Set VDD per mille to be used as the excitation voltage. | ||
| 31 | $ref: /schemas/types.yaml#/definitions/uint32 | ||
| 32 | enum: [125, 250, 375, 500] | ||
| 33 | |||
| 34 | adi,exca-output-en: | ||
| 35 | description: Enables the EXCA pin as the excitation output. | ||
| 36 | type: boolean | ||
| 37 | |||
| 38 | adi,exca-output-invert: | ||
| 39 | description: | | ||
| 40 | Inverts the excitation output in the EXCA pin. | ||
| 41 | Normally only one of the EXCX pins would be inverted, check the following | ||
| 42 | application notes for more details | ||
| 43 | https://www.analog.com/media/en/technical-documentation/application-notes/AN-1585.pdf | ||
| 44 | type: boolean | ||
| 45 | |||
| 46 | adi,excb-output-en: | ||
| 47 | description: Enables the EXCB pin as the excitation output. | ||
| 48 | type: boolean | ||
| 49 | |||
| 50 | adi,excb-output-invert: | ||
| 51 | description: Inverts the excitation output in the EXCB pin. | ||
| 52 | type: boolean | ||
| 53 | |||
| 54 | required: | ||
| 55 | - compatible | ||
| 56 | - reg | ||
| 57 | |||
| 58 | additionalProperties: false | ||
| 59 | |||
| 60 | examples: | ||
| 61 | - | | ||
| 62 | i2c { | ||
| 63 | #address-cells = <1>; | ||
| 64 | #size-cells = <0>; | ||
| 65 | |||
| 66 | ad7746: cdc@48 { | ||
| 67 | compatible = "adi,ad7746"; | ||
| 68 | reg = <0x48>; | ||
| 69 | adi,excitation-vdd-permille = <125>; | ||
| 70 | |||
| 71 | adi,exca-output-en; | ||
| 72 | adi,exca-output-invert; | ||
| 73 | adi,excb-output-en; | ||
| 74 | adi,excb-output-invert; | ||
| 75 | }; | ||
| 76 | }; | ||
| 77 | ... | ||
| @@ -22,7 +22,6 @@ properties: · 21 unmodified lines | |||
| 22 | 22 | ||
| 23 | required: | 23 | required: |
| 24 | - compatible | 24 | - compatible |
| 25 | - reg | ||
| 26 | 25 | ||
| 27 | additionalProperties: false | 26 | additionalProperties: false |
| 28 | 27 | ||
| @@ -37,5 +36,11 @@ examples: · 8 unmodified lines | |||
| 37 | reg = <0x69>; | 36 | reg = <0x69>; |
| 38 | }; | 37 | }; |
| 39 | }; | 38 | }; |
| 39 | - | | ||
| 40 | serial { | ||
| 41 | air-pollution-sensor { | ||
| 42 | compatible = "sensirion,sps30"; | ||
| 43 | }; | ||
| 44 | }; | ||
| 40 | 45 | ||
| 41 | ... | 46 | ... |
| @@ -1,124 +0,0 @@ | |||
| 1 | * Analog Devices AD5755 IIO Multi-Channel DAC Linux Driver | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: Has to contain one of the following: | ||
| 5 | adi,ad5755 | ||
| 6 | adi,ad5755-1 | ||
| 7 | adi,ad5757 | ||
| 8 | adi,ad5735 | ||
| 9 | adi,ad5737 | ||
| 10 | |||
| 11 | - reg: spi chip select number for the device | ||
| 12 | - spi-cpha or spi-cpol: is the only modes that is supported | ||
| 13 | |||
| 14 | Recommended properties: | ||
| 15 | - spi-max-frequency: Definition as per | ||
| 16 | Documentation/devicetree/bindings/spi/spi-bus.txt | ||
| 17 | |||
| 18 | Optional properties: | ||
| 19 | See include/dt-bindings/iio/ad5755.h | ||
| 20 | - adi,ext-dc-dc-compenstation-resistor: boolean set if the hardware have an | ||
| 21 | external resistor and thereby bypasses | ||
| 22 | the internal compensation resistor. | ||
| 23 | - adi,dc-dc-phase: | ||
| 24 | Valid values for DC DC Phase control is: | ||
| 25 | 0: All dc-to-dc converters clock on the same edge. | ||
| 26 | 1: Channel A and Channel B clock on the same edge, | ||
| 27 | Channel C and Channel D clock on opposite edges. | ||
| 28 | 2: Channel A and Channel C clock on the same edge, | ||
| 29 | Channel B and Channel D clock on opposite edges. | ||
| 30 | 3: Channel A, Channel B, Channel C, and Channel D | ||
| 31 | clock 90 degrees out of phase from each other. | ||
| 32 | - adi,dc-dc-freq-hz: | ||
| 33 | Valid values for DC DC frequency is [Hz]: | ||
| 34 | 250000 | ||
| 35 | 410000 | ||
| 36 | 650000 | ||
| 37 | - adi,dc-dc-max-microvolt: | ||
| 38 | Valid values for the maximum allowed Vboost voltage supplied by | ||
| 39 | the dc-to-dc converter is: | ||
| 40 | 23000000 | ||
| 41 | 24500000 | ||
| 42 | 27000000 | ||
| 43 | 29500000 | ||
| 44 | |||
| 45 | Optional for every channel: | ||
| 46 | - adi,mode: | ||
| 47 | Valid values for DAC modes is: | ||
| 48 | 0: 0 V to 5 V voltage range. | ||
| 49 | 1: 0 V to 10 V voltage range. | ||
| 50 | 2: Plus minus 5 V voltage range. | ||
| 51 | 3: Plus minus 10 V voltage range. | ||
| 52 | 4: 4 mA to 20 mA current range. | ||
| 53 | 5: 0 mA to 20 mA current range. | ||
| 54 | 6: 0 mA to 24 mA current range. | ||
| 55 | - adi,ext-current-sense-resistor: boolean set if the hardware a external | ||
| 56 | current sense resistor. | ||
| 57 | - adi,enable-voltage-overrange: boolean enable voltage overrange | ||
| 58 | - adi,slew: Array of slewrate settings should contain 3 fields: | ||
| 59 | 1: Should be either 0 or 1 in order to enable or disable slewrate. | ||
| 60 | 2: Slew rate settings: | ||
| 61 | Valid values for the slew rate update frequency: | ||
| 62 | 64000 | ||
| 63 | 32000 | ||
| 64 | 16000 | ||
| 65 | 8000 | ||
| 66 | 4000 | ||
| 67 | 2000 | ||
| 68 | 1000 | ||
| 69 | 500 | ||
| 70 | 250 | ||
| 71 | 125 | ||
| 72 | 64 | ||
| 73 | 32 | ||
| 74 | 16 | ||
| 75 | 8 | ||
| 76 | 4 | ||
| 77 | 0 | ||
| 78 | 3: Slew step size: | ||
| 79 | Valid values for the step size LSBs: | ||
| 80 | 1 | ||
| 81 | 2 | ||
| 82 | 4 | ||
| 83 | 16 | ||
| 84 | 32 | ||
| 85 | 64 | ||
| 86 | 128 | ||
| 87 | 256 | ||
| 88 | |||
| 89 | Example: | ||
| 90 | dac@0 { | ||
| 91 | #address-cells = <1>; | ||
| 92 | #size-cells = <0>; | ||
| 93 | compatible = "adi,ad5755"; | ||
| 94 | reg = <0>; | ||
| 95 | spi-max-frequency = <1000000>; | ||
| 96 | spi-cpha; | ||
| 97 | adi,dc-dc-phase = <0>; | ||
| 98 | adi,dc-dc-freq-hz = <410000>; | ||
| 99 | adi,dc-dc-max-microvolt = <23000000>; | ||
| 100 | channel@0 { | ||
| 101 | reg = <0>; | ||
| 102 | adi,mode = <4>; | ||
| 103 | adi,ext-current-sense-resistor; | ||
| 104 | adi,slew = <0 64000 1>; | ||
| 105 | }; | ||
| 106 | channel@1 { | ||
| 107 | reg = <1>; | ||
| 108 | adi,mode = <4>; | ||
| 109 | adi,ext-current-sense-resistor; | ||
| 110 | adi,slew = <0 64000 1>; | ||
| 111 | }; | ||
| 112 | channel@2 { | ||
| 113 | reg = <2>; | ||
| 114 | adi,mode = <4>; | ||
| 115 | adi,ext-current-sense-resistor; | ||
| 116 | adi,slew = <0 64000 1>; | ||
| 117 | }; | ||
| 118 | channel@3 { | ||
| 119 | reg = <3>; | ||
| 120 | adi,mode = <4>; | ||
| 121 | adi,ext-current-sense-resistor; | ||
| 122 | adi,slew = <0 64000 1>; | ||
| 123 | }; | ||
| 124 | }; | ||
| @@ -0,0 +1,169 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/dac/adi,ad5755.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Analog Devices AD5755 Multi-Channel DAC | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Sean Nyekjaer <sean.nyekjaer@prevas.dk> | ||
| 11 | |||
| 12 | properties: | ||
| 13 | compatible: | ||
| 14 | enum: | ||
| 15 | - adi,ad5755 | ||
| 16 | - adi,ad5755-1 | ||
| 17 | - adi,ad5757 | ||
| 18 | - adi,ad5735 | ||
| 19 | - adi,ad5737 | ||
| 20 | |||
| 21 | reg: | ||
| 22 | maxItems: 1 | ||
| 23 | |||
| 24 | spi-cpha: | ||
| 25 | description: Either this or spi-cpol but not both. | ||
| 26 | spi-cpol: true | ||
| 27 | |||
| 28 | spi-max-frequency: true | ||
| 29 | |||
| 30 | adi,ext-dc-dc-compenstation-resistor: | ||
| 31 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 32 | description: | ||
| 33 | Set if the hardware have an external resistor and thereby bypasses | ||
| 34 | the internal compensation resistor. | ||
| 35 | |||
| 36 | adi,dc-dc-phase: | ||
| 37 | $ref: /schemas/types.yaml#/definitions/uint32 | ||
| 38 | enum: [0, 1, 2, 3] | ||
| 39 | description: | | ||
| 40 | Valid values for DC DC Phase control is: | ||
| 41 | 0: All dc-to-dc converters clock on the same edge. | ||
| 42 | 1: Channel A and Channel B clock on the same edge, | ||
| 43 | Channel C and Channel D clock on opposite edges. | ||
| 44 | 2: Channel A and Channel C clock on the same edge, | ||
| 45 | Channel B and Channel D clock on opposite edges. | ||
| 46 | 3: Channel A, Channel B, Channel C, and Channel D | ||
| 47 | clock 90 degrees out of phase from each other. | ||
| 48 | |||
| 49 | adi,dc-dc-freq-hz: | ||
| 50 | enum: [250000, 410000, 650000] | ||
| 51 | |||
| 52 | adi,dc-dc-max-microvolt: | ||
| 53 | description: | ||
| 54 | Maximum allowed Vboost voltage supplied by the dc-to-dc converter. | ||
| 55 | enum: [23000000, 24500000, 27000000, 29500000] | ||
| 56 | |||
| 57 | "#address-cells": | ||
| 58 | const: 1 | ||
| 59 | |||
| 60 | "#size-cells": | ||
| 61 | const: 0 | ||
| 62 | |||
| 63 | "#io-channel-cells": | ||
| 64 | const: 1 | ||
| 65 | |||
| 66 | required: | ||
| 67 | - compatible | ||
| 68 | - reg | ||
| 69 | |||
| 70 | additionalProperties: false | ||
| 71 | |||
| 72 | patternProperties: | ||
| 73 | "^channel@[0-7]$": | ||
| 74 | type: object | ||
| 75 | description: Child node to describe a channel | ||
| 76 | properties: | ||
| 77 | reg: | ||
| 78 | maxItems: 1 | ||
| 79 | |||
| 80 | adi,mode: | ||
| 81 | $ref: /schemas/types.yaml#/definitions/uint32 | ||
| 82 | minimum: 0 | ||
| 83 | maximum: 6 | ||
| 84 | description: | | ||
| 85 | Valid values for DAC modes is: | ||
| 86 | 0: 0 V to 5 V voltage range. | ||
| 87 | 1: 0 V to 10 V voltage range. | ||
| 88 | 2: Plus minus 5 V voltage range. | ||
| 89 | 3: Plus minus 10 V voltage range. | ||
| 90 | 4: 4 mA to 20 mA current range. | ||
| 91 | 5: 0 mA to 20 mA current range. | ||
| 92 | 6: 0 mA to 24 mA current range. | ||
| 93 | |||
| 94 | adi,ext-current-sense-resistor: | ||
| 95 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 96 | description: | ||
| 97 | Set if the hardware has an external current sense resistor | ||
| 98 | |||
| 99 | adi,enable-voltage-overrange: | ||
| 100 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 101 | description: Enable voltage overrange | ||
| 102 | |||
| 103 | adi,slew: | ||
| 104 | $ref: /schemas/types.yaml#/definitions/uint32-array | ||
| 105 | description: | | ||
| 106 | Array of slewrate settings should contain 3 fields: | ||
| 107 | 1: Should be either 0 or 1 in order to enable or disable slewrate. | ||
| 108 | 2: Slew rate update frequency | ||
| 109 | 3: Slew step size | ||
| 110 | items: | ||
| 111 | - enum: [0, 1] | ||
| 112 | - enum: [64000, 32000, 16000, 8000, 4000, 2000, 1000, 500, 250, 125, 64, 32, 16, 8, 4, 0] | ||
| 113 | - enum: [1, 2, 4, 16, 32, 64, 128, 256] | ||
| 114 | |||
| 115 | required: | ||
| 116 | - reg | ||
| 117 | |||
| 118 | additionalProperties: false | ||
| 119 | |||
| 120 | oneOf: | ||
| 121 | - required: | ||
| 122 | - spi-cpha | ||
| 123 | - required: | ||
| 124 | - spi-cpol | ||
| 125 | |||
| 126 | examples: | ||
| 127 | - | | ||
| 128 | #include <dt-bindings/iio/adi,ad5592r.h> | ||
| 129 | spi { | ||
| 130 | #address-cells = <1>; | ||
| 131 | #size-cells = <0>; | ||
| 132 | |||
| 133 | dac@0 { | ||
| 134 | #address-cells = <1>; | ||
| 135 | #size-cells = <0>; | ||
| 136 | compatible = "adi,ad5755"; | ||
| 137 | reg = <0>; | ||
| 138 | spi-max-frequency = <1000000>; | ||
| 139 | spi-cpha; | ||
| 140 | adi,dc-dc-phase = <0>; | ||
| 141 | adi,dc-dc-freq-hz = <410000>; | ||
| 142 | adi,dc-dc-max-microvolt = <23000000>; | ||
| 143 | channel@0 { | ||
| 144 | reg = <0>; | ||
| 145 | adi,mode = <4>; | ||
| 146 | adi,ext-current-sense-resistor; | ||
| 147 | adi,slew = <0 64000 1>; | ||
| 148 | }; | ||
| 149 | channel@1 { | ||
| 150 | reg = <1>; | ||
| 151 | adi,mode = <4>; | ||
| 152 | adi,ext-current-sense-resistor; | ||
| 153 | adi,slew = <0 64000 1>; | ||
| 154 | }; | ||
| 155 | channel@2 { | ||
| 156 | reg = <2>; | ||
| 157 | adi,mode = <4>; | ||
| 158 | adi,ext-current-sense-resistor; | ||
| 159 | adi,slew = <0 64000 1>; | ||
| 160 | }; | ||
| 161 | channel@3 { | ||
| 162 | reg = <3>; | ||
| 163 | adi,mode = <4>; | ||
| 164 | adi,ext-current-sense-resistor; | ||
| 165 | adi,slew = <0 64000 1>; | ||
| 166 | }; | ||
| 167 | }; | ||
| 168 | }; | ||
| 169 | ... | ||
| @@ -0,0 +1,72 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/dac/ti,dac082s085.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Texas Instruments DAC082s085 and similar DACs | ||
| 8 | |||
| 9 | description: | ||
| 10 | A family of Texas Instruments 8/10/12-bit 2/4-channel DACs | ||
| 11 | |||
| 12 | maintainers: | ||
| 13 | - Lukas Wunner <lukas@wunner.de> | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | enum: | ||
| 18 | - ti,dac082s085 | ||
| 19 | - ti,dac102s085 | ||
| 20 | - ti,dac122s085 | ||
| 21 | - ti,dac084s085 | ||
| 22 | - ti,dac104s085 | ||
| 23 | - ti,dac124s085 | ||
| 24 | |||
| 25 | reg: | ||
| 26 | maxItems: 1 | ||
| 27 | |||
| 28 | spi-cpha: true | ||
| 29 | spi-cpol: | ||
| 30 | description: | ||
| 31 | Must be either spi-cpha, or spi-cpol but not both. | ||
| 32 | |||
| 33 | vref-supply: | ||
| 34 | description: Needed to provide output scaling. | ||
| 35 | |||
| 36 | spi-max-frequency: true | ||
| 37 | |||
| 38 | required: | ||
| 39 | - compatible | ||
| 40 | - reg | ||
| 41 | - vref-supply | ||
| 42 | |||
| 43 | additionalProperties: false | ||
| 44 | |||
| 45 | oneOf: | ||
| 46 | - required: | ||
| 47 | - spi-cpha | ||
| 48 | - required: | ||
| 49 | - spi-cpol | ||
| 50 | |||
| 51 | examples: | ||
| 52 | - | | ||
| 53 | vref_2v5_reg: regulator-vref { | ||
| 54 | compatible = "regulator-fixed"; | ||
| 55 | regulator-name = "2v5"; | ||
| 56 | regulator-min-microvolt = <2500000>; | ||
| 57 | regulator-max-microvolt = <2500000>; | ||
| 58 | regulator-always-on; | ||
| 59 | }; | ||
| 60 | spi { | ||
| 61 | #address-cells = <1>; | ||
| 62 | #size-cells = <0>; | ||
| 63 | |||
| 64 | dac@0 { | ||
| 65 | compatible = "ti,dac082s085"; | ||
| 66 | reg = <0>; | ||
| 67 | spi-max-frequency = <40000000>; | ||
| 68 | spi-cpol; | ||
| 69 | vref-supply = <&vref_2v5_reg>; | ||
| 70 | }; | ||
| 71 | }; | ||
| 72 | ... | ||
| @@ -1,34 +0,0 @@ | |||
| 1 | Texas Instruments 8/10/12-bit 2/4-channel DAC driver | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: Must be one of: | ||
| 5 | "ti,dac082s085" | ||
| 6 | "ti,dac102s085" | ||
| 7 | "ti,dac122s085" | ||
| 8 | "ti,dac084s085" | ||
| 9 | "ti,dac104s085" | ||
| 10 | "ti,dac124s085" | ||
| 11 | - reg: Chip select number. | ||
| 12 | - spi-cpha, spi-cpol: SPI mode (0,1) or (1,0) must be used, so specify | ||
| 13 | either spi-cpha or spi-cpol (but not both). | ||
| 14 | - vref-supply: Phandle to the external reference voltage supply. | ||
| 15 | |||
| 16 | For other required and optional properties of SPI slave nodes please refer to | ||
| 17 | ../../spi/spi-bus.txt. | ||
| 18 | |||
| 19 | Example: | ||
| 20 | vref_2v5_reg: regulator-vref { | ||
| 21 | compatible = "regulator-fixed"; | ||
| 22 | regulator-name = "2v5"; | ||
| 23 | regulator-min-microvolt = <2500000>; | ||
| 24 | regulator-max-microvolt = <2500000>; | ||
| 25 | regulator-always-on; | ||
| 26 | }; | ||
| 27 | |||
| 28 | dac@0 { | ||
| 29 | compatible = "ti,dac082s085"; | ||
| 30 | reg = <0>; | ||
| 31 | spi-max-frequency = <40000000>; | ||
| 32 | spi-cpol; | ||
| 33 | vref-supply = <&vref_2v5_reg>; | ||
| 34 | }; | ||
| @@ -0,0 +1,50 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/iio/light/amstaos,tsl2591.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: AMS/TAOS TSL2591 Ambient Light Sensor (ALS) | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Joe Sandom <joe.g.sandom@gmail.com> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | AMS/TAOS TSL2591 is a very-high sensitivity | ||
| 14 | light-to-digital converter that transforms light intensity into a digital | ||
| 15 | signal. | ||
| 16 | |||
| 17 | properties: | ||
| 18 | compatible: | ||
| 19 | const: amstaos,tsl2591 | ||
| 20 | |||
| 21 | reg: | ||
| 22 | maxItems: 1 | ||
| 23 | |||
| 24 | interrupts: | ||
| 25 | maxItems: 1 | ||
| 26 | description: | ||
| 27 | Interrupt (INT:Pin 2) Active low. Should be set to IRQ_TYPE_EDGE_FALLING. | ||
| 28 | interrupt is used to detect if the light intensity has fallen below | ||
| 29 | or reached above the configured threshold values. | ||
| 30 | |||
| 31 | required: | ||
| 32 | - compatible | ||
| 33 | - reg | ||
| 34 | |||
| 35 | additionalProperties: false | ||
| 36 | |||
| 37 | examples: | ||
| 38 | - | | ||
| 39 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 40 | i2c { | ||
| 41 | #address-cells = <1>; | ||
| 42 | #size-cells = <0>; | ||
| 43 | |||
| 44 | tsl2591@29 { | ||
| 45 | compatible = "amstaos,tsl2591"; | ||
| 46 | reg = <0x29>; | ||
| 47 | interrupts = <20 IRQ_TYPE_EDGE_FALLING>; | ||
| 48 | }; | ||
| 49 | }; | ||
| 50 | ... | ||
| @@ -6,7 +6,9 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 5 unmodified lines | |||
| 6 | 6 | ||
| 7 | title: STMicroelectronics MEMS sensors | 7 | title: STMicroelectronics MEMS sensors |
| 8 | 8 | ||
| 9 | description: | | 9 | description: The STMicroelectronics sensor devices are pretty straight-forward |
| 10 | I2C or SPI devices, all sharing the same device tree descriptions no matter | ||
| 11 | what type of sensor it is. | ||
| 10 | Note that whilst this covers many STMicro MEMs sensors, some more complex | 12 | Note that whilst this covers many STMicro MEMs sensors, some more complex |
| 11 | IMUs need their own bindings. | 13 | IMUs need their own bindings. |
| 12 | The STMicroelectronics sensor devices are pretty straight-forward I2C or | 14 | The STMicroelectronics sensor devices are pretty straight-forward I2C or |
| @@ -15,90 +17,181 @@ description: | · 2 unmodified lines | |||
| 15 | 17 | ||
| 16 | maintainers: | 18 | maintainers: |
| 17 | - Denis Ciocca <denis.ciocca@st.com> | 19 | - Denis Ciocca <denis.ciocca@st.com> |
| 20 | - Linus Walleij <linus.walleij@linaro.org> | ||
| 18 | 21 | ||
| 19 | properties: | 22 | properties: |
| 20 | compatible: | 23 | compatible: |
| 21 | description: | | 24 | oneOf: |
| 22 | Some values are deprecated. | 25 | - description: STMicroelectronics Accelerometers |
| 23 | st,lis3lv02d (deprecated, use st,lis3lv02dl-accel) | 26 | enum: |
| 24 | st,lis302dl-spi (deprecated, use st,lis3lv02dl-accel) | 27 | - st,h3lis331dl-accel |
| 25 | enum: | 28 | - st,lis2de12 |
| 26 | # Accelerometers | 29 | - st,lis2dw12 |
| 27 | - st,lis3lv02d | 30 | - st,lis2hh12 |
| 28 | - st,lis302dl-spi | 31 | - st,lis2dh12-accel |
| 29 | - st,lis3lv02dl-accel | 32 | - st,lis331dl-accel |
| 30 | - st,lsm303dlh-accel | 33 | - st,lis331dlh-accel |
| 31 | - st,lsm303dlhc-accel | 34 | - st,lis3de |
| 32 | - st,lis3dh-accel | 35 | - st,lis3dh-accel |
| 33 | - st,lsm330d-accel | 36 | - st,lis3dhh |
| 34 | - st,lsm330dl-accel | 37 | - st,lis3l02dq |
| 35 | - st,lsm330dlc-accel | 38 | - st,lis3lv02dl-accel |
| 36 | - st,lis331dl-accel | 39 | - st,lng2dm-accel |
| 37 | - st,lis331dlh-accel | 40 | - st,lsm303agr-accel |
| 38 | - st,lsm303dl-accel | 41 | - st,lsm303dl-accel |
| 39 | - st,lsm303dlm-accel | 42 | - st,lsm303dlh-accel |
| 40 | - st,lsm330-accel | 43 | - st,lsm303dlhc-accel |
| 41 | - st,lsm303agr-accel | 44 | - st,lsm303dlm-accel |
| 42 | - st,lis2dh12-accel | 45 | - st,lsm330-accel |
| 43 | - st,h3lis331dl-accel | 46 | - st,lsm330d-accel |
| 44 | - st,lng2dm-accel | 47 | - st,lsm330dl-accel |
| 45 | - st,lis3l02dq | 48 | - st,lsm330dlc-accel |
| 46 | - st,lis2dw12 | 49 | - description: STMicroelectronics Gyroscopes |
| 47 | - st,lis3dhh | 50 | enum: |
| 48 | - st,lis3de | 51 | - st,l3g4200d-gyro |
| 49 | - st,lis2de12 | 52 | - st,l3g4is-gyro |
| 50 | - st,lis2hh12 | 53 | - st,l3gd20-gyro |
| 51 | # Gyroscopes | 54 | - st,l3gd20h-gyro |
| 52 | - st,l3g4200d-gyro | 55 | - st,lsm330-gyro |
| 53 | - st,lsm330d-gyro | 56 | - st,lsm330d-gyro |
| 54 | - st,lsm330dl-gyro | 57 | - st,lsm330dl-gyro |
| 55 | - st,lsm330dlc-gyro | 58 | - st,lsm330dlc-gyro |
| 56 | - st,l3gd20-gyro | 59 | - st,lsm9ds0-gyro |
| 57 | - st,l3gd20h-gyro | 60 | - description: STMicroelectronics Magnetometers |
| 58 | - st,l3g4is-gyro | 61 | enum: |
| 59 | - st,lsm330-gyro | 62 | - st,lis2mdl |
| 60 | - st,lsm9ds0-gyro | 63 | - st,lis3mdl-magn |
| 61 | # Magnetometers | 64 | - st,lsm303agr-magn |
| 62 | - st,lsm303agr-magn | 65 | - st,lsm303dlh-magn |
| 63 | - st,lsm303dlh-magn | 66 | - st,lsm303dlhc-magn |
| 64 | - st,lsm303dlhc-magn | 67 | - st,lsm303dlm-magn |
| 65 | - st,lsm303dlm-magn | 68 | - st,lsm9ds1-magn |
| 66 | - st,lis3mdl-magn | 69 | - description: STMicroelectronics Pressure Sensors |
| 67 | - st,lis2mdl | 70 | enum: |
| 68 | - st,lsm9ds1-magn | 71 | - st,lps001wp-press |
| 69 | - st,iis2mdc | 72 | - st,lps22hb-press |
| 70 | # Pressure sensors | 73 | - st,lps22hh |
| 71 | - st,lps001wp-press | 74 | - st,lps25h-press |
| 72 | - st,lps25h-press | 75 | - st,lps331ap-press |
| 73 | - st,lps331ap-press | 76 | - st,lps33hw |
| 74 | - st,lps22hb-press | 77 | - st,lps35hw |
| 75 | - st,lps33hw | 78 | - description: IMUs |
| 76 | - st,lps35hw | 79 | enum: |
| 77 | - st,lps22hh | 80 | - st,lsm9ds0-imu |
| 81 | - description: Deprecated bindings | ||
| 82 | enum: | ||
| 83 | - st,lis302dl-spi | ||
| 84 | - st,lis3lv02d | ||
| 85 | deprecated: true | ||
| 78 | 86 | ||
| 79 | reg: | 87 | reg: |
| 80 | maxItems: 1 | 88 | maxItems: 1 |
| 81 | 89 | ||
| 82 | interrupts: | 90 | interrupts: |
| 91 | description: interrupt line(s) connected to the DRDY line(s) and/or the | ||
| 92 | Intertial interrupt lines INT1 and INT2 if these exist. This means up to | ||
| 93 | three interrupts, and the DRDY must be the first one if it exists on | ||
| 94 | the package. The trigger edge of the interrupts is sometimes software | ||
| 95 | configurable in the hardware so the operating system should parse this | ||
| 96 | flag and set up the trigger edge as indicated in the device tree. | ||
| 83 | minItems: 1 | 97 | minItems: 1 |
| 98 | maxItems: 2 | ||
| 84 | 99 | ||
| 85 | vdd-supply: true | 100 | vdd-supply: true |
| 86 | vddio-supply: true | 101 | vddio-supply: true |
| 87 | 102 | ||
| 88 | st,drdy-int-pin: | 103 | st,drdy-int-pin: |
| 104 | description: the pin on the package that will be used to signal | ||
| 105 | "data ready" (valid values 1 or 2). This property is not configurable | ||
| 106 | on all sensors. | ||
| 89 | $ref: /schemas/types.yaml#/definitions/uint32 | 107 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 90 | description: | 108 | enum: [1, 2] |
| 91 | Some sensors have multiple possible pins via which they can provide | ||
| 92 | a data ready interrupt. This selects which one. | ||
| 93 | enum: | ||
| 94 | - 1 | ||
| 95 | - 2 | ||
| 96 | 109 | ||
| 97 | drive-open-drain: | 110 | drive-open-drain: |
| 98 | $ref: /schemas/types.yaml#/definitions/flag | 111 | $ref: /schemas/types.yaml#/definitions/flag |
| 99 | description: | | 112 | description: the interrupt/data ready line will be configured |
| 100 | The interrupt/data ready line will be configured as open drain, which | 113 | as open drain, which is useful if several sensors share the same |
| 101 | is useful if several sensors share the same interrupt line. | 114 | interrupt line. (This binding is taken from pinctrl.) |
| 115 | |||
| 116 | mount-matrix: | ||
| 117 | description: an optional 3x3 mounting rotation matrix. | ||
| 118 | |||
| 119 | allOf: | ||
| 120 | - if: | ||
| 121 | properties: | ||
| 122 | compatible: | ||
| 123 | enum: | ||
| 124 | # These have no interrupts | ||
| 125 | - st,lps001wp | ||
| 126 | then: | ||
| 127 | properties: | ||
| 128 | interrupts: false | ||
| 129 | st,drdy-int-pin: false | ||
| 130 | drive-open-drain: false | ||
| 131 | |||
| 132 | - if: | ||
| 133 | properties: | ||
| 134 | compatible: | ||
| 135 | enum: | ||
| 136 | # These have only DRDY | ||
| 137 | - st,lis2mdl | ||
| 138 | - st,lis3l02dq | ||
| 139 | - st,lis3lv02dl-accel | ||
| 140 | - st,lps22hb-press | ||
| 141 | - st,lps22hh | ||
| 142 | - st,lps25h-press | ||
| 143 | - st,lps33hw | ||
| 144 | - st,lps35hw | ||
| 145 | - st,lsm303agr-magn | ||
| 146 | - st,lsm303dlh-magn | ||
| 147 | - st,lsm303dlhc-magn | ||
| 148 | - st,lsm303dlm-magn | ||
| 149 | then: | ||
| 150 | properties: | ||
| 151 | interrupts: | ||
| 152 | maxItems: 1 | ||
| 153 | st,drdy-int-pin: false | ||
| 154 | |||
| 155 | - if: | ||
| 156 | properties: | ||
| 157 | compatible: | ||
| 158 | enum: | ||
| 159 | # Two intertial interrupts i.e. accelerometer/gyro interrupts | ||
| 160 | - st,h3lis331dl-accel | ||
| 161 | - st,l3g4200d-gyro | ||
| 162 | - st,l3g4is-gyro | ||
| 163 | - st,l3gd20-gyro | ||
| 164 | - st,l3gd20h-gyro | ||
| 165 | - st,lis2de12 | ||
| 166 | - st,lis2dw12 | ||
| 167 | - st,lis2hh12 | ||
| 168 | - st,lis2dh12-accel | ||
| 169 | - st,lis331dl-accel | ||
| 170 | - st,lis331dlh-accel | ||
| 171 | - st,lis3de | ||
| 172 | - st,lis3dh-accel | ||
| 173 | - st,lis3dhh | ||
| 174 | - st,lis3mdl-magn | ||
| 175 | - st,lng2dm-accel | ||
| 176 | - st,lps331ap-press | ||
| 177 | - st,lsm303agr-accel | ||
| 178 | - st,lsm303dlh-accel | ||
| 179 | - st,lsm303dlhc-accel | ||
| 180 | - st,lsm303dlm-accel | ||
| 181 | - st,lsm330-accel | ||
| 182 | - st,lsm330-gyro | ||
| 183 | - st,lsm330d-accel | ||
| 184 | - st,lsm330d-gyro | ||
| 185 | - st,lsm330dl-accel | ||
| 186 | - st,lsm330dl-gyro | ||
| 187 | - st,lsm330dlc-accel | ||
| 188 | - st,lsm330dlc-gyro | ||
| 189 | - st,lsm9ds0-gyro | ||
| 190 | - st,lsm9ds1-magn | ||
| 191 | then: | ||
| 192 | properties: | ||
| 193 | interrupts: | ||
| 194 | maxItems: 2 | ||
| 102 | 195 | ||
| 103 | required: | 196 | required: |
| 104 | - compatible | 197 | - compatible |
| @@ -110,15 +203,30 @@ examples: · 5 unmodified lines | |||
| 110 | - | | 203 | - | |
| 111 | #include <dt-bindings/interrupt-controller/irq.h> | 204 | #include <dt-bindings/interrupt-controller/irq.h> |
| 112 | i2c { | 205 | i2c { |
| 113 | #address-cells = <1>; | 206 | #address-cells = <1>; |
| 114 | #size-cells = <0>; | 207 | #size-cells = <0>; |
| 115 | accelerometer@1d { | 208 | |
| 116 | compatible = "st,lis3lv02dl-accel"; | 209 | accelerometer@1c { |
| 117 | reg = <0x1d>; | 210 | compatible = "st,lis331dl-accel"; |
| 118 | interrupt-parent = <&gpio2>; | 211 | reg = <0x1c>; |
| 119 | interrupts = <18 IRQ_TYPE_EDGE_RISING>; | 212 | st,drdy-int-pin = <1>; |
| 120 | pinctrl-0 = <&lis3lv02dl_nhk_mode>; | 213 | vdd-supply = <&ldo1>; |
| 121 | pinctrl-names = "default"; | 214 | vddio-supply = <&ldo2>; |
| 122 | }; | 215 | interrupt-parent = <&gpio>; |
| 216 | interrupts = <18 IRQ_TYPE_EDGE_RISING>, <19 IRQ_TYPE_EDGE_RISING>; | ||
| 217 | }; | ||
| 218 | }; | ||
| 219 | spi { | ||
| 220 | #address-cells = <1>; | ||
| 221 | #size-cells = <0>; | ||
| 222 | num-cs = <1>; | ||
| 223 | |||
| 224 | l3g4200d: gyroscope@0 { | ||
| 225 | compatible = "st,l3g4200d-gyro"; | ||
| 226 | st,drdy-int-pin = <2>; | ||
| 227 | reg = <0>; | ||
| 228 | vdd-supply = <&vcc_io>; | ||
| 229 | vddio-supply = <&vcc_io>; | ||
| 230 | }; | ||
| 123 | }; | 231 | }; |
| 124 | ... | 232 | ... |
| @@ -0,0 +1,41 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: "http://devicetree.org/schemas/iio/temperature/ti,tmp117.yaml#" | ||
| 5 | $schema: "http://devicetree.org/meta-schemas/core.yaml#" | ||
| 6 | |||
| 7 | title: "TI TMP117 - Digital temperature sensor with integrated NV memory" | ||
| 8 | |||
| 9 | description: | | ||
| 10 | TI TMP117 - Digital temperature sensor with integrated NV memory that supports | ||
| 11 | I2C interface. | ||
| 12 | https://www.ti.com/lit/gpn/tmp1 | ||
| 13 | |||
| 14 | maintainers: | ||
| 15 | - Puranjay Mohan <puranjay12@gmail.com> | ||
| 16 | |||
| 17 | properties: | ||
| 18 | compatible: | ||
| 19 | enum: | ||
| 20 | - ti,tmp117 | ||
| 21 | |||
| 22 | reg: | ||
| 23 | maxItems: 1 | ||
| 24 | |||
| 25 | required: | ||
| 26 | - compatible | ||
| 27 | - reg | ||
| 28 | |||
| 29 | additionalProperties: false | ||
| 30 | |||
| 31 | examples: | ||
| 32 | - | | ||
| 33 | i2c { | ||
| 34 | #address-cells = <1>; | ||
| 35 | #size-cells = <0>; | ||
| 36 | |||
| 37 | tmp117@48 { | ||
| 38 | compatible = "ti,tmp117"; | ||
| 39 | reg = <0x48>; | ||
| 40 | }; | ||
| 41 | }; | ||
File renamed without changes.
| @@ -14,7 +14,7 @@ description: | · 13 unmodified lines | |||
| 14 | It is a MIPI System Power Management (SPMI) controller. | 14 | It is a MIPI System Power Management (SPMI) controller. |
| 15 | 15 | ||
| 16 | The PMIC part is provided by | 16 | The PMIC part is provided by |
| 17 | drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml. | 17 | ./Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml. |
| 18 | 18 | ||
| 19 | allOf: | 19 | allOf: |
| 20 | - $ref: spmi.yaml# | 20 | - $ref: spmi.yaml# |
| @@ -30,7 +30,7 @@ properties: · 9 unmodified lines | |||
| 30 | reg: | 30 | reg: |
| 31 | maxItems: 1 | 31 | maxItems: 1 |
| 32 | 32 | ||
| 33 | spmi-channel: | 33 | hisilicon,spmi-channel: |
| 34 | $ref: /schemas/types.yaml#/definitions/uint32 | 34 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 35 | description: | | 35 | description: | |
| 36 | number of the Kirin 970 SPMI channel where the SPMI devices are connected. | 36 | number of the Kirin 970 SPMI channel where the SPMI devices are connected. |
| @@ -38,10 +38,12 @@ properties: · 1 unmodified line | |||
| 38 | required: | 38 | required: |
| 39 | - compatible | 39 | - compatible |
| 40 | - reg | 40 | - reg |
| 41 | - spmi-channel | 41 | - hisilicon,spmi-channel |
| 42 | 42 | ||
| 43 | patternProperties: | 43 | patternProperties: |
| 44 | "@[0-9a-f]$": | 44 | "@[0-9a-f]$": |
| 45 | type: object | ||
| 46 | |||
| 45 | description: | | 47 | description: | |
| 46 | PMIC properties, which are specific to the used SPMI PMIC device(s). | 48 | PMIC properties, which are specific to the used SPMI PMIC device(s). |
| 47 | When used in combination with HiSilicon 6421v600, the properties | 49 | When used in combination with HiSilicon 6421v600, the properties |
| @@ -61,7 +63,7 @@ examples: · 13 unmodified lines | |||
| 61 | #address-cells = <2>; | 63 | #address-cells = <2>; |
| 62 | #size-cells = <0>; | 64 | #size-cells = <0>; |
| 63 | reg = <0x0 0xfff24000 0x0 0x1000>; | 65 | reg = <0x0 0xfff24000 0x0 0x1000>; |
| 64 | spmi-channel = <2>; | 66 | hisilicon,spmi-channel = <2>; |
| 65 | 67 | ||
| 66 | pmic@0 { | 68 | pmic@0 { |
| 67 | reg = <0 0>; | 69 | reg = <0 0>; |
| @@ -177,8 +177,14 @@ properties: · 176 unmodified lines | |||
| 177 | - meas,tsys01 | 177 | - meas,tsys01 |
| 178 | # MEMSIC magnetometer | 178 | # MEMSIC magnetometer |
| 179 | - memsic,mmc35240 | 179 | - memsic,mmc35240 |
| 180 | # MEMSIC 3-axis accelerometer | ||
| 181 | - memsic,mx4005 | ||
| 180 | # MEMSIC 2-axis 8-bit digital accelerometer | 182 | # MEMSIC 2-axis 8-bit digital accelerometer |
| 181 | - memsic,mxc6225 | 183 | - memsic,mxc6225 |
| 184 | # MEMSIC 2-axis 8-bit digital accelerometer | ||
| 185 | - memsic,mxc6255 | ||
| 186 | # MEMSIC 3-axis accelerometer | ||
| 187 | - memsic,mxc6655 | ||
| 182 | # Microchip differential I2C ADC, 1 Channel, 18 bit | 188 | # Microchip differential I2C ADC, 1 Channel, 18 bit |
| 183 | - microchip,mcp3421 | 189 | - microchip,mcp3421 |
| 184 | # Microchip differential I2C ADC, 2 Channel, 18 bit | 190 | # Microchip differential I2C ADC, 2 Channel, 18 bit |
| @@ -263,6 +269,10 @@ properties: · 78 unmodified lines | |||
| 263 | - sensirion,sgpc3 | 269 | - sensirion,sgpc3 |
| 264 | # Sensirion multi-pixel gas sensor with I2C interface | 270 | # Sensirion multi-pixel gas sensor with I2C interface |
| 265 | - sensirion,sgp30 | 271 | - sensirion,sgp30 |
| 272 | # Sensortek 3 axis accelerometer | ||
| 273 | - sensortek,stk8312 | ||
| 274 | # Sensortek 3 axis accelerometer | ||
| 275 | - sensortek,stk8ba50 | ||
| 266 | # SGX Sensortech VZ89X Sensors | 276 | # SGX Sensortech VZ89X Sensors |
| 267 | - sgx,vz89x | 277 | - sgx,vz89x |
| 268 | # Relative Humidity and Temperature Sensors | 278 | # Relative Humidity and Temperature Sensors |
| @@ -307,7 +307,7 @@ Determining the type of extension to create is a matter of scope. · 306 unmodified lines | |||
| 307 | 307 | ||
| 308 | * Device extensions are attributes that expose information/control | 308 | * Device extensions are attributes that expose information/control |
| 309 | non-specific to a particular Count or Signal. This is where you would | 309 | non-specific to a particular Count or Signal. This is where you would |
| 310 | put your global features or other miscellanous functionality. | 310 | put your global features or other miscellaneous functionality. |
| 311 | 311 | ||
| 312 | For example, if your device has an overtemp sensor, you can report the | 312 | For example, if your device has an overtemp sensor, you can report the |
| 313 | chip overheated via a device extension called "error_overtemp": | 313 | chip overheated via a device extension called "error_overtemp": |
| @@ -299,7 +299,6 @@ M: William Breathitt Gray <vilhelm.gray@gmail.com> · 298 unmodified lines | |||
| 299 | M: Syed Nayyar Waris <syednwaris@gmail.com> | 299 | M: Syed Nayyar Waris <syednwaris@gmail.com> |
| 300 | L: linux-iio@vger.kernel.org | 300 | L: linux-iio@vger.kernel.org |
| 301 | S: Maintained | 301 | S: Maintained |
| 302 | F: Documentation/ABI/testing/sysfs-bus-counter-104-quad-8 | ||
| 303 | F: drivers/counter/104-quad-8.c | 302 | F: drivers/counter/104-quad-8.c |
| 304 | 303 | ||
| 305 | ACCES PCI-IDIO-16 GPIO DRIVER | 304 | ACCES PCI-IDIO-16 GPIO DRIVER |
| @@ -4738,7 +4737,7 @@ COUNTER SUBSYSTEM · 4432 unmodified lines | |||
| 4738 | M: William Breathitt Gray <vilhelm.gray@gmail.com> | 4737 | M: William Breathitt Gray <vilhelm.gray@gmail.com> |
| 4739 | L: linux-iio@vger.kernel.org | 4738 | L: linux-iio@vger.kernel.org |
| 4740 | S: Maintained | 4739 | S: Maintained |
| 4741 | F: Documentation/ABI/testing/sysfs-bus-counter* | 4740 | F: Documentation/ABI/testing/sysfs-bus-counter |
| 4742 | F: Documentation/driver-api/generic-counter.rst | 4741 | F: Documentation/driver-api/generic-counter.rst |
| 4743 | F: drivers/counter/ | 4742 | F: drivers/counter/ |
| 4744 | F: include/linux/counter.h | 4743 | F: include/linux/counter.h |
| @@ -7189,7 +7188,6 @@ FLEXTIMER FTM-QUADDEC DRIVER · 2444 unmodified lines | |||
| 7189 | M: Patrick Havelange <patrick.havelange@essensium.com> | 7188 | M: Patrick Havelange <patrick.havelange@essensium.com> |
| 7190 | L: linux-iio@vger.kernel.org | 7189 | L: linux-iio@vger.kernel.org |
| 7191 | S: Maintained | 7190 | S: Maintained |
| 7192 | F: Documentation/ABI/testing/sysfs-bus-counter-ftm-quaddec | ||
| 7193 | F: Documentation/devicetree/bindings/counter/ftm-quaddec.txt | 7191 | F: Documentation/devicetree/bindings/counter/ftm-quaddec.txt |
| 7194 | F: drivers/counter/ftm-quaddec.c | 7192 | F: drivers/counter/ftm-quaddec.c |
| 7195 | 7193 | ||
| @@ -8397,6 +8395,13 @@ S: Maintained · 1201 unmodified lines | |||
| 8397 | W: http://www.hisilicon.com | 8395 | W: http://www.hisilicon.com |
| 8398 | F: drivers/spi/spi-hisi-kunpeng.c | 8396 | F: drivers/spi/spi-hisi-kunpeng.c |
| 8399 | 8397 | ||
| 8398 | HISILICON SPMI CONTROLLER DRIVER FOR HIKEY 970 | ||
| 8399 | M: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | ||
| 8400 | L: linux-kernel@vger.kernel.org | ||
| 8401 | S: Maintained | ||
| 8402 | F: Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml | ||
| 8403 | F: drivers/spmi/hisi-spmi-controller.c | ||
| 8404 | |||
| 8400 | HISILICON STAGING DRIVERS FOR HIKEY 960/970 | 8405 | HISILICON STAGING DRIVERS FOR HIKEY 960/970 |
| 8401 | M: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> | 8406 | M: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
| 8402 | S: Maintained | 8407 | S: Maintained |
| @@ -9475,6 +9480,11 @@ L: linux-pm@vger.kernel.org · 1072 unmodified lines | |||
| 9475 | S: Supported | 9480 | S: Supported |
| 9476 | F: drivers/cpufreq/intel_pstate.c | 9481 | F: drivers/cpufreq/intel_pstate.c |
| 9477 | 9482 | ||
| 9483 | INTEL QUADRATURE ENCODER PERIPHERAL DRIVER | ||
| 9484 | M: Jarkko Nikula <jarkko.nikula@linux.intel.com> | ||
| 9485 | L: linux-iio@vger.kernel.org | ||
| 9486 | F: drivers/counter/intel-qep.c | ||
| 9487 | |||
| 9478 | INTEL SCU DRIVERS | 9488 | INTEL SCU DRIVERS |
| 9479 | M: Mika Westerberg <mika.westerberg@linux.intel.com> | 9489 | M: Mika Westerberg <mika.westerberg@linux.intel.com> |
| 9480 | S: Maintained | 9490 | S: Maintained |
| @@ -16661,6 +16671,8 @@ M: Tomasz Duszynski <tduszyns@gmail.com> · 7180 unmodified lines | |||
| 16661 | S: Maintained | 16671 | S: Maintained |
| 16662 | F: Documentation/devicetree/bindings/iio/chemical/sensirion,sps30.yaml | 16672 | F: Documentation/devicetree/bindings/iio/chemical/sensirion,sps30.yaml |
| 16663 | F: drivers/iio/chemical/sps30.c | 16673 | F: drivers/iio/chemical/sps30.c |
| 16674 | F: drivers/iio/chemical/sps30_i2c.c | ||
| 16675 | F: drivers/iio/chemical/sps30_serial.c | ||
| 16664 | 16676 | ||
| 16665 | SERIAL DEVICE BUS | 16677 | SERIAL DEVICE BUS |
| 16666 | M: Rob Herring <robh@kernel.org> | 16678 | M: Rob Herring <robh@kernel.org> |
| @@ -18285,6 +18297,13 @@ F: Documentation/devicetree/bindings/hwmon/ti,tps23861.yaml · 1618 unmodified lines | |||
| 18285 | F: Documentation/hwmon/tps23861.rst | 18297 | F: Documentation/hwmon/tps23861.rst |
| 18286 | F: drivers/hwmon/tps23861.c | 18298 | F: drivers/hwmon/tps23861.c |
| 18287 | 18299 | ||
| 18300 | TEXAS INSTRUMENTS' TMP117 TEMPERATURE SENSOR DRIVER | ||
| 18301 | M: Puranjay Mohan <puranjay12@gmail.com> | ||
| 18302 | L: linux-iio@vger.kernel.org | ||
| 18303 | S: Supported | ||
| 18304 | F: Documentation/devicetree/bindings/iio/temperature/ti,tmp117.yaml | ||
| 18305 | F: drivers/iio/temperature/tmp117.c | ||
| 18306 | |||
| 18288 | THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER | 18307 | THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER |
| 18289 | M: Hans Verkuil <hverkuil@xs4all.nl> | 18308 | M: Hans Verkuil <hverkuil@xs4all.nl> |
| 18290 | L: linux-media@vger.kernel.org | 18309 | L: linux-media@vger.kernel.org |
| @@ -18521,6 +18540,14 @@ S: Supported · 230 unmodified lines | |||
| 18521 | F: Documentation/devicetree/bindings/net/nfc/trf7970a.txt | 18540 | F: Documentation/devicetree/bindings/net/nfc/trf7970a.txt |
| 18522 | F: drivers/nfc/trf7970a.c | 18541 | F: drivers/nfc/trf7970a.c |
| 18523 | 18542 | ||
| 18543 | TI TSC2046 ADC DRIVER | ||
| 18544 | M: Oleksij Rempel <o.rempel@pengutronix.de> | ||
| 18545 | R: kernel@pengutronix.de | ||
| 18546 | L: linux-iio@vger.kernel.org | ||
| 18547 | S: Maintained | ||
| 18548 | F: Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml | ||
| 18549 | F: drivers/iio/adc/ti-tsc2046.c | ||
| 18550 | |||
| 18524 | TI TWL4030 SERIES SOC CODEC DRIVER | 18551 | TI TWL4030 SERIES SOC CODEC DRIVER |
| 18525 | M: Peter Ujfalusi <peter.ujfalusi@gmail.com> | 18552 | M: Peter Ujfalusi <peter.ujfalusi@gmail.com> |
| 18526 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | 18553 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
| @@ -19037,7 +19064,7 @@ L: linux-usb@vger.kernel.org · 510 unmodified lines | |||
| 19037 | S: Maintained | 19064 | S: Maintained |
| 19038 | F: drivers/usb/roles/intel-xhci-usb-role-switch.c | 19065 | F: drivers/usb/roles/intel-xhci-usb-role-switch.c |
| 19039 | 19066 | ||
| 19040 | USB IP DRIVER FOR HISILICON KIRIN | 19067 | USB IP DRIVER FOR HISILICON KIRIN 960 |
| 19041 | M: Yu Chen <chenyu56@huawei.com> | 19068 | M: Yu Chen <chenyu56@huawei.com> |
| 19042 | M: Binghui Wang <wangbinghui@hisilicon.com> | 19069 | M: Binghui Wang <wangbinghui@hisilicon.com> |
| 19043 | L: linux-usb@vger.kernel.org | 19070 | L: linux-usb@vger.kernel.org |
| @@ -19045,6 +19072,13 @@ S: Maintained · 1 unmodified line | |||
| 19045 | F: Documentation/devicetree/bindings/phy/hisilicon,hi3660-usb3.yaml | 19072 | F: Documentation/devicetree/bindings/phy/hisilicon,hi3660-usb3.yaml |
| 19046 | F: drivers/phy/hisilicon/phy-hi3660-usb3.c | 19073 | F: drivers/phy/hisilicon/phy-hi3660-usb3.c |
| 19047 | 19074 | ||
| 19075 | USB IP DRIVER FOR HISILICON KIRIN 970 | ||
| 19076 | M: Mauro Carvalho Chehab <mchehab@kernel.org> | ||
| 19077 | L: linux-usb@vger.kernel.org | ||
| 19078 | S: Maintained | ||
| 19079 | F: Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml | ||
| 19080 | F: drivers/phy/hisilicon/phy-kirin970-usb3.c | ||
| 19081 | |||
| 19048 | USB ISP116X DRIVER | 19082 | USB ISP116X DRIVER |
| 19049 | M: Olav Kongas <ok@artecdesign.ee> | 19083 | M: Olav Kongas <ok@artecdesign.ee> |
| 19050 | L: linux-usb@vger.kernel.org | 19084 | L: linux-usb@vger.kernel.org |
| @@ -0,0 +1,10 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef __ASM_MACH_RALINK_SPACES_H_ | ||
| 3 | #define __ASM_MACH_RALINK_SPACES_H_ | ||
| 4 | |||
| 5 | #define PCI_IOBASE _AC(0xa0000000, UL) | ||
| 6 | #define PCI_IOSIZE SZ_16M | ||
| 7 | #define IO_SPACE_LIMIT (PCI_IOSIZE - 1) | ||
| 8 | |||
| 9 | #include <asm/mach-generic/spaces.h> | ||
| 10 | #endif | ||
| @@ -186,19 +186,6 @@ static void set_full_scales(struct jr3_sensor __iomem *sensor, · 185 unmodified lines | |||
| 186 | set_s16(&sensor->command_word0, 0x0a00); | 186 | set_s16(&sensor->command_word0, 0x0a00); |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | static struct six_axis_t get_min_full_scales(struct jr3_sensor __iomem *sensor) | ||
| 190 | { | ||
| 191 | struct six_axis_t result; | ||
| 192 | |||
| 193 | result.fx = get_s16(&sensor->min_full_scale.fx); | ||
| 194 | result.fy = get_s16(&sensor->min_full_scale.fy); | ||
| 195 | result.fz = get_s16(&sensor->min_full_scale.fz); | ||
| 196 | result.mx = get_s16(&sensor->min_full_scale.mx); | ||
| 197 | result.my = get_s16(&sensor->min_full_scale.my); | ||
| 198 | result.mz = get_s16(&sensor->min_full_scale.mz); | ||
| 199 | return result; | ||
| 200 | } | ||
| 201 | |||
| 202 | static struct six_axis_t get_max_full_scales(struct jr3_sensor __iomem *sensor) | 189 | static struct six_axis_t get_max_full_scales(struct jr3_sensor __iomem *sensor) |
| 203 | { | 190 | { |
| 204 | struct six_axis_t result; | 191 | struct six_axis_t result; |
| @@ -504,10 +491,8 @@ jr3_pci_poll_subdevice(struct comedi_subdevice *s) · 299 unmodified lines | |||
| 504 | result = poll_delay_min_max(20, 100); | 491 | result = poll_delay_min_max(20, 100); |
| 505 | } else { | 492 | } else { |
| 506 | /* Set full scale */ | 493 | /* Set full scale */ |
| 507 | struct six_axis_t min_full_scale; | ||
| 508 | struct six_axis_t max_full_scale; | 494 | struct six_axis_t max_full_scale; |
| 509 | 495 | ||
| 510 | min_full_scale = get_min_full_scales(sensor); | ||
| 511 | max_full_scale = get_max_full_scales(sensor); | 496 | max_full_scale = get_max_full_scales(sensor); |
| 512 | set_full_scales(sensor, max_full_scale); | 497 | set_full_scales(sensor, max_full_scale); |
| 513 | 498 | ||
| @@ -21,7 +21,7 @@ · 20 unmodified lines | |||
| 21 | 21 | ||
| 22 | static unsigned int base[max_num_isa_dev(QUAD8_EXTENT)]; | 22 | static unsigned int base[max_num_isa_dev(QUAD8_EXTENT)]; |
| 23 | static unsigned int num_quad8; | 23 | static unsigned int num_quad8; |
| 24 | module_param_array(base, uint, &num_quad8, 0); | 24 | module_param_hw_array(base, uint, ioport, &num_quad8, 0); |
| 25 | MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses"); | 25 | MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses"); |
| 26 | 26 | ||
| 27 | #define QUAD8_NUM_COUNTERS 8 | 27 | #define QUAD8_NUM_COUNTERS 8 |
| @@ -193,7 +193,7 @@ enum quad8_count_function { · 165 unmodified lines | |||
| 193 | QUAD8_COUNT_FUNCTION_QUADRATURE_X4 | 193 | QUAD8_COUNT_FUNCTION_QUADRATURE_X4 |
| 194 | }; | 194 | }; |
| 195 | 195 | ||
| 196 | static enum counter_count_function quad8_count_functions_list[] = { | 196 | static const enum counter_count_function quad8_count_functions_list[] = { |
| 197 | [QUAD8_COUNT_FUNCTION_PULSE_DIRECTION] = COUNTER_COUNT_FUNCTION_PULSE_DIRECTION, | 197 | [QUAD8_COUNT_FUNCTION_PULSE_DIRECTION] = COUNTER_COUNT_FUNCTION_PULSE_DIRECTION, |
| 198 | [QUAD8_COUNT_FUNCTION_QUADRATURE_X1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A, | 198 | [QUAD8_COUNT_FUNCTION_QUADRATURE_X1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A, |
| 199 | [QUAD8_COUNT_FUNCTION_QUADRATURE_X2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A, | 199 | [QUAD8_COUNT_FUNCTION_QUADRATURE_X2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A, |
| @@ -305,12 +305,12 @@ enum quad8_synapse_action { · 105 unmodified lines | |||
| 305 | QUAD8_SYNAPSE_ACTION_BOTH_EDGES | 305 | QUAD8_SYNAPSE_ACTION_BOTH_EDGES |
| 306 | }; | 306 | }; |
| 307 | 307 | ||
| 308 | static enum counter_synapse_action quad8_index_actions_list[] = { | 308 | static const enum counter_synapse_action quad8_index_actions_list[] = { |
| 309 | [QUAD8_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, | 309 | [QUAD8_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, |
| 310 | [QUAD8_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE | 310 | [QUAD8_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE |
| 311 | }; | 311 | }; |
| 312 | 312 | ||
| 313 | static enum counter_synapse_action quad8_synapse_actions_list[] = { | 313 | static const enum counter_synapse_action quad8_synapse_actions_list[] = { |
| 314 | [QUAD8_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, | 314 | [QUAD8_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, |
| 315 | [QUAD8_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, | 315 | [QUAD8_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, |
| 316 | [QUAD8_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE, | 316 | [QUAD8_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE, |
| @@ -632,8 +632,8 @@ static ssize_t quad8_count_preset_read(struct counter_device *counter, · 315 unmodified lines | |||
| 632 | return sprintf(buf, "%u\n", priv->preset[count->id]); | 632 | return sprintf(buf, "%u\n", priv->preset[count->id]); |
| 633 | } | 633 | } |
| 634 | 634 | ||
| 635 | static void quad8_preset_register_set(struct quad8 *priv, int id, | 635 | static void quad8_preset_register_set(struct quad8 *const priv, const int id, |
| 636 | unsigned int preset) | 636 | const unsigned int preset) |
| 637 | { | 637 | { |
| 638 | const unsigned int base_offset = priv->base + 2 * id; | 638 | const unsigned int base_offset = priv->base + 2 * id; |
| 639 | int i; | 639 | int i; |
| @@ -1082,7 +1082,6 @@ static int quad8_probe(struct device *dev, unsigned int id) · 442 unmodified lines | |||
| 1082 | /* Enable all counters */ | 1082 | /* Enable all counters */ |
| 1083 | outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); | 1083 | outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); |
| 1084 | 1084 | ||
| 1085 | /* Register Counter device */ | ||
| 1086 | return devm_counter_register(dev, &priv->counter); | 1085 | return devm_counter_register(dev, &priv->counter); |
| 1087 | } | 1086 | } |
| 1088 | 1087 | ||
| @@ -91,4 +91,14 @@ config MICROCHIP_TCB_CAPTURE · 90 unmodified lines | |||
| 91 | To compile this driver as a module, choose M here: the | 91 | To compile this driver as a module, choose M here: the |
| 92 | module will be called microchip-tcb-capture. | 92 | module will be called microchip-tcb-capture. |
| 93 | 93 | ||
| 94 | config INTEL_QEP | ||
| 95 | tristate "Intel Quadrature Encoder Peripheral driver" | ||
| 96 | depends on PCI | ||
| 97 | help | ||
| 98 | Select this option to enable the Intel Quadrature Encoder Peripheral | ||
| 99 | driver. | ||
| 100 | |||
| 101 | To compile this driver as a module, choose M here: the module | ||
| 102 | will be called intel-qep. | ||
| 103 | |||
| 94 | endif # COUNTER | 104 | endif # COUNTER |
| @@ -12,3 +12,4 @@ obj-$(CONFIG_STM32_LPTIMER_CNT) += stm32-lptimer-cnt.o · 11 unmodified lines | |||
| 12 | obj-$(CONFIG_TI_EQEP) += ti-eqep.o | 12 | obj-$(CONFIG_TI_EQEP) += ti-eqep.o |
| 13 | obj-$(CONFIG_FTM_QUADDEC) += ftm-quaddec.o | 13 | obj-$(CONFIG_FTM_QUADDEC) += ftm-quaddec.o |
| 14 | obj-$(CONFIG_MICROCHIP_TCB_CAPTURE) += microchip-tcb-capture.o | 14 | obj-$(CONFIG_MICROCHIP_TCB_CAPTURE) += microchip-tcb-capture.o |
| 15 | obj-$(CONFIG_INTEL_QEP) += intel-qep.o | ||
| @@ -162,7 +162,7 @@ enum ftm_quaddec_synapse_action { · 161 unmodified lines | |||
| 162 | FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES, | 162 | FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES, |
| 163 | }; | 163 | }; |
| 164 | 164 | ||
| 165 | static enum counter_synapse_action ftm_quaddec_synapse_actions[] = { | 165 | static const enum counter_synapse_action ftm_quaddec_synapse_actions[] = { |
| 166 | [FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES] = | 166 | [FTM_QUADDEC_SYNAPSE_ACTION_BOTH_EDGES] = |
| 167 | COUNTER_SYNAPSE_ACTION_BOTH_EDGES | 167 | COUNTER_SYNAPSE_ACTION_BOTH_EDGES |
| 168 | }; | 168 | }; |
| @@ -0,0 +1,544 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Intel Quadrature Encoder Peripheral driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2019-2021 Intel Corporation | ||
| 6 | * | ||
| 7 | * Author: Felipe Balbi (Intel) | ||
| 8 | * Author: Jarkko Nikula <jarkko.nikula@linux.intel.com> | ||
| 9 | * Author: Raymond Tan <raymond.tan@intel.com> | ||
| 10 | */ | ||
| 11 | #include <linux/bitops.h> | ||
| 12 | #include <linux/counter.h> | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/mutex.h> | ||
| 16 | #include <linux/pci.h> | ||
| 17 | #include <linux/pm_runtime.h> | ||
| 18 | |||
| 19 | #define INTEL_QEPCON 0x00 | ||
| 20 | #define INTEL_QEPFLT 0x04 | ||
| 21 | #define INTEL_QEPCOUNT 0x08 | ||
| 22 | #define INTEL_QEPMAX 0x0c | ||
| 23 | #define INTEL_QEPWDT 0x10 | ||
| 24 | #define INTEL_QEPCAPDIV 0x14 | ||
| 25 | #define INTEL_QEPCNTR 0x18 | ||
| 26 | #define INTEL_QEPCAPBUF 0x1c | ||
| 27 | #define INTEL_QEPINT_STAT 0x20 | ||
| 28 | #define INTEL_QEPINT_MASK 0x24 | ||
| 29 | |||
| 30 | /* QEPCON */ | ||
| 31 | #define INTEL_QEPCON_EN BIT(0) | ||
| 32 | #define INTEL_QEPCON_FLT_EN BIT(1) | ||
| 33 | #define INTEL_QEPCON_EDGE_A BIT(2) | ||
| 34 | #define INTEL_QEPCON_EDGE_B BIT(3) | ||
| 35 | #define INTEL_QEPCON_EDGE_INDX BIT(4) | ||
| 36 | #define INTEL_QEPCON_SWPAB BIT(5) | ||
| 37 | #define INTEL_QEPCON_OP_MODE BIT(6) | ||
| 38 | #define INTEL_QEPCON_PH_ERR BIT(7) | ||
| 39 | #define INTEL_QEPCON_COUNT_RST_MODE BIT(8) | ||
| 40 | #define INTEL_QEPCON_INDX_GATING_MASK GENMASK(10, 9) | ||
| 41 | #define INTEL_QEPCON_INDX_GATING(n) (((n) & 3) << 9) | ||
| 42 | #define INTEL_QEPCON_INDX_PAL_PBL INTEL_QEPCON_INDX_GATING(0) | ||
| 43 | #define INTEL_QEPCON_INDX_PAL_PBH INTEL_QEPCON_INDX_GATING(1) | ||
| 44 | #define INTEL_QEPCON_INDX_PAH_PBL INTEL_QEPCON_INDX_GATING(2) | ||
| 45 | #define INTEL_QEPCON_INDX_PAH_PBH INTEL_QEPCON_INDX_GATING(3) | ||
| 46 | #define INTEL_QEPCON_CAP_MODE BIT(11) | ||
| 47 | #define INTEL_QEPCON_FIFO_THRE_MASK GENMASK(14, 12) | ||
| 48 | #define INTEL_QEPCON_FIFO_THRE(n) ((((n) - 1) & 7) << 12) | ||
| 49 | #define INTEL_QEPCON_FIFO_EMPTY BIT(15) | ||
| 50 | |||
| 51 | /* QEPFLT */ | ||
| 52 | #define INTEL_QEPFLT_MAX_COUNT(n) ((n) & 0x1fffff) | ||
| 53 | |||
| 54 | /* QEPINT */ | ||
| 55 | #define INTEL_QEPINT_FIFOCRIT BIT(5) | ||
| 56 | #define INTEL_QEPINT_FIFOENTRY BIT(4) | ||
| 57 | #define INTEL_QEPINT_QEPDIR BIT(3) | ||
| 58 | #define INTEL_QEPINT_QEPRST_UP BIT(2) | ||
| 59 | #define INTEL_QEPINT_QEPRST_DOWN BIT(1) | ||
| 60 | #define INTEL_QEPINT_WDT BIT(0) | ||
| 61 | |||
| 62 | #define INTEL_QEPINT_MASK_ALL GENMASK(5, 0) | ||
| 63 | |||
| 64 | #define INTEL_QEP_CLK_PERIOD_NS 10 | ||
| 65 | |||
| 66 | #define INTEL_QEP_COUNTER_EXT_RW(_name) \ | ||
| 67 | { \ | ||
| 68 | .name = #_name, \ | ||
| 69 | .read = _name##_read, \ | ||
| 70 | .write = _name##_write, \ | ||
| 71 | } | ||
| 72 | |||
| 73 | struct intel_qep { | ||
| 74 | struct counter_device counter; | ||
| 75 | struct mutex lock; | ||
| 76 | struct device *dev; | ||
| 77 | void __iomem *regs; | ||
| 78 | bool enabled; | ||
| 79 | /* Context save registers */ | ||
| 80 | u32 qepcon; | ||
| 81 | u32 qepflt; | ||
| 82 | u32 qepmax; | ||
| 83 | }; | ||
| 84 | |||
| 85 | static inline u32 intel_qep_readl(struct intel_qep *qep, u32 offset) | ||
| 86 | { | ||
| 87 | return readl(qep->regs + offset); | ||
| 88 | } | ||
| 89 | |||
| 90 | static inline void intel_qep_writel(struct intel_qep *qep, | ||
| 91 | u32 offset, u32 value) | ||
| 92 | { | ||
| 93 | writel(value, qep->regs + offset); | ||
| 94 | } | ||
| 95 | |||
| 96 | static void intel_qep_init(struct intel_qep *qep) | ||
| 97 | { | ||
| 98 | u32 reg; | ||
| 99 | |||
| 100 | reg = intel_qep_readl(qep, INTEL_QEPCON); | ||
| 101 | reg &= ~INTEL_QEPCON_EN; | ||
| 102 | intel_qep_writel(qep, INTEL_QEPCON, reg); | ||
| 103 | qep->enabled = false; | ||
| 104 | /* | ||
| 105 | * Make sure peripheral is disabled by flushing the write with | ||
| 106 | * a dummy read | ||
| 107 | */ | ||
| 108 | reg = intel_qep_readl(qep, INTEL_QEPCON); | ||
| 109 | |||
| 110 | reg &= ~(INTEL_QEPCON_OP_MODE | INTEL_QEPCON_FLT_EN); | ||
| 111 | reg |= INTEL_QEPCON_EDGE_A | INTEL_QEPCON_EDGE_B | | ||
| 112 | INTEL_QEPCON_EDGE_INDX | INTEL_QEPCON_COUNT_RST_MODE; | ||
| 113 | intel_qep_writel(qep, INTEL_QEPCON, reg); | ||
| 114 | intel_qep_writel(qep, INTEL_QEPINT_MASK, INTEL_QEPINT_MASK_ALL); | ||
| 115 | } | ||
| 116 | |||
| 117 | static int intel_qep_count_read(struct counter_device *counter, | ||
| 118 | struct counter_count *count, | ||
| 119 | unsigned long *val) | ||
| 120 | { | ||
| 121 | struct intel_qep *const qep = counter->priv; | ||
| 122 | |||
| 123 | pm_runtime_get_sync(qep->dev); | ||
| 124 | *val = intel_qep_readl(qep, INTEL_QEPCOUNT); | ||
| 125 | pm_runtime_put(qep->dev); | ||
| 126 | |||
| 127 | return 0; | ||
| 128 | } | ||
| 129 | |||
| 130 | static const enum counter_count_function intel_qep_count_functions[] = { | ||
| 131 | COUNTER_COUNT_FUNCTION_QUADRATURE_X4, | ||
| 132 | }; | ||
| 133 | |||
| 134 | static int intel_qep_function_get(struct counter_device *counter, | ||
| 135 | struct counter_count *count, | ||
| 136 | size_t *function) | ||
| 137 | { | ||
| 138 | *function = 0; | ||
| 139 | |||
| 140 | return 0; | ||
| 141 | } | ||
| 142 | |||
| 143 | static const enum counter_synapse_action intel_qep_synapse_actions[] = { | ||
| 144 | COUNTER_SYNAPSE_ACTION_BOTH_EDGES, | ||
| 145 | }; | ||
| 146 | |||
| 147 | static int intel_qep_action_get(struct counter_device *counter, | ||
| 148 | struct counter_count *count, | ||
| 149 | struct counter_synapse *synapse, | ||
| 150 | size_t *action) | ||
| 151 | { | ||
| 152 | *action = 0; | ||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | static const struct counter_ops intel_qep_counter_ops = { | ||
| 157 | .count_read = intel_qep_count_read, | ||
| 158 | .function_get = intel_qep_function_get, | ||
| 159 | .action_get = intel_qep_action_get, | ||
| 160 | }; | ||
| 161 | |||
| 162 | #define INTEL_QEP_SIGNAL(_id, _name) { \ | ||
| 163 | .id = (_id), \ | ||
| 164 | .name = (_name), \ | ||
| 165 | } | ||
| 166 | |||
| 167 | static struct counter_signal intel_qep_signals[] = { | ||
| 168 | INTEL_QEP_SIGNAL(0, "Phase A"), | ||
| 169 | INTEL_QEP_SIGNAL(1, "Phase B"), | ||
| 170 | INTEL_QEP_SIGNAL(2, "Index"), | ||
| 171 | }; | ||
| 172 | |||
| 173 | #define INTEL_QEP_SYNAPSE(_signal_id) { \ | ||
| 174 | .actions_list = intel_qep_synapse_actions, \ | ||
| 175 | .num_actions = ARRAY_SIZE(intel_qep_synapse_actions), \ | ||
| 176 | .signal = &intel_qep_signals[(_signal_id)], \ | ||
| 177 | } | ||
| 178 | |||
| 179 | static struct counter_synapse intel_qep_count_synapses[] = { | ||
| 180 | INTEL_QEP_SYNAPSE(0), | ||
| 181 | INTEL_QEP_SYNAPSE(1), | ||
| 182 | INTEL_QEP_SYNAPSE(2), | ||
| 183 | }; | ||
| 184 | |||
| 185 | static ssize_t ceiling_read(struct counter_device *counter, | ||
| 186 | struct counter_count *count, | ||
| 187 | void *priv, char *buf) | ||
| 188 | { | ||
| 189 | struct intel_qep *qep = counter->priv; | ||
| 190 | u32 reg; | ||
| 191 | |||
| 192 | pm_runtime_get_sync(qep->dev); | ||
| 193 | reg = intel_qep_readl(qep, INTEL_QEPMAX); | ||
| 194 | pm_runtime_put(qep->dev); | ||
| 195 | |||
| 196 | return sysfs_emit(buf, "%u\n", reg); | ||
| 197 | } | ||
| 198 | |||
| 199 | static ssize_t ceiling_write(struct counter_device *counter, | ||
| 200 | struct counter_count *count, | ||
| 201 | void *priv, const char *buf, size_t len) | ||
| 202 | { | ||
| 203 | struct intel_qep *qep = counter->priv; | ||
| 204 | u32 max; | ||
| 205 | int ret; | ||
| 206 | |||
| 207 | ret = kstrtou32(buf, 0, &max); | ||
| 208 | if (ret < 0) | ||
| 209 | return ret; | ||
| 210 | |||
| 211 | mutex_lock(&qep->lock); | ||
| 212 | if (qep->enabled) { | ||
| 213 | ret = -EBUSY; | ||
| 214 | goto out; | ||
| 215 | } | ||
| 216 | |||
| 217 | pm_runtime_get_sync(qep->dev); | ||
| 218 | intel_qep_writel(qep, INTEL_QEPMAX, max); | ||
| 219 | pm_runtime_put(qep->dev); | ||
| 220 | ret = len; | ||
| 221 | |||
| 222 | out: | ||
| 223 | mutex_unlock(&qep->lock); | ||
| 224 | return ret; | ||
| 225 | } | ||
| 226 | |||
| 227 | static ssize_t enable_read(struct counter_device *counter, | ||
| 228 | struct counter_count *count, | ||
| 229 | void *priv, char *buf) | ||
| 230 | { | ||
| 231 | struct intel_qep *qep = counter->priv; | ||
| 232 | |||
| 233 | return sysfs_emit(buf, "%u\n", qep->enabled); | ||
| 234 | } | ||
| 235 | |||
| 236 | static ssize_t enable_write(struct counter_device *counter, | ||
| 237 | struct counter_count *count, | ||
| 238 | void *priv, const char *buf, size_t len) | ||
| 239 | { | ||
| 240 | struct intel_qep *qep = counter->priv; | ||
| 241 | u32 reg; | ||
| 242 | bool val, changed; | ||
| 243 | int ret; | ||
| 244 | |||
| 245 | ret = kstrtobool(buf, &val); | ||
| 246 | if (ret) | ||
| 247 | return ret; | ||
| 248 | |||
| 249 | mutex_lock(&qep->lock); | ||
| 250 | changed = val ^ qep->enabled; | ||
| 251 | if (!changed) | ||
| 252 | goto out; | ||
| 253 | |||
| 254 | pm_runtime_get_sync(qep->dev); | ||
| 255 | reg = intel_qep_readl(qep, INTEL_QEPCON); | ||
| 256 | if (val) { | ||
| 257 | /* Enable peripheral and keep runtime PM always on */ | ||
| 258 | reg |= INTEL_QEPCON_EN; | ||
| 259 | pm_runtime_get_noresume(qep->dev); | ||
| 260 | } else { | ||
| 261 | /* Let runtime PM be idle and disable peripheral */ | ||
| 262 | pm_runtime_put_noidle(qep->dev); | ||
| 263 | reg &= ~INTEL_QEPCON_EN; | ||
| 264 | } | ||
| 265 | intel_qep_writel(qep, INTEL_QEPCON, reg); | ||
| 266 | pm_runtime_put(qep->dev); | ||
| 267 | qep->enabled = val; | ||
| 268 | |||
| 269 | out: | ||
| 270 | mutex_unlock(&qep->lock); | ||
| 271 | return len; | ||
| 272 | } | ||
| 273 | |||
| 274 | static ssize_t spike_filter_ns_read(struct counter_device *counter, | ||
| 275 | struct counter_count *count, | ||
| 276 | void *priv, char *buf) | ||
| 277 | { | ||
| 278 | struct intel_qep *qep = counter->priv; | ||
| 279 | u32 reg; | ||
| 280 | |||
| 281 | pm_runtime_get_sync(qep->dev); | ||
| 282 | reg = intel_qep_readl(qep, INTEL_QEPCON); | ||
| 283 | if (!(reg & INTEL_QEPCON_FLT_EN)) { | ||
| 284 | pm_runtime_put(qep->dev); | ||
| 285 | return sysfs_emit(buf, "0\n"); | ||
| 286 | } | ||
| 287 | reg = INTEL_QEPFLT_MAX_COUNT(intel_qep_readl(qep, INTEL_QEPFLT)); | ||
| 288 | pm_runtime_put(qep->dev); | ||
| 289 | |||
| 290 | return sysfs_emit(buf, "%u\n", (reg + 2) * INTEL_QEP_CLK_PERIOD_NS); | ||
| 291 | } | ||
| 292 | |||
| 293 | static ssize_t spike_filter_ns_write(struct counter_device *counter, | ||
| 294 | struct counter_count *count, | ||
| 295 | void *priv, const char *buf, size_t len) | ||
| 296 | { | ||
| 297 | struct intel_qep *qep = counter->priv; | ||
| 298 | u32 reg, length; | ||
| 299 | bool enable; | ||
| 300 | int ret; | ||
| 301 | |||
| 302 | ret = kstrtou32(buf, 0, &length); | ||
| 303 | if (ret < 0) | ||
| 304 | return ret; | ||
| 305 | |||
| 306 | /* | ||
| 307 | * Spike filter length is (MAX_COUNT + 2) clock periods. | ||
| 308 | * Disable filter when userspace writes 0, enable for valid | ||
| 309 | * nanoseconds values and error out otherwise. | ||
| 310 | */ | ||
| 311 | length /= INTEL_QEP_CLK_PERIOD_NS; | ||
| 312 | if (length == 0) { | ||
| 313 | enable = false; | ||
| 314 | length = 0; | ||
| 315 | } else if (length >= 2) { | ||
| 316 | enable = true; | ||
| 317 | length -= 2; | ||
| 318 | } else { | ||
| 319 | return -EINVAL; | ||
| 320 | } | ||
| 321 | |||
| 322 | if (length > INTEL_QEPFLT_MAX_COUNT(length)) | ||
| 323 | return -EINVAL; | ||
| 324 | |||
| 325 | mutex_lock(&qep->lock); | ||
| 326 | if (qep->enabled) { | ||
| 327 | ret = -EBUSY; | ||
| 328 | goto out; | ||
| 329 | } | ||
| 330 | |||
| 331 | pm_runtime_get_sync(qep->dev); | ||
| 332 | reg = intel_qep_readl(qep, INTEL_QEPCON); | ||
| 333 | if (enable) | ||
| 334 | reg |= INTEL_QEPCON_FLT_EN; | ||
| 335 | else | ||
| 336 | reg &= ~INTEL_QEPCON_FLT_EN; | ||
| 337 | intel_qep_writel(qep, INTEL_QEPFLT, length); | ||
| 338 | intel_qep_writel(qep, INTEL_QEPCON, reg); | ||
| 339 | pm_runtime_put(qep->dev); | ||
| 340 | ret = len; | ||
| 341 | |||
| 342 | out: | ||
| 343 | mutex_unlock(&qep->lock); | ||
| 344 | return ret; | ||
| 345 | } | ||
| 346 | |||
| 347 | static ssize_t preset_enable_read(struct counter_device *counter, | ||
| 348 | struct counter_count *count, | ||
| 349 | void *priv, char *buf) | ||
| 350 | { | ||
| 351 | struct intel_qep *qep = counter->priv; | ||
| 352 | u32 reg; | ||
| 353 | |||
| 354 | pm_runtime_get_sync(qep->dev); | ||
| 355 | reg = intel_qep_readl(qep, INTEL_QEPCON); | ||
| 356 | pm_runtime_put(qep->dev); | ||
| 357 | return sysfs_emit(buf, "%u\n", !(reg & INTEL_QEPCON_COUNT_RST_MODE)); | ||
| 358 | } | ||
| 359 | |||
| 360 | static ssize_t preset_enable_write(struct counter_device *counter, | ||
| 361 | struct counter_count *count, | ||
| 362 | void *priv, const char *buf, size_t len) | ||
| 363 | { | ||
| 364 | struct intel_qep *qep = counter->priv; | ||
| 365 | u32 reg; | ||
| 366 | bool val; | ||
| 367 | int ret; | ||
| 368 | |||
| 369 | ret = kstrtobool(buf, &val); | ||
| 370 | if (ret) | ||
| 371 | return ret; | ||
| 372 | |||
| 373 | mutex_lock(&qep->lock); | ||
| 374 | if (qep->enabled) { | ||
| 375 | ret = -EBUSY; | ||
| 376 | goto out; | ||
| 377 | } | ||
| 378 | |||
| 379 | pm_runtime_get_sync(qep->dev); | ||
| 380 | reg = intel_qep_readl(qep, INTEL_QEPCON); | ||
| 381 | if (val) | ||
| 382 | reg &= ~INTEL_QEPCON_COUNT_RST_MODE; | ||
| 383 | else | ||
| 384 | reg |= INTEL_QEPCON_COUNT_RST_MODE; | ||
| 385 | |||
| 386 | intel_qep_writel(qep, INTEL_QEPCON, reg); | ||
| 387 | pm_runtime_put(qep->dev); | ||
| 388 | ret = len; | ||
| 389 | |||
| 390 | out: | ||
| 391 | mutex_unlock(&qep->lock); | ||
| 392 | |||
| 393 | return ret; | ||
| 394 | } | ||
| 395 | |||
| 396 | static const struct counter_count_ext intel_qep_count_ext[] = { | ||
| 397 | INTEL_QEP_COUNTER_EXT_RW(ceiling), | ||
| 398 | INTEL_QEP_COUNTER_EXT_RW(enable), | ||
| 399 | INTEL_QEP_COUNTER_EXT_RW(spike_filter_ns), | ||
| 400 | INTEL_QEP_COUNTER_EXT_RW(preset_enable) | ||
| 401 | }; | ||
| 402 | |||
| 403 | static struct counter_count intel_qep_counter_count[] = { | ||
| 404 | { | ||
| 405 | .id = 0, | ||
| 406 | .name = "Channel 1 Count", | ||
| 407 | .functions_list = intel_qep_count_functions, | ||
| 408 | .num_functions = ARRAY_SIZE(intel_qep_count_functions), | ||
| 409 | .synapses = intel_qep_count_synapses, | ||
| 410 | .num_synapses = ARRAY_SIZE(intel_qep_count_synapses), | ||
| 411 | .ext = intel_qep_count_ext, | ||
| 412 | .num_ext = ARRAY_SIZE(intel_qep_count_ext), | ||
| 413 | }, | ||
| 414 | }; | ||
| 415 | |||
| 416 | static int intel_qep_probe(struct pci_dev *pci, const struct pci_device_id *id) | ||
| 417 | { | ||
| 418 | struct intel_qep *qep; | ||
| 419 | struct device *dev = &pci->dev; | ||
| 420 | void __iomem *regs; | ||
| 421 | int ret; | ||
| 422 | |||
| 423 | qep = devm_kzalloc(dev, sizeof(*qep), GFP_KERNEL); | ||
| 424 | if (!qep) | ||
| 425 | return -ENOMEM; | ||
| 426 | |||
| 427 | ret = pcim_enable_device(pci); | ||
| 428 | if (ret) | ||
| 429 | return ret; | ||
| 430 | |||
| 431 | pci_set_master(pci); | ||
| 432 | |||
| 433 | ret = pcim_iomap_regions(pci, BIT(0), pci_name(pci)); | ||
| 434 | if (ret) | ||
| 435 | return ret; | ||
| 436 | |||
| 437 | regs = pcim_iomap_table(pci)[0]; | ||
| 438 | if (!regs) | ||
| 439 | return -ENOMEM; | ||
| 440 | |||
| 441 | qep->dev = dev; | ||
| 442 | qep->regs = regs; | ||
| 443 | mutex_init(&qep->lock); | ||
| 444 | |||
| 445 | intel_qep_init(qep); | ||
| 446 | pci_set_drvdata(pci, qep); | ||
| 447 | |||
| 448 | qep->counter.name = pci_name(pci); | ||
| 449 | qep->counter.parent = dev; | ||
| 450 | qep->counter.ops = &intel_qep_counter_ops; | ||
| 451 | qep->counter.counts = intel_qep_counter_count; | ||
| 452 | qep->counter.num_counts = ARRAY_SIZE(intel_qep_counter_count); | ||
| 453 | qep->counter.signals = intel_qep_signals; | ||
| 454 | qep->counter.num_signals = ARRAY_SIZE(intel_qep_signals); | ||
| 455 | qep->counter.priv = qep; | ||
| 456 | qep->enabled = false; | ||
| 457 | |||
| 458 | pm_runtime_put(dev); | ||
| 459 | pm_runtime_allow(dev); | ||
| 460 | |||
| 461 | return devm_counter_register(&pci->dev, &qep->counter); | ||
| 462 | } | ||
| 463 | |||
| 464 | static void intel_qep_remove(struct pci_dev *pci) | ||
| 465 | { | ||
| 466 | struct intel_qep *qep = pci_get_drvdata(pci); | ||
| 467 | struct device *dev = &pci->dev; | ||
| 468 | |||
| 469 | pm_runtime_forbid(dev); | ||
| 470 | if (!qep->enabled) | ||
| 471 | pm_runtime_get(dev); | ||
| 472 | |||
| 473 | intel_qep_writel(qep, INTEL_QEPCON, 0); | ||
| 474 | } | ||
| 475 | |||
| 476 | static int __maybe_unused intel_qep_suspend(struct device *dev) | ||
| 477 | { | ||
| 478 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 479 | struct intel_qep *qep = pci_get_drvdata(pdev); | ||
| 480 | |||
| 481 | qep->qepcon = intel_qep_readl(qep, INTEL_QEPCON); | ||
| 482 | qep->qepflt = intel_qep_readl(qep, INTEL_QEPFLT); | ||
| 483 | qep->qepmax = intel_qep_readl(qep, INTEL_QEPMAX); | ||
| 484 | |||
| 485 | return 0; | ||
| 486 | } | ||
| 487 | |||
| 488 | static int __maybe_unused intel_qep_resume(struct device *dev) | ||
| 489 | { | ||
| 490 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 491 | struct intel_qep *qep = pci_get_drvdata(pdev); | ||
| 492 | |||
| 493 | /* | ||
| 494 | * Make sure peripheral is disabled when restoring registers and | ||
| 495 | * control register bits that are writable only when the peripheral | ||
| 496 | * is disabled | ||
| 497 | */ | ||
| 498 | intel_qep_writel(qep, INTEL_QEPCON, 0); | ||
| 499 | intel_qep_readl(qep, INTEL_QEPCON); | ||
| 500 | |||
| 501 | intel_qep_writel(qep, INTEL_QEPFLT, qep->qepflt); | ||
| 502 | intel_qep_writel(qep, INTEL_QEPMAX, qep->qepmax); | ||
| 503 | intel_qep_writel(qep, INTEL_QEPINT_MASK, INTEL_QEPINT_MASK_ALL); | ||
| 504 | |||
| 505 | /* Restore all other control register bits except enable status */ | ||
| 506 | intel_qep_writel(qep, INTEL_QEPCON, qep->qepcon & ~INTEL_QEPCON_EN); | ||
| 507 | intel_qep_readl(qep, INTEL_QEPCON); | ||
| 508 | |||
| 509 | /* Restore enable status */ | ||
| 510 | intel_qep_writel(qep, INTEL_QEPCON, qep->qepcon); | ||
| 511 | |||
| 512 | return 0; | ||
| 513 | } | ||
| 514 | |||
| 515 | static UNIVERSAL_DEV_PM_OPS(intel_qep_pm_ops, | ||
| 516 | intel_qep_suspend, intel_qep_resume, NULL); | ||
| 517 | |||
| 518 | static const struct pci_device_id intel_qep_id_table[] = { | ||
| 519 | /* EHL */ | ||
| 520 | { PCI_VDEVICE(INTEL, 0x4bc3), }, | ||
| 521 | { PCI_VDEVICE(INTEL, 0x4b81), }, | ||
| 522 | { PCI_VDEVICE(INTEL, 0x4b82), }, | ||
| 523 | { PCI_VDEVICE(INTEL, 0x4b83), }, | ||
| 524 | { } /* Terminating Entry */ | ||
| 525 | }; | ||
| 526 | MODULE_DEVICE_TABLE(pci, intel_qep_id_table); | ||
| 527 | |||
| 528 | static struct pci_driver intel_qep_driver = { | ||
| 529 | .name = "intel-qep", | ||
| 530 | .id_table = intel_qep_id_table, | ||
| 531 | .probe = intel_qep_probe, | ||
| 532 | .remove = intel_qep_remove, | ||
| 533 | .driver = { | ||
| 534 | .pm = &intel_qep_pm_ops, | ||
| 535 | } | ||
| 536 | }; | ||
| 537 | |||
| 538 | module_pci_driver(intel_qep_driver); | ||
| 539 | |||
| 540 | MODULE_AUTHOR("Felipe Balbi (Intel)"); | ||
| 541 | MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@linux.intel.com>"); | ||
| 542 | MODULE_AUTHOR("Raymond Tan <raymond.tan@intel.com>"); | ||
| 543 | MODULE_LICENSE("GPL"); | ||
| 544 | MODULE_DESCRIPTION("Intel Quadrature Encoder Peripheral driver"); | ||
| @@ -77,7 +77,7 @@ static const struct counter_count_ext interrupt_cnt_ext[] = { · 76 unmodified lines | |||
| 77 | }, | 77 | }, |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | static enum counter_synapse_action interrupt_cnt_synapse_actionss[] = { | 80 | static const enum counter_synapse_action interrupt_cnt_synapse_actions[] = { |
| 81 | COUNTER_SYNAPSE_ACTION_RISING_EDGE, | 81 | COUNTER_SYNAPSE_ACTION_RISING_EDGE, |
| 82 | }; | 82 | }; |
| 83 | 83 | ||
| @@ -112,7 +112,7 @@ static int interrupt_cnt_write(struct counter_device *counter, · 28 unmodified lines | |||
| 112 | return 0; | 112 | return 0; |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | static enum counter_count_function interrupt_cnt_functions[] = { | 115 | static const enum counter_count_function interrupt_cnt_functions[] = { |
| 116 | COUNTER_COUNT_FUNCTION_INCREASE, | 116 | COUNTER_COUNT_FUNCTION_INCREASE, |
| 117 | }; | 117 | }; |
| 118 | 118 | ||
| @@ -194,8 +194,8 @@ static int interrupt_cnt_probe(struct platform_device *pdev) · 75 unmodified lines | |||
| 194 | priv->counter.signals = &priv->signals; | 194 | priv->counter.signals = &priv->signals; |
| 195 | priv->counter.num_signals = 1; | 195 | priv->counter.num_signals = 1; |
| 196 | 196 | ||
| 197 | priv->synapses.actions_list = interrupt_cnt_synapse_actionss; | 197 | priv->synapses.actions_list = interrupt_cnt_synapse_actions; |
| 198 | priv->synapses.num_actions = ARRAY_SIZE(interrupt_cnt_synapse_actionss); | 198 | priv->synapses.num_actions = ARRAY_SIZE(interrupt_cnt_synapse_actions); |
| 199 | priv->synapses.signal = &priv->signals; | 199 | priv->synapses.signal = &priv->signals; |
| 200 | 200 | ||
| 201 | priv->cnts.name = "Channel 0 Count"; | 201 | priv->cnts.name = "Channel 0 Count"; |
| @@ -37,7 +37,7 @@ enum mchp_tc_count_function { · 36 unmodified lines | |||
| 37 | MCHP_TC_FUNCTION_QUADRATURE, | 37 | MCHP_TC_FUNCTION_QUADRATURE, |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | static enum counter_count_function mchp_tc_count_functions[] = { | 40 | static const enum counter_count_function mchp_tc_count_functions[] = { |
| 41 | [MCHP_TC_FUNCTION_INCREASE] = COUNTER_COUNT_FUNCTION_INCREASE, | 41 | [MCHP_TC_FUNCTION_INCREASE] = COUNTER_COUNT_FUNCTION_INCREASE, |
| 42 | [MCHP_TC_FUNCTION_QUADRATURE] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4, | 42 | [MCHP_TC_FUNCTION_QUADRATURE] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4, |
| 43 | }; | 43 | }; |
| @@ -49,7 +49,7 @@ enum mchp_tc_synapse_action { · 5 unmodified lines | |||
| 49 | MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE | 49 | MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | static enum counter_synapse_action mchp_tc_synapse_actions[] = { | 52 | static const enum counter_synapse_action mchp_tc_synapse_actions[] = { |
| 53 | [MCHP_TC_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, | 53 | [MCHP_TC_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, |
| 54 | [MCHP_TC_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, | 54 | [MCHP_TC_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, |
| 55 | [MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE, | 55 | [MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE, |
| @@ -134,7 +134,7 @@ enum stm32_lptim_cnt_function { · 133 unmodified lines | |||
| 134 | STM32_LPTIM_ENCODER_BOTH_EDGE, | 134 | STM32_LPTIM_ENCODER_BOTH_EDGE, |
| 135 | }; | 135 | }; |
| 136 | 136 | ||
| 137 | static enum counter_count_function stm32_lptim_cnt_functions[] = { | 137 | static const enum counter_count_function stm32_lptim_cnt_functions[] = { |
| 138 | [STM32_LPTIM_COUNTER_INCREASE] = COUNTER_COUNT_FUNCTION_INCREASE, | 138 | [STM32_LPTIM_COUNTER_INCREASE] = COUNTER_COUNT_FUNCTION_INCREASE, |
| 139 | [STM32_LPTIM_ENCODER_BOTH_EDGE] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4, | 139 | [STM32_LPTIM_ENCODER_BOTH_EDGE] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4, |
| 140 | }; | 140 | }; |
| @@ -146,7 +146,7 @@ enum stm32_lptim_synapse_action { · 5 unmodified lines | |||
| 146 | STM32_LPTIM_SYNAPSE_ACTION_NONE, | 146 | STM32_LPTIM_SYNAPSE_ACTION_NONE, |
| 147 | }; | 147 | }; |
| 148 | 148 | ||
| 149 | static enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = { | 149 | static const enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = { |
| 150 | /* Index must match with stm32_lptim_cnt_polarity[] (priv->polarity) */ | 150 | /* Index must match with stm32_lptim_cnt_polarity[] (priv->polarity) */ |
| 151 | [STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, | 151 | [STM32_LPTIM_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE, |
| 152 | [STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE, | 152 | [STM32_LPTIM_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE, |
| @@ -50,7 +50,7 @@ enum stm32_count_function { · 49 unmodified lines | |||
| 50 | STM32_COUNT_ENCODER_MODE_3, | 50 | STM32_COUNT_ENCODER_MODE_3, |
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| 53 | static enum counter_count_function stm32_count_functions[] = { | 53 | static const enum counter_count_function stm32_count_functions[] = { |
| 54 | [STM32_COUNT_SLAVE_MODE_DISABLED] = COUNTER_COUNT_FUNCTION_INCREASE, | 54 | [STM32_COUNT_SLAVE_MODE_DISABLED] = COUNTER_COUNT_FUNCTION_INCREASE, |
| 55 | [STM32_COUNT_ENCODER_MODE_1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A, | 55 | [STM32_COUNT_ENCODER_MODE_1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A, |
| 56 | [STM32_COUNT_ENCODER_MODE_2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B, | 56 | [STM32_COUNT_ENCODER_MODE_2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B, |
| @@ -267,7 +267,7 @@ enum stm32_synapse_action { · 210 unmodified lines | |||
| 267 | STM32_SYNAPSE_ACTION_BOTH_EDGES | 267 | STM32_SYNAPSE_ACTION_BOTH_EDGES |
| 268 | }; | 268 | }; |
| 269 | 269 | ||
| 270 | static enum counter_synapse_action stm32_synapse_actions[] = { | 270 | static const enum counter_synapse_action stm32_synapse_actions[] = { |
| 271 | [STM32_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, | 271 | [STM32_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE, |
| 272 | [STM32_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES | 272 | [STM32_SYNAPSE_ACTION_BOTH_EDGES] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES |
| 273 | }; | 273 | }; |
| @@ -89,13 +89,13 @@ config ADXL372_I2C · 88 unmodified lines | |||
| 89 | module will be called adxl372_i2c. | 89 | module will be called adxl372_i2c. |
| 90 | 90 | ||
| 91 | config BMA180 | 91 | config BMA180 |
| 92 | tristate "Bosch BMA023/BMA1x0/BMA25x 3-Axis Accelerometer Driver" | 92 | tristate "Bosch BMA023/BMA1x0/BMA250 3-Axis Accelerometer Driver" |
| 93 | depends on I2C && INPUT_BMA150=n | 93 | depends on I2C && INPUT_BMA150=n |
| 94 | select IIO_BUFFER | 94 | select IIO_BUFFER |
| 95 | select IIO_TRIGGERED_BUFFER | 95 | select IIO_TRIGGERED_BUFFER |
| 96 | help | 96 | help |
| 97 | Say Y here if you want to build a driver for the Bosch BMA023, BMA150 | 97 | Say Y here if you want to build a driver for the Bosch BMA023, BMA150 |
| 98 | BMA180, SMB380, or BMA25x triaxial acceleration sensor. | 98 | BMA180, BMA250 or SMB380 triaxial acceleration sensor. |
| 99 | 99 | ||
| 100 | To compile this driver as a module, choose M here: the | 100 | To compile this driver as a module, choose M here: the |
| 101 | module will be called bma180. | 101 | module will be called bma180. |
| @@ -143,9 +143,12 @@ config BMC150_ACCEL · 41 unmodified lines | |||
| 143 | select BMC150_ACCEL_SPI if SPI | 143 | select BMC150_ACCEL_SPI if SPI |
| 144 | help | 144 | help |
| 145 | Say yes here to build support for the following Bosch accelerometers: | 145 | Say yes here to build support for the following Bosch accelerometers: |
| 146 | BMC150, BMI055, BMA250E, BMA222E, BMA255, BMA280. | 146 | BMA222, BMA222E, BMA250E, BMA253, BMA254, BMA255, BMA280, BMC150, BMI055. |
| 147 | |||
| 148 | Note that some of these are combo modules: | ||
| 149 | - BMC150: accelerometer and magnetometer | ||
| 150 | - BMI055: accelerometer and gyroscope | ||
| 147 | 151 | ||
| 148 | This is a combo module with both accelerometer and magnetometer. | ||
| 149 | This driver is only implementing accelerometer part, which has | 152 | This driver is only implementing accelerometer part, which has |
| 150 | its own address and register map. | 153 | its own address and register map. |
| 151 | 154 | ||
| @@ -226,6 +229,33 @@ config DMARD10 · 74 unmodified lines | |||
| 226 | Choosing M will build the driver as a module. If so, the module | 229 | Choosing M will build the driver as a module. If so, the module |
| 227 | will be called dmard10. | 230 | will be called dmard10. |
| 228 | 231 | ||
| 232 | config FXLS8962AF | ||
| 233 | tristate | ||
| 234 | |||
| 235 | config FXLS8962AF_I2C | ||
| 236 | tristate "NXP FXLS8962AF/FXLS8964AF Accelerometer I2C Driver" | ||
| 237 | depends on I2C | ||
| 238 | select FXLS8962AF | ||
| 239 | select REGMAP_I2C | ||
| 240 | help | ||
| 241 | Say yes here to build support for the NXP 3-axis automotive | ||
| 242 | accelerometer FXLS8962AF/FXLS8964AF with I2C support. | ||
| 243 | |||
| 244 | To compile this driver as a module, choose M here: the module | ||
| 245 | will be called fxls8962af_i2c. | ||
| 246 | |||
| 247 | config FXLS8962AF_SPI | ||
| 248 | tristate "NXP FXLS8962AF/FXLS8964AF Accelerometer SPI Driver" | ||
| 249 | depends on SPI | ||
| 250 | select FXLS8962AF | ||
| 251 | select REGMAP_SPI | ||
| 252 | help | ||
| 253 | Say yes here to build support for the NXP 3-axis automotive | ||
| 254 | accelerometer FXLS8962AF/FXLS8964AF with SPI support. | ||
| 255 | |||
| 256 | To compile this driver as a module, choose M here: the module | ||
| 257 | will be called fxls8962af_spi. | ||
| 258 | |||
| 229 | config HID_SENSOR_ACCEL_3D | 259 | config HID_SENSOR_ACCEL_3D |
| 230 | depends on HID_SENSOR_HUB | 260 | depends on HID_SENSOR_HUB |
| 231 | select IIO_BUFFER | 261 | select IIO_BUFFER |
| @@ -449,6 +479,19 @@ config SCA3000 · 217 unmodified lines | |||
| 449 | To compile this driver as a module, say M here: the module will be | 479 | To compile this driver as a module, say M here: the module will be |
| 450 | called sca3000. | 480 | called sca3000. |
| 451 | 481 | ||
| 482 | config SCA3300 | ||
| 483 | tristate "Murata SCA3300 3-Axis Accelerometer Driver" | ||
| 484 | depends on SPI | ||
| 485 | select CRC8 | ||
| 486 | select IIO_BUFFER | ||
| 487 | select IIO_TRIGGERED_BUFFER | ||
| 488 | help | ||
| 489 | Say yes here to build support for Murata SCA3300 3-Axis | ||
| 490 | accelerometer. | ||
| 491 | |||
| 492 | To compile this driver as a module, choose M here: the module will be | ||
| 493 | called sca3300. | ||
| 494 | |||
| 452 | config STK8312 | 495 | config STK8312 |
| 453 | tristate "Sensortek STK8312 3-Axis Accelerometer Driver" | 496 | tristate "Sensortek STK8312 3-Axis Accelerometer Driver" |
| 454 | depends on I2C | 497 | depends on I2C |
| @@ -27,6 +27,9 @@ obj-$(CONFIG_DA311) += da311.o · 26 unmodified lines | |||
| 27 | obj-$(CONFIG_DMARD06) += dmard06.o | 27 | obj-$(CONFIG_DMARD06) += dmard06.o |
| 28 | obj-$(CONFIG_DMARD09) += dmard09.o | 28 | obj-$(CONFIG_DMARD09) += dmard09.o |
| 29 | obj-$(CONFIG_DMARD10) += dmard10.o | 29 | obj-$(CONFIG_DMARD10) += dmard10.o |
| 30 | obj-$(CONFIG_FXLS8962AF) += fxls8962af-core.o | ||
| 31 | obj-$(CONFIG_FXLS8962AF_I2C) += fxls8962af-i2c.o | ||
| 32 | obj-$(CONFIG_FXLS8962AF_SPI) += fxls8962af-spi.o | ||
| 30 | obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o | 33 | obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o |
| 31 | obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o | 34 | obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o |
| 32 | obj-$(CONFIG_KXSD9) += kxsd9.o | 35 | obj-$(CONFIG_KXSD9) += kxsd9.o |
| @@ -50,6 +53,7 @@ obj-$(CONFIG_MXC4005) += mxc4005.o · 17 unmodified lines | |||
| 50 | obj-$(CONFIG_MXC6255) += mxc6255.o | 53 | obj-$(CONFIG_MXC6255) += mxc6255.o |
| 51 | 54 | ||
| 52 | obj-$(CONFIG_SCA3000) += sca3000.o | 55 | obj-$(CONFIG_SCA3000) += sca3000.o |
| 56 | obj-$(CONFIG_SCA3300) += sca3300.o | ||
| 53 | 57 | ||
| 54 | obj-$(CONFIG_STK8312) += stk8312.o | 58 | obj-$(CONFIG_STK8312) += stk8312.o |
| 55 | obj-$(CONFIG_STK8BA50) += stk8ba50.o | 59 | obj-$(CONFIG_STK8BA50) += stk8ba50.o |
| @@ -8,10 +8,7 @@ · 7 unmodified lines | |||
| 8 | #include <linux/device.h> | 8 | #include <linux/device.h> |
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/mutex.h> | ||
| 12 | #include <linux/slab.h> | ||
| 13 | #include <linux/spi/spi.h> | 11 | #include <linux/spi/spi.h> |
| 14 | #include <linux/sysfs.h> | ||
| 15 | 12 | ||
| 16 | #include <linux/iio/iio.h> | 13 | #include <linux/iio/iio.h> |
| 17 | #include <linux/iio/imu/adis.h> | 14 | #include <linux/iio/imu/adis.h> |
| @@ -7,11 +7,8 @@ · 6 unmodified lines | |||
| 7 | 7 | ||
| 8 | #include <linux/device.h> | 8 | #include <linux/device.h> |
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/list.h> | ||
| 11 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 12 | #include <linux/spi/spi.h> | 11 | #include <linux/spi/spi.h> |
| 13 | #include <linux/slab.h> | ||
| 14 | #include <linux/sysfs.h> | ||
| 15 | 12 | ||
| 16 | #include <linux/iio/iio.h> | 13 | #include <linux/iio/iio.h> |
| 17 | #include <linux/iio/imu/adis.h> | 14 | #include <linux/iio/imu/adis.h> |
| @@ -1223,14 +1223,14 @@ int adxl372_probe(struct device *dev, struct regmap *regmap, · 1222 unmodified lines | |||
| 1223 | st->dready_trig = devm_iio_trigger_alloc(dev, | 1223 | st->dready_trig = devm_iio_trigger_alloc(dev, |
| 1224 | "%s-dev%d", | 1224 | "%s-dev%d", |
| 1225 | indio_dev->name, | 1225 | indio_dev->name, |
| 1226 | indio_dev->id); | 1226 | iio_device_id(indio_dev)); |
| 1227 | if (st->dready_trig == NULL) | 1227 | if (st->dready_trig == NULL) |
| 1228 | return -ENOMEM; | 1228 | return -ENOMEM; |
| 1229 | 1229 | ||
| 1230 | st->peak_datardy_trig = devm_iio_trigger_alloc(dev, | 1230 | st->peak_datardy_trig = devm_iio_trigger_alloc(dev, |
| 1231 | "%s-dev%d-peak", | 1231 | "%s-dev%d-peak", |
| 1232 | indio_dev->name, | 1232 | indio_dev->name, |
| 1233 | indio_dev->id); | 1233 | iio_device_id(indio_dev)); |
| 1234 | if (!st->peak_datardy_trig) | 1234 | if (!st->peak_datardy_trig) |
| 1235 | return -ENOMEM; | 1235 | return -ENOMEM; |
| 1236 | 1236 | ||
| @@ -10,7 +10,6 @@ · 9 unmodified lines | |||
| 10 | * BMA023/BMA150/SMB380: 7-bit I2C slave address 0x38 | 10 | * BMA023/BMA150/SMB380: 7-bit I2C slave address 0x38 |
| 11 | * BMA180: 7-bit I2C slave address 0x40 or 0x41 | 11 | * BMA180: 7-bit I2C slave address 0x40 or 0x41 |
| 12 | * BMA250: 7-bit I2C slave address 0x18 or 0x19 | 12 | * BMA250: 7-bit I2C slave address 0x18 or 0x19 |
| 13 | * BMA254: 7-bit I2C slave address 0x18 or 0x19 | ||
| 14 | */ | 13 | */ |
| 15 | 14 | ||
| 16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| @@ -38,7 +37,6 @@ enum chip_ids { · 21 unmodified lines | |||
| 38 | BMA150, | 37 | BMA150, |
| 39 | BMA180, | 38 | BMA180, |
| 40 | BMA250, | 39 | BMA250, |
| 41 | BMA254, | ||
| 42 | }; | 40 | }; |
| 43 | 41 | ||
| 44 | struct bma180_data; | 42 | struct bma180_data; |
| @@ -55,11 +53,10 @@ struct bma180_part_info { · 10 unmodified lines | |||
| 55 | 53 | ||
| 56 | u8 int_reset_reg, int_reset_mask; | 54 | u8 int_reset_reg, int_reset_mask; |
| 57 | u8 sleep_reg, sleep_mask; | 55 | u8 sleep_reg, sleep_mask; |
| 58 | u8 bw_reg, bw_mask; | 56 | u8 bw_reg, bw_mask, bw_offset; |
| 59 | u8 scale_reg, scale_mask; | 57 | u8 scale_reg, scale_mask; |
| 60 | u8 power_reg, power_mask, lowpower_val; | 58 | u8 power_reg, power_mask, lowpower_val; |
| 61 | u8 int_enable_reg, int_enable_mask; | 59 | u8 int_enable_reg, int_enable_mask; |
| 62 | u8 int_map_reg, int_enable_dataready_int1_mask; | ||
| 63 | u8 softreset_reg, softreset_val; | 60 | u8 softreset_reg, softreset_val; |
| 64 | 61 | ||
| 65 | int (*chip_config)(struct bma180_data *data); | 62 | int (*chip_config)(struct bma180_data *data); |
| @@ -112,7 +109,6 @@ struct bma180_part_info { · 46 unmodified lines | |||
| 112 | #define BMA023_ID_REG_VAL 0x02 | 109 | #define BMA023_ID_REG_VAL 0x02 |
| 113 | #define BMA180_ID_REG_VAL 0x03 | 110 | #define BMA180_ID_REG_VAL 0x03 |
| 114 | #define BMA250_ID_REG_VAL 0x03 | 111 | #define BMA250_ID_REG_VAL 0x03 |
| 115 | #define BMA254_ID_REG_VAL 0xfa /* 250 decimal */ | ||
| 116 | 112 | ||
| 117 | /* Chip power modes */ | 113 | /* Chip power modes */ |
| 118 | #define BMA180_LOW_POWER 0x03 | 114 | #define BMA180_LOW_POWER 0x03 |
| @@ -127,29 +123,13 @@ struct bma180_part_info { · 8 unmodified lines | |||
| 127 | 123 | ||
| 128 | #define BMA250_RANGE_MASK GENMASK(3, 0) /* Range of accel values */ | 124 | #define BMA250_RANGE_MASK GENMASK(3, 0) /* Range of accel values */ |
| 129 | #define BMA250_BW_MASK GENMASK(4, 0) /* Accel bandwidth */ | 125 | #define BMA250_BW_MASK GENMASK(4, 0) /* Accel bandwidth */ |
| 126 | #define BMA250_BW_OFFSET 8 | ||
| 130 | #define BMA250_SUSPEND_MASK BIT(7) /* chip will sleep */ | 127 | #define BMA250_SUSPEND_MASK BIT(7) /* chip will sleep */ |
| 131 | #define BMA250_LOWPOWER_MASK BIT(6) | 128 | #define BMA250_LOWPOWER_MASK BIT(6) |
| 132 | #define BMA250_DATA_INTEN_MASK BIT(4) | 129 | #define BMA250_DATA_INTEN_MASK BIT(4) |
| 133 | #define BMA250_INT1_DATA_MASK BIT(0) | 130 | #define BMA250_INT1_DATA_MASK BIT(0) |
| 134 | #define BMA250_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ | 131 | #define BMA250_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ |
| 135 | 132 | ||
| 136 | #define BMA254_RANGE_REG 0x0f | ||
| 137 | #define BMA254_BW_REG 0x10 | ||
| 138 | #define BMA254_POWER_REG 0x11 | ||
| 139 | #define BMA254_RESET_REG 0x14 | ||
| 140 | #define BMA254_INT_ENABLE_REG 0x17 | ||
| 141 | #define BMA254_INT_MAP_REG 0x1a | ||
| 142 | #define BMA254_INT_RESET_REG 0x21 | ||
| 143 | |||
| 144 | #define BMA254_RANGE_MASK GENMASK(3, 0) /* Range of accel values */ | ||
| 145 | #define BMA254_BW_MASK GENMASK(4, 0) /* Accel bandwidth */ | ||
| 146 | #define BMA254_SUSPEND_MASK BIT(7) /* chip will sleep */ | ||
| 147 | #define BMA254_LOWPOWER_MASK BIT(6) | ||
| 148 | #define BMA254_DATA_INTEN_MASK BIT(4) | ||
| 149 | #define BMA254_INT2_DATA_MASK BIT(7) | ||
| 150 | #define BMA254_INT1_DATA_MASK BIT(0) | ||
| 151 | #define BMA254_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ | ||
| 152 | |||
| 153 | struct bma180_data { | 133 | struct bma180_data { |
| 154 | struct regulator *vdd_supply; | 134 | struct regulator *vdd_supply; |
| 155 | struct regulator *vddio_supply; | 135 | struct regulator *vddio_supply; |
| @@ -162,7 +142,11 @@ struct bma180_data { · 6 unmodified lines | |||
| 162 | int scale; | 142 | int scale; |
| 163 | int bw; | 143 | int bw; |
| 164 | bool pmode; | 144 | bool pmode; |
| 165 | u8 buff[16]; /* 3x 16-bit + 8-bit + padding + timestamp */ | 145 | /* Ensure timestamp is naturally aligned */ |
| 146 | struct { | ||
| 147 | s16 chan[4]; | ||
| 148 | s64 timestamp __aligned(8); | ||
| 149 | } scan; | ||
| 166 | }; | 150 | }; |
| 167 | 151 | ||
| 168 | enum bma180_chan { | 152 | enum bma180_chan { |
| @@ -178,8 +162,8 @@ static int bma023_scale_table[] = { 2452, 4903, 9709, }; · 9 unmodified lines | |||
| 178 | static int bma180_bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */ | 162 | static int bma180_bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */ |
| 179 | static int bma180_scale_table[] = { 1275, 1863, 2452, 3727, 4903, 9709, 19417 }; | 163 | static int bma180_scale_table[] = { 1275, 1863, 2452, 3727, 4903, 9709, 19417 }; |
| 180 | 164 | ||
| 181 | static int bma25x_bw_table[] = { 8, 16, 31, 63, 125, 250 }; /* Hz */ | 165 | static int bma250_bw_table[] = { 8, 16, 31, 63, 125, 250, 500, 1000 }; /* Hz */ |
| 182 | static int bma25x_scale_table[] = { 0, 0, 0, 38344, 0, 76590, 0, 0, 153180, 0, | 166 | static int bma250_scale_table[] = { 0, 0, 0, 38344, 0, 76590, 0, 0, 153180, 0, |
| 183 | 0, 0, 306458 }; | 167 | 0, 0, 306458 }; |
| 184 | 168 | ||
| 185 | static int bma180_get_data_reg(struct bma180_data *data, enum bma180_chan chan) | 169 | static int bma180_get_data_reg(struct bma180_data *data, enum bma180_chan chan) |
| @@ -283,7 +267,8 @@ static int bma180_set_bw(struct bma180_data *data, int val) · 97 unmodified lines | |||
| 283 | for (i = 0; i < data->part_info->num_bw; ++i) { | 267 | for (i = 0; i < data->part_info->num_bw; ++i) { |
| 284 | if (data->part_info->bw_table[i] == val) { | 268 | if (data->part_info->bw_table[i] == val) { |
| 285 | ret = bma180_set_bits(data, data->part_info->bw_reg, | 269 | ret = bma180_set_bits(data, data->part_info->bw_reg, |
| 286 | data->part_info->bw_mask, i); | 270 | data->part_info->bw_mask, |
| 271 | i + data->part_info->bw_offset); | ||
| 287 | if (ret) { | 272 | if (ret) { |
| 288 | dev_err(&data->client->dev, | 273 | dev_err(&data->client->dev, |
| 289 | "failed to set bandwidth\n"); | 274 | "failed to set bandwidth\n"); |
| @@ -425,7 +410,7 @@ err: · 135 unmodified lines | |||
| 425 | return ret; | 410 | return ret; |
| 426 | } | 411 | } |
| 427 | 412 | ||
| 428 | static int bma25x_chip_config(struct bma180_data *data) | 413 | static int bma250_chip_config(struct bma180_data *data) |
| 429 | { | 414 | { |
| 430 | int ret = bma180_chip_init(data); | 415 | int ret = bma180_chip_init(data); |
| 431 | 416 | ||
| @@ -444,8 +429,7 @@ static int bma25x_chip_config(struct bma180_data *data) · 12 unmodified lines | |||
| 444 | * This enables dataready interrupt on the INT1 pin | 429 | * This enables dataready interrupt on the INT1 pin |
| 445 | * FIXME: support using the INT2 pin | 430 | * FIXME: support using the INT2 pin |
| 446 | */ | 431 | */ |
| 447 | ret = bma180_set_bits(data, data->part_info->int_map_reg, | 432 | ret = bma180_set_bits(data, BMA250_INT_MAP_REG, BMA250_INT1_DATA_MASK, 1); |
| 448 | data->part_info->int_enable_dataready_int1_mask, 1); | ||
| 449 | if (ret) | 433 | if (ret) |
| 450 | goto err; | 434 | goto err; |
| 451 | 435 | ||
| @@ -482,7 +466,7 @@ err: · 30 unmodified lines | |||
| 482 | dev_err(&data->client->dev, "failed to disable the chip\n"); | 466 | dev_err(&data->client->dev, "failed to disable the chip\n"); |
| 483 | } | 467 | } |
| 484 | 468 | ||
| 485 | static void bma25x_chip_disable(struct bma180_data *data) | 469 | static void bma250_chip_disable(struct bma180_data *data) |
| 486 | { | 470 | { |
| 487 | if (bma180_set_new_data_intr_state(data, false)) | 471 | if (bma180_set_new_data_intr_state(data, false)) |
| 488 | goto err; | 472 | goto err; |
| @@ -768,14 +752,6 @@ static const struct iio_chan_spec bma250_channels[] = { · 279 unmodified lines | |||
| 768 | IIO_CHAN_SOFT_TIMESTAMP(4), | 752 | IIO_CHAN_SOFT_TIMESTAMP(4), |
| 769 | }; | 753 | }; |
| 770 | 754 | ||
| 771 | static const struct iio_chan_spec bma254_channels[] = { | ||
| 772 | BMA180_ACC_CHANNEL(X, 12), | ||
| 773 | BMA180_ACC_CHANNEL(Y, 12), | ||
| 774 | BMA180_ACC_CHANNEL(Z, 12), | ||
| 775 | BMA180_TEMP_CHANNEL, | ||
| 776 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
| 777 | }; | ||
| 778 | |||
| 779 | static const struct bma180_part_info bma180_part_info[] = { | 755 | static const struct bma180_part_info bma180_part_info[] = { |
| 780 | [BMA023] = { | 756 | [BMA023] = { |
| 781 | .chip_id = BMA023_ID_REG_VAL, | 757 | .chip_id = BMA023_ID_REG_VAL, |
| @@ -865,10 +841,10 @@ static const struct bma180_part_info bma180_part_info[] = { · 83 unmodified lines | |||
| 865 | .chip_id = BMA250_ID_REG_VAL, | 841 | .chip_id = BMA250_ID_REG_VAL, |
| 866 | .channels = bma250_channels, | 842 | .channels = bma250_channels, |
| 867 | .num_channels = ARRAY_SIZE(bma250_channels), | 843 | .num_channels = ARRAY_SIZE(bma250_channels), |
| 868 | .scale_table = bma25x_scale_table, | 844 | .scale_table = bma250_scale_table, |
| 869 | .num_scales = ARRAY_SIZE(bma25x_scale_table), | 845 | .num_scales = ARRAY_SIZE(bma250_scale_table), |
| 870 | .bw_table = bma25x_bw_table, | 846 | .bw_table = bma250_bw_table, |
| 871 | .num_bw = ARRAY_SIZE(bma25x_bw_table), | 847 | .num_bw = ARRAY_SIZE(bma250_bw_table), |
| 872 | .temp_offset = 48, /* 0 LSB @ 24 degree C */ | 848 | .temp_offset = 48, /* 0 LSB @ 24 degree C */ |
| 873 | .int_reset_reg = BMA250_INT_RESET_REG, | 849 | .int_reset_reg = BMA250_INT_RESET_REG, |
| 874 | .int_reset_mask = BMA250_INT_RESET_MASK, | 850 | .int_reset_mask = BMA250_INT_RESET_MASK, |
| @@ -876,6 +852,7 @@ static const struct bma180_part_info bma180_part_info[] = { · 1 unmodified line | |||
| 876 | .sleep_mask = BMA250_SUSPEND_MASK, | 852 | .sleep_mask = BMA250_SUSPEND_MASK, |
| 877 | .bw_reg = BMA250_BW_REG, | 853 | .bw_reg = BMA250_BW_REG, |
| 878 | .bw_mask = BMA250_BW_MASK, | 854 | .bw_mask = BMA250_BW_MASK, |
| 855 | .bw_offset = BMA250_BW_OFFSET, | ||
| 879 | .scale_reg = BMA250_RANGE_REG, | 856 | .scale_reg = BMA250_RANGE_REG, |
| 880 | .scale_mask = BMA250_RANGE_MASK, | 857 | .scale_mask = BMA250_RANGE_MASK, |
| 881 | .power_reg = BMA250_POWER_REG, | 858 | .power_reg = BMA250_POWER_REG, |
| @@ -883,41 +860,10 @@ static const struct bma180_part_info bma180_part_info[] = { · 1 unmodified line | |||
| 883 | .lowpower_val = 1, | 860 | .lowpower_val = 1, |
| 884 | .int_enable_reg = BMA250_INT_ENABLE_REG, | 861 | .int_enable_reg = BMA250_INT_ENABLE_REG, |
| 885 | .int_enable_mask = BMA250_DATA_INTEN_MASK, | 862 | .int_enable_mask = BMA250_DATA_INTEN_MASK, |
| 886 | .int_map_reg = BMA250_INT_MAP_REG, | ||
| 887 | .int_enable_dataready_int1_mask = BMA250_INT1_DATA_MASK, | ||
| 888 | .softreset_reg = BMA250_RESET_REG, | 863 | .softreset_reg = BMA250_RESET_REG, |
| 889 | .softreset_val = BMA180_RESET_VAL, | 864 | .softreset_val = BMA180_RESET_VAL, |
| 890 | .chip_config = bma25x_chip_config, | 865 | .chip_config = bma250_chip_config, |
| 891 | .chip_disable = bma25x_chip_disable, | 866 | .chip_disable = bma250_chip_disable, |
| 892 | }, | ||
| 893 | [BMA254] = { | ||
| 894 | .chip_id = BMA254_ID_REG_VAL, | ||
| 895 | .channels = bma254_channels, | ||
| 896 | .num_channels = ARRAY_SIZE(bma254_channels), | ||
| 897 | .scale_table = bma25x_scale_table, | ||
| 898 | .num_scales = ARRAY_SIZE(bma25x_scale_table), | ||
| 899 | .bw_table = bma25x_bw_table, | ||
| 900 | .num_bw = ARRAY_SIZE(bma25x_bw_table), | ||
| 901 | .temp_offset = 46, /* 0 LSB @ 23 degree C */ | ||
| 902 | .int_reset_reg = BMA254_INT_RESET_REG, | ||
| 903 | .int_reset_mask = BMA254_INT_RESET_MASK, | ||
| 904 | .sleep_reg = BMA254_POWER_REG, | ||
| 905 | .sleep_mask = BMA254_SUSPEND_MASK, | ||
| 906 | .bw_reg = BMA254_BW_REG, | ||
| 907 | .bw_mask = BMA254_BW_MASK, | ||
| 908 | .scale_reg = BMA254_RANGE_REG, | ||
| 909 | .scale_mask = BMA254_RANGE_MASK, | ||
| 910 | .power_reg = BMA254_POWER_REG, | ||
| 911 | .power_mask = BMA254_LOWPOWER_MASK, | ||
| 912 | .lowpower_val = 1, | ||
| 913 | .int_enable_reg = BMA254_INT_ENABLE_REG, | ||
| 914 | .int_enable_mask = BMA254_DATA_INTEN_MASK, | ||
| 915 | .int_map_reg = BMA254_INT_MAP_REG, | ||
| 916 | .int_enable_dataready_int1_mask = BMA254_INT1_DATA_MASK, | ||
| 917 | .softreset_reg = BMA254_RESET_REG, | ||
| 918 | .softreset_val = BMA180_RESET_VAL, | ||
| 919 | .chip_config = bma25x_chip_config, | ||
| 920 | .chip_disable = bma25x_chip_disable, | ||
| 921 | }, | 867 | }, |
| 922 | }; | 868 | }; |
| 923 | 869 | ||
| @@ -938,12 +884,12 @@ static irqreturn_t bma180_trigger_handler(int irq, void *p) · 14 unmodified lines | |||
| 938 | mutex_unlock(&data->mutex); | 884 | mutex_unlock(&data->mutex); |
| 939 | goto err; | 885 | goto err; |
| 940 | } | 886 | } |
| 941 | ((s16 *)data->buff)[i++] = ret; | 887 | data->scan.chan[i++] = ret; |
| 942 | } | 888 | } |
| 943 | 889 | ||
| 944 | mutex_unlock(&data->mutex); | 890 | mutex_unlock(&data->mutex); |
| 945 | 891 | ||
| 946 | iio_push_to_buffers_with_timestamp(indio_dev, data->buff, time_ns); | 892 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, time_ns); |
| 947 | err: | 893 | err: |
| 948 | iio_trigger_notify_done(indio_dev->trig); | 894 | iio_trigger_notify_done(indio_dev->trig); |
| 949 | 895 | ||
| @@ -997,8 +943,7 @@ static int bma180_probe(struct i2c_client *client, · 47 unmodified lines | |||
| 997 | chip = id->driver_data; | 943 | chip = id->driver_data; |
| 998 | data->part_info = &bma180_part_info[chip]; | 944 | data->part_info = &bma180_part_info[chip]; |
| 999 | 945 | ||
| 1000 | ret = iio_read_mount_matrix(dev, "mount-matrix", | 946 | ret = iio_read_mount_matrix(dev, &data->orientation); |
| 1001 | &data->orientation); | ||
| 1002 | if (ret) | 947 | if (ret) |
| 1003 | return ret; | 948 | return ret; |
| 1004 | 949 | ||
| @@ -1045,7 +990,7 @@ static int bma180_probe(struct i2c_client *client, · 40 unmodified lines | |||
| 1045 | 990 | ||
| 1046 | if (client->irq > 0) { | 991 | if (client->irq > 0) { |
| 1047 | data->trig = iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, | 992 | data->trig = iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, |
| 1048 | indio_dev->id); | 993 | iio_device_id(indio_dev)); |
| 1049 | if (!data->trig) { | 994 | if (!data->trig) { |
| 1050 | ret = -ENOMEM; | 995 | ret = -ENOMEM; |
| 1051 | goto err_chip_disable; | 996 | goto err_chip_disable; |
| @@ -1158,7 +1103,6 @@ static const struct i2c_device_id bma180_ids[] = { · 106 unmodified lines | |||
| 1158 | { "bma150", BMA150 }, | 1103 | { "bma150", BMA150 }, |
| 1159 | { "bma180", BMA180 }, | 1104 | { "bma180", BMA180 }, |
| 1160 | { "bma250", BMA250 }, | 1105 | { "bma250", BMA250 }, |
| 1161 | { "bma254", BMA254 }, | ||
| 1162 | { "smb380", BMA150 }, | 1106 | { "smb380", BMA150 }, |
| 1163 | { } | 1107 | { } |
| 1164 | }; | 1108 | }; |
| @@ -1182,10 +1126,6 @@ static const struct of_device_id bma180_of_match[] = { · 17 unmodified lines | |||
| 1182 | .compatible = "bosch,bma250", | 1126 | .compatible = "bosch,bma250", |
| 1183 | .data = (void *)BMA250 | 1127 | .data = (void *)BMA250 |
| 1184 | }, | 1128 | }, |
| 1185 | { | ||
| 1186 | .compatible = "bosch,bma254", | ||
| 1187 | .data = (void *)BMA254 | ||
| 1188 | }, | ||
| 1189 | { | 1129 | { |
| 1190 | .compatible = "bosch,smb380", | 1130 | .compatible = "bosch,smb380", |
| 1191 | .data = (void *)BMA150 | 1131 | .data = (void *)BMA150 |
| @@ -1209,5 +1149,5 @@ module_i2c_driver(bma180_driver); · 17 unmodified lines | |||
| 1209 | 1149 | ||
| 1210 | MODULE_AUTHOR("Kravchenko Oleksandr <x0199363@ti.com>"); | 1150 | MODULE_AUTHOR("Kravchenko Oleksandr <x0199363@ti.com>"); |
| 1211 | MODULE_AUTHOR("Texas Instruments, Inc."); | 1151 | MODULE_AUTHOR("Texas Instruments, Inc."); |
| 1212 | MODULE_DESCRIPTION("Bosch BMA023/BMA1x0/BMA25x triaxial acceleration sensor"); | 1152 | MODULE_DESCRIPTION("Bosch BMA023/BMA1x0/BMA250 triaxial acceleration sensor"); |
| 1213 | MODULE_LICENSE("GPL"); | 1153 | MODULE_LICENSE("GPL"); |
| @@ -63,7 +63,11 @@ static const int bma220_scale_table[][2] = { · 62 unmodified lines | |||
| 63 | struct bma220_data { | 63 | struct bma220_data { |
| 64 | struct spi_device *spi_device; | 64 | struct spi_device *spi_device; |
| 65 | struct mutex lock; | 65 | struct mutex lock; |
| 66 | s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 8x8 timestamp */ | 66 | struct { |
| 67 | s8 chans[3]; | ||
| 68 | /* Ensure timestamp is naturally aligned. */ | ||
| 69 | s64 timestamp __aligned(8); | ||
| 70 | } scan; | ||
| 67 | u8 tx_buf[2] ____cacheline_aligned; | 71 | u8 tx_buf[2] ____cacheline_aligned; |
| 68 | }; | 72 | }; |
| 69 | 73 | ||
| @@ -94,12 +98,12 @@ static irqreturn_t bma220_trigger_handler(int irq, void *p) · 24 unmodified lines | |||
| 94 | 98 | ||
| 95 | mutex_lock(&data->lock); | 99 | mutex_lock(&data->lock); |
| 96 | data->tx_buf[0] = BMA220_REG_ACCEL_X | BMA220_READ_MASK; | 100 | data->tx_buf[0] = BMA220_REG_ACCEL_X | BMA220_READ_MASK; |
| 97 | ret = spi_write_then_read(spi, data->tx_buf, 1, data->buffer, | 101 | ret = spi_write_then_read(spi, data->tx_buf, 1, &data->scan.chans, |
| 98 | ARRAY_SIZE(bma220_channels) - 1); | 102 | ARRAY_SIZE(bma220_channels) - 1); |
| 99 | if (ret < 0) | 103 | if (ret < 0) |
| 100 | goto err; | 104 | goto err; |
| 101 | 105 | ||
| 102 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 106 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, |
| 103 | pf->timestamp); | 107 | pf->timestamp); |
| 104 | err: | 108 | err: |
| 105 | mutex_unlock(&data->lock); | 109 | mutex_unlock(&data->lock); |
| @@ -811,7 +811,7 @@ int bma400_probe(struct device *dev, struct regmap *regmap, const char *name) · 810 unmodified lines | |||
| 811 | if (ret) | 811 | if (ret) |
| 812 | return ret; | 812 | return ret; |
| 813 | 813 | ||
| 814 | ret = iio_read_mount_matrix(dev, "mount-matrix", &data->orientation); | 814 | ret = iio_read_mount_matrix(dev, &data->orientation); |
| 815 | if (ret) | 815 | if (ret) |
| 816 | return ret; | 816 | return ret; |
| 817 | 817 | ||
| @@ -1,14 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | /* | 2 | /* |
| 3 | * 3-axis accelerometer driver supporting following Bosch-Sensortec chips: | 3 | * 3-axis accelerometer driver supporting many Bosch-Sensortec chips |
| 4 | * - BMC150 | ||
| 5 | * - BMI055 | ||
| 6 | * - BMA255 | ||
| 7 | * - BMA250E | ||
| 8 | * - BMA222 | ||
| 9 | * - BMA222E | ||
| 10 | * - BMA280 | ||
| 11 | * | ||
| 12 | * Copyright (c) 2014, Intel Corporation. | 4 | * Copyright (c) 2014, Intel Corporation. |
| 13 | */ | 5 | */ |
| 14 | 6 | ||
| @@ -157,59 +149,6 @@ struct bmc150_accel_chip_info { · 142 unmodified lines | |||
| 157 | const struct bmc150_scale_info scale_table[4]; | 149 | const struct bmc150_scale_info scale_table[4]; |
| 158 | }; | 150 | }; |
| 159 | 151 | ||
| 160 | struct bmc150_accel_interrupt { | ||
| 161 | const struct bmc150_accel_interrupt_info *info; | ||
| 162 | atomic_t users; | ||
| 163 | }; | ||
| 164 | |||
| 165 | struct bmc150_accel_trigger { | ||
| 166 | struct bmc150_accel_data *data; | ||
| 167 | struct iio_trigger *indio_trig; | ||
| 168 | int (*setup)(struct bmc150_accel_trigger *t, bool state); | ||
| 169 | int intr; | ||
| 170 | bool enabled; | ||
| 171 | }; | ||
| 172 | |||
| 173 | enum bmc150_accel_interrupt_id { | ||
| 174 | BMC150_ACCEL_INT_DATA_READY, | ||
| 175 | BMC150_ACCEL_INT_ANY_MOTION, | ||
| 176 | BMC150_ACCEL_INT_WATERMARK, | ||
| 177 | BMC150_ACCEL_INTERRUPTS, | ||
| 178 | }; | ||
| 179 | |||
| 180 | enum bmc150_accel_trigger_id { | ||
| 181 | BMC150_ACCEL_TRIGGER_DATA_READY, | ||
| 182 | BMC150_ACCEL_TRIGGER_ANY_MOTION, | ||
| 183 | BMC150_ACCEL_TRIGGERS, | ||
| 184 | }; | ||
| 185 | |||
| 186 | struct bmc150_accel_data { | ||
| 187 | struct regmap *regmap; | ||
| 188 | struct regulator_bulk_data regulators[2]; | ||
| 189 | struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS]; | ||
| 190 | struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS]; | ||
| 191 | struct mutex mutex; | ||
| 192 | u8 fifo_mode, watermark; | ||
| 193 | s16 buffer[8]; | ||
| 194 | /* | ||
| 195 | * Ensure there is sufficient space and correct alignment for | ||
| 196 | * the timestamp if enabled | ||
| 197 | */ | ||
| 198 | struct { | ||
| 199 | __le16 channels[3]; | ||
| 200 | s64 ts __aligned(8); | ||
| 201 | } scan; | ||
| 202 | u8 bw_bits; | ||
| 203 | u32 slope_dur; | ||
| 204 | u32 slope_thres; | ||
| 205 | u32 range; | ||
| 206 | int ev_enable_state; | ||
| 207 | int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */ | ||
| 208 | const struct bmc150_accel_chip_info *chip_info; | ||
| 209 | struct i2c_client *second_device; | ||
| 210 | struct iio_mount_matrix orientation; | ||
| 211 | }; | ||
| 212 | |||
| 213 | static const struct { | 152 | static const struct { |
| 214 | int val; | 153 | int val; |
| 215 | int val2; | 154 | int val2; |
| @@ -389,7 +328,7 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on) · 173 unmodified lines | |||
| 389 | int ret; | 328 | int ret; |
| 390 | 329 | ||
| 391 | if (on) { | 330 | if (on) { |
| 392 | ret = pm_runtime_get_sync(dev); | 331 | ret = pm_runtime_resume_and_get(dev); |
| 393 | } else { | 332 | } else { |
| 394 | pm_runtime_mark_last_busy(dev); | 333 | pm_runtime_mark_last_busy(dev); |
| 395 | ret = pm_runtime_put_autosuspend(dev); | 334 | ret = pm_runtime_put_autosuspend(dev); |
| @@ -398,9 +337,6 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on) · 2 unmodified lines | |||
| 398 | if (ret < 0) { | 337 | if (ret < 0) { |
| 399 | dev_err(dev, | 338 | dev_err(dev, |
| 400 | "Failed: %s for %d\n", __func__, on); | 339 | "Failed: %s for %d\n", __func__, on); |
| 401 | if (on) | ||
| 402 | pm_runtime_put_noidle(dev); | ||
| 403 | |||
| 404 | return ret; | 340 | return ret; |
| 405 | } | 341 | } |
| 406 | 342 | ||
| @@ -439,8 +375,8 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on) · 32 unmodified lines | |||
| 439 | * Onda V80 plus | 375 | * Onda V80 plus |
| 440 | * Predia Basic Tablet | 376 | * Predia Basic Tablet |
| 441 | */ | 377 | */ |
| 442 | static bool bmc150_apply_acpi_orientation(struct device *dev, | 378 | static bool bmc150_apply_bosc0200_acpi_orientation(struct device *dev, |
| 443 | struct iio_mount_matrix *orientation) | 379 | struct iio_mount_matrix *orientation) |
| 444 | { | 380 | { |
| 445 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 381 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 446 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | 382 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
| @@ -450,9 +386,6 @@ static bool bmc150_apply_acpi_orientation(struct device *dev, · 3 unmodified lines | |||
| 450 | acpi_status status; | 386 | acpi_status status; |
| 451 | int i, j, val[3]; | 387 | int i, j, val[3]; |
| 452 | 388 | ||
| 453 | if (!adev || !acpi_dev_hid_uid_match(adev, "BOSC0200", NULL)) | ||
| 454 | return false; | ||
| 455 | |||
| 456 | if (strcmp(dev_name(dev), "i2c-BOSC0200:base") == 0) { | 389 | if (strcmp(dev_name(dev), "i2c-BOSC0200:base") == 0) { |
| 457 | alt_name = "ROMK"; | 390 | alt_name = "ROMK"; |
| 458 | label = "accel-base"; | 391 | label = "accel-base"; |
| @@ -508,6 +441,33 @@ unknown_format: · 49 unmodified lines | |||
| 508 | kfree(buffer.pointer); | 441 | kfree(buffer.pointer); |
| 509 | return false; | 442 | return false; |
| 510 | } | 443 | } |
| 444 | |||
| 445 | static bool bmc150_apply_dual250e_acpi_orientation(struct device *dev, | ||
| 446 | struct iio_mount_matrix *orientation) | ||
| 447 | { | ||
| 448 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
| 449 | |||
| 450 | if (strcmp(dev_name(dev), "i2c-DUAL250E:base") == 0) | ||
| 451 | indio_dev->label = "accel-base"; | ||
| 452 | else | ||
| 453 | indio_dev->label = "accel-display"; | ||
| 454 | |||
| 455 | return false; /* DUAL250E fwnodes have no mount matrix info */ | ||
| 456 | } | ||
| 457 | |||
| 458 | static bool bmc150_apply_acpi_orientation(struct device *dev, | ||
| 459 | struct iio_mount_matrix *orientation) | ||
| 460 | { | ||
| 461 | struct acpi_device *adev = ACPI_COMPANION(dev); | ||
| 462 | |||
| 463 | if (adev && acpi_dev_hid_uid_match(adev, "BOSC0200", NULL)) | ||
| 464 | return bmc150_apply_bosc0200_acpi_orientation(dev, orientation); | ||
| 465 | |||
| 466 | if (adev && acpi_dev_hid_uid_match(adev, "DUAL250E", NULL)) | ||
| 467 | return bmc150_apply_dual250e_acpi_orientation(dev, orientation); | ||
| 468 | |||
| 469 | return false; | ||
| 470 | } | ||
| 511 | #else | 471 | #else |
| 512 | static bool bmc150_apply_acpi_orientation(struct device *dev, | 472 | static bool bmc150_apply_acpi_orientation(struct device *dev, |
| 513 | struct iio_mount_matrix *orientation) | 473 | struct iio_mount_matrix *orientation) |
| @@ -1128,80 +1088,63 @@ static const struct iio_chan_spec bmc150_accel_channels[] = · 614 unmodified lines | |||
| 1128 | static const struct iio_chan_spec bma280_accel_channels[] = | 1088 | static const struct iio_chan_spec bma280_accel_channels[] = |
| 1129 | BMC150_ACCEL_CHANNELS(14); | 1089 | BMC150_ACCEL_CHANNELS(14); |
| 1130 | 1090 | ||
| 1091 | /* | ||
| 1092 | * The range for the Bosch sensors is typically +-2g/4g/8g/16g, distributed | ||
| 1093 | * over the amount of bits (see above). The scale table can be calculated using | ||
| 1094 | * (range / 2^bits) * g = (range / 2^bits) * 9.80665 m/s^2 | ||
| 1095 | * e.g. for +-2g and 12 bits: (4 / 2^12) * 9.80665 m/s^2 = 0.0095768... m/s^2 | ||
| 1096 | * Multiply 10^6 and round to get the values listed below. | ||
| 1097 | */ | ||
| 1131 | static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = { | 1098 | static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = { |
| 1132 | [bmc150] = { | 1099 | { |
| 1133 | .name = "BMC150A", | ||
| 1134 | .chip_id = 0xFA, | ||
| 1135 | .channels = bmc150_accel_channels, | ||
| 1136 | .num_channels = ARRAY_SIZE(bmc150_accel_channels), | ||
| 1137 | .scale_table = { {9610, BMC150_ACCEL_DEF_RANGE_2G}, | ||
| 1138 | {19122, BMC150_ACCEL_DEF_RANGE_4G}, | ||
| 1139 | {38344, BMC150_ACCEL_DEF_RANGE_8G}, | ||
| 1140 | {76590, BMC150_ACCEL_DEF_RANGE_16G} }, | ||
| 1141 | }, | ||
| 1142 | [bmi055] = { | ||
| 1143 | .name = "BMI055A", | ||
| 1144 | .chip_id = 0xFA, | ||
| 1145 | .channels = bmc150_accel_channels, | ||
| 1146 | .num_channels = ARRAY_SIZE(bmc150_accel_channels), | ||
| 1147 | .scale_table = { {9610, BMC150_ACCEL_DEF_RANGE_2G}, | ||
| 1148 | {19122, BMC150_ACCEL_DEF_RANGE_4G}, | ||
| 1149 | {38344, BMC150_ACCEL_DEF_RANGE_8G}, | ||
| 1150 | {76590, BMC150_ACCEL_DEF_RANGE_16G} }, | ||
| 1151 | }, | ||
| 1152 | [bma255] = { | ||
| 1153 | .name = "BMA0255", | ||
| 1154 | .chip_id = 0xFA, | ||
| 1155 | .channels = bmc150_accel_channels, | ||
| 1156 | .num_channels = ARRAY_SIZE(bmc150_accel_channels), | ||
| 1157 | .scale_table = { {9610, BMC150_ACCEL_DEF_RANGE_2G}, | ||
| 1158 | {19122, BMC150_ACCEL_DEF_RANGE_4G}, | ||
| 1159 | {38344, BMC150_ACCEL_DEF_RANGE_8G}, | ||
| 1160 | {76590, BMC150_ACCEL_DEF_RANGE_16G} }, | ||
| 1161 | }, | ||
| 1162 | [bma250e] = { | ||
| 1163 | .name = "BMA250E", | ||
| 1164 | .chip_id = 0xF9, | ||
| 1165 | .channels = bma250e_accel_channels, | ||
| 1166 | .num_channels = ARRAY_SIZE(bma250e_accel_channels), | ||
| 1167 | .scale_table = { {38344, BMC150_ACCEL_DEF_RANGE_2G}, | ||
| 1168 | {76590, BMC150_ACCEL_DEF_RANGE_4G}, | ||
| 1169 | {153277, BMC150_ACCEL_DEF_RANGE_8G}, | ||
| 1170 | {306457, BMC150_ACCEL_DEF_RANGE_16G} }, | ||
| 1171 | }, | ||
| 1172 | [bma222] = { | ||
| 1173 | .name = "BMA222", | 1100 | .name = "BMA222", |
| 1174 | .chip_id = 0x03, | 1101 | .chip_id = 0x03, |
| 1175 | .channels = bma222e_accel_channels, | 1102 | .channels = bma222e_accel_channels, |
| 1176 | .num_channels = ARRAY_SIZE(bma222e_accel_channels), | 1103 | .num_channels = ARRAY_SIZE(bma222e_accel_channels), |
| 1177 | /* | 1104 | .scale_table = { {153229, BMC150_ACCEL_DEF_RANGE_2G}, |
| 1178 | * The datasheet page 17 says: | 1105 | {306458, BMC150_ACCEL_DEF_RANGE_4G}, |
| 1179 | * 15.6, 31.3, 62.5 and 125 mg per LSB. | 1106 | {612916, BMC150_ACCEL_DEF_RANGE_8G}, |
| 1180 | */ | 1107 | {1225831, BMC150_ACCEL_DEF_RANGE_16G} }, |
| 1181 | .scale_table = { {156000, BMC150_ACCEL_DEF_RANGE_2G}, | ||
| 1182 | {313000, BMC150_ACCEL_DEF_RANGE_4G}, | ||
| 1183 | {625000, BMC150_ACCEL_DEF_RANGE_8G}, | ||
| 1184 | {1250000, BMC150_ACCEL_DEF_RANGE_16G} }, | ||
| 1185 | }, | 1108 | }, |
| 1186 | [bma222e] = { | 1109 | { |
| 1187 | .name = "BMA222E", | 1110 | .name = "BMA222E", |
| 1188 | .chip_id = 0xF8, | 1111 | .chip_id = 0xF8, |
| 1189 | .channels = bma222e_accel_channels, | 1112 | .channels = bma222e_accel_channels, |
| 1190 | .num_channels = ARRAY_SIZE(bma222e_accel_channels), | 1113 | .num_channels = ARRAY_SIZE(bma222e_accel_channels), |
| 1191 | .scale_table = { {153277, BMC150_ACCEL_DEF_RANGE_2G}, | 1114 | .scale_table = { {153229, BMC150_ACCEL_DEF_RANGE_2G}, |
| 1192 | {306457, BMC150_ACCEL_DEF_RANGE_4G}, | 1115 | {306458, BMC150_ACCEL_DEF_RANGE_4G}, |
| 1193 | {612915, BMC150_ACCEL_DEF_RANGE_8G}, | 1116 | {612916, BMC150_ACCEL_DEF_RANGE_8G}, |
| 1194 | {1225831, BMC150_ACCEL_DEF_RANGE_16G} }, | 1117 | {1225831, BMC150_ACCEL_DEF_RANGE_16G} }, |
| 1195 | }, | 1118 | }, |
| 1196 | [bma280] = { | 1119 | { |
| 1197 | .name = "BMA0280", | 1120 | .name = "BMA250E", |
| 1121 | .chip_id = 0xF9, | ||
| 1122 | .channels = bma250e_accel_channels, | ||
| 1123 | .num_channels = ARRAY_SIZE(bma250e_accel_channels), | ||
| 1124 | .scale_table = { {38307, BMC150_ACCEL_DEF_RANGE_2G}, | ||
| 1125 | {76614, BMC150_ACCEL_DEF_RANGE_4G}, | ||
| 1126 | {153229, BMC150_ACCEL_DEF_RANGE_8G}, | ||
| 1127 | {306458, BMC150_ACCEL_DEF_RANGE_16G} }, | ||
| 1128 | }, | ||
| 1129 | { | ||
| 1130 | .name = "BMA253/BMA254/BMA255/BMC150/BMI055", | ||
| 1131 | .chip_id = 0xFA, | ||
| 1132 | .channels = bmc150_accel_channels, | ||
| 1133 | .num_channels = ARRAY_SIZE(bmc150_accel_channels), | ||
| 1134 | .scale_table = { {9577, BMC150_ACCEL_DEF_RANGE_2G}, | ||
| 1135 | {19154, BMC150_ACCEL_DEF_RANGE_4G}, | ||
| 1136 | {38307, BMC150_ACCEL_DEF_RANGE_8G}, | ||
| 1137 | {76614, BMC150_ACCEL_DEF_RANGE_16G} }, | ||
| 1138 | }, | ||
| 1139 | { | ||
| 1140 | .name = "BMA280", | ||
| 1198 | .chip_id = 0xFB, | 1141 | .chip_id = 0xFB, |
| 1199 | .channels = bma280_accel_channels, | 1142 | .channels = bma280_accel_channels, |
| 1200 | .num_channels = ARRAY_SIZE(bma280_accel_channels), | 1143 | .num_channels = ARRAY_SIZE(bma280_accel_channels), |
| 1201 | .scale_table = { {2392, BMC150_ACCEL_DEF_RANGE_2G}, | 1144 | .scale_table = { {2394, BMC150_ACCEL_DEF_RANGE_2G}, |
| 1202 | {4785, BMC150_ACCEL_DEF_RANGE_4G}, | 1145 | {4788, BMC150_ACCEL_DEF_RANGE_4G}, |
| 1203 | {9581, BMC150_ACCEL_DEF_RANGE_8G}, | 1146 | {9577, BMC150_ACCEL_DEF_RANGE_8G}, |
| 1204 | {19152, BMC150_ACCEL_DEF_RANGE_16G} }, | 1147 | {19154, BMC150_ACCEL_DEF_RANGE_16G} }, |
| 1205 | }, | 1148 | }, |
| 1206 | }; | 1149 | }; |
| 1207 | 1150 | ||
| @@ -1470,9 +1413,9 @@ static int bmc150_accel_triggers_setup(struct iio_dev *indio_dev, · 262 unmodified lines | |||
| 1470 | struct bmc150_accel_trigger *t = &data->triggers[i]; | 1413 | struct bmc150_accel_trigger *t = &data->triggers[i]; |
| 1471 | 1414 | ||
| 1472 | t->indio_trig = devm_iio_trigger_alloc(dev, | 1415 | t->indio_trig = devm_iio_trigger_alloc(dev, |
| 1473 | bmc150_accel_triggers[i].name, | 1416 | bmc150_accel_triggers[i].name, |
| 1474 | indio_dev->name, | 1417 | indio_dev->name, |
| 1475 | indio_dev->id); | 1418 | iio_device_id(indio_dev)); |
| 1476 | if (!t->indio_trig) { | 1419 | if (!t->indio_trig) { |
| 1477 | ret = -ENOMEM; | 1420 | ret = -ENOMEM; |
| 1478 | break; | 1421 | break; |
| @@ -1688,8 +1631,7 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, · 209 unmodified lines | |||
| 1688 | data->regmap = regmap; | 1631 | data->regmap = regmap; |
| 1689 | 1632 | ||
| 1690 | if (!bmc150_apply_acpi_orientation(dev, &data->orientation)) { | 1633 | if (!bmc150_apply_acpi_orientation(dev, &data->orientation)) { |
| 1691 | ret = iio_read_mount_matrix(dev, "mount-matrix", | 1634 | ret = iio_read_mount_matrix(dev, &data->orientation); |
| 1692 | &data->orientation); | ||
| 1693 | if (ret) | 1635 | if (ret) |
| 1694 | return ret; | 1636 | return ret; |
| 1695 | } | 1637 | } |
| @@ -1807,26 +1749,6 @@ err_disable_regulators: · 111 unmodified lines | |||
| 1807 | } | 1749 | } |
| 1808 | EXPORT_SYMBOL_GPL(bmc150_accel_core_probe); | 1750 | EXPORT_SYMBOL_GPL(bmc150_accel_core_probe); |
| 1809 | 1751 | ||
| 1810 | struct i2c_client *bmc150_get_second_device(struct i2c_client *client) | ||
| 1811 | { | ||
| 1812 | struct bmc150_accel_data *data = i2c_get_clientdata(client); | ||
| 1813 | |||
| 1814 | if (!data) | ||
| 1815 | return NULL; | ||
| 1816 | |||
| 1817 | return data->second_device; | ||
| 1818 | } | ||
| 1819 | EXPORT_SYMBOL_GPL(bmc150_get_second_device); | ||
| 1820 | |||
| 1821 | void bmc150_set_second_device(struct i2c_client *client) | ||
| 1822 | { | ||
| 1823 | struct bmc150_accel_data *data = i2c_get_clientdata(client); | ||
| 1824 | |||
| 1825 | if (data) | ||
| 1826 | data->second_device = client; | ||
| 1827 | } | ||
| 1828 | EXPORT_SYMBOL_GPL(bmc150_set_second_device); | ||
| 1829 | |||
| 1830 | int bmc150_accel_core_remove(struct device *dev) | 1752 | int bmc150_accel_core_remove(struct device *dev) |
| 1831 | { | 1753 | { |
| 1832 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | 1754 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
| @@ -1836,7 +1758,6 @@ int bmc150_accel_core_remove(struct device *dev) · 3 unmodified lines | |||
| 1836 | 1758 | ||
| 1837 | pm_runtime_disable(dev); | 1759 | pm_runtime_disable(dev); |
| 1838 | pm_runtime_set_suspended(dev); | 1760 | pm_runtime_set_suspended(dev); |
| 1839 | pm_runtime_put_noidle(dev); | ||
| 1840 | 1761 | ||
| 1841 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); | 1762 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); |
| 1842 | 1763 | ||
| @@ -1876,6 +1797,9 @@ static int bmc150_accel_resume(struct device *dev) · 33 unmodified lines | |||
| 1876 | bmc150_accel_fifo_set_mode(data); | 1797 | bmc150_accel_fifo_set_mode(data); |
| 1877 | mutex_unlock(&data->mutex); | 1798 | mutex_unlock(&data->mutex); |
| 1878 | 1799 | ||
| 1800 | if (data->resume_callback) | ||
| 1801 | data->resume_callback(dev); | ||
| 1802 | |||
| 1879 | return 0; | 1803 | return 0; |
| 1880 | } | 1804 | } |
| 1881 | #endif | 1805 | #endif |
| @@ -1,14 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | /* | 2 | /* |
| 3 | * 3-axis accelerometer driver supporting following I2C Bosch-Sensortec chips: | 3 | * 3-axis accelerometer driver supporting many I2C Bosch-Sensortec chips |
| 4 | * - BMC150 | ||
| 5 | * - BMI055 | ||
| 6 | * - BMA255 | ||
| 7 | * - BMA250E | ||
| 8 | * - BMA222 | ||
| 9 | * - BMA222E | ||
| 10 | * - BMA280 | ||
| 11 | * | ||
| 12 | * Copyright (c) 2014, Intel Corporation. | 4 | * Copyright (c) 2014, Intel Corporation. |
| 13 | */ | 5 | */ |
| 14 | 6 | ||
| @@ -21,6 +13,164 @@ · 6 unmodified lines | |||
| 21 | 13 | ||
| 22 | #include "bmc150-accel.h" | 14 | #include "bmc150-accel.h" |
| 23 | 15 | ||
| 16 | #ifdef CONFIG_ACPI | ||
| 17 | static const struct acpi_device_id bmc150_acpi_dual_accel_ids[] = { | ||
| 18 | {"BOSC0200"}, | ||
| 19 | {"DUAL250E"}, | ||
| 20 | { } | ||
| 21 | }; | ||
| 22 | |||
| 23 | /* | ||
| 24 | * The DUAL250E ACPI device for 360° hinges type 2-in-1s with 1 accelerometer | ||
| 25 | * in the display and 1 in the hinge has an ACPI-method (DSM) to tell the | ||
| 26 | * ACPI code about the angle between the 2 halves. This will make the ACPI | ||
| 27 | * code enable/disable the keyboard and touchpad. We need to call this to avoid | ||
| 28 | * the keyboard being disabled when the 2-in-1 is turned-on or resumed while | ||
| 29 | * fully folded into tablet mode (which gets detected with a HALL-sensor). | ||
| 30 | * If we don't call this then the keyboard won't work even when the 2-in-1 is | ||
| 31 | * changed to be used in laptop mode after the power-on / resume. | ||
| 32 | * | ||
| 33 | * This DSM takes 2 angles, selected by setting aux0 to 0 or 1, these presumably | ||
| 34 | * define the angle between the gravity vector measured by the accelerometer in | ||
| 35 | * the display (aux0=0) resp. the base (aux0=1) and some reference vector. | ||
| 36 | * The 2 angles get subtracted from each other so the reference vector does | ||
| 37 | * not matter and we can simply leave the second angle at 0. | ||
| 38 | */ | ||
| 39 | |||
| 40 | #define BMC150_DSM_GUID "7681541e-8827-4239-8d9d-36be7fe12542" | ||
| 41 | #define DUAL250E_SET_ANGLE_FN_INDEX 3 | ||
| 42 | |||
| 43 | struct dual250e_set_angle_args { | ||
| 44 | u32 aux0; | ||
| 45 | u32 ang0; | ||
| 46 | u32 rawx; | ||
| 47 | u32 rawy; | ||
| 48 | u32 rawz; | ||
| 49 | } __packed; | ||
| 50 | |||
| 51 | static bool bmc150_acpi_set_angle_dsm(struct i2c_client *client, u32 aux0, u32 ang0) | ||
| 52 | { | ||
| 53 | struct acpi_device *adev = ACPI_COMPANION(&client->dev); | ||
| 54 | struct dual250e_set_angle_args args = { | ||
| 55 | .aux0 = aux0, | ||
| 56 | .ang0 = ang0, | ||
| 57 | }; | ||
| 58 | union acpi_object args_obj, *obj; | ||
| 59 | guid_t guid; | ||
| 60 | |||
| 61 | if (!acpi_dev_hid_uid_match(adev, "DUAL250E", NULL)) | ||
| 62 | return false; | ||
| 63 | |||
| 64 | guid_parse(BMC150_DSM_GUID, &guid); | ||
| 65 | |||
| 66 | if (!acpi_check_dsm(adev->handle, &guid, 0, BIT(DUAL250E_SET_ANGLE_FN_INDEX))) | ||
| 67 | return false; | ||
| 68 | |||
| 69 | /* | ||
| 70 | * Note this triggers the following warning: | ||
| 71 | * "ACPI Warning: \_SB.PCI0.I2C2.ACC1._DSM: Argument #4 type mismatch - | ||
| 72 | * Found [Buffer], ACPI requires [Package]" | ||
| 73 | * This is unavoidable since the _DSM implementation expects a "naked" | ||
| 74 | * buffer, so wrapping it in a package will _not_ work. | ||
| 75 | */ | ||
| 76 | args_obj.type = ACPI_TYPE_BUFFER; | ||
| 77 | args_obj.buffer.length = sizeof(args); | ||
| 78 | args_obj.buffer.pointer = (u8 *)&args; | ||
| 79 | |||
| 80 | obj = acpi_evaluate_dsm(adev->handle, &guid, 0, DUAL250E_SET_ANGLE_FN_INDEX, &args_obj); | ||
| 81 | if (!obj) { | ||
| 82 | dev_err(&client->dev, "Failed to call DSM to enable keyboard and touchpad\n"); | ||
| 83 | return false; | ||
| 84 | } | ||
| 85 | |||
| 86 | ACPI_FREE(obj); | ||
| 87 | return true; | ||
| 88 | } | ||
| 89 | |||
| 90 | static bool bmc150_acpi_enable_keyboard(struct i2c_client *client) | ||
| 91 | { | ||
| 92 | /* | ||
| 93 | * The EC must see a change for it to re-enable the kbd, so first | ||
| 94 | * set the angle to 270° (tent/stand mode) and then change it to | ||
| 95 | * 90° (laptop mode). | ||
| 96 | */ | ||
| 97 | if (!bmc150_acpi_set_angle_dsm(client, 0, 270)) | ||
| 98 | return false; | ||
| 99 | |||
| 100 | /* The EC needs some time to notice the angle being changed */ | ||
| 101 | msleep(100); | ||
| 102 | |||
| 103 | return bmc150_acpi_set_angle_dsm(client, 0, 90); | ||
| 104 | } | ||
| 105 | |||
| 106 | static void bmc150_acpi_resume_work(struct work_struct *work) | ||
| 107 | { | ||
| 108 | struct bmc150_accel_data *data = | ||
| 109 | container_of(work, struct bmc150_accel_data, resume_work.work); | ||
| 110 | |||
| 111 | bmc150_acpi_enable_keyboard(data->second_device); | ||
| 112 | } | ||
| 113 | |||
| 114 | static void bmc150_acpi_resume_handler(struct device *dev) | ||
| 115 | { | ||
| 116 | struct bmc150_accel_data *data = iio_priv(dev_get_drvdata(dev)); | ||
| 117 | |||
| 118 | /* | ||
| 119 | * Delay the bmc150_acpi_enable_keyboard() call till after the system | ||
| 120 | * resume has completed, otherwise it will not work. | ||
| 121 | */ | ||
| 122 | schedule_delayed_work(&data->resume_work, msecs_to_jiffies(1000)); | ||
| 123 | } | ||
| 124 | |||
| 125 | /* | ||
| 126 | * Some acpi_devices describe 2 accelerometers in a single ACPI device, | ||
| 127 | * try instantiating a second i2c_client for an I2cSerialBusV2 ACPI resource | ||
| 128 | * with index 1. | ||
| 129 | */ | ||
| 130 | static void bmc150_acpi_dual_accel_probe(struct i2c_client *client) | ||
| 131 | { | ||
| 132 | struct bmc150_accel_data *data = iio_priv(i2c_get_clientdata(client)); | ||
| 133 | struct acpi_device *adev = ACPI_COMPANION(&client->dev); | ||
| 134 | char dev_name[16]; | ||
| 135 | struct i2c_board_info board_info = { | ||
| 136 | .type = "bmc150_accel", | ||
| 137 | .dev_name = dev_name, | ||
| 138 | .fwnode = client->dev.fwnode, | ||
| 139 | }; | ||
| 140 | |||
| 141 | if (acpi_match_device_ids(adev, bmc150_acpi_dual_accel_ids)) | ||
| 142 | return; | ||
| 143 | |||
| 144 | /* | ||
| 145 | * The 2nd accel sits in the base of 2-in-1s. The suffix is static, as | ||
| 146 | * there should never be more then 1 ACPI node with 2 accelerometers. | ||
| 147 | */ | ||
| 148 | snprintf(dev_name, sizeof(dev_name), "%s:base", acpi_device_hid(adev)); | ||
| 149 | |||
| 150 | board_info.irq = acpi_dev_gpio_irq_get(adev, 1); | ||
| 151 | |||
| 152 | data->second_device = i2c_acpi_new_device(&client->dev, 1, &board_info); | ||
| 153 | |||
| 154 | if (!IS_ERR(data->second_device) && bmc150_acpi_enable_keyboard(data->second_device)) { | ||
| 155 | INIT_DELAYED_WORK(&data->resume_work, bmc150_acpi_resume_work); | ||
| 156 | data->resume_callback = bmc150_acpi_resume_handler; | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | static void bmc150_acpi_dual_accel_remove(struct i2c_client *client) | ||
| 161 | { | ||
| 162 | struct bmc150_accel_data *data = iio_priv(i2c_get_clientdata(client)); | ||
| 163 | |||
| 164 | if (data->resume_callback) | ||
| 165 | cancel_delayed_work_sync(&data->resume_work); | ||
| 166 | |||
| 167 | i2c_unregister_device(data->second_device); | ||
| 168 | } | ||
| 169 | #else | ||
| 170 | static void bmc150_acpi_dual_accel_probe(struct i2c_client *client) {} | ||
| 171 | static void bmc150_acpi_dual_accel_remove(struct i2c_client *client) {} | ||
| 172 | #endif | ||
| 173 | |||
| 24 | static int bmc150_accel_probe(struct i2c_client *client, | 174 | static int bmc150_accel_probe(struct i2c_client *client, |
| 25 | const struct i2c_device_id *id) | 175 | const struct i2c_device_id *id) |
| 26 | { | 176 | { |
| @@ -30,7 +180,6 @@ static int bmc150_accel_probe(struct i2c_client *client, · 3 unmodified lines | |||
| 30 | i2c_check_functionality(client->adapter, I2C_FUNC_I2C) || | 180 | i2c_check_functionality(client->adapter, I2C_FUNC_I2C) || |
| 31 | i2c_check_functionality(client->adapter, | 181 | i2c_check_functionality(client->adapter, |
| 32 | I2C_FUNC_SMBUS_READ_I2C_BLOCK); | 182 | I2C_FUNC_SMBUS_READ_I2C_BLOCK); |
| 33 | struct acpi_device __maybe_unused *adev; | ||
| 34 | int ret; | 183 | int ret; |
| 35 | 184 | ||
| 36 | regmap = devm_regmap_init_i2c(client, &bmc150_regmap_conf); | 185 | regmap = devm_regmap_init_i2c(client, &bmc150_regmap_conf); |
| @@ -47,80 +196,62 @@ static int bmc150_accel_probe(struct i2c_client *client, · 10 unmodified lines | |||
| 47 | return ret; | 196 | return ret; |
| 48 | 197 | ||
| 49 | /* | 198 | /* |
| 50 | * Some BOSC0200 acpi_devices describe 2 accelerometers in a single ACPI | 199 | * The !id check avoids recursion when probe() gets called |
| 51 | * device, try instantiating a second i2c_client for an I2cSerialBusV2 | 200 | * for the second client. |
| 52 | * ACPI resource with index 1. The !id check avoids recursion when | ||
| 53 | * bmc150_accel_probe() gets called for the second client. | ||
| 54 | */ | 201 | */ |
| 55 | #ifdef CONFIG_ACPI | 202 | if (!id && has_acpi_companion(&client->dev)) |
| 56 | adev = ACPI_COMPANION(&client->dev); | 203 | bmc150_acpi_dual_accel_probe(client); |
| 57 | if (!id && adev && strcmp(acpi_device_hid(adev), "BOSC0200") == 0) { | ||
| 58 | struct i2c_board_info board_info = { | ||
| 59 | .type = "bmc150_accel", | ||
| 60 | /* | ||
| 61 | * The 2nd accel sits in the base of 2-in-1s. Note this | ||
| 62 | * name is static, as there should never be more then 1 | ||
| 63 | * BOSC0200 ACPI node with 2 accelerometers in it. | ||
| 64 | */ | ||
| 65 | .dev_name = "BOSC0200:base", | ||
| 66 | .fwnode = client->dev.fwnode, | ||
| 67 | .irq = -ENOENT, | ||
| 68 | }; | ||
| 69 | struct i2c_client *second_dev; | ||
| 70 | |||
| 71 | second_dev = i2c_acpi_new_device(&client->dev, 1, &board_info); | ||
| 72 | if (!IS_ERR(second_dev)) | ||
| 73 | bmc150_set_second_device(second_dev); | ||
| 74 | } | ||
| 75 | #endif | ||
| 76 | 204 | ||
| 77 | return 0; | 205 | return 0; |
| 78 | } | 206 | } |
| 79 | 207 | ||
| 80 | static int bmc150_accel_remove(struct i2c_client *client) | 208 | static int bmc150_accel_remove(struct i2c_client *client) |
| 81 | { | 209 | { |
| 82 | struct i2c_client *second_dev = bmc150_get_second_device(client); | 210 | bmc150_acpi_dual_accel_remove(client); |
| 83 | |||
| 84 | i2c_unregister_device(second_dev); | ||
| 85 | 211 | ||
| 86 | return bmc150_accel_core_remove(&client->dev); | 212 | return bmc150_accel_core_remove(&client->dev); |
| 87 | } | 213 | } |
| 88 | 214 | ||
| 89 | static const struct acpi_device_id bmc150_accel_acpi_match[] = { | 215 | static const struct acpi_device_id bmc150_accel_acpi_match[] = { |
| 90 | {"BSBA0150", bmc150}, | 216 | {"BMA0255"}, |
| 91 | {"BMC150A", bmc150}, | 217 | {"BMA0280"}, |
| 92 | {"BMI055A", bmi055}, | 218 | {"BMA222"}, |
| 93 | {"BMA0255", bma255}, | 219 | {"BMA222E"}, |
| 94 | {"BMA250E", bma250e}, | 220 | {"BMA250E"}, |
| 95 | {"BMA222", bma222}, | 221 | {"BMC150A"}, |
| 96 | {"BMA222E", bma222e}, | 222 | {"BMI055A"}, |
| 97 | {"BMA0280", bma280}, | ||
| 98 | {"BOSC0200"}, | 223 | {"BOSC0200"}, |
| 224 | {"BSBA0150"}, | ||
| 225 | {"DUAL250E"}, | ||
| 99 | { }, | 226 | { }, |
| 100 | }; | 227 | }; |
| 101 | MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); | 228 | MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); |
| 102 | 229 | ||
| 103 | static const struct i2c_device_id bmc150_accel_id[] = { | 230 | static const struct i2c_device_id bmc150_accel_id[] = { |
| 104 | {"bmc150_accel", bmc150}, | 231 | {"bma222"}, |
| 105 | {"bmi055_accel", bmi055}, | 232 | {"bma222e"}, |
| 106 | {"bma255", bma255}, | 233 | {"bma250e"}, |
| 107 | {"bma250e", bma250e}, | 234 | {"bma253"}, |
| 108 | {"bma222", bma222}, | 235 | {"bma254"}, |
| 109 | {"bma222e", bma222e}, | 236 | {"bma255"}, |
| 110 | {"bma280", bma280}, | 237 | {"bma280"}, |
| 238 | {"bmc150_accel"}, | ||
| 239 | {"bmi055_accel"}, | ||
| 111 | {} | 240 | {} |
| 112 | }; | 241 | }; |
| 113 | 242 | ||
| 114 | MODULE_DEVICE_TABLE(i2c, bmc150_accel_id); | 243 | MODULE_DEVICE_TABLE(i2c, bmc150_accel_id); |
| 115 | 244 | ||
| 116 | static const struct of_device_id bmc150_accel_of_match[] = { | 245 | static const struct of_device_id bmc150_accel_of_match[] = { |
| 117 | { .compatible = "bosch,bmc150_accel" }, | ||
| 118 | { .compatible = "bosch,bmi055_accel" }, | ||
| 119 | { .compatible = "bosch,bma255" }, | ||
| 120 | { .compatible = "bosch,bma250e" }, | ||
| 121 | { .compatible = "bosch,bma222" }, | 246 | { .compatible = "bosch,bma222" }, |
| 122 | { .compatible = "bosch,bma222e" }, | 247 | { .compatible = "bosch,bma222e" }, |
| 248 | { .compatible = "bosch,bma250e" }, | ||
| 249 | { .compatible = "bosch,bma253" }, | ||
| 250 | { .compatible = "bosch,bma254" }, | ||
| 251 | { .compatible = "bosch,bma255" }, | ||
| 123 | { .compatible = "bosch,bma280" }, | 252 | { .compatible = "bosch,bma280" }, |
| 253 | { .compatible = "bosch,bmc150_accel" }, | ||
| 254 | { .compatible = "bosch,bmi055_accel" }, | ||
| 124 | { }, | 255 | { }, |
| 125 | }; | 256 | }; |
| 126 | MODULE_DEVICE_TABLE(of, bmc150_accel_of_match); | 257 | MODULE_DEVICE_TABLE(of, bmc150_accel_of_match); |
| @@ -34,26 +34,27 @@ static int bmc150_accel_remove(struct spi_device *spi) · 33 unmodified lines | |||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | static const struct acpi_device_id bmc150_accel_acpi_match[] = { | 36 | static const struct acpi_device_id bmc150_accel_acpi_match[] = { |
| 37 | {"BSBA0150", bmc150}, | 37 | {"BMA0255"}, |
| 38 | {"BMC150A", bmc150}, | 38 | {"BMA0280"}, |
| 39 | {"BMI055A", bmi055}, | 39 | {"BMA222"}, |
| 40 | {"BMA0255", bma255}, | 40 | {"BMA222E"}, |
| 41 | {"BMA250E", bma250e}, | 41 | {"BMA250E"}, |
| 42 | {"BMA222", bma222}, | 42 | {"BMC150A"}, |
| 43 | {"BMA222E", bma222e}, | 43 | {"BMI055A"}, |
| 44 | {"BMA0280", bma280}, | 44 | {"BSBA0150"}, |
| 45 | { }, | 45 | { }, |
| 46 | }; | 46 | }; |
| 47 | MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); | 47 | MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); |
| 48 | 48 | ||
| 49 | static const struct spi_device_id bmc150_accel_id[] = { | 49 | static const struct spi_device_id bmc150_accel_id[] = { |
| 50 | {"bmc150_accel", bmc150}, | 50 | {"bma222"}, |
| 51 | {"bmi055_accel", bmi055}, | 51 | {"bma222e"}, |
| 52 | {"bma255", bma255}, | 52 | {"bma250e"}, |
| 53 | {"bma250e", bma250e}, | 53 | {"bma253"}, |
| 54 | {"bma222", bma222}, | 54 | {"bma255"}, |
| 55 | {"bma222e", bma222e}, | 55 | {"bma280"}, |
| 56 | {"bma280", bma280}, | 56 | {"bmc150_accel"}, |
| 57 | {"bmi055_accel"}, | ||
| 57 | {} | 58 | {} |
| 58 | }; | 59 | }; |
| 59 | MODULE_DEVICE_TABLE(spi, bmc150_accel_id); | 60 | MODULE_DEVICE_TABLE(spi, bmc150_accel_id); |
| @@ -2,23 +2,75 @@ · 1 unmodified line | |||
| 2 | #ifndef _BMC150_ACCEL_H_ | 2 | #ifndef _BMC150_ACCEL_H_ |
| 3 | #define _BMC150_ACCEL_H_ | 3 | #define _BMC150_ACCEL_H_ |
| 4 | 4 | ||
| 5 | #include <linux/atomic.h> | ||
| 6 | #include <linux/iio/iio.h> | ||
| 7 | #include <linux/mutex.h> | ||
| 8 | #include <linux/regulator/consumer.h> | ||
| 9 | #include <linux/workqueue.h> | ||
| 10 | |||
| 5 | struct regmap; | 11 | struct regmap; |
| 12 | struct i2c_client; | ||
| 13 | struct bmc150_accel_chip_info; | ||
| 14 | struct bmc150_accel_interrupt_info; | ||
| 15 | |||
| 16 | struct bmc150_accel_interrupt { | ||
| 17 | const struct bmc150_accel_interrupt_info *info; | ||
| 18 | atomic_t users; | ||
| 19 | }; | ||
| 20 | |||
| 21 | struct bmc150_accel_trigger { | ||
| 22 | struct bmc150_accel_data *data; | ||
| 23 | struct iio_trigger *indio_trig; | ||
| 24 | int (*setup)(struct bmc150_accel_trigger *t, bool state); | ||
| 25 | int intr; | ||
| 26 | bool enabled; | ||
| 27 | }; | ||
| 28 | |||
| 29 | enum bmc150_accel_interrupt_id { | ||
| 30 | BMC150_ACCEL_INT_DATA_READY, | ||
| 31 | BMC150_ACCEL_INT_ANY_MOTION, | ||
| 32 | BMC150_ACCEL_INT_WATERMARK, | ||
| 33 | BMC150_ACCEL_INTERRUPTS, | ||
| 34 | }; | ||
| 35 | |||
| 36 | enum bmc150_accel_trigger_id { | ||
| 37 | BMC150_ACCEL_TRIGGER_DATA_READY, | ||
| 38 | BMC150_ACCEL_TRIGGER_ANY_MOTION, | ||
| 39 | BMC150_ACCEL_TRIGGERS, | ||
| 40 | }; | ||
| 6 | 41 | ||
| 7 | enum { | 42 | struct bmc150_accel_data { |
| 8 | bmc150, | 43 | struct regmap *regmap; |
| 9 | bmi055, | 44 | struct regulator_bulk_data regulators[2]; |
| 10 | bma255, | 45 | struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS]; |
| 11 | bma250e, | 46 | struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS]; |
| 12 | bma222, | 47 | struct mutex mutex; |
| 13 | bma222e, | 48 | u8 fifo_mode, watermark; |
| 14 | bma280, | 49 | s16 buffer[8]; |
| 50 | /* | ||
| 51 | * Ensure there is sufficient space and correct alignment for | ||
| 52 | * the timestamp if enabled | ||
| 53 | */ | ||
| 54 | struct { | ||
| 55 | __le16 channels[3]; | ||
| 56 | s64 ts __aligned(8); | ||
| 57 | } scan; | ||
| 58 | u8 bw_bits; | ||
| 59 | u32 slope_dur; | ||
| 60 | u32 slope_thres; | ||
| 61 | u32 range; | ||
| 62 | int ev_enable_state; | ||
| 63 | int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */ | ||
| 64 | const struct bmc150_accel_chip_info *chip_info; | ||
| 65 | struct i2c_client *second_device; | ||
| 66 | void (*resume_callback)(struct device *dev); | ||
| 67 | struct delayed_work resume_work; | ||
| 68 | struct iio_mount_matrix orientation; | ||
| 15 | }; | 69 | }; |
| 16 | 70 | ||
| 17 | int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, | 71 | int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, |
| 18 | const char *name, bool block_supported); | 72 | const char *name, bool block_supported); |
| 19 | int bmc150_accel_core_remove(struct device *dev); | 73 | int bmc150_accel_core_remove(struct device *dev); |
| 20 | struct i2c_client *bmc150_get_second_device(struct i2c_client *second_device); | ||
| 21 | void bmc150_set_second_device(struct i2c_client *second_device); | ||
| 22 | extern const struct dev_pm_ops bmc150_accel_pm_ops; | 74 | extern const struct dev_pm_ops bmc150_accel_pm_ops; |
| 23 | extern const struct regmap_config bmc150_regmap_conf; | 75 | extern const struct regmap_config bmc150_regmap_conf; |
| 24 | 76 | ||
| @@ -285,11 +285,17 @@ static int bmi088_accel_read_raw(struct iio_dev *indio_dev, · 284 unmodified lines | |||
| 285 | case IIO_CHAN_INFO_RAW: | 285 | case IIO_CHAN_INFO_RAW: |
| 286 | switch (chan->type) { | 286 | switch (chan->type) { |
| 287 | case IIO_TEMP: | 287 | case IIO_TEMP: |
| 288 | pm_runtime_get_sync(dev); | 288 | ret = pm_runtime_resume_and_get(dev); |
| 289 | if (ret) | ||
| 290 | return ret; | ||
| 291 | |||
| 289 | ret = bmi088_accel_get_temp(data, val); | 292 | ret = bmi088_accel_get_temp(data, val); |
| 290 | goto out_read_raw_pm_put; | 293 | goto out_read_raw_pm_put; |
| 291 | case IIO_ACCEL: | 294 | case IIO_ACCEL: |
| 292 | pm_runtime_get_sync(dev); | 295 | ret = pm_runtime_resume_and_get(dev); |
| 296 | if (ret) | ||
| 297 | return ret; | ||
| 298 | |||
| 293 | ret = iio_device_claim_direct_mode(indio_dev); | 299 | ret = iio_device_claim_direct_mode(indio_dev); |
| 294 | if (ret) | 300 | if (ret) |
| 295 | goto out_read_raw_pm_put; | 301 | goto out_read_raw_pm_put; |
| @@ -319,7 +325,10 @@ static int bmi088_accel_read_raw(struct iio_dev *indio_dev, · 23 unmodified lines | |||
| 319 | *val = BMI088_ACCEL_TEMP_UNIT; | 325 | *val = BMI088_ACCEL_TEMP_UNIT; |
| 320 | return IIO_VAL_INT; | 326 | return IIO_VAL_INT; |
| 321 | case IIO_ACCEL: | 327 | case IIO_ACCEL: |
| 322 | pm_runtime_get_sync(dev); | 328 | ret = pm_runtime_resume_and_get(dev); |
| 329 | if (ret) | ||
| 330 | return ret; | ||
| 331 | |||
| 323 | ret = regmap_read(data->regmap, | 332 | ret = regmap_read(data->regmap, |
| 324 | BMI088_ACCEL_REG_ACC_RANGE, val); | 333 | BMI088_ACCEL_REG_ACC_RANGE, val); |
| 325 | if (ret) | 334 | if (ret) |
| @@ -334,7 +343,10 @@ static int bmi088_accel_read_raw(struct iio_dev *indio_dev, · 8 unmodified lines | |||
| 334 | return -EINVAL; | 343 | return -EINVAL; |
| 335 | } | 344 | } |
| 336 | case IIO_CHAN_INFO_SAMP_FREQ: | 345 | case IIO_CHAN_INFO_SAMP_FREQ: |
| 337 | pm_runtime_get_sync(dev); | 346 | ret = pm_runtime_resume_and_get(dev); |
| 347 | if (ret) | ||
| 348 | return ret; | ||
| 349 | |||
| 338 | ret = bmi088_accel_get_sample_freq(data, val, val2); | 350 | ret = bmi088_accel_get_sample_freq(data, val, val2); |
| 339 | goto out_read_raw_pm_put; | 351 | goto out_read_raw_pm_put; |
| 340 | default: | 352 | default: |
| @@ -376,7 +388,10 @@ static int bmi088_accel_write_raw(struct iio_dev *indio_dev, · 35 unmodified lines | |||
| 376 | 388 | ||
| 377 | switch (mask) { | 389 | switch (mask) { |
| 378 | case IIO_CHAN_INFO_SAMP_FREQ: | 390 | case IIO_CHAN_INFO_SAMP_FREQ: |
| 379 | pm_runtime_get_sync(dev); | 391 | ret = pm_runtime_resume_and_get(dev); |
| 392 | if (ret) | ||
| 393 | return ret; | ||
| 394 | |||
| 380 | ret = bmi088_accel_set_sample_freq(data, val); | 395 | ret = bmi088_accel_set_sample_freq(data, val); |
| 381 | pm_runtime_mark_last_busy(dev); | 396 | pm_runtime_mark_last_busy(dev); |
| 382 | pm_runtime_put_autosuspend(dev); | 397 | pm_runtime_put_autosuspend(dev); |
| @@ -496,7 +511,6 @@ int bmi088_accel_core_probe(struct device *dev, struct regmap *regmap, · 113 unmodified lines | |||
| 496 | if (ret) | 511 | if (ret) |
| 497 | return ret; | 512 | return ret; |
| 498 | 513 | ||
| 499 | indio_dev->dev.parent = dev; | ||
| 500 | indio_dev->channels = data->chip_info->channels; | 514 | indio_dev->channels = data->chip_info->channels; |
| 501 | indio_dev->num_channels = data->chip_info->num_channels; | 515 | indio_dev->num_channels = data->chip_info->num_channels; |
| 502 | indio_dev->name = name ? name : data->chip_info->name; | 516 | indio_dev->name = name ? name : data->chip_info->name; |
| @@ -531,7 +545,6 @@ int bmi088_accel_core_remove(struct device *dev) · 28 unmodified lines | |||
| 531 | 545 | ||
| 532 | pm_runtime_disable(dev); | 546 | pm_runtime_disable(dev); |
| 533 | pm_runtime_set_suspended(dev); | 547 | pm_runtime_set_suspended(dev); |
| 534 | pm_runtime_put_noidle(dev); | ||
| 535 | bmi088_accel_power_down(data); | 548 | bmi088_accel_power_down(data); |
| 536 | 549 | ||
| 537 | return 0; | 550 | return 0; |
| @@ -0,0 +1,968 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * NXP FXLS8962AF/FXLS8964AF Accelerometer Core Driver | ||
| 4 | * | ||
| 5 | * Copyright 2021 Connected Cars A/S | ||
| 6 | * | ||
| 7 | * Datasheet: | ||
| 8 | * https://www.nxp.com/docs/en/data-sheet/FXLS8962AF.pdf | ||
| 9 | * https://www.nxp.com/docs/en/data-sheet/FXLS8964AF.pdf | ||
| 10 | * | ||
| 11 | * Errata: | ||
| 12 | * https://www.nxp.com/docs/en/errata/ES_FXLS8962AF.pdf | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/bits.h> | ||
| 16 | #include <linux/bitfield.h> | ||
| 17 | #include <linux/i2c.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/of_irq.h> | ||
| 20 | #include <linux/pm_runtime.h> | ||
| 21 | #include <linux/regulator/consumer.h> | ||
| 22 | #include <linux/regmap.h> | ||
| 23 | |||
| 24 | #include <linux/iio/buffer.h> | ||
| 25 | #include <linux/iio/iio.h> | ||
| 26 | #include <linux/iio/kfifo_buf.h> | ||
| 27 | #include <linux/iio/sysfs.h> | ||
| 28 | |||
| 29 | #include "fxls8962af.h" | ||
| 30 | |||
| 31 | #define FXLS8962AF_INT_STATUS 0x00 | ||
| 32 | #define FXLS8962AF_INT_STATUS_SRC_BOOT BIT(0) | ||
| 33 | #define FXLS8962AF_INT_STATUS_SRC_BUF BIT(5) | ||
| 34 | #define FXLS8962AF_INT_STATUS_SRC_DRDY BIT(7) | ||
| 35 | #define FXLS8962AF_TEMP_OUT 0x01 | ||
| 36 | #define FXLS8962AF_VECM_LSB 0x02 | ||
| 37 | #define FXLS8962AF_OUT_X_LSB 0x04 | ||
| 38 | #define FXLS8962AF_OUT_Y_LSB 0x06 | ||
| 39 | #define FXLS8962AF_OUT_Z_LSB 0x08 | ||
| 40 | #define FXLS8962AF_BUF_STATUS 0x0b | ||
| 41 | #define FXLS8962AF_BUF_STATUS_BUF_CNT GENMASK(5, 0) | ||
| 42 | #define FXLS8962AF_BUF_STATUS_BUF_OVF BIT(6) | ||
| 43 | #define FXLS8962AF_BUF_STATUS_BUF_WMRK BIT(7) | ||
| 44 | #define FXLS8962AF_BUF_X_LSB 0x0c | ||
| 45 | #define FXLS8962AF_BUF_Y_LSB 0x0e | ||
| 46 | #define FXLS8962AF_BUF_Z_LSB 0x10 | ||
| 47 | |||
| 48 | #define FXLS8962AF_PROD_REV 0x12 | ||
| 49 | #define FXLS8962AF_WHO_AM_I 0x13 | ||
| 50 | |||
| 51 | #define FXLS8962AF_SYS_MODE 0x14 | ||
| 52 | #define FXLS8962AF_SENS_CONFIG1 0x15 | ||
| 53 | #define FXLS8962AF_SENS_CONFIG1_ACTIVE BIT(0) | ||
| 54 | #define FXLS8962AF_SENS_CONFIG1_RST BIT(7) | ||
| 55 | #define FXLS8962AF_SC1_FSR_MASK GENMASK(2, 1) | ||
| 56 | #define FXLS8962AF_SC1_FSR_PREP(x) FIELD_PREP(FXLS8962AF_SC1_FSR_MASK, (x)) | ||
| 57 | #define FXLS8962AF_SC1_FSR_GET(x) FIELD_GET(FXLS8962AF_SC1_FSR_MASK, (x)) | ||
| 58 | |||
| 59 | #define FXLS8962AF_SENS_CONFIG2 0x16 | ||
| 60 | #define FXLS8962AF_SENS_CONFIG3 0x17 | ||
| 61 | #define FXLS8962AF_SC3_WAKE_ODR_MASK GENMASK(7, 4) | ||
| 62 | #define FXLS8962AF_SC3_WAKE_ODR_PREP(x) FIELD_PREP(FXLS8962AF_SC3_WAKE_ODR_MASK, (x)) | ||
| 63 | #define FXLS8962AF_SC3_WAKE_ODR_GET(x) FIELD_GET(FXLS8962AF_SC3_WAKE_ODR_MASK, (x)) | ||
| 64 | #define FXLS8962AF_SENS_CONFIG4 0x18 | ||
| 65 | #define FXLS8962AF_SC4_INT_PP_OD_MASK BIT(1) | ||
| 66 | #define FXLS8962AF_SC4_INT_PP_OD_PREP(x) FIELD_PREP(FXLS8962AF_SC4_INT_PP_OD_MASK, (x)) | ||
| 67 | #define FXLS8962AF_SC4_INT_POL_MASK BIT(0) | ||
| 68 | #define FXLS8962AF_SC4_INT_POL_PREP(x) FIELD_PREP(FXLS8962AF_SC4_INT_POL_MASK, (x)) | ||
| 69 | #define FXLS8962AF_SENS_CONFIG5 0x19 | ||
| 70 | |||
| 71 | #define FXLS8962AF_WAKE_IDLE_LSB 0x1b | ||
| 72 | #define FXLS8962AF_SLEEP_IDLE_LSB 0x1c | ||
| 73 | #define FXLS8962AF_ASLP_COUNT_LSB 0x1e | ||
| 74 | |||
| 75 | #define FXLS8962AF_INT_EN 0x20 | ||
| 76 | #define FXLS8962AF_INT_EN_BUF_EN BIT(6) | ||
| 77 | #define FXLS8962AF_INT_PIN_SEL 0x21 | ||
| 78 | #define FXLS8962AF_INT_PIN_SEL_MASK GENMASK(7, 0) | ||
| 79 | #define FXLS8962AF_INT_PIN_SEL_INT1 0x00 | ||
| 80 | #define FXLS8962AF_INT_PIN_SEL_INT2 GENMASK(7, 0) | ||
| 81 | |||
| 82 | #define FXLS8962AF_OFF_X 0x22 | ||
| 83 | #define FXLS8962AF_OFF_Y 0x23 | ||
| 84 | #define FXLS8962AF_OFF_Z 0x24 | ||
| 85 | |||
| 86 | #define FXLS8962AF_BUF_CONFIG1 0x26 | ||
| 87 | #define FXLS8962AF_BC1_BUF_MODE_MASK GENMASK(6, 5) | ||
| 88 | #define FXLS8962AF_BC1_BUF_MODE_PREP(x) FIELD_PREP(FXLS8962AF_BC1_BUF_MODE_MASK, (x)) | ||
| 89 | #define FXLS8962AF_BUF_CONFIG2 0x27 | ||
| 90 | #define FXLS8962AF_BUF_CONFIG2_BUF_WMRK GENMASK(5, 0) | ||
| 91 | |||
| 92 | #define FXLS8962AF_ORIENT_STATUS 0x28 | ||
| 93 | #define FXLS8962AF_ORIENT_CONFIG 0x29 | ||
| 94 | #define FXLS8962AF_ORIENT_DBCOUNT 0x2a | ||
| 95 | #define FXLS8962AF_ORIENT_BF_ZCOMP 0x2b | ||
| 96 | #define FXLS8962AF_ORIENT_THS_REG 0x2c | ||
| 97 | |||
| 98 | #define FXLS8962AF_SDCD_INT_SRC1 0x2d | ||
| 99 | #define FXLS8962AF_SDCD_INT_SRC2 0x2e | ||
| 100 | #define FXLS8962AF_SDCD_CONFIG1 0x2f | ||
| 101 | #define FXLS8962AF_SDCD_CONFIG2 0x30 | ||
| 102 | #define FXLS8962AF_SDCD_OT_DBCNT 0x31 | ||
| 103 | #define FXLS8962AF_SDCD_WT_DBCNT 0x32 | ||
| 104 | #define FXLS8962AF_SDCD_LTHS_LSB 0x33 | ||
| 105 | #define FXLS8962AF_SDCD_UTHS_LSB 0x35 | ||
| 106 | |||
| 107 | #define FXLS8962AF_SELF_TEST_CONFIG1 0x37 | ||
| 108 | #define FXLS8962AF_SELF_TEST_CONFIG2 0x38 | ||
| 109 | |||
| 110 | #define FXLS8962AF_MAX_REG 0x38 | ||
| 111 | |||
| 112 | #define FXLS8962AF_DEVICE_ID 0x62 | ||
| 113 | #define FXLS8964AF_DEVICE_ID 0x84 | ||
| 114 | |||
| 115 | /* Raw temp channel offset */ | ||
| 116 | #define FXLS8962AF_TEMP_CENTER_VAL 25 | ||
| 117 | |||
| 118 | #define FXLS8962AF_AUTO_SUSPEND_DELAY_MS 2000 | ||
| 119 | |||
| 120 | #define FXLS8962AF_FIFO_LENGTH 32 | ||
| 121 | #define FXLS8962AF_SCALE_TABLE_LEN 4 | ||
| 122 | #define FXLS8962AF_SAMP_FREQ_TABLE_LEN 13 | ||
| 123 | |||
| 124 | static const int fxls8962af_scale_table[FXLS8962AF_SCALE_TABLE_LEN][2] = { | ||
| 125 | {0, IIO_G_TO_M_S_2(980000)}, | ||
| 126 | {0, IIO_G_TO_M_S_2(1950000)}, | ||
| 127 | {0, IIO_G_TO_M_S_2(3910000)}, | ||
| 128 | {0, IIO_G_TO_M_S_2(7810000)}, | ||
| 129 | }; | ||
| 130 | |||
| 131 | static const int fxls8962af_samp_freq_table[FXLS8962AF_SAMP_FREQ_TABLE_LEN][2] = { | ||
| 132 | {3200, 0}, {1600, 0}, {800, 0}, {400, 0}, {200, 0}, {100, 0}, | ||
| 133 | {50, 0}, {25, 0}, {12, 500000}, {6, 250000}, {3, 125000}, | ||
| 134 | {1, 563000}, {0, 781000}, | ||
| 135 | }; | ||
| 136 | |||
| 137 | struct fxls8962af_chip_info { | ||
| 138 | const char *name; | ||
| 139 | const struct iio_chan_spec *channels; | ||
| 140 | int num_channels; | ||
| 141 | u8 chip_id; | ||
| 142 | }; | ||
| 143 | |||
| 144 | struct fxls8962af_data { | ||
| 145 | struct regmap *regmap; | ||
| 146 | const struct fxls8962af_chip_info *chip_info; | ||
| 147 | struct regulator *vdd_reg; | ||
| 148 | struct { | ||
| 149 | __le16 channels[3]; | ||
| 150 | s64 ts __aligned(8); | ||
| 151 | } scan; | ||
| 152 | int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */ | ||
| 153 | struct iio_mount_matrix orientation; | ||
| 154 | u8 watermark; | ||
| 155 | }; | ||
| 156 | |||
| 157 | const struct regmap_config fxls8962af_regmap_conf = { | ||
| 158 | .reg_bits = 8, | ||
| 159 | .val_bits = 8, | ||
| 160 | .max_register = FXLS8962AF_MAX_REG, | ||
| 161 | }; | ||
| 162 | EXPORT_SYMBOL_GPL(fxls8962af_regmap_conf); | ||
| 163 | |||
| 164 | enum { | ||
| 165 | fxls8962af_idx_x, | ||
| 166 | fxls8962af_idx_y, | ||
| 167 | fxls8962af_idx_z, | ||
| 168 | fxls8962af_idx_ts, | ||
| 169 | }; | ||
| 170 | |||
| 171 | enum fxls8962af_int_pin { | ||
| 172 | FXLS8962AF_PIN_INT1, | ||
| 173 | FXLS8962AF_PIN_INT2, | ||
| 174 | }; | ||
| 175 | |||
| 176 | static int fxls8962af_power_on(struct fxls8962af_data *data) | ||
| 177 | { | ||
| 178 | struct device *dev = regmap_get_device(data->regmap); | ||
| 179 | int ret; | ||
| 180 | |||
| 181 | ret = pm_runtime_resume_and_get(dev); | ||
| 182 | if (ret) | ||
| 183 | dev_err(dev, "failed to power on\n"); | ||
| 184 | |||
| 185 | return ret; | ||
| 186 | } | ||
| 187 | |||
| 188 | static int fxls8962af_power_off(struct fxls8962af_data *data) | ||
| 189 | { | ||
| 190 | struct device *dev = regmap_get_device(data->regmap); | ||
| 191 | int ret; | ||
| 192 | |||
| 193 | pm_runtime_mark_last_busy(dev); | ||
| 194 | ret = pm_runtime_put_autosuspend(dev); | ||
| 195 | if (ret) | ||
| 196 | dev_err(dev, "failed to power off\n"); | ||
| 197 | |||
| 198 | return ret; | ||
| 199 | } | ||
| 200 | |||
| 201 | static int fxls8962af_standby(struct fxls8962af_data *data) | ||
| 202 | { | ||
| 203 | return regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, | ||
| 204 | FXLS8962AF_SENS_CONFIG1_ACTIVE, 0); | ||
| 205 | } | ||
| 206 | |||
| 207 | static int fxls8962af_active(struct fxls8962af_data *data) | ||
| 208 | { | ||
| 209 | return regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, | ||
| 210 | FXLS8962AF_SENS_CONFIG1_ACTIVE, 1); | ||
| 211 | } | ||
| 212 | |||
| 213 | static int fxls8962af_is_active(struct fxls8962af_data *data) | ||
| 214 | { | ||
| 215 | unsigned int reg; | ||
| 216 | int ret; | ||
| 217 | |||
| 218 | ret = regmap_read(data->regmap, FXLS8962AF_SENS_CONFIG1, ®); | ||
| 219 | if (ret) | ||
| 220 | return ret; | ||
| 221 | |||
| 222 | return reg & FXLS8962AF_SENS_CONFIG1_ACTIVE; | ||
| 223 | } | ||
| 224 | |||
| 225 | static int fxls8962af_get_out(struct fxls8962af_data *data, | ||
| 226 | struct iio_chan_spec const *chan, int *val) | ||
| 227 | { | ||
| 228 | struct device *dev = regmap_get_device(data->regmap); | ||
| 229 | __le16 raw_val; | ||
| 230 | int is_active; | ||
| 231 | int ret; | ||
| 232 | |||
| 233 | is_active = fxls8962af_is_active(data); | ||
| 234 | if (!is_active) { | ||
| 235 | ret = fxls8962af_power_on(data); | ||
| 236 | if (ret) | ||
| 237 | return ret; | ||
| 238 | } | ||
| 239 | |||
| 240 | ret = regmap_bulk_read(data->regmap, chan->address, | ||
| 241 | &raw_val, (chan->scan_type.storagebits / 8)); | ||
| 242 | |||
| 243 | if (!is_active) | ||
| 244 | fxls8962af_power_off(data); | ||
| 245 | |||
| 246 | if (ret) { | ||
| 247 | dev_err(dev, "failed to get out reg 0x%lx\n", chan->address); | ||
| 248 | return ret; | ||
| 249 | } | ||
| 250 | |||
| 251 | *val = sign_extend32(le16_to_cpu(raw_val), | ||
| 252 | chan->scan_type.realbits - 1); | ||
| 253 | |||
| 254 | return IIO_VAL_INT; | ||
| 255 | } | ||
| 256 | |||
| 257 | static int fxls8962af_read_avail(struct iio_dev *indio_dev, | ||
| 258 | struct iio_chan_spec const *chan, | ||
| 259 | const int **vals, int *type, int *length, | ||
| 260 | long mask) | ||
| 261 | { | ||
| 262 | switch (mask) { | ||
| 263 | case IIO_CHAN_INFO_SCALE: | ||
| 264 | *type = IIO_VAL_INT_PLUS_NANO; | ||
| 265 | *vals = (int *)fxls8962af_scale_table; | ||
| 266 | *length = ARRAY_SIZE(fxls8962af_scale_table) * 2; | ||
| 267 | return IIO_AVAIL_LIST; | ||
| 268 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 269 | *type = IIO_VAL_INT_PLUS_MICRO; | ||
| 270 | *vals = (int *)fxls8962af_samp_freq_table; | ||
| 271 | *length = ARRAY_SIZE(fxls8962af_samp_freq_table) * 2; | ||
| 272 | return IIO_AVAIL_LIST; | ||
| 273 | default: | ||
| 274 | return -EINVAL; | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 278 | static int fxls8962af_write_raw_get_fmt(struct iio_dev *indio_dev, | ||
| 279 | struct iio_chan_spec const *chan, | ||
| 280 | long mask) | ||
| 281 | { | ||
| 282 | switch (mask) { | ||
| 283 | case IIO_CHAN_INFO_SCALE: | ||
| 284 | return IIO_VAL_INT_PLUS_NANO; | ||
| 285 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 286 | return IIO_VAL_INT_PLUS_MICRO; | ||
| 287 | default: | ||
| 288 | return IIO_VAL_INT_PLUS_NANO; | ||
| 289 | } | ||
| 290 | } | ||
| 291 | |||
| 292 | static int fxls8962af_update_config(struct fxls8962af_data *data, u8 reg, | ||
| 293 | u8 mask, u8 val) | ||
| 294 | { | ||
| 295 | int ret; | ||
| 296 | int is_active; | ||
| 297 | |||
| 298 | is_active = fxls8962af_is_active(data); | ||
| 299 | if (is_active) { | ||
| 300 | ret = fxls8962af_standby(data); | ||
| 301 | if (ret) | ||
| 302 | return ret; | ||
| 303 | } | ||
| 304 | |||
| 305 | ret = regmap_update_bits(data->regmap, reg, mask, val); | ||
| 306 | if (ret) | ||
| 307 | return ret; | ||
| 308 | |||
| 309 | if (is_active) { | ||
| 310 | ret = fxls8962af_active(data); | ||
| 311 | if (ret) | ||
| 312 | return ret; | ||
| 313 | } | ||
| 314 | |||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 318 | static int fxls8962af_set_full_scale(struct fxls8962af_data *data, u32 scale) | ||
| 319 | { | ||
| 320 | int i; | ||
| 321 | |||
| 322 | for (i = 0; i < ARRAY_SIZE(fxls8962af_scale_table); i++) | ||
| 323 | if (scale == fxls8962af_scale_table[i][1]) | ||
| 324 | break; | ||
| 325 | |||
| 326 | if (i == ARRAY_SIZE(fxls8962af_scale_table)) | ||
| 327 | return -EINVAL; | ||
| 328 | |||
| 329 | return fxls8962af_update_config(data, FXLS8962AF_SENS_CONFIG1, | ||
| 330 | FXLS8962AF_SC1_FSR_MASK, | ||
| 331 | FXLS8962AF_SC1_FSR_PREP(i)); | ||
| 332 | } | ||
| 333 | |||
| 334 | static unsigned int fxls8962af_read_full_scale(struct fxls8962af_data *data, | ||
| 335 | int *val) | ||
| 336 | { | ||
| 337 | int ret; | ||
| 338 | unsigned int reg; | ||
| 339 | u8 range_idx; | ||
| 340 | |||
| 341 | ret = regmap_read(data->regmap, FXLS8962AF_SENS_CONFIG1, ®); | ||
| 342 | if (ret) | ||
| 343 | return ret; | ||
| 344 | |||
| 345 | range_idx = FXLS8962AF_SC1_FSR_GET(reg); | ||
| 346 | |||
| 347 | *val = fxls8962af_scale_table[range_idx][1]; | ||
| 348 | |||
| 349 | return IIO_VAL_INT_PLUS_NANO; | ||
| 350 | } | ||
| 351 | |||
| 352 | static int fxls8962af_set_samp_freq(struct fxls8962af_data *data, u32 val, | ||
| 353 | u32 val2) | ||
| 354 | { | ||
| 355 | int i; | ||
| 356 | |||
| 357 | for (i = 0; i < ARRAY_SIZE(fxls8962af_samp_freq_table); i++) | ||
| 358 | if (val == fxls8962af_samp_freq_table[i][0] && | ||
| 359 | val2 == fxls8962af_samp_freq_table[i][1]) | ||
| 360 | break; | ||
| 361 | |||
| 362 | if (i == ARRAY_SIZE(fxls8962af_samp_freq_table)) | ||
| 363 | return -EINVAL; | ||
| 364 | |||
| 365 | return fxls8962af_update_config(data, FXLS8962AF_SENS_CONFIG3, | ||
| 366 | FXLS8962AF_SC3_WAKE_ODR_MASK, | ||
| 367 | FXLS8962AF_SC3_WAKE_ODR_PREP(i)); | ||
| 368 | } | ||
| 369 | |||
| 370 | static unsigned int fxls8962af_read_samp_freq(struct fxls8962af_data *data, | ||
| 371 | int *val, int *val2) | ||
| 372 | { | ||
| 373 | int ret; | ||
| 374 | unsigned int reg; | ||
| 375 | u8 range_idx; | ||
| 376 | |||
| 377 | ret = regmap_read(data->regmap, FXLS8962AF_SENS_CONFIG3, ®); | ||
| 378 | if (ret) | ||
| 379 | return ret; | ||
| 380 | |||
| 381 | range_idx = FXLS8962AF_SC3_WAKE_ODR_GET(reg); | ||
| 382 | |||
| 383 | *val = fxls8962af_samp_freq_table[range_idx][0]; | ||
| 384 | *val2 = fxls8962af_samp_freq_table[range_idx][1]; | ||
| 385 | |||
| 386 | return IIO_VAL_INT_PLUS_MICRO; | ||
| 387 | } | ||
| 388 | |||
| 389 | static int fxls8962af_read_raw(struct iio_dev *indio_dev, | ||
| 390 | struct iio_chan_spec const *chan, | ||
| 391 | int *val, int *val2, long mask) | ||
| 392 | { | ||
| 393 | struct fxls8962af_data *data = iio_priv(indio_dev); | ||
| 394 | |||
| 395 | switch (mask) { | ||
| 396 | case IIO_CHAN_INFO_RAW: | ||
| 397 | switch (chan->type) { | ||
| 398 | case IIO_TEMP: | ||
| 399 | case IIO_ACCEL: | ||
| 400 | return fxls8962af_get_out(data, chan, val); | ||
| 401 | default: | ||
| 402 | return -EINVAL; | ||
| 403 | } | ||
| 404 | case IIO_CHAN_INFO_OFFSET: | ||
| 405 | if (chan->type != IIO_TEMP) | ||
| 406 | return -EINVAL; | ||
| 407 | |||
| 408 | *val = FXLS8962AF_TEMP_CENTER_VAL; | ||
| 409 | return IIO_VAL_INT; | ||
| 410 | case IIO_CHAN_INFO_SCALE: | ||
| 411 | *val = 0; | ||
| 412 | return fxls8962af_read_full_scale(data, val2); | ||
| 413 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 414 | return fxls8962af_read_samp_freq(data, val, val2); | ||
| 415 | default: | ||
| 416 | return -EINVAL; | ||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 420 | static int fxls8962af_write_raw(struct iio_dev *indio_dev, | ||
| 421 | struct iio_chan_spec const *chan, | ||
| 422 | int val, int val2, long mask) | ||
| 423 | { | ||
| 424 | struct fxls8962af_data *data = iio_priv(indio_dev); | ||
| 425 | int ret; | ||
| 426 | |||
| 427 | switch (mask) { | ||
| 428 | case IIO_CHAN_INFO_SCALE: | ||
| 429 | if (val != 0) | ||
| 430 | return -EINVAL; | ||
| 431 | |||
| 432 | ret = iio_device_claim_direct_mode(indio_dev); | ||
| 433 | if (ret) | ||
| 434 | return ret; | ||
| 435 | |||
| 436 | ret = fxls8962af_set_full_scale(data, val2); | ||
| 437 | |||
| 438 | iio_device_release_direct_mode(indio_dev); | ||
| 439 | return ret; | ||
| 440 | case IIO_CHAN_INFO_SAMP_FREQ: | ||
| 441 | ret = iio_device_claim_direct_mode(indio_dev); | ||
| 442 | if (ret) | ||
| 443 | return ret; | ||
| 444 | |||
| 445 | ret = fxls8962af_set_samp_freq(data, val, val2); | ||
| 446 | |||
| 447 | iio_device_release_direct_mode(indio_dev); | ||
| 448 | return ret; | ||
| 449 | default: | ||
| 450 | return -EINVAL; | ||
| 451 | } | ||
| 452 | } | ||
| 453 | |||
| 454 | static int fxls8962af_set_watermark(struct iio_dev *indio_dev, unsigned val) | ||
| 455 | { | ||
| 456 | struct fxls8962af_data *data = iio_priv(indio_dev); | ||
| 457 | |||
| 458 | if (val > FXLS8962AF_FIFO_LENGTH) | ||
| 459 | val = FXLS8962AF_FIFO_LENGTH; | ||
| 460 | |||
| 461 | data->watermark = val; | ||
| 462 | |||
| 463 | return 0; | ||
| 464 | } | ||
| 465 | |||
| 466 | #define FXLS8962AF_CHANNEL(axis, reg, idx) { \ | ||
| 467 | .type = IIO_ACCEL, \ | ||
| 468 | .address = reg, \ | ||
| 469 | .modified = 1, \ | ||
| 470 | .channel2 = IIO_MOD_##axis, \ | ||
| 471 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
| 472 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ | ||
| 473 | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | ||
| 474 | .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE) | \ | ||
| 475 | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | ||
| 476 | .scan_index = idx, \ | ||
| 477 | .scan_type = { \ | ||
| 478 | .sign = 's', \ | ||
| 479 | .realbits = 12, \ | ||
| 480 | .storagebits = 16, \ | ||
| 481 | .shift = 4, \ | ||
| 482 | .endianness = IIO_BE, \ | ||
| 483 | }, \ | ||
| 484 | } | ||
| 485 | |||
| 486 | #define FXLS8962AF_TEMP_CHANNEL { \ | ||
| 487 | .type = IIO_TEMP, \ | ||
| 488 | .address = FXLS8962AF_TEMP_OUT, \ | ||
| 489 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | ||
| 490 | BIT(IIO_CHAN_INFO_OFFSET),\ | ||
| 491 | .scan_index = -1, \ | ||
| 492 | .scan_type = { \ | ||
| 493 | .realbits = 8, \ | ||
| 494 | .storagebits = 8, \ | ||
| 495 | }, \ | ||
| 496 | } | ||
| 497 | |||
| 498 | static const struct iio_chan_spec fxls8962af_channels[] = { | ||
| 499 | FXLS8962AF_CHANNEL(X, FXLS8962AF_OUT_X_LSB, fxls8962af_idx_x), | ||
| 500 | FXLS8962AF_CHANNEL(Y, FXLS8962AF_OUT_Y_LSB, fxls8962af_idx_y), | ||
| 501 | FXLS8962AF_CHANNEL(Z, FXLS8962AF_OUT_Z_LSB, fxls8962af_idx_z), | ||
| 502 | IIO_CHAN_SOFT_TIMESTAMP(fxls8962af_idx_ts), | ||
| 503 | FXLS8962AF_TEMP_CHANNEL, | ||
| 504 | }; | ||
| 505 | |||
| 506 | static const struct fxls8962af_chip_info fxls_chip_info_table[] = { | ||
| 507 | [fxls8962af] = { | ||
| 508 | .chip_id = FXLS8962AF_DEVICE_ID, | ||
| 509 | .name = "fxls8962af", | ||
| 510 | .channels = fxls8962af_channels, | ||
| 511 | .num_channels = ARRAY_SIZE(fxls8962af_channels), | ||
| 512 | }, | ||
| 513 | [fxls8964af] = { | ||
| 514 | .chip_id = FXLS8964AF_DEVICE_ID, | ||
| 515 | .name = "fxls8964af", | ||
| 516 | .channels = fxls8962af_channels, | ||
| 517 | .num_channels = ARRAY_SIZE(fxls8962af_channels), | ||
| 518 | }, | ||
| 519 | }; | ||
| 520 | |||
| 521 | static const struct iio_info fxls8962af_info = { | ||
| 522 | .read_raw = &fxls8962af_read_raw, | ||
| 523 | .write_raw = &fxls8962af_write_raw, | ||
| 524 | .write_raw_get_fmt = fxls8962af_write_raw_get_fmt, | ||
| 525 | .read_avail = fxls8962af_read_avail, | ||
| 526 | .hwfifo_set_watermark = fxls8962af_set_watermark, | ||
| 527 | }; | ||
| 528 | |||
| 529 | static int fxls8962af_reset(struct fxls8962af_data *data) | ||
| 530 | { | ||
| 531 | struct device *dev = regmap_get_device(data->regmap); | ||
| 532 | unsigned int reg; | ||
| 533 | int ret; | ||
| 534 | |||
| 535 | ret = regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG1, | ||
| 536 | FXLS8962AF_SENS_CONFIG1_RST, | ||
| 537 | FXLS8962AF_SENS_CONFIG1_RST); | ||
| 538 | if (ret) | ||
| 539 | return ret; | ||
| 540 | |||
| 541 | /* TBOOT1, TBOOT2, specifies we have to wait between 1 - 17.7ms */ | ||
| 542 | ret = regmap_read_poll_timeout(data->regmap, FXLS8962AF_INT_STATUS, reg, | ||
| 543 | (reg & FXLS8962AF_INT_STATUS_SRC_BOOT), | ||
| 544 | 1000, 18000); | ||
| 545 | if (ret == -ETIMEDOUT) | ||
| 546 | dev_err(dev, "reset timeout, int_status = 0x%x\n", reg); | ||
| 547 | |||
| 548 | return ret; | ||
| 549 | } | ||
| 550 | |||
| 551 | static int __fxls8962af_fifo_set_mode(struct fxls8962af_data *data, bool onoff) | ||
| 552 | { | ||
| 553 | int ret; | ||
| 554 | |||
| 555 | /* Enable watermark at max fifo size */ | ||
| 556 | ret = regmap_update_bits(data->regmap, FXLS8962AF_BUF_CONFIG2, | ||
| 557 | FXLS8962AF_BUF_CONFIG2_BUF_WMRK, | ||
| 558 | data->watermark); | ||
| 559 | if (ret) | ||
| 560 | return ret; | ||
| 561 | |||
| 562 | return regmap_update_bits(data->regmap, FXLS8962AF_BUF_CONFIG1, | ||
| 563 | FXLS8962AF_BC1_BUF_MODE_MASK, | ||
| 564 | FXLS8962AF_BC1_BUF_MODE_PREP(onoff)); | ||
| 565 | } | ||
| 566 | |||
| 567 | static int fxls8962af_buffer_preenable(struct iio_dev *indio_dev) | ||
| 568 | { | ||
| 569 | return fxls8962af_power_on(iio_priv(indio_dev)); | ||
| 570 | } | ||
| 571 | |||
| 572 | static int fxls8962af_buffer_postenable(struct iio_dev *indio_dev) | ||
| 573 | { | ||
| 574 | struct fxls8962af_data *data = iio_priv(indio_dev); | ||
| 575 | int ret; | ||
| 576 | |||
| 577 | fxls8962af_standby(data); | ||
| 578 | |||
| 579 | /* Enable buffer interrupt */ | ||
| 580 | ret = regmap_update_bits(data->regmap, FXLS8962AF_INT_EN, | ||
| 581 | FXLS8962AF_INT_EN_BUF_EN, | ||
| 582 | FXLS8962AF_INT_EN_BUF_EN); | ||
| 583 | if (ret) | ||
| 584 | return ret; | ||
| 585 | |||
| 586 | ret = __fxls8962af_fifo_set_mode(data, true); | ||
| 587 | |||
| 588 | fxls8962af_active(data); | ||
| 589 | |||
| 590 | return ret; | ||
| 591 | } | ||
| 592 | |||
| 593 | static int fxls8962af_buffer_predisable(struct iio_dev *indio_dev) | ||
| 594 | { | ||
| 595 | struct fxls8962af_data *data = iio_priv(indio_dev); | ||
| 596 | int ret; | ||
| 597 | |||
| 598 | fxls8962af_standby(data); | ||
| 599 | |||
| 600 | /* Disable buffer interrupt */ | ||
| 601 | ret = regmap_update_bits(data->regmap, FXLS8962AF_INT_EN, | ||
| 602 | FXLS8962AF_INT_EN_BUF_EN, 0); | ||
| 603 | if (ret) | ||
| 604 | return ret; | ||
| 605 | |||
| 606 | ret = __fxls8962af_fifo_set_mode(data, false); | ||
| 607 | |||
| 608 | fxls8962af_active(data); | ||
| 609 | |||
| 610 | return ret; | ||
| 611 | } | ||
| 612 | |||
| 613 | static int fxls8962af_buffer_postdisable(struct iio_dev *indio_dev) | ||
| 614 | { | ||
| 615 | struct fxls8962af_data *data = iio_priv(indio_dev); | ||
| 616 | |||
| 617 | return fxls8962af_power_off(data); | ||
| 618 | } | ||
| 619 | |||
| 620 | static const struct iio_buffer_setup_ops fxls8962af_buffer_ops = { | ||
| 621 | .preenable = fxls8962af_buffer_preenable, | ||
| 622 | .postenable = fxls8962af_buffer_postenable, | ||
| 623 | .predisable = fxls8962af_buffer_predisable, | ||
| 624 | .postdisable = fxls8962af_buffer_postdisable, | ||
| 625 | }; | ||
| 626 | |||
| 627 | static int fxls8962af_i2c_raw_read_errata3(struct fxls8962af_data *data, | ||
| 628 | u16 *buffer, int samples, | ||
| 629 | int sample_length) | ||
| 630 | { | ||
| 631 | int i, ret; | ||
| 632 | |||
| 633 | for (i = 0; i < samples; i++) { | ||
| 634 | ret = regmap_raw_read(data->regmap, FXLS8962AF_BUF_X_LSB, | ||
| 635 | &buffer[i * 3], sample_length); | ||
| 636 | if (ret) | ||
| 637 | return ret; | ||
| 638 | } | ||
| 639 | |||
| 640 | return ret; | ||
| 641 | } | ||
| 642 | |||
| 643 | static int fxls8962af_fifo_transfer(struct fxls8962af_data *data, | ||
| 644 | u16 *buffer, int samples) | ||
| 645 | { | ||
| 646 | struct device *dev = regmap_get_device(data->regmap); | ||
| 647 | int sample_length = 3 * sizeof(*buffer); | ||
| 648 | int total_length = samples * sample_length; | ||
| 649 | int ret; | ||
| 650 | |||
| 651 | if (i2c_verify_client(dev)) | ||
| 652 | /* | ||
| 653 | * Due to errata bug: | ||
| 654 | * E3: FIFO burst read operation error using I2C interface | ||
| 655 | * We have to avoid burst reads on I2C.. | ||
| 656 | */ | ||
| 657 | ret = fxls8962af_i2c_raw_read_errata3(data, buffer, samples, | ||
| 658 | sample_length); | ||
| 659 | else | ||
| 660 | ret = regmap_raw_read(data->regmap, FXLS8962AF_BUF_X_LSB, buffer, | ||
| 661 | total_length); | ||
| 662 | |||
| 663 | if (ret) | ||
| 664 | dev_err(dev, "Error transferring data from fifo: %d\n", ret); | ||
| 665 | |||
| 666 | return ret; | ||
| 667 | } | ||
| 668 | |||
| 669 | static int fxls8962af_fifo_flush(struct iio_dev *indio_dev) | ||
| 670 | { | ||
| 671 | struct fxls8962af_data *data = iio_priv(indio_dev); | ||
| 672 | struct device *dev = regmap_get_device(data->regmap); | ||
| 673 | u16 buffer[FXLS8962AF_FIFO_LENGTH * 3]; | ||
| 674 | uint64_t sample_period; | ||
| 675 | unsigned int reg; | ||
| 676 | int64_t tstamp; | ||
| 677 | int ret, i; | ||
| 678 | u8 count; | ||
| 679 | |||
| 680 | ret = regmap_read(data->regmap, FXLS8962AF_BUF_STATUS, ®); | ||
| 681 | if (ret) | ||
| 682 | return ret; | ||
| 683 | |||
| 684 | if (reg & FXLS8962AF_BUF_STATUS_BUF_OVF) { | ||
| 685 | dev_err(dev, "Buffer overflow"); | ||
| 686 | return -EOVERFLOW; | ||
| 687 | } | ||
| 688 | |||
| 689 | count = reg & FXLS8962AF_BUF_STATUS_BUF_CNT; | ||
| 690 | if (!count) | ||
| 691 | return 0; | ||
| 692 | |||
| 693 | data->old_timestamp = data->timestamp; | ||
| 694 | data->timestamp = iio_get_time_ns(indio_dev); | ||
| 695 | |||
| 696 | /* | ||
| 697 | * Approximate timestamps for each of the sample based on the sampling, | ||
| 698 | * frequency, timestamp for last sample and number of samples. | ||
| 699 | */ | ||
| 700 | sample_period = (data->timestamp - data->old_timestamp); | ||
| 701 | do_div(sample_period, count); | ||
| 702 | tstamp = data->timestamp - (count - 1) * sample_period; | ||
| 703 | |||
| 704 | ret = fxls8962af_fifo_transfer(data, buffer, count); | ||
| 705 | if (ret) | ||
| 706 | return ret; | ||
| 707 | |||
| 708 | /* Demux hw FIFO into kfifo. */ | ||
| 709 | for (i = 0; i < count; i++) { | ||
| 710 | int j, bit; | ||
| 711 | |||
| 712 | j = 0; | ||
| 713 | for_each_set_bit(bit, indio_dev->active_scan_mask, | ||
| 714 | indio_dev->masklength) { | ||
| 715 | memcpy(&data->scan.channels[j++], &buffer[i * 3 + bit], | ||
| 716 | sizeof(data->scan.channels[0])); | ||
| 717 | } | ||
| 718 | |||
| 719 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, | ||
| 720 | tstamp); | ||
| 721 | |||
| 722 | tstamp += sample_period; | ||
| 723 | } | ||
| 724 | |||
| 725 | return count; | ||
| 726 | } | ||
| 727 | |||
| 728 | static irqreturn_t fxls8962af_interrupt(int irq, void *p) | ||
| 729 | { | ||
| 730 | struct iio_dev *indio_dev = p; | ||
| 731 | struct fxls8962af_data *data = iio_priv(indio_dev); | ||
| 732 | unsigned int reg; | ||
| 733 | int ret; | ||
| 734 | |||
| 735 | ret = regmap_read(data->regmap, FXLS8962AF_INT_STATUS, ®); | ||
| 736 | if (ret) | ||
| 737 | return IRQ_NONE; | ||
| 738 | |||
| 739 | if (reg & FXLS8962AF_INT_STATUS_SRC_BUF) { | ||
| 740 | ret = fxls8962af_fifo_flush(indio_dev); | ||
| 741 | if (ret) | ||
| 742 | return IRQ_NONE; | ||
| 743 | |||
| 744 | return IRQ_HANDLED; | ||
| 745 | } | ||
| 746 | |||
| 747 | return IRQ_NONE; | ||
| 748 | } | ||
| 749 | |||
| 750 | static void fxls8962af_regulator_disable(void *data_ptr) | ||
| 751 | { | ||
| 752 | struct fxls8962af_data *data = data_ptr; | ||
| 753 | |||
| 754 | regulator_disable(data->vdd_reg); | ||
| 755 | } | ||
| 756 | |||
| 757 | static void fxls8962af_pm_disable(void *dev_ptr) | ||
| 758 | { | ||
| 759 | struct device *dev = dev_ptr; | ||
| 760 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
| 761 | |||
| 762 | pm_runtime_disable(dev); | ||
| 763 | pm_runtime_set_suspended(dev); | ||
| 764 | pm_runtime_put_noidle(dev); | ||
| 765 | |||
| 766 | fxls8962af_standby(iio_priv(indio_dev)); | ||
| 767 | } | ||
| 768 | |||
| 769 | static void fxls8962af_get_irq(struct device_node *of_node, | ||
| 770 | enum fxls8962af_int_pin *pin) | ||
| 771 | { | ||
| 772 | int irq; | ||
| 773 | |||
| 774 | irq = of_irq_get_byname(of_node, "INT2"); | ||
| 775 | if (irq > 0) { | ||
| 776 | *pin = FXLS8962AF_PIN_INT2; | ||
| 777 | return; | ||
| 778 | } | ||
| 779 | |||
| 780 | *pin = FXLS8962AF_PIN_INT1; | ||
| 781 | } | ||
| 782 | |||
| 783 | static int fxls8962af_irq_setup(struct iio_dev *indio_dev, int irq) | ||
| 784 | { | ||
| 785 | struct fxls8962af_data *data = iio_priv(indio_dev); | ||
| 786 | struct device *dev = regmap_get_device(data->regmap); | ||
| 787 | unsigned long irq_type; | ||
| 788 | bool irq_active_high; | ||
| 789 | enum fxls8962af_int_pin int_pin; | ||
| 790 | u8 int_pin_sel; | ||
| 791 | int ret; | ||
| 792 | |||
| 793 | fxls8962af_get_irq(dev->of_node, &int_pin); | ||
| 794 | switch (int_pin) { | ||
| 795 | case FXLS8962AF_PIN_INT1: | ||
| 796 | int_pin_sel = FXLS8962AF_INT_PIN_SEL_INT1; | ||
| 797 | break; | ||
| 798 | case FXLS8962AF_PIN_INT2: | ||
| 799 | int_pin_sel = FXLS8962AF_INT_PIN_SEL_INT2; | ||
| 800 | break; | ||
| 801 | default: | ||
| 802 | dev_err(dev, "unsupported int pin selected\n"); | ||
| 803 | return -EINVAL; | ||
| 804 | } | ||
| 805 | |||
| 806 | ret = regmap_update_bits(data->regmap, FXLS8962AF_INT_PIN_SEL, | ||
| 807 | FXLS8962AF_INT_PIN_SEL_MASK, int_pin_sel); | ||
| 808 | if (ret) | ||
| 809 | return ret; | ||
| 810 | |||
| 811 | irq_type = irqd_get_trigger_type(irq_get_irq_data(irq)); | ||
| 812 | |||
| 813 | switch (irq_type) { | ||
| 814 | case IRQF_TRIGGER_HIGH: | ||
| 815 | case IRQF_TRIGGER_RISING: | ||
| 816 | irq_active_high = true; | ||
| 817 | break; | ||
| 818 | case IRQF_TRIGGER_LOW: | ||
| 819 | case IRQF_TRIGGER_FALLING: | ||
| 820 | irq_active_high = false; | ||
| 821 | break; | ||
| 822 | default: | ||
| 823 | dev_info(dev, "mode %lx unsupported\n", irq_type); | ||
| 824 | return -EINVAL; | ||
| 825 | } | ||
| 826 | |||
| 827 | ret = regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG4, | ||
| 828 | FXLS8962AF_SC4_INT_POL_MASK, | ||
| 829 | FXLS8962AF_SC4_INT_POL_PREP(irq_active_high)); | ||
| 830 | if (ret) | ||
| 831 | return ret; | ||
| 832 | |||
| 833 | if (device_property_read_bool(dev, "drive-open-drain")) { | ||
| 834 | ret = regmap_update_bits(data->regmap, FXLS8962AF_SENS_CONFIG4, | ||
| 835 | FXLS8962AF_SC4_INT_PP_OD_MASK, | ||
| 836 | FXLS8962AF_SC4_INT_PP_OD_PREP(1)); | ||
| 837 | if (ret) | ||
| 838 | return ret; | ||
| 839 | |||
| 840 | irq_type |= IRQF_SHARED; | ||
| 841 | } | ||
| 842 | |||
| 843 | return devm_request_threaded_irq(dev, | ||
| 844 | irq, | ||
| 845 | NULL, fxls8962af_interrupt, | ||
| 846 | irq_type | IRQF_ONESHOT, | ||
| 847 | indio_dev->name, indio_dev); | ||
| 848 | } | ||
| 849 | |||
| 850 | int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq) | ||
| 851 | { | ||
| 852 | struct fxls8962af_data *data; | ||
| 853 | struct iio_dev *indio_dev; | ||
| 854 | unsigned int reg; | ||
| 855 | int ret, i; | ||
| 856 | |||
| 857 | indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); | ||
| 858 | if (!indio_dev) | ||
| 859 | return -ENOMEM; | ||
| 860 | |||
| 861 | data = iio_priv(indio_dev); | ||
| 862 | dev_set_drvdata(dev, indio_dev); | ||
| 863 | data->regmap = regmap; | ||
| 864 | |||
| 865 | ret = iio_read_mount_matrix(dev, &data->orientation); | ||
| 866 | if (ret) | ||
| 867 | return ret; | ||
| 868 | |||
| 869 | data->vdd_reg = devm_regulator_get(dev, "vdd"); | ||
| 870 | if (IS_ERR(data->vdd_reg)) | ||
| 871 | return dev_err_probe(dev, PTR_ERR(data->vdd_reg), | ||
| 872 | "Failed to get vdd regulator\n"); | ||
| 873 | |||
| 874 | ret = regulator_enable(data->vdd_reg); | ||
| 875 | if (ret) { | ||
| 876 | dev_err(dev, "Failed to enable vdd regulator: %d\n", ret); | ||
| 877 | return ret; | ||
| 878 | } | ||
| 879 | |||
| 880 | ret = devm_add_action_or_reset(dev, fxls8962af_regulator_disable, data); | ||
| 881 | if (ret) | ||
| 882 | return ret; | ||
| 883 | |||
| 884 | ret = regmap_read(data->regmap, FXLS8962AF_WHO_AM_I, ®); | ||
| 885 | if (ret) | ||
| 886 | return ret; | ||
| 887 | |||
| 888 | for (i = 0; i < ARRAY_SIZE(fxls_chip_info_table); i++) { | ||
| 889 | if (fxls_chip_info_table[i].chip_id == reg) { | ||
| 890 | data->chip_info = &fxls_chip_info_table[i]; | ||
| 891 | break; | ||
| 892 | } | ||
| 893 | } | ||
| 894 | if (i == ARRAY_SIZE(fxls_chip_info_table)) { | ||
| 895 | dev_err(dev, "failed to match device in table\n"); | ||
| 896 | return -ENXIO; | ||
| 897 | } | ||
| 898 | |||
| 899 | indio_dev->channels = data->chip_info->channels; | ||
| 900 | indio_dev->num_channels = data->chip_info->num_channels; | ||
| 901 | indio_dev->name = data->chip_info->name; | ||
| 902 | indio_dev->info = &fxls8962af_info; | ||
| 903 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
| 904 | |||
| 905 | ret = fxls8962af_reset(data); | ||
| 906 | if (ret) | ||
| 907 | return ret; | ||
| 908 | |||
| 909 | if (irq) { | ||
| 910 | ret = fxls8962af_irq_setup(indio_dev, irq); | ||
| 911 | if (ret) | ||
| 912 | return ret; | ||
| 913 | |||
| 914 | ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, | ||
| 915 | INDIO_BUFFER_SOFTWARE, | ||
| 916 | &fxls8962af_buffer_ops); | ||
| 917 | if (ret) | ||
| 918 | return ret; | ||
| 919 | } | ||
| 920 | |||
| 921 | ret = pm_runtime_set_active(dev); | ||
| 922 | if (ret) | ||
| 923 | return ret; | ||
| 924 | |||
| 925 | pm_runtime_enable(dev); | ||
| 926 | pm_runtime_set_autosuspend_delay(dev, FXLS8962AF_AUTO_SUSPEND_DELAY_MS); | ||
| 927 | pm_runtime_use_autosuspend(dev); | ||
| 928 | |||
| 929 | ret = devm_add_action_or_reset(dev, fxls8962af_pm_disable, dev); | ||
| 930 | if (ret) | ||
| 931 | return ret; | ||
| 932 | |||
| 933 | return devm_iio_device_register(dev, indio_dev); | ||
| 934 | } | ||
| 935 | EXPORT_SYMBOL_GPL(fxls8962af_core_probe); | ||
| 936 | |||
| 937 | static int __maybe_unused fxls8962af_runtime_suspend(struct device *dev) | ||
| 938 | { | ||
| 939 | struct fxls8962af_data *data = iio_priv(dev_get_drvdata(dev)); | ||
| 940 | int ret; | ||
| 941 | |||
| 942 | ret = fxls8962af_standby(data); | ||
| 943 | if (ret) { | ||
| 944 | dev_err(dev, "powering off device failed\n"); | ||
| 945 | return ret; | ||
| 946 | } | ||
| 947 | |||
| 948 | return 0; | ||
| 949 | } | ||
| 950 | |||
| 951 | static int __maybe_unused fxls8962af_runtime_resume(struct device *dev) | ||
| 952 | { | ||
| 953 | struct fxls8962af_data *data = iio_priv(dev_get_drvdata(dev)); | ||
| 954 | |||
| 955 | return fxls8962af_active(data); | ||
| 956 | } | ||
| 957 | |||
| 958 | const struct dev_pm_ops fxls8962af_pm_ops = { | ||
| 959 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | ||
| 960 | pm_runtime_force_resume) | ||
| 961 | SET_RUNTIME_PM_OPS(fxls8962af_runtime_suspend, | ||
| 962 | fxls8962af_runtime_resume, NULL) | ||
| 963 | }; | ||
| 964 | EXPORT_SYMBOL_GPL(fxls8962af_pm_ops); | ||
| 965 | |||
| 966 | MODULE_AUTHOR("Sean Nyekjaer <sean@geanix.com>"); | ||
| 967 | MODULE_DESCRIPTION("NXP FXLS8962AF/FXLS8964AF accelerometer driver"); | ||
| 968 | MODULE_LICENSE("GPL v2"); | ||
| @@ -0,0 +1,57 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * NXP FXLS8962AF/FXLS8964AF Accelerometer I2C Driver | ||
| 4 | * | ||
| 5 | * Copyright 2021 Connected Cars A/S | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/dev_printk.h> | ||
| 9 | #include <linux/err.h> | ||
| 10 | #include <linux/i2c.h> | ||
| 11 | #include <linux/mod_devicetable.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/regmap.h> | ||
| 14 | |||
| 15 | #include "fxls8962af.h" | ||
| 16 | |||
| 17 | static int fxls8962af_probe(struct i2c_client *client) | ||
| 18 | { | ||
| 19 | struct regmap *regmap; | ||
| 20 | |||
| 21 | regmap = devm_regmap_init_i2c(client, &fxls8962af_regmap_conf); | ||
| 22 | if (IS_ERR(regmap)) { | ||
| 23 | dev_err(&client->dev, "Failed to initialize i2c regmap\n"); | ||
| 24 | return PTR_ERR(regmap); | ||
| 25 | } | ||
| 26 | |||
| 27 | return fxls8962af_core_probe(&client->dev, regmap, client->irq); | ||
| 28 | } | ||
| 29 | |||
| 30 | static const struct i2c_device_id fxls8962af_id[] = { | ||
| 31 | { "fxls8962af", fxls8962af }, | ||
| 32 | { "fxls8964af", fxls8964af }, | ||
| 33 | {} | ||
| 34 | }; | ||
| 35 | MODULE_DEVICE_TABLE(i2c, fxls8962af_id); | ||
| 36 | |||
| 37 | static const struct of_device_id fxls8962af_of_match[] = { | ||
| 38 | { .compatible = "nxp,fxls8962af" }, | ||
| 39 | { .compatible = "nxp,fxls8964af" }, | ||
| 40 | {} | ||
| 41 | }; | ||
| 42 | MODULE_DEVICE_TABLE(of, fxls8962af_of_match); | ||
| 43 | |||
| 44 | static struct i2c_driver fxls8962af_driver = { | ||
| 45 | .driver = { | ||
| 46 | .name = "fxls8962af_i2c", | ||
| 47 | .of_match_table = fxls8962af_of_match, | ||
| 48 | .pm = &fxls8962af_pm_ops, | ||
| 49 | }, | ||
| 50 | .probe_new = fxls8962af_probe, | ||
| 51 | .id_table = fxls8962af_id, | ||
| 52 | }; | ||
| 53 | module_i2c_driver(fxls8962af_driver); | ||
| 54 | |||
| 55 | MODULE_AUTHOR("Sean Nyekjaer <sean@geanix.com>"); | ||
| 56 | MODULE_DESCRIPTION("NXP FXLS8962AF/FXLS8964AF accelerometer i2c driver"); | ||
| 57 | MODULE_LICENSE("GPL v2"); | ||
| @@ -0,0 +1,57 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * NXP FXLS8962AF/FXLS8964AF Accelerometer SPI Driver | ||
| 4 | * | ||
| 5 | * Copyright 2021 Connected Cars A/S | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/dev_printk.h> | ||
| 9 | #include <linux/err.h> | ||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/mod_devicetable.h> | ||
| 12 | #include <linux/spi/spi.h> | ||
| 13 | #include <linux/regmap.h> | ||
| 14 | |||
| 15 | #include "fxls8962af.h" | ||
| 16 | |||
| 17 | static int fxls8962af_probe(struct spi_device *spi) | ||
| 18 | { | ||
| 19 | struct regmap *regmap; | ||
| 20 | |||
| 21 | regmap = devm_regmap_init_spi(spi, &fxls8962af_regmap_conf); | ||
| 22 | if (IS_ERR(regmap)) { | ||
| 23 | dev_err(&spi->dev, "Failed to initialize spi regmap\n"); | ||
| 24 | return PTR_ERR(regmap); | ||
| 25 | } | ||
| 26 | |||
| 27 | return fxls8962af_core_probe(&spi->dev, regmap, spi->irq); | ||
| 28 | } | ||
| 29 | |||
| 30 | static const struct of_device_id fxls8962af_spi_of_match[] = { | ||
| 31 | { .compatible = "nxp,fxls8962af" }, | ||
| 32 | { .compatible = "nxp,fxls8964af" }, | ||
| 33 | {} | ||
| 34 | }; | ||
| 35 | MODULE_DEVICE_TABLE(of, fxls8962af_spi_of_match); | ||
| 36 | |||
| 37 | static const struct spi_device_id fxls8962af_spi_id_table[] = { | ||
| 38 | { "fxls8962af", fxls8962af }, | ||
| 39 | { "fxls8964af", fxls8964af }, | ||
| 40 | {} | ||
| 41 | }; | ||
| 42 | MODULE_DEVICE_TABLE(spi, fxls8962af_spi_id_table); | ||
| 43 | |||
| 44 | static struct spi_driver fxls8962af_driver = { | ||
| 45 | .driver = { | ||
| 46 | .name = "fxls8962af_spi", | ||
| 47 | .pm = &fxls8962af_pm_ops, | ||
| 48 | .of_match_table = fxls8962af_spi_of_match, | ||
| 49 | }, | ||
| 50 | .probe = fxls8962af_probe, | ||
| 51 | .id_table = fxls8962af_spi_id_table, | ||
| 52 | }; | ||
| 53 | module_spi_driver(fxls8962af_driver); | ||
| 54 | |||
| 55 | MODULE_AUTHOR("Sean Nyekjaer <sean@geanix.com>"); | ||
| 56 | MODULE_DESCRIPTION("NXP FXLS8962AF/FXLS8964AF accelerometer spi driver"); | ||
| 57 | MODULE_LICENSE("GPL v2"); | ||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * Copyright 2021 Connected Cars A/S | ||
| 4 | */ | ||
| 5 | #ifndef _FXLS8962AF_H_ | ||
| 6 | #define _FXLS8962AF_H_ | ||
| 7 | |||
| 8 | struct regmap; | ||
| 9 | struct device; | ||
| 10 | |||
| 11 | enum { | ||
| 12 | fxls8962af, | ||
| 13 | fxls8964af, | ||
| 14 | }; | ||
| 15 | |||
| 16 | int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq); | ||
| 17 | int fxls8962af_core_remove(struct device *dev); | ||
| 18 | |||
| 19 | extern const struct dev_pm_ops fxls8962af_pm_ops; | ||
| 20 | extern const struct regmap_config fxls8962af_regmap_conf; | ||
| 21 | |||
| 22 | #endif /* _FXLS8962AF_H_ */ | ||
| @@ -6,13 +6,10 @@ · 5 unmodified lines | |||
| 6 | #include <linux/device.h> | 6 | #include <linux/device.h> |
| 7 | #include <linux/platform_device.h> | 7 | #include <linux/platform_device.h> |
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/interrupt.h> | 9 | #include <linux/mod_devicetable.h> |
| 10 | #include <linux/irq.h> | ||
| 11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
| 12 | #include <linux/delay.h> | ||
| 13 | #include <linux/hid-sensor-hub.h> | 11 | #include <linux/hid-sensor-hub.h> |
| 14 | #include <linux/iio/iio.h> | 12 | #include <linux/iio/iio.h> |
| 15 | #include <linux/iio/sysfs.h> | ||
| 16 | #include <linux/iio/buffer.h> | 13 | #include <linux/iio/buffer.h> |
| 17 | #include "../common/hid-sensors/hid-sensor-trigger.h" | 14 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 18 | 15 | ||
| @@ -28,8 +25,11 @@ struct accel_3d_state { · 9 unmodified lines | |||
| 28 | struct hid_sensor_hub_callbacks callbacks; | 25 | struct hid_sensor_hub_callbacks callbacks; |
| 29 | struct hid_sensor_common common_attributes; | 26 | struct hid_sensor_common common_attributes; |
| 30 | struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX]; | 27 | struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX]; |
| 31 | /* Reserve for 3 channels + padding + timestamp */ | 28 | /* Ensure timestamp is naturally aligned */ |
| 32 | u32 accel_val[ACCEL_3D_CHANNEL_MAX + 3]; | 29 | struct { |
| 30 | u32 accel_val[3]; | ||
| 31 | s64 timestamp __aligned(8); | ||
| 32 | } scan; | ||
| 33 | int scale_pre_decml; | 33 | int scale_pre_decml; |
| 34 | int scale_post_decml; | 34 | int scale_post_decml; |
| 35 | int scale_precision; | 35 | int scale_precision; |
| @@ -245,8 +245,8 @@ static int accel_3d_proc_event(struct hid_sensor_hub_device *hsdev, · 209 unmodified lines | |||
| 245 | accel_state->timestamp = iio_get_time_ns(indio_dev); | 245 | accel_state->timestamp = iio_get_time_ns(indio_dev); |
| 246 | 246 | ||
| 247 | hid_sensor_push_data(indio_dev, | 247 | hid_sensor_push_data(indio_dev, |
| 248 | accel_state->accel_val, | 248 | &accel_state->scan, |
| 249 | sizeof(accel_state->accel_val), | 249 | sizeof(accel_state->scan), |
| 250 | accel_state->timestamp); | 250 | accel_state->timestamp); |
| 251 | 251 | ||
| 252 | accel_state->timestamp = 0; | 252 | accel_state->timestamp = 0; |
| @@ -271,7 +271,7 @@ static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev, · 18 unmodified lines | |||
| 271 | case HID_USAGE_SENSOR_ACCEL_Y_AXIS: | 271 | case HID_USAGE_SENSOR_ACCEL_Y_AXIS: |
| 272 | case HID_USAGE_SENSOR_ACCEL_Z_AXIS: | 272 | case HID_USAGE_SENSOR_ACCEL_Z_AXIS: |
| 273 | offset = usage_id - HID_USAGE_SENSOR_ACCEL_X_AXIS; | 273 | offset = usage_id - HID_USAGE_SENSOR_ACCEL_X_AXIS; |
| 274 | accel_state->accel_val[CHANNEL_SCAN_INDEX_X + offset] = | 274 | accel_state->scan.accel_val[CHANNEL_SCAN_INDEX_X + offset] = |
| 275 | *(u32 *)raw_data; | 275 | *(u32 *)raw_data; |
| 276 | ret = 0; | 276 | ret = 0; |
| 277 | break; | 277 | break; |
| @@ -462,3 +462,4 @@ module_platform_driver(hid_accel_3d_platform_driver); · 184 unmodified lines | |||
| 462 | MODULE_DESCRIPTION("HID Sensor Accel 3D"); | 462 | MODULE_DESCRIPTION("HID Sensor Accel 3D"); |
| 463 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); | 463 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); |
| 464 | MODULE_LICENSE("GPL"); | 464 | MODULE_LICENSE("GPL"); |
| 465 | MODULE_IMPORT_NS(IIO_HID); | ||
| @@ -51,13 +51,15 @@ · 50 unmodified lines | |||
| 51 | #define KXTF9_REG_TILT_POS_CUR 0x10 | 51 | #define KXTF9_REG_TILT_POS_CUR 0x10 |
| 52 | #define KXTF9_REG_TILT_POS_PREV 0x11 | 52 | #define KXTF9_REG_TILT_POS_PREV 0x11 |
| 53 | #define KXTF9_REG_INT_SRC1 0x15 | 53 | #define KXTF9_REG_INT_SRC1 0x15 |
| 54 | #define KXCJK1013_REG_INT_SRC1 0x16 /* compatible, but called INT_SRC2 in KXTF9 ds */ | 54 | #define KXTF9_REG_INT_SRC2 0x16 |
| 55 | #define KXCJK1013_REG_INT_SRC1 0x16 | ||
| 55 | #define KXCJK1013_REG_INT_SRC2 0x17 | 56 | #define KXCJK1013_REG_INT_SRC2 0x17 |
| 56 | #define KXCJK1013_REG_STATUS_REG 0x18 | 57 | #define KXCJK1013_REG_STATUS_REG 0x18 |
| 57 | #define KXCJK1013_REG_INT_REL 0x1A | 58 | #define KXCJK1013_REG_INT_REL 0x1A |
| 58 | #define KXCJK1013_REG_CTRL1 0x1B | 59 | #define KXCJK1013_REG_CTRL1 0x1B |
| 59 | #define KXTF9_REG_CTRL2 0x1C | 60 | #define KXTF9_REG_CTRL2 0x1C |
| 60 | #define KXCJK1013_REG_CTRL2 0x1D /* mostly compatible, CTRL_REG3 in KTXF9 ds */ | 61 | #define KXTF9_REG_CTRL3 0x1D |
| 62 | #define KXCJK1013_REG_CTRL2 0x1D | ||
| 61 | #define KXCJK1013_REG_INT_CTRL1 0x1E | 63 | #define KXCJK1013_REG_INT_CTRL1 0x1E |
| 62 | #define KXCJK1013_REG_INT_CTRL2 0x1F | 64 | #define KXCJK1013_REG_INT_CTRL2 0x1F |
| 63 | #define KXTF9_REG_INT_CTRL3 0x20 | 65 | #define KXTF9_REG_INT_CTRL3 0x20 |
| @@ -77,6 +79,45 @@ · 13 unmodified lines | |||
| 77 | #define KXTF9_REG_HYST_SET 0x5F | 79 | #define KXTF9_REG_HYST_SET 0x5F |
| 78 | #define KXCJK1013_REG_WAKE_THRES 0x6A | 80 | #define KXCJK1013_REG_WAKE_THRES 0x6A |
| 79 | 81 | ||
| 82 | /* Everything up to 0x11 is equal to KXCJK1013/KXTF9 above */ | ||
| 83 | #define KX023_REG_INS1 0x12 | ||
| 84 | #define KX023_REG_INS2 0x13 | ||
| 85 | #define KX023_REG_INS3 0x14 | ||
| 86 | #define KX023_REG_STAT 0x15 | ||
| 87 | #define KX023_REG_INT_REL 0x17 | ||
| 88 | #define KX023_REG_CNTL1 0x18 | ||
| 89 | #define KX023_REG_CNTL2 0x19 | ||
| 90 | #define KX023_REG_CNTL3 0x1A | ||
| 91 | #define KX023_REG_ODCNTL 0x1B | ||
| 92 | #define KX023_REG_INC1 0x1C | ||
| 93 | #define KX023_REG_INC2 0x1D | ||
| 94 | #define KX023_REG_INC3 0x1E | ||
| 95 | #define KX023_REG_INC4 0x1F | ||
| 96 | #define KX023_REG_INC5 0x20 | ||
| 97 | #define KX023_REG_INC6 0x21 | ||
| 98 | #define KX023_REG_TILT_TIMER 0x22 | ||
| 99 | #define KX023_REG_WUFC 0x23 | ||
| 100 | #define KX023_REG_TDTRC 0x24 | ||
| 101 | #define KX023_REG_TDTC 0x25 | ||
| 102 | #define KX023_REG_TTH 0x26 | ||
| 103 | #define KX023_REG_TTL 0x27 | ||
| 104 | #define KX023_REG_FTD 0x28 | ||
| 105 | #define KX023_REG_STD 0x29 | ||
| 106 | #define KX023_REG_TLT 0x2A | ||
| 107 | #define KX023_REG_TWS 0x2B | ||
| 108 | #define KX023_REG_ATH 0x30 | ||
| 109 | #define KX023_REG_TILT_ANGLE_LL 0x32 | ||
| 110 | #define KX023_REG_TILT_ANGLE_HL 0x33 | ||
| 111 | #define KX023_REG_HYST_SET 0x34 | ||
| 112 | #define KX023_REG_LP_CNTL 0x35 | ||
| 113 | #define KX023_REG_BUF_CNTL1 0x3A | ||
| 114 | #define KX023_REG_BUF_CNTL2 0x3B | ||
| 115 | #define KX023_REG_BUF_STATUS_1 0x3C | ||
| 116 | #define KX023_REG_BUF_STATUS_2 0x3D | ||
| 117 | #define KX023_REG_BUF_CLEAR 0x3E | ||
| 118 | #define KX023_REG_BUF_READ 0x3F | ||
| 119 | #define KX023_REG_SELF_TEST 0x60 | ||
| 120 | |||
| 80 | #define KXCJK1013_REG_CTRL1_BIT_PC1 BIT(7) | 121 | #define KXCJK1013_REG_CTRL1_BIT_PC1 BIT(7) |
| 81 | #define KXCJK1013_REG_CTRL1_BIT_RES BIT(6) | 122 | #define KXCJK1013_REG_CTRL1_BIT_RES BIT(6) |
| 82 | #define KXCJK1013_REG_CTRL1_BIT_DRDY BIT(5) | 123 | #define KXCJK1013_REG_CTRL1_BIT_DRDY BIT(5) |
| @@ -117,6 +158,14 @@ · 34 unmodified lines | |||
| 117 | #define KXCJK1013_REG_INT_SRC2_BIT_XP BIT(4) | 158 | #define KXCJK1013_REG_INT_SRC2_BIT_XP BIT(4) |
| 118 | #define KXCJK1013_REG_INT_SRC2_BIT_XN BIT(5) | 159 | #define KXCJK1013_REG_INT_SRC2_BIT_XN BIT(5) |
| 119 | 160 | ||
| 161 | /* KX023 interrupt routing to INT1. INT2 can be configured with INC6 */ | ||
| 162 | #define KX023_REG_INC4_BFI1 BIT(6) | ||
| 163 | #define KX023_REG_INC4_WMI1 BIT(5) | ||
| 164 | #define KX023_REG_INC4_DRDY1 BIT(4) | ||
| 165 | #define KX023_REG_INC4_TDTI1 BIT(2) | ||
| 166 | #define KX023_REG_INC4_WUFI1 BIT(1) | ||
| 167 | #define KX023_REG_INC4_TPI1 BIT(0) | ||
| 168 | |||
| 120 | #define KXCJK1013_DEFAULT_WAKE_THRES 1 | 169 | #define KXCJK1013_DEFAULT_WAKE_THRES 1 |
| 121 | 170 | ||
| 122 | enum kx_chipset { | 171 | enum kx_chipset { |
| @@ -124,6 +173,7 @@ enum kx_chipset { · 1 unmodified line | |||
| 124 | KXCJ91008, | 173 | KXCJ91008, |
| 125 | KXTJ21009, | 174 | KXTJ21009, |
| 126 | KXTF9, | 175 | KXTF9, |
| 176 | KX0231025, | ||
| 127 | KX_MAX_CHIPS /* this must be last */ | 177 | KX_MAX_CHIPS /* this must be last */ |
| 128 | }; | 178 | }; |
| 129 | 179 | ||
| @@ -133,6 +183,63 @@ enum kx_acpi_type { · 3 unmodified lines | |||
| 133 | ACPI_KIOX010A, | 183 | ACPI_KIOX010A, |
| 134 | }; | 184 | }; |
| 135 | 185 | ||
| 186 | struct kx_chipset_regs { | ||
| 187 | u8 int_src1; | ||
| 188 | u8 int_src2; | ||
| 189 | u8 int_rel; | ||
| 190 | u8 ctrl1; | ||
| 191 | u8 wuf_ctrl; | ||
| 192 | u8 int_ctrl1; | ||
| 193 | u8 data_ctrl; | ||
| 194 | u8 wake_timer; | ||
| 195 | u8 wake_thres; | ||
| 196 | }; | ||
| 197 | |||
| 198 | static const struct kx_chipset_regs kxcjk1013_regs = { | ||
| 199 | .int_src1 = KXCJK1013_REG_INT_SRC1, | ||
| 200 | .int_src2 = KXCJK1013_REG_INT_SRC2, | ||
| 201 | .int_rel = KXCJK1013_REG_INT_REL, | ||
| 202 | .ctrl1 = KXCJK1013_REG_CTRL1, | ||
| 203 | .wuf_ctrl = KXCJK1013_REG_CTRL2, | ||
| 204 | .int_ctrl1 = KXCJK1013_REG_INT_CTRL1, | ||
| 205 | .data_ctrl = KXCJK1013_REG_DATA_CTRL, | ||
| 206 | .wake_timer = KXCJK1013_REG_WAKE_TIMER, | ||
| 207 | .wake_thres = KXCJK1013_REG_WAKE_THRES, | ||
| 208 | }; | ||
| 209 | |||
| 210 | static const struct kx_chipset_regs kxtf9_regs = { | ||
| 211 | /* .int_src1 was moved to INT_SRC2 on KXTF9 */ | ||
| 212 | .int_src1 = KXTF9_REG_INT_SRC2, | ||
| 213 | /* .int_src2 is not available */ | ||
| 214 | .int_rel = KXCJK1013_REG_INT_REL, | ||
| 215 | .ctrl1 = KXCJK1013_REG_CTRL1, | ||
| 216 | .wuf_ctrl = KXTF9_REG_CTRL3, | ||
| 217 | .int_ctrl1 = KXCJK1013_REG_INT_CTRL1, | ||
| 218 | .data_ctrl = KXCJK1013_REG_DATA_CTRL, | ||
| 219 | .wake_timer = KXCJK1013_REG_WAKE_TIMER, | ||
| 220 | .wake_thres = KXTF9_REG_WAKE_THRESH, | ||
| 221 | }; | ||
| 222 | |||
| 223 | /* The registers have totally different names but the bits are compatible */ | ||
| 224 | static const struct kx_chipset_regs kx0231025_regs = { | ||
| 225 | .int_src1 = KX023_REG_INS2, | ||
| 226 | .int_src2 = KX023_REG_INS3, | ||
| 227 | .int_rel = KX023_REG_INT_REL, | ||
| 228 | .ctrl1 = KX023_REG_CNTL1, | ||
| 229 | .wuf_ctrl = KX023_REG_CNTL3, | ||
| 230 | .int_ctrl1 = KX023_REG_INC1, | ||
| 231 | .data_ctrl = KX023_REG_ODCNTL, | ||
| 232 | .wake_timer = KX023_REG_WUFC, | ||
| 233 | .wake_thres = KX023_REG_ATH, | ||
| 234 | }; | ||
| 235 | |||
| 236 | enum kxcjk1013_axis { | ||
| 237 | AXIS_X, | ||
| 238 | AXIS_Y, | ||
| 239 | AXIS_Z, | ||
| 240 | AXIS_MAX | ||
| 241 | }; | ||
| 242 | |||
| 136 | struct kxcjk1013_data { | 243 | struct kxcjk1013_data { |
| 137 | struct regulator_bulk_data regulators[2]; | 244 | struct regulator_bulk_data regulators[2]; |
| 138 | struct i2c_client *client; | 245 | struct i2c_client *client; |
| @@ -140,7 +247,11 @@ struct kxcjk1013_data { · 1 unmodified line | |||
| 140 | struct iio_trigger *motion_trig; | 247 | struct iio_trigger *motion_trig; |
| 141 | struct iio_mount_matrix orientation; | 248 | struct iio_mount_matrix orientation; |
| 142 | struct mutex mutex; | 249 | struct mutex mutex; |
| 143 | s16 buffer[8]; | 250 | /* Ensure timestamp naturally aligned */ |
| 251 | struct { | ||
| 252 | s16 chans[AXIS_MAX]; | ||
| 253 | s64 timestamp __aligned(8); | ||
| 254 | } scan; | ||
| 144 | u8 odr_bits; | 255 | u8 odr_bits; |
| 145 | u8 range; | 256 | u8 range; |
| 146 | int wake_thres; | 257 | int wake_thres; |
| @@ -152,13 +263,7 @@ struct kxcjk1013_data { · 5 unmodified lines | |||
| 152 | int64_t timestamp; | 263 | int64_t timestamp; |
| 153 | enum kx_chipset chipset; | 264 | enum kx_chipset chipset; |
| 154 | enum kx_acpi_type acpi_type; | 265 | enum kx_acpi_type acpi_type; |
| 155 | }; | 266 | const struct kx_chipset_regs *regs; |
| 156 | |||
| 157 | enum kxcjk1013_axis { | ||
| 158 | AXIS_X, | ||
| 159 | AXIS_Y, | ||
| 160 | AXIS_Z, | ||
| 161 | AXIS_MAX, | ||
| 162 | }; | 267 | }; |
| 163 | 268 | ||
| 164 | enum kxcjk1013_mode { | 269 | enum kxcjk1013_mode { |
| @@ -268,6 +373,22 @@ static const struct { · 103 unmodified lines | |||
| 268 | {0x05, 5100}, | 373 | {0x05, 5100}, |
| 269 | {0x06, 2700}, | 374 | {0x06, 2700}, |
| 270 | }, | 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 | }, | ||
| 271 | }; | 392 | }; |
| 272 | 393 | ||
| 273 | static const struct { | 394 | static const struct { |
| @@ -309,7 +430,7 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data, · 35 unmodified lines | |||
| 309 | { | 430 | { |
| 310 | int ret; | 431 | int ret; |
| 311 | 432 | ||
| 312 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); | 433 | ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); |
| 313 | if (ret < 0) { | 434 | if (ret < 0) { |
| 314 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | 435 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); |
| 315 | return ret; | 436 | return ret; |
| @@ -320,8 +441,7 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data, · 4 unmodified lines | |||
| 320 | else | 441 | else |
| 321 | ret |= KXCJK1013_REG_CTRL1_BIT_PC1; | 442 | ret |= KXCJK1013_REG_CTRL1_BIT_PC1; |
| 322 | 443 | ||
| 323 | ret = i2c_smbus_write_byte_data(data->client, | 444 | ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); |
| 324 | KXCJK1013_REG_CTRL1, ret); | ||
| 325 | if (ret < 0) { | 445 | if (ret < 0) { |
| 326 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); | 446 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); |
| 327 | return ret; | 447 | return ret; |
| @@ -335,7 +455,7 @@ static int kxcjk1013_get_mode(struct kxcjk1013_data *data, · 7 unmodified lines | |||
| 335 | { | 455 | { |
| 336 | int ret; | 456 | int ret; |
| 337 | 457 | ||
| 338 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); | 458 | ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); |
| 339 | if (ret < 0) { | 459 | if (ret < 0) { |
| 340 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | 460 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); |
| 341 | return ret; | 461 | return ret; |
| @@ -353,7 +473,7 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index) · 11 unmodified lines | |||
| 353 | { | 473 | { |
| 354 | int ret; | 474 | int ret; |
| 355 | 475 | ||
| 356 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); | 476 | ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); |
| 357 | if (ret < 0) { | 477 | if (ret < 0) { |
| 358 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | 478 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); |
| 359 | return ret; | 479 | return ret; |
| @@ -364,9 +484,7 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index) · 4 unmodified lines | |||
| 364 | ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3); | 484 | ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3); |
| 365 | ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4); | 485 | ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4); |
| 366 | 486 | ||
| 367 | ret = i2c_smbus_write_byte_data(data->client, | 487 | ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); |
| 368 | KXCJK1013_REG_CTRL1, | ||
| 369 | ret); | ||
| 370 | if (ret < 0) { | 488 | if (ret < 0) { |
| 371 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); | 489 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); |
| 372 | return ret; | 490 | return ret; |
| @@ -400,7 +518,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) · 27 unmodified lines | |||
| 400 | if (ret < 0) | 518 | if (ret < 0) |
| 401 | return ret; | 519 | return ret; |
| 402 | 520 | ||
| 403 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); | 521 | ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); |
| 404 | if (ret < 0) { | 522 | if (ret < 0) { |
| 405 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | 523 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); |
| 406 | return ret; | 524 | return ret; |
| @@ -409,8 +527,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) · 2 unmodified lines | |||
| 409 | /* Set 12 bit mode */ | 527 | /* Set 12 bit mode */ |
| 410 | ret |= KXCJK1013_REG_CTRL1_BIT_RES; | 528 | ret |= KXCJK1013_REG_CTRL1_BIT_RES; |
| 411 | 529 | ||
| 412 | ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL1, | 530 | ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); |
| 413 | ret); | ||
| 414 | if (ret < 0) { | 531 | if (ret < 0) { |
| 415 | dev_err(&data->client->dev, "Error reading reg_ctrl\n"); | 532 | dev_err(&data->client->dev, "Error reading reg_ctrl\n"); |
| 416 | return ret; | 533 | return ret; |
| @@ -421,7 +538,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) · 4 unmodified lines | |||
| 421 | if (ret < 0) | 538 | if (ret < 0) |
| 422 | return ret; | 539 | return ret; |
| 423 | 540 | ||
| 424 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_DATA_CTRL); | 541 | ret = i2c_smbus_read_byte_data(data->client, data->regs->data_ctrl); |
| 425 | if (ret < 0) { | 542 | if (ret < 0) { |
| 426 | dev_err(&data->client->dev, "Error reading reg_data_ctrl\n"); | 543 | dev_err(&data->client->dev, "Error reading reg_data_ctrl\n"); |
| 427 | return ret; | 544 | return ret; |
| @@ -430,7 +547,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) · 2 unmodified lines | |||
| 430 | data->odr_bits = ret; | 547 | data->odr_bits = ret; |
| 431 | 548 | ||
| 432 | /* Set up INT polarity */ | 549 | /* Set up INT polarity */ |
| 433 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); | 550 | ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1); |
| 434 | if (ret < 0) { | 551 | if (ret < 0) { |
| 435 | dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); | 552 | dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); |
| 436 | return ret; | 553 | return ret; |
| @@ -441,13 +558,23 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) · 4 unmodified lines | |||
| 441 | else | 558 | else |
| 442 | ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEA; | 559 | ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEA; |
| 443 | 560 | ||
| 444 | ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, | 561 | ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret); |
| 445 | ret); | ||
| 446 | if (ret < 0) { | 562 | if (ret < 0) { |
| 447 | dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); | 563 | dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); |
| 448 | return ret; | 564 | return ret; |
| 449 | } | 565 | } |
| 450 | 566 | ||
| 567 | /* On KX023, route all used interrupts to INT1 for now */ | ||
| 568 | if (data->chipset == KX0231025 && data->client->irq > 0) { | ||
| 569 | ret = i2c_smbus_write_byte_data(data->client, KX023_REG_INC4, | ||
| 570 | KX023_REG_INC4_DRDY1 | | ||
| 571 | KX023_REG_INC4_WUFI1); | ||
| 572 | if (ret < 0) { | ||
| 573 | dev_err(&data->client->dev, "Error writing reg_inc4\n"); | ||
| 574 | return ret; | ||
| 575 | } | ||
| 576 | } | ||
| 577 | |||
| 451 | ret = kxcjk1013_set_mode(data, OPERATION); | 578 | ret = kxcjk1013_set_mode(data, OPERATION); |
| 452 | if (ret < 0) | 579 | if (ret < 0) |
| 453 | return ret; | 580 | return ret; |
| @@ -478,7 +605,7 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) · 24 unmodified lines | |||
| 478 | int ret; | 605 | int ret; |
| 479 | 606 | ||
| 480 | if (on) | 607 | if (on) |
| 481 | ret = pm_runtime_get_sync(&data->client->dev); | 608 | ret = pm_runtime_resume_and_get(&data->client->dev); |
| 482 | else { | 609 | else { |
| 483 | pm_runtime_mark_last_busy(&data->client->dev); | 610 | pm_runtime_mark_last_busy(&data->client->dev); |
| 484 | ret = pm_runtime_put_autosuspend(&data->client->dev); | 611 | ret = pm_runtime_put_autosuspend(&data->client->dev); |
| @@ -486,8 +613,6 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) · 1 unmodified line | |||
| 486 | if (ret < 0) { | 613 | if (ret < 0) { |
| 487 | dev_err(&data->client->dev, | 614 | dev_err(&data->client->dev, |
| 488 | "Failed: %s for %d\n", __func__, on); | 615 | "Failed: %s for %d\n", __func__, on); |
| 489 | if (on) | ||
| 490 | pm_runtime_put_noidle(&data->client->dev); | ||
| 491 | return ret; | 616 | return ret; |
| 492 | } | 617 | } |
| 493 | #endif | 618 | #endif |
| @@ -497,10 +622,9 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) · 3 unmodified lines | |||
| 497 | 622 | ||
| 498 | static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data) | 623 | static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data) |
| 499 | { | 624 | { |
| 500 | int waketh_reg, ret; | 625 | int ret; |
| 501 | 626 | ||
| 502 | ret = i2c_smbus_write_byte_data(data->client, | 627 | ret = i2c_smbus_write_byte_data(data->client, data->regs->wake_timer, |
| 503 | KXCJK1013_REG_WAKE_TIMER, | ||
| 504 | data->wake_dur); | 628 | data->wake_dur); |
| 505 | if (ret < 0) { | 629 | if (ret < 0) { |
| 506 | dev_err(&data->client->dev, | 630 | dev_err(&data->client->dev, |
| @@ -508,9 +632,7 @@ static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data) · 1 unmodified line | |||
| 508 | return ret; | 632 | return ret; |
| 509 | } | 633 | } |
| 510 | 634 | ||
| 511 | waketh_reg = data->chipset == KXTF9 ? | 635 | ret = i2c_smbus_write_byte_data(data->client, data->regs->wake_thres, |
| 512 | KXTF9_REG_WAKE_THRESH : KXCJK1013_REG_WAKE_THRES; | ||
| 513 | ret = i2c_smbus_write_byte_data(data->client, waketh_reg, | ||
| 514 | data->wake_thres); | 636 | data->wake_thres); |
| 515 | if (ret < 0) { | 637 | if (ret < 0) { |
| 516 | dev_err(&data->client->dev, "Error writing reg_wake_thres\n"); | 638 | dev_err(&data->client->dev, "Error writing reg_wake_thres\n"); |
| @@ -539,7 +661,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, · 22 unmodified lines | |||
| 539 | if (ret < 0) | 661 | if (ret < 0) |
| 540 | return ret; | 662 | return ret; |
| 541 | 663 | ||
| 542 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); | 664 | ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1); |
| 543 | if (ret < 0) { | 665 | if (ret < 0) { |
| 544 | dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); | 666 | dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); |
| 545 | return ret; | 667 | return ret; |
| @@ -550,14 +672,13 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, · 4 unmodified lines | |||
| 550 | else | 672 | else |
| 551 | ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; | 673 | ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; |
| 552 | 674 | ||
| 553 | ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, | 675 | ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret); |
| 554 | ret); | ||
| 555 | if (ret < 0) { | 676 | if (ret < 0) { |
| 556 | dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); | 677 | dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); |
| 557 | return ret; | 678 | return ret; |
| 558 | } | 679 | } |
| 559 | 680 | ||
| 560 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); | 681 | ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); |
| 561 | if (ret < 0) { | 682 | if (ret < 0) { |
| 562 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | 683 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); |
| 563 | return ret; | 684 | return ret; |
| @@ -568,8 +689,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, · 4 unmodified lines | |||
| 568 | else | 689 | else |
| 569 | ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE; | 690 | ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE; |
| 570 | 691 | ||
| 571 | ret = i2c_smbus_write_byte_data(data->client, | 692 | ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); |
| 572 | KXCJK1013_REG_CTRL1, ret); | ||
| 573 | if (ret < 0) { | 693 | if (ret < 0) { |
| 574 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); | 694 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); |
| 575 | return ret; | 695 | return ret; |
| @@ -599,7 +719,7 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, · 23 unmodified lines | |||
| 599 | if (ret < 0) | 719 | if (ret < 0) |
| 600 | return ret; | 720 | return ret; |
| 601 | 721 | ||
| 602 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1); | 722 | ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1); |
| 603 | if (ret < 0) { | 723 | if (ret < 0) { |
| 604 | dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); | 724 | dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); |
| 605 | return ret; | 725 | return ret; |
| @@ -610,14 +730,13 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, · 4 unmodified lines | |||
| 610 | else | 730 | else |
| 611 | ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; | 731 | ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; |
| 612 | 732 | ||
| 613 | ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1, | 733 | ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret); |
| 614 | ret); | ||
| 615 | if (ret < 0) { | 734 | if (ret < 0) { |
| 616 | dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); | 735 | dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); |
| 617 | return ret; | 736 | return ret; |
| 618 | } | 737 | } |
| 619 | 738 | ||
| 620 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); | 739 | ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1); |
| 621 | if (ret < 0) { | 740 | if (ret < 0) { |
| 622 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | 741 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); |
| 623 | return ret; | 742 | return ret; |
| @@ -628,8 +747,7 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, · 4 unmodified lines | |||
| 628 | else | 747 | else |
| 629 | ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY; | 748 | ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY; |
| 630 | 749 | ||
| 631 | ret = i2c_smbus_write_byte_data(data->client, | 750 | ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret); |
| 632 | KXCJK1013_REG_CTRL1, ret); | ||
| 633 | if (ret < 0) { | 751 | if (ret < 0) { |
| 634 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); | 752 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); |
| 635 | return ret; | 753 | return ret; |
| @@ -701,7 +819,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2) · 65 unmodified lines | |||
| 701 | if (ret < 0) | 819 | if (ret < 0) |
| 702 | return ret; | 820 | return ret; |
| 703 | 821 | ||
| 704 | ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_DATA_CTRL, | 822 | ret = i2c_smbus_write_byte_data(data->client, data->regs->data_ctrl, |
| 705 | odr_setting->odr_bits); | 823 | odr_setting->odr_bits); |
| 706 | if (ret < 0) { | 824 | if (ret < 0) { |
| 707 | dev_err(&data->client->dev, "Error writing data_ctrl\n"); | 825 | dev_err(&data->client->dev, "Error writing data_ctrl\n"); |
| @@ -710,7 +828,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2) · 2 unmodified lines | |||
| 710 | 828 | ||
| 711 | data->odr_bits = odr_setting->odr_bits; | 829 | data->odr_bits = odr_setting->odr_bits; |
| 712 | 830 | ||
| 713 | ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL2, | 831 | ret = i2c_smbus_write_byte_data(data->client, data->regs->wuf_ctrl, |
| 714 | odr_setting->wuf_bits); | 832 | odr_setting->wuf_bits); |
| 715 | if (ret < 0) { | 833 | if (ret < 0) { |
| 716 | dev_err(&data->client->dev, "Error writing reg_ctrl2\n"); | 834 | dev_err(&data->client->dev, "Error writing reg_ctrl2\n"); |
| @@ -1094,12 +1212,12 @@ static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p) · 377 unmodified lines | |||
| 1094 | ret = i2c_smbus_read_i2c_block_data_or_emulated(data->client, | 1212 | ret = i2c_smbus_read_i2c_block_data_or_emulated(data->client, |
| 1095 | KXCJK1013_REG_XOUT_L, | 1213 | KXCJK1013_REG_XOUT_L, |
| 1096 | AXIS_MAX * 2, | 1214 | AXIS_MAX * 2, |
| 1097 | (u8 *)data->buffer); | 1215 | (u8 *)data->scan.chans); |
| 1098 | mutex_unlock(&data->mutex); | 1216 | mutex_unlock(&data->mutex); |
| 1099 | if (ret < 0) | 1217 | if (ret < 0) |
| 1100 | goto err; | 1218 | goto err; |
| 1101 | 1219 | ||
| 1102 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 1220 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, |
| 1103 | data->timestamp); | 1221 | data->timestamp); |
| 1104 | err: | 1222 | err: |
| 1105 | iio_trigger_notify_done(indio_dev->trig); | 1223 | iio_trigger_notify_done(indio_dev->trig); |
| @@ -1113,7 +1231,7 @@ static void kxcjk1013_trig_reen(struct iio_trigger *trig) · 7 unmodified lines | |||
| 1113 | struct kxcjk1013_data *data = iio_priv(indio_dev); | 1231 | struct kxcjk1013_data *data = iio_priv(indio_dev); |
| 1114 | int ret; | 1232 | int ret; |
| 1115 | 1233 | ||
| 1116 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL); | 1234 | ret = i2c_smbus_read_byte_data(data->client, data->regs->int_rel); |
| 1117 | if (ret < 0) | 1235 | if (ret < 0) |
| 1118 | dev_err(&data->client->dev, "Error reading reg_int_rel\n"); | 1236 | dev_err(&data->client->dev, "Error reading reg_int_rel\n"); |
| 1119 | } | 1237 | } |
| @@ -1166,8 +1284,7 @@ static void kxcjk1013_report_motion_event(struct iio_dev *indio_dev) · 46 unmodified lines | |||
| 1166 | { | 1284 | { |
| 1167 | struct kxcjk1013_data *data = iio_priv(indio_dev); | 1285 | struct kxcjk1013_data *data = iio_priv(indio_dev); |
| 1168 | 1286 | ||
| 1169 | int ret = i2c_smbus_read_byte_data(data->client, | 1287 | int ret = i2c_smbus_read_byte_data(data->client, data->regs->int_src2); |
| 1170 | KXCJK1013_REG_INT_SRC2); | ||
| 1171 | if (ret < 0) { | 1288 | if (ret < 0) { |
| 1172 | dev_err(&data->client->dev, "Error reading reg_int_src2\n"); | 1289 | dev_err(&data->client->dev, "Error reading reg_int_src2\n"); |
| 1173 | return; | 1290 | return; |
| @@ -1234,7 +1351,7 @@ static irqreturn_t kxcjk1013_event_handler(int irq, void *private) · 60 unmodified lines | |||
| 1234 | struct kxcjk1013_data *data = iio_priv(indio_dev); | 1351 | struct kxcjk1013_data *data = iio_priv(indio_dev); |
| 1235 | int ret; | 1352 | int ret; |
| 1236 | 1353 | ||
| 1237 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_SRC1); | 1354 | ret = i2c_smbus_read_byte_data(data->client, data->regs->int_src1); |
| 1238 | if (ret < 0) { | 1355 | if (ret < 0) { |
| 1239 | dev_err(&data->client->dev, "Error reading reg_int_src1\n"); | 1356 | dev_err(&data->client->dev, "Error reading reg_int_src1\n"); |
| 1240 | goto ack_intr; | 1357 | goto ack_intr; |
| @@ -1257,7 +1374,7 @@ ack_intr: · 16 unmodified lines | |||
| 1257 | if (data->dready_trigger_on) | 1374 | if (data->dready_trigger_on) |
| 1258 | return IRQ_HANDLED; | 1375 | return IRQ_HANDLED; |
| 1259 | 1376 | ||
| 1260 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL); | 1377 | ret = i2c_smbus_read_byte_data(data->client, data->regs->int_rel); |
| 1261 | if (ret < 0) | 1378 | if (ret < 0) |
| 1262 | dev_err(&data->client->dev, "Error reading reg_int_rel\n"); | 1379 | dev_err(&data->client->dev, "Error reading reg_int_rel\n"); |
| 1263 | 1380 | ||
| @@ -1338,8 +1455,7 @@ static int kxcjk1013_probe(struct i2c_client *client, · 74 unmodified lines | |||
| 1338 | } else { | 1455 | } else { |
| 1339 | data->active_high_intr = true; /* default polarity */ | 1456 | data->active_high_intr = true; /* default polarity */ |
| 1340 | 1457 | ||
| 1341 | ret = iio_read_mount_matrix(&client->dev, "mount-matrix", | 1458 | ret = iio_read_mount_matrix(&client->dev, &data->orientation); |
| 1342 | &data->orientation); | ||
| 1343 | if (ret) | 1459 | if (ret) |
| 1344 | return ret; | 1460 | return ret; |
| 1345 | } | 1461 | } |
| @@ -1378,6 +1494,22 @@ static int kxcjk1013_probe(struct i2c_client *client, · 32 unmodified lines | |||
| 1378 | } else | 1494 | } else |
| 1379 | return -ENODEV; | 1495 | return -ENODEV; |
| 1380 | 1496 | ||
| 1497 | switch (data->chipset) { | ||
| 1498 | case KXCJK1013: | ||
| 1499 | case KXCJ91008: | ||
| 1500 | case KXTJ21009: | ||
| 1501 | data->regs = &kxcjk1013_regs; | ||
| 1502 | break; | ||
| 1503 | case KXTF9: | ||
| 1504 | data->regs = &kxtf9_regs; | ||
| 1505 | break; | ||
| 1506 | case KX0231025: | ||
| 1507 | data->regs = &kx0231025_regs; | ||
| 1508 | break; | ||
| 1509 | default: | ||
| 1510 | return -EINVAL; | ||
| 1511 | } | ||
| 1512 | |||
| 1381 | ret = kxcjk1013_chip_init(data); | 1513 | ret = kxcjk1013_chip_init(data); |
| 1382 | if (ret < 0) | 1514 | if (ret < 0) |
| 1383 | return ret; | 1515 | return ret; |
| @@ -1404,7 +1536,7 @@ static int kxcjk1013_probe(struct i2c_client *client, · 20 unmodified lines | |||
| 1404 | data->dready_trig = devm_iio_trigger_alloc(&client->dev, | 1536 | data->dready_trig = devm_iio_trigger_alloc(&client->dev, |
| 1405 | "%s-dev%d", | 1537 | "%s-dev%d", |
| 1406 | indio_dev->name, | 1538 | indio_dev->name, |
| 1407 | indio_dev->id); | 1539 | iio_device_id(indio_dev)); |
| 1408 | if (!data->dready_trig) { | 1540 | if (!data->dready_trig) { |
| 1409 | ret = -ENOMEM; | 1541 | ret = -ENOMEM; |
| 1410 | goto err_poweroff; | 1542 | goto err_poweroff; |
| @@ -1413,7 +1545,7 @@ static int kxcjk1013_probe(struct i2c_client *client, · 2 unmodified lines | |||
| 1413 | data->motion_trig = devm_iio_trigger_alloc(&client->dev, | 1545 | data->motion_trig = devm_iio_trigger_alloc(&client->dev, |
| 1414 | "%s-any-motion-dev%d", | 1546 | "%s-any-motion-dev%d", |
| 1415 | indio_dev->name, | 1547 | indio_dev->name, |
| 1416 | indio_dev->id); | 1548 | iio_device_id(indio_dev)); |
| 1417 | if (!data->motion_trig) { | 1549 | if (!data->motion_trig) { |
| 1418 | ret = -ENOMEM; | 1550 | ret = -ENOMEM; |
| 1419 | goto err_poweroff; | 1551 | goto err_poweroff; |
| @@ -1485,7 +1617,6 @@ static int kxcjk1013_remove(struct i2c_client *client) · 65 unmodified lines | |||
| 1485 | 1617 | ||
| 1486 | pm_runtime_disable(&client->dev); | 1618 | pm_runtime_disable(&client->dev); |
| 1487 | pm_runtime_set_suspended(&client->dev); | 1619 | pm_runtime_set_suspended(&client->dev); |
| 1488 | pm_runtime_put_noidle(&client->dev); | ||
| 1489 | 1620 | ||
| 1490 | if (data->dready_trig) { | 1621 | if (data->dready_trig) { |
| 1491 | iio_triggered_buffer_cleanup(indio_dev); | 1622 | iio_triggered_buffer_cleanup(indio_dev); |
| @@ -1593,6 +1724,7 @@ static const struct i2c_device_id kxcjk1013_id[] = { · 101 unmodified lines | |||
| 1593 | {"kxcj91008", KXCJ91008}, | 1724 | {"kxcj91008", KXCJ91008}, |
| 1594 | {"kxtj21009", KXTJ21009}, | 1725 | {"kxtj21009", KXTJ21009}, |
| 1595 | {"kxtf9", KXTF9}, | 1726 | {"kxtf9", KXTF9}, |
| 1727 | {"kx023-1025", KX0231025}, | ||
| 1596 | {"SMO8500", KXCJ91008}, | 1728 | {"SMO8500", KXCJ91008}, |
| 1597 | {} | 1729 | {} |
| 1598 | }; | 1730 | }; |
| @@ -1604,6 +1736,7 @@ static const struct of_device_id kxcjk1013_of_match[] = { · 5 unmodified lines | |||
| 1604 | { .compatible = "kionix,kxcj91008", }, | 1736 | { .compatible = "kionix,kxcj91008", }, |
| 1605 | { .compatible = "kionix,kxtj21009", }, | 1737 | { .compatible = "kionix,kxtj21009", }, |
| 1606 | { .compatible = "kionix,kxtf9", }, | 1738 | { .compatible = "kionix,kxtf9", }, |
| 1739 | { .compatible = "kionix,kx023-1025", }, | ||
| 1607 | { } | 1740 | { } |
| 1608 | }; | 1741 | }; |
| 1609 | MODULE_DEVICE_TABLE(of, kxcjk1013_of_match); | 1742 | MODULE_DEVICE_TABLE(of, kxcjk1013_of_match); |
| @@ -420,7 +420,7 @@ int kxsd9_common_probe(struct device *dev, · 419 unmodified lines | |||
| 420 | indio_dev->available_scan_masks = kxsd9_scan_masks; | 420 | indio_dev->available_scan_masks = kxsd9_scan_masks; |
| 421 | 421 | ||
| 422 | /* Read the mounting matrix, if present */ | 422 | /* Read the mounting matrix, if present */ |
| 423 | ret = iio_read_mount_matrix(dev, "mount-matrix", &st->orientation); | 423 | ret = iio_read_mount_matrix(dev, &st->orientation); |
| 424 | if (ret) | 424 | if (ret) |
| 425 | return ret; | 425 | return ret; |
| 426 | 426 | ||
| @@ -221,7 +221,7 @@ static int mma8452_set_runtime_pm_state(struct i2c_client *client, bool on) · 220 unmodified lines | |||
| 221 | int ret; | 221 | int ret; |
| 222 | 222 | ||
| 223 | if (on) { | 223 | if (on) { |
| 224 | ret = pm_runtime_get_sync(&client->dev); | 224 | ret = pm_runtime_resume_and_get(&client->dev); |
| 225 | } else { | 225 | } else { |
| 226 | pm_runtime_mark_last_busy(&client->dev); | 226 | pm_runtime_mark_last_busy(&client->dev); |
| 227 | ret = pm_runtime_put_autosuspend(&client->dev); | 227 | ret = pm_runtime_put_autosuspend(&client->dev); |
| @@ -230,8 +230,6 @@ static int mma8452_set_runtime_pm_state(struct i2c_client *client, bool on) · 2 unmodified lines | |||
| 230 | if (ret < 0) { | 230 | if (ret < 0) { |
| 231 | dev_err(&client->dev, | 231 | dev_err(&client->dev, |
| 232 | "failed to change power state to %d\n", on); | 232 | "failed to change power state to %d\n", on); |
| 233 | if (on) | ||
| 234 | pm_runtime_put_noidle(&client->dev); | ||
| 235 | 233 | ||
| 236 | return ret; | 234 | return ret; |
| 237 | } | 235 | } |
| @@ -1461,7 +1459,7 @@ static int mma8452_trigger_setup(struct iio_dev *indio_dev) · 1223 unmodified lines | |||
| 1461 | 1459 | ||
| 1462 | trig = devm_iio_trigger_alloc(&data->client->dev, "%s-dev%d", | 1460 | trig = devm_iio_trigger_alloc(&data->client->dev, "%s-dev%d", |
| 1463 | indio_dev->name, | 1461 | indio_dev->name, |
| 1464 | indio_dev->id); | 1462 | iio_device_id(indio_dev)); |
| 1465 | if (!trig) | 1463 | if (!trig) |
| 1466 | return -ENOMEM; | 1464 | return -ENOMEM; |
| 1467 | 1465 | ||
| @@ -1711,7 +1709,6 @@ static int mma8452_remove(struct i2c_client *client) · 243 unmodified lines | |||
| 1711 | 1709 | ||
| 1712 | pm_runtime_disable(&client->dev); | 1710 | pm_runtime_disable(&client->dev); |
| 1713 | pm_runtime_set_suspended(&client->dev); | 1711 | pm_runtime_set_suspended(&client->dev); |
| 1714 | pm_runtime_put_noidle(&client->dev); | ||
| 1715 | 1712 | ||
| 1716 | iio_triggered_buffer_cleanup(indio_dev); | 1713 | iio_triggered_buffer_cleanup(indio_dev); |
| 1717 | mma8452_trigger_cleanup(indio_dev); | 1714 | mma8452_trigger_cleanup(indio_dev); |
| @@ -515,7 +515,6 @@ static int mma9551_remove(struct i2c_client *client) · 514 unmodified lines | |||
| 515 | 515 | ||
| 516 | pm_runtime_disable(&client->dev); | 516 | pm_runtime_disable(&client->dev); |
| 517 | pm_runtime_set_suspended(&client->dev); | 517 | pm_runtime_set_suspended(&client->dev); |
| 518 | pm_runtime_put_noidle(&client->dev); | ||
| 519 | 518 | ||
| 520 | mutex_lock(&data->mutex); | 519 | mutex_lock(&data->mutex); |
| 521 | mma9551_set_device_state(data->client, false); | 520 | mma9551_set_device_state(data->client, false); |
| @@ -664,7 +664,7 @@ int mma9551_set_power_state(struct i2c_client *client, bool on) · 663 unmodified lines | |||
| 664 | int ret; | 664 | int ret; |
| 665 | 665 | ||
| 666 | if (on) | 666 | if (on) |
| 667 | ret = pm_runtime_get_sync(&client->dev); | 667 | ret = pm_runtime_resume_and_get(&client->dev); |
| 668 | else { | 668 | else { |
| 669 | pm_runtime_mark_last_busy(&client->dev); | 669 | pm_runtime_mark_last_busy(&client->dev); |
| 670 | ret = pm_runtime_put_autosuspend(&client->dev); | 670 | ret = pm_runtime_put_autosuspend(&client->dev); |
| @@ -673,8 +673,6 @@ int mma9551_set_power_state(struct i2c_client *client, bool on) · 2 unmodified lines | |||
| 673 | if (ret < 0) { | 673 | if (ret < 0) { |
| 674 | dev_err(&client->dev, | 674 | dev_err(&client->dev, |
| 675 | "failed to change power state to %d\n", on); | 675 | "failed to change power state to %d\n", on); |
| 676 | if (on) | ||
| 677 | pm_runtime_put_noidle(&client->dev); | ||
| 678 | 676 | ||
| 679 | return ret; | 677 | return ret; |
| 680 | } | 678 | } |
| @@ -1154,7 +1154,6 @@ static int mma9553_remove(struct i2c_client *client) · 1153 unmodified lines | |||
| 1154 | 1154 | ||
| 1155 | pm_runtime_disable(&client->dev); | 1155 | pm_runtime_disable(&client->dev); |
| 1156 | pm_runtime_set_suspended(&client->dev); | 1156 | pm_runtime_set_suspended(&client->dev); |
| 1157 | pm_runtime_put_noidle(&client->dev); | ||
| 1158 | 1157 | ||
| 1159 | mutex_lock(&data->mutex); | 1158 | mutex_lock(&data->mutex); |
| 1160 | mma9551_set_device_state(data->client, false); | 1159 | mma9551_set_device_state(data->client, false); |
| @@ -56,7 +56,11 @@ struct mxc4005_data { · 55 unmodified lines | |||
| 56 | struct mutex mutex; | 56 | struct mutex mutex; |
| 57 | struct regmap *regmap; | 57 | struct regmap *regmap; |
| 58 | struct iio_trigger *dready_trig; | 58 | struct iio_trigger *dready_trig; |
| 59 | __be16 buffer[8]; | 59 | /* Ensure timestamp is naturally aligned */ |
| 60 | struct { | ||
| 61 | __be16 chans[3]; | ||
| 62 | s64 timestamp __aligned(8); | ||
| 63 | } scan; | ||
| 60 | bool trigger_enabled; | 64 | bool trigger_enabled; |
| 61 | }; | 65 | }; |
| 62 | 66 | ||
| @@ -135,7 +139,7 @@ static int mxc4005_read_xyz(struct mxc4005_data *data) · 72 unmodified lines | |||
| 135 | int ret; | 139 | int ret; |
| 136 | 140 | ||
| 137 | ret = regmap_bulk_read(data->regmap, MXC4005_REG_XOUT_UPPER, | 141 | ret = regmap_bulk_read(data->regmap, MXC4005_REG_XOUT_UPPER, |
| 138 | data->buffer, sizeof(data->buffer)); | 142 | data->scan.chans, sizeof(data->scan.chans)); |
| 139 | if (ret < 0) { | 143 | if (ret < 0) { |
| 140 | dev_err(data->dev, "failed to read axes\n"); | 144 | dev_err(data->dev, "failed to read axes\n"); |
| 141 | return ret; | 145 | return ret; |
| @@ -301,7 +305,7 @@ static irqreturn_t mxc4005_trigger_handler(int irq, void *private) · 159 unmodified lines | |||
| 301 | if (ret < 0) | 305 | if (ret < 0) |
| 302 | goto err; | 306 | goto err; |
| 303 | 307 | ||
| 304 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 308 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, |
| 305 | pf->timestamp); | 309 | pf->timestamp); |
| 306 | 310 | ||
| 307 | err: | 311 | err: |
| @@ -433,7 +437,7 @@ static int mxc4005_probe(struct i2c_client *client, · 125 unmodified lines | |||
| 433 | data->dready_trig = devm_iio_trigger_alloc(&client->dev, | 437 | data->dready_trig = devm_iio_trigger_alloc(&client->dev, |
| 434 | "%s-dev%d", | 438 | "%s-dev%d", |
| 435 | indio_dev->name, | 439 | indio_dev->name, |
| 436 | indio_dev->id); | 440 | iio_device_id(indio_dev)); |
| 437 | if (!data->dready_trig) | 441 | if (!data->dready_trig) |
| 438 | return -ENOMEM; | 442 | return -ENOMEM; |
| 439 | 443 | ||
| @@ -0,0 +1,472 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Murata SCA3300 3-axis industrial accelerometer | ||
| 4 | * | ||
| 5 | * Copyright (c) 2021 Vaisala Oyj. All rights reserved. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/bitops.h> | ||
| 9 | #include <linux/crc8.h> | ||
| 10 | #include <linux/delay.h> | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/spi/spi.h> | ||
| 14 | |||
| 15 | #include <asm/unaligned.h> | ||
| 16 | |||
| 17 | #include <linux/iio/buffer.h> | ||
| 18 | #include <linux/iio/iio.h> | ||
| 19 | #include <linux/iio/sysfs.h> | ||
| 20 | #include <linux/iio/trigger_consumer.h> | ||
| 21 | #include <linux/iio/triggered_buffer.h> | ||
| 22 | |||
| 23 | #define SCA3300_ALIAS "sca3300" | ||
| 24 | |||
| 25 | #define SCA3300_CRC8_POLYNOMIAL 0x1d | ||
| 26 | |||
| 27 | /* Device mode register */ | ||
| 28 | #define SCA3300_REG_MODE 0xd | ||
| 29 | #define SCA3300_MODE_SW_RESET 0x20 | ||
| 30 | |||
| 31 | /* Last register in map */ | ||
| 32 | #define SCA3300_REG_SELBANK 0x1f | ||
| 33 | |||
| 34 | /* Device status and mask */ | ||
| 35 | #define SCA3300_REG_STATUS 0x6 | ||
| 36 | #define SCA3300_STATUS_MASK GENMASK(8, 0) | ||
| 37 | |||
| 38 | /* Device ID */ | ||
| 39 | #define SCA3300_REG_WHOAMI 0x10 | ||
| 40 | #define SCA3300_WHOAMI_ID 0x51 | ||
| 41 | |||
| 42 | /* Device return status and mask */ | ||
| 43 | #define SCA3300_VALUE_RS_ERROR 0x3 | ||
| 44 | #define SCA3300_MASK_RS_STATUS GENMASK(1, 0) | ||
| 45 | |||
| 46 | enum sca3300_scan_indexes { | ||
| 47 | SCA3300_ACC_X = 0, | ||
| 48 | SCA3300_ACC_Y, | ||
| 49 | SCA3300_ACC_Z, | ||
| 50 | SCA3300_TEMP, | ||
| 51 | SCA3300_TIMESTAMP, | ||
| 52 | }; | ||
| 53 | |||
| 54 | #define SCA3300_ACCEL_CHANNEL(index, reg, axis) { \ | ||
| 55 | .type = IIO_ACCEL, \ | ||
| 56 | .address = reg, \ | ||
| 57 | .modified = 1, \ | ||
| 58 | .channel2 = IIO_MOD_##axis, \ | ||
| 59 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
| 60 | .info_mask_shared_by_type = \ | ||
| 61 | BIT(IIO_CHAN_INFO_SCALE) | \ | ||
| 62 | BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ | ||
| 63 | .info_mask_shared_by_type_available = \ | ||
| 64 | BIT(IIO_CHAN_INFO_SCALE) | \ | ||
| 65 | BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ | ||
| 66 | .scan_index = index, \ | ||
| 67 | .scan_type = { \ | ||
| 68 | .sign = 's', \ | ||
| 69 | .realbits = 16, \ | ||
| 70 | .storagebits = 16, \ | ||
| 71 | .endianness = IIO_CPU, \ | ||
| 72 | }, \ | ||
| 73 | } | ||
| 74 | |||
| 75 | static const struct iio_chan_spec sca3300_channels[] = { | ||
| 76 | SCA3300_ACCEL_CHANNEL(SCA3300_ACC_X, 0x1, X), | ||
| 77 | SCA3300_ACCEL_CHANNEL(SCA3300_ACC_Y, 0x2, Y), | ||
| 78 | SCA3300_ACCEL_CHANNEL(SCA3300_ACC_Z, 0x3, Z), | ||
| 79 | { | ||
| 80 | .type = IIO_TEMP, | ||
| 81 | .address = 0x5, | ||
| 82 | .scan_index = SCA3300_TEMP, | ||
| 83 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
| 84 | .scan_type = { | ||
| 85 | .sign = 's', | ||
| 86 | .realbits = 16, | ||
| 87 | .storagebits = 16, | ||
| 88 | .endianness = IIO_CPU, | ||
| 89 | }, | ||
| 90 | }, | ||
| 91 | IIO_CHAN_SOFT_TIMESTAMP(4), | ||
| 92 | }; | ||
| 93 | |||
| 94 | static const int sca3300_lp_freq[] = {70, 70, 70, 10}; | ||
| 95 | static const int sca3300_accel_scale[][2] = {{0, 370}, {0, 741}, {0, 185}, {0, 185}}; | ||
| 96 | |||
| 97 | static const unsigned long sca3300_scan_masks[] = { | ||
| 98 | BIT(SCA3300_ACC_X) | BIT(SCA3300_ACC_Y) | BIT(SCA3300_ACC_Z) | | ||
| 99 | BIT(SCA3300_TEMP), | ||
| 100 | 0 | ||
| 101 | }; | ||
| 102 | |||
| 103 | /** | ||
| 104 | * struct sca3300_data - device data | ||
| 105 | * @spi: SPI device structure | ||
| 106 | * @lock: Data buffer lock | ||
| 107 | * @scan: Triggered buffer. Four channel 16-bit data + 64-bit timestamp | ||
| 108 | * @txbuf: Transmit buffer | ||
| 109 | * @rxbuf: Receive buffer | ||
| 110 | */ | ||
| 111 | struct sca3300_data { | ||
| 112 | struct spi_device *spi; | ||
| 113 | struct mutex lock; | ||
| 114 | struct { | ||
| 115 | s16 channels[4]; | ||
| 116 | s64 ts __aligned(sizeof(s64)); | ||
| 117 | } scan; | ||
| 118 | u8 txbuf[4] ____cacheline_aligned; | ||
| 119 | u8 rxbuf[4]; | ||
| 120 | }; | ||
| 121 | |||
| 122 | DECLARE_CRC8_TABLE(sca3300_crc_table); | ||
| 123 | |||
| 124 | static int sca3300_transfer(struct sca3300_data *sca_data, int *val) | ||
| 125 | { | ||
| 126 | /* Consecutive requests min. 10 us delay (Datasheet section 5.1.2) */ | ||
| 127 | struct spi_delay delay = { .value = 10, .unit = SPI_DELAY_UNIT_USECS }; | ||
| 128 | int32_t ret; | ||
| 129 | int rs; | ||
| 130 | u8 crc; | ||
| 131 | struct spi_transfer xfers[2] = { | ||
| 132 | { | ||
| 133 | .tx_buf = sca_data->txbuf, | ||
| 134 | .len = ARRAY_SIZE(sca_data->txbuf), | ||
| 135 | .delay = delay, | ||
| 136 | .cs_change = 1, | ||
| 137 | }, | ||
| 138 | { | ||
| 139 | .rx_buf = sca_data->rxbuf, | ||
| 140 | .len = ARRAY_SIZE(sca_data->rxbuf), | ||
| 141 | .delay = delay, | ||
| 142 | } | ||
| 143 | }; | ||
| 144 | |||
| 145 | /* inverted crc value as described in device data sheet */ | ||
| 146 | crc = ~crc8(sca3300_crc_table, &sca_data->txbuf[0], 3, CRC8_INIT_VALUE); | ||
| 147 | sca_data->txbuf[3] = crc; | ||
| 148 | |||
| 149 | ret = spi_sync_transfer(sca_data->spi, xfers, ARRAY_SIZE(xfers)); | ||
| 150 | if (ret) { | ||
| 151 | dev_err(&sca_data->spi->dev, | ||
| 152 | "transfer error, error: %d\n", ret); | ||
| 153 | return -EIO; | ||
| 154 | } | ||
| 155 | |||
| 156 | crc = ~crc8(sca3300_crc_table, &sca_data->rxbuf[0], 3, CRC8_INIT_VALUE); | ||
| 157 | if (sca_data->rxbuf[3] != crc) { | ||
| 158 | dev_err(&sca_data->spi->dev, "CRC checksum mismatch"); | ||
| 159 | return -EIO; | ||
| 160 | } | ||
| 161 | |||
| 162 | /* get return status */ | ||
| 163 | rs = sca_data->rxbuf[0] & SCA3300_MASK_RS_STATUS; | ||
| 164 | if (rs == SCA3300_VALUE_RS_ERROR) | ||
| 165 | ret = -EINVAL; | ||
| 166 | |||
| 167 | *val = sign_extend32(get_unaligned_be16(&sca_data->rxbuf[1]), 15); | ||
| 168 | |||
| 169 | return ret; | ||
| 170 | } | ||
| 171 | |||
| 172 | static int sca3300_error_handler(struct sca3300_data *sca_data) | ||
| 173 | { | ||
| 174 | int ret; | ||
| 175 | int val; | ||
| 176 | |||
| 177 | mutex_lock(&sca_data->lock); | ||
| 178 | sca_data->txbuf[0] = SCA3300_REG_STATUS << 2; | ||
| 179 | ret = sca3300_transfer(sca_data, &val); | ||
| 180 | mutex_unlock(&sca_data->lock); | ||
| 181 | /* | ||
| 182 | * Return status error is cleared after reading status register once, | ||
| 183 | * expect EINVAL here. | ||
| 184 | */ | ||
| 185 | if (ret != -EINVAL) { | ||
| 186 | dev_err(&sca_data->spi->dev, | ||
| 187 | "error reading device status: %d\n", ret); | ||
| 188 | return ret; | ||
| 189 | } | ||
| 190 | |||
| 191 | dev_err(&sca_data->spi->dev, "device status: 0x%lx\n", | ||
| 192 | val & SCA3300_STATUS_MASK); | ||
| 193 | |||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | |||
| 197 | static int sca3300_read_reg(struct sca3300_data *sca_data, u8 reg, int *val) | ||
| 198 | { | ||
| 199 | int ret; | ||
| 200 | |||
| 201 | mutex_lock(&sca_data->lock); | ||
| 202 | sca_data->txbuf[0] = reg << 2; | ||
| 203 | ret = sca3300_transfer(sca_data, val); | ||
| 204 | mutex_unlock(&sca_data->lock); | ||
| 205 | if (ret != -EINVAL) | ||
| 206 | return ret; | ||
| 207 | |||
| 208 | return sca3300_error_handler(sca_data); | ||
| 209 | } | ||
| 210 | |||
| 211 | static int sca3300_write_reg(struct sca3300_data *sca_data, u8 reg, int val) | ||
| 212 | { | ||
| 213 | int reg_val = 0; | ||
| 214 | int ret; | ||
| 215 | |||
| 216 | mutex_lock(&sca_data->lock); | ||
| 217 | /* BIT(7) for write operation */ | ||
| 218 | sca_data->txbuf[0] = BIT(7) | (reg << 2); | ||
| 219 | put_unaligned_be16(val, &sca_data->txbuf[1]); | ||
| 220 | ret = sca3300_transfer(sca_data, ®_val); | ||
| 221 | mutex_unlock(&sca_data->lock); | ||
| 222 | if (ret != -EINVAL) | ||
| 223 | return ret; | ||
| 224 | |||
| 225 | return sca3300_error_handler(sca_data); | ||
| 226 | } | ||
| 227 | |||
| 228 | static int sca3300_write_raw(struct iio_dev *indio_dev, | ||
| 229 | struct iio_chan_spec const *chan, | ||
| 230 | int val, int val2, long mask) | ||
| 231 | { | ||
| 232 | struct sca3300_data *data = iio_priv(indio_dev); | ||
| 233 | int reg_val; | ||
| 234 | int ret; | ||
| 235 | int i; | ||
| 236 | |||
| 237 | switch (mask) { | ||
| 238 | case IIO_CHAN_INFO_SCALE: | ||
| 239 | if (val) | ||
| 240 | return -EINVAL; | ||
| 241 | |||
| 242 | for (i = 0; i < ARRAY_SIZE(sca3300_accel_scale); i++) { | ||
| 243 | if (val2 == sca3300_accel_scale[i][1]) | ||
| 244 | return sca3300_write_reg(data, SCA3300_REG_MODE, i); | ||
| 245 | } | ||
| 246 | return -EINVAL; | ||
| 247 | |||
| 248 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | ||
| 249 | ret = sca3300_read_reg(data, SCA3300_REG_MODE, ®_val); | ||
| 250 | if (ret) | ||
| 251 | return ret; | ||
| 252 | /* freq. change is possible only for mode 3 and 4 */ | ||
| 253 | if (reg_val == 2 && val == sca3300_lp_freq[3]) | ||
| 254 | return sca3300_write_reg(data, SCA3300_REG_MODE, 3); | ||
| 255 | if (reg_val == 3 && val == sca3300_lp_freq[2]) | ||
| 256 | return sca3300_write_reg(data, SCA3300_REG_MODE, 2); | ||
| 257 | return -EINVAL; | ||
| 258 | default: | ||
| 259 | return -EINVAL; | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | static int sca3300_read_raw(struct iio_dev *indio_dev, | ||
| 264 | struct iio_chan_spec const *chan, | ||
| 265 | int *val, int *val2, long mask) | ||
| 266 | { | ||
| 267 | struct sca3300_data *data = iio_priv(indio_dev); | ||
| 268 | int ret; | ||
| 269 | int reg_val; | ||
| 270 | |||
| 271 | switch (mask) { | ||
| 272 | case IIO_CHAN_INFO_RAW: | ||
| 273 | ret = sca3300_read_reg(data, chan->address, val); | ||
| 274 | if (ret) | ||
| 275 | return ret; | ||
| 276 | return IIO_VAL_INT; | ||
| 277 | case IIO_CHAN_INFO_SCALE: | ||
| 278 | ret = sca3300_read_reg(data, SCA3300_REG_MODE, ®_val); | ||
| 279 | if (ret) | ||
| 280 | return ret; | ||
| 281 | *val = 0; | ||
| 282 | *val2 = sca3300_accel_scale[reg_val][1]; | ||
| 283 | return IIO_VAL_INT_PLUS_MICRO; | ||
| 284 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | ||
| 285 | ret = sca3300_read_reg(data, SCA3300_REG_MODE, ®_val); | ||
| 286 | if (ret) | ||
| 287 | return ret; | ||
| 288 | *val = sca3300_lp_freq[reg_val]; | ||
| 289 | return IIO_VAL_INT; | ||
| 290 | default: | ||
| 291 | return -EINVAL; | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | static irqreturn_t sca3300_trigger_handler(int irq, void *p) | ||
| 296 | { | ||
| 297 | struct iio_poll_func *pf = p; | ||
| 298 | struct iio_dev *indio_dev = pf->indio_dev; | ||
| 299 | struct sca3300_data *data = iio_priv(indio_dev); | ||
| 300 | int bit, ret, val, i = 0; | ||
| 301 | |||
| 302 | for_each_set_bit(bit, indio_dev->active_scan_mask, | ||
| 303 | indio_dev->masklength) { | ||
| 304 | ret = sca3300_read_reg(data, sca3300_channels[bit].address, | ||
| 305 | &val); | ||
| 306 | if (ret) { | ||
| 307 | dev_err_ratelimited(&data->spi->dev, | ||
| 308 | "failed to read register, error: %d\n", ret); | ||
| 309 | /* handled, but bailing out due to errors */ | ||
| 310 | goto out; | ||
| 311 | } | ||
| 312 | data->scan.channels[i++] = val; | ||
| 313 | } | ||
| 314 | |||
| 315 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, | ||
| 316 | iio_get_time_ns(indio_dev)); | ||
| 317 | out: | ||
| 318 | iio_trigger_notify_done(indio_dev->trig); | ||
| 319 | |||
| 320 | return IRQ_HANDLED; | ||
| 321 | } | ||
| 322 | |||
| 323 | /* | ||
| 324 | * sca3300_init - Device init sequence. See datasheet rev 2 section | ||
| 325 | * 4.2 Start-Up Sequence for details. | ||
| 326 | */ | ||
| 327 | static int sca3300_init(struct sca3300_data *sca_data, | ||
| 328 | struct iio_dev *indio_dev) | ||
| 329 | { | ||
| 330 | int value = 0; | ||
| 331 | int ret; | ||
| 332 | |||
| 333 | ret = sca3300_write_reg(sca_data, SCA3300_REG_MODE, | ||
| 334 | SCA3300_MODE_SW_RESET); | ||
| 335 | if (ret) | ||
| 336 | return ret; | ||
| 337 | |||
| 338 | /* | ||
| 339 | * Wait 1ms after SW-reset command. | ||
| 340 | * Wait 15ms for settling of signal paths. | ||
| 341 | */ | ||
| 342 | usleep_range(16e3, 50e3); | ||
| 343 | |||
| 344 | ret = sca3300_read_reg(sca_data, SCA3300_REG_WHOAMI, &value); | ||
| 345 | if (ret) | ||
| 346 | return ret; | ||
| 347 | |||
| 348 | if (value != SCA3300_WHOAMI_ID) { | ||
| 349 | dev_err(&sca_data->spi->dev, | ||
| 350 | "device id not expected value, %d != %u\n", | ||
| 351 | value, SCA3300_WHOAMI_ID); | ||
| 352 | return -ENODEV; | ||
| 353 | } | ||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | static int sca3300_debugfs_reg_access(struct iio_dev *indio_dev, | ||
| 358 | unsigned int reg, unsigned int writeval, | ||
| 359 | unsigned int *readval) | ||
| 360 | { | ||
| 361 | struct sca3300_data *data = iio_priv(indio_dev); | ||
| 362 | int value; | ||
| 363 | int ret; | ||
| 364 | |||
| 365 | if (reg > SCA3300_REG_SELBANK) | ||
| 366 | return -EINVAL; | ||
| 367 | |||
| 368 | if (!readval) | ||
| 369 | return sca3300_write_reg(data, reg, writeval); | ||
| 370 | |||
| 371 | ret = sca3300_read_reg(data, reg, &value); | ||
| 372 | if (ret) | ||
| 373 | return ret; | ||
| 374 | |||
| 375 | *readval = value; | ||
| 376 | |||
| 377 | return 0; | ||
| 378 | } | ||
| 379 | |||
| 380 | static int sca3300_read_avail(struct iio_dev *indio_dev, | ||
| 381 | struct iio_chan_spec const *chan, | ||
| 382 | const int **vals, int *type, int *length, | ||
| 383 | long mask) | ||
| 384 | { | ||
| 385 | switch (mask) { | ||
| 386 | case IIO_CHAN_INFO_SCALE: | ||
| 387 | *vals = (const int *)sca3300_accel_scale; | ||
| 388 | *length = ARRAY_SIZE(sca3300_accel_scale) * 2 - 2; | ||
| 389 | *type = IIO_VAL_INT_PLUS_MICRO; | ||
| 390 | return IIO_AVAIL_LIST; | ||
| 391 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | ||
| 392 | *vals = &sca3300_lp_freq[2]; | ||
| 393 | *length = 2; | ||
| 394 | *type = IIO_VAL_INT; | ||
| 395 | return IIO_AVAIL_LIST; | ||
| 396 | default: | ||
| 397 | return -EINVAL; | ||
| 398 | } | ||
| 399 | } | ||
| 400 | |||
| 401 | static const struct iio_info sca3300_info = { | ||
| 402 | .read_raw = sca3300_read_raw, | ||
| 403 | .write_raw = sca3300_write_raw, | ||
| 404 | .debugfs_reg_access = &sca3300_debugfs_reg_access, | ||
| 405 | .read_avail = sca3300_read_avail, | ||
| 406 | }; | ||
| 407 | |||
| 408 | static int sca3300_probe(struct spi_device *spi) | ||
| 409 | { | ||
| 410 | struct sca3300_data *sca_data; | ||
| 411 | struct iio_dev *indio_dev; | ||
| 412 | int ret; | ||
| 413 | |||
| 414 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*sca_data)); | ||
| 415 | if (!indio_dev) | ||
| 416 | return -ENOMEM; | ||
| 417 | |||
| 418 | sca_data = iio_priv(indio_dev); | ||
| 419 | mutex_init(&sca_data->lock); | ||
| 420 | sca_data->spi = spi; | ||
| 421 | |||
| 422 | crc8_populate_msb(sca3300_crc_table, SCA3300_CRC8_POLYNOMIAL); | ||
| 423 | |||
| 424 | indio_dev->info = &sca3300_info; | ||
| 425 | indio_dev->name = SCA3300_ALIAS; | ||
| 426 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
| 427 | indio_dev->channels = sca3300_channels; | ||
| 428 | indio_dev->num_channels = ARRAY_SIZE(sca3300_channels); | ||
| 429 | indio_dev->available_scan_masks = sca3300_scan_masks; | ||
| 430 | |||
| 431 | ret = sca3300_init(sca_data, indio_dev); | ||
| 432 | if (ret) { | ||
| 433 | dev_err(&spi->dev, "failed to init device, error: %d\n", ret); | ||
| 434 | return ret; | ||
| 435 | } | ||
| 436 | |||
| 437 | ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, | ||
| 438 | iio_pollfunc_store_time, | ||
| 439 | sca3300_trigger_handler, NULL); | ||
| 440 | if (ret) { | ||
| 441 | dev_err(&spi->dev, | ||
| 442 | "iio triggered buffer setup failed, error: %d\n", ret); | ||
| 443 | return ret; | ||
| 444 | } | ||
| 445 | |||
| 446 | ret = devm_iio_device_register(&spi->dev, indio_dev); | ||
| 447 | if (ret) { | ||
| 448 | dev_err(&spi->dev, "iio device register failed, error: %d\n", | ||
| 449 | ret); | ||
| 450 | } | ||
| 451 | |||
| 452 | return ret; | ||
| 453 | } | ||
| 454 | |||
| 455 | static const struct of_device_id sca3300_dt_ids[] = { | ||
| 456 | { .compatible = "murata,sca3300"}, | ||
| 457 | {} | ||
| 458 | }; | ||
| 459 | MODULE_DEVICE_TABLE(of, sca3300_dt_ids); | ||
| 460 | |||
| 461 | static struct spi_driver sca3300_driver = { | ||
| 462 | .driver = { | ||
| 463 | .name = SCA3300_ALIAS, | ||
| 464 | .of_match_table = sca3300_dt_ids, | ||
| 465 | }, | ||
| 466 | .probe = sca3300_probe, | ||
| 467 | }; | ||
| 468 | module_spi_driver(sca3300_driver); | ||
| 469 | |||
| 470 | MODULE_AUTHOR("Tomas Melin <tomas.melin@vaisala.com>"); | ||
| 471 | MODULE_DESCRIPTION("Murata SCA3300 SPI Accelerometer"); | ||
| 472 | MODULE_LICENSE("GPL v2"); | ||
| @@ -62,18 +62,6 @@ enum st_accel_type { · 61 unmodified lines | |||
| 62 | #define LIS2DE12_ACCEL_DEV_NAME "lis2de12" | 62 | #define LIS2DE12_ACCEL_DEV_NAME "lis2de12" |
| 63 | #define LIS2HH12_ACCEL_DEV_NAME "lis2hh12" | 63 | #define LIS2HH12_ACCEL_DEV_NAME "lis2hh12" |
| 64 | 64 | ||
| 65 | /** | ||
| 66 | * struct st_sensors_platform_data - default accel platform data | ||
| 67 | * @drdy_int_pin: default accel DRDY is available on INT1 pin. | ||
| 68 | */ | ||
| 69 | static __maybe_unused const struct st_sensors_platform_data default_accel_pdata = { | ||
| 70 | .drdy_int_pin = 1, | ||
| 71 | }; | ||
| 72 | |||
| 73 | const struct st_sensor_settings *st_accel_get_settings(const char *name); | ||
| 74 | int st_accel_common_probe(struct iio_dev *indio_dev); | ||
| 75 | void st_accel_common_remove(struct iio_dev *indio_dev); | ||
| 76 | |||
| 77 | #ifdef CONFIG_IIO_BUFFER | 65 | #ifdef CONFIG_IIO_BUFFER |
| 78 | int st_accel_allocate_ring(struct iio_dev *indio_dev); | 66 | int st_accel_allocate_ring(struct iio_dev *indio_dev); |
| 79 | void st_accel_deallocate_ring(struct iio_dev *indio_dev); | 67 | void st_accel_deallocate_ring(struct iio_dev *indio_dev); |
| @@ -41,51 +41,74 @@ · 40 unmodified lines | |||
| 41 | #define ST_ACCEL_FS_AVL_200G 200 | 41 | #define ST_ACCEL_FS_AVL_200G 200 |
| 42 | #define ST_ACCEL_FS_AVL_400G 400 | 42 | #define ST_ACCEL_FS_AVL_400G 400 |
| 43 | 43 | ||
| 44 | static const struct iio_mount_matrix * | ||
| 45 | st_accel_get_mount_matrix(const struct iio_dev *indio_dev, | ||
| 46 | const struct iio_chan_spec *chan) | ||
| 47 | { | ||
| 48 | struct st_sensor_data *adata = iio_priv(indio_dev); | ||
| 49 | |||
| 50 | return &adata->mount_matrix; | ||
| 51 | } | ||
| 52 | |||
| 53 | static const struct iio_chan_spec_ext_info st_accel_mount_matrix_ext_info[] = { | ||
| 54 | IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_accel_get_mount_matrix), | ||
| 55 | { } | ||
| 56 | }; | ||
| 57 | |||
| 44 | static const struct iio_chan_spec st_accel_8bit_channels[] = { | 58 | static const struct iio_chan_spec st_accel_8bit_channels[] = { |
| 45 | ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, | 59 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, |
| 46 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 60 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 47 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 8, 8, | 61 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 8, 8, |
| 48 | ST_ACCEL_DEFAULT_OUT_X_L_ADDR+1), | 62 | ST_ACCEL_DEFAULT_OUT_X_L_ADDR+1, |
| 49 | ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, | 63 | st_accel_mount_matrix_ext_info), |
| 64 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, | ||
| 50 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 65 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 51 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 8, 8, | 66 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 8, 8, |
| 52 | ST_ACCEL_DEFAULT_OUT_Y_L_ADDR+1), | 67 | ST_ACCEL_DEFAULT_OUT_Y_L_ADDR+1, |
| 53 | ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, | 68 | st_accel_mount_matrix_ext_info), |
| 69 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, | ||
| 54 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 70 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 55 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 8, 8, | 71 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 8, 8, |
| 56 | ST_ACCEL_DEFAULT_OUT_Z_L_ADDR+1), | 72 | ST_ACCEL_DEFAULT_OUT_Z_L_ADDR+1, |
| 73 | st_accel_mount_matrix_ext_info), | ||
| 57 | IIO_CHAN_SOFT_TIMESTAMP(3) | 74 | IIO_CHAN_SOFT_TIMESTAMP(3) |
| 58 | }; | 75 | }; |
| 59 | 76 | ||
| 60 | static const struct iio_chan_spec st_accel_12bit_channels[] = { | 77 | static const struct iio_chan_spec st_accel_12bit_channels[] = { |
| 61 | ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, | 78 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, |
| 62 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 79 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 63 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 12, 16, | 80 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 12, 16, |
| 64 | ST_ACCEL_DEFAULT_OUT_X_L_ADDR), | 81 | ST_ACCEL_DEFAULT_OUT_X_L_ADDR, |
| 65 | ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, | 82 | st_accel_mount_matrix_ext_info), |
| 83 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, | ||
| 66 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 84 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 67 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 12, 16, | 85 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 12, 16, |
| 68 | ST_ACCEL_DEFAULT_OUT_Y_L_ADDR), | 86 | ST_ACCEL_DEFAULT_OUT_Y_L_ADDR, |
| 69 | ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, | 87 | st_accel_mount_matrix_ext_info), |
| 88 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, | ||
| 70 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 89 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 71 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 12, 16, | 90 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 12, 16, |
| 72 | ST_ACCEL_DEFAULT_OUT_Z_L_ADDR), | 91 | ST_ACCEL_DEFAULT_OUT_Z_L_ADDR, |
| 92 | st_accel_mount_matrix_ext_info), | ||
| 73 | IIO_CHAN_SOFT_TIMESTAMP(3) | 93 | IIO_CHAN_SOFT_TIMESTAMP(3) |
| 74 | }; | 94 | }; |
| 75 | 95 | ||
| 76 | static const struct iio_chan_spec st_accel_16bit_channels[] = { | 96 | static const struct iio_chan_spec st_accel_16bit_channels[] = { |
| 77 | ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, | 97 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, |
| 78 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 98 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 79 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, | 99 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, |
| 80 | ST_ACCEL_DEFAULT_OUT_X_L_ADDR), | 100 | ST_ACCEL_DEFAULT_OUT_X_L_ADDR, |
| 81 | ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, | 101 | st_accel_mount_matrix_ext_info), |
| 102 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, | ||
| 82 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 103 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 83 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, | 104 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, |
| 84 | ST_ACCEL_DEFAULT_OUT_Y_L_ADDR), | 105 | ST_ACCEL_DEFAULT_OUT_Y_L_ADDR, |
| 85 | ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, | 106 | st_accel_mount_matrix_ext_info), |
| 107 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL, | ||
| 86 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 108 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 87 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, | 109 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, |
| 88 | ST_ACCEL_DEFAULT_OUT_Z_L_ADDR), | 110 | ST_ACCEL_DEFAULT_OUT_Z_L_ADDR, |
| 111 | st_accel_mount_matrix_ext_info), | ||
| 89 | IIO_CHAN_SOFT_TIMESTAMP(3) | 112 | IIO_CHAN_SOFT_TIMESTAMP(3) |
| 90 | }; | 113 | }; |
| 91 | 114 | ||
| @@ -980,7 +1003,99 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { · 888 unmodified lines | |||
| 980 | .multi_read_bit = true, | 1003 | .multi_read_bit = true, |
| 981 | .bootime = 2, | 1004 | .bootime = 2, |
| 982 | }, | 1005 | }, |
| 1006 | { | ||
| 1007 | .wai = 0x49, | ||
| 1008 | .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, | ||
| 1009 | .sensors_supported = { | ||
| 1010 | [0] = LSM9DS0_IMU_DEV_NAME, | ||
| 1011 | }, | ||
| 1012 | .ch = (struct iio_chan_spec *)st_accel_16bit_channels, | ||
| 1013 | .odr = { | ||
| 1014 | .addr = 0x20, | ||
| 1015 | .mask = GENMASK(7, 4), | ||
| 1016 | .odr_avl = { | ||
| 1017 | { 3, 0x01, }, | ||
| 1018 | { 6, 0x02, }, | ||
| 1019 | { 12, 0x03, }, | ||
| 1020 | { 25, 0x04, }, | ||
| 1021 | { 50, 0x05, }, | ||
| 1022 | { 100, 0x06, }, | ||
| 1023 | { 200, 0x07, }, | ||
| 1024 | { 400, 0x08, }, | ||
| 1025 | { 800, 0x09, }, | ||
| 1026 | { 1600, 0x0a, }, | ||
| 1027 | }, | ||
| 1028 | }, | ||
| 1029 | .pw = { | ||
| 1030 | .addr = 0x20, | ||
| 1031 | .mask = GENMASK(7, 4), | ||
| 1032 | .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, | ||
| 1033 | }, | ||
| 1034 | .enable_axis = { | ||
| 1035 | .addr = ST_SENSORS_DEFAULT_AXIS_ADDR, | ||
| 1036 | .mask = ST_SENSORS_DEFAULT_AXIS_MASK, | ||
| 1037 | }, | ||
| 1038 | .fs = { | ||
| 1039 | .addr = 0x21, | ||
| 1040 | .mask = GENMASK(5, 3), | ||
| 1041 | .fs_avl = { | ||
| 1042 | [0] = { | ||
| 1043 | .num = ST_ACCEL_FS_AVL_2G, | ||
| 1044 | .value = 0x00, | ||
| 1045 | .gain = IIO_G_TO_M_S_2(61), | ||
| 1046 | }, | ||
| 1047 | [1] = { | ||
| 1048 | .num = ST_ACCEL_FS_AVL_4G, | ||
| 1049 | .value = 0x01, | ||
| 1050 | .gain = IIO_G_TO_M_S_2(122), | ||
| 1051 | }, | ||
| 1052 | [2] = { | ||
| 1053 | .num = ST_ACCEL_FS_AVL_6G, | ||
| 1054 | .value = 0x02, | ||
| 1055 | .gain = IIO_G_TO_M_S_2(183), | ||
| 1056 | }, | ||
| 1057 | [3] = { | ||
| 1058 | .num = ST_ACCEL_FS_AVL_8G, | ||
| 1059 | .value = 0x03, | ||
| 1060 | .gain = IIO_G_TO_M_S_2(244), | ||
| 1061 | }, | ||
| 1062 | [4] = { | ||
| 1063 | .num = ST_ACCEL_FS_AVL_16G, | ||
| 1064 | .value = 0x04, | ||
| 1065 | .gain = IIO_G_TO_M_S_2(732), | ||
| 1066 | }, | ||
| 1067 | }, | ||
| 1068 | }, | ||
| 1069 | .bdu = { | ||
| 1070 | .addr = 0x20, | ||
| 1071 | .mask = BIT(3), | ||
| 1072 | }, | ||
| 1073 | .drdy_irq = { | ||
| 1074 | .int1 = { | ||
| 1075 | .addr = 0x22, | ||
| 1076 | .mask = BIT(2), | ||
| 1077 | }, | ||
| 1078 | .int2 = { | ||
| 1079 | .addr = 0x23, | ||
| 1080 | .mask = BIT(3), | ||
| 1081 | }, | ||
| 1082 | .stat_drdy = { | ||
| 1083 | .addr = ST_SENSORS_DEFAULT_STAT_ADDR, | ||
| 1084 | .mask = GENMASK(2, 0), | ||
| 1085 | }, | ||
| 1086 | }, | ||
| 1087 | .sim = { | ||
| 1088 | .addr = 0x21, | ||
| 1089 | .value = BIT(0), | ||
| 1090 | }, | ||
| 1091 | .multi_read_bit = true, | ||
| 1092 | .bootime = 2, | ||
| 1093 | }, | ||
| 1094 | }; | ||
| 983 | 1095 | ||
| 1096 | /* Default accel DRDY is available on INT1 pin */ | ||
| 1097 | static const struct st_sensors_platform_data default_accel_pdata = { | ||
| 1098 | .drdy_int_pin = 1, | ||
| 984 | }; | 1099 | }; |
| 985 | 1100 | ||
| 986 | static int st_accel_read_raw(struct iio_dev *indio_dev, | 1101 | static int st_accel_read_raw(struct iio_dev *indio_dev, |
| @@ -1070,25 +1185,10 @@ static const struct iio_trigger_ops st_accel_trigger_ops = { · 83 unmodified lines | |||
| 1070 | #endif | 1185 | #endif |
| 1071 | 1186 | ||
| 1072 | #ifdef CONFIG_ACPI | 1187 | #ifdef CONFIG_ACPI |
| 1073 | static const struct iio_mount_matrix * | ||
| 1074 | get_mount_matrix(const struct iio_dev *indio_dev, | ||
| 1075 | const struct iio_chan_spec *chan) | ||
| 1076 | { | ||
| 1077 | struct st_sensor_data *adata = iio_priv(indio_dev); | ||
| 1078 | |||
| 1079 | return adata->mount_matrix; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | static const struct iio_chan_spec_ext_info mount_matrix_ext_info[] = { | ||
| 1083 | IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, get_mount_matrix), | ||
| 1084 | { }, | ||
| 1085 | }; | ||
| 1086 | |||
| 1087 | /* Read ST-specific _ONT orientation data from ACPI and generate an | 1188 | /* Read ST-specific _ONT orientation data from ACPI and generate an |
| 1088 | * appropriate mount matrix. | 1189 | * appropriate mount matrix. |
| 1089 | */ | 1190 | */ |
| 1090 | static int apply_acpi_orientation(struct iio_dev *indio_dev, | 1191 | static int apply_acpi_orientation(struct iio_dev *indio_dev) |
| 1091 | struct iio_chan_spec *channels) | ||
| 1092 | { | 1192 | { |
| 1093 | struct st_sensor_data *adata = iio_priv(indio_dev); | 1193 | struct st_sensor_data *adata = iio_priv(indio_dev); |
| 1094 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | 1194 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
| @@ -1177,14 +1277,6 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev, · 82 unmodified lines | |||
| 1177 | } | 1277 | } |
| 1178 | 1278 | ||
| 1179 | /* Convert our integer matrix to a string-based iio_mount_matrix */ | 1279 | /* Convert our integer matrix to a string-based iio_mount_matrix */ |
| 1180 | adata->mount_matrix = devm_kmalloc(&indio_dev->dev, | ||
| 1181 | sizeof(*adata->mount_matrix), | ||
| 1182 | GFP_KERNEL); | ||
| 1183 | if (!adata->mount_matrix) { | ||
| 1184 | ret = -ENOMEM; | ||
| 1185 | goto out; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | for (i = 0; i < 3; i++) { | 1280 | for (i = 0; i < 3; i++) { |
| 1189 | for (j = 0; j < 3; j++) { | 1281 | for (j = 0; j < 3; j++) { |
| 1190 | int matrix_val = final_ont[i][j]; | 1282 | int matrix_val = final_ont[i][j]; |
| @@ -1203,26 +1295,25 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev, · 12 unmodified lines | |||
| 1203 | default: | 1295 | default: |
| 1204 | goto out; | 1296 | goto out; |
| 1205 | } | 1297 | } |
| 1206 | adata->mount_matrix->rotation[i * 3 + j] = str_value; | 1298 | adata->mount_matrix.rotation[i * 3 + j] = str_value; |
| 1207 | } | 1299 | } |
| 1208 | } | 1300 | } |
| 1209 | 1301 | ||
| 1210 | /* Expose the mount matrix via ext_info */ | ||
| 1211 | for (i = 0; i < indio_dev->num_channels; i++) | ||
| 1212 | channels[i].ext_info = mount_matrix_ext_info; | ||
| 1213 | |||
| 1214 | ret = 0; | 1302 | ret = 0; |
| 1215 | dev_info(&indio_dev->dev, "computed mount matrix from ACPI\n"); | 1303 | dev_info(&indio_dev->dev, "computed mount matrix from ACPI\n"); |
| 1216 | 1304 | ||
| 1217 | out: | 1305 | out: |
| 1218 | kfree(buffer.pointer); | 1306 | kfree(buffer.pointer); |
| 1307 | if (ret) | ||
| 1308 | dev_dbg(&indio_dev->dev, | ||
| 1309 | "failed to apply ACPI orientation data: %d\n", ret); | ||
| 1310 | |||
| 1219 | return ret; | 1311 | return ret; |
| 1220 | } | 1312 | } |
| 1221 | #else /* !CONFIG_ACPI */ | 1313 | #else /* !CONFIG_ACPI */ |
| 1222 | static int apply_acpi_orientation(struct iio_dev *indio_dev, | 1314 | static int apply_acpi_orientation(struct iio_dev *indio_dev) |
| 1223 | struct iio_chan_spec *channels) | ||
| 1224 | { | 1315 | { |
| 1225 | return 0; | 1316 | return -EINVAL; |
| 1226 | } | 1317 | } |
| 1227 | #endif | 1318 | #endif |
| 1228 | 1319 | ||
| @@ -1248,38 +1339,30 @@ int st_accel_common_probe(struct iio_dev *indio_dev) · 19 unmodified lines | |||
| 1248 | { | 1339 | { |
| 1249 | struct st_sensor_data *adata = iio_priv(indio_dev); | 1340 | struct st_sensor_data *adata = iio_priv(indio_dev); |
| 1250 | struct st_sensors_platform_data *pdata = dev_get_platdata(adata->dev); | 1341 | struct st_sensors_platform_data *pdata = dev_get_platdata(adata->dev); |
| 1251 | struct iio_chan_spec *channels; | ||
| 1252 | size_t channels_size; | ||
| 1253 | int err; | 1342 | int err; |
| 1254 | 1343 | ||
| 1255 | indio_dev->modes = INDIO_DIRECT_MODE; | 1344 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 1256 | indio_dev->info = &accel_info; | 1345 | indio_dev->info = &accel_info; |
| 1257 | 1346 | ||
| 1258 | err = st_sensors_power_enable(indio_dev); | ||
| 1259 | if (err) | ||
| 1260 | return err; | ||
| 1261 | |||
| 1262 | err = st_sensors_verify_id(indio_dev); | 1347 | err = st_sensors_verify_id(indio_dev); |
| 1263 | if (err < 0) | 1348 | if (err < 0) |
| 1264 | goto st_accel_power_off; | 1349 | return err; |
| 1265 | 1350 | ||
| 1266 | adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS; | 1351 | adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS; |
| 1352 | indio_dev->channels = adata->sensor_settings->ch; | ||
| 1267 | indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; | 1353 | indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; |
| 1268 | 1354 | ||
| 1269 | channels_size = indio_dev->num_channels * sizeof(struct iio_chan_spec); | 1355 | /* |
| 1270 | channels = devm_kmemdup(&indio_dev->dev, | 1356 | * First try specific ACPI methods to retrieve orientation then try the |
| 1271 | adata->sensor_settings->ch, | 1357 | * generic function. |
| 1272 | channels_size, GFP_KERNEL); | 1358 | */ |
| 1273 | if (!channels) { | 1359 | err = apply_acpi_orientation(indio_dev); |
| 1274 | err = -ENOMEM; | 1360 | if (err) { |
| 1275 | goto st_accel_power_off; | 1361 | err = iio_read_mount_matrix(adata->dev, &adata->mount_matrix); |
| 1362 | if (err) | ||
| 1363 | return err; | ||
| 1276 | } | 1364 | } |
| 1277 | 1365 | ||
| 1278 | if (apply_acpi_orientation(indio_dev, channels)) | ||
| 1279 | dev_warn(&indio_dev->dev, | ||
| 1280 | "failed to apply ACPI orientation data: %d\n", err); | ||
| 1281 | |||
| 1282 | indio_dev->channels = channels; | ||
| 1283 | adata->current_fullscale = &adata->sensor_settings->fs.fs_avl[0]; | 1366 | adata->current_fullscale = &adata->sensor_settings->fs.fs_avl[0]; |
| 1284 | adata->odr = adata->sensor_settings->odr.odr_avl[0].hz; | 1367 | adata->odr = adata->sensor_settings->odr.odr_avl[0].hz; |
| 1285 | 1368 | ||
| @@ -1288,11 +1371,11 @@ int st_accel_common_probe(struct iio_dev *indio_dev) · 2 unmodified lines | |||
| 1288 | 1371 | ||
| 1289 | err = st_sensors_init_sensor(indio_dev, pdata); | 1372 | err = st_sensors_init_sensor(indio_dev, pdata); |
| 1290 | if (err < 0) | 1373 | if (err < 0) |
| 1291 | goto st_accel_power_off; | 1374 | return err; |
| 1292 | 1375 | ||
| 1293 | err = st_accel_allocate_ring(indio_dev); | 1376 | err = st_accel_allocate_ring(indio_dev); |
| 1294 | if (err < 0) | 1377 | if (err < 0) |
| 1295 | goto st_accel_power_off; | 1378 | return err; |
| 1296 | 1379 | ||
| 1297 | if (adata->irq > 0) { | 1380 | if (adata->irq > 0) { |
| 1298 | err = st_sensors_allocate_trigger(indio_dev, | 1381 | err = st_sensors_allocate_trigger(indio_dev, |
| @@ -1315,9 +1398,6 @@ st_accel_device_register_error: · 16 unmodified lines | |||
| 1315 | st_sensors_deallocate_trigger(indio_dev); | 1398 | st_sensors_deallocate_trigger(indio_dev); |
| 1316 | st_accel_probe_trigger_error: | 1399 | st_accel_probe_trigger_error: |
| 1317 | st_accel_deallocate_ring(indio_dev); | 1400 | st_accel_deallocate_ring(indio_dev); |
| 1318 | st_accel_power_off: | ||
| 1319 | st_sensors_power_disable(indio_dev); | ||
| 1320 | |||
| 1321 | return err; | 1401 | return err; |
| 1322 | } | 1402 | } |
| 1323 | EXPORT_SYMBOL(st_accel_common_probe); | 1403 | EXPORT_SYMBOL(st_accel_common_probe); |
| @@ -1326,8 +1406,6 @@ void st_accel_common_remove(struct iio_dev *indio_dev) · 2 unmodified lines | |||
| 1326 | { | 1406 | { |
| 1327 | struct st_sensor_data *adata = iio_priv(indio_dev); | 1407 | struct st_sensor_data *adata = iio_priv(indio_dev); |
| 1328 | 1408 | ||
| 1329 | st_sensors_power_disable(indio_dev); | ||
| 1330 | |||
| 1331 | iio_device_unregister(indio_dev); | 1409 | iio_device_unregister(indio_dev); |
| 1332 | if (adata->irq > 0) | 1410 | if (adata->irq > 0) |
| 1333 | st_sensors_deallocate_trigger(indio_dev); | 1411 | st_sensors_deallocate_trigger(indio_dev); |
| @@ -174,16 +174,29 @@ static int st_accel_i2c_probe(struct i2c_client *client) · 173 unmodified lines | |||
| 174 | if (ret < 0) | 174 | if (ret < 0) |
| 175 | return ret; | 175 | return ret; |
| 176 | 176 | ||
| 177 | ret = st_sensors_power_enable(indio_dev); | ||
| 178 | if (ret) | ||
| 179 | return ret; | ||
| 180 | |||
| 177 | ret = st_accel_common_probe(indio_dev); | 181 | ret = st_accel_common_probe(indio_dev); |
| 178 | if (ret < 0) | 182 | if (ret < 0) |
| 179 | return ret; | 183 | goto st_accel_power_off; |
| 180 | 184 | ||
| 181 | return 0; | 185 | return 0; |
| 186 | |||
| 187 | st_accel_power_off: | ||
| 188 | st_sensors_power_disable(indio_dev); | ||
| 189 | |||
| 190 | return ret; | ||
| 182 | } | 191 | } |
| 183 | 192 | ||
| 184 | static int st_accel_i2c_remove(struct i2c_client *client) | 193 | static int st_accel_i2c_remove(struct i2c_client *client) |
| 185 | { | 194 | { |
| 186 | st_accel_common_remove(i2c_get_clientdata(client)); | 195 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 196 | |||
| 197 | st_sensors_power_disable(indio_dev); | ||
| 198 | |||
| 199 | st_accel_common_remove(indio_dev); | ||
| 187 | 200 | ||
| 188 | return 0; | 201 | return 0; |
| 189 | } | 202 | } |
| @@ -123,16 +123,29 @@ static int st_accel_spi_probe(struct spi_device *spi) · 122 unmodified lines | |||
| 123 | if (err < 0) | 123 | if (err < 0) |
| 124 | return err; | 124 | return err; |
| 125 | 125 | ||
| 126 | err = st_sensors_power_enable(indio_dev); | ||
| 127 | if (err) | ||
| 128 | return err; | ||
| 129 | |||
| 126 | err = st_accel_common_probe(indio_dev); | 130 | err = st_accel_common_probe(indio_dev); |
| 127 | if (err < 0) | 131 | if (err < 0) |
| 128 | return err; | 132 | goto st_accel_power_off; |
| 129 | 133 | ||
| 130 | return 0; | 134 | return 0; |
| 135 | |||
| 136 | st_accel_power_off: | ||
| 137 | st_sensors_power_disable(indio_dev); | ||
| 138 | |||
| 139 | return err; | ||
| 131 | } | 140 | } |
| 132 | 141 | ||
| 133 | static int st_accel_spi_remove(struct spi_device *spi) | 142 | static int st_accel_spi_remove(struct spi_device *spi) |
| 134 | { | 143 | { |
| 135 | st_accel_common_remove(spi_get_drvdata(spi)); | 144 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
| 145 | |||
| 146 | st_sensors_power_disable(indio_dev); | ||
| 147 | |||
| 148 | st_accel_common_remove(indio_dev); | ||
| 136 | 149 | ||
| 137 | return 0; | 150 | return 0; |
| 138 | } | 151 | } |
| @@ -7,7 +7,6 @@ · 6 unmodified lines | |||
| 7 | * IIO driver for STK8312; 7-bit I2C address: 0x3D. | 7 | * IIO driver for STK8312; 7-bit I2C address: 0x3D. |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/acpi.h> | ||
| 11 | #include <linux/i2c.h> | 10 | #include <linux/i2c.h> |
| 12 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
| 13 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| @@ -103,7 +102,11 @@ struct stk8312_data { · 89 unmodified lines | |||
| 103 | u8 mode; | 102 | u8 mode; |
| 104 | struct iio_trigger *dready_trig; | 103 | struct iio_trigger *dready_trig; |
| 105 | bool dready_trigger_on; | 104 | bool dready_trigger_on; |
| 106 | s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 64-bit timestamp */ | 105 | /* Ensure timestamp is naturally aligned */ |
| 106 | struct { | ||
| 107 | s8 chans[3]; | ||
| 108 | s64 timestamp __aligned(8); | ||
| 109 | } scan; | ||
| 107 | }; | 110 | }; |
| 108 | 111 | ||
| 109 | static IIO_CONST_ATTR(in_accel_scale_available, STK8312_SCALE_AVAIL); | 112 | static IIO_CONST_ATTR(in_accel_scale_available, STK8312_SCALE_AVAIL); |
| @@ -438,7 +441,7 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p) · 328 unmodified lines | |||
| 438 | ret = i2c_smbus_read_i2c_block_data(data->client, | 441 | ret = i2c_smbus_read_i2c_block_data(data->client, |
| 439 | STK8312_REG_XOUT, | 442 | STK8312_REG_XOUT, |
| 440 | STK8312_ALL_CHANNEL_SIZE, | 443 | STK8312_ALL_CHANNEL_SIZE, |
| 441 | data->buffer); | 444 | data->scan.chans); |
| 442 | if (ret < STK8312_ALL_CHANNEL_SIZE) { | 445 | if (ret < STK8312_ALL_CHANNEL_SIZE) { |
| 443 | dev_err(&data->client->dev, "register read failed\n"); | 446 | dev_err(&data->client->dev, "register read failed\n"); |
| 444 | mutex_unlock(&data->lock); | 447 | mutex_unlock(&data->lock); |
| @@ -452,12 +455,12 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p) · 7 unmodified lines | |||
| 452 | mutex_unlock(&data->lock); | 455 | mutex_unlock(&data->lock); |
| 453 | goto err; | 456 | goto err; |
| 454 | } | 457 | } |
| 455 | data->buffer[i++] = ret; | 458 | data->scan.chans[i++] = ret; |
| 456 | } | 459 | } |
| 457 | } | 460 | } |
| 458 | mutex_unlock(&data->lock); | 461 | mutex_unlock(&data->lock); |
| 459 | 462 | ||
| 460 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 463 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, |
| 461 | pf->timestamp); | 464 | pf->timestamp); |
| 462 | err: | 465 | err: |
| 463 | iio_trigger_notify_done(indio_dev->trig); | 466 | iio_trigger_notify_done(indio_dev->trig); |
| @@ -552,7 +555,7 @@ static int stk8312_probe(struct i2c_client *client, · 88 unmodified lines | |||
| 552 | data->dready_trig = devm_iio_trigger_alloc(&client->dev, | 555 | data->dready_trig = devm_iio_trigger_alloc(&client->dev, |
| 553 | "%s-dev%d", | 556 | "%s-dev%d", |
| 554 | indio_dev->name, | 557 | indio_dev->name, |
| 555 | indio_dev->id); | 558 | iio_device_id(indio_dev)); |
| 556 | if (!data->dready_trig) { | 559 | if (!data->dready_trig) { |
| 557 | ret = -ENOMEM; | 560 | ret = -ENOMEM; |
| 558 | goto err_power_off; | 561 | goto err_power_off; |
| @@ -635,23 +638,17 @@ static SIMPLE_DEV_PM_OPS(stk8312_pm_ops, stk8312_suspend, stk8312_resume); · 76 unmodified lines | |||
| 635 | #endif | 638 | #endif |
| 636 | 639 | ||
| 637 | static const struct i2c_device_id stk8312_i2c_id[] = { | 640 | static const struct i2c_device_id stk8312_i2c_id[] = { |
| 638 | {"STK8312", 0}, | 641 | /* Deprecated in favour of lowercase form */ |
| 642 | { "STK8312", 0 }, | ||
| 643 | { "stk8312", 0 }, | ||
| 639 | {} | 644 | {} |
| 640 | }; | 645 | }; |
| 641 | MODULE_DEVICE_TABLE(i2c, stk8312_i2c_id); | 646 | MODULE_DEVICE_TABLE(i2c, stk8312_i2c_id); |
| 642 | 647 | ||
| 643 | static const struct acpi_device_id stk8312_acpi_id[] = { | ||
| 644 | {"STK8312", 0}, | ||
| 645 | {} | ||
| 646 | }; | ||
| 647 | |||
| 648 | MODULE_DEVICE_TABLE(acpi, stk8312_acpi_id); | ||
| 649 | |||
| 650 | static struct i2c_driver stk8312_driver = { | 648 | static struct i2c_driver stk8312_driver = { |
| 651 | .driver = { | 649 | .driver = { |
| 652 | .name = STK8312_DRIVER_NAME, | 650 | .name = STK8312_DRIVER_NAME, |
| 653 | .pm = STK8312_PM_OPS, | 651 | .pm = STK8312_PM_OPS, |
| 654 | .acpi_match_table = ACPI_PTR(stk8312_acpi_id), | ||
| 655 | }, | 652 | }, |
| 656 | .probe = stk8312_probe, | 653 | .probe = stk8312_probe, |
| 657 | .remove = stk8312_remove, | 654 | .remove = stk8312_remove, |
| @@ -91,12 +91,11 @@ struct stk8ba50_data { · 90 unmodified lines | |||
| 91 | u8 sample_rate_idx; | 91 | u8 sample_rate_idx; |
| 92 | struct iio_trigger *dready_trig; | 92 | struct iio_trigger *dready_trig; |
| 93 | bool dready_trigger_on; | 93 | bool dready_trigger_on; |
| 94 | /* | 94 | /* Ensure timestamp is naturally aligned */ |
| 95 | * 3 x 16-bit channels (10-bit data, 6-bit padding) + | 95 | struct { |
| 96 | * 1 x 16 padding + | 96 | s16 chans[3]; |
| 97 | * 4 x 16 64-bit timestamp | 97 | s64 timetamp __aligned(8); |
| 98 | */ | 98 | } scan; |
| 99 | s16 buffer[8]; | ||
| 100 | }; | 99 | }; |
| 101 | 100 | ||
| 102 | #define STK8BA50_ACCEL_CHANNEL(index, reg, axis) { \ | 101 | #define STK8BA50_ACCEL_CHANNEL(index, reg, axis) { \ |
| @@ -324,7 +323,7 @@ static irqreturn_t stk8ba50_trigger_handler(int irq, void *p) · 221 unmodified lines | |||
| 324 | ret = i2c_smbus_read_i2c_block_data(data->client, | 323 | ret = i2c_smbus_read_i2c_block_data(data->client, |
| 325 | STK8BA50_REG_XOUT, | 324 | STK8BA50_REG_XOUT, |
| 326 | STK8BA50_ALL_CHANNEL_SIZE, | 325 | STK8BA50_ALL_CHANNEL_SIZE, |
| 327 | (u8 *)data->buffer); | 326 | (u8 *)data->scan.chans); |
| 328 | if (ret < STK8BA50_ALL_CHANNEL_SIZE) { | 327 | if (ret < STK8BA50_ALL_CHANNEL_SIZE) { |
| 329 | dev_err(&data->client->dev, "register read failed\n"); | 328 | dev_err(&data->client->dev, "register read failed\n"); |
| 330 | goto err; | 329 | goto err; |
| @@ -337,10 +336,10 @@ static irqreturn_t stk8ba50_trigger_handler(int irq, void *p) · 6 unmodified lines | |||
| 337 | if (ret < 0) | 336 | if (ret < 0) |
| 338 | goto err; | 337 | goto err; |
| 339 | 338 | ||
| 340 | data->buffer[i++] = ret; | 339 | data->scan.chans[i++] = ret; |
| 341 | } | 340 | } |
| 342 | } | 341 | } |
| 343 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 342 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, |
| 344 | pf->timestamp); | 343 | pf->timestamp); |
| 345 | err: | 344 | err: |
| 346 | mutex_unlock(&data->lock); | 345 | mutex_unlock(&data->lock); |
| @@ -448,7 +447,7 @@ static int stk8ba50_probe(struct i2c_client *client, · 101 unmodified lines | |||
| 448 | data->dready_trig = devm_iio_trigger_alloc(&client->dev, | 447 | data->dready_trig = devm_iio_trigger_alloc(&client->dev, |
| 449 | "%s-dev%d", | 448 | "%s-dev%d", |
| 450 | indio_dev->name, | 449 | indio_dev->name, |
| 451 | indio_dev->id); | 450 | iio_device_id(indio_dev)); |
| 452 | if (!data->dready_trig) { | 451 | if (!data->dready_trig) { |
| 453 | ret = -ENOMEM; | 452 | ret = -ENOMEM; |
| 454 | goto err_power_off; | 453 | goto err_power_off; |
| @@ -1190,6 +1190,18 @@ config TI_TLC4541 · 1189 unmodified lines | |||
| 1190 | This driver can also be built as a module. If so, the module will be | 1190 | This driver can also be built as a module. If so, the module will be |
| 1191 | called ti-tlc4541. | 1191 | called ti-tlc4541. |
| 1192 | 1192 | ||
| 1193 | config TI_TSC2046 | ||
| 1194 | tristate "Texas Instruments TSC2046 ADC driver" | ||
| 1195 | depends on SPI | ||
| 1196 | select IIO_BUFFER | ||
| 1197 | select IIO_TRIGGERED_BUFFER | ||
| 1198 | help | ||
| 1199 | Say yes here to build support for ADC functionality of Texas | ||
| 1200 | Instruments TSC2046 touch screen controller. | ||
| 1201 | |||
| 1202 | This driver can also be built as a module. If so, the module will be | ||
| 1203 | called ti-tsc2046. | ||
| 1204 | |||
| 1193 | config TWL4030_MADC | 1205 | config TWL4030_MADC |
| 1194 | tristate "TWL4030 MADC (Monitoring A/D Converter)" | 1206 | tristate "TWL4030 MADC (Monitoring A/D Converter)" |
| 1195 | depends on TWL4030_CORE | 1207 | depends on TWL4030_CORE |
| @@ -106,6 +106,7 @@ obj-$(CONFIG_TI_ADS124S08) += ti-ads124s08.o · 105 unmodified lines | |||
| 106 | obj-$(CONFIG_TI_ADS131E08) += ti-ads131e08.o | 106 | obj-$(CONFIG_TI_ADS131E08) += ti-ads131e08.o |
| 107 | obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o | 107 | obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o |
| 108 | obj-$(CONFIG_TI_TLC4541) += ti-tlc4541.o | 108 | obj-$(CONFIG_TI_TLC4541) += ti-tlc4541.o |
| 109 | obj-$(CONFIG_TI_TSC2046) += ti-tsc2046.o | ||
| 109 | obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o | 110 | obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o |
| 110 | obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o | 111 | obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o |
| 111 | obj-$(CONFIG_VF610_ADC) += vf610_adc.o | 112 | obj-$(CONFIG_VF610_ADC) += vf610_adc.o |
| @@ -862,6 +862,11 @@ static void ad7124_reg_disable(void *r) · 861 unmodified lines | |||
| 862 | regulator_disable(r); | 862 | regulator_disable(r); |
| 863 | } | 863 | } |
| 864 | 864 | ||
| 865 | static void ad7124_clk_disable(void *c) | ||
| 866 | { | ||
| 867 | clk_disable_unprepare(c); | ||
| 868 | } | ||
| 869 | |||
| 865 | static int ad7124_probe(struct spi_device *spi) | 870 | static int ad7124_probe(struct spi_device *spi) |
| 866 | { | 871 | { |
| 867 | const struct ad7124_chip_info *info; | 872 | const struct ad7124_chip_info *info; |
| @@ -883,8 +888,6 @@ static int ad7124_probe(struct spi_device *spi) · 15 unmodified lines | |||
| 883 | 888 | ||
| 884 | ad_sd_init(&st->sd, indio_dev, spi, &ad7124_sigma_delta_info); | 889 | ad_sd_init(&st->sd, indio_dev, spi, &ad7124_sigma_delta_info); |
| 885 | 890 | ||
| 886 | spi_set_drvdata(spi, indio_dev); | ||
| 887 | |||
| 888 | indio_dev->name = st->chip_info->name; | 891 | indio_dev->name = st->chip_info->name; |
| 889 | indio_dev->modes = INDIO_DIRECT_MODE; | 892 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 890 | indio_dev->info = &ad7124_info; | 893 | indio_dev->info = &ad7124_info; |
| @@ -922,48 +925,28 @@ static int ad7124_probe(struct spi_device *spi) · 31 unmodified lines | |||
| 922 | if (ret < 0) | 925 | if (ret < 0) |
| 923 | return ret; | 926 | return ret; |
| 924 | 927 | ||
| 928 | ret = devm_add_action_or_reset(&spi->dev, ad7124_clk_disable, st->mclk); | ||
| 929 | if (ret) | ||
| 930 | return ret; | ||
| 931 | |||
| 925 | ret = ad7124_soft_reset(st); | 932 | ret = ad7124_soft_reset(st); |
| 926 | if (ret < 0) | 933 | if (ret < 0) |
| 927 | goto error_clk_disable_unprepare; | 934 | return ret; |
| 928 | 935 | ||
| 929 | ret = ad7124_check_chip_id(st); | 936 | ret = ad7124_check_chip_id(st); |
| 930 | if (ret) | 937 | if (ret) |
| 931 | goto error_clk_disable_unprepare; | 938 | return ret; |
| 932 | 939 | ||
| 933 | ret = ad7124_setup(st); | 940 | ret = ad7124_setup(st); |
| 934 | if (ret < 0) | 941 | if (ret < 0) |
| 935 | goto error_clk_disable_unprepare; | 942 | return ret; |
| 936 | 943 | ||
| 937 | ret = ad_sd_setup_buffer_and_trigger(indio_dev); | 944 | ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); |
| 938 | if (ret < 0) | 945 | if (ret < 0) |
| 939 | goto error_clk_disable_unprepare; | 946 | return ret; |
| 940 | |||
| 941 | ret = iio_device_register(indio_dev); | ||
| 942 | if (ret < 0) { | ||
| 943 | dev_err(&spi->dev, "Failed to register iio device\n"); | ||
| 944 | goto error_remove_trigger; | ||
| 945 | } | ||
| 946 | |||
| 947 | return 0; | ||
| 948 | |||
| 949 | error_remove_trigger: | ||
| 950 | ad_sd_cleanup_buffer_and_trigger(indio_dev); | ||
| 951 | error_clk_disable_unprepare: | ||
| 952 | clk_disable_unprepare(st->mclk); | ||
| 953 | |||
| 954 | return ret; | ||
| 955 | } | ||
| 956 | |||
| 957 | static int ad7124_remove(struct spi_device *spi) | ||
| 958 | { | ||
| 959 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 960 | struct ad7124_state *st = iio_priv(indio_dev); | ||
| 961 | 947 | ||
| 962 | iio_device_unregister(indio_dev); | 948 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 963 | ad_sd_cleanup_buffer_and_trigger(indio_dev); | ||
| 964 | clk_disable_unprepare(st->mclk); | ||
| 965 | 949 | ||
| 966 | return 0; | ||
| 967 | } | 950 | } |
| 968 | 951 | ||
| 969 | static const struct of_device_id ad7124_of_match[] = { | 952 | static const struct of_device_id ad7124_of_match[] = { |
| @@ -981,7 +964,6 @@ static struct spi_driver ad71124_driver = { · 11 unmodified lines | |||
| 981 | .of_match_table = ad7124_of_match, | 964 | .of_match_table = ad7124_of_match, |
| 982 | }, | 965 | }, |
| 983 | .probe = ad7124_probe, | 966 | .probe = ad7124_probe, |
| 984 | .remove = ad7124_remove, | ||
| 985 | }; | 967 | }; |
| 986 | module_spi_driver(ad71124_driver); | 968 | module_spi_driver(ad71124_driver); |
| 987 | 969 | ||
| @@ -326,7 +326,7 @@ static int ad7192_of_clock_select(struct ad7192_state *st) · 325 unmodified lines | |||
| 326 | clock_sel = AD7192_CLK_INT; | 326 | clock_sel = AD7192_CLK_INT; |
| 327 | 327 | ||
| 328 | /* use internal clock */ | 328 | /* use internal clock */ |
| 329 | if (PTR_ERR(st->mclk) == -ENOENT) { | 329 | if (st->mclk) { |
| 330 | if (of_property_read_bool(np, "adi,int-clock-output-enable")) | 330 | if (of_property_read_bool(np, "adi,int-clock-output-enable")) |
| 331 | clock_sel = AD7192_CLK_INT_CO; | 331 | clock_sel = AD7192_CLK_INT_CO; |
| 332 | } else { | 332 | } else { |
| @@ -908,6 +908,16 @@ static int ad7192_channels_config(struct iio_dev *indio_dev) · 575 unmodified lines | |||
| 908 | return 0; | 908 | return 0; |
| 909 | } | 909 | } |
| 910 | 910 | ||
| 911 | static void ad7192_reg_disable(void *reg) | ||
| 912 | { | ||
| 913 | regulator_disable(reg); | ||
| 914 | } | ||
| 915 | |||
| 916 | static void ad7192_clk_disable(void *clk) | ||
| 917 | { | ||
| 918 | clk_disable_unprepare(clk); | ||
| 919 | } | ||
| 920 | |||
| 911 | static int ad7192_probe(struct spi_device *spi) | 921 | static int ad7192_probe(struct spi_device *spi) |
| 912 | { | 922 | { |
| 913 | struct ad7192_state *st; | 923 | struct ad7192_state *st; |
| @@ -937,33 +947,38 @@ static int ad7192_probe(struct spi_device *spi) · 23 unmodified lines | |||
| 937 | return ret; | 947 | return ret; |
| 938 | } | 948 | } |
| 939 | 949 | ||
| 950 | ret = devm_add_action_or_reset(&spi->dev, ad7192_reg_disable, st->avdd); | ||
| 951 | if (ret) | ||
| 952 | return ret; | ||
| 953 | |||
| 940 | st->dvdd = devm_regulator_get(&spi->dev, "dvdd"); | 954 | st->dvdd = devm_regulator_get(&spi->dev, "dvdd"); |
| 941 | if (IS_ERR(st->dvdd)) { | 955 | if (IS_ERR(st->dvdd)) |
| 942 | ret = PTR_ERR(st->dvdd); | 956 | return PTR_ERR(st->dvdd); |
| 943 | goto error_disable_avdd; | ||
| 944 | } | ||
| 945 | 957 | ||
| 946 | ret = regulator_enable(st->dvdd); | 958 | ret = regulator_enable(st->dvdd); |
| 947 | if (ret) { | 959 | if (ret) { |
| 948 | dev_err(&spi->dev, "Failed to enable specified DVdd supply\n"); | 960 | dev_err(&spi->dev, "Failed to enable specified DVdd supply\n"); |
| 949 | goto error_disable_avdd; | 961 | return ret; |
| 950 | } | 962 | } |
| 951 | 963 | ||
| 964 | ret = devm_add_action_or_reset(&spi->dev, ad7192_reg_disable, st->dvdd); | ||
| 965 | if (ret) | ||
| 966 | return ret; | ||
| 967 | |||
| 952 | ret = regulator_get_voltage(st->avdd); | 968 | ret = regulator_get_voltage(st->avdd); |
| 953 | if (ret < 0) { | 969 | if (ret < 0) { |
| 954 | dev_err(&spi->dev, "Device tree error, reference voltage undefined\n"); | 970 | dev_err(&spi->dev, "Device tree error, reference voltage undefined\n"); |
| 955 | goto error_disable_avdd; | 971 | return ret; |
| 956 | } | 972 | } |
| 957 | st->int_vref_mv = ret / 1000; | 973 | st->int_vref_mv = ret / 1000; |
| 958 | 974 | ||
| 959 | spi_set_drvdata(spi, indio_dev); | ||
| 960 | st->chip_info = of_device_get_match_data(&spi->dev); | 975 | st->chip_info = of_device_get_match_data(&spi->dev); |
| 961 | indio_dev->name = st->chip_info->name; | 976 | indio_dev->name = st->chip_info->name; |
| 962 | indio_dev->modes = INDIO_DIRECT_MODE; | 977 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 963 | 978 | ||
| 964 | ret = ad7192_channels_config(indio_dev); | 979 | ret = ad7192_channels_config(indio_dev); |
| 965 | if (ret < 0) | 980 | if (ret < 0) |
| 966 | goto error_disable_dvdd; | 981 | return ret; |
| 967 | 982 | ||
| 968 | if (st->chip_info->chip_id == CHIPID_AD7195) | 983 | if (st->chip_info->chip_id == CHIPID_AD7195) |
| 969 | indio_dev->info = &ad7195_info; | 984 | indio_dev->info = &ad7195_info; |
| @@ -972,17 +987,15 @@ static int ad7192_probe(struct spi_device *spi) · 2 unmodified lines | |||
| 972 | 987 | ||
| 973 | ad_sd_init(&st->sd, indio_dev, spi, &ad7192_sigma_delta_info); | 988 | ad_sd_init(&st->sd, indio_dev, spi, &ad7192_sigma_delta_info); |
| 974 | 989 | ||
| 975 | ret = ad_sd_setup_buffer_and_trigger(indio_dev); | 990 | ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); |
| 976 | if (ret) | 991 | if (ret) |
| 977 | goto error_disable_dvdd; | 992 | return ret; |
| 978 | 993 | ||
| 979 | st->fclk = AD7192_INT_FREQ_MHZ; | 994 | st->fclk = AD7192_INT_FREQ_MHZ; |
| 980 | 995 | ||
| 981 | st->mclk = devm_clk_get(&st->sd.spi->dev, "mclk"); | 996 | st->mclk = devm_clk_get_optional(&spi->dev, "mclk"); |
| 982 | if (IS_ERR(st->mclk) && PTR_ERR(st->mclk) != -ENOENT) { | 997 | if (IS_ERR(st->mclk)) |
| 983 | ret = PTR_ERR(st->mclk); | 998 | return PTR_ERR(st->mclk); |
| 984 | goto error_remove_trigger; | ||
| 985 | } | ||
| 986 | 999 | ||
| 987 | st->clock_sel = ad7192_of_clock_select(st); | 1000 | st->clock_sel = ad7192_of_clock_select(st); |
| 988 | 1001 | ||
| @@ -990,55 +1003,26 @@ static int ad7192_probe(struct spi_device *spi) · 1 unmodified line | |||
| 990 | st->clock_sel == AD7192_CLK_EXT_MCLK2) { | 1003 | st->clock_sel == AD7192_CLK_EXT_MCLK2) { |
| 991 | ret = clk_prepare_enable(st->mclk); | 1004 | ret = clk_prepare_enable(st->mclk); |
| 992 | if (ret < 0) | 1005 | if (ret < 0) |
| 993 | goto error_remove_trigger; | 1006 | return ret; |
| 1007 | |||
| 1008 | ret = devm_add_action_or_reset(&spi->dev, ad7192_clk_disable, | ||
| 1009 | st->mclk); | ||
| 1010 | if (ret) | ||
| 1011 | return ret; | ||
| 994 | 1012 | ||
| 995 | st->fclk = clk_get_rate(st->mclk); | 1013 | st->fclk = clk_get_rate(st->mclk); |
| 996 | if (!ad7192_valid_external_frequency(st->fclk)) { | 1014 | if (!ad7192_valid_external_frequency(st->fclk)) { |
| 997 | ret = -EINVAL; | ||
| 998 | dev_err(&spi->dev, | 1015 | dev_err(&spi->dev, |
| 999 | "External clock frequency out of bounds\n"); | 1016 | "External clock frequency out of bounds\n"); |
| 1000 | goto error_disable_clk; | 1017 | return -EINVAL; |
| 1001 | } | 1018 | } |
| 1002 | } | 1019 | } |
| 1003 | 1020 | ||
| 1004 | ret = ad7192_setup(st, spi->dev.of_node); | 1021 | ret = ad7192_setup(st, spi->dev.of_node); |
| 1005 | if (ret) | 1022 | if (ret) |
| 1006 | goto error_disable_clk; | 1023 | return ret; |
| 1007 | |||
| 1008 | ret = iio_device_register(indio_dev); | ||
| 1009 | if (ret < 0) | ||
| 1010 | goto error_disable_clk; | ||
| 1011 | return 0; | ||
| 1012 | |||
| 1013 | error_disable_clk: | ||
| 1014 | if (st->clock_sel == AD7192_CLK_EXT_MCLK1_2 || | ||
| 1015 | st->clock_sel == AD7192_CLK_EXT_MCLK2) | ||
| 1016 | clk_disable_unprepare(st->mclk); | ||
| 1017 | error_remove_trigger: | ||
| 1018 | ad_sd_cleanup_buffer_and_trigger(indio_dev); | ||
| 1019 | error_disable_dvdd: | ||
| 1020 | regulator_disable(st->dvdd); | ||
| 1021 | error_disable_avdd: | ||
| 1022 | regulator_disable(st->avdd); | ||
| 1023 | |||
| 1024 | return ret; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | static int ad7192_remove(struct spi_device *spi) | ||
| 1028 | { | ||
| 1029 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 1030 | struct ad7192_state *st = iio_priv(indio_dev); | ||
| 1031 | |||
| 1032 | iio_device_unregister(indio_dev); | ||
| 1033 | if (st->clock_sel == AD7192_CLK_EXT_MCLK1_2 || | ||
| 1034 | st->clock_sel == AD7192_CLK_EXT_MCLK2) | ||
| 1035 | clk_disable_unprepare(st->mclk); | ||
| 1036 | ad_sd_cleanup_buffer_and_trigger(indio_dev); | ||
| 1037 | |||
| 1038 | regulator_disable(st->dvdd); | ||
| 1039 | regulator_disable(st->avdd); | ||
| 1040 | 1024 | ||
| 1041 | return 0; | 1025 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 1042 | } | 1026 | } |
| 1043 | 1027 | ||
| 1044 | static const struct of_device_id ad7192_of_match[] = { | 1028 | static const struct of_device_id ad7192_of_match[] = { |
| @@ -1056,7 +1040,6 @@ static struct spi_driver ad7192_driver = { · 11 unmodified lines | |||
| 1056 | .of_match_table = ad7192_of_match, | 1040 | .of_match_table = ad7192_of_match, |
| 1057 | }, | 1041 | }, |
| 1058 | .probe = ad7192_probe, | 1042 | .probe = ad7192_probe, |
| 1059 | .remove = ad7192_remove, | ||
| 1060 | }; | 1043 | }; |
| 1061 | module_spi_driver(ad7192_driver); | 1044 | module_spi_driver(ad7192_driver); |
| 1062 | 1045 | ||
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/regulator/consumer.h> | 13 | #include <linux/regulator/consumer.h> |
| 14 | #include <linux/err.h> | 14 | #include <linux/err.h> |
| 15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
| 16 | #include <linux/mod_devicetable.h> | ||
| 16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 17 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
| 18 | #include <linux/bitops.h> | 19 | #include <linux/bitops.h> |
| @@ -346,6 +347,12 @@ static int ad7298_probe(struct spi_device *spi) · 327 unmodified lines | |||
| 346 | return devm_iio_device_register(&spi->dev, indio_dev); | 347 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 347 | } | 348 | } |
| 348 | 349 | ||
| 350 | static const struct acpi_device_id ad7298_acpi_ids[] = { | ||
| 351 | { "INT3494", 0 }, | ||
| 352 | { } | ||
| 353 | }; | ||
| 354 | MODULE_DEVICE_TABLE(acpi, ad7298_acpi_ids); | ||
| 355 | |||
| 349 | static const struct spi_device_id ad7298_id[] = { | 356 | static const struct spi_device_id ad7298_id[] = { |
| 350 | {"ad7298", 0}, | 357 | {"ad7298", 0}, |
| 351 | {} | 358 | {} |
| @@ -355,6 +362,7 @@ MODULE_DEVICE_TABLE(spi, ad7298_id); · 3 unmodified lines | |||
| 355 | static struct spi_driver ad7298_driver = { | 362 | static struct spi_driver ad7298_driver = { |
| 356 | .driver = { | 363 | .driver = { |
| 357 | .name = "ad7298", | 364 | .name = "ad7298", |
| 365 | .acpi_match_table = ad7298_acpi_ids, | ||
| 358 | }, | 366 | }, |
| 359 | .probe = ad7298_probe, | 367 | .probe = ad7298_probe, |
| 360 | .id_table = ad7298_id, | 368 | .id_table = ad7298_id, |
| @@ -32,12 +32,14 @@ struct ad7476_chip_info { · 31 unmodified lines | |||
| 32 | /* channels used when convst gpio is defined */ | 32 | /* channels used when convst gpio is defined */ |
| 33 | struct iio_chan_spec convst_channel[2]; | 33 | struct iio_chan_spec convst_channel[2]; |
| 34 | void (*reset)(struct ad7476_state *); | 34 | void (*reset)(struct ad7476_state *); |
| 35 | bool has_vref; | ||
| 36 | bool has_vdrive; | ||
| 35 | }; | 37 | }; |
| 36 | 38 | ||
| 37 | struct ad7476_state { | 39 | struct ad7476_state { |
| 38 | struct spi_device *spi; | 40 | struct spi_device *spi; |
| 39 | const struct ad7476_chip_info *chip_info; | 41 | const struct ad7476_chip_info *chip_info; |
| 40 | struct regulator *reg; | 42 | struct regulator *ref_reg; |
| 41 | struct gpio_desc *convst_gpio; | 43 | struct gpio_desc *convst_gpio; |
| 42 | struct spi_transfer xfer; | 44 | struct spi_transfer xfer; |
| 43 | struct spi_message msg; | 45 | struct spi_message msg; |
| @@ -52,13 +54,17 @@ struct ad7476_state { · 8 unmodified lines | |||
| 52 | }; | 54 | }; |
| 53 | 55 | ||
| 54 | enum ad7476_supported_device_ids { | 56 | enum ad7476_supported_device_ids { |
| 57 | ID_AD7091, | ||
| 55 | ID_AD7091R, | 58 | ID_AD7091R, |
| 59 | ID_AD7273, | ||
| 60 | ID_AD7274, | ||
| 56 | ID_AD7276, | 61 | ID_AD7276, |
| 57 | ID_AD7277, | 62 | ID_AD7277, |
| 58 | ID_AD7278, | 63 | ID_AD7278, |
| 59 | ID_AD7466, | 64 | ID_AD7466, |
| 60 | ID_AD7467, | 65 | ID_AD7467, |
| 61 | ID_AD7468, | 66 | ID_AD7468, |
| 67 | ID_AD7475, | ||
| 62 | ID_AD7495, | 68 | ID_AD7495, |
| 63 | ID_AD7940, | 69 | ID_AD7940, |
| 64 | ID_ADC081S, | 70 | ID_ADC081S, |
| @@ -145,8 +151,8 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, · 80 unmodified lines | |||
| 145 | GENMASK(st->chip_info->channel[0].scan_type.realbits - 1, 0); | 151 | GENMASK(st->chip_info->channel[0].scan_type.realbits - 1, 0); |
| 146 | return IIO_VAL_INT; | 152 | return IIO_VAL_INT; |
| 147 | case IIO_CHAN_INFO_SCALE: | 153 | case IIO_CHAN_INFO_SCALE: |
| 148 | if (!st->chip_info->int_vref_uv) { | 154 | if (st->ref_reg) { |
| 149 | scale_uv = regulator_get_voltage(st->reg); | 155 | scale_uv = regulator_get_voltage(st->ref_reg); |
| 150 | if (scale_uv < 0) | 156 | if (scale_uv < 0) |
| 151 | return scale_uv; | 157 | return scale_uv; |
| 152 | } else { | 158 | } else { |
| @@ -187,13 +193,32 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, · 34 unmodified lines | |||
| 187 | BIT(IIO_CHAN_INFO_RAW)) | 193 | BIT(IIO_CHAN_INFO_RAW)) |
| 188 | 194 | ||
| 189 | static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { | 195 | static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { |
| 196 | [ID_AD7091] = { | ||
| 197 | .channel[0] = AD7091R_CHAN(12), | ||
| 198 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | ||
| 199 | .convst_channel[0] = AD7091R_CONVST_CHAN(12), | ||
| 200 | .convst_channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | ||
| 201 | .reset = ad7091_reset, | ||
| 202 | }, | ||
| 190 | [ID_AD7091R] = { | 203 | [ID_AD7091R] = { |
| 191 | .channel[0] = AD7091R_CHAN(12), | 204 | .channel[0] = AD7091R_CHAN(12), |
| 192 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | 205 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
| 193 | .convst_channel[0] = AD7091R_CONVST_CHAN(12), | 206 | .convst_channel[0] = AD7091R_CONVST_CHAN(12), |
| 194 | .convst_channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | 207 | .convst_channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
| 208 | .int_vref_uv = 2500000, | ||
| 209 | .has_vref = true, | ||
| 195 | .reset = ad7091_reset, | 210 | .reset = ad7091_reset, |
| 196 | }, | 211 | }, |
| 212 | [ID_AD7273] = { | ||
| 213 | .channel[0] = AD7940_CHAN(10), | ||
| 214 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | ||
| 215 | .has_vref = true, | ||
| 216 | }, | ||
| 217 | [ID_AD7274] = { | ||
| 218 | .channel[0] = AD7940_CHAN(12), | ||
| 219 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | ||
| 220 | .has_vref = true, | ||
| 221 | }, | ||
| 197 | [ID_AD7276] = { | 222 | [ID_AD7276] = { |
| 198 | .channel[0] = AD7940_CHAN(12), | 223 | .channel[0] = AD7940_CHAN(12), |
| 199 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | 224 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
| @@ -218,10 +243,17 @@ static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { · 18 unmodified lines | |||
| 218 | .channel[0] = AD7476_CHAN(8), | 243 | .channel[0] = AD7476_CHAN(8), |
| 219 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | 244 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
| 220 | }, | 245 | }, |
| 246 | [ID_AD7475] = { | ||
| 247 | .channel[0] = AD7476_CHAN(12), | ||
| 248 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | ||
| 249 | .has_vref = true, | ||
| 250 | .has_vdrive = true, | ||
| 251 | }, | ||
| 221 | [ID_AD7495] = { | 252 | [ID_AD7495] = { |
| 222 | .channel[0] = AD7476_CHAN(12), | 253 | .channel[0] = AD7476_CHAN(12), |
| 223 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | 254 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
| 224 | .int_vref_uv = 2500000, | 255 | .int_vref_uv = 2500000, |
| 256 | .has_vdrive = true, | ||
| 225 | }, | 257 | }, |
| 226 | [ID_AD7940] = { | 258 | [ID_AD7940] = { |
| 227 | .channel[0] = AD7940_CHAN(14), | 259 | .channel[0] = AD7940_CHAN(14), |
| @@ -254,6 +286,7 @@ static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { · 26 unmodified lines | |||
| 254 | [ID_LTC2314_14] = { | 286 | [ID_LTC2314_14] = { |
| 255 | .channel[0] = AD7940_CHAN(14), | 287 | .channel[0] = AD7940_CHAN(14), |
| 256 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | 288 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), |
| 289 | .has_vref = true, | ||
| 257 | }, | 290 | }, |
| 258 | }; | 291 | }; |
| 259 | 292 | ||
| @@ -263,15 +296,16 @@ static const struct iio_info ad7476_info = { · 3 unmodified lines | |||
| 263 | 296 | ||
| 264 | static void ad7476_reg_disable(void *data) | 297 | static void ad7476_reg_disable(void *data) |
| 265 | { | 298 | { |
| 266 | struct ad7476_state *st = data; | 299 | struct regulator *reg = data; |
| 267 | 300 | ||
| 268 | regulator_disable(st->reg); | 301 | regulator_disable(reg); |
| 269 | } | 302 | } |
| 270 | 303 | ||
| 271 | static int ad7476_probe(struct spi_device *spi) | 304 | static int ad7476_probe(struct spi_device *spi) |
| 272 | { | 305 | { |
| 273 | struct ad7476_state *st; | 306 | struct ad7476_state *st; |
| 274 | struct iio_dev *indio_dev; | 307 | struct iio_dev *indio_dev; |
| 308 | struct regulator *reg; | ||
| 275 | int ret; | 309 | int ret; |
| 276 | 310 | ||
| 277 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); | 311 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); |
| @@ -282,27 +316,79 @@ static int ad7476_probe(struct spi_device *spi) · 4 unmodified lines | |||
| 282 | st->chip_info = | 316 | st->chip_info = |
| 283 | &ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | 317 | &ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data]; |
| 284 | 318 | ||
| 285 | st->reg = devm_regulator_get(&spi->dev, "vcc"); | 319 | reg = devm_regulator_get(&spi->dev, "vcc"); |
| 286 | if (IS_ERR(st->reg)) | 320 | if (IS_ERR(reg)) |
| 287 | return PTR_ERR(st->reg); | 321 | return PTR_ERR(reg); |
| 288 | 322 | ||
| 289 | ret = regulator_enable(st->reg); | 323 | ret = regulator_enable(reg); |
| 290 | if (ret) | 324 | if (ret) |
| 291 | return ret; | 325 | return ret; |
| 292 | 326 | ||
| 293 | ret = devm_add_action_or_reset(&spi->dev, ad7476_reg_disable, | 327 | ret = devm_add_action_or_reset(&spi->dev, ad7476_reg_disable, reg); |
| 294 | st); | ||
| 295 | if (ret) | 328 | if (ret) |
| 296 | return ret; | 329 | return ret; |
| 297 | 330 | ||
| 331 | /* Either vcc or vref (below) as appropriate */ | ||
| 332 | if (!st->chip_info->int_vref_uv) | ||
| 333 | st->ref_reg = reg; | ||
| 334 | |||
| 335 | if (st->chip_info->has_vref) { | ||
| 336 | |||
| 337 | /* If a device has an internal reference vref is optional */ | ||
| 338 | if (st->chip_info->int_vref_uv) { | ||
| 339 | reg = devm_regulator_get_optional(&spi->dev, "vref"); | ||
| 340 | if (IS_ERR(reg) && (PTR_ERR(reg) != -ENODEV)) | ||
| 341 | return PTR_ERR(reg); | ||
| 342 | } else { | ||
| 343 | reg = devm_regulator_get(&spi->dev, "vref"); | ||
| 344 | if (IS_ERR(reg)) | ||
| 345 | return PTR_ERR(reg); | ||
| 346 | } | ||
| 347 | |||
| 348 | if (!IS_ERR(reg)) { | ||
| 349 | ret = regulator_enable(reg); | ||
| 350 | if (ret) | ||
| 351 | return ret; | ||
| 352 | |||
| 353 | ret = devm_add_action_or_reset(&spi->dev, | ||
| 354 | ad7476_reg_disable, | ||
| 355 | reg); | ||
| 356 | if (ret) | ||
| 357 | return ret; | ||
| 358 | st->ref_reg = reg; | ||
| 359 | } else { | ||
| 360 | /* | ||
| 361 | * Can only get here if device supports both internal | ||
| 362 | * and external reference, but the regulator connected | ||
| 363 | * to the external reference is not connected. | ||
| 364 | * Set the reference regulator pointer to NULL to | ||
| 365 | * indicate this. | ||
| 366 | */ | ||
| 367 | st->ref_reg = NULL; | ||
| 368 | } | ||
| 369 | } | ||
| 370 | |||
| 371 | if (st->chip_info->has_vdrive) { | ||
| 372 | reg = devm_regulator_get(&spi->dev, "vdrive"); | ||
| 373 | if (IS_ERR(reg)) | ||
| 374 | return PTR_ERR(reg); | ||
| 375 | |||
| 376 | ret = regulator_enable(reg); | ||
| 377 | if (ret) | ||
| 378 | return ret; | ||
| 379 | |||
| 380 | ret = devm_add_action_or_reset(&spi->dev, ad7476_reg_disable, | ||
| 381 | reg); | ||
| 382 | if (ret) | ||
| 383 | return ret; | ||
| 384 | } | ||
| 385 | |||
| 298 | st->convst_gpio = devm_gpiod_get_optional(&spi->dev, | 386 | st->convst_gpio = devm_gpiod_get_optional(&spi->dev, |
| 299 | "adi,conversion-start", | 387 | "adi,conversion-start", |
| 300 | GPIOD_OUT_LOW); | 388 | GPIOD_OUT_LOW); |
| 301 | if (IS_ERR(st->convst_gpio)) | 389 | if (IS_ERR(st->convst_gpio)) |
| 302 | return PTR_ERR(st->convst_gpio); | 390 | return PTR_ERR(st->convst_gpio); |
| 303 | 391 | ||
| 304 | spi_set_drvdata(spi, indio_dev); | ||
| 305 | |||
| 306 | st->spi = spi; | 392 | st->spi = spi; |
| 307 | 393 | ||
| 308 | indio_dev->name = spi_get_device_id(spi)->name; | 394 | indio_dev->name = spi_get_device_id(spi)->name; |
| @@ -333,17 +419,17 @@ static int ad7476_probe(struct spi_device *spi) · 24 unmodified lines | |||
| 333 | } | 419 | } |
| 334 | 420 | ||
| 335 | static const struct spi_device_id ad7476_id[] = { | 421 | static const struct spi_device_id ad7476_id[] = { |
| 336 | {"ad7091", ID_AD7091R}, | 422 | {"ad7091", ID_AD7091}, |
| 337 | {"ad7091r", ID_AD7091R}, | 423 | {"ad7091r", ID_AD7091R}, |
| 338 | {"ad7273", ID_AD7277}, | 424 | {"ad7273", ID_AD7273}, |
| 339 | {"ad7274", ID_AD7276}, | 425 | {"ad7274", ID_AD7274}, |
| 340 | {"ad7276", ID_AD7276}, | 426 | {"ad7276", ID_AD7276}, |
| 341 | {"ad7277", ID_AD7277}, | 427 | {"ad7277", ID_AD7277}, |
| 342 | {"ad7278", ID_AD7278}, | 428 | {"ad7278", ID_AD7278}, |
| 343 | {"ad7466", ID_AD7466}, | 429 | {"ad7466", ID_AD7466}, |
| 344 | {"ad7467", ID_AD7467}, | 430 | {"ad7467", ID_AD7467}, |
| 345 | {"ad7468", ID_AD7468}, | 431 | {"ad7468", ID_AD7468}, |
| 346 | {"ad7475", ID_AD7466}, | 432 | {"ad7475", ID_AD7475}, |
| 347 | {"ad7476", ID_AD7466}, | 433 | {"ad7476", ID_AD7466}, |
| 348 | {"ad7476a", ID_AD7466}, | 434 | {"ad7476a", ID_AD7466}, |
| 349 | {"ad7477", ID_AD7467}, | 435 | {"ad7477", ID_AD7467}, |
| @@ -663,7 +663,8 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, · 662 unmodified lines | |||
| 663 | } | 663 | } |
| 664 | 664 | ||
| 665 | st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", | 665 | st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", |
| 666 | indio_dev->name, indio_dev->id); | 666 | indio_dev->name, |
| 667 | iio_device_id(indio_dev)); | ||
| 667 | if (!st->trig) | 668 | if (!st->trig) |
| 668 | return -ENOMEM; | 669 | return -ENOMEM; |
| 669 | 670 | ||
| @@ -248,7 +248,8 @@ static int ad7766_probe(struct spi_device *spi) · 247 unmodified lines | |||
| 248 | 248 | ||
| 249 | if (spi->irq > 0) { | 249 | if (spi->irq > 0) { |
| 250 | ad7766->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", | 250 | ad7766->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", |
| 251 | indio_dev->name, indio_dev->id); | 251 | indio_dev->name, |
| 252 | iio_device_id(indio_dev)); | ||
| 252 | if (!ad7766->trig) | 253 | if (!ad7766->trig) |
| 253 | return -ENOMEM; | 254 | return -ENOMEM; |
| 254 | 255 | ||
| @@ -272,8 +273,6 @@ static int ad7766_probe(struct spi_device *spi) · 17 unmodified lines | |||
| 272 | return ret; | 273 | return ret; |
| 273 | } | 274 | } |
| 274 | 275 | ||
| 275 | spi_set_drvdata(spi, indio_dev); | ||
| 276 | |||
| 277 | ad7766->spi = spi; | 276 | ad7766->spi = spi; |
| 278 | 277 | ||
| 279 | /* First byte always 0 */ | 278 | /* First byte always 0 */ |
| @@ -289,10 +288,7 @@ static int ad7766_probe(struct spi_device *spi) · 9 unmodified lines | |||
| 289 | if (ret) | 288 | if (ret) |
| 290 | return ret; | 289 | return ret; |
| 291 | 290 | ||
| 292 | ret = devm_iio_device_register(&spi->dev, indio_dev); | 291 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 293 | if (ret) | ||
| 294 | return ret; | ||
| 295 | return 0; | ||
| 296 | } | 292 | } |
| 297 | 293 | ||
| 298 | static const struct spi_device_id ad7766_id[] = { | 294 | static const struct spi_device_id ad7766_id[] = { |
| @@ -614,7 +614,6 @@ static int ad7768_probe(struct spi_device *spi) · 613 unmodified lines | |||
| 614 | 614 | ||
| 615 | st->mclk_freq = clk_get_rate(st->mclk); | 615 | st->mclk_freq = clk_get_rate(st->mclk); |
| 616 | 616 | ||
| 617 | spi_set_drvdata(spi, indio_dev); | ||
| 618 | mutex_init(&st->lock); | 617 | mutex_init(&st->lock); |
| 619 | 618 | ||
| 620 | indio_dev->channels = ad7768_channels; | 619 | indio_dev->channels = ad7768_channels; |
| @@ -630,7 +629,8 @@ static int ad7768_probe(struct spi_device *spi) · 9 unmodified lines | |||
| 630 | } | 629 | } |
| 631 | 630 | ||
| 632 | st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", | 631 | st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", |
| 633 | indio_dev->name, indio_dev->id); | 632 | indio_dev->name, |
| 633 | iio_device_id(indio_dev)); | ||
| 634 | if (!st->trig) | 634 | if (!st->trig) |
| 635 | return -ENOMEM; | 635 | return -ENOMEM; |
| 636 | 636 | ||
| @@ -300,6 +300,11 @@ static int ad7780_init_gpios(struct device *dev, struct ad7780_state *st) · 299 unmodified lines | |||
| 300 | return 0; | 300 | return 0; |
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | static void ad7780_reg_disable(void *reg) | ||
| 304 | { | ||
| 305 | regulator_disable(reg); | ||
| 306 | } | ||
| 307 | |||
| 303 | static int ad7780_probe(struct spi_device *spi) | 308 | static int ad7780_probe(struct spi_device *spi) |
| 304 | { | 309 | { |
| 305 | struct ad7780_state *st; | 310 | struct ad7780_state *st; |
| @@ -318,8 +323,6 @@ static int ad7780_probe(struct spi_device *spi) · 12 unmodified lines | |||
| 318 | st->chip_info = | 323 | st->chip_info = |
| 319 | &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | 324 | &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data]; |
| 320 | 325 | ||
| 321 | spi_set_drvdata(spi, indio_dev); | ||
| 322 | |||
| 323 | indio_dev->name = spi_get_device_id(spi)->name; | 326 | indio_dev->name = spi_get_device_id(spi)->name; |
| 324 | indio_dev->modes = INDIO_DIRECT_MODE; | 327 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 325 | indio_dev->channels = &st->chip_info->channel; | 328 | indio_dev->channels = &st->chip_info->channel; |
| @@ -340,35 +343,15 @@ static int ad7780_probe(struct spi_device *spi) · 14 unmodified lines | |||
| 340 | return ret; | 343 | return ret; |
| 341 | } | 344 | } |
| 342 | 345 | ||
| 343 | ret = ad_sd_setup_buffer_and_trigger(indio_dev); | 346 | ret = devm_add_action_or_reset(&spi->dev, ad7780_reg_disable, st->reg); |
| 344 | if (ret) | 347 | if (ret) |
| 345 | goto error_disable_reg; | 348 | return ret; |
| 346 | 349 | ||
| 347 | ret = iio_device_register(indio_dev); | 350 | ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); |
| 348 | if (ret) | 351 | if (ret) |
| 349 | goto error_cleanup_buffer_and_trigger; | 352 | return ret; |
| 350 | |||
| 351 | return 0; | ||
| 352 | |||
| 353 | error_cleanup_buffer_and_trigger: | ||
| 354 | ad_sd_cleanup_buffer_and_trigger(indio_dev); | ||
| 355 | error_disable_reg: | ||
| 356 | regulator_disable(st->reg); | ||
| 357 | |||
| 358 | return ret; | ||
| 359 | } | ||
| 360 | |||
| 361 | static int ad7780_remove(struct spi_device *spi) | ||
| 362 | { | ||
| 363 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 364 | struct ad7780_state *st = iio_priv(indio_dev); | ||
| 365 | |||
| 366 | iio_device_unregister(indio_dev); | ||
| 367 | ad_sd_cleanup_buffer_and_trigger(indio_dev); | ||
| 368 | |||
| 369 | regulator_disable(st->reg); | ||
| 370 | 353 | ||
| 371 | return 0; | 354 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 372 | } | 355 | } |
| 373 | 356 | ||
| 374 | static const struct spi_device_id ad7780_id[] = { | 357 | static const struct spi_device_id ad7780_id[] = { |
| @@ -385,7 +368,6 @@ static struct spi_driver ad7780_driver = { · 10 unmodified lines | |||
| 385 | .name = "ad7780", | 368 | .name = "ad7780", |
| 386 | }, | 369 | }, |
| 387 | .probe = ad7780_probe, | 370 | .probe = ad7780_probe, |
| 388 | .remove = ad7780_remove, | ||
| 389 | .id_table = ad7780_id, | 371 | .id_table = ad7780_id, |
| 390 | }; | 372 | }; |
| 391 | module_spi_driver(ad7780_driver); | 373 | module_spi_driver(ad7780_driver); |
| @@ -394,6 +394,11 @@ static int ad7791_setup(struct ad7791_state *st, · 393 unmodified lines | |||
| 394 | st->mode); | 394 | st->mode); |
| 395 | } | 395 | } |
| 396 | 396 | ||
| 397 | static void ad7791_reg_disable(void *reg) | ||
| 398 | { | ||
| 399 | regulator_disable(reg); | ||
| 400 | } | ||
| 401 | |||
| 397 | static int ad7791_probe(struct spi_device *spi) | 402 | static int ad7791_probe(struct spi_device *spi) |
| 398 | { | 403 | { |
| 399 | struct ad7791_platform_data *pdata = spi->dev.platform_data; | 404 | struct ad7791_platform_data *pdata = spi->dev.platform_data; |
| @@ -420,11 +425,13 @@ static int ad7791_probe(struct spi_device *spi) · 20 unmodified lines | |||
| 420 | if (ret) | 425 | if (ret) |
| 421 | return ret; | 426 | return ret; |
| 422 | 427 | ||
| 428 | ret = devm_add_action_or_reset(&spi->dev, ad7791_reg_disable, st->reg); | ||
| 429 | if (ret) | ||
| 430 | return ret; | ||
| 431 | |||
| 423 | st->info = &ad7791_chip_infos[spi_get_device_id(spi)->driver_data]; | 432 | st->info = &ad7791_chip_infos[spi_get_device_id(spi)->driver_data]; |
| 424 | ad_sd_init(&st->sd, indio_dev, spi, &ad7791_sigma_delta_info); | 433 | ad_sd_init(&st->sd, indio_dev, spi, &ad7791_sigma_delta_info); |
| 425 | 434 | ||
| 426 | spi_set_drvdata(spi, indio_dev); | ||
| 427 | |||
| 428 | indio_dev->name = spi_get_device_id(spi)->name; | 435 | indio_dev->name = spi_get_device_id(spi)->name; |
| 429 | indio_dev->modes = INDIO_DIRECT_MODE; | 436 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 430 | indio_dev->channels = st->info->channels; | 437 | indio_dev->channels = st->info->channels; |
| @@ -434,39 +441,15 @@ static int ad7791_probe(struct spi_device *spi) · 3 unmodified lines | |||
| 434 | else | 441 | else |
| 435 | indio_dev->info = &ad7791_no_filter_info; | 442 | indio_dev->info = &ad7791_no_filter_info; |
| 436 | 443 | ||
| 437 | ret = ad_sd_setup_buffer_and_trigger(indio_dev); | 444 | ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); |
| 438 | if (ret) | 445 | if (ret) |
| 439 | goto error_disable_reg; | 446 | return ret; |
| 440 | 447 | ||
| 441 | ret = ad7791_setup(st, pdata); | 448 | ret = ad7791_setup(st, pdata); |
| 442 | if (ret) | 449 | if (ret) |
| 443 | goto error_remove_trigger; | 450 | return ret; |
| 444 | |||
| 445 | ret = iio_device_register(indio_dev); | ||
| 446 | if (ret) | ||
| 447 | goto error_remove_trigger; | ||
| 448 | |||
| 449 | return 0; | ||
| 450 | |||
| 451 | error_remove_trigger: | ||
| 452 | ad_sd_cleanup_buffer_and_trigger(indio_dev); | ||
| 453 | error_disable_reg: | ||
| 454 | regulator_disable(st->reg); | ||
| 455 | |||
| 456 | return ret; | ||
| 457 | } | ||
| 458 | |||
| 459 | static int ad7791_remove(struct spi_device *spi) | ||
| 460 | { | ||
| 461 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 462 | struct ad7791_state *st = iio_priv(indio_dev); | ||
| 463 | |||
| 464 | iio_device_unregister(indio_dev); | ||
| 465 | ad_sd_cleanup_buffer_and_trigger(indio_dev); | ||
| 466 | |||
| 467 | regulator_disable(st->reg); | ||
| 468 | 451 | ||
| 469 | return 0; | 452 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 470 | } | 453 | } |
| 471 | 454 | ||
| 472 | static const struct spi_device_id ad7791_spi_ids[] = { | 455 | static const struct spi_device_id ad7791_spi_ids[] = { |
| @@ -484,7 +467,6 @@ static struct spi_driver ad7791_driver = { · 11 unmodified lines | |||
| 484 | .name = "ad7791", | 467 | .name = "ad7791", |
| 485 | }, | 468 | }, |
| 486 | .probe = ad7791_probe, | 469 | .probe = ad7791_probe, |
| 487 | .remove = ad7791_remove, | ||
| 488 | .id_table = ad7791_spi_ids, | 470 | .id_table = ad7791_spi_ids, |
| 489 | }; | 471 | }; |
| 490 | module_spi_driver(ad7791_driver); | 472 | module_spi_driver(ad7791_driver); |
| @@ -769,6 +769,11 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { · 768 unmodified lines | |||
| 769 | }, | 769 | }, |
| 770 | }; | 770 | }; |
| 771 | 771 | ||
| 772 | static void ad7793_reg_disable(void *reg) | ||
| 773 | { | ||
| 774 | regulator_disable(reg); | ||
| 775 | } | ||
| 776 | |||
| 772 | static int ad7793_probe(struct spi_device *spi) | 777 | static int ad7793_probe(struct spi_device *spi) |
| 773 | { | 778 | { |
| 774 | const struct ad7793_platform_data *pdata = spi->dev.platform_data; | 779 | const struct ad7793_platform_data *pdata = spi->dev.platform_data; |
| @@ -803,11 +808,13 @@ static int ad7793_probe(struct spi_device *spi) · 28 unmodified lines | |||
| 803 | if (ret) | 808 | if (ret) |
| 804 | return ret; | 809 | return ret; |
| 805 | 810 | ||
| 811 | ret = devm_add_action_or_reset(&spi->dev, ad7793_reg_disable, st->reg); | ||
| 812 | if (ret) | ||
| 813 | return ret; | ||
| 814 | |||
| 806 | vref_mv = regulator_get_voltage(st->reg); | 815 | vref_mv = regulator_get_voltage(st->reg); |
| 807 | if (vref_mv < 0) { | 816 | if (vref_mv < 0) |
| 808 | ret = vref_mv; | 817 | return vref_mv; |
| 809 | goto error_disable_reg; | ||
| 810 | } | ||
| 811 | 818 | ||
| 812 | vref_mv /= 1000; | 819 | vref_mv /= 1000; |
| 813 | } else { | 820 | } else { |
| @@ -817,50 +824,21 @@ static int ad7793_probe(struct spi_device *spi) · 3 unmodified lines | |||
| 817 | st->chip_info = | 824 | st->chip_info = |
| 818 | &ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | 825 | &ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data]; |
| 819 | 826 | ||
| 820 | spi_set_drvdata(spi, indio_dev); | ||
| 821 | |||
| 822 | indio_dev->name = spi_get_device_id(spi)->name; | 827 | indio_dev->name = spi_get_device_id(spi)->name; |
| 823 | indio_dev->modes = INDIO_DIRECT_MODE; | 828 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 824 | indio_dev->channels = st->chip_info->channels; | 829 | indio_dev->channels = st->chip_info->channels; |
| 825 | indio_dev->num_channels = st->chip_info->num_channels; | 830 | indio_dev->num_channels = st->chip_info->num_channels; |
| 826 | indio_dev->info = st->chip_info->iio_info; | 831 | indio_dev->info = st->chip_info->iio_info; |
| 827 | 832 | ||
| 828 | ret = ad_sd_setup_buffer_and_trigger(indio_dev); | 833 | ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev); |
| 829 | if (ret) | 834 | if (ret) |
| 830 | goto error_disable_reg; | 835 | return ret; |
| 831 | 836 | ||
| 832 | ret = ad7793_setup(indio_dev, pdata, vref_mv); | 837 | ret = ad7793_setup(indio_dev, pdata, vref_mv); |
| 833 | if (ret) | 838 | if (ret) |
| 834 | goto error_remove_trigger; | 839 | return ret; |
| 835 | |||
| 836 | ret = iio_device_register(indio_dev); | ||
| 837 | if (ret) | ||
| 838 | goto error_remove_trigger; | ||
| 839 | |||
| 840 | return 0; | ||
| 841 | |||
| 842 | error_remove_trigger: | ||
| 843 | ad_sd_cleanup_buffer_and_trigger(indio_dev); | ||
| 844 | error_disable_reg: | ||
| 845 | if (pdata->refsel != AD7793_REFSEL_INTERNAL) | ||
| 846 | regulator_disable(st->reg); | ||
| 847 | |||
| 848 | return ret; | ||
| 849 | } | ||
| 850 | |||
| 851 | static int ad7793_remove(struct spi_device *spi) | ||
| 852 | { | ||
| 853 | const struct ad7793_platform_data *pdata = spi->dev.platform_data; | ||
| 854 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 855 | struct ad7793_state *st = iio_priv(indio_dev); | ||
| 856 | |||
| 857 | iio_device_unregister(indio_dev); | ||
| 858 | ad_sd_cleanup_buffer_and_trigger(indio_dev); | ||
| 859 | |||
| 860 | if (pdata->refsel != AD7793_REFSEL_INTERNAL) | ||
| 861 | regulator_disable(st->reg); | ||
| 862 | 840 | ||
| 863 | return 0; | 841 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 864 | } | 842 | } |
| 865 | 843 | ||
| 866 | static const struct spi_device_id ad7793_id[] = { | 844 | static const struct spi_device_id ad7793_id[] = { |
| @@ -882,7 +860,6 @@ static struct spi_driver ad7793_driver = { · 15 unmodified lines | |||
| 882 | .name = "ad7793", | 860 | .name = "ad7793", |
| 883 | }, | 861 | }, |
| 884 | .probe = ad7793_probe, | 862 | .probe = ad7793_probe, |
| 885 | .remove = ad7793_remove, | ||
| 886 | .id_table = ad7793_id, | 863 | .id_table = ad7793_id, |
| 887 | }; | 864 | }; |
| 888 | module_spi_driver(ad7793_driver); | 865 | module_spi_driver(ad7793_driver); |
| @@ -268,7 +268,6 @@ static int ad7887_probe(struct spi_device *spi) · 267 unmodified lines | |||
| 268 | st->chip_info = | 268 | st->chip_info = |
| 269 | &ad7887_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | 269 | &ad7887_chip_info_tbl[spi_get_device_id(spi)->driver_data]; |
| 270 | 270 | ||
| 271 | spi_set_drvdata(spi, indio_dev); | ||
| 272 | st->spi = spi; | 271 | st->spi = spi; |
| 273 | 272 | ||
| 274 | indio_dev->name = spi_get_device_id(spi)->name; | 273 | indio_dev->name = spi_get_device_id(spi)->name; |
| @@ -434,8 +434,6 @@ static int ad9467_probe(struct spi_device *spi) · 433 unmodified lines | |||
| 434 | mdelay(10); | 434 | mdelay(10); |
| 435 | } | 435 | } |
| 436 | 436 | ||
| 437 | spi_set_drvdata(spi, st); | ||
| 438 | |||
| 439 | conv->chip_info = &info->axi_adc_info; | 437 | conv->chip_info = &info->axi_adc_info; |
| 440 | 438 | ||
| 441 | id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID); | 439 | id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID); |
| @@ -470,91 +470,65 @@ EXPORT_SYMBOL_GPL(ad_sd_validate_trigger); · 469 unmodified lines | |||
| 470 | static const struct iio_trigger_ops ad_sd_trigger_ops = { | 470 | static const struct iio_trigger_ops ad_sd_trigger_ops = { |
| 471 | }; | 471 | }; |
| 472 | 472 | ||
| 473 | static int ad_sd_probe_trigger(struct iio_dev *indio_dev) | 473 | static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_dev) |
| 474 | { | 474 | { |
| 475 | struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); | 475 | struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); |
| 476 | int ret; | 476 | int ret; |
| 477 | 477 | ||
| 478 | sigma_delta->trig = iio_trigger_alloc(&sigma_delta->spi->dev, | 478 | if (dev != &sigma_delta->spi->dev) { |
| 479 | "%s-dev%d", indio_dev->name, | 479 | dev_err(dev, "Trigger parent should be '%s', got '%s'\n", |
| 480 | indio_dev->id); | 480 | dev_name(dev), dev_name(&sigma_delta->spi->dev)); |
| 481 | if (sigma_delta->trig == NULL) { | 481 | return -EFAULT; |
| 482 | ret = -ENOMEM; | ||
| 483 | goto error_ret; | ||
| 484 | } | 482 | } |
| 483 | |||
| 484 | sigma_delta->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, | ||
| 485 | iio_device_id(indio_dev)); | ||
| 486 | if (sigma_delta->trig == NULL) | ||
| 487 | return -ENOMEM; | ||
| 488 | |||
| 485 | sigma_delta->trig->ops = &ad_sd_trigger_ops; | 489 | sigma_delta->trig->ops = &ad_sd_trigger_ops; |
| 486 | init_completion(&sigma_delta->completion); | 490 | init_completion(&sigma_delta->completion); |
| 487 | 491 | ||
| 488 | sigma_delta->irq_dis = true; | 492 | sigma_delta->irq_dis = true; |
| 489 | ret = request_irq(sigma_delta->spi->irq, | 493 | ret = devm_request_irq(dev, sigma_delta->spi->irq, |
| 490 | ad_sd_data_rdy_trig_poll, | 494 | ad_sd_data_rdy_trig_poll, |
| 491 | sigma_delta->info->irq_flags | IRQF_NO_AUTOEN, | 495 | sigma_delta->info->irq_flags | IRQF_NO_AUTOEN, |
| 492 | indio_dev->name, | 496 | indio_dev->name, |
| 493 | sigma_delta); | 497 | sigma_delta); |
| 494 | if (ret) | 498 | if (ret) |
| 495 | goto error_free_trig; | 499 | return ret; |
| 496 | 500 | ||
| 497 | iio_trigger_set_drvdata(sigma_delta->trig, sigma_delta); | 501 | iio_trigger_set_drvdata(sigma_delta->trig, sigma_delta); |
| 498 | 502 | ||
| 499 | ret = iio_trigger_register(sigma_delta->trig); | 503 | ret = devm_iio_trigger_register(dev, sigma_delta->trig); |
| 500 | if (ret) | 504 | if (ret) |
| 501 | goto error_free_irq; | 505 | return ret; |
| 502 | 506 | ||
| 503 | /* select default trigger */ | 507 | /* select default trigger */ |
| 504 | indio_dev->trig = iio_trigger_get(sigma_delta->trig); | 508 | indio_dev->trig = iio_trigger_get(sigma_delta->trig); |
| 505 | 509 | ||
| 506 | return 0; | 510 | return 0; |
| 507 | |||
| 508 | error_free_irq: | ||
| 509 | free_irq(sigma_delta->spi->irq, sigma_delta); | ||
| 510 | error_free_trig: | ||
| 511 | iio_trigger_free(sigma_delta->trig); | ||
| 512 | error_ret: | ||
| 513 | return ret; | ||
| 514 | } | ||
| 515 | |||
| 516 | static void ad_sd_remove_trigger(struct iio_dev *indio_dev) | ||
| 517 | { | ||
| 518 | struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); | ||
| 519 | |||
| 520 | iio_trigger_unregister(sigma_delta->trig); | ||
| 521 | free_irq(sigma_delta->spi->irq, sigma_delta); | ||
| 522 | iio_trigger_free(sigma_delta->trig); | ||
| 523 | } | 511 | } |
| 524 | 512 | ||
| 525 | /** | 513 | /** |
| 526 | * ad_sd_setup_buffer_and_trigger() - | 514 | * devm_ad_sd_setup_buffer_and_trigger() - Device-managed buffer & trigger setup |
| 515 | * @dev: Device object to which to bind the life-time of the resources attached | ||
| 527 | * @indio_dev: The IIO device | 516 | * @indio_dev: The IIO device |
| 528 | */ | 517 | */ |
| 529 | int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev) | 518 | int devm_ad_sd_setup_buffer_and_trigger(struct device *dev, struct iio_dev *indio_dev) |
| 530 | { | 519 | { |
| 531 | int ret; | 520 | int ret; |
| 532 | 521 | ||
| 533 | ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | 522 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, |
| 534 | &ad_sd_trigger_handler, &ad_sd_buffer_setup_ops); | 523 | &iio_pollfunc_store_time, |
| 524 | &ad_sd_trigger_handler, | ||
| 525 | &ad_sd_buffer_setup_ops); | ||
| 535 | if (ret) | 526 | if (ret) |
| 536 | return ret; | 527 | return ret; |
| 537 | 528 | ||
| 538 | ret = ad_sd_probe_trigger(indio_dev); | 529 | return devm_ad_sd_probe_trigger(dev, indio_dev); |
| 539 | if (ret) { | ||
| 540 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 541 | return ret; | ||
| 542 | } | ||
| 543 | |||
| 544 | return 0; | ||
| 545 | } | ||
| 546 | EXPORT_SYMBOL_GPL(ad_sd_setup_buffer_and_trigger); | ||
| 547 | |||
| 548 | /** | ||
| 549 | * ad_sd_cleanup_buffer_and_trigger() - | ||
| 550 | * @indio_dev: The IIO device | ||
| 551 | */ | ||
| 552 | void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev) | ||
| 553 | { | ||
| 554 | ad_sd_remove_trigger(indio_dev); | ||
| 555 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 556 | } | 530 | } |
| 557 | EXPORT_SYMBOL_GPL(ad_sd_cleanup_buffer_and_trigger); | 531 | EXPORT_SYMBOL_GPL(devm_ad_sd_setup_buffer_and_trigger); |
| 558 | 532 | ||
| 559 | /** | 533 | /** |
| 560 | * ad_sd_init() - Initializes a ad_sigma_delta struct | 534 | * ad_sd_init() - Initializes a ad_sigma_delta struct |
| @@ -202,29 +202,25 @@ static void adi_axi_adc_conv_unregister(struct adi_axi_adc_conv *conv) · 201 unmodified lines | |||
| 202 | kfree(cl); | 202 | kfree(cl); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | static void devm_adi_axi_adc_conv_release(struct device *dev, void *res) | 205 | static void devm_adi_axi_adc_conv_release(void *conv) |
| 206 | { | 206 | { |
| 207 | adi_axi_adc_conv_unregister(*(struct adi_axi_adc_conv **)res); | 207 | adi_axi_adc_conv_unregister(conv); |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev, | 210 | struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev, |
| 211 | size_t sizeof_priv) | 211 | size_t sizeof_priv) |
| 212 | { | 212 | { |
| 213 | struct adi_axi_adc_conv **ptr, *conv; | 213 | struct adi_axi_adc_conv *conv; |
| 214 | 214 | int ret; | |
| 215 | ptr = devres_alloc(devm_adi_axi_adc_conv_release, sizeof(*ptr), | ||
| 216 | GFP_KERNEL); | ||
| 217 | if (!ptr) | ||
| 218 | return ERR_PTR(-ENOMEM); | ||
| 219 | 215 | ||
| 220 | conv = adi_axi_adc_conv_register(dev, sizeof_priv); | 216 | conv = adi_axi_adc_conv_register(dev, sizeof_priv); |
| 221 | if (IS_ERR(conv)) { | 217 | if (IS_ERR(conv)) |
| 222 | devres_free(ptr); | 218 | return conv; |
| 223 | return ERR_CAST(conv); | ||
| 224 | } | ||
| 225 | 219 | ||
| 226 | *ptr = conv; | 220 | ret = devm_add_action_or_reset(dev, devm_adi_axi_adc_conv_release, |
| 227 | devres_add(dev, ptr); | 221 | conv); |
| 222 | if (ret) | ||
| 223 | return ERR_PTR(ret); | ||
| 228 | 224 | ||
| 229 | return conv; | 225 | return conv; |
| 230 | } | 226 | } |
| @@ -403,7 +403,8 @@ struct at91_adc_state { · 402 unmodified lines | |||
| 403 | struct at91_adc_dma dma_st; | 403 | struct at91_adc_dma dma_st; |
| 404 | struct at91_adc_touch touch_st; | 404 | struct at91_adc_touch touch_st; |
| 405 | struct iio_dev *indio_dev; | 405 | struct iio_dev *indio_dev; |
| 406 | u16 buffer[AT91_BUFFER_MAX_HWORDS]; | 406 | /* Ensure naturally aligned timestamp */ |
| 407 | u16 buffer[AT91_BUFFER_MAX_HWORDS] __aligned(8); | ||
| 407 | /* | 408 | /* |
| 408 | * lock to prevent concurrent 'single conversion' requests through | 409 | * lock to prevent concurrent 'single conversion' requests through |
| 409 | * sysfs. | 410 | * sysfs. |
| @@ -997,7 +998,7 @@ static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio, · 587 unmodified lines | |||
| 997 | int ret; | 998 | int ret; |
| 998 | 999 | ||
| 999 | trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name, | 1000 | trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name, |
| 1000 | indio->id, trigger_name); | 1001 | iio_device_id(indio), trigger_name); |
| 1001 | if (!trig) | 1002 | if (!trig) |
| 1002 | return NULL; | 1003 | return NULL; |
| 1003 | 1004 | ||
| @@ -547,7 +547,7 @@ static int at91_adc_get_trigger_value_by_name(struct iio_dev *idev, · 546 unmodified lines | |||
| 547 | char *name = kasprintf(GFP_KERNEL, | 547 | char *name = kasprintf(GFP_KERNEL, |
| 548 | "%s-dev%d-%s", | 548 | "%s-dev%d-%s", |
| 549 | idev->name, | 549 | idev->name, |
| 550 | idev->id, | 550 | iio_device_id(idev), |
| 551 | triggers[i].name); | 551 | triggers[i].name); |
| 552 | if (!name) | 552 | if (!name) |
| 553 | return -ENOMEM; | 553 | return -ENOMEM; |
| @@ -626,7 +626,7 @@ static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *idev, · 72 unmodified lines | |||
| 626 | int ret; | 626 | int ret; |
| 627 | 627 | ||
| 628 | trig = iio_trigger_alloc(idev->dev.parent, "%s-dev%d-%s", idev->name, | 628 | trig = iio_trigger_alloc(idev->dev.parent, "%s-dev%d-%s", idev->name, |
| 629 | idev->id, trigger->name); | 629 | iio_device_id(idev), trigger->name); |
| 630 | if (trig == NULL) | 630 | if (trig == NULL) |
| 631 | return NULL; | 631 | return NULL; |
| 632 | 632 | ||
| @@ -649,7 +649,8 @@ static int dln2_adc_probe(struct platform_device *pdev) · 648 unmodified lines | |||
| 649 | indio_dev->setup_ops = &dln2_adc_buffer_setup_ops; | 649 | indio_dev->setup_ops = &dln2_adc_buffer_setup_ops; |
| 650 | 650 | ||
| 651 | dln2->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", | 651 | dln2->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", |
| 652 | indio_dev->name, indio_dev->id); | 652 | indio_dev->name, |
| 653 | iio_device_id(indio_dev)); | ||
| 653 | if (!dln2->trig) { | 654 | if (!dln2->trig) { |
| 654 | dev_err(dev, "failed to allocate trigger\n"); | 655 | dev_err(dev, "failed to allocate trigger\n"); |
| 655 | return -ENOMEM; | 656 | return -ENOMEM; |
| @@ -165,10 +165,8 @@ static int ep93xx_adc_probe(struct platform_device *pdev) · 164 unmodified lines | |||
| 165 | 165 | ||
| 166 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 166 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 167 | priv->base = devm_ioremap_resource(&pdev->dev, res); | 167 | priv->base = devm_ioremap_resource(&pdev->dev, res); |
| 168 | if (IS_ERR(priv->base)) { | 168 | if (IS_ERR(priv->base)) |
| 169 | dev_err(&pdev->dev, "Cannot map memory resource\n"); | ||
| 170 | return PTR_ERR(priv->base); | 169 | return PTR_ERR(priv->base); |
| 171 | } | ||
| 172 | 170 | ||
| 173 | iiodev->name = dev_name(&pdev->dev); | 171 | iiodev->name = dev_name(&pdev->dev); |
| 174 | iiodev->modes = INDIO_DIRECT_MODE; | 172 | iiodev->modes = INDIO_DIRECT_MODE; |
| @@ -794,7 +794,7 @@ static int exynos_adc_probe(struct platform_device *pdev) · 793 unmodified lines | |||
| 794 | struct s3c2410_ts_mach_info *pdata = dev_get_platdata(&pdev->dev); | 794 | struct s3c2410_ts_mach_info *pdata = dev_get_platdata(&pdev->dev); |
| 795 | struct iio_dev *indio_dev = NULL; | 795 | struct iio_dev *indio_dev = NULL; |
| 796 | bool has_ts = false; | 796 | bool has_ts = false; |
| 797 | int ret = -ENODEV; | 797 | int ret; |
| 798 | int irq; | 798 | int irq; |
| 799 | 799 | ||
| 800 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct exynos_adc)); | 800 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct exynos_adc)); |
| @@ -483,7 +483,6 @@ static int hi8435_probe(struct spi_device *spi) · 482 unmodified lines | |||
| 483 | gpiod_set_value_cansleep(reset_gpio, 1); | 483 | gpiod_set_value_cansleep(reset_gpio, 1); |
| 484 | } | 484 | } |
| 485 | 485 | ||
| 486 | spi_set_drvdata(spi, idev); | ||
| 487 | mutex_init(&priv->lock); | 486 | mutex_init(&priv->lock); |
| 488 | 487 | ||
| 489 | idev->name = spi_get_device_id(spi)->name; | 488 | idev->name = spi_get_device_id(spi)->name; |
| @@ -86,9 +86,9 @@ struct hx711_data { · 85 unmodified lines | |||
| 86 | struct mutex lock; | 86 | struct mutex lock; |
| 87 | /* | 87 | /* |
| 88 | * triggered buffer | 88 | * triggered buffer |
| 89 | * 2x32-bit channel + 64-bit timestamp | 89 | * 2x32-bit channel + 64-bit naturally aligned timestamp |
| 90 | */ | 90 | */ |
| 91 | u32 buffer[4]; | 91 | u32 buffer[4] __aligned(8); |
| 92 | /* | 92 | /* |
| 93 | * delay after a rising edge on SCK until the data is ready DOUT | 93 | * delay after a rising edge on SCK until the data is ready DOUT |
| 94 | * this is dependent on the hx711 where the datasheet tells a | 94 | * this is dependent on the hx711 where the datasheet tells a |
| @@ -843,7 +843,8 @@ static int ina2xx_buffer_enable(struct iio_dev *indio_dev) · 842 unmodified lines | |||
| 843 | chip->allow_async_readout); | 843 | chip->allow_async_readout); |
| 844 | 844 | ||
| 845 | task = kthread_create(ina2xx_capture_thread, (void *)indio_dev, | 845 | task = kthread_create(ina2xx_capture_thread, (void *)indio_dev, |
| 846 | "%s:%d-%uus", indio_dev->name, indio_dev->id, | 846 | "%s:%d-%uus", indio_dev->name, |
| 847 | iio_device_id(indio_dev), | ||
| 847 | sampling_us); | 848 | sampling_us); |
| 848 | if (IS_ERR(task)) | 849 | if (IS_ERR(task)) |
| 849 | return PTR_ERR(task); | 850 | return PTR_ERR(task); |
| @@ -430,8 +430,6 @@ static int max1027_probe(struct spi_device *spi) · 429 unmodified lines | |||
| 430 | return -ENOMEM; | 430 | return -ENOMEM; |
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | spi_set_drvdata(spi, indio_dev); | ||
| 434 | |||
| 435 | st = iio_priv(indio_dev); | 433 | st = iio_priv(indio_dev); |
| 436 | st->spi = spi; | 434 | st->spi = spi; |
| 437 | st->info = &max1027_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | 435 | st->info = &max1027_chip_info_tbl[spi_get_device_id(spi)->driver_data]; |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/regulator/consumer.h> | 13 | #include <linux/regulator/consumer.h> |
| 14 | #include <linux/spi/spi.h> | 14 | #include <linux/spi/spi.h> |
| 15 | #include <asm/unaligned.h> | ||
| 15 | 16 | ||
| 16 | #include <linux/iio/iio.h> | 17 | #include <linux/iio/iio.h> |
| 17 | #include <linux/iio/driver.h> | 18 | #include <linux/iio/driver.h> |
| @@ -63,7 +64,7 @@ static int max11100_read_single(struct iio_dev *indio_dev, int *val) · 45 unmodified lines | |||
| 63 | return -EINVAL; | 64 | return -EINVAL; |
| 64 | } | 65 | } |
| 65 | 66 | ||
| 66 | *val = (state->buffer[1] << 8) | state->buffer[2]; | 67 | *val = get_unaligned_be16(&state->buffer[1]); |
| 67 | 68 | ||
| 68 | return 0; | 69 | return 0; |
| 69 | } | 70 | } |
| @@ -101,6 +102,11 @@ static const struct iio_info max11100_info = { · 31 unmodified lines | |||
| 101 | .read_raw = max11100_read_raw, | 102 | .read_raw = max11100_read_raw, |
| 102 | }; | 103 | }; |
| 103 | 104 | ||
| 105 | static void max11100_regulator_disable(void *reg) | ||
| 106 | { | ||
| 107 | regulator_disable(reg); | ||
| 108 | } | ||
| 109 | |||
| 104 | static int max11100_probe(struct spi_device *spi) | 110 | static int max11100_probe(struct spi_device *spi) |
| 105 | { | 111 | { |
| 106 | int ret; | 112 | int ret; |
| @@ -111,8 +117,6 @@ static int max11100_probe(struct spi_device *spi) · 4 unmodified lines | |||
| 111 | if (!indio_dev) | 117 | if (!indio_dev) |
| 112 | return -ENOMEM; | 118 | return -ENOMEM; |
| 113 | 119 | ||
| 114 | spi_set_drvdata(spi, indio_dev); | ||
| 115 | |||
| 116 | state = iio_priv(indio_dev); | 120 | state = iio_priv(indio_dev); |
| 117 | state->spi = spi; | 121 | state->spi = spi; |
| 118 | 122 | ||
| @@ -130,27 +134,12 @@ static int max11100_probe(struct spi_device *spi) · 11 unmodified lines | |||
| 130 | if (ret) | 134 | if (ret) |
| 131 | return ret; | 135 | return ret; |
| 132 | 136 | ||
| 133 | ret = iio_device_register(indio_dev); | 137 | ret = devm_add_action_or_reset(&spi->dev, max11100_regulator_disable, |
| 138 | state->vref_reg); | ||
| 134 | if (ret) | 139 | if (ret) |
| 135 | goto disable_regulator; | 140 | return ret; |
| 136 | |||
| 137 | return 0; | ||
| 138 | |||
| 139 | disable_regulator: | ||
| 140 | regulator_disable(state->vref_reg); | ||
| 141 | |||
| 142 | return ret; | ||
| 143 | } | ||
| 144 | |||
| 145 | static int max11100_remove(struct spi_device *spi) | ||
| 146 | { | ||
| 147 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 148 | struct max11100_state *state = iio_priv(indio_dev); | ||
| 149 | |||
| 150 | iio_device_unregister(indio_dev); | ||
| 151 | regulator_disable(state->vref_reg); | ||
| 152 | 141 | ||
| 153 | return 0; | 142 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 154 | } | 143 | } |
| 155 | 144 | ||
| 156 | static const struct of_device_id max11100_ids[] = { | 145 | static const struct of_device_id max11100_ids[] = { |
| @@ -165,7 +154,6 @@ static struct spi_driver max11100_driver = { · 8 unmodified lines | |||
| 165 | .of_match_table = max11100_ids, | 154 | .of_match_table = max11100_ids, |
| 166 | }, | 155 | }, |
| 167 | .probe = max11100_probe, | 156 | .probe = max11100_probe, |
| 168 | .remove = max11100_remove, | ||
| 169 | }; | 157 | }; |
| 170 | 158 | ||
| 171 | module_spi_driver(max11100_driver); | 159 | module_spi_driver(max11100_driver); |
| @@ -66,9 +66,8 @@ static const struct iio_chan_spec max1118_channels[] = { · 65 unmodified lines | |||
| 66 | IIO_CHAN_SOFT_TIMESTAMP(2), | 66 | IIO_CHAN_SOFT_TIMESTAMP(2), |
| 67 | }; | 67 | }; |
| 68 | 68 | ||
| 69 | static int max1118_read(struct spi_device *spi, int channel) | 69 | static int max1118_read(struct iio_dev *indio_dev, int channel) |
| 70 | { | 70 | { |
| 71 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 72 | struct max1118 *adc = iio_priv(indio_dev); | 71 | struct max1118 *adc = iio_priv(indio_dev); |
| 73 | struct spi_transfer xfers[] = { | 72 | struct spi_transfer xfers[] = { |
| 74 | /* | 73 | /* |
| @@ -103,9 +102,9 @@ static int max1118_read(struct spi_device *spi, int channel) · 28 unmodified lines | |||
| 103 | int ret; | 102 | int ret; |
| 104 | 103 | ||
| 105 | if (channel == 0) | 104 | if (channel == 0) |
| 106 | ret = spi_sync_transfer(spi, xfers + 1, 2); | 105 | ret = spi_sync_transfer(adc->spi, xfers + 1, 2); |
| 107 | else | 106 | else |
| 108 | ret = spi_sync_transfer(spi, xfers, 3); | 107 | ret = spi_sync_transfer(adc->spi, xfers, 3); |
| 109 | 108 | ||
| 110 | if (ret) | 109 | if (ret) |
| 111 | return ret; | 110 | return ret; |
| @@ -113,11 +112,10 @@ static int max1118_read(struct spi_device *spi, int channel) · 1 unmodified line | |||
| 113 | return adc->data; | 112 | return adc->data; |
| 114 | } | 113 | } |
| 115 | 114 | ||
| 116 | static int max1118_get_vref_mV(struct spi_device *spi) | 115 | static int max1118_get_vref_mV(struct iio_dev *indio_dev) |
| 117 | { | 116 | { |
| 118 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 119 | struct max1118 *adc = iio_priv(indio_dev); | 117 | struct max1118 *adc = iio_priv(indio_dev); |
| 120 | const struct spi_device_id *id = spi_get_device_id(spi); | 118 | const struct spi_device_id *id = spi_get_device_id(adc->spi); |
| 121 | int vref_uV; | 119 | int vref_uV; |
| 122 | 120 | ||
| 123 | switch (id->driver_data) { | 121 | switch (id->driver_data) { |
| @@ -144,14 +142,14 @@ static int max1118_read_raw(struct iio_dev *indio_dev, · 20 unmodified lines | |||
| 144 | switch (mask) { | 142 | switch (mask) { |
| 145 | case IIO_CHAN_INFO_RAW: | 143 | case IIO_CHAN_INFO_RAW: |
| 146 | mutex_lock(&adc->lock); | 144 | mutex_lock(&adc->lock); |
| 147 | *val = max1118_read(adc->spi, chan->channel); | 145 | *val = max1118_read(indio_dev, chan->channel); |
| 148 | mutex_unlock(&adc->lock); | 146 | mutex_unlock(&adc->lock); |
| 149 | if (*val < 0) | 147 | if (*val < 0) |
| 150 | return *val; | 148 | return *val; |
| 151 | 149 | ||
| 152 | return IIO_VAL_INT; | 150 | return IIO_VAL_INT; |
| 153 | case IIO_CHAN_INFO_SCALE: | 151 | case IIO_CHAN_INFO_SCALE: |
| 154 | *val = max1118_get_vref_mV(adc->spi); | 152 | *val = max1118_get_vref_mV(indio_dev); |
| 155 | if (*val < 0) | 153 | if (*val < 0) |
| 156 | return *val; | 154 | return *val; |
| 157 | *val2 = 8; | 155 | *val2 = 8; |
| @@ -180,7 +178,7 @@ static irqreturn_t max1118_trigger_handler(int irq, void *p) · 22 unmodified lines | |||
| 180 | indio_dev->masklength) { | 178 | indio_dev->masklength) { |
| 181 | const struct iio_chan_spec *scan_chan = | 179 | const struct iio_chan_spec *scan_chan = |
| 182 | &indio_dev->channels[scan_index]; | 180 | &indio_dev->channels[scan_index]; |
| 183 | int ret = max1118_read(adc->spi, scan_chan->channel); | 181 | int ret = max1118_read(indio_dev, scan_chan->channel); |
| 184 | 182 | ||
| 185 | if (ret < 0) { | 183 | if (ret < 0) { |
| 186 | dev_warn(&adc->spi->dev, | 184 | dev_warn(&adc->spi->dev, |
| @@ -201,6 +199,11 @@ out: · 14 unmodified lines | |||
| 201 | return IRQ_HANDLED; | 199 | return IRQ_HANDLED; |
| 202 | } | 200 | } |
| 203 | 201 | ||
| 202 | static void max1118_reg_disable(void *reg) | ||
| 203 | { | ||
| 204 | regulator_disable(reg); | ||
| 205 | } | ||
| 206 | |||
| 204 | static int max1118_probe(struct spi_device *spi) | 207 | static int max1118_probe(struct spi_device *spi) |
| 205 | { | 208 | { |
| 206 | struct iio_dev *indio_dev; | 209 | struct iio_dev *indio_dev; |
| @@ -225,9 +228,13 @@ static int max1118_probe(struct spi_device *spi) · 18 unmodified lines | |||
| 225 | ret = regulator_enable(adc->reg); | 228 | ret = regulator_enable(adc->reg); |
| 226 | if (ret) | 229 | if (ret) |
| 227 | return ret; | 230 | return ret; |
| 228 | } | ||
| 229 | 231 | ||
| 230 | spi_set_drvdata(spi, indio_dev); | 232 | ret = devm_add_action_or_reset(&spi->dev, max1118_reg_disable, |
| 233 | adc->reg); | ||
| 234 | if (ret) | ||
| 235 | return ret; | ||
| 236 | |||
| 237 | } | ||
| 231 | 238 | ||
| 232 | indio_dev->name = spi_get_device_id(spi)->name; | 239 | indio_dev->name = spi_get_device_id(spi)->name; |
| 233 | indio_dev->info = &max1118_info; | 240 | indio_dev->info = &max1118_info; |
| @@ -241,40 +248,14 @@ static int max1118_probe(struct spi_device *spi) · 7 unmodified lines | |||
| 241 | * a conversion has been completed, the MAX1117/MAX1118/MAX1119 will go | 248 | * a conversion has been completed, the MAX1117/MAX1118/MAX1119 will go |
| 242 | * into AutoShutdown mode until the next conversion is initiated. | 249 | * into AutoShutdown mode until the next conversion is initiated. |
| 243 | */ | 250 | */ |
| 244 | max1118_read(spi, 0); | 251 | max1118_read(indio_dev, 0); |
| 245 | |||
| 246 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | ||
| 247 | max1118_trigger_handler, NULL); | ||
| 248 | if (ret) | ||
| 249 | goto err_reg_disable; | ||
| 250 | 252 | ||
| 251 | ret = iio_device_register(indio_dev); | 253 | ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, |
| 254 | max1118_trigger_handler, NULL); | ||
| 252 | if (ret) | 255 | if (ret) |
| 253 | goto err_buffer_cleanup; | 256 | return ret; |
| 254 | |||
| 255 | return 0; | ||
| 256 | |||
| 257 | err_buffer_cleanup: | ||
| 258 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 259 | err_reg_disable: | ||
| 260 | if (id->driver_data == max1118) | ||
| 261 | regulator_disable(adc->reg); | ||
| 262 | |||
| 263 | return ret; | ||
| 264 | } | ||
| 265 | |||
| 266 | static int max1118_remove(struct spi_device *spi) | ||
| 267 | { | ||
| 268 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 269 | struct max1118 *adc = iio_priv(indio_dev); | ||
| 270 | const struct spi_device_id *id = spi_get_device_id(spi); | ||
| 271 | |||
| 272 | iio_device_unregister(indio_dev); | ||
| 273 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 274 | if (id->driver_data == max1118) | ||
| 275 | return regulator_disable(adc->reg); | ||
| 276 | 257 | ||
| 277 | return 0; | 258 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 278 | } | 259 | } |
| 279 | 260 | ||
| 280 | static const struct spi_device_id max1118_id[] = { | 261 | static const struct spi_device_id max1118_id[] = { |
| @@ -299,7 +280,6 @@ static struct spi_driver max1118_spi_driver = { · 18 unmodified lines | |||
| 299 | .of_match_table = max1118_dt_ids, | 280 | .of_match_table = max1118_dt_ids, |
| 300 | }, | 281 | }, |
| 301 | .probe = max1118_probe, | 282 | .probe = max1118_probe, |
| 302 | .remove = max1118_remove, | ||
| 303 | .id_table = max1118_id, | 283 | .id_table = max1118_id, |
| 304 | }; | 284 | }; |
| 305 | module_spi_driver(max1118_spi_driver); | 285 | module_spi_driver(max1118_spi_driver); |
| @@ -147,8 +147,6 @@ static int max1241_probe(struct spi_device *spi) · 146 unmodified lines | |||
| 147 | adc->spi = spi; | 147 | adc->spi = spi; |
| 148 | mutex_init(&adc->lock); | 148 | mutex_init(&adc->lock); |
| 149 | 149 | ||
| 150 | spi_set_drvdata(spi, indio_dev); | ||
| 151 | |||
| 152 | adc->vdd = devm_regulator_get(dev, "vdd"); | 150 | adc->vdd = devm_regulator_get(dev, "vdd"); |
| 153 | if (IS_ERR(adc->vdd)) { | 151 | if (IS_ERR(adc->vdd)) { |
| 154 | dev_err(dev, "failed to get vdd regulator\n"); | 152 | dev_err(dev, "failed to get vdd regulator\n"); |
| @@ -144,7 +144,6 @@ static int mp2629_adc_probe(struct platform_device *pdev) · 143 unmodified lines | |||
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | indio_dev->name = "mp2629-adc"; | 146 | indio_dev->name = "mp2629-adc"; |
| 147 | indio_dev->dev.parent = dev; | ||
| 148 | indio_dev->channels = mp2629_channels; | 147 | indio_dev->channels = mp2629_channels; |
| 149 | indio_dev->num_channels = ARRAY_SIZE(mp2629_channels); | 148 | indio_dev->num_channels = ARRAY_SIZE(mp2629_channels); |
| 150 | indio_dev->modes = INDIO_DIRECT_MODE; | 149 | indio_dev->modes = INDIO_DIRECT_MODE; |
| @@ -337,7 +337,6 @@ static int mt6360_adc_probe(struct platform_device *pdev) · 336 unmodified lines | |||
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | indio_dev->name = dev_name(&pdev->dev); | 339 | indio_dev->name = dev_name(&pdev->dev); |
| 340 | indio_dev->dev.parent = &pdev->dev; | ||
| 341 | indio_dev->info = &mt6360_adc_iio_info; | 340 | indio_dev->info = &mt6360_adc_iio_info; |
| 342 | indio_dev->modes = INDIO_DIRECT_MODE; | 341 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 343 | indio_dev->channels = mt6360_adc_channels; | 342 | indio_dev->channels = mt6360_adc_channels; |
| @@ -115,7 +115,8 @@ struct mxs_lradc_adc { · 114 unmodified lines | |||
| 115 | struct device *dev; | 115 | struct device *dev; |
| 116 | 116 | ||
| 117 | void __iomem *base; | 117 | void __iomem *base; |
| 118 | u32 buffer[10]; | 118 | /* Maximum of 8 channels + 8 byte ts */ |
| 119 | u32 buffer[10] __aligned(8); | ||
| 119 | struct iio_trigger *trig; | 120 | struct iio_trigger *trig; |
| 120 | struct completion completion; | 121 | struct completion completion; |
| 121 | spinlock_t lock; | 122 | spinlock_t lock; |
| @@ -455,7 +456,7 @@ static int mxs_lradc_adc_trigger_init(struct iio_dev *iio) · 333 unmodified lines | |||
| 455 | struct mxs_lradc_adc *adc = iio_priv(iio); | 456 | struct mxs_lradc_adc *adc = iio_priv(iio); |
| 456 | 457 | ||
| 457 | trig = devm_iio_trigger_alloc(&iio->dev, "%s-dev%i", iio->name, | 458 | trig = devm_iio_trigger_alloc(&iio->dev, "%s-dev%i", iio->name, |
| 458 | iio->id); | 459 | iio_device_id(iio)); |
| 459 | if (!trig) | 460 | if (!trig) |
| 460 | return -ENOMEM; | 461 | return -ENOMEM; |
| 461 | 462 | ||
| @@ -162,18 +162,13 @@ static const struct iio_chan_spec rcar_gyroadc_iio_channels_3[] = { · 161 unmodified lines | |||
| 162 | static int rcar_gyroadc_set_power(struct rcar_gyroadc *priv, bool on) | 162 | static int rcar_gyroadc_set_power(struct rcar_gyroadc *priv, bool on) |
| 163 | { | 163 | { |
| 164 | struct device *dev = priv->dev; | 164 | struct device *dev = priv->dev; |
| 165 | int ret; | ||
| 166 | 165 | ||
| 167 | if (on) { | 166 | if (on) { |
| 168 | ret = pm_runtime_get_sync(dev); | 167 | return pm_runtime_resume_and_get(dev); |
| 169 | if (ret < 0) | ||
| 170 | pm_runtime_put_noidle(dev); | ||
| 171 | } else { | 168 | } else { |
| 172 | pm_runtime_mark_last_busy(dev); | 169 | pm_runtime_mark_last_busy(dev); |
| 173 | ret = pm_runtime_put_autosuspend(dev); | 170 | return pm_runtime_put_autosuspend(dev); |
| 174 | } | 171 | } |
| 175 | |||
| 176 | return ret; | ||
| 177 | } | 172 | } |
| 178 | 173 | ||
| 179 | static int rcar_gyroadc_read_raw(struct iio_dev *indio_dev, | 174 | static int rcar_gyroadc_read_raw(struct iio_dev *indio_dev, |
| @@ -535,7 +530,10 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) · 355 unmodified lines | |||
| 535 | pm_runtime_use_autosuspend(dev); | 530 | pm_runtime_use_autosuspend(dev); |
| 536 | pm_runtime_enable(dev); | 531 | pm_runtime_enable(dev); |
| 537 | 532 | ||
| 538 | pm_runtime_get_sync(dev); | 533 | ret = pm_runtime_resume_and_get(dev); |
| 534 | if (ret) | ||
| 535 | goto err_power_up; | ||
| 536 | |||
| 539 | rcar_gyroadc_hw_init(priv); | 537 | rcar_gyroadc_hw_init(priv); |
| 540 | rcar_gyroadc_hw_start(priv); | 538 | rcar_gyroadc_hw_start(priv); |
| 541 | 539 | ||
| @@ -552,6 +550,7 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) · 10 unmodified lines | |||
| 552 | err_iio_device_register: | 550 | err_iio_device_register: |
| 553 | rcar_gyroadc_hw_stop(priv); | 551 | rcar_gyroadc_hw_stop(priv); |
| 554 | pm_runtime_put_sync(dev); | 552 | pm_runtime_put_sync(dev); |
| 553 | err_power_up: | ||
| 555 | pm_runtime_disable(dev); | 554 | pm_runtime_disable(dev); |
| 556 | pm_runtime_set_suspended(dev); | 555 | pm_runtime_set_suspended(dev); |
| 557 | clk_disable_unprepare(priv->clk); | 556 | clk_disable_unprepare(priv->clk); |
| @@ -549,6 +549,7 @@ static const struct of_device_id sc27xx_adc_of_match[] = { · 548 unmodified lines | |||
| 549 | { .compatible = "sprd,sc2731-adc", }, | 549 | { .compatible = "sprd,sc2731-adc", }, |
| 550 | { } | 550 | { } |
| 551 | }; | 551 | }; |
| 552 | MODULE_DEVICE_TABLE(of, sc27xx_adc_of_match); | ||
| 552 | 553 | ||
| 553 | static struct platform_driver sc27xx_adc_driver = { | 554 | static struct platform_driver sc27xx_adc_driver = { |
| 554 | .probe = sc27xx_adc_probe, | 555 | .probe = sc27xx_adc_probe, |
| @@ -449,7 +449,7 @@ static const struct stm32_adc_regspec stm32h7_adc_regspec = { · 448 unmodified lines | |||
| 449 | .smp_bits = stm32h7_smp_bits, | 449 | .smp_bits = stm32h7_smp_bits, |
| 450 | }; | 450 | }; |
| 451 | 451 | ||
| 452 | /** | 452 | /* |
| 453 | * STM32 ADC registers access routines | 453 | * STM32 ADC registers access routines |
| 454 | * @adc: stm32 adc instance | 454 | * @adc: stm32 adc instance |
| 455 | * @reg: reg offset in adc instance | 455 | * @reg: reg offset in adc instance |
| @@ -851,7 +851,7 @@ static int stm32h7_adc_restore_selfcalib(struct iio_dev *indio_dev) · 395 unmodified lines | |||
| 851 | return 0; | 851 | return 0; |
| 852 | } | 852 | } |
| 853 | 853 | ||
| 854 | /** | 854 | /* |
| 855 | * Fixed timeout value for ADC calibration. | 855 | * Fixed timeout value for ADC calibration. |
| 856 | * worst cases: | 856 | * worst cases: |
| 857 | * - low clock frequency | 857 | * - low clock frequency |
| @@ -1158,11 +1158,9 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, · 300 unmodified lines | |||
| 1158 | 1158 | ||
| 1159 | adc->bufi = 0; | 1159 | adc->bufi = 0; |
| 1160 | 1160 | ||
| 1161 | ret = pm_runtime_get_sync(dev); | 1161 | ret = pm_runtime_resume_and_get(dev); |
| 1162 | if (ret < 0) { | 1162 | if (ret < 0) |
| 1163 | pm_runtime_put_noidle(dev); | ||
| 1164 | return ret; | 1163 | return ret; |
| 1165 | } | ||
| 1166 | 1164 | ||
| 1167 | /* Apply sampling time settings */ | 1165 | /* Apply sampling time settings */ |
| 1168 | stm32_adc_writel(adc, regs->smpr[0], adc->smpr_val[0]); | 1166 | stm32_adc_writel(adc, regs->smpr[0], adc->smpr_val[0]); |
| @@ -1364,11 +1362,9 @@ static int stm32_adc_update_scan_mode(struct iio_dev *indio_dev, · 195 unmodified lines | |||
| 1364 | struct device *dev = indio_dev->dev.parent; | 1362 | struct device *dev = indio_dev->dev.parent; |
| 1365 | int ret; | 1363 | int ret; |
| 1366 | 1364 | ||
| 1367 | ret = pm_runtime_get_sync(dev); | 1365 | ret = pm_runtime_resume_and_get(dev); |
| 1368 | if (ret < 0) { | 1366 | if (ret < 0) |
| 1369 | pm_runtime_put_noidle(dev); | ||
| 1370 | return ret; | 1367 | return ret; |
| 1371 | } | ||
| 1372 | 1368 | ||
| 1373 | adc->num_conv = bitmap_weight(scan_mask, indio_dev->masklength); | 1369 | adc->num_conv = bitmap_weight(scan_mask, indio_dev->masklength); |
| 1374 | 1370 | ||
| @@ -1413,11 +1409,9 @@ static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev, · 38 unmodified lines | |||
| 1413 | struct device *dev = indio_dev->dev.parent; | 1409 | struct device *dev = indio_dev->dev.parent; |
| 1414 | int ret; | 1410 | int ret; |
| 1415 | 1411 | ||
| 1416 | ret = pm_runtime_get_sync(dev); | 1412 | ret = pm_runtime_resume_and_get(dev); |
| 1417 | if (ret < 0) { | 1413 | if (ret < 0) |
| 1418 | pm_runtime_put_noidle(dev); | ||
| 1419 | return ret; | 1414 | return ret; |
| 1420 | } | ||
| 1421 | 1415 | ||
| 1422 | if (!readval) | 1416 | if (!readval) |
| 1423 | stm32_adc_writel(adc, reg, writeval); | 1417 | stm32_adc_writel(adc, reg, writeval); |
| @@ -1537,11 +1531,9 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev) · 113 unmodified lines | |||
| 1537 | struct device *dev = indio_dev->dev.parent; | 1531 | struct device *dev = indio_dev->dev.parent; |
| 1538 | int ret; | 1532 | int ret; |
| 1539 | 1533 | ||
| 1540 | ret = pm_runtime_get_sync(dev); | 1534 | ret = pm_runtime_resume_and_get(dev); |
| 1541 | if (ret < 0) { | 1535 | if (ret < 0) |
| 1542 | pm_runtime_put_noidle(dev); | ||
| 1543 | return ret; | 1536 | return ret; |
| 1544 | } | ||
| 1545 | 1537 | ||
| 1546 | ret = stm32_adc_set_trig(indio_dev, indio_dev->trig); | 1538 | ret = stm32_adc_set_trig(indio_dev, indio_dev->trig); |
| 1547 | if (ret) { | 1539 | if (ret) { |
| @@ -135,11 +135,9 @@ int stm32_dfsdm_start_dfsdm(struct stm32_dfsdm *dfsdm) · 134 unmodified lines | |||
| 135 | int ret; | 135 | int ret; |
| 136 | 136 | ||
| 137 | if (atomic_inc_return(&priv->n_active_ch) == 1) { | 137 | if (atomic_inc_return(&priv->n_active_ch) == 1) { |
| 138 | ret = pm_runtime_get_sync(dev); | 138 | ret = pm_runtime_resume_and_get(dev); |
| 139 | if (ret < 0) { | 139 | if (ret < 0) |
| 140 | pm_runtime_put_noidle(dev); | ||
| 141 | goto error_ret; | 140 | goto error_ret; |
| 142 | } | ||
| 143 | 141 | ||
| 144 | /* select clock source, e.g. 0 for "dfsdm" or 1 for "audio" */ | 142 | /* select clock source, e.g. 0 for "dfsdm" or 1 for "audio" */ |
| 145 | clk_src = priv->aclk ? 1 : 0; | 143 | clk_src = priv->aclk ? 1 : 0; |
| @@ -146,6 +146,11 @@ out: · 145 unmodified lines | |||
| 146 | return IRQ_HANDLED; | 146 | return IRQ_HANDLED; |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | static void adc081c_reg_disable(void *reg) | ||
| 150 | { | ||
| 151 | regulator_disable(reg); | ||
| 152 | } | ||
| 153 | |||
| 149 | static int adc081c_probe(struct i2c_client *client, | 154 | static int adc081c_probe(struct i2c_client *client, |
| 150 | const struct i2c_device_id *id) | 155 | const struct i2c_device_id *id) |
| 151 | { | 156 | { |
| @@ -175,6 +180,11 @@ static int adc081c_probe(struct i2c_client *client, · 23 unmodified lines | |||
| 175 | if (err < 0) | 180 | if (err < 0) |
| 176 | return err; | 181 | return err; |
| 177 | 182 | ||
| 183 | err = devm_add_action_or_reset(&client->dev, adc081c_reg_disable, | ||
| 184 | adc->ref); | ||
| 185 | if (err) | ||
| 186 | return err; | ||
| 187 | |||
| 178 | iio->name = dev_name(&client->dev); | 188 | iio->name = dev_name(&client->dev); |
| 179 | iio->modes = INDIO_DIRECT_MODE; | 189 | iio->modes = INDIO_DIRECT_MODE; |
| 180 | iio->info = &adc081c_info; | 190 | iio->info = &adc081c_info; |
| @@ -182,38 +192,14 @@ static int adc081c_probe(struct i2c_client *client, · 1 unmodified line | |||
| 182 | iio->channels = model->channels; | 192 | iio->channels = model->channels; |
| 183 | iio->num_channels = ADC081C_NUM_CHANNELS; | 193 | iio->num_channels = ADC081C_NUM_CHANNELS; |
| 184 | 194 | ||
| 185 | err = iio_triggered_buffer_setup(iio, NULL, adc081c_trigger_handler, NULL); | 195 | err = devm_iio_triggered_buffer_setup(&client->dev, iio, NULL, |
| 196 | adc081c_trigger_handler, NULL); | ||
| 186 | if (err < 0) { | 197 | if (err < 0) { |
| 187 | dev_err(&client->dev, "iio triggered buffer setup failed\n"); | 198 | dev_err(&client->dev, "iio triggered buffer setup failed\n"); |
| 188 | goto err_regulator_disable; | 199 | return err; |
| 189 | } | 200 | } |
| 190 | 201 | ||
| 191 | err = iio_device_register(iio); | 202 | return devm_iio_device_register(&client->dev, iio); |
| 192 | if (err < 0) | ||
| 193 | goto err_buffer_cleanup; | ||
| 194 | |||
| 195 | i2c_set_clientdata(client, iio); | ||
| 196 | |||
| 197 | return 0; | ||
| 198 | |||
| 199 | err_buffer_cleanup: | ||
| 200 | iio_triggered_buffer_cleanup(iio); | ||
| 201 | err_regulator_disable: | ||
| 202 | regulator_disable(adc->ref); | ||
| 203 | |||
| 204 | return err; | ||
| 205 | } | ||
| 206 | |||
| 207 | static int adc081c_remove(struct i2c_client *client) | ||
| 208 | { | ||
| 209 | struct iio_dev *iio = i2c_get_clientdata(client); | ||
| 210 | struct adc081c *adc = iio_priv(iio); | ||
| 211 | |||
| 212 | iio_device_unregister(iio); | ||
| 213 | iio_triggered_buffer_cleanup(iio); | ||
| 214 | regulator_disable(adc->ref); | ||
| 215 | |||
| 216 | return 0; | ||
| 217 | } | 203 | } |
| 218 | 204 | ||
| 219 | static const struct i2c_device_id adc081c_id[] = { | 205 | static const struct i2c_device_id adc081c_id[] = { |
| @@ -238,7 +224,6 @@ static struct i2c_driver adc081c_driver = { · 18 unmodified lines | |||
| 238 | .of_match_table = adc081c_of_match, | 224 | .of_match_table = adc081c_of_match, |
| 239 | }, | 225 | }, |
| 240 | .probe = adc081c_probe, | 226 | .probe = adc081c_probe, |
| 241 | .remove = adc081c_remove, | ||
| 242 | .id_table = adc081c_id, | 227 | .id_table = adc081c_id, |
| 243 | }; | 228 | }; |
| 244 | module_i2c_driver(adc081c_driver); | 229 | module_i2c_driver(adc081c_driver); |
| @@ -236,6 +236,11 @@ out: · 235 unmodified lines | |||
| 236 | return IRQ_HANDLED; | 236 | return IRQ_HANDLED; |
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | static void adc0832_reg_disable(void *reg) | ||
| 240 | { | ||
| 241 | regulator_disable(reg); | ||
| 242 | } | ||
| 243 | |||
| 239 | static int adc0832_probe(struct spi_device *spi) | 244 | static int adc0832_probe(struct spi_device *spi) |
| 240 | { | 245 | { |
| 241 | struct iio_dev *indio_dev; | 246 | struct iio_dev *indio_dev; |
| @@ -287,36 +292,17 @@ static int adc0832_probe(struct spi_device *spi) · 45 unmodified lines | |||
| 287 | if (ret) | 292 | if (ret) |
| 288 | return ret; | 293 | return ret; |
| 289 | 294 | ||
| 290 | spi_set_drvdata(spi, indio_dev); | 295 | ret = devm_add_action_or_reset(&spi->dev, adc0832_reg_disable, |
| 291 | 296 | adc->reg); | |
| 292 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | ||
| 293 | adc0832_trigger_handler, NULL); | ||
| 294 | if (ret) | 297 | if (ret) |
| 295 | goto err_reg_disable; | 298 | return ret; |
| 296 | 299 | ||
| 297 | ret = iio_device_register(indio_dev); | 300 | ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, |
| 301 | adc0832_trigger_handler, NULL); | ||
| 298 | if (ret) | 302 | if (ret) |
| 299 | goto err_buffer_cleanup; | 303 | return ret; |
| 300 | |||
| 301 | return 0; | ||
| 302 | err_buffer_cleanup: | ||
| 303 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 304 | err_reg_disable: | ||
| 305 | regulator_disable(adc->reg); | ||
| 306 | |||
| 307 | return ret; | ||
| 308 | } | ||
| 309 | |||
| 310 | static int adc0832_remove(struct spi_device *spi) | ||
| 311 | { | ||
| 312 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 313 | struct adc0832 *adc = iio_priv(indio_dev); | ||
| 314 | |||
| 315 | iio_device_unregister(indio_dev); | ||
| 316 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 317 | regulator_disable(adc->reg); | ||
| 318 | 304 | ||
| 319 | return 0; | 305 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 320 | } | 306 | } |
| 321 | 307 | ||
| 322 | static const struct of_device_id adc0832_dt_ids[] = { | 308 | static const struct of_device_id adc0832_dt_ids[] = { |
| @@ -343,7 +329,6 @@ static struct spi_driver adc0832_driver = { · 20 unmodified lines | |||
| 343 | .of_match_table = adc0832_dt_ids, | 329 | .of_match_table = adc0832_dt_ids, |
| 344 | }, | 330 | }, |
| 345 | .probe = adc0832_probe, | 331 | .probe = adc0832_probe, |
| 346 | .remove = adc0832_remove, | ||
| 347 | .id_table = adc0832_id, | 332 | .id_table = adc0832_id, |
| 348 | }; | 333 | }; |
| 349 | module_spi_driver(adc0832_driver); | 334 | module_spi_driver(adc0832_driver); |
| @@ -210,9 +210,6 @@ static int adc084s021_probe(struct spi_device *spi) · 209 unmodified lines | |||
| 210 | adc = iio_priv(indio_dev); | 210 | adc = iio_priv(indio_dev); |
| 211 | adc->spi = spi; | 211 | adc->spi = spi; |
| 212 | 212 | ||
| 213 | /* Connect the SPI device and the iio dev */ | ||
| 214 | spi_set_drvdata(spi, indio_dev); | ||
| 215 | |||
| 216 | /* Initiate the Industrial I/O device */ | 213 | /* Initiate the Industrial I/O device */ |
| 217 | indio_dev->name = spi_get_device_id(spi)->name; | 214 | indio_dev->name = spi_get_device_id(spi)->name; |
| 218 | indio_dev->modes = INDIO_DIRECT_MODE; | 215 | indio_dev->modes = INDIO_DIRECT_MODE; |
| @@ -215,6 +215,11 @@ static const struct iio_info adc108s102_info = { · 214 unmodified lines | |||
| 215 | .update_scan_mode = &adc108s102_update_scan_mode, | 215 | .update_scan_mode = &adc108s102_update_scan_mode, |
| 216 | }; | 216 | }; |
| 217 | 217 | ||
| 218 | static void adc108s102_reg_disable(void *reg) | ||
| 219 | { | ||
| 220 | regulator_disable(reg); | ||
| 221 | } | ||
| 222 | |||
| 218 | static int adc108s102_probe(struct spi_device *spi) | 223 | static int adc108s102_probe(struct spi_device *spi) |
| 219 | { | 224 | { |
| 220 | struct adc108s102_state *st; | 225 | struct adc108s102_state *st; |
| @@ -239,6 +244,10 @@ static int adc108s102_probe(struct spi_device *spi) · 18 unmodified lines | |||
| 239 | dev_err(&spi->dev, "Cannot enable vref regulator\n"); | 244 | dev_err(&spi->dev, "Cannot enable vref regulator\n"); |
| 240 | return ret; | 245 | return ret; |
| 241 | } | 246 | } |
| 247 | ret = devm_add_action_or_reset(&spi->dev, adc108s102_reg_disable, | ||
| 248 | st->reg); | ||
| 249 | if (ret) | ||
| 250 | return ret; | ||
| 242 | 251 | ||
| 243 | ret = regulator_get_voltage(st->reg); | 252 | ret = regulator_get_voltage(st->reg); |
| 244 | if (ret < 0) { | 253 | if (ret < 0) { |
| @@ -249,7 +258,6 @@ static int adc108s102_probe(struct spi_device *spi) · 4 unmodified lines | |||
| 249 | st->va_millivolt = ret / 1000; | 258 | st->va_millivolt = ret / 1000; |
| 250 | } | 259 | } |
| 251 | 260 | ||
| 252 | spi_set_drvdata(spi, indio_dev); | ||
| 253 | st->spi = spi; | 261 | st->spi = spi; |
| 254 | 262 | ||
| 255 | indio_dev->name = spi->modalias; | 263 | indio_dev->name = spi->modalias; |
| @@ -266,40 +274,18 @@ static int adc108s102_probe(struct spi_device *spi) · 10 unmodified lines | |||
| 266 | spi_message_init_with_transfers(&st->scan_single_msg, | 274 | spi_message_init_with_transfers(&st->scan_single_msg, |
| 267 | &st->scan_single_xfer, 1); | 275 | &st->scan_single_xfer, 1); |
| 268 | 276 | ||
| 269 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | 277 | ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, |
| 270 | &adc108s102_trigger_handler, NULL); | 278 | &adc108s102_trigger_handler, |
| 279 | NULL); | ||
| 271 | if (ret) | 280 | if (ret) |
| 272 | goto error_disable_reg; | 281 | return ret; |
| 273 | 282 | ||
| 274 | ret = iio_device_register(indio_dev); | 283 | ret = devm_iio_device_register(&spi->dev, indio_dev); |
| 275 | if (ret) { | 284 | if (ret) |
| 276 | dev_err(&spi->dev, "Failed to register IIO device\n"); | 285 | dev_err(&spi->dev, "Failed to register IIO device\n"); |
| 277 | goto error_cleanup_triggered_buffer; | ||
| 278 | } | ||
| 279 | return 0; | ||
| 280 | |||
| 281 | error_cleanup_triggered_buffer: | ||
| 282 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 283 | |||
| 284 | error_disable_reg: | ||
| 285 | regulator_disable(st->reg); | ||
| 286 | |||
| 287 | return ret; | 286 | return ret; |
| 288 | } | 287 | } |
| 289 | 288 | ||
| 290 | static int adc108s102_remove(struct spi_device *spi) | ||
| 291 | { | ||
| 292 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 293 | struct adc108s102_state *st = iio_priv(indio_dev); | ||
| 294 | |||
| 295 | iio_device_unregister(indio_dev); | ||
| 296 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 297 | |||
| 298 | regulator_disable(st->reg); | ||
| 299 | |||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | static const struct of_device_id adc108s102_of_match[] = { | 289 | static const struct of_device_id adc108s102_of_match[] = { |
| 304 | { .compatible = "ti,adc108s102" }, | 290 | { .compatible = "ti,adc108s102" }, |
| 305 | { } | 291 | { } |
| @@ -327,7 +313,6 @@ static struct spi_driver adc108s102_driver = { · 21 unmodified lines | |||
| 327 | .acpi_match_table = ACPI_PTR(adc108s102_acpi_ids), | 313 | .acpi_match_table = ACPI_PTR(adc108s102_acpi_ids), |
| 328 | }, | 314 | }, |
| 329 | .probe = adc108s102_probe, | 315 | .probe = adc108s102_probe, |
| 330 | .remove = adc108s102_remove, | ||
| 331 | .id_table = adc108s102_id, | 316 | .id_table = adc108s102_id, |
| 332 | }; | 317 | }; |
| 333 | module_spi_driver(adc108s102_driver); | 318 | module_spi_driver(adc108s102_driver); |
| @@ -169,6 +169,11 @@ static const struct iio_info ti_adc_info = { · 168 unmodified lines | |||
| 169 | .read_raw = ti_adc_read_raw, | 169 | .read_raw = ti_adc_read_raw, |
| 170 | }; | 170 | }; |
| 171 | 171 | ||
| 172 | static void ti_adc_reg_disable(void *reg) | ||
| 173 | { | ||
| 174 | regulator_disable(reg); | ||
| 175 | } | ||
| 176 | |||
| 172 | static int ti_adc_probe(struct spi_device *spi) | 177 | static int ti_adc_probe(struct spi_device *spi) |
| 173 | { | 178 | { |
| 174 | struct iio_dev *indio_dev; | 179 | struct iio_dev *indio_dev; |
| @@ -182,7 +187,6 @@ static int ti_adc_probe(struct spi_device *spi) · 7 unmodified lines | |||
| 182 | indio_dev->info = &ti_adc_info; | 187 | indio_dev->info = &ti_adc_info; |
| 183 | indio_dev->name = TI_ADC_DRV_NAME; | 188 | indio_dev->name = TI_ADC_DRV_NAME; |
| 184 | indio_dev->modes = INDIO_DIRECT_MODE; | 189 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 185 | spi_set_drvdata(spi, indio_dev); | ||
| 186 | 190 | ||
| 187 | data = iio_priv(indio_dev); | 191 | data = iio_priv(indio_dev); |
| 188 | data->spi = spi; | 192 | data->spi = spi; |
| @@ -203,42 +207,24 @@ static int ti_adc_probe(struct spi_device *spi) · 14 unmodified lines | |||
| 203 | } | 207 | } |
| 204 | 208 | ||
| 205 | data->ref = devm_regulator_get(&spi->dev, "vdda"); | 209 | data->ref = devm_regulator_get(&spi->dev, "vdda"); |
| 206 | if (!IS_ERR(data->ref)) { | 210 | if (IS_ERR(data->ref)) |
| 207 | ret = regulator_enable(data->ref); | 211 | return PTR_ERR(data->ref); |
| 208 | if (ret < 0) | ||
| 209 | return ret; | ||
| 210 | } | ||
| 211 | 212 | ||
| 212 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | 213 | ret = regulator_enable(data->ref); |
| 213 | ti_adc_trigger_handler, NULL); | 214 | if (ret < 0) |
| 214 | if (ret) | 215 | return ret; |
| 215 | goto error_regulator_disable; | ||
| 216 | 216 | ||
| 217 | ret = iio_device_register(indio_dev); | 217 | ret = devm_add_action_or_reset(&spi->dev, ti_adc_reg_disable, |
| 218 | data->ref); | ||
| 218 | if (ret) | 219 | if (ret) |
| 219 | goto error_unreg_buffer; | 220 | return ret; |
| 220 | |||
| 221 | return 0; | ||
| 222 | 221 | ||
| 223 | error_unreg_buffer: | 222 | ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, |
| 224 | iio_triggered_buffer_cleanup(indio_dev); | 223 | ti_adc_trigger_handler, NULL); |
| 225 | 224 | if (ret) | |
| 226 | error_regulator_disable: | 225 | return ret; |
| 227 | regulator_disable(data->ref); | ||
| 228 | |||
| 229 | return ret; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int ti_adc_remove(struct spi_device *spi) | ||
| 233 | { | ||
| 234 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
| 235 | struct ti_adc_data *data = iio_priv(indio_dev); | ||
| 236 | |||
| 237 | iio_device_unregister(indio_dev); | ||
| 238 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 239 | regulator_disable(data->ref); | ||
| 240 | 226 | ||
| 241 | return 0; | 227 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 242 | } | 228 | } |
| 243 | 229 | ||
| 244 | static const struct of_device_id ti_adc_dt_ids[] = { | 230 | static const struct of_device_id ti_adc_dt_ids[] = { |
| @@ -261,7 +247,6 @@ static struct spi_driver ti_adc_driver = { · 16 unmodified lines | |||
| 261 | .of_match_table = ti_adc_dt_ids, | 247 | .of_match_table = ti_adc_dt_ids, |
| 262 | }, | 248 | }, |
| 263 | .probe = ti_adc_probe, | 249 | .probe = ti_adc_probe, |
| 264 | .remove = ti_adc_remove, | ||
| 265 | .id_table = ti_adc_id, | 250 | .id_table = ti_adc_id, |
| 266 | }; | 251 | }; |
| 267 | module_spi_driver(ti_adc_driver); | 252 | module_spi_driver(ti_adc_driver); |
| @@ -323,9 +323,7 @@ static int ads1015_set_power_state(struct ads1015_data *data, bool on) · 322 unmodified lines | |||
| 323 | struct device *dev = regmap_get_device(data->regmap); | 323 | struct device *dev = regmap_get_device(data->regmap); |
| 324 | 324 | ||
| 325 | if (on) { | 325 | if (on) { |
| 326 | ret = pm_runtime_get_sync(dev); | 326 | ret = pm_runtime_resume_and_get(dev); |
| 327 | if (ret < 0) | ||
| 328 | pm_runtime_put_noidle(dev); | ||
| 329 | } else { | 327 | } else { |
| 330 | pm_runtime_mark_last_busy(dev); | 328 | pm_runtime_mark_last_busy(dev); |
| 331 | ret = pm_runtime_put_autosuspend(dev); | 329 | ret = pm_runtime_put_autosuspend(dev); |
| @@ -395,10 +393,14 @@ static irqreturn_t ads1015_trigger_handler(int irq, void *p) · 63 unmodified lines | |||
| 395 | struct iio_poll_func *pf = p; | 393 | struct iio_poll_func *pf = p; |
| 396 | struct iio_dev *indio_dev = pf->indio_dev; | 394 | struct iio_dev *indio_dev = pf->indio_dev; |
| 397 | struct ads1015_data *data = iio_priv(indio_dev); | 395 | struct ads1015_data *data = iio_priv(indio_dev); |
| 398 | s16 buf[8]; /* 1x s16 ADC val + 3x s16 padding + 4x s16 timestamp */ | 396 | /* Ensure natural alignment of timestamp */ |
| 397 | struct { | ||
| 398 | s16 chan; | ||
| 399 | s64 timestamp __aligned(8); | ||
| 400 | } scan; | ||
| 399 | int chan, ret, res; | 401 | int chan, ret, res; |
| 400 | 402 | ||
| 401 | memset(buf, 0, sizeof(buf)); | 403 | memset(&scan, 0, sizeof(scan)); |
| 402 | 404 | ||
| 403 | mutex_lock(&data->lock); | 405 | mutex_lock(&data->lock); |
| 404 | chan = find_first_bit(indio_dev->active_scan_mask, | 406 | chan = find_first_bit(indio_dev->active_scan_mask, |
| @@ -409,10 +411,10 @@ static irqreturn_t ads1015_trigger_handler(int irq, void *p) · 4 unmodified lines | |||
| 409 | goto err; | 411 | goto err; |
| 410 | } | 412 | } |
| 411 | 413 | ||
| 412 | buf[0] = res; | 414 | scan.chan = res; |
| 413 | mutex_unlock(&data->lock); | 415 | mutex_unlock(&data->lock); |
| 414 | 416 | ||
| 415 | iio_push_to_buffers_with_timestamp(indio_dev, buf, | 417 | iio_push_to_buffers_with_timestamp(indio_dev, &scan, |
| 416 | iio_get_time_ns(indio_dev)); | 418 | iio_get_time_ns(indio_dev)); |
| 417 | 419 | ||
| 418 | err: | 420 | err: |
| @@ -1066,7 +1068,6 @@ static int ads1015_remove(struct i2c_client *client) · 647 unmodified lines | |||
| 1066 | 1068 | ||
| 1067 | pm_runtime_disable(&client->dev); | 1069 | pm_runtime_disable(&client->dev); |
| 1068 | pm_runtime_set_suspended(&client->dev); | 1070 | pm_runtime_set_suspended(&client->dev); |
| 1069 | pm_runtime_put_noidle(&client->dev); | ||
| 1070 | 1071 | ||
| 1071 | /* power down single shot mode */ | 1072 | /* power down single shot mode */ |
| 1072 | return ads1015_set_conv_mode(data, ADS1015_SINGLESHOT); | 1073 | return ads1015_set_conv_mode(data, ADS1015_SINGLESHOT); |
| @@ -327,8 +327,6 @@ static int ads124s_probe(struct spi_device *spi) · 326 unmodified lines | |||
| 327 | 327 | ||
| 328 | ads124s_priv->chip_info = &ads124s_chip_info_tbl[spi_id->driver_data]; | 328 | ads124s_priv->chip_info = &ads124s_chip_info_tbl[spi_id->driver_data]; |
| 329 | 329 | ||
| 330 | spi_set_drvdata(spi, indio_dev); | ||
| 331 | |||
| 332 | ads124s_priv->spi = spi; | 330 | ads124s_priv->spi = spi; |
| 333 | 331 | ||
| 334 | indio_dev->name = spi_id->name; | 332 | indio_dev->name = spi_id->name; |
| @@ -830,7 +830,6 @@ static int ads131e08_probe(struct spi_device *spi) · 829 unmodified lines | |||
| 830 | return ret; | 830 | return ret; |
| 831 | 831 | ||
| 832 | indio_dev->name = st->info->name; | 832 | indio_dev->name = st->info->name; |
| 833 | indio_dev->dev.parent = &spi->dev; | ||
| 834 | indio_dev->info = &ads131e08_iio_info; | 833 | indio_dev->info = &ads131e08_iio_info; |
| 835 | indio_dev->modes = INDIO_DIRECT_MODE; | 834 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 836 | 835 | ||
| @@ -850,7 +849,7 @@ static int ads131e08_probe(struct spi_device *spi) · 13 unmodified lines | |||
| 850 | } | 849 | } |
| 851 | 850 | ||
| 852 | st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", | 851 | st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", |
| 853 | indio_dev->name, indio_dev->id); | 852 | indio_dev->name, iio_device_id(indio_dev)); |
| 854 | if (!st->trig) { | 853 | if (!st->trig) { |
| 855 | dev_err(&spi->dev, "failed to allocate IIO trigger\n"); | 854 | dev_err(&spi->dev, "failed to allocate IIO trigger\n"); |
| 856 | return -ENOMEM; | 855 | return -ENOMEM; |
| @@ -383,7 +383,8 @@ static irqreturn_t ads8688_trigger_handler(int irq, void *p) · 382 unmodified lines | |||
| 383 | { | 383 | { |
| 384 | struct iio_poll_func *pf = p; | 384 | struct iio_poll_func *pf = p; |
| 385 | struct iio_dev *indio_dev = pf->indio_dev; | 385 | struct iio_dev *indio_dev = pf->indio_dev; |
| 386 | u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)]; | 386 | /* Ensure naturally aligned timestamp */ |
| 387 | u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)] __aligned(8); | ||
| 387 | int i, j = 0; | 388 | int i, j = 0; |
| 388 | 389 | ||
| 389 | for (i = 0; i < indio_dev->masklength; i++) { | 390 | for (i = 0; i < indio_dev->masklength; i++) { |
| @@ -0,0 +1,712 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Texas Instruments TSC2046 SPI ADC driver | ||
| 4 | * | ||
| 5 | * Copyright (c) 2021 Oleksij Rempel <kernel@pengutronix.de>, Pengutronix | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/bitfield.h> | ||
| 9 | #include <linux/delay.h> | ||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/spi/spi.h> | ||
| 12 | |||
| 13 | #include <asm/unaligned.h> | ||
| 14 | |||
| 15 | #include <linux/iio/buffer.h> | ||
| 16 | #include <linux/iio/trigger_consumer.h> | ||
| 17 | #include <linux/iio/triggered_buffer.h> | ||
| 18 | #include <linux/iio/trigger.h> | ||
| 19 | |||
| 20 | /* | ||
| 21 | * The PENIRQ of TSC2046 controller is implemented as level shifter attached to | ||
| 22 | * the X+ line. If voltage of the X+ line reaches a specific level the IRQ will | ||
| 23 | * be activated or deactivated. | ||
| 24 | * To make this kind of IRQ reusable as trigger following additions were | ||
| 25 | * implemented: | ||
| 26 | * - rate limiting: | ||
| 27 | * For typical touchscreen use case, we need to trigger about each 10ms. | ||
| 28 | * - hrtimer: | ||
| 29 | * Continue triggering at least once after the IRQ was deactivated. Then | ||
| 30 | * deactivate this trigger to stop sampling in order to reduce power | ||
| 31 | * consumption. | ||
| 32 | */ | ||
| 33 | |||
| 34 | #define TI_TSC2046_NAME "tsc2046" | ||
| 35 | |||
| 36 | /* This driver doesn't aim at the peak continuous sample rate */ | ||
| 37 | #define TI_TSC2046_MAX_SAMPLE_RATE 125000 | ||
| 38 | #define TI_TSC2046_SAMPLE_BITS \ | ||
| 39 | BITS_PER_TYPE(struct tsc2046_adc_atom) | ||
| 40 | #define TI_TSC2046_MAX_CLK_FREQ \ | ||
| 41 | (TI_TSC2046_MAX_SAMPLE_RATE * TI_TSC2046_SAMPLE_BITS) | ||
| 42 | |||
| 43 | #define TI_TSC2046_SAMPLE_INTERVAL_US 10000 | ||
| 44 | |||
| 45 | #define TI_TSC2046_START BIT(7) | ||
| 46 | #define TI_TSC2046_ADDR GENMASK(6, 4) | ||
| 47 | #define TI_TSC2046_ADDR_TEMP1 7 | ||
| 48 | #define TI_TSC2046_ADDR_AUX 6 | ||
| 49 | #define TI_TSC2046_ADDR_X 5 | ||
| 50 | #define TI_TSC2046_ADDR_Z2 4 | ||
| 51 | #define TI_TSC2046_ADDR_Z1 3 | ||
| 52 | #define TI_TSC2046_ADDR_VBAT 2 | ||
| 53 | #define TI_TSC2046_ADDR_Y 1 | ||
| 54 | #define TI_TSC2046_ADDR_TEMP0 0 | ||
| 55 | |||
| 56 | /* | ||
| 57 | * The mode bit sets the resolution of the ADC. With this bit low, the next | ||
| 58 | * conversion has 12-bit resolution, whereas with this bit high, the next | ||
| 59 | * conversion has 8-bit resolution. This driver is optimized for 12-bit mode. | ||
| 60 | * So, for this driver, this bit should stay zero. | ||
| 61 | */ | ||
| 62 | #define TI_TSC2046_8BIT_MODE BIT(3) | ||
| 63 | |||
| 64 | /* | ||
| 65 | * SER/DFR - The SER/DFR bit controls the reference mode, either single-ended | ||
| 66 | * (high) or differential (low). | ||
| 67 | */ | ||
| 68 | #define TI_TSC2046_SER BIT(2) | ||
| 69 | |||
| 70 | /* | ||
| 71 | * If VREF_ON and ADC_ON are both zero, then the chip operates in | ||
| 72 | * auto-wake/suspend mode. In most case this bits should stay zero. | ||
| 73 | */ | ||
| 74 | #define TI_TSC2046_PD1_VREF_ON BIT(1) | ||
| 75 | #define TI_TSC2046_PD0_ADC_ON BIT(0) | ||
| 76 | |||
| 77 | /* | ||
| 78 | * All supported devices can do 8 or 12bit resolution. This driver | ||
| 79 | * supports only 12bit mode, here we have a 16bit data transfer, where | ||
| 80 | * the MSB and the 3 LSB are 0. | ||
| 81 | */ | ||
| 82 | #define TI_TSC2046_DATA_12BIT GENMASK(14, 3) | ||
| 83 | |||
| 84 | #define TI_TSC2046_MAX_CHAN 8 | ||
| 85 | |||
| 86 | /* Represents a HW sample */ | ||
| 87 | struct tsc2046_adc_atom { | ||
| 88 | /* | ||
| 89 | * Command transmitted to the controller. This field is empty on the RX | ||
| 90 | * buffer. | ||
| 91 | */ | ||
| 92 | u8 cmd; | ||
| 93 | /* | ||
| 94 | * Data received from the controller. This field is empty for the TX | ||
| 95 | * buffer | ||
| 96 | */ | ||
| 97 | __be16 data; | ||
| 98 | } __packed; | ||
| 99 | |||
| 100 | /* Layout of atomic buffers within big buffer */ | ||
| 101 | struct tsc2046_adc_group_layout { | ||
| 102 | /* Group offset within the SPI RX buffer */ | ||
| 103 | unsigned int offset; | ||
| 104 | /* | ||
| 105 | * Amount of tsc2046_adc_atom structs within the same command gathered | ||
| 106 | * within same group. | ||
| 107 | */ | ||
| 108 | unsigned int count; | ||
| 109 | /* | ||
| 110 | * Settling samples (tsc2046_adc_atom structs) which should be skipped | ||
| 111 | * before good samples will start. | ||
| 112 | */ | ||
| 113 | unsigned int skip; | ||
| 114 | }; | ||
| 115 | |||
| 116 | struct tsc2046_adc_dcfg { | ||
| 117 | const struct iio_chan_spec *channels; | ||
| 118 | unsigned int num_channels; | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct tsc2046_adc_ch_cfg { | ||
| 122 | unsigned int settling_time_us; | ||
| 123 | unsigned int oversampling_ratio; | ||
| 124 | }; | ||
| 125 | |||
| 126 | struct tsc2046_adc_priv { | ||
| 127 | struct spi_device *spi; | ||
| 128 | const struct tsc2046_adc_dcfg *dcfg; | ||
| 129 | |||
| 130 | struct iio_trigger *trig; | ||
| 131 | struct hrtimer trig_timer; | ||
| 132 | spinlock_t trig_lock; | ||
| 133 | unsigned int trig_more_count; | ||
| 134 | |||
| 135 | struct spi_transfer xfer; | ||
| 136 | struct spi_message msg; | ||
| 137 | |||
| 138 | struct { | ||
| 139 | /* Scan data for each channel */ | ||
| 140 | u16 data[TI_TSC2046_MAX_CHAN]; | ||
| 141 | /* Timestamp */ | ||
| 142 | s64 ts __aligned(8); | ||
| 143 | } scan_buf; | ||
| 144 | |||
| 145 | /* | ||
| 146 | * Lock to protect the layout and the SPI transfer buffer. | ||
| 147 | * tsc2046_adc_group_layout can be changed within update_scan_mode(), | ||
| 148 | * in this case the l[] and tx/rx buffer will be out of sync to each | ||
| 149 | * other. | ||
| 150 | */ | ||
| 151 | struct mutex slock; | ||
| 152 | struct tsc2046_adc_group_layout l[TI_TSC2046_MAX_CHAN]; | ||
| 153 | struct tsc2046_adc_atom *rx; | ||
| 154 | struct tsc2046_adc_atom *tx; | ||
| 155 | |||
| 156 | struct tsc2046_adc_atom *rx_one; | ||
| 157 | struct tsc2046_adc_atom *tx_one; | ||
| 158 | |||
| 159 | unsigned int count; | ||
| 160 | unsigned int groups; | ||
| 161 | u32 effective_speed_hz; | ||
| 162 | u32 scan_interval_us; | ||
| 163 | u32 time_per_scan_us; | ||
| 164 | u32 time_per_bit_ns; | ||
| 165 | |||
| 166 | struct tsc2046_adc_ch_cfg ch_cfg[TI_TSC2046_MAX_CHAN]; | ||
| 167 | }; | ||
| 168 | |||
| 169 | #define TI_TSC2046_V_CHAN(index, bits, name) \ | ||
| 170 | { \ | ||
| 171 | .type = IIO_VOLTAGE, \ | ||
| 172 | .indexed = 1, \ | ||
| 173 | .channel = index, \ | ||
| 174 | .datasheet_name = "#name", \ | ||
| 175 | .scan_index = index, \ | ||
| 176 | .scan_type = { \ | ||
| 177 | .sign = 'u', \ | ||
| 178 | .realbits = bits, \ | ||
| 179 | .storagebits = 16, \ | ||
| 180 | .endianness = IIO_CPU, \ | ||
| 181 | }, \ | ||
| 182 | } | ||
| 183 | |||
| 184 | #define DECLARE_TI_TSC2046_8_CHANNELS(name, bits) \ | ||
| 185 | const struct iio_chan_spec name ## _channels[] = { \ | ||
| 186 | TI_TSC2046_V_CHAN(0, bits, TEMP0), \ | ||
| 187 | TI_TSC2046_V_CHAN(1, bits, Y), \ | ||
| 188 | TI_TSC2046_V_CHAN(2, bits, VBAT), \ | ||
| 189 | TI_TSC2046_V_CHAN(3, bits, Z1), \ | ||
| 190 | TI_TSC2046_V_CHAN(4, bits, Z2), \ | ||
| 191 | TI_TSC2046_V_CHAN(5, bits, X), \ | ||
| 192 | TI_TSC2046_V_CHAN(6, bits, AUX), \ | ||
| 193 | TI_TSC2046_V_CHAN(7, bits, TEMP1), \ | ||
| 194 | IIO_CHAN_SOFT_TIMESTAMP(8), \ | ||
| 195 | } | ||
| 196 | |||
| 197 | static DECLARE_TI_TSC2046_8_CHANNELS(tsc2046_adc, 12); | ||
| 198 | |||
| 199 | static const struct tsc2046_adc_dcfg tsc2046_adc_dcfg_tsc2046e = { | ||
| 200 | .channels = tsc2046_adc_channels, | ||
| 201 | .num_channels = ARRAY_SIZE(tsc2046_adc_channels), | ||
| 202 | }; | ||
| 203 | |||
| 204 | /* | ||
| 205 | * Convert time to a number of samples which can be transferred within this | ||
| 206 | * time. | ||
| 207 | */ | ||
| 208 | static unsigned int tsc2046_adc_time_to_count(struct tsc2046_adc_priv *priv, | ||
| 209 | unsigned long time) | ||
| 210 | { | ||
| 211 | unsigned int bit_count, sample_count; | ||
| 212 | |||
| 213 | bit_count = DIV_ROUND_UP(time * NSEC_PER_USEC, priv->time_per_bit_ns); | ||
| 214 | sample_count = DIV_ROUND_UP(bit_count, TI_TSC2046_SAMPLE_BITS); | ||
| 215 | |||
| 216 | dev_dbg(&priv->spi->dev, "Effective speed %u, time per bit: %u, count bits: %u, count samples: %u\n", | ||
| 217 | priv->effective_speed_hz, priv->time_per_bit_ns, | ||
| 218 | bit_count, sample_count); | ||
| 219 | |||
| 220 | return sample_count; | ||
| 221 | } | ||
| 222 | |||
| 223 | static u8 tsc2046_adc_get_cmd(struct tsc2046_adc_priv *priv, int ch_idx, | ||
| 224 | bool keep_power) | ||
| 225 | { | ||
| 226 | u32 pd; | ||
| 227 | |||
| 228 | /* | ||
| 229 | * if PD bits are 0, controller will automatically disable ADC, VREF and | ||
| 230 | * enable IRQ. | ||
| 231 | */ | ||
| 232 | if (keep_power) | ||
| 233 | pd = TI_TSC2046_PD0_ADC_ON; | ||
| 234 | else | ||
| 235 | pd = 0; | ||
| 236 | |||
| 237 | return TI_TSC2046_START | FIELD_PREP(TI_TSC2046_ADDR, ch_idx) | pd; | ||
| 238 | } | ||
| 239 | |||
| 240 | static u16 tsc2046_adc_get_value(struct tsc2046_adc_atom *buf) | ||
| 241 | { | ||
| 242 | return FIELD_GET(TI_TSC2046_DATA_12BIT, get_unaligned_be16(&buf->data)); | ||
| 243 | } | ||
| 244 | |||
| 245 | static int tsc2046_adc_read_one(struct tsc2046_adc_priv *priv, int ch_idx, | ||
| 246 | u32 *effective_speed_hz) | ||
| 247 | { | ||
| 248 | struct spi_transfer xfer; | ||
| 249 | struct spi_message msg; | ||
| 250 | int ret; | ||
| 251 | |||
| 252 | memset(&xfer, 0, sizeof(xfer)); | ||
| 253 | priv->tx_one->cmd = tsc2046_adc_get_cmd(priv, ch_idx, false); | ||
| 254 | priv->tx_one->data = 0; | ||
| 255 | xfer.tx_buf = priv->tx_one; | ||
| 256 | xfer.rx_buf = priv->rx_one; | ||
| 257 | xfer.len = sizeof(*priv->tx_one); | ||
| 258 | spi_message_init_with_transfers(&msg, &xfer, 1); | ||
| 259 | |||
| 260 | /* | ||
| 261 | * We aren't using spi_write_then_read() because we need to be able | ||
| 262 | * to get hold of the effective_speed_hz from the xfer | ||
| 263 | */ | ||
| 264 | ret = spi_sync(priv->spi, &msg); | ||
| 265 | if (ret) { | ||
| 266 | dev_err_ratelimited(&priv->spi->dev, "SPI transfer failed %pe\n", | ||
| 267 | ERR_PTR(ret)); | ||
| 268 | return ret; | ||
| 269 | } | ||
| 270 | |||
| 271 | if (effective_speed_hz) | ||
| 272 | *effective_speed_hz = xfer.effective_speed_hz; | ||
| 273 | |||
| 274 | return tsc2046_adc_get_value(priv->rx_one); | ||
| 275 | } | ||
| 276 | |||
| 277 | static size_t tsc2046_adc_group_set_layout(struct tsc2046_adc_priv *priv, | ||
| 278 | unsigned int group, | ||
| 279 | unsigned int ch_idx) | ||
| 280 | { | ||
| 281 | struct tsc2046_adc_ch_cfg *ch = &priv->ch_cfg[ch_idx]; | ||
| 282 | struct tsc2046_adc_group_layout *cur; | ||
| 283 | unsigned int max_count, count_skip; | ||
| 284 | unsigned int offset = 0; | ||
| 285 | |||
| 286 | if (group) | ||
| 287 | offset = priv->l[group - 1].offset + priv->l[group - 1].count; | ||
| 288 | |||
| 289 | count_skip = tsc2046_adc_time_to_count(priv, ch->settling_time_us); | ||
| 290 | max_count = count_skip + ch->oversampling_ratio; | ||
| 291 | |||
| 292 | cur = &priv->l[group]; | ||
| 293 | cur->offset = offset; | ||
| 294 | cur->count = max_count; | ||
| 295 | cur->skip = count_skip; | ||
| 296 | |||
| 297 | return sizeof(*priv->tx) * max_count; | ||
| 298 | } | ||
| 299 | |||
| 300 | static void tsc2046_adc_group_set_cmd(struct tsc2046_adc_priv *priv, | ||
| 301 | unsigned int group, int ch_idx) | ||
| 302 | { | ||
| 303 | struct tsc2046_adc_group_layout *l = &priv->l[group]; | ||
| 304 | unsigned int i; | ||
| 305 | u8 cmd; | ||
| 306 | |||
| 307 | /* | ||
| 308 | * Do not enable automatic power down on working samples. Otherwise the | ||
| 309 | * plates will never be completely charged. | ||
| 310 | */ | ||
| 311 | cmd = tsc2046_adc_get_cmd(priv, ch_idx, true); | ||
| 312 | |||
| 313 | for (i = 0; i < l->count - 1; i++) | ||
| 314 | priv->tx[l->offset + i].cmd = cmd; | ||
| 315 | |||
| 316 | /* automatically power down on last sample */ | ||
| 317 | priv->tx[l->offset + i].cmd = tsc2046_adc_get_cmd(priv, ch_idx, false); | ||
| 318 | } | ||
| 319 | |||
| 320 | static u16 tsc2046_adc_get_val(struct tsc2046_adc_priv *priv, int group) | ||
| 321 | { | ||
| 322 | struct tsc2046_adc_group_layout *l; | ||
| 323 | unsigned int val, val_normalized = 0; | ||
| 324 | int valid_count, i; | ||
| 325 | |||
| 326 | l = &priv->l[group]; | ||
| 327 | valid_count = l->count - l->skip; | ||
| 328 | |||
| 329 | for (i = 0; i < valid_count; i++) { | ||
| 330 | val = tsc2046_adc_get_value(&priv->rx[l->offset + l->skip + i]); | ||
| 331 | val_normalized += val; | ||
| 332 | } | ||
| 333 | |||
| 334 | return DIV_ROUND_UP(val_normalized, valid_count); | ||
| 335 | } | ||
| 336 | |||
| 337 | static int tsc2046_adc_scan(struct iio_dev *indio_dev) | ||
| 338 | { | ||
| 339 | struct tsc2046_adc_priv *priv = iio_priv(indio_dev); | ||
| 340 | struct device *dev = &priv->spi->dev; | ||
| 341 | int group; | ||
| 342 | int ret; | ||
| 343 | |||
| 344 | ret = spi_sync(priv->spi, &priv->msg); | ||
| 345 | if (ret < 0) { | ||
| 346 | dev_err_ratelimited(dev, "SPI transfer failed: %pe\n", ERR_PTR(ret)); | ||
| 347 | return ret; | ||
| 348 | } | ||
| 349 | |||
| 350 | for (group = 0; group < priv->groups; group++) | ||
| 351 | priv->scan_buf.data[group] = tsc2046_adc_get_val(priv, group); | ||
| 352 | |||
| 353 | ret = iio_push_to_buffers_with_timestamp(indio_dev, &priv->scan_buf, | ||
| 354 | iio_get_time_ns(indio_dev)); | ||
| 355 | /* If the consumer is kfifo, we may get a EBUSY here - ignore it. */ | ||
| 356 | if (ret < 0 && ret != -EBUSY) { | ||
| 357 | dev_err_ratelimited(dev, "Failed to push scan buffer %pe\n", | ||
| 358 | ERR_PTR(ret)); | ||
| 359 | |||
| 360 | return ret; | ||
| 361 | } | ||
| 362 | |||
| 363 | return 0; | ||
| 364 | } | ||
| 365 | |||
| 366 | static irqreturn_t tsc2046_adc_trigger_handler(int irq, void *p) | ||
| 367 | { | ||
| 368 | struct iio_poll_func *pf = p; | ||
| 369 | struct iio_dev *indio_dev = pf->indio_dev; | ||
| 370 | struct tsc2046_adc_priv *priv = iio_priv(indio_dev); | ||
| 371 | |||
| 372 | mutex_lock(&priv->slock); | ||
| 373 | tsc2046_adc_scan(indio_dev); | ||
| 374 | mutex_unlock(&priv->slock); | ||
| 375 | |||
| 376 | iio_trigger_notify_done(indio_dev->trig); | ||
| 377 | |||
| 378 | return IRQ_HANDLED; | ||
| 379 | } | ||
| 380 | |||
| 381 | static int tsc2046_adc_update_scan_mode(struct iio_dev *indio_dev, | ||
| 382 | const unsigned long *active_scan_mask) | ||
| 383 | { | ||
| 384 | struct tsc2046_adc_priv *priv = iio_priv(indio_dev); | ||
| 385 | unsigned int ch_idx, group = 0; | ||
| 386 | size_t size; | ||
| 387 | |||
| 388 | mutex_lock(&priv->slock); | ||
| 389 | |||
| 390 | size = 0; | ||
| 391 | for_each_set_bit(ch_idx, active_scan_mask, indio_dev->num_channels) { | ||
| 392 | size += tsc2046_adc_group_set_layout(priv, group, ch_idx); | ||
| 393 | tsc2046_adc_group_set_cmd(priv, group, ch_idx); | ||
| 394 | group++; | ||
| 395 | } | ||
| 396 | |||
| 397 | priv->groups = group; | ||
| 398 | priv->xfer.len = size; | ||
| 399 | priv->time_per_scan_us = size * 8 * priv->time_per_bit_ns / NSEC_PER_USEC; | ||
| 400 | |||
| 401 | if (priv->scan_interval_us > priv->time_per_scan_us) | ||
| 402 | dev_warn(&priv->spi->dev, "The scan interval (%d) is less then calculated scan time (%d)\n", | ||
| 403 | priv->scan_interval_us, priv->time_per_scan_us); | ||
| 404 | |||
| 405 | mutex_unlock(&priv->slock); | ||
| 406 | |||
| 407 | return 0; | ||
| 408 | } | ||
| 409 | |||
| 410 | static const struct iio_info tsc2046_adc_info = { | ||
| 411 | .update_scan_mode = tsc2046_adc_update_scan_mode, | ||
| 412 | }; | ||
| 413 | |||
| 414 | static enum hrtimer_restart tsc2046_adc_trig_more(struct hrtimer *hrtimer) | ||
| 415 | { | ||
| 416 | struct tsc2046_adc_priv *priv = container_of(hrtimer, | ||
| 417 | struct tsc2046_adc_priv, | ||
| 418 | trig_timer); | ||
| 419 | unsigned long flags; | ||
| 420 | |||
| 421 | spin_lock_irqsave(&priv->trig_lock, flags); | ||
| 422 | |||
| 423 | disable_irq_nosync(priv->spi->irq); | ||
| 424 | |||
| 425 | priv->trig_more_count++; | ||
| 426 | iio_trigger_poll(priv->trig); | ||
| 427 | |||
| 428 | spin_unlock_irqrestore(&priv->trig_lock, flags); | ||
| 429 | |||
| 430 | return HRTIMER_NORESTART; | ||
| 431 | } | ||
| 432 | |||
| 433 | static irqreturn_t tsc2046_adc_irq(int irq, void *dev_id) | ||
| 434 | { | ||
| 435 | struct iio_dev *indio_dev = dev_id; | ||
| 436 | struct tsc2046_adc_priv *priv = iio_priv(indio_dev); | ||
| 437 | |||
| 438 | spin_lock(&priv->trig_lock); | ||
| 439 | |||
| 440 | hrtimer_try_to_cancel(&priv->trig_timer); | ||
| 441 | |||
| 442 | priv->trig_more_count = 0; | ||
| 443 | disable_irq_nosync(priv->spi->irq); | ||
| 444 | iio_trigger_poll(priv->trig); | ||
| 445 | |||
| 446 | spin_unlock(&priv->trig_lock); | ||
| 447 | |||
| 448 | return IRQ_HANDLED; | ||
| 449 | } | ||
| 450 | |||
| 451 | static void tsc2046_adc_reenable_trigger(struct iio_trigger *trig) | ||
| 452 | { | ||
| 453 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | ||
| 454 | struct tsc2046_adc_priv *priv = iio_priv(indio_dev); | ||
| 455 | unsigned long flags; | ||
| 456 | int delta; | ||
| 457 | |||
| 458 | /* | ||
| 459 | * We can sample it as fast as we can, but usually we do not need so | ||
| 460 | * many samples. Reduce the sample rate for default (touchscreen) use | ||
| 461 | * case. | ||
| 462 | * Currently we do not need a highly precise sample rate. It is enough | ||
| 463 | * to have calculated numbers. | ||
| 464 | */ | ||
| 465 | delta = priv->scan_interval_us - priv->time_per_scan_us; | ||
| 466 | if (delta > 0) | ||
| 467 | fsleep(delta); | ||
| 468 | |||
| 469 | spin_lock_irqsave(&priv->trig_lock, flags); | ||
| 470 | |||
| 471 | /* | ||
| 472 | * We need to trigger at least one extra sample to detect state | ||
| 473 | * difference on ADC side. | ||
| 474 | */ | ||
| 475 | if (!priv->trig_more_count) { | ||
| 476 | int timeout_ms = DIV_ROUND_UP(priv->scan_interval_us, | ||
| 477 | USEC_PER_MSEC); | ||
| 478 | |||
| 479 | hrtimer_start(&priv->trig_timer, ms_to_ktime(timeout_ms), | ||
| 480 | HRTIMER_MODE_REL_SOFT); | ||
| 481 | } | ||
| 482 | |||
| 483 | enable_irq(priv->spi->irq); | ||
| 484 | |||
| 485 | spin_unlock_irqrestore(&priv->trig_lock, flags); | ||
| 486 | } | ||
| 487 | |||
| 488 | static int tsc2046_adc_set_trigger_state(struct iio_trigger *trig, bool enable) | ||
| 489 | { | ||
| 490 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | ||
| 491 | struct tsc2046_adc_priv *priv = iio_priv(indio_dev); | ||
| 492 | |||
| 493 | if (enable) { | ||
| 494 | enable_irq(priv->spi->irq); | ||
| 495 | } else { | ||
| 496 | disable_irq(priv->spi->irq); | ||
| 497 | hrtimer_try_to_cancel(&priv->trig_timer); | ||
| 498 | } | ||
| 499 | |||
| 500 | return 0; | ||
| 501 | } | ||
| 502 | |||
| 503 | static const struct iio_trigger_ops tsc2046_adc_trigger_ops = { | ||
| 504 | .set_trigger_state = tsc2046_adc_set_trigger_state, | ||
| 505 | .reenable = tsc2046_adc_reenable_trigger, | ||
| 506 | }; | ||
| 507 | |||
| 508 | static int tsc2046_adc_setup_spi_msg(struct tsc2046_adc_priv *priv) | ||
| 509 | { | ||
| 510 | unsigned int ch_idx; | ||
| 511 | size_t size; | ||
| 512 | int ret; | ||
| 513 | |||
| 514 | priv->tx_one = devm_kzalloc(&priv->spi->dev, sizeof(*priv->tx_one), | ||
| 515 | GFP_KERNEL); | ||
| 516 | if (!priv->tx_one) | ||
| 517 | return -ENOMEM; | ||
| 518 | |||
| 519 | priv->rx_one = devm_kzalloc(&priv->spi->dev, sizeof(*priv->rx_one), | ||
| 520 | GFP_KERNEL); | ||
| 521 | if (!priv->rx_one) | ||
| 522 | return -ENOMEM; | ||
| 523 | |||
| 524 | /* | ||
| 525 | * Make dummy read to set initial power state and get real SPI clock | ||
| 526 | * freq. It seems to be not important which channel is used for this | ||
| 527 | * case. | ||
| 528 | */ | ||
| 529 | ret = tsc2046_adc_read_one(priv, TI_TSC2046_ADDR_TEMP0, | ||
| 530 | &priv->effective_speed_hz); | ||
| 531 | if (ret < 0) | ||
| 532 | return ret; | ||
| 533 | |||
| 534 | /* | ||
| 535 | * In case SPI controller do not report effective_speed_hz, use | ||
| 536 | * configure value and hope it will match. | ||
| 537 | */ | ||
| 538 | if (!priv->effective_speed_hz) | ||
| 539 | priv->effective_speed_hz = priv->spi->max_speed_hz; | ||
| 540 | |||
| 541 | |||
| 542 | priv->scan_interval_us = TI_TSC2046_SAMPLE_INTERVAL_US; | ||
| 543 | priv->time_per_bit_ns = DIV_ROUND_UP(NSEC_PER_SEC, | ||
| 544 | priv->effective_speed_hz); | ||
| 545 | |||
| 546 | /* | ||
| 547 | * Calculate and allocate maximal size buffer if all channels are | ||
| 548 | * enabled. | ||
| 549 | */ | ||
| 550 | size = 0; | ||
| 551 | for (ch_idx = 0; ch_idx < priv->dcfg->num_channels; ch_idx++) | ||
| 552 | size += tsc2046_adc_group_set_layout(priv, ch_idx, ch_idx); | ||
| 553 | |||
| 554 | priv->tx = devm_kzalloc(&priv->spi->dev, size, GFP_KERNEL); | ||
| 555 | if (!priv->tx) | ||
| 556 | return -ENOMEM; | ||
| 557 | |||
| 558 | priv->rx = devm_kzalloc(&priv->spi->dev, size, GFP_KERNEL); | ||
| 559 | if (!priv->rx) | ||
| 560 | return -ENOMEM; | ||
| 561 | |||
| 562 | priv->xfer.tx_buf = priv->tx; | ||
| 563 | priv->xfer.rx_buf = priv->rx; | ||
| 564 | priv->xfer.len = size; | ||
| 565 | spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1); | ||
| 566 | |||
| 567 | return 0; | ||
| 568 | } | ||
| 569 | |||
| 570 | static void tsc2046_adc_parse_fwnode(struct tsc2046_adc_priv *priv) | ||
| 571 | { | ||
| 572 | struct fwnode_handle *child; | ||
| 573 | struct device *dev = &priv->spi->dev; | ||
| 574 | unsigned int i; | ||
| 575 | |||
| 576 | for (i = 0; i < ARRAY_SIZE(priv->ch_cfg); i++) { | ||
| 577 | priv->ch_cfg[i].settling_time_us = 1; | ||
| 578 | priv->ch_cfg[i].oversampling_ratio = 1; | ||
| 579 | } | ||
| 580 | |||
| 581 | device_for_each_child_node(dev, child) { | ||
| 582 | u32 stl, overs, reg; | ||
| 583 | int ret; | ||
| 584 | |||
| 585 | ret = fwnode_property_read_u32(child, "reg", ®); | ||
| 586 | if (ret) { | ||
| 587 | dev_err(dev, "invalid reg on %pfw, err: %pe\n", child, | ||
| 588 | ERR_PTR(ret)); | ||
| 589 | continue; | ||
| 590 | } | ||
| 591 | |||
| 592 | if (reg >= ARRAY_SIZE(priv->ch_cfg)) { | ||
| 593 | dev_err(dev, "%pfw: Unsupported reg value: %i, max supported is: %zu.\n", | ||
| 594 | child, reg, ARRAY_SIZE(priv->ch_cfg)); | ||
| 595 | continue; | ||
| 596 | } | ||
| 597 | |||
| 598 | ret = fwnode_property_read_u32(child, "settling-time-us", &stl); | ||
| 599 | if (!ret) | ||
| 600 | priv->ch_cfg[reg].settling_time_us = stl; | ||
| 601 | |||
| 602 | ret = fwnode_property_read_u32(child, "oversampling-ratio", | ||
| 603 | &overs); | ||
| 604 | if (!ret) | ||
| 605 | priv->ch_cfg[reg].oversampling_ratio = overs; | ||
| 606 | } | ||
| 607 | } | ||
| 608 | |||
| 609 | static int tsc2046_adc_probe(struct spi_device *spi) | ||
| 610 | { | ||
| 611 | const struct tsc2046_adc_dcfg *dcfg; | ||
| 612 | struct device *dev = &spi->dev; | ||
| 613 | struct tsc2046_adc_priv *priv; | ||
| 614 | struct iio_dev *indio_dev; | ||
| 615 | struct iio_trigger *trig; | ||
| 616 | int ret; | ||
| 617 | |||
| 618 | if (spi->max_speed_hz > TI_TSC2046_MAX_CLK_FREQ) { | ||
| 619 | dev_err(dev, "SPI max_speed_hz is too high: %d Hz. Max supported freq is %zu Hz\n", | ||
| 620 | spi->max_speed_hz, TI_TSC2046_MAX_CLK_FREQ); | ||
| 621 | return -EINVAL; | ||
| 622 | } | ||
| 623 | |||
| 624 | dcfg = device_get_match_data(dev); | ||
| 625 | if (!dcfg) | ||
| 626 | return -EINVAL; | ||
| 627 | |||
| 628 | spi->bits_per_word = 8; | ||
| 629 | spi->mode &= ~SPI_MODE_X_MASK; | ||
| 630 | spi->mode |= SPI_MODE_0; | ||
| 631 | ret = spi_setup(spi); | ||
| 632 | if (ret < 0) | ||
| 633 | return dev_err_probe(dev, ret, "Error in SPI setup\n"); | ||
| 634 | |||
| 635 | indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); | ||
| 636 | if (!indio_dev) | ||
| 637 | return -ENOMEM; | ||
| 638 | |||
| 639 | priv = iio_priv(indio_dev); | ||
| 640 | priv->dcfg = dcfg; | ||
| 641 | |||
| 642 | priv->spi = spi; | ||
| 643 | |||
| 644 | indio_dev->name = TI_TSC2046_NAME; | ||
| 645 | indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED; | ||
| 646 | indio_dev->channels = dcfg->channels; | ||
| 647 | indio_dev->num_channels = dcfg->num_channels; | ||
| 648 | indio_dev->info = &tsc2046_adc_info; | ||
| 649 | |||
| 650 | tsc2046_adc_parse_fwnode(priv); | ||
| 651 | |||
| 652 | ret = tsc2046_adc_setup_spi_msg(priv); | ||
| 653 | if (ret) | ||
| 654 | return ret; | ||
| 655 | |||
| 656 | mutex_init(&priv->slock); | ||
| 657 | |||
| 658 | ret = devm_request_irq(dev, spi->irq, &tsc2046_adc_irq, | ||
| 659 | IRQF_NO_AUTOEN, indio_dev->name, indio_dev); | ||
| 660 | if (ret) | ||
| 661 | return ret; | ||
| 662 | |||
| 663 | trig = devm_iio_trigger_alloc(dev, "touchscreen-%s", indio_dev->name); | ||
| 664 | if (!trig) | ||
| 665 | return -ENOMEM; | ||
| 666 | |||
| 667 | priv->trig = trig; | ||
| 668 | iio_trigger_set_drvdata(trig, indio_dev); | ||
| 669 | trig->ops = &tsc2046_adc_trigger_ops; | ||
| 670 | |||
| 671 | spin_lock_init(&priv->trig_lock); | ||
| 672 | hrtimer_init(&priv->trig_timer, CLOCK_MONOTONIC, | ||
| 673 | HRTIMER_MODE_REL_SOFT); | ||
| 674 | priv->trig_timer.function = tsc2046_adc_trig_more; | ||
| 675 | |||
| 676 | ret = devm_iio_trigger_register(dev, trig); | ||
| 677 | if (ret) { | ||
| 678 | dev_err(dev, "failed to register trigger\n"); | ||
| 679 | return ret; | ||
| 680 | } | ||
| 681 | |||
| 682 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, | ||
| 683 | &tsc2046_adc_trigger_handler, NULL); | ||
| 684 | if (ret) { | ||
| 685 | dev_err(dev, "Failed to setup triggered buffer\n"); | ||
| 686 | return ret; | ||
| 687 | } | ||
| 688 | |||
| 689 | /* set default trigger */ | ||
| 690 | indio_dev->trig = iio_trigger_get(priv->trig); | ||
| 691 | |||
| 692 | return devm_iio_device_register(dev, indio_dev); | ||
| 693 | } | ||
| 694 | |||
| 695 | static const struct of_device_id ads7950_of_table[] = { | ||
| 696 | { .compatible = "ti,tsc2046e-adc", .data = &tsc2046_adc_dcfg_tsc2046e }, | ||
| 697 | { } | ||
| 698 | }; | ||
| 699 | MODULE_DEVICE_TABLE(of, ads7950_of_table); | ||
| 700 | |||
| 701 | static struct spi_driver tsc2046_adc_driver = { | ||
| 702 | .driver = { | ||
| 703 | .name = "tsc2046", | ||
| 704 | .of_match_table = ads7950_of_table, | ||
| 705 | }, | ||
| 706 | .probe = tsc2046_adc_probe, | ||
| 707 | }; | ||
| 708 | module_spi_driver(tsc2046_adc_driver); | ||
| 709 | |||
| 710 | MODULE_AUTHOR("Oleksij Rempel <kernel@pengutronix.de>"); | ||
| 711 | MODULE_DESCRIPTION("TI TSC2046 ADC"); | ||
| 712 | MODULE_LICENSE("GPL v2"); | ||
| @@ -167,7 +167,11 @@ struct vf610_adc { · 166 unmodified lines | |||
| 167 | u32 sample_freq_avail[5]; | 167 | u32 sample_freq_avail[5]; |
| 168 | 168 | ||
| 169 | struct completion completion; | 169 | struct completion completion; |
| 170 | u16 buffer[8]; | 170 | /* Ensure the timestamp is naturally aligned */ |
| 171 | struct { | ||
| 172 | u16 chan; | ||
| 173 | s64 timestamp __aligned(8); | ||
| 174 | } scan; | ||
| 171 | }; | 175 | }; |
| 172 | 176 | ||
| 173 | static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 }; | 177 | static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 }; |
| @@ -579,9 +583,9 @@ static irqreturn_t vf610_adc_isr(int irq, void *dev_id) · 405 unmodified lines | |||
| 579 | if (coco & VF610_ADC_HS_COCO0) { | 583 | if (coco & VF610_ADC_HS_COCO0) { |
| 580 | info->value = vf610_adc_read_data(info); | 584 | info->value = vf610_adc_read_data(info); |
| 581 | if (iio_buffer_enabled(indio_dev)) { | 585 | if (iio_buffer_enabled(indio_dev)) { |
| 582 | info->buffer[0] = info->value; | 586 | info->scan.chan = info->value; |
| 583 | iio_push_to_buffers_with_timestamp(indio_dev, | 587 | iio_push_to_buffers_with_timestamp(indio_dev, |
| 584 | info->buffer, | 588 | &info->scan, |
| 585 | iio_get_time_ns(indio_dev)); | 589 | iio_get_time_ns(indio_dev)); |
| 586 | iio_trigger_notify_done(indio_dev->trig); | 590 | iio_trigger_notify_done(indio_dev->trig); |
| 587 | } else | 591 | } else |
| @@ -743,7 +743,7 @@ static struct iio_trigger *xadc_alloc_trigger(struct iio_dev *indio_dev, · 742 unmodified lines | |||
| 743 | int ret; | 743 | int ret; |
| 744 | 744 | ||
| 745 | trig = devm_iio_trigger_alloc(dev, "%s%d-%s", indio_dev->name, | 745 | trig = devm_iio_trigger_alloc(dev, "%s%d-%s", indio_dev->name, |
| 746 | indio_dev->id, name); | 746 | iio_device_id(indio_dev), name); |
| 747 | if (trig == NULL) | 747 | if (trig == NULL) |
| 748 | return ERR_PTR(-ENOMEM); | 748 | return ERR_PTR(-ENOMEM); |
| 749 | 749 | ||
| @@ -29,6 +29,7 @@ struct rescale { · 28 unmodified lines | |||
| 29 | struct iio_channel *source; | 29 | struct iio_channel *source; |
| 30 | struct iio_chan_spec chan; | 30 | struct iio_chan_spec chan; |
| 31 | struct iio_chan_spec_ext_info *ext_info; | 31 | struct iio_chan_spec_ext_info *ext_info; |
| 32 | bool chan_processed; | ||
| 32 | s32 numerator; | 33 | s32 numerator; |
| 33 | s32 denominator; | 34 | s32 denominator; |
| 34 | }; | 35 | }; |
| @@ -43,10 +44,27 @@ static int rescale_read_raw(struct iio_dev *indio_dev, · 8 unmodified lines | |||
| 43 | 44 | ||
| 44 | switch (mask) { | 45 | switch (mask) { |
| 45 | case IIO_CHAN_INFO_RAW: | 46 | case IIO_CHAN_INFO_RAW: |
| 46 | return iio_read_channel_raw(rescale->source, val); | 47 | if (rescale->chan_processed) |
| 48 | /* | ||
| 49 | * When only processed channels are supported, we | ||
| 50 | * read the processed data and scale it by 1/1 | ||
| 51 | * augmented with whatever the rescaler has calculated. | ||
| 52 | */ | ||
| 53 | return iio_read_channel_processed(rescale->source, val); | ||
| 54 | else | ||
| 55 | return iio_read_channel_raw(rescale->source, val); | ||
| 47 | 56 | ||
| 48 | case IIO_CHAN_INFO_SCALE: | 57 | case IIO_CHAN_INFO_SCALE: |
| 49 | ret = iio_read_channel_scale(rescale->source, val, val2); | 58 | if (rescale->chan_processed) { |
| 59 | /* | ||
| 60 | * Processed channels are scaled 1-to-1 | ||
| 61 | */ | ||
| 62 | *val = 1; | ||
| 63 | *val2 = 1; | ||
| 64 | ret = IIO_VAL_FRACTIONAL; | ||
| 65 | } else { | ||
| 66 | ret = iio_read_channel_scale(rescale->source, val, val2); | ||
| 67 | } | ||
| 50 | switch (ret) { | 68 | switch (ret) { |
| 51 | case IIO_VAL_FRACTIONAL: | 69 | case IIO_VAL_FRACTIONAL: |
| 52 | *val *= rescale->numerator; | 70 | *val *= rescale->numerator; |
| @@ -130,16 +148,27 @@ static int rescale_configure_channel(struct device *dev, · 77 unmodified lines | |||
| 130 | chan->ext_info = rescale->ext_info; | 148 | chan->ext_info = rescale->ext_info; |
| 131 | chan->type = rescale->cfg->type; | 149 | chan->type = rescale->cfg->type; |
| 132 | 150 | ||
| 133 | if (!iio_channel_has_info(schan, IIO_CHAN_INFO_RAW) || | 151 | if (iio_channel_has_info(schan, IIO_CHAN_INFO_RAW) || |
| 134 | !iio_channel_has_info(schan, IIO_CHAN_INFO_SCALE)) { | 152 | iio_channel_has_info(schan, IIO_CHAN_INFO_SCALE)) { |
| 135 | dev_err(dev, "source channel does not support raw/scale\n"); | 153 | dev_info(dev, "using raw+scale source channel\n"); |
| 154 | } else if (iio_channel_has_info(schan, IIO_CHAN_INFO_PROCESSED)) { | ||
| 155 | dev_info(dev, "using processed channel\n"); | ||
| 156 | rescale->chan_processed = true; | ||
| 157 | } else { | ||
| 158 | dev_err(dev, "source channel is not supported\n"); | ||
| 136 | return -EINVAL; | 159 | return -EINVAL; |
| 137 | } | 160 | } |
| 138 | 161 | ||
| 139 | chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | 162 | chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
| 140 | BIT(IIO_CHAN_INFO_SCALE); | 163 | BIT(IIO_CHAN_INFO_SCALE); |
| 141 | 164 | ||
| 142 | if (iio_channel_has_available(schan, IIO_CHAN_INFO_RAW)) | 165 | /* |
| 166 | * Using .read_avail() is fringe to begin with and makes no sense | ||
| 167 | * whatsoever for processed channels, so we make sure that this cannot | ||
| 168 | * be called on a processed channel. | ||
| 169 | */ | ||
| 170 | if (iio_channel_has_available(schan, IIO_CHAN_INFO_RAW) && | ||
| 171 | !rescale->chan_processed) | ||
| 143 | chan->info_mask_separate_available |= BIT(IIO_CHAN_INFO_RAW); | 172 | chan->info_mask_separate_available |= BIT(IIO_CHAN_INFO_RAW); |
| 144 | 173 | ||
| 145 | return 0; | 174 | return 0; |
| @@ -228,9 +228,9 @@ static void iio_dmaengine_buffer_free(struct iio_buffer *buffer) · 227 unmodified lines | |||
| 228 | iio_buffer_put(buffer); | 228 | iio_buffer_put(buffer); |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | static void __devm_iio_dmaengine_buffer_free(struct device *dev, void *res) | 231 | static void __devm_iio_dmaengine_buffer_free(void *buffer) |
| 232 | { | 232 | { |
| 233 | iio_dmaengine_buffer_free(*(struct iio_buffer **)res); | 233 | iio_dmaengine_buffer_free(buffer); |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | /** | 236 | /** |
| @@ -247,21 +247,17 @@ static void __devm_iio_dmaengine_buffer_free(struct device *dev, void *res) · 10 unmodified lines | |||
| 247 | static struct iio_buffer *devm_iio_dmaengine_buffer_alloc(struct device *dev, | 247 | static struct iio_buffer *devm_iio_dmaengine_buffer_alloc(struct device *dev, |
| 248 | const char *channel) | 248 | const char *channel) |
| 249 | { | 249 | { |
| 250 | struct iio_buffer **bufferp, *buffer; | 250 | struct iio_buffer *buffer; |
| 251 | 251 | int ret; | |
| 252 | bufferp = devres_alloc(__devm_iio_dmaengine_buffer_free, | ||
| 253 | sizeof(*bufferp), GFP_KERNEL); | ||
| 254 | if (!bufferp) | ||
| 255 | return ERR_PTR(-ENOMEM); | ||
| 256 | 252 | ||
| 257 | buffer = iio_dmaengine_buffer_alloc(dev, channel); | 253 | buffer = iio_dmaengine_buffer_alloc(dev, channel); |
| 258 | if (IS_ERR(buffer)) { | 254 | if (IS_ERR(buffer)) |
| 259 | devres_free(bufferp); | ||
| 260 | return buffer; | 255 | return buffer; |
| 261 | } | ||
| 262 | 256 | ||
| 263 | *bufferp = buffer; | 257 | ret = devm_add_action_or_reset(dev, __devm_iio_dmaengine_buffer_free, |
| 264 | devres_add(dev, bufferp); | 258 | buffer); |
| 259 | if (ret) | ||
| 260 | return ERR_PTR(ret); | ||
| 265 | 261 | ||
| 266 | return buffer; | 262 | return buffer; |
| 267 | } | 263 | } |
| @@ -137,9 +137,9 @@ void iio_hw_consumer_free(struct iio_hw_consumer *hwc) · 136 unmodified lines | |||
| 137 | } | 137 | } |
| 138 | EXPORT_SYMBOL_GPL(iio_hw_consumer_free); | 138 | EXPORT_SYMBOL_GPL(iio_hw_consumer_free); |
| 139 | 139 | ||
| 140 | static void devm_iio_hw_consumer_release(struct device *dev, void *res) | 140 | static void devm_iio_hw_consumer_release(void *iio_hwc) |
| 141 | { | 141 | { |
| 142 | iio_hw_consumer_free(*(struct iio_hw_consumer **)res); | 142 | iio_hw_consumer_free(iio_hwc); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | /** | 145 | /** |
| @@ -153,20 +153,17 @@ static void devm_iio_hw_consumer_release(struct device *dev, void *res) · 7 unmodified lines | |||
| 153 | */ | 153 | */ |
| 154 | struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev) | 154 | struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev) |
| 155 | { | 155 | { |
| 156 | struct iio_hw_consumer **ptr, *iio_hwc; | 156 | struct iio_hw_consumer *iio_hwc; |
| 157 | 157 | int ret; | |
| 158 | ptr = devres_alloc(devm_iio_hw_consumer_release, sizeof(*ptr), | ||
| 159 | GFP_KERNEL); | ||
| 160 | if (!ptr) | ||
| 161 | return NULL; | ||
| 162 | 158 | ||
| 163 | iio_hwc = iio_hw_consumer_alloc(dev); | 159 | iio_hwc = iio_hw_consumer_alloc(dev); |
| 164 | if (IS_ERR(iio_hwc)) { | 160 | if (IS_ERR(iio_hwc)) |
| 165 | devres_free(ptr); | 161 | return iio_hwc; |
| 166 | } else { | 162 | |
| 167 | *ptr = iio_hwc; | 163 | ret = devm_add_action_or_reset(dev, devm_iio_hw_consumer_release, |
| 168 | devres_add(dev, ptr); | 164 | iio_hwc); |
| 169 | } | 165 | if (ret) |
| 166 | return ERR_PTR(ret); | ||
| 170 | 167 | ||
| 171 | return iio_hwc; | 168 | return iio_hwc; |
| 172 | } | 169 | } |
| @@ -56,7 +56,7 @@ int iio_triggered_buffer_setup_ext(struct iio_dev *indio_dev, · 55 unmodified lines | |||
| 56 | indio_dev, | 56 | indio_dev, |
| 57 | "%s_consumer%d", | 57 | "%s_consumer%d", |
| 58 | indio_dev->name, | 58 | indio_dev->name, |
| 59 | indio_dev->id); | 59 | iio_device_id(indio_dev)); |
| 60 | if (indio_dev->pollfunc == NULL) { | 60 | if (indio_dev->pollfunc == NULL) { |
| 61 | ret = -ENOMEM; | 61 | ret = -ENOMEM; |
| 62 | goto error_kfifo_free; | 62 | goto error_kfifo_free; |
| @@ -96,9 +96,9 @@ void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev) · 33 unmodified lines | |||
| 96 | } | 96 | } |
| 97 | EXPORT_SYMBOL(iio_triggered_buffer_cleanup); | 97 | EXPORT_SYMBOL(iio_triggered_buffer_cleanup); |
| 98 | 98 | ||
| 99 | static void devm_iio_triggered_buffer_clean(struct device *dev, void *res) | 99 | static void devm_iio_triggered_buffer_clean(void *indio_dev) |
| 100 | { | 100 | { |
| 101 | iio_triggered_buffer_cleanup(*(struct iio_dev **)res); | 101 | iio_triggered_buffer_cleanup(indio_dev); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | int devm_iio_triggered_buffer_setup_ext(struct device *dev, | 104 | int devm_iio_triggered_buffer_setup_ext(struct device *dev, |
| @@ -108,24 +108,15 @@ int devm_iio_triggered_buffer_setup_ext(struct device *dev, · 3 unmodified lines | |||
| 108 | const struct iio_buffer_setup_ops *ops, | 108 | const struct iio_buffer_setup_ops *ops, |
| 109 | const struct attribute **buffer_attrs) | 109 | const struct attribute **buffer_attrs) |
| 110 | { | 110 | { |
| 111 | struct iio_dev **ptr; | ||
| 112 | int ret; | 111 | int ret; |
| 113 | 112 | ||
| 114 | ptr = devres_alloc(devm_iio_triggered_buffer_clean, sizeof(*ptr), | ||
| 115 | GFP_KERNEL); | ||
| 116 | if (!ptr) | ||
| 117 | return -ENOMEM; | ||
| 118 | |||
| 119 | *ptr = indio_dev; | ||
| 120 | |||
| 121 | ret = iio_triggered_buffer_setup_ext(indio_dev, h, thread, ops, | 113 | ret = iio_triggered_buffer_setup_ext(indio_dev, h, thread, ops, |
| 122 | buffer_attrs); | 114 | buffer_attrs); |
| 123 | if (!ret) | 115 | if (ret) |
| 124 | devres_add(dev, ptr); | 116 | return ret; |
| 125 | else | ||
| 126 | devres_free(ptr); | ||
| 127 | 117 | ||
| 128 | return ret; | 118 | return devm_add_action_or_reset(dev, devm_iio_triggered_buffer_clean, |
| 119 | indio_dev); | ||
| 129 | } | 120 | } |
| 130 | EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_setup_ext); | 121 | EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_setup_ext); |
| 131 | 122 | ||
| @@ -132,17 +132,32 @@ config SENSIRION_SGP30 · 131 unmodified lines | |||
| 132 | module will be called sgp30. | 132 | module will be called sgp30. |
| 133 | 133 | ||
| 134 | config SPS30 | 134 | config SPS30 |
| 135 | tristate "SPS30 particulate matter sensor" | 135 | tristate |
| 136 | depends on I2C | ||
| 137 | select CRC8 | ||
| 138 | select IIO_BUFFER | 136 | select IIO_BUFFER |
| 139 | select IIO_TRIGGERED_BUFFER | 137 | select IIO_TRIGGERED_BUFFER |
| 138 | |||
| 139 | config SPS30_I2C | ||
| 140 | tristate "SPS30 particulate matter sensor I2C driver" | ||
| 141 | depends on I2C | ||
| 142 | select SPS30 | ||
| 143 | select CRC8 | ||
| 140 | help | 144 | help |
| 141 | Say Y here to build support for the Sensirion SPS30 particulate | 145 | Say Y here to build support for the Sensirion SPS30 I2C interface |
| 142 | matter sensor. | 146 | driver. |
| 147 | |||
| 148 | To compile this driver as a module, choose M here: the module will | ||
| 149 | be called sps30_i2c. | ||
| 150 | |||
| 151 | config SPS30_SERIAL | ||
| 152 | tristate "SPS30 particulate matter sensor serial driver" | ||
| 153 | depends on SERIAL_DEV_BUS | ||
| 154 | select SPS30 | ||
| 155 | help | ||
| 156 | Say Y here to build support for the Sensirion SPS30 serial interface | ||
| 157 | driver. | ||
| 143 | 158 | ||
| 144 | To compile this driver as a module, choose M here: the module will | 159 | To compile this driver as a module, choose M here: the module will |
| 145 | be called sps30. | 160 | be called sps30_serial. |
| 146 | 161 | ||
| 147 | config VZ89X | 162 | config VZ89X |
| 148 | tristate "SGX Sensortech MiCS VZ89X VOC sensor" | 163 | tristate "SGX Sensortech MiCS VZ89X VOC sensor" |
| @@ -17,4 +17,6 @@ obj-$(CONFIG_SCD30_I2C) += scd30_i2c.o · 16 unmodified lines | |||
| 17 | obj-$(CONFIG_SCD30_SERIAL) += scd30_serial.o | 17 | obj-$(CONFIG_SCD30_SERIAL) += scd30_serial.o |
| 18 | obj-$(CONFIG_SENSIRION_SGP30) += sgp30.o | 18 | obj-$(CONFIG_SENSIRION_SGP30) += sgp30.o |
| 19 | obj-$(CONFIG_SPS30) += sps30.o | 19 | obj-$(CONFIG_SPS30) += sps30.o |
| 20 | obj-$(CONFIG_SPS30_I2C) += sps30_i2c.o | ||
| 21 | obj-$(CONFIG_SPS30_SERIAL) += sps30_serial.o | ||
| 20 | obj-$(CONFIG_VZ89X) += vz89x.o | 22 | obj-$(CONFIG_VZ89X) += vz89x.o |
| @@ -91,8 +91,8 @@ struct atlas_data { · 90 unmodified lines | |||
| 91 | struct regmap *regmap; | 91 | struct regmap *regmap; |
| 92 | struct irq_work work; | 92 | struct irq_work work; |
| 93 | unsigned int interrupt_enabled; | 93 | unsigned int interrupt_enabled; |
| 94 | 94 | /* 96-bit data + 32-bit pad + 64-bit timestamp */ | |
| 95 | __be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */ | 95 | __be32 buffer[6] __aligned(8); |
| 96 | }; | 96 | }; |
| 97 | 97 | ||
| 98 | static const struct regmap_config atlas_regmap_config = { | 98 | static const struct regmap_config atlas_regmap_config = { |
| @@ -410,11 +410,9 @@ static int atlas_buffer_postenable(struct iio_dev *indio_dev) · 311 unmodified lines | |||
| 410 | struct atlas_data *data = iio_priv(indio_dev); | 410 | struct atlas_data *data = iio_priv(indio_dev); |
| 411 | int ret; | 411 | int ret; |
| 412 | 412 | ||
| 413 | ret = pm_runtime_get_sync(&data->client->dev); | 413 | ret = pm_runtime_resume_and_get(&data->client->dev); |
| 414 | if (ret < 0) { | 414 | if (ret) |
| 415 | pm_runtime_put_noidle(&data->client->dev); | ||
| 416 | return ret; | 415 | return ret; |
| 417 | } | ||
| 418 | 416 | ||
| 419 | return atlas_set_interrupt(data, true); | 417 | return atlas_set_interrupt(data, true); |
| 420 | } | 418 | } |
| @@ -487,11 +485,9 @@ static int atlas_read_measurement(struct atlas_data *data, int reg, __be32 *val) · 66 unmodified lines | |||
| 487 | int suspended = pm_runtime_suspended(dev); | 485 | int suspended = pm_runtime_suspended(dev); |
| 488 | int ret; | 486 | int ret; |
| 489 | 487 | ||
| 490 | ret = pm_runtime_get_sync(dev); | 488 | ret = pm_runtime_resume_and_get(dev); |
| 491 | if (ret < 0) { | 489 | if (ret) |
| 492 | pm_runtime_put_noidle(dev); | ||
| 493 | return ret; | 490 | return ret; |
| 494 | } | ||
| 495 | 491 | ||
| 496 | if (suspended) | 492 | if (suspended) |
| 497 | msleep(data->chip->delay); | 493 | msleep(data->chip->delay); |
| @@ -640,7 +636,7 @@ static int atlas_probe(struct i2c_client *client, · 142 unmodified lines | |||
| 640 | indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE; | 636 | indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE; |
| 641 | 637 | ||
| 642 | trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", | 638 | trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", |
| 643 | indio_dev->name, indio_dev->id); | 639 | indio_dev->name, iio_device_id(indio_dev)); |
| 644 | 640 | ||
| 645 | if (!trig) | 641 | if (!trig) |
| 646 | return -ENOMEM; | 642 | return -ENOMEM; |
| @@ -741,7 +737,6 @@ static int atlas_remove(struct i2c_client *client) · 94 unmodified lines | |||
| 741 | 737 | ||
| 742 | pm_runtime_disable(&client->dev); | 738 | pm_runtime_disable(&client->dev); |
| 743 | pm_runtime_set_suspended(&client->dev); | 739 | pm_runtime_set_suspended(&client->dev); |
| 744 | pm_runtime_put_noidle(&client->dev); | ||
| 745 | 740 | ||
| 746 | return atlas_set_powermode(data, 0); | 741 | return atlas_set_powermode(data, 0); |
| 747 | } | 742 | } |
| @@ -11,7 +11,6 @@ · 10 unmodified lines | |||
| 11 | * Note: SDO pin cannot be left floating otherwise I2C address | 11 | * Note: SDO pin cannot be left floating otherwise I2C address |
| 12 | * will be undefined. | 12 | * will be undefined. |
| 13 | */ | 13 | */ |
| 14 | #include <linux/acpi.h> | ||
| 15 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
| 16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 17 | #include <linux/regmap.h> | 16 | #include <linux/regmap.h> |
| @@ -42,12 +41,6 @@ static const struct i2c_device_id bme680_i2c_id[] = { · 24 unmodified lines | |||
| 42 | }; | 41 | }; |
| 43 | MODULE_DEVICE_TABLE(i2c, bme680_i2c_id); | 42 | MODULE_DEVICE_TABLE(i2c, bme680_i2c_id); |
| 44 | 43 | ||
| 45 | static const struct acpi_device_id bme680_acpi_match[] = { | ||
| 46 | {"BME0680", 0}, | ||
| 47 | {}, | ||
| 48 | }; | ||
| 49 | MODULE_DEVICE_TABLE(acpi, bme680_acpi_match); | ||
| 50 | |||
| 51 | static const struct of_device_id bme680_of_i2c_match[] = { | 44 | static const struct of_device_id bme680_of_i2c_match[] = { |
| 52 | { .compatible = "bosch,bme680", }, | 45 | { .compatible = "bosch,bme680", }, |
| 53 | {}, | 46 | {}, |
| @@ -57,7 +50,6 @@ MODULE_DEVICE_TABLE(of, bme680_of_i2c_match); · 3 unmodified lines | |||
| 57 | static struct i2c_driver bme680_i2c_driver = { | 50 | static struct i2c_driver bme680_i2c_driver = { |
| 58 | .driver = { | 51 | .driver = { |
| 59 | .name = "bme680_i2c", | 52 | .name = "bme680_i2c", |
| 60 | .acpi_match_table = ACPI_PTR(bme680_acpi_match), | ||
| 61 | .of_match_table = bme680_of_i2c_match, | 53 | .of_match_table = bme680_of_i2c_match, |
| 62 | }, | 54 | }, |
| 63 | .probe = bme680_i2c_probe, | 55 | .probe = bme680_i2c_probe, |
| @@ -4,7 +4,6 @@ · 3 unmodified lines | |||
| 4 | * | 4 | * |
| 5 | * Copyright (C) 2018 Himanshu Jha <himanshujha199640@gmail.com> | 5 | * Copyright (C) 2018 Himanshu Jha <himanshujha199640@gmail.com> |
| 6 | */ | 6 | */ |
| 7 | #include <linux/acpi.h> | ||
| 8 | #include <linux/module.h> | 7 | #include <linux/module.h> |
| 9 | #include <linux/of.h> | 8 | #include <linux/of.h> |
| 10 | #include <linux/regmap.h> | 9 | #include <linux/regmap.h> |
| @@ -145,12 +144,6 @@ static const struct spi_device_id bme680_spi_id[] = { · 134 unmodified lines | |||
| 145 | }; | 144 | }; |
| 146 | MODULE_DEVICE_TABLE(spi, bme680_spi_id); | 145 | MODULE_DEVICE_TABLE(spi, bme680_spi_id); |
| 147 | 146 | ||
| 148 | static const struct acpi_device_id bme680_acpi_match[] = { | ||
| 149 | {"BME0680", 0}, | ||
| 150 | {}, | ||
| 151 | }; | ||
| 152 | MODULE_DEVICE_TABLE(acpi, bme680_acpi_match); | ||
| 153 | |||
| 154 | static const struct of_device_id bme680_of_spi_match[] = { | 147 | static const struct of_device_id bme680_of_spi_match[] = { |
| 155 | { .compatible = "bosch,bme680", }, | 148 | { .compatible = "bosch,bme680", }, |
| 156 | {}, | 149 | {}, |
| @@ -160,7 +153,6 @@ MODULE_DEVICE_TABLE(of, bme680_of_spi_match); · 3 unmodified lines | |||
| 160 | static struct spi_driver bme680_spi_driver = { | 153 | static struct spi_driver bme680_spi_driver = { |
| 161 | .driver = { | 154 | .driver = { |
| 162 | .name = "bme680_spi", | 155 | .name = "bme680_spi", |
| 163 | .acpi_match_table = ACPI_PTR(bme680_acpi_match), | ||
| 164 | .of_match_table = bme680_of_spi_match, | 156 | .of_match_table = bme680_of_spi_match, |
| 165 | }, | 157 | }, |
| 166 | .probe = bme680_spi_probe, | 158 | .probe = bme680_spi_probe, |
| @@ -491,7 +491,7 @@ static int ccs811_probe(struct i2c_client *client, · 490 unmodified lines | |||
| 491 | data->drdy_trig = devm_iio_trigger_alloc(&client->dev, | 491 | data->drdy_trig = devm_iio_trigger_alloc(&client->dev, |
| 492 | "%s-dev%d", | 492 | "%s-dev%d", |
| 493 | indio_dev->name, | 493 | indio_dev->name, |
| 494 | indio_dev->id); | 494 | iio_device_id(indio_dev)); |
| 495 | if (!data->drdy_trig) { | 495 | if (!data->drdy_trig) { |
| 496 | ret = -ENOMEM; | 496 | ret = -ENOMEM; |
| 497 | goto err_poweroff; | 497 | goto err_poweroff; |
| @@ -640,7 +640,8 @@ static int scd30_setup_trigger(struct iio_dev *indio_dev) · 639 unmodified lines | |||
| 640 | struct iio_trigger *trig; | 640 | struct iio_trigger *trig; |
| 641 | int ret; | 641 | int ret; |
| 642 | 642 | ||
| 643 | trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, indio_dev->id); | 643 | trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, |
| 644 | iio_device_id(indio_dev)); | ||
| 644 | if (!trig) { | 645 | if (!trig) { |
| 645 | dev_err(dev, "failed to allocate trigger\n"); | 646 | dev_err(dev, "failed to allocate trigger\n"); |
| 646 | return -ENOMEM; | 647 | return -ENOMEM; |
| @@ -425,7 +425,7 @@ static int sgp_check_compat(struct sgp_data *data, · 424 unmodified lines | |||
| 425 | 425 | ||
| 426 | product = SGP_VERS_PRODUCT(data); | 426 | product = SGP_VERS_PRODUCT(data); |
| 427 | if (product != product_id) { | 427 | if (product != product_id) { |
| 428 | dev_err(dev, "sensor reports a different product: 0x%04hx\n", | 428 | dev_err(dev, "sensor reports a different product: 0x%04x\n", |
| 429 | product); | 429 | product); |
| 430 | return -ENODEV; | 430 | return -ENODEV; |
| 431 | } | 431 | } |
| @@ -3,11 +3,8 @@ · 2 unmodified lines | |||
| 3 | * Sensirion SPS30 particulate matter sensor driver | 3 | * Sensirion SPS30 particulate matter sensor driver |
| 4 | * | 4 | * |
| 5 | * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com> | 5 | * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com> |
| 6 | * | ||
| 7 | * I2C slave address: 0x69 | ||
| 8 | */ | 6 | */ |
| 9 | 7 | ||
| 10 | #include <asm/unaligned.h> | ||
| 11 | #include <linux/crc8.h> | 8 | #include <linux/crc8.h> |
| 12 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
| 13 | #include <linux/i2c.h> | 10 | #include <linux/i2c.h> |
| @@ -19,27 +16,14 @@ · 5 unmodified lines | |||
| 19 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 20 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 21 | 18 | ||
| 22 | #define SPS30_CRC8_POLYNOMIAL 0x31 | 19 | #include "sps30.h" |
| 23 | /* max number of bytes needed to store PM measurements or serial string */ | 20 | |
| 24 | #define SPS30_MAX_READ_SIZE 48 | ||
| 25 | /* sensor measures reliably up to 3000 ug / m3 */ | 21 | /* sensor measures reliably up to 3000 ug / m3 */ |
| 26 | #define SPS30_MAX_PM 3000 | 22 | #define SPS30_MAX_PM 3000 |
| 27 | /* minimum and maximum self cleaning periods in seconds */ | 23 | /* minimum and maximum self cleaning periods in seconds */ |
| 28 | #define SPS30_AUTO_CLEANING_PERIOD_MIN 0 | 24 | #define SPS30_AUTO_CLEANING_PERIOD_MIN 0 |
| 29 | #define SPS30_AUTO_CLEANING_PERIOD_MAX 604800 | 25 | #define SPS30_AUTO_CLEANING_PERIOD_MAX 604800 |
| 30 | 26 | ||
| 31 | /* SPS30 commands */ | ||
| 32 | #define SPS30_START_MEAS 0x0010 | ||
| 33 | #define SPS30_STOP_MEAS 0x0104 | ||
| 34 | #define SPS30_RESET 0xd304 | ||
| 35 | #define SPS30_READ_DATA_READY_FLAG 0x0202 | ||
| 36 | #define SPS30_READ_DATA 0x0300 | ||
| 37 | #define SPS30_READ_SERIAL 0xd033 | ||
| 38 | #define SPS30_START_FAN_CLEANING 0x5607 | ||
| 39 | #define SPS30_AUTO_CLEANING_PERIOD 0x8004 | ||
| 40 | /* not a sensor command per se, used only to distinguish write from read */ | ||
| 41 | #define SPS30_READ_AUTO_CLEANING_PERIOD 0x8005 | ||
| 42 | |||
| 43 | enum { | 27 | enum { |
| 44 | PM1, | 28 | PM1, |
| 45 | PM2P5, | 29 | PM2P5, |
| @@ -52,114 +36,9 @@ enum { · 6 unmodified lines | |||
| 52 | MEASURING, | 36 | MEASURING, |
| 53 | }; | 37 | }; |
| 54 | 38 | ||
| 55 | struct sps30_state { | 39 | static s32 sps30_float_to_int_clamped(__be32 *fp) |
| 56 | struct i2c_client *client; | ||
| 57 | /* | ||
| 58 | * Guards against concurrent access to sensor registers. | ||
| 59 | * Must be held whenever sequence of commands is to be executed. | ||
| 60 | */ | ||
| 61 | struct mutex lock; | ||
| 62 | int state; | ||
| 63 | }; | ||
| 64 | |||
| 65 | DECLARE_CRC8_TABLE(sps30_crc8_table); | ||
| 66 | |||
| 67 | static int sps30_write_then_read(struct sps30_state *state, u8 *txbuf, | ||
| 68 | int txsize, u8 *rxbuf, int rxsize) | ||
| 69 | { | ||
| 70 | int ret; | ||
| 71 | |||
| 72 | /* | ||
| 73 | * Sensor does not support repeated start so instead of | ||
| 74 | * sending two i2c messages in a row we just send one by one. | ||
| 75 | */ | ||
| 76 | ret = i2c_master_send(state->client, txbuf, txsize); | ||
| 77 | if (ret != txsize) | ||
| 78 | return ret < 0 ? ret : -EIO; | ||
| 79 | |||
| 80 | if (!rxbuf) | ||
| 81 | return 0; | ||
| 82 | |||
| 83 | ret = i2c_master_recv(state->client, rxbuf, rxsize); | ||
| 84 | if (ret != rxsize) | ||
| 85 | return ret < 0 ? ret : -EIO; | ||
| 86 | |||
| 87 | return 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | static int sps30_do_cmd(struct sps30_state *state, u16 cmd, u8 *data, int size) | ||
| 91 | { | ||
| 92 | /* | ||
| 93 | * Internally sensor stores measurements in a following manner: | ||
| 94 | * | ||
| 95 | * PM1: upper two bytes, crc8, lower two bytes, crc8 | ||
| 96 | * PM2P5: upper two bytes, crc8, lower two bytes, crc8 | ||
| 97 | * PM4: upper two bytes, crc8, lower two bytes, crc8 | ||
| 98 | * PM10: upper two bytes, crc8, lower two bytes, crc8 | ||
| 99 | * | ||
| 100 | * What follows next are number concentration measurements and | ||
| 101 | * typical particle size measurement which we omit. | ||
| 102 | */ | ||
| 103 | u8 buf[SPS30_MAX_READ_SIZE] = { cmd >> 8, cmd }; | ||
| 104 | int i, ret = 0; | ||
| 105 | |||
| 106 | switch (cmd) { | ||
| 107 | case SPS30_START_MEAS: | ||
| 108 | buf[2] = 0x03; | ||
| 109 | buf[3] = 0x00; | ||
| 110 | buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE); | ||
| 111 | ret = sps30_write_then_read(state, buf, 5, NULL, 0); | ||
| 112 | break; | ||
| 113 | case SPS30_STOP_MEAS: | ||
| 114 | case SPS30_RESET: | ||
| 115 | case SPS30_START_FAN_CLEANING: | ||
| 116 | ret = sps30_write_then_read(state, buf, 2, NULL, 0); | ||
| 117 | break; | ||
| 118 | case SPS30_READ_AUTO_CLEANING_PERIOD: | ||
| 119 | buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8; | ||
| 120 | buf[1] = (u8)(SPS30_AUTO_CLEANING_PERIOD & 0xff); | ||
| 121 | fallthrough; | ||
| 122 | case SPS30_READ_DATA_READY_FLAG: | ||
| 123 | case SPS30_READ_DATA: | ||
| 124 | case SPS30_READ_SERIAL: | ||
| 125 | /* every two data bytes are checksummed */ | ||
| 126 | size += size / 2; | ||
| 127 | ret = sps30_write_then_read(state, buf, 2, buf, size); | ||
| 128 | break; | ||
| 129 | case SPS30_AUTO_CLEANING_PERIOD: | ||
| 130 | buf[2] = data[0]; | ||
| 131 | buf[3] = data[1]; | ||
| 132 | buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE); | ||
| 133 | buf[5] = data[2]; | ||
| 134 | buf[6] = data[3]; | ||
| 135 | buf[7] = crc8(sps30_crc8_table, &buf[5], 2, CRC8_INIT_VALUE); | ||
| 136 | ret = sps30_write_then_read(state, buf, 8, NULL, 0); | ||
| 137 | break; | ||
| 138 | } | ||
| 139 | |||
| 140 | if (ret) | ||
| 141 | return ret; | ||
| 142 | |||
| 143 | /* validate received data and strip off crc bytes */ | ||
| 144 | for (i = 0; i < size; i += 3) { | ||
| 145 | u8 crc = crc8(sps30_crc8_table, &buf[i], 2, CRC8_INIT_VALUE); | ||
| 146 | |||
| 147 | if (crc != buf[i + 2]) { | ||
| 148 | dev_err(&state->client->dev, | ||
| 149 | "data integrity check failed\n"); | ||
| 150 | return -EIO; | ||
| 151 | } | ||
| 152 | |||
| 153 | *data++ = buf[i]; | ||
| 154 | *data++ = buf[i + 1]; | ||
| 155 | } | ||
| 156 | |||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | static s32 sps30_float_to_int_clamped(const u8 *fp) | ||
| 161 | { | 40 | { |
| 162 | int val = get_unaligned_be32(fp); | 41 | int val = be32_to_cpup(fp); |
| 163 | int mantissa = val & GENMASK(22, 0); | 42 | int mantissa = val & GENMASK(22, 0); |
| 164 | /* this is fine since passed float is always non-negative */ | 43 | /* this is fine since passed float is always non-negative */ |
| 165 | int exp = val >> 23; | 44 | int exp = val >> 23; |
| @@ -188,38 +67,35 @@ static s32 sps30_float_to_int_clamped(const u8 *fp) · 22 unmodified lines | |||
| 188 | 67 | ||
| 189 | static int sps30_do_meas(struct sps30_state *state, s32 *data, int size) | 68 | static int sps30_do_meas(struct sps30_state *state, s32 *data, int size) |
| 190 | { | 69 | { |
| 191 | int i, ret, tries = 5; | 70 | int i, ret; |
| 192 | u8 tmp[16]; | ||
| 193 | 71 | ||
| 194 | if (state->state == RESET) { | 72 | if (state->state == RESET) { |
| 195 | ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0); | 73 | ret = state->ops->start_meas(state); |
| 196 | if (ret) | 74 | if (ret) |
| 197 | return ret; | 75 | return ret; |
| 198 | 76 | ||
| 199 | state->state = MEASURING; | 77 | state->state = MEASURING; |
| 200 | } | 78 | } |
| 201 | 79 | ||
| 202 | while (tries--) { | 80 | ret = state->ops->read_meas(state, (__be32 *)data, size); |
| 203 | ret = sps30_do_cmd(state, SPS30_READ_DATA_READY_FLAG, tmp, 2); | 81 | if (ret) |
| 204 | if (ret) | 82 | return ret; |
| 205 | return -EIO; | ||
| 206 | 83 | ||
| 207 | /* new measurements ready to be read */ | 84 | for (i = 0; i < size; i++) |
| 208 | if (tmp[1] == 1) | 85 | data[i] = sps30_float_to_int_clamped((__be32 *)&data[i]); |
| 209 | break; | ||
| 210 | 86 | ||
| 211 | msleep_interruptible(300); | 87 | return 0; |
| 212 | } | 88 | } |
| 213 | 89 | ||
| 214 | if (tries == -1) | 90 | static int sps30_do_reset(struct sps30_state *state) |
| 215 | return -ETIMEDOUT; | 91 | { |
| 92 | int ret; | ||
| 216 | 93 | ||
| 217 | ret = sps30_do_cmd(state, SPS30_READ_DATA, tmp, sizeof(int) * size); | 94 | ret = state->ops->reset(state); |
| 218 | if (ret) | 95 | if (ret) |
| 219 | return ret; | 96 | return ret; |
| 220 | 97 | ||
| 221 | for (i = 0; i < size; i++) | 98 | state->state = RESET; |
| 222 | data[i] = sps30_float_to_int_clamped(&tmp[4 * i]); | ||
| 223 | 99 | ||
| 224 | return 0; | 100 | return 0; |
| 225 | } | 101 | } |
| @@ -310,24 +186,6 @@ static int sps30_read_raw(struct iio_dev *indio_dev, · 84 unmodified lines | |||
| 310 | return -EINVAL; | 186 | return -EINVAL; |
| 311 | } | 187 | } |
| 312 | 188 | ||
| 313 | static int sps30_do_cmd_reset(struct sps30_state *state) | ||
| 314 | { | ||
| 315 | int ret; | ||
| 316 | |||
| 317 | ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0); | ||
| 318 | msleep(300); | ||
| 319 | /* | ||
| 320 | * Power-on-reset causes sensor to produce some glitch on i2c bus and | ||
| 321 | * some controllers end up in error state. Recover simply by placing | ||
| 322 | * some data on the bus, for example STOP_MEAS command, which | ||
| 323 | * is NOP in this case. | ||
| 324 | */ | ||
| 325 | sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); | ||
| 326 | state->state = RESET; | ||
| 327 | |||
| 328 | return ret; | ||
| 329 | } | ||
| 330 | |||
| 331 | static ssize_t start_cleaning_store(struct device *dev, | 189 | static ssize_t start_cleaning_store(struct device *dev, |
| 332 | struct device_attribute *attr, | 190 | struct device_attribute *attr, |
| 333 | const char *buf, size_t len) | 191 | const char *buf, size_t len) |
| @@ -340,7 +198,7 @@ static ssize_t start_cleaning_store(struct device *dev, · 6 unmodified lines | |||
| 340 | return -EINVAL; | 198 | return -EINVAL; |
| 341 | 199 | ||
| 342 | mutex_lock(&state->lock); | 200 | mutex_lock(&state->lock); |
| 343 | ret = sps30_do_cmd(state, SPS30_START_FAN_CLEANING, NULL, 0); | 201 | ret = state->ops->clean_fan(state); |
| 344 | mutex_unlock(&state->lock); | 202 | mutex_unlock(&state->lock); |
| 345 | if (ret) | 203 | if (ret) |
| 346 | return ret; | 204 | return ret; |
| @@ -349,31 +207,29 @@ static ssize_t start_cleaning_store(struct device *dev, · 2 unmodified lines | |||
| 349 | } | 207 | } |
| 350 | 208 | ||
| 351 | static ssize_t cleaning_period_show(struct device *dev, | 209 | static ssize_t cleaning_period_show(struct device *dev, |
| 352 | struct device_attribute *attr, | 210 | struct device_attribute *attr, |
| 353 | char *buf) | 211 | char *buf) |
| 354 | { | 212 | { |
| 355 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 213 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 356 | struct sps30_state *state = iio_priv(indio_dev); | 214 | struct sps30_state *state = iio_priv(indio_dev); |
| 357 | u8 tmp[4]; | 215 | __be32 val; |
| 358 | int ret; | 216 | int ret; |
| 359 | 217 | ||
| 360 | mutex_lock(&state->lock); | 218 | mutex_lock(&state->lock); |
| 361 | ret = sps30_do_cmd(state, SPS30_READ_AUTO_CLEANING_PERIOD, tmp, 4); | 219 | ret = state->ops->read_cleaning_period(state, &val); |
| 362 | mutex_unlock(&state->lock); | 220 | mutex_unlock(&state->lock); |
| 363 | if (ret) | 221 | if (ret) |
| 364 | return ret; | 222 | return ret; |
| 365 | 223 | ||
| 366 | return sprintf(buf, "%d\n", get_unaligned_be32(tmp)); | 224 | return sprintf(buf, "%d\n", be32_to_cpu(val)); |
| 367 | } | 225 | } |
| 368 | 226 | ||
| 369 | static ssize_t cleaning_period_store(struct device *dev, | 227 | static ssize_t cleaning_period_store(struct device *dev, struct device_attribute *attr, |
| 370 | struct device_attribute *attr, | 228 | const char *buf, size_t len) |
| 371 | const char *buf, size_t len) | ||
| 372 | { | 229 | { |
| 373 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 230 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 374 | struct sps30_state *state = iio_priv(indio_dev); | 231 | struct sps30_state *state = iio_priv(indio_dev); |
| 375 | int val, ret; | 232 | int val, ret; |
| 376 | u8 tmp[4]; | ||
| 377 | 233 | ||
| 378 | if (kstrtoint(buf, 0, &val)) | 234 | if (kstrtoint(buf, 0, &val)) |
| 379 | return -EINVAL; | 235 | return -EINVAL; |
| @@ -382,10 +238,8 @@ static ssize_t cleaning_period_store(struct device *dev, · 2 unmodified lines | |||
| 382 | (val > SPS30_AUTO_CLEANING_PERIOD_MAX)) | 238 | (val > SPS30_AUTO_CLEANING_PERIOD_MAX)) |
| 383 | return -EINVAL; | 239 | return -EINVAL; |
| 384 | 240 | ||
| 385 | put_unaligned_be32(val, tmp); | ||
| 386 | |||
| 387 | mutex_lock(&state->lock); | 241 | mutex_lock(&state->lock); |
| 388 | ret = sps30_do_cmd(state, SPS30_AUTO_CLEANING_PERIOD, tmp, 0); | 242 | ret = state->ops->write_cleaning_period(state, cpu_to_be32(val)); |
| 389 | if (ret) { | 243 | if (ret) { |
| 390 | mutex_unlock(&state->lock); | 244 | mutex_unlock(&state->lock); |
| 391 | return ret; | 245 | return ret; |
| @@ -397,7 +251,7 @@ static ssize_t cleaning_period_store(struct device *dev, · 5 unmodified lines | |||
| 397 | * sensor requires reset in order to return up to date self cleaning | 251 | * sensor requires reset in order to return up to date self cleaning |
| 398 | * period | 252 | * period |
| 399 | */ | 253 | */ |
| 400 | ret = sps30_do_cmd_reset(state); | 254 | ret = sps30_do_reset(state); |
| 401 | if (ret) | 255 | if (ret) |
| 402 | dev_warn(dev, | 256 | dev_warn(dev, |
| 403 | "period changed but reads will return the old value\n"); | 257 | "period changed but reads will return the old value\n"); |
| @@ -411,9 +265,9 @@ static ssize_t cleaning_period_available_show(struct device *dev, · 7 unmodified lines | |||
| 411 | struct device_attribute *attr, | 265 | struct device_attribute *attr, |
| 412 | char *buf) | 266 | char *buf) |
| 413 | { | 267 | { |
| 414 | return snprintf(buf, PAGE_SIZE, "[%d %d %d]\n", | 268 | return sysfs_emit(buf, "[%d %d %d]\n", |
| 415 | SPS30_AUTO_CLEANING_PERIOD_MIN, 1, | 269 | SPS30_AUTO_CLEANING_PERIOD_MIN, 1, |
| 416 | SPS30_AUTO_CLEANING_PERIOD_MAX); | 270 | SPS30_AUTO_CLEANING_PERIOD_MAX); |
| 417 | } | 271 | } |
| 418 | 272 | ||
| 419 | static IIO_DEVICE_ATTR_WO(start_cleaning, 0); | 273 | static IIO_DEVICE_ATTR_WO(start_cleaning, 0); |
| @@ -460,90 +314,65 @@ static const struct iio_chan_spec sps30_channels[] = { · 40 unmodified lines | |||
| 460 | IIO_CHAN_SOFT_TIMESTAMP(4), | 314 | IIO_CHAN_SOFT_TIMESTAMP(4), |
| 461 | }; | 315 | }; |
| 462 | 316 | ||
| 463 | static void sps30_stop_meas(void *data) | 317 | static void sps30_devm_stop_meas(void *data) |
| 464 | { | 318 | { |
| 465 | struct sps30_state *state = data; | 319 | struct sps30_state *state = data; |
| 466 | 320 | ||
| 467 | sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); | 321 | if (state->state == MEASURING) |
| 322 | state->ops->stop_meas(state); | ||
| 468 | } | 323 | } |
| 469 | 324 | ||
| 470 | static const unsigned long sps30_scan_masks[] = { 0x0f, 0x00 }; | 325 | static const unsigned long sps30_scan_masks[] = { 0x0f, 0x00 }; |
| 471 | 326 | ||
| 472 | static int sps30_probe(struct i2c_client *client) | 327 | int sps30_probe(struct device *dev, const char *name, void *priv, const struct sps30_ops *ops) |
| 473 | { | 328 | { |
| 474 | struct iio_dev *indio_dev; | 329 | struct iio_dev *indio_dev; |
| 475 | struct sps30_state *state; | 330 | struct sps30_state *state; |
| 476 | u8 buf[32]; | ||
| 477 | int ret; | 331 | int ret; |
| 478 | 332 | ||
| 479 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | 333 | indio_dev = devm_iio_device_alloc(dev, sizeof(*state)); |
| 480 | return -EOPNOTSUPP; | ||
| 481 | |||
| 482 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*state)); | ||
| 483 | if (!indio_dev) | 334 | if (!indio_dev) |
| 484 | return -ENOMEM; | 335 | return -ENOMEM; |
| 485 | 336 | ||
| 337 | dev_set_drvdata(dev, indio_dev); | ||
| 338 | |||
| 486 | state = iio_priv(indio_dev); | 339 | state = iio_priv(indio_dev); |
| 487 | i2c_set_clientdata(client, indio_dev); | 340 | state->dev = dev; |
| 488 | state->client = client; | 341 | state->priv = priv; |
| 489 | state->state = RESET; | 342 | state->ops = ops; |
| 343 | mutex_init(&state->lock); | ||
| 344 | |||
| 490 | indio_dev->info = &sps30_info; | 345 | indio_dev->info = &sps30_info; |
| 491 | indio_dev->name = client->name; | 346 | indio_dev->name = name; |
| 492 | indio_dev->channels = sps30_channels; | 347 | indio_dev->channels = sps30_channels; |
| 493 | indio_dev->num_channels = ARRAY_SIZE(sps30_channels); | 348 | indio_dev->num_channels = ARRAY_SIZE(sps30_channels); |
| 494 | indio_dev->modes = INDIO_DIRECT_MODE; | 349 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 495 | indio_dev->available_scan_masks = sps30_scan_masks; | 350 | indio_dev->available_scan_masks = sps30_scan_masks; |
| 496 | 351 | ||
| 497 | mutex_init(&state->lock); | 352 | ret = sps30_do_reset(state); |
| 498 | crc8_populate_msb(sps30_crc8_table, SPS30_CRC8_POLYNOMIAL); | ||
| 499 | |||
| 500 | ret = sps30_do_cmd_reset(state); | ||
| 501 | if (ret) { | 353 | if (ret) { |
| 502 | dev_err(&client->dev, "failed to reset device\n"); | 354 | dev_err(dev, "failed to reset device\n"); |
| 503 | return ret; | 355 | return ret; |
| 504 | } | 356 | } |
| 505 | 357 | ||
| 506 | ret = sps30_do_cmd(state, SPS30_READ_SERIAL, buf, sizeof(buf)); | 358 | ret = state->ops->show_info(state); |
| 507 | if (ret) { | 359 | if (ret) { |
| 508 | dev_err(&client->dev, "failed to read serial number\n"); | 360 | dev_err(dev, "failed to read device info\n"); |
| 509 | return ret; | 361 | return ret; |
| 510 | } | 362 | } |
| 511 | /* returned serial number is already NUL terminated */ | ||
| 512 | dev_info(&client->dev, "serial number: %s\n", buf); | ||
| 513 | 363 | ||
| 514 | ret = devm_add_action_or_reset(&client->dev, sps30_stop_meas, state); | 364 | ret = devm_add_action_or_reset(dev, sps30_devm_stop_meas, state); |
| 515 | if (ret) | 365 | if (ret) |
| 516 | return ret; | 366 | return ret; |
| 517 | 367 | ||
| 518 | ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL, | 368 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, |
| 519 | sps30_trigger_handler, NULL); | 369 | sps30_trigger_handler, NULL); |
| 520 | if (ret) | 370 | if (ret) |
| 521 | return ret; | 371 | return ret; |
| 522 | 372 | ||
| 523 | return devm_iio_device_register(&client->dev, indio_dev); | 373 | return devm_iio_device_register(dev, indio_dev); |
| 524 | } | 374 | } |
| 525 | 375 | EXPORT_SYMBOL_GPL(sps30_probe); | |
| 526 | static const struct i2c_device_id sps30_id[] = { | ||
| 527 | { "sps30" }, | ||
| 528 | { } | ||
| 529 | }; | ||
| 530 | MODULE_DEVICE_TABLE(i2c, sps30_id); | ||
| 531 | |||
| 532 | static const struct of_device_id sps30_of_match[] = { | ||
| 533 | { .compatible = "sensirion,sps30" }, | ||
| 534 | { } | ||
| 535 | }; | ||
| 536 | MODULE_DEVICE_TABLE(of, sps30_of_match); | ||
| 537 | |||
| 538 | static struct i2c_driver sps30_driver = { | ||
| 539 | .driver = { | ||
| 540 | .name = "sps30", | ||
| 541 | .of_match_table = sps30_of_match, | ||
| 542 | }, | ||
| 543 | .id_table = sps30_id, | ||
| 544 | .probe_new = sps30_probe, | ||
| 545 | }; | ||
| 546 | module_i2c_driver(sps30_driver); | ||
| 547 | 376 | ||
| 548 | MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>"); | 377 | MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>"); |
| 549 | MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor driver"); | 378 | MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor driver"); |
| @@ -0,0 +1,35 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef _SPS30_H | ||
| 3 | #define _SPS30_H | ||
| 4 | |||
| 5 | #include <linux/types.h> | ||
| 6 | |||
| 7 | struct sps30_state; | ||
| 8 | struct sps30_ops { | ||
| 9 | int (*start_meas)(struct sps30_state *state); | ||
| 10 | int (*stop_meas)(struct sps30_state *state); | ||
| 11 | int (*read_meas)(struct sps30_state *state, __be32 *meas, size_t num); | ||
| 12 | int (*reset)(struct sps30_state *state); | ||
| 13 | int (*clean_fan)(struct sps30_state *state); | ||
| 14 | int (*read_cleaning_period)(struct sps30_state *state, __be32 *period); | ||
| 15 | int (*write_cleaning_period)(struct sps30_state *state, __be32 period); | ||
| 16 | int (*show_info)(struct sps30_state *state); | ||
| 17 | }; | ||
| 18 | |||
| 19 | struct sps30_state { | ||
| 20 | /* serialize access to the device */ | ||
| 21 | struct mutex lock; | ||
| 22 | struct device *dev; | ||
| 23 | int state; | ||
| 24 | /* | ||
| 25 | * priv pointer is solely for serdev driver private data. We keep it | ||
| 26 | * here because driver_data inside dev has been already used for iio and | ||
| 27 | * struct serdev_device doesn't have one. | ||
| 28 | */ | ||
| 29 | void *priv; | ||
| 30 | const struct sps30_ops *ops; | ||
| 31 | }; | ||
| 32 | |||
| 33 | int sps30_probe(struct device *dev, const char *name, void *priv, const struct sps30_ops *ops); | ||
| 34 | |||
| 35 | #endif | ||
| @@ -0,0 +1,258 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Sensirion SPS30 particulate matter sensor i2c driver | ||
| 4 | * | ||
| 5 | * Copyright (c) 2020 Tomasz Duszynski <tomasz.duszynski@octakon.com> | ||
| 6 | * | ||
| 7 | * I2C slave address: 0x69 | ||
| 8 | */ | ||
| 9 | #include <asm/unaligned.h> | ||
| 10 | #include <linux/crc8.h> | ||
| 11 | #include <linux/delay.h> | ||
| 12 | #include <linux/device.h> | ||
| 13 | #include <linux/errno.h> | ||
| 14 | #include <linux/i2c.h> | ||
| 15 | #include <linux/mod_devicetable.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/types.h> | ||
| 18 | |||
| 19 | #include "sps30.h" | ||
| 20 | |||
| 21 | #define SPS30_I2C_CRC8_POLYNOMIAL 0x31 | ||
| 22 | /* max number of bytes needed to store PM measurements or serial string */ | ||
| 23 | #define SPS30_I2C_MAX_BUF_SIZE 48 | ||
| 24 | |||
| 25 | DECLARE_CRC8_TABLE(sps30_i2c_crc8_table); | ||
| 26 | |||
| 27 | #define SPS30_I2C_START_MEAS 0x0010 | ||
| 28 | #define SPS30_I2C_STOP_MEAS 0x0104 | ||
| 29 | #define SPS30_I2C_READ_MEAS 0x0300 | ||
| 30 | #define SPS30_I2C_MEAS_READY 0x0202 | ||
| 31 | #define SPS30_I2C_RESET 0xd304 | ||
| 32 | #define SPS30_I2C_CLEAN_FAN 0x5607 | ||
| 33 | #define SPS30_I2C_PERIOD 0x8004 | ||
| 34 | #define SPS30_I2C_READ_SERIAL 0xd033 | ||
| 35 | #define SPS30_I2C_READ_VERSION 0xd100 | ||
| 36 | |||
| 37 | static int sps30_i2c_xfer(struct sps30_state *state, unsigned char *txbuf, size_t txsize, | ||
| 38 | unsigned char *rxbuf, size_t rxsize) | ||
| 39 | { | ||
| 40 | struct i2c_client *client = to_i2c_client(state->dev); | ||
| 41 | int ret; | ||
| 42 | |||
| 43 | /* | ||
| 44 | * Sensor does not support repeated start so instead of | ||
| 45 | * sending two i2c messages in a row we just send one by one. | ||
| 46 | */ | ||
| 47 | ret = i2c_master_send(client, txbuf, txsize); | ||
| 48 | if (ret < 0) | ||
| 49 | return ret; | ||
| 50 | if (ret != txsize) | ||
| 51 | return -EIO; | ||
| 52 | |||
| 53 | if (!rxsize) | ||
| 54 | return 0; | ||
| 55 | |||
| 56 | ret = i2c_master_recv(client, rxbuf, rxsize); | ||
| 57 | if (ret < 0) | ||
| 58 | return ret; | ||
| 59 | if (ret != rxsize) | ||
| 60 | return -EIO; | ||
| 61 | |||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static int sps30_i2c_command(struct sps30_state *state, u16 cmd, void *arg, size_t arg_size, | ||
| 66 | void *rsp, size_t rsp_size) | ||
| 67 | { | ||
| 68 | /* | ||
| 69 | * Internally sensor stores measurements in a following manner: | ||
| 70 | * | ||
| 71 | * PM1: upper two bytes, crc8, lower two bytes, crc8 | ||
| 72 | * PM2P5: upper two bytes, crc8, lower two bytes, crc8 | ||
| 73 | * PM4: upper two bytes, crc8, lower two bytes, crc8 | ||
| 74 | * PM10: upper two bytes, crc8, lower two bytes, crc8 | ||
| 75 | * | ||
| 76 | * What follows next are number concentration measurements and | ||
| 77 | * typical particle size measurement which we omit. | ||
| 78 | */ | ||
| 79 | unsigned char buf[SPS30_I2C_MAX_BUF_SIZE]; | ||
| 80 | unsigned char *tmp; | ||
| 81 | unsigned char crc; | ||
| 82 | size_t i; | ||
| 83 | int ret; | ||
| 84 | |||
| 85 | put_unaligned_be16(cmd, buf); | ||
| 86 | i = 2; | ||
| 87 | |||
| 88 | if (rsp) { | ||
| 89 | /* each two bytes are followed by a crc8 */ | ||
| 90 | rsp_size += rsp_size / 2; | ||
| 91 | } else { | ||
| 92 | tmp = arg; | ||
| 93 | |||
| 94 | while (arg_size) { | ||
| 95 | buf[i] = *tmp++; | ||
| 96 | buf[i + 1] = *tmp++; | ||
| 97 | buf[i + 2] = crc8(sps30_i2c_crc8_table, buf + i, 2, CRC8_INIT_VALUE); | ||
| 98 | arg_size -= 2; | ||
| 99 | i += 3; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | ret = sps30_i2c_xfer(state, buf, i, buf, rsp_size); | ||
| 104 | if (ret) | ||
| 105 | return ret; | ||
| 106 | |||
| 107 | /* validate received data and strip off crc bytes */ | ||
| 108 | tmp = rsp; | ||
| 109 | for (i = 0; i < rsp_size; i += 3) { | ||
| 110 | crc = crc8(sps30_i2c_crc8_table, buf + i, 2, CRC8_INIT_VALUE); | ||
| 111 | if (crc != buf[i + 2]) { | ||
| 112 | dev_err(state->dev, "data integrity check failed\n"); | ||
| 113 | return -EIO; | ||
| 114 | } | ||
| 115 | |||
| 116 | *tmp++ = buf[i]; | ||
| 117 | *tmp++ = buf[i + 1]; | ||
| 118 | } | ||
| 119 | |||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | static int sps30_i2c_start_meas(struct sps30_state *state) | ||
| 124 | { | ||
| 125 | /* request BE IEEE754 formatted data */ | ||
| 126 | unsigned char buf[] = { 0x03, 0x00 }; | ||
| 127 | |||
| 128 | return sps30_i2c_command(state, SPS30_I2C_START_MEAS, buf, sizeof(buf), NULL, 0); | ||
| 129 | } | ||
| 130 | |||
| 131 | static int sps30_i2c_stop_meas(struct sps30_state *state) | ||
| 132 | { | ||
| 133 | return sps30_i2c_command(state, SPS30_I2C_STOP_MEAS, NULL, 0, NULL, 0); | ||
| 134 | } | ||
| 135 | |||
| 136 | static int sps30_i2c_reset(struct sps30_state *state) | ||
| 137 | { | ||
| 138 | int ret; | ||
| 139 | |||
| 140 | ret = sps30_i2c_command(state, SPS30_I2C_RESET, NULL, 0, NULL, 0); | ||
| 141 | msleep(500); | ||
| 142 | /* | ||
| 143 | * Power-on-reset causes sensor to produce some glitch on i2c bus and | ||
| 144 | * some controllers end up in error state. Recover simply by placing | ||
| 145 | * some data on the bus, for example STOP_MEAS command, which | ||
| 146 | * is NOP in this case. | ||
| 147 | */ | ||
| 148 | sps30_i2c_stop_meas(state); | ||
| 149 | |||
| 150 | return ret; | ||
| 151 | } | ||
| 152 | |||
| 153 | static bool sps30_i2c_meas_ready(struct sps30_state *state) | ||
| 154 | { | ||
| 155 | unsigned char buf[2]; | ||
| 156 | int ret; | ||
| 157 | |||
| 158 | ret = sps30_i2c_command(state, SPS30_I2C_MEAS_READY, NULL, 0, buf, sizeof(buf)); | ||
| 159 | if (ret) | ||
| 160 | return false; | ||
| 161 | |||
| 162 | return buf[1]; | ||
| 163 | } | ||
| 164 | |||
| 165 | static int sps30_i2c_read_meas(struct sps30_state *state, __be32 *meas, size_t num) | ||
| 166 | { | ||
| 167 | /* measurements are ready within a second */ | ||
| 168 | if (msleep_interruptible(1000)) | ||
| 169 | return -EINTR; | ||
| 170 | |||
| 171 | if (!sps30_i2c_meas_ready(state)) | ||
| 172 | return -ETIMEDOUT; | ||
| 173 | |||
| 174 | return sps30_i2c_command(state, SPS30_I2C_READ_MEAS, NULL, 0, meas, sizeof(num) * num); | ||
| 175 | } | ||
| 176 | |||
| 177 | static int sps30_i2c_clean_fan(struct sps30_state *state) | ||
| 178 | { | ||
| 179 | return sps30_i2c_command(state, SPS30_I2C_CLEAN_FAN, NULL, 0, NULL, 0); | ||
| 180 | } | ||
| 181 | |||
| 182 | static int sps30_i2c_read_cleaning_period(struct sps30_state *state, __be32 *period) | ||
| 183 | { | ||
| 184 | return sps30_i2c_command(state, SPS30_I2C_PERIOD, NULL, 0, period, sizeof(*period)); | ||
| 185 | } | ||
| 186 | |||
| 187 | static int sps30_i2c_write_cleaning_period(struct sps30_state *state, __be32 period) | ||
| 188 | { | ||
| 189 | return sps30_i2c_command(state, SPS30_I2C_PERIOD, &period, sizeof(period), NULL, 0); | ||
| 190 | } | ||
| 191 | |||
| 192 | static int sps30_i2c_show_info(struct sps30_state *state) | ||
| 193 | { | ||
| 194 | /* extra nul just in case */ | ||
| 195 | unsigned char buf[32 + 1] = { 0x00 }; | ||
| 196 | int ret; | ||
| 197 | |||
| 198 | ret = sps30_i2c_command(state, SPS30_I2C_READ_SERIAL, NULL, 0, buf, sizeof(buf) - 1); | ||
| 199 | if (ret) | ||
| 200 | return ret; | ||
| 201 | |||
| 202 | dev_info(state->dev, "serial number: %s\n", buf); | ||
| 203 | |||
| 204 | ret = sps30_i2c_command(state, SPS30_I2C_READ_VERSION, NULL, 0, buf, 2); | ||
| 205 | if (ret) | ||
| 206 | return ret; | ||
| 207 | |||
| 208 | dev_info(state->dev, "fw version: %u.%u\n", buf[0], buf[1]); | ||
| 209 | |||
| 210 | return 0; | ||
| 211 | } | ||
| 212 | |||
| 213 | static const struct sps30_ops sps30_i2c_ops = { | ||
| 214 | .start_meas = sps30_i2c_start_meas, | ||
| 215 | .stop_meas = sps30_i2c_stop_meas, | ||
| 216 | .read_meas = sps30_i2c_read_meas, | ||
| 217 | .reset = sps30_i2c_reset, | ||
| 218 | .clean_fan = sps30_i2c_clean_fan, | ||
| 219 | .read_cleaning_period = sps30_i2c_read_cleaning_period, | ||
| 220 | .write_cleaning_period = sps30_i2c_write_cleaning_period, | ||
| 221 | .show_info = sps30_i2c_show_info, | ||
| 222 | }; | ||
| 223 | |||
| 224 | static int sps30_i2c_probe(struct i2c_client *client) | ||
| 225 | { | ||
| 226 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
| 227 | return -EOPNOTSUPP; | ||
| 228 | |||
| 229 | crc8_populate_msb(sps30_i2c_crc8_table, SPS30_I2C_CRC8_POLYNOMIAL); | ||
| 230 | |||
| 231 | return sps30_probe(&client->dev, client->name, NULL, &sps30_i2c_ops); | ||
| 232 | } | ||
| 233 | |||
| 234 | static const struct i2c_device_id sps30_i2c_id[] = { | ||
| 235 | { "sps30" }, | ||
| 236 | { } | ||
| 237 | }; | ||
| 238 | MODULE_DEVICE_TABLE(i2c, sps30_i2c_id); | ||
| 239 | |||
| 240 | static const struct of_device_id sps30_i2c_of_match[] = { | ||
| 241 | { .compatible = "sensirion,sps30" }, | ||
| 242 | { } | ||
| 243 | }; | ||
| 244 | MODULE_DEVICE_TABLE(of, sps30_i2c_of_match); | ||
| 245 | |||
| 246 | static struct i2c_driver sps30_i2c_driver = { | ||
| 247 | .driver = { | ||
| 248 | .name = KBUILD_MODNAME, | ||
| 249 | .of_match_table = sps30_i2c_of_match, | ||
| 250 | }, | ||
| 251 | .id_table = sps30_i2c_id, | ||
| 252 | .probe_new = sps30_i2c_probe, | ||
| 253 | }; | ||
| 254 | module_i2c_driver(sps30_i2c_driver); | ||
| 255 | |||
| 256 | MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>"); | ||
| 257 | MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor i2c driver"); | ||
| 258 | MODULE_LICENSE("GPL v2"); | ||
| @@ -0,0 +1,431 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Sensirion SPS30 particulate matter sensor serial driver | ||
| 4 | * | ||
| 5 | * Copyright (c) 2021 Tomasz Duszynski <tomasz.duszynski@octakon.com> | ||
| 6 | */ | ||
| 7 | #include <linux/completion.h> | ||
| 8 | #include <linux/device.h> | ||
| 9 | #include <linux/errno.h> | ||
| 10 | #include <linux/iio/iio.h> | ||
| 11 | #include <linux/minmax.h> | ||
| 12 | #include <linux/mod_devicetable.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/serdev.h> | ||
| 15 | #include <linux/types.h> | ||
| 16 | |||
| 17 | #include "sps30.h" | ||
| 18 | |||
| 19 | #define SPS30_SERIAL_DEV_NAME "sps30" | ||
| 20 | |||
| 21 | #define SPS30_SERIAL_SOF_EOF 0x7e | ||
| 22 | #define SPS30_SERIAL_TIMEOUT msecs_to_jiffies(20) | ||
| 23 | #define SPS30_SERIAL_MAX_BUF_SIZE 263 | ||
| 24 | #define SPS30_SERIAL_ESCAPE_CHAR 0x7d | ||
| 25 | |||
| 26 | #define SPS30_SERIAL_FRAME_MIN_SIZE 7 | ||
| 27 | #define SPS30_SERIAL_FRAME_ADR_OFFSET 1 | ||
| 28 | #define SPS30_SERIAL_FRAME_CMD_OFFSET 2 | ||
| 29 | #define SPS30_SERIAL_FRAME_MOSI_LEN_OFFSET 3 | ||
| 30 | #define SPS30_SERIAL_FRAME_MISO_STATE_OFFSET 3 | ||
| 31 | #define SPS30_SERIAL_FRAME_MISO_LEN_OFFSET 4 | ||
| 32 | #define SPS30_SERIAL_FRAME_MISO_DATA_OFFSET 5 | ||
| 33 | |||
| 34 | #define SPS30_SERIAL_START_MEAS 0x00 | ||
| 35 | #define SPS30_SERIAL_STOP_MEAS 0x01 | ||
| 36 | #define SPS30_SERIAL_READ_MEAS 0x03 | ||
| 37 | #define SPS30_SERIAL_RESET 0xd3 | ||
| 38 | #define SPS30_SERIAL_CLEAN_FAN 0x56 | ||
| 39 | #define SPS30_SERIAL_PERIOD 0x80 | ||
| 40 | #define SPS30_SERIAL_DEV_INFO 0xd0 | ||
| 41 | #define SPS30_SERIAL_READ_VERSION 0xd1 | ||
| 42 | |||
| 43 | struct sps30_serial_priv { | ||
| 44 | struct completion new_frame; | ||
| 45 | unsigned char buf[SPS30_SERIAL_MAX_BUF_SIZE]; | ||
| 46 | size_t num; | ||
| 47 | bool escaped; | ||
| 48 | bool done; | ||
| 49 | }; | ||
| 50 | |||
| 51 | static int sps30_serial_xfer(struct sps30_state *state, const unsigned char *buf, size_t size) | ||
| 52 | { | ||
| 53 | struct serdev_device *serdev = to_serdev_device(state->dev); | ||
| 54 | struct sps30_serial_priv *priv = state->priv; | ||
| 55 | int ret; | ||
| 56 | |||
| 57 | priv->num = 0; | ||
| 58 | priv->escaped = false; | ||
| 59 | priv->done = false; | ||
| 60 | |||
| 61 | ret = serdev_device_write(serdev, buf, size, SPS30_SERIAL_TIMEOUT); | ||
| 62 | if (ret < 0) | ||
| 63 | return ret; | ||
| 64 | if (ret != size) | ||
| 65 | return -EIO; | ||
| 66 | |||
| 67 | ret = wait_for_completion_interruptible_timeout(&priv->new_frame, SPS30_SERIAL_TIMEOUT); | ||
| 68 | if (ret < 0) | ||
| 69 | return ret; | ||
| 70 | if (!ret) | ||
| 71 | return -ETIMEDOUT; | ||
| 72 | |||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | static const struct { | ||
| 77 | unsigned char byte; | ||
| 78 | unsigned char byte2; | ||
| 79 | } sps30_serial_bytes[] = { | ||
| 80 | { 0x11, 0x31 }, | ||
| 81 | { 0x13, 0x33 }, | ||
| 82 | { 0x7e, 0x5e }, | ||
| 83 | { 0x7d, 0x5d }, | ||
| 84 | }; | ||
| 85 | |||
| 86 | static int sps30_serial_put_byte(unsigned char *buf, unsigned char byte) | ||
| 87 | { | ||
| 88 | int i; | ||
| 89 | |||
| 90 | for (i = 0; i < ARRAY_SIZE(sps30_serial_bytes); i++) { | ||
| 91 | if (sps30_serial_bytes[i].byte != byte) | ||
| 92 | continue; | ||
| 93 | |||
| 94 | buf[0] = SPS30_SERIAL_ESCAPE_CHAR; | ||
| 95 | buf[1] = sps30_serial_bytes[i].byte2; | ||
| 96 | |||
| 97 | return 2; | ||
| 98 | } | ||
| 99 | |||
| 100 | buf[0] = byte; | ||
| 101 | |||
| 102 | return 1; | ||
| 103 | } | ||
| 104 | |||
| 105 | static char sps30_serial_get_byte(bool escaped, unsigned char byte2) | ||
| 106 | { | ||
| 107 | int i; | ||
| 108 | |||
| 109 | if (!escaped) | ||
| 110 | return byte2; | ||
| 111 | |||
| 112 | for (i = 0; i < ARRAY_SIZE(sps30_serial_bytes); i++) { | ||
| 113 | if (sps30_serial_bytes[i].byte2 != byte2) | ||
| 114 | continue; | ||
| 115 | |||
| 116 | return sps30_serial_bytes[i].byte; | ||
| 117 | } | ||
| 118 | |||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | static unsigned char sps30_serial_calc_chksum(const unsigned char *buf, size_t num) | ||
| 123 | { | ||
| 124 | unsigned int chksum = 0; | ||
| 125 | size_t i; | ||
| 126 | |||
| 127 | for (i = 0; i < num; i++) | ||
| 128 | chksum += buf[i]; | ||
| 129 | |||
| 130 | return ~chksum; | ||
| 131 | } | ||
| 132 | |||
| 133 | static int sps30_serial_prep_frame(unsigned char *buf, unsigned char cmd, | ||
| 134 | const unsigned char *arg, size_t arg_size) | ||
| 135 | { | ||
| 136 | unsigned char chksum; | ||
| 137 | int num = 0; | ||
| 138 | size_t i; | ||
| 139 | |||
| 140 | buf[num++] = SPS30_SERIAL_SOF_EOF; | ||
| 141 | buf[num++] = 0; | ||
| 142 | num += sps30_serial_put_byte(buf + num, cmd); | ||
| 143 | num += sps30_serial_put_byte(buf + num, arg_size); | ||
| 144 | |||
| 145 | for (i = 0; i < arg_size; i++) | ||
| 146 | num += sps30_serial_put_byte(buf + num, arg[i]); | ||
| 147 | |||
| 148 | /* SOF isn't checksummed */ | ||
| 149 | chksum = sps30_serial_calc_chksum(buf + 1, num - 1); | ||
| 150 | num += sps30_serial_put_byte(buf + num, chksum); | ||
| 151 | buf[num++] = SPS30_SERIAL_SOF_EOF; | ||
| 152 | |||
| 153 | return num; | ||
| 154 | } | ||
| 155 | |||
| 156 | static bool sps30_serial_frame_valid(struct sps30_state *state, const unsigned char *buf) | ||
| 157 | { | ||
| 158 | struct sps30_serial_priv *priv = state->priv; | ||
| 159 | unsigned char chksum; | ||
| 160 | |||
| 161 | if ((priv->num < SPS30_SERIAL_FRAME_MIN_SIZE) || | ||
| 162 | (priv->num != SPS30_SERIAL_FRAME_MIN_SIZE + | ||
| 163 | priv->buf[SPS30_SERIAL_FRAME_MISO_LEN_OFFSET])) { | ||
| 164 | dev_err(state->dev, "frame has invalid number of bytes\n"); | ||
| 165 | return false; | ||
| 166 | } | ||
| 167 | |||
| 168 | if ((priv->buf[SPS30_SERIAL_FRAME_ADR_OFFSET] != buf[SPS30_SERIAL_FRAME_ADR_OFFSET]) || | ||
| 169 | (priv->buf[SPS30_SERIAL_FRAME_CMD_OFFSET] != buf[SPS30_SERIAL_FRAME_CMD_OFFSET])) { | ||
| 170 | dev_err(state->dev, "frame has wrong ADR and CMD bytes\n"); | ||
| 171 | return false; | ||
| 172 | } | ||
| 173 | |||
| 174 | if (priv->buf[SPS30_SERIAL_FRAME_MISO_STATE_OFFSET]) { | ||
| 175 | dev_err(state->dev, "frame with non-zero state received (0x%02x)\n", | ||
| 176 | priv->buf[SPS30_SERIAL_FRAME_MISO_STATE_OFFSET]); | ||
| 177 | return false; | ||
| 178 | } | ||
| 179 | |||
| 180 | /* SOF, checksum and EOF are not checksummed */ | ||
| 181 | chksum = sps30_serial_calc_chksum(priv->buf + 1, priv->num - 3); | ||
| 182 | if (priv->buf[priv->num - 2] != chksum) { | ||
| 183 | dev_err(state->dev, "frame integrity check failed\n"); | ||
| 184 | return false; | ||
| 185 | } | ||
| 186 | |||
| 187 | return true; | ||
| 188 | } | ||
| 189 | |||
| 190 | static int sps30_serial_command(struct sps30_state *state, unsigned char cmd, | ||
| 191 | const void *arg, size_t arg_size, void *rsp, size_t rsp_size) | ||
| 192 | { | ||
| 193 | struct sps30_serial_priv *priv = state->priv; | ||
| 194 | unsigned char buf[SPS30_SERIAL_MAX_BUF_SIZE]; | ||
| 195 | int ret, size; | ||
| 196 | |||
| 197 | size = sps30_serial_prep_frame(buf, cmd, arg, arg_size); | ||
| 198 | ret = sps30_serial_xfer(state, buf, size); | ||
| 199 | if (ret) | ||
| 200 | return ret; | ||
| 201 | |||
| 202 | if (!sps30_serial_frame_valid(state, buf)) | ||
| 203 | return -EIO; | ||
| 204 | |||
| 205 | if (rsp) { | ||
| 206 | rsp_size = min_t(size_t, priv->buf[SPS30_SERIAL_FRAME_MISO_LEN_OFFSET], rsp_size); | ||
| 207 | memcpy(rsp, &priv->buf[SPS30_SERIAL_FRAME_MISO_DATA_OFFSET], rsp_size); | ||
| 208 | } | ||
| 209 | |||
| 210 | return rsp_size; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int sps30_serial_receive_buf(struct serdev_device *serdev, | ||
| 214 | const unsigned char *buf, size_t size) | ||
| 215 | { | ||
| 216 | struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev); | ||
| 217 | struct sps30_serial_priv *priv; | ||
| 218 | struct sps30_state *state; | ||
| 219 | unsigned char byte; | ||
| 220 | size_t i; | ||
| 221 | |||
| 222 | if (!indio_dev) | ||
| 223 | return 0; | ||
| 224 | |||
| 225 | state = iio_priv(indio_dev); | ||
| 226 | priv = state->priv; | ||
| 227 | |||
| 228 | /* just in case device put some unexpected data on the bus */ | ||
| 229 | if (priv->done) | ||
| 230 | return size; | ||
| 231 | |||
| 232 | /* wait for the start of frame */ | ||
| 233 | if (!priv->num && size && buf[0] != SPS30_SERIAL_SOF_EOF) | ||
| 234 | return 1; | ||
| 235 | |||
| 236 | if (priv->num + size >= ARRAY_SIZE(priv->buf)) | ||
| 237 | size = ARRAY_SIZE(priv->buf) - priv->num; | ||
| 238 | |||
| 239 | for (i = 0; i < size; i++) { | ||
| 240 | byte = buf[i]; | ||
| 241 | /* remove stuffed bytes on-the-fly */ | ||
| 242 | if (byte == SPS30_SERIAL_ESCAPE_CHAR) { | ||
| 243 | priv->escaped = true; | ||
| 244 | continue; | ||
| 245 | } | ||
| 246 | |||
| 247 | byte = sps30_serial_get_byte(priv->escaped, byte); | ||
| 248 | if (priv->escaped && !byte) | ||
| 249 | dev_warn(state->dev, "unrecognized escaped char (0x%02x)\n", byte); | ||
| 250 | |||
| 251 | priv->buf[priv->num++] = byte; | ||
| 252 | |||
| 253 | /* EOF received */ | ||
| 254 | if (!priv->escaped && byte == SPS30_SERIAL_SOF_EOF) { | ||
| 255 | if (priv->num < SPS30_SERIAL_FRAME_MIN_SIZE) | ||
| 256 | continue; | ||
| 257 | |||
| 258 | priv->done = true; | ||
| 259 | complete(&priv->new_frame); | ||
| 260 | i++; | ||
| 261 | break; | ||
| 262 | } | ||
| 263 | |||
| 264 | priv->escaped = false; | ||
| 265 | } | ||
| 266 | |||
| 267 | return i; | ||
| 268 | } | ||
| 269 | |||
| 270 | static const struct serdev_device_ops sps30_serial_device_ops = { | ||
| 271 | .receive_buf = sps30_serial_receive_buf, | ||
| 272 | .write_wakeup = serdev_device_write_wakeup, | ||
| 273 | }; | ||
| 274 | |||
| 275 | static int sps30_serial_start_meas(struct sps30_state *state) | ||
| 276 | { | ||
| 277 | /* request BE IEEE754 formatted data */ | ||
| 278 | unsigned char buf[] = { 0x01, 0x03 }; | ||
| 279 | |||
| 280 | return sps30_serial_command(state, SPS30_SERIAL_START_MEAS, buf, sizeof(buf), NULL, 0); | ||
| 281 | } | ||
| 282 | |||
| 283 | static int sps30_serial_stop_meas(struct sps30_state *state) | ||
| 284 | { | ||
| 285 | return sps30_serial_command(state, SPS30_SERIAL_STOP_MEAS, NULL, 0, NULL, 0); | ||
| 286 | } | ||
| 287 | |||
| 288 | static int sps30_serial_reset(struct sps30_state *state) | ||
| 289 | { | ||
| 290 | int ret; | ||
| 291 | |||
| 292 | ret = sps30_serial_command(state, SPS30_SERIAL_RESET, NULL, 0, NULL, 0); | ||
| 293 | msleep(500); | ||
| 294 | |||
| 295 | return ret; | ||
| 296 | } | ||
| 297 | |||
| 298 | static int sps30_serial_read_meas(struct sps30_state *state, __be32 *meas, size_t num) | ||
| 299 | { | ||
| 300 | int ret; | ||
| 301 | |||
| 302 | /* measurements are ready within a second */ | ||
| 303 | if (msleep_interruptible(1000)) | ||
| 304 | return -EINTR; | ||
| 305 | |||
| 306 | ret = sps30_serial_command(state, SPS30_SERIAL_READ_MEAS, NULL, 0, meas, num * sizeof(num)); | ||
| 307 | if (ret < 0) | ||
| 308 | return ret; | ||
| 309 | /* if measurements aren't ready sensor returns empty frame */ | ||
| 310 | if (ret == SPS30_SERIAL_FRAME_MIN_SIZE) | ||
| 311 | return -ETIMEDOUT; | ||
| 312 | if (ret != num * sizeof(*meas)) | ||
| 313 | return -EIO; | ||
| 314 | |||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 318 | static int sps30_serial_clean_fan(struct sps30_state *state) | ||
| 319 | { | ||
| 320 | return sps30_serial_command(state, SPS30_SERIAL_CLEAN_FAN, NULL, 0, NULL, 0); | ||
| 321 | } | ||
| 322 | |||
| 323 | static int sps30_serial_read_cleaning_period(struct sps30_state *state, __be32 *period) | ||
| 324 | { | ||
| 325 | unsigned char buf[] = { 0x00 }; | ||
| 326 | int ret; | ||
| 327 | |||
| 328 | ret = sps30_serial_command(state, SPS30_SERIAL_PERIOD, buf, sizeof(buf), | ||
| 329 | period, sizeof(*period)); | ||
| 330 | if (ret < 0) | ||
| 331 | return ret; | ||
| 332 | if (ret != sizeof(*period)) | ||
| 333 | return -EIO; | ||
| 334 | |||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | static int sps30_serial_write_cleaning_period(struct sps30_state *state, __be32 period) | ||
| 339 | { | ||
| 340 | unsigned char buf[5] = { 0x00 }; | ||
| 341 | |||
| 342 | memcpy(buf + 1, &period, sizeof(period)); | ||
| 343 | |||
| 344 | return sps30_serial_command(state, SPS30_SERIAL_PERIOD, buf, sizeof(buf), NULL, 0); | ||
| 345 | } | ||
| 346 | |||
| 347 | static int sps30_serial_show_info(struct sps30_state *state) | ||
| 348 | { | ||
| 349 | /* | ||
| 350 | * tell device do return serial number and add extra nul byte just in case | ||
| 351 | * serial number isn't a valid string | ||
| 352 | */ | ||
| 353 | unsigned char buf[32 + 1] = { 0x03 }; | ||
| 354 | struct device *dev = state->dev; | ||
| 355 | int ret; | ||
| 356 | |||
| 357 | ret = sps30_serial_command(state, SPS30_SERIAL_DEV_INFO, buf, 1, buf, sizeof(buf) - 1); | ||
| 358 | if (ret < 0) | ||
| 359 | return ret; | ||
| 360 | if (ret != sizeof(buf) - 1) | ||
| 361 | return -EIO; | ||
| 362 | |||
| 363 | dev_info(dev, "serial number: %s\n", buf); | ||
| 364 | |||
| 365 | ret = sps30_serial_command(state, SPS30_SERIAL_READ_VERSION, NULL, 0, buf, sizeof(buf) - 1); | ||
| 366 | if (ret < 0) | ||
| 367 | return ret; | ||
| 368 | if (ret < 2) | ||
| 369 | return -EIO; | ||
| 370 | |||
| 371 | dev_info(dev, "fw version: %u.%u\n", buf[0], buf[1]); | ||
| 372 | |||
| 373 | return 0; | ||
| 374 | } | ||
| 375 | |||
| 376 | static const struct sps30_ops sps30_serial_ops = { | ||
| 377 | .start_meas = sps30_serial_start_meas, | ||
| 378 | .stop_meas = sps30_serial_stop_meas, | ||
| 379 | .read_meas = sps30_serial_read_meas, | ||
| 380 | .reset = sps30_serial_reset, | ||
| 381 | .clean_fan = sps30_serial_clean_fan, | ||
| 382 | .read_cleaning_period = sps30_serial_read_cleaning_period, | ||
| 383 | .write_cleaning_period = sps30_serial_write_cleaning_period, | ||
| 384 | .show_info = sps30_serial_show_info, | ||
| 385 | }; | ||
| 386 | |||
| 387 | static int sps30_serial_probe(struct serdev_device *serdev) | ||
| 388 | { | ||
| 389 | struct device *dev = &serdev->dev; | ||
| 390 | struct sps30_serial_priv *priv; | ||
| 391 | int ret; | ||
| 392 | |||
| 393 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
| 394 | if (!priv) | ||
| 395 | return -ENOMEM; | ||
| 396 | |||
| 397 | init_completion(&priv->new_frame); | ||
| 398 | serdev_device_set_client_ops(serdev, &sps30_serial_device_ops); | ||
| 399 | |||
| 400 | ret = devm_serdev_device_open(dev, serdev); | ||
| 401 | if (ret) | ||
| 402 | return ret; | ||
| 403 | |||
| 404 | serdev_device_set_baudrate(serdev, 115200); | ||
| 405 | serdev_device_set_flow_control(serdev, false); | ||
| 406 | |||
| 407 | ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE); | ||
| 408 | if (ret) | ||
| 409 | return ret; | ||
| 410 | |||
| 411 | return sps30_probe(dev, SPS30_SERIAL_DEV_NAME, priv, &sps30_serial_ops); | ||
| 412 | } | ||
| 413 | |||
| 414 | static const struct of_device_id sps30_serial_of_match[] = { | ||
| 415 | { .compatible = "sensirion,sps30" }, | ||
| 416 | { } | ||
| 417 | }; | ||
| 418 | MODULE_DEVICE_TABLE(of, sps30_serial_of_match); | ||
| 419 | |||
| 420 | static struct serdev_device_driver sps30_serial_driver = { | ||
| 421 | .driver = { | ||
| 422 | .name = KBUILD_MODNAME, | ||
| 423 | .of_match_table = sps30_serial_of_match, | ||
| 424 | }, | ||
| 425 | .probe = sps30_serial_probe, | ||
| 426 | }; | ||
| 427 | module_serdev_device_driver(sps30_serial_driver); | ||
| 428 | |||
| 429 | MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>"); | ||
| 430 | MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor serial driver"); | ||
| 431 | MODULE_LICENSE("GPL v2"); | ||
| @@ -3,18 +3,12 @@ · 2 unmodified lines | |||
| 3 | * HID Sensors Driver | 3 | * HID Sensors Driver |
| 4 | * Copyright (c) 2012, Intel Corporation. | 4 | * Copyright (c) 2012, Intel Corporation. |
| 5 | */ | 5 | */ |
| 6 | #include <linux/device.h> | ||
| 7 | #include <linux/platform_device.h> | ||
| 8 | #include <linux/module.h> | 6 | #include <linux/module.h> |
| 9 | #include <linux/interrupt.h> | ||
| 10 | #include <linux/irq.h> | ||
| 11 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 12 | #include <linux/slab.h> | ||
| 13 | #include <linux/time.h> | 8 | #include <linux/time.h> |
| 14 | 9 | ||
| 15 | #include <linux/hid-sensor-hub.h> | 10 | #include <linux/hid-sensor-hub.h> |
| 16 | #include <linux/iio/iio.h> | 11 | #include <linux/iio/iio.h> |
| 17 | #include <linux/iio/sysfs.h> | ||
| 18 | 12 | ||
| 19 | #define HZ_PER_MHZ 1000000L | 13 | #define HZ_PER_MHZ 1000000L |
| 20 | 14 | ||
| @@ -176,7 +170,7 @@ s32 hid_sensor_read_poll_value(struct hid_sensor_common *st) · 155 unmodified lines | |||
| 176 | 170 | ||
| 177 | return value; | 171 | return value; |
| 178 | } | 172 | } |
| 179 | EXPORT_SYMBOL(hid_sensor_read_poll_value); | 173 | EXPORT_SYMBOL_NS(hid_sensor_read_poll_value, IIO_HID_ATTRIBUTES); |
| 180 | 174 | ||
| 181 | int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, | 175 | int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, |
| 182 | int *val1, int *val2) | 176 | int *val1, int *val2) |
| @@ -203,7 +197,7 @@ int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st, · 20 unmodified lines | |||
| 203 | 197 | ||
| 204 | return IIO_VAL_INT_PLUS_MICRO; | 198 | return IIO_VAL_INT_PLUS_MICRO; |
| 205 | } | 199 | } |
| 206 | EXPORT_SYMBOL(hid_sensor_read_samp_freq_value); | 200 | EXPORT_SYMBOL_NS(hid_sensor_read_samp_freq_value, IIO_HID); |
| 207 | 201 | ||
| 208 | int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, | 202 | int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, |
| 209 | int val1, int val2) | 203 | int val1, int val2) |
| @@ -238,7 +232,7 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, · 28 unmodified lines | |||
| 238 | 232 | ||
| 239 | return 0; | 233 | return 0; |
| 240 | } | 234 | } |
| 241 | EXPORT_SYMBOL(hid_sensor_write_samp_freq_value); | 235 | EXPORT_SYMBOL_NS(hid_sensor_write_samp_freq_value, IIO_HID); |
| 242 | 236 | ||
| 243 | int hid_sensor_read_raw_hyst_value(struct hid_sensor_common *st, | 237 | int hid_sensor_read_raw_hyst_value(struct hid_sensor_common *st, |
| 244 | int *val1, int *val2) | 238 | int *val1, int *val2) |
| @@ -261,7 +255,7 @@ int hid_sensor_read_raw_hyst_value(struct hid_sensor_common *st, · 16 unmodified lines | |||
| 261 | 255 | ||
| 262 | return IIO_VAL_INT_PLUS_MICRO; | 256 | return IIO_VAL_INT_PLUS_MICRO; |
| 263 | } | 257 | } |
| 264 | EXPORT_SYMBOL(hid_sensor_read_raw_hyst_value); | 258 | EXPORT_SYMBOL_NS(hid_sensor_read_raw_hyst_value, IIO_HID); |
| 265 | 259 | ||
| 266 | int hid_sensor_read_raw_hyst_rel_value(struct hid_sensor_common *st, int *val1, | 260 | int hid_sensor_read_raw_hyst_rel_value(struct hid_sensor_common *st, int *val1, |
| 267 | int *val2) | 261 | int *val2) |
| @@ -283,7 +277,7 @@ int hid_sensor_read_raw_hyst_rel_value(struct hid_sensor_common *st, int *val1, · 15 unmodified lines | |||
| 283 | 277 | ||
| 284 | return IIO_VAL_INT_PLUS_MICRO; | 278 | return IIO_VAL_INT_PLUS_MICRO; |
| 285 | } | 279 | } |
| 286 | EXPORT_SYMBOL(hid_sensor_read_raw_hyst_rel_value); | 280 | EXPORT_SYMBOL_NS(hid_sensor_read_raw_hyst_rel_value, IIO_HID); |
| 287 | 281 | ||
| 288 | 282 | ||
| 289 | int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st, | 283 | int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st, |
| @@ -315,7 +309,7 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st, · 25 unmodified lines | |||
| 315 | 309 | ||
| 316 | return 0; | 310 | return 0; |
| 317 | } | 311 | } |
| 318 | EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); | 312 | EXPORT_SYMBOL_NS(hid_sensor_write_raw_hyst_value, IIO_HID); |
| 319 | 313 | ||
| 320 | int hid_sensor_write_raw_hyst_rel_value(struct hid_sensor_common *st, | 314 | int hid_sensor_write_raw_hyst_rel_value(struct hid_sensor_common *st, |
| 321 | int val1, int val2) | 315 | int val1, int val2) |
| @@ -346,7 +340,7 @@ int hid_sensor_write_raw_hyst_rel_value(struct hid_sensor_common *st, · 24 unmodified lines | |||
| 346 | 340 | ||
| 347 | return 0; | 341 | return 0; |
| 348 | } | 342 | } |
| 349 | EXPORT_SYMBOL(hid_sensor_write_raw_hyst_rel_value); | 343 | EXPORT_SYMBOL_NS(hid_sensor_write_raw_hyst_rel_value, IIO_HID); |
| 350 | 344 | ||
| 351 | /* | 345 | /* |
| 352 | * This fuction applies the unit exponent to the scale. | 346 | * This fuction applies the unit exponent to the scale. |
| @@ -430,14 +424,14 @@ int hid_sensor_format_scale(u32 usage_id, · 77 unmodified lines | |||
| 430 | 424 | ||
| 431 | return IIO_VAL_INT_PLUS_NANO; | 425 | return IIO_VAL_INT_PLUS_NANO; |
| 432 | } | 426 | } |
| 433 | EXPORT_SYMBOL(hid_sensor_format_scale); | 427 | EXPORT_SYMBOL_NS(hid_sensor_format_scale, IIO_HID); |
| 434 | 428 | ||
| 435 | int64_t hid_sensor_convert_timestamp(struct hid_sensor_common *st, | 429 | int64_t hid_sensor_convert_timestamp(struct hid_sensor_common *st, |
| 436 | int64_t raw_value) | 430 | int64_t raw_value) |
| 437 | { | 431 | { |
| 438 | return st->timestamp_ns_scale * raw_value; | 432 | return st->timestamp_ns_scale * raw_value; |
| 439 | } | 433 | } |
| 440 | EXPORT_SYMBOL(hid_sensor_convert_timestamp); | 434 | EXPORT_SYMBOL_NS(hid_sensor_convert_timestamp, IIO_HID); |
| 441 | 435 | ||
| 442 | static | 436 | static |
| 443 | int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev, | 437 | int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev, |
| @@ -484,7 +478,7 @@ int hid_sensor_get_report_latency(struct hid_sensor_common *st) · 40 unmodified lines | |||
| 484 | 478 | ||
| 485 | return value; | 479 | return value; |
| 486 | } | 480 | } |
| 487 | EXPORT_SYMBOL(hid_sensor_get_report_latency); | 481 | EXPORT_SYMBOL_NS(hid_sensor_get_report_latency, IIO_HID_ATTRIBUTES); |
| 488 | 482 | ||
| 489 | int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency_ms) | 483 | int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency_ms) |
| 490 | { | 484 | { |
| @@ -492,13 +486,13 @@ int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency_ms) · 1 unmodified line | |||
| 492 | st->report_latency.index, | 486 | st->report_latency.index, |
| 493 | sizeof(latency_ms), &latency_ms); | 487 | sizeof(latency_ms), &latency_ms); |
| 494 | } | 488 | } |
| 495 | EXPORT_SYMBOL(hid_sensor_set_report_latency); | 489 | EXPORT_SYMBOL_NS(hid_sensor_set_report_latency, IIO_HID_ATTRIBUTES); |
| 496 | 490 | ||
| 497 | bool hid_sensor_batch_mode_supported(struct hid_sensor_common *st) | 491 | bool hid_sensor_batch_mode_supported(struct hid_sensor_common *st) |
| 498 | { | 492 | { |
| 499 | return st->report_latency.index > 0 && st->report_latency.report_id > 0; | 493 | return st->report_latency.index > 0 && st->report_latency.report_id > 0; |
| 500 | } | 494 | } |
| 501 | EXPORT_SYMBOL(hid_sensor_batch_mode_supported); | 495 | EXPORT_SYMBOL_NS(hid_sensor_batch_mode_supported, IIO_HID_ATTRIBUTES); |
| 502 | 496 | ||
| 503 | int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, | 497 | int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, |
| 504 | u32 usage_id, | 498 | u32 usage_id, |
| @@ -590,7 +584,7 @@ int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev, · 85 unmodified lines | |||
| 590 | 584 | ||
| 591 | return 0; | 585 | return 0; |
| 592 | } | 586 | } |
| 593 | EXPORT_SYMBOL(hid_sensor_parse_common_attributes); | 587 | EXPORT_SYMBOL_NS(hid_sensor_parse_common_attributes, IIO_HID); |
| 594 | 588 | ||
| 595 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); | 589 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); |
| 596 | MODULE_DESCRIPTION("HID Sensor common attribute processing"); | 590 | MODULE_DESCRIPTION("HID Sensor common attribute processing"); |
| @@ -6,16 +6,13 @@ · 5 unmodified lines | |||
| 6 | #include <linux/device.h> | 6 | #include <linux/device.h> |
| 7 | #include <linux/platform_device.h> | 7 | #include <linux/platform_device.h> |
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/interrupt.h> | ||
| 10 | #include <linux/irq.h> | ||
| 11 | #include <linux/slab.h> | ||
| 12 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
| 13 | #include <linux/hid-sensor-hub.h> | 10 | #include <linux/hid-sensor-hub.h> |
| 11 | #include <linux/workqueue.h> | ||
| 14 | #include <linux/iio/iio.h> | 12 | #include <linux/iio/iio.h> |
| 15 | #include <linux/iio/trigger.h> | 13 | #include <linux/iio/trigger.h> |
| 16 | #include <linux/iio/triggered_buffer.h> | 14 | #include <linux/iio/triggered_buffer.h> |
| 17 | #include <linux/iio/trigger_consumer.h> | 15 | #include <linux/iio/trigger_consumer.h> |
| 18 | #include <linux/iio/buffer.h> | ||
| 19 | #include <linux/iio/sysfs.h> | 16 | #include <linux/iio/sysfs.h> |
| 20 | #include "hid-sensor-trigger.h" | 17 | #include "hid-sensor-trigger.h" |
| 21 | 18 | ||
| @@ -150,7 +147,7 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) · 128 unmodified lines | |||
| 150 | 147 | ||
| 151 | return 0; | 148 | return 0; |
| 152 | } | 149 | } |
| 153 | EXPORT_SYMBOL(hid_sensor_power_state); | 150 | EXPORT_SYMBOL_NS(hid_sensor_power_state, IIO_HID); |
| 154 | 151 | ||
| 155 | int hid_sensor_power_state(struct hid_sensor_common *st, bool state) | 152 | int hid_sensor_power_state(struct hid_sensor_common *st, bool state) |
| 156 | { | 153 | { |
| @@ -163,18 +160,15 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state) · 6 unmodified lines | |||
| 163 | 160 | ||
| 164 | if (state) { | 161 | if (state) { |
| 165 | atomic_inc(&st->user_requested_state); | 162 | atomic_inc(&st->user_requested_state); |
| 166 | ret = pm_runtime_get_sync(&st->pdev->dev); | 163 | ret = pm_runtime_resume_and_get(&st->pdev->dev); |
| 167 | } else { | 164 | } else { |
| 168 | atomic_dec(&st->user_requested_state); | 165 | atomic_dec(&st->user_requested_state); |
| 169 | pm_runtime_mark_last_busy(&st->pdev->dev); | 166 | pm_runtime_mark_last_busy(&st->pdev->dev); |
| 170 | pm_runtime_use_autosuspend(&st->pdev->dev); | 167 | pm_runtime_use_autosuspend(&st->pdev->dev); |
| 171 | ret = pm_runtime_put_autosuspend(&st->pdev->dev); | 168 | ret = pm_runtime_put_autosuspend(&st->pdev->dev); |
| 172 | } | 169 | } |
| 173 | if (ret < 0) { | 170 | if (ret < 0) |
| 174 | if (state) | ||
| 175 | pm_runtime_put_noidle(&st->pdev->dev); | ||
| 176 | return ret; | 171 | return ret; |
| 177 | } | ||
| 178 | 172 | ||
| 179 | return 0; | 173 | return 0; |
| 180 | #else | 174 | #else |
| @@ -222,14 +216,13 @@ void hid_sensor_remove_trigger(struct iio_dev *indio_dev, · 41 unmodified lines | |||
| 222 | pm_runtime_disable(&attrb->pdev->dev); | 216 | pm_runtime_disable(&attrb->pdev->dev); |
| 223 | 217 | ||
| 224 | pm_runtime_set_suspended(&attrb->pdev->dev); | 218 | pm_runtime_set_suspended(&attrb->pdev->dev); |
| 225 | pm_runtime_put_noidle(&attrb->pdev->dev); | ||
| 226 | 219 | ||
| 227 | cancel_work_sync(&attrb->work); | 220 | cancel_work_sync(&attrb->work); |
| 228 | iio_trigger_unregister(attrb->trigger); | 221 | iio_trigger_unregister(attrb->trigger); |
| 229 | iio_trigger_free(attrb->trigger); | 222 | iio_trigger_free(attrb->trigger); |
| 230 | iio_triggered_buffer_cleanup(indio_dev); | 223 | iio_triggered_buffer_cleanup(indio_dev); |
| 231 | } | 224 | } |
| 232 | EXPORT_SYMBOL(hid_sensor_remove_trigger); | 225 | EXPORT_SYMBOL_NS(hid_sensor_remove_trigger, IIO_HID); |
| 233 | 226 | ||
| 234 | static const struct iio_trigger_ops hid_sensor_trigger_ops = { | 227 | static const struct iio_trigger_ops hid_sensor_trigger_ops = { |
| 235 | .set_trigger_state = &hid_sensor_data_rdy_trigger_set_state, | 228 | .set_trigger_state = &hid_sensor_data_rdy_trigger_set_state, |
| @@ -256,7 +249,7 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, · 20 unmodified lines | |||
| 256 | } | 249 | } |
| 257 | 250 | ||
| 258 | trig = iio_trigger_alloc(indio_dev->dev.parent, | 251 | trig = iio_trigger_alloc(indio_dev->dev.parent, |
| 259 | "%s-dev%d", name, indio_dev->id); | 252 | "%s-dev%d", name, iio_device_id(indio_dev)); |
| 260 | if (trig == NULL) { | 253 | if (trig == NULL) { |
| 261 | dev_err(&indio_dev->dev, "Trigger Allocate Failed\n"); | 254 | dev_err(&indio_dev->dev, "Trigger Allocate Failed\n"); |
| 262 | ret = -ENOMEM; | 255 | ret = -ENOMEM; |
| @@ -295,7 +288,7 @@ error_triggered_buffer_cleanup: · 32 unmodified lines | |||
| 295 | iio_triggered_buffer_cleanup(indio_dev); | 288 | iio_triggered_buffer_cleanup(indio_dev); |
| 296 | return ret; | 289 | return ret; |
| 297 | } | 290 | } |
| 298 | EXPORT_SYMBOL(hid_sensor_setup_trigger); | 291 | EXPORT_SYMBOL_NS(hid_sensor_setup_trigger, IIO_HID); |
| 299 | 292 | ||
| 300 | static int __maybe_unused hid_sensor_suspend(struct device *dev) | 293 | static int __maybe_unused hid_sensor_suspend(struct device *dev) |
| 301 | { | 294 | { |
| @@ -325,8 +318,9 @@ const struct dev_pm_ops hid_sensor_pm_ops = { · 23 unmodified lines | |||
| 325 | SET_RUNTIME_PM_OPS(hid_sensor_suspend, | 318 | SET_RUNTIME_PM_OPS(hid_sensor_suspend, |
| 326 | hid_sensor_runtime_resume, NULL) | 319 | hid_sensor_runtime_resume, NULL) |
| 327 | }; | 320 | }; |
| 328 | EXPORT_SYMBOL(hid_sensor_pm_ops); | 321 | EXPORT_SYMBOL_NS(hid_sensor_pm_ops, IIO_HID); |
| 329 | 322 | ||
| 330 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); | 323 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); |
| 331 | MODULE_DESCRIPTION("HID Sensor trigger processing"); | 324 | MODULE_DESCRIPTION("HID Sensor trigger processing"); |
| 332 | MODULE_LICENSE("GPL"); | 325 | MODULE_LICENSE("GPL"); |
| 326 | MODULE_IMPORT_NS(IIO_HID_ATTRIBUTES); | ||
| @@ -9,6 +9,9 @@ · 8 unmodified lines | |||
| 9 | #include <linux/pm.h> | 9 | #include <linux/pm.h> |
| 10 | #include <linux/pm_runtime.h> | 10 | #include <linux/pm_runtime.h> |
| 11 | 11 | ||
| 12 | struct hid_sensor_common; | ||
| 13 | struct iio_dev; | ||
| 14 | |||
| 12 | extern const struct dev_pm_ops hid_sensor_pm_ops; | 15 | extern const struct dev_pm_ops hid_sensor_pm_ops; |
| 13 | 16 | ||
| 14 | int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, | 17 | int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, |
| @@ -1,4 +1,4 @@ | |||
| 1 | # SPDX - License - Identifier : GPL - 2.0 - only | 1 | # SPDX-License-Identifier: GPL-2.0-only |
| 2 | # | 2 | # |
| 3 | # Makefile for the IIO over SCMI | 3 | # Makefile for the IIO over SCMI |
| 4 | # | 4 | # |
| @@ -525,7 +525,6 @@ scmi_alloc_iiodev(struct scmi_device *sdev, · 524 unmodified lines | |||
| 525 | return ERR_PTR(-ENOMEM); | 525 | return ERR_PTR(-ENOMEM); |
| 526 | 526 | ||
| 527 | iiodev->modes = INDIO_DIRECT_MODE; | 527 | iiodev->modes = INDIO_DIRECT_MODE; |
| 528 | iiodev->dev.parent = dev; | ||
| 529 | sensor = iio_priv(iiodev); | 528 | sensor = iio_priv(iiodev); |
| 530 | sensor->sensor_ops = ops; | 529 | sensor->sensor_ops = ops; |
| 531 | sensor->ph = ph; | 530 | sensor->ph = ph; |
| @@ -597,8 +597,6 @@ static int ad5766_probe(struct spi_device *spi) · 596 unmodified lines | |||
| 597 | indio_dev->channels = st->chip_info->channels; | 597 | indio_dev->channels = st->chip_info->channels; |
| 598 | indio_dev->num_channels = st->chip_info->num_channels; | 598 | indio_dev->num_channels = st->chip_info->num_channels; |
| 599 | indio_dev->info = &ad5766_info; | 599 | indio_dev->info = &ad5766_info; |
| 600 | indio_dev->dev.parent = &spi->dev; | ||
| 601 | indio_dev->dev.of_node = spi->dev.of_node; | ||
| 602 | indio_dev->name = spi_get_device_id(spi)->name; | 600 | indio_dev->name = spi_get_device_id(spi)->name; |
| 603 | indio_dev->modes = INDIO_DIRECT_MODE; | 601 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 604 | 602 | ||
| @@ -69,9 +69,8 @@ static int stm32_dac_set_enable_state(struct iio_dev *indio_dev, int ch, · 68 unmodified lines | |||
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | if (enable) { | 71 | if (enable) { |
| 72 | ret = pm_runtime_get_sync(dev); | 72 | ret = pm_runtime_resume_and_get(dev); |
| 73 | if (ret < 0) { | 73 | if (ret < 0) { |
| 74 | pm_runtime_put_noidle(dev); | ||
| 75 | mutex_unlock(&dac->lock); | 74 | mutex_unlock(&dac->lock); |
| 76 | return ret; | 75 | return ret; |
| 77 | } | 76 | } |
| @@ -34,6 +34,7 @@ config IIO_SIMPLE_DUMMY_BUFFER · 33 unmodified lines | |||
| 34 | select IIO_BUFFER | 34 | select IIO_BUFFER |
| 35 | select IIO_TRIGGER | 35 | select IIO_TRIGGER |
| 36 | select IIO_KFIFO_BUF | 36 | select IIO_KFIFO_BUF |
| 37 | select IIO_TRIGGERED_BUFFER | ||
| 37 | help | 38 | help |
| 38 | Add buffered data capture to the simple dummy driver. | 39 | Add buffered data capture to the simple dummy driver. |
| 39 | 40 | ||
| @@ -563,8 +563,10 @@ static int adf4350_probe(struct spi_device *spi) · 562 unmodified lines | |||
| 563 | 563 | ||
| 564 | st->lock_detect_gpiod = devm_gpiod_get_optional(&spi->dev, NULL, | 564 | st->lock_detect_gpiod = devm_gpiod_get_optional(&spi->dev, NULL, |
| 565 | GPIOD_IN); | 565 | GPIOD_IN); |
| 566 | if (IS_ERR(st->lock_detect_gpiod)) | 566 | if (IS_ERR(st->lock_detect_gpiod)) { |
| 567 | return PTR_ERR(st->lock_detect_gpiod); | 567 | ret = PTR_ERR(st->lock_detect_gpiod); |
| 568 | goto error_disable_reg; | ||
| 569 | } | ||
| 568 | 570 | ||
| 569 | if (pdata->power_up_frequency) { | 571 | if (pdata->power_up_frequency) { |
| 570 | ret = adf4350_set_freq(st, pdata->power_up_frequency); | 572 | ret = adf4350_set_freq(st, pdata->power_up_frequency); |
| @@ -6,19 +6,14 @@ · 5 unmodified lines | |||
| 6 | * Author: Lars-Peter Clausen <lars@metafoo.de> | 6 | * Author: Lars-Peter Clausen <lars@metafoo.de> |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/interrupt.h> | ||
| 10 | #include <linux/delay.h> | ||
| 11 | #include <linux/mutex.h> | ||
| 12 | #include <linux/device.h> | 9 | #include <linux/device.h> |
| 13 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
| 14 | #include <linux/spi/spi.h> | 11 | #include <linux/spi/spi.h> |
| 15 | #include <linux/slab.h> | ||
| 16 | #include <linux/sysfs.h> | 12 | #include <linux/sysfs.h> |
| 17 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 18 | 14 | ||
| 19 | #include <linux/iio/iio.h> | 15 | #include <linux/iio/iio.h> |
| 20 | #include <linux/iio/sysfs.h> | 16 | #include <linux/iio/sysfs.h> |
| 21 | #include <linux/iio/buffer.h> | ||
| 22 | #include <linux/iio/imu/adis.h> | 17 | #include <linux/iio/imu/adis.h> |
| 23 | 18 | ||
| 24 | #include <linux/debugfs.h> | 19 | #include <linux/debugfs.h> |
| @@ -223,13 +218,12 @@ static ssize_t adis16136_read_frequency(struct device *dev, · 198 unmodified lines | |||
| 223 | { | 218 | { |
| 224 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 219 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 225 | struct adis16136 *adis16136 = iio_priv(indio_dev); | 220 | struct adis16136 *adis16136 = iio_priv(indio_dev); |
| 226 | struct mutex *slock = &adis16136->adis.state_lock; | ||
| 227 | unsigned int freq; | 221 | unsigned int freq; |
| 228 | int ret; | 222 | int ret; |
| 229 | 223 | ||
| 230 | mutex_lock(slock); | 224 | adis_dev_lock(&adis16136->adis); |
| 231 | ret = __adis16136_get_freq(adis16136, &freq); | 225 | ret = __adis16136_get_freq(adis16136, &freq); |
| 232 | mutex_unlock(slock); | 226 | adis_dev_unlock(&adis16136->adis); |
| 233 | if (ret) | 227 | if (ret) |
| 234 | return ret; | 228 | return ret; |
| 235 | 229 | ||
| @@ -254,11 +248,10 @@ static const unsigned adis16136_3db_divisors[] = { · 18 unmodified lines | |||
| 254 | static int adis16136_set_filter(struct iio_dev *indio_dev, int val) | 248 | static int adis16136_set_filter(struct iio_dev *indio_dev, int val) |
| 255 | { | 249 | { |
| 256 | struct adis16136 *adis16136 = iio_priv(indio_dev); | 250 | struct adis16136 *adis16136 = iio_priv(indio_dev); |
| 257 | struct mutex *slock = &adis16136->adis.state_lock; | ||
| 258 | unsigned int freq; | 251 | unsigned int freq; |
| 259 | int i, ret; | 252 | int i, ret; |
| 260 | 253 | ||
| 261 | mutex_lock(slock); | 254 | adis_dev_lock(&adis16136->adis); |
| 262 | ret = __adis16136_get_freq(adis16136, &freq); | 255 | ret = __adis16136_get_freq(adis16136, &freq); |
| 263 | if (ret) | 256 | if (ret) |
| 264 | goto out_unlock; | 257 | goto out_unlock; |
| @@ -270,7 +263,7 @@ static int adis16136_set_filter(struct iio_dev *indio_dev, int val) · 5 unmodified lines | |||
| 270 | 263 | ||
| 271 | ret = __adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i); | 264 | ret = __adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i); |
| 272 | out_unlock: | 265 | out_unlock: |
| 273 | mutex_unlock(slock); | 266 | adis_dev_unlock(&adis16136->adis); |
| 274 | 267 | ||
| 275 | return ret; | 268 | return ret; |
| 276 | } | 269 | } |
| @@ -278,12 +271,11 @@ out_unlock: · 1 unmodified line | |||
| 278 | static int adis16136_get_filter(struct iio_dev *indio_dev, int *val) | 271 | static int adis16136_get_filter(struct iio_dev *indio_dev, int *val) |
| 279 | { | 272 | { |
| 280 | struct adis16136 *adis16136 = iio_priv(indio_dev); | 273 | struct adis16136 *adis16136 = iio_priv(indio_dev); |
| 281 | struct mutex *slock = &adis16136->adis.state_lock; | ||
| 282 | unsigned int freq; | 274 | unsigned int freq; |
| 283 | uint16_t val16; | 275 | uint16_t val16; |
| 284 | int ret; | 276 | int ret; |
| 285 | 277 | ||
| 286 | mutex_lock(slock); | 278 | adis_dev_lock(&adis16136->adis); |
| 287 | 279 | ||
| 288 | ret = __adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, | 280 | ret = __adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, |
| 289 | &val16); | 281 | &val16); |
| @@ -297,7 +289,7 @@ static int adis16136_get_filter(struct iio_dev *indio_dev, int *val) · 7 unmodified lines | |||
| 297 | *val = freq / adis16136_3db_divisors[val16 & 0x07]; | 289 | *val = freq / adis16136_3db_divisors[val16 & 0x07]; |
| 298 | 290 | ||
| 299 | err_unlock: | 291 | err_unlock: |
| 300 | mutex_unlock(slock); | 292 | adis_dev_unlock(&adis16136->adis); |
| 301 | 293 | ||
| 302 | return ret ? ret : IIO_VAL_INT; | 294 | return ret ? ret : IIO_VAL_INT; |
| 303 | } | 295 | } |
| @@ -5,17 +5,12 @@ · 4 unmodified lines | |||
| 5 | * Copyright 2010 Analog Devices Inc. | 5 | * Copyright 2010 Analog Devices Inc. |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include <linux/interrupt.h> | ||
| 9 | #include <linux/mutex.h> | ||
| 10 | #include <linux/device.h> | 8 | #include <linux/device.h> |
| 11 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 12 | #include <linux/spi/spi.h> | 10 | #include <linux/spi/spi.h> |
| 13 | #include <linux/sysfs.h> | ||
| 14 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 15 | 12 | ||
| 16 | #include <linux/iio/iio.h> | 13 | #include <linux/iio/iio.h> |
| 17 | #include <linux/iio/sysfs.h> | ||
| 18 | #include <linux/iio/buffer.h> | ||
| 19 | #include <linux/iio/imu/adis.h> | 14 | #include <linux/iio/imu/adis.h> |
| 20 | 15 | ||
| 21 | #define ADIS16260_STARTUP_DELAY 220 /* ms */ | 16 | #define ADIS16260_STARTUP_DELAY 220 /* ms */ |
| @@ -293,7 +288,7 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, · 271 unmodified lines | |||
| 293 | addr = adis16260_addresses[chan->scan_index][1]; | 288 | addr = adis16260_addresses[chan->scan_index][1]; |
| 294 | return adis_write_reg_16(adis, addr, val); | 289 | return adis_write_reg_16(adis, addr, val); |
| 295 | case IIO_CHAN_INFO_SAMP_FREQ: | 290 | case IIO_CHAN_INFO_SAMP_FREQ: |
| 296 | mutex_lock(&adis->state_lock); | 291 | adis_dev_lock(adis); |
| 297 | if (spi_get_device_id(adis->spi)->driver_data) | 292 | if (spi_get_device_id(adis->spi)->driver_data) |
| 298 | t = 256 / val; | 293 | t = 256 / val; |
| 299 | else | 294 | else |
| @@ -310,7 +305,7 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, · 10 unmodified lines | |||
| 310 | adis->spi->max_speed_hz = ADIS16260_SPI_FAST; | 305 | adis->spi->max_speed_hz = ADIS16260_SPI_FAST; |
| 311 | ret = __adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t); | 306 | ret = __adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t); |
| 312 | 307 | ||
| 313 | mutex_unlock(&adis->state_lock); | 308 | adis_dev_unlock(adis); |
| 314 | return ret; | 309 | return ret; |
| 315 | } | 310 | } |
| 316 | return -EINVAL; | 311 | return -EINVAL; |
| @@ -589,7 +589,7 @@ static int adxrs290_probe_trigger(struct iio_dev *indio_dev) · 588 unmodified lines | |||
| 589 | 589 | ||
| 590 | st->dready_trig = devm_iio_trigger_alloc(&st->spi->dev, "%s-dev%d", | 590 | st->dready_trig = devm_iio_trigger_alloc(&st->spi->dev, "%s-dev%d", |
| 591 | indio_dev->name, | 591 | indio_dev->name, |
| 592 | indio_dev->id); | 592 | iio_device_id(indio_dev)); |
| 593 | if (!st->dready_trig) | 593 | if (!st->dready_trig) |
| 594 | return -ENOMEM; | 594 | return -ENOMEM; |
| 595 | 595 | ||
| @@ -98,7 +98,11 @@ struct bmg160_data { · 97 unmodified lines | |||
| 98 | struct iio_trigger *motion_trig; | 98 | struct iio_trigger *motion_trig; |
| 99 | struct iio_mount_matrix orientation; | 99 | struct iio_mount_matrix orientation; |
| 100 | struct mutex mutex; | 100 | struct mutex mutex; |
| 101 | s16 buffer[8]; | 101 | /* Ensure naturally aligned timestamp */ |
| 102 | struct { | ||
| 103 | s16 chans[3]; | ||
| 104 | s64 timestamp __aligned(8); | ||
| 105 | } scan; | ||
| 102 | u32 dps_range; | 106 | u32 dps_range; |
| 103 | int ev_enable_state; | 107 | int ev_enable_state; |
| 104 | int slope_thres; | 108 | int slope_thres; |
| @@ -882,12 +886,12 @@ static irqreturn_t bmg160_trigger_handler(int irq, void *p) · 777 unmodified lines | |||
| 882 | 886 | ||
| 883 | mutex_lock(&data->mutex); | 887 | mutex_lock(&data->mutex); |
| 884 | ret = regmap_bulk_read(data->regmap, BMG160_REG_XOUT_L, | 888 | ret = regmap_bulk_read(data->regmap, BMG160_REG_XOUT_L, |
| 885 | data->buffer, AXIS_MAX * 2); | 889 | data->scan.chans, AXIS_MAX * 2); |
| 886 | mutex_unlock(&data->mutex); | 890 | mutex_unlock(&data->mutex); |
| 887 | if (ret < 0) | 891 | if (ret < 0) |
| 888 | goto err; | 892 | goto err; |
| 889 | 893 | ||
| 890 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 894 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, |
| 891 | pf->timestamp); | 895 | pf->timestamp); |
| 892 | err: | 896 | err: |
| 893 | iio_trigger_notify_done(indio_dev->trig); | 897 | iio_trigger_notify_done(indio_dev->trig); |
| @@ -1102,8 +1106,7 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, · 208 unmodified lines | |||
| 1102 | if (ret) | 1106 | if (ret) |
| 1103 | return ret; | 1107 | return ret; |
| 1104 | 1108 | ||
| 1105 | ret = iio_read_mount_matrix(dev, "mount-matrix", | 1109 | ret = iio_read_mount_matrix(dev, &data->orientation); |
| 1106 | &data->orientation); | ||
| 1107 | if (ret) | 1110 | if (ret) |
| 1108 | return ret; | 1111 | return ret; |
| 1109 | 1112 | ||
| @@ -1137,14 +1140,14 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, · 27 unmodified lines | |||
| 1137 | data->dready_trig = devm_iio_trigger_alloc(dev, | 1140 | data->dready_trig = devm_iio_trigger_alloc(dev, |
| 1138 | "%s-dev%d", | 1141 | "%s-dev%d", |
| 1139 | indio_dev->name, | 1142 | indio_dev->name, |
| 1140 | indio_dev->id); | 1143 | iio_device_id(indio_dev)); |
| 1141 | if (!data->dready_trig) | 1144 | if (!data->dready_trig) |
| 1142 | return -ENOMEM; | 1145 | return -ENOMEM; |
| 1143 | 1146 | ||
| 1144 | data->motion_trig = devm_iio_trigger_alloc(dev, | 1147 | data->motion_trig = devm_iio_trigger_alloc(dev, |
| 1145 | "%s-any-motion-dev%d", | 1148 | "%s-any-motion-dev%d", |
| 1146 | indio_dev->name, | 1149 | indio_dev->name, |
| 1147 | indio_dev->id); | 1150 | iio_device_id(indio_dev)); |
| 1148 | if (!data->motion_trig) | 1151 | if (!data->motion_trig) |
| 1149 | return -ENOMEM; | 1152 | return -ENOMEM; |
| 1150 | 1153 | ||
| @@ -366,14 +366,7 @@ out_unlock: · 365 unmodified lines | |||
| 366 | 366 | ||
| 367 | static int fxas21002c_pm_get(struct fxas21002c_data *data) | 367 | static int fxas21002c_pm_get(struct fxas21002c_data *data) |
| 368 | { | 368 | { |
| 369 | struct device *dev = regmap_get_device(data->regmap); | 369 | return pm_runtime_resume_and_get(regmap_get_device(data->regmap)); |
| 370 | int ret; | ||
| 371 | |||
| 372 | ret = pm_runtime_get_sync(dev); | ||
| 373 | if (ret < 0) | ||
| 374 | pm_runtime_put_noidle(dev); | ||
| 375 | |||
| 376 | return ret; | ||
| 377 | } | 370 | } |
| 378 | 371 | ||
| 379 | static int fxas21002c_pm_put(struct fxas21002c_data *data) | 372 | static int fxas21002c_pm_put(struct fxas21002c_data *data) |
| @@ -854,7 +847,7 @@ static int fxas21002c_trigger_probe(struct fxas21002c_data *data) · 474 unmodified lines | |||
| 854 | 847 | ||
| 855 | data->dready_trig = devm_iio_trigger_alloc(dev, "%s-dev%d", | 848 | data->dready_trig = devm_iio_trigger_alloc(dev, "%s-dev%d", |
| 856 | indio_dev->name, | 849 | indio_dev->name, |
| 857 | indio_dev->id); | 850 | iio_device_id(indio_dev)); |
| 858 | if (!data->dready_trig) | 851 | if (!data->dready_trig) |
| 859 | return -ENOMEM; | 852 | return -ENOMEM; |
| 860 | 853 | ||
| @@ -1004,7 +997,6 @@ int fxas21002c_core_probe(struct device *dev, struct regmap *regmap, int irq, · 143 unmodified lines | |||
| 1004 | pm_disable: | 997 | pm_disable: |
| 1005 | pm_runtime_disable(dev); | 998 | pm_runtime_disable(dev); |
| 1006 | pm_runtime_set_suspended(dev); | 999 | pm_runtime_set_suspended(dev); |
| 1007 | pm_runtime_put_noidle(dev); | ||
| 1008 | 1000 | ||
| 1009 | return ret; | 1001 | return ret; |
| 1010 | } | 1002 | } |
| @@ -1018,7 +1010,6 @@ void fxas21002c_core_remove(struct device *dev) · 7 unmodified lines | |||
| 1018 | 1010 | ||
| 1019 | pm_runtime_disable(dev); | 1011 | pm_runtime_disable(dev); |
| 1020 | pm_runtime_set_suspended(dev); | 1012 | pm_runtime_set_suspended(dev); |
| 1021 | pm_runtime_put_noidle(dev); | ||
| 1022 | } | 1013 | } |
| 1023 | EXPORT_SYMBOL_GPL(fxas21002c_core_remove); | 1014 | EXPORT_SYMBOL_GPL(fxas21002c_core_remove); |
| 1024 | 1015 | ||
| @@ -6,13 +6,10 @@ · 5 unmodified lines | |||
| 6 | #include <linux/device.h> | 6 | #include <linux/device.h> |
| 7 | #include <linux/platform_device.h> | 7 | #include <linux/platform_device.h> |
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/interrupt.h> | 9 | #include <linux/mod_devicetable.h> |
| 10 | #include <linux/irq.h> | ||
| 11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
| 12 | #include <linux/delay.h> | ||
| 13 | #include <linux/hid-sensor-hub.h> | 11 | #include <linux/hid-sensor-hub.h> |
| 14 | #include <linux/iio/iio.h> | 12 | #include <linux/iio/iio.h> |
| 15 | #include <linux/iio/sysfs.h> | ||
| 16 | #include <linux/iio/buffer.h> | 13 | #include <linux/iio/buffer.h> |
| 17 | #include "../common/hid-sensors/hid-sensor-trigger.h" | 14 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 18 | 15 | ||
| @@ -400,3 +397,4 @@ module_platform_driver(hid_gyro_3d_platform_driver); · 381 unmodified lines | |||
| 400 | MODULE_DESCRIPTION("HID Sensor Gyroscope 3D"); | 397 | MODULE_DESCRIPTION("HID Sensor Gyroscope 3D"); |
| 401 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); | 398 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); |
| 402 | MODULE_LICENSE("GPL"); | 399 | MODULE_LICENSE("GPL"); |
| 400 | MODULE_IMPORT_NS(IIO_HID); | ||
| @@ -114,7 +114,7 @@ int itg3200_probe_trigger(struct iio_dev *indio_dev) · 113 unmodified lines | |||
| 114 | struct itg3200 *st = iio_priv(indio_dev); | 114 | struct itg3200 *st = iio_priv(indio_dev); |
| 115 | 115 | ||
| 116 | st->trig = iio_trigger_alloc(&st->i2c->dev, "%s-dev%d", indio_dev->name, | 116 | st->trig = iio_trigger_alloc(&st->i2c->dev, "%s-dev%d", indio_dev->name, |
| 117 | indio_dev->id); | 117 | iio_device_id(indio_dev)); |
| 118 | if (!st->trig) | 118 | if (!st->trig) |
| 119 | return -ENOMEM; | 119 | return -ENOMEM; |
| 120 | 120 | ||
| @@ -308,8 +308,7 @@ static int itg3200_probe(struct i2c_client *client, · 307 unmodified lines | |||
| 308 | 308 | ||
| 309 | st = iio_priv(indio_dev); | 309 | st = iio_priv(indio_dev); |
| 310 | 310 | ||
| 311 | ret = iio_read_mount_matrix(&client->dev, "mount-matrix", | 311 | ret = iio_read_mount_matrix(&client->dev, &st->orientation); |
| 312 | &st->orientation); | ||
| 313 | if (ret) | 312 | if (ret) |
| 314 | return ret; | 313 | return ret; |
| 315 | 314 | ||
| @@ -1058,7 +1058,7 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq) · 1057 unmodified lines | |||
| 1058 | mpu3050->trig = devm_iio_trigger_alloc(&indio_dev->dev, | 1058 | mpu3050->trig = devm_iio_trigger_alloc(&indio_dev->dev, |
| 1059 | "%s-dev%d", | 1059 | "%s-dev%d", |
| 1060 | indio_dev->name, | 1060 | indio_dev->name, |
| 1061 | indio_dev->id); | 1061 | iio_device_id(indio_dev)); |
| 1062 | if (!mpu3050->trig) | 1062 | if (!mpu3050->trig) |
| 1063 | return -ENOMEM; | 1063 | return -ENOMEM; |
| 1064 | 1064 | ||
| @@ -1164,7 +1164,7 @@ int mpu3050_common_probe(struct device *dev, · 99 unmodified lines | |||
| 1164 | mpu3050->divisor = 99; | 1164 | mpu3050->divisor = 99; |
| 1165 | 1165 | ||
| 1166 | /* Read the mounting matrix, if present */ | 1166 | /* Read the mounting matrix, if present */ |
| 1167 | ret = iio_read_mount_matrix(dev, "mount-matrix", &mpu3050->orientation); | 1167 | ret = iio_read_mount_matrix(dev, &mpu3050->orientation); |
| 1168 | if (ret) | 1168 | if (ret) |
| 1169 | return ret; | 1169 | return ret; |
| 1170 | 1170 | ||
| @@ -24,18 +24,6 @@ · 23 unmodified lines | |||
| 24 | #define LSM330_GYRO_DEV_NAME "lsm330_gyro" | 24 | #define LSM330_GYRO_DEV_NAME "lsm330_gyro" |
| 25 | #define LSM9DS0_GYRO_DEV_NAME "lsm9ds0_gyro" | 25 | #define LSM9DS0_GYRO_DEV_NAME "lsm9ds0_gyro" |
| 26 | 26 | ||
| 27 | /** | ||
| 28 | * struct st_sensors_platform_data - gyro platform data | ||
| 29 | * @drdy_int_pin: DRDY on gyros is available only on INT2 pin. | ||
| 30 | */ | ||
| 31 | static __maybe_unused const struct st_sensors_platform_data gyro_pdata = { | ||
| 32 | .drdy_int_pin = 2, | ||
| 33 | }; | ||
| 34 | |||
| 35 | const struct st_sensor_settings *st_gyro_get_settings(const char *name); | ||
| 36 | int st_gyro_common_probe(struct iio_dev *indio_dev); | ||
| 37 | void st_gyro_common_remove(struct iio_dev *indio_dev); | ||
| 38 | |||
| 39 | #ifdef CONFIG_IIO_BUFFER | 27 | #ifdef CONFIG_IIO_BUFFER |
| 40 | int st_gyro_allocate_ring(struct iio_dev *indio_dev); | 28 | int st_gyro_allocate_ring(struct iio_dev *indio_dev); |
| 41 | void st_gyro_deallocate_ring(struct iio_dev *indio_dev); | 29 | void st_gyro_deallocate_ring(struct iio_dev *indio_dev); |
| @@ -37,19 +37,36 @@ · 36 unmodified lines | |||
| 37 | #define ST_GYRO_FS_AVL_500DPS 500 | 37 | #define ST_GYRO_FS_AVL_500DPS 500 |
| 38 | #define ST_GYRO_FS_AVL_2000DPS 2000 | 38 | #define ST_GYRO_FS_AVL_2000DPS 2000 |
| 39 | 39 | ||
| 40 | static const struct iio_mount_matrix * | ||
| 41 | st_gyro_get_mount_matrix(const struct iio_dev *indio_dev, | ||
| 42 | const struct iio_chan_spec *chan) | ||
| 43 | { | ||
| 44 | struct st_sensor_data *gdata = iio_priv(indio_dev); | ||
| 45 | |||
| 46 | return &gdata->mount_matrix; | ||
| 47 | } | ||
| 48 | |||
| 49 | static const struct iio_chan_spec_ext_info st_gyro_mount_matrix_ext_info[] = { | ||
| 50 | IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_gyro_get_mount_matrix), | ||
| 51 | { } | ||
| 52 | }; | ||
| 53 | |||
| 40 | static const struct iio_chan_spec st_gyro_16bit_channels[] = { | 54 | static const struct iio_chan_spec st_gyro_16bit_channels[] = { |
| 41 | ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, | 55 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL, |
| 42 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 56 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 43 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, | 57 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, |
| 44 | ST_GYRO_DEFAULT_OUT_X_L_ADDR), | 58 | ST_GYRO_DEFAULT_OUT_X_L_ADDR, |
| 45 | ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, | 59 | st_gyro_mount_matrix_ext_info), |
| 60 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL, | ||
| 46 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 61 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 47 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, | 62 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, |
| 48 | ST_GYRO_DEFAULT_OUT_Y_L_ADDR), | 63 | ST_GYRO_DEFAULT_OUT_Y_L_ADDR, |
| 49 | ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, | 64 | st_gyro_mount_matrix_ext_info), |
| 65 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_ANGL_VEL, | ||
| 50 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 66 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 51 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, | 67 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, |
| 52 | ST_GYRO_DEFAULT_OUT_Z_L_ADDR), | 68 | ST_GYRO_DEFAULT_OUT_Z_L_ADDR, |
| 69 | st_gyro_mount_matrix_ext_info), | ||
| 53 | IIO_CHAN_SOFT_TIMESTAMP(3) | 70 | IIO_CHAN_SOFT_TIMESTAMP(3) |
| 54 | }; | 71 | }; |
| 55 | 72 | ||
| @@ -357,6 +374,11 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { · 301 unmodified lines | |||
| 357 | }, | 374 | }, |
| 358 | }; | 375 | }; |
| 359 | 376 | ||
| 377 | /* DRDY on gyros is available only on INT2 pin */ | ||
| 378 | static const struct st_sensors_platform_data gyro_pdata = { | ||
| 379 | .drdy_int_pin = 2, | ||
| 380 | }; | ||
| 381 | |||
| 360 | static int st_gyro_read_raw(struct iio_dev *indio_dev, | 382 | static int st_gyro_read_raw(struct iio_dev *indio_dev, |
| 361 | struct iio_chan_spec const *ch, int *val, | 383 | struct iio_chan_spec const *ch, int *val, |
| 362 | int *val2, long mask) | 384 | int *val2, long mask) |
| @@ -466,18 +488,18 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) · 103 unmodified lines | |||
| 466 | indio_dev->modes = INDIO_DIRECT_MODE; | 488 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 467 | indio_dev->info = &gyro_info; | 489 | indio_dev->info = &gyro_info; |
| 468 | 490 | ||
| 469 | err = st_sensors_power_enable(indio_dev); | ||
| 470 | if (err) | ||
| 471 | return err; | ||
| 472 | |||
| 473 | err = st_sensors_verify_id(indio_dev); | 491 | err = st_sensors_verify_id(indio_dev); |
| 474 | if (err < 0) | 492 | if (err < 0) |
| 475 | goto st_gyro_power_off; | 493 | return err; |
| 476 | 494 | ||
| 477 | gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS; | 495 | gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS; |
| 478 | indio_dev->channels = gdata->sensor_settings->ch; | 496 | indio_dev->channels = gdata->sensor_settings->ch; |
| 479 | indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; | 497 | indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; |
| 480 | 498 | ||
| 499 | err = iio_read_mount_matrix(gdata->dev, &gdata->mount_matrix); | ||
| 500 | if (err) | ||
| 501 | return err; | ||
| 502 | |||
| 481 | gdata->current_fullscale = &gdata->sensor_settings->fs.fs_avl[0]; | 503 | gdata->current_fullscale = &gdata->sensor_settings->fs.fs_avl[0]; |
| 482 | gdata->odr = gdata->sensor_settings->odr.odr_avl[0].hz; | 504 | gdata->odr = gdata->sensor_settings->odr.odr_avl[0].hz; |
| 483 | 505 | ||
| @@ -485,11 +507,11 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) · 1 unmodified line | |||
| 485 | 507 | ||
| 486 | err = st_sensors_init_sensor(indio_dev, pdata); | 508 | err = st_sensors_init_sensor(indio_dev, pdata); |
| 487 | if (err < 0) | 509 | if (err < 0) |
| 488 | goto st_gyro_power_off; | 510 | return err; |
| 489 | 511 | ||
| 490 | err = st_gyro_allocate_ring(indio_dev); | 512 | err = st_gyro_allocate_ring(indio_dev); |
| 491 | if (err < 0) | 513 | if (err < 0) |
| 492 | goto st_gyro_power_off; | 514 | return err; |
| 493 | 515 | ||
| 494 | if (gdata->irq > 0) { | 516 | if (gdata->irq > 0) { |
| 495 | err = st_sensors_allocate_trigger(indio_dev, | 517 | err = st_sensors_allocate_trigger(indio_dev, |
| @@ -512,9 +534,6 @@ st_gyro_device_register_error: · 16 unmodified lines | |||
| 512 | st_sensors_deallocate_trigger(indio_dev); | 534 | st_sensors_deallocate_trigger(indio_dev); |
| 513 | st_gyro_probe_trigger_error: | 535 | st_gyro_probe_trigger_error: |
| 514 | st_gyro_deallocate_ring(indio_dev); | 536 | st_gyro_deallocate_ring(indio_dev); |
| 515 | st_gyro_power_off: | ||
| 516 | st_sensors_power_disable(indio_dev); | ||
| 517 | |||
| 518 | return err; | 537 | return err; |
| 519 | } | 538 | } |
| 520 | EXPORT_SYMBOL(st_gyro_common_probe); | 539 | EXPORT_SYMBOL(st_gyro_common_probe); |
| @@ -523,8 +542,6 @@ void st_gyro_common_remove(struct iio_dev *indio_dev) · 2 unmodified lines | |||
| 523 | { | 542 | { |
| 524 | struct st_sensor_data *gdata = iio_priv(indio_dev); | 543 | struct st_sensor_data *gdata = iio_priv(indio_dev); |
| 525 | 544 | ||
| 526 | st_sensors_power_disable(indio_dev); | ||
| 527 | |||
| 528 | iio_device_unregister(indio_dev); | 545 | iio_device_unregister(indio_dev); |
| 529 | if (gdata->irq > 0) | 546 | if (gdata->irq > 0) |
| 530 | st_sensors_deallocate_trigger(indio_dev); | 547 | st_sensors_deallocate_trigger(indio_dev); |
| @@ -86,16 +86,29 @@ static int st_gyro_i2c_probe(struct i2c_client *client, · 85 unmodified lines | |||
| 86 | if (err < 0) | 86 | if (err < 0) |
| 87 | return err; | 87 | return err; |
| 88 | 88 | ||
| 89 | err = st_sensors_power_enable(indio_dev); | ||
| 90 | if (err) | ||
| 91 | return err; | ||
| 92 | |||
| 89 | err = st_gyro_common_probe(indio_dev); | 93 | err = st_gyro_common_probe(indio_dev); |
| 90 | if (err < 0) | 94 | if (err < 0) |
| 91 | return err; | 95 | goto st_gyro_power_off; |
| 92 | 96 | ||
| 93 | return 0; | 97 | return 0; |
| 98 | |||
| 99 | st_gyro_power_off: | ||
| 100 | st_sensors_power_disable(indio_dev); | ||
| 101 | |||
| 102 | return err; | ||
| 94 | } | 103 | } |
| 95 | 104 | ||
| 96 | static int st_gyro_i2c_remove(struct i2c_client *client) | 105 | static int st_gyro_i2c_remove(struct i2c_client *client) |
| 97 | { | 106 | { |
| 98 | st_gyro_common_remove(i2c_get_clientdata(client)); | 107 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 108 | |||
| 109 | st_sensors_power_disable(indio_dev); | ||
| 110 | |||
| 111 | st_gyro_common_remove(indio_dev); | ||
| 99 | 112 | ||
| 100 | return 0; | 113 | return 0; |
| 101 | } | 114 | } |
| @@ -90,16 +90,29 @@ static int st_gyro_spi_probe(struct spi_device *spi) · 89 unmodified lines | |||
| 90 | if (err < 0) | 90 | if (err < 0) |
| 91 | return err; | 91 | return err; |
| 92 | 92 | ||
| 93 | err = st_sensors_power_enable(indio_dev); | ||
| 94 | if (err) | ||
| 95 | return err; | ||
| 96 | |||
| 93 | err = st_gyro_common_probe(indio_dev); | 97 | err = st_gyro_common_probe(indio_dev); |
| 94 | if (err < 0) | 98 | if (err < 0) |
| 95 | return err; | 99 | goto st_gyro_power_off; |
| 96 | 100 | ||
| 97 | return 0; | 101 | return 0; |
| 102 | |||
| 103 | st_gyro_power_off: | ||
| 104 | st_sensors_power_disable(indio_dev); | ||
| 105 | |||
| 106 | return err; | ||
| 98 | } | 107 | } |
| 99 | 108 | ||
| 100 | static int st_gyro_spi_remove(struct spi_device *spi) | 109 | static int st_gyro_spi_remove(struct spi_device *spi) |
| 101 | { | 110 | { |
| 102 | st_gyro_common_remove(spi_get_drvdata(spi)); | 111 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
| 112 | |||
| 113 | st_sensors_power_disable(indio_dev); | ||
| 114 | |||
| 115 | st_gyro_common_remove(indio_dev); | ||
| 103 | 116 | ||
| 104 | return 0; | 117 | return 0; |
| 105 | } | 118 | } |
| @@ -521,7 +521,7 @@ static int afe4403_probe(struct spi_device *spi) · 520 unmodified lines | |||
| 521 | afe->trig = devm_iio_trigger_alloc(afe->dev, | 521 | afe->trig = devm_iio_trigger_alloc(afe->dev, |
| 522 | "%s-dev%d", | 522 | "%s-dev%d", |
| 523 | indio_dev->name, | 523 | indio_dev->name, |
| 524 | indio_dev->id); | 524 | iio_device_id(indio_dev)); |
| 525 | if (!afe->trig) { | 525 | if (!afe->trig) { |
| 526 | dev_err(afe->dev, "Unable to allocate IIO trigger\n"); | 526 | dev_err(afe->dev, "Unable to allocate IIO trigger\n"); |
| 527 | ret = -ENOMEM; | 527 | ret = -ENOMEM; |
| @@ -528,7 +528,7 @@ static int afe4404_probe(struct i2c_client *client, · 527 unmodified lines | |||
| 528 | afe->trig = devm_iio_trigger_alloc(afe->dev, | 528 | afe->trig = devm_iio_trigger_alloc(afe->dev, |
| 529 | "%s-dev%d", | 529 | "%s-dev%d", |
| 530 | indio_dev->name, | 530 | indio_dev->name, |
| 531 | indio_dev->id); | 531 | iio_device_id(indio_dev)); |
| 532 | if (!afe->trig) { | 532 | if (!afe->trig) { |
| 533 | dev_err(afe->dev, "Unable to allocate IIO trigger\n"); | 533 | dev_err(afe->dev, "Unable to allocate IIO trigger\n"); |
| 534 | ret = -ENOMEM; | 534 | ret = -ENOMEM; |
| @@ -7,7 +7,6 @@ · 6 unmodified lines | |||
| 7 | * 7-bit I2C address: 0x5C. | 7 | * 7-bit I2C address: 0x5C. |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/acpi.h> | ||
| 11 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
| 12 | #include <linux/i2c.h> | 11 | #include <linux/i2c.h> |
| 13 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| @@ -33,7 +32,11 @@ · 19 unmodified lines | |||
| 33 | struct am2315_data { | 32 | struct am2315_data { |
| 34 | struct i2c_client *client; | 33 | struct i2c_client *client; |
| 35 | struct mutex lock; | 34 | struct mutex lock; |
| 36 | s16 buffer[8]; /* 2x16-bit channels + 2x16 padding + 4x16 timestamp */ | 35 | /* Ensure timestamp is naturally aligned */ |
| 36 | struct { | ||
| 37 | s16 chans[2]; | ||
| 38 | s64 timestamp __aligned(8); | ||
| 39 | } scan; | ||
| 37 | }; | 40 | }; |
| 38 | 41 | ||
| 39 | struct am2315_sensor_data { | 42 | struct am2315_sensor_data { |
| @@ -167,20 +170,20 @@ static irqreturn_t am2315_trigger_handler(int irq, void *p) · 127 unmodified lines | |||
| 167 | 170 | ||
| 168 | mutex_lock(&data->lock); | 171 | mutex_lock(&data->lock); |
| 169 | if (*(indio_dev->active_scan_mask) == AM2315_ALL_CHANNEL_MASK) { | 172 | if (*(indio_dev->active_scan_mask) == AM2315_ALL_CHANNEL_MASK) { |
| 170 | data->buffer[0] = sensor_data.hum_data; | 173 | data->scan.chans[0] = sensor_data.hum_data; |
| 171 | data->buffer[1] = sensor_data.temp_data; | 174 | data->scan.chans[1] = sensor_data.temp_data; |
| 172 | } else { | 175 | } else { |
| 173 | i = 0; | 176 | i = 0; |
| 174 | for_each_set_bit(bit, indio_dev->active_scan_mask, | 177 | for_each_set_bit(bit, indio_dev->active_scan_mask, |
| 175 | indio_dev->masklength) { | 178 | indio_dev->masklength) { |
| 176 | data->buffer[i] = (bit ? sensor_data.temp_data : | 179 | data->scan.chans[i] = (bit ? sensor_data.temp_data : |
| 177 | sensor_data.hum_data); | 180 | sensor_data.hum_data); |
| 178 | i++; | 181 | i++; |
| 179 | } | 182 | } |
| 180 | } | 183 | } |
| 181 | mutex_unlock(&data->lock); | 184 | mutex_unlock(&data->lock); |
| 182 | 185 | ||
| 183 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 186 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, |
| 184 | pf->timestamp); | 187 | pf->timestamp); |
| 185 | err: | 188 | err: |
| 186 | iio_trigger_notify_done(indio_dev->trig); | 189 | iio_trigger_notify_done(indio_dev->trig); |
| @@ -256,17 +259,9 @@ static const struct i2c_device_id am2315_i2c_id[] = { · 69 unmodified lines | |||
| 256 | }; | 259 | }; |
| 257 | MODULE_DEVICE_TABLE(i2c, am2315_i2c_id); | 260 | MODULE_DEVICE_TABLE(i2c, am2315_i2c_id); |
| 258 | 261 | ||
| 259 | static const struct acpi_device_id am2315_acpi_id[] = { | ||
| 260 | {"AOS2315", 0}, | ||
| 261 | {} | ||
| 262 | }; | ||
| 263 | |||
| 264 | MODULE_DEVICE_TABLE(acpi, am2315_acpi_id); | ||
| 265 | |||
| 266 | static struct i2c_driver am2315_driver = { | 262 | static struct i2c_driver am2315_driver = { |
| 267 | .driver = { | 263 | .driver = { |
| 268 | .name = "am2315", | 264 | .name = "am2315", |
| 269 | .acpi_match_table = ACPI_PTR(am2315_acpi_id), | ||
| 270 | }, | 265 | }, |
| 271 | .probe = am2315_probe, | 266 | .probe = am2315_probe, |
| 272 | .id_table = am2315_i2c_id, | 267 | .id_table = am2315_i2c_id, |
| @@ -272,7 +272,6 @@ static int hdc2010_probe(struct i2c_client *client, · 271 unmodified lines | |||
| 272 | data->client = client; | 272 | data->client = client; |
| 273 | mutex_init(&data->lock); | 273 | mutex_init(&data->lock); |
| 274 | 274 | ||
| 275 | indio_dev->dev.parent = &client->dev; | ||
| 276 | /* | 275 | /* |
| 277 | * As DEVICE ID register does not differentiate between | 276 | * As DEVICE ID register does not differentiate between |
| 278 | * HDC2010 and HDC2080, we have the name hardcoded | 277 | * HDC2010 and HDC2080, we have the name hardcoded |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | #include <linux/iio/buffer.h> | 8 | #include <linux/iio/buffer.h> |
| 9 | #include <linux/iio/iio.h> | 9 | #include <linux/iio/iio.h> |
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/mod_devicetable.h> | ||
| 11 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
| 12 | 13 | ||
| 13 | #include "hid-sensor-trigger.h" | 14 | #include "hid-sensor-trigger.h" |
| @@ -295,3 +296,4 @@ module_platform_driver(hid_humidity_platform_driver); · 281 unmodified lines | |||
| 295 | MODULE_DESCRIPTION("HID Environmental humidity sensor"); | 296 | MODULE_DESCRIPTION("HID Environmental humidity sensor"); |
| 296 | MODULE_AUTHOR("Song Hongyan <hongyan.song@intel.com>"); | 297 | MODULE_AUTHOR("Song Hongyan <hongyan.song@intel.com>"); |
| 297 | MODULE_LICENSE("GPL v2"); | 298 | MODULE_LICENSE("GPL v2"); |
| 299 | MODULE_IMPORT_NS(IIO_HID); | ||
| @@ -94,6 +94,7 @@ config KMX61 · 93 unmodified lines | |||
| 94 | source "drivers/iio/imu/inv_icm42600/Kconfig" | 94 | source "drivers/iio/imu/inv_icm42600/Kconfig" |
| 95 | source "drivers/iio/imu/inv_mpu6050/Kconfig" | 95 | source "drivers/iio/imu/inv_mpu6050/Kconfig" |
| 96 | source "drivers/iio/imu/st_lsm6dsx/Kconfig" | 96 | source "drivers/iio/imu/st_lsm6dsx/Kconfig" |
| 97 | source "drivers/iio/imu/st_lsm9ds0/Kconfig" | ||
| 97 | 98 | ||
| 98 | endmenu | 99 | endmenu |
| 99 | 100 | ||
| @@ -26,3 +26,4 @@ obj-y += inv_mpu6050/ · 25 unmodified lines | |||
| 26 | obj-$(CONFIG_KMX61) += kmx61.o | 26 | obj-$(CONFIG_KMX61) += kmx61.o |
| 27 | 27 | ||
| 28 | obj-y += st_lsm6dsx/ | 28 | obj-y += st_lsm6dsx/ |
| 29 | obj-y += st_lsm9ds0/ | ||
| @@ -12,14 +12,10 @@ · 11 unmodified lines | |||
| 12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | #include <linux/spi/spi.h> | 14 | #include <linux/spi/spi.h> |
| 15 | #include <linux/slab.h> | ||
| 16 | #include <linux/sysfs.h> | ||
| 17 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 18 | #include <asm/unaligned.h> | 16 | #include <asm/unaligned.h> |
| 19 | 17 | ||
| 20 | #include <linux/iio/iio.h> | 18 | #include <linux/iio/iio.h> |
| 21 | #include <linux/iio/sysfs.h> | ||
| 22 | #include <linux/iio/buffer.h> | ||
| 23 | #include <linux/iio/imu/adis.h> | 19 | #include <linux/iio/imu/adis.h> |
| 24 | 20 | ||
| 25 | #define ADIS_MSC_CTRL_DATA_RDY_EN BIT(2) | 21 | #define ADIS_MSC_CTRL_DATA_RDY_EN BIT(2) |
| @@ -10,22 +10,15 @@ · 9 unmodified lines | |||
| 10 | * Copyright (c) 2011 Analog Devices Inc. | 10 | * Copyright (c) 2011 Analog Devices Inc. |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #include <linux/interrupt.h> | ||
| 14 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
| 15 | #include <linux/delay.h> | ||
| 16 | #include <linux/mutex.h> | ||
| 17 | #include <linux/device.h> | 14 | #include <linux/device.h> |
| 18 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 19 | #include <linux/spi/spi.h> | 16 | #include <linux/spi/spi.h> |
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/sysfs.h> | ||
| 22 | #include <linux/list.h> | ||
| 23 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 24 | #include <linux/debugfs.h> | 18 | #include <linux/debugfs.h> |
| 25 | #include <linux/bitops.h> | 19 | #include <linux/bitops.h> |
| 26 | 20 | ||
| 27 | #include <linux/iio/iio.h> | 21 | #include <linux/iio/iio.h> |
| 28 | #include <linux/iio/sysfs.h> | ||
| 29 | #include <linux/iio/buffer.h> | 22 | #include <linux/iio/buffer.h> |
| 30 | #include <linux/iio/trigger_consumer.h> | 23 | #include <linux/iio/trigger_consumer.h> |
| 31 | #include <linux/iio/imu/adis.h> | 24 | #include <linux/iio/imu/adis.h> |
| @@ -641,28 +634,13 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) · 609 unmodified lines | |||
| 641 | struct iio_dev *indio_dev = pf->indio_dev; | 634 | struct iio_dev *indio_dev = pf->indio_dev; |
| 642 | struct adis16400_state *st = iio_priv(indio_dev); | 635 | struct adis16400_state *st = iio_priv(indio_dev); |
| 643 | struct adis *adis = &st->adis; | 636 | struct adis *adis = &st->adis; |
| 644 | u32 old_speed_hz = st->adis.spi->max_speed_hz; | ||
| 645 | void *buffer; | 637 | void *buffer; |
| 646 | int ret; | 638 | int ret; |
| 647 | 639 | ||
| 648 | if (!adis->buffer) | ||
| 649 | return -ENOMEM; | ||
| 650 | |||
| 651 | if (!(st->variant->flags & ADIS16400_NO_BURST) && | ||
| 652 | st->adis.spi->max_speed_hz > ADIS16400_SPI_BURST) { | ||
| 653 | st->adis.spi->max_speed_hz = ADIS16400_SPI_BURST; | ||
| 654 | spi_setup(st->adis.spi); | ||
| 655 | } | ||
| 656 | |||
| 657 | ret = spi_sync(adis->spi, &adis->msg); | 640 | ret = spi_sync(adis->spi, &adis->msg); |
| 658 | if (ret) | 641 | if (ret) |
| 659 | dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret); | 642 | dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret); |
| 660 | 643 | ||
| 661 | if (!(st->variant->flags & ADIS16400_NO_BURST)) { | ||
| 662 | st->adis.spi->max_speed_hz = old_speed_hz; | ||
| 663 | spi_setup(st->adis.spi); | ||
| 664 | } | ||
| 665 | |||
| 666 | if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) | 644 | if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) |
| 667 | buffer = adis->buffer + sizeof(u16); | 645 | buffer = adis->buffer + sizeof(u16); |
| 668 | else | 646 | else |
| @@ -968,7 +946,8 @@ static const char * const adis16400_status_error_msgs[] = { · 299 unmodified lines | |||
| 968 | BIT(ADIS16400_DIAG_STAT_POWER_LOW), \ | 946 | BIT(ADIS16400_DIAG_STAT_POWER_LOW), \ |
| 969 | .timeouts = (_timeouts), \ | 947 | .timeouts = (_timeouts), \ |
| 970 | .burst_reg_cmd = ADIS16400_GLOB_CMD, \ | 948 | .burst_reg_cmd = ADIS16400_GLOB_CMD, \ |
| 971 | .burst_len = (_burst_len) \ | 949 | .burst_len = (_burst_len), \ |
| 950 | .burst_max_speed_hz = ADIS16400_SPI_BURST \ | ||
| 972 | } | 951 | } |
| 973 | 952 | ||
| 974 | static const struct adis_timeout adis16300_timeouts = { | 953 | static const struct adis_timeout adis16300_timeouts = { |
| @@ -1178,8 +1157,6 @@ static int adis16400_probe(struct spi_device *spi) · 203 unmodified lines | |||
| 1178 | return -ENOMEM; | 1157 | return -ENOMEM; |
| 1179 | 1158 | ||
| 1180 | st = iio_priv(indio_dev); | 1159 | st = iio_priv(indio_dev); |
| 1181 | /* this is only used for removal purposes */ | ||
| 1182 | spi_set_drvdata(spi, indio_dev); | ||
| 1183 | 1160 | ||
| 1184 | /* setup the industrialio driver allocated elements */ | 1161 | /* setup the industrialio driver allocated elements */ |
| 1185 | st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data]; | 1162 | st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data]; |
| @@ -5,7 +5,6 @@ · 4 unmodified lines | |||
| 5 | * Copyright 2019 Analog Devices Inc. | 5 | * Copyright 2019 Analog Devices Inc. |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include <linux/delay.h> | ||
| 9 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 10 | #include <linux/spi/spi.h> | 9 | #include <linux/spi/spi.h> |
| 11 | 10 | ||
| @@ -388,8 +387,6 @@ static int adis16460_probe(struct spi_device *spi) · 376 unmodified lines | |||
| 388 | if (indio_dev == NULL) | 387 | if (indio_dev == NULL) |
| 389 | return -ENOMEM; | 388 | return -ENOMEM; |
| 390 | 389 | ||
| 391 | spi_set_drvdata(spi, indio_dev); | ||
| 392 | |||
| 393 | st = iio_priv(indio_dev); | 390 | st = iio_priv(indio_dev); |
| 394 | 391 | ||
| 395 | st->chip_info = &adis16460_chip_info; | 392 | st->chip_info = &adis16460_chip_info; |
| @@ -14,7 +14,6 @@ · 13 unmodified lines | |||
| 14 | #include <linux/iio/buffer.h> | 14 | #include <linux/iio/buffer.h> |
| 15 | #include <linux/iio/iio.h> | 15 | #include <linux/iio/iio.h> |
| 16 | #include <linux/iio/imu/adis.h> | 16 | #include <linux/iio/imu/adis.h> |
| 17 | #include <linux/iio/sysfs.h> | ||
| 18 | #include <linux/iio/trigger_consumer.h> | 17 | #include <linux/iio/trigger_consumer.h> |
| 19 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
| 20 | #include <linux/lcm.h> | 19 | #include <linux/lcm.h> |
| @@ -645,7 +644,8 @@ static int adis16475_enable_irq(struct adis *adis, bool enable) · 624 unmodified lines | |||
| 645 | .timeouts = (_timeouts), \ | 644 | .timeouts = (_timeouts), \ |
| 646 | .burst_reg_cmd = ADIS16475_REG_GLOB_CMD, \ | 645 | .burst_reg_cmd = ADIS16475_REG_GLOB_CMD, \ |
| 647 | .burst_len = ADIS16475_BURST_MAX_DATA, \ | 646 | .burst_len = ADIS16475_BURST_MAX_DATA, \ |
| 648 | .burst_max_len = ADIS16475_BURST32_MAX_DATA \ | 647 | .burst_max_len = ADIS16475_BURST32_MAX_DATA, \ |
| 648 | .burst_max_speed_hz = ADIS16475_BURST_MAX_SPEED \ | ||
| 649 | } | 649 | } |
| 650 | 650 | ||
| 651 | static const struct adis16475_sync adis16475_sync_mode[] = { | 651 | static const struct adis16475_sync adis16475_sync_mode[] = { |
| @@ -1062,15 +1062,11 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p) · 410 unmodified lines | |||
| 1062 | bool valid; | 1062 | bool valid; |
| 1063 | /* offset until the first element after gyro and accel */ | 1063 | /* offset until the first element after gyro and accel */ |
| 1064 | const u8 offset = st->burst32 ? 13 : 7; | 1064 | const u8 offset = st->burst32 ? 13 : 7; |
| 1065 | const u32 cached_spi_speed_hz = adis->spi->max_speed_hz; | ||
| 1066 | |||
| 1067 | adis->spi->max_speed_hz = ADIS16475_BURST_MAX_SPEED; | ||
| 1068 | 1065 | ||
| 1069 | ret = spi_sync(adis->spi, &adis->msg); | 1066 | ret = spi_sync(adis->spi, &adis->msg); |
| 1070 | if (ret) | 1067 | if (ret) |
| 1071 | return ret; | 1068 | goto check_burst32; |
| 1072 | 1069 | ||
| 1073 | adis->spi->max_speed_hz = cached_spi_speed_hz; | ||
| 1074 | buffer = adis->buffer; | 1070 | buffer = adis->buffer; |
| 1075 | 1071 | ||
| 1076 | crc = be16_to_cpu(buffer[offset + 2]); | 1072 | crc = be16_to_cpu(buffer[offset + 2]); |
| @@ -1332,7 +1328,6 @@ static int adis16475_probe(struct spi_device *spi) · 255 unmodified lines | |||
| 1332 | return -ENOMEM; | 1328 | return -ENOMEM; |
| 1333 | 1329 | ||
| 1334 | st = iio_priv(indio_dev); | 1330 | st = iio_priv(indio_dev); |
| 1335 | spi_set_drvdata(spi, indio_dev); | ||
| 1336 | 1331 | ||
| 1337 | st->info = device_get_match_data(&spi->dev); | 1332 | st->info = device_get_match_data(&spi->dev); |
| 1338 | if (!st->info) | 1333 | if (!st->info) |
| @@ -9,21 +9,19 @@ · 8 unmodified lines | |||
| 9 | #include <linux/bitfield.h> | 9 | #include <linux/bitfield.h> |
| 10 | #include <linux/of_irq.h> | 10 | #include <linux/of_irq.h> |
| 11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
| 12 | #include <linux/delay.h> | ||
| 13 | #include <linux/math.h> | 12 | #include <linux/math.h> |
| 14 | #include <linux/mutex.h> | ||
| 15 | #include <linux/device.h> | 13 | #include <linux/device.h> |
| 16 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 17 | #include <linux/spi/spi.h> | 15 | #include <linux/spi/spi.h> |
| 18 | #include <linux/slab.h> | ||
| 19 | #include <linux/sysfs.h> | ||
| 20 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 21 | #include <linux/lcm.h> | 17 | #include <linux/lcm.h> |
| 18 | #include <linux/swab.h> | ||
| 19 | #include <linux/crc32.h> | ||
| 22 | 20 | ||
| 23 | #include <linux/iio/iio.h> | 21 | #include <linux/iio/iio.h> |
| 24 | #include <linux/iio/sysfs.h> | ||
| 25 | #include <linux/iio/buffer.h> | 22 | #include <linux/iio/buffer.h> |
| 26 | #include <linux/iio/imu/adis.h> | 23 | #include <linux/iio/imu/adis.h> |
| 24 | #include <linux/iio/trigger_consumer.h> | ||
| 27 | 25 | ||
| 28 | #include <linux/debugfs.h> | 26 | #include <linux/debugfs.h> |
| 29 | 27 | ||
| @@ -103,6 +101,12 @@ · 73 unmodified lines | |||
| 103 | * Available only for ADIS1649x devices | 101 | * Available only for ADIS1649x devices |
| 104 | */ | 102 | */ |
| 105 | #define ADIS16495_REG_SYNC_SCALE ADIS16480_REG(0x03, 0x10) | 103 | #define ADIS16495_REG_SYNC_SCALE ADIS16480_REG(0x03, 0x10) |
| 104 | #define ADIS16495_REG_BURST_CMD ADIS16480_REG(0x00, 0x7C) | ||
| 105 | #define ADIS16495_BURST_ID 0xA5A5 | ||
| 106 | /* total number of segments in burst */ | ||
| 107 | #define ADIS16495_BURST_MAX_DATA 20 | ||
| 108 | /* spi max speed in burst mode */ | ||
| 109 | #define ADIS16495_BURST_MAX_SPEED 6000000 | ||
| 106 | 110 | ||
| 107 | #define ADIS16480_REG_SERIAL_NUM ADIS16480_REG(0x04, 0x20) | 111 | #define ADIS16480_REG_SERIAL_NUM ADIS16480_REG(0x04, 0x20) |
| 108 | 112 | ||
| @@ -163,6 +167,8 @@ struct adis16480 { · 54 unmodified lines | |||
| 163 | struct clk *ext_clk; | 167 | struct clk *ext_clk; |
| 164 | enum adis16480_clock_mode clk_mode; | 168 | enum adis16480_clock_mode clk_mode; |
| 165 | unsigned int clk_freq; | 169 | unsigned int clk_freq; |
| 170 | /* Alignment needed for the timestamp */ | ||
| 171 | __be16 data[ADIS16495_BURST_MAX_DATA] __aligned(8); | ||
| 166 | }; | 172 | }; |
| 167 | 173 | ||
| 168 | static const char * const adis16480_int_pin_names[4] = { | 174 | static const char * const adis16480_int_pin_names[4] = { |
| @@ -863,7 +869,7 @@ static const char * const adis16480_status_error_msgs[] = { · 694 unmodified lines | |||
| 863 | 869 | ||
| 864 | static int adis16480_enable_irq(struct adis *adis, bool enable); | 870 | static int adis16480_enable_irq(struct adis *adis, bool enable); |
| 865 | 871 | ||
| 866 | #define ADIS16480_DATA(_prod_id, _timeouts) \ | 872 | #define ADIS16480_DATA(_prod_id, _timeouts, _burst_len) \ |
| 867 | { \ | 873 | { \ |
| 868 | .diag_stat_reg = ADIS16480_REG_DIAG_STS, \ | 874 | .diag_stat_reg = ADIS16480_REG_DIAG_STS, \ |
| 869 | .glob_cmd_reg = ADIS16480_REG_GLOB_CMD, \ | 875 | .glob_cmd_reg = ADIS16480_REG_GLOB_CMD, \ |
| @@ -887,6 +893,9 @@ static int adis16480_enable_irq(struct adis *adis, bool enable); · 17 unmodified lines | |||
| 887 | BIT(ADIS16480_DIAG_STAT_BARO_FAIL), \ | 893 | BIT(ADIS16480_DIAG_STAT_BARO_FAIL), \ |
| 888 | .enable_irq = adis16480_enable_irq, \ | 894 | .enable_irq = adis16480_enable_irq, \ |
| 889 | .timeouts = (_timeouts), \ | 895 | .timeouts = (_timeouts), \ |
| 896 | .burst_reg_cmd = ADIS16495_REG_BURST_CMD, \ | ||
| 897 | .burst_len = (_burst_len), \ | ||
| 898 | .burst_max_speed_hz = ADIS16495_BURST_MAX_SPEED \ | ||
| 890 | } | 899 | } |
| 891 | 900 | ||
| 892 | static const struct adis_timeout adis16485_timeouts = { | 901 | static const struct adis_timeout adis16485_timeouts = { |
| @@ -931,7 +940,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { · 38 unmodified lines | |||
| 931 | .int_clk = 2460000, | 940 | .int_clk = 2460000, |
| 932 | .max_dec_rate = 2048, | 941 | .max_dec_rate = 2048, |
| 933 | .filter_freqs = adis16480_def_filter_freqs, | 942 | .filter_freqs = adis16480_def_filter_freqs, |
| 934 | .adis_data = ADIS16480_DATA(16375, &adis16485_timeouts), | 943 | .adis_data = ADIS16480_DATA(16375, &adis16485_timeouts, 0), |
| 935 | }, | 944 | }, |
| 936 | [ADIS16480] = { | 945 | [ADIS16480] = { |
| 937 | .channels = adis16480_channels, | 946 | .channels = adis16480_channels, |
| @@ -944,7 +953,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { · 6 unmodified lines | |||
| 944 | .int_clk = 2460000, | 953 | .int_clk = 2460000, |
| 945 | .max_dec_rate = 2048, | 954 | .max_dec_rate = 2048, |
| 946 | .filter_freqs = adis16480_def_filter_freqs, | 955 | .filter_freqs = adis16480_def_filter_freqs, |
| 947 | .adis_data = ADIS16480_DATA(16480, &adis16480_timeouts), | 956 | .adis_data = ADIS16480_DATA(16480, &adis16480_timeouts, 0), |
| 948 | }, | 957 | }, |
| 949 | [ADIS16485] = { | 958 | [ADIS16485] = { |
| 950 | .channels = adis16485_channels, | 959 | .channels = adis16485_channels, |
| @@ -957,7 +966,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { · 6 unmodified lines | |||
| 957 | .int_clk = 2460000, | 966 | .int_clk = 2460000, |
| 958 | .max_dec_rate = 2048, | 967 | .max_dec_rate = 2048, |
| 959 | .filter_freqs = adis16480_def_filter_freqs, | 968 | .filter_freqs = adis16480_def_filter_freqs, |
| 960 | .adis_data = ADIS16480_DATA(16485, &adis16485_timeouts), | 969 | .adis_data = ADIS16480_DATA(16485, &adis16485_timeouts, 0), |
| 961 | }, | 970 | }, |
| 962 | [ADIS16488] = { | 971 | [ADIS16488] = { |
| 963 | .channels = adis16480_channels, | 972 | .channels = adis16480_channels, |
| @@ -970,7 +979,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { · 6 unmodified lines | |||
| 970 | .int_clk = 2460000, | 979 | .int_clk = 2460000, |
| 971 | .max_dec_rate = 2048, | 980 | .max_dec_rate = 2048, |
| 972 | .filter_freqs = adis16480_def_filter_freqs, | 981 | .filter_freqs = adis16480_def_filter_freqs, |
| 973 | .adis_data = ADIS16480_DATA(16488, &adis16485_timeouts), | 982 | .adis_data = ADIS16480_DATA(16488, &adis16485_timeouts, 0), |
| 974 | }, | 983 | }, |
| 975 | [ADIS16490] = { | 984 | [ADIS16490] = { |
| 976 | .channels = adis16485_channels, | 985 | .channels = adis16485_channels, |
| @@ -984,7 +993,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { · 7 unmodified lines | |||
| 984 | .max_dec_rate = 4250, | 993 | .max_dec_rate = 4250, |
| 985 | .filter_freqs = adis16495_def_filter_freqs, | 994 | .filter_freqs = adis16495_def_filter_freqs, |
| 986 | .has_pps_clk_mode = true, | 995 | .has_pps_clk_mode = true, |
| 987 | .adis_data = ADIS16480_DATA(16490, &adis16495_timeouts), | 996 | .adis_data = ADIS16480_DATA(16490, &adis16495_timeouts, 0), |
| 988 | }, | 997 | }, |
| 989 | [ADIS16495_1] = { | 998 | [ADIS16495_1] = { |
| 990 | .channels = adis16485_channels, | 999 | .channels = adis16485_channels, |
| @@ -998,7 +1007,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { · 7 unmodified lines | |||
| 998 | .max_dec_rate = 4250, | 1007 | .max_dec_rate = 4250, |
| 999 | .filter_freqs = adis16495_def_filter_freqs, | 1008 | .filter_freqs = adis16495_def_filter_freqs, |
| 1000 | .has_pps_clk_mode = true, | 1009 | .has_pps_clk_mode = true, |
| 1001 | .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts), | 1010 | /* 20 elements of 16bits */ |
| 1011 | .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts, | ||
| 1012 | ADIS16495_BURST_MAX_DATA * 2), | ||
| 1002 | }, | 1013 | }, |
| 1003 | [ADIS16495_2] = { | 1014 | [ADIS16495_2] = { |
| 1004 | .channels = adis16485_channels, | 1015 | .channels = adis16485_channels, |
| @@ -1012,7 +1023,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { · 7 unmodified lines | |||
| 1012 | .max_dec_rate = 4250, | 1023 | .max_dec_rate = 4250, |
| 1013 | .filter_freqs = adis16495_def_filter_freqs, | 1024 | .filter_freqs = adis16495_def_filter_freqs, |
| 1014 | .has_pps_clk_mode = true, | 1025 | .has_pps_clk_mode = true, |
| 1015 | .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts), | 1026 | /* 20 elements of 16bits */ |
| 1027 | .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts, | ||
| 1028 | ADIS16495_BURST_MAX_DATA * 2), | ||
| 1016 | }, | 1029 | }, |
| 1017 | [ADIS16495_3] = { | 1030 | [ADIS16495_3] = { |
| 1018 | .channels = adis16485_channels, | 1031 | .channels = adis16485_channels, |
| @@ -1026,7 +1039,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { · 7 unmodified lines | |||
| 1026 | .max_dec_rate = 4250, | 1039 | .max_dec_rate = 4250, |
| 1027 | .filter_freqs = adis16495_def_filter_freqs, | 1040 | .filter_freqs = adis16495_def_filter_freqs, |
| 1028 | .has_pps_clk_mode = true, | 1041 | .has_pps_clk_mode = true, |
| 1029 | .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts), | 1042 | /* 20 elements of 16bits */ |
| 1043 | .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts, | ||
| 1044 | ADIS16495_BURST_MAX_DATA * 2), | ||
| 1030 | }, | 1045 | }, |
| 1031 | [ADIS16497_1] = { | 1046 | [ADIS16497_1] = { |
| 1032 | .channels = adis16485_channels, | 1047 | .channels = adis16485_channels, |
| @@ -1040,7 +1055,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { · 7 unmodified lines | |||
| 1040 | .max_dec_rate = 4250, | 1055 | .max_dec_rate = 4250, |
| 1041 | .filter_freqs = adis16495_def_filter_freqs, | 1056 | .filter_freqs = adis16495_def_filter_freqs, |
| 1042 | .has_pps_clk_mode = true, | 1057 | .has_pps_clk_mode = true, |
| 1043 | .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts), | 1058 | /* 20 elements of 16bits */ |
| 1059 | .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts, | ||
| 1060 | ADIS16495_BURST_MAX_DATA * 2), | ||
| 1044 | }, | 1061 | }, |
| 1045 | [ADIS16497_2] = { | 1062 | [ADIS16497_2] = { |
| 1046 | .channels = adis16485_channels, | 1063 | .channels = adis16485_channels, |
| @@ -1054,7 +1071,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { · 7 unmodified lines | |||
| 1054 | .max_dec_rate = 4250, | 1071 | .max_dec_rate = 4250, |
| 1055 | .filter_freqs = adis16495_def_filter_freqs, | 1072 | .filter_freqs = adis16495_def_filter_freqs, |
| 1056 | .has_pps_clk_mode = true, | 1073 | .has_pps_clk_mode = true, |
| 1057 | .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts), | 1074 | /* 20 elements of 16bits */ |
| 1075 | .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts, | ||
| 1076 | ADIS16495_BURST_MAX_DATA * 2), | ||
| 1058 | }, | 1077 | }, |
| 1059 | [ADIS16497_3] = { | 1078 | [ADIS16497_3] = { |
| 1060 | .channels = adis16485_channels, | 1079 | .channels = adis16485_channels, |
| @@ -1068,10 +1087,118 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { · 7 unmodified lines | |||
| 1068 | .max_dec_rate = 4250, | 1087 | .max_dec_rate = 4250, |
| 1069 | .filter_freqs = adis16495_def_filter_freqs, | 1088 | .filter_freqs = adis16495_def_filter_freqs, |
| 1070 | .has_pps_clk_mode = true, | 1089 | .has_pps_clk_mode = true, |
| 1071 | .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts), | 1090 | /* 20 elements of 16bits */ |
| 1091 | .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts, | ||
| 1092 | ADIS16495_BURST_MAX_DATA * 2), | ||
| 1072 | }, | 1093 | }, |
| 1073 | }; | 1094 | }; |
| 1074 | 1095 | ||
| 1096 | static bool adis16480_validate_crc(const u16 *buf, const u8 n_elem, const u32 crc) | ||
| 1097 | { | ||
| 1098 | u32 crc_calc; | ||
| 1099 | u16 crc_buf[15]; | ||
| 1100 | int j; | ||
| 1101 | |||
| 1102 | for (j = 0; j < n_elem; j++) | ||
| 1103 | crc_buf[j] = swab16(buf[j]); | ||
| 1104 | |||
| 1105 | crc_calc = crc32(~0, crc_buf, n_elem * 2); | ||
| 1106 | crc_calc ^= ~0; | ||
| 1107 | |||
| 1108 | return (crc == crc_calc); | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | static irqreturn_t adis16480_trigger_handler(int irq, void *p) | ||
| 1112 | { | ||
| 1113 | struct iio_poll_func *pf = p; | ||
| 1114 | struct iio_dev *indio_dev = pf->indio_dev; | ||
| 1115 | struct adis16480 *st = iio_priv(indio_dev); | ||
| 1116 | struct adis *adis = &st->adis; | ||
| 1117 | int ret, bit, offset, i = 0; | ||
| 1118 | __be16 *buffer; | ||
| 1119 | u32 crc; | ||
| 1120 | bool valid; | ||
| 1121 | |||
| 1122 | adis_dev_lock(adis); | ||
| 1123 | if (adis->current_page != 0) { | ||
| 1124 | adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); | ||
| 1125 | adis->tx[1] = 0; | ||
| 1126 | ret = spi_write(adis->spi, adis->tx, 2); | ||
| 1127 | if (ret) { | ||
| 1128 | dev_err(&adis->spi->dev, "Failed to change device page: %d\n", ret); | ||
| 1129 | adis_dev_unlock(adis); | ||
| 1130 | goto irq_done; | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | adis->current_page = 0; | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | ret = spi_sync(adis->spi, &adis->msg); | ||
| 1137 | if (ret) { | ||
| 1138 | dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret); | ||
| 1139 | adis_dev_unlock(adis); | ||
| 1140 | goto irq_done; | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | adis_dev_unlock(adis); | ||
| 1144 | |||
| 1145 | /* | ||
| 1146 | * After making the burst request, the response can have one or two | ||
| 1147 | * 16-bit responses containing the BURST_ID depending on the sclk. If | ||
| 1148 | * clk > 3.6MHz, then we will have two BURST_ID in a row. If clk < 3MHZ, | ||
| 1149 | * we have only one. To manage that variation, we use the transition from the | ||
| 1150 | * BURST_ID to the SYS_E_FLAG register, which will not be equal to 0xA5A5. If | ||
| 1151 | * we not find this variation in the first 4 segments, then the data should | ||
| 1152 | * not be valid. | ||
| 1153 | */ | ||
| 1154 | buffer = adis->buffer; | ||
| 1155 | for (offset = 0; offset < 4; offset++) { | ||
| 1156 | u16 curr = be16_to_cpu(buffer[offset]); | ||
| 1157 | u16 next = be16_to_cpu(buffer[offset + 1]); | ||
| 1158 | |||
| 1159 | if (curr == ADIS16495_BURST_ID && next != ADIS16495_BURST_ID) { | ||
| 1160 | offset++; | ||
| 1161 | break; | ||
| 1162 | } | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | if (offset == 4) { | ||
| 1166 | dev_err(&adis->spi->dev, "Invalid burst data\n"); | ||
| 1167 | goto irq_done; | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | crc = be16_to_cpu(buffer[offset + 16]) << 16 | be16_to_cpu(buffer[offset + 15]); | ||
| 1171 | valid = adis16480_validate_crc((u16 *)&buffer[offset], 15, crc); | ||
| 1172 | if (!valid) { | ||
| 1173 | dev_err(&adis->spi->dev, "Invalid crc\n"); | ||
| 1174 | goto irq_done; | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) { | ||
| 1178 | /* | ||
| 1179 | * When burst mode is used, temperature is the first data | ||
| 1180 | * channel in the sequence, but the temperature scan index | ||
| 1181 | * is 10. | ||
| 1182 | */ | ||
| 1183 | switch (bit) { | ||
| 1184 | case ADIS16480_SCAN_TEMP: | ||
| 1185 | st->data[i++] = buffer[offset + 1]; | ||
| 1186 | break; | ||
| 1187 | case ADIS16480_SCAN_GYRO_X ... ADIS16480_SCAN_ACCEL_Z: | ||
| 1188 | /* The lower register data is sequenced first */ | ||
| 1189 | st->data[i++] = buffer[2 * bit + offset + 3]; | ||
| 1190 | st->data[i++] = buffer[2 * bit + offset + 2]; | ||
| 1191 | break; | ||
| 1192 | } | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | iio_push_to_buffers_with_timestamp(indio_dev, st->data, pf->timestamp); | ||
| 1196 | irq_done: | ||
| 1197 | iio_trigger_notify_done(indio_dev->trig); | ||
| 1198 | |||
| 1199 | return IRQ_HANDLED; | ||
| 1200 | } | ||
| 1201 | |||
| 1075 | static const struct iio_info adis16480_info = { | 1202 | static const struct iio_info adis16480_info = { |
| 1076 | .read_raw = &adis16480_read_raw, | 1203 | .read_raw = &adis16480_read_raw, |
| 1077 | .write_raw = &adis16480_write_raw, | 1204 | .write_raw = &adis16480_write_raw, |
| @@ -1279,8 +1406,6 @@ static int adis16480_probe(struct spi_device *spi) · 201 unmodified lines | |||
| 1279 | if (indio_dev == NULL) | 1406 | if (indio_dev == NULL) |
| 1280 | return -ENOMEM; | 1407 | return -ENOMEM; |
| 1281 | 1408 | ||
| 1282 | spi_set_drvdata(spi, indio_dev); | ||
| 1283 | |||
| 1284 | st = iio_priv(indio_dev); | 1409 | st = iio_priv(indio_dev); |
| 1285 | 1410 | ||
| 1286 | st->chip_info = &adis16480_chip_info[id->driver_data]; | 1411 | st->chip_info = &adis16480_chip_info[id->driver_data]; |
| @@ -1341,7 +1466,8 @@ static int adis16480_probe(struct spi_device *spi) · 54 unmodified lines | |||
| 1341 | st->clk_freq = st->chip_info->int_clk; | 1466 | st->clk_freq = st->chip_info->int_clk; |
| 1342 | } | 1467 | } |
| 1343 | 1468 | ||
| 1344 | ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); | 1469 | ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, |
| 1470 | adis16480_trigger_handler); | ||
| 1345 | if (ret) | 1471 | if (ret) |
| 1346 | return ret; | 1472 | return ret; |
| 1347 | 1473 | ||
| @@ -51,9 +51,13 @@ static int adis_update_scan_mode_burst(struct iio_dev *indio_dev, · 50 unmodified lines | |||
| 51 | adis->xfer[0].tx_buf = tx; | 51 | adis->xfer[0].tx_buf = tx; |
| 52 | adis->xfer[0].bits_per_word = 8; | 52 | adis->xfer[0].bits_per_word = 8; |
| 53 | adis->xfer[0].len = 2; | 53 | adis->xfer[0].len = 2; |
| 54 | if (adis->data->burst_max_speed_hz) | ||
| 55 | adis->xfer[0].speed_hz = adis->data->burst_max_speed_hz; | ||
| 54 | adis->xfer[1].rx_buf = adis->buffer; | 56 | adis->xfer[1].rx_buf = adis->buffer; |
| 55 | adis->xfer[1].bits_per_word = 8; | 57 | adis->xfer[1].bits_per_word = 8; |
| 56 | adis->xfer[1].len = burst_length; | 58 | adis->xfer[1].len = burst_length; |
| 59 | if (adis->data->burst_max_speed_hz) | ||
| 60 | adis->xfer[1].speed_hz = adis->data->burst_max_speed_hz; | ||
| 57 | 61 | ||
| 58 | spi_message_init(&adis->msg); | 62 | spi_message_init(&adis->msg); |
| 59 | spi_message_add_tail(&adis->xfer[0], &adis->msg); | 63 | spi_message_add_tail(&adis->xfer[0], &adis->msg); |
| @@ -129,31 +133,34 @@ static irqreturn_t adis_trigger_handler(int irq, void *p) · 69 unmodified lines | |||
| 129 | struct adis *adis = iio_device_get_drvdata(indio_dev); | 133 | struct adis *adis = iio_device_get_drvdata(indio_dev); |
| 130 | int ret; | 134 | int ret; |
| 131 | 135 | ||
| 132 | if (!adis->buffer) | ||
| 133 | return -ENOMEM; | ||
| 134 | |||
| 135 | if (adis->data->has_paging) { | 136 | if (adis->data->has_paging) { |
| 136 | mutex_lock(&adis->state_lock); | 137 | mutex_lock(&adis->state_lock); |
| 137 | if (adis->current_page != 0) { | 138 | if (adis->current_page != 0) { |
| 138 | adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); | 139 | adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); |
| 139 | adis->tx[1] = 0; | 140 | adis->tx[1] = 0; |
| 140 | spi_write(adis->spi, adis->tx, 2); | 141 | ret = spi_write(adis->spi, adis->tx, 2); |
| 142 | if (ret) { | ||
| 143 | dev_err(&adis->spi->dev, "Failed to change device page: %d\n", ret); | ||
| 144 | mutex_unlock(&adis->state_lock); | ||
| 145 | goto irq_done; | ||
| 146 | } | ||
| 147 | |||
| 148 | adis->current_page = 0; | ||
| 141 | } | 149 | } |
| 142 | } | 150 | } |
| 143 | 151 | ||
| 144 | ret = spi_sync(adis->spi, &adis->msg); | 152 | ret = spi_sync(adis->spi, &adis->msg); |
| 145 | if (ret) | 153 | if (adis->data->has_paging) |
| 146 | dev_err(&adis->spi->dev, "Failed to read data: %d", ret); | ||
| 147 | |||
| 148 | |||
| 149 | if (adis->data->has_paging) { | ||
| 150 | adis->current_page = 0; | ||
| 151 | mutex_unlock(&adis->state_lock); | 154 | mutex_unlock(&adis->state_lock); |
| 155 | if (ret) { | ||
| 156 | dev_err(&adis->spi->dev, "Failed to read data: %d", ret); | ||
| 157 | goto irq_done; | ||
| 152 | } | 158 | } |
| 153 | 159 | ||
| 154 | iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer, | 160 | iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer, |
| 155 | pf->timestamp); | 161 | pf->timestamp); |
| 156 | 162 | ||
| 163 | irq_done: | ||
| 157 | iio_trigger_notify_done(indio_dev->trig); | 164 | iio_trigger_notify_done(indio_dev->trig); |
| 158 | 165 | ||
| 159 | return IRQ_HANDLED; | 166 | return IRQ_HANDLED; |
| @@ -62,7 +62,8 @@ int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) · 61 unmodified lines | |||
| 62 | int ret; | 62 | int ret; |
| 63 | 63 | ||
| 64 | adis->trig = devm_iio_trigger_alloc(&adis->spi->dev, "%s-dev%d", | 64 | adis->trig = devm_iio_trigger_alloc(&adis->spi->dev, "%s-dev%d", |
| 65 | indio_dev->name, indio_dev->id); | 65 | indio_dev->name, |
| 66 | iio_device_id(indio_dev)); | ||
| 66 | if (!adis->trig) | 67 | if (!adis->trig) |
| 67 | return -ENOMEM; | 68 | return -ENOMEM; |
| 68 | 69 | ||
| @@ -785,7 +785,8 @@ int bmi160_probe_trigger(struct iio_dev *indio_dev, int irq, u32 irq_type) · 784 unmodified lines | |||
| 785 | int ret; | 785 | int ret; |
| 786 | 786 | ||
| 787 | data->trig = devm_iio_trigger_alloc(&indio_dev->dev, "%s-dev%d", | 787 | data->trig = devm_iio_trigger_alloc(&indio_dev->dev, "%s-dev%d", |
| 788 | indio_dev->name, indio_dev->id); | 788 | indio_dev->name, |
| 789 | iio_device_id(indio_dev)); | ||
| 789 | 790 | ||
| 790 | if (data->trig == NULL) | 791 | if (data->trig == NULL) |
| 791 | return -ENOMEM; | 792 | return -ENOMEM; |
| @@ -851,8 +852,7 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap, · 59 unmodified lines | |||
| 851 | return ret; | 852 | return ret; |
| 852 | } | 853 | } |
| 853 | 854 | ||
| 854 | ret = iio_read_mount_matrix(dev, "mount-matrix", | 855 | ret = iio_read_mount_matrix(dev, &data->orientation); |
| 855 | &data->orientation); | ||
| 856 | if (ret) | 856 | if (ret) |
| 857 | return ret; | 857 | return ret; |
| 858 | 858 | ||
| @@ -592,7 +592,7 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, · 591 unmodified lines | |||
| 592 | st->chip = chip; | 592 | st->chip = chip; |
| 593 | st->map = regmap; | 593 | st->map = regmap; |
| 594 | 594 | ||
| 595 | ret = iio_read_mount_matrix(dev, "mount-matrix", &st->orientation); | 595 | ret = iio_read_mount_matrix(dev, &st->orientation); |
| 596 | if (ret) { | 596 | if (ret) { |
| 597 | dev_err(dev, "failed to retrieve mounting matrix %d\n", ret); | 597 | dev_err(dev, "failed to retrieve mounting matrix %d\n", ret); |
| 598 | return ret; | 598 | return ret; |
| @@ -570,11 +570,9 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev, · 569 unmodified lines | |||
| 570 | freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider); | 570 | freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider); |
| 571 | period_us = 1000000 / freq_hz; | 571 | period_us = 1000000 / freq_hz; |
| 572 | 572 | ||
| 573 | result = pm_runtime_get_sync(pdev); | 573 | result = pm_runtime_resume_and_get(pdev); |
| 574 | if (result < 0) { | 574 | if (result) |
| 575 | pm_runtime_put_noidle(pdev); | ||
| 576 | return result; | 575 | return result; |
| 577 | } | ||
| 578 | 576 | ||
| 579 | switch (chan->type) { | 577 | switch (chan->type) { |
| 580 | case IIO_ANGL_VEL: | 578 | case IIO_ANGL_VEL: |
| @@ -812,11 +810,9 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, · 231 unmodified lines | |||
| 812 | return result; | 810 | return result; |
| 813 | 811 | ||
| 814 | mutex_lock(&st->lock); | 812 | mutex_lock(&st->lock); |
| 815 | result = pm_runtime_get_sync(pdev); | 813 | result = pm_runtime_resume_and_get(pdev); |
| 816 | if (result < 0) { | 814 | if (result) |
| 817 | pm_runtime_put_noidle(pdev); | ||
| 818 | goto error_write_raw_unlock; | 815 | goto error_write_raw_unlock; |
| 819 | } | ||
| 820 | 816 | ||
| 821 | switch (mask) { | 817 | switch (mask) { |
| 822 | case IIO_CHAN_INFO_SCALE: | 818 | case IIO_CHAN_INFO_SCALE: |
| @@ -930,11 +926,9 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr, · 107 unmodified lines | |||
| 930 | result = 0; | 926 | result = 0; |
| 931 | goto fifo_rate_fail_unlock; | 927 | goto fifo_rate_fail_unlock; |
| 932 | } | 928 | } |
| 933 | result = pm_runtime_get_sync(pdev); | 929 | result = pm_runtime_resume_and_get(pdev); |
| 934 | if (result < 0) { | 930 | if (result) |
| 935 | pm_runtime_put_noidle(pdev); | ||
| 936 | goto fifo_rate_fail_unlock; | 931 | goto fifo_rate_fail_unlock; |
| 937 | } | ||
| 938 | 932 | ||
| 939 | result = regmap_write(st->map, st->reg->sample_rate_div, d); | 933 | result = regmap_write(st->map, st->reg->sample_rate_div, d); |
| 940 | if (result) | 934 | if (result) |
| @@ -1314,8 +1308,7 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) · 373 unmodified lines | |||
| 1314 | for (i = 0; i < INV_NUM_PARTS; ++i) { | 1308 | for (i = 0; i < INV_NUM_PARTS; ++i) { |
| 1315 | if (regval == hw_info[i].whoami) { | 1309 | if (regval == hw_info[i].whoami) { |
| 1316 | dev_warn(regmap_get_device(st->map), | 1310 | dev_warn(regmap_get_device(st->map), |
| 1317 | "whoami mismatch got %#02x (%s)" | 1311 | "whoami mismatch got 0x%02x (%s) expected 0x%02x (%s)\n", |
| 1318 | "expected %#02hhx (%s)\n", | ||
| 1319 | regval, hw_info[i].name, | 1312 | regval, hw_info[i].name, |
| 1320 | st->hw->whoami, st->hw->name); | 1313 | st->hw->whoami, st->hw->name); |
| 1321 | break; | 1314 | break; |
| @@ -1323,7 +1316,7 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) · 1 unmodified line | |||
| 1323 | } | 1316 | } |
| 1324 | if (i >= INV_NUM_PARTS) { | 1317 | if (i >= INV_NUM_PARTS) { |
| 1325 | dev_err(regmap_get_device(st->map), | 1318 | dev_err(regmap_get_device(st->map), |
| 1326 | "invalid whoami %#02x expected %#02hhx (%s)\n", | 1319 | "invalid whoami 0x%02x expected 0x%02x (%s)\n", |
| 1327 | regval, st->hw->whoami, st->hw->name); | 1320 | regval, st->hw->whoami, st->hw->name); |
| 1328 | return -ENODEV; | 1321 | return -ENODEV; |
| 1329 | } | 1322 | } |
| @@ -1422,7 +1415,6 @@ static void inv_mpu_pm_disable(void *data) · 92 unmodified lines | |||
| 1422 | { | 1415 | { |
| 1423 | struct device *dev = data; | 1416 | struct device *dev = data; |
| 1424 | 1417 | ||
| 1425 | pm_runtime_put_sync_suspend(dev); | ||
| 1426 | pm_runtime_disable(dev); | 1418 | pm_runtime_disable(dev); |
| 1427 | } | 1419 | } |
| 1428 | 1420 | ||
| @@ -1455,8 +1447,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, · 26 unmodified lines | |||
| 1455 | 1447 | ||
| 1456 | pdata = dev_get_platdata(dev); | 1448 | pdata = dev_get_platdata(dev); |
| 1457 | if (!pdata) { | 1449 | if (!pdata) { |
| 1458 | result = iio_read_mount_matrix(dev, "mount-matrix", | 1450 | result = iio_read_mount_matrix(dev, &st->orientation); |
| 1459 | &st->orientation); | ||
| 1460 | if (result) { | 1451 | if (result) { |
| 1461 | dev_err(dev, "Failed to retrieve mounting matrix %d\n", | 1452 | dev_err(dev, "Failed to retrieve mounting matrix %d\n", |
| 1462 | result); | 1453 | result); |
| @@ -173,11 +173,9 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable) · 172 unmodified lines | |||
| 173 | 173 | ||
| 174 | if (enable) { | 174 | if (enable) { |
| 175 | scan = inv_scan_query(indio_dev); | 175 | scan = inv_scan_query(indio_dev); |
| 176 | result = pm_runtime_get_sync(pdev); | 176 | result = pm_runtime_resume_and_get(pdev); |
| 177 | if (result < 0) { | 177 | if (result) |
| 178 | pm_runtime_put_noidle(pdev); | ||
| 179 | return result; | 178 | return result; |
| 180 | } | ||
| 181 | /* | 179 | /* |
| 182 | * In case autosuspend didn't trigger, turn off first not | 180 | * In case autosuspend didn't trigger, turn off first not |
| 183 | * required sensors. | 181 | * required sensors. |
| @@ -238,7 +236,7 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type) · 54 unmodified lines | |||
| 238 | st->trig = devm_iio_trigger_alloc(&indio_dev->dev, | 236 | st->trig = devm_iio_trigger_alloc(&indio_dev->dev, |
| 239 | "%s-dev%d", | 237 | "%s-dev%d", |
| 240 | indio_dev->name, | 238 | indio_dev->name, |
| 241 | indio_dev->id); | 239 | iio_device_id(indio_dev)); |
| 242 | if (!st->trig) | 240 | if (!st->trig) |
| 243 | return -ENOMEM; | 241 | return -ENOMEM; |
| 244 | 242 | ||
| @@ -750,7 +750,7 @@ static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device) · 749 unmodified lines | |||
| 750 | } | 750 | } |
| 751 | 751 | ||
| 752 | if (on) { | 752 | if (on) { |
| 753 | ret = pm_runtime_get_sync(&data->client->dev); | 753 | ret = pm_runtime_resume_and_get(&data->client->dev); |
| 754 | } else { | 754 | } else { |
| 755 | pm_runtime_mark_last_busy(&data->client->dev); | 755 | pm_runtime_mark_last_busy(&data->client->dev); |
| 756 | ret = pm_runtime_put_autosuspend(&data->client->dev); | 756 | ret = pm_runtime_put_autosuspend(&data->client->dev); |
| @@ -759,8 +759,6 @@ static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device) · 2 unmodified lines | |||
| 759 | dev_err(&data->client->dev, | 759 | dev_err(&data->client->dev, |
| 760 | "Failed: kmx61_set_power_state for %d, ret %d\n", | 760 | "Failed: kmx61_set_power_state for %d, ret %d\n", |
| 761 | on, ret); | 761 | on, ret); |
| 762 | if (on) | ||
| 763 | pm_runtime_put_noidle(&data->client->dev); | ||
| 764 | 762 | ||
| 765 | return ret; | 763 | return ret; |
| 766 | } | 764 | } |
| @@ -1264,7 +1262,7 @@ static struct iio_trigger *kmx61_trigger_setup(struct kmx61_data *data, · 497 unmodified lines | |||
| 1264 | "%s-%s-dev%d", | 1262 | "%s-%s-dev%d", |
| 1265 | indio_dev->name, | 1263 | indio_dev->name, |
| 1266 | tag, | 1264 | tag, |
| 1267 | indio_dev->id); | 1265 | iio_device_id(indio_dev)); |
| 1268 | if (!trig) | 1266 | if (!trig) |
| 1269 | return ERR_PTR(-ENOMEM); | 1267 | return ERR_PTR(-ENOMEM); |
| 1270 | 1268 | ||
| @@ -1426,7 +1424,6 @@ static int kmx61_remove(struct i2c_client *client) · 155 unmodified lines | |||
| 1426 | 1424 | ||
| 1427 | pm_runtime_disable(&client->dev); | 1425 | pm_runtime_disable(&client->dev); |
| 1428 | pm_runtime_set_suspended(&client->dev); | 1426 | pm_runtime_set_suspended(&client->dev); |
| 1429 | pm_runtime_put_noidle(&client->dev); | ||
| 1430 | 1427 | ||
| 1431 | if (client->irq > 0) { | 1428 | if (client->irq > 0) { |
| 1432 | iio_triggered_buffer_cleanup(data->acc_indio_dev); | 1429 | iio_triggered_buffer_cleanup(data->acc_indio_dev); |
| @@ -15,19 +15,19 @@ · 14 unmodified lines | |||
| 15 | * | 15 | * |
| 16 | * Supported sensors: | 16 | * Supported sensors: |
| 17 | * - LSM6DS3: | 17 | * - LSM6DS3: |
| 18 | * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 | 18 | * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416 |
| 19 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 | 19 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 |
| 20 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 | 20 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 |
| 21 | * - FIFO size: 8KB | 21 | * - FIFO size: 8KB |
| 22 | * | 22 | * |
| 23 | * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C: | 23 | * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C: |
| 24 | * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 | 24 | * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416 |
| 25 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 | 25 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 |
| 26 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 | 26 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 |
| 27 | * - FIFO size: 4KB | 27 | * - FIFO size: 4KB |
| 28 | * | 28 | * |
| 29 | * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX/LSM6DST/LSM6DSOP: | 29 | * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX/LSM6DST/LSM6DSOP: |
| 30 | * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416, | 30 | * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416, |
| 31 | * 833 | 31 | * 833 |
| 32 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 | 32 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 |
| 33 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 | 33 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 |
| @@ -2256,7 +2256,7 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, · 2222 unmodified lines | |||
| 2256 | return err; | 2256 | return err; |
| 2257 | } | 2257 | } |
| 2258 | 2258 | ||
| 2259 | err = iio_read_mount_matrix(hw->dev, "mount-matrix", &hw->orientation); | 2259 | err = iio_read_mount_matrix(hw->dev, &hw->orientation); |
| 2260 | if (err) | 2260 | if (err) |
| 2261 | return err; | 2261 | return err; |
| 2262 | 2262 | ||
| @@ -0,0 +1,28 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | |||
| 3 | config IIO_ST_LSM9DS0 | ||
| 4 | tristate "STMicroelectronics LSM9DS0 IMU driver" | ||
| 5 | depends on (I2C || SPI_MASTER) && SYSFS | ||
| 6 | depends on !SENSORS_LIS3_I2C | ||
| 7 | depends on !SENSORS_LIS3_SPI | ||
| 8 | select IIO_ST_LSM9DS0_I2C if I2C | ||
| 9 | select IIO_ST_LSM9DS0_SPI if SPI_MASTER | ||
| 10 | select IIO_ST_ACCEL_3AXIS | ||
| 11 | select IIO_ST_MAGN_3AXIS | ||
| 12 | |||
| 13 | help | ||
| 14 | Say yes here to build support for STMicroelectronics LSM9DS0 IMU | ||
| 15 | sensor. Supported devices: accelerometer/magnetometer of lsm9ds0. | ||
| 16 | |||
| 17 | To compile this driver as a module, choose M here: the module | ||
| 18 | will be called st_lsm9ds0. | ||
| 19 | |||
| 20 | config IIO_ST_LSM9DS0_I2C | ||
| 21 | tristate | ||
| 22 | depends on IIO_ST_LSM9DS0 | ||
| 23 | select REGMAP_I2C | ||
| 24 | |||
| 25 | config IIO_ST_LSM9DS0_SPI | ||
| 26 | tristate | ||
| 27 | depends on IIO_ST_LSM9DS0 | ||
| 28 | select REGMAP_SPI | ||
| @@ -0,0 +1,5 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | obj-$(CONFIG_IIO_ST_LSM9DS0) += st_lsm9ds0.o | ||
| 3 | st_lsm9ds0-y := st_lsm9ds0_core.o | ||
| 4 | obj-$(CONFIG_IIO_ST_LSM9DS0_I2C) += st_lsm9ds0_i2c.o | ||
| 5 | obj-$(CONFIG_IIO_ST_LSM9DS0_SPI) += st_lsm9ds0_spi.o | ||
| @@ -0,0 +1,23 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | // STMicroelectronics LSM9DS0 IMU driver | ||
| 3 | |||
| 4 | #ifndef ST_LSM9DS0_H | ||
| 5 | #define ST_LSM9DS0_H | ||
| 6 | |||
| 7 | struct iio_dev; | ||
| 8 | struct regulator; | ||
| 9 | |||
| 10 | struct st_lsm9ds0 { | ||
| 11 | struct device *dev; | ||
| 12 | const char *name; | ||
| 13 | int irq; | ||
| 14 | struct iio_dev *accel; | ||
| 15 | struct iio_dev *magn; | ||
| 16 | struct regulator *vdd; | ||
| 17 | struct regulator *vdd_io; | ||
| 18 | }; | ||
| 19 | |||
| 20 | int st_lsm9ds0_probe(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap); | ||
| 21 | int st_lsm9ds0_remove(struct st_lsm9ds0 *lsm9ds0); | ||
| 22 | |||
| 23 | #endif /* ST_LSM9DS0_H */ | ||
| @@ -0,0 +1,163 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * STMicroelectronics LSM9DS0 IMU driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2021, Intel Corporation | ||
| 6 | * | ||
| 7 | * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/device.h> | ||
| 11 | #include <linux/err.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/regulator/consumer.h> | ||
| 14 | |||
| 15 | #include <linux/iio/common/st_sensors.h> | ||
| 16 | #include <linux/iio/iio.h> | ||
| 17 | |||
| 18 | #include "st_lsm9ds0.h" | ||
| 19 | |||
| 20 | static int st_lsm9ds0_power_enable(struct device *dev, struct st_lsm9ds0 *lsm9ds0) | ||
| 21 | { | ||
| 22 | int ret; | ||
| 23 | |||
| 24 | /* Regulators not mandatory, but if requested we should enable them. */ | ||
| 25 | lsm9ds0->vdd = devm_regulator_get(dev, "vdd"); | ||
| 26 | if (IS_ERR(lsm9ds0->vdd)) { | ||
| 27 | dev_err(dev, "unable to get Vdd supply\n"); | ||
| 28 | return PTR_ERR(lsm9ds0->vdd); | ||
| 29 | } | ||
| 30 | ret = regulator_enable(lsm9ds0->vdd); | ||
| 31 | if (ret) { | ||
| 32 | dev_warn(dev, "Failed to enable specified Vdd supply\n"); | ||
| 33 | return ret; | ||
| 34 | } | ||
| 35 | |||
| 36 | lsm9ds0->vdd_io = devm_regulator_get(dev, "vddio"); | ||
| 37 | if (IS_ERR(lsm9ds0->vdd_io)) { | ||
| 38 | dev_err(dev, "unable to get Vdd_IO supply\n"); | ||
| 39 | regulator_disable(lsm9ds0->vdd); | ||
| 40 | return PTR_ERR(lsm9ds0->vdd_io); | ||
| 41 | } | ||
| 42 | ret = regulator_enable(lsm9ds0->vdd_io); | ||
| 43 | if (ret) { | ||
| 44 | dev_warn(dev, "Failed to enable specified Vdd_IO supply\n"); | ||
| 45 | regulator_disable(lsm9ds0->vdd); | ||
| 46 | return ret; | ||
| 47 | } | ||
| 48 | |||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | static void st_lsm9ds0_power_disable(void *data) | ||
| 53 | { | ||
| 54 | struct st_lsm9ds0 *lsm9ds0 = data; | ||
| 55 | |||
| 56 | regulator_disable(lsm9ds0->vdd_io); | ||
| 57 | regulator_disable(lsm9ds0->vdd); | ||
| 58 | } | ||
| 59 | |||
| 60 | static int devm_st_lsm9ds0_power_enable(struct st_lsm9ds0 *lsm9ds0) | ||
| 61 | { | ||
| 62 | struct device *dev = lsm9ds0->dev; | ||
| 63 | int ret; | ||
| 64 | |||
| 65 | ret = st_lsm9ds0_power_enable(dev, lsm9ds0); | ||
| 66 | if (ret) | ||
| 67 | return ret; | ||
| 68 | |||
| 69 | return devm_add_action_or_reset(dev, st_lsm9ds0_power_disable, lsm9ds0); | ||
| 70 | } | ||
| 71 | |||
| 72 | static int st_lsm9ds0_probe_accel(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap) | ||
| 73 | { | ||
| 74 | const struct st_sensor_settings *settings; | ||
| 75 | struct device *dev = lsm9ds0->dev; | ||
| 76 | struct st_sensor_data *data; | ||
| 77 | |||
| 78 | settings = st_accel_get_settings(lsm9ds0->name); | ||
| 79 | if (!settings) { | ||
| 80 | dev_err(dev, "device name %s not recognized.\n", lsm9ds0->name); | ||
| 81 | return -ENODEV; | ||
| 82 | } | ||
| 83 | |||
| 84 | lsm9ds0->accel = devm_iio_device_alloc(dev, sizeof(*data)); | ||
| 85 | if (!lsm9ds0->accel) | ||
| 86 | return -ENOMEM; | ||
| 87 | |||
| 88 | lsm9ds0->accel->name = lsm9ds0->name; | ||
| 89 | |||
| 90 | data = iio_priv(lsm9ds0->accel); | ||
| 91 | data->sensor_settings = (struct st_sensor_settings *)settings; | ||
| 92 | data->dev = dev; | ||
| 93 | data->irq = lsm9ds0->irq; | ||
| 94 | data->regmap = regmap; | ||
| 95 | data->vdd = lsm9ds0->vdd; | ||
| 96 | data->vdd_io = lsm9ds0->vdd_io; | ||
| 97 | |||
| 98 | return st_accel_common_probe(lsm9ds0->accel); | ||
| 99 | } | ||
| 100 | |||
| 101 | static int st_lsm9ds0_probe_magn(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap) | ||
| 102 | { | ||
| 103 | const struct st_sensor_settings *settings; | ||
| 104 | struct device *dev = lsm9ds0->dev; | ||
| 105 | struct st_sensor_data *data; | ||
| 106 | |||
| 107 | settings = st_magn_get_settings(lsm9ds0->name); | ||
| 108 | if (!settings) { | ||
| 109 | dev_err(dev, "device name %s not recognized.\n", lsm9ds0->name); | ||
| 110 | return -ENODEV; | ||
| 111 | } | ||
| 112 | |||
| 113 | lsm9ds0->magn = devm_iio_device_alloc(dev, sizeof(*data)); | ||
| 114 | if (!lsm9ds0->magn) | ||
| 115 | return -ENOMEM; | ||
| 116 | |||
| 117 | lsm9ds0->magn->name = lsm9ds0->name; | ||
| 118 | |||
| 119 | data = iio_priv(lsm9ds0->magn); | ||
| 120 | data->sensor_settings = (struct st_sensor_settings *)settings; | ||
| 121 | data->dev = dev; | ||
| 122 | data->irq = lsm9ds0->irq; | ||
| 123 | data->regmap = regmap; | ||
| 124 | data->vdd = lsm9ds0->vdd; | ||
| 125 | data->vdd_io = lsm9ds0->vdd_io; | ||
| 126 | |||
| 127 | return st_magn_common_probe(lsm9ds0->magn); | ||
| 128 | } | ||
| 129 | |||
| 130 | int st_lsm9ds0_probe(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap) | ||
| 131 | { | ||
| 132 | int ret; | ||
| 133 | |||
| 134 | ret = devm_st_lsm9ds0_power_enable(lsm9ds0); | ||
| 135 | if (ret) | ||
| 136 | return ret; | ||
| 137 | |||
| 138 | /* Setup accelerometer device */ | ||
| 139 | ret = st_lsm9ds0_probe_accel(lsm9ds0, regmap); | ||
| 140 | if (ret) | ||
| 141 | return ret; | ||
| 142 | |||
| 143 | /* Setup magnetometer device */ | ||
| 144 | ret = st_lsm9ds0_probe_magn(lsm9ds0, regmap); | ||
| 145 | if (ret) | ||
| 146 | st_accel_common_remove(lsm9ds0->accel); | ||
| 147 | |||
| 148 | return ret; | ||
| 149 | } | ||
| 150 | EXPORT_SYMBOL_GPL(st_lsm9ds0_probe); | ||
| 151 | |||
| 152 | int st_lsm9ds0_remove(struct st_lsm9ds0 *lsm9ds0) | ||
| 153 | { | ||
| 154 | st_magn_common_remove(lsm9ds0->magn); | ||
| 155 | st_accel_common_remove(lsm9ds0->accel); | ||
| 156 | |||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | EXPORT_SYMBOL_GPL(st_lsm9ds0_remove); | ||
| 160 | |||
| 161 | MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); | ||
| 162 | MODULE_DESCRIPTION("STMicroelectronics LSM9DS0 IMU core driver"); | ||
| 163 | MODULE_LICENSE("GPL v2"); | ||
| @@ -0,0 +1,84 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * STMicroelectronics LSM9DS0 IMU driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2021, Intel Corporation | ||
| 6 | * | ||
| 7 | * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/i2c.h> | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/slab.h> | ||
| 14 | |||
| 15 | #include <linux/iio/common/st_sensors_i2c.h> | ||
| 16 | |||
| 17 | #include "st_lsm9ds0.h" | ||
| 18 | |||
| 19 | static const struct of_device_id st_lsm9ds0_of_match[] = { | ||
| 20 | { | ||
| 21 | .compatible = "st,lsm9ds0-imu", | ||
| 22 | .data = LSM9DS0_IMU_DEV_NAME, | ||
| 23 | }, | ||
| 24 | {} | ||
| 25 | }; | ||
| 26 | MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match); | ||
| 27 | |||
| 28 | static const struct i2c_device_id st_lsm9ds0_id_table[] = { | ||
| 29 | { LSM9DS0_IMU_DEV_NAME }, | ||
| 30 | {} | ||
| 31 | }; | ||
| 32 | MODULE_DEVICE_TABLE(i2c, st_lsm9ds0_id_table); | ||
| 33 | |||
| 34 | static const struct regmap_config st_lsm9ds0_regmap_config = { | ||
| 35 | .reg_bits = 8, | ||
| 36 | .val_bits = 8, | ||
| 37 | .read_flag_mask = 0x80, | ||
| 38 | }; | ||
| 39 | |||
| 40 | static int st_lsm9ds0_i2c_probe(struct i2c_client *client) | ||
| 41 | { | ||
| 42 | const struct regmap_config *config = &st_lsm9ds0_regmap_config; | ||
| 43 | struct device *dev = &client->dev; | ||
| 44 | struct st_lsm9ds0 *lsm9ds0; | ||
| 45 | struct regmap *regmap; | ||
| 46 | |||
| 47 | st_sensors_dev_name_probe(dev, client->name, sizeof(client->name)); | ||
| 48 | |||
| 49 | lsm9ds0 = devm_kzalloc(dev, sizeof(*lsm9ds0), GFP_KERNEL); | ||
| 50 | if (!lsm9ds0) | ||
| 51 | return -ENOMEM; | ||
| 52 | |||
| 53 | lsm9ds0->dev = dev; | ||
| 54 | lsm9ds0->name = client->name; | ||
| 55 | lsm9ds0->irq = client->irq; | ||
| 56 | |||
| 57 | regmap = devm_regmap_init_i2c(client, config); | ||
| 58 | if (IS_ERR(regmap)) | ||
| 59 | return PTR_ERR(regmap); | ||
| 60 | |||
| 61 | i2c_set_clientdata(client, lsm9ds0); | ||
| 62 | |||
| 63 | return st_lsm9ds0_probe(lsm9ds0, regmap); | ||
| 64 | } | ||
| 65 | |||
| 66 | static int st_lsm9ds0_i2c_remove(struct i2c_client *client) | ||
| 67 | { | ||
| 68 | return st_lsm9ds0_remove(i2c_get_clientdata(client)); | ||
| 69 | } | ||
| 70 | |||
| 71 | static struct i2c_driver st_lsm9ds0_driver = { | ||
| 72 | .driver = { | ||
| 73 | .name = "st-lsm9ds0-i2c", | ||
| 74 | .of_match_table = st_lsm9ds0_of_match, | ||
| 75 | }, | ||
| 76 | .probe_new = st_lsm9ds0_i2c_probe, | ||
| 77 | .remove = st_lsm9ds0_i2c_remove, | ||
| 78 | .id_table = st_lsm9ds0_id_table, | ||
| 79 | }; | ||
| 80 | module_i2c_driver(st_lsm9ds0_driver); | ||
| 81 | |||
| 82 | MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); | ||
| 83 | MODULE_DESCRIPTION("STMicroelectronics LSM9DS0 IMU I2C driver"); | ||
| 84 | MODULE_LICENSE("GPL v2"); | ||
| @@ -0,0 +1,83 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * STMicroelectronics LSM9DS0 IMU driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2021, Intel Corporation | ||
| 6 | * | ||
| 7 | * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/kernel.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/slab.h> | ||
| 13 | #include <linux/spi/spi.h> | ||
| 14 | |||
| 15 | #include <linux/iio/common/st_sensors_spi.h> | ||
| 16 | |||
| 17 | #include "st_lsm9ds0.h" | ||
| 18 | |||
| 19 | static const struct of_device_id st_lsm9ds0_of_match[] = { | ||
| 20 | { | ||
| 21 | .compatible = "st,lsm9ds0-imu", | ||
| 22 | .data = LSM9DS0_IMU_DEV_NAME, | ||
| 23 | }, | ||
| 24 | {} | ||
| 25 | }; | ||
| 26 | MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match); | ||
| 27 | |||
| 28 | static const struct spi_device_id st_lsm9ds0_id_table[] = { | ||
| 29 | { LSM9DS0_IMU_DEV_NAME }, | ||
| 30 | {} | ||
| 31 | }; | ||
| 32 | MODULE_DEVICE_TABLE(spi, st_lsm9ds0_id_table); | ||
| 33 | |||
| 34 | static const struct regmap_config st_lsm9ds0_regmap_config = { | ||
| 35 | .reg_bits = 8, | ||
| 36 | .val_bits = 8, | ||
| 37 | .read_flag_mask = 0xc0, | ||
| 38 | }; | ||
| 39 | |||
| 40 | static int st_lsm9ds0_spi_probe(struct spi_device *spi) | ||
| 41 | { | ||
| 42 | struct device *dev = &spi->dev; | ||
| 43 | struct st_lsm9ds0 *lsm9ds0; | ||
| 44 | struct regmap *regmap; | ||
| 45 | |||
| 46 | st_sensors_dev_name_probe(dev, spi->modalias, sizeof(spi->modalias)); | ||
| 47 | |||
| 48 | lsm9ds0 = devm_kzalloc(dev, sizeof(*lsm9ds0), GFP_KERNEL); | ||
| 49 | if (!lsm9ds0) | ||
| 50 | return -ENOMEM; | ||
| 51 | |||
| 52 | lsm9ds0->dev = dev; | ||
| 53 | lsm9ds0->name = spi->modalias; | ||
| 54 | lsm9ds0->irq = spi->irq; | ||
| 55 | |||
| 56 | regmap = devm_regmap_init_spi(spi, &st_lsm9ds0_regmap_config); | ||
| 57 | if (IS_ERR(regmap)) | ||
| 58 | return PTR_ERR(regmap); | ||
| 59 | |||
| 60 | spi_set_drvdata(spi, lsm9ds0); | ||
| 61 | |||
| 62 | return st_lsm9ds0_probe(lsm9ds0, regmap); | ||
| 63 | } | ||
| 64 | |||
| 65 | static int st_lsm9ds0_spi_remove(struct spi_device *spi) | ||
| 66 | { | ||
| 67 | return st_lsm9ds0_remove(spi_get_drvdata(spi)); | ||
| 68 | } | ||
| 69 | |||
| 70 | static struct spi_driver st_lsm9ds0_driver = { | ||
| 71 | .driver = { | ||
| 72 | .name = "st-lsm9ds0-spi", | ||
| 73 | .of_match_table = st_lsm9ds0_of_match, | ||
| 74 | }, | ||
| 75 | .probe = st_lsm9ds0_spi_probe, | ||
| 76 | .remove = st_lsm9ds0_spi_remove, | ||
| 77 | .id_table = st_lsm9ds0_id_table, | ||
| 78 | }; | ||
| 79 | module_spi_driver(st_lsm9ds0_driver); | ||
| 80 | |||
| 81 | MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); | ||
| 82 | MODULE_DESCRIPTION("STMicroelectronics LSM9DS0 IMU SPI driver"); | ||
| 83 | MODULE_LICENSE("GPL v2"); | ||
| @@ -601,8 +601,10 @@ static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev, · 600 unmodified lines | |||
| 601 | 601 | ||
| 602 | static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev) | 602 | static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev) |
| 603 | { | 603 | { |
| 604 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); | ||
| 605 | |||
| 604 | return iio_storage_bytes_for_si(indio_dev, | 606 | return iio_storage_bytes_for_si(indio_dev, |
| 605 | indio_dev->scan_index_timestamp); | 607 | iio_dev_opaque->scan_index_timestamp); |
| 606 | } | 608 | } |
| 607 | 609 | ||
| 608 | static int iio_compute_scan_bytes(struct iio_dev *indio_dev, | 610 | static int iio_compute_scan_bytes(struct iio_dev *indio_dev, |
| @@ -924,7 +926,6 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, · 315 unmodified lines | |||
| 924 | if (ret) | 926 | if (ret) |
| 925 | goto error_clear_mux_table; | 927 | goto error_clear_mux_table; |
| 926 | out_loc += length; | 928 | out_loc += length; |
| 927 | in_loc += length; | ||
| 928 | } | 929 | } |
| 929 | buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL); | 930 | buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL); |
| 930 | if (buffer->demux_bounce == NULL) { | 931 | if (buffer->demux_bounce == NULL) { |
| @@ -1148,12 +1149,13 @@ int iio_update_buffers(struct iio_dev *indio_dev, · 217 unmodified lines | |||
| 1148 | struct iio_buffer *insert_buffer, | 1149 | struct iio_buffer *insert_buffer, |
| 1149 | struct iio_buffer *remove_buffer) | 1150 | struct iio_buffer *remove_buffer) |
| 1150 | { | 1151 | { |
| 1152 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); | ||
| 1151 | int ret; | 1153 | int ret; |
| 1152 | 1154 | ||
| 1153 | if (insert_buffer == remove_buffer) | 1155 | if (insert_buffer == remove_buffer) |
| 1154 | return 0; | 1156 | return 0; |
| 1155 | 1157 | ||
| 1156 | mutex_lock(&indio_dev->info_exist_lock); | 1158 | mutex_lock(&iio_dev_opaque->info_exist_lock); |
| 1157 | mutex_lock(&indio_dev->mlock); | 1159 | mutex_lock(&indio_dev->mlock); |
| 1158 | 1160 | ||
| 1159 | if (insert_buffer && iio_buffer_is_active(insert_buffer)) | 1161 | if (insert_buffer && iio_buffer_is_active(insert_buffer)) |
| @@ -1176,7 +1178,7 @@ int iio_update_buffers(struct iio_dev *indio_dev, · 16 unmodified lines | |||
| 1176 | 1178 | ||
| 1177 | out_unlock: | 1179 | out_unlock: |
| 1178 | mutex_unlock(&indio_dev->mlock); | 1180 | mutex_unlock(&indio_dev->mlock); |
| 1179 | mutex_unlock(&indio_dev->info_exist_lock); | 1181 | mutex_unlock(&iio_dev_opaque->info_exist_lock); |
| 1180 | 1182 | ||
| 1181 | return ret; | 1183 | return ret; |
| 1182 | } | 1184 | } |
| @@ -1469,6 +1471,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, · 286 unmodified lines | |||
| 1469 | struct iio_dev *indio_dev, | 1471 | struct iio_dev *indio_dev, |
| 1470 | int index) | 1472 | int index) |
| 1471 | { | 1473 | { |
| 1474 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); | ||
| 1472 | struct iio_dev_attr *p; | 1475 | struct iio_dev_attr *p; |
| 1473 | struct attribute **attr; | 1476 | struct attribute **attr; |
| 1474 | int ret, i, attrn, scan_el_attrcount, buffer_attrcount; | 1477 | int ret, i, attrn, scan_el_attrcount, buffer_attrcount; |
| @@ -1495,7 +1498,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, · 20 unmodified lines | |||
| 1495 | goto error_cleanup_dynamic; | 1498 | goto error_cleanup_dynamic; |
| 1496 | scan_el_attrcount += ret; | 1499 | scan_el_attrcount += ret; |
| 1497 | if (channels[i].type == IIO_TIMESTAMP) | 1500 | if (channels[i].type == IIO_TIMESTAMP) |
| 1498 | indio_dev->scan_index_timestamp = | 1501 | iio_dev_opaque->scan_index_timestamp = |
| 1499 | channels[i].scan_index; | 1502 | channels[i].scan_index; |
| 1500 | } | 1503 | } |
| 1501 | if (indio_dev->masklength && buffer->scan_mask == NULL) { | 1504 | if (indio_dev->masklength && buffer->scan_mask == NULL) { |
| @@ -169,6 +169,20 @@ static const char * const iio_chan_info_postfix[] = { · 168 unmodified lines | |||
| 169 | [IIO_CHAN_INFO_THERMOCOUPLE_TYPE] = "thermocouple_type", | 169 | [IIO_CHAN_INFO_THERMOCOUPLE_TYPE] = "thermocouple_type", |
| 170 | [IIO_CHAN_INFO_CALIBAMBIENT] = "calibambient", | 170 | [IIO_CHAN_INFO_CALIBAMBIENT] = "calibambient", |
| 171 | }; | 171 | }; |
| 172 | /** | ||
| 173 | * iio_device_id() - query the unique ID for the device | ||
| 174 | * @indio_dev: Device structure whose ID is being queried | ||
| 175 | * | ||
| 176 | * The IIO device ID is a unique index used for example for the naming | ||
| 177 | * of the character device /dev/iio\:device[ID] | ||
| 178 | */ | ||
| 179 | int iio_device_id(struct iio_dev *indio_dev) | ||
| 180 | { | ||
| 181 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); | ||
| 182 | |||
| 183 | return iio_dev_opaque->id; | ||
| 184 | } | ||
| 185 | EXPORT_SYMBOL_GPL(iio_device_id); | ||
| 172 | 186 | ||
| 173 | /** | 187 | /** |
| 174 | * iio_sysfs_match_string_with_gaps - matches given string in an array with gaps | 188 | * iio_sysfs_match_string_with_gaps - matches given string in an array with gaps |
| @@ -257,13 +271,25 @@ int iio_device_set_clock(struct iio_dev *indio_dev, clockid_t clock_id) · 82 unmodified lines | |||
| 257 | mutex_unlock(&indio_dev->mlock); | 271 | mutex_unlock(&indio_dev->mlock); |
| 258 | return -EBUSY; | 272 | return -EBUSY; |
| 259 | } | 273 | } |
| 260 | indio_dev->clock_id = clock_id; | 274 | iio_dev_opaque->clock_id = clock_id; |
| 261 | mutex_unlock(&indio_dev->mlock); | 275 | mutex_unlock(&indio_dev->mlock); |
| 262 | 276 | ||
| 263 | return 0; | 277 | return 0; |
| 264 | } | 278 | } |
| 265 | EXPORT_SYMBOL(iio_device_set_clock); | 279 | EXPORT_SYMBOL(iio_device_set_clock); |
| 266 | 280 | ||
| 281 | /** | ||
| 282 | * iio_device_get_clock() - Retrieve current timestamping clock for the device | ||
| 283 | * @indio_dev: IIO device structure containing the device | ||
| 284 | */ | ||
| 285 | clockid_t iio_device_get_clock(const struct iio_dev *indio_dev) | ||
| 286 | { | ||
| 287 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); | ||
| 288 | |||
| 289 | return iio_dev_opaque->clock_id; | ||
| 290 | } | ||
| 291 | EXPORT_SYMBOL(iio_device_get_clock); | ||
| 292 | |||
| 267 | /** | 293 | /** |
| 268 | * iio_get_time_ns() - utility function to get a time stamp for events etc | 294 | * iio_get_time_ns() - utility function to get a time stamp for events etc |
| 269 | * @indio_dev: device | 295 | * @indio_dev: device |
| @@ -591,7 +617,6 @@ EXPORT_SYMBOL_GPL(iio_show_mount_matrix); · 321 unmodified lines | |||
| 591 | * iio_read_mount_matrix() - retrieve iio device mounting matrix from | 617 | * iio_read_mount_matrix() - retrieve iio device mounting matrix from |
| 592 | * device "mount-matrix" property | 618 | * device "mount-matrix" property |
| 593 | * @dev: device the mounting matrix property is assigned to | 619 | * @dev: device the mounting matrix property is assigned to |
| 594 | * @propname: device specific mounting matrix property name | ||
| 595 | * @matrix: where to store retrieved matrix | 620 | * @matrix: where to store retrieved matrix |
| 596 | * | 621 | * |
| 597 | * If device is assigned no mounting matrix property, a default 3x3 identity | 622 | * If device is assigned no mounting matrix property, a default 3x3 identity |
| @@ -599,14 +624,12 @@ EXPORT_SYMBOL_GPL(iio_show_mount_matrix); · 1 unmodified line | |||
| 599 | * | 624 | * |
| 600 | * Return: 0 if success, or a negative error code on failure. | 625 | * Return: 0 if success, or a negative error code on failure. |
| 601 | */ | 626 | */ |
| 602 | int iio_read_mount_matrix(struct device *dev, const char *propname, | 627 | int iio_read_mount_matrix(struct device *dev, struct iio_mount_matrix *matrix) |
| 603 | struct iio_mount_matrix *matrix) | ||
| 604 | { | 628 | { |
| 605 | size_t len = ARRAY_SIZE(iio_mount_idmatrix.rotation); | 629 | size_t len = ARRAY_SIZE(iio_mount_idmatrix.rotation); |
| 606 | int err; | 630 | int err; |
| 607 | 631 | ||
| 608 | err = device_property_read_string_array(dev, propname, | 632 | err = device_property_read_string_array(dev, "mount-matrix", matrix->rotation, len); |
| 609 | matrix->rotation, len); | ||
| 610 | if (err == len) | 633 | if (err == len) |
| 611 | return 0; | 634 | return 0; |
| 612 | 635 | ||
| @@ -1588,7 +1611,7 @@ static void iio_dev_release(struct device *device) · 975 unmodified lines | |||
| 1588 | 1611 | ||
| 1589 | iio_device_detach_buffers(indio_dev); | 1612 | iio_device_detach_buffers(indio_dev); |
| 1590 | 1613 | ||
| 1591 | ida_simple_remove(&iio_ida, indio_dev->id); | 1614 | ida_simple_remove(&iio_ida, iio_dev_opaque->id); |
| 1592 | kfree(iio_dev_opaque); | 1615 | kfree(iio_dev_opaque); |
| 1593 | } | 1616 | } |
| 1594 | 1617 | ||
| @@ -1628,17 +1651,17 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) · 33 unmodified lines | |||
| 1628 | device_initialize(&indio_dev->dev); | 1651 | device_initialize(&indio_dev->dev); |
| 1629 | iio_device_set_drvdata(indio_dev, (void *)indio_dev); | 1652 | iio_device_set_drvdata(indio_dev, (void *)indio_dev); |
| 1630 | mutex_init(&indio_dev->mlock); | 1653 | mutex_init(&indio_dev->mlock); |
| 1631 | mutex_init(&indio_dev->info_exist_lock); | 1654 | mutex_init(&iio_dev_opaque->info_exist_lock); |
| 1632 | INIT_LIST_HEAD(&iio_dev_opaque->channel_attr_list); | 1655 | INIT_LIST_HEAD(&iio_dev_opaque->channel_attr_list); |
| 1633 | 1656 | ||
| 1634 | indio_dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); | 1657 | iio_dev_opaque->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); |
| 1635 | if (indio_dev->id < 0) { | 1658 | if (iio_dev_opaque->id < 0) { |
| 1636 | /* cannot use a dev_err as the name isn't available */ | 1659 | /* cannot use a dev_err as the name isn't available */ |
| 1637 | pr_err("failed to get device id\n"); | 1660 | pr_err("failed to get device id\n"); |
| 1638 | kfree(iio_dev_opaque); | 1661 | kfree(iio_dev_opaque); |
| 1639 | return NULL; | 1662 | return NULL; |
| 1640 | } | 1663 | } |
| 1641 | dev_set_name(&indio_dev->dev, "iio:device%d", indio_dev->id); | 1664 | dev_set_name(&indio_dev->dev, "iio:device%d", iio_dev_opaque->id); |
| 1642 | INIT_LIST_HEAD(&iio_dev_opaque->buffer_list); | 1665 | INIT_LIST_HEAD(&iio_dev_opaque->buffer_list); |
| 1643 | INIT_LIST_HEAD(&iio_dev_opaque->ioctl_handlers); | 1666 | INIT_LIST_HEAD(&iio_dev_opaque->ioctl_handlers); |
| 1644 | 1667 | ||
| @@ -1657,9 +1680,9 @@ void iio_device_free(struct iio_dev *dev) · 12 unmodified lines | |||
| 1657 | } | 1680 | } |
| 1658 | EXPORT_SYMBOL(iio_device_free); | 1681 | EXPORT_SYMBOL(iio_device_free); |
| 1659 | 1682 | ||
| 1660 | static void devm_iio_device_release(struct device *dev, void *res) | 1683 | static void devm_iio_device_release(void *iio_dev) |
| 1661 | { | 1684 | { |
| 1662 | iio_device_free(*(struct iio_dev **)res); | 1685 | iio_device_free(iio_dev); |
| 1663 | } | 1686 | } |
| 1664 | 1687 | ||
| 1665 | /** | 1688 | /** |
| @@ -1675,20 +1698,17 @@ static void devm_iio_device_release(struct device *dev, void *res) · 9 unmodified lines | |||
| 1675 | */ | 1698 | */ |
| 1676 | struct iio_dev *devm_iio_device_alloc(struct device *parent, int sizeof_priv) | 1699 | struct iio_dev *devm_iio_device_alloc(struct device *parent, int sizeof_priv) |
| 1677 | { | 1700 | { |
| 1678 | struct iio_dev **ptr, *iio_dev; | 1701 | struct iio_dev *iio_dev; |
| 1702 | int ret; | ||
| 1679 | 1703 | ||
| 1680 | ptr = devres_alloc(devm_iio_device_release, sizeof(*ptr), | 1704 | iio_dev = iio_device_alloc(parent, sizeof_priv); |
| 1681 | GFP_KERNEL); | 1705 | if (!iio_dev) |
| 1682 | if (!ptr) | ||
| 1683 | return NULL; | 1706 | return NULL; |
| 1684 | 1707 | ||
| 1685 | iio_dev = iio_device_alloc(parent, sizeof_priv); | 1708 | ret = devm_add_action_or_reset(parent, devm_iio_device_release, |
| 1686 | if (iio_dev) { | 1709 | iio_dev); |
| 1687 | *ptr = iio_dev; | 1710 | if (ret) |
| 1688 | devres_add(parent, ptr); | 1711 | return NULL; |
| 1689 | } else { | ||
| 1690 | devres_free(ptr); | ||
| 1691 | } | ||
| 1692 | 1712 | ||
| 1693 | return iio_dev; | 1713 | return iio_dev; |
| 1694 | } | 1714 | } |
| @@ -1704,11 +1724,12 @@ EXPORT_SYMBOL_GPL(devm_iio_device_alloc); · 9 unmodified lines | |||
| 1704 | **/ | 1724 | **/ |
| 1705 | static int iio_chrdev_open(struct inode *inode, struct file *filp) | 1725 | static int iio_chrdev_open(struct inode *inode, struct file *filp) |
| 1706 | { | 1726 | { |
| 1707 | struct iio_dev *indio_dev = container_of(inode->i_cdev, | 1727 | struct iio_dev_opaque *iio_dev_opaque = |
| 1708 | struct iio_dev, chrdev); | 1728 | container_of(inode->i_cdev, struct iio_dev_opaque, chrdev); |
| 1729 | struct iio_dev *indio_dev = &iio_dev_opaque->indio_dev; | ||
| 1709 | struct iio_dev_buffer_pair *ib; | 1730 | struct iio_dev_buffer_pair *ib; |
| 1710 | 1731 | ||
| 1711 | if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags)) | 1732 | if (test_and_set_bit(IIO_BUSY_BIT_POS, &iio_dev_opaque->flags)) |
| 1712 | return -EBUSY; | 1733 | return -EBUSY; |
| 1713 | 1734 | ||
| 1714 | iio_device_get(indio_dev); | 1735 | iio_device_get(indio_dev); |
| @@ -1716,7 +1737,7 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp) · 1 unmodified line | |||
| 1716 | ib = kmalloc(sizeof(*ib), GFP_KERNEL); | 1737 | ib = kmalloc(sizeof(*ib), GFP_KERNEL); |
| 1717 | if (!ib) { | 1738 | if (!ib) { |
| 1718 | iio_device_put(indio_dev); | 1739 | iio_device_put(indio_dev); |
| 1719 | clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); | 1740 | clear_bit(IIO_BUSY_BIT_POS, &iio_dev_opaque->flags); |
| 1720 | return -ENOMEM; | 1741 | return -ENOMEM; |
| 1721 | } | 1742 | } |
| 1722 | 1743 | ||
| @@ -1738,10 +1759,11 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp) · 15 unmodified lines | |||
| 1738 | static int iio_chrdev_release(struct inode *inode, struct file *filp) | 1759 | static int iio_chrdev_release(struct inode *inode, struct file *filp) |
| 1739 | { | 1760 | { |
| 1740 | struct iio_dev_buffer_pair *ib = filp->private_data; | 1761 | struct iio_dev_buffer_pair *ib = filp->private_data; |
| 1741 | struct iio_dev *indio_dev = container_of(inode->i_cdev, | 1762 | struct iio_dev_opaque *iio_dev_opaque = |
| 1742 | struct iio_dev, chrdev); | 1763 | container_of(inode->i_cdev, struct iio_dev_opaque, chrdev); |
| 1764 | struct iio_dev *indio_dev = &iio_dev_opaque->indio_dev; | ||
| 1743 | kfree(ib); | 1765 | kfree(ib); |
| 1744 | clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); | 1766 | clear_bit(IIO_BUSY_BIT_POS, &iio_dev_opaque->flags); |
| 1745 | iio_device_put(indio_dev); | 1767 | iio_device_put(indio_dev); |
| 1746 | 1768 | ||
| 1747 | return 0; | 1769 | return 0; |
| @@ -1768,7 +1790,7 @@ static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) · 20 unmodified lines | |||
| 1768 | struct iio_ioctl_handler *h; | 1790 | struct iio_ioctl_handler *h; |
| 1769 | int ret = -ENODEV; | 1791 | int ret = -ENODEV; |
| 1770 | 1792 | ||
| 1771 | mutex_lock(&indio_dev->info_exist_lock); | 1793 | mutex_lock(&iio_dev_opaque->info_exist_lock); |
| 1772 | 1794 | ||
| 1773 | /** | 1795 | /** |
| 1774 | * The NULL check here is required to prevent crashing when a device | 1796 | * The NULL check here is required to prevent crashing when a device |
| @@ -1788,7 +1810,7 @@ static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) · 13 unmodified lines | |||
| 1788 | ret = -ENODEV; | 1810 | ret = -ENODEV; |
| 1789 | 1811 | ||
| 1790 | out_unlock: | 1812 | out_unlock: |
| 1791 | mutex_unlock(&indio_dev->info_exist_lock); | 1813 | mutex_unlock(&iio_dev_opaque->info_exist_lock); |
| 1792 | 1814 | ||
| 1793 | return ret; | 1815 | return ret; |
| 1794 | } | 1816 | } |
| @@ -1847,7 +1869,7 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) · 52 unmodified lines | |||
| 1847 | if (!indio_dev->info) | 1869 | if (!indio_dev->info) |
| 1848 | return -EINVAL; | 1870 | return -EINVAL; |
| 1849 | 1871 | ||
| 1850 | indio_dev->driver_module = this_mod; | 1872 | iio_dev_opaque->driver_module = this_mod; |
| 1851 | /* If the calling driver did not initialize of_node, do it here */ | 1873 | /* If the calling driver did not initialize of_node, do it here */ |
| 1852 | if (!indio_dev->dev.of_node && indio_dev->dev.parent) | 1874 | if (!indio_dev->dev.of_node && indio_dev->dev.parent) |
| 1853 | indio_dev->dev.of_node = indio_dev->dev.parent->of_node; | 1875 | indio_dev->dev.of_node = indio_dev->dev.parent->of_node; |
| @@ -1889,19 +1911,19 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) · 35 unmodified lines | |||
| 1889 | indio_dev->setup_ops = &noop_ring_setup_ops; | 1911 | indio_dev->setup_ops = &noop_ring_setup_ops; |
| 1890 | 1912 | ||
| 1891 | if (iio_dev_opaque->attached_buffers_cnt) | 1913 | if (iio_dev_opaque->attached_buffers_cnt) |
| 1892 | cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); | 1914 | cdev_init(&iio_dev_opaque->chrdev, &iio_buffer_fileops); |
| 1893 | else if (iio_dev_opaque->event_interface) | 1915 | else if (iio_dev_opaque->event_interface) |
| 1894 | cdev_init(&indio_dev->chrdev, &iio_event_fileops); | 1916 | cdev_init(&iio_dev_opaque->chrdev, &iio_event_fileops); |
| 1895 | 1917 | ||
| 1896 | if (iio_dev_opaque->attached_buffers_cnt || iio_dev_opaque->event_interface) { | 1918 | if (iio_dev_opaque->attached_buffers_cnt || iio_dev_opaque->event_interface) { |
| 1897 | indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); | 1919 | indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), iio_dev_opaque->id); |
| 1898 | indio_dev->chrdev.owner = this_mod; | 1920 | iio_dev_opaque->chrdev.owner = this_mod; |
| 1899 | } | 1921 | } |
| 1900 | 1922 | ||
| 1901 | /* assign device groups now; they should be all registered now */ | 1923 | /* assign device groups now; they should be all registered now */ |
| 1902 | indio_dev->dev.groups = iio_dev_opaque->groups; | 1924 | indio_dev->dev.groups = iio_dev_opaque->groups; |
| 1903 | 1925 | ||
| 1904 | ret = cdev_device_add(&indio_dev->chrdev, &indio_dev->dev); | 1926 | ret = cdev_device_add(&iio_dev_opaque->chrdev, &indio_dev->dev); |
| 1905 | if (ret < 0) | 1927 | if (ret < 0) |
| 1906 | goto error_unreg_eventset; | 1928 | goto error_unreg_eventset; |
| 1907 | 1929 | ||
| @@ -1925,9 +1947,11 @@ EXPORT_SYMBOL(__iio_device_register); · 17 unmodified lines | |||
| 1925 | **/ | 1947 | **/ |
| 1926 | void iio_device_unregister(struct iio_dev *indio_dev) | 1948 | void iio_device_unregister(struct iio_dev *indio_dev) |
| 1927 | { | 1949 | { |
| 1928 | cdev_device_del(&indio_dev->chrdev, &indio_dev->dev); | 1950 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
| 1929 | 1951 | ||
| 1930 | mutex_lock(&indio_dev->info_exist_lock); | 1952 | cdev_device_del(&iio_dev_opaque->chrdev, &indio_dev->dev); |
| 1953 | |||
| 1954 | mutex_lock(&iio_dev_opaque->info_exist_lock); | ||
| 1931 | 1955 | ||
| 1932 | iio_device_unregister_debugfs(indio_dev); | 1956 | iio_device_unregister_debugfs(indio_dev); |
| 1933 | 1957 | ||
| @@ -1938,35 +1962,27 @@ void iio_device_unregister(struct iio_dev *indio_dev) · 4 unmodified lines | |||
| 1938 | iio_device_wakeup_eventset(indio_dev); | 1962 | iio_device_wakeup_eventset(indio_dev); |
| 1939 | iio_buffer_wakeup_poll(indio_dev); | 1963 | iio_buffer_wakeup_poll(indio_dev); |
| 1940 | 1964 | ||
| 1941 | mutex_unlock(&indio_dev->info_exist_lock); | 1965 | mutex_unlock(&iio_dev_opaque->info_exist_lock); |
| 1942 | 1966 | ||
| 1943 | iio_buffers_free_sysfs_and_mask(indio_dev); | 1967 | iio_buffers_free_sysfs_and_mask(indio_dev); |
| 1944 | } | 1968 | } |
| 1945 | EXPORT_SYMBOL(iio_device_unregister); | 1969 | EXPORT_SYMBOL(iio_device_unregister); |
| 1946 | 1970 | ||
| 1947 | static void devm_iio_device_unreg(struct device *dev, void *res) | 1971 | static void devm_iio_device_unreg(void *indio_dev) |
| 1948 | { | 1972 | { |
| 1949 | iio_device_unregister(*(struct iio_dev **)res); | 1973 | iio_device_unregister(indio_dev); |
| 1950 | } | 1974 | } |
| 1951 | 1975 | ||
| 1952 | int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev, | 1976 | int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev, |
| 1953 | struct module *this_mod) | 1977 | struct module *this_mod) |
| 1954 | { | 1978 | { |
| 1955 | struct iio_dev **ptr; | ||
| 1956 | int ret; | 1979 | int ret; |
| 1957 | 1980 | ||
| 1958 | ptr = devres_alloc(devm_iio_device_unreg, sizeof(*ptr), GFP_KERNEL); | ||
| 1959 | if (!ptr) | ||
| 1960 | return -ENOMEM; | ||
| 1961 | |||
| 1962 | *ptr = indio_dev; | ||
| 1963 | ret = __iio_device_register(indio_dev, this_mod); | 1981 | ret = __iio_device_register(indio_dev, this_mod); |
| 1964 | if (!ret) | 1982 | if (ret) |
| 1965 | devres_add(dev, ptr); | 1983 | return ret; |
| 1966 | else | ||
| 1967 | devres_free(ptr); | ||
| 1968 | 1984 | ||
| 1969 | return ret; | 1985 | return devm_add_action_or_reset(dev, devm_iio_device_unreg, indio_dev); |
| 1970 | } | 1986 | } |
| 1971 | EXPORT_SYMBOL_GPL(__devm_iio_device_register); | 1987 | EXPORT_SYMBOL_GPL(__devm_iio_device_register); |
| 1972 | 1988 | ||
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
| 14 | 14 | ||
| 15 | #include <linux/iio/iio.h> | 15 | #include <linux/iio/iio.h> |
| 16 | #include <linux/iio/iio-opaque.h> | ||
| 16 | #include <linux/iio/trigger.h> | 17 | #include <linux/iio/trigger.h> |
| 17 | #include "iio_core.h" | 18 | #include "iio_core.h" |
| 18 | #include "iio_core_trigger.h" | 19 | #include "iio_core_trigger.h" |
| @@ -116,14 +117,17 @@ EXPORT_SYMBOL(iio_trigger_unregister); · 97 unmodified lines | |||
| 116 | 117 | ||
| 117 | int iio_trigger_set_immutable(struct iio_dev *indio_dev, struct iio_trigger *trig) | 118 | int iio_trigger_set_immutable(struct iio_dev *indio_dev, struct iio_trigger *trig) |
| 118 | { | 119 | { |
| 120 | struct iio_dev_opaque *iio_dev_opaque; | ||
| 121 | |||
| 119 | if (!indio_dev || !trig) | 122 | if (!indio_dev || !trig) |
| 120 | return -EINVAL; | 123 | return -EINVAL; |
| 121 | 124 | ||
| 125 | iio_dev_opaque = to_iio_dev_opaque(indio_dev); | ||
| 122 | mutex_lock(&indio_dev->mlock); | 126 | mutex_lock(&indio_dev->mlock); |
| 123 | WARN_ON(indio_dev->trig_readonly); | 127 | WARN_ON(iio_dev_opaque->trig_readonly); |
| 124 | 128 | ||
| 125 | indio_dev->trig = iio_trigger_get(trig); | 129 | indio_dev->trig = iio_trigger_get(trig); |
| 126 | indio_dev->trig_readonly = true; | 130 | iio_dev_opaque->trig_readonly = true; |
| 127 | mutex_unlock(&indio_dev->mlock); | 131 | mutex_unlock(&indio_dev->mlock); |
| 128 | 132 | ||
| 129 | return 0; | 133 | return 0; |
| @@ -240,12 +244,13 @@ static void iio_trigger_put_irq(struct iio_trigger *trig, int irq) · 110 unmodified lines | |||
| 240 | int iio_trigger_attach_poll_func(struct iio_trigger *trig, | 244 | int iio_trigger_attach_poll_func(struct iio_trigger *trig, |
| 241 | struct iio_poll_func *pf) | 245 | struct iio_poll_func *pf) |
| 242 | { | 246 | { |
| 247 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(pf->indio_dev); | ||
| 243 | bool notinuse = | 248 | bool notinuse = |
| 244 | bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER); | 249 | bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER); |
| 245 | int ret = 0; | 250 | int ret = 0; |
| 246 | 251 | ||
| 247 | /* Prevent the module from being removed whilst attached to a trigger */ | 252 | /* Prevent the module from being removed whilst attached to a trigger */ |
| 248 | __module_get(pf->indio_dev->driver_module); | 253 | __module_get(iio_dev_opaque->driver_module); |
| 249 | 254 | ||
| 250 | /* Get irq number */ | 255 | /* Get irq number */ |
| 251 | pf->irq = iio_trigger_get_irq(trig); | 256 | pf->irq = iio_trigger_get_irq(trig); |
| @@ -284,13 +289,14 @@ out_free_irq: · 32 unmodified lines | |||
| 284 | out_put_irq: | 289 | out_put_irq: |
| 285 | iio_trigger_put_irq(trig, pf->irq); | 290 | iio_trigger_put_irq(trig, pf->irq); |
| 286 | out_put_module: | 291 | out_put_module: |
| 287 | module_put(pf->indio_dev->driver_module); | 292 | module_put(iio_dev_opaque->driver_module); |
| 288 | return ret; | 293 | return ret; |
| 289 | } | 294 | } |
| 290 | 295 | ||
| 291 | int iio_trigger_detach_poll_func(struct iio_trigger *trig, | 296 | int iio_trigger_detach_poll_func(struct iio_trigger *trig, |
| 292 | struct iio_poll_func *pf) | 297 | struct iio_poll_func *pf) |
| 293 | { | 298 | { |
| 299 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(pf->indio_dev); | ||
| 294 | bool no_other_users = | 300 | bool no_other_users = |
| 295 | bitmap_weight(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER) == 1; | 301 | bitmap_weight(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER) == 1; |
| 296 | int ret = 0; | 302 | int ret = 0; |
| @@ -304,7 +310,7 @@ int iio_trigger_detach_poll_func(struct iio_trigger *trig, · 7 unmodified lines | |||
| 304 | trig->attached_own_device = false; | 310 | trig->attached_own_device = false; |
| 305 | iio_trigger_put_irq(trig, pf->irq); | 311 | iio_trigger_put_irq(trig, pf->irq); |
| 306 | free_irq(pf->irq, pf); | 312 | free_irq(pf->irq, pf); |
| 307 | module_put(pf->indio_dev->driver_module); | 313 | module_put(iio_dev_opaque->driver_module); |
| 308 | 314 | ||
| 309 | return ret; | 315 | return ret; |
| 310 | } | 316 | } |
| @@ -399,6 +405,7 @@ static ssize_t iio_trigger_write_current(struct device *dev, · 88 unmodified lines | |||
| 399 | size_t len) | 405 | size_t len) |
| 400 | { | 406 | { |
| 401 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 407 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 408 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); | ||
| 402 | struct iio_trigger *oldtrig = indio_dev->trig; | 409 | struct iio_trigger *oldtrig = indio_dev->trig; |
| 403 | struct iio_trigger *trig; | 410 | struct iio_trigger *trig; |
| 404 | int ret; | 411 | int ret; |
| @@ -408,7 +415,7 @@ static ssize_t iio_trigger_write_current(struct device *dev, · 3 unmodified lines | |||
| 408 | mutex_unlock(&indio_dev->mlock); | 415 | mutex_unlock(&indio_dev->mlock); |
| 409 | return -EBUSY; | 416 | return -EBUSY; |
| 410 | } | 417 | } |
| 411 | if (indio_dev->trig_readonly) { | 418 | if (iio_dev_opaque->trig_readonly) { |
| 412 | mutex_unlock(&indio_dev->mlock); | 419 | mutex_unlock(&indio_dev->mlock); |
| 413 | return -EPERM; | 420 | return -EPERM; |
| 414 | } | 421 | } |
| @@ -634,9 +641,9 @@ struct iio_trigger *devm_iio_trigger_alloc(struct device *parent, const char *fm · 219 unmodified lines | |||
| 634 | } | 641 | } |
| 635 | EXPORT_SYMBOL_GPL(devm_iio_trigger_alloc); | 642 | EXPORT_SYMBOL_GPL(devm_iio_trigger_alloc); |
| 636 | 643 | ||
| 637 | static void devm_iio_trigger_unreg(struct device *dev, void *res) | 644 | static void devm_iio_trigger_unreg(void *trigger_info) |
| 638 | { | 645 | { |
| 639 | iio_trigger_unregister(*(struct iio_trigger **)res); | 646 | iio_trigger_unregister(trigger_info); |
| 640 | } | 647 | } |
| 641 | 648 | ||
| 642 | /** | 649 | /** |
| @@ -657,21 +664,13 @@ int __devm_iio_trigger_register(struct device *dev, · 14 unmodified lines | |||
| 657 | struct iio_trigger *trig_info, | 664 | struct iio_trigger *trig_info, |
| 658 | struct module *this_mod) | 665 | struct module *this_mod) |
| 659 | { | 666 | { |
| 660 | struct iio_trigger **ptr; | ||
| 661 | int ret; | 667 | int ret; |
| 662 | 668 | ||
| 663 | ptr = devres_alloc(devm_iio_trigger_unreg, sizeof(*ptr), GFP_KERNEL); | ||
| 664 | if (!ptr) | ||
| 665 | return -ENOMEM; | ||
| 666 | |||
| 667 | *ptr = trig_info; | ||
| 668 | ret = __iio_trigger_register(trig_info, this_mod); | 669 | ret = __iio_trigger_register(trig_info, this_mod); |
| 669 | if (!ret) | 670 | if (ret) |
| 670 | devres_add(dev, ptr); | 671 | return ret; |
| 671 | else | ||
| 672 | devres_free(ptr); | ||
| 673 | 672 | ||
| 674 | return ret; | 673 | return devm_add_action_or_reset(dev, devm_iio_trigger_unreg, trig_info); |
| 675 | } | 674 | } |
| 676 | EXPORT_SYMBOL_GPL(__devm_iio_trigger_register); | 675 | EXPORT_SYMBOL_GPL(__devm_iio_trigger_register); |
| 677 | 676 | ||
| @@ -37,7 +37,7 @@ int iio_triggered_event_setup(struct iio_dev *indio_dev, · 36 unmodified lines | |||
| 37 | indio_dev, | 37 | indio_dev, |
| 38 | "%s_consumer%d", | 38 | "%s_consumer%d", |
| 39 | indio_dev->name, | 39 | indio_dev->name, |
| 40 | indio_dev->id); | 40 | iio_device_id(indio_dev)); |
| 41 | if (indio_dev->pollfunc_event == NULL) | 41 | if (indio_dev->pollfunc_event == NULL) |
| 42 | return -ENOMEM; | 42 | return -ENOMEM; |
| 43 | 43 | ||
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | #include <linux/of.h> | 10 | #include <linux/of.h> |
| 11 | 11 | ||
| 12 | #include <linux/iio/iio.h> | 12 | #include <linux/iio/iio.h> |
| 13 | #include <linux/iio/iio-opaque.h> | ||
| 13 | #include "iio_core.h" | 14 | #include "iio_core.h" |
| 14 | #include <linux/iio/machine.h> | 15 | #include <linux/iio/machine.h> |
| 15 | #include <linux/iio/driver.h> | 16 | #include <linux/iio/driver.h> |
| @@ -359,30 +360,24 @@ void iio_channel_release(struct iio_channel *channel) · 343 unmodified lines | |||
| 359 | } | 360 | } |
| 360 | EXPORT_SYMBOL_GPL(iio_channel_release); | 361 | EXPORT_SYMBOL_GPL(iio_channel_release); |
| 361 | 362 | ||
| 362 | static void devm_iio_channel_free(struct device *dev, void *res) | 363 | static void devm_iio_channel_free(void *iio_channel) |
| 363 | { | 364 | { |
| 364 | struct iio_channel *channel = *(struct iio_channel **)res; | 365 | iio_channel_release(iio_channel); |
| 365 | |||
| 366 | iio_channel_release(channel); | ||
| 367 | } | 366 | } |
| 368 | 367 | ||
| 369 | struct iio_channel *devm_iio_channel_get(struct device *dev, | 368 | struct iio_channel *devm_iio_channel_get(struct device *dev, |
| 370 | const char *channel_name) | 369 | const char *channel_name) |
| 371 | { | 370 | { |
| 372 | struct iio_channel **ptr, *channel; | 371 | struct iio_channel *channel; |
| 373 | 372 | int ret; | |
| 374 | ptr = devres_alloc(devm_iio_channel_free, sizeof(*ptr), GFP_KERNEL); | ||
| 375 | if (!ptr) | ||
| 376 | return ERR_PTR(-ENOMEM); | ||
| 377 | 373 | ||
| 378 | channel = iio_channel_get(dev, channel_name); | 374 | channel = iio_channel_get(dev, channel_name); |
| 379 | if (IS_ERR(channel)) { | 375 | if (IS_ERR(channel)) |
| 380 | devres_free(ptr); | ||
| 381 | return channel; | 376 | return channel; |
| 382 | } | ||
| 383 | 377 | ||
| 384 | *ptr = channel; | 378 | ret = devm_add_action_or_reset(dev, devm_iio_channel_free, channel); |
| 385 | devres_add(dev, ptr); | 379 | if (ret) |
| 380 | return ERR_PTR(ret); | ||
| 386 | 381 | ||
| 387 | return channel; | 382 | return channel; |
| 388 | } | 383 | } |
| @@ -392,20 +387,16 @@ struct iio_channel *devm_of_iio_channel_get_by_name(struct device *dev, · 3 unmodified lines | |||
| 392 | struct device_node *np, | 387 | struct device_node *np, |
| 393 | const char *channel_name) | 388 | const char *channel_name) |
| 394 | { | 389 | { |
| 395 | struct iio_channel **ptr, *channel; | 390 | struct iio_channel *channel; |
| 396 | 391 | int ret; | |
| 397 | ptr = devres_alloc(devm_iio_channel_free, sizeof(*ptr), GFP_KERNEL); | ||
| 398 | if (!ptr) | ||
| 399 | return ERR_PTR(-ENOMEM); | ||
| 400 | 392 | ||
| 401 | channel = of_iio_channel_get_by_name(np, channel_name); | 393 | channel = of_iio_channel_get_by_name(np, channel_name); |
| 402 | if (IS_ERR(channel)) { | 394 | if (IS_ERR(channel)) |
| 403 | devres_free(ptr); | ||
| 404 | return channel; | 395 | return channel; |
| 405 | } | ||
| 406 | 396 | ||
| 407 | *ptr = channel; | 397 | ret = devm_add_action_or_reset(dev, devm_iio_channel_free, channel); |
| 408 | devres_add(dev, ptr); | 398 | if (ret) |
| 399 | return ERR_PTR(ret); | ||
| 409 | 400 | ||
| 410 | return channel; | 401 | return channel; |
| 411 | } | 402 | } |
| @@ -496,29 +487,24 @@ void iio_channel_release_all(struct iio_channel *channels) · 84 unmodified lines | |||
| 496 | } | 487 | } |
| 497 | EXPORT_SYMBOL_GPL(iio_channel_release_all); | 488 | EXPORT_SYMBOL_GPL(iio_channel_release_all); |
| 498 | 489 | ||
| 499 | static void devm_iio_channel_free_all(struct device *dev, void *res) | 490 | static void devm_iio_channel_free_all(void *iio_channels) |
| 500 | { | 491 | { |
| 501 | struct iio_channel *channels = *(struct iio_channel **)res; | 492 | iio_channel_release_all(iio_channels); |
| 502 | |||
| 503 | iio_channel_release_all(channels); | ||
| 504 | } | 493 | } |
| 505 | 494 | ||
| 506 | struct iio_channel *devm_iio_channel_get_all(struct device *dev) | 495 | struct iio_channel *devm_iio_channel_get_all(struct device *dev) |
| 507 | { | 496 | { |
| 508 | struct iio_channel **ptr, *channels; | 497 | struct iio_channel *channels; |
| 509 | 498 | int ret; | |
| 510 | ptr = devres_alloc(devm_iio_channel_free_all, sizeof(*ptr), GFP_KERNEL); | ||
| 511 | if (!ptr) | ||
| 512 | return ERR_PTR(-ENOMEM); | ||
| 513 | 499 | ||
| 514 | channels = iio_channel_get_all(dev); | 500 | channels = iio_channel_get_all(dev); |
| 515 | if (IS_ERR(channels)) { | 501 | if (IS_ERR(channels)) |
| 516 | devres_free(ptr); | ||
| 517 | return channels; | 502 | return channels; |
| 518 | } | ||
| 519 | 503 | ||
| 520 | *ptr = channels; | 504 | ret = devm_add_action_or_reset(dev, devm_iio_channel_free_all, |
| 521 | devres_add(dev, ptr); | 505 | channels); |
| 506 | if (ret) | ||
| 507 | return ERR_PTR(ret); | ||
| 522 | 508 | ||
| 523 | return channels; | 509 | return channels; |
| 524 | } | 510 | } |
| @@ -553,9 +539,10 @@ static int iio_channel_read(struct iio_channel *chan, int *val, int *val2, · 28 unmodified lines | |||
| 553 | 539 | ||
| 554 | int iio_read_channel_raw(struct iio_channel *chan, int *val) | 540 | int iio_read_channel_raw(struct iio_channel *chan, int *val) |
| 555 | { | 541 | { |
| 542 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); | ||
| 556 | int ret; | 543 | int ret; |
| 557 | 544 | ||
| 558 | mutex_lock(&chan->indio_dev->info_exist_lock); | 545 | mutex_lock(&iio_dev_opaque->info_exist_lock); |
| 559 | if (chan->indio_dev->info == NULL) { | 546 | if (chan->indio_dev->info == NULL) { |
| 560 | ret = -ENODEV; | 547 | ret = -ENODEV; |
| 561 | goto err_unlock; | 548 | goto err_unlock; |
| @@ -563,7 +550,7 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val) · 1 unmodified line | |||
| 563 | 550 | ||
| 564 | ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW); | 551 | ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW); |
| 565 | err_unlock: | 552 | err_unlock: |
| 566 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 553 | mutex_unlock(&iio_dev_opaque->info_exist_lock); |
| 567 | 554 | ||
| 568 | return ret; | 555 | return ret; |
| 569 | } | 556 | } |
| @@ -571,9 +558,10 @@ EXPORT_SYMBOL_GPL(iio_read_channel_raw); · 1 unmodified line | |||
| 571 | 558 | ||
| 572 | int iio_read_channel_average_raw(struct iio_channel *chan, int *val) | 559 | int iio_read_channel_average_raw(struct iio_channel *chan, int *val) |
| 573 | { | 560 | { |
| 561 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); | ||
| 574 | int ret; | 562 | int ret; |
| 575 | 563 | ||
| 576 | mutex_lock(&chan->indio_dev->info_exist_lock); | 564 | mutex_lock(&iio_dev_opaque->info_exist_lock); |
| 577 | if (chan->indio_dev->info == NULL) { | 565 | if (chan->indio_dev->info == NULL) { |
| 578 | ret = -ENODEV; | 566 | ret = -ENODEV; |
| 579 | goto err_unlock; | 567 | goto err_unlock; |
| @@ -581,7 +569,7 @@ int iio_read_channel_average_raw(struct iio_channel *chan, int *val) · 1 unmodified line | |||
| 581 | 569 | ||
| 582 | ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_AVERAGE_RAW); | 570 | ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_AVERAGE_RAW); |
| 583 | err_unlock: | 571 | err_unlock: |
| 584 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 572 | mutex_unlock(&iio_dev_opaque->info_exist_lock); |
| 585 | 573 | ||
| 586 | return ret; | 574 | return ret; |
| 587 | } | 575 | } |
| @@ -646,9 +634,10 @@ static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, · 58 unmodified lines | |||
| 646 | int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, | 634 | int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, |
| 647 | int *processed, unsigned int scale) | 635 | int *processed, unsigned int scale) |
| 648 | { | 636 | { |
| 637 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); | ||
| 649 | int ret; | 638 | int ret; |
| 650 | 639 | ||
| 651 | mutex_lock(&chan->indio_dev->info_exist_lock); | 640 | mutex_lock(&iio_dev_opaque->info_exist_lock); |
| 652 | if (chan->indio_dev->info == NULL) { | 641 | if (chan->indio_dev->info == NULL) { |
| 653 | ret = -ENODEV; | 642 | ret = -ENODEV; |
| 654 | goto err_unlock; | 643 | goto err_unlock; |
| @@ -657,7 +646,7 @@ int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, · 2 unmodified lines | |||
| 657 | ret = iio_convert_raw_to_processed_unlocked(chan, raw, processed, | 646 | ret = iio_convert_raw_to_processed_unlocked(chan, raw, processed, |
| 658 | scale); | 647 | scale); |
| 659 | err_unlock: | 648 | err_unlock: |
| 660 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 649 | mutex_unlock(&iio_dev_opaque->info_exist_lock); |
| 661 | 650 | ||
| 662 | return ret; | 651 | return ret; |
| 663 | } | 652 | } |
| @@ -666,9 +655,10 @@ EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed); · 2 unmodified lines | |||
| 666 | int iio_read_channel_attribute(struct iio_channel *chan, int *val, int *val2, | 655 | int iio_read_channel_attribute(struct iio_channel *chan, int *val, int *val2, |
| 667 | enum iio_chan_info_enum attribute) | 656 | enum iio_chan_info_enum attribute) |
| 668 | { | 657 | { |
| 658 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); | ||
| 669 | int ret; | 659 | int ret; |
| 670 | 660 | ||
| 671 | mutex_lock(&chan->indio_dev->info_exist_lock); | 661 | mutex_lock(&iio_dev_opaque->info_exist_lock); |
| 672 | if (chan->indio_dev->info == NULL) { | 662 | if (chan->indio_dev->info == NULL) { |
| 673 | ret = -ENODEV; | 663 | ret = -ENODEV; |
| 674 | goto err_unlock; | 664 | goto err_unlock; |
| @@ -676,7 +666,7 @@ int iio_read_channel_attribute(struct iio_channel *chan, int *val, int *val2, · 1 unmodified line | |||
| 676 | 666 | ||
| 677 | ret = iio_channel_read(chan, val, val2, attribute); | 667 | ret = iio_channel_read(chan, val, val2, attribute); |
| 678 | err_unlock: | 668 | err_unlock: |
| 679 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 669 | mutex_unlock(&iio_dev_opaque->info_exist_lock); |
| 680 | 670 | ||
| 681 | return ret; | 671 | return ret; |
| 682 | } | 672 | } |
| @@ -691,9 +681,10 @@ EXPORT_SYMBOL_GPL(iio_read_channel_offset); · 8 unmodified lines | |||
| 691 | int iio_read_channel_processed_scale(struct iio_channel *chan, int *val, | 681 | int iio_read_channel_processed_scale(struct iio_channel *chan, int *val, |
| 692 | unsigned int scale) | 682 | unsigned int scale) |
| 693 | { | 683 | { |
| 684 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); | ||
| 694 | int ret; | 685 | int ret; |
| 695 | 686 | ||
| 696 | mutex_lock(&chan->indio_dev->info_exist_lock); | 687 | mutex_lock(&iio_dev_opaque->info_exist_lock); |
| 697 | if (chan->indio_dev->info == NULL) { | 688 | if (chan->indio_dev->info == NULL) { |
| 698 | ret = -ENODEV; | 689 | ret = -ENODEV; |
| 699 | goto err_unlock; | 690 | goto err_unlock; |
| @@ -714,7 +705,7 @@ int iio_read_channel_processed_scale(struct iio_channel *chan, int *val, · 14 unmodified lines | |||
| 714 | } | 705 | } |
| 715 | 706 | ||
| 716 | err_unlock: | 707 | err_unlock: |
| 717 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 708 | mutex_unlock(&iio_dev_opaque->info_exist_lock); |
| 718 | 709 | ||
| 719 | return ret; | 710 | return ret; |
| 720 | } | 711 | } |
| @@ -748,9 +739,10 @@ int iio_read_avail_channel_attribute(struct iio_channel *chan, · 27 unmodified lines | |||
| 748 | const int **vals, int *type, int *length, | 739 | const int **vals, int *type, int *length, |
| 749 | enum iio_chan_info_enum attribute) | 740 | enum iio_chan_info_enum attribute) |
| 750 | { | 741 | { |
| 742 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); | ||
| 751 | int ret; | 743 | int ret; |
| 752 | 744 | ||
| 753 | mutex_lock(&chan->indio_dev->info_exist_lock); | 745 | mutex_lock(&iio_dev_opaque->info_exist_lock); |
| 754 | if (!chan->indio_dev->info) { | 746 | if (!chan->indio_dev->info) { |
| 755 | ret = -ENODEV; | 747 | ret = -ENODEV; |
| 756 | goto err_unlock; | 748 | goto err_unlock; |
| @@ -758,7 +750,7 @@ int iio_read_avail_channel_attribute(struct iio_channel *chan, · 1 unmodified line | |||
| 758 | 750 | ||
| 759 | ret = iio_channel_read_avail(chan, vals, type, length, attribute); | 751 | ret = iio_channel_read_avail(chan, vals, type, length, attribute); |
| 760 | err_unlock: | 752 | err_unlock: |
| 761 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 753 | mutex_unlock(&iio_dev_opaque->info_exist_lock); |
| 762 | 754 | ||
| 763 | return ret; | 755 | return ret; |
| 764 | } | 756 | } |
| @@ -830,10 +822,11 @@ static int iio_channel_read_max(struct iio_channel *chan, · 65 unmodified lines | |||
| 830 | 822 | ||
| 831 | int iio_read_max_channel_raw(struct iio_channel *chan, int *val) | 823 | int iio_read_max_channel_raw(struct iio_channel *chan, int *val) |
| 832 | { | 824 | { |
| 825 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); | ||
| 833 | int ret; | 826 | int ret; |
| 834 | int type; | 827 | int type; |
| 835 | 828 | ||
| 836 | mutex_lock(&chan->indio_dev->info_exist_lock); | 829 | mutex_lock(&iio_dev_opaque->info_exist_lock); |
| 837 | if (!chan->indio_dev->info) { | 830 | if (!chan->indio_dev->info) { |
| 838 | ret = -ENODEV; | 831 | ret = -ENODEV; |
| 839 | goto err_unlock; | 832 | goto err_unlock; |
| @@ -841,7 +834,7 @@ int iio_read_max_channel_raw(struct iio_channel *chan, int *val) · 1 unmodified line | |||
| 841 | 834 | ||
| 842 | ret = iio_channel_read_max(chan, val, NULL, &type, IIO_CHAN_INFO_RAW); | 835 | ret = iio_channel_read_max(chan, val, NULL, &type, IIO_CHAN_INFO_RAW); |
| 843 | err_unlock: | 836 | err_unlock: |
| 844 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 837 | mutex_unlock(&iio_dev_opaque->info_exist_lock); |
| 845 | 838 | ||
| 846 | return ret; | 839 | return ret; |
| 847 | } | 840 | } |
| @@ -849,10 +842,11 @@ EXPORT_SYMBOL_GPL(iio_read_max_channel_raw); · 1 unmodified line | |||
| 849 | 842 | ||
| 850 | int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type) | 843 | int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type) |
| 851 | { | 844 | { |
| 845 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); | ||
| 852 | int ret = 0; | 846 | int ret = 0; |
| 853 | /* Need to verify underlying driver has not gone away */ | 847 | /* Need to verify underlying driver has not gone away */ |
| 854 | 848 | ||
| 855 | mutex_lock(&chan->indio_dev->info_exist_lock); | 849 | mutex_lock(&iio_dev_opaque->info_exist_lock); |
| 856 | if (chan->indio_dev->info == NULL) { | 850 | if (chan->indio_dev->info == NULL) { |
| 857 | ret = -ENODEV; | 851 | ret = -ENODEV; |
| 858 | goto err_unlock; | 852 | goto err_unlock; |
| @@ -860,7 +854,7 @@ int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type) · 1 unmodified line | |||
| 860 | 854 | ||
| 861 | *type = chan->channel->type; | 855 | *type = chan->channel->type; |
| 862 | err_unlock: | 856 | err_unlock: |
| 863 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 857 | mutex_unlock(&iio_dev_opaque->info_exist_lock); |
| 864 | 858 | ||
| 865 | return ret; | 859 | return ret; |
| 866 | } | 860 | } |
| @@ -876,9 +870,10 @@ static int iio_channel_write(struct iio_channel *chan, int val, int val2, · 9 unmodified lines | |||
| 876 | int iio_write_channel_attribute(struct iio_channel *chan, int val, int val2, | 870 | int iio_write_channel_attribute(struct iio_channel *chan, int val, int val2, |
| 877 | enum iio_chan_info_enum attribute) | 871 | enum iio_chan_info_enum attribute) |
| 878 | { | 872 | { |
| 873 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); | ||
| 879 | int ret; | 874 | int ret; |
| 880 | 875 | ||
| 881 | mutex_lock(&chan->indio_dev->info_exist_lock); | 876 | mutex_lock(&iio_dev_opaque->info_exist_lock); |
| 882 | if (chan->indio_dev->info == NULL) { | 877 | if (chan->indio_dev->info == NULL) { |
| 883 | ret = -ENODEV; | 878 | ret = -ENODEV; |
| 884 | goto err_unlock; | 879 | goto err_unlock; |
| @@ -886,7 +881,7 @@ int iio_write_channel_attribute(struct iio_channel *chan, int val, int val2, · 1 unmodified line | |||
| 886 | 881 | ||
| 887 | ret = iio_channel_write(chan, val, val2, attribute); | 882 | ret = iio_channel_write(chan, val, val2, attribute); |
| 888 | err_unlock: | 883 | err_unlock: |
| 889 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 884 | mutex_unlock(&iio_dev_opaque->info_exist_lock); |
| 890 | 885 | ||
| 891 | return ret; | 886 | return ret; |
| 892 | } | 887 | } |
| @@ -499,6 +499,17 @@ config TSL2583 · 498 unmodified lines | |||
| 499 | Provides support for the TAOS tsl2580, tsl2581 and tsl2583 devices. | 499 | Provides support for the TAOS tsl2580, tsl2581 and tsl2583 devices. |
| 500 | Access ALS data via iio, sysfs. | 500 | Access ALS data via iio, sysfs. |
| 501 | 501 | ||
| 502 | config TSL2591 | ||
| 503 | tristate "TAOS TSL2591 ambient light sensor" | ||
| 504 | depends on I2C | ||
| 505 | help | ||
| 506 | Select Y here for support of the AMS/TAOS TSL2591 ambient light sensor, | ||
| 507 | featuring channels for combined visible + IR intensity and lux illuminance. | ||
| 508 | Access data via iio and sysfs. Supports iio_events. | ||
| 509 | |||
| 510 | To compile this driver as a module, select M: the | ||
| 511 | module will be called tsl2591. | ||
| 512 | |||
| 502 | config TSL2772 | 513 | config TSL2772 |
| 503 | tristate "TAOS TSL/TMD2x71 and TSL/TMD2x72 Family of light and proximity sensors" | 514 | tristate "TAOS TSL/TMD2x71 and TSL/TMD2x72 Family of light and proximity sensors" |
| 504 | depends on I2C | 515 | depends on I2C |
| @@ -48,6 +48,7 @@ obj-$(CONFIG_ST_UVIS25_SPI) += st_uvis25_spi.o · 47 unmodified lines | |||
| 48 | obj-$(CONFIG_TCS3414) += tcs3414.o | 48 | obj-$(CONFIG_TCS3414) += tcs3414.o |
| 49 | obj-$(CONFIG_TCS3472) += tcs3472.o | 49 | obj-$(CONFIG_TCS3472) += tcs3472.o |
| 50 | obj-$(CONFIG_TSL2583) += tsl2583.o | 50 | obj-$(CONFIG_TSL2583) += tsl2583.o |
| 51 | obj-$(CONFIG_TSL2591) += tsl2591.o | ||
| 51 | obj-$(CONFIG_TSL2772) += tsl2772.o | 52 | obj-$(CONFIG_TSL2772) += tsl2772.o |
| 52 | obj-$(CONFIG_TSL4531) += tsl4531.o | 53 | obj-$(CONFIG_TSL4531) += tsl4531.o |
| 53 | obj-$(CONFIG_US5182D) += us5182d.o | 54 | obj-$(CONFIG_US5182D) += us5182d.o |
| @@ -204,7 +204,8 @@ static int acpi_als_add(struct acpi_device *device) · 203 unmodified lines | |||
| 204 | indio_dev->channels = acpi_als_channels; | 204 | indio_dev->channels = acpi_als_channels; |
| 205 | indio_dev->num_channels = ARRAY_SIZE(acpi_als_channels); | 205 | indio_dev->num_channels = ARRAY_SIZE(acpi_als_channels); |
| 206 | 206 | ||
| 207 | als->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, indio_dev->id); | 207 | als->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, |
| 208 | iio_device_id(indio_dev)); | ||
| 208 | if (!als->trig) | 209 | if (!als->trig) |
| 209 | return -ENOMEM; | 210 | return -ENOMEM; |
| 210 | 211 | ||
| @@ -6,13 +6,10 @@ · 5 unmodified lines | |||
| 6 | #include <linux/device.h> | 6 | #include <linux/device.h> |
| 7 | #include <linux/platform_device.h> | 7 | #include <linux/platform_device.h> |
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/interrupt.h> | 9 | #include <linux/mod_devicetable.h> |
| 10 | #include <linux/irq.h> | ||
| 11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
| 12 | #include <linux/delay.h> | ||
| 13 | #include <linux/hid-sensor-hub.h> | 11 | #include <linux/hid-sensor-hub.h> |
| 14 | #include <linux/iio/iio.h> | 12 | #include <linux/iio/iio.h> |
| 15 | #include <linux/iio/sysfs.h> | ||
| 16 | #include <linux/iio/buffer.h> | 13 | #include <linux/iio/buffer.h> |
| 17 | #include "../common/hid-sensors/hid-sensor-trigger.h" | 14 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 18 | 15 | ||
| @@ -392,3 +389,4 @@ module_platform_driver(hid_als_platform_driver); · 373 unmodified lines | |||
| 392 | MODULE_DESCRIPTION("HID Sensor ALS"); | 389 | MODULE_DESCRIPTION("HID Sensor ALS"); |
| 393 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); | 390 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); |
| 394 | MODULE_LICENSE("GPL"); | 391 | MODULE_LICENSE("GPL"); |
| 392 | MODULE_IMPORT_NS(IIO_HID); | ||
| @@ -6,13 +6,10 @@ · 5 unmodified lines | |||
| 6 | #include <linux/device.h> | 6 | #include <linux/device.h> |
| 7 | #include <linux/platform_device.h> | 7 | #include <linux/platform_device.h> |
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/interrupt.h> | 9 | #include <linux/mod_devicetable.h> |
| 10 | #include <linux/irq.h> | ||
| 11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
| 12 | #include <linux/delay.h> | ||
| 13 | #include <linux/hid-sensor-hub.h> | 11 | #include <linux/hid-sensor-hub.h> |
| 14 | #include <linux/iio/iio.h> | 12 | #include <linux/iio/iio.h> |
| 15 | #include <linux/iio/sysfs.h> | ||
| 16 | #include <linux/iio/buffer.h> | 13 | #include <linux/iio/buffer.h> |
| 17 | #include "../common/hid-sensors/hid-sensor-trigger.h" | 14 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 18 | 15 | ||
| @@ -350,3 +347,4 @@ module_platform_driver(hid_prox_platform_driver); · 331 unmodified lines | |||
| 350 | MODULE_DESCRIPTION("HID Sensor Proximity"); | 347 | MODULE_DESCRIPTION("HID Sensor Proximity"); |
| 351 | MODULE_AUTHOR("Archana Patni <archana.patni@intel.com>"); | 348 | MODULE_AUTHOR("Archana Patni <archana.patni@intel.com>"); |
| 352 | MODULE_LICENSE("GPL"); | 349 | MODULE_LICENSE("GPL"); |
| 350 | MODULE_IMPORT_NS(IIO_HID); | ||
| @@ -339,9 +339,7 @@ static int isl29028_set_pm_runtime_busy(struct isl29028_chip *chip, bool on) · 338 unmodified lines | |||
| 339 | int ret; | 339 | int ret; |
| 340 | 340 | ||
| 341 | if (on) { | 341 | if (on) { |
| 342 | ret = pm_runtime_get_sync(dev); | 342 | ret = pm_runtime_resume_and_get(dev); |
| 343 | if (ret < 0) | ||
| 344 | pm_runtime_put_noidle(dev); | ||
| 345 | } else { | 343 | } else { |
| 346 | pm_runtime_mark_last_busy(dev); | 344 | pm_runtime_mark_last_busy(dev); |
| 347 | ret = pm_runtime_put_autosuspend(dev); | 345 | ret = pm_runtime_put_autosuspend(dev); |
| @@ -647,7 +645,6 @@ static int isl29028_remove(struct i2c_client *client) · 299 unmodified lines | |||
| 647 | 645 | ||
| 648 | pm_runtime_disable(&client->dev); | 646 | pm_runtime_disable(&client->dev); |
| 649 | pm_runtime_set_suspended(&client->dev); | 647 | pm_runtime_set_suspended(&client->dev); |
| 650 | pm_runtime_put_noidle(&client->dev); | ||
| 651 | 648 | ||
| 652 | return isl29028_clear_configure_reg(chip); | 649 | return isl29028_clear_configure_reg(chip); |
| 653 | } | 650 | } |
| @@ -51,7 +51,11 @@ · 50 unmodified lines | |||
| 51 | struct isl29125_data { | 51 | struct isl29125_data { |
| 52 | struct i2c_client *client; | 52 | struct i2c_client *client; |
| 53 | u8 conf1; | 53 | u8 conf1; |
| 54 | u16 buffer[8]; /* 3x 16-bit, padding, 8 bytes timestamp */ | 54 | /* Ensure timestamp is naturally aligned */ |
| 55 | struct { | ||
| 56 | u16 chans[3]; | ||
| 57 | s64 timestamp __aligned(8); | ||
| 58 | } scan; | ||
| 55 | }; | 59 | }; |
| 56 | 60 | ||
| 57 | #define ISL29125_CHANNEL(_color, _si) { \ | 61 | #define ISL29125_CHANNEL(_color, _si) { \ |
| @@ -184,10 +188,10 @@ static irqreturn_t isl29125_trigger_handler(int irq, void *p) · 126 unmodified lines | |||
| 184 | if (ret < 0) | 188 | if (ret < 0) |
| 185 | goto done; | 189 | goto done; |
| 186 | 190 | ||
| 187 | data->buffer[j++] = ret; | 191 | data->scan.chans[j++] = ret; |
| 188 | } | 192 | } |
| 189 | 193 | ||
| 190 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 194 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, |
| 191 | iio_get_time_ns(indio_dev)); | 195 | iio_get_time_ns(indio_dev)); |
| 192 | 196 | ||
| 193 | done: | 197 | done: |
| @@ -32,9 +32,12 @@ · 31 unmodified lines | |||
| 32 | #define LTR501_PART_ID 0x86 | 32 | #define LTR501_PART_ID 0x86 |
| 33 | #define LTR501_MANUFAC_ID 0x87 | 33 | #define LTR501_MANUFAC_ID 0x87 |
| 34 | #define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */ | 34 | #define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */ |
| 35 | #define LTR501_ALS_DATA1_UPPER 0x89 /* upper 8 bits of LTR501_ALS_DATA1 */ | ||
| 35 | #define LTR501_ALS_DATA0 0x8a /* 16-bit, little endian */ | 36 | #define LTR501_ALS_DATA0 0x8a /* 16-bit, little endian */ |
| 37 | #define LTR501_ALS_DATA0_UPPER 0x8b /* upper 8 bits of LTR501_ALS_DATA0 */ | ||
| 36 | #define LTR501_ALS_PS_STATUS 0x8c | 38 | #define LTR501_ALS_PS_STATUS 0x8c |
| 37 | #define LTR501_PS_DATA 0x8d /* 16-bit, little endian */ | 39 | #define LTR501_PS_DATA 0x8d /* 16-bit, little endian */ |
| 40 | #define LTR501_PS_DATA_UPPER 0x8e /* upper 8 bits of LTR501_PS_DATA */ | ||
| 38 | #define LTR501_INTR 0x8f /* output mode, polarity, mode */ | 41 | #define LTR501_INTR 0x8f /* output mode, polarity, mode */ |
| 39 | #define LTR501_PS_THRESH_UP 0x90 /* 11 bit, ps upper threshold */ | 42 | #define LTR501_PS_THRESH_UP 0x90 /* 11 bit, ps upper threshold */ |
| 40 | #define LTR501_PS_THRESH_LOW 0x92 /* 11 bit, ps lower threshold */ | 43 | #define LTR501_PS_THRESH_LOW 0x92 /* 11 bit, ps lower threshold */ |
| @@ -149,7 +152,7 @@ struct ltr501_chip_info { · 108 unmodified lines | |||
| 149 | struct ltr501_data { | 152 | struct ltr501_data { |
| 150 | struct i2c_client *client; | 153 | struct i2c_client *client; |
| 151 | struct mutex lock_als, lock_ps; | 154 | struct mutex lock_als, lock_ps; |
| 152 | struct ltr501_chip_info *chip_info; | 155 | const struct ltr501_chip_info *chip_info; |
| 153 | u8 als_contr, ps_contr; | 156 | u8 als_contr, ps_contr; |
| 154 | int als_period, ps_period; /* period in micro seconds */ | 157 | int als_period, ps_period; /* period in micro seconds */ |
| 155 | struct regmap *regmap; | 158 | struct regmap *regmap; |
| @@ -406,18 +409,19 @@ static int ltr501_read_als(const struct ltr501_data *data, __le16 buf[2]) · 250 unmodified lines | |||
| 406 | 409 | ||
| 407 | static int ltr501_read_ps(const struct ltr501_data *data) | 410 | static int ltr501_read_ps(const struct ltr501_data *data) |
| 408 | { | 411 | { |
| 409 | int ret, status; | 412 | __le16 status; |
| 413 | int ret; | ||
| 410 | 414 | ||
| 411 | ret = ltr501_drdy(data, LTR501_STATUS_PS_RDY); | 415 | ret = ltr501_drdy(data, LTR501_STATUS_PS_RDY); |
| 412 | if (ret < 0) | 416 | if (ret < 0) |
| 413 | return ret; | 417 | return ret; |
| 414 | 418 | ||
| 415 | ret = regmap_bulk_read(data->regmap, LTR501_PS_DATA, | 419 | ret = regmap_bulk_read(data->regmap, LTR501_PS_DATA, |
| 416 | &status, 2); | 420 | &status, sizeof(status)); |
| 417 | if (ret < 0) | 421 | if (ret < 0) |
| 418 | return ret; | 422 | return ret; |
| 419 | 423 | ||
| 420 | return status; | 424 | return le16_to_cpu(status); |
| 421 | } | 425 | } |
| 422 | 426 | ||
| 423 | static int ltr501_read_intr_prst(const struct ltr501_data *data, | 427 | static int ltr501_read_intr_prst(const struct ltr501_data *data, |
| @@ -735,7 +739,7 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, · 311 unmodified lines | |||
| 735 | { | 739 | { |
| 736 | struct ltr501_data *data = iio_priv(indio_dev); | 740 | struct ltr501_data *data = iio_priv(indio_dev); |
| 737 | int i, ret, freq_val, freq_val2; | 741 | int i, ret, freq_val, freq_val2; |
| 738 | struct ltr501_chip_info *info = data->chip_info; | 742 | const struct ltr501_chip_info *info = data->chip_info; |
| 739 | 743 | ||
| 740 | ret = iio_device_claim_direct_mode(indio_dev); | 744 | ret = iio_device_claim_direct_mode(indio_dev); |
| 741 | if (ret) | 745 | if (ret) |
| @@ -1082,7 +1086,7 @@ static ssize_t ltr501_show_proximity_scale_avail(struct device *dev, · 340 unmodified lines | |||
| 1082 | char *buf) | 1086 | char *buf) |
| 1083 | { | 1087 | { |
| 1084 | struct ltr501_data *data = iio_priv(dev_to_iio_dev(dev)); | 1088 | struct ltr501_data *data = iio_priv(dev_to_iio_dev(dev)); |
| 1085 | struct ltr501_chip_info *info = data->chip_info; | 1089 | const struct ltr501_chip_info *info = data->chip_info; |
| 1086 | ssize_t len = 0; | 1090 | ssize_t len = 0; |
| 1087 | int i; | 1091 | int i; |
| 1088 | 1092 | ||
| @@ -1104,7 +1108,7 @@ static ssize_t ltr501_show_intensity_scale_avail(struct device *dev, · 15 unmodified lines | |||
| 1104 | char *buf) | 1108 | char *buf) |
| 1105 | { | 1109 | { |
| 1106 | struct ltr501_data *data = iio_priv(dev_to_iio_dev(dev)); | 1110 | struct ltr501_data *data = iio_priv(dev_to_iio_dev(dev)); |
| 1107 | struct ltr501_chip_info *info = data->chip_info; | 1111 | const struct ltr501_chip_info *info = data->chip_info; |
| 1108 | ssize_t len = 0; | 1112 | ssize_t len = 0; |
| 1109 | int i; | 1113 | int i; |
| 1110 | 1114 | ||
| @@ -1184,7 +1188,7 @@ static const struct iio_info ltr301_info = { · 73 unmodified lines | |||
| 1184 | .write_event_config = <r501_write_event_config, | 1188 | .write_event_config = <r501_write_event_config, |
| 1185 | }; | 1189 | }; |
| 1186 | 1190 | ||
| 1187 | static struct ltr501_chip_info ltr501_chip_info_tbl[] = { | 1191 | static const struct ltr501_chip_info ltr501_chip_info_tbl[] = { |
| 1188 | [ltr501] = { | 1192 | [ltr501] = { |
| 1189 | .partid = 0x08, | 1193 | .partid = 0x08, |
| 1190 | .als_gain = ltr501_als_gain_tbl, | 1194 | .als_gain = ltr501_als_gain_tbl, |
| @@ -1205,7 +1209,7 @@ static struct ltr501_chip_info ltr501_chip_info_tbl[] = { · 14 unmodified lines | |||
| 1205 | .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl), | 1209 | .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl), |
| 1206 | .ps_gain = ltr559_ps_gain_tbl, | 1210 | .ps_gain = ltr559_ps_gain_tbl, |
| 1207 | .ps_gain_tbl_size = ARRAY_SIZE(ltr559_ps_gain_tbl), | 1211 | .ps_gain_tbl_size = ARRAY_SIZE(ltr559_ps_gain_tbl), |
| 1208 | .als_mode_active = BIT(1), | 1212 | .als_mode_active = BIT(0), |
| 1209 | .als_gain_mask = BIT(2) | BIT(3) | BIT(4), | 1213 | .als_gain_mask = BIT(2) | BIT(3) | BIT(4), |
| 1210 | .als_gain_shift = 2, | 1214 | .als_gain_shift = 2, |
| 1211 | .info = <r501_info, | 1215 | .info = <r501_info, |
| @@ -1354,9 +1358,12 @@ static bool ltr501_is_volatile_reg(struct device *dev, unsigned int reg) · 142 unmodified lines | |||
| 1354 | { | 1358 | { |
| 1355 | switch (reg) { | 1359 | switch (reg) { |
| 1356 | case LTR501_ALS_DATA1: | 1360 | case LTR501_ALS_DATA1: |
| 1361 | case LTR501_ALS_DATA1_UPPER: | ||
| 1357 | case LTR501_ALS_DATA0: | 1362 | case LTR501_ALS_DATA0: |
| 1363 | case LTR501_ALS_DATA0_UPPER: | ||
| 1358 | case LTR501_ALS_PS_STATUS: | 1364 | case LTR501_ALS_PS_STATUS: |
| 1359 | case LTR501_PS_DATA: | 1365 | case LTR501_PS_DATA: |
| 1366 | case LTR501_PS_DATA_UPPER: | ||
| 1360 | return true; | 1367 | return true; |
| 1361 | default: | 1368 | default: |
| 1362 | return false; | 1369 | return false; |
| @@ -186,9 +186,7 @@ static int pa12203001_set_power_state(struct pa12203001_data *data, bool on, · 185 unmodified lines | |||
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | if (on) { | 188 | if (on) { |
| 189 | ret = pm_runtime_get_sync(&data->client->dev); | 189 | ret = pm_runtime_resume_and_get(&data->client->dev); |
| 190 | if (ret < 0) | ||
| 191 | pm_runtime_put_noidle(&data->client->dev); | ||
| 192 | 190 | ||
| 193 | } else { | 191 | } else { |
| 194 | pm_runtime_mark_last_busy(&data->client->dev); | 192 | pm_runtime_mark_last_busy(&data->client->dev); |
| @@ -360,7 +360,7 @@ static int rpr0521_set_power_state(struct rpr0521_data *data, bool on, · 359 unmodified lines | |||
| 360 | * both stay enabled until _suspend(). | 360 | * both stay enabled until _suspend(). |
| 361 | */ | 361 | */ |
| 362 | if (on) { | 362 | if (on) { |
| 363 | ret = pm_runtime_get_sync(&data->client->dev); | 363 | ret = pm_runtime_resume_and_get(&data->client->dev); |
| 364 | } else { | 364 | } else { |
| 365 | pm_runtime_mark_last_busy(&data->client->dev); | 365 | pm_runtime_mark_last_busy(&data->client->dev); |
| 366 | ret = pm_runtime_put_autosuspend(&data->client->dev); | 366 | ret = pm_runtime_put_autosuspend(&data->client->dev); |
| @@ -369,9 +369,6 @@ static int rpr0521_set_power_state(struct rpr0521_data *data, bool on, · 2 unmodified lines | |||
| 369 | dev_err(&data->client->dev, | 369 | dev_err(&data->client->dev, |
| 370 | "Failed: rpr0521_set_power_state for %d, ret %d\n", | 370 | "Failed: rpr0521_set_power_state for %d, ret %d\n", |
| 371 | on, ret); | 371 | on, ret); |
| 372 | if (on) | ||
| 373 | pm_runtime_put_noidle(&data->client->dev); | ||
| 374 | |||
| 375 | return ret; | 372 | return ret; |
| 376 | } | 373 | } |
| 377 | 374 | ||
| @@ -985,7 +982,7 @@ static int rpr0521_probe(struct i2c_client *client, · 607 unmodified lines | |||
| 985 | /* Trigger0 producer setup */ | 982 | /* Trigger0 producer setup */ |
| 986 | data->drdy_trigger0 = devm_iio_trigger_alloc( | 983 | data->drdy_trigger0 = devm_iio_trigger_alloc( |
| 987 | indio_dev->dev.parent, | 984 | indio_dev->dev.parent, |
| 988 | "%s-dev%d", indio_dev->name, indio_dev->id); | 985 | "%s-dev%d", indio_dev->name, iio_device_id(indio_dev)); |
| 989 | if (!data->drdy_trigger0) { | 986 | if (!data->drdy_trigger0) { |
| 990 | ret = -ENOMEM; | 987 | ret = -ENOMEM; |
| 991 | goto err_pm_disable; | 988 | goto err_pm_disable; |
| @@ -1038,7 +1035,6 @@ static int rpr0521_probe(struct i2c_client *client, · 46 unmodified lines | |||
| 1038 | err_pm_disable: | 1035 | err_pm_disable: |
| 1039 | pm_runtime_disable(&client->dev); | 1036 | pm_runtime_disable(&client->dev); |
| 1040 | pm_runtime_set_suspended(&client->dev); | 1037 | pm_runtime_set_suspended(&client->dev); |
| 1041 | pm_runtime_put_noidle(&client->dev); | ||
| 1042 | err_poweroff: | 1038 | err_poweroff: |
| 1043 | rpr0521_poweroff(data); | 1039 | rpr0521_poweroff(data); |
| 1044 | 1040 | ||
| @@ -1053,7 +1049,6 @@ static int rpr0521_remove(struct i2c_client *client) · 8 unmodified lines | |||
| 1053 | 1049 | ||
| 1054 | pm_runtime_disable(&client->dev); | 1050 | pm_runtime_disable(&client->dev); |
| 1055 | pm_runtime_set_suspended(&client->dev); | 1051 | pm_runtime_set_suspended(&client->dev); |
| 1056 | pm_runtime_put_noidle(&client->dev); | ||
| 1057 | 1052 | ||
| 1058 | rpr0521_poweroff(iio_priv(indio_dev)); | 1053 | rpr0521_poweroff(iio_priv(indio_dev)); |
| 1059 | 1054 | ||
| @@ -352,22 +352,22 @@ static int si1133_parse_response_err(struct device *dev, u32 resp, u8 cmd) · 351 unmodified lines | |||
| 352 | 352 | ||
| 353 | switch (resp) { | 353 | switch (resp) { |
| 354 | case SI1133_ERR_OUTPUT_BUFFER_OVERFLOW: | 354 | case SI1133_ERR_OUTPUT_BUFFER_OVERFLOW: |
| 355 | dev_warn(dev, "Output buffer overflow: %#02hhx\n", cmd); | 355 | dev_warn(dev, "Output buffer overflow: 0x%02x\n", cmd); |
| 356 | return -EOVERFLOW; | 356 | return -EOVERFLOW; |
| 357 | case SI1133_ERR_SATURATION_ADC_OR_OVERFLOW_ACCUMULATION: | 357 | case SI1133_ERR_SATURATION_ADC_OR_OVERFLOW_ACCUMULATION: |
| 358 | dev_warn(dev, "Saturation of the ADC or overflow of accumulation: %#02hhx\n", | 358 | dev_warn(dev, "Saturation of the ADC or overflow of accumulation: 0x%02x\n", |
| 359 | cmd); | 359 | cmd); |
| 360 | return -EOVERFLOW; | 360 | return -EOVERFLOW; |
| 361 | case SI1133_ERR_INVALID_LOCATION_CMD: | 361 | case SI1133_ERR_INVALID_LOCATION_CMD: |
| 362 | dev_warn(dev, | 362 | dev_warn(dev, |
| 363 | "Parameter access to an invalid location: %#02hhx\n", | 363 | "Parameter access to an invalid location: 0x%02x\n", |
| 364 | cmd); | 364 | cmd); |
| 365 | return -EINVAL; | 365 | return -EINVAL; |
| 366 | case SI1133_ERR_INVALID_CMD: | 366 | case SI1133_ERR_INVALID_CMD: |
| 367 | dev_warn(dev, "Invalid command %#02hhx\n", cmd); | 367 | dev_warn(dev, "Invalid command 0x%02x\n", cmd); |
| 368 | return -EINVAL; | 368 | return -EINVAL; |
| 369 | default: | 369 | default: |
| 370 | dev_warn(dev, "Unknown error %#02hhx\n", cmd); | 370 | dev_warn(dev, "Unknown error 0x%02x\n", cmd); |
| 371 | return -EINVAL; | 371 | return -EINVAL; |
| 372 | } | 372 | } |
| 373 | } | 373 | } |
| @@ -400,7 +400,7 @@ static int si1133_command(struct si1133_data *data, u8 cmd) · 26 unmodified lines | |||
| 400 | 400 | ||
| 401 | err = regmap_write(data->regmap, SI1133_REG_COMMAND, cmd); | 401 | err = regmap_write(data->regmap, SI1133_REG_COMMAND, cmd); |
| 402 | if (err) { | 402 | if (err) { |
| 403 | dev_warn(dev, "Failed to write command %#02hhx, ret=%d\n", cmd, | 403 | dev_warn(dev, "Failed to write command 0x%02x, ret=%d\n", cmd, |
| 404 | err); | 404 | err); |
| 405 | goto out; | 405 | goto out; |
| 406 | } | 406 | } |
| @@ -425,7 +425,7 @@ static int si1133_command(struct si1133_data *data, u8 cmd) · 18 unmodified lines | |||
| 425 | SI1133_CMD_TIMEOUT_MS * 1000); | 425 | SI1133_CMD_TIMEOUT_MS * 1000); |
| 426 | if (err) { | 426 | if (err) { |
| 427 | dev_warn(dev, | 427 | dev_warn(dev, |
| 428 | "Failed to read command %#02hhx, ret=%d\n", | 428 | "Failed to read command 0x%02x, ret=%d\n", |
| 429 | cmd, err); | 429 | cmd, err); |
| 430 | goto out; | 430 | goto out; |
| 431 | } | 431 | } |
| @@ -978,11 +978,11 @@ static int si1133_validate_ids(struct iio_dev *iio_dev) · 546 unmodified lines | |||
| 978 | return err; | 978 | return err; |
| 979 | 979 | ||
| 980 | dev_info(&iio_dev->dev, | 980 | dev_info(&iio_dev->dev, |
| 981 | "Device ID part %#02hhx rev %#02hhx mfr %#02hhx\n", | 981 | "Device ID part 0x%02x rev 0x%02x mfr 0x%02x\n", |
| 982 | part_id, rev_id, mfr_id); | 982 | part_id, rev_id, mfr_id); |
| 983 | if (part_id != SI1133_PART_ID) { | 983 | if (part_id != SI1133_PART_ID) { |
| 984 | dev_err(&iio_dev->dev, | 984 | dev_err(&iio_dev->dev, |
| 985 | "Part ID mismatch got %#02hhx, expected %#02x\n", | 985 | "Part ID mismatch got 0x%02x, expected 0x%02x\n", |
| 986 | part_id, SI1133_PART_ID); | 986 | part_id, SI1133_PART_ID); |
| 987 | return -ENODEV; | 987 | return -ENODEV; |
| 988 | } | 988 | } |
| @@ -271,7 +271,7 @@ static int si1145_command(struct si1145_data *data, u8 cmd) · 270 unmodified lines | |||
| 271 | if ((ret & ~SI1145_RSP_COUNTER_MASK) == 0) { | 271 | if ((ret & ~SI1145_RSP_COUNTER_MASK) == 0) { |
| 272 | if (ret == data->rsp_seq) { | 272 | if (ret == data->rsp_seq) { |
| 273 | if (time_after(jiffies, stop_jiffies)) { | 273 | if (time_after(jiffies, stop_jiffies)) { |
| 274 | dev_warn(dev, "timeout on command %#02hhx\n", | 274 | dev_warn(dev, "timeout on command 0x%02x\n", |
| 275 | cmd); | 275 | cmd); |
| 276 | ret = -ETIMEDOUT; | 276 | ret = -ETIMEDOUT; |
| 277 | break; | 277 | break; |
| @@ -291,12 +291,12 @@ static int si1145_command(struct si1145_data *data, u8 cmd) · 13 unmodified lines | |||
| 291 | ret = -EIO; | 291 | ret = -EIO; |
| 292 | } else { | 292 | } else { |
| 293 | if (ret == SI1145_RSP_INVALID_SETTING) { | 293 | if (ret == SI1145_RSP_INVALID_SETTING) { |
| 294 | dev_warn(dev, "INVALID_SETTING error on command %#02hhx\n", | 294 | dev_warn(dev, "INVALID_SETTING error on command 0x%02x\n", |
| 295 | cmd); | 295 | cmd); |
| 296 | ret = -EINVAL; | 296 | ret = -EINVAL; |
| 297 | } else { | 297 | } else { |
| 298 | /* All overflows are treated identically */ | 298 | /* All overflows are treated identically */ |
| 299 | dev_dbg(dev, "overflow, ret=%d, cmd=%#02hhx\n", | 299 | dev_dbg(dev, "overflow, ret=%d, cmd=0x%02x\n", |
| 300 | ret, cmd); | 300 | ret, cmd); |
| 301 | ret = -EOVERFLOW; | 301 | ret = -EOVERFLOW; |
| 302 | } | 302 | } |
| @@ -1243,7 +1243,7 @@ static int si1145_probe_trigger(struct iio_dev *indio_dev) · 940 unmodified lines | |||
| 1243 | int ret; | 1243 | int ret; |
| 1244 | 1244 | ||
| 1245 | trig = devm_iio_trigger_alloc(&client->dev, | 1245 | trig = devm_iio_trigger_alloc(&client->dev, |
| 1246 | "%s-dev%d", indio_dev->name, indio_dev->id); | 1246 | "%s-dev%d", indio_dev->name, iio_device_id(indio_dev)); |
| 1247 | if (!trig) | 1247 | if (!trig) |
| 1248 | return -ENOMEM; | 1248 | return -ENOMEM; |
| 1249 | 1249 | ||
| @@ -1299,10 +1299,10 @@ static int si1145_probe(struct i2c_client *client, · 49 unmodified lines | |||
| 1299 | SI1145_REG_SEQ_ID); | 1299 | SI1145_REG_SEQ_ID); |
| 1300 | if (ret < 0) | 1300 | if (ret < 0) |
| 1301 | return ret; | 1301 | return ret; |
| 1302 | dev_info(&client->dev, "device ID part %#02hhx rev %#02hhx seq %#02hhx\n", | 1302 | dev_info(&client->dev, "device ID part 0x%02x rev 0x%02x seq 0x%02x\n", |
| 1303 | part_id, rev_id, seq_id); | 1303 | part_id, rev_id, seq_id); |
| 1304 | if (part_id != data->part_info->part) { | 1304 | if (part_id != data->part_info->part) { |
| 1305 | dev_err(&client->dev, "part ID mismatch got %#02hhx, expected %#02x\n", | 1305 | dev_err(&client->dev, "part ID mismatch got 0x%02x, expected 0x%02x\n", |
| 1306 | part_id, data->part_info->part); | 1306 | part_id, data->part_info->part); |
| 1307 | return -ENODEV; | 1307 | return -ENODEV; |
| 1308 | } | 1308 | } |
| @@ -53,7 +53,11 @@ struct tcs3414_data { · 52 unmodified lines | |||
| 53 | u8 control; | 53 | u8 control; |
| 54 | u8 gain; | 54 | u8 gain; |
| 55 | u8 timing; | 55 | u8 timing; |
| 56 | u16 buffer[8]; /* 4x 16-bit + 8 bytes timestamp */ | 56 | /* Ensure timestamp is naturally aligned */ |
| 57 | struct { | ||
| 58 | u16 chans[4]; | ||
| 59 | s64 timestamp __aligned(8); | ||
| 60 | } scan; | ||
| 57 | }; | 61 | }; |
| 58 | 62 | ||
| 59 | #define TCS3414_CHANNEL(_color, _si, _addr) { \ | 63 | #define TCS3414_CHANNEL(_color, _si, _addr) { \ |
| @@ -209,10 +213,10 @@ static irqreturn_t tcs3414_trigger_handler(int irq, void *p) · 149 unmodified lines | |||
| 209 | if (ret < 0) | 213 | if (ret < 0) |
| 210 | goto done; | 214 | goto done; |
| 211 | 215 | ||
| 212 | data->buffer[j++] = ret; | 216 | data->scan.chans[j++] = ret; |
| 213 | } | 217 | } |
| 214 | 218 | ||
| 215 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 219 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, |
| 216 | iio_get_time_ns(indio_dev)); | 220 | iio_get_time_ns(indio_dev)); |
| 217 | 221 | ||
| 218 | done: | 222 | done: |
| @@ -64,7 +64,11 @@ struct tcs3472_data { · 63 unmodified lines | |||
| 64 | u8 control; | 64 | u8 control; |
| 65 | u8 atime; | 65 | u8 atime; |
| 66 | u8 apers; | 66 | u8 apers; |
| 67 | u16 buffer[8]; /* 4 16-bit channels + 64-bit timestamp */ | 67 | /* Ensure timestamp is naturally aligned */ |
| 68 | struct { | ||
| 69 | u16 chans[4]; | ||
| 70 | s64 timestamp __aligned(8); | ||
| 71 | } scan; | ||
| 68 | }; | 72 | }; |
| 69 | 73 | ||
| 70 | static const struct iio_event_spec tcs3472_events[] = { | 74 | static const struct iio_event_spec tcs3472_events[] = { |
| @@ -386,10 +390,10 @@ static irqreturn_t tcs3472_trigger_handler(int irq, void *p) · 315 unmodified lines | |||
| 386 | if (ret < 0) | 390 | if (ret < 0) |
| 387 | goto done; | 391 | goto done; |
| 388 | 392 | ||
| 389 | data->buffer[j++] = ret; | 393 | data->scan.chans[j++] = ret; |
| 390 | } | 394 | } |
| 391 | 395 | ||
| 392 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 396 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, |
| 393 | iio_get_time_ns(indio_dev)); | 397 | iio_get_time_ns(indio_dev)); |
| 394 | 398 | ||
| 395 | done: | 399 | done: |
| @@ -531,7 +535,8 @@ static int tcs3472_probe(struct i2c_client *client, · 135 unmodified lines | |||
| 531 | return 0; | 535 | return 0; |
| 532 | 536 | ||
| 533 | free_irq: | 537 | free_irq: |
| 534 | free_irq(client->irq, indio_dev); | 538 | if (client->irq) |
| 539 | free_irq(client->irq, indio_dev); | ||
| 535 | buffer_cleanup: | 540 | buffer_cleanup: |
| 536 | iio_triggered_buffer_cleanup(indio_dev); | 541 | iio_triggered_buffer_cleanup(indio_dev); |
| 537 | return ret; | 542 | return ret; |
| @@ -559,7 +564,8 @@ static int tcs3472_remove(struct i2c_client *client) · 21 unmodified lines | |||
| 559 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | 564 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 560 | 565 | ||
| 561 | iio_device_unregister(indio_dev); | 566 | iio_device_unregister(indio_dev); |
| 562 | free_irq(client->irq, indio_dev); | 567 | if (client->irq) |
| 568 | free_irq(client->irq, indio_dev); | ||
| 563 | iio_triggered_buffer_cleanup(indio_dev); | 569 | iio_triggered_buffer_cleanup(indio_dev); |
| 564 | tcs3472_powerdown(iio_priv(indio_dev)); | 570 | tcs3472_powerdown(iio_priv(indio_dev)); |
| 565 | 571 | ||
| @@ -644,9 +644,7 @@ static int tsl2583_set_pm_runtime_busy(struct tsl2583_chip *chip, bool on) · 643 unmodified lines | |||
| 644 | int ret; | 644 | int ret; |
| 645 | 645 | ||
| 646 | if (on) { | 646 | if (on) { |
| 647 | ret = pm_runtime_get_sync(&chip->client->dev); | 647 | ret = pm_runtime_resume_and_get(&chip->client->dev); |
| 648 | if (ret < 0) | ||
| 649 | pm_runtime_put_noidle(&chip->client->dev); | ||
| 650 | } else { | 648 | } else { |
| 651 | pm_runtime_mark_last_busy(&chip->client->dev); | 649 | pm_runtime_mark_last_busy(&chip->client->dev); |
| 652 | ret = pm_runtime_put_autosuspend(&chip->client->dev); | 650 | ret = pm_runtime_put_autosuspend(&chip->client->dev); |
| @@ -729,8 +727,10 @@ static int tsl2583_read_raw(struct iio_dev *indio_dev, · 76 unmodified lines | |||
| 729 | read_done: | 727 | read_done: |
| 730 | mutex_unlock(&chip->als_mutex); | 728 | mutex_unlock(&chip->als_mutex); |
| 731 | 729 | ||
| 732 | if (ret < 0) | 730 | if (ret < 0) { |
| 731 | tsl2583_set_pm_runtime_busy(chip, false); | ||
| 733 | return ret; | 732 | return ret; |
| 733 | } | ||
| 734 | 734 | ||
| 735 | /* | 735 | /* |
| 736 | * Preserve the ret variable if the call to | 736 | * Preserve the ret variable if the call to |
| @@ -791,8 +791,10 @@ static int tsl2583_write_raw(struct iio_dev *indio_dev, · 54 unmodified lines | |||
| 791 | 791 | ||
| 792 | mutex_unlock(&chip->als_mutex); | 792 | mutex_unlock(&chip->als_mutex); |
| 793 | 793 | ||
| 794 | if (ret < 0) | 794 | if (ret < 0) { |
| 795 | tsl2583_set_pm_runtime_busy(chip, false); | ||
| 795 | return ret; | 796 | return ret; |
| 797 | } | ||
| 796 | 798 | ||
| 797 | ret = tsl2583_set_pm_runtime_busy(chip, false); | 799 | ret = tsl2583_set_pm_runtime_busy(chip, false); |
| 798 | if (ret < 0) | 800 | if (ret < 0) |
| @@ -880,7 +882,6 @@ static int tsl2583_remove(struct i2c_client *client) · 81 unmodified lines | |||
| 880 | 882 | ||
| 881 | pm_runtime_disable(&client->dev); | 883 | pm_runtime_disable(&client->dev); |
| 882 | pm_runtime_set_suspended(&client->dev); | 884 | pm_runtime_set_suspended(&client->dev); |
| 883 | pm_runtime_put_noidle(&client->dev); | ||
| 884 | 885 | ||
| 885 | return tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_OFF); | 886 | return tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_OFF); |
| 886 | } | 887 | } |
| @@ -0,0 +1,1225 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021 Joe Sandom <joe.g.sandom@gmail.com> | ||
| 4 | * | ||
| 5 | * Datasheet: https://ams.com/tsl25911#tab/documents | ||
| 6 | * | ||
| 7 | * Device driver for the TAOS TSL2591. This is a very-high sensitivity | ||
| 8 | * light-to-digital converter that transforms light intensity into a digital | ||
| 9 | * signal. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/bitfield.h> | ||
| 13 | #include <linux/debugfs.h> | ||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/i2c.h> | ||
| 16 | #include <linux/interrupt.h> | ||
| 17 | #include <linux/iopoll.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/mutex.h> | ||
| 21 | #include <linux/pm_runtime.h> | ||
| 22 | #include <linux/sysfs.h> | ||
| 23 | |||
| 24 | #include <asm/unaligned.h> | ||
| 25 | |||
| 26 | #include <linux/iio/events.h> | ||
| 27 | #include <linux/iio/iio.h> | ||
| 28 | #include <linux/iio/sysfs.h> | ||
| 29 | |||
| 30 | /* ADC integration time, field value to time in ms */ | ||
| 31 | #define TSL2591_FVAL_TO_MSEC(x) (((x) + 1) * 100) | ||
| 32 | /* ADC integration time, field value to time in seconds */ | ||
| 33 | #define TSL2591_FVAL_TO_SEC(x) ((x) + 1) | ||
| 34 | /* ADC integration time, time in seconds to field value */ | ||
| 35 | #define TSL2591_SEC_TO_FVAL(x) ((x) - 1) | ||
| 36 | |||
| 37 | /* TSL2591 register set */ | ||
| 38 | #define TSL2591_ENABLE 0x00 | ||
| 39 | #define TSL2591_CONTROL 0x01 | ||
| 40 | #define TSL2591_AILTL 0x04 | ||
| 41 | #define TSL2591_AILTH 0x05 | ||
| 42 | #define TSL2591_AIHTL 0x06 | ||
| 43 | #define TSL2591_AIHTH 0x07 | ||
| 44 | #define TSL2591_NP_AILTL 0x08 | ||
| 45 | #define TSL2591_NP_AILTH 0x09 | ||
| 46 | #define TSL2591_NP_AIHTL 0x0A | ||
| 47 | #define TSL2591_NP_AIHTH 0x0B | ||
| 48 | #define TSL2591_PERSIST 0x0C | ||
| 49 | #define TSL2591_PACKAGE_ID 0x11 | ||
| 50 | #define TSL2591_DEVICE_ID 0x12 | ||
| 51 | #define TSL2591_STATUS 0x13 | ||
| 52 | #define TSL2591_C0_DATAL 0x14 | ||
| 53 | #define TSL2591_C0_DATAH 0x15 | ||
| 54 | #define TSL2591_C1_DATAL 0x16 | ||
| 55 | #define TSL2591_C1_DATAH 0x17 | ||
| 56 | |||
| 57 | /* TSL2591 command register definitions */ | ||
| 58 | #define TSL2591_CMD_NOP 0xA0 | ||
| 59 | #define TSL2591_CMD_SF_INTSET 0xE4 | ||
| 60 | #define TSL2591_CMD_SF_CALS_I 0xE5 | ||
| 61 | #define TSL2591_CMD_SF_CALS_NPI 0xE7 | ||
| 62 | #define TSL2591_CMD_SF_CNP_ALSI 0xEA | ||
| 63 | |||
| 64 | /* TSL2591 enable register definitions */ | ||
| 65 | #define TSL2591_PWR_ON 0x01 | ||
| 66 | #define TSL2591_PWR_OFF 0x00 | ||
| 67 | #define TSL2591_ENABLE_ALS 0x02 | ||
| 68 | #define TSL2591_ENABLE_ALS_INT 0x10 | ||
| 69 | #define TSL2591_ENABLE_SLEEP_INT 0x40 | ||
| 70 | #define TSL2591_ENABLE_NP_INT 0x80 | ||
| 71 | |||
| 72 | /* TSL2591 control register definitions */ | ||
| 73 | #define TSL2591_CTRL_ALS_INTEGRATION_100MS 0x00 | ||
| 74 | #define TSL2591_CTRL_ALS_INTEGRATION_200MS 0x01 | ||
| 75 | #define TSL2591_CTRL_ALS_INTEGRATION_300MS 0x02 | ||
| 76 | #define TSL2591_CTRL_ALS_INTEGRATION_400MS 0x03 | ||
| 77 | #define TSL2591_CTRL_ALS_INTEGRATION_500MS 0x04 | ||
| 78 | #define TSL2591_CTRL_ALS_INTEGRATION_600MS 0x05 | ||
| 79 | #define TSL2591_CTRL_ALS_LOW_GAIN 0x00 | ||
| 80 | #define TSL2591_CTRL_ALS_MED_GAIN 0x10 | ||
| 81 | #define TSL2591_CTRL_ALS_HIGH_GAIN 0x20 | ||
| 82 | #define TSL2591_CTRL_ALS_MAX_GAIN 0x30 | ||
| 83 | #define TSL2591_CTRL_SYS_RESET 0x80 | ||
| 84 | |||
| 85 | /* TSL2591 persist register definitions */ | ||
| 86 | #define TSL2591_PRST_ALS_INT_CYCLE_0 0x00 | ||
| 87 | #define TSL2591_PRST_ALS_INT_CYCLE_ANY 0x01 | ||
| 88 | #define TSL2591_PRST_ALS_INT_CYCLE_2 0x02 | ||
| 89 | #define TSL2591_PRST_ALS_INT_CYCLE_3 0x03 | ||
| 90 | #define TSL2591_PRST_ALS_INT_CYCLE_5 0x04 | ||
| 91 | #define TSL2591_PRST_ALS_INT_CYCLE_10 0x05 | ||
| 92 | #define TSL2591_PRST_ALS_INT_CYCLE_15 0x06 | ||
| 93 | #define TSL2591_PRST_ALS_INT_CYCLE_20 0x07 | ||
| 94 | #define TSL2591_PRST_ALS_INT_CYCLE_25 0x08 | ||
| 95 | #define TSL2591_PRST_ALS_INT_CYCLE_30 0x09 | ||
| 96 | #define TSL2591_PRST_ALS_INT_CYCLE_35 0x0A | ||
| 97 | #define TSL2591_PRST_ALS_INT_CYCLE_40 0x0B | ||
| 98 | #define TSL2591_PRST_ALS_INT_CYCLE_45 0x0C | ||
| 99 | #define TSL2591_PRST_ALS_INT_CYCLE_50 0x0D | ||
| 100 | #define TSL2591_PRST_ALS_INT_CYCLE_55 0x0E | ||
| 101 | #define TSL2591_PRST_ALS_INT_CYCLE_60 0x0F | ||
| 102 | #define TSL2591_PRST_ALS_INT_CYCLE_MAX (BIT(4) - 1) | ||
| 103 | |||
| 104 | /* TSL2591 PID register mask */ | ||
| 105 | #define TSL2591_PACKAGE_ID_MASK GENMASK(5, 4) | ||
| 106 | |||
| 107 | /* TSL2591 ID register mask */ | ||
| 108 | #define TSL2591_DEVICE_ID_MASK GENMASK(7, 0) | ||
| 109 | |||
| 110 | /* TSL2591 status register masks */ | ||
| 111 | #define TSL2591_STS_ALS_VALID_MASK BIT(0) | ||
| 112 | #define TSL2591_STS_ALS_INT_MASK BIT(4) | ||
| 113 | #define TSL2591_STS_NPERS_INT_MASK BIT(5) | ||
| 114 | #define TSL2591_STS_VAL_HIGH_MASK BIT(0) | ||
| 115 | |||
| 116 | /* TSL2591 constant values */ | ||
| 117 | #define TSL2591_PACKAGE_ID_VAL 0x00 | ||
| 118 | #define TSL2591_DEVICE_ID_VAL 0x50 | ||
| 119 | |||
| 120 | /* Power off suspend delay time MS */ | ||
| 121 | #define TSL2591_POWER_OFF_DELAY_MS 2000 | ||
| 122 | |||
| 123 | /* TSL2591 default values */ | ||
| 124 | #define TSL2591_DEFAULT_ALS_INT_TIME TSL2591_CTRL_ALS_INTEGRATION_300MS | ||
| 125 | #define TSL2591_DEFAULT_ALS_GAIN TSL2591_CTRL_ALS_MED_GAIN | ||
| 126 | #define TSL2591_DEFAULT_ALS_PERSIST TSL2591_PRST_ALS_INT_CYCLE_ANY | ||
| 127 | #define TSL2591_DEFAULT_ALS_LOWER_THRESH 100 | ||
| 128 | #define TSL2591_DEFAULT_ALS_UPPER_THRESH 1500 | ||
| 129 | |||
| 130 | /* TSL2591 number of data registers */ | ||
| 131 | #define TSL2591_NUM_DATA_REGISTERS 4 | ||
| 132 | |||
| 133 | /* TSL2591 number of valid status reads on ADC complete */ | ||
| 134 | #define TSL2591_ALS_STS_VALID_COUNT 10 | ||
| 135 | |||
| 136 | /* TSL2591 delay period between polls when checking for ALS valid flag */ | ||
| 137 | #define TSL2591_DELAY_PERIOD_US 10000 | ||
| 138 | |||
| 139 | /* TSL2591 maximum values */ | ||
| 140 | #define TSL2591_MAX_ALS_INT_TIME_MS 600 | ||
| 141 | #define TSL2591_ALS_MAX_VALUE (BIT(16) - 1) | ||
| 142 | |||
| 143 | /* | ||
| 144 | * LUX calculations; | ||
| 145 | * AGAIN values from Adafruit's TSL2591 Arduino library | ||
| 146 | * https://github.com/adafruit/Adafruit_TSL2591_Library | ||
| 147 | */ | ||
| 148 | #define TSL2591_CTRL_ALS_LOW_GAIN_MULTIPLIER 1 | ||
| 149 | #define TSL2591_CTRL_ALS_MED_GAIN_MULTIPLIER 25 | ||
| 150 | #define TSL2591_CTRL_ALS_HIGH_GAIN_MULTIPLIER 428 | ||
| 151 | #define TSL2591_CTRL_ALS_MAX_GAIN_MULTIPLIER 9876 | ||
| 152 | #define TSL2591_LUX_COEFFICIENT 408 | ||
| 153 | |||
| 154 | struct tsl2591_als_settings { | ||
| 155 | u16 als_lower_thresh; | ||
| 156 | u16 als_upper_thresh; | ||
| 157 | u8 als_int_time; | ||
| 158 | u8 als_persist; | ||
| 159 | u8 als_gain; | ||
| 160 | }; | ||
| 161 | |||
| 162 | struct tsl2591_chip { | ||
| 163 | struct tsl2591_als_settings als_settings; | ||
| 164 | struct i2c_client *client; | ||
| 165 | /* | ||
| 166 | * Keep als_settings in sync with hardware state | ||
| 167 | * and ensure multiple readers are serialized. | ||
| 168 | */ | ||
| 169 | struct mutex als_mutex; | ||
| 170 | bool events_enabled; | ||
| 171 | }; | ||
| 172 | |||
| 173 | /* | ||
| 174 | * Period table is ALS persist cycle x integration time setting | ||
| 175 | * Integration times: 100ms, 200ms, 300ms, 400ms, 500ms, 600ms | ||
| 176 | * ALS cycles: 1, 2, 3, 5, 10, 20, 25, 30, 35, 40, 45, 50, 55, 60 | ||
| 177 | */ | ||
| 178 | static const char * const tsl2591_als_period_list[] = { | ||
| 179 | "0.1 0.2 0.3 0.5 1.0 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0", | ||
| 180 | "0.2 0.4 0.6 1.0 2.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0", | ||
| 181 | "0.3 0.6 0.9 1.5 3.0 6.0 7.5 9.0 10.5 12.0 13.5 15.0 16.5 18.0", | ||
| 182 | "0.4 0.8 1.2 2.0 4.0 8.0 10.0 12.0 14.0 16.0 18.0 20.0 22.0 24.0", | ||
| 183 | "0.5 1.0 1.5 2.5 5.0 10.0 12.5 15.0 17.5 20.0 22.5 25.0 27.5 30.0", | ||
| 184 | "0.6 1.2 1.8 3.0 6.0 12.0 15.0 18.0 21.0 24.0 27.0 30.0 33.0 36.0", | ||
| 185 | }; | ||
| 186 | |||
| 187 | static const int tsl2591_int_time_available[] = { | ||
| 188 | 1, 2, 3, 4, 5, 6, | ||
| 189 | }; | ||
| 190 | |||
| 191 | static const int tsl2591_calibscale_available[] = { | ||
| 192 | 1, 25, 428, 9876, | ||
| 193 | }; | ||
| 194 | |||
| 195 | static int tsl2591_set_als_lower_threshold(struct tsl2591_chip *chip, | ||
| 196 | u16 als_lower_threshold); | ||
| 197 | static int tsl2591_set_als_upper_threshold(struct tsl2591_chip *chip, | ||
| 198 | u16 als_upper_threshold); | ||
| 199 | |||
| 200 | static int tsl2591_gain_to_multiplier(const u8 als_gain) | ||
| 201 | { | ||
| 202 | switch (als_gain) { | ||
| 203 | case TSL2591_CTRL_ALS_LOW_GAIN: | ||
| 204 | return TSL2591_CTRL_ALS_LOW_GAIN_MULTIPLIER; | ||
| 205 | case TSL2591_CTRL_ALS_MED_GAIN: | ||
| 206 | return TSL2591_CTRL_ALS_MED_GAIN_MULTIPLIER; | ||
| 207 | case TSL2591_CTRL_ALS_HIGH_GAIN: | ||
| 208 | return TSL2591_CTRL_ALS_HIGH_GAIN_MULTIPLIER; | ||
| 209 | case TSL2591_CTRL_ALS_MAX_GAIN: | ||
| 210 | return TSL2591_CTRL_ALS_MAX_GAIN_MULTIPLIER; | ||
| 211 | default: | ||
| 212 | return -EINVAL; | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | static int tsl2591_multiplier_to_gain(const u32 multiplier) | ||
| 217 | { | ||
| 218 | switch (multiplier) { | ||
| 219 | case TSL2591_CTRL_ALS_LOW_GAIN_MULTIPLIER: | ||
| 220 | return TSL2591_CTRL_ALS_LOW_GAIN; | ||
| 221 | case TSL2591_CTRL_ALS_MED_GAIN_MULTIPLIER: | ||
| 222 | return TSL2591_CTRL_ALS_MED_GAIN; | ||
| 223 | case TSL2591_CTRL_ALS_HIGH_GAIN_MULTIPLIER: | ||
| 224 | return TSL2591_CTRL_ALS_HIGH_GAIN; | ||
| 225 | case TSL2591_CTRL_ALS_MAX_GAIN_MULTIPLIER: | ||
| 226 | return TSL2591_CTRL_ALS_MAX_GAIN; | ||
| 227 | default: | ||
| 228 | return -EINVAL; | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | static int tsl2591_persist_cycle_to_lit(const u8 als_persist) | ||
| 233 | { | ||
| 234 | switch (als_persist) { | ||
| 235 | case TSL2591_PRST_ALS_INT_CYCLE_ANY: | ||
| 236 | return 1; | ||
| 237 | case TSL2591_PRST_ALS_INT_CYCLE_2: | ||
| 238 | return 2; | ||
| 239 | case TSL2591_PRST_ALS_INT_CYCLE_3: | ||
| 240 | return 3; | ||
| 241 | case TSL2591_PRST_ALS_INT_CYCLE_5: | ||
| 242 | return 5; | ||
| 243 | case TSL2591_PRST_ALS_INT_CYCLE_10: | ||
| 244 | return 10; | ||
| 245 | case TSL2591_PRST_ALS_INT_CYCLE_15: | ||
| 246 | return 15; | ||
| 247 | case TSL2591_PRST_ALS_INT_CYCLE_20: | ||
| 248 | return 20; | ||
| 249 | case TSL2591_PRST_ALS_INT_CYCLE_25: | ||
| 250 | return 25; | ||
| 251 | case TSL2591_PRST_ALS_INT_CYCLE_30: | ||
| 252 | return 30; | ||
| 253 | case TSL2591_PRST_ALS_INT_CYCLE_35: | ||
| 254 | return 35; | ||
| 255 | case TSL2591_PRST_ALS_INT_CYCLE_40: | ||
| 256 | return 40; | ||
| 257 | case TSL2591_PRST_ALS_INT_CYCLE_45: | ||
| 258 | return 45; | ||
| 259 | case TSL2591_PRST_ALS_INT_CYCLE_50: | ||
| 260 | return 50; | ||
| 261 | case TSL2591_PRST_ALS_INT_CYCLE_55: | ||
| 262 | return 55; | ||
| 263 | case TSL2591_PRST_ALS_INT_CYCLE_60: | ||
| 264 | return 60; | ||
| 265 | default: | ||
| 266 | return -EINVAL; | ||
| 267 | } | ||
| 268 | } | ||
| 269 | |||
| 270 | static int tsl2591_persist_lit_to_cycle(const u8 als_persist) | ||
| 271 | { | ||
| 272 | switch (als_persist) { | ||
| 273 | case 1: | ||
| 274 | return TSL2591_PRST_ALS_INT_CYCLE_ANY; | ||
| 275 | case 2: | ||
| 276 | return TSL2591_PRST_ALS_INT_CYCLE_2; | ||
| 277 | case 3: | ||
| 278 | return TSL2591_PRST_ALS_INT_CYCLE_3; | ||
| 279 | case 5: | ||
| 280 | return TSL2591_PRST_ALS_INT_CYCLE_5; | ||
| 281 | case 10: | ||
| 282 | return TSL2591_PRST_ALS_INT_CYCLE_10; | ||
| 283 | case 15: | ||
| 284 | return TSL2591_PRST_ALS_INT_CYCLE_15; | ||
| 285 | case 20: | ||
| 286 | return TSL2591_PRST_ALS_INT_CYCLE_20; | ||
| 287 | case 25: | ||
| 288 | return TSL2591_PRST_ALS_INT_CYCLE_25; | ||
| 289 | case 30: | ||
| 290 | return TSL2591_PRST_ALS_INT_CYCLE_30; | ||
| 291 | case 35: | ||
| 292 | return TSL2591_PRST_ALS_INT_CYCLE_35; | ||
| 293 | case 40: | ||
| 294 | return TSL2591_PRST_ALS_INT_CYCLE_40; | ||
| 295 | case 45: | ||
| 296 | return TSL2591_PRST_ALS_INT_CYCLE_45; | ||
| 297 | case 50: | ||
| 298 | return TSL2591_PRST_ALS_INT_CYCLE_50; | ||
| 299 | case 55: | ||
| 300 | return TSL2591_PRST_ALS_INT_CYCLE_55; | ||
| 301 | case 60: | ||
| 302 | return TSL2591_PRST_ALS_INT_CYCLE_60; | ||
| 303 | default: | ||
| 304 | return -EINVAL; | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | static int tsl2591_compatible_int_time(struct tsl2591_chip *chip, | ||
| 309 | const u32 als_integration_time) | ||
| 310 | { | ||
| 311 | switch (als_integration_time) { | ||
| 312 | case TSL2591_CTRL_ALS_INTEGRATION_100MS: | ||
| 313 | case TSL2591_CTRL_ALS_INTEGRATION_200MS: | ||
| 314 | case TSL2591_CTRL_ALS_INTEGRATION_300MS: | ||
| 315 | case TSL2591_CTRL_ALS_INTEGRATION_400MS: | ||
| 316 | case TSL2591_CTRL_ALS_INTEGRATION_500MS: | ||
| 317 | case TSL2591_CTRL_ALS_INTEGRATION_600MS: | ||
| 318 | return 0; | ||
| 319 | default: | ||
| 320 | return -EINVAL; | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | static int tsl2591_als_time_to_fval(const u32 als_integration_time) | ||
| 325 | { | ||
| 326 | int i; | ||
| 327 | |||
| 328 | for (i = 0; i < ARRAY_SIZE(tsl2591_int_time_available); i++) { | ||
| 329 | if (als_integration_time == tsl2591_int_time_available[i]) | ||
| 330 | return TSL2591_SEC_TO_FVAL(als_integration_time); | ||
| 331 | } | ||
| 332 | |||
| 333 | return -EINVAL; | ||
| 334 | } | ||
| 335 | |||
| 336 | static int tsl2591_compatible_gain(struct tsl2591_chip *chip, const u8 als_gain) | ||
| 337 | { | ||
| 338 | switch (als_gain) { | ||
| 339 | case TSL2591_CTRL_ALS_LOW_GAIN: | ||
| 340 | case TSL2591_CTRL_ALS_MED_GAIN: | ||
| 341 | case TSL2591_CTRL_ALS_HIGH_GAIN: | ||
| 342 | case TSL2591_CTRL_ALS_MAX_GAIN: | ||
| 343 | return 0; | ||
| 344 | default: | ||
| 345 | return -EINVAL; | ||
| 346 | } | ||
| 347 | } | ||
| 348 | |||
| 349 | static int tsl2591_compatible_als_persist_cycle(struct tsl2591_chip *chip, | ||
| 350 | const u32 als_persist) | ||
| 351 | { | ||
| 352 | switch (als_persist) { | ||
| 353 | case TSL2591_PRST_ALS_INT_CYCLE_ANY: | ||
| 354 | case TSL2591_PRST_ALS_INT_CYCLE_2: | ||
| 355 | case TSL2591_PRST_ALS_INT_CYCLE_3: | ||
| 356 | case TSL2591_PRST_ALS_INT_CYCLE_5: | ||
| 357 | case TSL2591_PRST_ALS_INT_CYCLE_10: | ||
| 358 | case TSL2591_PRST_ALS_INT_CYCLE_15: | ||
| 359 | case TSL2591_PRST_ALS_INT_CYCLE_20: | ||
| 360 | case TSL2591_PRST_ALS_INT_CYCLE_25: | ||
| 361 | case TSL2591_PRST_ALS_INT_CYCLE_30: | ||
| 362 | case TSL2591_PRST_ALS_INT_CYCLE_35: | ||
| 363 | case TSL2591_PRST_ALS_INT_CYCLE_40: | ||
| 364 | case TSL2591_PRST_ALS_INT_CYCLE_45: | ||
| 365 | case TSL2591_PRST_ALS_INT_CYCLE_50: | ||
| 366 | case TSL2591_PRST_ALS_INT_CYCLE_55: | ||
| 367 | case TSL2591_PRST_ALS_INT_CYCLE_60: | ||
| 368 | return 0; | ||
| 369 | default: | ||
| 370 | return -EINVAL; | ||
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | static int tsl2591_check_als_valid(struct i2c_client *client) | ||
| 375 | { | ||
| 376 | int ret; | ||
| 377 | |||
| 378 | ret = i2c_smbus_read_byte_data(client, TSL2591_CMD_NOP | TSL2591_STATUS); | ||
| 379 | if (ret < 0) { | ||
| 380 | dev_err(&client->dev, "Failed to read register\n"); | ||
| 381 | return -EINVAL; | ||
| 382 | } | ||
| 383 | |||
| 384 | return FIELD_GET(TSL2591_STS_ALS_VALID_MASK, ret); | ||
| 385 | } | ||
| 386 | |||
| 387 | static int tsl2591_wait_adc_complete(struct tsl2591_chip *chip) | ||
| 388 | { | ||
| 389 | struct tsl2591_als_settings settings = chip->als_settings; | ||
| 390 | struct i2c_client *client = chip->client; | ||
| 391 | int delay; | ||
| 392 | int val; | ||
| 393 | int ret; | ||
| 394 | |||
| 395 | delay = TSL2591_FVAL_TO_MSEC(settings.als_int_time); | ||
| 396 | if (!delay) | ||
| 397 | return -EINVAL; | ||
| 398 | |||
| 399 | /* | ||
| 400 | * Sleep for ALS integration time to allow enough time or an ADC read | ||
| 401 | * cycle to complete. Check status after delay for ALS valid. | ||
| 402 | */ | ||
| 403 | msleep(delay); | ||
| 404 | |||
| 405 | /* Check for status ALS valid flag for up to 100ms */ | ||
| 406 | ret = readx_poll_timeout(tsl2591_check_als_valid, client, | ||
| 407 | val, val == TSL2591_STS_VAL_HIGH_MASK, | ||
| 408 | TSL2591_DELAY_PERIOD_US, | ||
| 409 | TSL2591_DELAY_PERIOD_US * TSL2591_ALS_STS_VALID_COUNT); | ||
| 410 | if (ret) | ||
| 411 | dev_err(&client->dev, "Timed out waiting for valid ALS data\n"); | ||
| 412 | |||
| 413 | return ret; | ||
| 414 | } | ||
| 415 | |||
| 416 | /* | ||
| 417 | * tsl2591_read_channel_data - Reads raw channel data and calculates lux | ||
| 418 | * | ||
| 419 | * Formula for lux calculation; | ||
| 420 | * Derived from Adafruit's TSL2591 library | ||
| 421 | * Link: https://github.com/adafruit/Adafruit_TSL2591_Library | ||
| 422 | * Counts Per Lux (CPL) = (ATIME_ms * AGAIN) / LUX DF | ||
| 423 | * lux = ((C0DATA - C1DATA) * (1 - (C1DATA / C0DATA))) / CPL | ||
| 424 | * | ||
| 425 | * Scale values to get more representative value of lux i.e. | ||
| 426 | * lux = ((C0DATA - C1DATA) * (1000 - ((C1DATA * 1000) / C0DATA))) / CPL | ||
| 427 | * | ||
| 428 | * Channel 0 = IR + Visible | ||
| 429 | * Channel 1 = IR only | ||
| 430 | */ | ||
| 431 | static int tsl2591_read_channel_data(struct iio_dev *indio_dev, | ||
| 432 | struct iio_chan_spec const *chan, | ||
| 433 | int *val, int *val2) | ||
| 434 | { | ||
| 435 | struct tsl2591_chip *chip = iio_priv(indio_dev); | ||
| 436 | struct tsl2591_als_settings *settings = &chip->als_settings; | ||
| 437 | struct i2c_client *client = chip->client; | ||
| 438 | u8 als_data[TSL2591_NUM_DATA_REGISTERS]; | ||
| 439 | int counts_per_lux, int_time_fval, gain_multi, lux; | ||
| 440 | u16 als_ch0, als_ch1; | ||
| 441 | int ret; | ||
| 442 | |||
| 443 | ret = tsl2591_wait_adc_complete(chip); | ||
| 444 | if (ret < 0) { | ||
| 445 | dev_err(&client->dev, "No data available. Err: %d\n", ret); | ||
| 446 | return ret; | ||
| 447 | } | ||
| 448 | |||
| 449 | ret = i2c_smbus_read_i2c_block_data(client, | ||
| 450 | TSL2591_CMD_NOP | TSL2591_C0_DATAL, | ||
| 451 | sizeof(als_data), als_data); | ||
| 452 | if (ret < 0) { | ||
| 453 | dev_err(&client->dev, "Failed to read data bytes"); | ||
| 454 | return ret; | ||
| 455 | } | ||
| 456 | |||
| 457 | als_ch0 = get_unaligned_le16(&als_data[0]); | ||
| 458 | als_ch1 = get_unaligned_le16(&als_data[2]); | ||
| 459 | |||
| 460 | switch (chan->type) { | ||
| 461 | case IIO_INTENSITY: | ||
| 462 | if (chan->channel2 == IIO_MOD_LIGHT_BOTH) | ||
| 463 | *val = als_ch0; | ||
| 464 | else if (chan->channel2 == IIO_MOD_LIGHT_IR) | ||
| 465 | *val = als_ch1; | ||
| 466 | else | ||
| 467 | return -EINVAL; | ||
| 468 | break; | ||
| 469 | case IIO_LIGHT: | ||
| 470 | gain_multi = tsl2591_gain_to_multiplier(settings->als_gain); | ||
| 471 | if (gain_multi < 0) { | ||
| 472 | dev_err(&client->dev, "Invalid multiplier"); | ||
| 473 | return gain_multi; | ||
| 474 | } | ||
| 475 | |||
| 476 | int_time_fval = TSL2591_FVAL_TO_MSEC(settings->als_int_time); | ||
| 477 | /* Calculate counts per lux value */ | ||
| 478 | counts_per_lux = (int_time_fval * gain_multi) / TSL2591_LUX_COEFFICIENT; | ||
| 479 | |||
| 480 | dev_dbg(&client->dev, "Counts Per Lux: %d\n", counts_per_lux); | ||
| 481 | |||
| 482 | /* Calculate lux value */ | ||
| 483 | lux = ((als_ch0 - als_ch1) * | ||
| 484 | (1000 - ((als_ch1 * 1000) / als_ch0))) / counts_per_lux; | ||
| 485 | |||
| 486 | dev_dbg(&client->dev, "Raw lux calculation: %d\n", lux); | ||
| 487 | |||
| 488 | /* Divide by 1000 to get real lux value before scaling */ | ||
| 489 | *val = lux / 1000; | ||
| 490 | |||
| 491 | /* Get the decimal part of lux reading */ | ||
| 492 | *val2 = (lux - (*val * 1000)) * 1000; | ||
| 493 | |||
| 494 | break; | ||
| 495 | default: | ||
| 496 | return -EINVAL; | ||
| 497 | } | ||
| 498 | |||
| 499 | return 0; | ||
| 500 | } | ||
| 501 | |||
| 502 | static int tsl2591_set_als_gain_int_time(struct tsl2591_chip *chip) | ||
| 503 | { | ||
| 504 | struct tsl2591_als_settings als_settings = chip->als_settings; | ||
| 505 | struct i2c_client *client = chip->client; | ||
| 506 | int ret; | ||
| 507 | |||
| 508 | ret = i2c_smbus_write_byte_data(client, | ||
| 509 | TSL2591_CMD_NOP | TSL2591_CONTROL, | ||
| 510 | als_settings.als_int_time | als_settings.als_gain); | ||
| 511 | if (ret) | ||
| 512 | dev_err(&client->dev, "Failed to set als gain & int time\n"); | ||
| 513 | |||
| 514 | return ret; | ||
| 515 | } | ||
| 516 | |||
| 517 | static int tsl2591_set_als_lower_threshold(struct tsl2591_chip *chip, | ||
| 518 | u16 als_lower_threshold) | ||
| 519 | { | ||
| 520 | struct tsl2591_als_settings als_settings = chip->als_settings; | ||
| 521 | struct i2c_client *client = chip->client; | ||
| 522 | u16 als_upper_threshold; | ||
| 523 | u8 als_lower_l; | ||
| 524 | u8 als_lower_h; | ||
| 525 | int ret; | ||
| 526 | |||
| 527 | chip->als_settings.als_lower_thresh = als_lower_threshold; | ||
| 528 | |||
| 529 | /* | ||
| 530 | * Lower threshold should not be greater or equal to upper. | ||
| 531 | * If this is the case, then assert upper threshold to new lower | ||
| 532 | * threshold + 1 to avoid ordering issues when setting thresholds. | ||
| 533 | */ | ||
| 534 | if (als_lower_threshold >= als_settings.als_upper_thresh) { | ||
| 535 | als_upper_threshold = als_lower_threshold + 1; | ||
| 536 | tsl2591_set_als_upper_threshold(chip, als_upper_threshold); | ||
| 537 | } | ||
| 538 | |||
| 539 | als_lower_l = als_lower_threshold; | ||
| 540 | als_lower_h = als_lower_threshold >> 8; | ||
| 541 | |||
| 542 | ret = i2c_smbus_write_byte_data(client, | ||
| 543 | TSL2591_CMD_NOP | TSL2591_AILTL, | ||
| 544 | als_lower_l); | ||
| 545 | if (ret) { | ||
| 546 | dev_err(&client->dev, "Failed to set als lower threshold\n"); | ||
| 547 | return ret; | ||
| 548 | } | ||
| 549 | |||
| 550 | ret = i2c_smbus_write_byte_data(client, | ||
| 551 | TSL2591_CMD_NOP | TSL2591_AILTH, | ||
| 552 | als_lower_h); | ||
| 553 | if (ret) { | ||
| 554 | dev_err(&client->dev, "Failed to set als lower threshold\n"); | ||
| 555 | return ret; | ||
| 556 | } | ||
| 557 | |||
| 558 | return 0; | ||
| 559 | } | ||
| 560 | |||
| 561 | static int tsl2591_set_als_upper_threshold(struct tsl2591_chip *chip, | ||
| 562 | u16 als_upper_threshold) | ||
| 563 | { | ||
| 564 | struct tsl2591_als_settings als_settings = chip->als_settings; | ||
| 565 | struct i2c_client *client = chip->client; | ||
| 566 | u16 als_lower_threshold; | ||
| 567 | u8 als_upper_l; | ||
| 568 | u8 als_upper_h; | ||
| 569 | int ret; | ||
| 570 | |||
| 571 | if (als_upper_threshold > TSL2591_ALS_MAX_VALUE) | ||
| 572 | return -EINVAL; | ||
| 573 | |||
| 574 | chip->als_settings.als_upper_thresh = als_upper_threshold; | ||
| 575 | |||
| 576 | /* | ||
| 577 | * Upper threshold should not be less than lower. If this | ||
| 578 | * is the case, then assert lower threshold to new upper | ||
| 579 | * threshold - 1 to avoid ordering issues when setting thresholds. | ||
| 580 | */ | ||
| 581 | if (als_upper_threshold < als_settings.als_lower_thresh) { | ||
| 582 | als_lower_threshold = als_upper_threshold - 1; | ||
| 583 | tsl2591_set_als_lower_threshold(chip, als_lower_threshold); | ||
| 584 | } | ||
| 585 | |||
| 586 | als_upper_l = als_upper_threshold; | ||
| 587 | als_upper_h = als_upper_threshold >> 8; | ||
| 588 | |||
| 589 | ret = i2c_smbus_write_byte_data(client, | ||
| 590 | TSL2591_CMD_NOP | TSL2591_AIHTL, | ||
| 591 | als_upper_l); | ||
| 592 | if (ret) { | ||
| 593 | dev_err(&client->dev, "Failed to set als upper threshold\n"); | ||
| 594 | return ret; | ||
| 595 | } | ||
| 596 | |||
| 597 | ret = i2c_smbus_write_byte_data(client, | ||
| 598 | TSL2591_CMD_NOP | TSL2591_AIHTH, | ||
| 599 | als_upper_h); | ||
| 600 | if (ret) { | ||
| 601 | dev_err(&client->dev, "Failed to set als upper threshold\n"); | ||
| 602 | return ret; | ||
| 603 | } | ||
| 604 | |||
| 605 | return 0; | ||
| 606 | } | ||
| 607 | |||
| 608 | static int tsl2591_set_als_persist_cycle(struct tsl2591_chip *chip, | ||
| 609 | u8 als_persist) | ||
| 610 | { | ||
| 611 | struct i2c_client *client = chip->client; | ||
| 612 | int ret; | ||
| 613 | |||
| 614 | ret = i2c_smbus_write_byte_data(client, | ||
| 615 | TSL2591_CMD_NOP | TSL2591_PERSIST, | ||
| 616 | als_persist); | ||
| 617 | if (ret) | ||
| 618 | dev_err(&client->dev, "Failed to set als persist cycle\n"); | ||
| 619 | |||
| 620 | chip->als_settings.als_persist = als_persist; | ||
| 621 | |||
| 622 | return ret; | ||
| 623 | } | ||
| 624 | |||
| 625 | static int tsl2591_set_power_state(struct tsl2591_chip *chip, u8 state) | ||
| 626 | { | ||
| 627 | struct i2c_client *client = chip->client; | ||
| 628 | int ret; | ||
| 629 | |||
| 630 | ret = i2c_smbus_write_byte_data(client, | ||
| 631 | TSL2591_CMD_NOP | TSL2591_ENABLE, | ||
| 632 | state); | ||
| 633 | if (ret) | ||
| 634 | dev_err(&client->dev, | ||
| 635 | "Failed to set the power state to %#04x\n", state); | ||
| 636 | |||
| 637 | return ret; | ||
| 638 | } | ||
| 639 | |||
| 640 | static ssize_t tsl2591_in_illuminance_period_available_show(struct device *dev, | ||
| 641 | struct device_attribute *attr, | ||
| 642 | char *buf) | ||
| 643 | { | ||
| 644 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
| 645 | struct tsl2591_chip *chip = iio_priv(indio_dev); | ||
| 646 | |||
| 647 | return sysfs_emit(buf, "%s\n", | ||
| 648 | tsl2591_als_period_list[chip->als_settings.als_int_time]); | ||
| 649 | } | ||
| 650 | |||
| 651 | static IIO_DEVICE_ATTR_RO(tsl2591_in_illuminance_period_available, 0); | ||
| 652 | |||
| 653 | static struct attribute *tsl2591_event_attrs_ctrl[] = { | ||
| 654 | &iio_dev_attr_tsl2591_in_illuminance_period_available.dev_attr.attr, | ||
| 655 | NULL | ||
| 656 | }; | ||
| 657 | |||
| 658 | static const struct attribute_group tsl2591_event_attribute_group = { | ||
| 659 | .attrs = tsl2591_event_attrs_ctrl, | ||
| 660 | }; | ||
| 661 | |||
| 662 | static const struct iio_event_spec tsl2591_events[] = { | ||
| 663 | { | ||
| 664 | .type = IIO_EV_TYPE_THRESH, | ||
| 665 | .dir = IIO_EV_DIR_RISING, | ||
| 666 | .mask_separate = BIT(IIO_EV_INFO_VALUE), | ||
| 667 | }, { | ||
| 668 | .type = IIO_EV_TYPE_THRESH, | ||
| 669 | .dir = IIO_EV_DIR_FALLING, | ||
| 670 | .mask_separate = BIT(IIO_EV_INFO_VALUE), | ||
| 671 | }, { | ||
| 672 | .type = IIO_EV_TYPE_THRESH, | ||
| 673 | .dir = IIO_EV_DIR_EITHER, | ||
| 674 | .mask_separate = BIT(IIO_EV_INFO_PERIOD) | | ||
| 675 | BIT(IIO_EV_INFO_ENABLE), | ||
| 676 | }, | ||
| 677 | }; | ||
| 678 | |||
| 679 | static const struct iio_chan_spec tsl2591_channels[] = { | ||
| 680 | { | ||
| 681 | .type = IIO_INTENSITY, | ||
| 682 | .modified = 1, | ||
| 683 | .channel2 = IIO_MOD_LIGHT_IR, | ||
| 684 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
| 685 | .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | | ||
| 686 | BIT(IIO_CHAN_INFO_CALIBSCALE), | ||
| 687 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) | | ||
| 688 | BIT(IIO_CHAN_INFO_CALIBSCALE) | ||
| 689 | }, | ||
| 690 | { | ||
| 691 | .type = IIO_INTENSITY, | ||
| 692 | .modified = 1, | ||
| 693 | .channel2 = IIO_MOD_LIGHT_BOTH, | ||
| 694 | .event_spec = tsl2591_events, | ||
| 695 | .num_event_specs = ARRAY_SIZE(tsl2591_events), | ||
| 696 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
| 697 | .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | | ||
| 698 | BIT(IIO_CHAN_INFO_CALIBSCALE), | ||
| 699 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) | | ||
| 700 | BIT(IIO_CHAN_INFO_CALIBSCALE) | ||
| 701 | }, | ||
| 702 | { | ||
| 703 | .type = IIO_LIGHT, | ||
| 704 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), | ||
| 705 | .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | | ||
| 706 | BIT(IIO_CHAN_INFO_CALIBSCALE), | ||
| 707 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) | | ||
| 708 | BIT(IIO_CHAN_INFO_CALIBSCALE) | ||
| 709 | }, | ||
| 710 | }; | ||
| 711 | |||
| 712 | static int tsl2591_read_raw(struct iio_dev *indio_dev, | ||
| 713 | struct iio_chan_spec const *chan, | ||
| 714 | int *val, int *val2, long mask) | ||
| 715 | { | ||
| 716 | struct tsl2591_chip *chip = iio_priv(indio_dev); | ||
| 717 | struct i2c_client *client = chip->client; | ||
| 718 | int ret; | ||
| 719 | |||
| 720 | pm_runtime_get_sync(&client->dev); | ||
| 721 | |||
| 722 | mutex_lock(&chip->als_mutex); | ||
| 723 | |||
| 724 | switch (mask) { | ||
| 725 | case IIO_CHAN_INFO_RAW: | ||
| 726 | if (chan->type != IIO_INTENSITY) { | ||
| 727 | ret = -EINVAL; | ||
| 728 | goto err_unlock; | ||
| 729 | } | ||
| 730 | |||
| 731 | ret = tsl2591_read_channel_data(indio_dev, chan, val, val2); | ||
| 732 | if (ret < 0) | ||
| 733 | goto err_unlock; | ||
| 734 | |||
| 735 | ret = IIO_VAL_INT; | ||
| 736 | break; | ||
| 737 | case IIO_CHAN_INFO_PROCESSED: | ||
| 738 | if (chan->type != IIO_LIGHT) { | ||
| 739 | ret = -EINVAL; | ||
| 740 | goto err_unlock; | ||
| 741 | } | ||
| 742 | |||
| 743 | ret = tsl2591_read_channel_data(indio_dev, chan, val, val2); | ||
| 744 | if (ret < 0) | ||
| 745 | break; | ||
| 746 | |||
| 747 | ret = IIO_VAL_INT_PLUS_MICRO; | ||
| 748 | break; | ||
| 749 | case IIO_CHAN_INFO_INT_TIME: | ||
| 750 | if (chan->type != IIO_INTENSITY) { | ||
| 751 | ret = -EINVAL; | ||
| 752 | goto err_unlock; | ||
| 753 | } | ||
| 754 | |||
| 755 | *val = TSL2591_FVAL_TO_SEC(chip->als_settings.als_int_time); | ||
| 756 | ret = IIO_VAL_INT; | ||
| 757 | break; | ||
| 758 | case IIO_CHAN_INFO_CALIBSCALE: | ||
| 759 | if (chan->type != IIO_INTENSITY) { | ||
| 760 | ret = -EINVAL; | ||
| 761 | goto err_unlock; | ||
| 762 | } | ||
| 763 | |||
| 764 | *val = tsl2591_gain_to_multiplier(chip->als_settings.als_gain); | ||
| 765 | ret = IIO_VAL_INT; | ||
| 766 | break; | ||
| 767 | default: | ||
| 768 | ret = -EINVAL; | ||
| 769 | break; | ||
| 770 | } | ||
| 771 | |||
| 772 | err_unlock: | ||
| 773 | mutex_unlock(&chip->als_mutex); | ||
| 774 | |||
| 775 | pm_runtime_mark_last_busy(&client->dev); | ||
| 776 | pm_runtime_put_autosuspend(&client->dev); | ||
| 777 | |||
| 778 | return ret; | ||
| 779 | } | ||
| 780 | |||
| 781 | static int tsl2591_write_raw(struct iio_dev *indio_dev, | ||
| 782 | struct iio_chan_spec const *chan, | ||
| 783 | int val, int val2, long mask) | ||
| 784 | { | ||
| 785 | struct tsl2591_chip *chip = iio_priv(indio_dev); | ||
| 786 | int int_time; | ||
| 787 | int gain; | ||
| 788 | int ret; | ||
| 789 | |||
| 790 | mutex_lock(&chip->als_mutex); | ||
| 791 | |||
| 792 | switch (mask) { | ||
| 793 | case IIO_CHAN_INFO_INT_TIME: | ||
| 794 | int_time = tsl2591_als_time_to_fval(val); | ||
| 795 | if (int_time < 0) { | ||
| 796 | ret = int_time; | ||
| 797 | goto err_unlock; | ||
| 798 | } | ||
| 799 | ret = tsl2591_compatible_int_time(chip, int_time); | ||
| 800 | if (ret < 0) | ||
| 801 | goto err_unlock; | ||
| 802 | |||
| 803 | chip->als_settings.als_int_time = int_time; | ||
| 804 | break; | ||
| 805 | case IIO_CHAN_INFO_CALIBSCALE: | ||
| 806 | gain = tsl2591_multiplier_to_gain(val); | ||
| 807 | if (gain < 0) { | ||
| 808 | ret = gain; | ||
| 809 | goto err_unlock; | ||
| 810 | } | ||
| 811 | ret = tsl2591_compatible_gain(chip, gain); | ||
| 812 | if (ret < 0) | ||
| 813 | goto err_unlock; | ||
| 814 | |||
| 815 | chip->als_settings.als_gain = gain; | ||
| 816 | break; | ||
| 817 | default: | ||
| 818 | ret = -EINVAL; | ||
| 819 | goto err_unlock; | ||
| 820 | } | ||
| 821 | |||
| 822 | ret = tsl2591_set_als_gain_int_time(chip); | ||
| 823 | |||
| 824 | err_unlock: | ||
| 825 | mutex_unlock(&chip->als_mutex); | ||
| 826 | return ret; | ||
| 827 | } | ||
| 828 | |||
| 829 | static int tsl2591_read_available(struct iio_dev *indio_dev, | ||
| 830 | struct iio_chan_spec const *chan, | ||
| 831 | const int **vals, int *type, int *length, | ||
| 832 | long mask) | ||
| 833 | { | ||
| 834 | switch (mask) { | ||
| 835 | case IIO_CHAN_INFO_INT_TIME: | ||
| 836 | *length = ARRAY_SIZE(tsl2591_int_time_available); | ||
| 837 | *vals = tsl2591_int_time_available; | ||
| 838 | *type = IIO_VAL_INT; | ||
| 839 | return IIO_AVAIL_LIST; | ||
| 840 | |||
| 841 | case IIO_CHAN_INFO_CALIBSCALE: | ||
| 842 | *length = ARRAY_SIZE(tsl2591_calibscale_available); | ||
| 843 | *vals = tsl2591_calibscale_available; | ||
| 844 | *type = IIO_VAL_INT; | ||
| 845 | return IIO_AVAIL_LIST; | ||
| 846 | default: | ||
| 847 | return -EINVAL; | ||
| 848 | } | ||
| 849 | } | ||
| 850 | |||
| 851 | static int tsl2591_read_event_value(struct iio_dev *indio_dev, | ||
| 852 | const struct iio_chan_spec *chan, | ||
| 853 | enum iio_event_type type, | ||
| 854 | enum iio_event_direction dir, | ||
| 855 | enum iio_event_info info, int *val, | ||
| 856 | int *val2) | ||
| 857 | { | ||
| 858 | struct tsl2591_chip *chip = iio_priv(indio_dev); | ||
| 859 | struct i2c_client *client = chip->client; | ||
| 860 | int als_persist, int_time, period; | ||
| 861 | int ret; | ||
| 862 | |||
| 863 | mutex_lock(&chip->als_mutex); | ||
| 864 | |||
| 865 | switch (info) { | ||
| 866 | case IIO_EV_INFO_VALUE: | ||
| 867 | switch (dir) { | ||
| 868 | case IIO_EV_DIR_RISING: | ||
| 869 | *val = chip->als_settings.als_upper_thresh; | ||
| 870 | break; | ||
| 871 | case IIO_EV_DIR_FALLING: | ||
| 872 | *val = chip->als_settings.als_lower_thresh; | ||
| 873 | break; | ||
| 874 | default: | ||
| 875 | ret = -EINVAL; | ||
| 876 | goto err_unlock; | ||
| 877 | } | ||
| 878 | ret = IIO_VAL_INT; | ||
| 879 | break; | ||
| 880 | case IIO_EV_INFO_PERIOD: | ||
| 881 | ret = i2c_smbus_read_byte_data(client, | ||
| 882 | TSL2591_CMD_NOP | TSL2591_PERSIST); | ||
| 883 | if (ret <= 0 || ret > TSL2591_PRST_ALS_INT_CYCLE_MAX) | ||
| 884 | goto err_unlock; | ||
| 885 | |||
| 886 | als_persist = tsl2591_persist_cycle_to_lit(ret); | ||
| 887 | int_time = TSL2591_FVAL_TO_MSEC(chip->als_settings.als_int_time); | ||
| 888 | period = als_persist * (int_time * MSEC_PER_SEC); | ||
| 889 | |||
| 890 | *val = period / USEC_PER_SEC; | ||
| 891 | *val2 = period % USEC_PER_SEC; | ||
| 892 | |||
| 893 | ret = IIO_VAL_INT_PLUS_MICRO; | ||
| 894 | break; | ||
| 895 | default: | ||
| 896 | ret = -EINVAL; | ||
| 897 | break; | ||
| 898 | } | ||
| 899 | |||
| 900 | err_unlock: | ||
| 901 | mutex_unlock(&chip->als_mutex); | ||
| 902 | return ret; | ||
| 903 | } | ||
| 904 | |||
| 905 | static int tsl2591_write_event_value(struct iio_dev *indio_dev, | ||
| 906 | const struct iio_chan_spec *chan, | ||
| 907 | enum iio_event_type type, | ||
| 908 | enum iio_event_direction dir, | ||
| 909 | enum iio_event_info info, int val, | ||
| 910 | int val2) | ||
| 911 | { | ||
| 912 | struct tsl2591_chip *chip = iio_priv(indio_dev); | ||
| 913 | int period, int_time, als_persist; | ||
| 914 | int ret; | ||
| 915 | |||
| 916 | if (val < 0 || val2 < 0) | ||
| 917 | return -EINVAL; | ||
| 918 | |||
| 919 | mutex_lock(&chip->als_mutex); | ||
| 920 | |||
| 921 | switch (info) { | ||
| 922 | case IIO_EV_INFO_VALUE: | ||
| 923 | if (val > TSL2591_ALS_MAX_VALUE) { | ||
| 924 | ret = -EINVAL; | ||
| 925 | goto err_unlock; | ||
| 926 | } | ||
| 927 | |||
| 928 | switch (dir) { | ||
| 929 | case IIO_EV_DIR_RISING: | ||
| 930 | ret = tsl2591_set_als_upper_threshold(chip, val); | ||
| 931 | if (ret < 0) | ||
| 932 | goto err_unlock; | ||
| 933 | break; | ||
| 934 | case IIO_EV_DIR_FALLING: | ||
| 935 | ret = tsl2591_set_als_lower_threshold(chip, val); | ||
| 936 | if (ret < 0) | ||
| 937 | goto err_unlock; | ||
| 938 | break; | ||
| 939 | default: | ||
| 940 | ret = -EINVAL; | ||
| 941 | goto err_unlock; | ||
| 942 | } | ||
| 943 | break; | ||
| 944 | case IIO_EV_INFO_PERIOD: | ||
| 945 | int_time = TSL2591_FVAL_TO_MSEC(chip->als_settings.als_int_time); | ||
| 946 | |||
| 947 | period = ((val * MSEC_PER_SEC) + | ||
| 948 | (val2 / MSEC_PER_SEC)) / int_time; | ||
| 949 | |||
| 950 | als_persist = tsl2591_persist_lit_to_cycle(period); | ||
| 951 | if (als_persist < 0) { | ||
| 952 | ret = -EINVAL; | ||
| 953 | goto err_unlock; | ||
| 954 | } | ||
| 955 | |||
| 956 | ret = tsl2591_compatible_als_persist_cycle(chip, als_persist); | ||
| 957 | if (ret < 0) | ||
| 958 | goto err_unlock; | ||
| 959 | |||
| 960 | ret = tsl2591_set_als_persist_cycle(chip, als_persist); | ||
| 961 | if (ret < 0) | ||
| 962 | goto err_unlock; | ||
| 963 | break; | ||
| 964 | default: | ||
| 965 | ret = -EINVAL; | ||
| 966 | break; | ||
| 967 | } | ||
| 968 | |||
| 969 | err_unlock: | ||
| 970 | mutex_unlock(&chip->als_mutex); | ||
| 971 | return ret; | ||
| 972 | } | ||
| 973 | |||
| 974 | static int tsl2591_read_event_config(struct iio_dev *indio_dev, | ||
| 975 | const struct iio_chan_spec *chan, | ||
| 976 | enum iio_event_type type, | ||
| 977 | enum iio_event_direction dir) | ||
| 978 | { | ||
| 979 | struct tsl2591_chip *chip = iio_priv(indio_dev); | ||
| 980 | |||
| 981 | return chip->events_enabled; | ||
| 982 | } | ||
| 983 | |||
| 984 | static int tsl2591_write_event_config(struct iio_dev *indio_dev, | ||
| 985 | const struct iio_chan_spec *chan, | ||
| 986 | enum iio_event_type type, | ||
| 987 | enum iio_event_direction dir, | ||
| 988 | int state) | ||
| 989 | { | ||
| 990 | struct tsl2591_chip *chip = iio_priv(indio_dev); | ||
| 991 | struct i2c_client *client = chip->client; | ||
| 992 | |||
| 993 | if (state && !chip->events_enabled) { | ||
| 994 | chip->events_enabled = true; | ||
| 995 | pm_runtime_get_sync(&client->dev); | ||
| 996 | } else if (!state && chip->events_enabled) { | ||
| 997 | chip->events_enabled = false; | ||
| 998 | pm_runtime_mark_last_busy(&client->dev); | ||
| 999 | pm_runtime_put_autosuspend(&client->dev); | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | return 0; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | static const struct iio_info tsl2591_info = { | ||
| 1006 | .event_attrs = &tsl2591_event_attribute_group, | ||
| 1007 | .read_raw = tsl2591_read_raw, | ||
| 1008 | .write_raw = tsl2591_write_raw, | ||
| 1009 | .read_avail = tsl2591_read_available, | ||
| 1010 | .read_event_value = tsl2591_read_event_value, | ||
| 1011 | .write_event_value = tsl2591_write_event_value, | ||
| 1012 | .read_event_config = tsl2591_read_event_config, | ||
| 1013 | .write_event_config = tsl2591_write_event_config, | ||
| 1014 | }; | ||
| 1015 | |||
| 1016 | static const struct iio_info tsl2591_info_no_irq = { | ||
| 1017 | .read_raw = tsl2591_read_raw, | ||
| 1018 | .write_raw = tsl2591_write_raw, | ||
| 1019 | .read_avail = tsl2591_read_available, | ||
| 1020 | }; | ||
| 1021 | |||
| 1022 | static int __maybe_unused tsl2591_suspend(struct device *dev) | ||
| 1023 | { | ||
| 1024 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
| 1025 | struct tsl2591_chip *chip = iio_priv(indio_dev); | ||
| 1026 | int ret; | ||
| 1027 | |||
| 1028 | mutex_lock(&chip->als_mutex); | ||
| 1029 | ret = tsl2591_set_power_state(chip, TSL2591_PWR_OFF); | ||
| 1030 | mutex_unlock(&chip->als_mutex); | ||
| 1031 | |||
| 1032 | return ret; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | static int __maybe_unused tsl2591_resume(struct device *dev) | ||
| 1036 | { | ||
| 1037 | int power_state = TSL2591_PWR_ON | TSL2591_ENABLE_ALS; | ||
| 1038 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
| 1039 | struct tsl2591_chip *chip = iio_priv(indio_dev); | ||
| 1040 | int ret; | ||
| 1041 | |||
| 1042 | if (chip->events_enabled) | ||
| 1043 | power_state |= TSL2591_ENABLE_ALS_INT; | ||
| 1044 | |||
| 1045 | mutex_lock(&chip->als_mutex); | ||
| 1046 | ret = tsl2591_set_power_state(chip, power_state); | ||
| 1047 | mutex_unlock(&chip->als_mutex); | ||
| 1048 | |||
| 1049 | return ret; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | static const struct dev_pm_ops tsl2591_pm_ops = { | ||
| 1053 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) | ||
| 1054 | SET_RUNTIME_PM_OPS(tsl2591_suspend, tsl2591_resume, NULL) | ||
| 1055 | }; | ||
| 1056 | |||
| 1057 | static irqreturn_t tsl2591_event_handler(int irq, void *private) | ||
| 1058 | { | ||
| 1059 | struct iio_dev *dev_info = private; | ||
| 1060 | struct tsl2591_chip *chip = iio_priv(dev_info); | ||
| 1061 | struct i2c_client *client = chip->client; | ||
| 1062 | |||
| 1063 | if (!chip->events_enabled) | ||
| 1064 | return IRQ_NONE; | ||
| 1065 | |||
| 1066 | iio_push_event(dev_info, | ||
| 1067 | IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0, | ||
| 1068 | IIO_EV_TYPE_THRESH, | ||
| 1069 | IIO_EV_DIR_EITHER), | ||
| 1070 | iio_get_time_ns(dev_info)); | ||
| 1071 | |||
| 1072 | /* Clear ALS irq */ | ||
| 1073 | i2c_smbus_write_byte(client, TSL2591_CMD_SF_CALS_NPI); | ||
| 1074 | |||
| 1075 | return IRQ_HANDLED; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | static int tsl2591_load_defaults(struct tsl2591_chip *chip) | ||
| 1079 | { | ||
| 1080 | int ret; | ||
| 1081 | |||
| 1082 | chip->als_settings.als_int_time = TSL2591_DEFAULT_ALS_INT_TIME; | ||
| 1083 | chip->als_settings.als_gain = TSL2591_DEFAULT_ALS_GAIN; | ||
| 1084 | chip->als_settings.als_lower_thresh = TSL2591_DEFAULT_ALS_LOWER_THRESH; | ||
| 1085 | chip->als_settings.als_upper_thresh = TSL2591_DEFAULT_ALS_UPPER_THRESH; | ||
| 1086 | |||
| 1087 | ret = tsl2591_set_als_gain_int_time(chip); | ||
| 1088 | if (ret < 0) | ||
| 1089 | return ret; | ||
| 1090 | |||
| 1091 | ret = tsl2591_set_als_persist_cycle(chip, TSL2591_DEFAULT_ALS_PERSIST); | ||
| 1092 | if (ret < 0) | ||
| 1093 | return ret; | ||
| 1094 | |||
| 1095 | ret = tsl2591_set_als_lower_threshold(chip, TSL2591_DEFAULT_ALS_LOWER_THRESH); | ||
| 1096 | if (ret < 0) | ||
| 1097 | return ret; | ||
| 1098 | |||
| 1099 | ret = tsl2591_set_als_upper_threshold(chip, TSL2591_DEFAULT_ALS_UPPER_THRESH); | ||
| 1100 | if (ret < 0) | ||
| 1101 | return ret; | ||
| 1102 | |||
| 1103 | return 0; | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | static void tsl2591_chip_off(void *data) | ||
| 1107 | { | ||
| 1108 | struct iio_dev *indio_dev = data; | ||
| 1109 | struct tsl2591_chip *chip = iio_priv(indio_dev); | ||
| 1110 | struct i2c_client *client = chip->client; | ||
| 1111 | |||
| 1112 | pm_runtime_disable(&client->dev); | ||
| 1113 | pm_runtime_set_suspended(&client->dev); | ||
| 1114 | pm_runtime_put_noidle(&client->dev); | ||
| 1115 | |||
| 1116 | tsl2591_set_power_state(chip, TSL2591_PWR_OFF); | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | static int tsl2591_probe(struct i2c_client *client) | ||
| 1120 | { | ||
| 1121 | struct tsl2591_chip *chip; | ||
| 1122 | struct iio_dev *indio_dev; | ||
| 1123 | int ret; | ||
| 1124 | |||
| 1125 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
| 1126 | dev_err(&client->dev, | ||
| 1127 | "I2C smbus byte data functionality is not supported\n"); | ||
| 1128 | return -EOPNOTSUPP; | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); | ||
| 1132 | if (!indio_dev) | ||
| 1133 | return -ENOMEM; | ||
| 1134 | |||
| 1135 | chip = iio_priv(indio_dev); | ||
| 1136 | chip->client = client; | ||
| 1137 | i2c_set_clientdata(client, indio_dev); | ||
| 1138 | |||
| 1139 | if (client->irq) { | ||
| 1140 | ret = devm_request_threaded_irq(&client->dev, client->irq, | ||
| 1141 | NULL, tsl2591_event_handler, | ||
| 1142 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
| 1143 | "tsl2591_irq", indio_dev); | ||
| 1144 | if (ret) { | ||
| 1145 | dev_err_probe(&client->dev, ret, "IRQ request error\n"); | ||
| 1146 | return -EINVAL; | ||
| 1147 | } | ||
| 1148 | indio_dev->info = &tsl2591_info; | ||
| 1149 | } else { | ||
| 1150 | indio_dev->info = &tsl2591_info_no_irq; | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | mutex_init(&chip->als_mutex); | ||
| 1154 | |||
| 1155 | ret = i2c_smbus_read_byte_data(client, | ||
| 1156 | TSL2591_CMD_NOP | TSL2591_DEVICE_ID); | ||
| 1157 | if (ret < 0) { | ||
| 1158 | dev_err(&client->dev, | ||
| 1159 | "Failed to read the device ID register\n"); | ||
| 1160 | return ret; | ||
| 1161 | } | ||
| 1162 | ret = FIELD_GET(TSL2591_DEVICE_ID_MASK, ret); | ||
| 1163 | if (ret != TSL2591_DEVICE_ID_VAL) { | ||
| 1164 | dev_err(&client->dev, "Device ID: %#04x unknown\n", ret); | ||
| 1165 | return -EINVAL; | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | indio_dev->channels = tsl2591_channels; | ||
| 1169 | indio_dev->num_channels = ARRAY_SIZE(tsl2591_channels); | ||
| 1170 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
| 1171 | indio_dev->name = chip->client->name; | ||
| 1172 | chip->events_enabled = false; | ||
| 1173 | |||
| 1174 | pm_runtime_enable(&client->dev); | ||
| 1175 | pm_runtime_set_autosuspend_delay(&client->dev, | ||
| 1176 | TSL2591_POWER_OFF_DELAY_MS); | ||
| 1177 | pm_runtime_use_autosuspend(&client->dev); | ||
| 1178 | |||
| 1179 | /* | ||
| 1180 | * Add chip off to automatically managed path and disable runtime | ||
| 1181 | * power management. This ensures that the chip power management | ||
| 1182 | * is handled correctly on driver remove. tsl2591_chip_off() must be | ||
| 1183 | * added to the managed path after pm runtime is enabled and before | ||
| 1184 | * any error exit paths are met to ensure we're not left in a state | ||
| 1185 | * of pm runtime not being disabled properly. | ||
| 1186 | */ | ||
| 1187 | ret = devm_add_action_or_reset(&client->dev, tsl2591_chip_off, | ||
| 1188 | indio_dev); | ||
| 1189 | if (ret < 0) | ||
| 1190 | return -EINVAL; | ||
| 1191 | |||
| 1192 | ret = tsl2591_load_defaults(chip); | ||
| 1193 | if (ret < 0) { | ||
| 1194 | dev_err(&client->dev, "Failed to load sensor defaults\n"); | ||
| 1195 | return -EINVAL; | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | ret = i2c_smbus_write_byte(client, TSL2591_CMD_SF_CALS_NPI); | ||
| 1199 | if (ret < 0) { | ||
| 1200 | dev_err(&client->dev, "Failed to clear als irq\n"); | ||
| 1201 | return -EINVAL; | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | return devm_iio_device_register(&client->dev, indio_dev); | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | static const struct of_device_id tsl2591_of_match[] = { | ||
| 1208 | { .compatible = "amstaos,tsl2591"}, | ||
| 1209 | {} | ||
| 1210 | }; | ||
| 1211 | MODULE_DEVICE_TABLE(of, tsl2591_of_match); | ||
| 1212 | |||
| 1213 | static struct i2c_driver tsl2591_driver = { | ||
| 1214 | .driver = { | ||
| 1215 | .name = "tsl2591", | ||
| 1216 | .pm = &tsl2591_pm_ops, | ||
| 1217 | .of_match_table = tsl2591_of_match, | ||
| 1218 | }, | ||
| 1219 | .probe_new = tsl2591_probe | ||
| 1220 | }; | ||
| 1221 | module_i2c_driver(tsl2591_driver); | ||
| 1222 | |||
| 1223 | MODULE_AUTHOR("Joe Sandom <joe.g.sandom@gmail.com>"); | ||
| 1224 | MODULE_DESCRIPTION("TAOS tsl2591 ambient light sensor driver"); | ||
| 1225 | MODULE_LICENSE("GPL"); | ||
| @@ -367,9 +367,7 @@ static int us5182d_set_power_state(struct us5182d_data *data, bool on) · 366 unmodified lines | |||
| 367 | return 0; | 367 | return 0; |
| 368 | 368 | ||
| 369 | if (on) { | 369 | if (on) { |
| 370 | ret = pm_runtime_get_sync(&data->client->dev); | 370 | ret = pm_runtime_resume_and_get(&data->client->dev); |
| 371 | if (ret < 0) | ||
| 372 | pm_runtime_put_noidle(&data->client->dev); | ||
| 373 | } else { | 371 | } else { |
| 374 | pm_runtime_mark_last_busy(&data->client->dev); | 372 | pm_runtime_mark_last_busy(&data->client->dev); |
| 375 | ret = pm_runtime_put_autosuspend(&data->client->dev); | 373 | ret = pm_runtime_put_autosuspend(&data->client->dev); |
| @@ -413,9 +413,7 @@ static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on) · 412 unmodified lines | |||
| 413 | int ret; | 413 | int ret; |
| 414 | 414 | ||
| 415 | if (on) { | 415 | if (on) { |
| 416 | ret = pm_runtime_get_sync(dev); | 416 | ret = pm_runtime_resume_and_get(dev); |
| 417 | if (ret < 0) | ||
| 418 | pm_runtime_put_noidle(dev); | ||
| 419 | } else { | 417 | } else { |
| 420 | pm_runtime_mark_last_busy(dev); | 418 | pm_runtime_mark_last_busy(dev); |
| 421 | ret = pm_runtime_put_autosuspend(dev); | 419 | ret = pm_runtime_put_autosuspend(dev); |
| @@ -910,7 +908,7 @@ static irqreturn_t vcnl4010_trigger_handler(int irq, void *p) · 488 unmodified lines | |||
| 910 | struct iio_dev *indio_dev = pf->indio_dev; | 908 | struct iio_dev *indio_dev = pf->indio_dev; |
| 911 | struct vcnl4000_data *data = iio_priv(indio_dev); | 909 | struct vcnl4000_data *data = iio_priv(indio_dev); |
| 912 | const unsigned long *active_scan_mask = indio_dev->active_scan_mask; | 910 | const unsigned long *active_scan_mask = indio_dev->active_scan_mask; |
| 913 | u16 buffer[8] = {0}; /* 1x16-bit + ts */ | 911 | u16 buffer[8] __aligned(8) = {0}; /* 1x16-bit + naturally aligned ts */ |
| 914 | bool data_read = false; | 912 | bool data_read = false; |
| 915 | unsigned long isr; | 913 | unsigned long isr; |
| 916 | int val = 0; | 914 | int val = 0; |
| @@ -998,7 +996,8 @@ static int vcnl4010_probe_trigger(struct iio_dev *indio_dev) · 81 unmodified lines | |||
| 998 | struct iio_trigger *trigger; | 996 | struct iio_trigger *trigger; |
| 999 | 997 | ||
| 1000 | trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", | 998 | trigger = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", |
| 1001 | indio_dev->name, indio_dev->id); | 999 | indio_dev->name, |
| 1000 | iio_device_id(indio_dev)); | ||
| 1002 | if (!trigger) | 1001 | if (!trigger) |
| 1003 | return -ENOMEM; | 1002 | return -ENOMEM; |
| 1004 | 1003 | ||
| @@ -102,7 +102,8 @@ static irqreturn_t vcnl4035_trigger_consumer_handler(int irq, void *p) · 101 unmodified lines | |||
| 102 | struct iio_poll_func *pf = p; | 102 | struct iio_poll_func *pf = p; |
| 103 | struct iio_dev *indio_dev = pf->indio_dev; | 103 | struct iio_dev *indio_dev = pf->indio_dev; |
| 104 | struct vcnl4035_data *data = iio_priv(indio_dev); | 104 | struct vcnl4035_data *data = iio_priv(indio_dev); |
| 105 | u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)]; | 105 | /* Ensure naturally aligned timestamp */ |
| 106 | u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)] __aligned(8); | ||
| 106 | int ret; | 107 | int ret; |
| 107 | 108 | ||
| 108 | ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, (int *)buffer); | 109 | ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, (int *)buffer); |
| @@ -144,9 +145,7 @@ static int vcnl4035_set_pm_runtime_state(struct vcnl4035_data *data, bool on) · 35 unmodified lines | |||
| 144 | struct device *dev = &data->client->dev; | 145 | struct device *dev = &data->client->dev; |
| 145 | 146 | ||
| 146 | if (on) { | 147 | if (on) { |
| 147 | ret = pm_runtime_get_sync(dev); | 148 | ret = pm_runtime_resume_and_get(dev); |
| 148 | if (ret < 0) | ||
| 149 | pm_runtime_put_noidle(dev); | ||
| 150 | } else { | 149 | } else { |
| 151 | pm_runtime_mark_last_busy(dev); | 150 | pm_runtime_mark_last_busy(dev); |
| 152 | ret = pm_runtime_put_autosuspend(dev); | 151 | ret = pm_runtime_put_autosuspend(dev); |
| @@ -507,7 +506,7 @@ static int vcnl4035_probe_trigger(struct iio_dev *indio_dev) · 354 unmodified lines | |||
| 507 | 506 | ||
| 508 | data->drdy_trigger0 = devm_iio_trigger_alloc( | 507 | data->drdy_trigger0 = devm_iio_trigger_alloc( |
| 509 | indio_dev->dev.parent, | 508 | indio_dev->dev.parent, |
| 510 | "%s-dev%d", indio_dev->name, indio_dev->id); | 509 | "%s-dev%d", indio_dev->name, iio_device_id(indio_dev)); |
| 511 | if (!data->drdy_trigger0) | 510 | if (!data->drdy_trigger0) |
| 512 | return -ENOMEM; | 511 | return -ENOMEM; |
| 513 | 512 | ||
| @@ -128,7 +128,7 @@ static ssize_t in_illuminance_period_available_show(struct device *dev, · 127 unmodified lines | |||
| 128 | return -EINVAL; | 128 | return -EINVAL; |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | return snprintf(buf, PAGE_SIZE, "%s\n", period_values[x]); | 131 | return sysfs_emit(buf, "%s\n", period_values[x]); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | static IIO_DEVICE_ATTR_RO(in_illuminance_period_available, 0); | 134 | static IIO_DEVICE_ATTR_RO(in_illuminance_period_available, 0); |
| @@ -833,8 +833,7 @@ static int ak8974_probe(struct i2c_client *i2c, · 832 unmodified lines | |||
| 833 | ak8974->i2c = i2c; | 833 | ak8974->i2c = i2c; |
| 834 | mutex_init(&ak8974->lock); | 834 | mutex_init(&ak8974->lock); |
| 835 | 835 | ||
| 836 | ret = iio_read_mount_matrix(&i2c->dev, "mount-matrix", | 836 | ret = iio_read_mount_matrix(&i2c->dev, &ak8974->orientation); |
| 837 | &ak8974->orientation); | ||
| 838 | if (ret) | 837 | if (ret) |
| 839 | return ret; | 838 | return ret; |
| 840 | 839 | ||
| @@ -890,7 +890,7 @@ static int ak8975_probe(struct i2c_client *client, · 889 unmodified lines | |||
| 890 | data->reset_gpiod = reset_gpiod; | 890 | data->reset_gpiod = reset_gpiod; |
| 891 | data->eoc_irq = 0; | 891 | data->eoc_irq = 0; |
| 892 | 892 | ||
| 893 | err = iio_read_mount_matrix(&client->dev, "mount-matrix", &data->orientation); | 893 | err = iio_read_mount_matrix(&client->dev, &data->orientation); |
| 894 | if (err) | 894 | if (err) |
| 895 | return err; | 895 | return err; |
| 896 | 896 | ||
| @@ -138,8 +138,11 @@ struct bmc150_magn_data { · 137 unmodified lines | |||
| 138 | struct regmap *regmap; | 138 | struct regmap *regmap; |
| 139 | struct regulator_bulk_data regulators[2]; | 139 | struct regulator_bulk_data regulators[2]; |
| 140 | struct iio_mount_matrix orientation; | 140 | struct iio_mount_matrix orientation; |
| 141 | /* 4 x 32 bits for x, y z, 4 bytes align, 64 bits timestamp */ | 141 | /* Ensure timestamp is naturally aligned */ |
| 142 | s32 buffer[6]; | 142 | struct { |
| 143 | s32 chans[3]; | ||
| 144 | s64 timestamp __aligned(8); | ||
| 145 | } scan; | ||
| 143 | struct iio_trigger *dready_trig; | 146 | struct iio_trigger *dready_trig; |
| 144 | bool dready_trigger_on; | 147 | bool dready_trigger_on; |
| 145 | int max_odr; | 148 | int max_odr; |
| @@ -262,7 +265,7 @@ static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on) · 116 unmodified lines | |||
| 262 | int ret; | 265 | int ret; |
| 263 | 266 | ||
| 264 | if (on) { | 267 | if (on) { |
| 265 | ret = pm_runtime_get_sync(data->dev); | 268 | ret = pm_runtime_resume_and_get(data->dev); |
| 266 | } else { | 269 | } else { |
| 267 | pm_runtime_mark_last_busy(data->dev); | 270 | pm_runtime_mark_last_busy(data->dev); |
| 268 | ret = pm_runtime_put_autosuspend(data->dev); | 271 | ret = pm_runtime_put_autosuspend(data->dev); |
| @@ -271,9 +274,6 @@ static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on) · 2 unmodified lines | |||
| 271 | if (ret < 0) { | 274 | if (ret < 0) { |
| 272 | dev_err(data->dev, | 275 | dev_err(data->dev, |
| 273 | "failed to change power state to %d\n", on); | 276 | "failed to change power state to %d\n", on); |
| 274 | if (on) | ||
| 275 | pm_runtime_put_noidle(data->dev); | ||
| 276 | |||
| 277 | return ret; | 277 | return ret; |
| 278 | } | 278 | } |
| 279 | #endif | 279 | #endif |
| @@ -675,11 +675,11 @@ static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p) · 395 unmodified lines | |||
| 675 | int ret; | 675 | int ret; |
| 676 | 676 | ||
| 677 | mutex_lock(&data->mutex); | 677 | mutex_lock(&data->mutex); |
| 678 | ret = bmc150_magn_read_xyz(data, data->buffer); | 678 | ret = bmc150_magn_read_xyz(data, data->scan.chans); |
| 679 | if (ret < 0) | 679 | if (ret < 0) |
| 680 | goto err; | 680 | goto err; |
| 681 | 681 | ||
| 682 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 682 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, |
| 683 | pf->timestamp); | 683 | pf->timestamp); |
| 684 | 684 | ||
| 685 | err: | 685 | err: |
| @@ -890,8 +890,7 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, · 204 unmodified lines | |||
| 890 | if (ret) | 890 | if (ret) |
| 891 | return dev_err_probe(dev, ret, "failed to get regulators\n"); | 891 | return dev_err_probe(dev, ret, "failed to get regulators\n"); |
| 892 | 892 | ||
| 893 | ret = iio_read_mount_matrix(dev, "mount-matrix", | 893 | ret = iio_read_mount_matrix(dev, &data->orientation); |
| 894 | &data->orientation); | ||
| 895 | if (ret) | 894 | if (ret) |
| 896 | return ret; | 895 | return ret; |
| 897 | 896 | ||
| @@ -915,7 +914,7 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, · 17 unmodified lines | |||
| 915 | data->dready_trig = devm_iio_trigger_alloc(dev, | 914 | data->dready_trig = devm_iio_trigger_alloc(dev, |
| 916 | "%s-dev%d", | 915 | "%s-dev%d", |
| 917 | indio_dev->name, | 916 | indio_dev->name, |
| 918 | indio_dev->id); | 917 | iio_device_id(indio_dev)); |
| 919 | if (!data->dready_trig) { | 918 | if (!data->dready_trig) { |
| 920 | ret = -ENOMEM; | 919 | ret = -ENOMEM; |
| 921 | dev_err(dev, "iio trigger alloc failed\n"); | 920 | dev_err(dev, "iio trigger alloc failed\n"); |
| @@ -963,12 +962,14 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, · 41 unmodified lines | |||
| 963 | ret = iio_device_register(indio_dev); | 962 | ret = iio_device_register(indio_dev); |
| 964 | if (ret < 0) { | 963 | if (ret < 0) { |
| 965 | dev_err(dev, "unable to register iio device\n"); | 964 | dev_err(dev, "unable to register iio device\n"); |
| 966 | goto err_buffer_cleanup; | 965 | goto err_disable_runtime_pm; |
| 967 | } | 966 | } |
| 968 | 967 | ||
| 969 | dev_dbg(dev, "Registered device %s\n", name); | 968 | dev_dbg(dev, "Registered device %s\n", name); |
| 970 | return 0; | 969 | return 0; |
| 971 | 970 | ||
| 971 | err_disable_runtime_pm: | ||
| 972 | pm_runtime_disable(dev); | ||
| 972 | err_buffer_cleanup: | 973 | err_buffer_cleanup: |
| 973 | iio_triggered_buffer_cleanup(indio_dev); | 974 | iio_triggered_buffer_cleanup(indio_dev); |
| 974 | err_free_irq: | 975 | err_free_irq: |
| @@ -992,7 +993,6 @@ int bmc150_magn_remove(struct device *dev) · 17 unmodified lines | |||
| 992 | 993 | ||
| 993 | pm_runtime_disable(dev); | 994 | pm_runtime_disable(dev); |
| 994 | pm_runtime_set_suspended(dev); | 995 | pm_runtime_set_suspended(dev); |
| 995 | pm_runtime_put_noidle(dev); | ||
| 996 | 996 | ||
| 997 | iio_triggered_buffer_cleanup(indio_dev); | 997 | iio_triggered_buffer_cleanup(indio_dev); |
| 998 | 998 | ||
| @@ -6,13 +6,9 @@ · 5 unmodified lines | |||
| 6 | #include <linux/device.h> | 6 | #include <linux/device.h> |
| 7 | #include <linux/platform_device.h> | 7 | #include <linux/platform_device.h> |
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/interrupt.h> | 9 | #include <linux/mod_devicetable.h> |
| 10 | #include <linux/irq.h> | ||
| 11 | #include <linux/slab.h> | ||
| 12 | #include <linux/delay.h> | ||
| 13 | #include <linux/hid-sensor-hub.h> | 10 | #include <linux/hid-sensor-hub.h> |
| 14 | #include <linux/iio/iio.h> | 11 | #include <linux/iio/iio.h> |
| 15 | #include <linux/iio/sysfs.h> | ||
| 16 | #include <linux/iio/buffer.h> | 12 | #include <linux/iio/buffer.h> |
| 17 | #include "../common/hid-sensors/hid-sensor-trigger.h" | 13 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 18 | 14 | ||
| @@ -587,3 +583,4 @@ module_platform_driver(hid_magn_3d_platform_driver); · 568 unmodified lines | |||
| 587 | MODULE_DESCRIPTION("HID Sensor Magnetometer 3D"); | 583 | MODULE_DESCRIPTION("HID Sensor Magnetometer 3D"); |
| 588 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); | 584 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>"); |
| 589 | MODULE_LICENSE("GPL"); | 585 | MODULE_LICENSE("GPL"); |
| 586 | MODULE_IMPORT_NS(IIO_HID); | ||
| @@ -33,7 +33,8 @@ enum hmc5843_ids { · 32 unmodified lines | |||
| 33 | * @lock: update and read regmap data | 33 | * @lock: update and read regmap data |
| 34 | * @regmap: hardware access register maps | 34 | * @regmap: hardware access register maps |
| 35 | * @variant: describe chip variants | 35 | * @variant: describe chip variants |
| 36 | * @buffer: 3x 16-bit channels + padding + 64-bit timestamp | 36 | * @scan: buffer to pack data for passing to |
| 37 | * iio_push_to_buffers_with_timestamp() | ||
| 37 | */ | 38 | */ |
| 38 | struct hmc5843_data { | 39 | struct hmc5843_data { |
| 39 | struct device *dev; | 40 | struct device *dev; |
| @@ -41,7 +42,10 @@ struct hmc5843_data { · 1 unmodified line | |||
| 41 | struct regmap *regmap; | 42 | struct regmap *regmap; |
| 42 | const struct hmc5843_chip_info *variant; | 43 | const struct hmc5843_chip_info *variant; |
| 43 | struct iio_mount_matrix orientation; | 44 | struct iio_mount_matrix orientation; |
| 44 | __be16 buffer[8]; | 45 | struct { |
| 46 | __be16 chans[3]; | ||
| 47 | s64 timestamp __aligned(8); | ||
| 48 | } scan; | ||
| 45 | }; | 49 | }; |
| 46 | 50 | ||
| 47 | int hmc5843_common_probe(struct device *dev, struct regmap *regmap, | 51 | int hmc5843_common_probe(struct device *dev, struct regmap *regmap, |
| @@ -446,13 +446,13 @@ static irqreturn_t hmc5843_trigger_handler(int irq, void *p) · 445 unmodified lines | |||
| 446 | } | 446 | } |
| 447 | 447 | ||
| 448 | ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS, | 448 | ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS, |
| 449 | data->buffer, 3 * sizeof(__be16)); | 449 | data->scan.chans, sizeof(data->scan.chans)); |
| 450 | 450 | ||
| 451 | mutex_unlock(&data->lock); | 451 | mutex_unlock(&data->lock); |
| 452 | if (ret < 0) | 452 | if (ret < 0) |
| 453 | goto done; | 453 | goto done; |
| 454 | 454 | ||
| 455 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 455 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, |
| 456 | iio_get_time_ns(indio_dev)); | 456 | iio_get_time_ns(indio_dev)); |
| 457 | 457 | ||
| 458 | done: | 458 | done: |
| @@ -637,8 +637,7 @@ int hmc5843_common_probe(struct device *dev, struct regmap *regmap, · 178 unmodified lines | |||
| 637 | data->variant = &hmc5843_chip_info_tbl[id]; | 637 | data->variant = &hmc5843_chip_info_tbl[id]; |
| 638 | mutex_init(&data->lock); | 638 | mutex_init(&data->lock); |
| 639 | 639 | ||
| 640 | ret = iio_read_mount_matrix(dev, "mount-matrix", | 640 | ret = iio_read_mount_matrix(dev, &data->orientation); |
| 641 | &data->orientation); | ||
| 642 | if (ret) | 641 | if (ret) |
| 643 | return ret; | 642 | return ret; |
| 644 | 643 | ||
| @@ -78,7 +78,8 @@ struct rm3100_data { · 77 unmodified lines | |||
| 78 | bool use_interrupt; | 78 | bool use_interrupt; |
| 79 | int conversion_time; | 79 | int conversion_time; |
| 80 | int scale; | 80 | int scale; |
| 81 | u8 buffer[RM3100_SCAN_BYTES]; | 81 | /* Ensure naturally aligned timestamp */ |
| 82 | u8 buffer[RM3100_SCAN_BYTES] __aligned(8); | ||
| 82 | struct iio_trigger *drdy_trig; | 83 | struct iio_trigger *drdy_trig; |
| 83 | 84 | ||
| 84 | /* | 85 | /* |
| @@ -575,7 +576,7 @@ int rm3100_common_probe(struct device *dev, struct regmap *regmap, int irq) · 490 unmodified lines | |||
| 575 | 576 | ||
| 576 | data->drdy_trig = devm_iio_trigger_alloc(dev, "%s-drdy%d", | 577 | data->drdy_trig = devm_iio_trigger_alloc(dev, "%s-drdy%d", |
| 577 | indio_dev->name, | 578 | indio_dev->name, |
| 578 | indio_dev->id); | 579 | iio_device_id(indio_dev)); |
| 579 | if (!data->drdy_trig) | 580 | if (!data->drdy_trig) |
| 580 | return -ENOMEM; | 581 | return -ENOMEM; |
| 581 | 582 | ||
| @@ -23,10 +23,6 @@ · 22 unmodified lines | |||
| 23 | #define LSM9DS1_MAGN_DEV_NAME "lsm9ds1_magn" | 23 | #define LSM9DS1_MAGN_DEV_NAME "lsm9ds1_magn" |
| 24 | #define IIS2MDC_MAGN_DEV_NAME "iis2mdc" | 24 | #define IIS2MDC_MAGN_DEV_NAME "iis2mdc" |
| 25 | 25 | ||
| 26 | const struct st_sensor_settings *st_magn_get_settings(const char *name); | ||
| 27 | int st_magn_common_probe(struct iio_dev *indio_dev); | ||
| 28 | void st_magn_common_remove(struct iio_dev *indio_dev); | ||
| 29 | |||
| 30 | #ifdef CONFIG_IIO_BUFFER | 26 | #ifdef CONFIG_IIO_BUFFER |
| 31 | int st_magn_allocate_ring(struct iio_dev *indio_dev); | 27 | int st_magn_allocate_ring(struct iio_dev *indio_dev); |
| 32 | void st_magn_deallocate_ring(struct iio_dev *indio_dev); | 28 | void st_magn_deallocate_ring(struct iio_dev *indio_dev); |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | |||
| 33 | /* FULLSCALE */ | 33 | /* FULLSCALE */ |
| 34 | #define ST_MAGN_FS_AVL_1300MG 1300 | 34 | #define ST_MAGN_FS_AVL_1300MG 1300 |
| 35 | #define ST_MAGN_FS_AVL_1900MG 1900 | 35 | #define ST_MAGN_FS_AVL_1900MG 1900 |
| 36 | #define ST_MAGN_FS_AVL_2000MG 2000 | ||
| 36 | #define ST_MAGN_FS_AVL_2500MG 2500 | 37 | #define ST_MAGN_FS_AVL_2500MG 2500 |
| 37 | #define ST_MAGN_FS_AVL_4000MG 4000 | 38 | #define ST_MAGN_FS_AVL_4000MG 4000 |
| 38 | #define ST_MAGN_FS_AVL_4700MG 4700 | 39 | #define ST_MAGN_FS_AVL_4700MG 4700 |
| @@ -53,51 +54,95 @@ · 14 unmodified lines | |||
| 53 | #define ST_MAGN_3_OUT_Y_L_ADDR 0x6a | 54 | #define ST_MAGN_3_OUT_Y_L_ADDR 0x6a |
| 54 | #define ST_MAGN_3_OUT_Z_L_ADDR 0x6c | 55 | #define ST_MAGN_3_OUT_Z_L_ADDR 0x6c |
| 55 | 56 | ||
| 57 | /* Special L addresses for sensor 4 */ | ||
| 58 | #define ST_MAGN_4_OUT_X_L_ADDR 0x08 | ||
| 59 | #define ST_MAGN_4_OUT_Y_L_ADDR 0x0a | ||
| 60 | #define ST_MAGN_4_OUT_Z_L_ADDR 0x0c | ||
| 61 | |||
| 62 | static const struct iio_mount_matrix * | ||
| 63 | st_magn_get_mount_matrix(const struct iio_dev *indio_dev, | ||
| 64 | const struct iio_chan_spec *chan) | ||
| 65 | { | ||
| 66 | struct st_sensor_data *mdata = iio_priv(indio_dev); | ||
| 67 | |||
| 68 | return &mdata->mount_matrix; | ||
| 69 | } | ||
| 70 | |||
| 71 | static const struct iio_chan_spec_ext_info st_magn_mount_matrix_ext_info[] = { | ||
| 72 | IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_magn_get_mount_matrix), | ||
| 73 | { } | ||
| 74 | }; | ||
| 75 | |||
| 56 | static const struct iio_chan_spec st_magn_16bit_channels[] = { | 76 | static const struct iio_chan_spec st_magn_16bit_channels[] = { |
| 57 | ST_SENSORS_LSM_CHANNELS(IIO_MAGN, | 77 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, |
| 58 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 78 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 59 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_BE, 16, 16, | 79 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_BE, 16, 16, |
| 60 | ST_MAGN_DEFAULT_OUT_X_H_ADDR), | 80 | ST_MAGN_DEFAULT_OUT_X_H_ADDR, |
| 61 | ST_SENSORS_LSM_CHANNELS(IIO_MAGN, | 81 | st_magn_mount_matrix_ext_info), |
| 82 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, | ||
| 62 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 83 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 63 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_BE, 16, 16, | 84 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_BE, 16, 16, |
| 64 | ST_MAGN_DEFAULT_OUT_Y_H_ADDR), | 85 | ST_MAGN_DEFAULT_OUT_Y_H_ADDR, |
| 65 | ST_SENSORS_LSM_CHANNELS(IIO_MAGN, | 86 | st_magn_mount_matrix_ext_info), |
| 87 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, | ||
| 66 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 88 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 67 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_BE, 16, 16, | 89 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_BE, 16, 16, |
| 68 | ST_MAGN_DEFAULT_OUT_Z_H_ADDR), | 90 | ST_MAGN_DEFAULT_OUT_Z_H_ADDR, |
| 91 | st_magn_mount_matrix_ext_info), | ||
| 69 | IIO_CHAN_SOFT_TIMESTAMP(3) | 92 | IIO_CHAN_SOFT_TIMESTAMP(3) |
| 70 | }; | 93 | }; |
| 71 | 94 | ||
| 72 | static const struct iio_chan_spec st_magn_2_16bit_channels[] = { | 95 | static const struct iio_chan_spec st_magn_2_16bit_channels[] = { |
| 73 | ST_SENSORS_LSM_CHANNELS(IIO_MAGN, | 96 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, |
| 74 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 97 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 75 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, | 98 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, |
| 76 | ST_MAGN_2_OUT_X_L_ADDR), | 99 | ST_MAGN_2_OUT_X_L_ADDR, |
| 77 | ST_SENSORS_LSM_CHANNELS(IIO_MAGN, | 100 | st_magn_mount_matrix_ext_info), |
| 101 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, | ||
| 78 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 102 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 79 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, | 103 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, |
| 80 | ST_MAGN_2_OUT_Y_L_ADDR), | 104 | ST_MAGN_2_OUT_Y_L_ADDR, |
| 81 | ST_SENSORS_LSM_CHANNELS(IIO_MAGN, | 105 | st_magn_mount_matrix_ext_info), |
| 106 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, | ||
| 82 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 107 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 83 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, | 108 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, |
| 84 | ST_MAGN_2_OUT_Z_L_ADDR), | 109 | ST_MAGN_2_OUT_Z_L_ADDR, |
| 110 | st_magn_mount_matrix_ext_info), | ||
| 85 | IIO_CHAN_SOFT_TIMESTAMP(3) | 111 | IIO_CHAN_SOFT_TIMESTAMP(3) |
| 86 | }; | 112 | }; |
| 87 | 113 | ||
| 88 | static const struct iio_chan_spec st_magn_3_16bit_channels[] = { | 114 | static const struct iio_chan_spec st_magn_3_16bit_channels[] = { |
| 115 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, | ||
| 116 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | ||
| 117 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, | ||
| 118 | ST_MAGN_3_OUT_X_L_ADDR, | ||
| 119 | st_magn_mount_matrix_ext_info), | ||
| 120 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, | ||
| 121 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | ||
| 122 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, | ||
| 123 | ST_MAGN_3_OUT_Y_L_ADDR, | ||
| 124 | st_magn_mount_matrix_ext_info), | ||
| 125 | ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN, | ||
| 126 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | ||
| 127 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, | ||
| 128 | ST_MAGN_3_OUT_Z_L_ADDR, | ||
| 129 | st_magn_mount_matrix_ext_info), | ||
| 130 | IIO_CHAN_SOFT_TIMESTAMP(3) | ||
| 131 | }; | ||
| 132 | |||
| 133 | static const struct iio_chan_spec st_magn_4_16bit_channels[] = { | ||
| 89 | ST_SENSORS_LSM_CHANNELS(IIO_MAGN, | 134 | ST_SENSORS_LSM_CHANNELS(IIO_MAGN, |
| 90 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 135 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 91 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, | 136 | ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16, |
| 92 | ST_MAGN_3_OUT_X_L_ADDR), | 137 | ST_MAGN_4_OUT_X_L_ADDR), |
| 93 | ST_SENSORS_LSM_CHANNELS(IIO_MAGN, | 138 | ST_SENSORS_LSM_CHANNELS(IIO_MAGN, |
| 94 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 139 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 95 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, | 140 | ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16, |
| 96 | ST_MAGN_3_OUT_Y_L_ADDR), | 141 | ST_MAGN_4_OUT_Y_L_ADDR), |
| 97 | ST_SENSORS_LSM_CHANNELS(IIO_MAGN, | 142 | ST_SENSORS_LSM_CHANNELS(IIO_MAGN, |
| 98 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 143 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| 99 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, | 144 | ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16, |
| 100 | ST_MAGN_3_OUT_Z_L_ADDR), | 145 | ST_MAGN_4_OUT_Z_L_ADDR), |
| 101 | IIO_CHAN_SOFT_TIMESTAMP(3) | 146 | IIO_CHAN_SOFT_TIMESTAMP(3) |
| 102 | }; | 147 | }; |
| 103 | 148 | ||
| @@ -381,6 +426,87 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = { · 277 unmodified lines | |||
| 381 | .multi_read_bit = false, | 426 | .multi_read_bit = false, |
| 382 | .bootime = 2, | 427 | .bootime = 2, |
| 383 | }, | 428 | }, |
| 429 | { | ||
| 430 | .wai = 0x49, | ||
| 431 | .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, | ||
| 432 | .sensors_supported = { | ||
| 433 | [0] = LSM9DS0_IMU_DEV_NAME, | ||
| 434 | }, | ||
| 435 | .ch = (struct iio_chan_spec *)st_magn_4_16bit_channels, | ||
| 436 | .odr = { | ||
| 437 | .addr = 0x24, | ||
| 438 | .mask = GENMASK(4, 2), | ||
| 439 | .odr_avl = { | ||
| 440 | { 3, 0x00, }, | ||
| 441 | { 6, 0x01, }, | ||
| 442 | { 12, 0x02, }, | ||
| 443 | { 25, 0x03, }, | ||
| 444 | { 50, 0x04, }, | ||
| 445 | { 100, 0x05, }, | ||
| 446 | }, | ||
| 447 | }, | ||
| 448 | .pw = { | ||
| 449 | .addr = 0x26, | ||
| 450 | .mask = GENMASK(1, 0), | ||
| 451 | .value_on = 0x00, | ||
| 452 | .value_off = 0x03, | ||
| 453 | }, | ||
| 454 | .fs = { | ||
| 455 | .addr = 0x25, | ||
| 456 | .mask = GENMASK(6, 5), | ||
| 457 | .fs_avl = { | ||
| 458 | [0] = { | ||
| 459 | .num = ST_MAGN_FS_AVL_2000MG, | ||
| 460 | .value = 0x00, | ||
| 461 | .gain = 73, | ||
| 462 | }, | ||
| 463 | [1] = { | ||
| 464 | .num = ST_MAGN_FS_AVL_4000MG, | ||
| 465 | .value = 0x01, | ||
| 466 | .gain = 146, | ||
| 467 | }, | ||
| 468 | [2] = { | ||
| 469 | .num = ST_MAGN_FS_AVL_8000MG, | ||
| 470 | .value = 0x02, | ||
| 471 | .gain = 292, | ||
| 472 | }, | ||
| 473 | [3] = { | ||
| 474 | .num = ST_MAGN_FS_AVL_12000MG, | ||
| 475 | .value = 0x03, | ||
| 476 | .gain = 438, | ||
| 477 | }, | ||
| 478 | }, | ||
| 479 | }, | ||
| 480 | .bdu = { | ||
| 481 | .addr = 0x20, | ||
| 482 | .mask = BIT(3), | ||
| 483 | }, | ||
| 484 | .drdy_irq = { | ||
| 485 | .int1 = { | ||
| 486 | .addr = 0x22, | ||
| 487 | .mask = BIT(1), | ||
| 488 | }, | ||
| 489 | .int2 = { | ||
| 490 | .addr = 0x23, | ||
| 491 | .mask = BIT(2), | ||
| 492 | }, | ||
| 493 | .stat_drdy = { | ||
| 494 | .addr = 0x07, | ||
| 495 | .mask = GENMASK(2, 0), | ||
| 496 | }, | ||
| 497 | }, | ||
| 498 | .sim = { | ||
| 499 | .addr = 0x21, | ||
| 500 | .value = BIT(0), | ||
| 501 | }, | ||
| 502 | .multi_read_bit = true, | ||
| 503 | .bootime = 2, | ||
| 504 | }, | ||
| 505 | }; | ||
| 506 | |||
| 507 | /* Default magn DRDY is available on INT2 pin */ | ||
| 508 | static const struct st_sensors_platform_data default_magn_pdata = { | ||
| 509 | .drdy_int_pin = 2, | ||
| 384 | }; | 510 | }; |
| 385 | 511 | ||
| 386 | static int st_magn_read_raw(struct iio_dev *indio_dev, | 512 | static int st_magn_read_raw(struct iio_dev *indio_dev, |
| @@ -490,33 +616,37 @@ EXPORT_SYMBOL(st_magn_get_settings); · 103 unmodified lines | |||
| 490 | int st_magn_common_probe(struct iio_dev *indio_dev) | 616 | int st_magn_common_probe(struct iio_dev *indio_dev) |
| 491 | { | 617 | { |
| 492 | struct st_sensor_data *mdata = iio_priv(indio_dev); | 618 | struct st_sensor_data *mdata = iio_priv(indio_dev); |
| 619 | struct st_sensors_platform_data *pdata = dev_get_platdata(mdata->dev); | ||
| 493 | int err; | 620 | int err; |
| 494 | 621 | ||
| 495 | indio_dev->modes = INDIO_DIRECT_MODE; | 622 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 496 | indio_dev->info = &magn_info; | 623 | indio_dev->info = &magn_info; |
| 497 | 624 | ||
| 498 | err = st_sensors_power_enable(indio_dev); | ||
| 499 | if (err) | ||
| 500 | return err; | ||
| 501 | |||
| 502 | err = st_sensors_verify_id(indio_dev); | 625 | err = st_sensors_verify_id(indio_dev); |
| 503 | if (err < 0) | 626 | if (err < 0) |
| 504 | goto st_magn_power_off; | 627 | return err; |
| 505 | 628 | ||
| 506 | mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS; | 629 | mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS; |
| 507 | indio_dev->channels = mdata->sensor_settings->ch; | 630 | indio_dev->channels = mdata->sensor_settings->ch; |
| 508 | indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; | 631 | indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; |
| 509 | 632 | ||
| 633 | err = iio_read_mount_matrix(mdata->dev, &mdata->mount_matrix); | ||
| 634 | if (err) | ||
| 635 | return err; | ||
| 636 | |||
| 510 | mdata->current_fullscale = &mdata->sensor_settings->fs.fs_avl[0]; | 637 | mdata->current_fullscale = &mdata->sensor_settings->fs.fs_avl[0]; |
| 511 | mdata->odr = mdata->sensor_settings->odr.odr_avl[0].hz; | 638 | mdata->odr = mdata->sensor_settings->odr.odr_avl[0].hz; |
| 512 | 639 | ||
| 513 | err = st_sensors_init_sensor(indio_dev, NULL); | 640 | if (!pdata) |
| 641 | pdata = (struct st_sensors_platform_data *)&default_magn_pdata; | ||
| 642 | |||
| 643 | err = st_sensors_init_sensor(indio_dev, pdata); | ||
| 514 | if (err < 0) | 644 | if (err < 0) |
| 515 | goto st_magn_power_off; | 645 | return err; |
| 516 | 646 | ||
| 517 | err = st_magn_allocate_ring(indio_dev); | 647 | err = st_magn_allocate_ring(indio_dev); |
| 518 | if (err < 0) | 648 | if (err < 0) |
| 519 | goto st_magn_power_off; | 649 | return err; |
| 520 | 650 | ||
| 521 | if (mdata->irq > 0) { | 651 | if (mdata->irq > 0) { |
| 522 | err = st_sensors_allocate_trigger(indio_dev, | 652 | err = st_sensors_allocate_trigger(indio_dev, |
| @@ -539,9 +669,6 @@ st_magn_device_register_error: · 16 unmodified lines | |||
| 539 | st_sensors_deallocate_trigger(indio_dev); | 669 | st_sensors_deallocate_trigger(indio_dev); |
| 540 | st_magn_probe_trigger_error: | 670 | st_magn_probe_trigger_error: |
| 541 | st_magn_deallocate_ring(indio_dev); | 671 | st_magn_deallocate_ring(indio_dev); |
| 542 | st_magn_power_off: | ||
| 543 | st_sensors_power_disable(indio_dev); | ||
| 544 | |||
| 545 | return err; | 672 | return err; |
| 546 | } | 673 | } |
| 547 | EXPORT_SYMBOL(st_magn_common_probe); | 674 | EXPORT_SYMBOL(st_magn_common_probe); |
| @@ -550,8 +677,6 @@ void st_magn_common_remove(struct iio_dev *indio_dev) · 2 unmodified lines | |||
| 550 | { | 677 | { |
| 551 | struct st_sensor_data *mdata = iio_priv(indio_dev); | 678 | struct st_sensor_data *mdata = iio_priv(indio_dev); |
| 552 | 679 | ||
| 553 | st_sensors_power_disable(indio_dev); | ||
| 554 | |||
| 555 | iio_device_unregister(indio_dev); | 680 | iio_device_unregister(indio_dev); |
| 556 | if (mdata->irq > 0) | 681 | if (mdata->irq > 0) |
| 557 | st_sensors_deallocate_trigger(indio_dev); | 682 | st_sensors_deallocate_trigger(indio_dev); |
| @@ -82,16 +82,28 @@ static int st_magn_i2c_probe(struct i2c_client *client, · 81 unmodified lines | |||
| 82 | if (err < 0) | 82 | if (err < 0) |
| 83 | return err; | 83 | return err; |
| 84 | 84 | ||
| 85 | err = st_sensors_power_enable(indio_dev); | ||
| 86 | if (err) | ||
| 87 | return err; | ||
| 88 | |||
| 85 | err = st_magn_common_probe(indio_dev); | 89 | err = st_magn_common_probe(indio_dev); |
| 86 | if (err < 0) | 90 | if (err < 0) |
| 87 | return err; | 91 | goto st_magn_power_off; |
| 88 | 92 | ||
| 89 | return 0; | 93 | return 0; |
| 94 | |||
| 95 | st_magn_power_off: | ||
| 96 | st_sensors_power_disable(indio_dev); | ||
| 97 | |||
| 98 | return err; | ||
| 90 | } | 99 | } |
| 91 | 100 | ||
| 92 | static int st_magn_i2c_remove(struct i2c_client *client) | 101 | static int st_magn_i2c_remove(struct i2c_client *client) |
| 93 | { | 102 | { |
| 94 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | 103 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 104 | |||
| 105 | st_sensors_power_disable(indio_dev); | ||
| 106 | |||
| 95 | st_magn_common_remove(indio_dev); | 107 | st_magn_common_remove(indio_dev); |
| 96 | 108 | ||
| 97 | return 0; | 109 | return 0; |
| @@ -76,16 +76,28 @@ static int st_magn_spi_probe(struct spi_device *spi) · 75 unmodified lines | |||
| 76 | if (err < 0) | 76 | if (err < 0) |
| 77 | return err; | 77 | return err; |
| 78 | 78 | ||
| 79 | err = st_sensors_power_enable(indio_dev); | ||
| 80 | if (err) | ||
| 81 | return err; | ||
| 82 | |||
| 79 | err = st_magn_common_probe(indio_dev); | 83 | err = st_magn_common_probe(indio_dev); |
| 80 | if (err < 0) | 84 | if (err < 0) |
| 81 | return err; | 85 | goto st_magn_power_off; |
| 82 | 86 | ||
| 83 | return 0; | 87 | return 0; |
| 88 | |||
| 89 | st_magn_power_off: | ||
| 90 | st_sensors_power_disable(indio_dev); | ||
| 91 | |||
| 92 | return err; | ||
| 84 | } | 93 | } |
| 85 | 94 | ||
| 86 | static int st_magn_spi_remove(struct spi_device *spi) | 95 | static int st_magn_spi_remove(struct spi_device *spi) |
| 87 | { | 96 | { |
| 88 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | 97 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
| 98 | |||
| 99 | st_sensors_power_disable(indio_dev); | ||
| 100 | |||
| 89 | st_magn_common_remove(indio_dev); | 101 | st_magn_common_remove(indio_dev); |
| 90 | 102 | ||
| 91 | return 0; | 103 | return 0; |
| @@ -831,7 +831,7 @@ static int yas5xx_probe(struct i2c_client *i2c, · 830 unmodified lines | |||
| 831 | yas5xx->dev = dev; | 831 | yas5xx->dev = dev; |
| 832 | mutex_init(&yas5xx->lock); | 832 | mutex_init(&yas5xx->lock); |
| 833 | 833 | ||
| 834 | ret = iio_read_mount_matrix(dev, "mount-matrix", &yas5xx->orientation); | 834 | ret = iio_read_mount_matrix(dev, &yas5xx->orientation); |
| 835 | if (ret) | 835 | if (ret) |
| 836 | return ret; | 836 | return ret; |
| 837 | 837 | ||
| @@ -7,13 +7,10 @@ · 6 unmodified lines | |||
| 7 | #include <linux/device.h> | 7 | #include <linux/device.h> |
| 8 | #include <linux/platform_device.h> | 8 | #include <linux/platform_device.h> |
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/interrupt.h> | 10 | #include <linux/mod_devicetable.h> |
| 11 | #include <linux/irq.h> | ||
| 12 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
| 13 | #include <linux/delay.h> | ||
| 14 | #include <linux/hid-sensor-hub.h> | 12 | #include <linux/hid-sensor-hub.h> |
| 15 | #include <linux/iio/iio.h> | 13 | #include <linux/iio/iio.h> |
| 16 | #include <linux/iio/sysfs.h> | ||
| 17 | #include <linux/iio/buffer.h> | 14 | #include <linux/iio/buffer.h> |
| 18 | #include "../common/hid-sensors/hid-sensor-trigger.h" | 15 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 19 | 16 | ||
| @@ -425,3 +422,4 @@ module_platform_driver(hid_incl_3d_platform_driver); · 405 unmodified lines | |||
| 425 | MODULE_DESCRIPTION("HID Sensor Inclinometer 3D"); | 422 | MODULE_DESCRIPTION("HID Sensor Inclinometer 3D"); |
| 426 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); | 423 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); |
| 427 | MODULE_LICENSE("GPL"); | 424 | MODULE_LICENSE("GPL"); |
| 425 | MODULE_IMPORT_NS(IIO_HID); | ||
| @@ -7,9 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <linux/device.h> | 7 | #include <linux/device.h> |
| 8 | #include <linux/platform_device.h> | 8 | #include <linux/platform_device.h> |
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/interrupt.h> | 10 | #include <linux/mod_devicetable.h> |
| 11 | #include <linux/irq.h> | ||
| 12 | #include <linux/slab.h> | ||
| 13 | #include <linux/hid-sensor-hub.h> | 11 | #include <linux/hid-sensor-hub.h> |
| 14 | #include <linux/iio/iio.h> | 12 | #include <linux/iio/iio.h> |
| 15 | #include <linux/iio/sysfs.h> | 13 | #include <linux/iio/sysfs.h> |
| @@ -373,3 +371,4 @@ module_platform_driver(hid_dev_rot_platform_driver); · 357 unmodified lines | |||
| 373 | MODULE_DESCRIPTION("HID Sensor Device Rotation"); | 371 | MODULE_DESCRIPTION("HID Sensor Device Rotation"); |
| 374 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); | 372 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); |
| 375 | MODULE_LICENSE("GPL"); | 373 | MODULE_LICENSE("GPL"); |
| 374 | MODULE_IMPORT_NS(IIO_HID); | ||
| @@ -7,6 +7,8 @@ · 6 unmodified lines | |||
| 7 | #include <linux/iio/buffer.h> | 7 | #include <linux/iio/buffer.h> |
| 8 | #include <linux/iio/iio.h> | 8 | #include <linux/iio/iio.h> |
| 9 | #include <linux/platform_device.h> | 9 | #include <linux/platform_device.h> |
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/mod_devicetable.h> | ||
| 10 | 12 | ||
| 11 | #include "../common/hid-sensors/hid-sensor-trigger.h" | 13 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 12 | 14 | ||
| @@ -303,7 +305,6 @@ static int hid_hinge_probe(struct platform_device *pdev) · 290 unmodified lines | |||
| 303 | return ret; | 305 | return ret; |
| 304 | } | 306 | } |
| 305 | 307 | ||
| 306 | indio_dev->dev.parent = &pdev->dev; | ||
| 307 | indio_dev->info = &hinge_info; | 308 | indio_dev->info = &hinge_info; |
| 308 | indio_dev->name = "hinge"; | 309 | indio_dev->name = "hinge"; |
| 309 | indio_dev->modes = INDIO_DIRECT_MODE; | 310 | indio_dev->modes = INDIO_DIRECT_MODE; |
| @@ -377,3 +378,4 @@ module_platform_driver(hid_hinge_platform_driver); · 67 unmodified lines | |||
| 377 | MODULE_DESCRIPTION("HID Sensor INTEL Hinge"); | 378 | MODULE_DESCRIPTION("HID Sensor INTEL Hinge"); |
| 378 | MODULE_AUTHOR("Ye Xiang <xiang.ye@intel.com>"); | 379 | MODULE_AUTHOR("Ye Xiang <xiang.ye@intel.com>"); |
| 379 | MODULE_LICENSE("GPL"); | 380 | MODULE_LICENSE("GPL"); |
| 381 | MODULE_IMPORT_NS(IIO_HID); | ||
| @@ -71,8 +71,8 @@ struct lmp91000_data { · 70 unmodified lines | |||
| 71 | 71 | ||
| 72 | struct completion completion; | 72 | struct completion completion; |
| 73 | u8 chan_select; | 73 | u8 chan_select; |
| 74 | 74 | /* 64-bit data + 64-bit naturally aligned timestamp */ | |
| 75 | u32 buffer[4]; /* 64-bit data + 64-bit timestamp */ | 75 | u32 buffer[4] __aligned(8); |
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | static const struct iio_chan_spec lmp91000_channels[] = { | 78 | static const struct iio_chan_spec lmp91000_channels[] = { |
| @@ -323,7 +323,8 @@ static int lmp91000_probe(struct i2c_client *client, · 244 unmodified lines | |||
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | data->trig = devm_iio_trigger_alloc(dev, "%s-mux%d", | 325 | data->trig = devm_iio_trigger_alloc(dev, "%s-mux%d", |
| 326 | indio_dev->name, indio_dev->id); | 326 | indio_dev->name, |
| 327 | iio_device_id(indio_dev)); | ||
| 327 | if (!data->trig) { | 328 | if (!data->trig) { |
| 328 | dev_err(dev, "cannot allocate iio trigger.\n"); | 329 | dev_err(dev, "cannot allocate iio trigger.\n"); |
| 329 | return -ENOMEM; | 330 | return -ENOMEM; |
| @@ -6,13 +6,10 @@ · 5 unmodified lines | |||
| 6 | #include <linux/device.h> | 6 | #include <linux/device.h> |
| 7 | #include <linux/platform_device.h> | 7 | #include <linux/platform_device.h> |
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/interrupt.h> | 9 | #include <linux/mod_devicetable.h> |
| 10 | #include <linux/irq.h> | ||
| 11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
| 12 | #include <linux/delay.h> | ||
| 13 | #include <linux/hid-sensor-hub.h> | 11 | #include <linux/hid-sensor-hub.h> |
| 14 | #include <linux/iio/iio.h> | 12 | #include <linux/iio/iio.h> |
| 15 | #include <linux/iio/sysfs.h> | ||
| 16 | #include <linux/iio/buffer.h> | 13 | #include <linux/iio/buffer.h> |
| 17 | #include "../common/hid-sensors/hid-sensor-trigger.h" | 14 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| 18 | 15 | ||
| @@ -357,3 +354,4 @@ module_platform_driver(hid_press_platform_driver); · 338 unmodified lines | |||
| 357 | MODULE_DESCRIPTION("HID Sensor Pressure"); | 354 | MODULE_DESCRIPTION("HID Sensor Pressure"); |
| 358 | MODULE_AUTHOR("Archana Patni <archana.patni@intel.com>"); | 355 | MODULE_AUTHOR("Archana Patni <archana.patni@intel.com>"); |
| 359 | MODULE_LICENSE("GPL"); | 356 | MODULE_LICENSE("GPL"); |
| 357 | MODULE_IMPORT_NS(IIO_HID); | ||
| @@ -250,7 +250,9 @@ static int icp10100_get_measures(struct icp10100_state *st, · 249 unmodified lines | |||
| 250 | __be16 measures[3]; | 250 | __be16 measures[3]; |
| 251 | int ret; | 251 | int ret; |
| 252 | 252 | ||
| 253 | pm_runtime_get_sync(&st->client->dev); | 253 | ret = pm_runtime_resume_and_get(&st->client->dev); |
| 254 | if (ret < 0) | ||
| 255 | return ret; | ||
| 254 | 256 | ||
| 255 | mutex_lock(&st->lock); | 257 | mutex_lock(&st->lock); |
| 256 | cmd = &icp10100_cmd_measure[st->mode]; | 258 | cmd = &icp10100_cmd_measure[st->mode]; |
| @@ -525,7 +527,6 @@ static void icp10100_pm_disable(void *data) · 268 unmodified lines | |||
| 525 | { | 527 | { |
| 526 | struct device *dev = data; | 528 | struct device *dev = data; |
| 527 | 529 | ||
| 528 | pm_runtime_put_sync_suspend(dev); | ||
| 529 | pm_runtime_disable(dev); | 530 | pm_runtime_disable(dev); |
| 530 | } | 531 | } |
| 531 | 532 | ||
| @@ -41,10 +41,6 @@ static __maybe_unused const struct st_sensors_platform_data default_press_pdata · 40 unmodified lines | |||
| 41 | .drdy_int_pin = 1, | 41 | .drdy_int_pin = 1, |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | const struct st_sensor_settings *st_press_get_settings(const char *name); | ||
| 45 | int st_press_common_probe(struct iio_dev *indio_dev); | ||
| 46 | void st_press_common_remove(struct iio_dev *indio_dev); | ||
| 47 | |||
| 48 | #ifdef CONFIG_IIO_BUFFER | 44 | #ifdef CONFIG_IIO_BUFFER |
| 49 | int st_press_allocate_ring(struct iio_dev *indio_dev); | 45 | int st_press_allocate_ring(struct iio_dev *indio_dev); |
| 50 | void st_press_deallocate_ring(struct iio_dev *indio_dev); | 46 | void st_press_deallocate_ring(struct iio_dev *indio_dev); |
| @@ -689,13 +689,9 @@ int st_press_common_probe(struct iio_dev *indio_dev) · 688 unmodified lines | |||
| 689 | indio_dev->modes = INDIO_DIRECT_MODE; | 689 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 690 | indio_dev->info = &press_info; | 690 | indio_dev->info = &press_info; |
| 691 | 691 | ||
| 692 | err = st_sensors_power_enable(indio_dev); | ||
| 693 | if (err) | ||
| 694 | return err; | ||
| 695 | |||
| 696 | err = st_sensors_verify_id(indio_dev); | 692 | err = st_sensors_verify_id(indio_dev); |
| 697 | if (err < 0) | 693 | if (err < 0) |
| 698 | goto st_press_power_off; | 694 | return err; |
| 699 | 695 | ||
| 700 | /* | 696 | /* |
| 701 | * Skip timestamping channel while declaring available channels to | 697 | * Skip timestamping channel while declaring available channels to |
| @@ -718,11 +714,11 @@ int st_press_common_probe(struct iio_dev *indio_dev) · 16 unmodified lines | |||
| 718 | 714 | ||
| 719 | err = st_sensors_init_sensor(indio_dev, pdata); | 715 | err = st_sensors_init_sensor(indio_dev, pdata); |
| 720 | if (err < 0) | 716 | if (err < 0) |
| 721 | goto st_press_power_off; | 717 | return err; |
| 722 | 718 | ||
| 723 | err = st_press_allocate_ring(indio_dev); | 719 | err = st_press_allocate_ring(indio_dev); |
| 724 | if (err < 0) | 720 | if (err < 0) |
| 725 | goto st_press_power_off; | 721 | return err; |
| 726 | 722 | ||
| 727 | if (press_data->irq > 0) { | 723 | if (press_data->irq > 0) { |
| 728 | err = st_sensors_allocate_trigger(indio_dev, | 724 | err = st_sensors_allocate_trigger(indio_dev, |
| @@ -745,9 +741,6 @@ st_press_device_register_error: · 16 unmodified lines | |||
| 745 | st_sensors_deallocate_trigger(indio_dev); | 741 | st_sensors_deallocate_trigger(indio_dev); |
| 746 | st_press_probe_trigger_error: | 742 | st_press_probe_trigger_error: |
| 747 | st_press_deallocate_ring(indio_dev); | 743 | st_press_deallocate_ring(indio_dev); |
| 748 | st_press_power_off: | ||
| 749 | st_sensors_power_disable(indio_dev); | ||
| 750 | |||
| 751 | return err; | 744 | return err; |
| 752 | } | 745 | } |
| 753 | EXPORT_SYMBOL(st_press_common_probe); | 746 | EXPORT_SYMBOL(st_press_common_probe); |
| @@ -756,8 +749,6 @@ void st_press_common_remove(struct iio_dev *indio_dev) · 2 unmodified lines | |||
| 756 | { | 749 | { |
| 757 | struct st_sensor_data *press_data = iio_priv(indio_dev); | 750 | struct st_sensor_data *press_data = iio_priv(indio_dev); |
| 758 | 751 | ||
| 759 | st_sensors_power_disable(indio_dev); | ||
| 760 | |||
| 761 | iio_device_unregister(indio_dev); | 752 | iio_device_unregister(indio_dev); |
| 762 | if (press_data->irq > 0) | 753 | if (press_data->irq > 0) |
| 763 | st_sensors_deallocate_trigger(indio_dev); | 754 | st_sensors_deallocate_trigger(indio_dev); |
| @@ -98,16 +98,29 @@ static int st_press_i2c_probe(struct i2c_client *client, · 97 unmodified lines | |||
| 98 | if (ret < 0) | 98 | if (ret < 0) |
| 99 | return ret; | 99 | return ret; |
| 100 | 100 | ||
| 101 | ret = st_sensors_power_enable(indio_dev); | ||
| 102 | if (ret) | ||
| 103 | return ret; | ||
| 104 | |||
| 101 | ret = st_press_common_probe(indio_dev); | 105 | ret = st_press_common_probe(indio_dev); |
| 102 | if (ret < 0) | 106 | if (ret < 0) |
| 103 | return ret; | 107 | goto st_press_power_off; |
| 104 | 108 | ||
| 105 | return 0; | 109 | return 0; |
| 110 | |||
| 111 | st_press_power_off: | ||
| 112 | st_sensors_power_disable(indio_dev); | ||
| 113 | |||
| 114 | return ret; | ||
| 106 | } | 115 | } |
| 107 | 116 | ||
| 108 | static int st_press_i2c_remove(struct i2c_client *client) | 117 | static int st_press_i2c_remove(struct i2c_client *client) |
| 109 | { | 118 | { |
| 110 | st_press_common_remove(i2c_get_clientdata(client)); | 119 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
| 120 | |||
| 121 | st_sensors_power_disable(indio_dev); | ||
| 122 | |||
| 123 | st_press_common_remove(indio_dev); | ||
| 111 | 124 | ||
| 112 | return 0; | 125 | return 0; |
| 113 | } | 126 | } |
| @@ -82,16 +82,29 @@ static int st_press_spi_probe(struct spi_device *spi) · 81 unmodified lines | |||
| 82 | if (err < 0) | 82 | if (err < 0) |
| 83 | return err; | 83 | return err; |
| 84 | 84 | ||
| 85 | err = st_sensors_power_enable(indio_dev); | ||
| 86 | if (err) | ||
| 87 | return err; | ||
| 88 | |||
| 85 | err = st_press_common_probe(indio_dev); | 89 | err = st_press_common_probe(indio_dev); |
| 86 | if (err < 0) | 90 | if (err < 0) |
| 87 | return err; | 91 | goto st_press_power_off; |
| 88 | 92 | ||
| 89 | return 0; | 93 | return 0; |
| 94 | |||
| 95 | st_press_power_off: | ||
| 96 | st_sensors_power_disable(indio_dev); | ||
| 97 | |||
| 98 | return err; | ||
| 90 | } | 99 | } |
| 91 | 100 | ||
| 92 | static int st_press_spi_remove(struct spi_device *spi) | 101 | static int st_press_spi_remove(struct spi_device *spi) |
| 93 | { | 102 | { |
| 94 | st_press_common_remove(spi_get_drvdata(spi)); | 103 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
| 104 | |||
| 105 | st_sensors_power_disable(indio_dev); | ||
| 106 | |||
| 107 | st_press_common_remove(indio_dev); | ||
| 95 | 108 | ||
| 96 | return 0; | 109 | return 0; |
| 97 | } | 110 | } |
| @@ -1408,7 +1408,8 @@ static int zpa2326_init_managed_trigger(struct device *parent, · 1407 unmodified lines | |||
| 1408 | return 0; | 1408 | return 0; |
| 1409 | 1409 | ||
| 1410 | trigger = devm_iio_trigger_alloc(parent, "%s-dev%d", | 1410 | trigger = devm_iio_trigger_alloc(parent, "%s-dev%d", |
| 1411 | indio_dev->name, indio_dev->id); | 1411 | indio_dev->name, |
| 1412 | iio_device_id(indio_dev)); | ||
| 1412 | if (!trigger) | 1413 | if (!trigger) |
| 1413 | return -ENOMEM; | 1414 | return -ENOMEM; |
| 1414 | 1415 | ||
| @@ -59,7 +59,11 @@ struct as3935_state { · 58 unmodified lines | |||
| 59 | unsigned long noise_tripped; | 59 | unsigned long noise_tripped; |
| 60 | u32 tune_cap; | 60 | u32 tune_cap; |
| 61 | u32 nflwdth_reg; | 61 | u32 nflwdth_reg; |
| 62 | u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */ | 62 | /* Ensure timestamp is naturally aligned */ |
| 63 | struct { | ||
| 64 | u8 chan; | ||
| 65 | s64 timestamp __aligned(8); | ||
| 66 | } scan; | ||
| 63 | u8 buf[2] ____cacheline_aligned; | 67 | u8 buf[2] ____cacheline_aligned; |
| 64 | }; | 68 | }; |
| 65 | 69 | ||
| @@ -225,8 +229,8 @@ static irqreturn_t as3935_trigger_handler(int irq, void *private) · 159 unmodified lines | |||
| 225 | if (ret) | 229 | if (ret) |
| 226 | goto err_read; | 230 | goto err_read; |
| 227 | 231 | ||
| 228 | st->buffer[0] = val & AS3935_DATA_MASK; | 232 | st->scan.chan = val & AS3935_DATA_MASK; |
| 229 | iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer, | 233 | iio_push_to_buffers_with_timestamp(indio_dev, &st->scan, |
| 230 | iio_get_time_ns(indio_dev)); | 234 | iio_get_time_ns(indio_dev)); |
| 231 | err_read: | 235 | err_read: |
| 232 | iio_trigger_notify_done(indio_dev->trig); | 236 | iio_trigger_notify_done(indio_dev->trig); |
| @@ -404,7 +408,8 @@ static int as3935_probe(struct spi_device *spi) · 171 unmodified lines | |||
| 404 | indio_dev->info = &as3935_info; | 408 | indio_dev->info = &as3935_info; |
| 405 | 409 | ||
| 406 | trig = devm_iio_trigger_alloc(dev, "%s-dev%d", | 410 | trig = devm_iio_trigger_alloc(dev, "%s-dev%d", |
| 407 | indio_dev->name, indio_dev->id); | 411 | indio_dev->name, |
| 412 | iio_device_id(indio_dev)); | ||
| 408 | 413 | ||
| 409 | if (!trig) | 414 | if (!trig) |
| 410 | return -ENOMEM; | 415 | return -ENOMEM; |
| @@ -938,7 +938,7 @@ static irqreturn_t isl29501_trigger_handler(int irq, void *p) · 937 unmodified lines | |||
| 938 | struct iio_dev *indio_dev = pf->indio_dev; | 938 | struct iio_dev *indio_dev = pf->indio_dev; |
| 939 | struct isl29501_private *isl29501 = iio_priv(indio_dev); | 939 | struct isl29501_private *isl29501 = iio_priv(indio_dev); |
| 940 | const unsigned long *active_mask = indio_dev->active_scan_mask; | 940 | const unsigned long *active_mask = indio_dev->active_scan_mask; |
| 941 | u32 buffer[4] = {}; /* 1x16-bit + ts */ | 941 | u32 buffer[4] __aligned(8) = {}; /* 1x16-bit + naturally aligned ts */ |
| 942 | 942 | ||
| 943 | if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask)) | 943 | if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask)) |
| 944 | isl29501_register_read(isl29501, REG_DISTANCE, buffer); | 944 | isl29501_register_read(isl29501, REG_DISTANCE, buffer); |
| @@ -44,7 +44,11 @@ struct lidar_data { · 43 unmodified lines | |||
| 44 | int (*xfer)(struct lidar_data *data, u8 reg, u8 *val, int len); | 44 | int (*xfer)(struct lidar_data *data, u8 reg, u8 *val, int len); |
| 45 | int i2c_enabled; | 45 | int i2c_enabled; |
| 46 | 46 | ||
| 47 | u16 buffer[8]; /* 2 byte distance + 8 byte timestamp */ | 47 | /* Ensure timestamp is naturally aligned */ |
| 48 | struct { | ||
| 49 | u16 chan; | ||
| 50 | s64 timestamp __aligned(8); | ||
| 51 | } scan; | ||
| 48 | }; | 52 | }; |
| 49 | 53 | ||
| 50 | static const struct iio_chan_spec lidar_channels[] = { | 54 | static const struct iio_chan_spec lidar_channels[] = { |
| @@ -154,7 +158,9 @@ static int lidar_get_measurement(struct lidar_data *data, u16 *reg) · 103 unmodified lines | |||
| 154 | int tries = 10; | 158 | int tries = 10; |
| 155 | int ret; | 159 | int ret; |
| 156 | 160 | ||
| 157 | pm_runtime_get_sync(&client->dev); | 161 | ret = pm_runtime_resume_and_get(&client->dev); |
| 162 | if (ret < 0) | ||
| 163 | return ret; | ||
| 158 | 164 | ||
| 159 | /* start sample */ | 165 | /* start sample */ |
| 160 | ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE); | 166 | ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE); |
| @@ -230,9 +236,9 @@ static irqreturn_t lidar_trigger_handler(int irq, void *private) · 69 unmodified lines | |||
| 230 | struct lidar_data *data = iio_priv(indio_dev); | 236 | struct lidar_data *data = iio_priv(indio_dev); |
| 231 | int ret; | 237 | int ret; |
| 232 | 238 | ||
| 233 | ret = lidar_get_measurement(data, data->buffer); | 239 | ret = lidar_get_measurement(data, &data->scan.chan); |
| 234 | if (!ret) { | 240 | if (!ret) { |
| 235 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 241 | iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, |
| 236 | iio_get_time_ns(indio_dev)); | 242 | iio_get_time_ns(indio_dev)); |
| 237 | } else if (ret != -EINVAL) { | 243 | } else if (ret != -EINVAL) { |
| 238 | dev_err(&data->client->dev, "cannot read LIDAR measurement"); | 244 | dev_err(&data->client->dev, "cannot read LIDAR measurement"); |
| @@ -100,9 +100,11 @@ static int srf04_read(struct srf04_data *data) · 99 unmodified lines | |||
| 100 | u64 dt_ns; | 100 | u64 dt_ns; |
| 101 | u32 time_ns, distance_mm; | 101 | u32 time_ns, distance_mm; |
| 102 | 102 | ||
| 103 | if (data->gpiod_power) | 103 | if (data->gpiod_power) { |
| 104 | pm_runtime_get_sync(data->dev); | 104 | ret = pm_runtime_resume_and_get(data->dev); |
| 105 | 105 | if (ret < 0) | |
| 106 | return ret; | ||
| 107 | } | ||
| 106 | /* | 108 | /* |
| 107 | * just one read-echo-cycle can take place at a time | 109 | * just one read-echo-cycle can take place at a time |
| 108 | * ==> lock against concurrent reading calls | 110 | * ==> lock against concurrent reading calls |
| @@ -63,11 +63,11 @@ struct srf08_data { · 62 unmodified lines | |||
| 63 | int range_mm; | 63 | int range_mm; |
| 64 | struct mutex lock; | 64 | struct mutex lock; |
| 65 | 65 | ||
| 66 | /* | 66 | /* Ensure timestamp is naturally aligned */ |
| 67 | * triggered buffer | 67 | struct { |
| 68 | * 1x16-bit channel + 3x16 padding + 4x16 timestamp | 68 | s16 chan; |
| 69 | */ | 69 | s64 timestamp __aligned(8); |
| 70 | s16 buffer[8]; | 70 | } scan; |
| 71 | 71 | ||
| 72 | /* Sensor-Type */ | 72 | /* Sensor-Type */ |
| 73 | enum srf08_sensor_type sensor_type; | 73 | enum srf08_sensor_type sensor_type; |
| @@ -190,9 +190,9 @@ static irqreturn_t srf08_trigger_handler(int irq, void *p) · 116 unmodified lines | |||
| 190 | 190 | ||
| 191 | mutex_lock(&data->lock); | 191 | mutex_lock(&data->lock); |
| 192 | 192 | ||
| 193 | data->buffer[0] = sensor_data; | 193 | data->scan.chan = sensor_data; |
| 194 | iio_push_to_buffers_with_timestamp(indio_dev, | 194 | iio_push_to_buffers_with_timestamp(indio_dev, |
| 195 | data->buffer, pf->timestamp); | 195 | &data->scan, pf->timestamp); |
| 196 | 196 | ||
| 197 | mutex_unlock(&data->lock); | 197 | mutex_unlock(&data->lock); |
| 198 | err: | 198 | err: |
| @@ -1473,7 +1473,7 @@ static int sx9310_probe(struct i2c_client *client) · 1472 unmodified lines | |||
| 1473 | 1473 | ||
| 1474 | data->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", | 1474 | data->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", |
| 1475 | indio_dev->name, | 1475 | indio_dev->name, |
| 1476 | indio_dev->id); | 1476 | iio_device_id(indio_dev)); |
| 1477 | if (!data->trig) | 1477 | if (!data->trig) |
| 1478 | return -ENOMEM; | 1478 | return -ENOMEM; |
| 1479 | 1479 | ||
| @@ -946,7 +946,7 @@ static int sx9500_probe(struct i2c_client *client, · 945 unmodified lines | |||
| 946 | return ret; | 946 | return ret; |
| 947 | 947 | ||
| 948 | data->trig = devm_iio_trigger_alloc(&client->dev, | 948 | data->trig = devm_iio_trigger_alloc(&client->dev, |
| 949 | "%s-dev%d", indio_dev->name, indio_dev->id); | 949 | "%s-dev%d", indio_dev->name, iio_device_id(indio_dev)); |
| 950 | if (!data->trig) | 950 | if (!data->trig) |
| 951 | return -ENOMEM; | 951 | return -ENOMEM; |
| 952 | 952 | ||
| @@ -96,6 +96,16 @@ config TMP007 · 95 unmodified lines | |||
| 96 | This driver can also be built as a module. If so, the module will | 96 | This driver can also be built as a module. If so, the module will |
| 97 | be called tmp007. | 97 | be called tmp007. |
| 98 | 98 | ||
| 99 | config TMP117 | ||
| 100 | tristate "TMP117 Digital temperature sensor with integrated NV memory" | ||
| 101 | depends on I2C | ||
| 102 | help | ||
| 103 | If you say yes here you get support for the Texas Instruments | ||
| 104 | TMP117 Digital temperature sensor with integrated NV memory. | ||
| 105 | |||
| 106 | This driver can also be built as a module. If so, the module will | ||
| 107 | be called tmp117. | ||
| 108 | |||
| 99 | config TSYS01 | 109 | config TSYS01 |
| 100 | tristate "Measurement Specialties TSYS01 temperature sensor using I2C bus connection" | 110 | tristate "Measurement Specialties TSYS01 temperature sensor using I2C bus connection" |
| 101 | depends on I2C | 111 | depends on I2C |
| @@ -12,5 +12,6 @@ obj-$(CONFIG_MLX90614) += mlx90614.o · 11 unmodified lines | |||
| 12 | obj-$(CONFIG_MLX90632) += mlx90632.o | 12 | obj-$(CONFIG_MLX90632) += mlx90632.o |
| 13 | obj-$(CONFIG_TMP006) += tmp006.o | 13 | obj-$(CONFIG_TMP006) += tmp006.o |
| 14 | obj-$(CONFIG_TMP007) += tmp007.o | 14 | obj-$(CONFIG_TMP007) += tmp007.o |
| 15 | obj-$(CONFIG_TMP117) += tmp117.o | ||
| 15 | obj-$(CONFIG_TSYS01) += tsys01.o | 16 | obj-$(CONFIG_TSYS01) += tsys01.o |
| 16 | obj-$(CONFIG_TSYS02D) += tsys02d.o | 17 | obj-$(CONFIG_TSYS02D) += tsys02d.o |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | #include <linux/iio/buffer.h> | 8 | #include <linux/iio/buffer.h> |
| 9 | #include <linux/iio/iio.h> | 9 | #include <linux/iio/iio.h> |
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/mod_devicetable.h> | ||
| 11 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
| 12 | 13 | ||
| 13 | #include "../common/hid-sensors/hid-sensor-trigger.h" | 14 | #include "../common/hid-sensors/hid-sensor-trigger.h" |
| @@ -291,3 +292,4 @@ module_platform_driver(hid_temperature_platform_driver); · 277 unmodified lines | |||
| 291 | MODULE_DESCRIPTION("HID Environmental temperature sensor"); | 292 | MODULE_DESCRIPTION("HID Environmental temperature sensor"); |
| 292 | MODULE_AUTHOR("Song Hongyan <hongyan.song@intel.com>"); | 293 | MODULE_AUTHOR("Song Hongyan <hongyan.song@intel.com>"); |
| 293 | MODULE_LICENSE("GPL v2"); | 294 | MODULE_LICENSE("GPL v2"); |
| 295 | MODULE_IMPORT_NS(IIO_HID); | ||
| @@ -176,11 +176,14 @@ static inline s32 mlx90614_iir_search(const struct i2c_client *client, · 175 unmodified lines | |||
| 176 | static int mlx90614_power_get(struct mlx90614_data *data, bool startup) | 176 | static int mlx90614_power_get(struct mlx90614_data *data, bool startup) |
| 177 | { | 177 | { |
| 178 | unsigned long now; | 178 | unsigned long now; |
| 179 | int ret; | ||
| 179 | 180 | ||
| 180 | if (!data->wakeup_gpio) | 181 | if (!data->wakeup_gpio) |
| 181 | return 0; | 182 | return 0; |
| 182 | 183 | ||
| 183 | pm_runtime_get_sync(&data->client->dev); | 184 | ret = pm_runtime_resume_and_get(&data->client->dev); |
| 185 | if (ret < 0) | ||
| 186 | return ret; | ||
| 184 | 187 | ||
| 185 | if (startup) { | 188 | if (startup) { |
| 186 | now = jiffies; | 189 | now = jiffies; |
| @@ -267,7 +270,10 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, · 80 unmodified lines | |||
| 267 | *val = MLX90614_CONST_SCALE; | 270 | *val = MLX90614_CONST_SCALE; |
| 268 | return IIO_VAL_INT; | 271 | return IIO_VAL_INT; |
| 269 | case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */ | 272 | case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */ |
| 270 | mlx90614_power_get(data, false); | 273 | ret = mlx90614_power_get(data, false); |
| 274 | if (ret < 0) | ||
| 275 | return ret; | ||
| 276 | |||
| 271 | mutex_lock(&data->lock); | 277 | mutex_lock(&data->lock); |
| 272 | ret = i2c_smbus_read_word_data(data->client, | 278 | ret = i2c_smbus_read_word_data(data->client, |
| 273 | MLX90614_EMISSIVITY); | 279 | MLX90614_EMISSIVITY); |
| @@ -287,7 +293,10 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, · 13 unmodified lines | |||
| 287 | return IIO_VAL_INT_PLUS_NANO; | 293 | return IIO_VAL_INT_PLUS_NANO; |
| 288 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* IIR setting with | 294 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* IIR setting with |
| 289 | FIR = 1024 */ | 295 | FIR = 1024 */ |
| 290 | mlx90614_power_get(data, false); | 296 | ret = mlx90614_power_get(data, false); |
| 297 | if (ret < 0) | ||
| 298 | return ret; | ||
| 299 | |||
| 291 | mutex_lock(&data->lock); | 300 | mutex_lock(&data->lock); |
| 292 | ret = i2c_smbus_read_word_data(data->client, MLX90614_CONFIG); | 301 | ret = i2c_smbus_read_word_data(data->client, MLX90614_CONFIG); |
| 293 | mutex_unlock(&data->lock); | 302 | mutex_unlock(&data->lock); |
| @@ -319,7 +328,10 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev, · 25 unmodified lines | |||
| 319 | val = val * MLX90614_CONST_RAW_EMISSIVITY_MAX + | 328 | val = val * MLX90614_CONST_RAW_EMISSIVITY_MAX + |
| 320 | val2 / MLX90614_CONST_EMISSIVITY_RESOLUTION; | 329 | val2 / MLX90614_CONST_EMISSIVITY_RESOLUTION; |
| 321 | 330 | ||
| 322 | mlx90614_power_get(data, false); | 331 | ret = mlx90614_power_get(data, false); |
| 332 | if (ret < 0) | ||
| 333 | return ret; | ||
| 334 | |||
| 323 | mutex_lock(&data->lock); | 335 | mutex_lock(&data->lock); |
| 324 | ret = mlx90614_write_word(data->client, MLX90614_EMISSIVITY, | 336 | ret = mlx90614_write_word(data->client, MLX90614_EMISSIVITY, |
| 325 | val); | 337 | val); |
| @@ -331,7 +343,10 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev, · 5 unmodified lines | |||
| 331 | if (val < 0 || val2 < 0) | 343 | if (val < 0 || val2 < 0) |
| 332 | return -EINVAL; | 344 | return -EINVAL; |
| 333 | 345 | ||
| 334 | mlx90614_power_get(data, false); | 346 | ret = mlx90614_power_get(data, false); |
| 347 | if (ret < 0) | ||
| 348 | return ret; | ||
| 349 | |||
| 335 | mutex_lock(&data->lock); | 350 | mutex_lock(&data->lock); |
| 336 | ret = mlx90614_iir_search(data->client, | 351 | ret = mlx90614_iir_search(data->client, |
| 337 | val * 100 + val2 / 10000); | 352 | val * 100 + val2 / 10000); |
| @@ -0,0 +1,185 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Digital temperature sensor with integrated Non-volatile memory | ||
| 4 | * Copyright (c) 2021 Puranjay Mohan <puranjay12@gmail.com> | ||
| 5 | * | ||
| 6 | * Driver for the Texas Instruments TMP117 Temperature Sensor | ||
| 7 | * (7-bit I2C slave address (0x48 - 0x4B), changeable via ADD pins) | ||
| 8 | * | ||
| 9 | * Note: This driver assumes that the sensor has been calibrated beforehand. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/err.h> | ||
| 13 | #include <linux/i2c.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/bitops.h> | ||
| 16 | #include <linux/types.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/limits.h> | ||
| 19 | |||
| 20 | #include <linux/iio/iio.h> | ||
| 21 | |||
| 22 | #define TMP117_REG_TEMP 0x0 | ||
| 23 | #define TMP117_REG_CFGR 0x1 | ||
| 24 | #define TMP117_REG_HIGH_LIM 0x2 | ||
| 25 | #define TMP117_REG_LOW_LIM 0x3 | ||
| 26 | #define TMP117_REG_EEPROM_UL 0x4 | ||
| 27 | #define TMP117_REG_EEPROM1 0x5 | ||
| 28 | #define TMP117_REG_EEPROM2 0x6 | ||
| 29 | #define TMP117_REG_TEMP_OFFSET 0x7 | ||
| 30 | #define TMP117_REG_EEPROM3 0x8 | ||
| 31 | #define TMP117_REG_DEVICE_ID 0xF | ||
| 32 | |||
| 33 | #define TMP117_RESOLUTION_10UC 78125 | ||
| 34 | #define TMP117_DEVICE_ID 0x0117 | ||
| 35 | #define MICRODEGREE_PER_10MILLIDEGREE 10000 | ||
| 36 | |||
| 37 | struct tmp117_data { | ||
| 38 | struct i2c_client *client; | ||
| 39 | s16 calibbias; | ||
| 40 | }; | ||
| 41 | |||
| 42 | static int tmp117_read_raw(struct iio_dev *indio_dev, | ||
| 43 | struct iio_chan_spec const *channel, int *val, | ||
| 44 | int *val2, long mask) | ||
| 45 | { | ||
| 46 | struct tmp117_data *data = iio_priv(indio_dev); | ||
| 47 | s32 ret; | ||
| 48 | |||
| 49 | switch (mask) { | ||
| 50 | case IIO_CHAN_INFO_RAW: | ||
| 51 | ret = i2c_smbus_read_word_swapped(data->client, | ||
| 52 | TMP117_REG_TEMP); | ||
| 53 | if (ret < 0) | ||
| 54 | return ret; | ||
| 55 | *val = sign_extend32(ret, 15); | ||
| 56 | return IIO_VAL_INT; | ||
| 57 | |||
| 58 | case IIO_CHAN_INFO_CALIBBIAS: | ||
| 59 | ret = i2c_smbus_read_word_swapped(data->client, | ||
| 60 | TMP117_REG_TEMP_OFFSET); | ||
| 61 | if (ret < 0) | ||
| 62 | return ret; | ||
| 63 | *val = sign_extend32(ret, 15); | ||
| 64 | return IIO_VAL_INT; | ||
| 65 | |||
| 66 | case IIO_CHAN_INFO_SCALE: | ||
| 67 | /* | ||
| 68 | * Conversion from 10s of uC to mC | ||
| 69 | * as IIO reports temperature in mC | ||
| 70 | */ | ||
| 71 | *val = TMP117_RESOLUTION_10UC / MICRODEGREE_PER_10MILLIDEGREE; | ||
| 72 | *val2 = (TMP117_RESOLUTION_10UC % | ||
| 73 | MICRODEGREE_PER_10MILLIDEGREE) * 100; | ||
| 74 | |||
| 75 | return IIO_VAL_INT_PLUS_MICRO; | ||
| 76 | |||
| 77 | default: | ||
| 78 | return -EINVAL; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | static int tmp117_write_raw(struct iio_dev *indio_dev, | ||
| 83 | struct iio_chan_spec const *channel, int val, | ||
| 84 | int val2, long mask) | ||
| 85 | { | ||
| 86 | struct tmp117_data *data = iio_priv(indio_dev); | ||
| 87 | s16 off; | ||
| 88 | |||
| 89 | switch (mask) { | ||
| 90 | case IIO_CHAN_INFO_CALIBBIAS: | ||
| 91 | off = clamp_t(int, val, S16_MIN, S16_MAX); | ||
| 92 | if (off == data->calibbias) | ||
| 93 | return 0; | ||
| 94 | data->calibbias = off; | ||
| 95 | return i2c_smbus_write_word_swapped(data->client, | ||
| 96 | TMP117_REG_TEMP_OFFSET, off); | ||
| 97 | |||
| 98 | default: | ||
| 99 | return -EINVAL; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | static const struct iio_chan_spec tmp117_channels[] = { | ||
| 104 | { | ||
| 105 | .type = IIO_TEMP, | ||
| 106 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | ||
| 107 | BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE), | ||
| 108 | }, | ||
| 109 | }; | ||
| 110 | |||
| 111 | static const struct iio_info tmp117_info = { | ||
| 112 | .read_raw = tmp117_read_raw, | ||
| 113 | .write_raw = tmp117_write_raw, | ||
| 114 | }; | ||
| 115 | |||
| 116 | static int tmp117_identify(struct i2c_client *client) | ||
| 117 | { | ||
| 118 | int dev_id; | ||
| 119 | |||
| 120 | dev_id = i2c_smbus_read_word_swapped(client, TMP117_REG_DEVICE_ID); | ||
| 121 | if (dev_id < 0) | ||
| 122 | return dev_id; | ||
| 123 | if (dev_id != TMP117_DEVICE_ID) { | ||
| 124 | dev_err(&client->dev, "TMP117 not found\n"); | ||
| 125 | return -ENODEV; | ||
| 126 | } | ||
| 127 | return 0; | ||
| 128 | } | ||
| 129 | |||
| 130 | static int tmp117_probe(struct i2c_client *client) | ||
| 131 | { | ||
| 132 | struct tmp117_data *data; | ||
| 133 | struct iio_dev *indio_dev; | ||
| 134 | int ret; | ||
| 135 | |||
| 136 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) | ||
| 137 | return -EOPNOTSUPP; | ||
| 138 | |||
| 139 | ret = tmp117_identify(client); | ||
| 140 | if (ret < 0) | ||
| 141 | return ret; | ||
| 142 | |||
| 143 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
| 144 | if (!indio_dev) | ||
| 145 | return -ENOMEM; | ||
| 146 | |||
| 147 | data = iio_priv(indio_dev); | ||
| 148 | data->client = client; | ||
| 149 | data->calibbias = 0; | ||
| 150 | |||
| 151 | indio_dev->name = "tmp117"; | ||
| 152 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
| 153 | indio_dev->info = &tmp117_info; | ||
| 154 | |||
| 155 | indio_dev->channels = tmp117_channels; | ||
| 156 | indio_dev->num_channels = ARRAY_SIZE(tmp117_channels); | ||
| 157 | |||
| 158 | return devm_iio_device_register(&client->dev, indio_dev); | ||
| 159 | } | ||
| 160 | |||
| 161 | static const struct of_device_id tmp117_of_match[] = { | ||
| 162 | { .compatible = "ti,tmp117", }, | ||
| 163 | { } | ||
| 164 | }; | ||
| 165 | MODULE_DEVICE_TABLE(of, tmp117_of_match); | ||
| 166 | |||
| 167 | static const struct i2c_device_id tmp117_id[] = { | ||
| 168 | { "tmp117", 0 }, | ||
| 169 | { } | ||
| 170 | }; | ||
| 171 | MODULE_DEVICE_TABLE(i2c, tmp117_id); | ||
| 172 | |||
| 173 | static struct i2c_driver tmp117_driver = { | ||
| 174 | .driver = { | ||
| 175 | .name = "tmp117", | ||
| 176 | .of_match_table = tmp117_of_match, | ||
| 177 | }, | ||
| 178 | .probe_new = tmp117_probe, | ||
| 179 | .id_table = tmp117_id, | ||
| 180 | }; | ||
| 181 | module_i2c_driver(tmp117_driver); | ||
| 182 | |||
| 183 | MODULE_AUTHOR("Puranjay Mohan <puranjay12@gmail.com>"); | ||
| 184 | MODULE_DESCRIPTION("TI TMP117 Temperature sensor driver"); | ||
| 185 | MODULE_LICENSE("GPL"); | ||
| @@ -296,7 +296,7 @@ static ssize_t stm32_tt_show_master_mode(struct device *dev, · 295 unmodified lines | |||
| 296 | else | 296 | else |
| 297 | cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT; | 297 | cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT; |
| 298 | 298 | ||
| 299 | return snprintf(buf, PAGE_SIZE, "%s\n", master_mode_table[cr2]); | 299 | return sysfs_emit(buf, "%s\n", master_mode_table[cr2]); |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | static ssize_t stm32_tt_store_master_mode(struct device *dev, | 302 | static ssize_t stm32_tt_store_master_mode(struct device *dev, |
| @@ -23,6 +23,16 @@ config PHY_HI3660_USB · 22 unmodified lines | |||
| 23 | 23 | ||
| 24 | To compile this driver as a module, choose M here. | 24 | To compile this driver as a module, choose M here. |
| 25 | 25 | ||
| 26 | config PHY_HI3670_USB | ||
| 27 | tristate "hi3670 USB PHY support" | ||
| 28 | depends on (ARCH_HISI && ARM64) || COMPILE_TEST | ||
| 29 | select GENERIC_PHY | ||
| 30 | select MFD_SYSCON | ||
| 31 | help | ||
| 32 | Enable this to support the HISILICON HI3670 USB PHY. | ||
| 33 | |||
| 34 | To compile this driver as a module, choose M here. | ||
| 35 | |||
| 26 | config PHY_HISTB_COMBPHY | 36 | config PHY_HISTB_COMBPHY |
| 27 | tristate "HiSilicon STB SoCs COMBPHY support" | 37 | tristate "HiSilicon STB SoCs COMBPHY support" |
| 28 | depends on (ARCH_HISI && ARM64) || COMPILE_TEST | 38 | depends on (ARCH_HISI && ARM64) || COMPILE_TEST |
| @@ -1,6 +1,7 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | 1 | # SPDX-License-Identifier: GPL-2.0-only |
| 2 | obj-$(CONFIG_PHY_HI6220_USB) += phy-hi6220-usb.o | 2 | obj-$(CONFIG_PHY_HI6220_USB) += phy-hi6220-usb.o |
| 3 | obj-$(CONFIG_PHY_HI3660_USB) += phy-hi3660-usb3.o | 3 | obj-$(CONFIG_PHY_HI3660_USB) += phy-hi3660-usb3.o |
| 4 | obj-$(CONFIG_PHY_HI3670_USB) += phy-hi3670-usb3.o | ||
| 4 | obj-$(CONFIG_PHY_HISTB_COMBPHY) += phy-histb-combphy.o | 5 | obj-$(CONFIG_PHY_HISTB_COMBPHY) += phy-histb-combphy.o |
| 5 | obj-$(CONFIG_PHY_HISI_INNO_USB2) += phy-hisi-inno-usb2.o | 6 | obj-$(CONFIG_PHY_HISI_INNO_USB2) += phy-hisi-inno-usb2.o |
| 6 | obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o | 7 | obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o |
| @@ -148,10 +148,8 @@ static int hi3670_phy_cr_clk(struct regmap *usb31misc) · 147 unmodified lines | |||
| 148 | return ret; | 148 | return ret; |
| 149 | 149 | ||
| 150 | /* Clock down */ | 150 | /* Clock down */ |
| 151 | ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, | 151 | return regmap_update_bits(usb31misc, USB_MISC_CFG54, |
| 152 | CFG54_USB31PHY_CR_CLK, 0); | 152 | CFG54_USB31PHY_CR_CLK, 0); |
| 153 | |||
| 154 | return ret; | ||
| 155 | } | 153 | } |
| 156 | 154 | ||
| 157 | static int hi3670_phy_cr_set_sel(struct regmap *usb31misc) | 155 | static int hi3670_phy_cr_set_sel(struct regmap *usb31misc) |
| @@ -215,17 +213,14 @@ static int hi3670_phy_cr_set_addr(struct regmap *usb31misc, u32 addr) · 57 unmodified lines | |||
| 215 | return ret; | 213 | return ret; |
| 216 | 214 | ||
| 217 | reg = FIELD_PREP(CFG54_USB31PHY_CR_ADDR_MASK, addr); | 215 | reg = FIELD_PREP(CFG54_USB31PHY_CR_ADDR_MASK, addr); |
| 218 | ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, | ||
| 219 | CFG54_USB31PHY_CR_ADDR_MASK, reg); | ||
| 220 | 216 | ||
| 221 | return ret; | 217 | return regmap_update_bits(usb31misc, USB_MISC_CFG54, |
| 218 | CFG54_USB31PHY_CR_ADDR_MASK, reg); | ||
| 222 | } | 219 | } |
| 223 | 220 | ||
| 224 | static int hi3670_phy_cr_read(struct regmap *usb31misc, u32 addr, u32 *val) | 221 | static int hi3670_phy_cr_read(struct regmap *usb31misc, u32 addr, u32 *val) |
| 225 | { | 222 | { |
| 226 | int reg; | 223 | int reg, i, ret; |
| 227 | int i; | ||
| 228 | int ret; | ||
| 229 | 224 | ||
| 230 | for (i = 0; i < 100; i++) { | 225 | for (i = 0; i < 100; i++) { |
| 231 | ret = hi3670_phy_cr_clk(usb31misc); | 226 | ret = hi3670_phy_cr_clk(usb31misc); |
| @@ -286,9 +281,7 @@ static int hi3670_phy_cr_write(struct regmap *usb31misc, u32 addr, u32 val) · 54 unmodified lines | |||
| 286 | if (ret) | 281 | if (ret) |
| 287 | return ret; | 282 | return ret; |
| 288 | 283 | ||
| 289 | ret = hi3670_phy_cr_wait_ack(usb31misc); | 284 | return hi3670_phy_cr_wait_ack(usb31misc); |
| 290 | |||
| 291 | return ret; | ||
| 292 | } | 285 | } |
| 293 | 286 | ||
| 294 | static int hi3670_phy_set_params(struct hi3670_priv *priv) | 287 | static int hi3670_phy_set_params(struct hi3670_priv *priv) |
| @@ -328,3 +328,4 @@ module_platform_driver(hid_time_platform_driver); · 327 unmodified lines | |||
| 328 | MODULE_DESCRIPTION("HID Sensor Time"); | 328 | MODULE_DESCRIPTION("HID Sensor Time"); |
| 329 | MODULE_AUTHOR("Alexander Holler <holler@ahsoftware.de>"); | 329 | MODULE_AUTHOR("Alexander Holler <holler@ahsoftware.de>"); |
| 330 | MODULE_LICENSE("GPL"); | 330 | MODULE_LICENSE("GPL"); |
| 331 | MODULE_IMPORT_NS(IIO_HID); | ||
| @@ -11,6 +11,15 @@ menuconfig SPMI · 10 unmodified lines | |||
| 11 | 11 | ||
| 12 | if SPMI | 12 | if SPMI |
| 13 | 13 | ||
| 14 | config SPMI_HISI3670 | ||
| 15 | tristate "Hisilicon 3670 SPMI Controller" | ||
| 16 | select IRQ_DOMAIN_HIERARCHY | ||
| 17 | depends on HAS_IOMEM | ||
| 18 | help | ||
| 19 | If you say yes to this option, support will be included for the | ||
| 20 | built-in SPMI PMIC Arbiter interface on Hisilicon 3670 | ||
| 21 | processors. | ||
| 22 | |||
| 14 | config SPMI_MSM_PMIC_ARB | 23 | config SPMI_MSM_PMIC_ARB |
| 15 | tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)" | 24 | tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)" |
| 16 | select IRQ_DOMAIN_HIERARCHY | 25 | select IRQ_DOMAIN_HIERARCHY |
| @@ -4,4 +4,5 @@ · 3 unmodified lines | |||
| 4 | # | 4 | # |
| 5 | obj-$(CONFIG_SPMI) += spmi.o | 5 | obj-$(CONFIG_SPMI) += spmi.o |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_SPMI_HISI3670) += hisi-spmi-controller.o | ||
| 7 | obj-$(CONFIG_SPMI_MSM_PMIC_ARB) += spmi-pmic-arb.o | 8 | obj-$(CONFIG_SPMI_MSM_PMIC_ARB) += spmi-pmic-arb.o |
| @@ -290,7 +290,7 @@ static int spmi_controller_probe(struct platform_device *pdev) · 289 unmodified lines | |||
| 290 | goto err_put_controller; | 290 | goto err_put_controller; |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | ret = of_property_read_u32(pdev->dev.of_node, "spmi-channel", | 293 | ret = of_property_read_u32(pdev->dev.of_node, "hisilicon,spmi-channel", |
| 294 | &spmi_controller->channel); | 294 | &spmi_controller->channel); |
| 295 | if (ret) { | 295 | if (ret) { |
| 296 | dev_err(&pdev->dev, "can not get channel\n"); | 296 | dev_err(&pdev->dev, "can not get channel\n"); |
| @@ -98,8 +98,6 @@ source "drivers/staging/axis-fifo/Kconfig" · 97 unmodified lines | |||
| 98 | 98 | ||
| 99 | source "drivers/staging/fieldbus/Kconfig" | 99 | source "drivers/staging/fieldbus/Kconfig" |
| 100 | 100 | ||
| 101 | source "drivers/staging/kpc2000/Kconfig" | ||
| 102 | |||
| 103 | source "drivers/staging/qlge/Kconfig" | 101 | source "drivers/staging/qlge/Kconfig" |
| 104 | 102 | ||
| 105 | source "drivers/staging/wfx/Kconfig" | 103 | source "drivers/staging/wfx/Kconfig" |
| @@ -39,7 +39,6 @@ obj-$(CONFIG_DMA_RALINK) += ralink-gdma/ · 38 unmodified lines | |||
| 39 | obj-$(CONFIG_SOC_MT7621) += mt7621-dts/ | 39 | obj-$(CONFIG_SOC_MT7621) += mt7621-dts/ |
| 40 | obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ | 40 | obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ |
| 41 | obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ | 41 | obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ |
| 42 | obj-$(CONFIG_KPC2000) += kpc2000/ | ||
| 43 | obj-$(CONFIG_QLGE) += qlge/ | 42 | obj-$(CONFIG_QLGE) += qlge/ |
| 44 | obj-$(CONFIG_WFX) += wfx/ | 43 | obj-$(CONFIG_WFX) += wfx/ |
| 45 | obj-y += hikey9xx/ | 44 | obj-y += hikey9xx/ |
| @@ -179,6 +179,7 @@ static inline void lru_del(struct ashmem_range *range) · 178 unmodified lines | |||
| 179 | * @purged: Initial purge status (ASMEM_NOT_PURGED or ASHMEM_WAS_PURGED) | 179 | * @purged: Initial purge status (ASMEM_NOT_PURGED or ASHMEM_WAS_PURGED) |
| 180 | * @start: The starting page (inclusive) | 180 | * @start: The starting page (inclusive) |
| 181 | * @end: The ending page (inclusive) | 181 | * @end: The ending page (inclusive) |
| 182 | * @new_range: The placeholder for the new range | ||
| 182 | * | 183 | * |
| 183 | * This function is protected by ashmem_mutex. | 184 | * This function is protected by ashmem_mutex. |
| 184 | */ | 185 | */ |
| @@ -894,6 +895,8 @@ static void ashmem_show_fdinfo(struct seq_file *m, struct file *file) · 709 unmodified lines | |||
| 894 | seq_printf(m, "name:\t%s\n", | 895 | seq_printf(m, "name:\t%s\n", |
| 895 | asma->name + ASHMEM_NAME_PREFIX_LEN); | 896 | asma->name + ASHMEM_NAME_PREFIX_LEN); |
| 896 | 897 | ||
| 898 | seq_printf(m, "size:\t%zu\n", asma->size); | ||
| 899 | |||
| 897 | mutex_unlock(&ashmem_mutex); | 900 | mutex_unlock(&ashmem_mutex); |
| 898 | } | 901 | } |
| 899 | #endif | 902 | #endif |
| @@ -337,11 +337,11 @@ static void reset_ip_core(struct axis_fifo *fifo) · 336 unmodified lines | |||
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | /** | 339 | /** |
| 340 | * axis_fifo_write() - Read a packet from AXIS-FIFO character device. | 340 | * axis_fifo_read() - Read a packet from AXIS-FIFO character device. |
| 341 | * @f Open file. | 341 | * @f: Open file. |
| 342 | * @buf User space buffer to read to. | 342 | * @buf: User space buffer to read to. |
| 343 | * @len User space buffer length. | 343 | * @len: User space buffer length. |
| 344 | * @off Buffer offset. | 344 | * @off: Buffer offset. |
| 345 | * | 345 | * |
| 346 | * As defined by the device's documentation, we need to check the device's | 346 | * As defined by the device's documentation, we need to check the device's |
| 347 | * occupancy before reading the length register and then the data. All these | 347 | * occupancy before reading the length register and then the data. All these |
| @@ -460,10 +460,10 @@ end_unlock: · 112 unmodified lines | |||
| 460 | 460 | ||
| 461 | /** | 461 | /** |
| 462 | * axis_fifo_write() - Write buffer to AXIS-FIFO character device. | 462 | * axis_fifo_write() - Write buffer to AXIS-FIFO character device. |
| 463 | * @f Open file. | 463 | * @f: Open file. |
| 464 | * @buf User space buffer to write to the device. | 464 | * @buf: User space buffer to write to the device. |
| 465 | * @len User space buffer length. | 465 | * @len: User space buffer length. |
| 466 | * @off Buffer offset. | 466 | * @off: Buffer offset. |
| 467 | * | 467 | * |
| 468 | * As defined by the device's documentation, we need to write to the device's | 468 | * As defined by the device's documentation, we need to write to the device's |
| 469 | * data buffer then to the device's packet length register atomically. Also, | 469 | * data buffer then to the device's packet length register atomically. Also, |
| @@ -1073,9 +1073,8 @@ static int _nbu2ss_epn_in_pio(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep, · 1072 unmodified lines | |||
| 1073 | i_word_length = length / sizeof(u32); | 1073 | i_word_length = length / sizeof(u32); |
| 1074 | if (i_word_length > 0) { | 1074 | if (i_word_length > 0) { |
| 1075 | for (i = 0; i < i_word_length; i++) { | 1075 | for (i = 0; i < i_word_length; i++) { |
| 1076 | _nbu2ss_writel( | 1076 | _nbu2ss_writel(&preg->EP_REGS[ep->epnum - 1].EP_WRITE, |
| 1077 | &preg->EP_REGS[ep->epnum - 1].EP_WRITE, | 1077 | p_buf_32->dw); |
| 1078 | p_buf_32->dw); | ||
| 1079 | 1078 | ||
| 1080 | p_buf_32++; | 1079 | p_buf_32++; |
| 1081 | } | 1080 | } |
| @@ -1225,8 +1224,7 @@ static void _nbu2ss_restert_transfer(struct nbu2ss_ep *ep) · 143 unmodified lines | |||
| 1225 | return; | 1224 | return; |
| 1226 | 1225 | ||
| 1227 | if (ep->epnum > 0) { | 1226 | if (ep->epnum > 0) { |
| 1228 | length = _nbu2ss_readl( | 1227 | length = _nbu2ss_readl(&ep->udc->p_regs->EP_REGS[ep->epnum - 1].EP_LEN_DCNT); |
| 1229 | &ep->udc->p_regs->EP_REGS[ep->epnum - 1].EP_LEN_DCNT); | ||
| 1230 | 1228 | ||
| 1231 | length &= EPN_LDATA; | 1229 | length &= EPN_LDATA; |
| 1232 | if (length < ep->ep.maxpacket) | 1230 | if (length < ep->ep.maxpacket) |
| @@ -1462,8 +1460,7 @@ static void _nbu2ss_epn_set_stall(struct nbu2ss_udc *udc, · 229 unmodified lines | |||
| 1462 | for (limit_cnt = 0 | 1460 | for (limit_cnt = 0 |
| 1463 | ; limit_cnt < IN_DATA_EMPTY_COUNT | 1461 | ; limit_cnt < IN_DATA_EMPTY_COUNT |
| 1464 | ; limit_cnt++) { | 1462 | ; limit_cnt++) { |
| 1465 | regdata = _nbu2ss_readl( | 1463 | regdata = _nbu2ss_readl(&preg->EP_REGS[ep->epnum - 1].EP_STATUS); |
| 1466 | &preg->EP_REGS[ep->epnum - 1].EP_STATUS); | ||
| 1467 | 1464 | ||
| 1468 | if ((regdata & EPN_IN_DATA) == 0) | 1465 | if ((regdata & EPN_IN_DATA) == 0) |
| 1469 | break; | 1466 | break; |
| @@ -1,8 +1,3 @@ | |||
| 1 | * convert all uses of the old GPIO API from <linux/gpio.h> to the | ||
| 2 | GPIO descriptor API in <linux/gpio/consumer.h> and look up GPIO | ||
| 3 | lines from device tree, ACPI or board files, board files should | ||
| 4 | use <linux/gpio/machine.h> | ||
| 5 | |||
| 6 | * convert all these over to drm_simple_display_pipe and submit for inclusion | 1 | * convert all these over to drm_simple_display_pipe and submit for inclusion |
| 7 | into the DRM subsystem under drivers/gpu/drm - fbdev doesn't take any new | 2 | into the DRM subsystem under drivers/gpu/drm - fbdev doesn't take any new |
| 8 | drivers anymore. | 3 | drivers anymore. |
| @@ -77,19 +77,6 @@ static int init_display(struct fbtft_par *par) · 76 unmodified lines | |||
| 77 | return 0; | 77 | return 0; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | static void reset(struct fbtft_par *par) | ||
| 81 | { | ||
| 82 | if (!par->gpio.reset) | ||
| 83 | return; | ||
| 84 | |||
| 85 | dev_dbg(par->info->device, "%s()\n", __func__); | ||
| 86 | |||
| 87 | gpiod_set_value(par->gpio.reset, 0); | ||
| 88 | udelay(20); | ||
| 89 | gpiod_set_value(par->gpio.reset, 1); | ||
| 90 | mdelay(120); | ||
| 91 | } | ||
| 92 | |||
| 93 | /* Check if all necessary GPIOS defined */ | 80 | /* Check if all necessary GPIOS defined */ |
| 94 | static int verify_gpios(struct fbtft_par *par) | 81 | static int verify_gpios(struct fbtft_par *par) |
| 95 | { | 82 | { |
| @@ -194,12 +181,12 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) · 98 unmodified lines | |||
| 194 | /* select chip */ | 181 | /* select chip */ |
| 195 | if (*buf) { | 182 | if (*buf) { |
| 196 | /* cs1 */ | 183 | /* cs1 */ |
| 197 | gpiod_set_value(par->CS0, 1); | ||
| 198 | gpiod_set_value(par->CS1, 0); | ||
| 199 | } else { | ||
| 200 | /* cs0 */ | ||
| 201 | gpiod_set_value(par->CS0, 0); | 184 | gpiod_set_value(par->CS0, 0); |
| 202 | gpiod_set_value(par->CS1, 1); | 185 | gpiod_set_value(par->CS1, 1); |
| 186 | } else { | ||
| 187 | /* cs0 */ | ||
| 188 | gpiod_set_value(par->CS0, 1); | ||
| 189 | gpiod_set_value(par->CS1, 0); | ||
| 203 | } | 190 | } |
| 204 | 191 | ||
| 205 | gpiod_set_value(par->RS, 0); /* RS->0 (command mode) */ | 192 | gpiod_set_value(par->RS, 0); /* RS->0 (command mode) */ |
| @@ -397,8 +384,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) · 191 unmodified lines | |||
| 397 | } | 384 | } |
| 398 | kfree(convert_buf); | 385 | kfree(convert_buf); |
| 399 | 386 | ||
| 400 | gpiod_set_value(par->CS0, 1); | 387 | gpiod_set_value(par->CS0, 0); |
| 401 | gpiod_set_value(par->CS1, 1); | 388 | gpiod_set_value(par->CS1, 0); |
| 402 | 389 | ||
| 403 | return ret; | 390 | return ret; |
| 404 | } | 391 | } |
| @@ -419,10 +406,10 @@ static int write(struct fbtft_par *par, void *buf, size_t len) · 14 unmodified lines | |||
| 419 | for (i = 0; i < 8; ++i) | 406 | for (i = 0; i < 8; ++i) |
| 420 | gpiod_set_value(par->gpio.db[i], data & (1 << i)); | 407 | gpiod_set_value(par->gpio.db[i], data & (1 << i)); |
| 421 | /* set E */ | 408 | /* set E */ |
| 422 | gpiod_set_value(par->EPIN, 1); | 409 | gpiod_set_value(par->EPIN, 0); |
| 423 | udelay(5); | 410 | udelay(5); |
| 424 | /* unset E - write */ | 411 | /* unset E - write */ |
| 425 | gpiod_set_value(par->EPIN, 0); | 412 | gpiod_set_value(par->EPIN, 1); |
| 426 | udelay(1); | 413 | udelay(1); |
| 427 | } | 414 | } |
| 428 | 415 | ||
| @@ -439,7 +426,6 @@ static struct fbtft_display display = { · 10 unmodified lines | |||
| 439 | .set_addr_win = set_addr_win, | 426 | .set_addr_win = set_addr_win, |
| 440 | .verify_gpios = verify_gpios, | 427 | .verify_gpios = verify_gpios, |
| 441 | .request_gpios_match = request_gpios_match, | 428 | .request_gpios_match = request_gpios_match, |
| 442 | .reset = reset, | ||
| 443 | .write = write, | 429 | .write = write, |
| 444 | .write_register = write_reg8_bus8, | 430 | .write_register = write_reg8_bus8, |
| 445 | .write_vmem = write_vmem, | 431 | .write_vmem = write_vmem, |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | |||
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/gpio/consumer.h> | ||
| 16 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
| 17 | 16 | ||
| 18 | #include "fbtft.h" | 17 | #include "fbtft.h" |
| @@ -24,9 +23,6 @@ · 5 unmodified lines | |||
| 24 | 23 | ||
| 25 | static int init_display(struct fbtft_par *par) | 24 | static int init_display(struct fbtft_par *par) |
| 26 | { | 25 | { |
| 27 | if (par->gpio.cs) | ||
| 28 | gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ | ||
| 29 | |||
| 30 | par->fbtftops.reset(par); | 26 | par->fbtftops.reset(par); |
| 31 | 27 | ||
| 32 | /* Initialization sequence from Lib_UTFT */ | 28 | /* Initialization sequence from Lib_UTFT */ |
| @@ -68,9 +68,6 @@ static int init_display(struct fbtft_par *par) · 67 unmodified lines | |||
| 68 | mdelay(40); | 68 | mdelay(40); |
| 69 | write_reg(par, 0x28, 0x3C); | 69 | write_reg(par, 0x28, 0x3C); |
| 70 | 70 | ||
| 71 | /* orientation */ | ||
| 72 | write_reg(par, 0x16, 0x60 | (par->bgr << 3)); | ||
| 73 | |||
| 74 | return 0; | 71 | return 0; |
| 75 | } | 72 | } |
| 76 | 73 | ||
| @@ -87,6 +84,31 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) · 10 unmodified lines | |||
| 87 | write_reg(par, 0x22); | 84 | write_reg(par, 0x22); |
| 88 | } | 85 | } |
| 89 | 86 | ||
| 87 | #define MEM_Y BIT(7) /* MY row address order */ | ||
| 88 | #define MEM_X BIT(6) /* MX column address order */ | ||
| 89 | #define MEM_V BIT(5) /* MV row / column exchange */ | ||
| 90 | #define MEM_L BIT(4) /* ML vertical refresh order */ | ||
| 91 | #define MEM_BGR (3) /* RGB-BGR Order */ | ||
| 92 | static int set_var(struct fbtft_par *par) | ||
| 93 | { | ||
| 94 | switch (par->info->var.rotate) { | ||
| 95 | case 0: | ||
| 96 | write_reg(par, 0x16, MEM_V | MEM_X | (par->bgr << MEM_BGR)); | ||
| 97 | break; | ||
| 98 | case 270: | ||
| 99 | write_reg(par, 0x16, par->bgr << MEM_BGR); | ||
| 100 | break; | ||
| 101 | case 180: | ||
| 102 | write_reg(par, 0x16, MEM_V | MEM_Y | (par->bgr << MEM_BGR)); | ||
| 103 | break; | ||
| 104 | case 90: | ||
| 105 | write_reg(par, 0x16, MEM_X | MEM_Y | (par->bgr << MEM_BGR)); | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | |||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 90 | /* | 112 | /* |
| 91 | * Gamma string format: | 113 | * Gamma string format: |
| 92 | * VRP0 VRP1 VRP2 VRP3 VRP4 VRP5 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 CGM | 114 | * VRP0 VRP1 VRP2 VRP3 VRP4 VRP5 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 CGM |
| @@ -144,6 +166,7 @@ static struct fbtft_display display = { · 51 unmodified lines | |||
| 144 | .fbtftops = { | 166 | .fbtftops = { |
| 145 | .init_display = init_display, | 167 | .init_display = init_display, |
| 146 | .set_addr_win = set_addr_win, | 168 | .set_addr_win = set_addr_win, |
| 169 | .set_var = set_var, | ||
| 147 | .set_gamma = set_gamma, | 170 | .set_gamma = set_gamma, |
| 148 | }, | 171 | }, |
| 149 | }; | 172 | }; |
| @@ -11,7 +11,6 @@ · 10 unmodified lines | |||
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/gpio/consumer.h> | ||
| 15 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
| 16 | #include <video/mipi_display.h> | 15 | #include <video/mipi_display.h> |
| 17 | 16 | ||
| @@ -77,9 +76,6 @@ static int init_display(struct fbtft_par *par) · 59 unmodified lines | |||
| 77 | { | 76 | { |
| 78 | par->fbtftops.reset(par); | 77 | par->fbtftops.reset(par); |
| 79 | 78 | ||
| 80 | if (par->gpio.cs) | ||
| 81 | gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ | ||
| 82 | |||
| 83 | write_reg(par, MIPI_DCS_SOFT_RESET); /* software reset */ | 79 | write_reg(par, MIPI_DCS_SOFT_RESET); /* software reset */ |
| 84 | mdelay(500); | 80 | mdelay(500); |
| 85 | write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE); /* exit sleep */ | 81 | write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE); /* exit sleep */ |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | |||
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
| 11 | #include <linux/gpio/consumer.h> | ||
| 12 | #include <linux/spi/spi.h> | 11 | #include <linux/spi/spi.h> |
| 13 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
| 14 | 13 | ||
| @@ -22,11 +21,10 @@ · 7 unmodified lines | |||
| 22 | 21 | ||
| 23 | static unsigned int read_devicecode(struct fbtft_par *par) | 22 | static unsigned int read_devicecode(struct fbtft_par *par) |
| 24 | { | 23 | { |
| 25 | int ret; | ||
| 26 | u8 rxbuf[8] = {0, }; | 24 | u8 rxbuf[8] = {0, }; |
| 27 | 25 | ||
| 28 | write_reg(par, 0x0000); | 26 | write_reg(par, 0x0000); |
| 29 | ret = par->fbtftops.read(par, rxbuf, 4); | 27 | par->fbtftops.read(par, rxbuf, 4); |
| 30 | return (rxbuf[2] << 8) | rxbuf[3]; | 28 | return (rxbuf[2] << 8) | rxbuf[3]; |
| 31 | } | 29 | } |
| 32 | 30 | ||
| @@ -10,7 +10,6 @@ · 9 unmodified lines | |||
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/gpio/consumer.h> | ||
| 14 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
| 15 | 14 | ||
| 16 | #include "fbtft.h" | 15 | #include "fbtft.h" |
| @@ -85,9 +84,6 @@ static int init_display(struct fbtft_par *par) · 68 unmodified lines | |||
| 85 | { | 84 | { |
| 86 | par->fbtftops.reset(par); | 85 | par->fbtftops.reset(par); |
| 87 | 86 | ||
| 88 | if (par->gpio.cs) | ||
| 89 | gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ | ||
| 90 | |||
| 91 | bt &= 0x07; | 87 | bt &= 0x07; |
| 92 | vc &= 0x07; | 88 | vc &= 0x07; |
| 93 | vrh &= 0x0f; | 89 | vrh &= 0x0f; |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | |||
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
| 11 | #include <linux/gpio/consumer.h> | ||
| 12 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
| 13 | #include <video/mipi_display.h> | 12 | #include <video/mipi_display.h> |
| 14 | 13 | ||
| @@ -12,7 +12,6 @@ · 11 unmodified lines | |||
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/gpio/consumer.h> | ||
| 16 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
| 17 | 16 | ||
| 18 | #include "fbtft.h" | 17 | #include "fbtft.h" |
| @@ -29,9 +28,6 @@ static int init_display(struct fbtft_par *par) · 10 unmodified lines | |||
| 29 | { | 28 | { |
| 30 | par->fbtftops.reset(par); | 29 | par->fbtftops.reset(par); |
| 31 | 30 | ||
| 32 | if (par->gpio.cs) | ||
| 33 | gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ | ||
| 34 | |||
| 35 | /* Initialization sequence from Lib_UTFT */ | 31 | /* Initialization sequence from Lib_UTFT */ |
| 36 | 32 | ||
| 37 | write_reg(par, 0x0011, 0x2004); | 33 | write_reg(par, 0x0011, 0x2004); |
| @@ -9,7 +9,6 @@ · 8 unmodified lines | |||
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
| 11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
| 12 | #include <linux/gpio/consumer.h> | ||
| 13 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
| 14 | 13 | ||
| 15 | #include "fbtft.h" | 14 | #include "fbtft.h" |
| @@ -10,7 +10,6 @@ · 9 unmodified lines | |||
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/gpio/consumer.h> | ||
| 14 | 13 | ||
| 15 | #include "fbtft.h" | 14 | #include "fbtft.h" |
| 16 | 15 | ||
| @@ -28,9 +27,6 @@ static int init_display(struct fbtft_par *par) · 11 unmodified lines | |||
| 28 | { | 27 | { |
| 29 | par->fbtftops.reset(par); | 28 | par->fbtftops.reset(par); |
| 30 | 29 | ||
| 31 | if (par->gpio.cs) | ||
| 32 | gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ | ||
| 33 | |||
| 34 | write_reg(par, 0x00, 0x0001); | 30 | write_reg(par, 0x00, 0x0001); |
| 35 | write_reg(par, 0x03, 0xA8A4); | 31 | write_reg(par, 0x03, 0xA8A4); |
| 36 | write_reg(par, 0x0C, 0x0000); | 32 | write_reg(par, 0x0C, 0x0000); |
| @@ -35,8 +35,6 @@ static int init_display(struct fbtft_par *par) · 34 unmodified lines | |||
| 35 | { | 35 | { |
| 36 | par->fbtftops.reset(par); | 36 | par->fbtftops.reset(par); |
| 37 | 37 | ||
| 38 | gpiod_set_value(par->gpio.cs, 0); | ||
| 39 | |||
| 40 | write_reg(par, 0xb3); | 38 | write_reg(par, 0xb3); |
| 41 | write_reg(par, 0xf0); | 39 | write_reg(par, 0xf0); |
| 42 | write_reg(par, 0xae); | 40 | write_reg(par, 0xae); |
| @@ -81,8 +81,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) · 80 unmodified lines | |||
| 81 | va_start(args, len); | 81 | va_start(args, len); |
| 82 | 82 | ||
| 83 | *buf = (u8)va_arg(args, unsigned int); | 83 | *buf = (u8)va_arg(args, unsigned int); |
| 84 | if (par->gpio.dc) | 84 | gpiod_set_value(par->gpio.dc, 0); |
| 85 | gpiod_set_value(par->gpio.dc, 0); | ||
| 86 | ret = par->fbtftops.write(par, par->buf, sizeof(u8)); | 85 | ret = par->fbtftops.write(par, par->buf, sizeof(u8)); |
| 87 | if (ret < 0) { | 86 | if (ret < 0) { |
| 88 | va_end(args); | 87 | va_end(args); |
| @@ -104,8 +103,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) · 15 unmodified lines | |||
| 104 | return; | 103 | return; |
| 105 | } | 104 | } |
| 106 | } | 105 | } |
| 107 | if (par->gpio.dc) | 106 | gpiod_set_value(par->gpio.dc, 1); |
| 108 | gpiod_set_value(par->gpio.dc, 1); | ||
| 109 | va_end(args); | 107 | va_end(args); |
| 110 | } | 108 | } |
| 111 | 109 | ||
| @@ -2,7 +2,6 @@ · 1 unmodified line | |||
| 2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
| 3 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
| 4 | #include <linux/init.h> | 4 | #include <linux/init.h> |
| 5 | #include <linux/gpio/consumer.h> | ||
| 6 | #include <linux/spi/spi.h> | 5 | #include <linux/spi/spi.h> |
| 7 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
| 8 | 7 | ||
| @@ -12,7 +12,6 @@ · 11 unmodified lines | |||
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/gpio/consumer.h> | ||
| 16 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
| 17 | 16 | ||
| 18 | #include "fbtft.h" | 17 | #include "fbtft.h" |
| @@ -26,9 +25,6 @@ static int init_display(struct fbtft_par *par) · 7 unmodified lines | |||
| 26 | { | 25 | { |
| 27 | par->fbtftops.reset(par); | 26 | par->fbtftops.reset(par); |
| 28 | 27 | ||
| 29 | if (par->gpio.cs) | ||
| 30 | gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ | ||
| 31 | |||
| 32 | /* Initialization sequence from Lib_UTFT */ | 28 | /* Initialization sequence from Lib_UTFT */ |
| 33 | 29 | ||
| 34 | /* register reset */ | 30 | /* register reset */ |
| @@ -8,7 +8,6 @@ · 7 unmodified lines | |||
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
| 11 | #include <linux/gpio/consumer.h> | ||
| 12 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
| 13 | 12 | ||
| 14 | #include "fbtft.h" | 13 | #include "fbtft.h" |
| @@ -135,8 +135,7 @@ int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len) · 134 unmodified lines | |||
| 135 | remain = len / 2; | 135 | remain = len / 2; |
| 136 | vmem16 = (u16 *)(par->info->screen_buffer + offset); | 136 | vmem16 = (u16 *)(par->info->screen_buffer + offset); |
| 137 | 137 | ||
| 138 | if (par->gpio.dc) | 138 | gpiod_set_value(par->gpio.dc, 1); |
| 139 | gpiod_set_value(par->gpio.dc, 1); | ||
| 140 | 139 | ||
| 141 | /* non buffered write */ | 140 | /* non buffered write */ |
| 142 | if (!par->txbuf.buf) | 141 | if (!par->txbuf.buf) |
| @@ -38,8 +38,7 @@ int fbtft_write_buf_dc(struct fbtft_par *par, void *buf, size_t len, int dc) · 37 unmodified lines | |||
| 38 | { | 38 | { |
| 39 | int ret; | 39 | int ret; |
| 40 | 40 | ||
| 41 | if (par->gpio.dc) | 41 | gpiod_set_value(par->gpio.dc, dc); |
| 42 | gpiod_set_value(par->gpio.dc, dc); | ||
| 43 | 42 | ||
| 44 | ret = par->fbtftops.write(par, buf, len); | 43 | ret = par->fbtftops.write(par, buf, len); |
| 45 | if (ret < 0) | 44 | if (ret < 0) |
| @@ -76,20 +75,16 @@ static int fbtft_request_one_gpio(struct fbtft_par *par, · 30 unmodified lines | |||
| 76 | struct gpio_desc **gpiop) | 75 | struct gpio_desc **gpiop) |
| 77 | { | 76 | { |
| 78 | struct device *dev = par->info->device; | 77 | struct device *dev = par->info->device; |
| 79 | int ret = 0; | ||
| 80 | 78 | ||
| 81 | *gpiop = devm_gpiod_get_index_optional(dev, name, index, | 79 | *gpiop = devm_gpiod_get_index_optional(dev, name, index, |
| 82 | GPIOD_OUT_HIGH); | 80 | GPIOD_OUT_LOW); |
| 83 | if (IS_ERR(*gpiop)) { | 81 | if (IS_ERR(*gpiop)) |
| 84 | ret = PTR_ERR(*gpiop); | 82 | return dev_err_probe(dev, PTR_ERR(*gpiop), "Failed to request %s GPIO\n", name); |
| 85 | dev_err(dev, | 83 | |
| 86 | "Failed to request %s GPIO: %d\n", name, ret); | ||
| 87 | return ret; | ||
| 88 | } | ||
| 89 | fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n", | 84 | fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n", |
| 90 | __func__, name); | 85 | __func__, name); |
| 91 | 86 | ||
| 92 | return ret; | 87 | return 0; |
| 93 | } | 88 | } |
| 94 | 89 | ||
| 95 | static int fbtft_request_gpios(struct fbtft_par *par) | 90 | static int fbtft_request_gpios(struct fbtft_par *par) |
| @@ -226,11 +221,15 @@ static void fbtft_reset(struct fbtft_par *par) · 130 unmodified lines | |||
| 226 | { | 221 | { |
| 227 | if (!par->gpio.reset) | 222 | if (!par->gpio.reset) |
| 228 | return; | 223 | return; |
| 224 | |||
| 229 | fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__); | 225 | fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__); |
| 226 | |||
| 230 | gpiod_set_value_cansleep(par->gpio.reset, 1); | 227 | gpiod_set_value_cansleep(par->gpio.reset, 1); |
| 231 | usleep_range(20, 40); | 228 | usleep_range(20, 40); |
| 232 | gpiod_set_value_cansleep(par->gpio.reset, 0); | 229 | gpiod_set_value_cansleep(par->gpio.reset, 0); |
| 233 | msleep(120); | 230 | msleep(120); |
| 231 | |||
| 232 | gpiod_set_value_cansleep(par->gpio.cs, 1); /* Activate chip */ | ||
| 234 | } | 233 | } |
| 235 | 234 | ||
| 236 | static void fbtft_update_display(struct fbtft_par *par, unsigned int start_line, | 235 | static void fbtft_update_display(struct fbtft_par *par, unsigned int start_line, |
| @@ -922,8 +921,6 @@ static int fbtft_init_display_from_property(struct fbtft_par *par) · 685 unmodified lines | |||
| 922 | goto out_free; | 921 | goto out_free; |
| 923 | 922 | ||
| 924 | par->fbtftops.reset(par); | 923 | par->fbtftops.reset(par); |
| 925 | if (par->gpio.cs) | ||
| 926 | gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ | ||
| 927 | 924 | ||
| 928 | index = -1; | 925 | index = -1; |
| 929 | val = values[++index]; | 926 | val = values[++index]; |
| @@ -1018,8 +1015,6 @@ int fbtft_init_display(struct fbtft_par *par) · 88 unmodified lines | |||
| 1018 | } | 1015 | } |
| 1019 | 1016 | ||
| 1020 | par->fbtftops.reset(par); | 1017 | par->fbtftops.reset(par); |
| 1021 | if (par->gpio.cs) | ||
| 1022 | gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ | ||
| 1023 | 1018 | ||
| 1024 | i = 0; | 1019 | i = 0; |
| 1025 | while (i < FBTFT_MAX_INIT_SEQUENCE) { | 1020 | while (i < FBTFT_MAX_INIT_SEQUENCE) { |
| @@ -142,12 +142,12 @@ int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len) · 141 unmodified lines | |||
| 142 | data = *(u8 *)buf; | 142 | data = *(u8 *)buf; |
| 143 | 143 | ||
| 144 | /* Start writing by pulling down /WR */ | 144 | /* Start writing by pulling down /WR */ |
| 145 | gpiod_set_value(par->gpio.wr, 0); | 145 | gpiod_set_value(par->gpio.wr, 1); |
| 146 | 146 | ||
| 147 | /* Set data */ | 147 | /* Set data */ |
| 148 | #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO | 148 | #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO |
| 149 | if (data == prev_data) { | 149 | if (data == prev_data) { |
| 150 | gpiod_set_value(par->gpio.wr, 0); /* used as delay */ | 150 | gpiod_set_value(par->gpio.wr, 1); /* used as delay */ |
| 151 | } else { | 151 | } else { |
| 152 | for (i = 0; i < 8; i++) { | 152 | for (i = 0; i < 8; i++) { |
| 153 | if ((data & 1) != (prev_data & 1)) | 153 | if ((data & 1) != (prev_data & 1)) |
| @@ -165,7 +165,7 @@ int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len) · 11 unmodified lines | |||
| 165 | #endif | 165 | #endif |
| 166 | 166 | ||
| 167 | /* Pullup /WR */ | 167 | /* Pullup /WR */ |
| 168 | gpiod_set_value(par->gpio.wr, 1); | 168 | gpiod_set_value(par->gpio.wr, 0); |
| 169 | 169 | ||
| 170 | #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO | 170 | #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO |
| 171 | prev_data = *(u8 *)buf; | 171 | prev_data = *(u8 *)buf; |
| @@ -192,12 +192,12 @@ int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len) · 20 unmodified lines | |||
| 192 | data = *(u16 *)buf; | 192 | data = *(u16 *)buf; |
| 193 | 193 | ||
| 194 | /* Start writing by pulling down /WR */ | 194 | /* Start writing by pulling down /WR */ |
| 195 | gpiod_set_value(par->gpio.wr, 0); | 195 | gpiod_set_value(par->gpio.wr, 1); |
| 196 | 196 | ||
| 197 | /* Set data */ | 197 | /* Set data */ |
| 198 | #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO | 198 | #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO |
| 199 | if (data == prev_data) { | 199 | if (data == prev_data) { |
| 200 | gpiod_set_value(par->gpio.wr, 0); /* used as delay */ | 200 | gpiod_set_value(par->gpio.wr, 1); /* used as delay */ |
| 201 | } else { | 201 | } else { |
| 202 | for (i = 0; i < 16; i++) { | 202 | for (i = 0; i < 16; i++) { |
| 203 | if ((data & 1) != (prev_data & 1)) | 203 | if ((data & 1) != (prev_data & 1)) |
| @@ -215,7 +215,7 @@ int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len) · 11 unmodified lines | |||
| 215 | #endif | 215 | #endif |
| 216 | 216 | ||
| 217 | /* Pullup /WR */ | 217 | /* Pullup /WR */ |
| 218 | gpiod_set_value(par->gpio.wr, 1); | 218 | gpiod_set_value(par->gpio.wr, 0); |
| 219 | 219 | ||
| 220 | #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO | 220 | #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO |
| 221 | prev_data = *(u16 *)buf; | 221 | prev_data = *(u16 *)buf; |
| @@ -32,7 +32,7 @@ struct anybuss_client { · 31 unmodified lines | |||
| 32 | struct anybuss_client_driver { | 32 | struct anybuss_client_driver { |
| 33 | struct device_driver driver; | 33 | struct device_driver driver; |
| 34 | int (*probe)(struct anybuss_client *adev); | 34 | int (*probe)(struct anybuss_client *adev); |
| 35 | int (*remove)(struct anybuss_client *adev); | 35 | void (*remove)(struct anybuss_client *adev); |
| 36 | u16 anybus_id; | 36 | u16 anybus_id; |
| 37 | }; | 37 | }; |
| 38 | 38 | ||
| @@ -190,12 +190,11 @@ static int profinet_probe(struct anybuss_client *client) · 189 unmodified lines | |||
| 190 | return 0; | 190 | return 0; |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | static int profinet_remove(struct anybuss_client *client) | 193 | static void profinet_remove(struct anybuss_client *client) |
| 194 | { | 194 | { |
| 195 | struct profi_priv *priv = anybuss_get_drvdata(client); | 195 | struct profi_priv *priv = anybuss_get_drvdata(client); |
| 196 | 196 | ||
| 197 | fieldbus_dev_unregister(&priv->fbdev); | 197 | fieldbus_dev_unregister(&priv->fbdev); |
| 198 | return 0; | ||
| 199 | } | 198 | } |
| 200 | 199 | ||
| 201 | static struct anybuss_client_driver profinet_driver = { | 200 | static struct anybuss_client_driver profinet_driver = { |
| @@ -1183,8 +1183,6 @@ static int anybus_bus_probe(struct device *dev) · 1182 unmodified lines | |||
| 1183 | struct anybuss_client *adev = | 1183 | struct anybuss_client *adev = |
| 1184 | to_anybuss_client(dev); | 1184 | to_anybuss_client(dev); |
| 1185 | 1185 | ||
| 1186 | if (!adrv->probe) | ||
| 1187 | return -ENODEV; | ||
| 1188 | return adrv->probe(adev); | 1186 | return adrv->probe(adev); |
| 1189 | } | 1187 | } |
| 1190 | 1188 | ||
| @@ -1194,7 +1192,8 @@ static int anybus_bus_remove(struct device *dev) · 3 unmodified lines | |||
| 1194 | to_anybuss_client_driver(dev->driver); | 1192 | to_anybuss_client_driver(dev->driver); |
| 1195 | 1193 | ||
| 1196 | if (adrv->remove) | 1194 | if (adrv->remove) |
| 1197 | return adrv->remove(to_anybuss_client(dev)); | 1195 | adrv->remove(to_anybuss_client(dev)); |
| 1196 | |||
| 1198 | return 0; | 1197 | return 0; |
| 1199 | } | 1198 | } |
| 1200 | 1199 | ||
| @@ -1207,6 +1206,9 @@ static struct bus_type anybus_bus = { · 6 unmodified lines | |||
| 1207 | 1206 | ||
| 1208 | int anybuss_client_driver_register(struct anybuss_client_driver *drv) | 1207 | int anybuss_client_driver_register(struct anybuss_client_driver *drv) |
| 1209 | { | 1208 | { |
| 1209 | if (!drv->probe) | ||
| 1210 | return -ENODEV; | ||
| 1211 | |||
| 1210 | drv->driver.bus = &anybus_bus; | 1212 | drv->driver.bus = &anybus_bus; |
| 1211 | return driver_register(&drv->driver); | 1213 | return driver_register(&drv->driver); |
| 1212 | } | 1214 | } |
| @@ -45,14 +45,14 @@ module_param_named(loop, create_loop_dev, bool, 0644); · 44 unmodified lines | |||
| 45 | */ | 45 | */ |
| 46 | #define WAKEUP_CHARS 256 | 46 | #define WAKEUP_CHARS 256 |
| 47 | 47 | ||
| 48 | /** | 48 | /* |
| 49 | * fwserial_list: list of every fw_serial created for each fw_card | 49 | * fwserial_list: list of every fw_serial created for each fw_card |
| 50 | * See discussion in fwserial_probe. | 50 | * See discussion in fwserial_probe. |
| 51 | */ | 51 | */ |
| 52 | static LIST_HEAD(fwserial_list); | 52 | static LIST_HEAD(fwserial_list); |
| 53 | static DEFINE_MUTEX(fwserial_list_mutex); | 53 | static DEFINE_MUTEX(fwserial_list_mutex); |
| 54 | 54 | ||
| 55 | /** | 55 | /* |
| 56 | * port_table: array of tty ports allocated to each fw_card | 56 | * port_table: array of tty ports allocated to each fw_card |
| 57 | * | 57 | * |
| 58 | * tty ports are allocated during probe when an fw_serial is first | 58 | * tty ports are allocated during probe when an fw_serial is first |
| @@ -284,7 +284,7 @@ static void fwtty_restart_tx(struct fwtty_port *port) · 225 unmodified lines | |||
| 284 | spin_unlock_bh(&port->lock); | 284 | spin_unlock_bh(&port->lock); |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | /** | 287 | /* |
| 288 | * fwtty_update_port_status - decodes & dispatches line status changes | 288 | * fwtty_update_port_status - decodes & dispatches line status changes |
| 289 | * | 289 | * |
| 290 | * Note: in loopback, the port->lock is being held. Only use functions that | 290 | * Note: in loopback, the port->lock is being held. Only use functions that |
| @@ -375,7 +375,7 @@ static void fwtty_update_port_status(struct fwtty_port *port, · 84 unmodified lines | |||
| 375 | wake_up_interruptible(&port->port.delta_msr_wait); | 375 | wake_up_interruptible(&port->port.delta_msr_wait); |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | /** | 378 | /* |
| 379 | * __fwtty_port_line_status - generate 'line status' for indicated port | 379 | * __fwtty_port_line_status - generate 'line status' for indicated port |
| 380 | * | 380 | * |
| 381 | * This function returns a remote 'MSR' state based on the local 'MCR' state, | 381 | * This function returns a remote 'MSR' state based on the local 'MCR' state, |
| @@ -403,7 +403,7 @@ static unsigned int __fwtty_port_line_status(struct fwtty_port *port) · 21 unmodified lines | |||
| 403 | return status; | 403 | return status; |
| 404 | } | 404 | } |
| 405 | 405 | ||
| 406 | /** | 406 | /* |
| 407 | * __fwtty_write_port_status - send the port line status to peer | 407 | * __fwtty_write_port_status - send the port line status to peer |
| 408 | * | 408 | * |
| 409 | * Note: caller must be holding the port lock. | 409 | * Note: caller must be holding the port lock. |
| @@ -426,7 +426,7 @@ static int __fwtty_write_port_status(struct fwtty_port *port) · 16 unmodified lines | |||
| 426 | return err; | 426 | return err; |
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | /** | 429 | /* |
| 430 | * fwtty_write_port_status - same as above but locked by port lock | 430 | * fwtty_write_port_status - same as above but locked by port lock |
| 431 | */ | 431 | */ |
| 432 | static int fwtty_write_port_status(struct fwtty_port *port) | 432 | static int fwtty_write_port_status(struct fwtty_port *port) |
| @@ -462,7 +462,7 @@ static void fwtty_throttle_port(struct fwtty_port *port) · 29 unmodified lines | |||
| 462 | tty_kref_put(tty); | 462 | tty_kref_put(tty); |
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | /** | 465 | /* |
| 466 | * fwtty_do_hangup - wait for ldisc to deliver all pending rx; only then hangup | 466 | * fwtty_do_hangup - wait for ldisc to deliver all pending rx; only then hangup |
| 467 | * | 467 | * |
| 468 | * When the remote has finished tx, and all in-flight rx has been received and | 468 | * When the remote has finished tx, and all in-flight rx has been received and |
| @@ -589,9 +589,8 @@ out: · 120 unmodified lines | |||
| 589 | return err; | 589 | return err; |
| 590 | } | 590 | } |
| 591 | 591 | ||
| 592 | /** | 592 | /* |
| 593 | * fwtty_port_handler - bus address handler for port reads/writes | 593 | * fwtty_port_handler - bus address handler for port reads/writes |
| 594 | * @parameters: fw_address_callback_t as specified by firewire core interface | ||
| 595 | * | 594 | * |
| 596 | * This handler is responsible for handling inbound read/write dma from remotes. | 595 | * This handler is responsible for handling inbound read/write dma from remotes. |
| 597 | */ | 596 | */ |
| @@ -656,7 +655,7 @@ respond: · 58 unmodified lines | |||
| 656 | fw_send_response(card, request, rcode); | 655 | fw_send_response(card, request, rcode); |
| 657 | } | 656 | } |
| 658 | 657 | ||
| 659 | /** | 658 | /* |
| 660 | * fwtty_tx_complete - callback for tx dma | 659 | * fwtty_tx_complete - callback for tx dma |
| 661 | * @data: ignored, has no meaning for write txns | 660 | * @data: ignored, has no meaning for write txns |
| 662 | * @length: ignored, has no meaning for write txns | 661 | * @length: ignored, has no meaning for write txns |
| @@ -904,7 +903,7 @@ static void fwtty_port_dtr_rts(struct tty_port *tty_port, int on) · 241 unmodified lines | |||
| 904 | spin_unlock_bh(&port->lock); | 903 | spin_unlock_bh(&port->lock); |
| 905 | } | 904 | } |
| 906 | 905 | ||
| 907 | /** | 906 | /* |
| 908 | * fwtty_port_carrier_raised: required tty_port operation | 907 | * fwtty_port_carrier_raised: required tty_port operation |
| 909 | * | 908 | * |
| 910 | * This port operation is polled after a tty has been opened and is waiting for | 909 | * This port operation is polled after a tty has been opened and is waiting for |
| @@ -1011,7 +1010,7 @@ static int fwtty_port_activate(struct tty_port *tty_port, · 100 unmodified lines | |||
| 1011 | return 0; | 1010 | return 0; |
| 1012 | } | 1011 | } |
| 1013 | 1012 | ||
| 1014 | /** | 1013 | /* |
| 1015 | * fwtty_port_shutdown | 1014 | * fwtty_port_shutdown |
| 1016 | * | 1015 | * |
| 1017 | * Note: the tty port core ensures this is not the console and | 1016 | * Note: the tty port core ensures this is not the console and |
| @@ -1297,7 +1296,7 @@ static void fwtty_set_termios(struct tty_struct *tty, struct ktermios *old) · 279 unmodified lines | |||
| 1297 | } | 1296 | } |
| 1298 | } | 1297 | } |
| 1299 | 1298 | ||
| 1300 | /** | 1299 | /* |
| 1301 | * fwtty_break_ctl - start/stop sending breaks | 1300 | * fwtty_break_ctl - start/stop sending breaks |
| 1302 | * | 1301 | * |
| 1303 | * Signals the remote to start or stop generating simulated breaks. | 1302 | * Signals the remote to start or stop generating simulated breaks. |
| @@ -1669,7 +1668,7 @@ static inline int fwserial_send_mgmt_sync(struct fwtty_peer *peer, · 365 unmodified lines | |||
| 1669 | return rcode; | 1668 | return rcode; |
| 1670 | } | 1669 | } |
| 1671 | 1670 | ||
| 1672 | /** | 1671 | /* |
| 1673 | * fwserial_claim_port - attempt to claim port @ index for peer | 1672 | * fwserial_claim_port - attempt to claim port @ index for peer |
| 1674 | * | 1673 | * |
| 1675 | * Returns ptr to claimed port or error code (as ERR_PTR()) | 1674 | * Returns ptr to claimed port or error code (as ERR_PTR()) |
| @@ -1697,7 +1696,7 @@ static struct fwtty_port *fwserial_claim_port(struct fwtty_peer *peer, · 21 unmodified lines | |||
| 1697 | return port; | 1696 | return port; |
| 1698 | } | 1697 | } |
| 1699 | 1698 | ||
| 1700 | /** | 1699 | /* |
| 1701 | * fwserial_find_port - find avail port and claim for peer | 1700 | * fwserial_find_port - find avail port and claim for peer |
| 1702 | * | 1701 | * |
| 1703 | * Returns ptr to claimed port or NULL if none avail | 1702 | * Returns ptr to claimed port or NULL if none avail |
| @@ -1764,7 +1763,7 @@ static void fwserial_plug_timeout(struct timer_list *t) · 60 unmodified lines | |||
| 1764 | fwserial_release_port(port, false); | 1763 | fwserial_release_port(port, false); |
| 1765 | } | 1764 | } |
| 1766 | 1765 | ||
| 1767 | /** | 1766 | /* |
| 1768 | * fwserial_connect_peer - initiate virtual cable with peer | 1767 | * fwserial_connect_peer - initiate virtual cable with peer |
| 1769 | * | 1768 | * |
| 1770 | * Returns 0 if VIRT_CABLE_PLUG request was successfully sent, | 1769 | * Returns 0 if VIRT_CABLE_PLUG request was successfully sent, |
| @@ -1829,7 +1828,7 @@ free_pkt: · 58 unmodified lines | |||
| 1829 | return err; | 1828 | return err; |
| 1830 | } | 1829 | } |
| 1831 | 1830 | ||
| 1832 | /** | 1831 | /* |
| 1833 | * fwserial_close_port - | 1832 | * fwserial_close_port - |
| 1834 | * HUP the tty (if the tty exists) and unregister the tty device. | 1833 | * HUP the tty (if the tty exists) and unregister the tty device. |
| 1835 | * Only used by the unit driver upon unit removal to disconnect and | 1834 | * Only used by the unit driver upon unit removal to disconnect and |
| @@ -1893,7 +1892,7 @@ static struct fw_serial *__fwserial_lookup_rcu(struct fw_card *card) · 57 unmodified lines | |||
| 1893 | return NULL; | 1892 | return NULL; |
| 1894 | } | 1893 | } |
| 1895 | 1894 | ||
| 1896 | /** | 1895 | /* |
| 1897 | * __fwserial_peer_by_node_id - finds a peer matching the given generation + id | 1896 | * __fwserial_peer_by_node_id - finds a peer matching the given generation + id |
| 1898 | * | 1897 | * |
| 1899 | * If a matching peer could not be found for the specified generation/node id, | 1898 | * If a matching peer could not be found for the specified generation/node id, |
| @@ -2076,7 +2075,7 @@ static int fwserial_add_peer(struct fw_serial *serial, struct fw_unit *unit) · 176 unmodified lines | |||
| 2076 | return 0; | 2075 | return 0; |
| 2077 | } | 2076 | } |
| 2078 | 2077 | ||
| 2079 | /** | 2078 | /* |
| 2080 | * fwserial_remove_peer - remove a 'serial' unit device as a 'peer' | 2079 | * fwserial_remove_peer - remove a 'serial' unit device as a 'peer' |
| 2081 | * | 2080 | * |
| 2082 | * Remove a 'peer' from its list of peers. This function is only | 2081 | * Remove a 'peer' from its list of peers. This function is only |
| @@ -2279,7 +2278,7 @@ free_ports: · 196 unmodified lines | |||
| 2279 | return err; | 2278 | return err; |
| 2280 | } | 2279 | } |
| 2281 | 2280 | ||
| 2282 | /** | 2281 | /* |
| 2283 | * fwserial_probe: bus probe function for firewire 'serial' unit devices | 2282 | * fwserial_probe: bus probe function for firewire 'serial' unit devices |
| 2284 | * | 2283 | * |
| 2285 | * A 'serial' unit device is created and probed as a result of: | 2284 | * A 'serial' unit device is created and probed as a result of: |
| @@ -2331,7 +2330,7 @@ static int fwserial_probe(struct fw_unit *unit, · 45 unmodified lines | |||
| 2331 | return err; | 2330 | return err; |
| 2332 | } | 2331 | } |
| 2333 | 2332 | ||
| 2334 | /** | 2333 | /* |
| 2335 | * fwserial_remove: bus removal function for firewire 'serial' unit devices | 2334 | * fwserial_remove: bus removal function for firewire 'serial' unit devices |
| 2336 | * | 2335 | * |
| 2337 | * The corresponding 'peer' for this unit device is removed from the list of | 2336 | * The corresponding 'peer' for this unit device is removed from the list of |
| @@ -2363,7 +2362,7 @@ static void fwserial_remove(struct fw_unit *unit) · 25 unmodified lines | |||
| 2363 | mutex_unlock(&fwserial_list_mutex); | 2362 | mutex_unlock(&fwserial_list_mutex); |
| 2364 | } | 2363 | } |
| 2365 | 2364 | ||
| 2366 | /** | 2365 | /* |
| 2367 | * fwserial_update: bus update function for 'firewire' serial unit devices | 2366 | * fwserial_update: bus update function for 'firewire' serial unit devices |
| 2368 | * | 2367 | * |
| 2369 | * Updates the new node_id and bus generation for this peer. Note that locking | 2368 | * Updates the new node_id and bus generation for this peer. Note that locking |
| @@ -2699,9 +2698,8 @@ static int fwserial_parse_mgmt_write(struct fwtty_peer *peer, · 329 unmodified lines | |||
| 2699 | return rcode; | 2698 | return rcode; |
| 2700 | } | 2699 | } |
| 2701 | 2700 | ||
| 2702 | /** | 2701 | /* |
| 2703 | * fwserial_mgmt_handler: bus address handler for mgmt requests | 2702 | * fwserial_mgmt_handler: bus address handler for mgmt requests |
| 2704 | * @parameters: fw_address_callback_t as specified by firewire core interface | ||
| 2705 | * | 2703 | * |
| 2706 | * This handler is responsible for handling virtual cable requests from remotes | 2704 | * This handler is responsible for handling virtual cable requests from remotes |
| 2707 | * for all cards. | 2705 | * for all cards. |
| @@ -611,10 +611,12 @@ static void gdm_lte_netif_rx(struct net_device *dev, char *buf, · 610 unmodified lines | |||
| 611 | * bytes (99,130,83,99 dec) | 611 | * bytes (99,130,83,99 dec) |
| 612 | */ | 612 | */ |
| 613 | } __packed; | 613 | } __packed; |
| 614 | void *addr = buf + sizeof(struct iphdr) + | 614 | int offset = sizeof(struct iphdr) + |
| 615 | sizeof(struct udphdr) + | 615 | sizeof(struct udphdr) + |
| 616 | offsetof(struct dhcp_packet, chaddr); | 616 | offsetof(struct dhcp_packet, chaddr); |
| 617 | ether_addr_copy(nic->dest_mac_addr, addr); | 617 | if (offset + ETH_ALEN > len) |
| 618 | return; | ||
| 619 | ether_addr_copy(nic->dest_mac_addr, buf + offset); | ||
| 618 | } | 620 | } |
| 619 | } | 621 | } |
| 620 | 622 | ||
| @@ -677,6 +679,7 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len) · 56 unmodified lines | |||
| 677 | struct sdu *sdu = NULL; | 679 | struct sdu *sdu = NULL; |
| 678 | u8 endian = phy_dev->get_endian(phy_dev->priv_dev); | 680 | u8 endian = phy_dev->get_endian(phy_dev->priv_dev); |
| 679 | u8 *data = (u8 *)multi_sdu->data; | 681 | u8 *data = (u8 *)multi_sdu->data; |
| 682 | int copied; | ||
| 680 | u16 i = 0; | 683 | u16 i = 0; |
| 681 | u16 num_packet; | 684 | u16 num_packet; |
| 682 | u16 hci_len; | 685 | u16 hci_len; |
| @@ -684,10 +687,15 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len) · 1 unmodified line | |||
| 684 | u32 nic_type; | 687 | u32 nic_type; |
| 685 | int index; | 688 | int index; |
| 686 | 689 | ||
| 687 | hci_len = gdm_dev16_to_cpu(endian, multi_sdu->len); | ||
| 688 | num_packet = gdm_dev16_to_cpu(endian, multi_sdu->num_packet); | 690 | num_packet = gdm_dev16_to_cpu(endian, multi_sdu->num_packet); |
| 689 | 691 | ||
| 690 | for (i = 0; i < num_packet; i++) { | 692 | for (i = 0; i < num_packet; i++) { |
| 693 | copied = data - multi_sdu->data; | ||
| 694 | if (len < copied + sizeof(*sdu)) { | ||
| 695 | pr_err("rx prevent buffer overflow"); | ||
| 696 | return; | ||
| 697 | } | ||
| 698 | |||
| 691 | sdu = (struct sdu *)data; | 699 | sdu = (struct sdu *)data; |
| 692 | 700 | ||
| 693 | cmd_evt = gdm_dev16_to_cpu(endian, sdu->cmd_evt); | 701 | cmd_evt = gdm_dev16_to_cpu(endian, sdu->cmd_evt); |
| @@ -698,7 +706,8 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len) · 4 unmodified lines | |||
| 698 | pr_err("rx sdu wrong hci %04x\n", cmd_evt); | 706 | pr_err("rx sdu wrong hci %04x\n", cmd_evt); |
| 699 | return; | 707 | return; |
| 700 | } | 708 | } |
| 701 | if (hci_len < 12) { | 709 | if (hci_len < 12 || |
| 710 | len < copied + sizeof(*sdu) + (hci_len - 12)) { | ||
| 702 | pr_err("rx sdu invalid len %d\n", hci_len); | 711 | pr_err("rx sdu invalid len %d\n", hci_len); |
| 703 | return; | 712 | return; |
| 704 | } | 713 | } |
| @@ -676,7 +676,7 @@ static int gbaudio_tplg_create_kcontrol(struct gbaudio_module_info *gb, · 675 unmodified lines | |||
| 676 | struct gbaudio_ctl_pvt *ctldata; | 676 | struct gbaudio_ctl_pvt *ctldata; |
| 677 | 677 | ||
| 678 | switch (ctl->iface) { | 678 | switch (ctl->iface) { |
| 679 | case SNDRV_CTL_ELEM_IFACE_MIXER: | 679 | case (__force int)SNDRV_CTL_ELEM_IFACE_MIXER: |
| 680 | switch (ctl->info.type) { | 680 | switch (ctl->info.type) { |
| 681 | case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: | 681 | case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: |
| 682 | ret = gbaudio_tplg_create_enum_kctl(gb, kctl, ctl); | 682 | ret = gbaudio_tplg_create_enum_kctl(gb, kctl, ctl); |
| @@ -903,7 +903,7 @@ static int gbaudio_tplg_create_wcontrol(struct gbaudio_module_info *gb, · 220 unmodified lines | |||
| 903 | int ret; | 903 | int ret; |
| 904 | 904 | ||
| 905 | switch (ctl->iface) { | 905 | switch (ctl->iface) { |
| 906 | case SNDRV_CTL_ELEM_IFACE_MIXER: | 906 | case (__force int)SNDRV_CTL_ELEM_IFACE_MIXER: |
| 907 | switch (ctl->info.type) { | 907 | switch (ctl->info.type) { |
| 908 | case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: | 908 | case GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED: |
| 909 | ret = gbaudio_tplg_create_enum_ctl(gb, kctl, ctl); | 909 | ret = gbaudio_tplg_create_enum_ctl(gb, kctl, ctl); |
| @@ -27,7 +27,7 @@ struct gbphy_host { · 26 unmodified lines | |||
| 27 | static DEFINE_IDA(gbphy_id); | 27 | static DEFINE_IDA(gbphy_id); |
| 28 | 28 | ||
| 29 | static ssize_t protocol_id_show(struct device *dev, | 29 | static ssize_t protocol_id_show(struct device *dev, |
| 30 | struct device_attribute *attr, char *buf) | 30 | struct device_attribute *attr, char *buf) |
| 31 | { | 31 | { |
| 32 | struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); | 32 | struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); |
| 33 | 33 | ||
| @@ -221,7 +221,7 @@ void gb_gbphy_deregister_driver(struct gbphy_driver *driver) · 187 unmodified lines | |||
| 221 | EXPORT_SYMBOL_GPL(gb_gbphy_deregister_driver); | 221 | EXPORT_SYMBOL_GPL(gb_gbphy_deregister_driver); |
| 222 | 222 | ||
| 223 | static struct gbphy_device *gb_gbphy_create_dev(struct gb_bundle *bundle, | 223 | static struct gbphy_device *gb_gbphy_create_dev(struct gb_bundle *bundle, |
| 224 | struct greybus_descriptor_cport *cport_desc) | 224 | struct greybus_descriptor_cport *cport_desc) |
| 225 | { | 225 | { |
| 226 | struct gbphy_device *gbphy_dev; | 226 | struct gbphy_device *gbphy_dev; |
| 227 | int retval; | 227 | int retval; |
| @@ -246,6 +246,7 @@ static struct gb_operation *gb_spi_operation_create(struct gb_spilib *spi, · 245 unmodified lines | |||
| 246 | xfer = spi->first_xfer; | 246 | xfer = spi->first_xfer; |
| 247 | while (msg->state != GB_SPI_STATE_OP_DONE) { | 247 | while (msg->state != GB_SPI_STATE_OP_DONE) { |
| 248 | int xfer_delay; | 248 | int xfer_delay; |
| 249 | |||
| 249 | if (xfer == spi->last_xfer) | 250 | if (xfer == spi->last_xfer) |
| 250 | xfer_len = spi->last_xfer_size; | 251 | xfer_len = spi->last_xfer_size; |
| 251 | else | 252 | else |
| @@ -39,7 +39,7 @@ TABLE OF CONTENTS. · 38 unmodified lines | |||
| 39 | 39 | ||
| 40 | 5. USE CASE (from a mailing list discussion with Greg) | 40 | 5. USE CASE (from a mailing list discussion with Greg) |
| 41 | 41 | ||
| 42 | a. As a FPGA development support tool, | 42 | a. As an FPGA development support tool, |
| 43 | During FPGA firmware development, you need to download a new FPGA | 43 | During FPGA firmware development, you need to download a new FPGA |
| 44 | image frequently. | 44 | image frequently. |
| 45 | You would do that with a dedicated JTAG, which usually a limited | 45 | You would do that with a dedicated JTAG, which usually a limited |
| @@ -1,27 +1,5 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | ||
| 3 | # to be placed at drivers/phy | ||
| 4 | config PHY_HI3670_USB | ||
| 5 | tristate "hi3670 USB PHY support" | ||
| 6 | depends on (ARCH_HISI && ARM64) || COMPILE_TEST | ||
| 7 | select GENERIC_PHY | ||
| 8 | select MFD_SYSCON | ||
| 9 | help | ||
| 10 | Enable this to support the HISILICON HI3670 USB PHY. | ||
| 11 | |||
| 12 | To compile this driver as a module, choose M here. | ||
| 13 | |||
| 14 | # to be placed at drivers/spmi | ||
| 15 | config SPMI_HISI3670 | ||
| 16 | tristate "Hisilicon 3670 SPMI Controller" | ||
| 17 | select IRQ_DOMAIN_HIERARCHY | ||
| 18 | depends on HAS_IOMEM | ||
| 19 | depends on SPMI | ||
| 20 | help | ||
| 21 | If you say yes to this option, support will be included for the | ||
| 22 | built-in SPMI PMIC Arbiter interface on Hisilicon 3670 | ||
| 23 | processors. | ||
| 24 | |||
| 25 | # to be placed at drivers/mfd | 3 | # to be placed at drivers/mfd |
| 26 | config MFD_HI6421_SPMI | 4 | config MFD_HI6421_SPMI |
| 27 | tristate "HiSilicon Hi6421v600 SPMI PMU/Codec IC" | 5 | tristate "HiSilicon Hi6421v600 SPMI PMU/Codec IC" |
| @@ -1,6 +1,3 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | ||
| 3 | obj-$(CONFIG_PHY_HI3670_USB) += phy-hi3670-usb3.o | ||
| 4 | |||
| 5 | obj-$(CONFIG_SPMI_HISI3670) += hisi-spmi-controller.o | ||
| 6 | obj-$(CONFIG_MFD_HI6421_SPMI) += hi6421-spmi-pmic.o | 3 | obj-$(CONFIG_MFD_HI6421_SPMI) += hi6421-spmi-pmic.o |
| @@ -33,17 +33,27 @@ enum hi6421_spmi_pmic_irq_list { · 32 unmodified lines | |||
| 33 | SIM0_HPD_F, | 33 | SIM0_HPD_F, |
| 34 | SIM1_HPD_R, | 34 | SIM1_HPD_R, |
| 35 | SIM1_HPD_F, | 35 | SIM1_HPD_F, |
| 36 | PMIC_IRQ_LIST_MAX, | 36 | |
| 37 | PMIC_IRQ_LIST_MAX | ||
| 37 | }; | 38 | }; |
| 38 | 39 | ||
| 39 | #define HISI_IRQ_ARRAY 2 | 40 | #define HISI_IRQ_BANK_SIZE 2 |
| 40 | #define HISI_IRQ_NUM (HISI_IRQ_ARRAY * 8) | ||
| 41 | 41 | ||
| 42 | #define HISI_IRQ_KEY_NUM 0 | 42 | /* |
| 43 | * IRQ number for the power key button and mask for both UP and DOWN IRQs | ||
| 44 | */ | ||
| 45 | #define HISI_POWERKEY_IRQ_NUM 0 | ||
| 46 | #define HISI_IRQ_POWERKEY_UP_DOWN (BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP)) | ||
| 43 | 47 | ||
| 44 | #define HISI_BITS 8 | 48 | /* |
| 45 | #define HISI_IRQ_KEY_VALUE (BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP)) | 49 | * Registers for IRQ address and IRQ mask bits |
| 46 | #define HISI_MASK GENMASK(HISI_BITS - 1, 0) | 50 | * |
| 51 | * Please notice that we need to regmap a larger region, as other | ||
| 52 | * registers are used by the regulators. | ||
| 53 | * See drivers/regulator/hi6421-regulator.c. | ||
| 54 | */ | ||
| 55 | #define SOC_PMIC_IRQ_MASK_0_ADDR 0x0202 | ||
| 56 | #define SOC_PMIC_IRQ0_ADDR 0x0212 | ||
| 47 | 57 | ||
| 48 | /* | 58 | /* |
| 49 | * The IRQs are mapped as: | 59 | * The IRQs are mapped as: |
| @@ -67,13 +77,14 @@ enum hi6421_spmi_pmic_irq_list { · 17 unmodified lines | |||
| 67 | * SIM1_HPD_R 0x0203 0x213 bit 4 | 77 | * SIM1_HPD_R 0x0203 0x213 bit 4 |
| 68 | * SIM1_HPD_F 0x0203 0x213 bit 5 | 78 | * SIM1_HPD_F 0x0203 0x213 bit 5 |
| 69 | * ====================== ============= ============ ===== | 79 | * ====================== ============= ============ ===== |
| 80 | * | ||
| 81 | * Each mask register contains 8 bits. The ancillary macros below | ||
| 82 | * convert a number from 0 to 14 into a register address and a bit mask | ||
| 70 | */ | 83 | */ |
| 71 | #define SOC_PMIC_IRQ_MASK_0_ADDR 0x0202 | 84 | #define HISI_IRQ_MASK_REG(irq_data) (SOC_PMIC_IRQ_MASK_0_ADDR + \ |
| 72 | #define SOC_PMIC_IRQ0_ADDR 0x0212 | 85 | (irqd_to_hwirq(irq_data) / BITS_PER_BYTE)) |
| 73 | 86 | #define HISI_IRQ_MASK_BIT(irq_data) BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1)) | |
| 74 | #define IRQ_MASK_REGISTER(irq_data) (SOC_PMIC_IRQ_MASK_0_ADDR + \ | 87 | #define HISI_8BITS_MASK 0xff |
| 75 | (irqd_to_hwirq(irq_data) >> 3)) | ||
| 76 | #define IRQ_MASK_BIT(irq_data) BIT(irqd_to_hwirq(irq_data) & 0x07) | ||
| 77 | 88 | ||
| 78 | static const struct mfd_cell hi6421v600_devs[] = { | 89 | static const struct mfd_cell hi6421v600_devs[] = { |
| 79 | { .name = "hi6421v600-regulator", }, | 90 | { .name = "hi6421v600-regulator", }, |
| @@ -86,23 +97,31 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv) · 6 unmodified lines | |||
| 86 | unsigned int in; | 97 | unsigned int in; |
| 87 | int i, offset; | 98 | int i, offset; |
| 88 | 99 | ||
| 89 | for (i = 0; i < HISI_IRQ_ARRAY; i++) { | 100 | for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) { |
| 90 | regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &in); | 101 | regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &in); |
| 91 | pending = HISI_MASK & in; | ||
| 92 | regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, pending); | ||
| 93 | 102 | ||
| 94 | if (i == HISI_IRQ_KEY_NUM && | 103 | /* Mark pending IRQs as handled */ |
| 95 | (pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE) { | 104 | regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, in); |
| 105 | |||
| 106 | pending = in & HISI_8BITS_MASK; | ||
| 107 | |||
| 108 | if (i == HISI_POWERKEY_IRQ_NUM && | ||
| 109 | (pending & HISI_IRQ_POWERKEY_UP_DOWN) == HISI_IRQ_POWERKEY_UP_DOWN) { | ||
| 110 | /* | ||
| 111 | * If both powerkey down and up IRQs are received, | ||
| 112 | * handle them at the right order | ||
| 113 | */ | ||
| 96 | generic_handle_irq(ddata->irqs[POWERKEY_DOWN]); | 114 | generic_handle_irq(ddata->irqs[POWERKEY_DOWN]); |
| 97 | generic_handle_irq(ddata->irqs[POWERKEY_UP]); | 115 | generic_handle_irq(ddata->irqs[POWERKEY_UP]); |
| 98 | pending &= (~HISI_IRQ_KEY_VALUE); | 116 | pending &= ~HISI_IRQ_POWERKEY_UP_DOWN; |
| 99 | } | 117 | } |
| 100 | 118 | ||
| 101 | if (!pending) | 119 | if (!pending) |
| 102 | continue; | 120 | continue; |
| 103 | 121 | ||
| 104 | for_each_set_bit(offset, &pending, HISI_BITS) | 122 | for_each_set_bit(offset, &pending, BITS_PER_BYTE) { |
| 105 | generic_handle_irq(ddata->irqs[offset + i * HISI_BITS]); | 123 | generic_handle_irq(ddata->irqs[offset + i * BITS_PER_BYTE]); |
| 124 | } | ||
| 106 | } | 125 | } |
| 107 | 126 | ||
| 108 | return IRQ_HANDLED; | 127 | return IRQ_HANDLED; |
| @@ -115,12 +134,12 @@ static void hi6421_spmi_irq_mask(struct irq_data *d) · 6 unmodified lines | |||
| 115 | unsigned int data; | 134 | unsigned int data; |
| 116 | u32 offset; | 135 | u32 offset; |
| 117 | 136 | ||
| 118 | offset = IRQ_MASK_REGISTER(d); | 137 | offset = HISI_IRQ_MASK_REG(d); |
| 119 | 138 | ||
| 120 | spin_lock_irqsave(&ddata->lock, flags); | 139 | spin_lock_irqsave(&ddata->lock, flags); |
| 121 | 140 | ||
| 122 | regmap_read(ddata->regmap, offset, &data); | 141 | regmap_read(ddata->regmap, offset, &data); |
| 123 | data |= IRQ_MASK_BIT(d); | 142 | data |= HISI_IRQ_MASK_BIT(d); |
| 124 | regmap_write(ddata->regmap, offset, data); | 143 | regmap_write(ddata->regmap, offset, data); |
| 125 | 144 | ||
| 126 | spin_unlock_irqrestore(&ddata->lock, flags); | 145 | spin_unlock_irqrestore(&ddata->lock, flags); |
| @@ -132,20 +151,19 @@ static void hi6421_spmi_irq_unmask(struct irq_data *d) · 5 unmodified lines | |||
| 132 | u32 data, offset; | 151 | u32 data, offset; |
| 133 | unsigned long flags; | 152 | unsigned long flags; |
| 134 | 153 | ||
| 135 | offset = (irqd_to_hwirq(d) >> 3); | 154 | offset = HISI_IRQ_MASK_REG(d); |
| 136 | offset += SOC_PMIC_IRQ_MASK_0_ADDR; | ||
| 137 | 155 | ||
| 138 | spin_lock_irqsave(&ddata->lock, flags); | 156 | spin_lock_irqsave(&ddata->lock, flags); |
| 139 | 157 | ||
| 140 | regmap_read(ddata->regmap, offset, &data); | 158 | regmap_read(ddata->regmap, offset, &data); |
| 141 | data &= ~(1 << (irqd_to_hwirq(d) & 0x07)); | 159 | data &= ~HISI_IRQ_MASK_BIT(d); |
| 142 | regmap_write(ddata->regmap, offset, data); | 160 | regmap_write(ddata->regmap, offset, data); |
| 143 | 161 | ||
| 144 | spin_unlock_irqrestore(&ddata->lock, flags); | 162 | spin_unlock_irqrestore(&ddata->lock, flags); |
| 145 | } | 163 | } |
| 146 | 164 | ||
| 147 | static struct irq_chip hi6421_spmi_pmu_irqchip = { | 165 | static struct irq_chip hi6421_spmi_pmu_irqchip = { |
| 148 | .name = "hisi-irq", | 166 | .name = "hi6421v600-irq", |
| 149 | .irq_mask = hi6421_spmi_irq_mask, | 167 | .irq_mask = hi6421_spmi_irq_mask, |
| 150 | .irq_unmask = hi6421_spmi_irq_unmask, | 168 | .irq_unmask = hi6421_spmi_irq_unmask, |
| 151 | .irq_disable = hi6421_spmi_irq_mask, | 169 | .irq_disable = hi6421_spmi_irq_mask, |
| @@ -158,7 +176,7 @@ static int hi6421_spmi_irq_map(struct irq_domain *d, unsigned int virq, · 6 unmodified lines | |||
| 158 | struct hi6421_spmi_pmic *ddata = d->host_data; | 176 | struct hi6421_spmi_pmic *ddata = d->host_data; |
| 159 | 177 | ||
| 160 | irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip, | 178 | irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip, |
| 161 | handle_simple_irq, "hisi"); | 179 | handle_simple_irq, "hi6421v600"); |
| 162 | irq_set_chip_data(virq, ddata); | 180 | irq_set_chip_data(virq, ddata); |
| 163 | irq_set_irq_type(virq, IRQ_TYPE_NONE); | 181 | irq_set_irq_type(virq, IRQ_TYPE_NONE); |
| 164 | 182 | ||
| @@ -175,22 +193,24 @@ static void hi6421_spmi_pmic_irq_init(struct hi6421_spmi_pmic *ddata) · 10 unmodified lines | |||
| 175 | int i; | 193 | int i; |
| 176 | unsigned int pending; | 194 | unsigned int pending; |
| 177 | 195 | ||
| 178 | for (i = 0; i < HISI_IRQ_ARRAY; i++) | 196 | /* Mask all IRQs */ |
| 197 | for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) | ||
| 179 | regmap_write(ddata->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i, | 198 | regmap_write(ddata->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i, |
| 180 | HISI_MASK); | 199 | HISI_8BITS_MASK); |
| 181 | 200 | ||
| 182 | for (i = 0; i < HISI_IRQ_ARRAY; i++) { | 201 | /* Mark all IRQs as handled */ |
| 202 | for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) { | ||
| 183 | regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending); | 203 | regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending); |
| 184 | regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, | 204 | regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, |
| 185 | HISI_MASK); | 205 | HISI_8BITS_MASK); |
| 186 | } | 206 | } |
| 187 | } | 207 | } |
| 188 | 208 | ||
| 189 | static const struct regmap_config regmap_config = { | 209 | static const struct regmap_config regmap_config = { |
| 190 | .reg_bits = 16, | 210 | .reg_bits = 16, |
| 191 | .val_bits = HISI_BITS, | 211 | .val_bits = BITS_PER_BYTE, |
| 192 | .max_register = 0xffff, | 212 | .max_register = 0xffff, |
| 193 | .fast_io = true | 213 | .fast_io = true |
| 194 | }; | 214 | }; |
| 195 | 215 | ||
| 196 | static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) | 216 | static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) |
| @@ -230,29 +250,31 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) · 33 unmodified lines | |||
| 230 | 250 | ||
| 231 | hi6421_spmi_pmic_irq_init(ddata); | 251 | hi6421_spmi_pmic_irq_init(ddata); |
| 232 | 252 | ||
| 233 | ddata->irqs = devm_kzalloc(dev, HISI_IRQ_NUM * sizeof(int), GFP_KERNEL); | 253 | ddata->irqs = devm_kzalloc(dev, PMIC_IRQ_LIST_MAX * sizeof(int), GFP_KERNEL); |
| 234 | if (!ddata->irqs) | 254 | if (!ddata->irqs) |
| 235 | return -ENOMEM; | 255 | return -ENOMEM; |
| 236 | 256 | ||
| 237 | ddata->domain = irq_domain_add_simple(np, HISI_IRQ_NUM, 0, | 257 | ddata->domain = irq_domain_add_simple(np, PMIC_IRQ_LIST_MAX, 0, |
| 238 | &hi6421_spmi_domain_ops, ddata); | 258 | &hi6421_spmi_domain_ops, ddata); |
| 239 | if (!ddata->domain) { | 259 | if (!ddata->domain) { |
| 240 | dev_err(dev, "Failed to create IRQ domain\n"); | 260 | dev_err(dev, "Failed to create IRQ domain\n"); |
| 241 | return -ENODEV; | 261 | return -ENODEV; |
| 242 | } | 262 | } |
| 243 | 263 | ||
| 244 | for (i = 0; i < HISI_IRQ_NUM; i++) { | 264 | for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) { |
| 245 | virq = irq_create_mapping(ddata->domain, i); | 265 | virq = irq_create_mapping(ddata->domain, i); |
| 246 | if (!virq) { | 266 | if (!virq) { |
| 247 | dev_err(dev, "Failed to map H/W IRQ\n"); | 267 | dev_err(dev, "Failed to map H/W IRQ\n"); |
| 248 | return -ENOSPC; | 268 | return -ENODEV; |
| 249 | } | 269 | } |
| 250 | ddata->irqs[i] = virq; | 270 | ddata->irqs[i] = virq; |
| 251 | } | 271 | } |
| 252 | 272 | ||
| 253 | ret = request_threaded_irq(ddata->irq, hi6421_spmi_irq_handler, NULL, | 273 | ret = devm_request_threaded_irq(dev, |
| 254 | IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND, | 274 | ddata->irq, hi6421_spmi_irq_handler, |
| 255 | "pmic", ddata); | 275 | NULL, |
| 276 | IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND, | ||
| 277 | "pmic", ddata); | ||
| 256 | if (ret < 0) { | 278 | if (ret < 0) { |
| 257 | dev_err(dev, "Failed to start IRQ handling thread: error %d\n", | 279 | dev_err(dev, "Failed to start IRQ handling thread: error %d\n", |
| 258 | ret); | 280 | ret); |
| @@ -270,13 +292,6 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) · 11 unmodified lines | |||
| 270 | return ret; | 292 | return ret; |
| 271 | } | 293 | } |
| 272 | 294 | ||
| 273 | static void hi6421_spmi_pmic_remove(struct spmi_device *pdev) | ||
| 274 | { | ||
| 275 | struct hi6421_spmi_pmic *ddata = dev_get_drvdata(&pdev->dev); | ||
| 276 | |||
| 277 | free_irq(ddata->irq, ddata); | ||
| 278 | } | ||
| 279 | |||
| 280 | static const struct of_device_id pmic_spmi_id_table[] = { | 295 | static const struct of_device_id pmic_spmi_id_table[] = { |
| 281 | { .compatible = "hisilicon,hi6421-spmi" }, | 296 | { .compatible = "hisilicon,hi6421-spmi" }, |
| 282 | { } | 297 | { } |
| @@ -289,7 +304,6 @@ static struct spmi_driver hi6421_spmi_pmic_driver = { · 6 unmodified lines | |||
| 289 | .of_match_table = pmic_spmi_id_table, | 304 | .of_match_table = pmic_spmi_id_table, |
| 290 | }, | 305 | }, |
| 291 | .probe = hi6421_spmi_pmic_probe, | 306 | .probe = hi6421_spmi_pmic_probe, |
| 292 | .remove = hi6421_spmi_pmic_remove, | ||
| 293 | }; | 307 | }; |
| 294 | module_spmi_driver(hi6421_spmi_pmic_driver); | 308 | module_spmi_driver(hi6421_spmi_pmic_driver); |
| 295 | 309 | ||
| @@ -17,7 +17,7 @@ description: | · 16 unmodified lines | |||
| 17 | node. | 17 | node. |
| 18 | 18 | ||
| 19 | The SPMI controller part is provided by | 19 | The SPMI controller part is provided by |
| 20 | drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml. | 20 | Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml |
| 21 | 21 | ||
| 22 | properties: | 22 | properties: |
| 23 | $nodename: | 23 | $nodename: |
| @@ -32,12 +32,11 @@ properties: · 8 unmodified lines | |||
| 32 | '#interrupt-cells': | 32 | '#interrupt-cells': |
| 33 | const: 2 | 33 | const: 2 |
| 34 | 34 | ||
| 35 | interrupt-controller: | 35 | interrupt-controller: true |
| 36 | description: | ||
| 37 | Identify that the PMIC is capable of behaving as an interrupt controller. | ||
| 38 | 36 | ||
| 39 | gpios: | 37 | gpios: |
| 40 | maxItems: 1 | 38 | maxItems: 1 |
| 39 | description: GPIO used for IRQs | ||
| 41 | 40 | ||
| 42 | regulators: | 41 | regulators: |
| 43 | type: object | 42 | type: object |
| @@ -5,20 +5,14 @@ · 4 unmodified lines | |||
| 5 | * Copyright 2010 Analog Devices Inc. | 5 | * Copyright 2010 Analog Devices Inc. |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include <linux/delay.h> | ||
| 9 | #include <linux/device.h> | 8 | #include <linux/device.h> |
| 10 | 9 | ||
| 11 | #include <linux/iio/buffer.h> | ||
| 12 | #include <linux/iio/iio.h> | 10 | #include <linux/iio/iio.h> |
| 13 | #include <linux/iio/imu/adis.h> | 11 | #include <linux/iio/imu/adis.h> |
| 14 | #include <linux/iio/sysfs.h> | ||
| 15 | 12 | ||
| 16 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 17 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 18 | #include <linux/mutex.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/spi/spi.h> | 15 | #include <linux/spi/spi.h> |
| 21 | #include <linux/sysfs.h> | ||
| 22 | 16 | ||
| 23 | #define ADIS16203_STARTUP_DELAY 220 /* ms */ | 17 | #define ADIS16203_STARTUP_DELAY 220 /* ms */ |
| 24 | 18 | ||
| @@ -5,20 +5,14 @@ · 4 unmodified lines | |||
| 5 | * Copyright 2010 Analog Devices Inc. | 5 | * Copyright 2010 Analog Devices Inc. |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include <linux/interrupt.h> | ||
| 9 | #include <linux/irq.h> | ||
| 10 | #include <linux/delay.h> | ||
| 11 | #include <linux/device.h> | 8 | #include <linux/device.h> |
| 12 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 13 | #include <linux/spi/spi.h> | 10 | #include <linux/spi/spi.h> |
| 14 | #include <linux/slab.h> | ||
| 15 | #include <linux/sysfs.h> | 11 | #include <linux/sysfs.h> |
| 16 | #include <linux/list.h> | ||
| 17 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 18 | 13 | ||
| 19 | #include <linux/iio/iio.h> | 14 | #include <linux/iio/iio.h> |
| 20 | #include <linux/iio/sysfs.h> | 15 | #include <linux/iio/sysfs.h> |
| 21 | #include <linux/iio/buffer.h> | ||
| 22 | #include <linux/iio/imu/adis.h> | 16 | #include <linux/iio/imu/adis.h> |
| 23 | 17 | ||
| 24 | #define ADIS16240_STARTUP_DELAY 220 /* ms */ | 18 | #define ADIS16240_STARTUP_DELAY 220 /* ms */ |
| @@ -1348,9 +1348,9 @@ static ssize_t adt7316_show_in_analog_temp_offset(struct device *dev, · 1347 unmodified lines | |||
| 1348 | } | 1348 | } |
| 1349 | 1349 | ||
| 1350 | static ssize_t adt7316_store_in_analog_temp_offset(struct device *dev, | 1350 | static ssize_t adt7316_store_in_analog_temp_offset(struct device *dev, |
| 1351 | struct device_attribute *attr, | 1351 | struct device_attribute *attr, |
| 1352 | const char *buf, | 1352 | const char *buf, |
| 1353 | size_t len) | 1353 | size_t len) |
| 1354 | { | 1354 | { |
| 1355 | struct iio_dev *dev_info = dev_to_iio_dev(dev); | 1355 | struct iio_dev *dev_info = dev_to_iio_dev(dev); |
| 1356 | struct adt7316_chip_info *chip = iio_priv(dev_info); | 1356 | struct adt7316_chip_info *chip = iio_priv(dev_info); |
| @@ -1375,9 +1375,9 @@ static ssize_t adt7316_show_ex_analog_temp_offset(struct device *dev, · 18 unmodified lines | |||
| 1375 | } | 1375 | } |
| 1376 | 1376 | ||
| 1377 | static ssize_t adt7316_store_ex_analog_temp_offset(struct device *dev, | 1377 | static ssize_t adt7316_store_ex_analog_temp_offset(struct device *dev, |
| 1378 | struct device_attribute *attr, | 1378 | struct device_attribute *attr, |
| 1379 | const char *buf, | 1379 | const char *buf, |
| 1380 | size_t len) | 1380 | size_t len) |
| 1381 | { | 1381 | { |
| 1382 | struct iio_dev *dev_info = dev_to_iio_dev(dev); | 1382 | struct iio_dev *dev_info = dev_to_iio_dev(dev); |
| 1383 | struct adt7316_chip_info *chip = iio_priv(dev_info); | 1383 | struct adt7316_chip_info *chip = iio_priv(dev_info); |
| @@ -18,8 +18,6 @@ · 17 unmodified lines | |||
| 18 | #include <linux/iio/iio.h> | 18 | #include <linux/iio/iio.h> |
| 19 | #include <linux/iio/sysfs.h> | 19 | #include <linux/iio/sysfs.h> |
| 20 | 20 | ||
| 21 | #include "ad7746.h" | ||
| 22 | |||
| 23 | /* | 21 | /* |
| 24 | * AD7746 Register Definition | 22 | * AD7746 Register Definition |
| 25 | */ | 23 | */ |
| @@ -84,10 +82,6 @@ · 58 unmodified lines | |||
| 84 | #define AD7746_CAPDAC_DACEN BIT(7) | 82 | #define AD7746_CAPDAC_DACEN BIT(7) |
| 85 | #define AD7746_CAPDAC_DACP(x) ((x) & 0x7F) | 83 | #define AD7746_CAPDAC_DACP(x) ((x) & 0x7F) |
| 86 | 84 | ||
| 87 | /* | ||
| 88 | * struct ad7746_chip_info - chip specific information | ||
| 89 | */ | ||
| 90 | |||
| 91 | struct ad7746_chip_info { | 85 | struct ad7746_chip_info { |
| 92 | struct i2c_client *client; | 86 | struct i2c_client *client; |
| 93 | struct mutex lock; /* protect sensor state */ | 87 | struct mutex lock; /* protect sensor state */ |
| @@ -215,6 +209,19 @@ static const unsigned char ad7746_cap_filter_rate_table[][2] = { · 121 unmodified lines | |||
| 215 | {16, 62 + 1}, {13, 77 + 1}, {11, 92 + 1}, {9, 110 + 1}, | 209 | {16, 62 + 1}, {13, 77 + 1}, {11, 92 + 1}, {9, 110 + 1}, |
| 216 | }; | 210 | }; |
| 217 | 211 | ||
| 212 | static int ad7746_set_capdac(struct ad7746_chip_info *chip, int channel) | ||
| 213 | { | ||
| 214 | int ret = i2c_smbus_write_byte_data(chip->client, | ||
| 215 | AD7746_REG_CAPDACA, | ||
| 216 | chip->capdac[channel][0]); | ||
| 217 | if (ret < 0) | ||
| 218 | return ret; | ||
| 219 | |||
| 220 | return i2c_smbus_write_byte_data(chip->client, | ||
| 221 | AD7746_REG_CAPDACB, | ||
| 222 | chip->capdac[channel][1]); | ||
| 223 | } | ||
| 224 | |||
| 218 | static int ad7746_select_channel(struct iio_dev *indio_dev, | 225 | static int ad7746_select_channel(struct iio_dev *indio_dev, |
| 219 | struct iio_chan_spec const *chan) | 226 | struct iio_chan_spec const *chan) |
| 220 | { | 227 | { |
| @@ -230,17 +237,11 @@ static int ad7746_select_channel(struct iio_dev *indio_dev, · 9 unmodified lines | |||
| 230 | AD7746_CONF_CAPFS_SHIFT; | 237 | AD7746_CONF_CAPFS_SHIFT; |
| 231 | delay = ad7746_cap_filter_rate_table[idx][1]; | 238 | delay = ad7746_cap_filter_rate_table[idx][1]; |
| 232 | 239 | ||
| 240 | ret = ad7746_set_capdac(chip, chan->channel); | ||
| 241 | if (ret < 0) | ||
| 242 | return ret; | ||
| 243 | |||
| 233 | if (chip->capdac_set != chan->channel) { | 244 | if (chip->capdac_set != chan->channel) { |
| 234 | ret = i2c_smbus_write_byte_data(chip->client, | ||
| 235 | AD7746_REG_CAPDACA, | ||
| 236 | chip->capdac[chan->channel][0]); | ||
| 237 | if (ret < 0) | ||
| 238 | return ret; | ||
| 239 | ret = i2c_smbus_write_byte_data(chip->client, | ||
| 240 | AD7746_REG_CAPDACB, | ||
| 241 | chip->capdac[chan->channel][1]); | ||
| 242 | if (ret < 0) | ||
| 243 | return ret; | ||
| 244 | 245 | ||
| 245 | chip->capdac_set = chan->channel; | 246 | chip->capdac_set = chan->channel; |
| 246 | } | 247 | } |
| @@ -484,14 +485,7 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, · 237 unmodified lines | |||
| 484 | chip->capdac[chan->channel][chan->differential] = val > 0 ? | 485 | chip->capdac[chan->channel][chan->differential] = val > 0 ? |
| 485 | AD7746_CAPDAC_DACP(val) | AD7746_CAPDAC_DACEN : 0; | 486 | AD7746_CAPDAC_DACP(val) | AD7746_CAPDAC_DACEN : 0; |
| 486 | 487 | ||
| 487 | ret = i2c_smbus_write_byte_data(chip->client, | 488 | ret = ad7746_set_capdac(chip, chan->channel); |
| 488 | AD7746_REG_CAPDACA, | ||
| 489 | chip->capdac[chan->channel][0]); | ||
| 490 | if (ret < 0) | ||
| 491 | goto out; | ||
| 492 | ret = i2c_smbus_write_byte_data(chip->client, | ||
| 493 | AD7746_REG_CAPDACB, | ||
| 494 | chip->capdac[chan->channel][1]); | ||
| 495 | if (ret < 0) | 489 | if (ret < 0) |
| 496 | goto out; | 490 | goto out; |
| 497 | 491 | ||
| @@ -564,10 +558,10 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, · 66 unmodified lines | |||
| 564 | 558 | ||
| 565 | switch (chan->type) { | 559 | switch (chan->type) { |
| 566 | case IIO_TEMP: | 560 | case IIO_TEMP: |
| 567 | /* | 561 | /* |
| 568 | * temperature in milli degrees Celsius | 562 | * temperature in milli degrees Celsius |
| 569 | * T = ((*val / 2048) - 4096) * 1000 | 563 | * T = ((*val / 2048) - 4096) * 1000 |
| 570 | */ | 564 | */ |
| 571 | *val = (*val * 125) / 256; | 565 | *val = (*val * 125) / 256; |
| 572 | break; | 566 | break; |
| 573 | case IIO_VOLTAGE: | 567 | case IIO_VOLTAGE: |
| @@ -669,18 +663,15 @@ static const struct iio_info ad7746_info = { · 95 unmodified lines | |||
| 669 | .write_raw = ad7746_write_raw, | 663 | .write_raw = ad7746_write_raw, |
| 670 | }; | 664 | }; |
| 671 | 665 | ||
| 672 | /* | ||
| 673 | * device probe and remove | ||
| 674 | */ | ||
| 675 | |||
| 676 | static int ad7746_probe(struct i2c_client *client, | 666 | static int ad7746_probe(struct i2c_client *client, |
| 677 | const struct i2c_device_id *id) | 667 | const struct i2c_device_id *id) |
| 678 | { | 668 | { |
| 679 | struct ad7746_platform_data *pdata = client->dev.platform_data; | 669 | struct device *dev = &client->dev; |
| 680 | struct ad7746_chip_info *chip; | 670 | struct ad7746_chip_info *chip; |
| 681 | struct iio_dev *indio_dev; | 671 | struct iio_dev *indio_dev; |
| 682 | unsigned char regval = 0; | 672 | unsigned char regval = 0; |
| 683 | int ret = 0; | 673 | unsigned int vdd_permille; |
| 674 | int ret; | ||
| 684 | 675 | ||
| 685 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); | 676 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); |
| 686 | if (!indio_dev) | 677 | if (!indio_dev) |
| @@ -702,26 +693,39 @@ static int ad7746_probe(struct i2c_client *client, · 15 unmodified lines | |||
| 702 | indio_dev->num_channels = ARRAY_SIZE(ad7746_channels) - 2; | 693 | indio_dev->num_channels = ARRAY_SIZE(ad7746_channels) - 2; |
| 703 | indio_dev->modes = INDIO_DIRECT_MODE; | 694 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 704 | 695 | ||
| 705 | if (pdata) { | 696 | if (device_property_read_bool(dev, "adi,exca-output-en")) { |
| 706 | if (pdata->exca_en) { | 697 | if (device_property_read_bool(dev, "adi,exca-output-invert")) |
| 707 | if (pdata->exca_inv_en) | 698 | regval |= AD7746_EXCSETUP_NEXCA; |
| 708 | regval |= AD7746_EXCSETUP_NEXCA; | 699 | else |
| 709 | else | 700 | regval |= AD7746_EXCSETUP_EXCA; |
| 710 | regval |= AD7746_EXCSETUP_EXCA; | 701 | } |
| 711 | } | ||
| 712 | 702 | ||
| 713 | if (pdata->excb_en) { | 703 | if (device_property_read_bool(dev, "adi,excb-output-en")) { |
| 714 | if (pdata->excb_inv_en) | 704 | if (device_property_read_bool(dev, "adi,excb-output-invert")) |
| 715 | regval |= AD7746_EXCSETUP_NEXCB; | 705 | regval |= AD7746_EXCSETUP_NEXCB; |
| 716 | else | 706 | else |
| 717 | regval |= AD7746_EXCSETUP_EXCB; | 707 | regval |= AD7746_EXCSETUP_EXCB; |
| 718 | } | 708 | } |
| 719 | 709 | ||
| 720 | regval |= AD7746_EXCSETUP_EXCLVL(pdata->exclvl); | 710 | ret = device_property_read_u32(dev, "adi,excitation-vdd-permille", |
| 721 | } else { | 711 | &vdd_permille); |
| 722 | dev_warn(&client->dev, "No platform data? using default\n"); | 712 | if (!ret) { |
| 723 | regval = AD7746_EXCSETUP_EXCA | AD7746_EXCSETUP_EXCB | | 713 | switch (vdd_permille) { |
| 724 | AD7746_EXCSETUP_EXCLVL(3); | 714 | case 125: |
| 715 | regval |= AD7746_EXCSETUP_EXCLVL(0); | ||
| 716 | break; | ||
| 717 | case 250: | ||
| 718 | regval |= AD7746_EXCSETUP_EXCLVL(1); | ||
| 719 | break; | ||
| 720 | case 375: | ||
| 721 | regval |= AD7746_EXCSETUP_EXCLVL(2); | ||
| 722 | break; | ||
| 723 | case 500: | ||
| 724 | regval |= AD7746_EXCSETUP_EXCLVL(3); | ||
| 725 | break; | ||
| 726 | default: | ||
| 727 | break; | ||
| 728 | } | ||
| 725 | } | 729 | } |
| 726 | 730 | ||
| 727 | ret = i2c_smbus_write_byte_data(chip->client, | 731 | ret = i2c_smbus_write_byte_data(chip->client, |
| @@ -729,11 +733,7 @@ static int ad7746_probe(struct i2c_client *client, · 1 unmodified line | |||
| 729 | if (ret < 0) | 733 | if (ret < 0) |
| 730 | return ret; | 734 | return ret; |
| 731 | 735 | ||
| 732 | ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev); | 736 | return devm_iio_device_register(indio_dev->dev.parent, indio_dev); |
| 733 | if (ret) | ||
| 734 | return ret; | ||
| 735 | |||
| 736 | return 0; | ||
| 737 | } | 737 | } |
| 738 | 738 | ||
| 739 | static const struct i2c_device_id ad7746_id[] = { | 739 | static const struct i2c_device_id ad7746_id[] = { |
| @@ -1,28 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * AD7746 capacitive sensor driver supporting AD7745, AD7746 and AD7747 | ||
| 4 | * | ||
| 5 | * Copyright 2011 Analog Devices Inc. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef IIO_CDC_AD7746_H_ | ||
| 9 | #define IIO_CDC_AD7746_H_ | ||
| 10 | |||
| 11 | /* | ||
| 12 | * TODO: struct ad7746_platform_data needs to go into include/linux/iio | ||
| 13 | */ | ||
| 14 | |||
| 15 | #define AD7466_EXCLVL_0 0 /* +-VDD/8 */ | ||
| 16 | #define AD7466_EXCLVL_1 1 /* +-VDD/4 */ | ||
| 17 | #define AD7466_EXCLVL_2 2 /* +-VDD * 3/8 */ | ||
| 18 | #define AD7466_EXCLVL_3 3 /* +-VDD/2 */ | ||
| 19 | |||
| 20 | struct ad7746_platform_data { | ||
| 21 | unsigned char exclvl; /*Excitation Voltage Level */ | ||
| 22 | bool exca_en; /* enables EXCA pin as the excitation output */ | ||
| 23 | bool exca_inv_en; /* enables /EXCA pin as the excitation output */ | ||
| 24 | bool excb_en; /* enables EXCB pin as the excitation output */ | ||
| 25 | bool excb_inv_en; /* enables /EXCB pin as the excitation output */ | ||
| 26 | }; | ||
| 27 | |||
| 28 | #endif /* IIO_CDC_AD7746_H_ */ | ||
| @@ -58,6 +58,7 @@ · 57 unmodified lines | |||
| 58 | * @spi: spi_device | 58 | * @spi: spi_device |
| 59 | * @mclk: external master clock | 59 | * @mclk: external master clock |
| 60 | * @control: cached control word | 60 | * @control: cached control word |
| 61 | * @devid: device id | ||
| 61 | * @xfer: default spi transfer | 62 | * @xfer: default spi transfer |
| 62 | * @msg: default spi message | 63 | * @msg: default spi message |
| 63 | * @freq_xfer: tuning word spi transfer | 64 | * @freq_xfer: tuning word spi transfer |
| @@ -86,7 +87,7 @@ struct ad9834_state { · 22 unmodified lines | |||
| 86 | __be16 freq_data[2]; | 87 | __be16 freq_data[2]; |
| 87 | }; | 88 | }; |
| 88 | 89 | ||
| 89 | /** | 90 | /* |
| 90 | * ad9834_supported_device_ids: | 91 | * ad9834_supported_device_ids: |
| 91 | */ | 92 | */ |
| 92 | 93 | ||
| @@ -316,7 +317,7 @@ ssize_t ad9834_show_out1_wavetype_available(struct device *dev, · 223 unmodified lines | |||
| 316 | static IIO_DEVICE_ATTR(out_altvoltage0_out1_wavetype_available, 0444, | 317 | static IIO_DEVICE_ATTR(out_altvoltage0_out1_wavetype_available, 0444, |
| 317 | ad9834_show_out1_wavetype_available, NULL, 0); | 318 | ad9834_show_out1_wavetype_available, NULL, 0); |
| 318 | 319 | ||
| 319 | /** | 320 | /* |
| 320 | * see dds.h for further information | 321 | * see dds.h for further information |
| 321 | */ | 322 | */ |
| 322 | 323 | ||
| @@ -1,59 +0,0 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | config KPC2000 | ||
| 4 | bool "Daktronics KPC Device support" | ||
| 5 | select MFD_CORE | ||
| 6 | depends on PCI | ||
| 7 | depends on UIO | ||
| 8 | help | ||
| 9 | Select this if you wish to use the Daktronics KPC PCI devices | ||
| 10 | |||
| 11 | If unsure, say N. | ||
| 12 | |||
| 13 | config KPC2000_CORE | ||
| 14 | tristate "Daktronics KPC PCI UIO device" | ||
| 15 | depends on KPC2000 | ||
| 16 | help | ||
| 17 | Say Y here if you wish to support the Daktronics KPC PCI | ||
| 18 | device in UIO mode. | ||
| 19 | |||
| 20 | To compile this driver as a module, choose M here: the module | ||
| 21 | will be called kpc2000 | ||
| 22 | |||
| 23 | If unsure, say N. | ||
| 24 | |||
| 25 | config KPC2000_SPI | ||
| 26 | tristate "Daktronics KPC SPI device" | ||
| 27 | depends on KPC2000 && SPI | ||
| 28 | help | ||
| 29 | Say Y here if you wish to support the Daktronics KPC PCI | ||
| 30 | device in SPI mode. | ||
| 31 | |||
| 32 | To compile this driver as a module, choose M here: the module | ||
| 33 | will be called kpc2000_spi | ||
| 34 | |||
| 35 | If unsure, say N. | ||
| 36 | |||
| 37 | config KPC2000_I2C | ||
| 38 | tristate "Daktronics KPC I2C device" | ||
| 39 | depends on KPC2000 && I2C | ||
| 40 | help | ||
| 41 | Say Y here if you wish to support the Daktronics KPC PCI | ||
| 42 | device in I2C mode. | ||
| 43 | |||
| 44 | To compile this driver as a module, choose M here: the module | ||
| 45 | will be called kpc2000_i2c | ||
| 46 | |||
| 47 | If unsure, say N. | ||
| 48 | |||
| 49 | config KPC2000_DMA | ||
| 50 | tristate "Daktronics KPC DMA controller" | ||
| 51 | depends on KPC2000 | ||
| 52 | help | ||
| 53 | Say Y here if you wish to support the Daktronics DMA controller. | ||
| 54 | |||
| 55 | To compile this driver as a module, choose M here: the module | ||
| 56 | will be called kpc2000_dma | ||
| 57 | |||
| 58 | If unsure, say N. | ||
| 59 | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | obj-$(CONFIG_KPC2000) += kpc2000/ | ||
| 4 | obj-$(CONFIG_KPC2000_I2C) += kpc2000_i2c.o | ||
| 5 | obj-$(CONFIG_KPC2000_SPI) += kpc2000_spi.o | ||
| 6 | obj-$(CONFIG_KPC2000_DMA) += kpc_dma/ | ||
| @@ -1,2 +0,0 @@ | |||
| 1 | - the kpc_spi driver doesn't seem to let multiple transactions (to different instances of the core) happen in parallel... | ||
| 2 | - The kpc_i2c driver is a hot mess, it should probably be cleaned up a ton. It functions against current hardware though. | ||
| @@ -1,23 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
| 2 | #ifndef KPC_H_ | ||
| 3 | #define KPC_H_ | ||
| 4 | |||
| 5 | /* ***** Driver Names ***** */ | ||
| 6 | #define KP_DRIVER_NAME_KP2000 "kp2000" | ||
| 7 | #define KP_DRIVER_NAME_INVALID "kpc_invalid" | ||
| 8 | #define KP_DRIVER_NAME_DMA_CONTROLLER "kpc_nwl_dma" | ||
| 9 | #define KP_DRIVER_NAME_UIO "uio_pdrv_genirq" | ||
| 10 | #define KP_DRIVER_NAME_I2C "kpc_i2c" | ||
| 11 | #define KP_DRIVER_NAME_SPI "kpc_spi" | ||
| 12 | |||
| 13 | struct kpc_core_device_platdata { | ||
| 14 | u32 card_id; | ||
| 15 | u32 build_version; | ||
| 16 | u32 hardware_revision; | ||
| 17 | u64 ssid; | ||
| 18 | u64 ddna; | ||
| 19 | }; | ||
| 20 | |||
| 21 | #define PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0 0x4b03 | ||
| 22 | |||
| 23 | #endif /* KPC_H_ */ | ||
| @@ -1,4 +0,0 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | obj-m := kpc2000.o | ||
| 4 | kpc2000-objs += core.o cell_probe.o | ||
| @@ -1,548 +0,0 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | #include <linux/module.h> | ||
| 3 | #include <linux/pci.h> | ||
| 4 | #include <linux/types.h> | ||
| 5 | #include <linux/export.h> | ||
| 6 | #include <linux/slab.h> | ||
| 7 | #include <linux/io.h> | ||
| 8 | #include <linux/io-64-nonatomic-lo-hi.h> | ||
| 9 | #include <linux/mfd/core.h> | ||
| 10 | #include <linux/platform_device.h> | ||
| 11 | #include <linux/ioport.h> | ||
| 12 | #include <linux/uio_driver.h> | ||
| 13 | #include "pcie.h" | ||
| 14 | |||
| 15 | /* Core (Resource) Table Layout: | ||
| 16 | * one Resource per record (8 bytes) | ||
| 17 | * 6 5 4 3 2 1 0 | ||
| 18 | * 3210987654321098765432109876543210987654321098765432109876543210 | ||
| 19 | * IIIIIIIIIIII Core Type [up to 4095 types] | ||
| 20 | * D S2C DMA Present | ||
| 21 | * DDD S2C DMA Channel Number [up to 8 channels] | ||
| 22 | * LLLLLLLLLLLLLLLL Register Count (64-bit registers) [up to 65535 registers] | ||
| 23 | * OOOOOOOOOOOOOOOO Core Offset (in 4kB blocks) [up to 65535 cores] | ||
| 24 | * D C2S DMA Present | ||
| 25 | * DDD C2S DMA Channel Number [up to 8 channels] | ||
| 26 | * II IRQ Count [0 to 3 IRQs per core] | ||
| 27 | * 1111111000 | ||
| 28 | * IIIIIII IRQ Base Number [up to 128 IRQs per card] | ||
| 29 | * ___ Spare | ||
| 30 | * | ||
| 31 | */ | ||
| 32 | |||
| 33 | #define KPC_OLD_DMA_CH_NUM(present, channel) \ | ||
| 34 | ((present) ? (0x8 | ((channel) & 0x7)) : 0) | ||
| 35 | #define KPC_OLD_S2C_DMA_CH_NUM(cte) \ | ||
| 36 | KPC_OLD_DMA_CH_NUM(cte.s2c_dma_present, cte.s2c_dma_channel_num) | ||
| 37 | #define KPC_OLD_C2S_DMA_CH_NUM(cte) \ | ||
| 38 | KPC_OLD_DMA_CH_NUM(cte.c2s_dma_present, cte.c2s_dma_channel_num) | ||
| 39 | |||
| 40 | #define KP_CORE_ID_INVALID 0 | ||
| 41 | #define KP_CORE_ID_I2C 3 | ||
| 42 | #define KP_CORE_ID_SPI 5 | ||
| 43 | |||
| 44 | struct core_table_entry { | ||
| 45 | u16 type; | ||
| 46 | u32 offset; | ||
| 47 | u32 length; | ||
| 48 | bool s2c_dma_present; | ||
| 49 | u8 s2c_dma_channel_num; | ||
| 50 | bool c2s_dma_present; | ||
| 51 | u8 c2s_dma_channel_num; | ||
| 52 | u8 irq_count; | ||
| 53 | u8 irq_base_num; | ||
| 54 | }; | ||
| 55 | |||
| 56 | static | ||
| 57 | void parse_core_table_entry_v0(struct core_table_entry *cte, const u64 read_val) | ||
| 58 | { | ||
| 59 | cte->type = ((read_val & 0xFFF0000000000000UL) >> 52); | ||
| 60 | cte->offset = ((read_val & 0x00000000FFFF0000UL) >> 16) * 4096; | ||
| 61 | cte->length = ((read_val & 0x0000FFFF00000000UL) >> 32) * 8; | ||
| 62 | cte->s2c_dma_present = ((read_val & 0x0008000000000000UL) >> 51); | ||
| 63 | cte->s2c_dma_channel_num = ((read_val & 0x0007000000000000UL) >> 48); | ||
| 64 | cte->c2s_dma_present = ((read_val & 0x0000000000008000UL) >> 15); | ||
| 65 | cte->c2s_dma_channel_num = ((read_val & 0x0000000000007000UL) >> 12); | ||
| 66 | cte->irq_count = ((read_val & 0x0000000000000C00UL) >> 10); | ||
| 67 | cte->irq_base_num = ((read_val & 0x00000000000003F8UL) >> 3); | ||
| 68 | } | ||
| 69 | |||
| 70 | static | ||
| 71 | void dbg_cte(struct kp2000_device *pcard, struct core_table_entry *cte) | ||
| 72 | { | ||
| 73 | dev_dbg(&pcard->pdev->dev, | ||
| 74 | "CTE: type:%3d offset:%3d (%3d) length:%3d (%3d) s2c:%d c2s:%d irq_count:%d base_irq:%d\n", | ||
| 75 | cte->type, | ||
| 76 | cte->offset, | ||
| 77 | cte->offset / 4096, | ||
| 78 | cte->length, | ||
| 79 | cte->length / 8, | ||
| 80 | (cte->s2c_dma_present ? cte->s2c_dma_channel_num : -1), | ||
| 81 | (cte->c2s_dma_present ? cte->c2s_dma_channel_num : -1), | ||
| 82 | cte->irq_count, | ||
| 83 | cte->irq_base_num | ||
| 84 | ); | ||
| 85 | } | ||
| 86 | |||
| 87 | static | ||
| 88 | void parse_core_table_entry(struct core_table_entry *cte, const u64 read_val, const u8 entry_rev) | ||
| 89 | { | ||
| 90 | switch (entry_rev) { | ||
| 91 | case 0: | ||
| 92 | parse_core_table_entry_v0(cte, read_val); | ||
| 93 | break; | ||
| 94 | default: | ||
| 95 | cte->type = 0; | ||
| 96 | break; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | static int probe_core_basic(unsigned int core_num, struct kp2000_device *pcard, | ||
| 101 | char *name, const struct core_table_entry cte) | ||
| 102 | { | ||
| 103 | struct mfd_cell cell = { .id = core_num, .name = name }; | ||
| 104 | struct resource resources[2]; | ||
| 105 | |||
| 106 | struct kpc_core_device_platdata core_pdata = { | ||
| 107 | .card_id = pcard->card_id, | ||
| 108 | .build_version = pcard->build_version, | ||
| 109 | .hardware_revision = pcard->hardware_revision, | ||
| 110 | .ssid = pcard->ssid, | ||
| 111 | .ddna = pcard->ddna, | ||
| 112 | }; | ||
| 113 | |||
| 114 | dev_dbg(&pcard->pdev->dev, | ||
| 115 | "Found Basic core: type = %02d dma = %02x / %02x offset = 0x%x length = 0x%x (%d regs)\n", | ||
| 116 | cte.type, | ||
| 117 | KPC_OLD_S2C_DMA_CH_NUM(cte), | ||
| 118 | KPC_OLD_C2S_DMA_CH_NUM(cte), | ||
| 119 | cte.offset, | ||
| 120 | cte.length, | ||
| 121 | cte.length / 8); | ||
| 122 | |||
| 123 | cell.platform_data = &core_pdata; | ||
| 124 | cell.pdata_size = sizeof(struct kpc_core_device_platdata); | ||
| 125 | cell.num_resources = 2; | ||
| 126 | |||
| 127 | memset(&resources, 0, sizeof(resources)); | ||
| 128 | |||
| 129 | resources[0].start = cte.offset; | ||
| 130 | resources[0].end = cte.offset + (cte.length - 1); | ||
| 131 | resources[0].flags = IORESOURCE_MEM; | ||
| 132 | |||
| 133 | resources[1].start = pcard->pdev->irq; | ||
| 134 | resources[1].end = pcard->pdev->irq; | ||
| 135 | resources[1].flags = IORESOURCE_IRQ; | ||
| 136 | |||
| 137 | cell.resources = resources; | ||
| 138 | |||
| 139 | return mfd_add_devices(PCARD_TO_DEV(pcard), // parent | ||
| 140 | pcard->card_num * 100, // id | ||
| 141 | &cell, // struct mfd_cell * | ||
| 142 | 1, // ndevs | ||
| 143 | &pcard->regs_base_resource, | ||
| 144 | 0, // irq_base | ||
| 145 | NULL); // struct irq_domain * | ||
| 146 | } | ||
| 147 | |||
| 148 | struct kpc_uio_device { | ||
| 149 | struct list_head list; | ||
| 150 | struct kp2000_device *pcard; | ||
| 151 | struct device *dev; | ||
| 152 | struct uio_info uioinfo; | ||
| 153 | struct core_table_entry cte; | ||
| 154 | u16 core_num; | ||
| 155 | }; | ||
| 156 | |||
| 157 | static ssize_t offset_show(struct device *dev, struct device_attribute *attr, | ||
| 158 | char *buf) | ||
| 159 | { | ||
| 160 | struct kpc_uio_device *kudev = dev_get_drvdata(dev); | ||
| 161 | |||
| 162 | return sprintf(buf, "%u\n", kudev->cte.offset); | ||
| 163 | } | ||
| 164 | static DEVICE_ATTR_RO(offset); | ||
| 165 | |||
| 166 | static ssize_t size_show(struct device *dev, struct device_attribute *attr, | ||
| 167 | char *buf) | ||
| 168 | { | ||
| 169 | struct kpc_uio_device *kudev = dev_get_drvdata(dev); | ||
| 170 | |||
| 171 | return sprintf(buf, "%u\n", kudev->cte.length); | ||
| 172 | } | ||
| 173 | static DEVICE_ATTR_RO(size); | ||
| 174 | |||
| 175 | static ssize_t type_show(struct device *dev, struct device_attribute *attr, | ||
| 176 | char *buf) | ||
| 177 | { | ||
| 178 | struct kpc_uio_device *kudev = dev_get_drvdata(dev); | ||
| 179 | |||
| 180 | return sprintf(buf, "%u\n", kudev->cte.type); | ||
| 181 | } | ||
| 182 | static DEVICE_ATTR_RO(type); | ||
| 183 | |||
| 184 | static ssize_t s2c_dma_show(struct device *dev, struct device_attribute *attr, | ||
| 185 | char *buf) | ||
| 186 | { | ||
| 187 | struct kpc_uio_device *kudev = dev_get_drvdata(dev); | ||
| 188 | |||
| 189 | if (!kudev->cte.s2c_dma_present) | ||
| 190 | return sprintf(buf, "%s", "not present\n"); | ||
| 191 | |||
| 192 | return sprintf(buf, "%u\n", kudev->cte.s2c_dma_channel_num); | ||
| 193 | } | ||
| 194 | static DEVICE_ATTR_RO(s2c_dma); | ||
| 195 | |||
| 196 | static ssize_t c2s_dma_show(struct device *dev, struct device_attribute *attr, | ||
| 197 | char *buf) | ||
| 198 | { | ||
| 199 | struct kpc_uio_device *kudev = dev_get_drvdata(dev); | ||
| 200 | |||
| 201 | if (!kudev->cte.c2s_dma_present) | ||
| 202 | return sprintf(buf, "%s", "not present\n"); | ||
| 203 | |||
| 204 | return sprintf(buf, "%u\n", kudev->cte.c2s_dma_channel_num); | ||
| 205 | } | ||
| 206 | static DEVICE_ATTR_RO(c2s_dma); | ||
| 207 | |||
| 208 | static ssize_t irq_count_show(struct device *dev, struct device_attribute *attr, | ||
| 209 | char *buf) | ||
| 210 | { | ||
| 211 | struct kpc_uio_device *kudev = dev_get_drvdata(dev); | ||
| 212 | |||
| 213 | return sprintf(buf, "%u\n", kudev->cte.irq_count); | ||
| 214 | } | ||
| 215 | static DEVICE_ATTR_RO(irq_count); | ||
| 216 | |||
| 217 | static ssize_t irq_base_num_show(struct device *dev, | ||
| 218 | struct device_attribute *attr, char *buf) | ||
| 219 | { | ||
| 220 | struct kpc_uio_device *kudev = dev_get_drvdata(dev); | ||
| 221 | |||
| 222 | return sprintf(buf, "%u\n", kudev->cte.irq_base_num); | ||
| 223 | } | ||
| 224 | static DEVICE_ATTR_RO(irq_base_num); | ||
| 225 | |||
| 226 | static ssize_t core_num_show(struct device *dev, struct device_attribute *attr, | ||
| 227 | char *buf) | ||
| 228 | { | ||
| 229 | struct kpc_uio_device *kudev = dev_get_drvdata(dev); | ||
| 230 | |||
| 231 | return sprintf(buf, "%u\n", kudev->core_num); | ||
| 232 | } | ||
| 233 | static DEVICE_ATTR_RO(core_num); | ||
| 234 | |||
| 235 | struct attribute *kpc_uio_class_attrs[] = { | ||
| 236 | &dev_attr_offset.attr, | ||
| 237 | &dev_attr_size.attr, | ||
| 238 | &dev_attr_type.attr, | ||
| 239 | &dev_attr_s2c_dma.attr, | ||
| 240 | &dev_attr_c2s_dma.attr, | ||
| 241 | &dev_attr_irq_count.attr, | ||
| 242 | &dev_attr_irq_base_num.attr, | ||
| 243 | &dev_attr_core_num.attr, | ||
| 244 | NULL, | ||
| 245 | }; | ||
| 246 | |||
| 247 | static | ||
| 248 | int kp2000_check_uio_irq(struct kp2000_device *pcard, u32 irq_num) | ||
| 249 | { | ||
| 250 | u64 interrupt_active = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); | ||
| 251 | u64 interrupt_mask_inv = ~readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); | ||
| 252 | u64 irq_check_mask = BIT_ULL(irq_num); | ||
| 253 | |||
| 254 | if (interrupt_active & irq_check_mask) { // if it's active (interrupt pending) | ||
| 255 | if (interrupt_mask_inv & irq_check_mask) { // and if it's not masked off | ||
| 256 | return 1; | ||
| 257 | } | ||
| 258 | } | ||
| 259 | return 0; | ||
| 260 | } | ||
| 261 | |||
| 262 | static | ||
| 263 | irqreturn_t kuio_handler(int irq, struct uio_info *uioinfo) | ||
| 264 | { | ||
| 265 | struct kpc_uio_device *kudev = uioinfo->priv; | ||
| 266 | |||
| 267 | if (irq != kudev->pcard->pdev->irq) | ||
| 268 | return IRQ_NONE; | ||
| 269 | |||
| 270 | if (kp2000_check_uio_irq(kudev->pcard, kudev->cte.irq_base_num)) { | ||
| 271 | /* Clear the active flag */ | ||
| 272 | writeq(BIT_ULL(kudev->cte.irq_base_num), | ||
| 273 | kudev->pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); | ||
| 274 | return IRQ_HANDLED; | ||
| 275 | } | ||
| 276 | return IRQ_NONE; | ||
| 277 | } | ||
| 278 | |||
| 279 | static | ||
| 280 | int kuio_irqcontrol(struct uio_info *uioinfo, s32 irq_on) | ||
| 281 | { | ||
| 282 | struct kpc_uio_device *kudev = uioinfo->priv; | ||
| 283 | struct kp2000_device *pcard = kudev->pcard; | ||
| 284 | u64 mask; | ||
| 285 | |||
| 286 | mutex_lock(&pcard->sem); | ||
| 287 | mask = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); | ||
| 288 | if (irq_on) | ||
| 289 | mask &= ~(BIT_ULL(kudev->cte.irq_base_num)); | ||
| 290 | else | ||
| 291 | mask |= BIT_ULL(kudev->cte.irq_base_num); | ||
| 292 | writeq(mask, pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); | ||
| 293 | mutex_unlock(&pcard->sem); | ||
| 294 | |||
| 295 | return 0; | ||
| 296 | } | ||
| 297 | |||
| 298 | static int probe_core_uio(unsigned int core_num, struct kp2000_device *pcard, | ||
| 299 | char *name, const struct core_table_entry cte) | ||
| 300 | { | ||
| 301 | struct kpc_uio_device *kudev; | ||
| 302 | int rv; | ||
| 303 | |||
| 304 | dev_dbg(&pcard->pdev->dev, | ||
| 305 | "Found UIO core: type = %02d dma = %02x / %02x offset = 0x%x length = 0x%x (%d regs)\n", | ||
| 306 | cte.type, | ||
| 307 | KPC_OLD_S2C_DMA_CH_NUM(cte), | ||
| 308 | KPC_OLD_C2S_DMA_CH_NUM(cte), | ||
| 309 | cte.offset, | ||
| 310 | cte.length, | ||
| 311 | cte.length / 8); | ||
| 312 | |||
| 313 | kudev = kzalloc(sizeof(*kudev), GFP_KERNEL); | ||
| 314 | if (!kudev) | ||
| 315 | return -ENOMEM; | ||
| 316 | |||
| 317 | INIT_LIST_HEAD(&kudev->list); | ||
| 318 | kudev->pcard = pcard; | ||
| 319 | kudev->cte = cte; | ||
| 320 | kudev->core_num = core_num; | ||
| 321 | |||
| 322 | kudev->uioinfo.priv = kudev; | ||
| 323 | kudev->uioinfo.name = name; | ||
| 324 | kudev->uioinfo.version = "0.0"; | ||
| 325 | if (cte.irq_count > 0) { | ||
| 326 | kudev->uioinfo.irq_flags = IRQF_SHARED; | ||
| 327 | kudev->uioinfo.irq = pcard->pdev->irq; | ||
| 328 | kudev->uioinfo.handler = kuio_handler; | ||
| 329 | kudev->uioinfo.irqcontrol = kuio_irqcontrol; | ||
| 330 | } else { | ||
| 331 | kudev->uioinfo.irq = 0; | ||
| 332 | } | ||
| 333 | |||
| 334 | kudev->uioinfo.mem[0].name = "uiomap"; | ||
| 335 | kudev->uioinfo.mem[0].addr = pci_resource_start(pcard->pdev, REG_BAR) + cte.offset; | ||
| 336 | |||
| 337 | // Round up to nearest PAGE_SIZE boundary | ||
| 338 | kudev->uioinfo.mem[0].size = (cte.length + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); | ||
| 339 | kudev->uioinfo.mem[0].memtype = UIO_MEM_PHYS; | ||
| 340 | |||
| 341 | kudev->dev = device_create(kpc_uio_class, | ||
| 342 | &pcard->pdev->dev, MKDEV(0, 0), kudev, "%s.%d.%d.%d", | ||
| 343 | kudev->uioinfo.name, pcard->card_num, cte.type, kudev->core_num); | ||
| 344 | if (IS_ERR(kudev->dev)) { | ||
| 345 | dev_err(&pcard->pdev->dev, "%s: device_create failed!\n", | ||
| 346 | __func__); | ||
| 347 | kfree(kudev); | ||
| 348 | return -ENODEV; | ||
| 349 | } | ||
| 350 | dev_set_drvdata(kudev->dev, kudev); | ||
| 351 | |||
| 352 | rv = uio_register_device(kudev->dev, &kudev->uioinfo); | ||
| 353 | if (rv) { | ||
| 354 | dev_err(&pcard->pdev->dev, "%s: failed uio_register_device: %d\n", | ||
| 355 | __func__, rv); | ||
| 356 | put_device(kudev->dev); | ||
| 357 | kfree(kudev); | ||
| 358 | return rv; | ||
| 359 | } | ||
| 360 | |||
| 361 | list_add_tail(&kudev->list, &pcard->uio_devices_list); | ||
| 362 | |||
| 363 | return 0; | ||
| 364 | } | ||
| 365 | |||
| 366 | static int create_dma_engine_core(struct kp2000_device *pcard, | ||
| 367 | size_t engine_regs_offset, | ||
| 368 | int engine_num, int irq_num) | ||
| 369 | { | ||
| 370 | struct mfd_cell cell = { .id = engine_num }; | ||
| 371 | struct resource resources[2]; | ||
| 372 | |||
| 373 | cell.platform_data = NULL; | ||
| 374 | cell.pdata_size = 0; | ||
| 375 | cell.name = KP_DRIVER_NAME_DMA_CONTROLLER; | ||
| 376 | cell.num_resources = 2; | ||
| 377 | |||
| 378 | memset(&resources, 0, sizeof(resources)); | ||
| 379 | |||
| 380 | resources[0].start = engine_regs_offset; | ||
| 381 | resources[0].end = engine_regs_offset + (KPC_DMA_ENGINE_SIZE - 1); | ||
| 382 | resources[0].flags = IORESOURCE_MEM; | ||
| 383 | |||
| 384 | resources[1].start = irq_num; | ||
| 385 | resources[1].end = irq_num; | ||
| 386 | resources[1].flags = IORESOURCE_IRQ; | ||
| 387 | |||
| 388 | cell.resources = resources; | ||
| 389 | |||
| 390 | return mfd_add_devices(PCARD_TO_DEV(pcard), // parent | ||
| 391 | pcard->card_num * 100, // id | ||
| 392 | &cell, // struct mfd_cell * | ||
| 393 | 1, // ndevs | ||
| 394 | &pcard->dma_base_resource, | ||
| 395 | 0, // irq_base | ||
| 396 | NULL); // struct irq_domain * | ||
| 397 | } | ||
| 398 | |||
| 399 | static int kp2000_setup_dma_controller(struct kp2000_device *pcard) | ||
| 400 | { | ||
| 401 | int err; | ||
| 402 | unsigned int i; | ||
| 403 | u64 capabilities_reg; | ||
| 404 | |||
| 405 | // S2C Engines | ||
| 406 | for (i = 0 ; i < 32 ; i++) { | ||
| 407 | capabilities_reg = readq(pcard->dma_bar_base + | ||
| 408 | KPC_DMA_S2C_BASE_OFFSET + | ||
| 409 | (KPC_DMA_ENGINE_SIZE * i)); | ||
| 410 | |||
| 411 | if (capabilities_reg & ENGINE_CAP_PRESENT_MASK) { | ||
| 412 | err = create_dma_engine_core(pcard, (KPC_DMA_S2C_BASE_OFFSET + | ||
| 413 | (KPC_DMA_ENGINE_SIZE * i)), | ||
| 414 | i, pcard->pdev->irq); | ||
| 415 | if (err) | ||
| 416 | goto err_out; | ||
| 417 | } | ||
| 418 | } | ||
| 419 | // C2S Engines | ||
| 420 | for (i = 0 ; i < 32 ; i++) { | ||
| 421 | capabilities_reg = readq(pcard->dma_bar_base + | ||
| 422 | KPC_DMA_C2S_BASE_OFFSET + | ||
| 423 | (KPC_DMA_ENGINE_SIZE * i)); | ||
| 424 | |||
| 425 | if (capabilities_reg & ENGINE_CAP_PRESENT_MASK) { | ||
| 426 | err = create_dma_engine_core(pcard, (KPC_DMA_C2S_BASE_OFFSET + | ||
| 427 | (KPC_DMA_ENGINE_SIZE * i)), | ||
| 428 | 32 + i, pcard->pdev->irq); | ||
| 429 | if (err) | ||
| 430 | goto err_out; | ||
| 431 | } | ||
| 432 | } | ||
| 433 | |||
| 434 | return 0; | ||
| 435 | |||
| 436 | err_out: | ||
| 437 | dev_err(&pcard->pdev->dev, "%s: failed to add a DMA Engine: %d\n", | ||
| 438 | __func__, err); | ||
| 439 | return err; | ||
| 440 | } | ||
| 441 | |||
| 442 | int kp2000_probe_cores(struct kp2000_device *pcard) | ||
| 443 | { | ||
| 444 | int err = 0; | ||
| 445 | int i; | ||
| 446 | int current_type_id; | ||
| 447 | u64 read_val; | ||
| 448 | unsigned int highest_core_id = 0; | ||
| 449 | struct core_table_entry cte; | ||
| 450 | |||
| 451 | err = kp2000_setup_dma_controller(pcard); | ||
| 452 | if (err) | ||
| 453 | return err; | ||
| 454 | |||
| 455 | INIT_LIST_HEAD(&pcard->uio_devices_list); | ||
| 456 | |||
| 457 | // First, iterate the core table looking for the highest CORE_ID | ||
| 458 | for (i = 0 ; i < pcard->core_table_length ; i++) { | ||
| 459 | read_val = readq(pcard->sysinfo_regs_base + ((pcard->core_table_offset + i) * 8)); | ||
| 460 | parse_core_table_entry(&cte, read_val, pcard->core_table_rev); | ||
| 461 | dbg_cte(pcard, &cte); | ||
| 462 | if (cte.type > highest_core_id) | ||
| 463 | highest_core_id = cte.type; | ||
| 464 | if (cte.type == KP_CORE_ID_INVALID) | ||
| 465 | dev_info(&pcard->pdev->dev, "Found Invalid core: %016llx\n", read_val); | ||
| 466 | } | ||
| 467 | // Then, iterate over the possible core types. | ||
| 468 | for (current_type_id = 1 ; current_type_id <= highest_core_id ; current_type_id++) { | ||
| 469 | unsigned int core_num = 0; | ||
| 470 | /* | ||
| 471 | * Foreach core type, iterate the whole table and instantiate | ||
| 472 | * subdevices for each core. | ||
| 473 | * Yes, this is O(n*m) but the actual runtime is small enough | ||
| 474 | * that it's an acceptable tradeoff. | ||
| 475 | */ | ||
| 476 | for (i = 0 ; i < pcard->core_table_length ; i++) { | ||
| 477 | read_val = readq(pcard->sysinfo_regs_base + | ||
| 478 | ((pcard->core_table_offset + i) * 8)); | ||
| 479 | parse_core_table_entry(&cte, read_val, pcard->core_table_rev); | ||
| 480 | |||
| 481 | if (cte.type != current_type_id) | ||
| 482 | continue; | ||
| 483 | |||
| 484 | switch (cte.type) { | ||
| 485 | case KP_CORE_ID_I2C: | ||
| 486 | err = probe_core_basic(core_num, pcard, | ||
| 487 | KP_DRIVER_NAME_I2C, cte); | ||
| 488 | break; | ||
| 489 | |||
| 490 | case KP_CORE_ID_SPI: | ||
| 491 | err = probe_core_basic(core_num, pcard, | ||
| 492 | KP_DRIVER_NAME_SPI, cte); | ||
| 493 | break; | ||
| 494 | |||
| 495 | default: | ||
| 496 | err = probe_core_uio(core_num, pcard, "kpc_uio", cte); | ||
| 497 | break; | ||
| 498 | } | ||
| 499 | if (err) { | ||
| 500 | dev_err(&pcard->pdev->dev, | ||
| 501 | "%s: failed to add core %d: %d\n", | ||
| 502 | __func__, i, err); | ||
| 503 | goto error; | ||
| 504 | } | ||
| 505 | core_num++; | ||
| 506 | } | ||
| 507 | } | ||
| 508 | |||
| 509 | // Finally, instantiate a UIO device for the core_table. | ||
| 510 | cte.type = 0; // CORE_ID_BOARD_INFO | ||
| 511 | cte.offset = 0; // board info is always at the beginning | ||
| 512 | cte.length = 512 * 8; | ||
| 513 | cte.s2c_dma_present = false; | ||
| 514 | cte.s2c_dma_channel_num = 0; | ||
| 515 | cte.c2s_dma_present = false; | ||
| 516 | cte.c2s_dma_channel_num = 0; | ||
| 517 | cte.irq_count = 0; | ||
| 518 | cte.irq_base_num = 0; | ||
| 519 | err = probe_core_uio(0, pcard, "kpc_uio", cte); | ||
| 520 | if (err) { | ||
| 521 | dev_err(&pcard->pdev->dev, "%s: failed to add board_info core: %d\n", | ||
| 522 | __func__, err); | ||
| 523 | goto error; | ||
| 524 | } | ||
| 525 | |||
| 526 | return 0; | ||
| 527 | |||
| 528 | error: | ||
| 529 | kp2000_remove_cores(pcard); | ||
| 530 | mfd_remove_devices(PCARD_TO_DEV(pcard)); | ||
| 531 | return err; | ||
| 532 | } | ||
| 533 | |||
| 534 | void kp2000_remove_cores(struct kp2000_device *pcard) | ||
| 535 | { | ||
| 536 | struct list_head *ptr; | ||
| 537 | struct list_head *next; | ||
| 538 | |||
| 539 | list_for_each_safe(ptr, next, &pcard->uio_devices_list) { | ||
| 540 | struct kpc_uio_device *kudev = list_entry(ptr, struct kpc_uio_device, list); | ||
| 541 | |||
| 542 | uio_unregister_device(&kudev->uioinfo); | ||
| 543 | device_unregister(kudev->dev); | ||
| 544 | list_del(&kudev->list); | ||
| 545 | kfree(kudev); | ||
| 546 | } | ||
| 547 | } | ||
| 548 | |||
| @@ -1,565 +0,0 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | ||
| 2 | #include <linux/kernel.h> | ||
| 3 | #include <linux/idr.h> | ||
| 4 | #include <linux/init.h> | ||
| 5 | #include <linux/module.h> | ||
| 6 | #include <linux/pci.h> | ||
| 7 | #include <linux/types.h> | ||
| 8 | #include <linux/export.h> | ||
| 9 | #include <linux/slab.h> | ||
| 10 | #include <linux/fs.h> | ||
| 11 | #include <linux/errno.h> | ||
| 12 | #include <linux/cdev.h> | ||
| 13 | #include <linux/rwsem.h> | ||
| 14 | #include <linux/uaccess.h> | ||
| 15 | #include <linux/io.h> | ||
| 16 | #include <linux/mfd/core.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/ioport.h> | ||
| 19 | #include <linux/io-64-nonatomic-lo-hi.h> | ||
| 20 | #include <linux/interrupt.h> | ||
| 21 | #include <linux/workqueue.h> | ||
| 22 | #include <linux/device.h> | ||
| 23 | #include <linux/sched.h> | ||
| 24 | #include <linux/jiffies.h> | ||
| 25 | #include "pcie.h" | ||
| 26 | #include "uapi.h" | ||
| 27 | |||
| 28 | static DEFINE_IDA(card_num_ida); | ||
| 29 | |||
| 30 | /******************************************************* | ||
| 31 | * SysFS Attributes | ||
| 32 | ******************************************************/ | ||
| 33 | |||
| 34 | static ssize_t ssid_show(struct device *dev, struct device_attribute *attr, | ||
| 35 | char *buf) | ||
| 36 | { | ||
| 37 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 38 | |||
| 39 | return sprintf(buf, "%016llx\n", pcard->ssid); | ||
| 40 | } | ||
| 41 | static DEVICE_ATTR_RO(ssid); | ||
| 42 | |||
| 43 | static ssize_t ddna_show(struct device *dev, struct device_attribute *attr, | ||
| 44 | char *buf) | ||
| 45 | { | ||
| 46 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 47 | |||
| 48 | return sprintf(buf, "%016llx\n", pcard->ddna); | ||
| 49 | } | ||
| 50 | static DEVICE_ATTR_RO(ddna); | ||
| 51 | |||
| 52 | static ssize_t card_id_show(struct device *dev, struct device_attribute *attr, | ||
| 53 | char *buf) | ||
| 54 | { | ||
| 55 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 56 | |||
| 57 | return sprintf(buf, "%08x\n", pcard->card_id); | ||
| 58 | } | ||
| 59 | static DEVICE_ATTR_RO(card_id); | ||
| 60 | |||
| 61 | static ssize_t hw_rev_show(struct device *dev, struct device_attribute *attr, | ||
| 62 | char *buf) | ||
| 63 | { | ||
| 64 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 65 | |||
| 66 | return sprintf(buf, "%08x\n", pcard->hardware_revision); | ||
| 67 | } | ||
| 68 | static DEVICE_ATTR_RO(hw_rev); | ||
| 69 | |||
| 70 | static ssize_t build_show(struct device *dev, struct device_attribute *attr, | ||
| 71 | char *buf) | ||
| 72 | { | ||
| 73 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 74 | |||
| 75 | return sprintf(buf, "%08x\n", pcard->build_version); | ||
| 76 | } | ||
| 77 | static DEVICE_ATTR_RO(build); | ||
| 78 | |||
| 79 | static ssize_t build_date_show(struct device *dev, | ||
| 80 | struct device_attribute *attr, char *buf) | ||
| 81 | { | ||
| 82 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 83 | |||
| 84 | return sprintf(buf, "%08x\n", pcard->build_datestamp); | ||
| 85 | } | ||
| 86 | static DEVICE_ATTR_RO(build_date); | ||
| 87 | |||
| 88 | static ssize_t build_time_show(struct device *dev, | ||
| 89 | struct device_attribute *attr, char *buf) | ||
| 90 | { | ||
| 91 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 92 | |||
| 93 | return sprintf(buf, "%08x\n", pcard->build_timestamp); | ||
| 94 | } | ||
| 95 | static DEVICE_ATTR_RO(build_time); | ||
| 96 | |||
| 97 | static ssize_t cpld_reg_show(struct device *dev, struct device_attribute *attr, | ||
| 98 | char *buf) | ||
| 99 | { | ||
| 100 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 101 | u64 val; | ||
| 102 | |||
| 103 | val = readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG); | ||
| 104 | return sprintf(buf, "%016llx\n", val); | ||
| 105 | } | ||
| 106 | static DEVICE_ATTR_RO(cpld_reg); | ||
| 107 | |||
| 108 | static ssize_t cpld_reconfigure(struct device *dev, | ||
| 109 | struct device_attribute *attr, | ||
| 110 | const char *buf, size_t count) | ||
| 111 | { | ||
| 112 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 113 | unsigned long wr_val; | ||
| 114 | int rv; | ||
| 115 | |||
| 116 | rv = kstrtoul(buf, 0, &wr_val); | ||
| 117 | if (rv < 0) | ||
| 118 | return rv; | ||
| 119 | if (wr_val > 7) | ||
| 120 | return -EINVAL; | ||
| 121 | |||
| 122 | wr_val = wr_val << 8; | ||
| 123 | wr_val |= 0x1; // Set the "Configure Go" bit | ||
| 124 | writeq(wr_val, pcard->sysinfo_regs_base + REG_CPLD_CONFIG); | ||
| 125 | return count; | ||
| 126 | } | ||
| 127 | |||
| 128 | static DEVICE_ATTR(cpld_reconfigure, 0220, NULL, cpld_reconfigure); | ||
| 129 | |||
| 130 | static ssize_t irq_mask_reg_show(struct device *dev, | ||
| 131 | struct device_attribute *attr, char *buf) | ||
| 132 | { | ||
| 133 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 134 | u64 val; | ||
| 135 | |||
| 136 | val = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); | ||
| 137 | return sprintf(buf, "%016llx\n", val); | ||
| 138 | } | ||
| 139 | static DEVICE_ATTR_RO(irq_mask_reg); | ||
| 140 | |||
| 141 | static ssize_t irq_active_reg_show(struct device *dev, | ||
| 142 | struct device_attribute *attr, char *buf) | ||
| 143 | { | ||
| 144 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 145 | u64 val; | ||
| 146 | |||
| 147 | val = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); | ||
| 148 | return sprintf(buf, "%016llx\n", val); | ||
| 149 | } | ||
| 150 | static DEVICE_ATTR_RO(irq_active_reg); | ||
| 151 | |||
| 152 | static ssize_t pcie_error_count_reg_show(struct device *dev, | ||
| 153 | struct device_attribute *attr, | ||
| 154 | char *buf) | ||
| 155 | { | ||
| 156 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 157 | u64 val; | ||
| 158 | |||
| 159 | val = readq(pcard->sysinfo_regs_base + REG_PCIE_ERROR_COUNT); | ||
| 160 | return sprintf(buf, "%016llx\n", val); | ||
| 161 | } | ||
| 162 | static DEVICE_ATTR_RO(pcie_error_count_reg); | ||
| 163 | |||
| 164 | static ssize_t core_table_offset_show(struct device *dev, | ||
| 165 | struct device_attribute *attr, char *buf) | ||
| 166 | { | ||
| 167 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 168 | |||
| 169 | return sprintf(buf, "%08x\n", pcard->core_table_offset); | ||
| 170 | } | ||
| 171 | static DEVICE_ATTR_RO(core_table_offset); | ||
| 172 | |||
| 173 | static ssize_t core_table_length_show(struct device *dev, | ||
| 174 | struct device_attribute *attr, char *buf) | ||
| 175 | { | ||
| 176 | struct kp2000_device *pcard = dev_get_drvdata(dev); | ||
| 177 | |||
| 178 | return sprintf(buf, "%08x\n", pcard->core_table_length); | ||
| 179 | } | ||
| 180 | static DEVICE_ATTR_RO(core_table_length); | ||
| 181 | |||
| 182 | static const struct attribute *kp_attr_list[] = { | ||
| 183 | &dev_attr_ssid.attr, | ||
| 184 | &dev_attr_ddna.attr, | ||
| 185 | &dev_attr_card_id.attr, | ||
| 186 | &dev_attr_hw_rev.attr, | ||
| 187 | &dev_attr_build.attr, | ||
| 188 | &dev_attr_build_date.attr, | ||
| 189 | &dev_attr_build_time.attr, | ||
| 190 | &dev_attr_cpld_reg.attr, | ||
| 191 | &dev_attr_cpld_reconfigure.attr, | ||
| 192 | &dev_attr_irq_mask_reg.attr, | ||
| 193 | &dev_attr_irq_active_reg.attr, | ||
| 194 | &dev_attr_pcie_error_count_reg.attr, | ||
| 195 | &dev_attr_core_table_offset.attr, | ||
| 196 | &dev_attr_core_table_length.attr, | ||
| 197 | NULL, | ||
| 198 | }; | ||
| 199 | |||
| 200 | /******************************************************* | ||
| 201 | * Functions | ||
| 202 | ******************************************************/ | ||
| 203 | |||
| 204 | static void wait_and_read_ssid(struct kp2000_device *pcard) | ||
| 205 | { | ||
| 206 | u64 read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); | ||
| 207 | unsigned long timeout; | ||
| 208 | |||
| 209 | if (read_val & 0x8000000000000000UL) { | ||
| 210 | pcard->ssid = read_val; | ||
| 211 | return; | ||
| 212 | } | ||
| 213 | |||
| 214 | timeout = jiffies + (HZ * 2); | ||
| 215 | do { | ||
| 216 | read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); | ||
| 217 | if (read_val & 0x8000000000000000UL) { | ||
| 218 | pcard->ssid = read_val; | ||
| 219 | return; | ||
| 220 | } | ||
| 221 | cpu_relax(); | ||
| 222 | //schedule(); | ||
| 223 | } while (time_before(jiffies, timeout)); | ||
| 224 | |||
| 225 | dev_notice(&pcard->pdev->dev, "SSID didn't show up!\n"); | ||
| 226 | |||
| 227 | // Timed out waiting for the SSID to show up, stick all zeros in the | ||
| 228 | // value | ||
| 229 | pcard->ssid = 0; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int read_system_regs(struct kp2000_device *pcard) | ||
| 233 | { | ||
| 234 | u64 read_val; | ||
| 235 | |||
| 236 | read_val = readq(pcard->sysinfo_regs_base + REG_MAGIC_NUMBER); | ||
329 more lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 732 lines aren’t shown here.
This diff is large: its 518 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 271 lines aren’t shown here.
This diff is large: its 364 lines aren’t shown here.
This diff is large: its 250 lines aren’t shown here.
This diff is large: its 223 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 154 lines aren’t shown here.
This diff is large: its 613 lines aren’t shown here.
This diff is large: its 28 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 32 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 428 lines aren’t shown here.
This diff is large: its 360 lines aren’t shown here.
This diff is large: its 188 lines aren’t shown here.
This diff is large: its 222 lines aren’t shown here.
This diff is large: its 296 lines aren’t shown here.
This diff is large: its 314 lines aren’t shown here.
This diff is large: its 204 lines aren’t shown here.
This diff is large: its 665 lines aren’t shown here.
This diff is large: its 1476 lines aren’t shown here.
This diff is large: its 272 lines aren’t shown here.
This diff is large: its 747 lines aren’t shown here.
This diff is large: its 117 lines aren’t shown here.
This diff is large: its 145 lines aren’t shown here.
This diff is large: its 252 lines aren’t shown here.
This diff is large: its 570 lines aren’t shown here.
This diff is large: its 316 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 390 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 152 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 192 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 205 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 377 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 28 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 374 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 20 lines aren’t shown here.
This diff is large: its 132 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 18 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 1042 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 308 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 343 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 11 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 10 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 18 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 11 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 12 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 136 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 26 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 76 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 410 lines aren’t shown here.
This diff is large: its 111 lines aren’t shown here.
This diff is large: its 107 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 73 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 247 lines aren’t shown here.
This diff is large: its 664 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 850 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 333 lines aren’t shown here.
This diff is large: its 183 lines aren’t shown here.
This diff is large: its 1995 lines aren’t shown here.
This diff is large: its 1279 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 712 lines aren’t shown here.
This diff is large: its 478 lines aren’t shown here.
This diff is large: its 823 lines aren’t shown here.
This diff is large: its 221 lines aren’t shown here.
This diff is large: its 307 lines aren’t shown here.
This diff is large: its 1480 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 265 lines aren’t shown here.
This diff is large: its 159 lines aren’t shown here.
This diff is large: its 179 lines aren’t shown here.
This diff is large: its 621 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 117 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 135 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 166 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 155 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 140 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 213 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 126 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 28 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 176 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 126 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 137 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 17 lines aren’t shown here.
This diff is large: its 107 lines aren’t shown here.
This diff is large: its 146 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 848 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 2316 lines aren’t shown here.
This diff is large: its 180 lines aren’t shown here.
This diff is large: its 20 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 77 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 22 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 85 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.