Jonathan writes: First set of new device support, features and cleanups for IIO in the 5.4 cycle Note includes a merge from i3c tree to get support needed for stm_lsm6dsx driver support for l3c devices. Done from immutable branch. A counter subsystem patche in here as well. Alongside the new device support (which is always good), Chuhong's work on using devres managed APIs has cleaned up a number of drivers. New device support * adis16460 - New driver based on ADIS framework which needed addition of support for cs_change_delay. Includes device tree binding. * cros_ec - Support fo the veyron-minnie which uses an older interface. * lsm6dsx - Support for LSM6DSTR-C gyro + magnetometer sensor (new IDs mainly) - Support for ISM330DHCX acc + gyro sensor (extensive rework needed!) * Maxim 5432 - New driver support MAX5432-MAX5435 family of potentiometers. * noa1305 - New driver for this ON Semiconductor Ambient light sensor. Features and cleanups * tree wide - Drop error prints after platform_get_irq as already prints errors internally if any occur. * docs - Document mounting matrix. - Fix a missing newline at end of file. * ad2s1210 - Switch to device managed APIs for all of probe and drop explicit remove. * ad7192 - Add of_device_id array to explicity handling DT bindings. * ad7606 - Lots of rework leading to support for software configure modes in ad7616 parts. - Debugfs register access support. * am2315 - Switch to device managed APIs for all of probe and drop explicit remove. * apds9960 - Typo in module description. * cm36651 - Convert to i2c_new_dummy_device. - Swithc to device managed APIs for all of probe adn drop explicit remove. * cros_ec - Calibscale support for accel, gyro and magnetometer. - Tidy up some error codes to return the error from the stack rather than -EIO. - Determine protocol version. - Add a sign vector to the core to fix sensor rotation if necessary. Cannot just be done with mount matrix as already in use in many devices. - Tidy up INFO_SCALE being in both the separate and shared lists. - Drop a lot of dplicate code from the cros-ec-accel-legacy driver and use the core provided code instead. - Make frequency range available to userspace. * counter / ftm-quaddec - Switch to device managed APIs for all of probe adn drop explicit remove. * hdc100x - Switch to device managed APIs for all of probe and drop explicit remove. * hi8435 - Use gpiod_set_value_cansleep as we don't care here and there is a board out there where it needs to sleep. - Switch to device managed APIs for all of probe and drop explict remove. * hp03 - Convert to i2c_new_dummy_device. * maxim thermocouple - Switch to device managed APIs for all of probe and drop explicit remove. * mmc35240 - Fix typo in constant naming. * mpu6050 - Use devm_add_action_or_reset in place of explicit error handling. - Make text in Kconfig more explicit about which parts are supported. * mxc4005 - Switch to device managed APIs for all of probe and drop explicit remove. * pms7003 - Convert device tree bindings to yaml. - Add a MAINTAINERS entry * sc27xx - Introduce a local struct device *dev pointer to avoid lots of deref. - Use devm_add_action_or_reset in place of explicit error handling. * sca3000 - Typo fix in naming. * si1145 - Switch to device managed APIs for all of probe and drop explicit remove. * st_sensors - Lots of rework to enable switch to regmap. - Regmap conversion at the end. - Tidy up some inconsistencies in buffer setup ops. - Tidy up an oddity by dropping get_irq_data_ready function in favour of direct access. - Stop allocating buffer in buffer enable in favour of just embedding a large enough constant size buffer in the iio_priv accessed structure. * st_lsm6dsx - l3c device support (LSM6DSO and LSM6DSR) - tidy up irq return logic which was strangely written. - fix up an ABI quirk where this driver used separate scale attributes, even though they were always shared by type. * stk33xx - Device tree bindings include manufacturer ID. * stm32-adc - Add control for supply to analog switches including DT bindings. * stm32 timer - Drop the quadrature mode support. Believed there were no users so take this opportunity to drop this unwanted ABI. * tsl2772 - Switch to device mangage APIs for all of probe and drop explicit remove. - Use regulator_bulk_* APIs to reduce repitition. * veml6070 - Convert to i2c_new_dummy_device. * tag 'iio-for-5.4a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (84 commits) iio: hi8435: Drop hi8435_remove() by using devres for remaining elements iio: hi8435: Use gpiod_set_value_cansleep() iio:st_sensors: remove buffer allocation at each buffer enable iio: imu: inv_mpu6050: be more explicit on supported chips iio: light: noa1305: Add support for NOA1305 dt-bindings: Add binding document for NOA1305 iio: remove get_irq_data_ready() function pointer and use IRQ number directly iio: imu: st_lsm6dsx: make IIO_CHAN_INFO_SCALE shared by type iio: tsl2772: Use regulator_bulk_() APIs iio: tsl2772: Use devm_iio_device_register iio: tsl2772: Use devm_add_action_or_reset for tsl2772_chip_off iio: tsl2772: Use devm_add_action_or_reset iio: Remove dev_err() usage after platform_get_irq() iio: light: si1145: Use device-managed APIs iio:pressure: preenable/postenable/predisable fixup for ST press buffer iio:magn: preenable/postenable/predisable fixup for ST magn buffer iio:gyro: preenable/postenable/predisable fixup for ST gyro buffer iio:accel: preenable/postenable/predisable fixup for ST accel buffer dt-bindings: iio: imu: st_lsm6dsx: add ism330dhcx device bindings iio: imu: st_lsm6dsx: add support to ISM330DHCX ...
Unified · Split
| @@ -13,4 +13,4 @@ Description: · 12 unmodified lines | ||
| 13 | 13 | error on writing |
| 14 | 14 | If DFSDM input is SPI Slave: |
| 15 | 15 | Reading returns value previously set. |
| 16 | − Writing value before starting conversions. | |
| 16 | + Writing value before starting conversions. | |
| @@ -91,29 +91,6 @@ Description: · 90 unmodified lines | ||
| 91 | 91 | When counting down the counter start from preset value |
| 92 | 92 | and fire event when reach 0. |
| 93 | 93 | |
| 94 | −What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available | |
| 95 | −KernelVersion: 4.12 | |
| 96 | −Contact: benjamin.gaignard@st.com | |
| 97 | −Description: | |
| 98 | − Reading returns the list possible quadrature modes. | |
| 99 | − | |
| 100 | −What: /sys/bus/iio/devices/iio:deviceX/in_count0_quadrature_mode | |
| 101 | −KernelVersion: 4.12 | |
| 102 | −Contact: benjamin.gaignard@st.com | |
| 103 | −Description: | |
| 104 | − Configure the device counter quadrature modes: | |
| 105 | − channel_A: | |
| 106 | − Encoder A input servers as the count input and B as | |
| 107 | − the UP/DOWN direction control input. | |
| 108 | − | |
| 109 | − channel_B: | |
| 110 | − Encoder B input serves as the count input and A as | |
| 111 | − the UP/DOWN direction control input. | |
| 112 | − | |
| 113 | − quadrature: | |
| 114 | − Encoder A and B inputs are mixed to get direction | |
| 115 | − and count with a scale of 0.25. | |
| 116 | − | |
| 117 | 94 | What: /sys/bus/iio/devices/iio:deviceX/in_count_enable_mode_available |
| 118 | 95 | KernelVersion: 4.12 |
| 119 | 96 | Contact: benjamin.gaignard@st.com |
| @@ -47,6 +47,12 @@ Required properties: · 46 unmodified lines | ||
| 47 | 47 | Optional properties: |
| 48 | 48 | - A pinctrl state named "default" for each ADC channel may be defined to set |
| 49 | 49 | inX ADC pins in mode of operation for analog input on external pin. |
| 50 | +- booster-supply: Phandle to the embedded booster regulator that can be used | |
| 51 | + to supply ADC analog input switches on stm32h7 and stm32mp1. | |
| 52 | +- vdd-supply: Phandle to the vdd input voltage. It can be used to supply ADC | |
| 53 | + analog input switches on stm32mp1. | |
| 54 | +- st,syscfg: Phandle to system configuration controller. It can be used to | |
| 55 | + control the analog circuitry on stm32mp1. | |
| 50 | 56 | |
| 51 | 57 | Contents of a stm32 adc child node: |
| 52 | 58 | ----------------------------------- |
| @@ -1,26 +0,0 @@ | ||
| 1 | −* Plantower PMS7003 particulate matter sensor | |
| 2 | − | |
| 3 | −Required properties: | |
| 4 | −- compatible: must one of: | |
| 5 | − "plantower,pms1003" | |
| 6 | − "plantower,pms3003" | |
| 7 | − "plantower,pms5003" | |
| 8 | − "plantower,pms6003" | |
| 9 | − "plantower,pms7003" | |
| 10 | − "plantower,pmsa003" | |
| 11 | −- vcc-supply: phandle to the regulator that provides power to the sensor | |
| 12 | − | |
| 13 | −Optional properties: | |
| 14 | −- plantower,set-gpios: phandle to the GPIO connected to the SET line | |
| 15 | −- reset-gpios: phandle to the GPIO connected to the RESET line | |
| 16 | − | |
| 17 | −Refer to serial/slave-device.txt for generic serial attached device bindings. | |
| 18 | − | |
| 19 | −Example: | |
| 20 | − | |
| 21 | −&uart0 { | |
| 22 | − air-pollution-sensor { | |
| 23 | − compatible = "plantower,pms7003"; | |
| 24 | − vcc-supply = <®_vcc5v0>; | |
| 25 | − }; | |
| 26 | −}; | |
| @@ -0,0 +1,51 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0 | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/iio/chemical/plantower,pms7003.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Plantower PMS7003 air pollution sensor | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Tomasz Duszynski <tduszyns@gmail.com> | |
| 11 | + | |
| 12 | +description: | | |
| 13 | + Air pollution sensor capable of measuring mass concentration of dust | |
| 14 | + particles. | |
| 15 | + | |
| 16 | +properties: | |
| 17 | + compatible: | |
| 18 | + enum: | |
| 19 | + - plantower,pms1003 | |
| 20 | + - plantower,pms3003 | |
| 21 | + - plantower,pms5003 | |
| 22 | + - plantower,pms6003 | |
| 23 | + - plantower,pms7003 | |
| 24 | + - plantower,pmsa003 | |
| 25 | + | |
| 26 | + vcc-supply: | |
| 27 | + description: regulator that provides power to the sensor | |
| 28 | + maxItems: 1 | |
| 29 | + | |
| 30 | + plantower,set-gpios: | |
| 31 | + description: GPIO connected to the SET line | |
| 32 | + maxItems: 1 | |
| 33 | + | |
| 34 | + reset-gpios: | |
| 35 | + description: GPIO connected to the RESET line | |
| 36 | + maxItems: 1 | |
| 37 | + | |
| 38 | +required: | |
| 39 | + - compatible | |
| 40 | + - vcc-supply | |
| 41 | + | |
| 42 | +examples: | |
| 43 | + - | | |
| 44 | + serial { | |
| 45 | + air-pollution-sensor { | |
| 46 | + compatible = "plantower,pms7003"; | |
| 47 | + vcc-supply = <®_vcc5v0>; | |
| 48 | + }; | |
| 49 | + }; | |
| 50 | + | |
| 51 | +... | |
| @@ -0,0 +1,53 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0 | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/iio/imu/adi,adis16460.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Analog Devices ADIS16460 and similar IMUs | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Dragos Bogdan <dragos.bogdan@analog.com> | |
| 11 | + | |
| 12 | +description: | | |
| 13 | + Analog Devices ADIS16460 and similar IMUs | |
| 14 | + https://www.analog.com/media/en/technical-documentation/data-sheets/ADIS16460.pdf | |
| 15 | + | |
| 16 | +properties: | |
| 17 | + compatible: | |
| 18 | + enum: | |
| 19 | + - adi,adis16460 | |
| 20 | + | |
| 21 | + reg: | |
| 22 | + maxItems: 1 | |
| 23 | + | |
| 24 | + spi-cpha: true | |
| 25 | + | |
| 26 | + spi-cpol: true | |
| 27 | + | |
| 28 | + interrupts: | |
| 29 | + maxItems: 1 | |
| 30 | + | |
| 31 | +required: | |
| 32 | + - compatible | |
| 33 | + - reg | |
| 34 | + - interrupts | |
| 35 | + | |
| 36 | +examples: | |
| 37 | + - | | |
| 38 | + #include <dt-bindings/gpio/gpio.h> | |
| 39 | + #include <dt-bindings/interrupt-controller/irq.h> | |
| 40 | + spi0 { | |
| 41 | + #address-cells = <1>; | |
| 42 | + #size-cells = <0>; | |
| 43 | + | |
| 44 | + imu@0 { | |
| 45 | + compatible = "adi,adis16460"; | |
| 46 | + reg = <0>; | |
| 47 | + spi-max-frequency = <5000000>; | |
| 48 | + spi-cpol; | |
| 49 | + spi-cpha; | |
| 50 | + interrupt-parent = <&gpio0>; | |
| 51 | + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; | |
| 52 | + }; | |
| 53 | + }; | |
| @@ -11,6 +11,8 @@ Required properties: · 10 unmodified lines | ||
| 11 | 11 | "st,asm330lhh" |
| 12 | 12 | "st,lsm6dsox" |
| 13 | 13 | "st,lsm6dsr" |
| 14 | + "st,lsm6ds3tr-c" | |
| 15 | + "st,ism330dhcx" | |
| 14 | 16 | - reg: i2c address of the sensor / spi cs line |
| 15 | 17 | |
| 16 | 18 | Optional properties: |
| @@ -0,0 +1,44 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0 | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/iio/light/noa1305.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: ON Semiconductor NOA1305 Ambient Light Sensor | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Martyn Welch <martyn.welch@collabora.com> | |
| 11 | + | |
| 12 | +description: | | |
| 13 | + Ambient sensing with an i2c interface. | |
| 14 | + | |
| 15 | + https://www.onsemi.com/pub/Collateral/NOA1305-D.PDF | |
| 16 | + | |
| 17 | +properties: | |
| 18 | + compatible: | |
| 19 | + enum: | |
| 20 | + - onnn,noa1305 | |
| 21 | + | |
| 22 | + reg: | |
| 23 | + maxItems: 1 | |
| 24 | + | |
| 25 | + vin-supply: | |
| 26 | + description: Regulator that provides power to the sensor | |
| 27 | + | |
| 28 | +required: | |
| 29 | + - compatible | |
| 30 | + - reg | |
| 31 | + | |
| 32 | +examples: | |
| 33 | + - | | |
| 34 | + i2c { | |
| 35 | + | |
| 36 | + #address-cells = <1>; | |
| 37 | + #size-cells = <0>; | |
| 38 | + | |
| 39 | + light@39 { | |
| 40 | + compatible = "onnn,noa1305"; | |
| 41 | + reg = <0x39>; | |
| 42 | + }; | |
| 43 | + }; | |
| 44 | +... | |
| @@ -0,0 +1,49 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/iio/light/stk33xx.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: | | |
| 8 | + Sensortek STK33xx I2C Ambient Light and Proximity sensor | |
| 9 | + | |
| 10 | +maintainers: | |
| 11 | + - Jonathan Cameron <jic23@kernel.org> | |
| 12 | + | |
| 13 | +description: | | |
| 14 | + Ambient light and proximity sensor over an i2c interface. | |
| 15 | + | |
| 16 | +properties: | |
| 17 | + compatible: | |
| 18 | + enum: | |
| 19 | + - sensortek,stk3310 | |
| 20 | + - sensortek,stk3311 | |
| 21 | + - sensortek,stk3335 | |
| 22 | + | |
| 23 | + reg: | |
| 24 | + maxItems: 1 | |
| 25 | + | |
| 26 | + interrupts: | |
| 27 | + maxItems: 1 | |
| 28 | + | |
| 29 | +required: | |
| 30 | + - compatible | |
| 31 | + - reg | |
| 32 | + | |
| 33 | +examples: | |
| 34 | + - | | |
| 35 | + #include <dt-bindings/interrupt-controller/irq.h> | |
| 36 | + | |
| 37 | + i2c { | |
| 38 | + | |
| 39 | + #address-cells = <1>; | |
| 40 | + #size-cells = <0>; | |
| 41 | + | |
| 42 | + stk3310@48 { | |
| 43 | + compatible = "sensortek,stk3310"; | |
| 44 | + reg = <0x48>; | |
| 45 | + interrupt-parent = <&gpio1>; | |
| 46 | + interrupts = <5 IRQ_TYPE_LEVEL_LOW>; | |
| 47 | + }; | |
| 48 | + }; | |
| 49 | +... | |
| @@ -0,0 +1,203 @@ | ||
| 1 | +For discussion. Unclear are: | |
| 2 | +* is the definition of +/- values practical or counterintuitive? | |
| 3 | +* are the definitions unambiguous and easy to follow? | |
| 4 | +* are the examples correct? | |
| 5 | +* should we have HOWTO engineer a correct matrix for a new device (without comparing to a different one)? | |
| 6 | + | |
| 7 | +==== | |
| 8 | + | |
| 9 | + | |
| 10 | +Mounting matrix | |
| 11 | + | |
| 12 | +The mounting matrix is a device tree property used to orient any device | |
| 13 | +that produce three-dimensional data in relation to the world where it is | |
| 14 | +deployed. | |
| 15 | + | |
| 16 | +The purpose of the mounting matrix is to translate the sensor frame of | |
| 17 | +reference into the device frame of reference using a translation matrix as | |
| 18 | +defined in linear algebra. | |
| 19 | + | |
| 20 | +The typical usecase is that where a component has an internal representation | |
| 21 | +of the (x,y,z) triplets, such as different registers to read these coordinates, | |
| 22 | +and thus implying that the component should be mounted in a certain orientation | |
| 23 | +relative to some specific device frame of reference. | |
| 24 | + | |
| 25 | +For example a device with some kind of screen, where the user is supposed to | |
| 26 | +interact with the environment using an accelerometer, gyroscope or magnetometer | |
| 27 | +mounted on the same chassis as this screen, will likely take the screen as | |
| 28 | +reference to (x,y,z) orientation, with (x,y) corresponding to these axes on the | |
| 29 | +screen and (z) being depth, the axis perpendicular to the screen. | |
| 30 | + | |
| 31 | +For a screen you probably want (x) coordinates to go from negative on the left | |
| 32 | +to positive on the right, (y) from negative on the bottom to positive on top | |
| 33 | +and (z) depth to be negative under the screen and positive in front of it, | |
| 34 | +toward the face of the user. | |
| 35 | + | |
| 36 | +A sensor can be mounted in any angle along the axes relative to the frame of | |
| 37 | +reference. This means that the sensor may be flipped upside-down, left-right, | |
| 38 | +or tilted at any angle relative to the frame of reference. | |
| 39 | + | |
| 40 | +Another frame of reference is how the device with its sensor relates to the | |
| 41 | +external world, the environment where the device is deployed. Usually the data | |
| 42 | +from the sensor is used to figure out how the device is oriented with respect | |
| 43 | +to this world. When using the mounting matrix, the sensor and device orientation | |
| 44 | +becomes identical and we can focus on the data as it relates to the surrounding | |
| 45 | +world. | |
| 46 | + | |
| 47 | +Device-to-world examples for some three-dimensional sensor types: | |
| 48 | + | |
| 49 | +- Accelerometers have their world frame of reference toward the center of | |
| 50 | + gravity, usually to the core of the planet. A reading of the (x,y,z) values | |
| 51 | + from the sensor will give a projection of the gravity vector through the | |
| 52 | + device relative to the center of the planet, i.e. relative to its surface at | |
| 53 | + this point. Up and down in the world relative to the device frame of | |
| 54 | + reference can thus be determined. and users would likely expect a value of | |
| 55 | + 9.81 m/s^2 upwards along the (z) axis, i.e. out of the screen when the device | |
| 56 | + is held with its screen flat on the planets surface and 0 on the other axes, | |
| 57 | + as the gravity vector is projected 1:1 onto the sensors (z)-axis. | |
| 58 | + | |
| 59 | + If you tilt the device, the g vector virtually coming out of the display | |
| 60 | + is projected onto the (x,y) plane of the display panel. | |
| 61 | + | |
| 62 | + Example: | |
| 63 | + | |
| 64 | + ^ z: +g ^ z: > 0 | |
| 65 | + ! /! | |
| 66 | + ! x=y=0 / ! x: > 0 | |
| 67 | + +--------+ +--------+ | |
| 68 | + ! ! ! ! | |
| 69 | + +--------+ +--------+ | |
| 70 | + ! / | |
| 71 | + ! / | |
| 72 | + v v | |
| 73 | + center of center of | |
| 74 | + gravity gravity | |
| 75 | + | |
| 76 | + | |
| 77 | + If the device is tilted to the left, you get a positive x value. If you point | |
| 78 | + its top towards surface, you get a negative y axis. | |
| 79 | + | |
| 80 | + (---------) | |
| 81 | + ! ! y: -g | |
| 82 | + ! ! ^ | |
| 83 | + ! ! ! | |
| 84 | + ! ! | |
| 85 | + ! ! x: +g <- z: +g -> x: -g | |
| 86 | + ! 1 2 3 ! | |
| 87 | + ! 4 5 6 ! ! | |
| 88 | + ! 7 8 9 ! v | |
| 89 | + ! * 0 # ! y: +g | |
| 90 | + (---------) | |
| 91 | + | |
| 92 | + | |
| 93 | +- Magnetometers (compasses) have their world frame of reference relative to the | |
| 94 | + geomagnetic field. The system orientation vis-a-vis the world is defined with | |
| 95 | + respect to the local earth geomagnetic reference frame where (y) is in the | |
| 96 | + ground plane and positive towards magnetic North, (x) is in the ground plane, | |
| 97 | + perpendicular to the North axis and positive towards the East and (z) is | |
| 98 | + perpendicular to the ground plane and positive upwards. | |
| 99 | + | |
| 100 | + | |
| 101 | + ^^^ North: y > 0 | |
| 102 | + | |
| 103 | + (---------) | |
| 104 | + ! ! | |
| 105 | + ! ! | |
| 106 | + ! ! | |
| 107 | + ! ! > | |
| 108 | + ! ! > North: x > 0 | |
| 109 | + ! 1 2 3 ! > | |
| 110 | + ! 4 5 6 ! | |
| 111 | + ! 7 8 9 ! | |
| 112 | + ! * 0 # ! | |
| 113 | + (---------) | |
| 114 | + | |
| 115 | + Since the geomagnetic field is not uniform this definition fails if we come | |
| 116 | + closer to the poles. | |
| 117 | + | |
| 118 | + Sensors and driver can not and should not take care of this because there | |
| 119 | + are complex calculations and empirical data to be taken care of. We leave | |
| 120 | + this up to user space. | |
| 121 | + | |
| 122 | + The definition we take: | |
| 123 | + | |
| 124 | + If the device is placed at the equator and the top is pointing north, the | |
| 125 | + display is readable by a person standing upright on the earth surface, this | |
| 126 | + defines a positive y value. | |
| 127 | + | |
| 128 | + | |
| 129 | +- Gyroscopes detects the movement relative the device itself. The angular | |
| 130 | + velocity is defined as orthogonal to the plane of rotation, so if you put the | |
| 131 | + device on a flat surface and spin it around the z axis (such as rotating a | |
| 132 | + device with a screen lying flat on a table), you should get a negative value | |
| 133 | + along the (z) axis if rotated clockwise, and a positive value if rotated | |
| 134 | + counter-clockwise according to the right-hand rule. | |
| 135 | + | |
| 136 | + | |
| 137 | + (---------) y > 0 | |
| 138 | + ! ! v---\ | |
| 139 | + ! ! | |
| 140 | + ! ! | |
| 141 | + ! ! <--\ | |
| 142 | + ! ! ! z > 0 | |
| 143 | + ! 1 2 3 ! --/ | |
| 144 | + ! 4 5 6 ! | |
| 145 | + ! 7 8 9 ! | |
| 146 | + ! * 0 # ! | |
| 147 | + (---------) | |
| 148 | + | |
| 149 | + | |
| 150 | +So unless the sensor is ideally mounted, we need a means to indicate the | |
| 151 | +relative orientation of any given sensor of this type with respect to the | |
| 152 | +frame of reference. | |
| 153 | + | |
| 154 | +To achieve this, use the device tree property "mount-matrix" for the sensor. | |
| 155 | + | |
| 156 | +This supplies a 3x3 rotation matrix in the strict linear algebraic sense, | |
| 157 | +to orient the senor axes relative to a desired point of reference. This means | |
| 158 | +the resulting values from the sensor, after scaling to proper units, should be | |
| 159 | +multiplied by this matrix to give the proper vectors values in three-dimensional | |
| 160 | +space, relative to the device or world point of reference. | |
| 161 | + | |
| 162 | +For more information, consult: | |
| 163 | +https://en.wikipedia.org/wiki/Rotation_matrix | |
| 164 | + | |
| 165 | +The mounting matrix has the layout: | |
| 166 | + | |
| 167 | + (mxx, myx, mzx) | |
| 168 | + (mxy, myy, mzy) | |
| 169 | + (mxz, myz, mzz) | |
| 170 | + | |
| 171 | +Values are intended to be multiplied as: | |
| 172 | + | |
| 173 | + x' = mxx * x + myx * y + mzx * z | |
| 174 | + y' = mxy * x + myy * y + mzy * z | |
| 175 | + z' = mxz * x + myz * y + mzz * z | |
| 176 | + | |
| 177 | +It is represented as an array of strings containing the real values for | |
| 178 | +producing the transformation matrix. | |
| 179 | + | |
| 180 | +Examples: | |
| 181 | + | |
| 182 | +Identity matrix (nothing happens to the coordinates, which means the device was | |
| 183 | +mechanically mounted in an ideal way and we need no transformation): | |
| 184 | + | |
| 185 | +mount-matrix = "1", "0", "0", | |
| 186 | + "0", "1", "0", | |
| 187 | + "0", "0", "1"; | |
| 188 | + | |
| 189 | +The sensor is mounted 30 degrees (Pi/6 radians) tilted along the X axis, so we | |
| 190 | +compensate by performing a -30 degrees rotation around the X axis: | |
| 191 | + | |
| 192 | +mount-matrix = "1", "0", "0", | |
| 193 | + "0", "0.866", "0.5", | |
| 194 | + "0", "-0.5", "0.866"; | |
| 195 | + | |
| 196 | +The sensor is flipped 180 degrees (Pi radians) around the Z axis, i.e. mounted | |
| 197 | +upside-down: | |
| 198 | + | |
| 199 | +mount-matrix = "0.998", "0.054", "0", | |
| 200 | + "-0.054", "0.998", "0", | |
| 201 | + "0", "0", "1"; | |
| 202 | + | |
| 203 | +???: this does not match "180 degrees" - factors indicate ca. 3 degrees compensation | |
| @@ -0,0 +1,44 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0 | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/iio/potentiometer/max5432.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: Maxim Integrated MAX5432-MAX5435 Digital Potentiometers | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Martin Kaiser <martin@kaiser.cx> | |
| 11 | + | |
| 12 | +description: | | |
| 13 | + Maxim Integrated MAX5432-MAX5435 Digital Potentiometers connected via I2C | |
| 14 | + | |
| 15 | + Datasheet: | |
| 16 | + https://datasheets.maximintegrated.com/en/ds/MAX5432-MAX5435.pdf | |
| 17 | + | |
| 18 | +properties: | |
| 19 | + compatible: | |
| 20 | + enum: | |
| 21 | + - maxim,max5432 | |
| 22 | + - maxim,max5433 | |
| 23 | + - maxim,max5434 | |
| 24 | + - maxim,max5435 | |
| 25 | + | |
| 26 | + reg: | |
| 27 | + maxItems: 1 | |
| 28 | + | |
| 29 | +required: | |
| 30 | + - compatible | |
| 31 | + - reg | |
| 32 | + | |
| 33 | +additionalProperties: false | |
| 34 | + | |
| 35 | +examples: | |
| 36 | + - | | |
| 37 | + i2c { | |
| 38 | + #address-cells = <1>; | |
| 39 | + #size-cells = <0>; | |
| 40 | + max5434@28 { | |
| 41 | + compatible = "maxim,max5434"; | |
| 42 | + reg = <0x28>; | |
| 43 | + }; | |
| 44 | + }; | |
| @@ -813,6 +813,8 @@ patternProperties: · 812 unmodified lines | ||
| 813 | 813 | description: Semtech Corporation |
| 814 | 814 | "^sensirion,.*": |
| 815 | 815 | description: Sensirion AG |
| 816 | + "^sensortek,.*": | |
| 817 | + description: Sensortek Technology Corporation | |
| 816 | 818 | "^sff,.*": |
| 817 | 819 | description: Small Form Factor Committee |
| 818 | 820 | "^sgd,.*": |
| @@ -945,6 +945,14 @@ L: linux-iio@vger.kernel.org · 944 unmodified lines | ||
| 945 | 945 | F: include/linux/iio/imu/adis.h |
| 946 | 946 | F: drivers/iio/imu/adis.c |
| 947 | 947 | |
| 948 | +ANALOG DEVICES INC ADIS16460 DRIVER | |
| 949 | +M: Dragos Bogdan <dragos.bogdan@analog.com> | |
| 950 | +S: Supported | |
| 951 | +L: linux-iio@vger.kernel.org | |
| 952 | +W: http://ez.analog.com/community/linux-device-drivers | |
| 953 | +F: drivers/iio/imu/adis16460.c | |
| 954 | +F: Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml | |
| 955 | + | |
| 948 | 956 | ANALOG DEVICES INC ADP5061 DRIVER |
| 949 | 957 | M: Stefan Popa <stefan.popa@analog.com> |
| 950 | 958 | L: linux-pm@vger.kernel.org |
| @@ -12776,6 +12784,12 @@ F: drivers/i2c/busses/i2c-puv3.c · 11825 unmodified lines | ||
| 12776 | 12784 | F: drivers/video/fbdev/fb-puv3.c |
| 12777 | 12785 | F: drivers/rtc/rtc-puv3.c |
| 12778 | 12786 | |
| 12787 | +PLANTOWER PMS7003 AIR POLLUTION SENSOR DRIVER | |
| 12788 | +M: Tomasz Duszynski <tduszyns@gmail.com> | |
| 12789 | +S: Maintained | |
| 12790 | +F: drivers/iio/chemical/pms7003.c | |
| 12791 | +F: Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml | |
| 12792 | + | |
| 12779 | 12793 | PMBUS HARDWARE MONITORING DRIVERS |
| 12780 | 12794 | M: Guenter Roeck <linux@roeck-us.net> |
| 12781 | 12795 | L: linux-hwmon@vger.kernel.org |
| @@ -100,16 +100,18 @@ static void ftm_quaddec_init(struct ftm_quaddec *ftm) · 99 unmodified lines | ||
| 100 | 100 | ftm_set_write_protection(ftm); |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | −static void ftm_quaddec_disable(struct ftm_quaddec *ftm) | |
| 103 | +static void ftm_quaddec_disable(void *ftm) | |
| 104 | 104 | { |
| 105 | − ftm_clear_write_protection(ftm); | |
| 106 | − ftm_write(ftm, FTM_MODE, 0); | |
| 107 | − ftm_write(ftm, FTM_QDCTRL, 0); | |
| 105 | + struct ftm_quaddec *ftm_qua = ftm; | |
| 106 | + | |
| 107 | + ftm_clear_write_protection(ftm_qua); | |
| 108 | + ftm_write(ftm_qua, FTM_MODE, 0); | |
| 109 | + ftm_write(ftm_qua, FTM_QDCTRL, 0); | |
| 108 | 110 | /* |
| 109 | 111 | * This is enough to disable the counter. No clock has been |
| 110 | 112 | * selected by writing to FTM_SC in init() |
| 111 | 113 | */ |
| 112 | − ftm_set_write_protection(ftm); | |
| 114 | + ftm_set_write_protection(ftm_qua); | |
| 113 | 115 | } |
| 114 | 116 | |
| 115 | 117 | static int ftm_quaddec_get_prescaler(struct counter_device *counter, |
| @@ -317,20 +319,13 @@ static int ftm_quaddec_probe(struct platform_device *pdev) · 201 unmodified lines | ||
| 317 | 319 | |
| 318 | 320 | ftm_quaddec_init(ftm); |
| 319 | 321 | |
| 320 | − ret = counter_register(&ftm->counter); | |
| 322 | + ret = devm_add_action_or_reset(&pdev->dev, ftm_quaddec_disable, ftm); | |
| 321 | 323 | if (ret) |
| 322 | − ftm_quaddec_disable(ftm); | |
| 323 | − | |
| 324 | − return ret; | |
| 325 | −} | |
| 324 | + return ret; | |
| 326 | 325 | |
| 327 | −static int ftm_quaddec_remove(struct platform_device *pdev) | |
| 328 | −{ | |
| 329 | − struct ftm_quaddec *ftm = platform_get_drvdata(pdev); | |
| 330 | − | |
| 331 | − counter_unregister(&ftm->counter); | |
| 332 | − | |
| 333 | − ftm_quaddec_disable(ftm); | |
| 326 | + ret = devm_counter_register(&pdev->dev, &ftm->counter); | |
| 327 | + if (ret) | |
| 328 | + return ret; | |
| 334 | 329 | |
| 335 | 330 | return 0; |
| 336 | 331 | } |
| @@ -346,7 +341,6 @@ static struct platform_driver ftm_quaddec_driver = { · 9 unmodified lines | ||
| 346 | 341 | .of_match_table = ftm_quaddec_match, |
| 347 | 342 | }, |
| 348 | 343 | .probe = ftm_quaddec_probe, |
| 349 | − .remove = ftm_quaddec_remove, | |
| 350 | 344 | }; |
| 351 | 345 | |
| 352 | 346 | module_platform_driver(ftm_quaddec_driver); |
| @@ -200,6 +200,59 @@ struct i3c_device *dev_to_i3cdev(struct device *dev) · 199 unmodified lines | ||
| 200 | 200 | } |
| 201 | 201 | EXPORT_SYMBOL_GPL(dev_to_i3cdev); |
| 202 | 202 | |
| 203 | +/** | |
| 204 | + * i3c_device_match_id() - Returns the i3c_device_id entry matching @i3cdev | |
| 205 | + * @i3cdev: I3C device | |
| 206 | + * @id_table: I3C device match table | |
| 207 | + * | |
| 208 | + * Return: a pointer to an i3c_device_id object or NULL if there's no match. | |
| 209 | + */ | |
| 210 | +const struct i3c_device_id * | |
| 211 | +i3c_device_match_id(struct i3c_device *i3cdev, | |
| 212 | + const struct i3c_device_id *id_table) | |
| 213 | +{ | |
| 214 | + struct i3c_device_info devinfo; | |
| 215 | + const struct i3c_device_id *id; | |
| 216 | + | |
| 217 | + i3c_device_get_info(i3cdev, &devinfo); | |
| 218 | + | |
| 219 | + /* | |
| 220 | + * The lower 32bits of the provisional ID is just filled with a random | |
| 221 | + * value, try to match using DCR info. | |
| 222 | + */ | |
| 223 | + if (!I3C_PID_RND_LOWER_32BITS(devinfo.pid)) { | |
| 224 | + u16 manuf = I3C_PID_MANUF_ID(devinfo.pid); | |
| 225 | + u16 part = I3C_PID_PART_ID(devinfo.pid); | |
| 226 | + u16 ext_info = I3C_PID_EXTRA_INFO(devinfo.pid); | |
| 227 | + | |
| 228 | + /* First try to match by manufacturer/part ID. */ | |
| 229 | + for (id = id_table; id->match_flags != 0; id++) { | |
| 230 | + if ((id->match_flags & I3C_MATCH_MANUF_AND_PART) != | |
| 231 | + I3C_MATCH_MANUF_AND_PART) | |
| 232 | + continue; | |
| 233 | + | |
| 234 | + if (manuf != id->manuf_id || part != id->part_id) | |
| 235 | + continue; | |
| 236 | + | |
| 237 | + if ((id->match_flags & I3C_MATCH_EXTRA_INFO) && | |
| 238 | + ext_info != id->extra_info) | |
| 239 | + continue; | |
| 240 | + | |
| 241 | + return id; | |
| 242 | + } | |
| 243 | + } | |
| 244 | + | |
| 245 | + /* Fallback to DCR match. */ | |
| 246 | + for (id = id_table; id->match_flags != 0; id++) { | |
| 247 | + if ((id->match_flags & I3C_MATCH_DCR) && | |
| 248 | + id->dcr == devinfo.dcr) | |
| 249 | + return id; | |
| 250 | + } | |
| 251 | + | |
| 252 | + return NULL; | |
| 253 | +} | |
| 254 | +EXPORT_SYMBOL_GPL(i3c_device_match_id); | |
| 255 | + | |
| 203 | 256 | /** |
| 204 | 257 | * i3c_driver_register_with_owner() - register an I3C device driver |
| 205 | 258 | * |
| @@ -276,51 +276,6 @@ static const struct device_type i3c_device_type = { · 275 unmodified lines | ||
| 276 | 276 | .uevent = i3c_device_uevent, |
| 277 | 277 | }; |
| 278 | 278 | |
| 279 | −static const struct i3c_device_id * | |
| 280 | −i3c_device_match_id(struct i3c_device *i3cdev, | |
| 281 | − const struct i3c_device_id *id_table) | |
| 282 | −{ | |
| 283 | − struct i3c_device_info devinfo; | |
| 284 | − const struct i3c_device_id *id; | |
| 285 | − | |
| 286 | − i3c_device_get_info(i3cdev, &devinfo); | |
| 287 | − | |
| 288 | − /* | |
| 289 | − * The lower 32bits of the provisional ID is just filled with a random | |
| 290 | − * value, try to match using DCR info. | |
| 291 | − */ | |
| 292 | − if (!I3C_PID_RND_LOWER_32BITS(devinfo.pid)) { | |
| 293 | − u16 manuf = I3C_PID_MANUF_ID(devinfo.pid); | |
| 294 | − u16 part = I3C_PID_PART_ID(devinfo.pid); | |
| 295 | − u16 ext_info = I3C_PID_EXTRA_INFO(devinfo.pid); | |
| 296 | − | |
| 297 | − /* First try to match by manufacturer/part ID. */ | |
| 298 | − for (id = id_table; id->match_flags != 0; id++) { | |
| 299 | − if ((id->match_flags & I3C_MATCH_MANUF_AND_PART) != | |
| 300 | − I3C_MATCH_MANUF_AND_PART) | |
| 301 | − continue; | |
| 302 | − | |
| 303 | − if (manuf != id->manuf_id || part != id->part_id) | |
| 304 | − continue; | |
| 305 | − | |
| 306 | − if ((id->match_flags & I3C_MATCH_EXTRA_INFO) && | |
| 307 | − ext_info != id->extra_info) | |
| 308 | − continue; | |
| 309 | − | |
| 310 | − return id; | |
| 311 | − } | |
| 312 | − } | |
| 313 | − | |
| 314 | − /* Fallback to DCR match. */ | |
| 315 | − for (id = id_table; id->match_flags != 0; id++) { | |
| 316 | − if ((id->match_flags & I3C_MATCH_DCR) && | |
| 317 | − id->dcr == devinfo.dcr) | |
| 318 | − return id; | |
| 319 | − } | |
| 320 | − | |
| 321 | − return NULL; | |
| 322 | −} | |
| 323 | − | |
| 324 | 279 | static int i3c_device_match(struct device *dev, struct device_driver *drv) |
| 325 | 280 | { |
| 326 | 281 | struct i3c_device *i3cdev; |
| @@ -202,9 +202,7 @@ config HID_SENSOR_ACCEL_3D · 201 unmodified lines | ||
| 202 | 202 | |
| 203 | 203 | config IIO_CROS_EC_ACCEL_LEGACY |
| 204 | 204 | tristate "ChromeOS EC Legacy Accelerometer Sensor" |
| 205 | − select IIO_BUFFER | |
| 206 | − select IIO_TRIGGERED_BUFFER | |
| 207 | − select CROS_EC_LPC_REGISTER_DEVICE | |
| 205 | + depends on IIO_CROS_EC_SENSORS_CORE | |
| 208 | 206 | help |
| 209 | 207 | Say yes here to get support for accelerometers on Chromebook using |
| 210 | 208 | legacy EC firmware. |
| @@ -5,13 +5,14 @@ · 4 unmodified lines | ||
| 5 | 5 | * Copyright 2017 Google, Inc |
| 6 | 6 | * |
| 7 | 7 | * This driver uses the memory mapper cros-ec interface to communicate |
| 8 | − * with the Chrome OS EC about accelerometer data. | |
| 8 | + * with the Chrome OS EC about accelerometer data or older commands. | |
| 9 | 9 | * Accelerometer access is presented through iio sysfs. |
| 10 | 10 | */ |
| 11 | 11 | |
| 12 | 12 | #include <linux/delay.h> |
| 13 | 13 | #include <linux/device.h> |
| 14 | 14 | #include <linux/iio/buffer.h> |
| 15 | +#include <linux/iio/common/cros_ec_sensors_core.h> | |
| 15 | 16 | #include <linux/iio/iio.h> |
| 16 | 17 | #include <linux/iio/kfifo_buf.h> |
| 17 | 18 | #include <linux/iio/trigger_consumer.h> |
| @@ -25,160 +26,41 @@ · 7 unmodified lines | ||
| 25 | 26 | |
| 26 | 27 | #define DRV_NAME "cros-ec-accel-legacy" |
| 27 | 28 | |
| 29 | +#define CROS_EC_SENSOR_LEGACY_NUM 2 | |
| 28 | 30 | /* |
| 29 | 31 | * Sensor scale hard coded at 10 bits per g, computed as: |
| 30 | 32 | * g / (2^10 - 1) = 0.009586168; with g = 9.80665 m.s^-2 |
| 31 | 33 | */ |
| 32 | 34 | #define ACCEL_LEGACY_NSCALE 9586168 |
| 33 | 35 | |
| 34 | −/* Indices for EC sensor values. */ | |
| 35 | −enum { | |
| 36 | − X, | |
| 37 | − Y, | |
| 38 | − Z, | |
| 39 | − MAX_AXIS, | |
| 40 | −}; | |
| 41 | − | |
| 42 | −/* State data for cros_ec_accel_legacy iio driver. */ | |
| 43 | −struct cros_ec_accel_legacy_state { | |
| 44 | − struct cros_ec_device *ec; | |
| 45 | − | |
| 46 | − /* | |
| 47 | − * Array holding data from a single capture. 2 bytes per channel | |
| 48 | − * for the 3 channels plus the timestamp which is always last and | |
| 49 | − * 8-bytes aligned. | |
| 50 | − */ | |
| 51 | − s16 capture_data[8]; | |
| 52 | − s8 sign[MAX_AXIS]; | |
| 53 | − u8 sensor_num; | |
| 54 | −}; | |
| 55 | − | |
| 56 | −static int ec_cmd_read_u8(struct cros_ec_device *ec, unsigned int offset, | |
| 57 | − u8 *dest) | |
| 58 | −{ | |
| 59 | − return ec->cmd_readmem(ec, offset, 1, dest); | |
| 60 | −} | |
| 61 | − | |
| 62 | −static int ec_cmd_read_u16(struct cros_ec_device *ec, unsigned int offset, | |
| 63 | − u16 *dest) | |
| 64 | −{ | |
| 65 | − __le16 tmp; | |
| 66 | − int ret = ec->cmd_readmem(ec, offset, 2, &tmp); | |
| 67 | − | |
| 68 | − *dest = le16_to_cpu(tmp); | |
| 69 | − | |
| 70 | − return ret; | |
| 71 | −} | |
| 72 | − | |
| 73 | −/** | |
| 74 | − * read_ec_until_not_busy() - Read from EC status byte until it reads not busy. | |
| 75 | − * @st: Pointer to state information for device. | |
| 76 | − * | |
| 77 | − * This function reads EC status until its busy bit gets cleared. It does not | |
| 78 | − * wait indefinitely and returns -EIO if the EC status is still busy after a | |
| 79 | − * few hundreds milliseconds. | |
| 80 | − * | |
| 81 | − * Return: 8-bit status if ok, -EIO on error | |
| 82 | − */ | |
| 83 | −static int read_ec_until_not_busy(struct cros_ec_accel_legacy_state *st) | |
| 84 | −{ | |
| 85 | − struct cros_ec_device *ec = st->ec; | |
| 86 | − u8 status; | |
| 87 | − int attempts = 0; | |
| 88 | − | |
| 89 | − ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status); | |
| 90 | − while (status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) { | |
| 91 | − /* Give up after enough attempts, return error. */ | |
| 92 | − if (attempts++ >= 50) | |
| 93 | − return -EIO; | |
| 94 | − | |
| 95 | − /* Small delay every so often. */ | |
| 96 | − if (attempts % 5 == 0) | |
| 97 | − msleep(25); | |
| 98 | − | |
| 99 | − ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status); | |
| 100 | − } | |
| 101 | − | |
| 102 | − return status; | |
| 103 | −} | |
| 104 | − | |
| 105 | −/** | |
| 106 | − * read_ec_accel_data_unsafe() - Read acceleration data from EC shared memory. | |
| 107 | − * @st: Pointer to state information for device. | |
| 108 | − * @scan_mask: Bitmap of the sensor indices to scan. | |
| 109 | − * @data: Location to store data. | |
| 110 | − * | |
| 111 | − * This is the unsafe function for reading the EC data. It does not guarantee | |
| 112 | − * that the EC will not modify the data as it is being read in. | |
| 113 | − */ | |
| 114 | −static void read_ec_accel_data_unsafe(struct cros_ec_accel_legacy_state *st, | |
| 115 | − unsigned long scan_mask, s16 *data) | |
| 116 | −{ | |
| 117 | − int i = 0; | |
| 118 | − int num_enabled = bitmap_weight(&scan_mask, MAX_AXIS); | |
| 119 | − | |
| 120 | − /* Read all sensors enabled in scan_mask. Each value is 2 bytes. */ | |
| 121 | − while (num_enabled--) { | |
| 122 | − i = find_next_bit(&scan_mask, MAX_AXIS, i); | |
| 123 | − ec_cmd_read_u16(st->ec, | |
| 124 | − EC_MEMMAP_ACC_DATA + | |
| 125 | − sizeof(s16) * | |
| 126 | − (1 + i + st->sensor_num * MAX_AXIS), | |
| 127 | − data); | |
| 128 | − *data *= st->sign[i]; | |
| 129 | − i++; | |
| 130 | − data++; | |
| 131 | − } | |
| 132 | −} | |
| 133 | − | |
| 134 | −/** | |
| 135 | − * read_ec_accel_data() - Read acceleration data from EC shared memory. | |
| 136 | − * @st: Pointer to state information for device. | |
| 137 | − * @scan_mask: Bitmap of the sensor indices to scan. | |
| 138 | − * @data: Location to store data. | |
| 139 | − * | |
| 140 | − * This is the safe function for reading the EC data. It guarantees that | |
| 141 | − * the data sampled was not modified by the EC while being read. | |
| 142 | − * | |
| 143 | − * Return: 0 if ok, -ve on error | |
| 144 | − */ | |
| 145 | −static int read_ec_accel_data(struct cros_ec_accel_legacy_state *st, | |
| 146 | − unsigned long scan_mask, s16 *data) | |
| 36 | +static int cros_ec_accel_legacy_read_cmd(struct iio_dev *indio_dev, | |
| 37 | + unsigned long scan_mask, s16 *data) | |
| 147 | 38 | { |
| 148 | − u8 samp_id = 0xff; | |
| 149 | − u8 status = 0; | |
| 39 | + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); | |
| 150 | 40 | int ret; |
| 151 | − int attempts = 0; | |
| 41 | + unsigned int i; | |
| 42 | + u8 sensor_num; | |
| 152 | 43 | |
| 153 | 44 | /* |
| 154 | − * Continually read all data from EC until the status byte after | |
| 155 | − * all reads reflects that the EC is not busy and the sample id | |
| 156 | − * matches the sample id from before all reads. This guarantees | |
| 157 | − * that data read in was not modified by the EC while reading. | |
| 45 | + * Read all sensor data through a command. | |
| 46 | + * Save sensor_num, it is assumed to stay. | |
| 158 | 47 | */ |
| 159 | − while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT | | |
| 160 | − EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) { | |
| 161 | − /* If we have tried to read too many times, return error. */ | |
| 162 | − if (attempts++ >= 5) | |
| 163 | − return -EIO; | |
| 164 | − | |
| 165 | − /* Read status byte until EC is not busy. */ | |
| 166 | − ret = read_ec_until_not_busy(st); | |
| 167 | − if (ret < 0) | |
| 168 | − return ret; | |
| 169 | − status = ret; | |
| 170 | − | |
| 171 | − /* | |
| 172 | − * Store the current sample id so that we can compare to the | |
| 173 | − * sample id after reading the data. | |
| 174 | − */ | |
| 175 | − samp_id = status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK; | |
| 176 | − | |
| 177 | − /* Read all EC data, format it, and store it into data. */ | |
| 178 | − read_ec_accel_data_unsafe(st, scan_mask, data); | |
| 48 | + sensor_num = st->param.info.sensor_num; | |
| 49 | + st->param.cmd = MOTIONSENSE_CMD_DUMP; | |
| 50 | + st->param.dump.max_sensor_count = CROS_EC_SENSOR_LEGACY_NUM; | |
| 51 | + ret = cros_ec_motion_send_host_cmd(st, | |
| 52 | + sizeof(st->resp->dump) + CROS_EC_SENSOR_LEGACY_NUM * | |
| 53 | + sizeof(struct ec_response_motion_sensor_data)); | |
| 54 | + st->param.info.sensor_num = sensor_num; | |
| 55 | + if (ret != 0) { | |
| 56 | + dev_warn(&indio_dev->dev, "Unable to read sensor data\n"); | |
| 57 | + return ret; | |
| 58 | + } | |
| 179 | 59 | |
| 180 | − /* Read status byte. */ | |
| 181 | − ec_cmd_read_u8(st->ec, EC_MEMMAP_ACC_STATUS, &status); | |
| 60 | + for_each_set_bit(i, &scan_mask, indio_dev->masklength) { | |
| 61 | + *data = st->resp->dump.sensor[sensor_num].data[i] * | |
| 62 | + st->sign[i]; | |
| 63 | + data++; | |
| 182 | 64 | } |
| 183 | 65 | |
| 184 | 66 | return 0; |
| @@ -188,28 +70,40 @@ static int cros_ec_accel_legacy_read(struct iio_dev *indio_dev, · 3 unmodified lines | ||
| 188 | 70 | struct iio_chan_spec const *chan, |
| 189 | 71 | int *val, int *val2, long mask) |
| 190 | 72 | { |
| 191 | − struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev); | |
| 73 | + struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); | |
| 192 | 74 | s16 data = 0; |
| 193 | − int ret = IIO_VAL_INT; | |
| 75 | + int ret; | |
| 76 | + int idx = chan->scan_index; | |
| 77 | + | |
| 78 | + mutex_lock(&st->cmd_lock); | |
| 194 | 79 | |
| 195 | 80 | switch (mask) { |
| 196 | 81 | case IIO_CHAN_INFO_RAW: |
| 197 | − ret = read_ec_accel_data(st, (1 << chan->scan_index), &data); | |
| 198 | − if (ret) | |
| 199 | − return ret; | |
| 82 | + ret = st->read_ec_sensors_data(indio_dev, 1 << idx, &data); | |
| 83 | + if (ret < 0) | |
| 84 | + break; | |
| 85 | + ret = IIO_VAL_INT; | |
| 200 | 86 | *val = data; |
| 201 | − return IIO_VAL_INT; | |
| 87 | + break; | |
| 202 | 88 | case IIO_CHAN_INFO_SCALE: |
| 89 | + WARN_ON(st->type != MOTIONSENSE_TYPE_ACCEL); | |
| 203 | 90 | *val = 0; |
| 204 | 91 | *val2 = ACCEL_LEGACY_NSCALE; |
| 205 | − return IIO_VAL_INT_PLUS_NANO; | |
| 92 | + ret = IIO_VAL_INT_PLUS_NANO; | |
| 93 | + break; | |
| 206 | 94 | case IIO_CHAN_INFO_CALIBBIAS: |
| 207 | 95 | /* Calibration not supported. */ |
| 208 | 96 | *val = 0; |
| 209 | − return IIO_VAL_INT; | |
| 97 | + ret = IIO_VAL_INT; | |
| 98 | + break; | |
| 210 | 99 | default: |
| 211 | − return -EINVAL; | |
| 100 | + ret = cros_ec_sensors_core_read(st, chan, val, val2, | |
| 101 | + mask); | |
| 102 | + break; | |
| 212 | 103 | } |
| 104 | + mutex_unlock(&st->cmd_lock); | |
| 105 | + | |
| 106 | + return ret; | |
| 213 | 107 | } |
| 214 | 108 | |
| 215 | 109 | static int cros_ec_accel_legacy_write(struct iio_dev *indio_dev, |
| @@ -231,86 +125,14 @@ static const struct iio_info cros_ec_accel_legacy_info = { · 15 unmodified lines | ||
| 231 | 125 | .write_raw = &cros_ec_accel_legacy_write, |
| 232 | 126 | }; |
| 233 | 127 | |
| 234 | −/** | |
| 235 | − * cros_ec_accel_legacy_capture() - The trigger handler function | |
| 236 | − * @irq: The interrupt number. | |
| 237 | − * @p: Private data - always a pointer to the poll func. | |
| 238 | − * | |
| 239 | − * On a trigger event occurring, if the pollfunc is attached then this | |
| 240 | − * handler is called as a threaded interrupt (and hence may sleep). It | |
| 241 | − * is responsible for grabbing data from the device and pushing it into | |
| 242 | − * the associated buffer. | |
| 243 | − * | |
| 244 | − * Return: IRQ_HANDLED | |
| 128 | +/* | |
| 129 | + * Present the channel using HTML5 standard: | |
| 130 | + * need to invert X and Y and invert some lid axis. | |
| 245 | 131 | */ |
| 246 | −static irqreturn_t cros_ec_accel_legacy_capture(int irq, void *p) | |
| 247 | −{ | |
| 248 | − struct iio_poll_func *pf = p; | |
| 249 | − struct iio_dev *indio_dev = pf->indio_dev; | |
| 250 | − struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev); | |
| 251 | − | |
| 252 | − /* Clear capture data. */ | |
| 253 | − memset(st->capture_data, 0, sizeof(st->capture_data)); | |
| 254 | − | |
| 255 | − /* | |
| 256 | − * Read data based on which channels are enabled in scan mask. Note | |
| 257 | − * that on a capture we are always reading the calibrated data. | |
| 258 | − */ | |
| 259 | − read_ec_accel_data(st, *indio_dev->active_scan_mask, st->capture_data); | |
| 260 | − | |
| 261 | − iio_push_to_buffers_with_timestamp(indio_dev, (void *)st->capture_data, | |
| 262 | − iio_get_time_ns(indio_dev)); | |
| 263 | − | |
| 264 | − /* | |
| 265 | − * Tell the core we are done with this trigger and ready for the | |
| 266 | − * next one. | |
| 267 | − */ | |
| 268 | − iio_trigger_notify_done(indio_dev->trig); | |
| 269 | − | |
| 270 | − return IRQ_HANDLED; | |
| 271 | −} | |
| 272 | − | |
| 273 | −static char *cros_ec_accel_legacy_loc_strings[] = { | |
| 274 | − [MOTIONSENSE_LOC_BASE] = "base", | |
| 275 | − [MOTIONSENSE_LOC_LID] = "lid", | |
| 276 | − [MOTIONSENSE_LOC_MAX] = "unknown", | |
| 277 | −}; | |
| 278 | − | |
| 279 | −static ssize_t cros_ec_accel_legacy_loc(struct iio_dev *indio_dev, | |
| 280 | − uintptr_t private, | |
| 281 | − const struct iio_chan_spec *chan, | |
| 282 | − char *buf) | |
| 283 | −{ | |
| 284 | − struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev); | |
| 285 | − | |
| 286 | − return sprintf(buf, "%s\n", | |
| 287 | − cros_ec_accel_legacy_loc_strings[st->sensor_num + | |
| 288 | − MOTIONSENSE_LOC_BASE]); | |
| 289 | −} | |
| 290 | − | |
| 291 | −static ssize_t cros_ec_accel_legacy_id(struct iio_dev *indio_dev, | |
| 292 | − uintptr_t private, | |
| 293 | − const struct iio_chan_spec *chan, | |
| 294 | − char *buf) | |
| 295 | −{ | |
| 296 | − struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev); | |
| 297 | − | |
| 298 | − return sprintf(buf, "%d\n", st->sensor_num); | |
| 299 | −} | |
| 300 | − | |
| 301 | −static const struct iio_chan_spec_ext_info cros_ec_accel_legacy_ext_info[] = { | |
| 302 | − { | |
| 303 | − .name = "id", | |
| 304 | − .shared = IIO_SHARED_BY_ALL, | |
| 305 | − .read = cros_ec_accel_legacy_id, | |
| 306 | − }, | |
| 307 | − { | |
| 308 | − .name = "location", | |
| 309 | − .shared = IIO_SHARED_BY_ALL, | |
| 310 | − .read = cros_ec_accel_legacy_loc, | |
| 311 | − }, | |
| 312 | − { } | |
| 313 | −}; | |
| 132 | +#define CROS_EC_ACCEL_ROTATE_AXIS(_axis) \ | |
| 133 | + ((_axis) == CROS_EC_SENSOR_Z ? CROS_EC_SENSOR_Z : \ | |
| 134 | + ((_axis) == CROS_EC_SENSOR_X ? CROS_EC_SENSOR_Y : \ | |
| 135 | + CROS_EC_SENSOR_X)) | |
| 314 | 136 | |
| 315 | 137 | #define CROS_EC_ACCEL_LEGACY_CHAN(_axis) \ |
| 316 | 138 | { \ |
| @@ -321,28 +143,28 @@ static const struct iio_chan_spec_ext_info cros_ec_accel_legacy_ext_info[] = { · 4 unmodified lines | ||
| 321 | 143 | BIT(IIO_CHAN_INFO_RAW) | \ |
| 322 | 144 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ |
| 323 | 145 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \ |
| 324 | − .ext_info = cros_ec_accel_legacy_ext_info, \ | |
| 146 | + .ext_info = cros_ec_sensors_ext_info, \ | |
| 325 | 147 | .scan_type = { \ |
| 326 | 148 | .sign = 's', \ |
| 327 | − .realbits = 16, \ | |
| 328 | − .storagebits = 16, \ | |
| 149 | + .realbits = CROS_EC_SENSOR_BITS, \ | |
| 150 | + .storagebits = CROS_EC_SENSOR_BITS, \ | |
| 329 | 151 | }, \ |
| 152 | + .scan_index = CROS_EC_ACCEL_ROTATE_AXIS(_axis), \ | |
| 330 | 153 | } \ |
| 331 | 154 | |
| 332 | −static struct iio_chan_spec ec_accel_channels[] = { | |
| 333 | − CROS_EC_ACCEL_LEGACY_CHAN(X), | |
| 334 | − CROS_EC_ACCEL_LEGACY_CHAN(Y), | |
| 335 | − CROS_EC_ACCEL_LEGACY_CHAN(Z), | |
| 336 | − IIO_CHAN_SOFT_TIMESTAMP(MAX_AXIS) | |
| 155 | +static const struct iio_chan_spec cros_ec_accel_legacy_channels[] = { | |
| 156 | + CROS_EC_ACCEL_LEGACY_CHAN(CROS_EC_SENSOR_X), | |
| 157 | + CROS_EC_ACCEL_LEGACY_CHAN(CROS_EC_SENSOR_Y), | |
| 158 | + CROS_EC_ACCEL_LEGACY_CHAN(CROS_EC_SENSOR_Z), | |
| 159 | + IIO_CHAN_SOFT_TIMESTAMP(CROS_EC_SENSOR_MAX_AXIS) | |
| 337 | 160 | }; |
| 338 | 161 | |
| 339 | 162 | static int cros_ec_accel_legacy_probe(struct platform_device *pdev) |
| 340 | 163 | { |
| 341 | 164 | struct device *dev = &pdev->dev; |
| 342 | 165 | struct cros_ec_dev *ec = dev_get_drvdata(dev->parent); |
| 343 | − struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); | |
| 344 | 166 | struct iio_dev *indio_dev; |
| 345 | − struct cros_ec_accel_legacy_state *state; | |
| 167 | + struct cros_ec_sensors_core_state *state; | |
| 346 | 168 | int ret; |
| 347 | 169 | |
| 348 | 170 | if (!ec || !ec->ec_dev) { |
| @@ -350,46 +172,32 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 350 | 172 | return -EINVAL; |
| 351 | 173 | } |
| 352 | 174 | |
| 353 | − if (!ec->ec_dev->cmd_readmem) { | |
| 354 | − dev_warn(&pdev->dev, "EC does not support direct reads.\n"); | |
| 355 | − return -EINVAL; | |
| 356 | − } | |
| 357 | − | |
| 358 | 175 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state)); |
| 359 | 176 | if (!indio_dev) |
| 360 | 177 | return -ENOMEM; |
| 361 | 178 | |
| 362 | − platform_set_drvdata(pdev, indio_dev); | |
| 363 | − state = iio_priv(indio_dev); | |
| 364 | − state->ec = ec->ec_dev; | |
| 365 | − state->sensor_num = sensor_platform->sensor_num; | |
| 366 | − | |
| 367 | − indio_dev->dev.parent = dev; | |
| 368 | − indio_dev->name = pdev->name; | |
| 369 | − indio_dev->channels = ec_accel_channels; | |
| 370 | − /* | |
| 371 | − * Present the channel using HTML5 standard: | |
| 372 | − * need to invert X and Y and invert some lid axis. | |
| 373 | − */ | |
| 374 | − ec_accel_channels[X].scan_index = Y; | |
| 375 | − ec_accel_channels[Y].scan_index = X; | |
| 376 | − ec_accel_channels[Z].scan_index = Z; | |
| 179 | + ret = cros_ec_sensors_core_init(pdev, indio_dev, true); | |
| 180 | + if (ret) | |
| 181 | + return ret; | |
| 377 | 182 | |
| 378 | − state->sign[Y] = 1; | |
| 183 | + indio_dev->info = &cros_ec_accel_legacy_info; | |
| 184 | + state = iio_priv(indio_dev); | |
| 379 | 185 | |
| 380 | − if (state->sensor_num == MOTIONSENSE_LOC_LID) | |
| 381 | − state->sign[X] = state->sign[Z] = -1; | |
| 186 | + if (state->ec->cmd_readmem != NULL) | |
| 187 | + state->read_ec_sensors_data = cros_ec_sensors_read_lpc; | |
| 382 | 188 | else |
| 383 | − state->sign[X] = state->sign[Z] = 1; | |
| 384 | − | |
| 385 | − indio_dev->num_channels = ARRAY_SIZE(ec_accel_channels); | |
| 386 | − indio_dev->dev.parent = &pdev->dev; | |
| 387 | − indio_dev->info = &cros_ec_accel_legacy_info; | |
| 388 | − indio_dev->modes = INDIO_DIRECT_MODE; | |
| 189 | + state->read_ec_sensors_data = cros_ec_accel_legacy_read_cmd; | |
| 190 | + | |
| 191 | + indio_dev->channels = cros_ec_accel_legacy_channels; | |
| 192 | + indio_dev->num_channels = ARRAY_SIZE(cros_ec_accel_legacy_channels); | |
| 193 | + /* The lid sensor needs to be presented inverted. */ | |
| 194 | + if (state->loc == MOTIONSENSE_LOC_LID) { | |
| 195 | + state->sign[CROS_EC_SENSOR_X] = -1; | |
| 196 | + state->sign[CROS_EC_SENSOR_Z] = -1; | |
| 197 | + } | |
| 389 | 198 | |
| 390 | 199 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, |
| 391 | − cros_ec_accel_legacy_capture, | |
| 392 | − NULL); | |
| 200 | + cros_ec_sensors_capture, NULL); | |
| 393 | 201 | if (ret) |
| 394 | 202 | return ret; |
| 395 | 203 | |
| @@ -424,7 +424,7 @@ static int mxc4005_probe(struct i2c_client *client, · 423 unmodified lines | ||
| 424 | 424 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 425 | 425 | indio_dev->info = &mxc4005_info; |
| 426 | 426 | |
| 427 | − ret = iio_triggered_buffer_setup(indio_dev, | |
| 427 | + ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, | |
| 428 | 428 | iio_pollfunc_store_time, |
| 429 | 429 | mxc4005_trigger_handler, |
| 430 | 430 | NULL); |
| @@ -452,7 +452,7 @@ static int mxc4005_probe(struct i2c_client *client, · 21 unmodified lines | ||
| 452 | 452 | if (ret) { |
| 453 | 453 | dev_err(&client->dev, |
| 454 | 454 | "failed to init threaded irq\n"); |
| 455 | − goto err_buffer_cleanup; | |
| 455 | + return ret; | |
| 456 | 456 | } |
| 457 | 457 | |
| 458 | 458 | data->dready_trig->dev.parent = &client->dev; |
| @@ -460,43 +460,16 @@ static int mxc4005_probe(struct i2c_client *client, · 1 unmodified line | ||
| 460 | 460 | iio_trigger_set_drvdata(data->dready_trig, indio_dev); |
| 461 | 461 | indio_dev->trig = data->dready_trig; |
| 462 | 462 | iio_trigger_get(indio_dev->trig); |
| 463 | − ret = iio_trigger_register(data->dready_trig); | |
| 463 | + ret = devm_iio_trigger_register(&client->dev, | |
| 464 | + data->dready_trig); | |
| 464 | 465 | if (ret) { |
| 465 | 466 | dev_err(&client->dev, |
| 466 | 467 | "failed to register trigger\n"); |
| 467 | − goto err_trigger_unregister; | |
| 468 | + return ret; | |
| 468 | 469 | } |
| 469 | 470 | } |
| 470 | 471 | |
| 471 | − ret = iio_device_register(indio_dev); | |
| 472 | − if (ret < 0) { | |
| 473 | − dev_err(&client->dev, | |
| 474 | − "unable to register iio device %d\n", ret); | |
| 475 | − goto err_buffer_cleanup; | |
| 476 | − } | |
| 477 | − | |
| 478 | − return 0; | |
| 479 | − | |
| 480 | −err_trigger_unregister: | |
| 481 | − iio_trigger_unregister(data->dready_trig); | |
| 482 | −err_buffer_cleanup: | |
| 483 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 484 | − | |
| 485 | − return ret; | |
| 486 | −} | |
| 487 | − | |
| 488 | −static int mxc4005_remove(struct i2c_client *client) | |
| 489 | −{ | |
| 490 | − struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 491 | − struct mxc4005_data *data = iio_priv(indio_dev); | |
| 492 | − | |
| 493 | − iio_device_unregister(indio_dev); | |
| 494 | − | |
| 495 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 496 | − if (data->dready_trig) | |
| 497 | − iio_trigger_unregister(data->dready_trig); | |
| 498 | − | |
| 499 | − return 0; | |
| 472 | + return devm_iio_device_register(&client->dev, indio_dev); | |
| 500 | 473 | } |
| 501 | 474 | |
| 502 | 475 | static const struct acpi_device_id mxc4005_acpi_match[] = { |
| @@ -517,7 +490,6 @@ static struct i2c_driver mxc4005_driver = { · 14 unmodified lines | ||
| 517 | 490 | .acpi_match_table = ACPI_PTR(mxc4005_acpi_match), |
| 518 | 491 | }, |
| 519 | 492 | .probe = mxc4005_probe, |
| 520 | − .remove = mxc4005_remove, | |
| 521 | 493 | .id_table = mxc4005_id, |
| 522 | 494 | }; |
| 523 | 495 | |
| @@ -111,7 +111,7 @@ · 110 unmodified lines | ||
| 111 | 111 | /* Currently unsupported */ |
| 112 | 112 | #define SCA3000_MD_CTRL_AND_Y BIT(3) |
| 113 | 113 | #define SCA3000_MD_CTRL_AND_X BIT(4) |
| 114 | −#define SAC3000_MD_CTRL_AND_Z BIT(5) | |
| 114 | +#define SCA3000_MD_CTRL_AND_Z BIT(5) | |
| 115 | 115 | |
| 116 | 116 | /* |
| 117 | 117 | * Some control registers of complex access methods requiring this register to |
| @@ -68,6 +68,7 @@ static const struct st_sensors_platform_data default_accel_pdata = { · 67 unmodified lines | ||
| 68 | 68 | .drdy_int_pin = 1, |
| 69 | 69 | }; |
| 70 | 70 | |
| 71 | +const struct st_sensor_settings *st_accel_get_settings(const char *name); | |
| 71 | 72 | int st_accel_common_probe(struct iio_dev *indio_dev); |
| 72 | 73 | void st_accel_common_remove(struct iio_dev *indio_dev); |
| 73 | 74 | |
| @@ -29,65 +29,51 @@ int st_accel_trig_set_state(struct iio_trigger *trig, bool state) · 28 unmodified lines | ||
| 29 | 29 | return st_sensors_set_dataready_irq(indio_dev, state); |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | −static int st_accel_buffer_preenable(struct iio_dev *indio_dev) | |
| 33 | −{ | |
| 34 | − return st_sensors_set_enable(indio_dev, true); | |
| 35 | −} | |
| 36 | − | |
| 37 | 32 | static int st_accel_buffer_postenable(struct iio_dev *indio_dev) |
| 38 | 33 | { |
| 39 | 34 | int err; |
| 40 | − struct st_sensor_data *adata = iio_priv(indio_dev); | |
| 41 | − | |
| 42 | − adata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); | |
| 43 | − if (adata->buffer_data == NULL) { | |
| 44 | − err = -ENOMEM; | |
| 45 | − goto allocate_memory_error; | |
| 46 | − } | |
| 47 | 35 | |
| 48 | 36 | err = iio_triggered_buffer_postenable(indio_dev); |
| 49 | 37 | if (err < 0) |
| 50 | − goto st_accel_buffer_postenable_error; | |
| 38 | + return err; | |
| 51 | 39 | |
| 52 | 40 | err = st_sensors_set_axis_enable(indio_dev, |
| 53 | − (u8)indio_dev->active_scan_mask[0]); | |
| 41 | + (u8)indio_dev->active_scan_mask[0]); | |
| 54 | 42 | if (err < 0) |
| 55 | − goto st_sensors_set_axis_enable_error; | |
| 43 | + goto st_accel_buffer_predisable; | |
| 56 | 44 | |
| 57 | − return err; | |
| 45 | + err = st_sensors_set_enable(indio_dev, true); | |
| 46 | + if (err < 0) | |
| 47 | + goto st_accel_buffer_enable_all_axis; | |
| 58 | 48 | |
| 59 | −st_sensors_set_axis_enable_error: | |
| 49 | + return 0; | |
| 50 | + | |
| 51 | +st_accel_buffer_enable_all_axis: | |
| 52 | + st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); | |
| 53 | +st_accel_buffer_predisable: | |
| 60 | 54 | iio_triggered_buffer_predisable(indio_dev); |
| 61 | −st_accel_buffer_postenable_error: | |
| 62 | − kfree(adata->buffer_data); | |
| 63 | −allocate_memory_error: | |
| 64 | 55 | return err; |
| 65 | 56 | } |
| 66 | 57 | |
| 67 | 58 | static int st_accel_buffer_predisable(struct iio_dev *indio_dev) |
| 68 | 59 | { |
| 69 | 60 | int err, err2; |
| 70 | − struct st_sensor_data *adata = iio_priv(indio_dev); | |
| 71 | − | |
| 72 | − err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); | |
| 73 | − if (err < 0) | |
| 74 | − goto st_accel_buffer_predisable_error; | |
| 75 | 61 | |
| 76 | 62 | err = st_sensors_set_enable(indio_dev, false); |
| 77 | 63 | if (err < 0) |
| 78 | − goto st_accel_buffer_predisable_error; | |
| 64 | + goto st_accel_buffer_predisable; | |
| 65 | + | |
| 66 | + err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); | |
| 79 | 67 | |
| 80 | −st_accel_buffer_predisable_error: | |
| 68 | +st_accel_buffer_predisable: | |
| 81 | 69 | err2 = iio_triggered_buffer_predisable(indio_dev); |
| 82 | 70 | if (!err) |
| 83 | 71 | err = err2; |
| 84 | 72 | |
| 85 | − kfree(adata->buffer_data); | |
| 86 | 73 | return err; |
| 87 | 74 | } |
| 88 | 75 | |
| 89 | 76 | static const struct iio_buffer_setup_ops st_accel_buffer_setup_ops = { |
| 90 | − .preenable = &st_accel_buffer_preenable, | |
| 91 | 77 | .postenable = &st_accel_buffer_postenable, |
| 92 | 78 | .predisable = &st_accel_buffer_predisable, |
| 93 | 79 | }; |
| @@ -13,7 +13,6 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/acpi.h> |
| 14 | 14 | #include <linux/errno.h> |
| 15 | 15 | #include <linux/types.h> |
| 16 | −#include <linux/mutex.h> | |
| 17 | 16 | #include <linux/interrupt.h> |
| 18 | 17 | #include <linux/i2c.h> |
| 19 | 18 | #include <linux/gpio.h> |
| @@ -1147,32 +1146,45 @@ out: · 1127 unmodified lines | ||
| 1147 | 1146 | #endif |
| 1148 | 1147 | } |
| 1149 | 1148 | |
| 1149 | +/* | |
| 1150 | + * st_accel_get_settings() - get sensor settings from device name | |
| 1151 | + * @name: device name buffer reference. | |
| 1152 | + * | |
| 1153 | + * Return: valid reference on success, NULL otherwise. | |
| 1154 | + */ | |
| 1155 | +const struct st_sensor_settings *st_accel_get_settings(const char *name) | |
| 1156 | +{ | |
| 1157 | + int index = st_sensors_get_settings_index(name, | |
| 1158 | + st_accel_sensors_settings, | |
| 1159 | + ARRAY_SIZE(st_accel_sensors_settings)); | |
| 1160 | + if (index < 0) | |
| 1161 | + return NULL; | |
| 1162 | + | |
| 1163 | + return &st_accel_sensors_settings[index]; | |
| 1164 | +} | |
| 1165 | +EXPORT_SYMBOL(st_accel_get_settings); | |
| 1166 | + | |
| 1150 | 1167 | int st_accel_common_probe(struct iio_dev *indio_dev) |
| 1151 | 1168 | { |
| 1152 | 1169 | struct st_sensor_data *adata = iio_priv(indio_dev); |
| 1153 | 1170 | struct st_sensors_platform_data *pdata = |
| 1154 | 1171 | (struct st_sensors_platform_data *)adata->dev->platform_data; |
| 1155 | − int irq = adata->get_irq_data_ready(indio_dev); | |
| 1156 | 1172 | struct iio_chan_spec *channels; |
| 1157 | 1173 | size_t channels_size; |
| 1158 | 1174 | int err; |
| 1159 | 1175 | |
| 1160 | 1176 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 1161 | 1177 | indio_dev->info = &accel_info; |
| 1162 | − mutex_init(&adata->tb.buf_lock); | |
| 1163 | 1178 | |
| 1164 | 1179 | err = st_sensors_power_enable(indio_dev); |
| 1165 | 1180 | if (err) |
| 1166 | 1181 | return err; |
| 1167 | 1182 | |
| 1168 | − err = st_sensors_check_device_support(indio_dev, | |
| 1169 | − ARRAY_SIZE(st_accel_sensors_settings), | |
| 1170 | − st_accel_sensors_settings); | |
| 1183 | + err = st_sensors_verify_id(indio_dev); | |
| 1171 | 1184 | if (err < 0) |
| 1172 | 1185 | goto st_accel_power_off; |
| 1173 | 1186 | |
| 1174 | 1187 | adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS; |
| 1175 | − adata->multiread_bit = adata->sensor_settings->multi_read_bit; | |
| 1176 | 1188 | indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; |
| 1177 | 1189 | |
| 1178 | 1190 | channels_size = indio_dev->num_channels * sizeof(struct iio_chan_spec); |
| @@ -1204,7 +1216,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev) · 25 unmodified lines | ||
| 1204 | 1216 | if (err < 0) |
| 1205 | 1217 | goto st_accel_power_off; |
| 1206 | 1218 | |
| 1207 | − if (irq > 0) { | |
| 1219 | + if (adata->irq > 0) { | |
| 1208 | 1220 | err = st_sensors_allocate_trigger(indio_dev, |
| 1209 | 1221 | ST_ACCEL_TRIGGER_OPS); |
| 1210 | 1222 | if (err < 0) |
| @@ -1221,7 +1233,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev) · 10 unmodified lines | ||
| 1221 | 1233 | return 0; |
| 1222 | 1234 | |
| 1223 | 1235 | st_accel_device_register_error: |
| 1224 | − if (irq > 0) | |
| 1236 | + if (adata->irq > 0) | |
| 1225 | 1237 | st_sensors_deallocate_trigger(indio_dev); |
| 1226 | 1238 | st_accel_probe_trigger_error: |
| 1227 | 1239 | st_accel_deallocate_ring(indio_dev); |
| @@ -1239,7 +1251,7 @@ void st_accel_common_remove(struct iio_dev *indio_dev) · 11 unmodified lines | ||
| 1239 | 1251 | st_sensors_power_disable(indio_dev); |
| 1240 | 1252 | |
| 1241 | 1253 | iio_device_unregister(indio_dev); |
| 1242 | − if (adata->get_irq_data_ready(indio_dev) > 0) | |
| 1254 | + if (adata->irq > 0) | |
| 1243 | 1255 | st_sensors_deallocate_trigger(indio_dev); |
| 1244 | 1256 | |
| 1245 | 1257 | st_accel_deallocate_ring(indio_dev); |
| @@ -150,22 +150,33 @@ MODULE_DEVICE_TABLE(i2c, st_accel_id_table); · 149 unmodified lines | ||
| 150 | 150 | |
| 151 | 151 | static int st_accel_i2c_probe(struct i2c_client *client) |
| 152 | 152 | { |
| 153 | − struct iio_dev *indio_dev; | |
| 153 | + const struct st_sensor_settings *settings; | |
| 154 | 154 | struct st_sensor_data *adata; |
| 155 | + struct iio_dev *indio_dev; | |
| 155 | 156 | const char *match; |
| 156 | 157 | int ret; |
| 157 | 158 | |
| 159 | + match = device_get_match_data(&client->dev); | |
| 160 | + if (match) | |
| 161 | + strlcpy(client->name, match, sizeof(client->name)); | |
| 162 | + | |
| 163 | + settings = st_accel_get_settings(client->name); | |
| 164 | + if (!settings) { | |
| 165 | + dev_err(&client->dev, "device name %s not recognized.\n", | |
| 166 | + client->name); | |
| 167 | + return -ENODEV; | |
| 168 | + } | |
| 169 | + | |
| 158 | 170 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*adata)); |
| 159 | 171 | if (!indio_dev) |
| 160 | 172 | return -ENOMEM; |
| 161 | 173 | |
| 162 | 174 | adata = iio_priv(indio_dev); |
| 175 | + adata->sensor_settings = (struct st_sensor_settings *)settings; | |
| 163 | 176 | |
| 164 | − match = device_get_match_data(&client->dev); | |
| 165 | − if (match) | |
| 166 | − strlcpy(client->name, match, sizeof(client->name)); | |
| 167 | − | |
| 168 | − st_sensors_i2c_configure(indio_dev, client, adata); | |
| 177 | + ret = st_sensors_i2c_configure(indio_dev, client); | |
| 178 | + if (ret < 0) | |
| 179 | + return ret; | |
| 169 | 180 | |
| 170 | 181 | ret = st_accel_common_probe(indio_dev); |
| 171 | 182 | if (ret < 0) |
| @@ -102,19 +102,31 @@ MODULE_DEVICE_TABLE(of, st_accel_of_match); · 101 unmodified lines | ||
| 102 | 102 | |
| 103 | 103 | static int st_accel_spi_probe(struct spi_device *spi) |
| 104 | 104 | { |
| 105 | − struct iio_dev *indio_dev; | |
| 105 | + const struct st_sensor_settings *settings; | |
| 106 | 106 | struct st_sensor_data *adata; |
| 107 | + struct iio_dev *indio_dev; | |
| 107 | 108 | int err; |
| 108 | 109 | |
| 110 | + st_sensors_of_name_probe(&spi->dev, st_accel_of_match, | |
| 111 | + spi->modalias, sizeof(spi->modalias)); | |
| 112 | + | |
| 113 | + settings = st_accel_get_settings(spi->modalias); | |
| 114 | + if (!settings) { | |
| 115 | + dev_err(&spi->dev, "device name %s not recognized.\n", | |
| 116 | + spi->modalias); | |
| 117 | + return -ENODEV; | |
| 118 | + } | |
| 119 | + | |
| 109 | 120 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adata)); |
| 110 | 121 | if (!indio_dev) |
| 111 | 122 | return -ENOMEM; |
| 112 | 123 | |
| 113 | 124 | adata = iio_priv(indio_dev); |
| 125 | + adata->sensor_settings = (struct st_sensor_settings *)settings; | |
| 114 | 126 | |
| 115 | − st_sensors_of_name_probe(&spi->dev, st_accel_of_match, | |
| 116 | − spi->modalias, sizeof(spi->modalias)); | |
| 117 | − st_sensors_spi_configure(indio_dev, spi, adata); | |
| 127 | + err = st_sensors_spi_configure(indio_dev, spi); | |
| 128 | + if (err < 0) | |
| 129 | + return err; | |
| 118 | 130 | |
| 119 | 131 | err = st_accel_common_probe(indio_dev); |
| 120 | 132 | if (err < 0) |
| @@ -35,6 +35,11 @@ static const unsigned int ad7606_scale_avail[2] = { · 34 unmodified lines | ||
| 35 | 35 | 152588, 305176 |
| 36 | 36 | }; |
| 37 | 37 | |
| 38 | + | |
| 39 | +static const unsigned int ad7616_sw_scale_avail[3] = { | |
| 40 | + 76293, 152588, 305176 | |
| 41 | +}; | |
| 42 | + | |
| 38 | 43 | static const unsigned int ad7606_oversampling_avail[7] = { |
| 39 | 44 | 1, 2, 4, 8, 16, 32, 64, |
| 40 | 45 | }; |
| @@ -55,6 +60,29 @@ static int ad7606_reset(struct ad7606_state *st) · 14 unmodified lines | ||
| 55 | 60 | return -ENODEV; |
| 56 | 61 | } |
| 57 | 62 | |
| 63 | +static int ad7606_reg_access(struct iio_dev *indio_dev, | |
| 64 | + unsigned int reg, | |
| 65 | + unsigned int writeval, | |
| 66 | + unsigned int *readval) | |
| 67 | +{ | |
| 68 | + struct ad7606_state *st = iio_priv(indio_dev); | |
| 69 | + int ret; | |
| 70 | + | |
| 71 | + mutex_lock(&st->lock); | |
| 72 | + if (readval) { | |
| 73 | + ret = st->bops->reg_read(st, reg); | |
| 74 | + if (ret < 0) | |
| 75 | + goto err_unlock; | |
| 76 | + *readval = ret; | |
| 77 | + ret = 0; | |
| 78 | + } else { | |
| 79 | + ret = st->bops->reg_write(st, reg, writeval); | |
| 80 | + } | |
| 81 | +err_unlock: | |
| 82 | + mutex_unlock(&st->lock); | |
| 83 | + return ret; | |
| 84 | +} | |
| 85 | + | |
| 58 | 86 | static int ad7606_read_samples(struct ad7606_state *st) |
| 59 | 87 | { |
| 60 | 88 | unsigned int num = st->chip_info->num_channels; |
| @@ -308,29 +336,6 @@ static const struct attribute_group ad7606_attribute_group_range = { · 247 unmodified lines | ||
| 308 | 336 | .attrs = ad7606_attributes_range, |
| 309 | 337 | }; |
| 310 | 338 | |
| 311 | −#define AD760X_CHANNEL(num, mask) { \ | |
| 312 | − .type = IIO_VOLTAGE, \ | |
| 313 | − .indexed = 1, \ | |
| 314 | − .channel = num, \ | |
| 315 | − .address = num, \ | |
| 316 | − .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| 317 | − .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ | |
| 318 | − .info_mask_shared_by_all = mask, \ | |
| 319 | − .scan_index = num, \ | |
| 320 | − .scan_type = { \ | |
| 321 | − .sign = 's', \ | |
| 322 | − .realbits = 16, \ | |
| 323 | − .storagebits = 16, \ | |
| 324 | − .endianness = IIO_CPU, \ | |
| 325 | − }, \ | |
| 326 | −} | |
| 327 | − | |
| 328 | −#define AD7605_CHANNEL(num) \ | |
| 329 | − AD760X_CHANNEL(num, 0) | |
| 330 | − | |
| 331 | −#define AD7606_CHANNEL(num) \ | |
| 332 | − AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) | |
| 333 | − | |
| 334 | 339 | static const struct iio_chan_spec ad7605_channels[] = { |
| 335 | 340 | IIO_CHAN_SOFT_TIMESTAMP(4), |
| 336 | 341 | AD7605_CHANNEL(0), |
| @@ -519,6 +524,14 @@ static const struct iio_info ad7606_info_os_and_range = { · 182 unmodified lines | ||
| 519 | 524 | .validate_trigger = &ad7606_validate_trigger, |
| 520 | 525 | }; |
| 521 | 526 | |
| 527 | +static const struct iio_info ad7606_info_os_range_and_debug = { | |
| 528 | + .read_raw = &ad7606_read_raw, | |
| 529 | + .write_raw = &ad7606_write_raw, | |
| 530 | + .debugfs_reg_access = &ad7606_reg_access, | |
| 531 | + .attrs = &ad7606_attribute_group_os_and_range, | |
| 532 | + .validate_trigger = &ad7606_validate_trigger, | |
| 533 | +}; | |
| 534 | + | |
| 522 | 535 | static const struct iio_info ad7606_info_os = { |
| 523 | 536 | .read_raw = &ad7606_read_raw, |
| 524 | 537 | .write_raw = &ad7606_write_raw, |
| @@ -617,35 +630,27 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, · 92 unmodified lines | ||
| 617 | 630 | if (ret) |
| 618 | 631 | dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); |
| 619 | 632 | |
| 633 | + /* AD7616 requires al least 15ms to reconfigure after a reset */ | |
| 634 | + if (msleep_interruptible(15)) | |
| 635 | + return -ERESTARTSYS; | |
| 636 | + | |
| 620 | 637 | st->write_scale = ad7606_write_scale_hw; |
| 621 | 638 | st->write_os = ad7606_write_os_hw; |
| 622 | 639 | |
| 623 | − if (st->chip_info->sw_mode_config) | |
| 640 | + if (st->bops->sw_mode_config) | |
| 624 | 641 | st->sw_mode_en = device_property_present(st->dev, |
| 625 | 642 | "adi,sw-mode"); |
| 626 | 643 | |
| 627 | 644 | if (st->sw_mode_en) { |
| 645 | + /* Scale of 0.076293 is only available in sw mode */ | |
| 646 | + st->scale_avail = ad7616_sw_scale_avail; | |
| 647 | + st->num_scales = ARRAY_SIZE(ad7616_sw_scale_avail); | |
| 648 | + | |
| 628 | 649 | /* After reset, in software mode, ±10 V is set by default */ |
| 629 | 650 | memset32(st->range, 2, ARRAY_SIZE(st->range)); |
| 630 | − indio_dev->info = &ad7606_info_os_and_range; | |
| 631 | − | |
| 632 | − /* | |
| 633 | − * In software mode, the range gpio has no longer its function. | |
| 634 | − * Instead, the scale can be configured individually for each | |
| 635 | − * channel from the range registers. | |
| 636 | − */ | |
| 637 | − if (st->chip_info->write_scale_sw) | |
| 638 | − st->write_scale = st->chip_info->write_scale_sw; | |
| 639 | − | |
| 640 | − /* | |
| 641 | − * In software mode, the oversampling is no longer configured | |
| 642 | − * with GPIO pins. Instead, the oversampling can be configured | |
| 643 | − * in configuratiion register. | |
| 644 | − */ | |
| 645 | − if (st->chip_info->write_os_sw) | |
| 646 | − st->write_os = st->chip_info->write_os_sw; | |
| 647 | − | |
| 648 | − ret = st->chip_info->sw_mode_config(indio_dev); | |
| 651 | + indio_dev->info = &ad7606_info_os_range_and_debug; | |
| 652 | + | |
| 653 | + ret = st->bops->sw_mode_config(indio_dev); | |
| 649 | 654 | if (ret < 0) |
| 650 | 655 | return ret; |
| 651 | 656 | } |
| @@ -8,6 +8,36 @@ · 7 unmodified lines | ||
| 8 | 8 | #ifndef IIO_ADC_AD7606_H_ |
| 9 | 9 | #define IIO_ADC_AD7606_H_ |
| 10 | 10 | |
| 11 | +#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all) { \ | |
| 12 | + .type = IIO_VOLTAGE, \ | |
| 13 | + .indexed = 1, \ | |
| 14 | + .channel = num, \ | |
| 15 | + .address = num, \ | |
| 16 | + .info_mask_separate = mask_sep, \ | |
| 17 | + .info_mask_shared_by_type = mask_type, \ | |
| 18 | + .info_mask_shared_by_all = mask_all, \ | |
| 19 | + .scan_index = num, \ | |
| 20 | + .scan_type = { \ | |
| 21 | + .sign = 's', \ | |
| 22 | + .realbits = 16, \ | |
| 23 | + .storagebits = 16, \ | |
| 24 | + .endianness = IIO_CPU, \ | |
| 25 | + }, \ | |
| 26 | +} | |
| 27 | + | |
| 28 | +#define AD7605_CHANNEL(num) \ | |
| 29 | + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ | |
| 30 | + BIT(IIO_CHAN_INFO_SCALE), 0) | |
| 31 | + | |
| 32 | +#define AD7606_CHANNEL(num) \ | |
| 33 | + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ | |
| 34 | + BIT(IIO_CHAN_INFO_SCALE), \ | |
| 35 | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) | |
| 36 | + | |
| 37 | +#define AD7616_CHANNEL(num) \ | |
| 38 | + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),\ | |
| 39 | + 0, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) | |
| 40 | + | |
| 11 | 41 | /** |
| 12 | 42 | * struct ad7606_chip_info - chip specific information |
| 13 | 43 | * @channels: channel specification |
| @@ -16,12 +46,6 @@ · 2 unmodified lines | ||
| 16 | 46 | * oversampling ratios. |
| 17 | 47 | * @oversampling_num number of elements stored in oversampling_avail array |
| 18 | 48 | * @os_req_reset some devices require a reset to update oversampling |
| 19 | − * @write_scale_sw pointer to the function which writes the scale via spi | |
| 20 | − in software mode | |
| 21 | − * @write_os_sw pointer to the function which writes the os via spi | |
| 22 | − in software mode | |
| 23 | − * @sw_mode_config: pointer to a function which configured the device | |
| 24 | − * for software mode | |
| 25 | 49 | */ |
| 26 | 50 | struct ad7606_chip_info { |
| 27 | 51 | const struct iio_chan_spec *channels; |
| @@ -29,9 +53,6 @@ struct ad7606_chip_info { · 1 unmodified line | ||
| 29 | 53 | const unsigned int *oversampling_avail; |
| 30 | 54 | unsigned int oversampling_num; |
| 31 | 55 | bool os_req_reset; |
| 32 | − int (*write_scale_sw)(struct iio_dev *indio_dev, int ch, int val); | |
| 33 | − int (*write_os_sw)(struct iio_dev *indio_dev, int val); | |
| 34 | − int (*sw_mode_config)(struct iio_dev *indio_dev); | |
| 35 | 56 | }; |
| 36 | 57 | |
| 37 | 58 | /** |
| @@ -63,6 +84,7 @@ struct ad7606_chip_info { · 25 unmodified lines | ||
| 63 | 84 | * @complete completion to indicate end of conversion |
| 64 | 85 | * @trig The IIO trigger associated with the device. |
| 65 | 86 | * @data buffer for reading data from the device |
| 87 | + * @d16 be16 buffer for reading data from the device | |
| 66 | 88 | */ |
| 67 | 89 | struct ad7606_state { |
| 68 | 90 | struct device *dev; |
| @@ -96,15 +118,32 @@ struct ad7606_state { · 27 unmodified lines | ||
| 96 | 118 | * 16 * 16-bit samples + 64-bit timestamp |
| 97 | 119 | */ |
| 98 | 120 | unsigned short data[20] ____cacheline_aligned; |
| 121 | + __be16 d16[2]; | |
| 99 | 122 | }; |
| 100 | 123 | |
| 101 | 124 | /** |
| 102 | 125 | * struct ad7606_bus_ops - driver bus operations |
| 103 | 126 | * @read_block function pointer for reading blocks of data |
| 127 | + * @sw_mode_config: pointer to a function which configured the device | |
| 128 | + * for software mode | |
| 129 | + * @reg_read function pointer for reading spi register | |
| 130 | + * @reg_write function pointer for writing spi register | |
| 131 | + * @write_mask function pointer for write spi register with mask | |
| 132 | + * @rd_wr_cmd pointer to the function which calculates the spi address | |
| 104 | 133 | */ |
| 105 | 134 | struct ad7606_bus_ops { |
| 106 | 135 | /* more methods added in future? */ |
| 107 | 136 | int (*read_block)(struct device *dev, int num, void *data); |
| 137 | + int (*sw_mode_config)(struct iio_dev *indio_dev); | |
| 138 | + int (*reg_read)(struct ad7606_state *st, unsigned int addr); | |
| 139 | + int (*reg_write)(struct ad7606_state *st, | |
| 140 | + unsigned int addr, | |
| 141 | + unsigned int val); | |
| 142 | + int (*write_mask)(struct ad7606_state *st, | |
| 143 | + unsigned int addr, | |
| 144 | + unsigned long mask, | |
| 145 | + unsigned int val); | |
| 146 | + u16 (*rd_wr_cmd)(int addr, char isWriteOp); | |
| 108 | 147 | }; |
| 109 | 148 | |
| 110 | 149 | int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, |
| @@ -53,10 +53,8 @@ static int ad7606_par_probe(struct platform_device *pdev) · 52 unmodified lines | ||
| 53 | 53 | int irq; |
| 54 | 54 | |
| 55 | 55 | irq = platform_get_irq(pdev, 0); |
| 56 | − if (irq < 0) { | |
| 57 | − dev_err(&pdev->dev, "no irq: %d\n", irq); | |
| 56 | + if (irq < 0) | |
| 58 | 57 | return irq; |
| 59 | − } | |
| 60 | 58 | |
| 61 | 59 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 62 | 60 | addr = devm_ioremap_resource(&pdev->dev, res); |
| @@ -15,6 +15,51 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | #define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */ |
| 17 | 17 | |
| 18 | +#define AD7616_CONFIGURATION_REGISTER 0x02 | |
| 19 | +#define AD7616_OS_MASK GENMASK(4, 2) | |
| 20 | +#define AD7616_BURST_MODE BIT(6) | |
| 21 | +#define AD7616_SEQEN_MODE BIT(5) | |
| 22 | +#define AD7616_RANGE_CH_A_ADDR_OFF 0x04 | |
| 23 | +#define AD7616_RANGE_CH_B_ADDR_OFF 0x06 | |
| 24 | +/* | |
| 25 | + * Range of channels from a group are stored in 2 registers. | |
| 26 | + * 0, 1, 2, 3 in a register followed by 4, 5, 6, 7 in second register. | |
| 27 | + * For channels from second group(8-15) the order is the same, only with | |
| 28 | + * an offset of 2 for register address. | |
| 29 | + */ | |
| 30 | +#define AD7616_RANGE_CH_ADDR(ch) ((ch) >> 2) | |
| 31 | +/* The range of the channel is stored on 2 bits*/ | |
| 32 | +#define AD7616_RANGE_CH_MSK(ch) (0b11 << (((ch) & 0b11) * 2)) | |
| 33 | +#define AD7616_RANGE_CH_MODE(ch, mode) ((mode) << ((((ch) & 0b11)) * 2)) | |
| 34 | +static const struct iio_chan_spec ad7616_sw_channels[] = { | |
| 35 | + IIO_CHAN_SOFT_TIMESTAMP(16), | |
| 36 | + AD7616_CHANNEL(0), | |
| 37 | + AD7616_CHANNEL(1), | |
| 38 | + AD7616_CHANNEL(2), | |
| 39 | + AD7616_CHANNEL(3), | |
| 40 | + AD7616_CHANNEL(4), | |
| 41 | + AD7616_CHANNEL(5), | |
| 42 | + AD7616_CHANNEL(6), | |
| 43 | + AD7616_CHANNEL(7), | |
| 44 | + AD7616_CHANNEL(8), | |
| 45 | + AD7616_CHANNEL(9), | |
| 46 | + AD7616_CHANNEL(10), | |
| 47 | + AD7616_CHANNEL(11), | |
| 48 | + AD7616_CHANNEL(12), | |
| 49 | + AD7616_CHANNEL(13), | |
| 50 | + AD7616_CHANNEL(14), | |
| 51 | + AD7616_CHANNEL(15), | |
| 52 | +}; | |
| 53 | + | |
| 54 | +static u16 ad7616_spi_rd_wr_cmd(int addr, char isWriteOp) | |
| 55 | +{ | |
| 56 | + /* | |
| 57 | + * The address of register consist of one w/r bit | |
| 58 | + * 6 bits of address followed by one reserved bit. | |
| 59 | + */ | |
| 60 | + return ((addr & 0x7F) << 1) | ((isWriteOp & 0x1) << 7); | |
| 61 | +} | |
| 62 | + | |
| 18 | 63 | static int ad7606_spi_read_block(struct device *dev, |
| 19 | 64 | int count, void *buf) |
| 20 | 65 | { |
| @@ -35,17 +80,145 @@ static int ad7606_spi_read_block(struct device *dev, · 14 unmodified lines | ||
| 35 | 80 | return 0; |
| 36 | 81 | } |
| 37 | 82 | |
| 83 | +static int ad7606_spi_reg_read(struct ad7606_state *st, unsigned int addr) | |
| 84 | +{ | |
| 85 | + struct spi_device *spi = to_spi_device(st->dev); | |
| 86 | + struct spi_transfer t[] = { | |
| 87 | + { | |
| 88 | + .tx_buf = &st->d16[0], | |
| 89 | + .len = 2, | |
| 90 | + .cs_change = 0, | |
| 91 | + }, { | |
| 92 | + .rx_buf = &st->d16[1], | |
| 93 | + .len = 2, | |
| 94 | + }, | |
| 95 | + }; | |
| 96 | + int ret; | |
| 97 | + | |
| 98 | + st->d16[0] = cpu_to_be16(st->bops->rd_wr_cmd(addr, 0) << 8); | |
| 99 | + | |
| 100 | + ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t)); | |
| 101 | + if (ret < 0) | |
| 102 | + return ret; | |
| 103 | + | |
| 104 | + return be16_to_cpu(st->d16[1]); | |
| 105 | +} | |
| 106 | + | |
| 107 | +static int ad7606_spi_reg_write(struct ad7606_state *st, | |
| 108 | + unsigned int addr, | |
| 109 | + unsigned int val) | |
| 110 | +{ | |
| 111 | + struct spi_device *spi = to_spi_device(st->dev); | |
| 112 | + | |
| 113 | + st->d16[0] = cpu_to_be16((st->bops->rd_wr_cmd(addr, 1) << 8) | | |
| 114 | + (val & 0x1FF)); | |
| 115 | + | |
| 116 | + return spi_write(spi, &st->d16[0], sizeof(st->d16[0])); | |
| 117 | +} | |
| 118 | + | |
| 119 | +static int ad7606_spi_write_mask(struct ad7606_state *st, | |
| 120 | + unsigned int addr, | |
| 121 | + unsigned long mask, | |
| 122 | + unsigned int val) | |
| 123 | +{ | |
| 124 | + int readval; | |
| 125 | + | |
| 126 | + readval = st->bops->reg_read(st, addr); | |
| 127 | + if (readval < 0) | |
| 128 | + return readval; | |
| 129 | + | |
| 130 | + readval &= ~mask; | |
| 131 | + readval |= val; | |
| 132 | + | |
| 133 | + return st->bops->reg_write(st, addr, readval); | |
| 134 | +} | |
| 135 | + | |
| 136 | +static int ad7616_write_scale_sw(struct iio_dev *indio_dev, int ch, int val) | |
| 137 | +{ | |
| 138 | + struct ad7606_state *st = iio_priv(indio_dev); | |
| 139 | + unsigned int ch_addr, mode, ch_index; | |
| 140 | + | |
| 141 | + | |
| 142 | + /* | |
| 143 | + * Ad7616 has 16 channels divided in group A and group B. | |
| 144 | + * The range of channels from A are stored in registers with address 4 | |
| 145 | + * while channels from B are stored in register with address 6. | |
| 146 | + * The last bit from channels determines if it is from group A or B | |
| 147 | + * because the order of channels in iio is 0A, 0B, 1A, 1B... | |
| 148 | + */ | |
| 149 | + ch_index = ch >> 1; | |
| 150 | + | |
| 151 | + ch_addr = AD7616_RANGE_CH_ADDR(ch_index); | |
| 152 | + | |
| 153 | + if ((ch & 0x1) == 0) /* channel A */ | |
| 154 | + ch_addr += AD7616_RANGE_CH_A_ADDR_OFF; | |
| 155 | + else /* channel B */ | |
| 156 | + ch_addr += AD7616_RANGE_CH_B_ADDR_OFF; | |
| 157 | + | |
| 158 | + /* 0b01 for 2.5v, 0b10 for 5v and 0b11 for 10v */ | |
| 159 | + mode = AD7616_RANGE_CH_MODE(ch_index, ((val + 1) & 0b11)); | |
| 160 | + return st->bops->write_mask(st, ch_addr, AD7616_RANGE_CH_MSK(ch_index), | |
| 161 | + mode); | |
| 162 | +} | |
| 163 | + | |
| 164 | +static int ad7616_write_os_sw(struct iio_dev *indio_dev, int val) | |
| 165 | +{ | |
| 166 | + struct ad7606_state *st = iio_priv(indio_dev); | |
| 167 | + | |
| 168 | + return st->bops->write_mask(st, AD7616_CONFIGURATION_REGISTER, | |
| 169 | + AD7616_OS_MASK, val << 2); | |
| 170 | +} | |
| 171 | + | |
| 172 | +static int ad7616_sw_mode_config(struct iio_dev *indio_dev) | |
| 173 | +{ | |
| 174 | + struct ad7606_state *st = iio_priv(indio_dev); | |
| 175 | + | |
| 176 | + /* | |
| 177 | + * Scale can be configured individually for each channel | |
| 178 | + * in software mode. | |
| 179 | + */ | |
| 180 | + indio_dev->channels = ad7616_sw_channels; | |
| 181 | + | |
| 182 | + st->write_scale = ad7616_write_scale_sw; | |
| 183 | + st->write_os = &ad7616_write_os_sw; | |
| 184 | + | |
| 185 | + /* Activate Burst mode and SEQEN MODE */ | |
| 186 | + return st->bops->write_mask(st, | |
| 187 | + AD7616_CONFIGURATION_REGISTER, | |
| 188 | + AD7616_BURST_MODE | AD7616_SEQEN_MODE, | |
| 189 | + AD7616_BURST_MODE | AD7616_SEQEN_MODE); | |
| 190 | +} | |
| 191 | + | |
| 38 | 192 | static const struct ad7606_bus_ops ad7606_spi_bops = { |
| 39 | 193 | .read_block = ad7606_spi_read_block, |
| 40 | 194 | }; |
| 41 | 195 | |
| 196 | +static const struct ad7606_bus_ops ad7616_spi_bops = { | |
| 197 | + .read_block = ad7606_spi_read_block, | |
| 198 | + .reg_read = ad7606_spi_reg_read, | |
| 199 | + .reg_write = ad7606_spi_reg_write, | |
| 200 | + .write_mask = ad7606_spi_write_mask, | |
| 201 | + .rd_wr_cmd = ad7616_spi_rd_wr_cmd, | |
| 202 | + .sw_mode_config = ad7616_sw_mode_config, | |
| 203 | +}; | |
| 204 | + | |
| 42 | 205 | static int ad7606_spi_probe(struct spi_device *spi) |
| 43 | 206 | { |
| 44 | 207 | const struct spi_device_id *id = spi_get_device_id(spi); |
| 208 | + const struct ad7606_bus_ops *bops; | |
| 209 | + | |
| 210 | + switch (id->driver_data) { | |
| 211 | + case ID_AD7616: | |
| 212 | + bops = &ad7616_spi_bops; | |
| 213 | + break; | |
| 214 | + default: | |
| 215 | + bops = &ad7606_spi_bops; | |
| 216 | + break; | |
| 217 | + } | |
| 45 | 218 | |
| 46 | 219 | return ad7606_probe(&spi->dev, spi->irq, NULL, |
| 47 | 220 | id->name, id->driver_data, |
| 48 | − &ad7606_spi_bops); | |
| 221 | + bops); | |
| 49 | 222 | } |
| 50 | 223 | |
| 51 | 224 | static const struct spi_device_id ad7606_id_table[] = { |
| @@ -1179,10 +1179,8 @@ static int at91_adc_probe(struct platform_device *pdev) · 1178 unmodified lines | ||
| 1179 | 1179 | idev->info = &at91_adc_info; |
| 1180 | 1180 | |
| 1181 | 1181 | st->irq = platform_get_irq(pdev, 0); |
| 1182 | − if (st->irq < 0) { | |
| 1183 | − dev_err(&pdev->dev, "No IRQ ID is designated\n"); | |
| 1182 | + if (st->irq < 0) | |
| 1184 | 1183 | return -ENODEV; |
| 1185 | − } | |
| 1186 | 1184 | |
| 1187 | 1185 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1188 | 1186 | |
| @@ -225,10 +225,8 @@ static int axp288_adc_probe(struct platform_device *pdev) · 224 unmodified lines | ||
| 225 | 225 | |
| 226 | 226 | info = iio_priv(indio_dev); |
| 227 | 227 | info->irq = platform_get_irq(pdev, 0); |
| 228 | − if (info->irq < 0) { | |
| 229 | − dev_err(&pdev->dev, "no irq resource?\n"); | |
| 228 | + if (info->irq < 0) | |
| 230 | 229 | return info->irq; |
| 231 | − } | |
| 232 | 230 | platform_set_drvdata(pdev, indio_dev); |
| 233 | 231 | info->regmap = axp20x->regmap; |
| 234 | 232 | /* |
| @@ -540,11 +540,8 @@ static int iproc_adc_probe(struct platform_device *pdev) · 539 unmodified lines | ||
| 540 | 540 | } |
| 541 | 541 | |
| 542 | 542 | adc_priv->irqno = platform_get_irq(pdev, 0); |
| 543 | − if (adc_priv->irqno <= 0) { | |
| 544 | − dev_err(&pdev->dev, "platform_get_irq failed\n"); | |
| 545 | − ret = -ENODEV; | |
| 546 | − return ret; | |
| 547 | − } | |
| 543 | + if (adc_priv->irqno <= 0) | |
| 544 | + return -ENODEV; | |
| 548 | 545 | |
| 549 | 546 | ret = regmap_update_bits(adc_priv->regmap, IPROC_REGCTL2, |
| 550 | 547 | IPROC_ADC_AUXIN_SCAN_ENA, 0); |
| @@ -337,10 +337,8 @@ static int da9150_gpadc_probe(struct platform_device *pdev) · 336 unmodified lines | ||
| 337 | 337 | init_completion(&gpadc->complete); |
| 338 | 338 | |
| 339 | 339 | irq = platform_get_irq_byname(pdev, "GPADC"); |
| 340 | − if (irq < 0) { | |
| 341 | − dev_err(dev, "Failed to get IRQ: %d\n", irq); | |
| 340 | + if (irq < 0) | |
| 342 | 341 | return irq; |
| 343 | − } | |
| 344 | 342 | |
| 345 | 343 | ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq, |
| 346 | 344 | IRQF_ONESHOT, "GPADC", gpadc); |
| @@ -357,11 +357,8 @@ static int envelope_detector_probe(struct platform_device *pdev) · 356 unmodified lines | ||
| 357 | 357 | } |
| 358 | 358 | |
| 359 | 359 | env->comp_irq = platform_get_irq_byname(pdev, "comp"); |
| 360 | − if (env->comp_irq < 0) { | |
| 361 | − if (env->comp_irq != -EPROBE_DEFER) | |
| 362 | − dev_err(dev, "failed to get compare interrupt\n"); | |
| 360 | + if (env->comp_irq < 0) | |
| 363 | 361 | return env->comp_irq; |
| 364 | − } | |
| 365 | 362 | |
| 366 | 363 | ret = devm_request_irq(dev, env->comp_irq, envelope_detector_comp_isr, |
| 367 | 364 | 0, "envelope-detector", env); |
| @@ -805,10 +805,8 @@ static int exynos_adc_probe(struct platform_device *pdev) · 804 unmodified lines | ||
| 805 | 805 | } |
| 806 | 806 | |
| 807 | 807 | irq = platform_get_irq(pdev, 0); |
| 808 | − if (irq < 0) { | |
| 809 | − dev_err(&pdev->dev, "no irq resource?\n"); | |
| 808 | + if (irq < 0) | |
| 810 | 809 | return irq; |
| 811 | − } | |
| 812 | 810 | info->irq = irq; |
| 813 | 811 | |
| 814 | 812 | irq = platform_get_irq(pdev, 1); |
| @@ -340,7 +340,6 @@ static int mx25_gcq_probe(struct platform_device *pdev) · 339 unmodified lines | ||
| 340 | 340 | |
| 341 | 341 | priv->irq = platform_get_irq(pdev, 0); |
| 342 | 342 | if (priv->irq <= 0) { |
| 343 | − dev_err(dev, "Failed to get IRQ\n"); | |
| 344 | 343 | ret = priv->irq; |
| 345 | 344 | if (!ret) |
| 346 | 345 | ret = -ENXIO; |
| @@ -456,6 +456,11 @@ err_read: · 455 unmodified lines | ||
| 456 | 456 | return IRQ_HANDLED; |
| 457 | 457 | } |
| 458 | 458 | |
| 459 | +static void hi8435_triggered_event_cleanup(void *data) | |
| 460 | +{ | |
| 461 | + iio_triggered_event_cleanup(data); | |
| 462 | +} | |
| 463 | + | |
| 459 | 464 | static int hi8435_probe(struct spi_device *spi) |
| 460 | 465 | { |
| 461 | 466 | struct iio_dev *idev; |
| @@ -477,7 +482,7 @@ static int hi8435_probe(struct spi_device *spi) · 15 unmodified lines | ||
| 477 | 482 | hi8435_writeb(priv, HI8435_CTRL_REG, 0); |
| 478 | 483 | } else { |
| 479 | 484 | udelay(5); |
| 480 | − gpiod_set_value(reset_gpio, 1); | |
| 485 | + gpiod_set_value_cansleep(reset_gpio, 1); | |
| 481 | 486 | } |
| 482 | 487 | |
| 483 | 488 | spi_set_drvdata(spi, idev); |
| @@ -513,27 +518,13 @@ static int hi8435_probe(struct spi_device *spi) · 29 unmodified lines | ||
| 513 | 518 | if (ret) |
| 514 | 519 | return ret; |
| 515 | 520 | |
| 516 | − ret = iio_device_register(idev); | |
| 517 | − if (ret < 0) { | |
| 518 | − dev_err(&spi->dev, "unable to register device\n"); | |
| 519 | − goto unregister_triggered_event; | |
| 520 | − } | |
| 521 | − | |
| 522 | − return 0; | |
| 523 | − | |
| 524 | −unregister_triggered_event: | |
| 525 | − iio_triggered_event_cleanup(idev); | |
| 526 | − return ret; | |
| 527 | −} | |
| 528 | − | |
| 529 | −static int hi8435_remove(struct spi_device *spi) | |
| 530 | −{ | |
| 531 | − struct iio_dev *idev = spi_get_drvdata(spi); | |
| 532 | − | |
| 533 | − iio_device_unregister(idev); | |
| 534 | − iio_triggered_event_cleanup(idev); | |
| 521 | + ret = devm_add_action_or_reset(&spi->dev, | |
| 522 | + hi8435_triggered_event_cleanup, | |
| 523 | + idev); | |
| 524 | + if (ret) | |
| 525 | + return ret; | |
| 535 | 526 | |
| 536 | − return 0; | |
| 527 | + return devm_iio_device_register(&spi->dev, idev); | |
| 537 | 528 | } |
| 538 | 529 | |
| 539 | 530 | static const struct of_device_id hi8435_dt_ids[] = { |
| @@ -554,7 +545,6 @@ static struct spi_driver hi8435_driver = { · 14 unmodified lines | ||
| 554 | 545 | .of_match_table = of_match_ptr(hi8435_dt_ids), |
| 555 | 546 | }, |
| 556 | 547 | .probe = hi8435_probe, |
| 557 | − .remove = hi8435_remove, | |
| 558 | 548 | .id_table = hi8435_id, |
| 559 | 549 | }; |
| 560 | 550 | module_spi_driver(hi8435_driver); |
| @@ -492,10 +492,8 @@ static int imx7d_adc_probe(struct platform_device *pdev) · 491 unmodified lines | ||
| 492 | 492 | return PTR_ERR(info->regs); |
| 493 | 493 | |
| 494 | 494 | irq = platform_get_irq(pdev, 0); |
| 495 | − if (irq < 0) { | |
| 496 | − dev_err(dev, "No irq resource?\n"); | |
| 495 | + if (irq < 0) | |
| 497 | 496 | return irq; |
| 498 | − } | |
| 499 | 497 | |
| 500 | 498 | info->clk = devm_clk_get(dev, "adc"); |
| 501 | 499 | if (IS_ERR(info->clk)) { |
| @@ -172,10 +172,8 @@ static int lpc32xx_adc_probe(struct platform_device *pdev) · 171 unmodified lines | ||
| 172 | 172 | } |
| 173 | 173 | |
| 174 | 174 | irq = platform_get_irq(pdev, 0); |
| 175 | − if (irq <= 0) { | |
| 176 | − dev_err(&pdev->dev, "failed getting interrupt resource\n"); | |
| 175 | + if (irq <= 0) | |
| 177 | 176 | return -ENXIO; |
| 178 | − } | |
| 179 | 177 | |
| 180 | 178 | retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0, |
| 181 | 179 | LPC32XXAD_NAME, st); |
| @@ -225,7 +225,6 @@ static int npcm_adc_probe(struct platform_device *pdev) · 224 unmodified lines | ||
| 225 | 225 | |
| 226 | 226 | irq = platform_get_irq(pdev, 0); |
| 227 | 227 | if (irq <= 0) { |
| 228 | − dev_err(dev, "failed getting interrupt resource\n"); | |
| 229 | 228 | ret = -EINVAL; |
| 230 | 229 | goto err_disable_clk; |
| 231 | 230 | } |
| @@ -244,10 +244,8 @@ static int rockchip_saradc_probe(struct platform_device *pdev) · 243 unmodified lines | ||
| 244 | 244 | init_completion(&info->completion); |
| 245 | 245 | |
| 246 | 246 | irq = platform_get_irq(pdev, 0); |
| 247 | − if (irq < 0) { | |
| 248 | − dev_err(&pdev->dev, "no irq resource?\n"); | |
| 247 | + if (irq < 0) | |
| 249 | 248 | return irq; |
| 250 | − } | |
| 251 | 249 | |
| 252 | 250 | ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, |
| 253 | 251 | 0, dev_name(&pdev->dev), info); |
| @@ -504,88 +504,85 @@ static void sc27xx_adc_free_hwlock(void *_data) · 503 unmodified lines | ||
| 504 | 504 | |
| 505 | 505 | static int sc27xx_adc_probe(struct platform_device *pdev) |
| 506 | 506 | { |
| 507 | − struct device_node *np = pdev->dev.of_node; | |
| 507 | + struct device *dev = &pdev->dev; | |
| 508 | + struct device_node *np = dev->of_node; | |
| 508 | 509 | struct sc27xx_adc_data *sc27xx_data; |
| 509 | 510 | struct iio_dev *indio_dev; |
| 510 | 511 | int ret; |
| 511 | 512 | |
| 512 | − indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*sc27xx_data)); | |
| 513 | + indio_dev = devm_iio_device_alloc(dev, sizeof(*sc27xx_data)); | |
| 513 | 514 | if (!indio_dev) |
| 514 | 515 | return -ENOMEM; |
| 515 | 516 | |
| 516 | 517 | sc27xx_data = iio_priv(indio_dev); |
| 517 | 518 | |
| 518 | − sc27xx_data->regmap = dev_get_regmap(pdev->dev.parent, NULL); | |
| 519 | + sc27xx_data->regmap = dev_get_regmap(dev->parent, NULL); | |
| 519 | 520 | if (!sc27xx_data->regmap) { |
| 520 | − dev_err(&pdev->dev, "failed to get ADC regmap\n"); | |
| 521 | + dev_err(dev, "failed to get ADC regmap\n"); | |
| 521 | 522 | return -ENODEV; |
| 522 | 523 | } |
| 523 | 524 | |
| 524 | 525 | ret = of_property_read_u32(np, "reg", &sc27xx_data->base); |
| 525 | 526 | if (ret) { |
| 526 | − dev_err(&pdev->dev, "failed to get ADC base address\n"); | |
| 527 | + dev_err(dev, "failed to get ADC base address\n"); | |
| 527 | 528 | return ret; |
| 528 | 529 | } |
| 529 | 530 | |
| 530 | 531 | sc27xx_data->irq = platform_get_irq(pdev, 0); |
| 531 | − if (sc27xx_data->irq < 0) { | |
| 532 | − dev_err(&pdev->dev, "failed to get ADC irq number\n"); | |
| 532 | + if (sc27xx_data->irq < 0) | |
| 533 | 533 | return sc27xx_data->irq; |
| 534 | − } | |
| 535 | 534 | |
| 536 | 535 | ret = of_hwspin_lock_get_id(np, 0); |
| 537 | 536 | if (ret < 0) { |
| 538 | − dev_err(&pdev->dev, "failed to get hwspinlock id\n"); | |
| 537 | + dev_err(dev, "failed to get hwspinlock id\n"); | |
| 539 | 538 | return ret; |
| 540 | 539 | } |
| 541 | 540 | |
| 542 | 541 | sc27xx_data->hwlock = hwspin_lock_request_specific(ret); |
| 543 | 542 | if (!sc27xx_data->hwlock) { |
| 544 | − dev_err(&pdev->dev, "failed to request hwspinlock\n"); | |
| 543 | + dev_err(dev, "failed to request hwspinlock\n"); | |
| 545 | 544 | return -ENXIO; |
| 546 | 545 | } |
| 547 | 546 | |
| 548 | − ret = devm_add_action(&pdev->dev, sc27xx_adc_free_hwlock, | |
| 547 | + ret = devm_add_action_or_reset(dev, sc27xx_adc_free_hwlock, | |
| 549 | 548 | sc27xx_data->hwlock); |
| 550 | 549 | if (ret) { |
| 551 | − sc27xx_adc_free_hwlock(sc27xx_data->hwlock); | |
| 552 | − dev_err(&pdev->dev, "failed to add hwspinlock action\n"); | |
| 550 | + dev_err(dev, "failed to add hwspinlock action\n"); | |
| 553 | 551 | return ret; |
| 554 | 552 | } |
| 555 | 553 | |
| 556 | 554 | init_completion(&sc27xx_data->completion); |
| 557 | − sc27xx_data->dev = &pdev->dev; | |
| 555 | + sc27xx_data->dev = dev; | |
| 558 | 556 | |
| 559 | 557 | ret = sc27xx_adc_enable(sc27xx_data); |
| 560 | 558 | if (ret) { |
| 561 | − dev_err(&pdev->dev, "failed to enable ADC module\n"); | |
| 559 | + dev_err(dev, "failed to enable ADC module\n"); | |
| 562 | 560 | return ret; |
| 563 | 561 | } |
| 564 | 562 | |
| 565 | − ret = devm_add_action(&pdev->dev, sc27xx_adc_disable, sc27xx_data); | |
| 563 | + ret = devm_add_action_or_reset(dev, sc27xx_adc_disable, sc27xx_data); | |
| 566 | 564 | if (ret) { |
| 567 | − sc27xx_adc_disable(sc27xx_data); | |
| 568 | − dev_err(&pdev->dev, "failed to add ADC disable action\n"); | |
| 565 | + dev_err(dev, "failed to add ADC disable action\n"); | |
| 569 | 566 | return ret; |
| 570 | 567 | } |
| 571 | 568 | |
| 572 | − ret = devm_request_threaded_irq(&pdev->dev, sc27xx_data->irq, NULL, | |
| 569 | + ret = devm_request_threaded_irq(dev, sc27xx_data->irq, NULL, | |
| 573 | 570 | sc27xx_adc_isr, IRQF_ONESHOT, |
| 574 | 571 | pdev->name, sc27xx_data); |
| 575 | 572 | if (ret) { |
| 576 | − dev_err(&pdev->dev, "failed to request ADC irq\n"); | |
| 573 | + dev_err(dev, "failed to request ADC irq\n"); | |
| 577 | 574 | return ret; |
| 578 | 575 | } |
| 579 | 576 | |
| 580 | − indio_dev->dev.parent = &pdev->dev; | |
| 581 | − indio_dev->name = dev_name(&pdev->dev); | |
| 577 | + indio_dev->dev.parent = dev; | |
| 578 | + indio_dev->name = dev_name(dev); | |
| 582 | 579 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 583 | 580 | indio_dev->info = &sc27xx_info; |
| 584 | 581 | indio_dev->channels = sc27xx_channels; |
| 585 | 582 | indio_dev->num_channels = ARRAY_SIZE(sc27xx_channels); |
| 586 | − ret = devm_iio_device_register(&pdev->dev, indio_dev); | |
| 583 | + ret = devm_iio_device_register(dev, indio_dev); | |
| 587 | 584 | if (ret) |
| 588 | − dev_err(&pdev->dev, "could not register iio (ADC)"); | |
| 585 | + dev_err(dev, "could not register iio (ADC)"); | |
| 589 | 586 | |
| 590 | 587 | return ret; |
| 591 | 588 | } |
| @@ -301,7 +301,6 @@ static int spear_adc_probe(struct platform_device *pdev) · 300 unmodified lines | ||
| 301 | 301 | |
| 302 | 302 | irq = platform_get_irq(pdev, 0); |
| 303 | 303 | if (irq <= 0) { |
| 304 | − dev_err(dev, "failed getting interrupt resource\n"); | |
| 305 | 304 | ret = -EINVAL; |
| 306 | 305 | goto errout2; |
| 307 | 306 | } |
| @@ -14,9 +14,11 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/irqchip/chained_irq.h> |
| 15 | 15 | #include <linux/irqdesc.h> |
| 16 | 16 | #include <linux/irqdomain.h> |
| 17 | +#include <linux/mfd/syscon.h> | |
| 17 | 18 | #include <linux/module.h> |
| 18 | 19 | #include <linux/of_device.h> |
| 19 | 20 | #include <linux/pm_runtime.h> |
| 21 | +#include <linux/regmap.h> | |
| 20 | 22 | #include <linux/regulator/consumer.h> |
| 21 | 23 | #include <linux/slab.h> |
| 22 | 24 | |
| @@ -51,6 +53,17 @@ · 28 unmodified lines | ||
| 51 | 53 | |
| 52 | 54 | #define STM32_ADC_CORE_SLEEP_DELAY_MS 2000 |
| 53 | 55 | |
| 56 | +/* SYSCFG registers */ | |
| 57 | +#define STM32MP1_SYSCFG_PMCSETR 0x04 | |
| 58 | +#define STM32MP1_SYSCFG_PMCCLRR 0x44 | |
| 59 | + | |
| 60 | +/* SYSCFG bit fields */ | |
| 61 | +#define STM32MP1_SYSCFG_ANASWVDD_MASK BIT(9) | |
| 62 | + | |
| 63 | +/* SYSCFG capability flags */ | |
| 64 | +#define HAS_VBOOSTER BIT(0) | |
| 65 | +#define HAS_ANASWVDD BIT(1) | |
| 66 | + | |
| 54 | 67 | /** |
| 55 | 68 | * stm32_adc_common_regs - stm32 common registers, compatible dependent data |
| 56 | 69 | * @csr: common status register offset |
| @@ -74,11 +87,13 @@ struct stm32_adc_priv; · 17 unmodified lines | ||
| 74 | 87 | * @regs: common registers for all instances |
| 75 | 88 | * @clk_sel: clock selection routine |
| 76 | 89 | * @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet) |
| 90 | + * @has_syscfg: SYSCFG capability flags | |
| 77 | 91 | */ |
| 78 | 92 | struct stm32_adc_priv_cfg { |
| 79 | 93 | const struct stm32_adc_common_regs *regs; |
| 80 | 94 | int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *); |
| 81 | 95 | u32 max_clk_rate_hz; |
| 96 | + unsigned int has_syscfg; | |
| 82 | 97 | }; |
| 83 | 98 | |
| 84 | 99 | /** |
| @@ -87,22 +102,32 @@ struct stm32_adc_priv_cfg { · 2 unmodified lines | ||
| 87 | 102 | * @domain: irq domain reference |
| 88 | 103 | * @aclk: clock reference for the analog circuitry |
| 89 | 104 | * @bclk: bus clock common for all ADCs, depends on part used |
| 105 | + * @booster: booster supply reference | |
| 106 | + * @vdd: vdd supply reference | |
| 90 | 107 | * @vdda: vdda analog supply reference |
| 91 | 108 | * @vref: regulator reference |
| 109 | + * @vdd_uv: vdd supply voltage (microvolts) | |
| 110 | + * @vdda_uv: vdda supply voltage (microvolts) | |
| 92 | 111 | * @cfg: compatible configuration data |
| 93 | 112 | * @common: common data for all ADC instances |
| 94 | 113 | * @ccr_bak: backup CCR in low power mode |
| 114 | + * @syscfg: reference to syscon, system control registers | |
| 95 | 115 | */ |
| 96 | 116 | struct stm32_adc_priv { |
| 97 | 117 | int irq[STM32_ADC_MAX_ADCS]; |
| 98 | 118 | struct irq_domain *domain; |
| 99 | 119 | struct clk *aclk; |
| 100 | 120 | struct clk *bclk; |
| 121 | + struct regulator *booster; | |
| 122 | + struct regulator *vdd; | |
| 101 | 123 | struct regulator *vdda; |
| 102 | 124 | struct regulator *vref; |
| 125 | + int vdd_uv; | |
| 126 | + int vdda_uv; | |
| 103 | 127 | const struct stm32_adc_priv_cfg *cfg; |
| 104 | 128 | struct stm32_adc_common common; |
| 105 | 129 | u32 ccr_bak; |
| 130 | + struct regmap *syscfg; | |
| 106 | 131 | }; |
| 107 | 132 | |
| 108 | 133 | static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com) |
| @@ -349,7 +374,6 @@ static int stm32_adc_irq_probe(struct platform_device *pdev, · 240 unmodified lines | ||
| 349 | 374 | */ |
| 350 | 375 | if (i && priv->irq[i] == -ENXIO) |
| 351 | 376 | continue; |
| 352 | − dev_err(&pdev->dev, "failed to get irq\n"); | |
| 353 | 377 | |
| 354 | 378 | return priv->irq[i]; |
| 355 | 379 | } |
| @@ -390,6 +414,82 @@ static void stm32_adc_irq_remove(struct platform_device *pdev, · 34 unmodified lines | ||
| 390 | 414 | } |
| 391 | 415 | } |
| 392 | 416 | |
| 417 | +static int stm32_adc_core_switches_supply_en(struct stm32_adc_priv *priv, | |
| 418 | + struct device *dev) | |
| 419 | +{ | |
| 420 | + int ret; | |
| 421 | + | |
| 422 | + /* | |
| 423 | + * On STM32H7 and STM32MP1, the ADC inputs are multiplexed with analog | |
| 424 | + * switches (via PCSEL) which have reduced performances when their | |
| 425 | + * supply is below 2.7V (vdda by default): | |
| 426 | + * - Voltage booster can be used, to get full ADC performances | |
| 427 | + * (increases power consumption). | |
| 428 | + * - Vdd can be used to supply them, if above 2.7V (STM32MP1 only). | |
| 429 | + * | |
| 430 | + * Recommended settings for ANASWVDD and EN_BOOSTER: | |
| 431 | + * - vdda < 2.7V but vdd > 2.7V: ANASWVDD = 1, EN_BOOSTER = 0 (stm32mp1) | |
| 432 | + * - vdda < 2.7V and vdd < 2.7V: ANASWVDD = 0, EN_BOOSTER = 1 | |
| 433 | + * - vdda >= 2.7V: ANASWVDD = 0, EN_BOOSTER = 0 (default) | |
| 434 | + */ | |
| 435 | + if (priv->vdda_uv < 2700000) { | |
| 436 | + if (priv->syscfg && priv->vdd_uv > 2700000) { | |
| 437 | + ret = regulator_enable(priv->vdd); | |
| 438 | + if (ret < 0) { | |
| 439 | + dev_err(dev, "vdd enable failed %d\n", ret); | |
| 440 | + return ret; | |
| 441 | + } | |
| 442 | + | |
| 443 | + ret = regmap_write(priv->syscfg, | |
| 444 | + STM32MP1_SYSCFG_PMCSETR, | |
| 445 | + STM32MP1_SYSCFG_ANASWVDD_MASK); | |
| 446 | + if (ret < 0) { | |
| 447 | + regulator_disable(priv->vdd); | |
| 448 | + dev_err(dev, "vdd select failed, %d\n", ret); | |
| 449 | + return ret; | |
| 450 | + } | |
| 451 | + dev_dbg(dev, "analog switches supplied by vdd\n"); | |
| 452 | + | |
| 453 | + return 0; | |
| 454 | + } | |
| 455 | + | |
| 456 | + if (priv->booster) { | |
| 457 | + /* | |
| 458 | + * This is optional, as this is a trade-off between | |
| 459 | + * analog performance and power consumption. | |
| 460 | + */ | |
| 461 | + ret = regulator_enable(priv->booster); | |
| 462 | + if (ret < 0) { | |
| 463 | + dev_err(dev, "booster enable failed %d\n", ret); | |
| 464 | + return ret; | |
| 465 | + } | |
| 466 | + dev_dbg(dev, "analog switches supplied by booster\n"); | |
| 467 | + | |
| 468 | + return 0; | |
| 469 | + } | |
| 470 | + } | |
| 471 | + | |
| 472 | + /* Fallback using vdda (default), nothing to do */ | |
| 473 | + dev_dbg(dev, "analog switches supplied by vdda (%d uV)\n", | |
| 474 | + priv->vdda_uv); | |
| 475 | + | |
| 476 | + return 0; | |
| 477 | +} | |
| 478 | + | |
| 479 | +static void stm32_adc_core_switches_supply_dis(struct stm32_adc_priv *priv) | |
| 480 | +{ | |
| 481 | + if (priv->vdda_uv < 2700000) { | |
| 482 | + if (priv->syscfg && priv->vdd_uv > 2700000) { | |
| 483 | + regmap_write(priv->syscfg, STM32MP1_SYSCFG_PMCCLRR, | |
| 484 | + STM32MP1_SYSCFG_ANASWVDD_MASK); | |
| 485 | + regulator_disable(priv->vdd); | |
| 486 | + return; | |
| 487 | + } | |
| 488 | + if (priv->booster) | |
| 489 | + regulator_disable(priv->booster); | |
| 490 | + } | |
| 491 | +} | |
| 492 | + | |
| 393 | 493 | static int stm32_adc_core_hw_start(struct device *dev) |
| 394 | 494 | { |
| 395 | 495 | struct stm32_adc_common *common = dev_get_drvdata(dev); |
| @@ -402,10 +502,21 @@ static int stm32_adc_core_hw_start(struct device *dev) · 6 unmodified lines | ||
| 402 | 502 | return ret; |
| 403 | 503 | } |
| 404 | 504 | |
| 505 | + ret = regulator_get_voltage(priv->vdda); | |
| 506 | + if (ret < 0) { | |
| 507 | + dev_err(dev, "vdda get voltage failed, %d\n", ret); | |
| 508 | + goto err_vdda_disable; | |
| 509 | + } | |
| 510 | + priv->vdda_uv = ret; | |
| 511 | + | |
| 512 | + ret = stm32_adc_core_switches_supply_en(priv, dev); | |
| 513 | + if (ret < 0) | |
| 514 | + goto err_vdda_disable; | |
| 515 | + | |
| 405 | 516 | ret = regulator_enable(priv->vref); |
| 406 | 517 | if (ret < 0) { |
| 407 | 518 | dev_err(dev, "vref enable failed\n"); |
| 408 | − goto err_vdda_disable; | |
| 519 | + goto err_switches_dis; | |
| 409 | 520 | } |
| 410 | 521 | |
| 411 | 522 | if (priv->bclk) { |
| @@ -433,6 +544,8 @@ err_bclk_disable: · 21 unmodified lines | ||
| 433 | 544 | clk_disable_unprepare(priv->bclk); |
| 434 | 545 | err_regulator_disable: |
| 435 | 546 | regulator_disable(priv->vref); |
| 547 | +err_switches_dis: | |
| 548 | + stm32_adc_core_switches_supply_dis(priv); | |
| 436 | 549 | err_vdda_disable: |
| 437 | 550 | regulator_disable(priv->vdda); |
| 438 | 551 | |
| @@ -451,9 +564,80 @@ static void stm32_adc_core_hw_stop(struct device *dev) · 12 unmodified lines | ||
| 451 | 564 | if (priv->bclk) |
| 452 | 565 | clk_disable_unprepare(priv->bclk); |
| 453 | 566 | regulator_disable(priv->vref); |
| 567 | + stm32_adc_core_switches_supply_dis(priv); | |
| 454 | 568 | regulator_disable(priv->vdda); |
| 455 | 569 | } |
| 456 | 570 | |
| 571 | +static int stm32_adc_core_switches_probe(struct device *dev, | |
| 572 | + struct stm32_adc_priv *priv) | |
| 573 | +{ | |
| 574 | + struct device_node *np = dev->of_node; | |
| 575 | + int ret; | |
| 576 | + | |
| 577 | + /* Analog switches supply can be controlled by syscfg (optional) */ | |
| 578 | + priv->syscfg = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); | |
| 579 | + if (IS_ERR(priv->syscfg)) { | |
| 580 | + ret = PTR_ERR(priv->syscfg); | |
| 581 | + if (ret != -ENODEV) { | |
| 582 | + if (ret != -EPROBE_DEFER) | |
| 583 | + dev_err(dev, "Can't probe syscfg: %d\n", ret); | |
| 584 | + return ret; | |
| 585 | + } | |
| 586 | + priv->syscfg = NULL; | |
| 587 | + } | |
| 588 | + | |
| 589 | + /* Booster can be used to supply analog switches (optional) */ | |
| 590 | + if (priv->cfg->has_syscfg & HAS_VBOOSTER && | |
| 591 | + of_property_read_bool(np, "booster-supply")) { | |
| 592 | + priv->booster = devm_regulator_get_optional(dev, "booster"); | |
| 593 | + if (IS_ERR(priv->booster)) { | |
| 594 | + ret = PTR_ERR(priv->booster); | |
| 595 | + if (ret != -ENODEV) { | |
| 596 | + if (ret != -EPROBE_DEFER) | |
| 597 | + dev_err(dev, "can't get booster %d\n", | |
| 598 | + ret); | |
| 599 | + return ret; | |
| 600 | + } | |
| 601 | + priv->booster = NULL; | |
| 602 | + } | |
| 603 | + } | |
| 604 | + | |
| 605 | + /* Vdd can be used to supply analog switches (optional) */ | |
| 606 | + if (priv->cfg->has_syscfg & HAS_ANASWVDD && | |
| 607 | + of_property_read_bool(np, "vdd-supply")) { | |
| 608 | + priv->vdd = devm_regulator_get_optional(dev, "vdd"); | |
| 609 | + if (IS_ERR(priv->vdd)) { | |
| 610 | + ret = PTR_ERR(priv->vdd); | |
| 611 | + if (ret != -ENODEV) { | |
| 612 | + if (ret != -EPROBE_DEFER) | |
| 613 | + dev_err(dev, "can't get vdd %d\n", ret); | |
| 614 | + return ret; | |
| 615 | + } | |
| 616 | + priv->vdd = NULL; | |
| 617 | + } | |
| 618 | + } | |
| 619 | + | |
| 620 | + if (priv->vdd) { | |
| 621 | + ret = regulator_enable(priv->vdd); | |
| 622 | + if (ret < 0) { | |
| 623 | + dev_err(dev, "vdd enable failed %d\n", ret); | |
| 624 | + return ret; | |
| 625 | + } | |
| 626 | + | |
| 627 | + ret = regulator_get_voltage(priv->vdd); | |
| 628 | + if (ret < 0) { | |
| 629 | + dev_err(dev, "vdd get voltage failed %d\n", ret); | |
| 630 | + regulator_disable(priv->vdd); | |
| 631 | + return ret; | |
| 632 | + } | |
| 633 | + priv->vdd_uv = ret; | |
| 634 | + | |
| 635 | + regulator_disable(priv->vdd); | |
| 636 | + } | |
| 637 | + | |
| 638 | + return 0; | |
| 639 | +} | |
| 640 | + | |
| 457 | 641 | static int stm32_adc_probe(struct platform_device *pdev) |
| 458 | 642 | { |
| 459 | 643 | struct stm32_adc_priv *priv; |
| @@ -514,6 +698,10 @@ static int stm32_adc_probe(struct platform_device *pdev) · 54 unmodified lines | ||
| 514 | 698 | priv->bclk = NULL; |
| 515 | 699 | } |
| 516 | 700 | |
| 701 | + ret = stm32_adc_core_switches_probe(dev, priv); | |
| 702 | + if (ret) | |
| 703 | + return ret; | |
| 704 | + | |
| 517 | 705 | pm_runtime_get_noresume(dev); |
| 518 | 706 | pm_runtime_set_active(dev); |
| 519 | 707 | pm_runtime_set_autosuspend_delay(dev, STM32_ADC_CORE_SLEEP_DELAY_MS); |
| @@ -611,12 +799,14 @@ static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = { · 91 unmodified lines | ||
| 611 | 799 | .regs = &stm32h7_adc_common_regs, |
| 612 | 800 | .clk_sel = stm32h7_adc_clk_sel, |
| 613 | 801 | .max_clk_rate_hz = 36000000, |
| 802 | + .has_syscfg = HAS_VBOOSTER, | |
| 614 | 803 | }; |
| 615 | 804 | |
| 616 | 805 | static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = { |
| 617 | 806 | .regs = &stm32h7_adc_common_regs, |
| 618 | 807 | .clk_sel = stm32h7_adc_clk_sel, |
| 619 | 808 | .max_clk_rate_hz = 40000000, |
| 809 | + .has_syscfg = HAS_VBOOSTER | HAS_ANASWVDD, | |
| 620 | 810 | }; |
| 621 | 811 | |
| 622 | 812 | static const struct of_device_id stm32_adc_of_match[] = { |
| @@ -1919,10 +1919,8 @@ static int stm32_adc_probe(struct platform_device *pdev) · 1918 unmodified lines | ||
| 1919 | 1919 | } |
| 1920 | 1920 | |
| 1921 | 1921 | adc->irq = platform_get_irq(pdev, 0); |
| 1922 | − if (adc->irq < 0) { | |
| 1923 | − dev_err(&pdev->dev, "failed to get irq\n"); | |
| 1922 | + if (adc->irq < 0) | |
| 1924 | 1923 | return adc->irq; |
| 1925 | − } | |
| 1926 | 1924 | |
| 1927 | 1925 | ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr, |
| 1928 | 1926 | 0, pdev->name, adc); |
| @@ -1601,11 +1601,8 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev) · 1600 unmodified lines | ||
| 1601 | 1601 | * So IRQ associated to filter instance 0 is dedicated to the Filter 0. |
| 1602 | 1602 | */ |
| 1603 | 1603 | irq = platform_get_irq(pdev, 0); |
| 1604 | − if (irq < 0) { | |
| 1605 | − if (irq != -EPROBE_DEFER) | |
| 1606 | − dev_err(dev, "Failed to get IRQ: %d\n", irq); | |
| 1604 | + if (irq < 0) | |
| 1607 | 1605 | return irq; |
| 1608 | − } | |
| 1609 | 1606 | |
| 1610 | 1607 | ret = devm_request_irq(dev, irq, stm32_dfsdm_irq, |
| 1611 | 1608 | 0, pdev->name, adc); |
| @@ -460,10 +460,8 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name, · 459 unmodified lines | ||
| 460 | 460 | atomic_set(atomic, 1); |
| 461 | 461 | |
| 462 | 462 | ret = platform_get_irq_byname(pdev, name); |
| 463 | − if (ret < 0) { | |
| 464 | − dev_err(&pdev->dev, "no %s interrupt registered\n", name); | |
| 463 | + if (ret < 0) | |
| 465 | 464 | return ret; |
| 466 | − } | |
| 467 | 465 | |
| 468 | 466 | ret = regmap_irq_get_virq(mfd_dev->regmap_irqc, ret); |
| 469 | 467 | if (ret < 0) { |
| @@ -905,10 +905,8 @@ static int twl6030_gpadc_probe(struct platform_device *pdev) · 904 unmodified lines | ||
| 905 | 905 | } |
| 906 | 906 | |
| 907 | 907 | irq = platform_get_irq(pdev, 0); |
| 908 | − if (irq < 0) { | |
| 909 | − dev_err(&pdev->dev, "failed to get irq\n"); | |
| 908 | + if (irq < 0) | |
| 910 | 909 | return irq; |
| 911 | − } | |
| 912 | 910 | |
| 913 | 911 | ret = devm_request_threaded_irq(dev, irq, NULL, |
| 914 | 912 | twl6030_gpadc_irq_handler, |
| @@ -821,10 +821,8 @@ static int vf610_adc_probe(struct platform_device *pdev) · 820 unmodified lines | ||
| 821 | 821 | return PTR_ERR(info->regs); |
| 822 | 822 | |
| 823 | 823 | irq = platform_get_irq(pdev, 0); |
| 824 | − if (irq < 0) { | |
| 825 | − dev_err(&pdev->dev, "no irq resource?\n"); | |
| 824 | + if (irq < 0) | |
| 826 | 825 | return irq; |
| 827 | − } | |
| 828 | 826 | |
| 829 | 827 | ret = devm_request_irq(info->dev, irq, |
| 830 | 828 | vf610_adc_isr, 0, |
| @@ -63,10 +63,35 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev, · 62 unmodified lines | ||
| 63 | 63 | |
| 64 | 64 | /* Save values */ |
| 65 | 65 | for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) |
| 66 | − st->core.calib[i] = | |
| 66 | + st->core.calib[i].offset = | |
| 67 | 67 | st->core.resp->sensor_offset.offset[i]; |
| 68 | 68 | ret = IIO_VAL_INT; |
| 69 | − *val = st->core.calib[idx]; | |
| 69 | + *val = st->core.calib[idx].offset; | |
| 70 | + break; | |
| 71 | + case IIO_CHAN_INFO_CALIBSCALE: | |
| 72 | + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE; | |
| 73 | + st->core.param.sensor_offset.flags = 0; | |
| 74 | + | |
| 75 | + ret = cros_ec_motion_send_host_cmd(&st->core, 0); | |
| 76 | + if (ret == -EPROTO) { | |
| 77 | + /* Reading calibscale is not supported on older EC. */ | |
| 78 | + *val = 1; | |
| 79 | + *val2 = 0; | |
| 80 | + ret = IIO_VAL_INT_PLUS_MICRO; | |
| 81 | + break; | |
| 82 | + } else if (ret) { | |
| 83 | + break; | |
| 84 | + } | |
| 85 | + | |
| 86 | + /* Save values */ | |
| 87 | + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) | |
| 88 | + st->core.calib[i].scale = | |
| 89 | + st->core.resp->sensor_scale.scale[i]; | |
| 90 | + | |
| 91 | + *val = st->core.calib[idx].scale >> 15; | |
| 92 | + *val2 = ((st->core.calib[idx].scale & 0x7FFF) * 1000000LL) / | |
| 93 | + MOTION_SENSE_DEFAULT_SCALE; | |
| 94 | + ret = IIO_VAL_INT_PLUS_MICRO; | |
| 70 | 95 | break; |
| 71 | 96 | case IIO_CHAN_INFO_SCALE: |
| 72 | 97 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; |
| @@ -134,7 +159,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, · 61 unmodified lines | ||
| 134 | 159 | |
| 135 | 160 | switch (mask) { |
| 136 | 161 | case IIO_CHAN_INFO_CALIBBIAS: |
| 137 | − st->core.calib[idx] = val; | |
| 162 | + st->core.calib[idx].offset = val; | |
| 138 | 163 | |
| 139 | 164 | /* Send to EC for each axis, even if not complete */ |
| 140 | 165 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; |
| @@ -142,10 +167,25 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, · 1 unmodified line | ||
| 142 | 167 | MOTION_SENSE_SET_OFFSET; |
| 143 | 168 | for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) |
| 144 | 169 | st->core.param.sensor_offset.offset[i] = |
| 145 | − st->core.calib[i]; | |
| 170 | + st->core.calib[i].offset; | |
| 146 | 171 | st->core.param.sensor_offset.temp = |
| 147 | 172 | EC_MOTION_SENSE_INVALID_CALIB_TEMP; |
| 148 | 173 | |
| 174 | + ret = cros_ec_motion_send_host_cmd(&st->core, 0); | |
| 175 | + break; | |
| 176 | + case IIO_CHAN_INFO_CALIBSCALE: | |
| 177 | + st->core.calib[idx].scale = val; | |
| 178 | + /* Send to EC for each axis, even if not complete */ | |
| 179 | + | |
| 180 | + st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE; | |
| 181 | + st->core.param.sensor_offset.flags = | |
| 182 | + MOTION_SENSE_SET_OFFSET; | |
| 183 | + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) | |
| 184 | + st->core.param.sensor_scale.scale[i] = | |
| 185 | + st->core.calib[i].scale; | |
| 186 | + st->core.param.sensor_scale.temp = | |
| 187 | + EC_MOTION_SENSE_INVALID_CALIB_TEMP; | |
| 188 | + | |
| 149 | 189 | ret = cros_ec_motion_send_host_cmd(&st->core, 0); |
| 150 | 190 | break; |
| 151 | 191 | case IIO_CHAN_INFO_SCALE: |
| @@ -175,6 +215,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev, · 23 unmodified lines | ||
| 175 | 215 | static const struct iio_info ec_sensors_info = { |
| 176 | 216 | .read_raw = &cros_ec_sensors_read, |
| 177 | 217 | .write_raw = &cros_ec_sensors_write, |
| 218 | + .read_avail = &cros_ec_sensors_core_read_avail, | |
| 178 | 219 | }; |
| 179 | 220 | |
| 180 | 221 | static int cros_ec_sensors_probe(struct platform_device *pdev) |
| @@ -206,11 +247,14 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) · 25 unmodified lines | ||
| 206 | 247 | /* Common part */ |
| 207 | 248 | channel->info_mask_separate = |
| 208 | 249 | BIT(IIO_CHAN_INFO_RAW) | |
| 209 | − BIT(IIO_CHAN_INFO_CALIBBIAS); | |
| 250 | + BIT(IIO_CHAN_INFO_CALIBBIAS) | | |
| 251 | + BIT(IIO_CHAN_INFO_CALIBSCALE); | |
| 210 | 252 | channel->info_mask_shared_by_all = |
| 211 | 253 | BIT(IIO_CHAN_INFO_SCALE) | |
| 212 | 254 | BIT(IIO_CHAN_INFO_FREQUENCY) | |
| 213 | 255 | BIT(IIO_CHAN_INFO_SAMP_FREQ); |
| 256 | + channel->info_mask_shared_by_all_available = | |
| 257 | + BIT(IIO_CHAN_INFO_SAMP_FREQ); | |
| 214 | 258 | channel->scan_type.realbits = CROS_EC_SENSOR_BITS; |
| 215 | 259 | channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; |
| 216 | 260 | channel->scan_index = i; |
| @@ -25,6 +25,62 @@ static char *cros_ec_loc[] = { · 24 unmodified lines | ||
| 25 | 25 | [MOTIONSENSE_LOC_MAX] = "unknown", |
| 26 | 26 | }; |
| 27 | 27 | |
| 28 | +static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev, | |
| 29 | + u16 cmd_offset, u16 cmd, u32 *mask) | |
| 30 | +{ | |
| 31 | + int ret; | |
| 32 | + struct { | |
| 33 | + struct cros_ec_command msg; | |
| 34 | + union { | |
| 35 | + struct ec_params_get_cmd_versions params; | |
| 36 | + struct ec_response_get_cmd_versions resp; | |
| 37 | + }; | |
| 38 | + } __packed buf = { | |
| 39 | + .msg = { | |
| 40 | + .command = EC_CMD_GET_CMD_VERSIONS + cmd_offset, | |
| 41 | + .insize = sizeof(struct ec_response_get_cmd_versions), | |
| 42 | + .outsize = sizeof(struct ec_params_get_cmd_versions) | |
| 43 | + }, | |
| 44 | + .params = {.cmd = cmd} | |
| 45 | + }; | |
| 46 | + | |
| 47 | + ret = cros_ec_cmd_xfer_status(ec_dev, &buf.msg); | |
| 48 | + if (ret >= 0) | |
| 49 | + *mask = buf.resp.version_mask; | |
| 50 | + return ret; | |
| 51 | +} | |
| 52 | + | |
| 53 | +static void get_default_min_max_freq(enum motionsensor_type type, | |
| 54 | + u32 *min_freq, | |
| 55 | + u32 *max_freq) | |
| 56 | +{ | |
| 57 | + switch (type) { | |
| 58 | + case MOTIONSENSE_TYPE_ACCEL: | |
| 59 | + case MOTIONSENSE_TYPE_GYRO: | |
| 60 | + *min_freq = 12500; | |
| 61 | + *max_freq = 100000; | |
| 62 | + break; | |
| 63 | + case MOTIONSENSE_TYPE_MAG: | |
| 64 | + *min_freq = 5000; | |
| 65 | + *max_freq = 25000; | |
| 66 | + break; | |
| 67 | + case MOTIONSENSE_TYPE_PROX: | |
| 68 | + case MOTIONSENSE_TYPE_LIGHT: | |
| 69 | + *min_freq = 100; | |
| 70 | + *max_freq = 50000; | |
| 71 | + break; | |
| 72 | + case MOTIONSENSE_TYPE_BARO: | |
| 73 | + *min_freq = 250; | |
| 74 | + *max_freq = 20000; | |
| 75 | + break; | |
| 76 | + case MOTIONSENSE_TYPE_ACTIVITY: | |
| 77 | + default: | |
| 78 | + *min_freq = 0; | |
| 79 | + *max_freq = 0; | |
| 80 | + break; | |
| 81 | + } | |
| 82 | +} | |
| 83 | + | |
| 28 | 84 | int cros_ec_sensors_core_init(struct platform_device *pdev, |
| 29 | 85 | struct iio_dev *indio_dev, |
| 30 | 86 | bool physical_device) |
| @@ -33,6 +89,8 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, · 2 unmodified lines | ||
| 33 | 89 | struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); |
| 34 | 90 | struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent); |
| 35 | 91 | struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); |
| 92 | + u32 ver_mask; | |
| 93 | + int ret; | |
| 36 | 94 | |
| 37 | 95 | platform_set_drvdata(pdev, indio_dev); |
| 38 | 96 | |
| @@ -47,8 +105,15 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, · 8 unmodified lines | ||
| 47 | 105 | |
| 48 | 106 | mutex_init(&state->cmd_lock); |
| 49 | 107 | |
| 108 | + ret = cros_ec_get_host_cmd_version_mask(state->ec, | |
| 109 | + ec->cmd_offset, | |
| 110 | + EC_CMD_MOTION_SENSE_CMD, | |
| 111 | + &ver_mask); | |
| 112 | + if (ret < 0) | |
| 113 | + return ret; | |
| 114 | + | |
| 50 | 115 | /* Set up the host command structure. */ |
| 51 | − state->msg->version = 2; | |
| 116 | + state->msg->version = fls(ver_mask) - 1; | |
| 52 | 117 | state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; |
| 53 | 118 | state->msg->outsize = sizeof(struct ec_params_motion_sense); |
| 54 | 119 | |
| @@ -60,12 +125,29 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, · 5 unmodified lines | ||
| 60 | 125 | |
| 61 | 126 | state->param.cmd = MOTIONSENSE_CMD_INFO; |
| 62 | 127 | state->param.info.sensor_num = sensor_platform->sensor_num; |
| 63 | − if (cros_ec_motion_send_host_cmd(state, 0)) { | |
| 128 | + ret = cros_ec_motion_send_host_cmd(state, 0); | |
| 129 | + if (ret) { | |
| 64 | 130 | dev_warn(dev, "Can not access sensor info\n"); |
| 65 | − return -EIO; | |
| 131 | + return ret; | |
| 66 | 132 | } |
| 67 | 133 | state->type = state->resp->info.type; |
| 68 | 134 | state->loc = state->resp->info.location; |
| 135 | + | |
| 136 | + /* Set sign vector, only used for backward compatibility. */ | |
| 137 | + memset(state->sign, 1, CROS_EC_SENSOR_MAX_AXIS); | |
| 138 | + | |
| 139 | + /* 0 is a correct value used to stop the device */ | |
| 140 | + state->frequencies[0] = 0; | |
| 141 | + if (state->msg->version < 3) { | |
| 142 | + get_default_min_max_freq(state->resp->info.type, | |
| 143 | + &state->frequencies[1], | |
| 144 | + &state->frequencies[2]); | |
| 145 | + } else { | |
| 146 | + state->frequencies[1] = | |
| 147 | + state->resp->info_3.min_frequency; | |
| 148 | + state->frequencies[2] = | |
| 149 | + state->resp->info_3.max_frequency; | |
| 150 | + } | |
| 69 | 151 | } |
| 70 | 152 | |
| 71 | 153 | return 0; |
| @@ -86,7 +168,7 @@ int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state, · 14 unmodified lines | ||
| 86 | 168 | |
| 87 | 169 | ret = cros_ec_cmd_xfer_status(state->ec, state->msg); |
| 88 | 170 | if (ret < 0) |
| 89 | − return -EIO; | |
| 171 | + return ret; | |
| 90 | 172 | |
| 91 | 173 | if (ret && |
| 92 | 174 | state->resp != (struct ec_response_motion_sense *)state->msg->data) |
| @@ -118,7 +200,7 @@ static ssize_t cros_ec_sensors_calibrate(struct iio_dev *indio_dev, · 25 unmodified lines | ||
| 118 | 200 | } else { |
| 119 | 201 | /* Save values */ |
| 120 | 202 | for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) |
| 121 | − st->calib[i] = st->resp->perform_calib.offset[i]; | |
| 203 | + st->calib[i].offset = st->resp->perform_calib.offset[i]; | |
| 122 | 204 | } |
| 123 | 205 | mutex_unlock(&st->cmd_lock); |
| 124 | 206 | |
| @@ -268,6 +350,7 @@ static int cros_ec_sensors_read_data_unsafe(struct iio_dev *indio_dev, · 143 unmodified lines | ||
| 268 | 350 | if (ret < 0) |
| 269 | 351 | return ret; |
| 270 | 352 | |
| 353 | + *data *= st->sign[i]; | |
| 271 | 354 | data++; |
| 272 | 355 | } |
| 273 | 356 | |
| @@ -396,7 +479,7 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, · 122 unmodified lines | ||
| 396 | 479 | struct iio_chan_spec const *chan, |
| 397 | 480 | int *val, int *val2, long mask) |
| 398 | 481 | { |
| 399 | − int ret = IIO_VAL_INT; | |
| 482 | + int ret; | |
| 400 | 483 | |
| 401 | 484 | switch (mask) { |
| 402 | 485 | case IIO_CHAN_INFO_SAMP_FREQ: |
| @@ -404,22 +487,27 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, · 1 unmodified line | ||
| 404 | 487 | st->param.ec_rate.data = |
| 405 | 488 | EC_MOTION_SENSE_NO_VALUE; |
| 406 | 489 | |
| 407 | − if (cros_ec_motion_send_host_cmd(st, 0)) | |
| 408 | − ret = -EIO; | |
| 409 | − else | |
| 410 | − *val = st->resp->ec_rate.ret; | |
| 490 | + ret = cros_ec_motion_send_host_cmd(st, 0); | |
| 491 | + if (ret) | |
| 492 | + break; | |
| 493 | + | |
| 494 | + *val = st->resp->ec_rate.ret; | |
| 495 | + ret = IIO_VAL_INT; | |
| 411 | 496 | break; |
| 412 | 497 | case IIO_CHAN_INFO_FREQUENCY: |
| 413 | 498 | st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR; |
| 414 | 499 | st->param.sensor_odr.data = |
| 415 | 500 | EC_MOTION_SENSE_NO_VALUE; |
| 416 | 501 | |
| 417 | − if (cros_ec_motion_send_host_cmd(st, 0)) | |
| 418 | − ret = -EIO; | |
| 419 | − else | |
| 420 | − *val = st->resp->sensor_odr.ret; | |
| 502 | + ret = cros_ec_motion_send_host_cmd(st, 0); | |
| 503 | + if (ret) | |
| 504 | + break; | |
| 505 | + | |
| 506 | + *val = st->resp->sensor_odr.ret; | |
| 507 | + ret = IIO_VAL_INT; | |
| 421 | 508 | break; |
| 422 | 509 | default: |
| 510 | + ret = -EINVAL; | |
| 423 | 511 | break; |
| 424 | 512 | } |
| 425 | 513 | |
| @@ -427,11 +515,32 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, · 1 unmodified line | ||
| 427 | 515 | } |
| 428 | 516 | EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read); |
| 429 | 517 | |
| 518 | +int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev, | |
| 519 | + struct iio_chan_spec const *chan, | |
| 520 | + const int **vals, | |
| 521 | + int *type, | |
| 522 | + int *length, | |
| 523 | + long mask) | |
| 524 | +{ | |
| 525 | + struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); | |
| 526 | + | |
| 527 | + switch (mask) { | |
| 528 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 529 | + *length = ARRAY_SIZE(state->frequencies); | |
| 530 | + *vals = (const int *)&state->frequencies; | |
| 531 | + *type = IIO_VAL_INT; | |
| 532 | + return IIO_AVAIL_LIST; | |
| 533 | + } | |
| 534 | + | |
| 535 | + return -EINVAL; | |
| 536 | +} | |
| 537 | +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read_avail); | |
| 538 | + | |
| 430 | 539 | int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, |
| 431 | 540 | struct iio_chan_spec const *chan, |
| 432 | 541 | int val, int val2, long mask) |
| 433 | 542 | { |
| 434 | − int ret = 0; | |
| 543 | + int ret; | |
| 435 | 544 | |
| 436 | 545 | switch (mask) { |
| 437 | 546 | case IIO_CHAN_INFO_FREQUENCY: |
| @@ -441,17 +550,16 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, · 3 unmodified lines | ||
| 441 | 550 | /* Always roundup, so caller gets at least what it asks for. */ |
| 442 | 551 | st->param.sensor_odr.roundup = 1; |
| 443 | 552 | |
| 444 | − if (cros_ec_motion_send_host_cmd(st, 0)) | |
| 445 | − ret = -EIO; | |
| 553 | + ret = cros_ec_motion_send_host_cmd(st, 0); | |
| 446 | 554 | break; |
| 447 | 555 | case IIO_CHAN_INFO_SAMP_FREQ: |
| 448 | 556 | st->param.cmd = MOTIONSENSE_CMD_EC_RATE; |
| 449 | 557 | st->param.ec_rate.data = val; |
| 450 | 558 | |
| 451 | − if (cros_ec_motion_send_host_cmd(st, 0)) | |
| 452 | − ret = -EIO; | |
| 453 | − else | |
| 454 | − st->curr_sampl_freq = val; | |
| 559 | + ret = cros_ec_motion_send_host_cmd(st, 0); | |
| 560 | + if (ret) | |
| 561 | + break; | |
| 562 | + st->curr_sampl_freq = val; | |
| 455 | 563 | break; |
| 456 | 564 | default: |
| 457 | 565 | ret = -EINVAL; |
| @@ -17,15 +17,16 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <linux/iio/trigger_consumer.h> |
| 18 | 18 | #include <linux/iio/triggered_buffer.h> |
| 19 | 19 | #include <linux/irqreturn.h> |
| 20 | +#include <linux/regmap.h> | |
| 20 | 21 | |
| 21 | 22 | #include <linux/iio/common/st_sensors.h> |
| 22 | 23 | |
| 23 | 24 | |
| 24 | 25 | static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) |
| 25 | 26 | { |
| 26 | − int i; | |
| 27 | 27 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
| 28 | 28 | unsigned int num_data_channels = sdata->num_data_channels; |
| 29 | + int i; | |
| 29 | 30 | |
| 30 | 31 | for_each_set_bit(i, indio_dev->active_scan_mask, num_data_channels) { |
| 31 | 32 | const struct iio_chan_spec *channel = &indio_dev->channels[i]; |
| @@ -36,11 +37,8 @@ static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) · 4 unmodified lines | ||
| 36 | 37 | channel->scan_type.storagebits >> 3; |
| 37 | 38 | |
| 38 | 39 | buf = PTR_ALIGN(buf, storage_bytes); |
| 39 | − if (sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, | |
| 40 | − channel->address, | |
| 41 | − bytes_to_read, buf, | |
| 42 | − sdata->multiread_bit) < | |
| 43 | − bytes_to_read) | |
| 40 | + if (regmap_bulk_read(sdata->regmap, channel->address, | |
| 41 | + buf, bytes_to_read) < 0) | |
| 44 | 42 | return -EIO; |
| 45 | 43 | |
| 46 | 44 | /* Advance the buffer pointer */ |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/regulator/consumer.h> |
| 16 | 16 | #include <linux/of.h> |
| 17 | 17 | #include <linux/of_device.h> |
| 18 | +#include <linux/regmap.h> | |
| 18 | 19 | #include <asm/unaligned.h> |
| 19 | 20 | #include <linux/iio/common/st_sensors.h> |
| 20 | 21 | |
| @@ -28,19 +29,10 @@ static inline u32 st_sensors_get_unaligned_le24(const u8 *p) · 7 unmodified lines | ||
| 28 | 29 | int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, |
| 29 | 30 | u8 reg_addr, u8 mask, u8 data) |
| 30 | 31 | { |
| 31 | − int err; | |
| 32 | − u8 new_data; | |
| 33 | 32 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
| 34 | 33 | |
| 35 | − err = sdata->tf->read_byte(&sdata->tb, sdata->dev, reg_addr, &new_data); | |
| 36 | − if (err < 0) | |
| 37 | − goto st_sensors_write_data_with_mask_error; | |
| 38 | − | |
| 39 | − new_data = ((new_data & (~mask)) | ((data << __ffs(mask)) & mask)); | |
| 40 | − err = sdata->tf->write_byte(&sdata->tb, sdata->dev, reg_addr, new_data); | |
| 41 | − | |
| 42 | −st_sensors_write_data_with_mask_error: | |
| 43 | − return err; | |
| 34 | + return regmap_update_bits(sdata->regmap, | |
| 35 | + reg_addr, mask, data << __ffs(mask)); | |
| 44 | 36 | } |
| 45 | 37 | |
| 46 | 38 | int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, |
| @@ -48,19 +40,15 @@ int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, · 1 unmodified line | ||
| 48 | 40 | unsigned *readval) |
| 49 | 41 | { |
| 50 | 42 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
| 51 | − u8 readdata; | |
| 52 | 43 | int err; |
| 53 | 44 | |
| 54 | 45 | if (!readval) |
| 55 | − return sdata->tf->write_byte(&sdata->tb, sdata->dev, | |
| 56 | − (u8)reg, (u8)writeval); | |
| 46 | + return regmap_write(sdata->regmap, reg, writeval); | |
| 57 | 47 | |
| 58 | − err = sdata->tf->read_byte(&sdata->tb, sdata->dev, (u8)reg, &readdata); | |
| 48 | + err = regmap_read(sdata->regmap, reg, readval); | |
| 59 | 49 | if (err < 0) |
| 60 | 50 | return err; |
| 61 | 51 | |
| 62 | − *readval = (unsigned)readdata; | |
| 63 | − | |
| 64 | 52 | return 0; |
| 65 | 53 | } |
| 66 | 54 | EXPORT_SYMBOL(st_sensors_debugfs_reg_access); |
| @@ -545,7 +533,7 @@ st_sensors_match_scale_error: · 478 unmodified lines | ||
| 545 | 533 | EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain); |
| 546 | 534 | |
| 547 | 535 | static int st_sensors_read_axis_data(struct iio_dev *indio_dev, |
| 548 | − struct iio_chan_spec const *ch, int *data) | |
| 536 | + struct iio_chan_spec const *ch, int *data) | |
| 549 | 537 | { |
| 550 | 538 | int err; |
| 551 | 539 | u8 *outdata; |
| @@ -554,13 +542,12 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev, · 2 unmodified lines | ||
| 554 | 542 | |
| 555 | 543 | byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits + |
| 556 | 544 | ch->scan_type.shift, 8); |
| 557 | − outdata = kmalloc(byte_for_channel, GFP_KERNEL); | |
| 545 | + outdata = kmalloc(byte_for_channel, GFP_DMA | GFP_KERNEL); | |
| 558 | 546 | if (!outdata) |
| 559 | 547 | return -ENOMEM; |
| 560 | 548 | |
| 561 | − err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, | |
| 562 | − ch->address, byte_for_channel, | |
| 563 | − outdata, sdata->multiread_bit); | |
| 549 | + err = regmap_bulk_read(sdata->regmap, ch->address, | |
| 550 | + outdata, byte_for_channel); | |
| 564 | 551 | if (err < 0) |
| 565 | 552 | goto st_sensors_free_memory; |
| 566 | 553 | |
| @@ -608,69 +595,55 @@ out: · 41 unmodified lines | ||
| 608 | 595 | } |
| 609 | 596 | EXPORT_SYMBOL(st_sensors_read_info_raw); |
| 610 | 597 | |
| 611 | −static int st_sensors_init_interface_mode(struct iio_dev *indio_dev, | |
| 612 | − const struct st_sensor_settings *sensor_settings) | |
| 598 | +/* | |
| 599 | + * st_sensors_get_settings_index() - get index of the sensor settings for a | |
| 600 | + * specific device from list of settings | |
| 601 | + * @name: device name buffer reference. | |
| 602 | + * @list: sensor settings list. | |
| 603 | + * @list_length: length of sensor settings list. | |
| 604 | + * | |
| 605 | + * Return: non negative number on success (valid index), | |
| 606 | + * negative error code otherwise. | |
| 607 | + */ | |
| 608 | +int st_sensors_get_settings_index(const char *name, | |
| 609 | + const struct st_sensor_settings *list, | |
| 610 | + const int list_length) | |
| 613 | 611 | { |
| 614 | − struct st_sensor_data *sdata = iio_priv(indio_dev); | |
| 615 | − struct device_node *np = sdata->dev->of_node; | |
| 616 | − struct st_sensors_platform_data *pdata; | |
| 612 | + int i, n; | |
| 617 | 613 | |
| 618 | − pdata = (struct st_sensors_platform_data *)sdata->dev->platform_data; | |
| 619 | − if (((np && of_property_read_bool(np, "spi-3wire")) || | |
| 620 | − (pdata && pdata->spi_3wire)) && sensor_settings->sim.addr) { | |
| 621 | − int err; | |
| 622 | − | |
| 623 | − err = sdata->tf->write_byte(&sdata->tb, sdata->dev, | |
| 624 | − sensor_settings->sim.addr, | |
| 625 | − sensor_settings->sim.value); | |
| 626 | − if (err < 0) { | |
| 627 | − dev_err(&indio_dev->dev, | |
| 628 | − "failed to init interface mode\n"); | |
| 629 | − return err; | |
| 614 | + for (i = 0; i < list_length; i++) { | |
| 615 | + for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) { | |
| 616 | + if (strcmp(name, list[i].sensors_supported[n]) == 0) | |
| 617 | + return i; | |
| 630 | 618 | } |
| 631 | 619 | } |
| 632 | 620 | |
| 633 | − return 0; | |
| 621 | + return -ENODEV; | |
| 634 | 622 | } |
| 623 | +EXPORT_SYMBOL(st_sensors_get_settings_index); | |
| 635 | 624 | |
| 636 | −int st_sensors_check_device_support(struct iio_dev *indio_dev, | |
| 637 | − int num_sensors_list, | |
| 638 | − const struct st_sensor_settings *sensor_settings) | |
| 625 | +/* | |
| 626 | + * st_sensors_verify_id() - verify sensor ID (WhoAmI) is matching with the | |
| 627 | + * expected value | |
| 628 | + * @indio_dev: IIO device reference. | |
| 629 | + * | |
| 630 | + * Return: 0 on success (valid sensor ID), else a negative error code. | |
| 631 | + */ | |
| 632 | +int st_sensors_verify_id(struct iio_dev *indio_dev) | |
| 639 | 633 | { |
| 640 | − int i, n, err = 0; | |
| 641 | − u8 wai; | |
| 642 | 634 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
| 635 | + int wai, err; | |
| 643 | 636 | |
| 644 | − for (i = 0; i < num_sensors_list; i++) { | |
| 645 | − for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) { | |
| 646 | − if (strcmp(indio_dev->name, | |
| 647 | − sensor_settings[i].sensors_supported[n]) == 0) { | |
| 648 | − break; | |
| 649 | − } | |
| 650 | − } | |
| 651 | − if (n < ST_SENSORS_MAX_4WAI) | |
| 652 | − break; | |
| 653 | − } | |
| 654 | − if (i == num_sensors_list) { | |
| 655 | − dev_err(&indio_dev->dev, "device name %s not recognized.\n", | |
| 656 | − indio_dev->name); | |
| 657 | − return -ENODEV; | |
| 658 | − } | |
| 659 | − | |
| 660 | − err = st_sensors_init_interface_mode(indio_dev, &sensor_settings[i]); | |
| 661 | − if (err < 0) | |
| 662 | − return err; | |
| 663 | − | |
| 664 | − if (sensor_settings[i].wai_addr) { | |
| 665 | − err = sdata->tf->read_byte(&sdata->tb, sdata->dev, | |
| 666 | − sensor_settings[i].wai_addr, &wai); | |
| 637 | + if (sdata->sensor_settings->wai_addr) { | |
| 638 | + err = regmap_read(sdata->regmap, | |
| 639 | + sdata->sensor_settings->wai_addr, &wai); | |
| 667 | 640 | if (err < 0) { |
| 668 | 641 | dev_err(&indio_dev->dev, |
| 669 | 642 | "failed to read Who-Am-I register.\n"); |
| 670 | 643 | return err; |
| 671 | 644 | } |
| 672 | 645 | |
| 673 | − if (sensor_settings[i].wai != wai) { | |
| 646 | + if (sdata->sensor_settings->wai != wai) { | |
| 674 | 647 | dev_err(&indio_dev->dev, |
| 675 | 648 | "%s: WhoAmI mismatch (0x%x).\n", |
| 676 | 649 | indio_dev->name, wai); |
| @@ -678,12 +651,9 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev, · 1 unmodified line | ||
| 678 | 651 | } |
| 679 | 652 | } |
| 680 | 653 | |
| 681 | − sdata->sensor_settings = | |
| 682 | − (struct st_sensor_settings *)&sensor_settings[i]; | |
| 683 | − | |
| 684 | − return i; | |
| 654 | + return 0; | |
| 685 | 655 | } |
| 686 | −EXPORT_SYMBOL(st_sensors_check_device_support); | |
| 656 | +EXPORT_SYMBOL(st_sensors_verify_id); | |
| 687 | 657 | |
| 688 | 658 | ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, |
| 689 | 659 | struct device_attribute *attr, char *buf) |
| @@ -13,68 +13,58 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/iio/iio.h> |
| 14 | 14 | #include <linux/of_device.h> |
| 15 | 15 | #include <linux/acpi.h> |
| 16 | +#include <linux/regmap.h> | |
| 16 | 17 | |
| 17 | 18 | #include <linux/iio/common/st_sensors_i2c.h> |
| 18 | 19 | |
| 19 | 20 | |
| 20 | 21 | #define ST_SENSORS_I2C_MULTIREAD 0x80 |
| 21 | 22 | |
| 22 | −static unsigned int st_sensors_i2c_get_irq(struct iio_dev *indio_dev) | |
| 23 | −{ | |
| 24 | − struct st_sensor_data *sdata = iio_priv(indio_dev); | |
| 25 | − | |
| 26 | − return to_i2c_client(sdata->dev)->irq; | |
| 27 | −} | |
| 28 | − | |
| 29 | −static int st_sensors_i2c_read_byte(struct st_sensor_transfer_buffer *tb, | |
| 30 | − struct device *dev, u8 reg_addr, u8 *res_byte) | |
| 31 | −{ | |
| 32 | − int err; | |
| 33 | − | |
| 34 | − err = i2c_smbus_read_byte_data(to_i2c_client(dev), reg_addr); | |
| 35 | − if (err < 0) | |
| 36 | − goto st_accel_i2c_read_byte_error; | |
| 37 | − | |
| 38 | − *res_byte = err & 0xff; | |
| 39 | − | |
| 40 | −st_accel_i2c_read_byte_error: | |
| 41 | − return err < 0 ? err : 0; | |
| 42 | −} | |
| 43 | − | |
| 44 | −static int st_sensors_i2c_read_multiple_byte( | |
| 45 | − struct st_sensor_transfer_buffer *tb, struct device *dev, | |
| 46 | − u8 reg_addr, int len, u8 *data, bool multiread_bit) | |
| 47 | −{ | |
| 48 | − if (multiread_bit) | |
| 49 | − reg_addr |= ST_SENSORS_I2C_MULTIREAD; | |
| 50 | − | |
| 51 | − return i2c_smbus_read_i2c_block_data_or_emulated(to_i2c_client(dev), | |
| 52 | − reg_addr, len, data); | |
| 53 | −} | |
| 54 | − | |
| 55 | −static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb, | |
| 56 | − struct device *dev, u8 reg_addr, u8 data) | |
| 57 | −{ | |
| 58 | − return i2c_smbus_write_byte_data(to_i2c_client(dev), reg_addr, data); | |
| 59 | −} | |
| 23 | +static const struct regmap_config st_sensors_i2c_regmap_config = { | |
| 24 | + .reg_bits = 8, | |
| 25 | + .val_bits = 8, | |
| 26 | +}; | |
| 60 | 27 | |
| 61 | −static const struct st_sensor_transfer_function st_sensors_tf_i2c = { | |
| 62 | − .read_byte = st_sensors_i2c_read_byte, | |
| 63 | − .write_byte = st_sensors_i2c_write_byte, | |
| 64 | − .read_multiple_byte = st_sensors_i2c_read_multiple_byte, | |
| 28 | +static const struct regmap_config st_sensors_i2c_regmap_multiread_bit_config = { | |
| 29 | + .reg_bits = 8, | |
| 30 | + .val_bits = 8, | |
| 31 | + .read_flag_mask = ST_SENSORS_I2C_MULTIREAD, | |
| 65 | 32 | }; |
| 66 | 33 | |
| 67 | −void st_sensors_i2c_configure(struct iio_dev *indio_dev, | |
| 68 | − struct i2c_client *client, struct st_sensor_data *sdata) | |
| 34 | +/* | |
| 35 | + * st_sensors_i2c_configure() - configure I2C interface | |
| 36 | + * @indio_dev: IIO device reference. | |
| 37 | + * @client: i2c client reference. | |
| 38 | + * | |
| 39 | + * Return: 0 on success, else a negative error code. | |
| 40 | + */ | |
| 41 | +int st_sensors_i2c_configure(struct iio_dev *indio_dev, | |
| 42 | + struct i2c_client *client) | |
| 69 | 43 | { |
| 44 | + struct st_sensor_data *sdata = iio_priv(indio_dev); | |
| 45 | + const struct regmap_config *config; | |
| 46 | + | |
| 47 | + if (sdata->sensor_settings->multi_read_bit) | |
| 48 | + config = &st_sensors_i2c_regmap_multiread_bit_config; | |
| 49 | + else | |
| 50 | + config = &st_sensors_i2c_regmap_config; | |
| 51 | + | |
| 52 | + sdata->regmap = devm_regmap_init_i2c(client, config); | |
| 53 | + if (IS_ERR(sdata->regmap)) { | |
| 54 | + dev_err(&client->dev, "Failed to register i2c regmap (%d)\n", | |
| 55 | + (int)PTR_ERR(sdata->regmap)); | |
| 56 | + return PTR_ERR(sdata->regmap); | |
| 57 | + } | |
| 58 | + | |
| 70 | 59 | i2c_set_clientdata(client, indio_dev); |
| 71 | 60 | |
| 72 | 61 | indio_dev->dev.parent = &client->dev; |
| 73 | 62 | indio_dev->name = client->name; |
| 74 | 63 | |
| 75 | 64 | sdata->dev = &client->dev; |
| 76 | − sdata->tf = &st_sensors_tf_i2c; | |
| 77 | − sdata->get_irq_data_ready = st_sensors_i2c_get_irq; | |
| 65 | + sdata->irq = client->irq; | |
| 66 | + | |
| 67 | + return 0; | |
| 78 | 68 | } |
| 79 | 69 | EXPORT_SYMBOL(st_sensors_i2c_configure); |
| 80 | 70 | |
| @@ -11,108 +11,108 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/module.h> |
| 12 | 12 | #include <linux/slab.h> |
| 13 | 13 | #include <linux/iio/iio.h> |
| 14 | +#include <linux/regmap.h> | |
| 14 | 15 | |
| 15 | 16 | #include <linux/iio/common/st_sensors_spi.h> |
| 16 | − | |
| 17 | +#include "st_sensors_core.h" | |
| 17 | 18 | |
| 18 | 19 | #define ST_SENSORS_SPI_MULTIREAD 0xc0 |
| 19 | −#define ST_SENSORS_SPI_READ 0x80 | |
| 20 | 20 | |
| 21 | −static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev) | |
| 22 | −{ | |
| 23 | − struct st_sensor_data *sdata = iio_priv(indio_dev); | |
| 21 | +static const struct regmap_config st_sensors_spi_regmap_config = { | |
| 22 | + .reg_bits = 8, | |
| 23 | + .val_bits = 8, | |
| 24 | +}; | |
| 24 | 25 | |
| 25 | − return to_spi_device(sdata->dev)->irq; | |
| 26 | −} | |
| 26 | +static const struct regmap_config st_sensors_spi_regmap_multiread_bit_config = { | |
| 27 | + .reg_bits = 8, | |
| 28 | + .val_bits = 8, | |
| 29 | + .read_flag_mask = ST_SENSORS_SPI_MULTIREAD, | |
| 30 | +}; | |
| 27 | 31 | |
| 28 | −static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb, | |
| 29 | − struct device *dev, u8 reg_addr, int len, u8 *data, bool multiread_bit) | |
| 32 | +/* | |
| 33 | + * st_sensors_is_spi_3_wire() - check if SPI 3-wire mode has been selected | |
| 34 | + * @spi: spi device reference. | |
| 35 | + * | |
| 36 | + * Return: true if SPI 3-wire mode is selected, false otherwise. | |
| 37 | + */ | |
| 38 | +static bool st_sensors_is_spi_3_wire(struct spi_device *spi) | |
| 30 | 39 | { |
| 31 | − int err; | |
| 32 | − | |
| 33 | − struct spi_transfer xfers[] = { | |
| 34 | − { | |
| 35 | − .tx_buf = tb->tx_buf, | |
| 36 | − .bits_per_word = 8, | |
| 37 | − .len = 1, | |
| 38 | − }, | |
| 39 | − { | |
| 40 | − .rx_buf = tb->rx_buf, | |
| 41 | − .bits_per_word = 8, | |
| 42 | − .len = len, | |
| 43 | − } | |
| 44 | − }; | |
| 45 | − | |
| 46 | − mutex_lock(&tb->buf_lock); | |
| 47 | − if ((multiread_bit) && (len > 1)) | |
| 48 | − tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_MULTIREAD; | |
| 49 | − else | |
| 50 | − tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_READ; | |
| 40 | + struct device_node *np = spi->dev.of_node; | |
| 41 | + struct st_sensors_platform_data *pdata; | |
| 51 | 42 | |
| 52 | − err = spi_sync_transfer(to_spi_device(dev), xfers, ARRAY_SIZE(xfers)); | |
| 53 | − if (err) | |
| 54 | − goto acc_spi_read_error; | |
| 43 | + pdata = (struct st_sensors_platform_data *)spi->dev.platform_data; | |
| 44 | + if ((np && of_property_read_bool(np, "spi-3wire")) || | |
| 45 | + (pdata && pdata->spi_3wire)) { | |
| 46 | + return true; | |
| 47 | + } | |
| 55 | 48 | |
| 56 | − memcpy(data, tb->rx_buf, len); | |
| 57 | − mutex_unlock(&tb->buf_lock); | |
| 58 | − return len; | |
| 59 | − | |
| 60 | −acc_spi_read_error: | |
| 61 | − mutex_unlock(&tb->buf_lock); | |
| 62 | − return err; | |
| 49 | + return false; | |
| 63 | 50 | } |
| 64 | 51 | |
| 65 | −static int st_sensors_spi_read_byte(struct st_sensor_transfer_buffer *tb, | |
| 66 | − struct device *dev, u8 reg_addr, u8 *res_byte) | |
| 52 | +/* | |
| 53 | + * st_sensors_configure_spi_3_wire() - configure SPI 3-wire if needed | |
| 54 | + * @spi: spi device reference. | |
| 55 | + * @settings: sensor specific settings reference. | |
| 56 | + * | |
| 57 | + * Return: 0 on success, else a negative error code. | |
| 58 | + */ | |
| 59 | +static int st_sensors_configure_spi_3_wire(struct spi_device *spi, | |
| 60 | + struct st_sensor_settings *settings) | |
| 67 | 61 | { |
| 68 | − return st_sensors_spi_read(tb, dev, reg_addr, 1, res_byte, false); | |
| 69 | −} | |
| 62 | + if (settings->sim.addr) { | |
| 63 | + u8 buffer[] = { | |
| 64 | + settings->sim.addr, | |
| 65 | + settings->sim.value | |
| 66 | + }; | |
| 70 | 67 | |
| 71 | −static int st_sensors_spi_read_multiple_byte( | |
| 72 | − struct st_sensor_transfer_buffer *tb, struct device *dev, | |
| 73 | − u8 reg_addr, int len, u8 *data, bool multiread_bit) | |
| 74 | −{ | |
| 75 | − return st_sensors_spi_read(tb, dev, reg_addr, len, data, multiread_bit); | |
| 68 | + return spi_write(spi, buffer, 2); | |
| 69 | + } | |
| 70 | + | |
| 71 | + return 0; | |
| 76 | 72 | } |
| 77 | 73 | |
| 78 | −static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb, | |
| 79 | − struct device *dev, u8 reg_addr, u8 data) | |
| 74 | +/* | |
| 75 | + * st_sensors_spi_configure() - configure SPI interface | |
| 76 | + * @indio_dev: IIO device reference. | |
| 77 | + * @spi: spi device reference. | |
| 78 | + * | |
| 79 | + * Return: 0 on success, else a negative error code. | |
| 80 | + */ | |
| 81 | +int st_sensors_spi_configure(struct iio_dev *indio_dev, | |
| 82 | + struct spi_device *spi) | |
| 80 | 83 | { |
| 84 | + struct st_sensor_data *sdata = iio_priv(indio_dev); | |
| 85 | + const struct regmap_config *config; | |
| 81 | 86 | int err; |
| 82 | 87 | |
| 83 | − struct spi_transfer xfers = { | |
| 84 | − .tx_buf = tb->tx_buf, | |
| 85 | − .bits_per_word = 8, | |
| 86 | − .len = 2, | |
| 87 | − }; | |
| 88 | + if (st_sensors_is_spi_3_wire(spi)) { | |
| 89 | + err = st_sensors_configure_spi_3_wire(spi, | |
| 90 | + sdata->sensor_settings); | |
| 91 | + if (err < 0) | |
| 92 | + return err; | |
| 93 | + } | |
| 88 | 94 | |
| 89 | − mutex_lock(&tb->buf_lock); | |
| 90 | − tb->tx_buf[0] = reg_addr; | |
| 91 | − tb->tx_buf[1] = data; | |
| 92 | − | |
| 93 | − err = spi_sync_transfer(to_spi_device(dev), &xfers, 1); | |
| 94 | − mutex_unlock(&tb->buf_lock); | |
| 95 | + if (sdata->sensor_settings->multi_read_bit) | |
| 96 | + config = &st_sensors_spi_regmap_multiread_bit_config; | |
| 97 | + else | |
| 98 | + config = &st_sensors_spi_regmap_config; | |
| 95 | 99 | |
| 96 | − return err; | |
| 97 | −} | |
| 100 | + sdata->regmap = devm_regmap_init_spi(spi, config); | |
| 101 | + if (IS_ERR(sdata->regmap)) { | |
| 102 | + dev_err(&spi->dev, "Failed to register spi regmap (%d)\n", | |
| 103 | + (int)PTR_ERR(sdata->regmap)); | |
| 104 | + return PTR_ERR(sdata->regmap); | |
| 105 | + } | |
| 98 | 106 | |
| 99 | −static const struct st_sensor_transfer_function st_sensors_tf_spi = { | |
| 100 | − .read_byte = st_sensors_spi_read_byte, | |
| 101 | − .write_byte = st_sensors_spi_write_byte, | |
| 102 | − .read_multiple_byte = st_sensors_spi_read_multiple_byte, | |
| 103 | −}; | |
| 104 | − | |
| 105 | −void st_sensors_spi_configure(struct iio_dev *indio_dev, | |
| 106 | − struct spi_device *spi, struct st_sensor_data *sdata) | |
| 107 | −{ | |
| 108 | 107 | spi_set_drvdata(spi, indio_dev); |
| 109 | 108 | |
| 110 | 109 | indio_dev->dev.parent = &spi->dev; |
| 111 | 110 | indio_dev->name = spi->modalias; |
| 112 | 111 | |
| 113 | 112 | sdata->dev = &spi->dev; |
| 114 | − sdata->tf = &st_sensors_tf_spi; | |
| 115 | − sdata->get_irq_data_ready = st_sensors_spi_get_irq; | |
| 113 | + sdata->irq = spi->irq; | |
| 114 | + | |
| 115 | + return 0; | |
| 116 | 116 | } |
| 117 | 117 | EXPORT_SYMBOL(st_sensors_spi_configure); |
| 118 | 118 | |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/iio/iio.h> |
| 14 | 14 | #include <linux/iio/trigger.h> |
| 15 | 15 | #include <linux/interrupt.h> |
| 16 | +#include <linux/regmap.h> | |
| 16 | 17 | #include <linux/iio/common/st_sensors.h> |
| 17 | 18 | #include "st_sensors_core.h" |
| 18 | 19 | |
| @@ -26,8 +27,7 @@ · 7 unmodified lines | ||
| 26 | 27 | static int st_sensors_new_samples_available(struct iio_dev *indio_dev, |
| 27 | 28 | struct st_sensor_data *sdata) |
| 28 | 29 | { |
| 29 | − u8 status; | |
| 30 | − int ret; | |
| 30 | + int ret, status; | |
| 31 | 31 | |
| 32 | 32 | /* How would I know if I can't check it? */ |
| 33 | 33 | if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr) |
| @@ -37,9 +37,9 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev, · 3 unmodified lines | ||
| 37 | 37 | if (!indio_dev->active_scan_mask) |
| 38 | 38 | return 0; |
| 39 | 39 | |
| 40 | − ret = sdata->tf->read_byte(&sdata->tb, sdata->dev, | |
| 41 | − sdata->sensor_settings->drdy_irq.stat_drdy.addr, | |
| 42 | − &status); | |
| 40 | + ret = regmap_read(sdata->regmap, | |
| 41 | + sdata->sensor_settings->drdy_irq.stat_drdy.addr, | |
| 42 | + &status); | |
| 43 | 43 | if (ret < 0) { |
| 44 | 44 | dev_err(sdata->dev, |
| 45 | 45 | "error checking samples available\n"); |
| @@ -121,9 +121,9 @@ static irqreturn_t st_sensors_irq_thread(int irq, void *p) · 75 unmodified lines | ||
| 121 | 121 | int st_sensors_allocate_trigger(struct iio_dev *indio_dev, |
| 122 | 122 | const struct iio_trigger_ops *trigger_ops) |
| 123 | 123 | { |
| 124 | − int err, irq; | |
| 125 | 124 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
| 126 | 125 | unsigned long irq_trig; |
| 126 | + int err; | |
| 127 | 127 | |
| 128 | 128 | sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name); |
| 129 | 129 | if (sdata->trig == NULL) { |
| @@ -135,8 +135,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, · 5 unmodified lines | ||
| 135 | 135 | sdata->trig->ops = trigger_ops; |
| 136 | 136 | sdata->trig->dev.parent = sdata->dev; |
| 137 | 137 | |
| 138 | − irq = sdata->get_irq_data_ready(indio_dev); | |
| 139 | − irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); | |
| 138 | + irq_trig = irqd_get_trigger_type(irq_get_irq_data(sdata->irq)); | |
| 140 | 139 | /* |
| 141 | 140 | * If the IRQ is triggered on falling edge, we need to mark the |
| 142 | 141 | * interrupt as active low, if the hardware supports this. |
| @@ -206,12 +205,12 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, · 63 unmodified lines | ||
| 206 | 205 | sdata->sensor_settings->drdy_irq.stat_drdy.addr) |
| 207 | 206 | irq_trig |= IRQF_SHARED; |
| 208 | 207 | |
| 209 | − err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev), | |
| 210 | − st_sensors_irq_handler, | |
| 211 | − st_sensors_irq_thread, | |
| 212 | − irq_trig, | |
| 213 | − sdata->trig->name, | |
| 214 | − sdata->trig); | |
| 208 | + err = request_threaded_irq(sdata->irq, | |
| 209 | + st_sensors_irq_handler, | |
| 210 | + st_sensors_irq_thread, | |
| 211 | + irq_trig, | |
| 212 | + sdata->trig->name, | |
| 213 | + sdata->trig); | |
| 215 | 214 | if (err) { |
| 216 | 215 | dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); |
| 217 | 216 | goto iio_trigger_free; |
| @@ -227,7 +226,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, · 9 unmodified lines | ||
| 227 | 226 | return 0; |
| 228 | 227 | |
| 229 | 228 | iio_trigger_register_error: |
| 230 | − free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig); | |
| 229 | + free_irq(sdata->irq, sdata->trig); | |
| 231 | 230 | iio_trigger_free: |
| 232 | 231 | iio_trigger_free(sdata->trig); |
| 233 | 232 | return err; |
| @@ -239,7 +238,7 @@ void st_sensors_deallocate_trigger(struct iio_dev *indio_dev) · 5 unmodified lines | ||
| 239 | 238 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
| 240 | 239 | |
| 241 | 240 | iio_trigger_unregister(sdata->trig); |
| 242 | − free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig); | |
| 241 | + free_irq(sdata->irq, sdata->trig); | |
| 243 | 242 | iio_trigger_free(sdata->trig); |
| 244 | 243 | } |
| 245 | 244 | EXPORT_SYMBOL(st_sensors_deallocate_trigger); |
| @@ -32,6 +32,7 @@ static const struct st_sensors_platform_data gyro_pdata = { · 31 unmodified lines | ||
| 32 | 32 | .drdy_int_pin = 2, |
| 33 | 33 | }; |
| 34 | 34 | |
| 35 | +const struct st_sensor_settings *st_gyro_get_settings(const char *name); | |
| 35 | 36 | int st_gyro_common_probe(struct iio_dev *indio_dev); |
| 36 | 37 | void st_gyro_common_remove(struct iio_dev *indio_dev); |
| 37 | 38 | |
| @@ -29,61 +29,51 @@ int st_gyro_trig_set_state(struct iio_trigger *trig, bool state) · 28 unmodified lines | ||
| 29 | 29 | return st_sensors_set_dataready_irq(indio_dev, state); |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | −static int st_gyro_buffer_preenable(struct iio_dev *indio_dev) | |
| 33 | −{ | |
| 34 | − return st_sensors_set_enable(indio_dev, true); | |
| 35 | −} | |
| 36 | − | |
| 37 | 32 | static int st_gyro_buffer_postenable(struct iio_dev *indio_dev) |
| 38 | 33 | { |
| 39 | 34 | int err; |
| 40 | − struct st_sensor_data *gdata = iio_priv(indio_dev); | |
| 41 | 35 | |
| 42 | − gdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); | |
| 43 | − if (gdata->buffer_data == NULL) { | |
| 44 | − err = -ENOMEM; | |
| 45 | − goto allocate_memory_error; | |
| 46 | − } | |
| 36 | + err = iio_triggered_buffer_postenable(indio_dev); | |
| 37 | + if (err < 0) | |
| 38 | + return err; | |
| 47 | 39 | |
| 48 | 40 | err = st_sensors_set_axis_enable(indio_dev, |
| 49 | − (u8)indio_dev->active_scan_mask[0]); | |
| 41 | + (u8)indio_dev->active_scan_mask[0]); | |
| 50 | 42 | if (err < 0) |
| 51 | − goto st_gyro_buffer_postenable_error; | |
| 43 | + goto st_gyro_buffer_predisable; | |
| 52 | 44 | |
| 53 | − err = iio_triggered_buffer_postenable(indio_dev); | |
| 45 | + err = st_sensors_set_enable(indio_dev, true); | |
| 54 | 46 | if (err < 0) |
| 55 | − goto st_gyro_buffer_postenable_error; | |
| 47 | + goto st_gyro_buffer_enable_all_axis; | |
| 56 | 48 | |
| 57 | − return err; | |
| 49 | + return 0; | |
| 58 | 50 | |
| 59 | −st_gyro_buffer_postenable_error: | |
| 60 | − kfree(gdata->buffer_data); | |
| 61 | −allocate_memory_error: | |
| 51 | +st_gyro_buffer_enable_all_axis: | |
| 52 | + st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); | |
| 53 | +st_gyro_buffer_predisable: | |
| 54 | + iio_triggered_buffer_predisable(indio_dev); | |
| 62 | 55 | return err; |
| 63 | 56 | } |
| 64 | 57 | |
| 65 | 58 | static int st_gyro_buffer_predisable(struct iio_dev *indio_dev) |
| 66 | 59 | { |
| 67 | − int err; | |
| 68 | − struct st_sensor_data *gdata = iio_priv(indio_dev); | |
| 60 | + int err, err2; | |
| 69 | 61 | |
| 70 | − err = iio_triggered_buffer_predisable(indio_dev); | |
| 62 | + err = st_sensors_set_enable(indio_dev, false); | |
| 71 | 63 | if (err < 0) |
| 72 | − goto st_gyro_buffer_predisable_error; | |
| 64 | + goto st_gyro_buffer_predisable; | |
| 73 | 65 | |
| 74 | 66 | err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); |
| 75 | − if (err < 0) | |
| 76 | − goto st_gyro_buffer_predisable_error; | |
| 77 | 67 | |
| 78 | − err = st_sensors_set_enable(indio_dev, false); | |
| 68 | +st_gyro_buffer_predisable: | |
| 69 | + err2 = iio_triggered_buffer_predisable(indio_dev); | |
| 70 | + if (!err) | |
| 71 | + err = err2; | |
| 79 | 72 | |
| 80 | −st_gyro_buffer_predisable_error: | |
| 81 | − kfree(gdata->buffer_data); | |
| 82 | 73 | return err; |
| 83 | 74 | } |
| 84 | 75 | |
| 85 | 76 | static const struct iio_buffer_setup_ops st_gyro_buffer_setup_ops = { |
| 86 | − .preenable = &st_gyro_buffer_preenable, | |
| 87 | 77 | .postenable = &st_gyro_buffer_postenable, |
| 88 | 78 | .predisable = &st_gyro_buffer_predisable, |
| 89 | 79 | }; |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/slab.h> |
| 13 | 13 | #include <linux/errno.h> |
| 14 | 14 | #include <linux/types.h> |
| 15 | −#include <linux/mutex.h> | |
| 16 | 15 | #include <linux/interrupt.h> |
| 17 | 16 | #include <linux/i2c.h> |
| 18 | 17 | #include <linux/gpio.h> |
| @@ -368,28 +367,41 @@ static const struct iio_trigger_ops st_gyro_trigger_ops = { · 349 unmodified lines | ||
| 368 | 367 | #define ST_GYRO_TRIGGER_OPS NULL |
| 369 | 368 | #endif |
| 370 | 369 | |
| 370 | +/* | |
| 371 | + * st_gyro_get_settings() - get sensor settings from device name | |
| 372 | + * @name: device name buffer reference. | |
| 373 | + * | |
| 374 | + * Return: valid reference on success, NULL otherwise. | |
| 375 | + */ | |
| 376 | +const struct st_sensor_settings *st_gyro_get_settings(const char *name) | |
| 377 | +{ | |
| 378 | + int index = st_sensors_get_settings_index(name, | |
| 379 | + st_gyro_sensors_settings, | |
| 380 | + ARRAY_SIZE(st_gyro_sensors_settings)); | |
| 381 | + if (index < 0) | |
| 382 | + return NULL; | |
| 383 | + | |
| 384 | + return &st_gyro_sensors_settings[index]; | |
| 385 | +} | |
| 386 | +EXPORT_SYMBOL(st_gyro_get_settings); | |
| 387 | + | |
| 371 | 388 | int st_gyro_common_probe(struct iio_dev *indio_dev) |
| 372 | 389 | { |
| 373 | 390 | struct st_sensor_data *gdata = iio_priv(indio_dev); |
| 374 | − int irq = gdata->get_irq_data_ready(indio_dev); | |
| 375 | 391 | int err; |
| 376 | 392 | |
| 377 | 393 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 378 | 394 | indio_dev->info = &gyro_info; |
| 379 | − mutex_init(&gdata->tb.buf_lock); | |
| 380 | 395 | |
| 381 | 396 | err = st_sensors_power_enable(indio_dev); |
| 382 | 397 | if (err) |
| 383 | 398 | return err; |
| 384 | 399 | |
| 385 | − err = st_sensors_check_device_support(indio_dev, | |
| 386 | − ARRAY_SIZE(st_gyro_sensors_settings), | |
| 387 | − st_gyro_sensors_settings); | |
| 400 | + err = st_sensors_verify_id(indio_dev); | |
| 388 | 401 | if (err < 0) |
| 389 | 402 | goto st_gyro_power_off; |
| 390 | 403 | |
| 391 | 404 | gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS; |
| 392 | − gdata->multiread_bit = gdata->sensor_settings->multi_read_bit; | |
| 393 | 405 | indio_dev->channels = gdata->sensor_settings->ch; |
| 394 | 406 | indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; |
| 395 | 407 | |
| @@ -406,7 +418,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) · 10 unmodified lines | ||
| 406 | 418 | if (err < 0) |
| 407 | 419 | goto st_gyro_power_off; |
| 408 | 420 | |
| 409 | − if (irq > 0) { | |
| 421 | + if (gdata->irq > 0) { | |
| 410 | 422 | err = st_sensors_allocate_trigger(indio_dev, |
| 411 | 423 | ST_GYRO_TRIGGER_OPS); |
| 412 | 424 | if (err < 0) |
| @@ -423,7 +435,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) · 10 unmodified lines | ||
| 423 | 435 | return 0; |
| 424 | 436 | |
| 425 | 437 | st_gyro_device_register_error: |
| 426 | − if (irq > 0) | |
| 438 | + if (gdata->irq > 0) | |
| 427 | 439 | st_sensors_deallocate_trigger(indio_dev); |
| 428 | 440 | st_gyro_probe_trigger_error: |
| 429 | 441 | st_gyro_deallocate_ring(indio_dev); |
| @@ -441,7 +453,7 @@ void st_gyro_common_remove(struct iio_dev *indio_dev) · 11 unmodified lines | ||
| 441 | 453 | st_sensors_power_disable(indio_dev); |
| 442 | 454 | |
| 443 | 455 | iio_device_unregister(indio_dev); |
| 444 | − if (gdata->get_irq_data_ready(indio_dev) > 0) | |
| 456 | + if (gdata->irq > 0) | |
| 445 | 457 | st_sensors_deallocate_trigger(indio_dev); |
| 446 | 458 | |
| 447 | 459 | st_gyro_deallocate_ring(indio_dev); |
| @@ -63,21 +63,33 @@ MODULE_DEVICE_TABLE(of, st_gyro_of_match); · 62 unmodified lines | ||
| 63 | 63 | #endif |
| 64 | 64 | |
| 65 | 65 | static int st_gyro_i2c_probe(struct i2c_client *client, |
| 66 | − const struct i2c_device_id *id) | |
| 66 | + const struct i2c_device_id *id) | |
| 67 | 67 | { |
| 68 | − struct iio_dev *indio_dev; | |
| 68 | + const struct st_sensor_settings *settings; | |
| 69 | 69 | struct st_sensor_data *gdata; |
| 70 | + struct iio_dev *indio_dev; | |
| 70 | 71 | int err; |
| 71 | 72 | |
| 73 | + st_sensors_of_name_probe(&client->dev, st_gyro_of_match, | |
| 74 | + client->name, sizeof(client->name)); | |
| 75 | + | |
| 76 | + settings = st_gyro_get_settings(client->name); | |
| 77 | + if (!settings) { | |
| 78 | + dev_err(&client->dev, "device name %s not recognized.\n", | |
| 79 | + client->name); | |
| 80 | + return -ENODEV; | |
| 81 | + } | |
| 82 | + | |
| 72 | 83 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*gdata)); |
| 73 | 84 | if (!indio_dev) |
| 74 | 85 | return -ENOMEM; |
| 75 | 86 | |
| 76 | 87 | gdata = iio_priv(indio_dev); |
| 77 | − st_sensors_of_name_probe(&client->dev, st_gyro_of_match, | |
| 78 | − client->name, sizeof(client->name)); | |
| 88 | + gdata->sensor_settings = (struct st_sensor_settings *)settings; | |
| 79 | 89 | |
| 80 | − st_sensors_i2c_configure(indio_dev, client, gdata); | |
| 90 | + err = st_sensors_i2c_configure(indio_dev, client); | |
| 91 | + if (err < 0) | |
| 92 | + return err; | |
| 81 | 93 | |
| 82 | 94 | err = st_gyro_common_probe(indio_dev); |
| 83 | 95 | if (err < 0) |
| @@ -69,19 +69,31 @@ MODULE_DEVICE_TABLE(of, st_gyro_of_match); · 68 unmodified lines | ||
| 69 | 69 | |
| 70 | 70 | static int st_gyro_spi_probe(struct spi_device *spi) |
| 71 | 71 | { |
| 72 | − struct iio_dev *indio_dev; | |
| 72 | + const struct st_sensor_settings *settings; | |
| 73 | 73 | struct st_sensor_data *gdata; |
| 74 | + struct iio_dev *indio_dev; | |
| 74 | 75 | int err; |
| 75 | 76 | |
| 77 | + st_sensors_of_name_probe(&spi->dev, st_gyro_of_match, | |
| 78 | + spi->modalias, sizeof(spi->modalias)); | |
| 79 | + | |
| 80 | + settings = st_gyro_get_settings(spi->modalias); | |
| 81 | + if (!settings) { | |
| 82 | + dev_err(&spi->dev, "device name %s not recognized.\n", | |
| 83 | + spi->modalias); | |
| 84 | + return -ENODEV; | |
| 85 | + } | |
| 86 | + | |
| 76 | 87 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*gdata)); |
| 77 | 88 | if (!indio_dev) |
| 78 | 89 | return -ENOMEM; |
| 79 | 90 | |
| 80 | 91 | gdata = iio_priv(indio_dev); |
| 92 | + gdata->sensor_settings = (struct st_sensor_settings *)settings; | |
| 81 | 93 | |
| 82 | − st_sensors_of_name_probe(&spi->dev, st_gyro_of_match, | |
| 83 | − spi->modalias, sizeof(spi->modalias)); | |
| 84 | − st_sensors_spi_configure(indio_dev, spi, gdata); | |
| 94 | + err = st_sensors_spi_configure(indio_dev, spi); | |
| 95 | + if (err < 0) | |
| 96 | + return err; | |
| 85 | 97 | |
| 86 | 98 | err = st_gyro_common_probe(indio_dev); |
| 87 | 99 | if (err < 0) |
| @@ -240,32 +240,15 @@ static int am2315_probe(struct i2c_client *client, · 239 unmodified lines | ||
| 240 | 240 | indio_dev->channels = am2315_channels; |
| 241 | 241 | indio_dev->num_channels = ARRAY_SIZE(am2315_channels); |
| 242 | 242 | |
| 243 | − ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time, | |
| 243 | + ret = devm_iio_triggered_buffer_setup(&client->dev, | |
| 244 | + indio_dev, iio_pollfunc_store_time, | |
| 244 | 245 | am2315_trigger_handler, NULL); |
| 245 | 246 | if (ret < 0) { |
| 246 | 247 | dev_err(&client->dev, "iio triggered buffer setup failed\n"); |
| 247 | 248 | return ret; |
| 248 | 249 | } |
| 249 | 250 | |
| 250 | − ret = iio_device_register(indio_dev); | |
| 251 | − if (ret < 0) | |
| 252 | − goto err_buffer_cleanup; | |
| 253 | − | |
| 254 | − return 0; | |
| 255 | − | |
| 256 | −err_buffer_cleanup: | |
| 257 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 258 | − return ret; | |
| 259 | −} | |
| 260 | − | |
| 261 | −static int am2315_remove(struct i2c_client *client) | |
| 262 | −{ | |
| 263 | − struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 264 | − | |
| 265 | − iio_device_unregister(indio_dev); | |
| 266 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 267 | − | |
| 268 | − return 0; | |
| 251 | + return devm_iio_device_register(&client->dev, indio_dev); | |
| 269 | 252 | } |
| 270 | 253 | |
| 271 | 254 | static const struct i2c_device_id am2315_i2c_id[] = { |
| @@ -287,7 +270,6 @@ static struct i2c_driver am2315_driver = { · 15 unmodified lines | ||
| 287 | 270 | .acpi_match_table = ACPI_PTR(am2315_acpi_id), |
| 288 | 271 | }, |
| 289 | 272 | .probe = am2315_probe, |
| 290 | − .remove = am2315_remove, | |
| 291 | 273 | .id_table = am2315_i2c_id, |
| 292 | 274 | }; |
| 293 | 275 | |
| @@ -385,28 +385,16 @@ static int hdc100x_probe(struct i2c_client *client, · 384 unmodified lines | ||
| 385 | 385 | hdc100x_set_it_time(data, 1, hdc100x_int_time[1][0]); |
| 386 | 386 | hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0); |
| 387 | 387 | |
| 388 | − ret = iio_triggered_buffer_setup(indio_dev, NULL, | |
| 388 | + ret = devm_iio_triggered_buffer_setup(&client->dev, | |
| 389 | + indio_dev, NULL, | |
| 389 | 390 | hdc100x_trigger_handler, |
| 390 | 391 | &hdc_buffer_setup_ops); |
| 391 | 392 | if (ret < 0) { |
| 392 | 393 | dev_err(&client->dev, "iio triggered buffer setup failed\n"); |
| 393 | 394 | return ret; |
| 394 | 395 | } |
| 395 | − ret = iio_device_register(indio_dev); | |
| 396 | − if (ret < 0) | |
| 397 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 398 | 396 | |
| 399 | − return ret; | |
| 400 | −} | |
| 401 | − | |
| 402 | −static int hdc100x_remove(struct i2c_client *client) | |
| 403 | −{ | |
| 404 | − struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 405 | − | |
| 406 | − iio_device_unregister(indio_dev); | |
| 407 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 408 | − | |
| 409 | − return 0; | |
| 397 | + return devm_iio_device_register(&client->dev, indio_dev); | |
| 410 | 398 | } |
| 411 | 399 | |
| 412 | 400 | static const struct i2c_device_id hdc100x_id[] = { |
| @@ -436,7 +424,6 @@ static struct i2c_driver hdc100x_driver = { · 23 unmodified lines | ||
| 436 | 424 | .of_match_table = of_match_ptr(hdc100x_dt_ids), |
| 437 | 425 | }, |
| 438 | 426 | .probe = hdc100x_probe, |
| 439 | − .remove = hdc100x_remove, | |
| 440 | 427 | .id_table = hdc100x_id, |
| 441 | 428 | }; |
| 442 | 429 | module_i2c_driver(hdc100x_driver); |
| @@ -17,6 +17,18 @@ config ADIS16400 · 16 unmodified lines | ||
| 17 | 17 | adis16365, adis16400 and adis16405 triaxial inertial sensors |
| 18 | 18 | (adis16400 series also have magnetometers). |
| 19 | 19 | |
| 20 | +config ADIS16460 | |
| 21 | + tristate "Analog Devices ADIS16460 and similar IMU driver" | |
| 22 | + depends on SPI | |
| 23 | + select IIO_ADIS_LIB | |
| 24 | + select IIO_ADIS_LIB_BUFFER if IIO_BUFFER | |
| 25 | + help | |
| 26 | + Say yes here to build support for Analog Devices ADIS16460 inertial | |
| 27 | + sensor. | |
| 28 | + | |
| 29 | + To compile this driver as a module, choose M here: the module will be | |
| 30 | + called adis16460. | |
| 31 | + | |
| 20 | 32 | config ADIS16480 |
| 21 | 33 | tristate "Analog Devices ADIS16480 and similar IMU driver" |
| 22 | 34 | depends on SPI |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | # When adding new entries keep the list in alphabetical order |
| 7 | 7 | obj-$(CONFIG_ADIS16400) += adis16400.o |
| 8 | +obj-$(CONFIG_ADIS16460) += adis16460.o | |
| 8 | 9 | obj-$(CONFIG_ADIS16480) += adis16480.o |
| 9 | 10 | |
| 10 | 11 | adis_lib-y += adis.o |
| @@ -39,18 +39,24 @@ int adis_write_reg(struct adis *adis, unsigned int reg, · 38 unmodified lines | ||
| 39 | 39 | .len = 2, |
| 40 | 40 | .cs_change = 1, |
| 41 | 41 | .delay_usecs = adis->data->write_delay, |
| 42 | + .cs_change_delay = adis->data->cs_change_delay, | |
| 43 | + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, | |
| 42 | 44 | }, { |
| 43 | 45 | .tx_buf = adis->tx + 2, |
| 44 | 46 | .bits_per_word = 8, |
| 45 | 47 | .len = 2, |
| 46 | 48 | .cs_change = 1, |
| 47 | 49 | .delay_usecs = adis->data->write_delay, |
| 50 | + .cs_change_delay = adis->data->cs_change_delay, | |
| 51 | + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, | |
| 48 | 52 | }, { |
| 49 | 53 | .tx_buf = adis->tx + 4, |
| 50 | 54 | .bits_per_word = 8, |
| 51 | 55 | .len = 2, |
| 52 | 56 | .cs_change = 1, |
| 53 | 57 | .delay_usecs = adis->data->write_delay, |
| 58 | + .cs_change_delay = adis->data->cs_change_delay, | |
| 59 | + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, | |
| 54 | 60 | }, { |
| 55 | 61 | .tx_buf = adis->tx + 6, |
| 56 | 62 | .bits_per_word = 8, |
| @@ -133,12 +139,16 @@ int adis_read_reg(struct adis *adis, unsigned int reg, · 76 unmodified lines | ||
| 133 | 139 | .len = 2, |
| 134 | 140 | .cs_change = 1, |
| 135 | 141 | .delay_usecs = adis->data->write_delay, |
| 142 | + .cs_change_delay = adis->data->cs_change_delay, | |
| 143 | + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, | |
| 136 | 144 | }, { |
| 137 | 145 | .tx_buf = adis->tx + 2, |
| 138 | 146 | .bits_per_word = 8, |
| 139 | 147 | .len = 2, |
| 140 | 148 | .cs_change = 1, |
| 141 | 149 | .delay_usecs = adis->data->read_delay, |
| 150 | + .cs_change_delay = adis->data->cs_change_delay, | |
| 151 | + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, | |
| 142 | 152 | }, { |
| 143 | 153 | .tx_buf = adis->tx + 4, |
| 144 | 154 | .rx_buf = adis->rx, |
| @@ -146,6 +156,8 @@ int adis_read_reg(struct adis *adis, unsigned int reg, · 1 unmodified line | ||
| 146 | 156 | .len = 2, |
| 147 | 157 | .cs_change = 1, |
| 148 | 158 | .delay_usecs = adis->data->read_delay, |
| 159 | + .cs_change_delay = adis->data->cs_change_delay, | |
| 160 | + .cs_change_delay_unit = SPI_DELAY_UNIT_USECS, | |
| 149 | 161 | }, { |
| 150 | 162 | .rx_buf = adis->rx + 2, |
| 151 | 163 | .bits_per_word = 8, |
| @@ -0,0 +1,489 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0+ | |
| 2 | +/* | |
| 3 | + * ADIS16460 IMU driver | |
| 4 | + * | |
| 5 | + * Copyright 2019 Analog Devices Inc. | |
| 6 | + */ | |
| 7 | + | |
| 8 | +#include <linux/delay.h> | |
| 9 | +#include <linux/module.h> | |
| 10 | +#include <linux/spi/spi.h> | |
| 11 | + | |
| 12 | +#include <linux/iio/iio.h> | |
| 13 | +#include <linux/iio/imu/adis.h> | |
| 14 | + | |
| 15 | +#include <linux/debugfs.h> | |
| 16 | + | |
| 17 | +#define ADIS16460_REG_FLASH_CNT 0x00 | |
| 18 | +#define ADIS16460_REG_DIAG_STAT 0x02 | |
| 19 | +#define ADIS16460_REG_X_GYRO_LOW 0x04 | |
| 20 | +#define ADIS16460_REG_X_GYRO_OUT 0x06 | |
| 21 | +#define ADIS16460_REG_Y_GYRO_LOW 0x08 | |
| 22 | +#define ADIS16460_REG_Y_GYRO_OUT 0x0A | |
| 23 | +#define ADIS16460_REG_Z_GYRO_LOW 0x0C | |
| 24 | +#define ADIS16460_REG_Z_GYRO_OUT 0x0E | |
| 25 | +#define ADIS16460_REG_X_ACCL_LOW 0x10 | |
| 26 | +#define ADIS16460_REG_X_ACCL_OUT 0x12 | |
| 27 | +#define ADIS16460_REG_Y_ACCL_LOW 0x14 | |
| 28 | +#define ADIS16460_REG_Y_ACCL_OUT 0x16 | |
| 29 | +#define ADIS16460_REG_Z_ACCL_LOW 0x18 | |
| 30 | +#define ADIS16460_REG_Z_ACCL_OUT 0x1A | |
| 31 | +#define ADIS16460_REG_SMPL_CNTR 0x1C | |
| 32 | +#define ADIS16460_REG_TEMP_OUT 0x1E | |
| 33 | +#define ADIS16460_REG_X_DELT_ANG 0x24 | |
| 34 | +#define ADIS16460_REG_Y_DELT_ANG 0x26 | |
| 35 | +#define ADIS16460_REG_Z_DELT_ANG 0x28 | |
| 36 | +#define ADIS16460_REG_X_DELT_VEL 0x2A | |
| 37 | +#define ADIS16460_REG_Y_DELT_VEL 0x2C | |
| 38 | +#define ADIS16460_REG_Z_DELT_VEL 0x2E | |
| 39 | +#define ADIS16460_REG_MSC_CTRL 0x32 | |
| 40 | +#define ADIS16460_REG_SYNC_SCAL 0x34 | |
| 41 | +#define ADIS16460_REG_DEC_RATE 0x36 | |
| 42 | +#define ADIS16460_REG_FLTR_CTRL 0x38 | |
| 43 | +#define ADIS16460_REG_GLOB_CMD 0x3E | |
| 44 | +#define ADIS16460_REG_X_GYRO_OFF 0x40 | |
| 45 | +#define ADIS16460_REG_Y_GYRO_OFF 0x42 | |
| 46 | +#define ADIS16460_REG_Z_GYRO_OFF 0x44 | |
| 47 | +#define ADIS16460_REG_X_ACCL_OFF 0x46 | |
| 48 | +#define ADIS16460_REG_Y_ACCL_OFF 0x48 | |
| 49 | +#define ADIS16460_REG_Z_ACCL_OFF 0x4A | |
| 50 | +#define ADIS16460_REG_LOT_ID1 0x52 | |
| 51 | +#define ADIS16460_REG_LOT_ID2 0x54 | |
| 52 | +#define ADIS16460_REG_PROD_ID 0x56 | |
| 53 | +#define ADIS16460_REG_SERIAL_NUM 0x58 | |
| 54 | +#define ADIS16460_REG_CAL_SGNTR 0x60 | |
| 55 | +#define ADIS16460_REG_CAL_CRC 0x62 | |
| 56 | +#define ADIS16460_REG_CODE_SGNTR 0x64 | |
| 57 | +#define ADIS16460_REG_CODE_CRC 0x66 | |
| 58 | + | |
| 59 | +struct adis16460_chip_info { | |
| 60 | + unsigned int num_channels; | |
| 61 | + const struct iio_chan_spec *channels; | |
| 62 | + unsigned int gyro_max_val; | |
| 63 | + unsigned int gyro_max_scale; | |
| 64 | + unsigned int accel_max_val; | |
| 65 | + unsigned int accel_max_scale; | |
| 66 | +}; | |
| 67 | + | |
| 68 | +struct adis16460 { | |
| 69 | + const struct adis16460_chip_info *chip_info; | |
| 70 | + struct adis adis; | |
| 71 | +}; | |
| 72 | + | |
| 73 | +#ifdef CONFIG_DEBUG_FS | |
| 74 | + | |
| 75 | +static int adis16460_show_serial_number(void *arg, u64 *val) | |
| 76 | +{ | |
| 77 | + struct adis16460 *adis16460 = arg; | |
| 78 | + u16 serial; | |
| 79 | + int ret; | |
| 80 | + | |
| 81 | + ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_SERIAL_NUM, | |
| 82 | + &serial); | |
| 83 | + if (ret < 0) | |
| 84 | + return ret; | |
| 85 | + | |
| 86 | + *val = serial; | |
| 87 | + | |
| 88 | + return 0; | |
| 89 | +} | |
| 90 | +DEFINE_SIMPLE_ATTRIBUTE(adis16460_serial_number_fops, | |
| 91 | + adis16460_show_serial_number, NULL, "0x%.4llx\n"); | |
| 92 | + | |
| 93 | +static int adis16460_show_product_id(void *arg, u64 *val) | |
| 94 | +{ | |
| 95 | + struct adis16460 *adis16460 = arg; | |
| 96 | + u16 prod_id; | |
| 97 | + int ret; | |
| 98 | + | |
| 99 | + ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_PROD_ID, | |
| 100 | + &prod_id); | |
| 101 | + if (ret < 0) | |
| 102 | + return ret; | |
| 103 | + | |
| 104 | + *val = prod_id; | |
| 105 | + | |
| 106 | + return 0; | |
| 107 | +} | |
| 108 | +DEFINE_SIMPLE_ATTRIBUTE(adis16460_product_id_fops, | |
| 109 | + adis16460_show_product_id, NULL, "%llu\n"); | |
| 110 | + | |
| 111 | +static int adis16460_show_flash_count(void *arg, u64 *val) | |
| 112 | +{ | |
| 113 | + struct adis16460 *adis16460 = arg; | |
| 114 | + u32 flash_count; | |
| 115 | + int ret; | |
| 116 | + | |
| 117 | + ret = adis_read_reg_32(&adis16460->adis, ADIS16460_REG_FLASH_CNT, | |
| 118 | + &flash_count); | |
| 119 | + if (ret < 0) | |
| 120 | + return ret; | |
| 121 | + | |
| 122 | + *val = flash_count; | |
| 123 | + | |
| 124 | + return 0; | |
| 125 | +} | |
| 126 | +DEFINE_SIMPLE_ATTRIBUTE(adis16460_flash_count_fops, | |
| 127 | + adis16460_show_flash_count, NULL, "%lld\n"); | |
| 128 | + | |
| 129 | +static int adis16460_debugfs_init(struct iio_dev *indio_dev) | |
| 130 | +{ | |
| 131 | + struct adis16460 *adis16460 = iio_priv(indio_dev); | |
| 132 | + | |
| 133 | + debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry, | |
| 134 | + adis16460, &adis16460_serial_number_fops); | |
| 135 | + debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry, | |
| 136 | + adis16460, &adis16460_product_id_fops); | |
| 137 | + debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry, | |
| 138 | + adis16460, &adis16460_flash_count_fops); | |
| 139 | + | |
| 140 | + return 0; | |
| 141 | +} | |
| 142 | + | |
| 143 | +#else | |
| 144 | + | |
| 145 | +static int adis16460_debugfs_init(struct iio_dev *indio_dev) | |
| 146 | +{ | |
| 147 | + return 0; | |
| 148 | +} | |
| 149 | + | |
| 150 | +#endif | |
| 151 | + | |
| 152 | +static int adis16460_set_freq(struct iio_dev *indio_dev, int val, int val2) | |
| 153 | +{ | |
| 154 | + struct adis16460 *st = iio_priv(indio_dev); | |
| 155 | + unsigned int t; | |
| 156 | + | |
| 157 | + t = val * 1000 + val2 / 1000; | |
| 158 | + if (t <= 0) | |
| 159 | + return -EINVAL; | |
| 160 | + | |
| 161 | + t = 2048000 / t; | |
| 162 | + if (t > 2048) | |
| 163 | + t = 2048; | |
| 164 | + | |
| 165 | + if (t != 0) | |
| 166 | + t--; | |
| 167 | + | |
| 168 | + return adis_write_reg_16(&st->adis, ADIS16460_REG_DEC_RATE, t); | |
| 169 | +} | |
| 170 | + | |
| 171 | +static int adis16460_get_freq(struct iio_dev *indio_dev, int *val, int *val2) | |
| 172 | +{ | |
| 173 | + struct adis16460 *st = iio_priv(indio_dev); | |
| 174 | + uint16_t t; | |
| 175 | + int ret; | |
| 176 | + unsigned int freq; | |
| 177 | + | |
| 178 | + ret = adis_read_reg_16(&st->adis, ADIS16460_REG_DEC_RATE, &t); | |
| 179 | + if (ret < 0) | |
| 180 | + return ret; | |
| 181 | + | |
| 182 | + freq = 2048000 / (t + 1); | |
| 183 | + *val = freq / 1000; | |
| 184 | + *val2 = (freq % 1000) * 1000; | |
| 185 | + | |
| 186 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 187 | +} | |
| 188 | + | |
| 189 | +static int adis16460_read_raw(struct iio_dev *indio_dev, | |
| 190 | + const struct iio_chan_spec *chan, int *val, int *val2, long info) | |
| 191 | +{ | |
| 192 | + struct adis16460 *st = iio_priv(indio_dev); | |
| 193 | + | |
| 194 | + switch (info) { | |
| 195 | + case IIO_CHAN_INFO_RAW: | |
| 196 | + return adis_single_conversion(indio_dev, chan, 0, val); | |
| 197 | + case IIO_CHAN_INFO_SCALE: | |
| 198 | + switch (chan->type) { | |
| 199 | + case IIO_ANGL_VEL: | |
| 200 | + *val = st->chip_info->gyro_max_scale; | |
| 201 | + *val2 = st->chip_info->gyro_max_val; | |
| 202 | + return IIO_VAL_FRACTIONAL; | |
| 203 | + case IIO_ACCEL: | |
| 204 | + *val = st->chip_info->accel_max_scale; | |
| 205 | + *val2 = st->chip_info->accel_max_val; | |
| 206 | + return IIO_VAL_FRACTIONAL; | |
| 207 | + case IIO_TEMP: | |
| 208 | + *val = 50; /* 50 milli degrees Celsius/LSB */ | |
| 209 | + return IIO_VAL_INT; | |
| 210 | + default: | |
| 211 | + return -EINVAL; | |
| 212 | + } | |
| 213 | + case IIO_CHAN_INFO_OFFSET: | |
| 214 | + *val = 500; /* 25 degrees Celsius = 0x0000 */ | |
| 215 | + return IIO_VAL_INT; | |
| 216 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 217 | + return adis16460_get_freq(indio_dev, val, val2); | |
| 218 | + default: | |
| 219 | + return -EINVAL; | |
| 220 | + } | |
| 221 | +} | |
| 222 | + | |
| 223 | +static int adis16460_write_raw(struct iio_dev *indio_dev, | |
| 224 | + const struct iio_chan_spec *chan, int val, int val2, long info) | |
| 225 | +{ | |
| 226 | + switch (info) { | |
| 227 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 228 | + return adis16460_set_freq(indio_dev, val, val2); | |
| 229 | + default: | |
| 230 | + return -EINVAL; | |
| 231 | + } | |
| 232 | +} | |
| 233 | + | |
| 234 | +enum { | |
| 235 | + ADIS16460_SCAN_GYRO_X, | |
| 236 | + ADIS16460_SCAN_GYRO_Y, | |
| 237 | + ADIS16460_SCAN_GYRO_Z, | |
| 238 | + ADIS16460_SCAN_ACCEL_X, | |
| 239 | + ADIS16460_SCAN_ACCEL_Y, | |
| 240 | + ADIS16460_SCAN_ACCEL_Z, | |
| 241 | + ADIS16460_SCAN_TEMP, | |
| 242 | +}; | |
| 243 | + | |
| 244 | +#define ADIS16460_MOD_CHANNEL(_type, _mod, _address, _si, _bits) \ | |
| 245 | + { \ | |
| 246 | + .type = (_type), \ | |
| 247 | + .modified = 1, \ | |
| 248 | + .channel2 = (_mod), \ | |
| 249 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| 250 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | |
| 251 | + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | |
| 252 | + .address = (_address), \ | |
| 253 | + .scan_index = (_si), \ | |
| 254 | + .scan_type = { \ | |
| 255 | + .sign = 's', \ | |
| 256 | + .realbits = (_bits), \ | |
| 257 | + .storagebits = (_bits), \ | |
| 258 | + .endianness = IIO_BE, \ | |
| 259 | + }, \ | |
| 260 | + } | |
| 261 | + | |
| 262 | +#define ADIS16460_GYRO_CHANNEL(_mod) \ | |
| 263 | + ADIS16460_MOD_CHANNEL(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \ | |
| 264 | + ADIS16460_REG_ ## _mod ## _GYRO_LOW, ADIS16460_SCAN_GYRO_ ## _mod, \ | |
| 265 | + 32) | |
| 266 | + | |
| 267 | +#define ADIS16460_ACCEL_CHANNEL(_mod) \ | |
| 268 | + ADIS16460_MOD_CHANNEL(IIO_ACCEL, IIO_MOD_ ## _mod, \ | |
| 269 | + ADIS16460_REG_ ## _mod ## _ACCL_LOW, ADIS16460_SCAN_ACCEL_ ## _mod, \ | |
| 270 | + 32) | |
| 271 | + | |
| 272 | +#define ADIS16460_TEMP_CHANNEL() { \ | |
| 273 | + .type = IIO_TEMP, \ | |
| 274 | + .indexed = 1, \ | |
| 275 | + .channel = 0, \ | |
| 276 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | |
| 277 | + BIT(IIO_CHAN_INFO_SCALE) | \ | |
| 278 | + BIT(IIO_CHAN_INFO_OFFSET), \ | |
| 279 | + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | |
| 280 | + .address = ADIS16460_REG_TEMP_OUT, \ | |
| 281 | + .scan_index = ADIS16460_SCAN_TEMP, \ | |
| 282 | + .scan_type = { \ | |
| 283 | + .sign = 's', \ | |
| 284 | + .realbits = 16, \ | |
| 285 | + .storagebits = 16, \ | |
| 286 | + .endianness = IIO_BE, \ | |
| 287 | + }, \ | |
| 288 | + } | |
| 289 | + | |
| 290 | +static const struct iio_chan_spec adis16460_channels[] = { | |
| 291 | + ADIS16460_GYRO_CHANNEL(X), | |
| 292 | + ADIS16460_GYRO_CHANNEL(Y), | |
| 293 | + ADIS16460_GYRO_CHANNEL(Z), | |
| 294 | + ADIS16460_ACCEL_CHANNEL(X), | |
| 295 | + ADIS16460_ACCEL_CHANNEL(Y), | |
| 296 | + ADIS16460_ACCEL_CHANNEL(Z), | |
| 297 | + ADIS16460_TEMP_CHANNEL(), | |
| 298 | + IIO_CHAN_SOFT_TIMESTAMP(7) | |
| 299 | +}; | |
| 300 | + | |
| 301 | +static const struct adis16460_chip_info adis16460_chip_info = { | |
| 302 | + .channels = adis16460_channels, | |
| 303 | + .num_channels = ARRAY_SIZE(adis16460_channels), | |
| 304 | + /* | |
| 305 | + * storing the value in rad/degree and the scale in degree | |
| 306 | + * gives us the result in rad and better precession than | |
| 307 | + * storing the scale directly in rad. | |
| 308 | + */ | |
| 309 | + .gyro_max_val = IIO_RAD_TO_DEGREE(200 << 16), | |
| 310 | + .gyro_max_scale = 1, | |
| 311 | + .accel_max_val = IIO_M_S_2_TO_G(20000 << 16), | |
| 312 | + .accel_max_scale = 5, | |
| 313 | +}; | |
| 314 | + | |
| 315 | +static const struct iio_info adis16460_info = { | |
| 316 | + .read_raw = &adis16460_read_raw, | |
| 317 | + .write_raw = &adis16460_write_raw, | |
| 318 | + .update_scan_mode = adis_update_scan_mode, | |
| 319 | + .debugfs_reg_access = adis_debugfs_reg_access, | |
| 320 | +}; | |
| 321 | + | |
| 322 | +static int adis16460_enable_irq(struct adis *adis, bool enable) | |
| 323 | +{ | |
| 324 | + /* | |
| 325 | + * There is no way to gate the data-ready signal internally inside the | |
| 326 | + * ADIS16460 :( | |
| 327 | + */ | |
| 328 | + if (enable) | |
| 329 | + enable_irq(adis->spi->irq); | |
| 330 | + else | |
| 331 | + disable_irq(adis->spi->irq); | |
| 332 | + | |
| 333 | + return 0; | |
| 334 | +} | |
| 335 | + | |
| 336 | +static int adis16460_initial_setup(struct iio_dev *indio_dev) | |
| 337 | +{ | |
| 338 | + struct adis16460 *st = iio_priv(indio_dev); | |
| 339 | + uint16_t prod_id; | |
| 340 | + unsigned int device_id; | |
| 341 | + int ret; | |
| 342 | + | |
| 343 | + adis_reset(&st->adis); | |
| 344 | + msleep(222); | |
| 345 | + | |
| 346 | + ret = adis_write_reg_16(&st->adis, ADIS16460_REG_GLOB_CMD, BIT(1)); | |
| 347 | + if (ret) | |
| 348 | + return ret; | |
| 349 | + msleep(75); | |
| 350 | + | |
| 351 | + ret = adis_check_status(&st->adis); | |
| 352 | + if (ret) | |
| 353 | + return ret; | |
| 354 | + | |
| 355 | + ret = adis_read_reg_16(&st->adis, ADIS16460_REG_PROD_ID, &prod_id); | |
| 356 | + if (ret) | |
| 357 | + return ret; | |
| 358 | + | |
| 359 | + ret = sscanf(indio_dev->name, "adis%u\n", &device_id); | |
| 360 | + if (ret != 1) | |
| 361 | + return -EINVAL; | |
| 362 | + | |
| 363 | + if (prod_id != device_id) | |
| 364 | + dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", | |
| 365 | + device_id, prod_id); | |
| 366 | + | |
| 367 | + return 0; | |
| 368 | +} | |
| 369 | + | |
| 370 | +#define ADIS16460_DIAG_STAT_IN_CLK_OOS 7 | |
| 371 | +#define ADIS16460_DIAG_STAT_FLASH_MEM 6 | |
| 372 | +#define ADIS16460_DIAG_STAT_SELF_TEST 5 | |
| 373 | +#define ADIS16460_DIAG_STAT_OVERRANGE 4 | |
| 374 | +#define ADIS16460_DIAG_STAT_SPI_COMM 3 | |
| 375 | +#define ADIS16460_DIAG_STAT_FLASH_UPT 2 | |
| 376 | + | |
| 377 | +static const char * const adis16460_status_error_msgs[] = { | |
| 378 | + [ADIS16460_DIAG_STAT_IN_CLK_OOS] = "Input clock out of sync", | |
| 379 | + [ADIS16460_DIAG_STAT_FLASH_MEM] = "Flash memory failure", | |
| 380 | + [ADIS16460_DIAG_STAT_SELF_TEST] = "Self test diagnostic failure", | |
| 381 | + [ADIS16460_DIAG_STAT_OVERRANGE] = "Sensor overrange", | |
| 382 | + [ADIS16460_DIAG_STAT_SPI_COMM] = "SPI communication failure", | |
| 383 | + [ADIS16460_DIAG_STAT_FLASH_UPT] = "Flash update failure", | |
| 384 | +}; | |
| 385 | + | |
| 386 | +static const struct adis_data adis16460_data = { | |
| 387 | + .diag_stat_reg = ADIS16460_REG_DIAG_STAT, | |
| 388 | + .glob_cmd_reg = ADIS16460_REG_GLOB_CMD, | |
| 389 | + .has_paging = false, | |
| 390 | + .read_delay = 5, | |
| 391 | + .write_delay = 5, | |
| 392 | + .cs_change_delay = 16, | |
| 393 | + .status_error_msgs = adis16460_status_error_msgs, | |
| 394 | + .status_error_mask = BIT(ADIS16460_DIAG_STAT_IN_CLK_OOS) | | |
| 395 | + BIT(ADIS16460_DIAG_STAT_FLASH_MEM) | | |
| 396 | + BIT(ADIS16460_DIAG_STAT_SELF_TEST) | | |
| 397 | + BIT(ADIS16460_DIAG_STAT_OVERRANGE) | | |
| 398 | + BIT(ADIS16460_DIAG_STAT_SPI_COMM) | | |
| 399 | + BIT(ADIS16460_DIAG_STAT_FLASH_UPT), | |
| 400 | + .enable_irq = adis16460_enable_irq, | |
| 401 | +}; | |
| 402 | + | |
| 403 | +static int adis16460_probe(struct spi_device *spi) | |
| 404 | +{ | |
| 405 | + struct iio_dev *indio_dev; | |
| 406 | + struct adis16460 *st; | |
| 407 | + int ret; | |
| 408 | + | |
| 409 | + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); | |
| 410 | + if (indio_dev == NULL) | |
| 411 | + return -ENOMEM; | |
| 412 | + | |
| 413 | + spi_set_drvdata(spi, indio_dev); | |
| 414 | + | |
| 415 | + st = iio_priv(indio_dev); | |
| 416 | + | |
| 417 | + st->chip_info = &adis16460_chip_info; | |
| 418 | + indio_dev->dev.parent = &spi->dev; | |
| 419 | + indio_dev->name = spi_get_device_id(spi)->name; | |
| 420 | + indio_dev->channels = st->chip_info->channels; | |
| 421 | + indio_dev->num_channels = st->chip_info->num_channels; | |
| 422 | + indio_dev->info = &adis16460_info; | |
| 423 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 424 | + | |
| 425 | + ret = adis_init(&st->adis, indio_dev, spi, &adis16460_data); | |
| 426 | + if (ret) | |
| 427 | + return ret; | |
| 428 | + | |
| 429 | + ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); | |
| 430 | + if (ret) | |
| 431 | + return ret; | |
| 432 | + | |
| 433 | + adis16460_enable_irq(&st->adis, 0); | |
| 434 | + | |
| 435 | + ret = adis16460_initial_setup(indio_dev); | |
| 436 | + if (ret) | |
| 437 | + goto error_cleanup_buffer; | |
| 438 | + | |
| 439 | + ret = iio_device_register(indio_dev); | |
| 440 | + if (ret) | |
| 441 | + goto error_cleanup_buffer; | |
| 442 | + | |
| 443 | + adis16460_debugfs_init(indio_dev); | |
| 444 | + | |
| 445 | + return 0; | |
| 446 | + | |
| 447 | +error_cleanup_buffer: | |
| 448 | + adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); | |
| 449 | + return ret; | |
| 450 | +} | |
| 451 | + | |
| 452 | +static int adis16460_remove(struct spi_device *spi) | |
| 453 | +{ | |
| 454 | + struct iio_dev *indio_dev = spi_get_drvdata(spi); | |
| 455 | + struct adis16460 *st = iio_priv(indio_dev); | |
| 456 | + | |
| 457 | + iio_device_unregister(indio_dev); | |
| 458 | + | |
| 459 | + adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); | |
| 460 | + | |
| 461 | + return 0; | |
| 462 | +} | |
| 463 | + | |
| 464 | +static const struct spi_device_id adis16460_ids[] = { | |
| 465 | + { "adis16460", 0 }, | |
| 466 | + {} | |
| 467 | +}; | |
| 468 | +MODULE_DEVICE_TABLE(spi, adis16460_ids); | |
| 469 | + | |
| 470 | +static const struct of_device_id adis16460_of_match[] = { | |
| 471 | + { .compatible = "adi,adis16460" }, | |
| 472 | + {} | |
| 473 | +}; | |
| 474 | +MODULE_DEVICE_TABLE(of, adis16460_of_match); | |
| 475 | + | |
| 476 | +static struct spi_driver adis16460_driver = { | |
| 477 | + .driver = { | |
| 478 | + .name = "adis16460", | |
| 479 | + .of_match_table = adis16460_of_match, | |
| 480 | + }, | |
| 481 | + .id_table = adis16460_ids, | |
| 482 | + .probe = adis16460_probe, | |
| 483 | + .remove = adis16460_remove, | |
| 484 | +}; | |
| 485 | +module_spi_driver(adis16460_driver); | |
| 486 | + | |
| 487 | +MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>"); | |
| 488 | +MODULE_DESCRIPTION("Analog Devices ADIS16460 IMU driver"); | |
| 489 | +MODULE_LICENSE("GPL"); | |
| @@ -14,8 +14,9 @@ config INV_MPU6050_I2C · 13 unmodified lines | ||
| 14 | 14 | select INV_MPU6050_IIO |
| 15 | 15 | select REGMAP_I2C |
| 16 | 16 | help |
| 17 | − This driver supports the Invensense MPU6050/6500/9150 and | |
| 18 | − ICM20608/20602 motion tracking devices over I2C. | |
| 17 | + This driver supports the Invensense MPU6000/6050/6500/6515, | |
| 18 | + MPU9150/9250/9255 and ICM20608/20602 motion tracking devices | |
| 19 | + over I2C. | |
| 19 | 20 | This driver can be built as a module. The module will be called |
| 20 | 21 | inv-mpu6050-i2c. |
| 21 | 22 | |
| @@ -25,7 +26,8 @@ config INV_MPU6050_SPI · 3 unmodified lines | ||
| 25 | 26 | select INV_MPU6050_IIO |
| 26 | 27 | select REGMAP_SPI |
| 27 | 28 | help |
| 28 | − This driver supports the Invensense MPU6050/6500/9150 and | |
| 29 | − ICM20608/20602 motion tracking devices over SPI. | |
| 29 | + This driver supports the Invensense MPU6000/6050/6500/6515, | |
| 30 | + MPU9150/9250/9255 and ICM20608/20602 motion tracking devices | |
| 31 | + over SPI. | |
| 30 | 32 | This driver can be built as a module. The module will be called |
| 31 | 33 | inv-mpu6050-spi. |
| @@ -1137,10 +1137,9 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, · 1136 unmodified lines | ||
| 1137 | 1137 | if (result) |
| 1138 | 1138 | return result; |
| 1139 | 1139 | |
| 1140 | − result = devm_add_action(dev, inv_mpu_core_disable_regulator_action, | |
| 1140 | + result = devm_add_action_or_reset(dev, inv_mpu_core_disable_regulator_action, | |
| 1141 | 1141 | st); |
| 1142 | 1142 | if (result) { |
| 1143 | − inv_mpu_core_disable_regulator_action(st); | |
| 1144 | 1143 | dev_err(dev, "Failed to setup regulator cleanup action %d\n", |
| 1145 | 1144 | result); |
| 1146 | 1145 | return result; |
| @@ -2,15 +2,17 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | config IIO_ST_LSM6DSX |
| 4 | 4 | tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors" |
| 5 | − depends on (I2C || SPI) | |
| 5 | + depends on (I2C || SPI || I3C) | |
| 6 | 6 | select IIO_BUFFER |
| 7 | 7 | select IIO_KFIFO_BUF |
| 8 | 8 | select IIO_ST_LSM6DSX_I2C if (I2C) |
| 9 | 9 | select IIO_ST_LSM6DSX_SPI if (SPI_MASTER) |
| 10 | + select IIO_ST_LSM6DSX_I3C if (I3C) | |
| 10 | 11 | help |
| 11 | 12 | Say yes here to build support for STMicroelectronics LSM6DSx imu |
| 12 | 13 | sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm, |
| 13 | − ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr | |
| 14 | + ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr, lsm6ds3tr-c, | |
| 15 | + ism330dhcx | |
| 14 | 16 | |
| 15 | 17 | To compile this driver as a module, choose M here: the module |
| 16 | 18 | will be called st_lsm6dsx. |
| @@ -24,3 +26,8 @@ config IIO_ST_LSM6DSX_SPI · 7 unmodified lines | ||
| 24 | 26 | tristate |
| 25 | 27 | depends on IIO_ST_LSM6DSX |
| 26 | 28 | select REGMAP_SPI |
| 29 | + | |
| 30 | +config IIO_ST_LSM6DSX_I3C | |
| 31 | + tristate | |
| 32 | + depends on IIO_ST_LSM6DSX | |
| 33 | + select REGMAP_I3C | |
| @@ -5,3 +5,4 @@ st_lsm6dsx-y := st_lsm6dsx_core.o st_lsm6dsx_buffer.o \ · 4 unmodified lines | ||
| 5 | 5 | obj-$(CONFIG_IIO_ST_LSM6DSX) += st_lsm6dsx.o |
| 6 | 6 | obj-$(CONFIG_IIO_ST_LSM6DSX_I2C) += st_lsm6dsx_i2c.o |
| 7 | 7 | obj-$(CONFIG_IIO_ST_LSM6DSX_SPI) += st_lsm6dsx_spi.o |
| 8 | +obj-$(CONFIG_IIO_ST_LSM6DSX_I3C) += st_lsm6dsx_i3c.o | |
| @@ -22,6 +22,8 @@ · 21 unmodified lines | ||
| 22 | 22 | #define ST_ASM330LHH_DEV_NAME "asm330lhh" |
| 23 | 23 | #define ST_LSM6DSOX_DEV_NAME "lsm6dsox" |
| 24 | 24 | #define ST_LSM6DSR_DEV_NAME "lsm6dsr" |
| 25 | +#define ST_LSM6DS3TRC_DEV_NAME "lsm6ds3tr-c" | |
| 26 | +#define ST_ISM330DHCX_DEV_NAME "ism330dhcx" | |
| 25 | 27 | |
| 26 | 28 | enum st_lsm6dsx_hw_id { |
| 27 | 29 | ST_LSM6DS3_ID, |
| @@ -33,6 +35,8 @@ enum st_lsm6dsx_hw_id { · 5 unmodified lines | ||
| 33 | 35 | ST_ASM330LHH_ID, |
| 34 | 36 | ST_LSM6DSOX_ID, |
| 35 | 37 | ST_LSM6DSR_ID, |
| 38 | + ST_LSM6DS3TRC_ID, | |
| 39 | + ST_ISM330DHCX_ID, | |
| 36 | 40 | ST_LSM6DSX_MAX_ID, |
| 37 | 41 | }; |
| 38 | 42 | |
| @@ -54,8 +58,8 @@ enum st_lsm6dsx_hw_id { · 15 unmodified lines | ||
| 54 | 58 | .address = addr, \ |
| 55 | 59 | .modified = 1, \ |
| 56 | 60 | .channel2 = mod, \ |
| 57 | − .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | |
| 58 | − BIT(IIO_CHAN_INFO_SCALE), \ | |
| 61 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| 62 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | |
| 59 | 63 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ |
| 60 | 64 | .scan_index = scan_idx, \ |
| 61 | 65 | .scan_type = { \ |
| @@ -198,6 +202,9 @@ struct st_lsm6dsx_ext_dev_settings { · 136 unmodified lines | ||
| 198 | 202 | * @wai: Sensor WhoAmI default value. |
| 199 | 203 | * @max_fifo_size: Sensor max fifo length in FIFO words. |
| 200 | 204 | * @id: List of hw id/device name supported by the driver configuration. |
| 205 | + * @channels: IIO channels supported by the device. | |
| 206 | + * @odr_table: Hw sensors odr table (Hz + val). | |
| 207 | + * @fs_table: Hw sensors gain table (gain + val). | |
| 201 | 208 | * @decimator: List of decimator register info (addr + mask). |
| 202 | 209 | * @batch: List of FIFO batching register info (addr + mask). |
| 203 | 210 | * @fifo_ops: Sensor hw FIFO parameters. |
| @@ -211,6 +218,12 @@ struct st_lsm6dsx_settings { · 7 unmodified lines | ||
| 211 | 218 | enum st_lsm6dsx_hw_id hw_id; |
| 212 | 219 | const char *name; |
| 213 | 220 | } id[ST_LSM6DSX_MAX_ID]; |
| 221 | + struct { | |
| 222 | + const struct iio_chan_spec *chan; | |
| 223 | + int len; | |
| 224 | + } channels[2]; | |
| 225 | + struct st_lsm6dsx_odr_table_entry odr_table[2]; | |
| 226 | + struct st_lsm6dsx_fs_table_entry fs_table[2]; | |
| 214 | 227 | struct st_lsm6dsx_reg decimator[ST_LSM6DSX_MAX_ID]; |
| 215 | 228 | struct st_lsm6dsx_reg batch[ST_LSM6DSX_MAX_ID]; |
| 216 | 229 | struct st_lsm6dsx_fifo_ops fifo_ops; |
| @@ -2,10 +2,10 @@ · 1 unmodified line | ||
| 2 | 2 | /* |
| 3 | 3 | * STMicroelectronics st_lsm6dsx FIFO buffer library driver |
| 4 | 4 | * |
| 5 | − * LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC: The FIFO buffer can be | |
| 6 | − * configured to store data from gyroscope and accelerometer. Samples are | |
| 7 | − * queued without any tag according to a specific pattern based on | |
| 8 | − * 'FIFO data sets' (6 bytes each): | |
| 5 | + * LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C: | |
| 6 | + * The FIFO buffer can be configured to store data from gyroscope and | |
| 7 | + * accelerometer. Samples are queued without any tag according to a | |
| 8 | + * specific pattern based on 'FIFO data sets' (6 bytes each): | |
| 9 | 9 | * - 1st data set is reserved for gyroscope data |
| 10 | 10 | * - 2nd data set is reserved for accelerometer data |
| 11 | 11 | * The FIFO pattern changes depending on the ODRs and decimation factors |
| @@ -14,9 +14,10 @@ · 2 unmodified lines | ||
| 14 | 14 | * (e.g. Gx, Gy, Gz, Ax, Ay, Az), then data are repeated depending on the |
| 15 | 15 | * value of the decimation factor and ODR set for each FIFO data set. |
| 16 | 16 | * |
| 17 | − * LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR: The FIFO buffer can be configured to | |
| 18 | − * store data from gyroscope and accelerometer. Each sample is queued with | |
| 19 | − * a tag (1B) indicating data source (gyroscope, accelerometer, hw timer). | |
| 17 | + * LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX: The FIFO buffer can be | |
| 18 | + * configured to store data from gyroscope and accelerometer. Each sample | |
| 19 | + * is queued with a tag (1B) indicating data source (gyroscope, accelerometer, | |
| 20 | + * hw timer). | |
| 20 | 21 | * |
| 21 | 22 | * FIFO supported modes: |
| 22 | 23 | * - BYPASS: FIFO disabled |
| @@ -670,7 +671,7 @@ static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) · 647 unmodified lines | ||
| 670 | 671 | count = hw->settings->fifo_ops.read_fifo(hw); |
| 671 | 672 | mutex_unlock(&hw->fifo_lock); |
| 672 | 673 | |
| 673 | − return !count ? IRQ_NONE : IRQ_HANDLED; | |
| 674 | + return count ? IRQ_HANDLED : IRQ_NONE; | |
| 674 | 675 | } |
| 675 | 676 | |
| 676 | 677 | static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev) |
| @@ -18,13 +18,13 @@ · 17 unmodified lines | ||
| 18 | 18 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 |
| 19 | 19 | * - FIFO size: 8KB |
| 20 | 20 | * |
| 21 | − * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC: | |
| 21 | + * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C: | |
| 22 | 22 | * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 |
| 23 | 23 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 |
| 24 | 24 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 |
| 25 | 25 | * - FIFO size: 4KB |
| 26 | 26 | * |
| 27 | − * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR | |
| 27 | + * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX: | |
| 28 | 28 | * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 |
| 29 | 29 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 |
| 30 | 30 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 |
| @@ -61,62 +61,18 @@ · 30 unmodified lines | ||
| 61 | 61 | #define ST_LSM6DSX_REG_INT2_ON_INT1_ADDR 0x13 |
| 62 | 62 | #define ST_LSM6DSX_REG_INT2_ON_INT1_MASK BIT(5) |
| 63 | 63 | |
| 64 | −#define ST_LSM6DSX_REG_ACC_OUT_X_L_ADDR 0x28 | |
| 65 | −#define ST_LSM6DSX_REG_ACC_OUT_Y_L_ADDR 0x2a | |
| 66 | −#define ST_LSM6DSX_REG_ACC_OUT_Z_L_ADDR 0x2c | |
| 67 | − | |
| 68 | −#define ST_LSM6DSX_REG_GYRO_OUT_X_L_ADDR 0x22 | |
| 69 | −#define ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR 0x24 | |
| 70 | −#define ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR 0x26 | |
| 71 | − | |
| 72 | −static const struct st_lsm6dsx_odr_table_entry st_lsm6dsx_odr_table[] = { | |
| 73 | − [ST_LSM6DSX_ID_ACC] = { | |
| 74 | − .reg = { | |
| 75 | − .addr = 0x10, | |
| 76 | − .mask = GENMASK(7, 4), | |
| 77 | − }, | |
| 78 | − .odr_avl[0] = { 13, 0x01 }, | |
| 79 | − .odr_avl[1] = { 26, 0x02 }, | |
| 80 | − .odr_avl[2] = { 52, 0x03 }, | |
| 81 | − .odr_avl[3] = { 104, 0x04 }, | |
| 82 | − .odr_avl[4] = { 208, 0x05 }, | |
| 83 | − .odr_avl[5] = { 416, 0x06 }, | |
| 84 | − }, | |
| 85 | − [ST_LSM6DSX_ID_GYRO] = { | |
| 86 | − .reg = { | |
| 87 | − .addr = 0x11, | |
| 88 | − .mask = GENMASK(7, 4), | |
| 89 | − }, | |
| 90 | − .odr_avl[0] = { 13, 0x01 }, | |
| 91 | − .odr_avl[1] = { 26, 0x02 }, | |
| 92 | − .odr_avl[2] = { 52, 0x03 }, | |
| 93 | − .odr_avl[3] = { 104, 0x04 }, | |
| 94 | − .odr_avl[4] = { 208, 0x05 }, | |
| 95 | − .odr_avl[5] = { 416, 0x06 }, | |
| 96 | − } | |
| 64 | +static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { | |
| 65 | + ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x28, IIO_MOD_X, 0), | |
| 66 | + ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), | |
| 67 | + ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2), | |
| 68 | + IIO_CHAN_SOFT_TIMESTAMP(3), | |
| 97 | 69 | }; |
| 98 | 70 | |
| 99 | −static const struct st_lsm6dsx_fs_table_entry st_lsm6dsx_fs_table[] = { | |
| 100 | − [ST_LSM6DSX_ID_ACC] = { | |
| 101 | − .reg = { | |
| 102 | − .addr = 0x10, | |
| 103 | − .mask = GENMASK(3, 2), | |
| 104 | − }, | |
| 105 | − .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, | |
| 106 | − .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
| 107 | − .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
| 108 | − .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, | |
| 109 | − }, | |
| 110 | − [ST_LSM6DSX_ID_GYRO] = { | |
| 111 | − .reg = { | |
| 112 | − .addr = 0x11, | |
| 113 | − .mask = GENMASK(3, 2), | |
| 114 | − }, | |
| 115 | − .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
| 116 | − .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
| 117 | − .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, | |
| 118 | − .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
| 119 | − } | |
| 71 | +static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { | |
| 72 | + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x22, IIO_MOD_X, 0), | |
| 73 | + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x24, IIO_MOD_Y, 1), | |
| 74 | + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x26, IIO_MOD_Z, 2), | |
| 75 | + IIO_CHAN_SOFT_TIMESTAMP(3), | |
| 120 | 76 | }; |
| 121 | 77 | |
| 122 | 78 | static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { |
| @@ -129,6 +85,64 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 6 unmodified lines | ||
| 129 | 85 | .name = ST_LSM6DS3_DEV_NAME, |
| 130 | 86 | }, |
| 131 | 87 | }, |
| 88 | + .channels = { | |
| 89 | + [ST_LSM6DSX_ID_ACC] = { | |
| 90 | + .chan = st_lsm6dsx_acc_channels, | |
| 91 | + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), | |
| 92 | + }, | |
| 93 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 94 | + .chan = st_lsm6dsx_gyro_channels, | |
| 95 | + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), | |
| 96 | + }, | |
| 97 | + }, | |
| 98 | + .odr_table = { | |
| 99 | + [ST_LSM6DSX_ID_ACC] = { | |
| 100 | + .reg = { | |
| 101 | + .addr = 0x10, | |
| 102 | + .mask = GENMASK(7, 4), | |
| 103 | + }, | |
| 104 | + .odr_avl[0] = { 13, 0x01 }, | |
| 105 | + .odr_avl[1] = { 26, 0x02 }, | |
| 106 | + .odr_avl[2] = { 52, 0x03 }, | |
| 107 | + .odr_avl[3] = { 104, 0x04 }, | |
| 108 | + .odr_avl[4] = { 208, 0x05 }, | |
| 109 | + .odr_avl[5] = { 416, 0x06 }, | |
| 110 | + }, | |
| 111 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 112 | + .reg = { | |
| 113 | + .addr = 0x11, | |
| 114 | + .mask = GENMASK(7, 4), | |
| 115 | + }, | |
| 116 | + .odr_avl[0] = { 13, 0x01 }, | |
| 117 | + .odr_avl[1] = { 26, 0x02 }, | |
| 118 | + .odr_avl[2] = { 52, 0x03 }, | |
| 119 | + .odr_avl[3] = { 104, 0x04 }, | |
| 120 | + .odr_avl[4] = { 208, 0x05 }, | |
| 121 | + .odr_avl[5] = { 416, 0x06 }, | |
| 122 | + }, | |
| 123 | + }, | |
| 124 | + .fs_table = { | |
| 125 | + [ST_LSM6DSX_ID_ACC] = { | |
| 126 | + .reg = { | |
| 127 | + .addr = 0x10, | |
| 128 | + .mask = GENMASK(3, 2), | |
| 129 | + }, | |
| 130 | + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, | |
| 131 | + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
| 132 | + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
| 133 | + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, | |
| 134 | + }, | |
| 135 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 136 | + .reg = { | |
| 137 | + .addr = 0x11, | |
| 138 | + .mask = GENMASK(3, 2), | |
| 139 | + }, | |
| 140 | + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
| 141 | + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
| 142 | + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, | |
| 143 | + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
| 144 | + }, | |
| 145 | + }, | |
| 132 | 146 | .decimator = { |
| 133 | 147 | [ST_LSM6DSX_ID_ACC] = { |
| 134 | 148 | .addr = 0x08, |
| @@ -179,6 +193,64 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 44 unmodified lines | ||
| 179 | 193 | .name = ST_LSM6DS3H_DEV_NAME, |
| 180 | 194 | }, |
| 181 | 195 | }, |
| 196 | + .channels = { | |
| 197 | + [ST_LSM6DSX_ID_ACC] = { | |
| 198 | + .chan = st_lsm6dsx_acc_channels, | |
| 199 | + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), | |
| 200 | + }, | |
| 201 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 202 | + .chan = st_lsm6dsx_gyro_channels, | |
| 203 | + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), | |
| 204 | + }, | |
| 205 | + }, | |
| 206 | + .odr_table = { | |
| 207 | + [ST_LSM6DSX_ID_ACC] = { | |
| 208 | + .reg = { | |
| 209 | + .addr = 0x10, | |
| 210 | + .mask = GENMASK(7, 4), | |
| 211 | + }, | |
| 212 | + .odr_avl[0] = { 13, 0x01 }, | |
| 213 | + .odr_avl[1] = { 26, 0x02 }, | |
| 214 | + .odr_avl[2] = { 52, 0x03 }, | |
| 215 | + .odr_avl[3] = { 104, 0x04 }, | |
| 216 | + .odr_avl[4] = { 208, 0x05 }, | |
| 217 | + .odr_avl[5] = { 416, 0x06 }, | |
| 218 | + }, | |
| 219 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 220 | + .reg = { | |
| 221 | + .addr = 0x11, | |
| 222 | + .mask = GENMASK(7, 4), | |
| 223 | + }, | |
| 224 | + .odr_avl[0] = { 13, 0x01 }, | |
| 225 | + .odr_avl[1] = { 26, 0x02 }, | |
| 226 | + .odr_avl[2] = { 52, 0x03 }, | |
| 227 | + .odr_avl[3] = { 104, 0x04 }, | |
| 228 | + .odr_avl[4] = { 208, 0x05 }, | |
| 229 | + .odr_avl[5] = { 416, 0x06 }, | |
| 230 | + }, | |
| 231 | + }, | |
| 232 | + .fs_table = { | |
| 233 | + [ST_LSM6DSX_ID_ACC] = { | |
| 234 | + .reg = { | |
| 235 | + .addr = 0x10, | |
| 236 | + .mask = GENMASK(3, 2), | |
| 237 | + }, | |
| 238 | + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, | |
| 239 | + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
| 240 | + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
| 241 | + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, | |
| 242 | + }, | |
| 243 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 244 | + .reg = { | |
| 245 | + .addr = 0x11, | |
| 246 | + .mask = GENMASK(3, 2), | |
| 247 | + }, | |
| 248 | + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
| 249 | + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
| 250 | + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, | |
| 251 | + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
| 252 | + }, | |
| 253 | + }, | |
| 182 | 254 | .decimator = { |
| 183 | 255 | [ST_LSM6DSX_ID_ACC] = { |
| 184 | 256 | .addr = 0x08, |
| @@ -233,6 +305,67 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 48 unmodified lines | ||
| 233 | 305 | }, { |
| 234 | 306 | .hw_id = ST_ISM330DLC_ID, |
| 235 | 307 | .name = ST_ISM330DLC_DEV_NAME, |
| 308 | + }, { | |
| 309 | + .hw_id = ST_LSM6DS3TRC_ID, | |
| 310 | + .name = ST_LSM6DS3TRC_DEV_NAME, | |
| 311 | + }, | |
| 312 | + }, | |
| 313 | + .channels = { | |
| 314 | + [ST_LSM6DSX_ID_ACC] = { | |
| 315 | + .chan = st_lsm6dsx_acc_channels, | |
| 316 | + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), | |
| 317 | + }, | |
| 318 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 319 | + .chan = st_lsm6dsx_gyro_channels, | |
| 320 | + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), | |
| 321 | + }, | |
| 322 | + }, | |
| 323 | + .odr_table = { | |
| 324 | + [ST_LSM6DSX_ID_ACC] = { | |
| 325 | + .reg = { | |
| 326 | + .addr = 0x10, | |
| 327 | + .mask = GENMASK(7, 4), | |
| 328 | + }, | |
| 329 | + .odr_avl[0] = { 13, 0x01 }, | |
| 330 | + .odr_avl[1] = { 26, 0x02 }, | |
| 331 | + .odr_avl[2] = { 52, 0x03 }, | |
| 332 | + .odr_avl[3] = { 104, 0x04 }, | |
| 333 | + .odr_avl[4] = { 208, 0x05 }, | |
| 334 | + .odr_avl[5] = { 416, 0x06 }, | |
| 335 | + }, | |
| 336 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 337 | + .reg = { | |
| 338 | + .addr = 0x11, | |
| 339 | + .mask = GENMASK(7, 4), | |
| 340 | + }, | |
| 341 | + .odr_avl[0] = { 13, 0x01 }, | |
| 342 | + .odr_avl[1] = { 26, 0x02 }, | |
| 343 | + .odr_avl[2] = { 52, 0x03 }, | |
| 344 | + .odr_avl[3] = { 104, 0x04 }, | |
| 345 | + .odr_avl[4] = { 208, 0x05 }, | |
| 346 | + .odr_avl[5] = { 416, 0x06 }, | |
| 347 | + }, | |
| 348 | + }, | |
| 349 | + .fs_table = { | |
| 350 | + [ST_LSM6DSX_ID_ACC] = { | |
| 351 | + .reg = { | |
| 352 | + .addr = 0x10, | |
| 353 | + .mask = GENMASK(3, 2), | |
| 354 | + }, | |
| 355 | + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, | |
| 356 | + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
| 357 | + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
| 358 | + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, | |
| 359 | + }, | |
| 360 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 361 | + .reg = { | |
| 362 | + .addr = 0x11, | |
| 363 | + .mask = GENMASK(3, 2), | |
| 364 | + }, | |
| 365 | + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
| 366 | + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
| 367 | + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, | |
| 368 | + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
| 236 | 369 | }, |
| 237 | 370 | }, |
| 238 | 371 | .decimator = { |
| @@ -288,6 +421,64 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 49 unmodified lines | ||
| 288 | 421 | .name = ST_LSM6DSOX_DEV_NAME, |
| 289 | 422 | }, |
| 290 | 423 | }, |
| 424 | + .channels = { | |
| 425 | + [ST_LSM6DSX_ID_ACC] = { | |
| 426 | + .chan = st_lsm6dsx_acc_channels, | |
| 427 | + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), | |
| 428 | + }, | |
| 429 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 430 | + .chan = st_lsm6dsx_gyro_channels, | |
| 431 | + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), | |
| 432 | + }, | |
| 433 | + }, | |
| 434 | + .odr_table = { | |
| 435 | + [ST_LSM6DSX_ID_ACC] = { | |
| 436 | + .reg = { | |
| 437 | + .addr = 0x10, | |
| 438 | + .mask = GENMASK(7, 4), | |
| 439 | + }, | |
| 440 | + .odr_avl[0] = { 13, 0x01 }, | |
| 441 | + .odr_avl[1] = { 26, 0x02 }, | |
| 442 | + .odr_avl[2] = { 52, 0x03 }, | |
| 443 | + .odr_avl[3] = { 104, 0x04 }, | |
| 444 | + .odr_avl[4] = { 208, 0x05 }, | |
| 445 | + .odr_avl[5] = { 416, 0x06 }, | |
| 446 | + }, | |
| 447 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 448 | + .reg = { | |
| 449 | + .addr = 0x11, | |
| 450 | + .mask = GENMASK(7, 4), | |
| 451 | + }, | |
| 452 | + .odr_avl[0] = { 13, 0x01 }, | |
| 453 | + .odr_avl[1] = { 26, 0x02 }, | |
| 454 | + .odr_avl[2] = { 52, 0x03 }, | |
| 455 | + .odr_avl[3] = { 104, 0x04 }, | |
| 456 | + .odr_avl[4] = { 208, 0x05 }, | |
| 457 | + .odr_avl[5] = { 416, 0x06 }, | |
| 458 | + }, | |
| 459 | + }, | |
| 460 | + .fs_table = { | |
| 461 | + [ST_LSM6DSX_ID_ACC] = { | |
| 462 | + .reg = { | |
| 463 | + .addr = 0x10, | |
| 464 | + .mask = GENMASK(3, 2), | |
| 465 | + }, | |
| 466 | + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, | |
| 467 | + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
| 468 | + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
| 469 | + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, | |
| 470 | + }, | |
| 471 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 472 | + .reg = { | |
| 473 | + .addr = 0x11, | |
| 474 | + .mask = GENMASK(3, 2), | |
| 475 | + }, | |
| 476 | + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
| 477 | + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
| 478 | + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, | |
| 479 | + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
| 480 | + }, | |
| 481 | + }, | |
| 291 | 482 | .batch = { |
| 292 | 483 | [ST_LSM6DSX_ID_ACC] = { |
| 293 | 484 | .addr = 0x09, |
| @@ -356,6 +547,64 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 62 unmodified lines | ||
| 356 | 547 | .name = ST_ASM330LHH_DEV_NAME, |
| 357 | 548 | }, |
| 358 | 549 | }, |
| 550 | + .channels = { | |
| 551 | + [ST_LSM6DSX_ID_ACC] = { | |
| 552 | + .chan = st_lsm6dsx_acc_channels, | |
| 553 | + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), | |
| 554 | + }, | |
| 555 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 556 | + .chan = st_lsm6dsx_gyro_channels, | |
| 557 | + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), | |
| 558 | + }, | |
| 559 | + }, | |
| 560 | + .odr_table = { | |
| 561 | + [ST_LSM6DSX_ID_ACC] = { | |
| 562 | + .reg = { | |
| 563 | + .addr = 0x10, | |
| 564 | + .mask = GENMASK(7, 4), | |
| 565 | + }, | |
| 566 | + .odr_avl[0] = { 13, 0x01 }, | |
| 567 | + .odr_avl[1] = { 26, 0x02 }, | |
| 568 | + .odr_avl[2] = { 52, 0x03 }, | |
| 569 | + .odr_avl[3] = { 104, 0x04 }, | |
| 570 | + .odr_avl[4] = { 208, 0x05 }, | |
| 571 | + .odr_avl[5] = { 416, 0x06 }, | |
| 572 | + }, | |
| 573 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 574 | + .reg = { | |
| 575 | + .addr = 0x11, | |
| 576 | + .mask = GENMASK(7, 4), | |
| 577 | + }, | |
| 578 | + .odr_avl[0] = { 13, 0x01 }, | |
| 579 | + .odr_avl[1] = { 26, 0x02 }, | |
| 580 | + .odr_avl[2] = { 52, 0x03 }, | |
| 581 | + .odr_avl[3] = { 104, 0x04 }, | |
| 582 | + .odr_avl[4] = { 208, 0x05 }, | |
| 583 | + .odr_avl[5] = { 416, 0x06 }, | |
| 584 | + }, | |
| 585 | + }, | |
| 586 | + .fs_table = { | |
| 587 | + [ST_LSM6DSX_ID_ACC] = { | |
| 588 | + .reg = { | |
| 589 | + .addr = 0x10, | |
| 590 | + .mask = GENMASK(3, 2), | |
| 591 | + }, | |
| 592 | + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, | |
| 593 | + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
| 594 | + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
| 595 | + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, | |
| 596 | + }, | |
| 597 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 598 | + .reg = { | |
| 599 | + .addr = 0x11, | |
| 600 | + .mask = GENMASK(3, 2), | |
| 601 | + }, | |
| 602 | + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
| 603 | + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
| 604 | + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, | |
| 605 | + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
| 606 | + }, | |
| 607 | + }, | |
| 359 | 608 | .batch = { |
| 360 | 609 | [ST_LSM6DSX_ID_ACC] = { |
| 361 | 610 | .addr = 0x09, |
| @@ -396,6 +645,67 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 34 unmodified lines | ||
| 396 | 645 | { |
| 397 | 646 | .hw_id = ST_LSM6DSR_ID, |
| 398 | 647 | .name = ST_LSM6DSR_DEV_NAME, |
| 648 | + }, { | |
| 649 | + .hw_id = ST_ISM330DHCX_ID, | |
| 650 | + .name = ST_ISM330DHCX_DEV_NAME, | |
| 651 | + }, | |
| 652 | + }, | |
| 653 | + .channels = { | |
| 654 | + [ST_LSM6DSX_ID_ACC] = { | |
| 655 | + .chan = st_lsm6dsx_acc_channels, | |
| 656 | + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), | |
| 657 | + }, | |
| 658 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 659 | + .chan = st_lsm6dsx_gyro_channels, | |
| 660 | + .len = ARRAY_SIZE(st_lsm6dsx_gyro_channels), | |
| 661 | + }, | |
| 662 | + }, | |
| 663 | + .odr_table = { | |
| 664 | + [ST_LSM6DSX_ID_ACC] = { | |
| 665 | + .reg = { | |
| 666 | + .addr = 0x10, | |
| 667 | + .mask = GENMASK(7, 4), | |
| 668 | + }, | |
| 669 | + .odr_avl[0] = { 13, 0x01 }, | |
| 670 | + .odr_avl[1] = { 26, 0x02 }, | |
| 671 | + .odr_avl[2] = { 52, 0x03 }, | |
| 672 | + .odr_avl[3] = { 104, 0x04 }, | |
| 673 | + .odr_avl[4] = { 208, 0x05 }, | |
| 674 | + .odr_avl[5] = { 416, 0x06 }, | |
| 675 | + }, | |
| 676 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 677 | + .reg = { | |
| 678 | + .addr = 0x11, | |
| 679 | + .mask = GENMASK(7, 4), | |
| 680 | + }, | |
| 681 | + .odr_avl[0] = { 13, 0x01 }, | |
| 682 | + .odr_avl[1] = { 26, 0x02 }, | |
| 683 | + .odr_avl[2] = { 52, 0x03 }, | |
| 684 | + .odr_avl[3] = { 104, 0x04 }, | |
| 685 | + .odr_avl[4] = { 208, 0x05 }, | |
| 686 | + .odr_avl[5] = { 416, 0x06 }, | |
| 687 | + }, | |
| 688 | + }, | |
| 689 | + .fs_table = { | |
| 690 | + [ST_LSM6DSX_ID_ACC] = { | |
| 691 | + .reg = { | |
| 692 | + .addr = 0x10, | |
| 693 | + .mask = GENMASK(3, 2), | |
| 694 | + }, | |
| 695 | + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, | |
| 696 | + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, | |
| 697 | + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, | |
| 698 | + .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, | |
| 699 | + }, | |
| 700 | + [ST_LSM6DSX_ID_GYRO] = { | |
| 701 | + .reg = { | |
| 702 | + .addr = 0x11, | |
| 703 | + .mask = GENMASK(3, 2), | |
| 704 | + }, | |
| 705 | + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, | |
| 706 | + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, | |
| 707 | + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, | |
| 708 | + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, | |
| 399 | 709 | }, |
| 400 | 710 | }, |
| 401 | 711 | .batch = { |
| @@ -459,26 +769,6 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 57 unmodified lines | ||
| 459 | 769 | }, |
| 460 | 770 | }; |
| 461 | 771 | |
| 462 | −static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { | |
| 463 | − ST_LSM6DSX_CHANNEL(IIO_ACCEL, ST_LSM6DSX_REG_ACC_OUT_X_L_ADDR, | |
| 464 | − IIO_MOD_X, 0), | |
| 465 | − ST_LSM6DSX_CHANNEL(IIO_ACCEL, ST_LSM6DSX_REG_ACC_OUT_Y_L_ADDR, | |
| 466 | − IIO_MOD_Y, 1), | |
| 467 | − ST_LSM6DSX_CHANNEL(IIO_ACCEL, ST_LSM6DSX_REG_ACC_OUT_Z_L_ADDR, | |
| 468 | − IIO_MOD_Z, 2), | |
| 469 | − IIO_CHAN_SOFT_TIMESTAMP(3), | |
| 470 | −}; | |
| 471 | − | |
| 472 | −static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { | |
| 473 | − ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM6DSX_REG_GYRO_OUT_X_L_ADDR, | |
| 474 | − IIO_MOD_X, 0), | |
| 475 | − ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR, | |
| 476 | − IIO_MOD_Y, 1), | |
| 477 | − ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR, | |
| 478 | − IIO_MOD_Z, 2), | |
| 479 | − IIO_CHAN_SOFT_TIMESTAMP(3), | |
| 480 | −}; | |
| 481 | − | |
| 482 | 772 | int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable) |
| 483 | 773 | { |
| 484 | 774 | const struct st_lsm6dsx_shub_settings *hub_settings; |
| @@ -533,23 +823,22 @@ static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id, · 48 unmodified lines | ||
| 533 | 823 | static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor, |
| 534 | 824 | u32 gain) |
| 535 | 825 | { |
| 536 | − struct st_lsm6dsx_hw *hw = sensor->hw; | |
| 537 | − const struct st_lsm6dsx_reg *reg; | |
| 826 | + const struct st_lsm6dsx_fs_table_entry *fs_table; | |
| 538 | 827 | unsigned int data; |
| 539 | 828 | int i, err; |
| 540 | − u8 val; | |
| 541 | 829 | |
| 830 | + fs_table = &sensor->hw->settings->fs_table[sensor->id]; | |
| 542 | 831 | for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) |
| 543 | − if (st_lsm6dsx_fs_table[sensor->id].fs_avl[i].gain == gain) | |
| 832 | + if (fs_table->fs_avl[i].gain == gain) | |
| 544 | 833 | break; |
| 545 | 834 | |
| 546 | 835 | if (i == ST_LSM6DSX_FS_LIST_SIZE) |
| 547 | 836 | return -EINVAL; |
| 548 | 837 | |
| 549 | − val = st_lsm6dsx_fs_table[sensor->id].fs_avl[i].val; | |
| 550 | − reg = &st_lsm6dsx_fs_table[sensor->id].reg; | |
| 551 | − data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); | |
| 552 | − err = st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data); | |
| 838 | + data = ST_LSM6DSX_SHIFT_VAL(fs_table->fs_avl[i].val, | |
| 839 | + fs_table->reg.mask); | |
| 840 | + err = st_lsm6dsx_update_bits_locked(sensor->hw, fs_table->reg.addr, | |
| 841 | + fs_table->reg.mask, data); | |
| 553 | 842 | if (err < 0) |
| 554 | 843 | return err; |
| 555 | 844 | |
| @@ -560,20 +849,22 @@ static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor, · 4 unmodified lines | ||
| 560 | 849 | |
| 561 | 850 | int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr, u8 *val) |
| 562 | 851 | { |
| 852 | + const struct st_lsm6dsx_odr_table_entry *odr_table; | |
| 563 | 853 | int i; |
| 564 | 854 | |
| 855 | + odr_table = &sensor->hw->settings->odr_table[sensor->id]; | |
| 565 | 856 | for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) |
| 566 | 857 | /* |
| 567 | 858 | * ext devices can run at different odr respect to |
| 568 | 859 | * accel sensor |
| 569 | 860 | */ |
| 570 | − if (st_lsm6dsx_odr_table[sensor->id].odr_avl[i].hz >= odr) | |
| 861 | + if (odr_table->odr_avl[i].hz >= odr) | |
| 571 | 862 | break; |
| 572 | 863 | |
| 573 | 864 | if (i == ST_LSM6DSX_ODR_LIST_SIZE) |
| 574 | 865 | return -EINVAL; |
| 575 | 866 | |
| 576 | − *val = st_lsm6dsx_odr_table[sensor->id].odr_avl[i].val; | |
| 867 | + *val = odr_table->odr_avl[i].val; | |
| 577 | 868 | |
| 578 | 869 | return 0; |
| 579 | 870 | } |
| @@ -638,7 +929,7 @@ static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 req_odr) · 58 unmodified lines | ||
| 638 | 929 | return err; |
| 639 | 930 | } |
| 640 | 931 | |
| 641 | − reg = &st_lsm6dsx_odr_table[ref_sensor->id].reg; | |
| 932 | + reg = &hw->settings->odr_table[ref_sensor->id].reg; | |
| 642 | 933 | data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); |
| 643 | 934 | return st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data); |
| 644 | 935 | } |
| @@ -783,11 +1074,12 @@ st_lsm6dsx_sysfs_sampling_frequency_avail(struct device *dev, · 138 unmodified lines | ||
| 783 | 1074 | { |
| 784 | 1075 | struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); |
| 785 | 1076 | enum st_lsm6dsx_sensor_id id = sensor->id; |
| 1077 | + struct st_lsm6dsx_hw *hw = sensor->hw; | |
| 786 | 1078 | int i, len = 0; |
| 787 | 1079 | |
| 788 | 1080 | for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) |
| 789 | 1081 | len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", |
| 790 | − st_lsm6dsx_odr_table[id].odr_avl[i].hz); | |
| 1082 | + hw->settings->odr_table[id].odr_avl[i].hz); | |
| 791 | 1083 | buf[len - 1] = '\n'; |
| 792 | 1084 | |
| 793 | 1085 | return len; |
| @@ -799,11 +1091,12 @@ static ssize_t st_lsm6dsx_sysfs_scale_avail(struct device *dev, · 5 unmodified lines | ||
| 799 | 1091 | { |
| 800 | 1092 | struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); |
| 801 | 1093 | enum st_lsm6dsx_sensor_id id = sensor->id; |
| 1094 | + struct st_lsm6dsx_hw *hw = sensor->hw; | |
| 802 | 1095 | int i, len = 0; |
| 803 | 1096 | |
| 804 | 1097 | for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) |
| 805 | 1098 | len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", |
| 806 | − st_lsm6dsx_fs_table[id].fs_avl[i].gain); | |
| 1099 | + hw->settings->fs_table[id].fs_avl[i].gain); | |
| 807 | 1100 | buf[len - 1] = '\n'; |
| 808 | 1101 | |
| 809 | 1102 | return len; |
| @@ -1033,28 +1326,24 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, · 223 unmodified lines | ||
| 1033 | 1326 | iio_dev->modes = INDIO_DIRECT_MODE; |
| 1034 | 1327 | iio_dev->dev.parent = hw->dev; |
| 1035 | 1328 | iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks; |
| 1329 | + iio_dev->channels = hw->settings->channels[id].chan; | |
| 1330 | + iio_dev->num_channels = hw->settings->channels[id].len; | |
| 1036 | 1331 | |
| 1037 | 1332 | sensor = iio_priv(iio_dev); |
| 1038 | 1333 | sensor->id = id; |
| 1039 | 1334 | sensor->hw = hw; |
| 1040 | − sensor->odr = st_lsm6dsx_odr_table[id].odr_avl[0].hz; | |
| 1041 | − sensor->gain = st_lsm6dsx_fs_table[id].fs_avl[0].gain; | |
| 1335 | + sensor->odr = hw->settings->odr_table[id].odr_avl[0].hz; | |
| 1336 | + sensor->gain = hw->settings->fs_table[id].fs_avl[0].gain; | |
| 1042 | 1337 | sensor->watermark = 1; |
| 1043 | 1338 | |
| 1044 | 1339 | switch (id) { |
| 1045 | 1340 | case ST_LSM6DSX_ID_ACC: |
| 1046 | − iio_dev->channels = st_lsm6dsx_acc_channels; | |
| 1047 | − iio_dev->num_channels = ARRAY_SIZE(st_lsm6dsx_acc_channels); | |
| 1048 | 1341 | iio_dev->info = &st_lsm6dsx_acc_info; |
| 1049 | − | |
| 1050 | 1342 | scnprintf(sensor->name, sizeof(sensor->name), "%s_accel", |
| 1051 | 1343 | name); |
| 1052 | 1344 | break; |
| 1053 | 1345 | case ST_LSM6DSX_ID_GYRO: |
| 1054 | − iio_dev->channels = st_lsm6dsx_gyro_channels; | |
| 1055 | − iio_dev->num_channels = ARRAY_SIZE(st_lsm6dsx_gyro_channels); | |
| 1056 | 1346 | iio_dev->info = &st_lsm6dsx_gyro_info; |
| 1057 | − | |
| 1058 | 1347 | scnprintf(sensor->name, sizeof(sensor->name), "%s_gyro", |
| 1059 | 1348 | name); |
| 1060 | 1349 | break; |
| @@ -75,6 +75,14 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = { · 74 unmodified lines | ||
| 75 | 75 | .compatible = "st,lsm6dsr", |
| 76 | 76 | .data = (void *)ST_LSM6DSR_ID, |
| 77 | 77 | }, |
| 78 | + { | |
| 79 | + .compatible = "st,lsm6ds3tr-c", | |
| 80 | + .data = (void *)ST_LSM6DS3TRC_ID, | |
| 81 | + }, | |
| 82 | + { | |
| 83 | + .compatible = "st,ism330dhcx", | |
| 84 | + .data = (void *)ST_ISM330DHCX_ID, | |
| 85 | + }, | |
| 78 | 86 | {}, |
| 79 | 87 | }; |
| 80 | 88 | MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match); |
| @@ -89,6 +97,8 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = { · 8 unmodified lines | ||
| 89 | 97 | { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, |
| 90 | 98 | { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, |
| 91 | 99 | { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, |
| 100 | + { ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID }, | |
| 101 | + { ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID }, | |
| 92 | 102 | {}, |
| 93 | 103 | }; |
| 94 | 104 | MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table); |
| @@ -0,0 +1,57 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | +/* | |
| 3 | + * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates. | |
| 4 | + * | |
| 5 | + * Author: Vitor Soares <vitor.soares@synopsys.com> | |
| 6 | + */ | |
| 7 | + | |
| 8 | +#include <linux/kernel.h> | |
| 9 | +#include <linux/module.h> | |
| 10 | +#include <linux/i3c/device.h> | |
| 11 | +#include <linux/i3c/master.h> | |
| 12 | +#include <linux/slab.h> | |
| 13 | +#include <linux/of.h> | |
| 14 | +#include <linux/regmap.h> | |
| 15 | + | |
| 16 | +#include "st_lsm6dsx.h" | |
| 17 | + | |
| 18 | +static const struct i3c_device_id st_lsm6dsx_i3c_ids[] = { | |
| 19 | + I3C_DEVICE(0x0104, 0x006C, (void *)ST_LSM6DSO_ID), | |
| 20 | + I3C_DEVICE(0x0104, 0x006B, (void *)ST_LSM6DSR_ID), | |
| 21 | + { /* sentinel */ }, | |
| 22 | +}; | |
| 23 | +MODULE_DEVICE_TABLE(i3c, st_lsm6dsx_i3c_ids); | |
| 24 | + | |
| 25 | +static int st_lsm6dsx_i3c_probe(struct i3c_device *i3cdev) | |
| 26 | +{ | |
| 27 | + struct regmap_config st_lsm6dsx_i3c_regmap_config = { | |
| 28 | + .reg_bits = 8, | |
| 29 | + .val_bits = 8, | |
| 30 | + }; | |
| 31 | + const struct i3c_device_id *id = i3c_device_match_id(i3cdev, | |
| 32 | + st_lsm6dsx_i3c_ids); | |
| 33 | + struct regmap *regmap; | |
| 34 | + | |
| 35 | + regmap = devm_regmap_init_i3c(i3cdev, &st_lsm6dsx_i3c_regmap_config); | |
| 36 | + if (IS_ERR(regmap)) { | |
| 37 | + dev_err(&i3cdev->dev, "Failed to register i3c regmap %d\n", | |
| 38 | + (int)PTR_ERR(regmap)); | |
| 39 | + return PTR_ERR(regmap); | |
| 40 | + } | |
| 41 | + | |
| 42 | + return st_lsm6dsx_probe(&i3cdev->dev, 0, (uintptr_t)id->data, regmap); | |
| 43 | +} | |
| 44 | + | |
| 45 | +static struct i3c_driver st_lsm6dsx_driver = { | |
| 46 | + .driver = { | |
| 47 | + .name = "st_lsm6dsx_i3c", | |
| 48 | + .pm = &st_lsm6dsx_pm_ops, | |
| 49 | + }, | |
| 50 | + .probe = st_lsm6dsx_i3c_probe, | |
| 51 | + .id_table = st_lsm6dsx_i3c_ids, | |
| 52 | +}; | |
| 53 | +module_i3c_driver(st_lsm6dsx_driver); | |
| 54 | + | |
| 55 | +MODULE_AUTHOR("Vitor Soares <vitor.soares@synopsys.com>"); | |
| 56 | +MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx i3c driver"); | |
| 57 | +MODULE_LICENSE("GPL v2"); | |
| @@ -75,6 +75,14 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = { · 74 unmodified lines | ||
| 75 | 75 | .compatible = "st,lsm6dsr", |
| 76 | 76 | .data = (void *)ST_LSM6DSR_ID, |
| 77 | 77 | }, |
| 78 | + { | |
| 79 | + .compatible = "st,lsm6ds3tr-c", | |
| 80 | + .data = (void *)ST_LSM6DS3TRC_ID, | |
| 81 | + }, | |
| 82 | + { | |
| 83 | + .compatible = "st,ism330dhcx", | |
| 84 | + .data = (void *)ST_ISM330DHCX_ID, | |
| 85 | + }, | |
| 78 | 86 | {}, |
| 79 | 87 | }; |
| 80 | 88 | MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match); |
| @@ -89,6 +97,8 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = { · 8 unmodified lines | ||
| 89 | 97 | { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, |
| 90 | 98 | { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, |
| 91 | 99 | { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, |
| 100 | + { ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID }, | |
| 101 | + { ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID }, | |
| 92 | 102 | {}, |
| 93 | 103 | }; |
| 94 | 104 | MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table); |
| @@ -303,6 +303,7 @@ config MAX44000 · 302 unmodified lines | ||
| 303 | 303 | config MAX44009 |
| 304 | 304 | tristate "MAX44009 Ambient Light Sensor" |
| 305 | 305 | depends on I2C |
| 306 | + select REGMAP_I2C | |
| 306 | 307 | help |
| 307 | 308 | Say Y here if you want to build support for Maxim Integrated's |
| 308 | 309 | MAX44009 ambient light sensor device. |
| @@ -310,6 +311,16 @@ config MAX44009 · 1 unmodified line | ||
| 310 | 311 | To compile this driver as a module, choose M here: |
| 311 | 312 | the module will be called max44009. |
| 312 | 313 | |
| 314 | +config NOA1305 | |
| 315 | + tristate "ON Semiconductor NOA1305 ambient light sensor" | |
| 316 | + depends on I2C | |
| 317 | + help | |
| 318 | + Say Y here if you want to build support for the ON Semiconductor | |
| 319 | + NOA1305 ambient light sensor. | |
| 320 | + | |
| 321 | + To compile this driver as a module, choose M here: | |
| 322 | + The module will be called noa1305. | |
| 323 | + | |
| 313 | 324 | config OPT3001 |
| 314 | 325 | tristate "Texas Instruments OPT3001 Light Sensor" |
| 315 | 326 | depends on I2C |
| @@ -29,6 +29,7 @@ obj-$(CONFIG_LTR501) += ltr501.o · 28 unmodified lines | ||
| 29 | 29 | obj-$(CONFIG_LV0104CS) += lv0104cs.o |
| 30 | 30 | obj-$(CONFIG_MAX44000) += max44000.o |
| 31 | 31 | obj-$(CONFIG_MAX44009) += max44009.o |
| 32 | +obj-$(CONFIG_NOA1305) += noa1305.o | |
| 32 | 33 | obj-$(CONFIG_OPT3001) += opt3001.o |
| 33 | 34 | obj-$(CONFIG_PA12203001) += pa12203001.o |
| 34 | 35 | obj-$(CONFIG_RPR0521) += rpr0521.o |
| @@ -1135,5 +1135,5 @@ static struct i2c_driver apds9960_driver = { · 1134 unmodified lines | ||
| 1135 | 1135 | module_i2c_driver(apds9960_driver); |
| 1136 | 1136 | |
| 1137 | 1137 | MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>"); |
| 1138 | −MODULE_DESCRIPTION("ADPS9960 Gesture/RGB/ALS/Proximity sensor"); | |
| 1138 | +MODULE_DESCRIPTION("APDS9960 Gesture/RGB/ALS/Proximity sensor"); | |
| 1139 | 1139 | MODULE_LICENSE("GPL"); |
| @@ -101,15 +101,16 @@ static int cm3323_init(struct iio_dev *indio_dev) · 100 unmodified lines | ||
| 101 | 101 | return 0; |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | −static void cm3323_disable(struct iio_dev *indio_dev) | |
| 104 | +static void cm3323_disable(void *data) | |
| 105 | 105 | { |
| 106 | 106 | int ret; |
| 107 | − struct cm3323_data *data = iio_priv(indio_dev); | |
| 107 | + struct iio_dev *indio_dev = data; | |
| 108 | + struct cm3323_data *cm_data = iio_priv(indio_dev); | |
| 108 | 109 | |
| 109 | − ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, | |
| 110 | + ret = i2c_smbus_write_word_data(cm_data->client, CM3323_CMD_CONF, | |
| 110 | 111 | CM3323_CONF_SD_BIT); |
| 111 | 112 | if (ret < 0) |
| 112 | − dev_err(&data->client->dev, "Error writing reg_conf\n"); | |
| 113 | + dev_err(&cm_data->client->dev, "Error writing reg_conf\n"); | |
| 113 | 114 | } |
| 114 | 115 | |
| 115 | 116 | static int cm3323_set_it_bits(struct cm3323_data *data, int val, int val2) |
| @@ -243,26 +244,11 @@ static int cm3323_probe(struct i2c_client *client, · 127 unmodified lines | ||
| 243 | 244 | return ret; |
| 244 | 245 | } |
| 245 | 246 | |
| 246 | − ret = iio_device_register(indio_dev); | |
| 247 | − if (ret < 0) { | |
| 248 | − dev_err(&client->dev, "failed to register iio dev\n"); | |
| 249 | − goto err_init; | |
| 250 | − } | |
| 251 | − | |
| 252 | − return 0; | |
| 253 | −err_init: | |
| 254 | − cm3323_disable(indio_dev); | |
| 255 | − return ret; | |
| 256 | −} | |
| 257 | − | |
| 258 | −static int cm3323_remove(struct i2c_client *client) | |
| 259 | −{ | |
| 260 | − struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 261 | − | |
| 262 | − iio_device_unregister(indio_dev); | |
| 263 | − cm3323_disable(indio_dev); | |
| 247 | + ret = devm_add_action_or_reset(&client->dev, cm3323_disable, indio_dev); | |
| 248 | + if (ret < 0) | |
| 249 | + return ret; | |
| 264 | 250 | |
| 265 | − return 0; | |
| 251 | + return devm_iio_device_register(&client->dev, indio_dev); | |
| 266 | 252 | } |
| 267 | 253 | |
| 268 | 254 | static const struct i2c_device_id cm3323_id[] = { |
| @@ -276,7 +262,6 @@ static struct i2c_driver cm3323_driver = { · 7 unmodified lines | ||
| 276 | 262 | .name = CM3323_DRV_NAME, |
| 277 | 263 | }, |
| 278 | 264 | .probe = cm3323_probe, |
| 279 | − .remove = cm3323_remove, | |
| 280 | 265 | .id_table = cm3323_id, |
| 281 | 266 | }; |
| 282 | 267 | |
| @@ -646,18 +646,18 @@ static int cm36651_probe(struct i2c_client *client, · 645 unmodified lines | ||
| 646 | 646 | i2c_set_clientdata(client, indio_dev); |
| 647 | 647 | |
| 648 | 648 | cm36651->client = client; |
| 649 | − cm36651->ps_client = i2c_new_dummy(client->adapter, | |
| 649 | + cm36651->ps_client = i2c_new_dummy_device(client->adapter, | |
| 650 | 650 | CM36651_I2C_ADDR_PS); |
| 651 | − if (!cm36651->ps_client) { | |
| 651 | + if (IS_ERR(cm36651->ps_client)) { | |
| 652 | 652 | dev_err(&client->dev, "%s: new i2c device failed\n", __func__); |
| 653 | − ret = -ENODEV; | |
| 653 | + ret = PTR_ERR(cm36651->ps_client); | |
| 654 | 654 | goto error_disable_reg; |
| 655 | 655 | } |
| 656 | 656 | |
| 657 | − cm36651->ara_client = i2c_new_dummy(client->adapter, CM36651_ARA); | |
| 658 | − if (!cm36651->ara_client) { | |
| 657 | + cm36651->ara_client = i2c_new_dummy_device(client->adapter, CM36651_ARA); | |
| 658 | + if (IS_ERR(cm36651->ara_client)) { | |
| 659 | 659 | dev_err(&client->dev, "%s: new i2c device failed\n", __func__); |
| 660 | − ret = -ENODEV; | |
| 660 | + ret = PTR_ERR(cm36651->ara_client); | |
| 661 | 661 | goto error_i2c_unregister_ps; |
| 662 | 662 | } |
| 663 | 663 | |
| @@ -42,7 +42,7 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev, · 41 unmodified lines | ||
| 42 | 42 | struct cros_ec_light_prox_state *st = iio_priv(indio_dev); |
| 43 | 43 | u16 data = 0; |
| 44 | 44 | s64 val64; |
| 45 | − int ret = IIO_VAL_INT; | |
| 45 | + int ret; | |
| 46 | 46 | int idx = chan->scan_index; |
| 47 | 47 | |
| 48 | 48 | mutex_lock(&st->core.cmd_lock); |
| @@ -50,23 +50,22 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev, · 1 unmodified line | ||
| 50 | 50 | switch (mask) { |
| 51 | 51 | case IIO_CHAN_INFO_RAW: |
| 52 | 52 | if (chan->type == IIO_PROXIMITY) { |
| 53 | − if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx, | |
| 54 | − (s16 *)&data) < 0) { | |
| 55 | − ret = -EIO; | |
| 53 | + ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx, | |
| 54 | + (s16 *)&data); | |
| 55 | + if (ret) | |
| 56 | 56 | break; |
| 57 | − } | |
| 58 | 57 | *val = data; |
| 58 | + ret = IIO_VAL_INT; | |
| 59 | 59 | } else { |
| 60 | 60 | ret = -EINVAL; |
| 61 | 61 | } |
| 62 | 62 | break; |
| 63 | 63 | case IIO_CHAN_INFO_PROCESSED: |
| 64 | 64 | if (chan->type == IIO_LIGHT) { |
| 65 | − if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx, | |
| 66 | − (s16 *)&data) < 0) { | |
| 67 | − ret = -EIO; | |
| 65 | + ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx, | |
| 66 | + (s16 *)&data); | |
| 67 | + if (ret) | |
| 68 | 68 | break; |
| 69 | − } | |
| 70 | 69 | /* |
| 71 | 70 | * The data coming from the light sensor is |
| 72 | 71 | * pre-processed and represents the ambient light |
| @@ -82,15 +81,16 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev, · 9 unmodified lines | ||
| 82 | 81 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; |
| 83 | 82 | st->core.param.sensor_offset.flags = 0; |
| 84 | 83 | |
| 85 | − if (cros_ec_motion_send_host_cmd(&st->core, 0)) { | |
| 86 | − ret = -EIO; | |
| 84 | + ret = cros_ec_motion_send_host_cmd(&st->core, 0); | |
| 85 | + if (ret) | |
| 87 | 86 | break; |
| 88 | − } | |
| 89 | 87 | |
| 90 | 88 | /* Save values */ |
| 91 | − st->core.calib[0] = st->core.resp->sensor_offset.offset[0]; | |
| 89 | + st->core.calib[0].offset = | |
| 90 | + st->core.resp->sensor_offset.offset[0]; | |
| 92 | 91 | |
| 93 | − *val = st->core.calib[idx]; | |
| 92 | + *val = st->core.calib[idx].offset; | |
| 93 | + ret = IIO_VAL_INT; | |
| 94 | 94 | break; |
| 95 | 95 | case IIO_CHAN_INFO_CALIBSCALE: |
| 96 | 96 | /* |
| @@ -101,10 +101,9 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev, · 4 unmodified lines | ||
| 101 | 101 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; |
| 102 | 102 | st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE; |
| 103 | 103 | |
| 104 | − if (cros_ec_motion_send_host_cmd(&st->core, 0)) { | |
| 105 | − ret = -EIO; | |
| 104 | + ret = cros_ec_motion_send_host_cmd(&st->core, 0); | |
| 105 | + if (ret) | |
| 106 | 106 | break; |
| 107 | − } | |
| 108 | 107 | |
| 109 | 108 | val64 = st->core.resp->sensor_range.ret; |
| 110 | 109 | *val = val64 >> 16; |
| @@ -127,28 +126,27 @@ static int cros_ec_light_prox_write(struct iio_dev *indio_dev, · 16 unmodified lines | ||
| 127 | 126 | int val, int val2, long mask) |
| 128 | 127 | { |
| 129 | 128 | struct cros_ec_light_prox_state *st = iio_priv(indio_dev); |
| 130 | − int ret = 0; | |
| 129 | + int ret; | |
| 131 | 130 | int idx = chan->scan_index; |
| 132 | 131 | |
| 133 | 132 | mutex_lock(&st->core.cmd_lock); |
| 134 | 133 | |
| 135 | 134 | switch (mask) { |
| 136 | 135 | case IIO_CHAN_INFO_CALIBBIAS: |
| 137 | − st->core.calib[idx] = val; | |
| 136 | + st->core.calib[idx].offset = val; | |
| 138 | 137 | /* Send to EC for each axis, even if not complete */ |
| 139 | 138 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; |
| 140 | 139 | st->core.param.sensor_offset.flags = MOTION_SENSE_SET_OFFSET; |
| 141 | − st->core.param.sensor_offset.offset[0] = st->core.calib[0]; | |
| 140 | + st->core.param.sensor_offset.offset[0] = | |
| 141 | + st->core.calib[0].offset; | |
| 142 | 142 | st->core.param.sensor_offset.temp = |
| 143 | 143 | EC_MOTION_SENSE_INVALID_CALIB_TEMP; |
| 144 | − if (cros_ec_motion_send_host_cmd(&st->core, 0)) | |
| 145 | − ret = -EIO; | |
| 144 | + ret = cros_ec_motion_send_host_cmd(&st->core, 0); | |
| 146 | 145 | break; |
| 147 | 146 | case IIO_CHAN_INFO_CALIBSCALE: |
| 148 | 147 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; |
| 149 | 148 | st->core.param.sensor_range.data = (val << 16) | (val2 / 100); |
| 150 | − if (cros_ec_motion_send_host_cmd(&st->core, 0)) | |
| 151 | − ret = -EIO; | |
| 149 | + ret = cros_ec_motion_send_host_cmd(&st->core, 0); | |
| 152 | 150 | break; |
| 153 | 151 | default: |
| 154 | 152 | ret = cros_ec_sensors_core_write(&st->core, chan, val, val2, |
| @@ -164,6 +162,7 @@ static int cros_ec_light_prox_write(struct iio_dev *indio_dev, · 9 unmodified lines | ||
| 164 | 162 | static const struct iio_info cros_ec_light_prox_info = { |
| 165 | 163 | .read_raw = &cros_ec_light_prox_read, |
| 166 | 164 | .write_raw = &cros_ec_light_prox_write, |
| 165 | + .read_avail = &cros_ec_sensors_core_read_avail, | |
| 167 | 166 | }; |
| 168 | 167 | |
| 169 | 168 | static int cros_ec_light_prox_probe(struct platform_device *pdev) |
| @@ -198,6 +197,8 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) · 28 unmodified lines | ||
| 198 | 197 | channel->info_mask_shared_by_all = |
| 199 | 198 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
| 200 | 199 | BIT(IIO_CHAN_INFO_FREQUENCY); |
| 200 | + channel->info_mask_shared_by_all_available = | |
| 201 | + BIT(IIO_CHAN_INFO_SAMP_FREQ); | |
| 201 | 202 | channel->scan_type.realbits = CROS_EC_SENSOR_BITS; |
| 202 | 203 | channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; |
| 203 | 204 | channel->scan_type.shift = 0; |
| @@ -205,8 +206,6 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 205 | 206 | channel->ext_info = cros_ec_sensors_ext_info; |
| 206 | 207 | channel->scan_type.sign = 'u'; |
| 207 | 208 | |
| 208 | − state->core.calib[0] = 0; | |
| 209 | − | |
| 210 | 209 | /* Sensor specific */ |
| 211 | 210 | switch (state->core.type) { |
| 212 | 211 | case MOTIONSENSE_TYPE_LIGHT: |
| @@ -0,0 +1,312 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0+ | |
| 2 | +/* | |
| 3 | + * Support for ON Semiconductor NOA1305 ambient light sensor | |
| 4 | + * | |
| 5 | + * Copyright (C) 2016 Emcraft Systems | |
| 6 | + * Copyright (C) 2019 Collabora Ltd. | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#include <linux/delay.h> | |
| 10 | +#include <linux/err.h> | |
| 11 | +#include <linux/i2c.h> | |
| 12 | +#include <linux/iio/iio.h> | |
| 13 | +#include <linux/iio/sysfs.h> | |
| 14 | +#include <linux/module.h> | |
| 15 | +#include <linux/regmap.h> | |
| 16 | +#include <linux/regulator/consumer.h> | |
| 17 | + | |
| 18 | +#define NOA1305_REG_POWER_CONTROL 0x0 | |
| 19 | +#define NOA1305_POWER_CONTROL_DOWN 0x00 | |
| 20 | +#define NOA1305_POWER_CONTROL_ON 0x08 | |
| 21 | +#define NOA1305_REG_RESET 0x1 | |
| 22 | +#define NOA1305_RESET_RESET 0x10 | |
| 23 | +#define NOA1305_REG_INTEGRATION_TIME 0x2 | |
| 24 | +#define NOA1305_INTEGR_TIME_800MS 0x00 | |
| 25 | +#define NOA1305_INTEGR_TIME_400MS 0x01 | |
| 26 | +#define NOA1305_INTEGR_TIME_200MS 0x02 | |
| 27 | +#define NOA1305_INTEGR_TIME_100MS 0x03 | |
| 28 | +#define NOA1305_INTEGR_TIME_50MS 0x04 | |
| 29 | +#define NOA1305_INTEGR_TIME_25MS 0x05 | |
| 30 | +#define NOA1305_INTEGR_TIME_12_5MS 0x06 | |
| 31 | +#define NOA1305_INTEGR_TIME_6_25MS 0x07 | |
| 32 | +#define NOA1305_REG_INT_SELECT 0x3 | |
| 33 | +#define NOA1305_INT_SEL_ACTIVE_HIGH 0x01 | |
| 34 | +#define NOA1305_INT_SEL_ACTIVE_LOW 0x02 | |
| 35 | +#define NOA1305_INT_SEL_INACTIVE 0x03 | |
| 36 | +#define NOA1305_REG_INT_THRESH_LSB 0x4 | |
| 37 | +#define NOA1305_REG_INT_THRESH_MSB 0x5 | |
| 38 | +#define NOA1305_REG_ALS_DATA_LSB 0x6 | |
| 39 | +#define NOA1305_REG_ALS_DATA_MSB 0x7 | |
| 40 | +#define NOA1305_REG_DEVICE_ID_LSB 0x8 | |
| 41 | +#define NOA1305_REG_DEVICE_ID_MSB 0x9 | |
| 42 | + | |
| 43 | +#define NOA1305_DEVICE_ID 0x0519 | |
| 44 | +#define NOA1305_DRIVER_NAME "noa1305" | |
| 45 | + | |
| 46 | +struct noa1305_priv { | |
| 47 | + struct i2c_client *client; | |
| 48 | + struct regmap *regmap; | |
| 49 | + struct regulator *vin_reg; | |
| 50 | +}; | |
| 51 | + | |
| 52 | +static int noa1305_measure(struct noa1305_priv *priv) | |
| 53 | +{ | |
| 54 | + __le16 data; | |
| 55 | + int ret; | |
| 56 | + | |
| 57 | + ret = regmap_bulk_read(priv->regmap, NOA1305_REG_ALS_DATA_LSB, &data, | |
| 58 | + 2); | |
| 59 | + if (ret < 0) | |
| 60 | + return ret; | |
| 61 | + | |
| 62 | + return le16_to_cpu(data); | |
| 63 | +} | |
| 64 | + | |
| 65 | +static int noa1305_scale(struct noa1305_priv *priv, int *val, int *val2) | |
| 66 | +{ | |
| 67 | + int data; | |
| 68 | + int ret; | |
| 69 | + | |
| 70 | + ret = regmap_read(priv->regmap, NOA1305_REG_INTEGRATION_TIME, &data); | |
| 71 | + if (ret < 0) | |
| 72 | + return ret; | |
| 73 | + | |
| 74 | + /* | |
| 75 | + * Lux = count / (<Integration Constant> * <Integration Time>) | |
| 76 | + * | |
| 77 | + * Integration Constant = 7.7 | |
| 78 | + * Integration Time in Seconds | |
| 79 | + */ | |
| 80 | + switch (data) { | |
| 81 | + case NOA1305_INTEGR_TIME_800MS: | |
| 82 | + *val = 100; | |
| 83 | + *val2 = 77 * 8; | |
| 84 | + break; | |
| 85 | + case NOA1305_INTEGR_TIME_400MS: | |
| 86 | + *val = 100; | |
| 87 | + *val2 = 77 * 4; | |
| 88 | + case NOA1305_INTEGR_TIME_200MS: | |
| 89 | + *val = 100; | |
| 90 | + *val2 = 77 * 2; | |
| 91 | + break; | |
| 92 | + case NOA1305_INTEGR_TIME_100MS: | |
| 93 | + *val = 100; | |
| 94 | + *val2 = 77; | |
| 95 | + break; | |
| 96 | + case NOA1305_INTEGR_TIME_50MS: | |
| 97 | + *val = 1000; | |
| 98 | + *val2 = 77 * 5; | |
| 99 | + break; | |
| 100 | + case NOA1305_INTEGR_TIME_25MS: | |
| 101 | + *val = 10000; | |
| 102 | + *val2 = 77 * 25; | |
| 103 | + break; | |
| 104 | + case NOA1305_INTEGR_TIME_12_5MS: | |
| 105 | + *val = 100000; | |
| 106 | + *val2 = 77 * 125; | |
| 107 | + break; | |
| 108 | + case NOA1305_INTEGR_TIME_6_25MS: | |
| 109 | + *val = 1000000; | |
| 110 | + *val2 = 77 * 625; | |
| 111 | + break; | |
| 112 | + default: | |
| 113 | + return -EINVAL; | |
| 114 | + } | |
| 115 | + | |
| 116 | + return IIO_VAL_FRACTIONAL; | |
| 117 | +} | |
| 118 | + | |
| 119 | +static const struct iio_chan_spec noa1305_channels[] = { | |
| 120 | + { | |
| 121 | + .type = IIO_LIGHT, | |
| 122 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | |
| 123 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), | |
| 124 | + } | |
| 125 | +}; | |
| 126 | + | |
| 127 | +static int noa1305_read_raw(struct iio_dev *indio_dev, | |
| 128 | + struct iio_chan_spec const *chan, | |
| 129 | + int *val, int *val2, long mask) | |
| 130 | +{ | |
| 131 | + int ret = -EINVAL; | |
| 132 | + struct noa1305_priv *priv = iio_priv(indio_dev); | |
| 133 | + | |
| 134 | + switch (mask) { | |
| 135 | + case IIO_CHAN_INFO_RAW: | |
| 136 | + switch (chan->type) { | |
| 137 | + case IIO_LIGHT: | |
| 138 | + ret = noa1305_measure(priv); | |
| 139 | + if (ret < 0) | |
| 140 | + return ret; | |
| 141 | + *val = ret; | |
| 142 | + return IIO_VAL_INT; | |
| 143 | + default: | |
| 144 | + break; | |
| 145 | + } | |
| 146 | + break; | |
| 147 | + case IIO_CHAN_INFO_SCALE: | |
| 148 | + switch (chan->type) { | |
| 149 | + case IIO_LIGHT: | |
| 150 | + return noa1305_scale(priv, val, val2); | |
| 151 | + default: | |
| 152 | + break; | |
| 153 | + } | |
| 154 | + break; | |
| 155 | + default: | |
| 156 | + break; | |
| 157 | + } | |
| 158 | + | |
| 159 | + return ret; | |
| 160 | +} | |
| 161 | + | |
| 162 | +static const struct iio_info noa1305_info = { | |
| 163 | + .read_raw = noa1305_read_raw, | |
| 164 | +}; | |
| 165 | + | |
| 166 | +static bool noa1305_writable_reg(struct device *dev, unsigned int reg) | |
| 167 | +{ | |
| 168 | + switch (reg) { | |
| 169 | + case NOA1305_REG_POWER_CONTROL: | |
| 170 | + case NOA1305_REG_RESET: | |
| 171 | + case NOA1305_REG_INTEGRATION_TIME: | |
| 172 | + case NOA1305_REG_INT_SELECT: | |
| 173 | + case NOA1305_REG_INT_THRESH_LSB: | |
| 174 | + case NOA1305_REG_INT_THRESH_MSB: | |
| 175 | + return true; | |
| 176 | + default: | |
| 177 | + return false; | |
| 178 | + } | |
| 179 | +} | |
| 180 | + | |
| 181 | +static const struct regmap_config noa1305_regmap_config = { | |
| 182 | + .name = NOA1305_DRIVER_NAME, | |
| 183 | + .reg_bits = 8, | |
| 184 | + .val_bits = 8, | |
| 185 | + .max_register = NOA1305_REG_DEVICE_ID_MSB, | |
| 186 | + .writeable_reg = noa1305_writable_reg, | |
| 187 | +}; | |
| 188 | + | |
| 189 | +static void noa1305_reg_remove(void *data) | |
| 190 | +{ | |
| 191 | + struct noa1305_priv *priv = data; | |
| 192 | + | |
| 193 | + regulator_disable(priv->vin_reg); | |
| 194 | +} | |
| 195 | + | |
| 196 | +static int noa1305_probe(struct i2c_client *client, | |
| 197 | + const struct i2c_device_id *id) | |
| 198 | +{ | |
| 199 | + struct noa1305_priv *priv; | |
| 200 | + struct iio_dev *indio_dev; | |
| 201 | + struct regmap *regmap; | |
| 202 | + __le16 data; | |
| 203 | + unsigned int dev_id; | |
| 204 | + int ret; | |
| 205 | + | |
| 206 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*priv)); | |
| 207 | + if (!indio_dev) | |
| 208 | + return -ENOMEM; | |
| 209 | + | |
| 210 | + regmap = devm_regmap_init_i2c(client, &noa1305_regmap_config); | |
| 211 | + if (IS_ERR(regmap)) { | |
| 212 | + dev_err(&client->dev, "Regmap initialization failed.\n"); | |
| 213 | + return PTR_ERR(regmap); | |
| 214 | + } | |
| 215 | + | |
| 216 | + priv = iio_priv(indio_dev); | |
| 217 | + | |
| 218 | + priv->vin_reg = devm_regulator_get(&client->dev, "vin"); | |
| 219 | + if (IS_ERR(priv->vin_reg)) { | |
| 220 | + dev_err(&client->dev, "get regulator vin failed\n"); | |
| 221 | + return PTR_ERR(priv->vin_reg); | |
| 222 | + } | |
| 223 | + | |
| 224 | + ret = regulator_enable(priv->vin_reg); | |
| 225 | + if (ret) { | |
| 226 | + dev_err(&client->dev, "enable regulator vin failed\n"); | |
| 227 | + return ret; | |
| 228 | + } | |
| 229 | + | |
| 230 | + ret = devm_add_action_or_reset(&client->dev, noa1305_reg_remove, priv); | |
| 231 | + if (ret) { | |
| 232 | + dev_err(&client->dev, "addition of devm action failed\n"); | |
| 233 | + return ret; | |
| 234 | + } | |
| 235 | + | |
| 236 | + i2c_set_clientdata(client, indio_dev); | |
| 237 | + priv->client = client; | |
| 238 | + priv->regmap = regmap; | |
| 239 | + | |
| 240 | + ret = regmap_bulk_read(regmap, NOA1305_REG_DEVICE_ID_LSB, &data, 2); | |
| 241 | + if (ret < 0) { | |
| 242 | + dev_err(&client->dev, "ID reading failed: %d\n", ret); | |
| 243 | + return ret; | |
| 244 | + } | |
| 245 | + | |
| 246 | + dev_id = le16_to_cpu(data); | |
| 247 | + if (dev_id != NOA1305_DEVICE_ID) { | |
| 248 | + dev_err(&client->dev, "Unknown device ID: 0x%x\n", dev_id); | |
| 249 | + return -ENODEV; | |
| 250 | + } | |
| 251 | + | |
| 252 | + ret = regmap_write(regmap, NOA1305_REG_POWER_CONTROL, | |
| 253 | + NOA1305_POWER_CONTROL_ON); | |
| 254 | + if (ret < 0) { | |
| 255 | + dev_err(&client->dev, "Enabling power control failed\n"); | |
| 256 | + return ret; | |
| 257 | + } | |
| 258 | + | |
| 259 | + ret = regmap_write(regmap, NOA1305_REG_RESET, NOA1305_RESET_RESET); | |
| 260 | + if (ret < 0) { | |
| 261 | + dev_err(&client->dev, "Device reset failed\n"); | |
| 262 | + return ret; | |
| 263 | + } | |
| 264 | + | |
| 265 | + ret = regmap_write(regmap, NOA1305_REG_INTEGRATION_TIME, | |
| 266 | + NOA1305_INTEGR_TIME_800MS); | |
| 267 | + if (ret < 0) { | |
| 268 | + dev_err(&client->dev, "Setting integration time failed\n"); | |
| 269 | + return ret; | |
| 270 | + } | |
| 271 | + | |
| 272 | + indio_dev->dev.parent = &client->dev; | |
| 273 | + indio_dev->info = &noa1305_info; | |
| 274 | + indio_dev->channels = noa1305_channels; | |
| 275 | + indio_dev->num_channels = ARRAY_SIZE(noa1305_channels); | |
| 276 | + indio_dev->name = NOA1305_DRIVER_NAME; | |
| 277 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 278 | + | |
| 279 | + ret = devm_iio_device_register(&client->dev, indio_dev); | |
| 280 | + if (ret) | |
| 281 | + dev_err(&client->dev, "registering device failed\n"); | |
| 282 | + | |
| 283 | + return ret; | |
| 284 | +} | |
| 285 | + | |
| 286 | +static const struct of_device_id noa1305_of_match[] = { | |
| 287 | + { .compatible = "onnn,noa1305" }, | |
| 288 | + { } | |
| 289 | +}; | |
| 290 | +MODULE_DEVICE_TABLE(of, noa1305_of_match); | |
| 291 | + | |
| 292 | +static const struct i2c_device_id noa1305_ids[] = { | |
| 293 | + { "noa1305", 0 }, | |
| 294 | + { } | |
| 295 | +}; | |
| 296 | +MODULE_DEVICE_TABLE(i2c, noa1305_ids); | |
| 297 | + | |
| 298 | +static struct i2c_driver noa1305_driver = { | |
| 299 | + .driver = { | |
| 300 | + .name = NOA1305_DRIVER_NAME, | |
| 301 | + .of_match_table = noa1305_of_match, | |
| 302 | + }, | |
| 303 | + .probe = noa1305_probe, | |
| 304 | + .id_table = noa1305_ids, | |
| 305 | +}; | |
| 306 | + | |
| 307 | +module_i2c_driver(noa1305_driver); | |
| 308 | + | |
| 309 | +MODULE_AUTHOR("Sergei Miroshnichenko <sergeimir@emcraft.com>"); | |
| 310 | +MODULE_AUTHOR("Martyn Welch <martyn.welch@collabora.com"); | |
| 311 | +MODULE_DESCRIPTION("ON Semiconductor NOA1305 ambient light sensor"); | |
| 312 | +MODULE_LICENSE("GPL"); | |
| @@ -1261,7 +1261,7 @@ static int si1145_probe_trigger(struct iio_dev *indio_dev) · 1260 unmodified lines | ||
| 1261 | 1261 | return ret; |
| 1262 | 1262 | } |
| 1263 | 1263 | |
| 1264 | − ret = iio_trigger_register(trig); | |
| 1264 | + ret = devm_iio_trigger_register(&client->dev, trig); | |
| 1265 | 1265 | if (ret) |
| 1266 | 1266 | return ret; |
| 1267 | 1267 | |
| @@ -1271,16 +1271,6 @@ static int si1145_probe_trigger(struct iio_dev *indio_dev) · 3 unmodified lines | ||
| 1271 | 1271 | return 0; |
| 1272 | 1272 | } |
| 1273 | 1273 | |
| 1274 | −static void si1145_remove_trigger(struct iio_dev *indio_dev) | |
| 1275 | −{ | |
| 1276 | − struct si1145_data *data = iio_priv(indio_dev); | |
| 1277 | − | |
| 1278 | − if (data->trig) { | |
| 1279 | − iio_trigger_unregister(data->trig); | |
| 1280 | − data->trig = NULL; | |
| 1281 | − } | |
| 1282 | −} | |
| 1283 | − | |
| 1284 | 1274 | static int si1145_probe(struct i2c_client *client, |
| 1285 | 1275 | const struct i2c_device_id *id) |
| 1286 | 1276 | { |
| @@ -1332,7 +1322,8 @@ static int si1145_probe(struct i2c_client *client, · 45 unmodified lines | ||
| 1332 | 1322 | if (ret < 0) |
| 1333 | 1323 | return ret; |
| 1334 | 1324 | |
| 1335 | − ret = iio_triggered_buffer_setup(indio_dev, NULL, | |
| 1325 | + ret = devm_iio_triggered_buffer_setup(&client->dev, | |
| 1326 | + indio_dev, NULL, | |
| 1336 | 1327 | si1145_trigger_handler, &si1145_buffer_setup_ops); |
| 1337 | 1328 | if (ret < 0) |
| 1338 | 1329 | return ret; |
| @@ -1340,23 +1331,12 @@ static int si1145_probe(struct i2c_client *client, · 1 unmodified line | ||
| 1340 | 1331 | if (client->irq) { |
| 1341 | 1332 | ret = si1145_probe_trigger(indio_dev); |
| 1342 | 1333 | if (ret < 0) |
| 1343 | − goto error_free_buffer; | |
| 1334 | + return ret; | |
| 1344 | 1335 | } else { |
| 1345 | 1336 | dev_info(&client->dev, "no irq, using polling\n"); |
| 1346 | 1337 | } |
| 1347 | 1338 | |
| 1348 | − ret = iio_device_register(indio_dev); | |
| 1349 | − if (ret < 0) | |
| 1350 | − goto error_free_trigger; | |
| 1351 | − | |
| 1352 | − return 0; | |
| 1353 | − | |
| 1354 | −error_free_trigger: | |
| 1355 | − si1145_remove_trigger(indio_dev); | |
| 1356 | −error_free_buffer: | |
| 1357 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 1358 | − | |
| 1359 | − return ret; | |
| 1339 | + return devm_iio_device_register(&client->dev, indio_dev); | |
| 1360 | 1340 | } |
| 1361 | 1341 | |
| 1362 | 1342 | static const struct i2c_device_id si1145_ids[] = { |
| @@ -1371,23 +1351,11 @@ static const struct i2c_device_id si1145_ids[] = { · 8 unmodified lines | ||
| 1371 | 1351 | }; |
| 1372 | 1352 | MODULE_DEVICE_TABLE(i2c, si1145_ids); |
| 1373 | 1353 | |
| 1374 | −static int si1145_remove(struct i2c_client *client) | |
| 1375 | −{ | |
| 1376 | − struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 1377 | − | |
| 1378 | − iio_device_unregister(indio_dev); | |
| 1379 | − si1145_remove_trigger(indio_dev); | |
| 1380 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 1381 | − | |
| 1382 | − return 0; | |
| 1383 | −} | |
| 1384 | − | |
| 1385 | 1354 | static struct i2c_driver si1145_driver = { |
| 1386 | 1355 | .driver = { |
| 1387 | 1356 | .name = "si1145", |
| 1388 | 1357 | }, |
| 1389 | 1358 | .probe = si1145_probe, |
| 1390 | − .remove = si1145_remove, | |
| 1391 | 1359 | .id_table = si1145_ids, |
| 1392 | 1360 | }; |
| 1393 | 1361 | |
| @@ -679,9 +679,18 @@ static const struct acpi_device_id stk3310_acpi_id[] = { · 678 unmodified lines | ||
| 679 | 679 | |
| 680 | 680 | MODULE_DEVICE_TABLE(acpi, stk3310_acpi_id); |
| 681 | 681 | |
| 682 | +static const struct of_device_id stk3310_of_match[] = { | |
| 683 | + { .compatible = "sensortek,stk3310", }, | |
| 684 | + { .compatible = "sensortek,stk3311", }, | |
| 685 | + { .compatible = "sensortek,stk3335", }, | |
| 686 | + {} | |
| 687 | +}; | |
| 688 | +MODULE_DEVICE_TABLE(of, stk3310_of_match); | |
| 689 | + | |
| 682 | 690 | static struct i2c_driver stk3310_driver = { |
| 683 | 691 | .driver = { |
| 684 | 692 | .name = "stk3310", |
| 693 | + .of_match_table = stk3310_of_match, | |
| 685 | 694 | .pm = STK3310_PM_OPS, |
| 686 | 695 | .acpi_match_table = ACPI_PTR(stk3310_acpi_id), |
| 687 | 696 | }, |
| @@ -134,6 +134,12 @@ enum { · 133 unmodified lines | ||
| 134 | 134 | TSL2772_CHIP_SUSPENDED = 2 |
| 135 | 135 | }; |
| 136 | 136 | |
| 137 | +enum { | |
| 138 | + TSL2772_SUPPLY_VDD = 0, | |
| 139 | + TSL2772_SUPPLY_VDDIO = 1, | |
| 140 | + TSL2772_NUM_SUPPLIES = 2 | |
| 141 | +}; | |
| 142 | + | |
| 137 | 143 | /* Per-device data */ |
| 138 | 144 | struct tsl2772_als_info { |
| 139 | 145 | u16 als_ch0; |
| @@ -161,8 +167,7 @@ struct tsl2772_chip { · 21 unmodified lines | ||
| 161 | 167 | struct mutex prox_mutex; |
| 162 | 168 | struct mutex als_mutex; |
| 163 | 169 | struct i2c_client *client; |
| 164 | − struct regulator *vdd_supply; | |
| 165 | − struct regulator *vddio_supply; | |
| 170 | + struct regulator_bulk_data supplies[TSL2772_NUM_SUPPLIES]; | |
| 166 | 171 | u16 prox_data; |
| 167 | 172 | struct tsl2772_als_info als_cur_info; |
| 168 | 173 | struct tsl2772_settings settings; |
| @@ -697,46 +702,7 @@ static void tsl2772_disable_regulators_action(void *_data) · 528 unmodified lines | ||
| 697 | 702 | { |
| 698 | 703 | struct tsl2772_chip *chip = _data; |
| 699 | 704 | |
| 700 | − regulator_disable(chip->vdd_supply); | |
| 701 | − regulator_disable(chip->vddio_supply); | |
| 702 | −} | |
| 703 | − | |
| 704 | −static int tsl2772_enable_regulator(struct tsl2772_chip *chip, | |
| 705 | − struct regulator *regulator) | |
| 706 | −{ | |
| 707 | − int ret; | |
| 708 | − | |
| 709 | − ret = regulator_enable(regulator); | |
| 710 | − if (ret < 0) { | |
| 711 | − dev_err(&chip->client->dev, "Failed to enable regulator: %d\n", | |
| 712 | − ret); | |
| 713 | − return ret; | |
| 714 | − } | |
| 715 | − | |
| 716 | − return 0; | |
| 717 | −} | |
| 718 | − | |
| 719 | −static struct regulator *tsl2772_get_regulator(struct tsl2772_chip *chip, | |
| 720 | − char *name) | |
| 721 | −{ | |
| 722 | − struct regulator *regulator; | |
| 723 | − int ret; | |
| 724 | − | |
| 725 | − regulator = devm_regulator_get(&chip->client->dev, name); | |
| 726 | − if (IS_ERR(regulator)) { | |
| 727 | − if (PTR_ERR(regulator) != -EPROBE_DEFER) | |
| 728 | − dev_err(&chip->client->dev, | |
| 729 | − "Failed to get %s regulator %d\n", | |
| 730 | − name, (int)PTR_ERR(regulator)); | |
| 731 | − | |
| 732 | − return regulator; | |
| 733 | − } | |
| 734 | − | |
| 735 | − ret = tsl2772_enable_regulator(chip, regulator); | |
| 736 | − if (ret < 0) | |
| 737 | − return ERR_PTR(ret); | |
| 738 | − | |
| 739 | − return regulator; | |
| 705 | + regulator_bulk_disable(ARRAY_SIZE(chip->supplies), chip->supplies); | |
| 740 | 706 | } |
| 741 | 707 | |
| 742 | 708 | static int tsl2772_chip_on(struct iio_dev *indio_dev) |
| @@ -860,6 +826,13 @@ static int tsl2772_chip_off(struct iio_dev *indio_dev) · 117 unmodified lines | ||
| 860 | 826 | return tsl2772_write_control_reg(chip, 0x00); |
| 861 | 827 | } |
| 862 | 828 | |
| 829 | +static void tsl2772_chip_off_action(void *data) | |
| 830 | +{ | |
| 831 | + struct iio_dev *indio_dev = data; | |
| 832 | + | |
| 833 | + tsl2772_chip_off(indio_dev); | |
| 834 | +} | |
| 835 | + | |
| 863 | 836 | /** |
| 864 | 837 | * tsl2772_invoke_change - power cycle the device to implement the user |
| 865 | 838 | * parameters |
| @@ -1797,20 +1770,32 @@ static int tsl2772_probe(struct i2c_client *clientp, · 931 unmodified lines | ||
| 1797 | 1770 | chip->client = clientp; |
| 1798 | 1771 | i2c_set_clientdata(clientp, indio_dev); |
| 1799 | 1772 | |
| 1800 | − chip->vddio_supply = tsl2772_get_regulator(chip, "vddio"); | |
| 1801 | − if (IS_ERR(chip->vddio_supply)) | |
| 1802 | − return PTR_ERR(chip->vddio_supply); | |
| 1773 | + chip->supplies[TSL2772_SUPPLY_VDD].supply = "vdd"; | |
| 1774 | + chip->supplies[TSL2772_SUPPLY_VDDIO].supply = "vddio"; | |
| 1775 | + | |
| 1776 | + ret = devm_regulator_bulk_get(&clientp->dev, | |
| 1777 | + ARRAY_SIZE(chip->supplies), | |
| 1778 | + chip->supplies); | |
| 1779 | + if (ret < 0) { | |
| 1780 | + if (ret != -EPROBE_DEFER) | |
| 1781 | + dev_err(&clientp->dev, | |
| 1782 | + "Failed to get regulators: %d\n", | |
| 1783 | + ret); | |
| 1784 | + | |
| 1785 | + return ret; | |
| 1786 | + } | |
| 1803 | 1787 | |
| 1804 | − chip->vdd_supply = tsl2772_get_regulator(chip, "vdd"); | |
| 1805 | − if (IS_ERR(chip->vdd_supply)) { | |
| 1806 | − regulator_disable(chip->vddio_supply); | |
| 1807 | − return PTR_ERR(chip->vdd_supply); | |
| 1788 | + ret = regulator_bulk_enable(ARRAY_SIZE(chip->supplies), chip->supplies); | |
| 1789 | + if (ret < 0) { | |
| 1790 | + dev_err(&clientp->dev, "Failed to enable regulators: %d\n", | |
| 1791 | + ret); | |
| 1792 | + return ret; | |
| 1808 | 1793 | } |
| 1809 | 1794 | |
| 1810 | − ret = devm_add_action(&clientp->dev, tsl2772_disable_regulators_action, | |
| 1811 | − chip); | |
| 1795 | + ret = devm_add_action_or_reset(&clientp->dev, | |
| 1796 | + tsl2772_disable_regulators_action, | |
| 1797 | + chip); | |
| 1812 | 1798 | if (ret < 0) { |
| 1813 | − tsl2772_disable_regulators_action(chip); | |
| 1814 | 1799 | dev_err(&clientp->dev, "Failed to setup regulator cleanup action %d\n", |
| 1815 | 1800 | ret); |
| 1816 | 1801 | return ret; |
| @@ -1877,15 +1862,13 @@ static int tsl2772_probe(struct i2c_client *clientp, · 60 unmodified lines | ||
| 1877 | 1862 | if (ret < 0) |
| 1878 | 1863 | return ret; |
| 1879 | 1864 | |
| 1880 | − ret = iio_device_register(indio_dev); | |
| 1881 | − if (ret) { | |
| 1882 | − tsl2772_chip_off(indio_dev); | |
| 1883 | − dev_err(&clientp->dev, | |
| 1884 | − "%s: iio registration failed\n", __func__); | |
| 1865 | + ret = devm_add_action_or_reset(&clientp->dev, | |
| 1866 | + tsl2772_chip_off_action, | |
| 1867 | + indio_dev); | |
| 1868 | + if (ret < 0) | |
| 1885 | 1869 | return ret; |
| 1886 | − } | |
| 1887 | 1870 | |
| 1888 | − return 0; | |
| 1871 | + return devm_iio_device_register(&clientp->dev, indio_dev); | |
| 1889 | 1872 | } |
| 1890 | 1873 | |
| 1891 | 1874 | static int tsl2772_suspend(struct device *dev) |
| @@ -1895,8 +1878,7 @@ static int tsl2772_suspend(struct device *dev) · 3 unmodified lines | ||
| 1895 | 1878 | int ret; |
| 1896 | 1879 | |
| 1897 | 1880 | ret = tsl2772_chip_off(indio_dev); |
| 1898 | − regulator_disable(chip->vdd_supply); | |
| 1899 | − regulator_disable(chip->vddio_supply); | |
| 1881 | + regulator_bulk_disable(ARRAY_SIZE(chip->supplies), chip->supplies); | |
| 1900 | 1882 | |
| 1901 | 1883 | return ret; |
| 1902 | 1884 | } |
| @@ -1907,32 +1889,15 @@ static int tsl2772_resume(struct device *dev) · 4 unmodified lines | ||
| 1907 | 1889 | struct tsl2772_chip *chip = iio_priv(indio_dev); |
| 1908 | 1890 | int ret; |
| 1909 | 1891 | |
| 1910 | − ret = tsl2772_enable_regulator(chip, chip->vddio_supply); | |
| 1892 | + ret = regulator_bulk_enable(ARRAY_SIZE(chip->supplies), chip->supplies); | |
| 1911 | 1893 | if (ret < 0) |
| 1912 | 1894 | return ret; |
| 1913 | 1895 | |
| 1914 | − ret = tsl2772_enable_regulator(chip, chip->vdd_supply); | |
| 1915 | − if (ret < 0) { | |
| 1916 | − regulator_disable(chip->vddio_supply); | |
| 1917 | − return ret; | |
| 1918 | − } | |
| 1919 | − | |
| 1920 | 1896 | usleep_range(TSL2772_BOOT_MIN_SLEEP_TIME, TSL2772_BOOT_MAX_SLEEP_TIME); |
| 1921 | 1897 | |
| 1922 | 1898 | return tsl2772_chip_on(indio_dev); |
| 1923 | 1899 | } |
| 1924 | 1900 | |
| 1925 | −static int tsl2772_remove(struct i2c_client *client) | |
| 1926 | −{ | |
| 1927 | − struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 1928 | − | |
| 1929 | − tsl2772_chip_off(indio_dev); | |
| 1930 | − | |
| 1931 | − iio_device_unregister(indio_dev); | |
| 1932 | − | |
| 1933 | − return 0; | |
| 1934 | −} | |
| 1935 | − | |
| 1936 | 1901 | static const struct i2c_device_id tsl2772_idtable[] = { |
| 1937 | 1902 | { "tsl2571", tsl2571 }, |
| 1938 | 1903 | { "tsl2671", tsl2671 }, |
| @@ -1979,7 +1944,6 @@ static struct i2c_driver tsl2772_driver = { · 40 unmodified lines | ||
| 1979 | 1944 | }, |
| 1980 | 1945 | .id_table = tsl2772_idtable, |
| 1981 | 1946 | .probe = tsl2772_probe, |
| 1982 | − .remove = tsl2772_remove, | |
| 1983 | 1947 | }; |
| 1984 | 1948 | |
| 1985 | 1949 | module_i2c_driver(tsl2772_driver); |
| @@ -158,10 +158,10 @@ static int veml6070_probe(struct i2c_client *client, · 157 unmodified lines | ||
| 158 | 158 | indio_dev->name = VEML6070_DRV_NAME; |
| 159 | 159 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 160 | 160 | |
| 161 | − data->client2 = i2c_new_dummy(client->adapter, VEML6070_ADDR_DATA_LSB); | |
| 162 | − if (!data->client2) { | |
| 161 | + data->client2 = i2c_new_dummy_device(client->adapter, VEML6070_ADDR_DATA_LSB); | |
| 162 | + if (IS_ERR(data->client2)) { | |
| 163 | 163 | dev_err(&client->dev, "i2c device for second chip address failed\n"); |
| 164 | − return -ENODEV; | |
| 164 | + return PTR_ERR(data->client2); | |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | 167 | data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD | |
| @@ -53,7 +53,7 @@ · 52 unmodified lines | ||
| 53 | 53 | #define MMC35240_CTRL1_BW_SHIFT 0 |
| 54 | 54 | |
| 55 | 55 | #define MMC35240_WAIT_CHARGE_PUMP 50000 /* us */ |
| 56 | −#define MMC53240_WAIT_SET_RESET 1000 /* us */ | |
| 56 | +#define MMC35240_WAIT_SET_RESET 1000 /* us */ | |
| 57 | 57 | |
| 58 | 58 | /* |
| 59 | 59 | * Memsic OTP process code piece is put here for reference: |
| @@ -225,7 +225,7 @@ static int mmc35240_init(struct mmc35240_data *data) · 165 unmodified lines | ||
| 225 | 225 | ret = mmc35240_hw_set(data, true); |
| 226 | 226 | if (ret < 0) |
| 227 | 227 | return ret; |
| 228 | − usleep_range(MMC53240_WAIT_SET_RESET, MMC53240_WAIT_SET_RESET + 1); | |
| 228 | + usleep_range(MMC35240_WAIT_SET_RESET, MMC35240_WAIT_SET_RESET + 1); | |
| 229 | 229 | |
| 230 | 230 | ret = mmc35240_hw_set(data, false); |
| 231 | 231 | if (ret < 0) |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | #define LIS2MDL_MAGN_DEV_NAME "lis2mdl" |
| 23 | 23 | #define LSM9DS1_MAGN_DEV_NAME "lsm9ds1_magn" |
| 24 | 24 | |
| 25 | +const struct st_sensor_settings *st_magn_get_settings(const char *name); | |
| 25 | 26 | int st_magn_common_probe(struct iio_dev *indio_dev); |
| 26 | 27 | void st_magn_common_remove(struct iio_dev *indio_dev); |
| 27 | 28 | |
| @@ -32,39 +32,32 @@ int st_magn_trig_set_state(struct iio_trigger *trig, bool state) · 31 unmodified lines | ||
| 32 | 32 | static int st_magn_buffer_postenable(struct iio_dev *indio_dev) |
| 33 | 33 | { |
| 34 | 34 | int err; |
| 35 | − struct st_sensor_data *mdata = iio_priv(indio_dev); | |
| 36 | − | |
| 37 | − mdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); | |
| 38 | − if (mdata->buffer_data == NULL) { | |
| 39 | − err = -ENOMEM; | |
| 40 | − goto allocate_memory_error; | |
| 41 | − } | |
| 42 | 35 | |
| 43 | 36 | err = iio_triggered_buffer_postenable(indio_dev); |
| 44 | 37 | if (err < 0) |
| 45 | − goto st_magn_buffer_postenable_error; | |
| 38 | + return err; | |
| 39 | + | |
| 40 | + err = st_sensors_set_enable(indio_dev, true); | |
| 41 | + if (err < 0) | |
| 42 | + goto st_magn_buffer_predisable; | |
| 46 | 43 | |
| 47 | − return st_sensors_set_enable(indio_dev, true); | |
| 44 | + return 0; | |
| 48 | 45 | |
| 49 | −st_magn_buffer_postenable_error: | |
| 50 | − kfree(mdata->buffer_data); | |
| 51 | −allocate_memory_error: | |
| 46 | +st_magn_buffer_predisable: | |
| 47 | + iio_triggered_buffer_predisable(indio_dev); | |
| 52 | 48 | return err; |
| 53 | 49 | } |
| 54 | 50 | |
| 55 | 51 | static int st_magn_buffer_predisable(struct iio_dev *indio_dev) |
| 56 | 52 | { |
| 57 | − int err; | |
| 58 | − struct st_sensor_data *mdata = iio_priv(indio_dev); | |
| 53 | + int err, err2; | |
| 59 | 54 | |
| 60 | 55 | err = st_sensors_set_enable(indio_dev, false); |
| 61 | − if (err < 0) | |
| 62 | − goto st_magn_buffer_predisable_error; | |
| 63 | 56 | |
| 64 | − err = iio_triggered_buffer_predisable(indio_dev); | |
| 57 | + err2 = iio_triggered_buffer_predisable(indio_dev); | |
| 58 | + if (!err) | |
| 59 | + err = err2; | |
| 65 | 60 | |
| 66 | −st_magn_buffer_predisable_error: | |
| 67 | − kfree(mdata->buffer_data); | |
| 68 | 61 | return err; |
| 69 | 62 | } |
| 70 | 63 | |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/slab.h> |
| 13 | 13 | #include <linux/errno.h> |
| 14 | 14 | #include <linux/types.h> |
| 15 | −#include <linux/mutex.h> | |
| 16 | 15 | #include <linux/interrupt.h> |
| 17 | 16 | #include <linux/i2c.h> |
| 18 | 17 | #include <linux/gpio.h> |
| @@ -470,28 +469,41 @@ static const struct iio_trigger_ops st_magn_trigger_ops = { · 451 unmodified lines | ||
| 470 | 469 | #define ST_MAGN_TRIGGER_OPS NULL |
| 471 | 470 | #endif |
| 472 | 471 | |
| 472 | +/* | |
| 473 | + * st_magn_get_settings() - get sensor settings from device name | |
| 474 | + * @name: device name buffer reference. | |
| 475 | + * | |
| 476 | + * Return: valid reference on success, NULL otherwise. | |
| 477 | + */ | |
| 478 | +const struct st_sensor_settings *st_magn_get_settings(const char *name) | |
| 479 | +{ | |
| 480 | + int index = st_sensors_get_settings_index(name, | |
| 481 | + st_magn_sensors_settings, | |
| 482 | + ARRAY_SIZE(st_magn_sensors_settings)); | |
| 483 | + if (index < 0) | |
| 484 | + return NULL; | |
| 485 | + | |
| 486 | + return &st_magn_sensors_settings[index]; | |
| 487 | +} | |
| 488 | +EXPORT_SYMBOL(st_magn_get_settings); | |
| 489 | + | |
| 473 | 490 | int st_magn_common_probe(struct iio_dev *indio_dev) |
| 474 | 491 | { |
| 475 | 492 | struct st_sensor_data *mdata = iio_priv(indio_dev); |
| 476 | − int irq = mdata->get_irq_data_ready(indio_dev); | |
| 477 | 493 | int err; |
| 478 | 494 | |
| 479 | 495 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 480 | 496 | indio_dev->info = &magn_info; |
| 481 | − mutex_init(&mdata->tb.buf_lock); | |
| 482 | 497 | |
| 483 | 498 | err = st_sensors_power_enable(indio_dev); |
| 484 | 499 | if (err) |
| 485 | 500 | return err; |
| 486 | 501 | |
| 487 | − err = st_sensors_check_device_support(indio_dev, | |
| 488 | − ARRAY_SIZE(st_magn_sensors_settings), | |
| 489 | − st_magn_sensors_settings); | |
| 502 | + err = st_sensors_verify_id(indio_dev); | |
| 490 | 503 | if (err < 0) |
| 491 | 504 | goto st_magn_power_off; |
| 492 | 505 | |
| 493 | 506 | mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS; |
| 494 | − mdata->multiread_bit = mdata->sensor_settings->multi_read_bit; | |
| 495 | 507 | indio_dev->channels = mdata->sensor_settings->ch; |
| 496 | 508 | indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; |
| 497 | 509 | |
| @@ -507,7 +519,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev) · 9 unmodified lines | ||
| 507 | 519 | if (err < 0) |
| 508 | 520 | goto st_magn_power_off; |
| 509 | 521 | |
| 510 | − if (irq > 0) { | |
| 522 | + if (mdata->irq > 0) { | |
| 511 | 523 | err = st_sensors_allocate_trigger(indio_dev, |
| 512 | 524 | ST_MAGN_TRIGGER_OPS); |
| 513 | 525 | if (err < 0) |
| @@ -524,7 +536,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev) · 10 unmodified lines | ||
| 524 | 536 | return 0; |
| 525 | 537 | |
| 526 | 538 | st_magn_device_register_error: |
| 527 | − if (irq > 0) | |
| 539 | + if (mdata->irq > 0) | |
| 528 | 540 | st_sensors_deallocate_trigger(indio_dev); |
| 529 | 541 | st_magn_probe_trigger_error: |
| 530 | 542 | st_magn_deallocate_ring(indio_dev); |
| @@ -542,7 +554,7 @@ void st_magn_common_remove(struct iio_dev *indio_dev) · 11 unmodified lines | ||
| 542 | 554 | st_sensors_power_disable(indio_dev); |
| 543 | 555 | |
| 544 | 556 | iio_device_unregister(indio_dev); |
| 545 | − if (mdata->get_irq_data_ready(indio_dev) > 0) | |
| 557 | + if (mdata->irq > 0) | |
| 546 | 558 | st_sensors_deallocate_trigger(indio_dev); |
| 547 | 559 | |
| 548 | 560 | st_magn_deallocate_ring(indio_dev); |
| @@ -55,21 +55,33 @@ MODULE_DEVICE_TABLE(of, st_magn_of_match); · 54 unmodified lines | ||
| 55 | 55 | #endif |
| 56 | 56 | |
| 57 | 57 | static int st_magn_i2c_probe(struct i2c_client *client, |
| 58 | − const struct i2c_device_id *id) | |
| 58 | + const struct i2c_device_id *id) | |
| 59 | 59 | { |
| 60 | − struct iio_dev *indio_dev; | |
| 60 | + const struct st_sensor_settings *settings; | |
| 61 | 61 | struct st_sensor_data *mdata; |
| 62 | + struct iio_dev *indio_dev; | |
| 62 | 63 | int err; |
| 63 | 64 | |
| 65 | + st_sensors_of_name_probe(&client->dev, st_magn_of_match, | |
| 66 | + client->name, sizeof(client->name)); | |
| 67 | + | |
| 68 | + settings = st_magn_get_settings(client->name); | |
| 69 | + if (!settings) { | |
| 70 | + dev_err(&client->dev, "device name %s not recognized.\n", | |
| 71 | + client->name); | |
| 72 | + return -ENODEV; | |
| 73 | + } | |
| 74 | + | |
| 64 | 75 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*mdata)); |
| 65 | 76 | if (!indio_dev) |
| 66 | 77 | return -ENOMEM; |
| 67 | 78 | |
| 68 | 79 | mdata = iio_priv(indio_dev); |
| 69 | − st_sensors_of_name_probe(&client->dev, st_magn_of_match, | |
| 70 | − client->name, sizeof(client->name)); | |
| 80 | + mdata->sensor_settings = (struct st_sensor_settings *)settings; | |
| 71 | 81 | |
| 72 | − st_sensors_i2c_configure(indio_dev, client, mdata); | |
| 82 | + err = st_sensors_i2c_configure(indio_dev, client); | |
| 83 | + if (err < 0) | |
| 84 | + return err; | |
| 73 | 85 | |
| 74 | 86 | err = st_magn_common_probe(indio_dev); |
| 75 | 87 | if (err < 0) |
| @@ -51,19 +51,31 @@ MODULE_DEVICE_TABLE(of, st_magn_of_match); · 50 unmodified lines | ||
| 51 | 51 | |
| 52 | 52 | static int st_magn_spi_probe(struct spi_device *spi) |
| 53 | 53 | { |
| 54 | − struct iio_dev *indio_dev; | |
| 54 | + const struct st_sensor_settings *settings; | |
| 55 | 55 | struct st_sensor_data *mdata; |
| 56 | + struct iio_dev *indio_dev; | |
| 56 | 57 | int err; |
| 57 | 58 | |
| 59 | + st_sensors_of_name_probe(&spi->dev, st_magn_of_match, | |
| 60 | + spi->modalias, sizeof(spi->modalias)); | |
| 61 | + | |
| 62 | + settings = st_magn_get_settings(spi->modalias); | |
| 63 | + if (!settings) { | |
| 64 | + dev_err(&spi->dev, "device name %s not recognized.\n", | |
| 65 | + spi->modalias); | |
| 66 | + return -ENODEV; | |
| 67 | + } | |
| 68 | + | |
| 58 | 69 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*mdata)); |
| 59 | 70 | if (!indio_dev) |
| 60 | 71 | return -ENOMEM; |
| 61 | 72 | |
| 62 | 73 | mdata = iio_priv(indio_dev); |
| 74 | + mdata->sensor_settings = (struct st_sensor_settings *)settings; | |
| 63 | 75 | |
| 64 | − st_sensors_of_name_probe(&spi->dev, st_magn_of_match, | |
| 65 | − spi->modalias, sizeof(spi->modalias)); | |
| 66 | − st_sensors_spi_configure(indio_dev, spi, mdata); | |
| 76 | + err = st_sensors_spi_configure(indio_dev, spi); | |
| 77 | + if (err < 0) | |
| 78 | + return err; | |
| 67 | 79 | |
| 68 | 80 | err = st_magn_common_probe(indio_dev); |
| 69 | 81 | if (err < 0) |
| @@ -26,6 +26,17 @@ config DS1803 · 25 unmodified lines | ||
| 26 | 26 | To compile this driver as a module, choose M here: the |
| 27 | 27 | module will be called ds1803. |
| 28 | 28 | |
| 29 | +config MAX5432 | |
| 30 | + tristate "Maxim MAX5432-MAX5435 Digital Potentiometer driver" | |
| 31 | + depends on I2C | |
| 32 | + help | |
| 33 | + Say yes here to build support for the Maxim | |
| 34 | + MAX5432, MAX5433, MAX5434 and MAX5435 digital | |
| 35 | + potentiometer chips. | |
| 36 | + | |
| 37 | + To compile this driver as a module, choose M here: the | |
| 38 | + module will be called max5432. | |
| 39 | + | |
| 29 | 40 | config MAX5481 |
| 30 | 41 | tristate "Maxim MAX5481-MAX5484 Digital Potentiometer driver" |
| 31 | 42 | depends on SPI |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | # When adding new entries keep the list in alphabetical order |
| 7 | 7 | obj-$(CONFIG_AD5272) += ad5272.o |
| 8 | 8 | obj-$(CONFIG_DS1803) += ds1803.o |
| 9 | +obj-$(CONFIG_MAX5432) += max5432.o | |
| 9 | 10 | obj-$(CONFIG_MAX5481) += max5481.o |
| 10 | 11 | obj-$(CONFIG_MAX5487) += max5487.o |
| 11 | 12 | obj-$(CONFIG_MCP4018) += mcp4018.o |
| @@ -0,0 +1,135 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later | |
| 2 | +/* | |
| 3 | + * Maxim Integrated MAX5432-MAX5435 digital potentiometer driver | |
| 4 | + * Copyright (C) 2019 Martin Kaiser <martin@kaiser.cx> | |
| 5 | + * | |
| 6 | + * Datasheet: | |
| 7 | + * https://datasheets.maximintegrated.com/en/ds/MAX5432-MAX5435.pdf | |
| 8 | + */ | |
| 9 | + | |
| 10 | +#include <linux/i2c.h> | |
| 11 | +#include <linux/iio/iio.h> | |
| 12 | +#include <linux/limits.h> | |
| 13 | +#include <linux/module.h> | |
| 14 | +#include <linux/of.h> | |
| 15 | +#include <linux/of_device.h> | |
| 16 | + | |
| 17 | +/* All chip variants have 32 wiper positions. */ | |
| 18 | +#define MAX5432_MAX_POS 31 | |
| 19 | + | |
| 20 | +#define MAX5432_OHM_50K (50 * 1000) | |
| 21 | +#define MAX5432_OHM_100K (100 * 1000) | |
| 22 | + | |
| 23 | +/* Update the volatile (currently active) setting. */ | |
| 24 | +#define MAX5432_CMD_VREG 0x11 | |
| 25 | + | |
| 26 | +struct max5432_data { | |
| 27 | + struct i2c_client *client; | |
| 28 | + unsigned long ohm; | |
| 29 | +}; | |
| 30 | + | |
| 31 | +static const struct iio_chan_spec max5432_channels[] = { | |
| 32 | + { | |
| 33 | + .type = IIO_RESISTANCE, | |
| 34 | + .indexed = 1, | |
| 35 | + .output = 1, | |
| 36 | + .channel = 0, | |
| 37 | + .address = MAX5432_CMD_VREG, | |
| 38 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | |
| 39 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), | |
| 40 | + } | |
| 41 | +}; | |
| 42 | + | |
| 43 | +static int max5432_read_raw(struct iio_dev *indio_dev, | |
| 44 | + struct iio_chan_spec const *chan, | |
| 45 | + int *val, int *val2, long mask) | |
| 46 | +{ | |
| 47 | + struct max5432_data *data = iio_priv(indio_dev); | |
| 48 | + | |
| 49 | + if (mask != IIO_CHAN_INFO_SCALE) | |
| 50 | + return -EINVAL; | |
| 51 | + | |
| 52 | + if (unlikely(data->ohm > INT_MAX)) | |
| 53 | + return -ERANGE; | |
| 54 | + | |
| 55 | + *val = data->ohm; | |
| 56 | + *val2 = MAX5432_MAX_POS; | |
| 57 | + | |
| 58 | + return IIO_VAL_FRACTIONAL; | |
| 59 | +} | |
| 60 | + | |
| 61 | +static int max5432_write_raw(struct iio_dev *indio_dev, | |
| 62 | + struct iio_chan_spec const *chan, | |
| 63 | + int val, int val2, long mask) | |
| 64 | +{ | |
| 65 | + struct max5432_data *data = iio_priv(indio_dev); | |
| 66 | + u8 data_byte; | |
| 67 | + | |
| 68 | + if (mask != IIO_CHAN_INFO_RAW) | |
| 69 | + return -EINVAL; | |
| 70 | + | |
| 71 | + if (val < 0 || val > MAX5432_MAX_POS) | |
| 72 | + return -EINVAL; | |
| 73 | + | |
| 74 | + if (val2 != 0) | |
| 75 | + return -EINVAL; | |
| 76 | + | |
| 77 | + /* Wiper position is in bits D7-D3. (D2-D0 are don't care bits.) */ | |
| 78 | + data_byte = val << 3; | |
| 79 | + return i2c_smbus_write_byte_data(data->client, chan->address, | |
| 80 | + data_byte); | |
| 81 | +} | |
| 82 | + | |
| 83 | +static const struct iio_info max5432_info = { | |
| 84 | + .read_raw = max5432_read_raw, | |
| 85 | + .write_raw = max5432_write_raw, | |
| 86 | +}; | |
| 87 | + | |
| 88 | +static int max5432_probe(struct i2c_client *client, | |
| 89 | + const struct i2c_device_id *id) | |
| 90 | +{ | |
| 91 | + struct device *dev = &client->dev; | |
| 92 | + struct iio_dev *indio_dev; | |
| 93 | + struct max5432_data *data; | |
| 94 | + | |
| 95 | + indio_dev = devm_iio_device_alloc(dev, sizeof(struct max5432_data)); | |
| 96 | + if (!indio_dev) | |
| 97 | + return -ENOMEM; | |
| 98 | + | |
| 99 | + i2c_set_clientdata(client, indio_dev); | |
| 100 | + | |
| 101 | + data = iio_priv(indio_dev); | |
| 102 | + data->client = client; | |
| 103 | + data->ohm = (unsigned long)of_device_get_match_data(dev); | |
| 104 | + | |
| 105 | + indio_dev->dev.parent = dev; | |
| 106 | + indio_dev->info = &max5432_info; | |
| 107 | + indio_dev->channels = max5432_channels; | |
| 108 | + indio_dev->num_channels = ARRAY_SIZE(max5432_channels); | |
| 109 | + indio_dev->name = client->name; | |
| 110 | + | |
| 111 | + return devm_iio_device_register(dev, indio_dev); | |
| 112 | +} | |
| 113 | + | |
| 114 | +static const struct of_device_id max5432_dt_ids[] = { | |
| 115 | + { .compatible = "maxim,max5432", .data = (void *)MAX5432_OHM_50K }, | |
| 116 | + { .compatible = "maxim,max5433", .data = (void *)MAX5432_OHM_100K }, | |
| 117 | + { .compatible = "maxim,max5434", .data = (void *)MAX5432_OHM_50K }, | |
| 118 | + { .compatible = "maxim,max5435", .data = (void *)MAX5432_OHM_100K }, | |
| 119 | + { /* sentinel */ } | |
| 120 | +}; | |
| 121 | +MODULE_DEVICE_TABLE(of, max5432_dt_ids); | |
| 122 | + | |
| 123 | +static struct i2c_driver max5432_driver = { | |
| 124 | + .driver = { | |
| 125 | + .name = "max5432", | |
| 126 | + .of_match_table = of_match_ptr(max5432_dt_ids), | |
| 127 | + }, | |
| 128 | + .probe = max5432_probe, | |
| 129 | +}; | |
| 130 | + | |
| 131 | +module_i2c_driver(max5432_driver); | |
| 132 | + | |
| 133 | +MODULE_AUTHOR("Martin Kaiser <martin@kaiser.cx>"); | |
| 134 | +MODULE_DESCRIPTION("max5432-max5435 digital potentiometers"); | |
| 135 | +MODULE_LICENSE("GPL v2"); | |
| @@ -39,26 +39,29 @@ static int cros_ec_baro_read(struct iio_dev *indio_dev, · 38 unmodified lines | ||
| 39 | 39 | { |
| 40 | 40 | struct cros_ec_baro_state *st = iio_priv(indio_dev); |
| 41 | 41 | u16 data = 0; |
| 42 | − int ret = IIO_VAL_INT; | |
| 42 | + int ret; | |
| 43 | 43 | int idx = chan->scan_index; |
| 44 | 44 | |
| 45 | 45 | mutex_lock(&st->core.cmd_lock); |
| 46 | 46 | |
| 47 | 47 | switch (mask) { |
| 48 | 48 | case IIO_CHAN_INFO_RAW: |
| 49 | − if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx, | |
| 50 | − (s16 *)&data) < 0) | |
| 51 | − ret = -EIO; | |
| 49 | + ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx, | |
| 50 | + (s16 *)&data); | |
| 51 | + if (ret) | |
| 52 | + break; | |
| 53 | + | |
| 52 | 54 | *val = data; |
| 55 | + ret = IIO_VAL_INT; | |
| 53 | 56 | break; |
| 54 | 57 | case IIO_CHAN_INFO_SCALE: |
| 55 | 58 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; |
| 56 | 59 | st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE; |
| 57 | 60 | |
| 58 | − if (cros_ec_motion_send_host_cmd(&st->core, 0)) { | |
| 59 | − ret = -EIO; | |
| 61 | + ret = cros_ec_motion_send_host_cmd(&st->core, 0); | |
| 62 | + if (ret) | |
| 60 | 63 | break; |
| 61 | − } | |
| 64 | + | |
| 62 | 65 | *val = st->core.resp->sensor_range.ret; |
| 63 | 66 | |
| 64 | 67 | /* scale * in_pressure_raw --> kPa */ |
| @@ -152,8 +155,6 @@ static int cros_ec_baro_probe(struct platform_device *pdev) · 87 unmodified lines | ||
| 152 | 155 | channel->ext_info = cros_ec_sensors_ext_info; |
| 153 | 156 | channel->scan_type.sign = 'u'; |
| 154 | 157 | |
| 155 | − state->core.calib[0] = 0; | |
| 156 | − | |
| 157 | 158 | /* Sensor specific */ |
| 158 | 159 | switch (state->core.type) { |
| 159 | 160 | case MOTIONSENSE_TYPE_BARO: |
| @@ -243,10 +243,10 @@ static int hp03_probe(struct i2c_client *client, · 242 unmodified lines | ||
| 243 | 243 | * which has it's dedicated I2C address and contains |
| 244 | 244 | * the calibration constants for the sensor. |
| 245 | 245 | */ |
| 246 | − priv->eeprom_client = i2c_new_dummy(client->adapter, HP03_EEPROM_ADDR); | |
| 247 | − if (!priv->eeprom_client) { | |
| 246 | + priv->eeprom_client = i2c_new_dummy_device(client->adapter, HP03_EEPROM_ADDR); | |
| 247 | + if (IS_ERR(priv->eeprom_client)) { | |
| 248 | 248 | dev_err(dev, "New EEPROM I2C device failed\n"); |
| 249 | − return -ENODEV; | |
| 249 | + return PTR_ERR(priv->eeprom_client); | |
| 250 | 250 | } |
| 251 | 251 | |
| 252 | 252 | priv->eeprom_regmap = regmap_init_i2c(priv->eeprom_client, |
| @@ -41,6 +41,7 @@ static const struct st_sensors_platform_data default_press_pdata = { · 40 unmodified lines | ||
| 41 | 41 | .drdy_int_pin = 1, |
| 42 | 42 | }; |
| 43 | 43 | |
| 44 | +const struct st_sensor_settings *st_press_get_settings(const char *name); | |
| 44 | 45 | int st_press_common_probe(struct iio_dev *indio_dev); |
| 45 | 46 | void st_press_common_remove(struct iio_dev *indio_dev); |
| 46 | 47 | |
| @@ -29,52 +29,39 @@ int st_press_trig_set_state(struct iio_trigger *trig, bool state) · 28 unmodified lines | ||
| 29 | 29 | return st_sensors_set_dataready_irq(indio_dev, state); |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | −static int st_press_buffer_preenable(struct iio_dev *indio_dev) | |
| 33 | −{ | |
| 34 | − return st_sensors_set_enable(indio_dev, true); | |
| 35 | −} | |
| 36 | − | |
| 37 | 32 | static int st_press_buffer_postenable(struct iio_dev *indio_dev) |
| 38 | 33 | { |
| 39 | 34 | int err; |
| 40 | − struct st_sensor_data *press_data = iio_priv(indio_dev); | |
| 41 | − | |
| 42 | − press_data->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); | |
| 43 | − if (press_data->buffer_data == NULL) { | |
| 44 | − err = -ENOMEM; | |
| 45 | − goto allocate_memory_error; | |
| 46 | − } | |
| 47 | 35 | |
| 48 | 36 | err = iio_triggered_buffer_postenable(indio_dev); |
| 49 | 37 | if (err < 0) |
| 50 | − goto st_press_buffer_postenable_error; | |
| 38 | + return err; | |
| 51 | 39 | |
| 52 | − return err; | |
| 40 | + err = st_sensors_set_enable(indio_dev, true); | |
| 41 | + if (err < 0) | |
| 42 | + goto st_press_buffer_predisable; | |
| 53 | 43 | |
| 54 | −st_press_buffer_postenable_error: | |
| 55 | − kfree(press_data->buffer_data); | |
| 56 | −allocate_memory_error: | |
| 44 | + return 0; | |
| 45 | + | |
| 46 | +st_press_buffer_predisable: | |
| 47 | + iio_triggered_buffer_predisable(indio_dev); | |
| 57 | 48 | return err; |
| 58 | 49 | } |
| 59 | 50 | |
| 60 | 51 | static int st_press_buffer_predisable(struct iio_dev *indio_dev) |
| 61 | 52 | { |
| 62 | − int err; | |
| 63 | − struct st_sensor_data *press_data = iio_priv(indio_dev); | |
| 64 | − | |
| 65 | − err = iio_triggered_buffer_predisable(indio_dev); | |
| 66 | − if (err < 0) | |
| 67 | − goto st_press_buffer_predisable_error; | |
| 53 | + int err, err2; | |
| 68 | 54 | |
| 69 | 55 | err = st_sensors_set_enable(indio_dev, false); |
| 70 | 56 | |
| 71 | −st_press_buffer_predisable_error: | |
| 72 | − kfree(press_data->buffer_data); | |
| 57 | + err2 = iio_triggered_buffer_predisable(indio_dev); | |
| 58 | + if (!err) | |
| 59 | + err = err2; | |
| 60 | + | |
| 73 | 61 | return err; |
| 74 | 62 | } |
| 75 | 63 | |
| 76 | 64 | static const struct iio_buffer_setup_ops st_press_buffer_setup_ops = { |
| 77 | − .preenable = &st_press_buffer_preenable, | |
| 78 | 65 | .postenable = &st_press_buffer_postenable, |
| 79 | 66 | .predisable = &st_press_buffer_predisable, |
| 80 | 67 | }; |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/slab.h> |
| 13 | 13 | #include <linux/errno.h> |
| 14 | 14 | #include <linux/types.h> |
| 15 | −#include <linux/mutex.h> | |
| 16 | 15 | #include <linux/interrupt.h> |
| 17 | 16 | #include <linux/i2c.h> |
| 18 | 17 | #include <linux/gpio.h> |
| @@ -664,25 +663,39 @@ static const struct iio_trigger_ops st_press_trigger_ops = { · 645 unmodified lines | ||
| 664 | 663 | #define ST_PRESS_TRIGGER_OPS NULL |
| 665 | 664 | #endif |
| 666 | 665 | |
| 666 | +/* | |
| 667 | + * st_press_get_settings() - get sensor settings from device name | |
| 668 | + * @name: device name buffer reference. | |
| 669 | + * | |
| 670 | + * Return: valid reference on success, NULL otherwise. | |
| 671 | + */ | |
| 672 | +const struct st_sensor_settings *st_press_get_settings(const char *name) | |
| 673 | +{ | |
| 674 | + int index = st_sensors_get_settings_index(name, | |
| 675 | + st_press_sensors_settings, | |
| 676 | + ARRAY_SIZE(st_press_sensors_settings)); | |
| 677 | + if (index < 0) | |
| 678 | + return NULL; | |
| 679 | + | |
| 680 | + return &st_press_sensors_settings[index]; | |
| 681 | +} | |
| 682 | +EXPORT_SYMBOL(st_press_get_settings); | |
| 683 | + | |
| 667 | 684 | int st_press_common_probe(struct iio_dev *indio_dev) |
| 668 | 685 | { |
| 669 | 686 | struct st_sensor_data *press_data = iio_priv(indio_dev); |
| 670 | 687 | struct st_sensors_platform_data *pdata = |
| 671 | 688 | (struct st_sensors_platform_data *)press_data->dev->platform_data; |
| 672 | − int irq = press_data->get_irq_data_ready(indio_dev); | |
| 673 | 689 | int err; |
| 674 | 690 | |
| 675 | 691 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 676 | 692 | indio_dev->info = &press_info; |
| 677 | − mutex_init(&press_data->tb.buf_lock); | |
| 678 | 693 | |
| 679 | 694 | err = st_sensors_power_enable(indio_dev); |
| 680 | 695 | if (err) |
| 681 | 696 | return err; |
| 682 | 697 | |
| 683 | − err = st_sensors_check_device_support(indio_dev, | |
| 684 | − ARRAY_SIZE(st_press_sensors_settings), | |
| 685 | − st_press_sensors_settings); | |
| 698 | + err = st_sensors_verify_id(indio_dev); | |
| 686 | 699 | if (err < 0) |
| 687 | 700 | goto st_press_power_off; |
| 688 | 701 | |
| @@ -693,7 +706,6 @@ int st_press_common_probe(struct iio_dev *indio_dev) · 4 unmodified lines | ||
| 693 | 706 | * element. |
| 694 | 707 | */ |
| 695 | 708 | press_data->num_data_channels = press_data->sensor_settings->num_ch - 1; |
| 696 | − press_data->multiread_bit = press_data->sensor_settings->multi_read_bit; | |
| 697 | 709 | indio_dev->channels = press_data->sensor_settings->ch; |
| 698 | 710 | indio_dev->num_channels = press_data->sensor_settings->num_ch; |
| 699 | 711 | |
| @@ -716,7 +728,7 @@ int st_press_common_probe(struct iio_dev *indio_dev) · 16 unmodified lines | ||
| 716 | 728 | if (err < 0) |
| 717 | 729 | goto st_press_power_off; |
| 718 | 730 | |
| 719 | − if (irq > 0) { | |
| 731 | + if (press_data->irq > 0) { | |
| 720 | 732 | err = st_sensors_allocate_trigger(indio_dev, |
| 721 | 733 | ST_PRESS_TRIGGER_OPS); |
| 722 | 734 | if (err < 0) |
| @@ -733,7 +745,7 @@ int st_press_common_probe(struct iio_dev *indio_dev) · 10 unmodified lines | ||
| 733 | 745 | return err; |
| 734 | 746 | |
| 735 | 747 | st_press_device_register_error: |
| 736 | − if (irq > 0) | |
| 748 | + if (press_data->irq > 0) | |
| 737 | 749 | st_sensors_deallocate_trigger(indio_dev); |
| 738 | 750 | st_press_probe_trigger_error: |
| 739 | 751 | st_press_deallocate_ring(indio_dev); |
| @@ -751,7 +763,7 @@ void st_press_common_remove(struct iio_dev *indio_dev) · 11 unmodified lines | ||
| 751 | 763 | st_sensors_power_disable(indio_dev); |
| 752 | 764 | |
| 753 | 765 | iio_device_unregister(indio_dev); |
| 754 | − if (press_data->get_irq_data_ready(indio_dev) > 0) | |
| 766 | + if (press_data->irq > 0) | |
| 755 | 767 | st_sensors_deallocate_trigger(indio_dev); |
| 756 | 768 | |
| 757 | 769 | st_press_deallocate_ring(indio_dev); |
| @@ -78,18 +78,13 @@ static const struct i2c_device_id st_press_id_table[] = { · 77 unmodified lines | ||
| 78 | 78 | MODULE_DEVICE_TABLE(i2c, st_press_id_table); |
| 79 | 79 | |
| 80 | 80 | static int st_press_i2c_probe(struct i2c_client *client, |
| 81 | − const struct i2c_device_id *id) | |
| 81 | + const struct i2c_device_id *id) | |
| 82 | 82 | { |
| 83 | − struct iio_dev *indio_dev; | |
| 83 | + const struct st_sensor_settings *settings; | |
| 84 | 84 | struct st_sensor_data *press_data; |
| 85 | + struct iio_dev *indio_dev; | |
| 85 | 86 | int ret; |
| 86 | 87 | |
| 87 | − indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*press_data)); | |
| 88 | − if (!indio_dev) | |
| 89 | − return -ENOMEM; | |
| 90 | − | |
| 91 | − press_data = iio_priv(indio_dev); | |
| 92 | − | |
| 93 | 88 | if (client->dev.of_node) { |
| 94 | 89 | st_sensors_of_name_probe(&client->dev, st_press_of_match, |
| 95 | 90 | client->name, sizeof(client->name)); |
| @@ -99,11 +94,27 @@ static int st_press_i2c_probe(struct i2c_client *client, · 3 unmodified lines | ||
| 99 | 94 | return -ENODEV; |
| 100 | 95 | |
| 101 | 96 | strlcpy(client->name, st_press_id_table[ret].name, |
| 102 | − sizeof(client->name)); | |
| 97 | + sizeof(client->name)); | |
| 103 | 98 | } else if (!id) |
| 104 | 99 | return -ENODEV; |
| 105 | 100 | |
| 106 | − st_sensors_i2c_configure(indio_dev, client, press_data); | |
| 101 | + settings = st_press_get_settings(client->name); | |
| 102 | + if (!settings) { | |
| 103 | + dev_err(&client->dev, "device name %s not recognized.\n", | |
| 104 | + client->name); | |
| 105 | + return -ENODEV; | |
| 106 | + } | |
| 107 | + | |
| 108 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*press_data)); | |
| 109 | + if (!indio_dev) | |
| 110 | + return -ENOMEM; | |
| 111 | + | |
| 112 | + press_data = iio_priv(indio_dev); | |
| 113 | + press_data->sensor_settings = (struct st_sensor_settings *)settings; | |
| 114 | + | |
| 115 | + ret = st_sensors_i2c_configure(indio_dev, client); | |
| 116 | + if (ret < 0) | |
| 117 | + return ret; | |
| 107 | 118 | |
| 108 | 119 | ret = st_press_common_probe(indio_dev); |
| 109 | 120 | if (ret < 0) |
| @@ -61,19 +61,31 @@ MODULE_DEVICE_TABLE(of, st_press_of_match); · 60 unmodified lines | ||
| 61 | 61 | |
| 62 | 62 | static int st_press_spi_probe(struct spi_device *spi) |
| 63 | 63 | { |
| 64 | − struct iio_dev *indio_dev; | |
| 64 | + const struct st_sensor_settings *settings; | |
| 65 | 65 | struct st_sensor_data *press_data; |
| 66 | + struct iio_dev *indio_dev; | |
| 66 | 67 | int err; |
| 67 | 68 | |
| 69 | + st_sensors_of_name_probe(&spi->dev, st_press_of_match, | |
| 70 | + spi->modalias, sizeof(spi->modalias)); | |
| 71 | + | |
| 72 | + settings = st_press_get_settings(spi->modalias); | |
| 73 | + if (!settings) { | |
| 74 | + dev_err(&spi->dev, "device name %s not recognized.\n", | |
| 75 | + spi->modalias); | |
| 76 | + return -ENODEV; | |
| 77 | + } | |
| 78 | + | |
| 68 | 79 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*press_data)); |
| 69 | − if (indio_dev == NULL) | |
| 80 | + if (!indio_dev) | |
| 70 | 81 | return -ENOMEM; |
| 71 | 82 | |
| 72 | 83 | press_data = iio_priv(indio_dev); |
| 84 | + press_data->sensor_settings = (struct st_sensor_settings *)settings; | |
| 73 | 85 | |
| 74 | − st_sensors_of_name_probe(&spi->dev, st_press_of_match, | |
| 75 | − spi->modalias, sizeof(spi->modalias)); | |
| 76 | − st_sensors_spi_configure(indio_dev, spi, press_data); | |
| 86 | + err = st_sensors_spi_configure(indio_dev, spi); | |
| 87 | + if (err < 0) | |
| 88 | + return err; | |
| 77 | 89 | |
| 78 | 90 | err = st_press_common_probe(indio_dev); |
| 79 | 91 | if (err < 0) |
| @@ -230,31 +230,13 @@ static int maxim_thermocouple_probe(struct spi_device *spi) · 229 unmodified lines | ||
| 230 | 230 | data->spi = spi; |
| 231 | 231 | data->chip = chip; |
| 232 | 232 | |
| 233 | − ret = iio_triggered_buffer_setup(indio_dev, NULL, | |
| 233 | + ret = devm_iio_triggered_buffer_setup(&spi->dev, | |
| 234 | + indio_dev, NULL, | |
| 234 | 235 | maxim_thermocouple_trigger_handler, NULL); |
| 235 | 236 | if (ret) |
| 236 | 237 | return ret; |
| 237 | 238 | |
| 238 | − ret = iio_device_register(indio_dev); | |
| 239 | − if (ret) | |
| 240 | − goto error_unreg_buffer; | |
| 241 | − | |
| 242 | − return 0; | |
| 243 | − | |
| 244 | −error_unreg_buffer: | |
| 245 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 246 | − | |
| 247 | − return ret; | |
| 248 | −} | |
| 249 | − | |
| 250 | −static int maxim_thermocouple_remove(struct spi_device *spi) | |
| 251 | −{ | |
| 252 | − struct iio_dev *indio_dev = spi_get_drvdata(spi); | |
| 253 | − | |
| 254 | − iio_device_unregister(indio_dev); | |
| 255 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 256 | − | |
| 257 | − return 0; | |
| 239 | + return devm_iio_device_register(&spi->dev, indio_dev); | |
| 258 | 240 | } |
| 259 | 241 | |
| 260 | 242 | static const struct spi_device_id maxim_thermocouple_id[] = { |
| @@ -277,7 +259,6 @@ static struct spi_driver maxim_thermocouple_driver = { · 16 unmodified lines | ||
| 277 | 259 | .of_match_table = maxim_thermocouple_of_match, |
| 278 | 260 | }, |
| 279 | 261 | .probe = maxim_thermocouple_probe, |
| 280 | − .remove = maxim_thermocouple_remove, | |
| 281 | 262 | .id_table = maxim_thermocouple_id, |
| 282 | 263 | }; |
| 283 | 264 | module_spi_driver(maxim_thermocouple_driver); |
| @@ -608,86 +608,6 @@ static const struct iio_enum stm32_enable_mode_enum = { · 607 unmodified lines | ||
| 608 | 608 | .get = stm32_get_enable_mode |
| 609 | 609 | }; |
| 610 | 610 | |
| 611 | −static const char *const stm32_quadrature_modes[] = { | |
| 612 | − "channel_A", | |
| 613 | − "channel_B", | |
| 614 | − "quadrature", | |
| 615 | −}; | |
| 616 | − | |
| 617 | −static int stm32_set_quadrature_mode(struct iio_dev *indio_dev, | |
| 618 | − const struct iio_chan_spec *chan, | |
| 619 | − unsigned int mode) | |
| 620 | −{ | |
| 621 | − struct stm32_timer_trigger *priv = iio_priv(indio_dev); | |
| 622 | − | |
| 623 | − regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, mode + 1); | |
| 624 | − | |
| 625 | − return 0; | |
| 626 | −} | |
| 627 | − | |
| 628 | −static int stm32_get_quadrature_mode(struct iio_dev *indio_dev, | |
| 629 | − const struct iio_chan_spec *chan) | |
| 630 | −{ | |
| 631 | − struct stm32_timer_trigger *priv = iio_priv(indio_dev); | |
| 632 | − u32 smcr; | |
| 633 | − int mode; | |
| 634 | − | |
| 635 | − regmap_read(priv->regmap, TIM_SMCR, &smcr); | |
| 636 | − mode = (smcr & TIM_SMCR_SMS) - 1; | |
| 637 | − if ((mode < 0) || (mode > ARRAY_SIZE(stm32_quadrature_modes))) | |
| 638 | − return -EINVAL; | |
| 639 | − | |
| 640 | − return mode; | |
| 641 | −} | |
| 642 | − | |
| 643 | −static const struct iio_enum stm32_quadrature_mode_enum = { | |
| 644 | − .items = stm32_quadrature_modes, | |
| 645 | − .num_items = ARRAY_SIZE(stm32_quadrature_modes), | |
| 646 | − .set = stm32_set_quadrature_mode, | |
| 647 | − .get = stm32_get_quadrature_mode | |
| 648 | −}; | |
| 649 | − | |
| 650 | −static const char *const stm32_count_direction_states[] = { | |
| 651 | − "up", | |
| 652 | − "down" | |
| 653 | −}; | |
| 654 | − | |
| 655 | −static int stm32_set_count_direction(struct iio_dev *indio_dev, | |
| 656 | − const struct iio_chan_spec *chan, | |
| 657 | − unsigned int dir) | |
| 658 | −{ | |
| 659 | − struct stm32_timer_trigger *priv = iio_priv(indio_dev); | |
| 660 | − u32 val; | |
| 661 | − int mode; | |
| 662 | − | |
| 663 | − /* In encoder mode, direction is RO (given by TI1/TI2 signals) */ | |
| 664 | − regmap_read(priv->regmap, TIM_SMCR, &val); | |
| 665 | − mode = (val & TIM_SMCR_SMS) - 1; | |
| 666 | − if ((mode >= 0) || (mode < ARRAY_SIZE(stm32_quadrature_modes))) | |
| 667 | − return -EBUSY; | |
| 668 | − | |
| 669 | − return regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_DIR, | |
| 670 | − dir ? TIM_CR1_DIR : 0); | |
| 671 | −} | |
| 672 | − | |
| 673 | −static int stm32_get_count_direction(struct iio_dev *indio_dev, | |
| 674 | − const struct iio_chan_spec *chan) | |
| 675 | −{ | |
| 676 | − struct stm32_timer_trigger *priv = iio_priv(indio_dev); | |
| 677 | − u32 cr1; | |
| 678 | − | |
| 679 | − regmap_read(priv->regmap, TIM_CR1, &cr1); | |
| 680 | − | |
| 681 | − return ((cr1 & TIM_CR1_DIR) ? 1 : 0); | |
| 682 | −} | |
| 683 | − | |
| 684 | −static const struct iio_enum stm32_count_direction_enum = { | |
| 685 | − .items = stm32_count_direction_states, | |
| 686 | − .num_items = ARRAY_SIZE(stm32_count_direction_states), | |
| 687 | − .set = stm32_set_count_direction, | |
| 688 | − .get = stm32_get_count_direction | |
| 689 | −}; | |
| 690 | − | |
| 691 | 611 | static ssize_t stm32_count_get_preset(struct iio_dev *indio_dev, |
| 692 | 612 | uintptr_t private, |
| 693 | 613 | const struct iio_chan_spec *chan, |
| @@ -728,10 +648,6 @@ static const struct iio_chan_spec_ext_info stm32_trigger_count_info[] = { · 34 unmodified lines | ||
| 728 | 648 | .read = stm32_count_get_preset, |
| 729 | 649 | .write = stm32_count_set_preset |
| 730 | 650 | }, |
| 731 | − IIO_ENUM("count_direction", IIO_SEPARATE, &stm32_count_direction_enum), | |
| 732 | − IIO_ENUM_AVAILABLE("count_direction", &stm32_count_direction_enum), | |
| 733 | − IIO_ENUM("quadrature_mode", IIO_SEPARATE, &stm32_quadrature_mode_enum), | |
| 734 | − IIO_ENUM_AVAILABLE("quadrature_mode", &stm32_quadrature_mode_enum), | |
| 735 | 651 | IIO_ENUM("enable_mode", IIO_SEPARATE, &stm32_enable_mode_enum), |
| 736 | 652 | IIO_ENUM_AVAILABLE("enable_mode", &stm32_enable_mode_enum), |
| 737 | 653 | IIO_ENUM("trigger_mode", IIO_SEPARATE, &stm32_trigger_mode_enum), |
| @@ -809,11 +809,23 @@ static const struct spi_device_id ad7192_id[] = { · 808 unmodified lines | ||
| 809 | 809 | {"ad7195", ID_AD7195}, |
| 810 | 810 | {} |
| 811 | 811 | }; |
| 812 | + | |
| 812 | 813 | MODULE_DEVICE_TABLE(spi, ad7192_id); |
| 813 | 814 | |
| 815 | +static const struct of_device_id ad7192_of_match[] = { | |
| 816 | + { .compatible = "adi,ad7190" }, | |
| 817 | + { .compatible = "adi,ad7192" }, | |
| 818 | + { .compatible = "adi,ad7193" }, | |
| 819 | + { .compatible = "adi,ad7195" }, | |
| 820 | + {} | |
| 821 | +}; | |
| 822 | + | |
| 823 | +MODULE_DEVICE_TABLE(of, ad7192_of_match); | |
| 824 | + | |
| 814 | 825 | static struct spi_driver ad7192_driver = { |
| 815 | 826 | .driver = { |
| 816 | 827 | .name = "ad7192", |
| 828 | + .of_match_table = ad7192_of_match, | |
| 817 | 829 | }, |
| 818 | 830 | .probe = ad7192_probe, |
| 819 | 831 | .remove = ad7192_remove, |
| @@ -671,7 +671,7 @@ static int ad2s1210_probe(struct spi_device *spi) · 670 unmodified lines | ||
| 671 | 671 | indio_dev->num_channels = ARRAY_SIZE(ad2s1210_channels); |
| 672 | 672 | indio_dev->name = spi_get_device_id(spi)->name; |
| 673 | 673 | |
| 674 | − ret = iio_device_register(indio_dev); | |
| 674 | + ret = devm_iio_device_register(&spi->dev, indio_dev); | |
| 675 | 675 | if (ret) |
| 676 | 676 | return ret; |
| 677 | 677 | |
| @@ -683,15 +683,6 @@ static int ad2s1210_probe(struct spi_device *spi) · 5 unmodified lines | ||
| 683 | 683 | return 0; |
| 684 | 684 | } |
| 685 | 685 | |
| 686 | −static int ad2s1210_remove(struct spi_device *spi) | |
| 687 | −{ | |
| 688 | − struct iio_dev *indio_dev = spi_get_drvdata(spi); | |
| 689 | − | |
| 690 | − iio_device_unregister(indio_dev); | |
| 691 | − | |
| 692 | − return 0; | |
| 693 | −} | |
| 694 | − | |
| 695 | 686 | static const struct of_device_id ad2s1210_of_match[] = { |
| 696 | 687 | { .compatible = "adi,ad2s1210", }, |
| 697 | 688 | { } |
| @@ -710,7 +701,6 @@ static struct spi_driver ad2s1210_driver = { · 12 unmodified lines | ||
| 710 | 701 | .of_match_table = of_match_ptr(ad2s1210_of_match), |
| 711 | 702 | }, |
| 712 | 703 | .probe = ad2s1210_probe, |
| 713 | − .remove = ad2s1210_remove, | |
| 714 | 704 | .id_table = ad2s1210_id, |
| 715 | 705 | }; |
| 716 | 706 | module_spi_driver(ad2s1210_driver); |
| @@ -188,6 +188,10 @@ static inline struct i3c_driver *drv_to_i3cdrv(struct device_driver *drv) · 187 unmodified lines | ||
| 188 | 188 | struct device *i3cdev_to_dev(struct i3c_device *i3cdev); |
| 189 | 189 | struct i3c_device *dev_to_i3cdev(struct device *dev); |
| 190 | 190 | |
| 191 | +const struct i3c_device_id * | |
| 192 | +i3c_device_match_id(struct i3c_device *i3cdev, | |
| 193 | + const struct i3c_device_id *id_table); | |
| 194 | + | |
| 191 | 195 | static inline void i3cdev_set_drvdata(struct i3c_device *i3cdev, |
| 192 | 196 | void *data) |
| 193 | 197 | { |
| @@ -62,14 +62,20 @@ struct cros_ec_sensors_core_state { · 61 unmodified lines | ||
| 62 | 62 | enum motionsensor_type type; |
| 63 | 63 | enum motionsensor_location loc; |
| 64 | 64 | |
| 65 | − s16 calib[CROS_EC_SENSOR_MAX_AXIS]; | |
| 66 | − | |
| 65 | + struct calib_data { | |
| 66 | + s16 offset; | |
| 67 | + u16 scale; | |
| 68 | + } calib[CROS_EC_SENSOR_MAX_AXIS]; | |
| 69 | + s8 sign[CROS_EC_SENSOR_MAX_AXIS]; | |
| 67 | 70 | u8 samples[CROS_EC_SAMPLE_SIZE]; |
| 68 | 71 | |
| 69 | 72 | int (*read_ec_sensors_data)(struct iio_dev *indio_dev, |
| 70 | 73 | unsigned long scan_mask, s16 *data); |
| 71 | 74 | |
| 72 | 75 | int curr_sampl_freq; |
| 76 | + | |
| 77 | + /* Table of known available frequencies : 0, Min and Max in mHz */ | |
| 78 | + int frequencies[3]; | |
| 73 | 79 | }; |
| 74 | 80 | |
| 75 | 81 | /** |
| @@ -150,6 +156,24 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, · 74 unmodified lines | ||
| 150 | 156 | struct iio_chan_spec const *chan, |
| 151 | 157 | int *val, int *val2, long mask); |
| 152 | 158 | |
| 159 | +/** | |
| 160 | + * cros_ec_sensors_core_read_avail() - get available values | |
| 161 | + * @indio_dev: pointer to state information for device | |
| 162 | + * @chan: channel specification structure table | |
| 163 | + * @vals: list of available values | |
| 164 | + * @type: type of data returned | |
| 165 | + * @length: number of data returned in the array | |
| 166 | + * @mask: specifies which values to be requested | |
| 167 | + * | |
| 168 | + * Return: an error code, IIO_AVAIL_RANGE or IIO_AVAIL_LIST | |
| 169 | + */ | |
| 170 | +int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev, | |
| 171 | + struct iio_chan_spec const *chan, | |
| 172 | + const int **vals, | |
| 173 | + int *type, | |
| 174 | + int *length, | |
| 175 | + long mask); | |
| 176 | + | |
| 153 | 177 | /** |
| 154 | 178 | * cros_ec_sensors_core_write() - function to write a value to the sensor |
| 155 | 179 | * @st: pointer to state information for device |
| @@ -16,11 +16,16 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/iio/trigger.h> |
| 17 | 17 | #include <linux/bitops.h> |
| 18 | 18 | #include <linux/regulator/consumer.h> |
| 19 | +#include <linux/regmap.h> | |
| 19 | 20 | |
| 20 | 21 | #include <linux/platform_data/st_sensors_pdata.h> |
| 21 | 22 | |
| 22 | −#define ST_SENSORS_TX_MAX_LENGTH 2 | |
| 23 | −#define ST_SENSORS_RX_MAX_LENGTH 6 | |
| 23 | +/* | |
| 24 | + * Buffer size max case: 2bytes per channel, 3 channels in total + | |
| 25 | + * 8bytes timestamp channel (s64) | |
| 26 | + */ | |
| 27 | +#define ST_SENSORS_MAX_BUFFER_SIZE (ALIGN(2 * 3, sizeof(s64)) + \ | |
| 28 | + sizeof(s64)) | |
| 24 | 29 | |
| 25 | 30 | #define ST_SENSORS_ODR_LIST_MAX 10 |
| 26 | 31 | #define ST_SENSORS_FULLSCALE_AVL_MAX 10 |
| @@ -169,36 +174,6 @@ struct st_sensor_data_ready_irq { · 142 unmodified lines | ||
| 169 | 174 | } ig1; |
| 170 | 175 | }; |
| 171 | 176 | |
| 172 | −/** | |
| 173 | − * struct st_sensor_transfer_buffer - ST sensor device I/O buffer | |
| 174 | − * @buf_lock: Mutex to protect rx and tx buffers. | |
| 175 | − * @tx_buf: Buffer used by SPI transfer function to send data to the sensors. | |
| 176 | − * This buffer is used to avoid DMA not-aligned issue. | |
| 177 | − * @rx_buf: Buffer used by SPI transfer to receive data from sensors. | |
| 178 | − * This buffer is used to avoid DMA not-aligned issue. | |
| 179 | − */ | |
| 180 | −struct st_sensor_transfer_buffer { | |
| 181 | − struct mutex buf_lock; | |
| 182 | − u8 rx_buf[ST_SENSORS_RX_MAX_LENGTH]; | |
| 183 | − u8 tx_buf[ST_SENSORS_TX_MAX_LENGTH] ____cacheline_aligned; | |
| 184 | −}; | |
| 185 | − | |
| 186 | −/** | |
| 187 | − * struct st_sensor_transfer_function - ST sensor device I/O function | |
| 188 | − * @read_byte: Function used to read one byte. | |
| 189 | − * @write_byte: Function used to write one byte. | |
| 190 | − * @read_multiple_byte: Function used to read multiple byte. | |
| 191 | − */ | |
| 192 | −struct st_sensor_transfer_function { | |
| 193 | − int (*read_byte) (struct st_sensor_transfer_buffer *tb, | |
| 194 | − struct device *dev, u8 reg_addr, u8 *res_byte); | |
| 195 | − int (*write_byte) (struct st_sensor_transfer_buffer *tb, | |
| 196 | − struct device *dev, u8 reg_addr, u8 data); | |
| 197 | − int (*read_multiple_byte) (struct st_sensor_transfer_buffer *tb, | |
| 198 | − struct device *dev, u8 reg_addr, int len, u8 *data, | |
| 199 | − bool multiread_bit); | |
| 200 | −}; | |
| 201 | − | |
| 202 | 177 | /** |
| 203 | 178 | * struct st_sensor_settings - ST specific sensor settings |
| 204 | 179 | * @wai: Contents of WhoAmI register. |
| @@ -242,19 +217,17 @@ struct st_sensor_settings { · 37 unmodified lines | ||
| 242 | 217 | * @current_fullscale: Maximum range of measure by the sensor. |
| 243 | 218 | * @vdd: Pointer to sensor's Vdd power supply |
| 244 | 219 | * @vdd_io: Pointer to sensor's Vdd-IO power supply |
| 220 | + * @regmap: Pointer to specific sensor regmap configuration. | |
| 245 | 221 | * @enabled: Status of the sensor (false->off, true->on). |
| 246 | − * @multiread_bit: Use or not particular bit for [I2C/SPI] multiread. | |
| 247 | − * @buffer_data: Data used by buffer part. | |
| 248 | 222 | * @odr: Output data rate of the sensor [Hz]. |
| 249 | 223 | * num_data_channels: Number of data channels used in buffer. |
| 250 | 224 | * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2). |
| 251 | 225 | * @int_pin_open_drain: Set the interrupt/DRDY to open drain. |
| 252 | − * @get_irq_data_ready: Function to get the IRQ used for data ready signal. | |
| 253 | − * @tf: Transfer function structure used by I/O operations. | |
| 254 | − * @tb: Transfer buffers and mutex used by I/O operations. | |
| 226 | + * @irq: the IRQ number. | |
| 255 | 227 | * @edge_irq: the IRQ triggers on edges and need special handling. |
| 256 | 228 | * @hw_irq_trigger: if we're using the hardware interrupt on the sensor. |
| 257 | 229 | * @hw_timestamp: Latest timestamp from the interrupt handler, when in use. |
| 230 | + * @buffer_data: Data used by buffer part. | |
| 258 | 231 | */ |
| 259 | 232 | struct st_sensor_data { |
| 260 | 233 | struct device *dev; |
| @@ -264,26 +237,22 @@ struct st_sensor_data { · 3 unmodified lines | ||
| 264 | 237 | struct st_sensor_fullscale_avl *current_fullscale; |
| 265 | 238 | struct regulator *vdd; |
| 266 | 239 | struct regulator *vdd_io; |
| 240 | + struct regmap *regmap; | |
| 267 | 241 | |
| 268 | 242 | bool enabled; |
| 269 | − bool multiread_bit; | |
| 270 | − | |
| 271 | − char *buffer_data; | |
| 272 | 243 | |
| 273 | 244 | unsigned int odr; |
| 274 | 245 | unsigned int num_data_channels; |
| 275 | 246 | |
| 276 | 247 | u8 drdy_int_pin; |
| 277 | 248 | bool int_pin_open_drain; |
| 278 | − | |
| 279 | − unsigned int (*get_irq_data_ready) (struct iio_dev *indio_dev); | |
| 280 | − | |
| 281 | − const struct st_sensor_transfer_function *tf; | |
| 282 | − struct st_sensor_transfer_buffer tb; | |
| 249 | + int irq; | |
| 283 | 250 | |
| 284 | 251 | bool edge_irq; |
| 285 | 252 | bool hw_irq_trigger; |
| 286 | 253 | s64 hw_timestamp; |
| 254 | + | |
| 255 | + char buffer_data[ST_SENSORS_MAX_BUFFER_SIZE] ____cacheline_aligned; | |
| 287 | 256 | }; |
| 288 | 257 | |
| 289 | 258 | #ifdef CONFIG_IIO_BUFFER |
| @@ -334,8 +303,11 @@ int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale); · 44 unmodified lines | ||
| 334 | 303 | int st_sensors_read_info_raw(struct iio_dev *indio_dev, |
| 335 | 304 | struct iio_chan_spec const *ch, int *val); |
| 336 | 305 | |
| 337 | −int st_sensors_check_device_support(struct iio_dev *indio_dev, | |
| 338 | − int num_sensors_list, const struct st_sensor_settings *sensor_settings); | |
| 306 | +int st_sensors_get_settings_index(const char *name, | |
| 307 | + const struct st_sensor_settings *list, | |
| 308 | + const int list_length); | |
| 309 | + | |
| 310 | +int st_sensors_verify_id(struct iio_dev *indio_dev); | |
| 339 | 311 | |
| 340 | 312 | ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, |
| 341 | 313 | struct device_attribute *attr, char *buf); |
| @@ -14,8 +14,8 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/iio/common/st_sensors.h> |
| 15 | 15 | #include <linux/of.h> |
| 16 | 16 | |
| 17 | −void st_sensors_i2c_configure(struct iio_dev *indio_dev, | |
| 18 | − struct i2c_client *client, struct st_sensor_data *sdata); | |
| 17 | +int st_sensors_i2c_configure(struct iio_dev *indio_dev, | |
| 18 | + struct i2c_client *client); | |
| 19 | 19 | |
| 20 | 20 | #ifdef CONFIG_ACPI |
| 21 | 21 | int st_sensors_match_acpi_device(struct device *dev); |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/spi/spi.h> |
| 14 | 14 | #include <linux/iio/common/st_sensors.h> |
| 15 | 15 | |
| 16 | −void st_sensors_spi_configure(struct iio_dev *indio_dev, | |
| 17 | − struct spi_device *spi, struct st_sensor_data *sdata); | |
| 16 | +int st_sensors_spi_configure(struct iio_dev *indio_dev, | |
| 17 | + struct spi_device *spi); | |
| 18 | 18 | |
| 19 | 19 | #endif /* ST_SENSORS_SPI_H */ |
| @@ -26,6 +26,7 @@ struct adis_burst; · 25 unmodified lines | ||
| 26 | 26 | * struct adis_data - ADIS chip variant specific data |
| 27 | 27 | * @read_delay: SPI delay for read operations in us |
| 28 | 28 | * @write_delay: SPI delay for write operations in us |
| 29 | + * @cs_change_delay: SPI delay between CS changes in us | |
| 29 | 30 | * @glob_cmd_reg: Register address of the GLOB_CMD register |
| 30 | 31 | * @msc_ctrl_reg: Register address of the MSC_CTRL register |
| 31 | 32 | * @diag_stat_reg: Register address of the DIAG_STAT register |
| @@ -35,6 +36,7 @@ struct adis_burst; · 3 unmodified lines | ||
| 35 | 36 | struct adis_data { |
| 36 | 37 | unsigned int read_delay; |
| 37 | 38 | unsigned int write_delay; |
| 39 | + unsigned int cs_change_delay; | |
| 38 | 40 | |
| 39 | 41 | unsigned int glob_cmd_reg; |
| 40 | 42 | unsigned int msc_ctrl_reg; |