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 | error on writing | 13 | error on writing |
| 14 | If DFSDM input is SPI Slave: | 14 | If DFSDM input is SPI Slave: |
| 15 | Reading returns value previously set. | 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 | When counting down the counter start from preset value | 91 | When counting down the counter start from preset value |
| 92 | and fire event when reach 0. | 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 | What: /sys/bus/iio/devices/iio:deviceX/in_count_enable_mode_available | 94 | What: /sys/bus/iio/devices/iio:deviceX/in_count_enable_mode_available |
| 118 | KernelVersion: 4.12 | 95 | KernelVersion: 4.12 |
| 119 | Contact: benjamin.gaignard@st.com | 96 | Contact: benjamin.gaignard@st.com |
| @@ -47,6 +47,12 @@ Required properties: · 46 unmodified lines | |||
| 47 | Optional properties: | 47 | Optional properties: |
| 48 | - A pinctrl state named "default" for each ADC channel may be defined to set | 48 | - A pinctrl state named "default" for each ADC channel may be defined to set |
| 49 | inX ADC pins in mode of operation for analog input on external pin. | 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 | Contents of a stm32 adc child node: | 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 | "st,asm330lhh" | 11 | "st,asm330lhh" |
| 12 | "st,lsm6dsox" | 12 | "st,lsm6dsox" |
| 13 | "st,lsm6dsr" | 13 | "st,lsm6dsr" |
| 14 | "st,lsm6ds3tr-c" | ||
| 15 | "st,ism330dhcx" | ||
| 14 | - reg: i2c address of the sensor / spi cs line | 16 | - reg: i2c address of the sensor / spi cs line |
| 15 | 17 | ||
| 16 | Optional properties: | 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 | description: Semtech Corporation | 813 | description: Semtech Corporation |
| 814 | "^sensirion,.*": | 814 | "^sensirion,.*": |
| 815 | description: Sensirion AG | 815 | description: Sensirion AG |
| 816 | "^sensortek,.*": | ||
| 817 | description: Sensortek Technology Corporation | ||
| 816 | "^sff,.*": | 818 | "^sff,.*": |
| 817 | description: Small Form Factor Committee | 819 | description: Small Form Factor Committee |
| 818 | "^sgd,.*": | 820 | "^sgd,.*": |
| @@ -945,6 +945,14 @@ L: linux-iio@vger.kernel.org · 944 unmodified lines | |||
| 945 | F: include/linux/iio/imu/adis.h | 945 | F: include/linux/iio/imu/adis.h |
| 946 | F: drivers/iio/imu/adis.c | 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 | ANALOG DEVICES INC ADP5061 DRIVER | 956 | ANALOG DEVICES INC ADP5061 DRIVER |
| 949 | M: Stefan Popa <stefan.popa@analog.com> | 957 | M: Stefan Popa <stefan.popa@analog.com> |
| 950 | L: linux-pm@vger.kernel.org | 958 | L: linux-pm@vger.kernel.org |
| @@ -12776,6 +12784,12 @@ F: drivers/i2c/busses/i2c-puv3.c · 11825 unmodified lines | |||
| 12776 | F: drivers/video/fbdev/fb-puv3.c | 12784 | F: drivers/video/fbdev/fb-puv3.c |
| 12777 | F: drivers/rtc/rtc-puv3.c | 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 | PMBUS HARDWARE MONITORING DRIVERS | 12793 | PMBUS HARDWARE MONITORING DRIVERS |
| 12780 | M: Guenter Roeck <linux@roeck-us.net> | 12794 | M: Guenter Roeck <linux@roeck-us.net> |
| 12781 | L: linux-hwmon@vger.kernel.org | 12795 | L: linux-hwmon@vger.kernel.org |
| @@ -100,16 +100,18 @@ static void ftm_quaddec_init(struct ftm_quaddec *ftm) · 99 unmodified lines | |||
| 100 | ftm_set_write_protection(ftm); | 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); | 105 | struct ftm_quaddec *ftm_qua = ftm; |
| 106 | ftm_write(ftm, FTM_MODE, 0); | 106 | |
| 107 | ftm_write(ftm, FTM_QDCTRL, 0); | 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 | * This is enough to disable the counter. No clock has been | 111 | * This is enough to disable the counter. No clock has been |
| 110 | * selected by writing to FTM_SC in init() | 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 | static int ftm_quaddec_get_prescaler(struct counter_device *counter, | 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 | ftm_quaddec_init(ftm); | 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 | if (ret) | 323 | if (ret) |
| 322 | ftm_quaddec_disable(ftm); | 324 | return ret; |
| 323 | |||
| 324 | return ret; | ||
| 325 | } | ||
| 326 | 325 | ||
| 327 | static int ftm_quaddec_remove(struct platform_device *pdev) | 326 | ret = devm_counter_register(&pdev->dev, &ftm->counter); |
| 328 | { | 327 | if (ret) |
| 329 | struct ftm_quaddec *ftm = platform_get_drvdata(pdev); | 328 | return ret; |
| 330 | |||
| 331 | counter_unregister(&ftm->counter); | ||
| 332 | |||
| 333 | ftm_quaddec_disable(ftm); | ||
| 334 | 329 | ||
| 335 | return 0; | 330 | return 0; |
| 336 | } | 331 | } |
| @@ -346,7 +341,6 @@ static struct platform_driver ftm_quaddec_driver = { · 9 unmodified lines | |||
| 346 | .of_match_table = ftm_quaddec_match, | 341 | .of_match_table = ftm_quaddec_match, |
| 347 | }, | 342 | }, |
| 348 | .probe = ftm_quaddec_probe, | 343 | .probe = ftm_quaddec_probe, |
| 349 | .remove = ftm_quaddec_remove, | ||
| 350 | }; | 344 | }; |
| 351 | 345 | ||
| 352 | module_platform_driver(ftm_quaddec_driver); | 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 | EXPORT_SYMBOL_GPL(dev_to_i3cdev); | 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 | * i3c_driver_register_with_owner() - register an I3C device driver | 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 | .uevent = i3c_device_uevent, | 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 | static int i3c_device_match(struct device *dev, struct device_driver *drv) | 279 | static int i3c_device_match(struct device *dev, struct device_driver *drv) |
| 325 | { | 280 | { |
| 326 | struct i3c_device *i3cdev; | 281 | struct i3c_device *i3cdev; |
| @@ -202,9 +202,7 @@ config HID_SENSOR_ACCEL_3D · 201 unmodified lines | |||
| 202 | 202 | ||
| 203 | config IIO_CROS_EC_ACCEL_LEGACY | 203 | config IIO_CROS_EC_ACCEL_LEGACY |
| 204 | tristate "ChromeOS EC Legacy Accelerometer Sensor" | 204 | tristate "ChromeOS EC Legacy Accelerometer Sensor" |
| 205 | select IIO_BUFFER | 205 | depends on IIO_CROS_EC_SENSORS_CORE |
| 206 | select IIO_TRIGGERED_BUFFER | ||
| 207 | select CROS_EC_LPC_REGISTER_DEVICE | ||
| 208 | help | 206 | help |
| 209 | Say yes here to get support for accelerometers on Chromebook using | 207 | Say yes here to get support for accelerometers on Chromebook using |
| 210 | legacy EC firmware. | 208 | legacy EC firmware. |
| @@ -5,13 +5,14 @@ · 4 unmodified lines | |||
| 5 | * Copyright 2017 Google, Inc | 5 | * Copyright 2017 Google, Inc |
| 6 | * | 6 | * |
| 7 | * This driver uses the memory mapper cros-ec interface to communicate | 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 | * Accelerometer access is presented through iio sysfs. | 9 | * Accelerometer access is presented through iio sysfs. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
| 13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
| 14 | #include <linux/iio/buffer.h> | 14 | #include <linux/iio/buffer.h> |
| 15 | #include <linux/iio/common/cros_ec_sensors_core.h> | ||
| 15 | #include <linux/iio/iio.h> | 16 | #include <linux/iio/iio.h> |
| 16 | #include <linux/iio/kfifo_buf.h> | 17 | #include <linux/iio/kfifo_buf.h> |
| 17 | #include <linux/iio/trigger_consumer.h> | 18 | #include <linux/iio/trigger_consumer.h> |
| @@ -25,160 +26,41 @@ · 7 unmodified lines | |||
| 25 | 26 | ||
| 26 | #define DRV_NAME "cros-ec-accel-legacy" | 27 | #define DRV_NAME "cros-ec-accel-legacy" |
| 27 | 28 | ||
| 29 | #define CROS_EC_SENSOR_LEGACY_NUM 2 | ||
| 28 | /* | 30 | /* |
| 29 | * Sensor scale hard coded at 10 bits per g, computed as: | 31 | * Sensor scale hard coded at 10 bits per g, computed as: |
| 30 | * g / (2^10 - 1) = 0.009586168; with g = 9.80665 m.s^-2 | 32 | * g / (2^10 - 1) = 0.009586168; with g = 9.80665 m.s^-2 |
| 31 | */ | 33 | */ |
| 32 | #define ACCEL_LEGACY_NSCALE 9586168 | 34 | #define ACCEL_LEGACY_NSCALE 9586168 |
| 33 | 35 | ||
| 34 | /* Indices for EC sensor values. */ | 36 | static int cros_ec_accel_legacy_read_cmd(struct iio_dev *indio_dev, |
| 35 | enum { | 37 | unsigned long scan_mask, s16 *data) |
| 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) | ||
| 147 | { | 38 | { |
| 148 | u8 samp_id = 0xff; | 39 | struct cros_ec_sensors_core_state *st = iio_priv(indio_dev); |
| 149 | u8 status = 0; | ||
| 150 | int ret; | 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 | 45 | * Read all sensor data through a command. |
| 155 | * all reads reflects that the EC is not busy and the sample id | 46 | * Save sensor_num, it is assumed to stay. |
| 156 | * matches the sample id from before all reads. This guarantees | ||
| 157 | * that data read in was not modified by the EC while reading. | ||
| 158 | */ | 47 | */ |
| 159 | while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT | | 48 | sensor_num = st->param.info.sensor_num; |
| 160 | EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) { | 49 | st->param.cmd = MOTIONSENSE_CMD_DUMP; |
| 161 | /* If we have tried to read too many times, return error. */ | 50 | st->param.dump.max_sensor_count = CROS_EC_SENSOR_LEGACY_NUM; |
| 162 | if (attempts++ >= 5) | 51 | ret = cros_ec_motion_send_host_cmd(st, |
| 163 | return -EIO; | 52 | sizeof(st->resp->dump) + CROS_EC_SENSOR_LEGACY_NUM * |
| 164 | 53 | sizeof(struct ec_response_motion_sensor_data)); | |
| 165 | /* Read status byte until EC is not busy. */ | 54 | st->param.info.sensor_num = sensor_num; |
| 166 | ret = read_ec_until_not_busy(st); | 55 | if (ret != 0) { |
| 167 | if (ret < 0) | 56 | dev_warn(&indio_dev->dev, "Unable to read sensor data\n"); |
| 168 | return ret; | 57 | return ret; |
| 169 | status = ret; | 58 | } |
| 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); | ||
| 179 | 59 | ||
| 180 | /* Read status byte. */ | 60 | for_each_set_bit(i, &scan_mask, indio_dev->masklength) { |
| 181 | ec_cmd_read_u8(st->ec, EC_MEMMAP_ACC_STATUS, &status); | 61 | *data = st->resp->dump.sensor[sensor_num].data[i] * |
| 62 | st->sign[i]; | ||
| 63 | data++; | ||
| 182 | } | 64 | } |
| 183 | 65 | ||
| 184 | return 0; | 66 | return 0; |
| @@ -188,28 +70,40 @@ static int cros_ec_accel_legacy_read(struct iio_dev *indio_dev, · 3 unmodified lines | |||
| 188 | struct iio_chan_spec const *chan, | 70 | struct iio_chan_spec const *chan, |
| 189 | int *val, int *val2, long mask) | 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 | s16 data = 0; | 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 | switch (mask) { | 80 | switch (mask) { |
| 196 | case IIO_CHAN_INFO_RAW: | 81 | case IIO_CHAN_INFO_RAW: |
| 197 | ret = read_ec_accel_data(st, (1 << chan->scan_index), &data); | 82 | ret = st->read_ec_sensors_data(indio_dev, 1 << idx, &data); |
| 198 | if (ret) | 83 | if (ret < 0) |
| 199 | return ret; | 84 | break; |
| 85 | ret = IIO_VAL_INT; | ||
| 200 | *val = data; | 86 | *val = data; |
| 201 | return IIO_VAL_INT; | 87 | break; |
| 202 | case IIO_CHAN_INFO_SCALE: | 88 | case IIO_CHAN_INFO_SCALE: |
| 89 | WARN_ON(st->type != MOTIONSENSE_TYPE_ACCEL); | ||
| 203 | *val = 0; | 90 | *val = 0; |
| 204 | *val2 = ACCEL_LEGACY_NSCALE; | 91 | *val2 = ACCEL_LEGACY_NSCALE; |
| 205 | return IIO_VAL_INT_PLUS_NANO; | 92 | ret = IIO_VAL_INT_PLUS_NANO; |
| 93 | break; | ||
| 206 | case IIO_CHAN_INFO_CALIBBIAS: | 94 | case IIO_CHAN_INFO_CALIBBIAS: |
| 207 | /* Calibration not supported. */ | 95 | /* Calibration not supported. */ |
| 208 | *val = 0; | 96 | *val = 0; |
| 209 | return IIO_VAL_INT; | 97 | ret = IIO_VAL_INT; |
| 98 | break; | ||
| 210 | default: | 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 | static int cros_ec_accel_legacy_write(struct iio_dev *indio_dev, | 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 | .write_raw = &cros_ec_accel_legacy_write, | 125 | .write_raw = &cros_ec_accel_legacy_write, |
| 232 | }; | 126 | }; |
| 233 | 127 | ||
| 234 | /** | 128 | /* |
| 235 | * cros_ec_accel_legacy_capture() - The trigger handler function | 129 | * Present the channel using HTML5 standard: |
| 236 | * @irq: The interrupt number. | 130 | * need to invert X and Y and invert some lid axis. |
| 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 | ||
| 245 | */ | 131 | */ |
| 246 | static irqreturn_t cros_ec_accel_legacy_capture(int irq, void *p) | 132 | #define CROS_EC_ACCEL_ROTATE_AXIS(_axis) \ |
| 247 | { | 133 | ((_axis) == CROS_EC_SENSOR_Z ? CROS_EC_SENSOR_Z : \ |
| 248 | struct iio_poll_func *pf = p; | 134 | ((_axis) == CROS_EC_SENSOR_X ? CROS_EC_SENSOR_Y : \ |
| 249 | struct iio_dev *indio_dev = pf->indio_dev; | 135 | CROS_EC_SENSOR_X)) |
| 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 | }; | ||
| 314 | 136 | ||
| 315 | #define CROS_EC_ACCEL_LEGACY_CHAN(_axis) \ | 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 | BIT(IIO_CHAN_INFO_RAW) | \ | 143 | BIT(IIO_CHAN_INFO_RAW) | \ |
| 322 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ | 144 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ |
| 323 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \ | 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 | .scan_type = { \ | 147 | .scan_type = { \ |
| 326 | .sign = 's', \ | 148 | .sign = 's', \ |
| 327 | .realbits = 16, \ | 149 | .realbits = CROS_EC_SENSOR_BITS, \ |
| 328 | .storagebits = 16, \ | 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[] = { | 155 | static const struct iio_chan_spec cros_ec_accel_legacy_channels[] = { |
| 333 | CROS_EC_ACCEL_LEGACY_CHAN(X), | 156 | CROS_EC_ACCEL_LEGACY_CHAN(CROS_EC_SENSOR_X), |
| 334 | CROS_EC_ACCEL_LEGACY_CHAN(Y), | 157 | CROS_EC_ACCEL_LEGACY_CHAN(CROS_EC_SENSOR_Y), |
| 335 | CROS_EC_ACCEL_LEGACY_CHAN(Z), | 158 | CROS_EC_ACCEL_LEGACY_CHAN(CROS_EC_SENSOR_Z), |
| 336 | IIO_CHAN_SOFT_TIMESTAMP(MAX_AXIS) | 159 | IIO_CHAN_SOFT_TIMESTAMP(CROS_EC_SENSOR_MAX_AXIS) |
| 337 | }; | 160 | }; |
| 338 | 161 | ||
| 339 | static int cros_ec_accel_legacy_probe(struct platform_device *pdev) | 162 | static int cros_ec_accel_legacy_probe(struct platform_device *pdev) |
| 340 | { | 163 | { |
| 341 | struct device *dev = &pdev->dev; | 164 | struct device *dev = &pdev->dev; |
| 342 | struct cros_ec_dev *ec = dev_get_drvdata(dev->parent); | 165 | struct cros_ec_dev *ec = dev_get_drvdata(dev->parent); |
| 343 | struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); | ||
| 344 | struct iio_dev *indio_dev; | 166 | struct iio_dev *indio_dev; |
| 345 | struct cros_ec_accel_legacy_state *state; | 167 | struct cros_ec_sensors_core_state *state; |
| 346 | int ret; | 168 | int ret; |
| 347 | 169 | ||
| 348 | if (!ec || !ec->ec_dev) { | 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 | return -EINVAL; | 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 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state)); | 175 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state)); |
| 359 | if (!indio_dev) | 176 | if (!indio_dev) |
| 360 | return -ENOMEM; | 177 | return -ENOMEM; |
| 361 | 178 | ||
| 362 | platform_set_drvdata(pdev, indio_dev); | 179 | ret = cros_ec_sensors_core_init(pdev, indio_dev, true); |
| 363 | state = iio_priv(indio_dev); | 180 | if (ret) |
| 364 | state->ec = ec->ec_dev; | 181 | return ret; |
| 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; | ||
| 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) | 186 | if (state->ec->cmd_readmem != NULL) |
| 381 | state->sign[X] = state->sign[Z] = -1; | 187 | state->read_ec_sensors_data = cros_ec_sensors_read_lpc; |
| 382 | else | 188 | else |
| 383 | state->sign[X] = state->sign[Z] = 1; | 189 | state->read_ec_sensors_data = cros_ec_accel_legacy_read_cmd; |
| 384 | 190 | ||
| 385 | indio_dev->num_channels = ARRAY_SIZE(ec_accel_channels); | 191 | indio_dev->channels = cros_ec_accel_legacy_channels; |
| 386 | indio_dev->dev.parent = &pdev->dev; | 192 | indio_dev->num_channels = ARRAY_SIZE(cros_ec_accel_legacy_channels); |
| 387 | indio_dev->info = &cros_ec_accel_legacy_info; | 193 | /* The lid sensor needs to be presented inverted. */ |
| 388 | indio_dev->modes = INDIO_DIRECT_MODE; | 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 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, | 199 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, |
| 391 | cros_ec_accel_legacy_capture, | 200 | cros_ec_sensors_capture, NULL); |
| 392 | NULL); | ||
| 393 | if (ret) | 201 | if (ret) |
| 394 | return ret; | 202 | return ret; |
| 395 | 203 | ||
| @@ -424,7 +424,7 @@ static int mxc4005_probe(struct i2c_client *client, · 423 unmodified lines | |||
| 424 | indio_dev->modes = INDIO_DIRECT_MODE; | 424 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 425 | indio_dev->info = &mxc4005_info; | 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 | iio_pollfunc_store_time, | 428 | iio_pollfunc_store_time, |
| 429 | mxc4005_trigger_handler, | 429 | mxc4005_trigger_handler, |
| 430 | NULL); | 430 | NULL); |
| @@ -452,7 +452,7 @@ static int mxc4005_probe(struct i2c_client *client, · 21 unmodified lines | |||
| 452 | if (ret) { | 452 | if (ret) { |
| 453 | dev_err(&client->dev, | 453 | dev_err(&client->dev, |
| 454 | "failed to init threaded irq\n"); | 454 | "failed to init threaded irq\n"); |
| 455 | goto err_buffer_cleanup; | 455 | return ret; |
| 456 | } | 456 | } |
| 457 | 457 | ||
| 458 | data->dready_trig->dev.parent = &client->dev; | 458 | data->dready_trig->dev.parent = &client->dev; |
| @@ -460,43 +460,16 @@ static int mxc4005_probe(struct i2c_client *client, · 1 unmodified line | |||
| 460 | iio_trigger_set_drvdata(data->dready_trig, indio_dev); | 460 | iio_trigger_set_drvdata(data->dready_trig, indio_dev); |
| 461 | indio_dev->trig = data->dready_trig; | 461 | indio_dev->trig = data->dready_trig; |
| 462 | iio_trigger_get(indio_dev->trig); | 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 | if (ret) { | 465 | if (ret) { |
| 465 | dev_err(&client->dev, | 466 | dev_err(&client->dev, |
| 466 | "failed to register trigger\n"); | 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 | return devm_iio_device_register(&client->dev, 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; | ||
| 500 | } | 473 | } |
| 501 | 474 | ||
| 502 | static const struct acpi_device_id mxc4005_acpi_match[] = { | 475 | static const struct acpi_device_id mxc4005_acpi_match[] = { |
| @@ -517,7 +490,6 @@ static struct i2c_driver mxc4005_driver = { · 14 unmodified lines | |||
| 517 | .acpi_match_table = ACPI_PTR(mxc4005_acpi_match), | 490 | .acpi_match_table = ACPI_PTR(mxc4005_acpi_match), |
| 518 | }, | 491 | }, |
| 519 | .probe = mxc4005_probe, | 492 | .probe = mxc4005_probe, |
| 520 | .remove = mxc4005_remove, | ||
| 521 | .id_table = mxc4005_id, | 493 | .id_table = mxc4005_id, |
| 522 | }; | 494 | }; |
| 523 | 495 | ||
| @@ -111,7 +111,7 @@ · 110 unmodified lines | |||
| 111 | /* Currently unsupported */ | 111 | /* Currently unsupported */ |
| 112 | #define SCA3000_MD_CTRL_AND_Y BIT(3) | 112 | #define SCA3000_MD_CTRL_AND_Y BIT(3) |
| 113 | #define SCA3000_MD_CTRL_AND_X BIT(4) | 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 | * Some control registers of complex access methods requiring this register to | 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 | .drdy_int_pin = 1, | 68 | .drdy_int_pin = 1, |
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| 71 | const struct st_sensor_settings *st_accel_get_settings(const char *name); | ||
| 71 | int st_accel_common_probe(struct iio_dev *indio_dev); | 72 | int st_accel_common_probe(struct iio_dev *indio_dev); |
| 72 | void st_accel_common_remove(struct iio_dev *indio_dev); | 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 | return st_sensors_set_dataready_irq(indio_dev, state); | 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 | static int st_accel_buffer_postenable(struct iio_dev *indio_dev) | 32 | static int st_accel_buffer_postenable(struct iio_dev *indio_dev) |
| 38 | { | 33 | { |
| 39 | int err; | 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 | err = iio_triggered_buffer_postenable(indio_dev); | 36 | err = iio_triggered_buffer_postenable(indio_dev); |
| 49 | if (err < 0) | 37 | if (err < 0) |
| 50 | goto st_accel_buffer_postenable_error; | 38 | return err; |
| 51 | 39 | ||
| 52 | err = st_sensors_set_axis_enable(indio_dev, | 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 | if (err < 0) | 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 | iio_triggered_buffer_predisable(indio_dev); | 54 | iio_triggered_buffer_predisable(indio_dev); |
| 61 | st_accel_buffer_postenable_error: | ||
| 62 | kfree(adata->buffer_data); | ||
| 63 | allocate_memory_error: | ||
| 64 | return err; | 55 | return err; |
| 65 | } | 56 | } |
| 66 | 57 | ||
| 67 | static int st_accel_buffer_predisable(struct iio_dev *indio_dev) | 58 | static int st_accel_buffer_predisable(struct iio_dev *indio_dev) |
| 68 | { | 59 | { |
| 69 | int err, err2; | 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 | err = st_sensors_set_enable(indio_dev, false); | 62 | err = st_sensors_set_enable(indio_dev, false); |
| 77 | if (err < 0) | 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 | err2 = iio_triggered_buffer_predisable(indio_dev); | 69 | err2 = iio_triggered_buffer_predisable(indio_dev); |
| 82 | if (!err) | 70 | if (!err) |
| 83 | err = err2; | 71 | err = err2; |
| 84 | 72 | ||
| 85 | kfree(adata->buffer_data); | ||
| 86 | return err; | 73 | return err; |
| 87 | } | 74 | } |
| 88 | 75 | ||
| 89 | static const struct iio_buffer_setup_ops st_accel_buffer_setup_ops = { | 76 | static const struct iio_buffer_setup_ops st_accel_buffer_setup_ops = { |
| 90 | .preenable = &st_accel_buffer_preenable, | ||
| 91 | .postenable = &st_accel_buffer_postenable, | 77 | .postenable = &st_accel_buffer_postenable, |
| 92 | .predisable = &st_accel_buffer_predisable, | 78 | .predisable = &st_accel_buffer_predisable, |
| 93 | }; | 79 | }; |
| @@ -13,7 +13,6 @@ · 12 unmodified lines | |||
| 13 | #include <linux/acpi.h> | 13 | #include <linux/acpi.h> |
| 14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
| 15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
| 16 | #include <linux/mutex.h> | ||
| 17 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
| 18 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
| 19 | #include <linux/gpio.h> | 18 | #include <linux/gpio.h> |
| @@ -1147,32 +1146,45 @@ out: · 1127 unmodified lines | |||
| 1147 | #endif | 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 | int st_accel_common_probe(struct iio_dev *indio_dev) | 1167 | int st_accel_common_probe(struct iio_dev *indio_dev) |
| 1151 | { | 1168 | { |
| 1152 | struct st_sensor_data *adata = iio_priv(indio_dev); | 1169 | struct st_sensor_data *adata = iio_priv(indio_dev); |
| 1153 | struct st_sensors_platform_data *pdata = | 1170 | struct st_sensors_platform_data *pdata = |
| 1154 | (struct st_sensors_platform_data *)adata->dev->platform_data; | 1171 | (struct st_sensors_platform_data *)adata->dev->platform_data; |
| 1155 | int irq = adata->get_irq_data_ready(indio_dev); | ||
| 1156 | struct iio_chan_spec *channels; | 1172 | struct iio_chan_spec *channels; |
| 1157 | size_t channels_size; | 1173 | size_t channels_size; |
| 1158 | int err; | 1174 | int err; |
| 1159 | 1175 | ||
| 1160 | indio_dev->modes = INDIO_DIRECT_MODE; | 1176 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 1161 | indio_dev->info = &accel_info; | 1177 | indio_dev->info = &accel_info; |
| 1162 | mutex_init(&adata->tb.buf_lock); | ||
| 1163 | 1178 | ||
| 1164 | err = st_sensors_power_enable(indio_dev); | 1179 | err = st_sensors_power_enable(indio_dev); |
| 1165 | if (err) | 1180 | if (err) |
| 1166 | return err; | 1181 | return err; |
| 1167 | 1182 | ||
| 1168 | err = st_sensors_check_device_support(indio_dev, | 1183 | err = st_sensors_verify_id(indio_dev); |
| 1169 | ARRAY_SIZE(st_accel_sensors_settings), | ||
| 1170 | st_accel_sensors_settings); | ||
| 1171 | if (err < 0) | 1184 | if (err < 0) |
| 1172 | goto st_accel_power_off; | 1185 | goto st_accel_power_off; |
| 1173 | 1186 | ||
| 1174 | adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS; | 1187 | adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS; |
| 1175 | adata->multiread_bit = adata->sensor_settings->multi_read_bit; | ||
| 1176 | indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; | 1188 | indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; |
| 1177 | 1189 | ||
| 1178 | channels_size = indio_dev->num_channels * sizeof(struct iio_chan_spec); | 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 | if (err < 0) | 1216 | if (err < 0) |
| 1205 | goto st_accel_power_off; | 1217 | goto st_accel_power_off; |
| 1206 | 1218 | ||
| 1207 | if (irq > 0) { | 1219 | if (adata->irq > 0) { |
| 1208 | err = st_sensors_allocate_trigger(indio_dev, | 1220 | err = st_sensors_allocate_trigger(indio_dev, |
| 1209 | ST_ACCEL_TRIGGER_OPS); | 1221 | ST_ACCEL_TRIGGER_OPS); |
| 1210 | if (err < 0) | 1222 | if (err < 0) |
| @@ -1221,7 +1233,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev) · 10 unmodified lines | |||
| 1221 | return 0; | 1233 | return 0; |
| 1222 | 1234 | ||
| 1223 | st_accel_device_register_error: | 1235 | st_accel_device_register_error: |
| 1224 | if (irq > 0) | 1236 | if (adata->irq > 0) |
| 1225 | st_sensors_deallocate_trigger(indio_dev); | 1237 | st_sensors_deallocate_trigger(indio_dev); |
| 1226 | st_accel_probe_trigger_error: | 1238 | st_accel_probe_trigger_error: |
| 1227 | st_accel_deallocate_ring(indio_dev); | 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 | st_sensors_power_disable(indio_dev); | 1251 | st_sensors_power_disable(indio_dev); |
| 1240 | 1252 | ||
| 1241 | iio_device_unregister(indio_dev); | 1253 | iio_device_unregister(indio_dev); |
| 1242 | if (adata->get_irq_data_ready(indio_dev) > 0) | 1254 | if (adata->irq > 0) |
| 1243 | st_sensors_deallocate_trigger(indio_dev); | 1255 | st_sensors_deallocate_trigger(indio_dev); |
| 1244 | 1256 | ||
| 1245 | st_accel_deallocate_ring(indio_dev); | 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 | static int st_accel_i2c_probe(struct i2c_client *client) | 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 | struct st_sensor_data *adata; | 154 | struct st_sensor_data *adata; |
| 155 | struct iio_dev *indio_dev; | ||
| 155 | const char *match; | 156 | const char *match; |
| 156 | int ret; | 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 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*adata)); | 170 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*adata)); |
| 159 | if (!indio_dev) | 171 | if (!indio_dev) |
| 160 | return -ENOMEM; | 172 | return -ENOMEM; |
| 161 | 173 | ||
| 162 | adata = iio_priv(indio_dev); | 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); | 177 | ret = st_sensors_i2c_configure(indio_dev, client); |
| 165 | if (match) | 178 | if (ret < 0) |
| 166 | strlcpy(client->name, match, sizeof(client->name)); | 179 | return ret; |
| 167 | |||
| 168 | st_sensors_i2c_configure(indio_dev, client, adata); | ||
| 169 | 180 | ||
| 170 | ret = st_accel_common_probe(indio_dev); | 181 | ret = st_accel_common_probe(indio_dev); |
| 171 | if (ret < 0) | 182 | if (ret < 0) |
| @@ -102,19 +102,31 @@ MODULE_DEVICE_TABLE(of, st_accel_of_match); · 101 unmodified lines | |||
| 102 | 102 | ||
| 103 | static int st_accel_spi_probe(struct spi_device *spi) | 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 | struct st_sensor_data *adata; | 106 | struct st_sensor_data *adata; |
| 107 | struct iio_dev *indio_dev; | ||
| 107 | int err; | 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 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adata)); | 120 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adata)); |
| 110 | if (!indio_dev) | 121 | if (!indio_dev) |
| 111 | return -ENOMEM; | 122 | return -ENOMEM; |
| 112 | 123 | ||
| 113 | adata = iio_priv(indio_dev); | 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, | 127 | err = st_sensors_spi_configure(indio_dev, spi); |
| 116 | spi->modalias, sizeof(spi->modalias)); | 128 | if (err < 0) |
| 117 | st_sensors_spi_configure(indio_dev, spi, adata); | 129 | return err; |
| 118 | 130 | ||
| 119 | err = st_accel_common_probe(indio_dev); | 131 | err = st_accel_common_probe(indio_dev); |
| 120 | if (err < 0) | 132 | if (err < 0) |
| @@ -35,6 +35,11 @@ static const unsigned int ad7606_scale_avail[2] = { · 34 unmodified lines | |||
| 35 | 152588, 305176 | 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 | static const unsigned int ad7606_oversampling_avail[7] = { | 43 | static const unsigned int ad7606_oversampling_avail[7] = { |
| 39 | 1, 2, 4, 8, 16, 32, 64, | 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 | return -ENODEV; | 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 | static int ad7606_read_samples(struct ad7606_state *st) | 86 | static int ad7606_read_samples(struct ad7606_state *st) |
| 59 | { | 87 | { |
| 60 | unsigned int num = st->chip_info->num_channels; | 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 | .attrs = ad7606_attributes_range, | 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 | static const struct iio_chan_spec ad7605_channels[] = { | 339 | static const struct iio_chan_spec ad7605_channels[] = { |
| 335 | IIO_CHAN_SOFT_TIMESTAMP(4), | 340 | IIO_CHAN_SOFT_TIMESTAMP(4), |
| 336 | AD7605_CHANNEL(0), | 341 | AD7605_CHANNEL(0), |
| @@ -519,6 +524,14 @@ static const struct iio_info ad7606_info_os_and_range = { · 182 unmodified lines | |||
| 519 | .validate_trigger = &ad7606_validate_trigger, | 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 | static const struct iio_info ad7606_info_os = { | 535 | static const struct iio_info ad7606_info_os = { |
| 523 | .read_raw = &ad7606_read_raw, | 536 | .read_raw = &ad7606_read_raw, |
| 524 | .write_raw = &ad7606_write_raw, | 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 | if (ret) | 630 | if (ret) |
| 618 | dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); | 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 | st->write_scale = ad7606_write_scale_hw; | 637 | st->write_scale = ad7606_write_scale_hw; |
| 621 | st->write_os = ad7606_write_os_hw; | 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 | st->sw_mode_en = device_property_present(st->dev, | 641 | st->sw_mode_en = device_property_present(st->dev, |
| 625 | "adi,sw-mode"); | 642 | "adi,sw-mode"); |
| 626 | 643 | ||
| 627 | if (st->sw_mode_en) { | 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 | /* After reset, in software mode, ±10 V is set by default */ | 649 | /* After reset, in software mode, ±10 V is set by default */ |
| 629 | memset32(st->range, 2, ARRAY_SIZE(st->range)); | 650 | memset32(st->range, 2, ARRAY_SIZE(st->range)); |
| 630 | indio_dev->info = &ad7606_info_os_and_range; | 651 | indio_dev->info = &ad7606_info_os_range_and_debug; |
| 631 | 652 | ||
| 632 | /* | 653 | ret = st->bops->sw_mode_config(indio_dev); |
| 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); | ||
| 649 | if (ret < 0) | 654 | if (ret < 0) |
| 650 | return ret; | 655 | return ret; |
| 651 | } | 656 | } |
| @@ -8,6 +8,36 @@ · 7 unmodified lines | |||
| 8 | #ifndef IIO_ADC_AD7606_H_ | 8 | #ifndef IIO_ADC_AD7606_H_ |
| 9 | #define IIO_ADC_AD7606_H_ | 9 | #define IIO_ADC_AD7606_H_ |
| 10 | 10 | ||
| 11 | #define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all) { \ | ||
| 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 | * struct ad7606_chip_info - chip specific information | 42 | * struct ad7606_chip_info - chip specific information |
| 13 | * @channels: channel specification | 43 | * @channels: channel specification |
| @@ -16,12 +46,6 @@ · 2 unmodified lines | |||
| 16 | * oversampling ratios. | 46 | * oversampling ratios. |
| 17 | * @oversampling_num number of elements stored in oversampling_avail array | 47 | * @oversampling_num number of elements stored in oversampling_avail array |
| 18 | * @os_req_reset some devices require a reset to update oversampling | 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 | struct ad7606_chip_info { | 50 | struct ad7606_chip_info { |
| 27 | const struct iio_chan_spec *channels; | 51 | const struct iio_chan_spec *channels; |
| @@ -29,9 +53,6 @@ struct ad7606_chip_info { · 1 unmodified line | |||
| 29 | const unsigned int *oversampling_avail; | 53 | const unsigned int *oversampling_avail; |
| 30 | unsigned int oversampling_num; | 54 | unsigned int oversampling_num; |
| 31 | bool os_req_reset; | 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 | * @complete completion to indicate end of conversion | 84 | * @complete completion to indicate end of conversion |
| 64 | * @trig The IIO trigger associated with the device. | 85 | * @trig The IIO trigger associated with the device. |
| 65 | * @data buffer for reading data from the device | 86 | * @data buffer for reading data from the device |
| 87 | * @d16 be16 buffer for reading data from the device | ||
| 66 | */ | 88 | */ |
| 67 | struct ad7606_state { | 89 | struct ad7606_state { |
| 68 | struct device *dev; | 90 | struct device *dev; |
| @@ -96,15 +118,32 @@ struct ad7606_state { · 27 unmodified lines | |||
| 96 | * 16 * 16-bit samples + 64-bit timestamp | 118 | * 16 * 16-bit samples + 64-bit timestamp |
| 97 | */ | 119 | */ |
| 98 | unsigned short data[20] ____cacheline_aligned; | 120 | unsigned short data[20] ____cacheline_aligned; |
| 121 | __be16 d16[2]; | ||
| 99 | }; | 122 | }; |
| 100 | 123 | ||
| 101 | /** | 124 | /** |
| 102 | * struct ad7606_bus_ops - driver bus operations | 125 | * struct ad7606_bus_ops - driver bus operations |
| 103 | * @read_block function pointer for reading blocks of data | 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 | struct ad7606_bus_ops { | 134 | struct ad7606_bus_ops { |
| 106 | /* more methods added in future? */ | 135 | /* more methods added in future? */ |
| 107 | int (*read_block)(struct device *dev, int num, void *data); | 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 | int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, | 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 | int irq; | 53 | int irq; |
| 54 | 54 | ||
| 55 | irq = platform_get_irq(pdev, 0); | 55 | irq = platform_get_irq(pdev, 0); |
| 56 | if (irq < 0) { | 56 | if (irq < 0) |
| 57 | dev_err(&pdev->dev, "no irq: %d\n", irq); | ||
| 58 | return irq; | 57 | return irq; |
| 59 | } | ||
| 60 | 58 | ||
| 61 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 59 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 62 | addr = devm_ioremap_resource(&pdev->dev, res); | 60 | addr = devm_ioremap_resource(&pdev->dev, res); |
| @@ -15,6 +15,51 @@ · 14 unmodified lines | |||
| 15 | 15 | ||
| 16 | #define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */ | 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 | static int ad7606_spi_read_block(struct device *dev, | 63 | static int ad7606_spi_read_block(struct device *dev, |
| 19 | int count, void *buf) | 64 | int count, void *buf) |
| 20 | { | 65 | { |
| @@ -35,17 +80,145 @@ static int ad7606_spi_read_block(struct device *dev, · 14 unmodified lines | |||
| 35 | return 0; | 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 | static const struct ad7606_bus_ops ad7606_spi_bops = { | 192 | static const struct ad7606_bus_ops ad7606_spi_bops = { |
| 39 | .read_block = ad7606_spi_read_block, | 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 | static int ad7606_spi_probe(struct spi_device *spi) | 205 | static int ad7606_spi_probe(struct spi_device *spi) |
| 43 | { | 206 | { |
| 44 | const struct spi_device_id *id = spi_get_device_id(spi); | 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 | return ad7606_probe(&spi->dev, spi->irq, NULL, | 219 | return ad7606_probe(&spi->dev, spi->irq, NULL, |
| 47 | id->name, id->driver_data, | 220 | id->name, id->driver_data, |
| 48 | &ad7606_spi_bops); | 221 | bops); |
| 49 | } | 222 | } |
| 50 | 223 | ||
| 51 | static const struct spi_device_id ad7606_id_table[] = { | 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 | idev->info = &at91_adc_info; | 1179 | idev->info = &at91_adc_info; |
| 1180 | 1180 | ||
| 1181 | st->irq = platform_get_irq(pdev, 0); | 1181 | st->irq = platform_get_irq(pdev, 0); |
| 1182 | if (st->irq < 0) { | 1182 | if (st->irq < 0) |
| 1183 | dev_err(&pdev->dev, "No IRQ ID is designated\n"); | ||
| 1184 | return -ENODEV; | 1183 | return -ENODEV; |
| 1185 | } | ||
| 1186 | 1184 | ||
| 1187 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 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 | info = iio_priv(indio_dev); | 226 | info = iio_priv(indio_dev); |
| 227 | info->irq = platform_get_irq(pdev, 0); | 227 | info->irq = platform_get_irq(pdev, 0); |
| 228 | if (info->irq < 0) { | 228 | if (info->irq < 0) |
| 229 | dev_err(&pdev->dev, "no irq resource?\n"); | ||
| 230 | return info->irq; | 229 | return info->irq; |
| 231 | } | ||
| 232 | platform_set_drvdata(pdev, indio_dev); | 230 | platform_set_drvdata(pdev, indio_dev); |
| 233 | info->regmap = axp20x->regmap; | 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 | adc_priv->irqno = platform_get_irq(pdev, 0); | 542 | adc_priv->irqno = platform_get_irq(pdev, 0); |
| 543 | if (adc_priv->irqno <= 0) { | 543 | if (adc_priv->irqno <= 0) |
| 544 | dev_err(&pdev->dev, "platform_get_irq failed\n"); | 544 | return -ENODEV; |
| 545 | ret = -ENODEV; | ||
| 546 | return ret; | ||
| 547 | } | ||
| 548 | 545 | ||
| 549 | ret = regmap_update_bits(adc_priv->regmap, IPROC_REGCTL2, | 546 | ret = regmap_update_bits(adc_priv->regmap, IPROC_REGCTL2, |
| 550 | IPROC_ADC_AUXIN_SCAN_ENA, 0); | 547 | IPROC_ADC_AUXIN_SCAN_ENA, 0); |
| @@ -337,10 +337,8 @@ static int da9150_gpadc_probe(struct platform_device *pdev) · 336 unmodified lines | |||
| 337 | init_completion(&gpadc->complete); | 337 | init_completion(&gpadc->complete); |
| 338 | 338 | ||
| 339 | irq = platform_get_irq_byname(pdev, "GPADC"); | 339 | irq = platform_get_irq_byname(pdev, "GPADC"); |
| 340 | if (irq < 0) { | 340 | if (irq < 0) |
| 341 | dev_err(dev, "Failed to get IRQ: %d\n", irq); | ||
| 342 | return irq; | 341 | return irq; |
| 343 | } | ||
| 344 | 342 | ||
| 345 | ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq, | 343 | ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq, |
| 346 | IRQF_ONESHOT, "GPADC", gpadc); | 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 | env->comp_irq = platform_get_irq_byname(pdev, "comp"); | 359 | env->comp_irq = platform_get_irq_byname(pdev, "comp"); |
| 360 | if (env->comp_irq < 0) { | 360 | if (env->comp_irq < 0) |
| 361 | if (env->comp_irq != -EPROBE_DEFER) | ||
| 362 | dev_err(dev, "failed to get compare interrupt\n"); | ||
| 363 | return env->comp_irq; | 361 | return env->comp_irq; |
| 364 | } | ||
| 365 | 362 | ||
| 366 | ret = devm_request_irq(dev, env->comp_irq, envelope_detector_comp_isr, | 363 | ret = devm_request_irq(dev, env->comp_irq, envelope_detector_comp_isr, |
| 367 | 0, "envelope-detector", env); | 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 | irq = platform_get_irq(pdev, 0); | 807 | irq = platform_get_irq(pdev, 0); |
| 808 | if (irq < 0) { | 808 | if (irq < 0) |
| 809 | dev_err(&pdev->dev, "no irq resource?\n"); | ||
| 810 | return irq; | 809 | return irq; |
| 811 | } | ||
| 812 | info->irq = irq; | 810 | info->irq = irq; |
| 813 | 811 | ||
| 814 | irq = platform_get_irq(pdev, 1); | 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 | priv->irq = platform_get_irq(pdev, 0); | 341 | priv->irq = platform_get_irq(pdev, 0); |
| 342 | if (priv->irq <= 0) { | 342 | if (priv->irq <= 0) { |
| 343 | dev_err(dev, "Failed to get IRQ\n"); | ||
| 344 | ret = priv->irq; | 343 | ret = priv->irq; |
| 345 | if (!ret) | 344 | if (!ret) |
| 346 | ret = -ENXIO; | 345 | ret = -ENXIO; |
| @@ -456,6 +456,11 @@ err_read: · 455 unmodified lines | |||
| 456 | return IRQ_HANDLED; | 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 | static int hi8435_probe(struct spi_device *spi) | 464 | static int hi8435_probe(struct spi_device *spi) |
| 460 | { | 465 | { |
| 461 | struct iio_dev *idev; | 466 | struct iio_dev *idev; |
| @@ -477,7 +482,7 @@ static int hi8435_probe(struct spi_device *spi) · 15 unmodified lines | |||
| 477 | hi8435_writeb(priv, HI8435_CTRL_REG, 0); | 482 | hi8435_writeb(priv, HI8435_CTRL_REG, 0); |
| 478 | } else { | 483 | } else { |
| 479 | udelay(5); | 484 | udelay(5); |
| 480 | gpiod_set_value(reset_gpio, 1); | 485 | gpiod_set_value_cansleep(reset_gpio, 1); |
| 481 | } | 486 | } |
| 482 | 487 | ||
| 483 | spi_set_drvdata(spi, idev); | 488 | spi_set_drvdata(spi, idev); |
| @@ -513,27 +518,13 @@ static int hi8435_probe(struct spi_device *spi) · 29 unmodified lines | |||
| 513 | if (ret) | 518 | if (ret) |
| 514 | return ret; | 519 | return ret; |
| 515 | 520 | ||
| 516 | ret = iio_device_register(idev); | 521 | ret = devm_add_action_or_reset(&spi->dev, |
| 517 | if (ret < 0) { | 522 | hi8435_triggered_event_cleanup, |
| 518 | dev_err(&spi->dev, "unable to register device\n"); | 523 | idev); |
| 519 | goto unregister_triggered_event; | 524 | if (ret) |
| 520 | } | 525 | return ret; |
| 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); | ||
| 535 | 526 | ||
| 536 | return 0; | 527 | return devm_iio_device_register(&spi->dev, idev); |
| 537 | } | 528 | } |
| 538 | 529 | ||
| 539 | static const struct of_device_id hi8435_dt_ids[] = { | 530 | static const struct of_device_id hi8435_dt_ids[] = { |
| @@ -554,7 +545,6 @@ static struct spi_driver hi8435_driver = { · 14 unmodified lines | |||
| 554 | .of_match_table = of_match_ptr(hi8435_dt_ids), | 545 | .of_match_table = of_match_ptr(hi8435_dt_ids), |
| 555 | }, | 546 | }, |
| 556 | .probe = hi8435_probe, | 547 | .probe = hi8435_probe, |
| 557 | .remove = hi8435_remove, | ||
| 558 | .id_table = hi8435_id, | 548 | .id_table = hi8435_id, |
| 559 | }; | 549 | }; |
| 560 | module_spi_driver(hi8435_driver); | 550 | module_spi_driver(hi8435_driver); |
| @@ -492,10 +492,8 @@ static int imx7d_adc_probe(struct platform_device *pdev) · 491 unmodified lines | |||
| 492 | return PTR_ERR(info->regs); | 492 | return PTR_ERR(info->regs); |
| 493 | 493 | ||
| 494 | irq = platform_get_irq(pdev, 0); | 494 | irq = platform_get_irq(pdev, 0); |
| 495 | if (irq < 0) { | 495 | if (irq < 0) |
| 496 | dev_err(dev, "No irq resource?\n"); | ||
| 497 | return irq; | 496 | return irq; |
| 498 | } | ||
| 499 | 497 | ||
| 500 | info->clk = devm_clk_get(dev, "adc"); | 498 | info->clk = devm_clk_get(dev, "adc"); |
| 501 | if (IS_ERR(info->clk)) { | 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 | irq = platform_get_irq(pdev, 0); | 174 | irq = platform_get_irq(pdev, 0); |
| 175 | if (irq <= 0) { | 175 | if (irq <= 0) |
| 176 | dev_err(&pdev->dev, "failed getting interrupt resource\n"); | ||
| 177 | return -ENXIO; | 176 | return -ENXIO; |
| 178 | } | ||
| 179 | 177 | ||
| 180 | retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0, | 178 | retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0, |
| 181 | LPC32XXAD_NAME, st); | 179 | LPC32XXAD_NAME, st); |
| @@ -225,7 +225,6 @@ static int npcm_adc_probe(struct platform_device *pdev) · 224 unmodified lines | |||
| 225 | 225 | ||
| 226 | irq = platform_get_irq(pdev, 0); | 226 | irq = platform_get_irq(pdev, 0); |
| 227 | if (irq <= 0) { | 227 | if (irq <= 0) { |
| 228 | dev_err(dev, "failed getting interrupt resource\n"); | ||
| 229 | ret = -EINVAL; | 228 | ret = -EINVAL; |
| 230 | goto err_disable_clk; | 229 | goto err_disable_clk; |
| 231 | } | 230 | } |
| @@ -244,10 +244,8 @@ static int rockchip_saradc_probe(struct platform_device *pdev) · 243 unmodified lines | |||
| 244 | init_completion(&info->completion); | 244 | init_completion(&info->completion); |
| 245 | 245 | ||
| 246 | irq = platform_get_irq(pdev, 0); | 246 | irq = platform_get_irq(pdev, 0); |
| 247 | if (irq < 0) { | 247 | if (irq < 0) |
| 248 | dev_err(&pdev->dev, "no irq resource?\n"); | ||
| 249 | return irq; | 248 | return irq; |
| 250 | } | ||
| 251 | 249 | ||
| 252 | ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, | 250 | ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr, |
| 253 | 0, dev_name(&pdev->dev), info); | 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 | static int sc27xx_adc_probe(struct platform_device *pdev) | 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 | struct sc27xx_adc_data *sc27xx_data; | 509 | struct sc27xx_adc_data *sc27xx_data; |
| 509 | struct iio_dev *indio_dev; | 510 | struct iio_dev *indio_dev; |
| 510 | int ret; | 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 | if (!indio_dev) | 514 | if (!indio_dev) |
| 514 | return -ENOMEM; | 515 | return -ENOMEM; |
| 515 | 516 | ||
| 516 | sc27xx_data = iio_priv(indio_dev); | 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 | if (!sc27xx_data->regmap) { | 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 | return -ENODEV; | 522 | return -ENODEV; |
| 522 | } | 523 | } |
| 523 | 524 | ||
| 524 | ret = of_property_read_u32(np, "reg", &sc27xx_data->base); | 525 | ret = of_property_read_u32(np, "reg", &sc27xx_data->base); |
| 525 | if (ret) { | 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 | return ret; | 528 | return ret; |
| 528 | } | 529 | } |
| 529 | 530 | ||
| 530 | sc27xx_data->irq = platform_get_irq(pdev, 0); | 531 | sc27xx_data->irq = platform_get_irq(pdev, 0); |
| 531 | if (sc27xx_data->irq < 0) { | 532 | if (sc27xx_data->irq < 0) |
| 532 | dev_err(&pdev->dev, "failed to get ADC irq number\n"); | ||
| 533 | return sc27xx_data->irq; | 533 | return sc27xx_data->irq; |
| 534 | } | ||
| 535 | 534 | ||
| 536 | ret = of_hwspin_lock_get_id(np, 0); | 535 | ret = of_hwspin_lock_get_id(np, 0); |
| 537 | if (ret < 0) { | 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 | return ret; | 538 | return ret; |
| 540 | } | 539 | } |
| 541 | 540 | ||
| 542 | sc27xx_data->hwlock = hwspin_lock_request_specific(ret); | 541 | sc27xx_data->hwlock = hwspin_lock_request_specific(ret); |
| 543 | if (!sc27xx_data->hwlock) { | 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 | return -ENXIO; | 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 | sc27xx_data->hwlock); | 548 | sc27xx_data->hwlock); |
| 550 | if (ret) { | 549 | if (ret) { |
| 551 | sc27xx_adc_free_hwlock(sc27xx_data->hwlock); | 550 | dev_err(dev, "failed to add hwspinlock action\n"); |
| 552 | dev_err(&pdev->dev, "failed to add hwspinlock action\n"); | ||
| 553 | return ret; | 551 | return ret; |
| 554 | } | 552 | } |
| 555 | 553 | ||
| 556 | init_completion(&sc27xx_data->completion); | 554 | init_completion(&sc27xx_data->completion); |
| 557 | sc27xx_data->dev = &pdev->dev; | 555 | sc27xx_data->dev = dev; |
| 558 | 556 | ||
| 559 | ret = sc27xx_adc_enable(sc27xx_data); | 557 | ret = sc27xx_adc_enable(sc27xx_data); |
| 560 | if (ret) { | 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 | return ret; | 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 | if (ret) { | 564 | if (ret) { |
| 567 | sc27xx_adc_disable(sc27xx_data); | 565 | dev_err(dev, "failed to add ADC disable action\n"); |
| 568 | dev_err(&pdev->dev, "failed to add ADC disable action\n"); | ||
| 569 | return ret; | 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 | sc27xx_adc_isr, IRQF_ONESHOT, | 570 | sc27xx_adc_isr, IRQF_ONESHOT, |
| 574 | pdev->name, sc27xx_data); | 571 | pdev->name, sc27xx_data); |
| 575 | if (ret) { | 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 | return ret; | 574 | return ret; |
| 578 | } | 575 | } |
| 579 | 576 | ||
| 580 | indio_dev->dev.parent = &pdev->dev; | 577 | indio_dev->dev.parent = dev; |
| 581 | indio_dev->name = dev_name(&pdev->dev); | 578 | indio_dev->name = dev_name(dev); |
| 582 | indio_dev->modes = INDIO_DIRECT_MODE; | 579 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 583 | indio_dev->info = &sc27xx_info; | 580 | indio_dev->info = &sc27xx_info; |
| 584 | indio_dev->channels = sc27xx_channels; | 581 | indio_dev->channels = sc27xx_channels; |
| 585 | indio_dev->num_channels = ARRAY_SIZE(sc27xx_channels); | 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 | if (ret) | 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 | return ret; | 587 | return ret; |
| 591 | } | 588 | } |
| @@ -301,7 +301,6 @@ static int spear_adc_probe(struct platform_device *pdev) · 300 unmodified lines | |||
| 301 | 301 | ||
| 302 | irq = platform_get_irq(pdev, 0); | 302 | irq = platform_get_irq(pdev, 0); |
| 303 | if (irq <= 0) { | 303 | if (irq <= 0) { |
| 304 | dev_err(dev, "failed getting interrupt resource\n"); | ||
| 305 | ret = -EINVAL; | 304 | ret = -EINVAL; |
| 306 | goto errout2; | 305 | goto errout2; |
| 307 | } | 306 | } |
| @@ -14,9 +14,11 @@ · 13 unmodified lines | |||
| 14 | #include <linux/irqchip/chained_irq.h> | 14 | #include <linux/irqchip/chained_irq.h> |
| 15 | #include <linux/irqdesc.h> | 15 | #include <linux/irqdesc.h> |
| 16 | #include <linux/irqdomain.h> | 16 | #include <linux/irqdomain.h> |
| 17 | #include <linux/mfd/syscon.h> | ||
| 17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 18 | #include <linux/of_device.h> | 19 | #include <linux/of_device.h> |
| 19 | #include <linux/pm_runtime.h> | 20 | #include <linux/pm_runtime.h> |
| 21 | #include <linux/regmap.h> | ||
| 20 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
| 21 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 22 | 24 | ||
| @@ -51,6 +53,17 @@ · 28 unmodified lines | |||
| 51 | 53 | ||
| 52 | #define STM32_ADC_CORE_SLEEP_DELAY_MS 2000 | 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 | * stm32_adc_common_regs - stm32 common registers, compatible dependent data | 68 | * stm32_adc_common_regs - stm32 common registers, compatible dependent data |
| 56 | * @csr: common status register offset | 69 | * @csr: common status register offset |
| @@ -74,11 +87,13 @@ struct stm32_adc_priv; · 17 unmodified lines | |||
| 74 | * @regs: common registers for all instances | 87 | * @regs: common registers for all instances |
| 75 | * @clk_sel: clock selection routine | 88 | * @clk_sel: clock selection routine |
| 76 | * @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet) | 89 | * @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet) |
| 90 | * @has_syscfg: SYSCFG capability flags | ||
| 77 | */ | 91 | */ |
| 78 | struct stm32_adc_priv_cfg { | 92 | struct stm32_adc_priv_cfg { |
| 79 | const struct stm32_adc_common_regs *regs; | 93 | const struct stm32_adc_common_regs *regs; |
| 80 | int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *); | 94 | int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *); |
| 81 | u32 max_clk_rate_hz; | 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 | * @domain: irq domain reference | 102 | * @domain: irq domain reference |
| 88 | * @aclk: clock reference for the analog circuitry | 103 | * @aclk: clock reference for the analog circuitry |
| 89 | * @bclk: bus clock common for all ADCs, depends on part used | 104 | * @bclk: bus clock common for all ADCs, depends on part used |
| 105 | * @booster: booster supply reference | ||
| 106 | * @vdd: vdd supply reference | ||
| 90 | * @vdda: vdda analog supply reference | 107 | * @vdda: vdda analog supply reference |
| 91 | * @vref: regulator reference | 108 | * @vref: regulator reference |
| 109 | * @vdd_uv: vdd supply voltage (microvolts) | ||
| 110 | * @vdda_uv: vdda supply voltage (microvolts) | ||
| 92 | * @cfg: compatible configuration data | 111 | * @cfg: compatible configuration data |
| 93 | * @common: common data for all ADC instances | 112 | * @common: common data for all ADC instances |
| 94 | * @ccr_bak: backup CCR in low power mode | 113 | * @ccr_bak: backup CCR in low power mode |
| 114 | * @syscfg: reference to syscon, system control registers | ||
| 95 | */ | 115 | */ |
| 96 | struct stm32_adc_priv { | 116 | struct stm32_adc_priv { |
| 97 | int irq[STM32_ADC_MAX_ADCS]; | 117 | int irq[STM32_ADC_MAX_ADCS]; |
| 98 | struct irq_domain *domain; | 118 | struct irq_domain *domain; |
| 99 | struct clk *aclk; | 119 | struct clk *aclk; |
| 100 | struct clk *bclk; | 120 | struct clk *bclk; |
| 121 | struct regulator *booster; | ||
| 122 | struct regulator *vdd; | ||
| 101 | struct regulator *vdda; | 123 | struct regulator *vdda; |
| 102 | struct regulator *vref; | 124 | struct regulator *vref; |
| 125 | int vdd_uv; | ||
| 126 | int vdda_uv; | ||
| 103 | const struct stm32_adc_priv_cfg *cfg; | 127 | const struct stm32_adc_priv_cfg *cfg; |
| 104 | struct stm32_adc_common common; | 128 | struct stm32_adc_common common; |
| 105 | u32 ccr_bak; | 129 | u32 ccr_bak; |
| 130 | struct regmap *syscfg; | ||
| 106 | }; | 131 | }; |
| 107 | 132 | ||
| 108 | static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com) | 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 | if (i && priv->irq[i] == -ENXIO) | 375 | if (i && priv->irq[i] == -ENXIO) |
| 351 | continue; | 376 | continue; |
| 352 | dev_err(&pdev->dev, "failed to get irq\n"); | ||
| 353 | 377 | ||
| 354 | return priv->irq[i]; | 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 | static int stm32_adc_core_hw_start(struct device *dev) | 493 | static int stm32_adc_core_hw_start(struct device *dev) |
| 394 | { | 494 | { |
| 395 | struct stm32_adc_common *common = dev_get_drvdata(dev); | 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 | return ret; | 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 | ret = regulator_enable(priv->vref); | 516 | ret = regulator_enable(priv->vref); |
| 406 | if (ret < 0) { | 517 | if (ret < 0) { |
| 407 | dev_err(dev, "vref enable failed\n"); | 518 | dev_err(dev, "vref enable failed\n"); |
| 408 | goto err_vdda_disable; | 519 | goto err_switches_dis; |
| 409 | } | 520 | } |
| 410 | 521 | ||
| 411 | if (priv->bclk) { | 522 | if (priv->bclk) { |
| @@ -433,6 +544,8 @@ err_bclk_disable: · 21 unmodified lines | |||
| 433 | clk_disable_unprepare(priv->bclk); | 544 | clk_disable_unprepare(priv->bclk); |
| 434 | err_regulator_disable: | 545 | err_regulator_disable: |
| 435 | regulator_disable(priv->vref); | 546 | regulator_disable(priv->vref); |
| 547 | err_switches_dis: | ||
| 548 | stm32_adc_core_switches_supply_dis(priv); | ||
| 436 | err_vdda_disable: | 549 | err_vdda_disable: |
| 437 | regulator_disable(priv->vdda); | 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 | if (priv->bclk) | 564 | if (priv->bclk) |
| 452 | clk_disable_unprepare(priv->bclk); | 565 | clk_disable_unprepare(priv->bclk); |
| 453 | regulator_disable(priv->vref); | 566 | regulator_disable(priv->vref); |
| 567 | stm32_adc_core_switches_supply_dis(priv); | ||
| 454 | regulator_disable(priv->vdda); | 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 | static int stm32_adc_probe(struct platform_device *pdev) | 641 | static int stm32_adc_probe(struct platform_device *pdev) |
| 458 | { | 642 | { |
| 459 | struct stm32_adc_priv *priv; | 643 | struct stm32_adc_priv *priv; |
| @@ -514,6 +698,10 @@ static int stm32_adc_probe(struct platform_device *pdev) · 54 unmodified lines | |||
| 514 | priv->bclk = NULL; | 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 | pm_runtime_get_noresume(dev); | 705 | pm_runtime_get_noresume(dev); |
| 518 | pm_runtime_set_active(dev); | 706 | pm_runtime_set_active(dev); |
| 519 | pm_runtime_set_autosuspend_delay(dev, STM32_ADC_CORE_SLEEP_DELAY_MS); | 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 | .regs = &stm32h7_adc_common_regs, | 799 | .regs = &stm32h7_adc_common_regs, |
| 612 | .clk_sel = stm32h7_adc_clk_sel, | 800 | .clk_sel = stm32h7_adc_clk_sel, |
| 613 | .max_clk_rate_hz = 36000000, | 801 | .max_clk_rate_hz = 36000000, |
| 802 | .has_syscfg = HAS_VBOOSTER, | ||
| 614 | }; | 803 | }; |
| 615 | 804 | ||
| 616 | static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = { | 805 | static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = { |
| 617 | .regs = &stm32h7_adc_common_regs, | 806 | .regs = &stm32h7_adc_common_regs, |
| 618 | .clk_sel = stm32h7_adc_clk_sel, | 807 | .clk_sel = stm32h7_adc_clk_sel, |
| 619 | .max_clk_rate_hz = 40000000, | 808 | .max_clk_rate_hz = 40000000, |
| 809 | .has_syscfg = HAS_VBOOSTER | HAS_ANASWVDD, | ||
| 620 | }; | 810 | }; |
| 621 | 811 | ||
| 622 | static const struct of_device_id stm32_adc_of_match[] = { | 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 | adc->irq = platform_get_irq(pdev, 0); | 1921 | adc->irq = platform_get_irq(pdev, 0); |
| 1922 | if (adc->irq < 0) { | 1922 | if (adc->irq < 0) |
| 1923 | dev_err(&pdev->dev, "failed to get irq\n"); | ||
| 1924 | return adc->irq; | 1923 | return adc->irq; |
| 1925 | } | ||
| 1926 | 1924 | ||
| 1927 | ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr, | 1925 | ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr, |
| 1928 | 0, pdev->name, adc); | 1926 | 0, pdev->name, adc); |
| @@ -1601,11 +1601,8 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev) · 1600 unmodified lines | |||
| 1601 | * So IRQ associated to filter instance 0 is dedicated to the Filter 0. | 1601 | * So IRQ associated to filter instance 0 is dedicated to the Filter 0. |
| 1602 | */ | 1602 | */ |
| 1603 | irq = platform_get_irq(pdev, 0); | 1603 | irq = platform_get_irq(pdev, 0); |
| 1604 | if (irq < 0) { | 1604 | if (irq < 0) |
| 1605 | if (irq != -EPROBE_DEFER) | ||
| 1606 | dev_err(dev, "Failed to get IRQ: %d\n", irq); | ||
| 1607 | return irq; | 1605 | return irq; |
| 1608 | } | ||
| 1609 | 1606 | ||
| 1610 | ret = devm_request_irq(dev, irq, stm32_dfsdm_irq, | 1607 | ret = devm_request_irq(dev, irq, stm32_dfsdm_irq, |
| 1611 | 0, pdev->name, adc); | 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 | atomic_set(atomic, 1); | 460 | atomic_set(atomic, 1); |
| 461 | 461 | ||
| 462 | ret = platform_get_irq_byname(pdev, name); | 462 | ret = platform_get_irq_byname(pdev, name); |
| 463 | if (ret < 0) { | 463 | if (ret < 0) |
| 464 | dev_err(&pdev->dev, "no %s interrupt registered\n", name); | ||
| 465 | return ret; | 464 | return ret; |
| 466 | } | ||
| 467 | 465 | ||
| 468 | ret = regmap_irq_get_virq(mfd_dev->regmap_irqc, ret); | 466 | ret = regmap_irq_get_virq(mfd_dev->regmap_irqc, ret); |
| 469 | if (ret < 0) { | 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 | irq = platform_get_irq(pdev, 0); | 907 | irq = platform_get_irq(pdev, 0); |
| 908 | if (irq < 0) { | 908 | if (irq < 0) |
| 909 | dev_err(&pdev->dev, "failed to get irq\n"); | ||
| 910 | return irq; | 909 | return irq; |
| 911 | } | ||
| 912 | 910 | ||
| 913 | ret = devm_request_threaded_irq(dev, irq, NULL, | 911 | ret = devm_request_threaded_irq(dev, irq, NULL, |
| 914 | twl6030_gpadc_irq_handler, | 912 | twl6030_gpadc_irq_handler, |
| @@ -821,10 +821,8 @@ static int vf610_adc_probe(struct platform_device *pdev) · 820 unmodified lines | |||
| 821 | return PTR_ERR(info->regs); | 821 | return PTR_ERR(info->regs); |
| 822 | 822 | ||
| 823 | irq = platform_get_irq(pdev, 0); | 823 | irq = platform_get_irq(pdev, 0); |
| 824 | if (irq < 0) { | 824 | if (irq < 0) |
| 825 | dev_err(&pdev->dev, "no irq resource?\n"); | ||
| 826 | return irq; | 825 | return irq; |
| 827 | } | ||
| 828 | 826 | ||
| 829 | ret = devm_request_irq(info->dev, irq, | 827 | ret = devm_request_irq(info->dev, irq, |
| 830 | vf610_adc_isr, 0, | 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 | /* Save values */ | 64 | /* Save values */ |
| 65 | for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) | 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 | st->core.resp->sensor_offset.offset[i]; | 67 | st->core.resp->sensor_offset.offset[i]; |
| 68 | ret = IIO_VAL_INT; | 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 | break; | 95 | break; |
| 71 | case IIO_CHAN_INFO_SCALE: | 96 | case IIO_CHAN_INFO_SCALE: |
| 72 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; | 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 | switch (mask) { | 160 | switch (mask) { |
| 136 | case IIO_CHAN_INFO_CALIBBIAS: | 161 | case IIO_CHAN_INFO_CALIBBIAS: |
| 137 | st->core.calib[idx] = val; | 162 | st->core.calib[idx].offset = val; |
| 138 | 163 | ||
| 139 | /* Send to EC for each axis, even if not complete */ | 164 | /* Send to EC for each axis, even if not complete */ |
| 140 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; | 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 | MOTION_SENSE_SET_OFFSET; | 167 | MOTION_SENSE_SET_OFFSET; |
| 143 | for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) | 168 | for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) |
| 144 | st->core.param.sensor_offset.offset[i] = | 169 | st->core.param.sensor_offset.offset[i] = |
| 145 | st->core.calib[i]; | 170 | st->core.calib[i].offset; |
| 146 | st->core.param.sensor_offset.temp = | 171 | st->core.param.sensor_offset.temp = |
| 147 | EC_MOTION_SENSE_INVALID_CALIB_TEMP; | 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 | ret = cros_ec_motion_send_host_cmd(&st->core, 0); | 189 | ret = cros_ec_motion_send_host_cmd(&st->core, 0); |
| 150 | break; | 190 | break; |
| 151 | case IIO_CHAN_INFO_SCALE: | 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 | static const struct iio_info ec_sensors_info = { | 215 | static const struct iio_info ec_sensors_info = { |
| 176 | .read_raw = &cros_ec_sensors_read, | 216 | .read_raw = &cros_ec_sensors_read, |
| 177 | .write_raw = &cros_ec_sensors_write, | 217 | .write_raw = &cros_ec_sensors_write, |
| 218 | .read_avail = &cros_ec_sensors_core_read_avail, | ||
| 178 | }; | 219 | }; |
| 179 | 220 | ||
| 180 | static int cros_ec_sensors_probe(struct platform_device *pdev) | 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 | /* Common part */ | 247 | /* Common part */ |
| 207 | channel->info_mask_separate = | 248 | channel->info_mask_separate = |
| 208 | BIT(IIO_CHAN_INFO_RAW) | | 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 | channel->info_mask_shared_by_all = | 252 | channel->info_mask_shared_by_all = |
| 211 | BIT(IIO_CHAN_INFO_SCALE) | | 253 | BIT(IIO_CHAN_INFO_SCALE) | |
| 212 | BIT(IIO_CHAN_INFO_FREQUENCY) | | 254 | BIT(IIO_CHAN_INFO_FREQUENCY) | |
| 213 | BIT(IIO_CHAN_INFO_SAMP_FREQ); | 255 | BIT(IIO_CHAN_INFO_SAMP_FREQ); |
| 256 | channel->info_mask_shared_by_all_available = | ||
| 257 | BIT(IIO_CHAN_INFO_SAMP_FREQ); | ||
| 214 | channel->scan_type.realbits = CROS_EC_SENSOR_BITS; | 258 | channel->scan_type.realbits = CROS_EC_SENSOR_BITS; |
| 215 | channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; | 259 | channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; |
| 216 | channel->scan_index = i; | 260 | channel->scan_index = i; |
| @@ -25,6 +25,62 @@ static char *cros_ec_loc[] = { · 24 unmodified lines | |||
| 25 | [MOTIONSENSE_LOC_MAX] = "unknown", | 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 | int cros_ec_sensors_core_init(struct platform_device *pdev, | 84 | int cros_ec_sensors_core_init(struct platform_device *pdev, |
| 29 | struct iio_dev *indio_dev, | 85 | struct iio_dev *indio_dev, |
| 30 | bool physical_device) | 86 | bool physical_device) |
| @@ -33,6 +89,8 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, · 2 unmodified lines | |||
| 33 | struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); | 89 | struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); |
| 34 | struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent); | 90 | struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent); |
| 35 | struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); | 91 | struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); |
| 92 | u32 ver_mask; | ||
| 93 | int ret; | ||
| 36 | 94 | ||
| 37 | platform_set_drvdata(pdev, indio_dev); | 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 | mutex_init(&state->cmd_lock); | 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 | /* Set up the host command structure. */ | 115 | /* Set up the host command structure. */ |
| 51 | state->msg->version = 2; | 116 | state->msg->version = fls(ver_mask) - 1; |
| 52 | state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; | 117 | state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; |
| 53 | state->msg->outsize = sizeof(struct ec_params_motion_sense); | 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 | state->param.cmd = MOTIONSENSE_CMD_INFO; | 126 | state->param.cmd = MOTIONSENSE_CMD_INFO; |
| 62 | state->param.info.sensor_num = sensor_platform->sensor_num; | 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 | dev_warn(dev, "Can not access sensor info\n"); | 130 | dev_warn(dev, "Can not access sensor info\n"); |
| 65 | return -EIO; | 131 | return ret; |
| 66 | } | 132 | } |
| 67 | state->type = state->resp->info.type; | 133 | state->type = state->resp->info.type; |
| 68 | state->loc = state->resp->info.location; | 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 | return 0; | 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 | ret = cros_ec_cmd_xfer_status(state->ec, state->msg); | 169 | ret = cros_ec_cmd_xfer_status(state->ec, state->msg); |
| 88 | if (ret < 0) | 170 | if (ret < 0) |
| 89 | return -EIO; | 171 | return ret; |
| 90 | 172 | ||
| 91 | if (ret && | 173 | if (ret && |
| 92 | state->resp != (struct ec_response_motion_sense *)state->msg->data) | 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 | } else { | 200 | } else { |
| 119 | /* Save values */ | 201 | /* Save values */ |
| 120 | for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) | 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 | mutex_unlock(&st->cmd_lock); | 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 | if (ret < 0) | 350 | if (ret < 0) |
| 269 | return ret; | 351 | return ret; |
| 270 | 352 | ||
| 353 | *data *= st->sign[i]; | ||
| 271 | data++; | 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 | struct iio_chan_spec const *chan, | 479 | struct iio_chan_spec const *chan, |
| 397 | int *val, int *val2, long mask) | 480 | int *val, int *val2, long mask) |
| 398 | { | 481 | { |
| 399 | int ret = IIO_VAL_INT; | 482 | int ret; |
| 400 | 483 | ||
| 401 | switch (mask) { | 484 | switch (mask) { |
| 402 | case IIO_CHAN_INFO_SAMP_FREQ: | 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 | st->param.ec_rate.data = | 487 | st->param.ec_rate.data = |
| 405 | EC_MOTION_SENSE_NO_VALUE; | 488 | EC_MOTION_SENSE_NO_VALUE; |
| 406 | 489 | ||
| 407 | if (cros_ec_motion_send_host_cmd(st, 0)) | 490 | ret = cros_ec_motion_send_host_cmd(st, 0); |
| 408 | ret = -EIO; | 491 | if (ret) |
| 409 | else | 492 | break; |
| 410 | *val = st->resp->ec_rate.ret; | 493 | |
| 494 | *val = st->resp->ec_rate.ret; | ||
| 495 | ret = IIO_VAL_INT; | ||
| 411 | break; | 496 | break; |
| 412 | case IIO_CHAN_INFO_FREQUENCY: | 497 | case IIO_CHAN_INFO_FREQUENCY: |
| 413 | st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR; | 498 | st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR; |
| 414 | st->param.sensor_odr.data = | 499 | st->param.sensor_odr.data = |
| 415 | EC_MOTION_SENSE_NO_VALUE; | 500 | EC_MOTION_SENSE_NO_VALUE; |
| 416 | 501 | ||
| 417 | if (cros_ec_motion_send_host_cmd(st, 0)) | 502 | ret = cros_ec_motion_send_host_cmd(st, 0); |
| 418 | ret = -EIO; | 503 | if (ret) |
| 419 | else | 504 | break; |
| 420 | *val = st->resp->sensor_odr.ret; | 505 | |
| 506 | *val = st->resp->sensor_odr.ret; | ||
| 507 | ret = IIO_VAL_INT; | ||
| 421 | break; | 508 | break; |
| 422 | default: | 509 | default: |
| 510 | ret = -EINVAL; | ||
| 423 | break; | 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 | EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read); | 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 | int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, | 539 | int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, |
| 431 | struct iio_chan_spec const *chan, | 540 | struct iio_chan_spec const *chan, |
| 432 | int val, int val2, long mask) | 541 | int val, int val2, long mask) |
| 433 | { | 542 | { |
| 434 | int ret = 0; | 543 | int ret; |
| 435 | 544 | ||
| 436 | switch (mask) { | 545 | switch (mask) { |
| 437 | case IIO_CHAN_INFO_FREQUENCY: | 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 | /* Always roundup, so caller gets at least what it asks for. */ | 550 | /* Always roundup, so caller gets at least what it asks for. */ |
| 442 | st->param.sensor_odr.roundup = 1; | 551 | st->param.sensor_odr.roundup = 1; |
| 443 | 552 | ||
| 444 | if (cros_ec_motion_send_host_cmd(st, 0)) | 553 | ret = cros_ec_motion_send_host_cmd(st, 0); |
| 445 | ret = -EIO; | ||
| 446 | break; | 554 | break; |
| 447 | case IIO_CHAN_INFO_SAMP_FREQ: | 555 | case IIO_CHAN_INFO_SAMP_FREQ: |
| 448 | st->param.cmd = MOTIONSENSE_CMD_EC_RATE; | 556 | st->param.cmd = MOTIONSENSE_CMD_EC_RATE; |
| 449 | st->param.ec_rate.data = val; | 557 | st->param.ec_rate.data = val; |
| 450 | 558 | ||
| 451 | if (cros_ec_motion_send_host_cmd(st, 0)) | 559 | ret = cros_ec_motion_send_host_cmd(st, 0); |
| 452 | ret = -EIO; | 560 | if (ret) |
| 453 | else | 561 | break; |
| 454 | st->curr_sampl_freq = val; | 562 | st->curr_sampl_freq = val; |
| 455 | break; | 563 | break; |
| 456 | default: | 564 | default: |
| 457 | ret = -EINVAL; | 565 | ret = -EINVAL; |
| @@ -17,15 +17,16 @@ · 16 unmodified lines | |||
| 17 | #include <linux/iio/trigger_consumer.h> | 17 | #include <linux/iio/trigger_consumer.h> |
| 18 | #include <linux/iio/triggered_buffer.h> | 18 | #include <linux/iio/triggered_buffer.h> |
| 19 | #include <linux/irqreturn.h> | 19 | #include <linux/irqreturn.h> |
| 20 | #include <linux/regmap.h> | ||
| 20 | 21 | ||
| 21 | #include <linux/iio/common/st_sensors.h> | 22 | #include <linux/iio/common/st_sensors.h> |
| 22 | 23 | ||
| 23 | 24 | ||
| 24 | static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) | 25 | static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) |
| 25 | { | 26 | { |
| 26 | int i; | ||
| 27 | struct st_sensor_data *sdata = iio_priv(indio_dev); | 27 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
| 28 | unsigned int num_data_channels = sdata->num_data_channels; | 28 | unsigned int num_data_channels = sdata->num_data_channels; |
| 29 | int i; | ||
| 29 | 30 | ||
| 30 | for_each_set_bit(i, indio_dev->active_scan_mask, num_data_channels) { | 31 | for_each_set_bit(i, indio_dev->active_scan_mask, num_data_channels) { |
| 31 | const struct iio_chan_spec *channel = &indio_dev->channels[i]; | 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 | channel->scan_type.storagebits >> 3; | 37 | channel->scan_type.storagebits >> 3; |
| 37 | 38 | ||
| 38 | buf = PTR_ALIGN(buf, storage_bytes); | 39 | buf = PTR_ALIGN(buf, storage_bytes); |
| 39 | if (sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, | 40 | if (regmap_bulk_read(sdata->regmap, channel->address, |
| 40 | channel->address, | 41 | buf, bytes_to_read) < 0) |
| 41 | bytes_to_read, buf, | ||
| 42 | sdata->multiread_bit) < | ||
| 43 | bytes_to_read) | ||
| 44 | return -EIO; | 42 | return -EIO; |
| 45 | 43 | ||
| 46 | /* Advance the buffer pointer */ | 44 | /* Advance the buffer pointer */ |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | |||
| 15 | #include <linux/regulator/consumer.h> | 15 | #include <linux/regulator/consumer.h> |
| 16 | #include <linux/of.h> | 16 | #include <linux/of.h> |
| 17 | #include <linux/of_device.h> | 17 | #include <linux/of_device.h> |
| 18 | #include <linux/regmap.h> | ||
| 18 | #include <asm/unaligned.h> | 19 | #include <asm/unaligned.h> |
| 19 | #include <linux/iio/common/st_sensors.h> | 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 | int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, | 29 | int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, |
| 29 | u8 reg_addr, u8 mask, u8 data) | 30 | u8 reg_addr, u8 mask, u8 data) |
| 30 | { | 31 | { |
| 31 | int err; | ||
| 32 | u8 new_data; | ||
| 33 | struct st_sensor_data *sdata = iio_priv(indio_dev); | 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); | 34 | return regmap_update_bits(sdata->regmap, |
| 36 | if (err < 0) | 35 | reg_addr, mask, data << __ffs(mask)); |
| 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; | ||
| 44 | } | 36 | } |
| 45 | 37 | ||
| 46 | int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, | 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 | unsigned *readval) | 40 | unsigned *readval) |
| 49 | { | 41 | { |
| 50 | struct st_sensor_data *sdata = iio_priv(indio_dev); | 42 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
| 51 | u8 readdata; | ||
| 52 | int err; | 43 | int err; |
| 53 | 44 | ||
| 54 | if (!readval) | 45 | if (!readval) |
| 55 | return sdata->tf->write_byte(&sdata->tb, sdata->dev, | 46 | return regmap_write(sdata->regmap, reg, writeval); |
| 56 | (u8)reg, (u8)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 | if (err < 0) | 49 | if (err < 0) |
| 60 | return err; | 50 | return err; |
| 61 | 51 | ||
| 62 | *readval = (unsigned)readdata; | ||
| 63 | |||
| 64 | return 0; | 52 | return 0; |
| 65 | } | 53 | } |
| 66 | EXPORT_SYMBOL(st_sensors_debugfs_reg_access); | 54 | EXPORT_SYMBOL(st_sensors_debugfs_reg_access); |
| @@ -545,7 +533,7 @@ st_sensors_match_scale_error: · 478 unmodified lines | |||
| 545 | EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain); | 533 | EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain); |
| 546 | 534 | ||
| 547 | static int st_sensors_read_axis_data(struct iio_dev *indio_dev, | 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 | int err; | 538 | int err; |
| 551 | u8 *outdata; | 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 | byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits + | 543 | byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits + |
| 556 | ch->scan_type.shift, 8); | 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 | if (!outdata) | 546 | if (!outdata) |
| 559 | return -ENOMEM; | 547 | return -ENOMEM; |
| 560 | 548 | ||
| 561 | err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev, | 549 | err = regmap_bulk_read(sdata->regmap, ch->address, |
| 562 | ch->address, byte_for_channel, | 550 | outdata, byte_for_channel); |
| 563 | outdata, sdata->multiread_bit); | ||
| 564 | if (err < 0) | 551 | if (err < 0) |
| 565 | goto st_sensors_free_memory; | 552 | goto st_sensors_free_memory; |
| 566 | 553 | ||
| @@ -608,69 +595,55 @@ out: · 41 unmodified lines | |||
| 608 | } | 595 | } |
| 609 | EXPORT_SYMBOL(st_sensors_read_info_raw); | 596 | EXPORT_SYMBOL(st_sensors_read_info_raw); |
| 610 | 597 | ||
| 611 | static int st_sensors_init_interface_mode(struct iio_dev *indio_dev, | 598 | /* |
| 612 | const struct st_sensor_settings *sensor_settings) | 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); | 612 | int i, n; |
| 615 | struct device_node *np = sdata->dev->of_node; | ||
| 616 | struct st_sensors_platform_data *pdata; | ||
| 617 | 613 | ||
| 618 | pdata = (struct st_sensors_platform_data *)sdata->dev->platform_data; | 614 | for (i = 0; i < list_length; i++) { |
| 619 | if (((np && of_property_read_bool(np, "spi-3wire")) || | 615 | for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) { |
| 620 | (pdata && pdata->spi_3wire)) && sensor_settings->sim.addr) { | 616 | if (strcmp(name, list[i].sensors_supported[n]) == 0) |
| 621 | int err; | 617 | return i; |
| 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; | ||
| 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, | 625 | /* |
| 637 | int num_sensors_list, | 626 | * st_sensors_verify_id() - verify sensor ID (WhoAmI) is matching with the |
| 638 | const struct st_sensor_settings *sensor_settings) | 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 | struct st_sensor_data *sdata = iio_priv(indio_dev); | 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++) { | 637 | if (sdata->sensor_settings->wai_addr) { |
| 645 | for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) { | 638 | err = regmap_read(sdata->regmap, |
| 646 | if (strcmp(indio_dev->name, | 639 | sdata->sensor_settings->wai_addr, &wai); |
| 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); | ||
| 667 | if (err < 0) { | 640 | if (err < 0) { |
| 668 | dev_err(&indio_dev->dev, | 641 | dev_err(&indio_dev->dev, |
| 669 | "failed to read Who-Am-I register.\n"); | 642 | "failed to read Who-Am-I register.\n"); |
| 670 | return err; | 643 | return err; |
| 671 | } | 644 | } |
| 672 | 645 | ||
| 673 | if (sensor_settings[i].wai != wai) { | 646 | if (sdata->sensor_settings->wai != wai) { |
| 674 | dev_err(&indio_dev->dev, | 647 | dev_err(&indio_dev->dev, |
| 675 | "%s: WhoAmI mismatch (0x%x).\n", | 648 | "%s: WhoAmI mismatch (0x%x).\n", |
| 676 | indio_dev->name, wai); | 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 = | 654 | return 0; |
| 682 | (struct st_sensor_settings *)&sensor_settings[i]; | ||
| 683 | |||
| 684 | return i; | ||
| 685 | } | 655 | } |
| 686 | EXPORT_SYMBOL(st_sensors_check_device_support); | 656 | EXPORT_SYMBOL(st_sensors_verify_id); |
| 687 | 657 | ||
| 688 | ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, | 658 | ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, |
| 689 | struct device_attribute *attr, char *buf) | 659 | struct device_attribute *attr, char *buf) |
| @@ -13,68 +13,58 @@ · 12 unmodified lines | |||
| 13 | #include <linux/iio/iio.h> | 13 | #include <linux/iio/iio.h> |
| 14 | #include <linux/of_device.h> | 14 | #include <linux/of_device.h> |
| 15 | #include <linux/acpi.h> | 15 | #include <linux/acpi.h> |
| 16 | #include <linux/regmap.h> | ||
| 16 | 17 | ||
| 17 | #include <linux/iio/common/st_sensors_i2c.h> | 18 | #include <linux/iio/common/st_sensors_i2c.h> |
| 18 | 19 | ||
| 19 | 20 | ||
| 20 | #define ST_SENSORS_I2C_MULTIREAD 0x80 | 21 | #define ST_SENSORS_I2C_MULTIREAD 0x80 |
| 21 | 22 | ||
| 22 | static unsigned int st_sensors_i2c_get_irq(struct iio_dev *indio_dev) | 23 | static const struct regmap_config st_sensors_i2c_regmap_config = { |
| 23 | { | 24 | .reg_bits = 8, |
| 24 | struct st_sensor_data *sdata = iio_priv(indio_dev); | 25 | .val_bits = 8, |
| 25 | 26 | }; | |
| 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 | } | ||
| 60 | 27 | ||
| 61 | static const struct st_sensor_transfer_function st_sensors_tf_i2c = { | 28 | static const struct regmap_config st_sensors_i2c_regmap_multiread_bit_config = { |
| 62 | .read_byte = st_sensors_i2c_read_byte, | 29 | .reg_bits = 8, |
| 63 | .write_byte = st_sensors_i2c_write_byte, | 30 | .val_bits = 8, |
| 64 | .read_multiple_byte = st_sensors_i2c_read_multiple_byte, | 31 | .read_flag_mask = ST_SENSORS_I2C_MULTIREAD, |
| 65 | }; | 32 | }; |
| 66 | 33 | ||
| 67 | void st_sensors_i2c_configure(struct iio_dev *indio_dev, | 34 | /* |
| 68 | struct i2c_client *client, struct st_sensor_data *sdata) | 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 | i2c_set_clientdata(client, indio_dev); | 59 | i2c_set_clientdata(client, indio_dev); |
| 71 | 60 | ||
| 72 | indio_dev->dev.parent = &client->dev; | 61 | indio_dev->dev.parent = &client->dev; |
| 73 | indio_dev->name = client->name; | 62 | indio_dev->name = client->name; |
| 74 | 63 | ||
| 75 | sdata->dev = &client->dev; | 64 | sdata->dev = &client->dev; |
| 76 | sdata->tf = &st_sensors_tf_i2c; | 65 | sdata->irq = client->irq; |
| 77 | sdata->get_irq_data_ready = st_sensors_i2c_get_irq; | 66 | |
| 67 | return 0; | ||
| 78 | } | 68 | } |
| 79 | EXPORT_SYMBOL(st_sensors_i2c_configure); | 69 | EXPORT_SYMBOL(st_sensors_i2c_configure); |
| 80 | 70 | ||
| @@ -11,108 +11,108 @@ · 10 unmodified lines | |||
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/iio/iio.h> | 13 | #include <linux/iio/iio.h> |
| 14 | #include <linux/regmap.h> | ||
| 14 | 15 | ||
| 15 | #include <linux/iio/common/st_sensors_spi.h> | 16 | #include <linux/iio/common/st_sensors_spi.h> |
| 16 | 17 | #include "st_sensors_core.h" | |
| 17 | 18 | ||
| 18 | #define ST_SENSORS_SPI_MULTIREAD 0xc0 | 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) | 21 | static const struct regmap_config st_sensors_spi_regmap_config = { |
| 22 | { | 22 | .reg_bits = 8, |
| 23 | struct st_sensor_data *sdata = iio_priv(indio_dev); | 23 | .val_bits = 8, |
| 24 | }; | ||
| 24 | 25 | ||
| 25 | return to_spi_device(sdata->dev)->irq; | 26 | static const struct regmap_config st_sensors_spi_regmap_multiread_bit_config = { |
| 26 | } | 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, | 32 | /* |
| 29 | struct device *dev, u8 reg_addr, int len, u8 *data, bool multiread_bit) | 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; | 40 | struct device_node *np = spi->dev.of_node; |
| 32 | 41 | struct st_sensors_platform_data *pdata; | |
| 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; | ||
| 51 | 42 | ||
| 52 | err = spi_sync_transfer(to_spi_device(dev), xfers, ARRAY_SIZE(xfers)); | 43 | pdata = (struct st_sensors_platform_data *)spi->dev.platform_data; |
| 53 | if (err) | 44 | if ((np && of_property_read_bool(np, "spi-3wire")) || |
| 54 | goto acc_spi_read_error; | 45 | (pdata && pdata->spi_3wire)) { |
| 46 | return true; | ||
| 47 | } | ||
| 55 | 48 | ||
| 56 | memcpy(data, tb->rx_buf, len); | 49 | return false; |
| 57 | mutex_unlock(&tb->buf_lock); | ||
| 58 | return len; | ||
| 59 | |||
| 60 | acc_spi_read_error: | ||
| 61 | mutex_unlock(&tb->buf_lock); | ||
| 62 | return err; | ||
| 63 | } | 50 | } |
| 64 | 51 | ||
| 65 | static int st_sensors_spi_read_byte(struct st_sensor_transfer_buffer *tb, | 52 | /* |
| 66 | struct device *dev, u8 reg_addr, u8 *res_byte) | 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); | 62 | if (settings->sim.addr) { |
| 69 | } | 63 | u8 buffer[] = { |
| 64 | settings->sim.addr, | ||
| 65 | settings->sim.value | ||
| 66 | }; | ||
| 70 | 67 | ||
| 71 | static int st_sensors_spi_read_multiple_byte( | 68 | return spi_write(spi, buffer, 2); |
| 72 | struct st_sensor_transfer_buffer *tb, struct device *dev, | 69 | } |
| 73 | u8 reg_addr, int len, u8 *data, bool multiread_bit) | 70 | |
| 74 | { | 71 | return 0; |
| 75 | return st_sensors_spi_read(tb, dev, reg_addr, len, data, multiread_bit); | ||
| 76 | } | 72 | } |
| 77 | 73 | ||
| 78 | static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb, | 74 | /* |
| 79 | struct device *dev, u8 reg_addr, u8 data) | 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 | int err; | 86 | int err; |
| 82 | 87 | ||
| 83 | struct spi_transfer xfers = { | 88 | if (st_sensors_is_spi_3_wire(spi)) { |
| 84 | .tx_buf = tb->tx_buf, | 89 | err = st_sensors_configure_spi_3_wire(spi, |
| 85 | .bits_per_word = 8, | 90 | sdata->sensor_settings); |
| 86 | .len = 2, | 91 | if (err < 0) |
| 87 | }; | 92 | return err; |
| 93 | } | ||
| 88 | 94 | ||
| 89 | mutex_lock(&tb->buf_lock); | 95 | if (sdata->sensor_settings->multi_read_bit) |
| 90 | tb->tx_buf[0] = reg_addr; | 96 | config = &st_sensors_spi_regmap_multiread_bit_config; |
| 91 | tb->tx_buf[1] = data; | 97 | else |
| 92 | 98 | config = &st_sensors_spi_regmap_config; | |
| 93 | err = spi_sync_transfer(to_spi_device(dev), &xfers, 1); | ||
| 94 | mutex_unlock(&tb->buf_lock); | ||
| 95 | 99 | ||
| 96 | return err; | 100 | sdata->regmap = devm_regmap_init_spi(spi, config); |
| 97 | } | 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 | spi_set_drvdata(spi, indio_dev); | 107 | spi_set_drvdata(spi, indio_dev); |
| 109 | 108 | ||
| 110 | indio_dev->dev.parent = &spi->dev; | 109 | indio_dev->dev.parent = &spi->dev; |
| 111 | indio_dev->name = spi->modalias; | 110 | indio_dev->name = spi->modalias; |
| 112 | 111 | ||
| 113 | sdata->dev = &spi->dev; | 112 | sdata->dev = &spi->dev; |
| 114 | sdata->tf = &st_sensors_tf_spi; | 113 | sdata->irq = spi->irq; |
| 115 | sdata->get_irq_data_ready = st_sensors_spi_get_irq; | 114 | |
| 115 | return 0; | ||
| 116 | } | 116 | } |
| 117 | EXPORT_SYMBOL(st_sensors_spi_configure); | 117 | EXPORT_SYMBOL(st_sensors_spi_configure); |
| 118 | 118 | ||
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/iio/iio.h> | 13 | #include <linux/iio/iio.h> |
| 14 | #include <linux/iio/trigger.h> | 14 | #include <linux/iio/trigger.h> |
| 15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| 16 | #include <linux/regmap.h> | ||
| 16 | #include <linux/iio/common/st_sensors.h> | 17 | #include <linux/iio/common/st_sensors.h> |
| 17 | #include "st_sensors_core.h" | 18 | #include "st_sensors_core.h" |
| 18 | 19 | ||
| @@ -26,8 +27,7 @@ · 7 unmodified lines | |||
| 26 | static int st_sensors_new_samples_available(struct iio_dev *indio_dev, | 27 | static int st_sensors_new_samples_available(struct iio_dev *indio_dev, |
| 27 | struct st_sensor_data *sdata) | 28 | struct st_sensor_data *sdata) |
| 28 | { | 29 | { |
| 29 | u8 status; | 30 | int ret, status; |
| 30 | int ret; | ||
| 31 | 31 | ||
| 32 | /* How would I know if I can't check it? */ | 32 | /* How would I know if I can't check it? */ |
| 33 | if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr) | 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 | if (!indio_dev->active_scan_mask) | 37 | if (!indio_dev->active_scan_mask) |
| 38 | return 0; | 38 | return 0; |
| 39 | 39 | ||
| 40 | ret = sdata->tf->read_byte(&sdata->tb, sdata->dev, | 40 | ret = regmap_read(sdata->regmap, |
| 41 | sdata->sensor_settings->drdy_irq.stat_drdy.addr, | 41 | sdata->sensor_settings->drdy_irq.stat_drdy.addr, |
| 42 | &status); | 42 | &status); |
| 43 | if (ret < 0) { | 43 | if (ret < 0) { |
| 44 | dev_err(sdata->dev, | 44 | dev_err(sdata->dev, |
| 45 | "error checking samples available\n"); | 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 | int st_sensors_allocate_trigger(struct iio_dev *indio_dev, | 121 | int st_sensors_allocate_trigger(struct iio_dev *indio_dev, |
| 122 | const struct iio_trigger_ops *trigger_ops) | 122 | const struct iio_trigger_ops *trigger_ops) |
| 123 | { | 123 | { |
| 124 | int err, irq; | ||
| 125 | struct st_sensor_data *sdata = iio_priv(indio_dev); | 124 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
| 126 | unsigned long irq_trig; | 125 | unsigned long irq_trig; |
| 126 | int err; | ||
| 127 | 127 | ||
| 128 | sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name); | 128 | sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name); |
| 129 | if (sdata->trig == NULL) { | 129 | if (sdata->trig == NULL) { |
| @@ -135,8 +135,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, · 5 unmodified lines | |||
| 135 | sdata->trig->ops = trigger_ops; | 135 | sdata->trig->ops = trigger_ops; |
| 136 | sdata->trig->dev.parent = sdata->dev; | 136 | sdata->trig->dev.parent = sdata->dev; |
| 137 | 137 | ||
| 138 | irq = sdata->get_irq_data_ready(indio_dev); | 138 | irq_trig = irqd_get_trigger_type(irq_get_irq_data(sdata->irq)); |
| 139 | irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); | ||
| 140 | /* | 139 | /* |
| 141 | * If the IRQ is triggered on falling edge, we need to mark the | 140 | * If the IRQ is triggered on falling edge, we need to mark the |
| 142 | * interrupt as active low, if the hardware supports this. | 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 | sdata->sensor_settings->drdy_irq.stat_drdy.addr) | 205 | sdata->sensor_settings->drdy_irq.stat_drdy.addr) |
| 207 | irq_trig |= IRQF_SHARED; | 206 | irq_trig |= IRQF_SHARED; |
| 208 | 207 | ||
| 209 | err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev), | 208 | err = request_threaded_irq(sdata->irq, |
| 210 | st_sensors_irq_handler, | 209 | st_sensors_irq_handler, |
| 211 | st_sensors_irq_thread, | 210 | st_sensors_irq_thread, |
| 212 | irq_trig, | 211 | irq_trig, |
| 213 | sdata->trig->name, | 212 | sdata->trig->name, |
| 214 | sdata->trig); | 213 | sdata->trig); |
| 215 | if (err) { | 214 | if (err) { |
| 216 | dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); | 215 | dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); |
| 217 | goto iio_trigger_free; | 216 | goto iio_trigger_free; |
| @@ -227,7 +226,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, · 9 unmodified lines | |||
| 227 | return 0; | 226 | return 0; |
| 228 | 227 | ||
| 229 | iio_trigger_register_error: | 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 | iio_trigger_free: | 230 | iio_trigger_free: |
| 232 | iio_trigger_free(sdata->trig); | 231 | iio_trigger_free(sdata->trig); |
| 233 | return err; | 232 | return err; |
| @@ -239,7 +238,7 @@ void st_sensors_deallocate_trigger(struct iio_dev *indio_dev) · 5 unmodified lines | |||
| 239 | struct st_sensor_data *sdata = iio_priv(indio_dev); | 238 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
| 240 | 239 | ||
| 241 | iio_trigger_unregister(sdata->trig); | 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 | iio_trigger_free(sdata->trig); | 242 | iio_trigger_free(sdata->trig); |
| 244 | } | 243 | } |
| 245 | EXPORT_SYMBOL(st_sensors_deallocate_trigger); | 244 | EXPORT_SYMBOL(st_sensors_deallocate_trigger); |
| @@ -32,6 +32,7 @@ static const struct st_sensors_platform_data gyro_pdata = { · 31 unmodified lines | |||
| 32 | .drdy_int_pin = 2, | 32 | .drdy_int_pin = 2, |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | const struct st_sensor_settings *st_gyro_get_settings(const char *name); | ||
| 35 | int st_gyro_common_probe(struct iio_dev *indio_dev); | 36 | int st_gyro_common_probe(struct iio_dev *indio_dev); |
| 36 | void st_gyro_common_remove(struct iio_dev *indio_dev); | 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 | return st_sensors_set_dataready_irq(indio_dev, state); | 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 | static int st_gyro_buffer_postenable(struct iio_dev *indio_dev) | 32 | static int st_gyro_buffer_postenable(struct iio_dev *indio_dev) |
| 38 | { | 33 | { |
| 39 | int err; | 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); | 36 | err = iio_triggered_buffer_postenable(indio_dev); |
| 43 | if (gdata->buffer_data == NULL) { | 37 | if (err < 0) |
| 44 | err = -ENOMEM; | 38 | return err; |
| 45 | goto allocate_memory_error; | ||
| 46 | } | ||
| 47 | 39 | ||
| 48 | err = st_sensors_set_axis_enable(indio_dev, | 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 | if (err < 0) | 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 | if (err < 0) | 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: | 51 | st_gyro_buffer_enable_all_axis: |
| 60 | kfree(gdata->buffer_data); | 52 | st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); |
| 61 | allocate_memory_error: | 53 | st_gyro_buffer_predisable: |
| 54 | iio_triggered_buffer_predisable(indio_dev); | ||
| 62 | return err; | 55 | return err; |
| 63 | } | 56 | } |
| 64 | 57 | ||
| 65 | static int st_gyro_buffer_predisable(struct iio_dev *indio_dev) | 58 | static int st_gyro_buffer_predisable(struct iio_dev *indio_dev) |
| 66 | { | 59 | { |
| 67 | int err; | 60 | int err, err2; |
| 68 | struct st_sensor_data *gdata = iio_priv(indio_dev); | ||
| 69 | 61 | ||
| 70 | err = iio_triggered_buffer_predisable(indio_dev); | 62 | err = st_sensors_set_enable(indio_dev, false); |
| 71 | if (err < 0) | 63 | if (err < 0) |
| 72 | goto st_gyro_buffer_predisable_error; | 64 | goto st_gyro_buffer_predisable; |
| 73 | 65 | ||
| 74 | err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); | 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 | return err; | 73 | return err; |
| 83 | } | 74 | } |
| 84 | 75 | ||
| 85 | static const struct iio_buffer_setup_ops st_gyro_buffer_setup_ops = { | 76 | static const struct iio_buffer_setup_ops st_gyro_buffer_setup_ops = { |
| 86 | .preenable = &st_gyro_buffer_preenable, | ||
| 87 | .postenable = &st_gyro_buffer_postenable, | 77 | .postenable = &st_gyro_buffer_postenable, |
| 88 | .predisable = &st_gyro_buffer_predisable, | 78 | .predisable = &st_gyro_buffer_predisable, |
| 89 | }; | 79 | }; |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | |||
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
| 14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
| 15 | #include <linux/mutex.h> | ||
| 16 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| 17 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
| 18 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
| @@ -368,28 +367,41 @@ static const struct iio_trigger_ops st_gyro_trigger_ops = { · 349 unmodified lines | |||
| 368 | #define ST_GYRO_TRIGGER_OPS NULL | 367 | #define ST_GYRO_TRIGGER_OPS NULL |
| 369 | #endif | 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 | int st_gyro_common_probe(struct iio_dev *indio_dev) | 388 | int st_gyro_common_probe(struct iio_dev *indio_dev) |
| 372 | { | 389 | { |
| 373 | struct st_sensor_data *gdata = iio_priv(indio_dev); | 390 | struct st_sensor_data *gdata = iio_priv(indio_dev); |
| 374 | int irq = gdata->get_irq_data_ready(indio_dev); | ||
| 375 | int err; | 391 | int err; |
| 376 | 392 | ||
| 377 | indio_dev->modes = INDIO_DIRECT_MODE; | 393 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 378 | indio_dev->info = &gyro_info; | 394 | indio_dev->info = &gyro_info; |
| 379 | mutex_init(&gdata->tb.buf_lock); | ||
| 380 | 395 | ||
| 381 | err = st_sensors_power_enable(indio_dev); | 396 | err = st_sensors_power_enable(indio_dev); |
| 382 | if (err) | 397 | if (err) |
| 383 | return err; | 398 | return err; |
| 384 | 399 | ||
| 385 | err = st_sensors_check_device_support(indio_dev, | 400 | err = st_sensors_verify_id(indio_dev); |
| 386 | ARRAY_SIZE(st_gyro_sensors_settings), | ||
| 387 | st_gyro_sensors_settings); | ||
| 388 | if (err < 0) | 401 | if (err < 0) |
| 389 | goto st_gyro_power_off; | 402 | goto st_gyro_power_off; |
| 390 | 403 | ||
| 391 | gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS; | 404 | gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS; |
| 392 | gdata->multiread_bit = gdata->sensor_settings->multi_read_bit; | ||
| 393 | indio_dev->channels = gdata->sensor_settings->ch; | 405 | indio_dev->channels = gdata->sensor_settings->ch; |
| 394 | indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; | 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 | if (err < 0) | 418 | if (err < 0) |
| 407 | goto st_gyro_power_off; | 419 | goto st_gyro_power_off; |
| 408 | 420 | ||
| 409 | if (irq > 0) { | 421 | if (gdata->irq > 0) { |
| 410 | err = st_sensors_allocate_trigger(indio_dev, | 422 | err = st_sensors_allocate_trigger(indio_dev, |
| 411 | ST_GYRO_TRIGGER_OPS); | 423 | ST_GYRO_TRIGGER_OPS); |
| 412 | if (err < 0) | 424 | if (err < 0) |
| @@ -423,7 +435,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev) · 10 unmodified lines | |||
| 423 | return 0; | 435 | return 0; |
| 424 | 436 | ||
| 425 | st_gyro_device_register_error: | 437 | st_gyro_device_register_error: |
| 426 | if (irq > 0) | 438 | if (gdata->irq > 0) |
| 427 | st_sensors_deallocate_trigger(indio_dev); | 439 | st_sensors_deallocate_trigger(indio_dev); |
| 428 | st_gyro_probe_trigger_error: | 440 | st_gyro_probe_trigger_error: |
| 429 | st_gyro_deallocate_ring(indio_dev); | 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 | st_sensors_power_disable(indio_dev); | 453 | st_sensors_power_disable(indio_dev); |
| 442 | 454 | ||
| 443 | iio_device_unregister(indio_dev); | 455 | iio_device_unregister(indio_dev); |
| 444 | if (gdata->get_irq_data_ready(indio_dev) > 0) | 456 | if (gdata->irq > 0) |
| 445 | st_sensors_deallocate_trigger(indio_dev); | 457 | st_sensors_deallocate_trigger(indio_dev); |
| 446 | 458 | ||
| 447 | st_gyro_deallocate_ring(indio_dev); | 459 | st_gyro_deallocate_ring(indio_dev); |
| @@ -63,21 +63,33 @@ MODULE_DEVICE_TABLE(of, st_gyro_of_match); · 62 unmodified lines | |||
| 63 | #endif | 63 | #endif |
| 64 | 64 | ||
| 65 | static int st_gyro_i2c_probe(struct i2c_client *client, | 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 | struct st_sensor_data *gdata; | 69 | struct st_sensor_data *gdata; |
| 70 | struct iio_dev *indio_dev; | ||
| 70 | int err; | 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 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*gdata)); | 83 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*gdata)); |
| 73 | if (!indio_dev) | 84 | if (!indio_dev) |
| 74 | return -ENOMEM; | 85 | return -ENOMEM; |
| 75 | 86 | ||
| 76 | gdata = iio_priv(indio_dev); | 87 | gdata = iio_priv(indio_dev); |
| 77 | st_sensors_of_name_probe(&client->dev, st_gyro_of_match, | 88 | gdata->sensor_settings = (struct st_sensor_settings *)settings; |
| 78 | client->name, sizeof(client->name)); | ||
| 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 | err = st_gyro_common_probe(indio_dev); | 94 | err = st_gyro_common_probe(indio_dev); |
| 83 | if (err < 0) | 95 | if (err < 0) |
| @@ -69,19 +69,31 @@ MODULE_DEVICE_TABLE(of, st_gyro_of_match); · 68 unmodified lines | |||
| 69 | 69 | ||
| 70 | static int st_gyro_spi_probe(struct spi_device *spi) | 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 | struct st_sensor_data *gdata; | 73 | struct st_sensor_data *gdata; |
| 74 | struct iio_dev *indio_dev; | ||
| 74 | int err; | 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 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*gdata)); | 87 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*gdata)); |
| 77 | if (!indio_dev) | 88 | if (!indio_dev) |
| 78 | return -ENOMEM; | 89 | return -ENOMEM; |
| 79 | 90 | ||
| 80 | gdata = iio_priv(indio_dev); | 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, | 94 | err = st_sensors_spi_configure(indio_dev, spi); |
| 83 | spi->modalias, sizeof(spi->modalias)); | 95 | if (err < 0) |
| 84 | st_sensors_spi_configure(indio_dev, spi, gdata); | 96 | return err; |
| 85 | 97 | ||
| 86 | err = st_gyro_common_probe(indio_dev); | 98 | err = st_gyro_common_probe(indio_dev); |
| 87 | if (err < 0) | 99 | if (err < 0) |
| @@ -240,32 +240,15 @@ static int am2315_probe(struct i2c_client *client, · 239 unmodified lines | |||
| 240 | indio_dev->channels = am2315_channels; | 240 | indio_dev->channels = am2315_channels; |
| 241 | indio_dev->num_channels = ARRAY_SIZE(am2315_channels); | 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 | am2315_trigger_handler, NULL); | 245 | am2315_trigger_handler, NULL); |
| 245 | if (ret < 0) { | 246 | if (ret < 0) { |
| 246 | dev_err(&client->dev, "iio triggered buffer setup failed\n"); | 247 | dev_err(&client->dev, "iio triggered buffer setup failed\n"); |
| 247 | return ret; | 248 | return ret; |
| 248 | } | 249 | } |
| 249 | 250 | ||
| 250 | ret = iio_device_register(indio_dev); | 251 | return devm_iio_device_register(&client->dev, 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; | ||
| 269 | } | 252 | } |
| 270 | 253 | ||
| 271 | static const struct i2c_device_id am2315_i2c_id[] = { | 254 | static const struct i2c_device_id am2315_i2c_id[] = { |
| @@ -287,7 +270,6 @@ static struct i2c_driver am2315_driver = { · 15 unmodified lines | |||
| 287 | .acpi_match_table = ACPI_PTR(am2315_acpi_id), | 270 | .acpi_match_table = ACPI_PTR(am2315_acpi_id), |
| 288 | }, | 271 | }, |
| 289 | .probe = am2315_probe, | 272 | .probe = am2315_probe, |
| 290 | .remove = am2315_remove, | ||
| 291 | .id_table = am2315_i2c_id, | 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 | hdc100x_set_it_time(data, 1, hdc100x_int_time[1][0]); | 385 | hdc100x_set_it_time(data, 1, hdc100x_int_time[1][0]); |
| 386 | hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0); | 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 | hdc100x_trigger_handler, | 390 | hdc100x_trigger_handler, |
| 390 | &hdc_buffer_setup_ops); | 391 | &hdc_buffer_setup_ops); |
| 391 | if (ret < 0) { | 392 | if (ret < 0) { |
| 392 | dev_err(&client->dev, "iio triggered buffer setup failed\n"); | 393 | dev_err(&client->dev, "iio triggered buffer setup failed\n"); |
| 393 | return ret; | 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; | 397 | return devm_iio_device_register(&client->dev, indio_dev); |
| 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; | ||
| 410 | } | 398 | } |
| 411 | 399 | ||
| 412 | static const struct i2c_device_id hdc100x_id[] = { | 400 | static const struct i2c_device_id hdc100x_id[] = { |
| @@ -436,7 +424,6 @@ static struct i2c_driver hdc100x_driver = { · 23 unmodified lines | |||
| 436 | .of_match_table = of_match_ptr(hdc100x_dt_ids), | 424 | .of_match_table = of_match_ptr(hdc100x_dt_ids), |
| 437 | }, | 425 | }, |
| 438 | .probe = hdc100x_probe, | 426 | .probe = hdc100x_probe, |
| 439 | .remove = hdc100x_remove, | ||
| 440 | .id_table = hdc100x_id, | 427 | .id_table = hdc100x_id, |
| 441 | }; | 428 | }; |
| 442 | module_i2c_driver(hdc100x_driver); | 429 | module_i2c_driver(hdc100x_driver); |
| @@ -17,6 +17,18 @@ config ADIS16400 · 16 unmodified lines | |||
| 17 | adis16365, adis16400 and adis16405 triaxial inertial sensors | 17 | adis16365, adis16400 and adis16405 triaxial inertial sensors |
| 18 | (adis16400 series also have magnetometers). | 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 | config ADIS16480 | 32 | config ADIS16480 |
| 21 | tristate "Analog Devices ADIS16480 and similar IMU driver" | 33 | tristate "Analog Devices ADIS16480 and similar IMU driver" |
| 22 | depends on SPI | 34 | depends on SPI |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | |||
| 5 | 5 | ||
| 6 | # When adding new entries keep the list in alphabetical order | 6 | # When adding new entries keep the list in alphabetical order |
| 7 | obj-$(CONFIG_ADIS16400) += adis16400.o | 7 | obj-$(CONFIG_ADIS16400) += adis16400.o |
| 8 | obj-$(CONFIG_ADIS16460) += adis16460.o | ||
| 8 | obj-$(CONFIG_ADIS16480) += adis16480.o | 9 | obj-$(CONFIG_ADIS16480) += adis16480.o |
| 9 | 10 | ||
| 10 | adis_lib-y += adis.o | 11 | adis_lib-y += adis.o |
| @@ -39,18 +39,24 @@ int adis_write_reg(struct adis *adis, unsigned int reg, · 38 unmodified lines | |||
| 39 | .len = 2, | 39 | .len = 2, |
| 40 | .cs_change = 1, | 40 | .cs_change = 1, |
| 41 | .delay_usecs = adis->data->write_delay, | 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 | .tx_buf = adis->tx + 2, | 45 | .tx_buf = adis->tx + 2, |
| 44 | .bits_per_word = 8, | 46 | .bits_per_word = 8, |
| 45 | .len = 2, | 47 | .len = 2, |
| 46 | .cs_change = 1, | 48 | .cs_change = 1, |
| 47 | .delay_usecs = adis->data->write_delay, | 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 | .tx_buf = adis->tx + 4, | 53 | .tx_buf = adis->tx + 4, |
| 50 | .bits_per_word = 8, | 54 | .bits_per_word = 8, |
| 51 | .len = 2, | 55 | .len = 2, |
| 52 | .cs_change = 1, | 56 | .cs_change = 1, |
| 53 | .delay_usecs = adis->data->write_delay, | 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 | .tx_buf = adis->tx + 6, | 61 | .tx_buf = adis->tx + 6, |
| 56 | .bits_per_word = 8, | 62 | .bits_per_word = 8, |
| @@ -133,12 +139,16 @@ int adis_read_reg(struct adis *adis, unsigned int reg, · 76 unmodified lines | |||
| 133 | .len = 2, | 139 | .len = 2, |
| 134 | .cs_change = 1, | 140 | .cs_change = 1, |
| 135 | .delay_usecs = adis->data->write_delay, | 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 | .tx_buf = adis->tx + 2, | 145 | .tx_buf = adis->tx + 2, |
| 138 | .bits_per_word = 8, | 146 | .bits_per_word = 8, |
| 139 | .len = 2, | 147 | .len = 2, |
| 140 | .cs_change = 1, | 148 | .cs_change = 1, |
| 141 | .delay_usecs = adis->data->read_delay, | 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 | .tx_buf = adis->tx + 4, | 153 | .tx_buf = adis->tx + 4, |
| 144 | .rx_buf = adis->rx, | 154 | .rx_buf = adis->rx, |
| @@ -146,6 +156,8 @@ int adis_read_reg(struct adis *adis, unsigned int reg, · 1 unmodified line | |||
| 146 | .len = 2, | 156 | .len = 2, |
| 147 | .cs_change = 1, | 157 | .cs_change = 1, |
| 148 | .delay_usecs = adis->data->read_delay, | 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 | .rx_buf = adis->rx + 2, | 162 | .rx_buf = adis->rx + 2, |
| 151 | .bits_per_word = 8, | 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 | select INV_MPU6050_IIO | 14 | select INV_MPU6050_IIO |
| 15 | select REGMAP_I2C | 15 | select REGMAP_I2C |
| 16 | help | 16 | help |
| 17 | This driver supports the Invensense MPU6050/6500/9150 and | 17 | This driver supports the Invensense MPU6000/6050/6500/6515, |
| 18 | ICM20608/20602 motion tracking devices over I2C. | 18 | MPU9150/9250/9255 and ICM20608/20602 motion tracking devices |
| 19 | over I2C. | ||
| 19 | This driver can be built as a module. The module will be called | 20 | This driver can be built as a module. The module will be called |
| 20 | inv-mpu6050-i2c. | 21 | inv-mpu6050-i2c. |
| 21 | 22 | ||
| @@ -25,7 +26,8 @@ config INV_MPU6050_SPI · 3 unmodified lines | |||
| 25 | select INV_MPU6050_IIO | 26 | select INV_MPU6050_IIO |
| 26 | select REGMAP_SPI | 27 | select REGMAP_SPI |
| 27 | help | 28 | help |
| 28 | This driver supports the Invensense MPU6050/6500/9150 and | 29 | This driver supports the Invensense MPU6000/6050/6500/6515, |
| 29 | ICM20608/20602 motion tracking devices over SPI. | 30 | MPU9150/9250/9255 and ICM20608/20602 motion tracking devices |
| 31 | over SPI. | ||
| 30 | This driver can be built as a module. The module will be called | 32 | This driver can be built as a module. The module will be called |
| 31 | inv-mpu6050-spi. | 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 | if (result) | 1137 | if (result) |
| 1138 | return result; | 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 | st); | 1141 | st); |
| 1142 | if (result) { | 1142 | if (result) { |
| 1143 | inv_mpu_core_disable_regulator_action(st); | ||
| 1144 | dev_err(dev, "Failed to setup regulator cleanup action %d\n", | 1143 | dev_err(dev, "Failed to setup regulator cleanup action %d\n", |
| 1145 | result); | 1144 | result); |
| 1146 | return result; | 1145 | return result; |
| @@ -2,15 +2,17 @@ · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | config IIO_ST_LSM6DSX | 3 | config IIO_ST_LSM6DSX |
| 4 | tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors" | 4 | tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors" |
| 5 | depends on (I2C || SPI) | 5 | depends on (I2C || SPI || I3C) |
| 6 | select IIO_BUFFER | 6 | select IIO_BUFFER |
| 7 | select IIO_KFIFO_BUF | 7 | select IIO_KFIFO_BUF |
| 8 | select IIO_ST_LSM6DSX_I2C if (I2C) | 8 | select IIO_ST_LSM6DSX_I2C if (I2C) |
| 9 | select IIO_ST_LSM6DSX_SPI if (SPI_MASTER) | 9 | select IIO_ST_LSM6DSX_SPI if (SPI_MASTER) |
| 10 | select IIO_ST_LSM6DSX_I3C if (I3C) | ||
| 10 | help | 11 | help |
| 11 | Say yes here to build support for STMicroelectronics LSM6DSx imu | 12 | Say yes here to build support for STMicroelectronics LSM6DSx imu |
| 12 | sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm, | 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 | To compile this driver as a module, choose M here: the module | 17 | To compile this driver as a module, choose M here: the module |
| 16 | will be called st_lsm6dsx. | 18 | will be called st_lsm6dsx. |
| @@ -24,3 +26,8 @@ config IIO_ST_LSM6DSX_SPI · 7 unmodified lines | |||
| 24 | tristate | 26 | tristate |
| 25 | depends on IIO_ST_LSM6DSX | 27 | depends on IIO_ST_LSM6DSX |
| 26 | select REGMAP_SPI | 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 | obj-$(CONFIG_IIO_ST_LSM6DSX) += st_lsm6dsx.o | 5 | obj-$(CONFIG_IIO_ST_LSM6DSX) += st_lsm6dsx.o |
| 6 | obj-$(CONFIG_IIO_ST_LSM6DSX_I2C) += st_lsm6dsx_i2c.o | 6 | obj-$(CONFIG_IIO_ST_LSM6DSX_I2C) += st_lsm6dsx_i2c.o |
| 7 | obj-$(CONFIG_IIO_ST_LSM6DSX_SPI) += st_lsm6dsx_spi.o | 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 | #define ST_ASM330LHH_DEV_NAME "asm330lhh" | 22 | #define ST_ASM330LHH_DEV_NAME "asm330lhh" |
| 23 | #define ST_LSM6DSOX_DEV_NAME "lsm6dsox" | 23 | #define ST_LSM6DSOX_DEV_NAME "lsm6dsox" |
| 24 | #define ST_LSM6DSR_DEV_NAME "lsm6dsr" | 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 | enum st_lsm6dsx_hw_id { | 28 | enum st_lsm6dsx_hw_id { |
| 27 | ST_LSM6DS3_ID, | 29 | ST_LSM6DS3_ID, |
| @@ -33,6 +35,8 @@ enum st_lsm6dsx_hw_id { · 5 unmodified lines | |||
| 33 | ST_ASM330LHH_ID, | 35 | ST_ASM330LHH_ID, |
| 34 | ST_LSM6DSOX_ID, | 36 | ST_LSM6DSOX_ID, |
| 35 | ST_LSM6DSR_ID, | 37 | ST_LSM6DSR_ID, |
| 38 | ST_LSM6DS3TRC_ID, | ||
| 39 | ST_ISM330DHCX_ID, | ||
| 36 | ST_LSM6DSX_MAX_ID, | 40 | ST_LSM6DSX_MAX_ID, |
| 37 | }; | 41 | }; |
| 38 | 42 | ||
| @@ -54,8 +58,8 @@ enum st_lsm6dsx_hw_id { · 15 unmodified lines | |||
| 54 | .address = addr, \ | 58 | .address = addr, \ |
| 55 | .modified = 1, \ | 59 | .modified = 1, \ |
| 56 | .channel2 = mod, \ | 60 | .channel2 = mod, \ |
| 57 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | 61 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
| 58 | BIT(IIO_CHAN_INFO_SCALE), \ | 62 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
| 59 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | 63 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ |
| 60 | .scan_index = scan_idx, \ | 64 | .scan_index = scan_idx, \ |
| 61 | .scan_type = { \ | 65 | .scan_type = { \ |
| @@ -198,6 +202,9 @@ struct st_lsm6dsx_ext_dev_settings { · 136 unmodified lines | |||
| 198 | * @wai: Sensor WhoAmI default value. | 202 | * @wai: Sensor WhoAmI default value. |
| 199 | * @max_fifo_size: Sensor max fifo length in FIFO words. | 203 | * @max_fifo_size: Sensor max fifo length in FIFO words. |
| 200 | * @id: List of hw id/device name supported by the driver configuration. | 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 | * @decimator: List of decimator register info (addr + mask). | 208 | * @decimator: List of decimator register info (addr + mask). |
| 202 | * @batch: List of FIFO batching register info (addr + mask). | 209 | * @batch: List of FIFO batching register info (addr + mask). |
| 203 | * @fifo_ops: Sensor hw FIFO parameters. | 210 | * @fifo_ops: Sensor hw FIFO parameters. |
| @@ -211,6 +218,12 @@ struct st_lsm6dsx_settings { · 7 unmodified lines | |||
| 211 | enum st_lsm6dsx_hw_id hw_id; | 218 | enum st_lsm6dsx_hw_id hw_id; |
| 212 | const char *name; | 219 | const char *name; |
| 213 | } id[ST_LSM6DSX_MAX_ID]; | 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 | struct st_lsm6dsx_reg decimator[ST_LSM6DSX_MAX_ID]; | 227 | struct st_lsm6dsx_reg decimator[ST_LSM6DSX_MAX_ID]; |
| 215 | struct st_lsm6dsx_reg batch[ST_LSM6DSX_MAX_ID]; | 228 | struct st_lsm6dsx_reg batch[ST_LSM6DSX_MAX_ID]; |
| 216 | struct st_lsm6dsx_fifo_ops fifo_ops; | 229 | struct st_lsm6dsx_fifo_ops fifo_ops; |
| @@ -2,10 +2,10 @@ · 1 unmodified line | |||
| 2 | /* | 2 | /* |
| 3 | * STMicroelectronics st_lsm6dsx FIFO buffer library driver | 3 | * STMicroelectronics st_lsm6dsx FIFO buffer library driver |
| 4 | * | 4 | * |
| 5 | * LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC: The FIFO buffer can be | 5 | * LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C: |
| 6 | * configured to store data from gyroscope and accelerometer. Samples are | 6 | * The FIFO buffer can be configured to store data from gyroscope and |
| 7 | * queued without any tag according to a specific pattern based on | 7 | * accelerometer. Samples are queued without any tag according to a |
| 8 | * 'FIFO data sets' (6 bytes each): | 8 | * specific pattern based on 'FIFO data sets' (6 bytes each): |
| 9 | * - 1st data set is reserved for gyroscope data | 9 | * - 1st data set is reserved for gyroscope data |
| 10 | * - 2nd data set is reserved for accelerometer data | 10 | * - 2nd data set is reserved for accelerometer data |
| 11 | * The FIFO pattern changes depending on the ODRs and decimation factors | 11 | * The FIFO pattern changes depending on the ODRs and decimation factors |
| @@ -14,9 +14,10 @@ · 2 unmodified lines | |||
| 14 | * (e.g. Gx, Gy, Gz, Ax, Ay, Az), then data are repeated depending on the | 14 | * (e.g. Gx, Gy, Gz, Ax, Ay, Az), then data are repeated depending on the |
| 15 | * value of the decimation factor and ODR set for each FIFO data set. | 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 | 17 | * LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX: The FIFO buffer can be |
| 18 | * store data from gyroscope and accelerometer. Each sample is queued with | 18 | * configured to store data from gyroscope and accelerometer. Each sample |
| 19 | * a tag (1B) indicating data source (gyroscope, accelerometer, hw timer). | 19 | * is queued with a tag (1B) indicating data source (gyroscope, accelerometer, |
| 20 | * hw timer). | ||
| 20 | * | 21 | * |
| 21 | * FIFO supported modes: | 22 | * FIFO supported modes: |
| 22 | * - BYPASS: FIFO disabled | 23 | * - BYPASS: FIFO disabled |
| @@ -670,7 +671,7 @@ static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) · 647 unmodified lines | |||
| 670 | count = hw->settings->fifo_ops.read_fifo(hw); | 671 | count = hw->settings->fifo_ops.read_fifo(hw); |
| 671 | mutex_unlock(&hw->fifo_lock); | 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 | static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev) | 677 | static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev) |
| @@ -18,13 +18,13 @@ · 17 unmodified lines | |||
| 18 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 | 18 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 |
| 19 | * - FIFO size: 8KB | 19 | * - FIFO size: 8KB |
| 20 | * | 20 | * |
| 21 | * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC: | 21 | * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C: |
| 22 | * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 | 22 | * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 |
| 23 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 | 23 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 |
| 24 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 | 24 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 |
| 25 | * - FIFO size: 4KB | 25 | * - FIFO size: 4KB |
| 26 | * | 26 | * |
| 27 | * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR | 27 | * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX: |
| 28 | * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 | 28 | * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 |
| 29 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 | 29 | * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 |
| 30 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 | 30 | * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 |
| @@ -61,62 +61,18 @@ · 30 unmodified lines | |||
| 61 | #define ST_LSM6DSX_REG_INT2_ON_INT1_ADDR 0x13 | 61 | #define ST_LSM6DSX_REG_INT2_ON_INT1_ADDR 0x13 |
| 62 | #define ST_LSM6DSX_REG_INT2_ON_INT1_MASK BIT(5) | 62 | #define ST_LSM6DSX_REG_INT2_ON_INT1_MASK BIT(5) |
| 63 | 63 | ||
| 64 | #define ST_LSM6DSX_REG_ACC_OUT_X_L_ADDR 0x28 | 64 | static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { |
| 65 | #define ST_LSM6DSX_REG_ACC_OUT_Y_L_ADDR 0x2a | 65 | ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x28, IIO_MOD_X, 0), |
| 66 | #define ST_LSM6DSX_REG_ACC_OUT_Z_L_ADDR 0x2c | 66 | ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), |
| 67 | 67 | ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2c, IIO_MOD_Z, 2), | |
| 68 | #define ST_LSM6DSX_REG_GYRO_OUT_X_L_ADDR 0x22 | 68 | IIO_CHAN_SOFT_TIMESTAMP(3), |
| 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 | } | ||
| 97 | }; | 69 | }; |
| 98 | 70 | ||
| 99 | static const struct st_lsm6dsx_fs_table_entry st_lsm6dsx_fs_table[] = { | 71 | static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { |
| 100 | [ST_LSM6DSX_ID_ACC] = { | 72 | ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x22, IIO_MOD_X, 0), |
| 101 | .reg = { | 73 | ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x24, IIO_MOD_Y, 1), |
| 102 | .addr = 0x10, | 74 | ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x26, IIO_MOD_Z, 2), |
| 103 | .mask = GENMASK(3, 2), | 75 | IIO_CHAN_SOFT_TIMESTAMP(3), |
| 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 | } | ||
| 120 | }; | 76 | }; |
| 121 | 77 | ||
| 122 | static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { | 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 | .name = ST_LSM6DS3_DEV_NAME, | 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 | .decimator = { | 146 | .decimator = { |
| 133 | [ST_LSM6DSX_ID_ACC] = { | 147 | [ST_LSM6DSX_ID_ACC] = { |
| 134 | .addr = 0x08, | 148 | .addr = 0x08, |
| @@ -179,6 +193,64 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 44 unmodified lines | |||
| 179 | .name = ST_LSM6DS3H_DEV_NAME, | 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 | .decimator = { | 254 | .decimator = { |
| 183 | [ST_LSM6DSX_ID_ACC] = { | 255 | [ST_LSM6DSX_ID_ACC] = { |
| 184 | .addr = 0x08, | 256 | .addr = 0x08, |
| @@ -233,6 +305,67 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 48 unmodified lines | |||
| 233 | }, { | 305 | }, { |
| 234 | .hw_id = ST_ISM330DLC_ID, | 306 | .hw_id = ST_ISM330DLC_ID, |
| 235 | .name = ST_ISM330DLC_DEV_NAME, | 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 | .decimator = { | 371 | .decimator = { |
| @@ -288,6 +421,64 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 49 unmodified lines | |||
| 288 | .name = ST_LSM6DSOX_DEV_NAME, | 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 | .batch = { | 482 | .batch = { |
| 292 | [ST_LSM6DSX_ID_ACC] = { | 483 | [ST_LSM6DSX_ID_ACC] = { |
| 293 | .addr = 0x09, | 484 | .addr = 0x09, |
| @@ -356,6 +547,64 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 62 unmodified lines | |||
| 356 | .name = ST_ASM330LHH_DEV_NAME, | 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 | .batch = { | 608 | .batch = { |
| 360 | [ST_LSM6DSX_ID_ACC] = { | 609 | [ST_LSM6DSX_ID_ACC] = { |
| 361 | .addr = 0x09, | 610 | .addr = 0x09, |
| @@ -396,6 +645,67 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 34 unmodified lines | |||
| 396 | { | 645 | { |
| 397 | .hw_id = ST_LSM6DSR_ID, | 646 | .hw_id = ST_LSM6DSR_ID, |
| 398 | .name = ST_LSM6DSR_DEV_NAME, | 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 | .batch = { | 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 | int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable) | 772 | int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable) |
| 483 | { | 773 | { |
| 484 | const struct st_lsm6dsx_shub_settings *hub_settings; | 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 | static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor, | 823 | static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor, |
| 534 | u32 gain) | 824 | u32 gain) |
| 535 | { | 825 | { |
| 536 | struct st_lsm6dsx_hw *hw = sensor->hw; | 826 | const struct st_lsm6dsx_fs_table_entry *fs_table; |
| 537 | const struct st_lsm6dsx_reg *reg; | ||
| 538 | unsigned int data; | 827 | unsigned int data; |
| 539 | int i, err; | 828 | int i, err; |
| 540 | u8 val; | ||
| 541 | 829 | ||
| 830 | fs_table = &sensor->hw->settings->fs_table[sensor->id]; | ||
| 542 | for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) | 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 | break; | 833 | break; |
| 545 | 834 | ||
| 546 | if (i == ST_LSM6DSX_FS_LIST_SIZE) | 835 | if (i == ST_LSM6DSX_FS_LIST_SIZE) |
| 547 | return -EINVAL; | 836 | return -EINVAL; |
| 548 | 837 | ||
| 549 | val = st_lsm6dsx_fs_table[sensor->id].fs_avl[i].val; | 838 | data = ST_LSM6DSX_SHIFT_VAL(fs_table->fs_avl[i].val, |
| 550 | reg = &st_lsm6dsx_fs_table[sensor->id].reg; | 839 | fs_table->reg.mask); |
| 551 | data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); | 840 | err = st_lsm6dsx_update_bits_locked(sensor->hw, fs_table->reg.addr, |
| 552 | err = st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data); | 841 | fs_table->reg.mask, data); |
| 553 | if (err < 0) | 842 | if (err < 0) |
| 554 | return err; | 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 | int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr, u8 *val) | 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 | int i; | 853 | int i; |
| 564 | 854 | ||
| 855 | odr_table = &sensor->hw->settings->odr_table[sensor->id]; | ||
| 565 | for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) | 856 | for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) |
| 566 | /* | 857 | /* |
| 567 | * ext devices can run at different odr respect to | 858 | * ext devices can run at different odr respect to |
| 568 | * accel sensor | 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 | break; | 862 | break; |
| 572 | 863 | ||
| 573 | if (i == ST_LSM6DSX_ODR_LIST_SIZE) | 864 | if (i == ST_LSM6DSX_ODR_LIST_SIZE) |
| 574 | return -EINVAL; | 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 | return 0; | 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 | return err; | 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 | data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); | 933 | data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask); |
| 643 | return st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data); | 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 | struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); | 1075 | struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); |
| 785 | enum st_lsm6dsx_sensor_id id = sensor->id; | 1076 | enum st_lsm6dsx_sensor_id id = sensor->id; |
| 1077 | struct st_lsm6dsx_hw *hw = sensor->hw; | ||
| 786 | int i, len = 0; | 1078 | int i, len = 0; |
| 787 | 1079 | ||
| 788 | for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) | 1080 | for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) |
| 789 | len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", | 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 | buf[len - 1] = '\n'; | 1083 | buf[len - 1] = '\n'; |
| 792 | 1084 | ||
| 793 | return len; | 1085 | return len; |
| @@ -799,11 +1091,12 @@ static ssize_t st_lsm6dsx_sysfs_scale_avail(struct device *dev, · 5 unmodified lines | |||
| 799 | { | 1091 | { |
| 800 | struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); | 1092 | struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); |
| 801 | enum st_lsm6dsx_sensor_id id = sensor->id; | 1093 | enum st_lsm6dsx_sensor_id id = sensor->id; |
| 1094 | struct st_lsm6dsx_hw *hw = sensor->hw; | ||
| 802 | int i, len = 0; | 1095 | int i, len = 0; |
| 803 | 1096 | ||
| 804 | for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) | 1097 | for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) |
| 805 | len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", | 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 | buf[len - 1] = '\n'; | 1100 | buf[len - 1] = '\n'; |
| 808 | 1101 | ||
| 809 | return len; | 1102 | return len; |
| @@ -1033,28 +1326,24 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, · 223 unmodified lines | |||
| 1033 | iio_dev->modes = INDIO_DIRECT_MODE; | 1326 | iio_dev->modes = INDIO_DIRECT_MODE; |
| 1034 | iio_dev->dev.parent = hw->dev; | 1327 | iio_dev->dev.parent = hw->dev; |
| 1035 | iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks; | 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 | sensor = iio_priv(iio_dev); | 1332 | sensor = iio_priv(iio_dev); |
| 1038 | sensor->id = id; | 1333 | sensor->id = id; |
| 1039 | sensor->hw = hw; | 1334 | sensor->hw = hw; |
| 1040 | sensor->odr = st_lsm6dsx_odr_table[id].odr_avl[0].hz; | 1335 | sensor->odr = hw->settings->odr_table[id].odr_avl[0].hz; |
| 1041 | sensor->gain = st_lsm6dsx_fs_table[id].fs_avl[0].gain; | 1336 | sensor->gain = hw->settings->fs_table[id].fs_avl[0].gain; |
| 1042 | sensor->watermark = 1; | 1337 | sensor->watermark = 1; |
| 1043 | 1338 | ||
| 1044 | switch (id) { | 1339 | switch (id) { |
| 1045 | case ST_LSM6DSX_ID_ACC: | 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 | iio_dev->info = &st_lsm6dsx_acc_info; | 1341 | iio_dev->info = &st_lsm6dsx_acc_info; |
| 1049 | |||
| 1050 | scnprintf(sensor->name, sizeof(sensor->name), "%s_accel", | 1342 | scnprintf(sensor->name, sizeof(sensor->name), "%s_accel", |
| 1051 | name); | 1343 | name); |
| 1052 | break; | 1344 | break; |
| 1053 | case ST_LSM6DSX_ID_GYRO: | 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 | iio_dev->info = &st_lsm6dsx_gyro_info; | 1346 | iio_dev->info = &st_lsm6dsx_gyro_info; |
| 1057 | |||
| 1058 | scnprintf(sensor->name, sizeof(sensor->name), "%s_gyro", | 1347 | scnprintf(sensor->name, sizeof(sensor->name), "%s_gyro", |
| 1059 | name); | 1348 | name); |
| 1060 | break; | 1349 | break; |
| @@ -75,6 +75,14 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = { · 74 unmodified lines | |||
| 75 | .compatible = "st,lsm6dsr", | 75 | .compatible = "st,lsm6dsr", |
| 76 | .data = (void *)ST_LSM6DSR_ID, | 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 | MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match); | 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 | { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, | 97 | { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, |
| 90 | { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, | 98 | { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, |
| 91 | { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, | 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 | MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table); | 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 | .compatible = "st,lsm6dsr", | 75 | .compatible = "st,lsm6dsr", |
| 76 | .data = (void *)ST_LSM6DSR_ID, | 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 | MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match); | 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 | { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, | 97 | { ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID }, |
| 90 | { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, | 98 | { ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID }, |
| 91 | { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, | 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 | MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table); | 104 | MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table); |
| @@ -303,6 +303,7 @@ config MAX44000 · 302 unmodified lines | |||
| 303 | config MAX44009 | 303 | config MAX44009 |
| 304 | tristate "MAX44009 Ambient Light Sensor" | 304 | tristate "MAX44009 Ambient Light Sensor" |
| 305 | depends on I2C | 305 | depends on I2C |
| 306 | select REGMAP_I2C | ||
| 306 | help | 307 | help |
| 307 | Say Y here if you want to build support for Maxim Integrated's | 308 | Say Y here if you want to build support for Maxim Integrated's |
| 308 | MAX44009 ambient light sensor device. | 309 | MAX44009 ambient light sensor device. |
| @@ -310,6 +311,16 @@ config MAX44009 · 1 unmodified line | |||
| 310 | To compile this driver as a module, choose M here: | 311 | To compile this driver as a module, choose M here: |
| 311 | the module will be called max44009. | 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 | config OPT3001 | 324 | config OPT3001 |
| 314 | tristate "Texas Instruments OPT3001 Light Sensor" | 325 | tristate "Texas Instruments OPT3001 Light Sensor" |
| 315 | depends on I2C | 326 | depends on I2C |
| @@ -29,6 +29,7 @@ obj-$(CONFIG_LTR501) += ltr501.o · 28 unmodified lines | |||
| 29 | obj-$(CONFIG_LV0104CS) += lv0104cs.o | 29 | obj-$(CONFIG_LV0104CS) += lv0104cs.o |
| 30 | obj-$(CONFIG_MAX44000) += max44000.o | 30 | obj-$(CONFIG_MAX44000) += max44000.o |
| 31 | obj-$(CONFIG_MAX44009) += max44009.o | 31 | obj-$(CONFIG_MAX44009) += max44009.o |
| 32 | obj-$(CONFIG_NOA1305) += noa1305.o | ||
| 32 | obj-$(CONFIG_OPT3001) += opt3001.o | 33 | obj-$(CONFIG_OPT3001) += opt3001.o |
| 33 | obj-$(CONFIG_PA12203001) += pa12203001.o | 34 | obj-$(CONFIG_PA12203001) += pa12203001.o |
| 34 | obj-$(CONFIG_RPR0521) += rpr0521.o | 35 | obj-$(CONFIG_RPR0521) += rpr0521.o |
| @@ -1135,5 +1135,5 @@ static struct i2c_driver apds9960_driver = { · 1134 unmodified lines | |||
| 1135 | module_i2c_driver(apds9960_driver); | 1135 | module_i2c_driver(apds9960_driver); |
| 1136 | 1136 | ||
| 1137 | MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>"); | 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 | MODULE_LICENSE("GPL"); | 1139 | MODULE_LICENSE("GPL"); |
| @@ -101,15 +101,16 @@ static int cm3323_init(struct iio_dev *indio_dev) · 100 unmodified lines | |||
| 101 | return 0; | 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 | int ret; | 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 | CM3323_CONF_SD_BIT); | 111 | CM3323_CONF_SD_BIT); |
| 111 | if (ret < 0) | 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 | static int cm3323_set_it_bits(struct cm3323_data *data, int val, int val2) | 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 | return ret; | 244 | return ret; |
| 244 | } | 245 | } |
| 245 | 246 | ||
| 246 | ret = iio_device_register(indio_dev); | 247 | ret = devm_add_action_or_reset(&client->dev, cm3323_disable, indio_dev); |
| 247 | if (ret < 0) { | 248 | if (ret < 0) |
| 248 | dev_err(&client->dev, "failed to register iio dev\n"); | 249 | return ret; |
| 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); | ||
| 264 | 250 | ||
| 265 | return 0; | 251 | return devm_iio_device_register(&client->dev, indio_dev); |
| 266 | } | 252 | } |
| 267 | 253 | ||
| 268 | static const struct i2c_device_id cm3323_id[] = { | 254 | static const struct i2c_device_id cm3323_id[] = { |
| @@ -276,7 +262,6 @@ static struct i2c_driver cm3323_driver = { · 7 unmodified lines | |||
| 276 | .name = CM3323_DRV_NAME, | 262 | .name = CM3323_DRV_NAME, |
| 277 | }, | 263 | }, |
| 278 | .probe = cm3323_probe, | 264 | .probe = cm3323_probe, |
| 279 | .remove = cm3323_remove, | ||
| 280 | .id_table = cm3323_id, | 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 | i2c_set_clientdata(client, indio_dev); | 646 | i2c_set_clientdata(client, indio_dev); |
| 647 | 647 | ||
| 648 | cm36651->client = client; | 648 | cm36651->client = client; |
| 649 | cm36651->ps_client = i2c_new_dummy(client->adapter, | 649 | cm36651->ps_client = i2c_new_dummy_device(client->adapter, |
| 650 | CM36651_I2C_ADDR_PS); | 650 | CM36651_I2C_ADDR_PS); |
| 651 | if (!cm36651->ps_client) { | 651 | if (IS_ERR(cm36651->ps_client)) { |
| 652 | dev_err(&client->dev, "%s: new i2c device failed\n", __func__); | 652 | dev_err(&client->dev, "%s: new i2c device failed\n", __func__); |
| 653 | ret = -ENODEV; | 653 | ret = PTR_ERR(cm36651->ps_client); |
| 654 | goto error_disable_reg; | 654 | goto error_disable_reg; |
| 655 | } | 655 | } |
| 656 | 656 | ||
| 657 | cm36651->ara_client = i2c_new_dummy(client->adapter, CM36651_ARA); | 657 | cm36651->ara_client = i2c_new_dummy_device(client->adapter, CM36651_ARA); |
| 658 | if (!cm36651->ara_client) { | 658 | if (IS_ERR(cm36651->ara_client)) { |
| 659 | dev_err(&client->dev, "%s: new i2c device failed\n", __func__); | 659 | dev_err(&client->dev, "%s: new i2c device failed\n", __func__); |
| 660 | ret = -ENODEV; | 660 | ret = PTR_ERR(cm36651->ara_client); |
| 661 | goto error_i2c_unregister_ps; | 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 | struct cros_ec_light_prox_state *st = iio_priv(indio_dev); | 42 | struct cros_ec_light_prox_state *st = iio_priv(indio_dev); |
| 43 | u16 data = 0; | 43 | u16 data = 0; |
| 44 | s64 val64; | 44 | s64 val64; |
| 45 | int ret = IIO_VAL_INT; | 45 | int ret; |
| 46 | int idx = chan->scan_index; | 46 | int idx = chan->scan_index; |
| 47 | 47 | ||
| 48 | mutex_lock(&st->core.cmd_lock); | 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 | switch (mask) { | 50 | switch (mask) { |
| 51 | case IIO_CHAN_INFO_RAW: | 51 | case IIO_CHAN_INFO_RAW: |
| 52 | if (chan->type == IIO_PROXIMITY) { | 52 | if (chan->type == IIO_PROXIMITY) { |
| 53 | if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx, | 53 | ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx, |
| 54 | (s16 *)&data) < 0) { | 54 | (s16 *)&data); |
| 55 | ret = -EIO; | 55 | if (ret) |
| 56 | break; | 56 | break; |
| 57 | } | ||
| 58 | *val = data; | 57 | *val = data; |
| 58 | ret = IIO_VAL_INT; | ||
| 59 | } else { | 59 | } else { |
| 60 | ret = -EINVAL; | 60 | ret = -EINVAL; |
| 61 | } | 61 | } |
| 62 | break; | 62 | break; |
| 63 | case IIO_CHAN_INFO_PROCESSED: | 63 | case IIO_CHAN_INFO_PROCESSED: |
| 64 | if (chan->type == IIO_LIGHT) { | 64 | if (chan->type == IIO_LIGHT) { |
| 65 | if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx, | 65 | ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx, |
| 66 | (s16 *)&data) < 0) { | 66 | (s16 *)&data); |
| 67 | ret = -EIO; | 67 | if (ret) |
| 68 | break; | 68 | break; |
| 69 | } | ||
| 70 | /* | 69 | /* |
| 71 | * The data coming from the light sensor is | 70 | * The data coming from the light sensor is |
| 72 | * pre-processed and represents the ambient light | 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 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; | 81 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; |
| 83 | st->core.param.sensor_offset.flags = 0; | 82 | st->core.param.sensor_offset.flags = 0; |
| 84 | 83 | ||
| 85 | if (cros_ec_motion_send_host_cmd(&st->core, 0)) { | 84 | ret = cros_ec_motion_send_host_cmd(&st->core, 0); |
| 86 | ret = -EIO; | 85 | if (ret) |
| 87 | break; | 86 | break; |
| 88 | } | ||
| 89 | 87 | ||
| 90 | /* Save values */ | 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 | break; | 94 | break; |
| 95 | case IIO_CHAN_INFO_CALIBSCALE: | 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 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; | 101 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; |
| 102 | st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE; | 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)) { | 104 | ret = cros_ec_motion_send_host_cmd(&st->core, 0); |
| 105 | ret = -EIO; | 105 | if (ret) |
| 106 | break; | 106 | break; |
| 107 | } | ||
| 108 | 107 | ||
| 109 | val64 = st->core.resp->sensor_range.ret; | 108 | val64 = st->core.resp->sensor_range.ret; |
| 110 | *val = val64 >> 16; | 109 | *val = val64 >> 16; |
| @@ -127,28 +126,27 @@ static int cros_ec_light_prox_write(struct iio_dev *indio_dev, · 16 unmodified lines | |||
| 127 | int val, int val2, long mask) | 126 | int val, int val2, long mask) |
| 128 | { | 127 | { |
| 129 | struct cros_ec_light_prox_state *st = iio_priv(indio_dev); | 128 | struct cros_ec_light_prox_state *st = iio_priv(indio_dev); |
| 130 | int ret = 0; | 129 | int ret; |
| 131 | int idx = chan->scan_index; | 130 | int idx = chan->scan_index; |
| 132 | 131 | ||
| 133 | mutex_lock(&st->core.cmd_lock); | 132 | mutex_lock(&st->core.cmd_lock); |
| 134 | 133 | ||
| 135 | switch (mask) { | 134 | switch (mask) { |
| 136 | case IIO_CHAN_INFO_CALIBBIAS: | 135 | case IIO_CHAN_INFO_CALIBBIAS: |
| 137 | st->core.calib[idx] = val; | 136 | st->core.calib[idx].offset = val; |
| 138 | /* Send to EC for each axis, even if not complete */ | 137 | /* Send to EC for each axis, even if not complete */ |
| 139 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; | 138 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET; |
| 140 | st->core.param.sensor_offset.flags = MOTION_SENSE_SET_OFFSET; | 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 | st->core.param.sensor_offset.temp = | 142 | st->core.param.sensor_offset.temp = |
| 143 | EC_MOTION_SENSE_INVALID_CALIB_TEMP; | 143 | EC_MOTION_SENSE_INVALID_CALIB_TEMP; |
| 144 | if (cros_ec_motion_send_host_cmd(&st->core, 0)) | 144 | ret = cros_ec_motion_send_host_cmd(&st->core, 0); |
| 145 | ret = -EIO; | ||
| 146 | break; | 145 | break; |
| 147 | case IIO_CHAN_INFO_CALIBSCALE: | 146 | case IIO_CHAN_INFO_CALIBSCALE: |
| 148 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; | 147 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; |
| 149 | st->core.param.sensor_range.data = (val << 16) | (val2 / 100); | 148 | st->core.param.sensor_range.data = (val << 16) | (val2 / 100); |
| 150 | if (cros_ec_motion_send_host_cmd(&st->core, 0)) | 149 | ret = cros_ec_motion_send_host_cmd(&st->core, 0); |
| 151 | ret = -EIO; | ||
| 152 | break; | 150 | break; |
| 153 | default: | 151 | default: |
| 154 | ret = cros_ec_sensors_core_write(&st->core, chan, val, val2, | 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 | static const struct iio_info cros_ec_light_prox_info = { | 162 | static const struct iio_info cros_ec_light_prox_info = { |
| 165 | .read_raw = &cros_ec_light_prox_read, | 163 | .read_raw = &cros_ec_light_prox_read, |
| 166 | .write_raw = &cros_ec_light_prox_write, | 164 | .write_raw = &cros_ec_light_prox_write, |
| 165 | .read_avail = &cros_ec_sensors_core_read_avail, | ||
| 167 | }; | 166 | }; |
| 168 | 167 | ||
| 169 | static int cros_ec_light_prox_probe(struct platform_device *pdev) | 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 | channel->info_mask_shared_by_all = | 197 | channel->info_mask_shared_by_all = |
| 199 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | | 198 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
| 200 | BIT(IIO_CHAN_INFO_FREQUENCY); | 199 | BIT(IIO_CHAN_INFO_FREQUENCY); |
| 200 | channel->info_mask_shared_by_all_available = | ||
| 201 | BIT(IIO_CHAN_INFO_SAMP_FREQ); | ||
| 201 | channel->scan_type.realbits = CROS_EC_SENSOR_BITS; | 202 | channel->scan_type.realbits = CROS_EC_SENSOR_BITS; |
| 202 | channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; | 203 | channel->scan_type.storagebits = CROS_EC_SENSOR_BITS; |
| 203 | channel->scan_type.shift = 0; | 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 | channel->ext_info = cros_ec_sensors_ext_info; | 206 | channel->ext_info = cros_ec_sensors_ext_info; |
| 206 | channel->scan_type.sign = 'u'; | 207 | channel->scan_type.sign = 'u'; |
| 207 | 208 | ||
| 208 | state->core.calib[0] = 0; | ||
| 209 | |||
| 210 | /* Sensor specific */ | 209 | /* Sensor specific */ |
| 211 | switch (state->core.type) { | 210 | switch (state->core.type) { |
| 212 | case MOTIONSENSE_TYPE_LIGHT: | 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 | return ret; | 1261 | return ret; |
| 1262 | } | 1262 | } |
| 1263 | 1263 | ||
| 1264 | ret = iio_trigger_register(trig); | 1264 | ret = devm_iio_trigger_register(&client->dev, trig); |
| 1265 | if (ret) | 1265 | if (ret) |
| 1266 | return ret; | 1266 | return ret; |
| 1267 | 1267 | ||
| @@ -1271,16 +1271,6 @@ static int si1145_probe_trigger(struct iio_dev *indio_dev) · 3 unmodified lines | |||
| 1271 | return 0; | 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 | static int si1145_probe(struct i2c_client *client, | 1274 | static int si1145_probe(struct i2c_client *client, |
| 1285 | const struct i2c_device_id *id) | 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 | if (ret < 0) | 1322 | if (ret < 0) |
| 1333 | return ret; | 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 | si1145_trigger_handler, &si1145_buffer_setup_ops); | 1327 | si1145_trigger_handler, &si1145_buffer_setup_ops); |
| 1337 | if (ret < 0) | 1328 | if (ret < 0) |
| 1338 | return ret; | 1329 | return ret; |
| @@ -1340,23 +1331,12 @@ static int si1145_probe(struct i2c_client *client, · 1 unmodified line | |||
| 1340 | if (client->irq) { | 1331 | if (client->irq) { |
| 1341 | ret = si1145_probe_trigger(indio_dev); | 1332 | ret = si1145_probe_trigger(indio_dev); |
| 1342 | if (ret < 0) | 1333 | if (ret < 0) |
| 1343 | goto error_free_buffer; | 1334 | return ret; |
| 1344 | } else { | 1335 | } else { |
| 1345 | dev_info(&client->dev, "no irq, using polling\n"); | 1336 | dev_info(&client->dev, "no irq, using polling\n"); |
| 1346 | } | 1337 | } |
| 1347 | 1338 | ||
| 1348 | ret = iio_device_register(indio_dev); | 1339 | return devm_iio_device_register(&client->dev, 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; | ||
| 1360 | } | 1340 | } |
| 1361 | 1341 | ||
| 1362 | static const struct i2c_device_id si1145_ids[] = { | 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 | MODULE_DEVICE_TABLE(i2c, si1145_ids); | 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 | static struct i2c_driver si1145_driver = { | 1354 | static struct i2c_driver si1145_driver = { |
| 1386 | .driver = { | 1355 | .driver = { |
| 1387 | .name = "si1145", | 1356 | .name = "si1145", |
| 1388 | }, | 1357 | }, |
| 1389 | .probe = si1145_probe, | 1358 | .probe = si1145_probe, |
| 1390 | .remove = si1145_remove, | ||
| 1391 | .id_table = si1145_ids, | 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 | MODULE_DEVICE_TABLE(acpi, stk3310_acpi_id); | 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 | static struct i2c_driver stk3310_driver = { | 690 | static struct i2c_driver stk3310_driver = { |
| 683 | .driver = { | 691 | .driver = { |
| 684 | .name = "stk3310", | 692 | .name = "stk3310", |
| 693 | .of_match_table = stk3310_of_match, | ||
| 685 | .pm = STK3310_PM_OPS, | 694 | .pm = STK3310_PM_OPS, |
| 686 | .acpi_match_table = ACPI_PTR(stk3310_acpi_id), | 695 | .acpi_match_table = ACPI_PTR(stk3310_acpi_id), |
| 687 | }, | 696 | }, |
| @@ -134,6 +134,12 @@ enum { · 133 unmodified lines | |||
| 134 | TSL2772_CHIP_SUSPENDED = 2 | 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 | /* Per-device data */ | 143 | /* Per-device data */ |
| 138 | struct tsl2772_als_info { | 144 | struct tsl2772_als_info { |
| 139 | u16 als_ch0; | 145 | u16 als_ch0; |
| @@ -161,8 +167,7 @@ struct tsl2772_chip { · 21 unmodified lines | |||
| 161 | struct mutex prox_mutex; | 167 | struct mutex prox_mutex; |
| 162 | struct mutex als_mutex; | 168 | struct mutex als_mutex; |
| 163 | struct i2c_client *client; | 169 | struct i2c_client *client; |
| 164 | struct regulator *vdd_supply; | 170 | struct regulator_bulk_data supplies[TSL2772_NUM_SUPPLIES]; |
| 165 | struct regulator *vddio_supply; | ||
| 166 | u16 prox_data; | 171 | u16 prox_data; |
| 167 | struct tsl2772_als_info als_cur_info; | 172 | struct tsl2772_als_info als_cur_info; |
| 168 | struct tsl2772_settings settings; | 173 | struct tsl2772_settings settings; |
| @@ -697,46 +702,7 @@ static void tsl2772_disable_regulators_action(void *_data) · 528 unmodified lines | |||
| 697 | { | 702 | { |
| 698 | struct tsl2772_chip *chip = _data; | 703 | struct tsl2772_chip *chip = _data; |
| 699 | 704 | ||
| 700 | regulator_disable(chip->vdd_supply); | 705 | regulator_bulk_disable(ARRAY_SIZE(chip->supplies), chip->supplies); |
| 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; | ||
| 740 | } | 706 | } |
| 741 | 707 | ||
| 742 | static int tsl2772_chip_on(struct iio_dev *indio_dev) | 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 | return tsl2772_write_control_reg(chip, 0x00); | 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 | * tsl2772_invoke_change - power cycle the device to implement the user | 837 | * tsl2772_invoke_change - power cycle the device to implement the user |
| 865 | * parameters | 838 | * parameters |
| @@ -1797,20 +1770,32 @@ static int tsl2772_probe(struct i2c_client *clientp, · 931 unmodified lines | |||
| 1797 | chip->client = clientp; | 1770 | chip->client = clientp; |
| 1798 | i2c_set_clientdata(clientp, indio_dev); | 1771 | i2c_set_clientdata(clientp, indio_dev); |
| 1799 | 1772 | ||
| 1800 | chip->vddio_supply = tsl2772_get_regulator(chip, "vddio"); | 1773 | chip->supplies[TSL2772_SUPPLY_VDD].supply = "vdd"; |
| 1801 | if (IS_ERR(chip->vddio_supply)) | 1774 | chip->supplies[TSL2772_SUPPLY_VDDIO].supply = "vddio"; |
| 1802 | return PTR_ERR(chip->vddio_supply); | 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"); | 1788 | ret = regulator_bulk_enable(ARRAY_SIZE(chip->supplies), chip->supplies); |
| 1805 | if (IS_ERR(chip->vdd_supply)) { | 1789 | if (ret < 0) { |
| 1806 | regulator_disable(chip->vddio_supply); | 1790 | dev_err(&clientp->dev, "Failed to enable regulators: %d\n", |
| 1807 | return PTR_ERR(chip->vdd_supply); | 1791 | ret); |
| 1792 | return ret; | ||
| 1808 | } | 1793 | } |
| 1809 | 1794 | ||
| 1810 | ret = devm_add_action(&clientp->dev, tsl2772_disable_regulators_action, | 1795 | ret = devm_add_action_or_reset(&clientp->dev, |
| 1811 | chip); | 1796 | tsl2772_disable_regulators_action, |
| 1797 | chip); | ||
| 1812 | if (ret < 0) { | 1798 | if (ret < 0) { |
| 1813 | tsl2772_disable_regulators_action(chip); | ||
| 1814 | dev_err(&clientp->dev, "Failed to setup regulator cleanup action %d\n", | 1799 | dev_err(&clientp->dev, "Failed to setup regulator cleanup action %d\n", |
| 1815 | ret); | 1800 | ret); |
| 1816 | return ret; | 1801 | return ret; |
| @@ -1877,15 +1862,13 @@ static int tsl2772_probe(struct i2c_client *clientp, · 60 unmodified lines | |||
| 1877 | if (ret < 0) | 1862 | if (ret < 0) |
| 1878 | return ret; | 1863 | return ret; |
| 1879 | 1864 | ||
| 1880 | ret = iio_device_register(indio_dev); | 1865 | ret = devm_add_action_or_reset(&clientp->dev, |
| 1881 | if (ret) { | 1866 | tsl2772_chip_off_action, |
| 1882 | tsl2772_chip_off(indio_dev); | 1867 | indio_dev); |
| 1883 | dev_err(&clientp->dev, | 1868 | if (ret < 0) |
| 1884 | "%s: iio registration failed\n", __func__); | ||
| 1885 | return ret; | 1869 | return ret; |
| 1886 | } | ||
| 1887 | 1870 | ||
| 1888 | return 0; | 1871 | return devm_iio_device_register(&clientp->dev, indio_dev); |
| 1889 | } | 1872 | } |
| 1890 | 1873 | ||
| 1891 | static int tsl2772_suspend(struct device *dev) | 1874 | static int tsl2772_suspend(struct device *dev) |
| @@ -1895,8 +1878,7 @@ static int tsl2772_suspend(struct device *dev) · 3 unmodified lines | |||
| 1895 | int ret; | 1878 | int ret; |
| 1896 | 1879 | ||
| 1897 | ret = tsl2772_chip_off(indio_dev); | 1880 | ret = tsl2772_chip_off(indio_dev); |
| 1898 | regulator_disable(chip->vdd_supply); | 1881 | regulator_bulk_disable(ARRAY_SIZE(chip->supplies), chip->supplies); |
| 1899 | regulator_disable(chip->vddio_supply); | ||
| 1900 | 1882 | ||
| 1901 | return ret; | 1883 | return ret; |
| 1902 | } | 1884 | } |
| @@ -1907,32 +1889,15 @@ static int tsl2772_resume(struct device *dev) · 4 unmodified lines | |||
| 1907 | struct tsl2772_chip *chip = iio_priv(indio_dev); | 1889 | struct tsl2772_chip *chip = iio_priv(indio_dev); |
| 1908 | int ret; | 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 | if (ret < 0) | 1893 | if (ret < 0) |
| 1912 | return ret; | 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 | usleep_range(TSL2772_BOOT_MIN_SLEEP_TIME, TSL2772_BOOT_MAX_SLEEP_TIME); | 1896 | usleep_range(TSL2772_BOOT_MIN_SLEEP_TIME, TSL2772_BOOT_MAX_SLEEP_TIME); |
| 1921 | 1897 | ||
| 1922 | return tsl2772_chip_on(indio_dev); | 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 | static const struct i2c_device_id tsl2772_idtable[] = { | 1901 | static const struct i2c_device_id tsl2772_idtable[] = { |
| 1937 | { "tsl2571", tsl2571 }, | 1902 | { "tsl2571", tsl2571 }, |
| 1938 | { "tsl2671", tsl2671 }, | 1903 | { "tsl2671", tsl2671 }, |
| @@ -1979,7 +1944,6 @@ static struct i2c_driver tsl2772_driver = { · 40 unmodified lines | |||
| 1979 | }, | 1944 | }, |
| 1980 | .id_table = tsl2772_idtable, | 1945 | .id_table = tsl2772_idtable, |
| 1981 | .probe = tsl2772_probe, | 1946 | .probe = tsl2772_probe, |
| 1982 | .remove = tsl2772_remove, | ||
| 1983 | }; | 1947 | }; |
| 1984 | 1948 | ||
| 1985 | module_i2c_driver(tsl2772_driver); | 1949 | module_i2c_driver(tsl2772_driver); |
| @@ -158,10 +158,10 @@ static int veml6070_probe(struct i2c_client *client, · 157 unmodified lines | |||
| 158 | indio_dev->name = VEML6070_DRV_NAME; | 158 | indio_dev->name = VEML6070_DRV_NAME; |
| 159 | indio_dev->modes = INDIO_DIRECT_MODE; | 159 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 160 | 160 | ||
| 161 | data->client2 = i2c_new_dummy(client->adapter, VEML6070_ADDR_DATA_LSB); | 161 | data->client2 = i2c_new_dummy_device(client->adapter, VEML6070_ADDR_DATA_LSB); |
| 162 | if (!data->client2) { | 162 | if (IS_ERR(data->client2)) { |
| 163 | dev_err(&client->dev, "i2c device for second chip address failed\n"); | 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 | data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD | | 167 | data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD | |
| @@ -53,7 +53,7 @@ · 52 unmodified lines | |||
| 53 | #define MMC35240_CTRL1_BW_SHIFT 0 | 53 | #define MMC35240_CTRL1_BW_SHIFT 0 |
| 54 | 54 | ||
| 55 | #define MMC35240_WAIT_CHARGE_PUMP 50000 /* us */ | 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 | * Memsic OTP process code piece is put here for reference: | 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 | ret = mmc35240_hw_set(data, true); | 225 | ret = mmc35240_hw_set(data, true); |
| 226 | if (ret < 0) | 226 | if (ret < 0) |
| 227 | return ret; | 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 | ret = mmc35240_hw_set(data, false); | 230 | ret = mmc35240_hw_set(data, false); |
| 231 | if (ret < 0) | 231 | if (ret < 0) |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | |||
| 22 | #define LIS2MDL_MAGN_DEV_NAME "lis2mdl" | 22 | #define LIS2MDL_MAGN_DEV_NAME "lis2mdl" |
| 23 | #define LSM9DS1_MAGN_DEV_NAME "lsm9ds1_magn" | 23 | #define LSM9DS1_MAGN_DEV_NAME "lsm9ds1_magn" |
| 24 | 24 | ||
| 25 | const struct st_sensor_settings *st_magn_get_settings(const char *name); | ||
| 25 | int st_magn_common_probe(struct iio_dev *indio_dev); | 26 | int st_magn_common_probe(struct iio_dev *indio_dev); |
| 26 | void st_magn_common_remove(struct iio_dev *indio_dev); | 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 | static int st_magn_buffer_postenable(struct iio_dev *indio_dev) | 32 | static int st_magn_buffer_postenable(struct iio_dev *indio_dev) |
| 33 | { | 33 | { |
| 34 | int err; | 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 | err = iio_triggered_buffer_postenable(indio_dev); | 36 | err = iio_triggered_buffer_postenable(indio_dev); |
| 44 | if (err < 0) | 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: | 46 | st_magn_buffer_predisable: |
| 50 | kfree(mdata->buffer_data); | 47 | iio_triggered_buffer_predisable(indio_dev); |
| 51 | allocate_memory_error: | ||
| 52 | return err; | 48 | return err; |
| 53 | } | 49 | } |
| 54 | 50 | ||
| 55 | static int st_magn_buffer_predisable(struct iio_dev *indio_dev) | 51 | static int st_magn_buffer_predisable(struct iio_dev *indio_dev) |
| 56 | { | 52 | { |
| 57 | int err; | 53 | int err, err2; |
| 58 | struct st_sensor_data *mdata = iio_priv(indio_dev); | ||
| 59 | 54 | ||
| 60 | err = st_sensors_set_enable(indio_dev, false); | 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 | return err; | 61 | return err; |
| 69 | } | 62 | } |
| 70 | 63 | ||
| @@ -12,7 +12,6 @@ · 11 unmodified lines | |||
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
| 14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
| 15 | #include <linux/mutex.h> | ||
| 16 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| 17 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
| 18 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
| @@ -470,28 +469,41 @@ static const struct iio_trigger_ops st_magn_trigger_ops = { · 451 unmodified lines | |||
| 470 | #define ST_MAGN_TRIGGER_OPS NULL | 469 | #define ST_MAGN_TRIGGER_OPS NULL |
| 471 | #endif | 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 | int st_magn_common_probe(struct iio_dev *indio_dev) | 490 | int st_magn_common_probe(struct iio_dev *indio_dev) |
| 474 | { | 491 | { |
| 475 | struct st_sensor_data *mdata = iio_priv(indio_dev); | 492 | struct st_sensor_data *mdata = iio_priv(indio_dev); |
| 476 | int irq = mdata->get_irq_data_ready(indio_dev); | ||
| 477 | int err; | 493 | int err; |
| 478 | 494 | ||
| 479 | indio_dev->modes = INDIO_DIRECT_MODE; | 495 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 480 | indio_dev->info = &magn_info; | 496 | indio_dev->info = &magn_info; |
| 481 | mutex_init(&mdata->tb.buf_lock); | ||
| 482 | 497 | ||
| 483 | err = st_sensors_power_enable(indio_dev); | 498 | err = st_sensors_power_enable(indio_dev); |
| 484 | if (err) | 499 | if (err) |
| 485 | return err; | 500 | return err; |
| 486 | 501 | ||
| 487 | err = st_sensors_check_device_support(indio_dev, | 502 | err = st_sensors_verify_id(indio_dev); |
| 488 | ARRAY_SIZE(st_magn_sensors_settings), | ||
| 489 | st_magn_sensors_settings); | ||
| 490 | if (err < 0) | 503 | if (err < 0) |
| 491 | goto st_magn_power_off; | 504 | goto st_magn_power_off; |
| 492 | 505 | ||
| 493 | mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS; | 506 | mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS; |
| 494 | mdata->multiread_bit = mdata->sensor_settings->multi_read_bit; | ||
| 495 | indio_dev->channels = mdata->sensor_settings->ch; | 507 | indio_dev->channels = mdata->sensor_settings->ch; |
| 496 | indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS; | 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 | if (err < 0) | 519 | if (err < 0) |
| 508 | goto st_magn_power_off; | 520 | goto st_magn_power_off; |
| 509 | 521 | ||
| 510 | if (irq > 0) { | 522 | if (mdata->irq > 0) { |
| 511 | err = st_sensors_allocate_trigger(indio_dev, | 523 | err = st_sensors_allocate_trigger(indio_dev, |
| 512 | ST_MAGN_TRIGGER_OPS); | 524 | ST_MAGN_TRIGGER_OPS); |
| 513 | if (err < 0) | 525 | if (err < 0) |
| @@ -524,7 +536,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev) · 10 unmodified lines | |||
| 524 | return 0; | 536 | return 0; |
| 525 | 537 | ||
| 526 | st_magn_device_register_error: | 538 | st_magn_device_register_error: |
| 527 | if (irq > 0) | 539 | if (mdata->irq > 0) |
| 528 | st_sensors_deallocate_trigger(indio_dev); | 540 | st_sensors_deallocate_trigger(indio_dev); |
| 529 | st_magn_probe_trigger_error: | 541 | st_magn_probe_trigger_error: |
| 530 | st_magn_deallocate_ring(indio_dev); | 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 | st_sensors_power_disable(indio_dev); | 554 | st_sensors_power_disable(indio_dev); |
| 543 | 555 | ||
| 544 | iio_device_unregister(indio_dev); | 556 | iio_device_unregister(indio_dev); |
| 545 | if (mdata->get_irq_data_ready(indio_dev) > 0) | 557 | if (mdata->irq > 0) |
| 546 | st_sensors_deallocate_trigger(indio_dev); | 558 | st_sensors_deallocate_trigger(indio_dev); |
| 547 | 559 | ||
| 548 | st_magn_deallocate_ring(indio_dev); | 560 | st_magn_deallocate_ring(indio_dev); |
| @@ -55,21 +55,33 @@ MODULE_DEVICE_TABLE(of, st_magn_of_match); · 54 unmodified lines | |||
| 55 | #endif | 55 | #endif |
| 56 | 56 | ||
| 57 | static int st_magn_i2c_probe(struct i2c_client *client, | 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 | struct st_sensor_data *mdata; | 61 | struct st_sensor_data *mdata; |
| 62 | struct iio_dev *indio_dev; | ||
| 62 | int err; | 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 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*mdata)); | 75 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*mdata)); |
| 65 | if (!indio_dev) | 76 | if (!indio_dev) |
| 66 | return -ENOMEM; | 77 | return -ENOMEM; |
| 67 | 78 | ||
| 68 | mdata = iio_priv(indio_dev); | 79 | mdata = iio_priv(indio_dev); |
| 69 | st_sensors_of_name_probe(&client->dev, st_magn_of_match, | 80 | mdata->sensor_settings = (struct st_sensor_settings *)settings; |
| 70 | client->name, sizeof(client->name)); | ||
| 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 | err = st_magn_common_probe(indio_dev); | 86 | err = st_magn_common_probe(indio_dev); |
| 75 | if (err < 0) | 87 | if (err < 0) |
| @@ -51,19 +51,31 @@ MODULE_DEVICE_TABLE(of, st_magn_of_match); · 50 unmodified lines | |||
| 51 | 51 | ||
| 52 | static int st_magn_spi_probe(struct spi_device *spi) | 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 | struct st_sensor_data *mdata; | 55 | struct st_sensor_data *mdata; |
| 56 | struct iio_dev *indio_dev; | ||
| 56 | int err; | 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 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*mdata)); | 69 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*mdata)); |
| 59 | if (!indio_dev) | 70 | if (!indio_dev) |
| 60 | return -ENOMEM; | 71 | return -ENOMEM; |
| 61 | 72 | ||
| 62 | mdata = iio_priv(indio_dev); | 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, | 76 | err = st_sensors_spi_configure(indio_dev, spi); |
| 65 | spi->modalias, sizeof(spi->modalias)); | 77 | if (err < 0) |
| 66 | st_sensors_spi_configure(indio_dev, spi, mdata); | 78 | return err; |
| 67 | 79 | ||
| 68 | err = st_magn_common_probe(indio_dev); | 80 | err = st_magn_common_probe(indio_dev); |
| 69 | if (err < 0) | 81 | if (err < 0) |
| @@ -26,6 +26,17 @@ config DS1803 · 25 unmodified lines | |||
| 26 | To compile this driver as a module, choose M here: the | 26 | To compile this driver as a module, choose M here: the |
| 27 | module will be called ds1803. | 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 | config MAX5481 | 40 | config MAX5481 |
| 30 | tristate "Maxim MAX5481-MAX5484 Digital Potentiometer driver" | 41 | tristate "Maxim MAX5481-MAX5484 Digital Potentiometer driver" |
| 31 | depends on SPI | 42 | depends on SPI |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | |||
| 6 | # When adding new entries keep the list in alphabetical order | 6 | # When adding new entries keep the list in alphabetical order |
| 7 | obj-$(CONFIG_AD5272) += ad5272.o | 7 | obj-$(CONFIG_AD5272) += ad5272.o |
| 8 | obj-$(CONFIG_DS1803) += ds1803.o | 8 | obj-$(CONFIG_DS1803) += ds1803.o |
| 9 | obj-$(CONFIG_MAX5432) += max5432.o | ||
| 9 | obj-$(CONFIG_MAX5481) += max5481.o | 10 | obj-$(CONFIG_MAX5481) += max5481.o |
| 10 | obj-$(CONFIG_MAX5487) += max5487.o | 11 | obj-$(CONFIG_MAX5487) += max5487.o |
| 11 | obj-$(CONFIG_MCP4018) += mcp4018.o | 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 | struct cros_ec_baro_state *st = iio_priv(indio_dev); | 40 | struct cros_ec_baro_state *st = iio_priv(indio_dev); |
| 41 | u16 data = 0; | 41 | u16 data = 0; |
| 42 | int ret = IIO_VAL_INT; | 42 | int ret; |
| 43 | int idx = chan->scan_index; | 43 | int idx = chan->scan_index; |
| 44 | 44 | ||
| 45 | mutex_lock(&st->core.cmd_lock); | 45 | mutex_lock(&st->core.cmd_lock); |
| 46 | 46 | ||
| 47 | switch (mask) { | 47 | switch (mask) { |
| 48 | case IIO_CHAN_INFO_RAW: | 48 | case IIO_CHAN_INFO_RAW: |
| 49 | if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx, | 49 | ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx, |
| 50 | (s16 *)&data) < 0) | 50 | (s16 *)&data); |
| 51 | ret = -EIO; | 51 | if (ret) |
| 52 | break; | ||
| 53 | |||
| 52 | *val = data; | 54 | *val = data; |
| 55 | ret = IIO_VAL_INT; | ||
| 53 | break; | 56 | break; |
| 54 | case IIO_CHAN_INFO_SCALE: | 57 | case IIO_CHAN_INFO_SCALE: |
| 55 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; | 58 | st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE; |
| 56 | st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE; | 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)) { | 61 | ret = cros_ec_motion_send_host_cmd(&st->core, 0); |
| 59 | ret = -EIO; | 62 | if (ret) |
| 60 | break; | 63 | break; |
| 61 | } | 64 | |
| 62 | *val = st->core.resp->sensor_range.ret; | 65 | *val = st->core.resp->sensor_range.ret; |
| 63 | 66 | ||
| 64 | /* scale * in_pressure_raw --> kPa */ | 67 | /* scale * in_pressure_raw --> kPa */ |
| @@ -152,8 +155,6 @@ static int cros_ec_baro_probe(struct platform_device *pdev) · 87 unmodified lines | |||
| 152 | channel->ext_info = cros_ec_sensors_ext_info; | 155 | channel->ext_info = cros_ec_sensors_ext_info; |
| 153 | channel->scan_type.sign = 'u'; | 156 | channel->scan_type.sign = 'u'; |
| 154 | 157 | ||
| 155 | state->core.calib[0] = 0; | ||
| 156 | |||
| 157 | /* Sensor specific */ | 158 | /* Sensor specific */ |
| 158 | switch (state->core.type) { | 159 | switch (state->core.type) { |
| 159 | case MOTIONSENSE_TYPE_BARO: | 160 | case MOTIONSENSE_TYPE_BARO: |
| @@ -243,10 +243,10 @@ static int hp03_probe(struct i2c_client *client, · 242 unmodified lines | |||
| 243 | * which has it's dedicated I2C address and contains | 243 | * which has it's dedicated I2C address and contains |
| 244 | * the calibration constants for the sensor. | 244 | * the calibration constants for the sensor. |
| 245 | */ | 245 | */ |
| 246 | priv->eeprom_client = i2c_new_dummy(client->adapter, HP03_EEPROM_ADDR); | 246 | priv->eeprom_client = i2c_new_dummy_device(client->adapter, HP03_EEPROM_ADDR); |
| 247 | if (!priv->eeprom_client) { | 247 | if (IS_ERR(priv->eeprom_client)) { |
| 248 | dev_err(dev, "New EEPROM I2C device failed\n"); | 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 | priv->eeprom_regmap = regmap_init_i2c(priv->eeprom_client, | 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 | .drdy_int_pin = 1, | 41 | .drdy_int_pin = 1, |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | const struct st_sensor_settings *st_press_get_settings(const char *name); | ||
| 44 | int st_press_common_probe(struct iio_dev *indio_dev); | 45 | int st_press_common_probe(struct iio_dev *indio_dev); |
| 45 | void st_press_common_remove(struct iio_dev *indio_dev); | 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 | return st_sensors_set_dataready_irq(indio_dev, state); | 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 | static int st_press_buffer_postenable(struct iio_dev *indio_dev) | 32 | static int st_press_buffer_postenable(struct iio_dev *indio_dev) |
| 38 | { | 33 | { |
| 39 | int err; | 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 | err = iio_triggered_buffer_postenable(indio_dev); | 36 | err = iio_triggered_buffer_postenable(indio_dev); |
| 49 | if (err < 0) | 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: | 44 | return 0; |
| 55 | kfree(press_data->buffer_data); | 45 | |
| 56 | allocate_memory_error: | 46 | st_press_buffer_predisable: |
| 47 | iio_triggered_buffer_predisable(indio_dev); | ||
| 57 | return err; | 48 | return err; |
| 58 | } | 49 | } |
| 59 | 50 | ||
| 60 | static int st_press_buffer_predisable(struct iio_dev *indio_dev) | 51 | static int st_press_buffer_predisable(struct iio_dev *indio_dev) |
| 61 | { | 52 | { |
| 62 | int err; | 53 | int err, err2; |
| 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; | ||
| 68 | 54 | ||
| 69 | err = st_sensors_set_enable(indio_dev, false); | 55 | err = st_sensors_set_enable(indio_dev, false); |
| 70 | 56 | ||
| 71 | st_press_buffer_predisable_error: | 57 | err2 = iio_triggered_buffer_predisable(indio_dev); |
| 72 | kfree(press_data->buffer_data); | 58 | if (!err) |
| 59 | err = err2; | ||
| 60 | |||
| 73 | return err; | 61 | return err; |
| 74 | } | 62 | } |
| 75 | 63 | ||
| 76 | static const struct iio_buffer_setup_ops st_press_buffer_setup_ops = { | 64 | static const struct iio_buffer_setup_ops st_press_buffer_setup_ops = { |
| 77 | .preenable = &st_press_buffer_preenable, | ||
| 78 | .postenable = &st_press_buffer_postenable, | 65 | .postenable = &st_press_buffer_postenable, |
| 79 | .predisable = &st_press_buffer_predisable, | 66 | .predisable = &st_press_buffer_predisable, |
| 80 | }; | 67 | }; |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | |||
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
| 14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
| 15 | #include <linux/mutex.h> | ||
| 16 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| 17 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
| 18 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
| @@ -664,25 +663,39 @@ static const struct iio_trigger_ops st_press_trigger_ops = { · 645 unmodified lines | |||
| 664 | #define ST_PRESS_TRIGGER_OPS NULL | 663 | #define ST_PRESS_TRIGGER_OPS NULL |
| 665 | #endif | 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 | int st_press_common_probe(struct iio_dev *indio_dev) | 684 | int st_press_common_probe(struct iio_dev *indio_dev) |
| 668 | { | 685 | { |
| 669 | struct st_sensor_data *press_data = iio_priv(indio_dev); | 686 | struct st_sensor_data *press_data = iio_priv(indio_dev); |
| 670 | struct st_sensors_platform_data *pdata = | 687 | struct st_sensors_platform_data *pdata = |
| 671 | (struct st_sensors_platform_data *)press_data->dev->platform_data; | 688 | (struct st_sensors_platform_data *)press_data->dev->platform_data; |
| 672 | int irq = press_data->get_irq_data_ready(indio_dev); | ||
| 673 | int err; | 689 | int err; |
| 674 | 690 | ||
| 675 | indio_dev->modes = INDIO_DIRECT_MODE; | 691 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 676 | indio_dev->info = &press_info; | 692 | indio_dev->info = &press_info; |
| 677 | mutex_init(&press_data->tb.buf_lock); | ||
| 678 | 693 | ||
| 679 | err = st_sensors_power_enable(indio_dev); | 694 | err = st_sensors_power_enable(indio_dev); |
| 680 | if (err) | 695 | if (err) |
| 681 | return err; | 696 | return err; |
| 682 | 697 | ||
| 683 | err = st_sensors_check_device_support(indio_dev, | 698 | err = st_sensors_verify_id(indio_dev); |
| 684 | ARRAY_SIZE(st_press_sensors_settings), | ||
| 685 | st_press_sensors_settings); | ||
| 686 | if (err < 0) | 699 | if (err < 0) |
| 687 | goto st_press_power_off; | 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 | * element. | 706 | * element. |
| 694 | */ | 707 | */ |
| 695 | press_data->num_data_channels = press_data->sensor_settings->num_ch - 1; | 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 | indio_dev->channels = press_data->sensor_settings->ch; | 709 | indio_dev->channels = press_data->sensor_settings->ch; |
| 698 | indio_dev->num_channels = press_data->sensor_settings->num_ch; | 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 | if (err < 0) | 728 | if (err < 0) |
| 717 | goto st_press_power_off; | 729 | goto st_press_power_off; |
| 718 | 730 | ||
| 719 | if (irq > 0) { | 731 | if (press_data->irq > 0) { |
| 720 | err = st_sensors_allocate_trigger(indio_dev, | 732 | err = st_sensors_allocate_trigger(indio_dev, |
| 721 | ST_PRESS_TRIGGER_OPS); | 733 | ST_PRESS_TRIGGER_OPS); |
| 722 | if (err < 0) | 734 | if (err < 0) |
| @@ -733,7 +745,7 @@ int st_press_common_probe(struct iio_dev *indio_dev) · 10 unmodified lines | |||
| 733 | return err; | 745 | return err; |
| 734 | 746 | ||
| 735 | st_press_device_register_error: | 747 | st_press_device_register_error: |
| 736 | if (irq > 0) | 748 | if (press_data->irq > 0) |
| 737 | st_sensors_deallocate_trigger(indio_dev); | 749 | st_sensors_deallocate_trigger(indio_dev); |
| 738 | st_press_probe_trigger_error: | 750 | st_press_probe_trigger_error: |
| 739 | st_press_deallocate_ring(indio_dev); | 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 | st_sensors_power_disable(indio_dev); | 763 | st_sensors_power_disable(indio_dev); |
| 752 | 764 | ||
| 753 | iio_device_unregister(indio_dev); | 765 | iio_device_unregister(indio_dev); |
| 754 | if (press_data->get_irq_data_ready(indio_dev) > 0) | 766 | if (press_data->irq > 0) |
| 755 | st_sensors_deallocate_trigger(indio_dev); | 767 | st_sensors_deallocate_trigger(indio_dev); |
| 756 | 768 | ||
| 757 | st_press_deallocate_ring(indio_dev); | 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 | MODULE_DEVICE_TABLE(i2c, st_press_id_table); | 78 | MODULE_DEVICE_TABLE(i2c, st_press_id_table); |
| 79 | 79 | ||
| 80 | static int st_press_i2c_probe(struct i2c_client *client, | 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 | struct st_sensor_data *press_data; | 84 | struct st_sensor_data *press_data; |
| 85 | struct iio_dev *indio_dev; | ||
| 85 | int ret; | 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 | if (client->dev.of_node) { | 88 | if (client->dev.of_node) { |
| 94 | st_sensors_of_name_probe(&client->dev, st_press_of_match, | 89 | st_sensors_of_name_probe(&client->dev, st_press_of_match, |
| 95 | client->name, sizeof(client->name)); | 90 | client->name, sizeof(client->name)); |
| @@ -99,11 +94,27 @@ static int st_press_i2c_probe(struct i2c_client *client, · 3 unmodified lines | |||
| 99 | return -ENODEV; | 94 | return -ENODEV; |
| 100 | 95 | ||
| 101 | strlcpy(client->name, st_press_id_table[ret].name, | 96 | strlcpy(client->name, st_press_id_table[ret].name, |
| 102 | sizeof(client->name)); | 97 | sizeof(client->name)); |
| 103 | } else if (!id) | 98 | } else if (!id) |
| 104 | return -ENODEV; | 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 | ret = st_press_common_probe(indio_dev); | 119 | ret = st_press_common_probe(indio_dev); |
| 109 | if (ret < 0) | 120 | if (ret < 0) |
| @@ -61,19 +61,31 @@ MODULE_DEVICE_TABLE(of, st_press_of_match); · 60 unmodified lines | |||
| 61 | 61 | ||
| 62 | static int st_press_spi_probe(struct spi_device *spi) | 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 | struct st_sensor_data *press_data; | 65 | struct st_sensor_data *press_data; |
| 66 | struct iio_dev *indio_dev; | ||
| 66 | int err; | 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 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*press_data)); | 79 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*press_data)); |
| 69 | if (indio_dev == NULL) | 80 | if (!indio_dev) |
| 70 | return -ENOMEM; | 81 | return -ENOMEM; |
| 71 | 82 | ||
| 72 | press_data = iio_priv(indio_dev); | 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, | 86 | err = st_sensors_spi_configure(indio_dev, spi); |
| 75 | spi->modalias, sizeof(spi->modalias)); | 87 | if (err < 0) |
| 76 | st_sensors_spi_configure(indio_dev, spi, press_data); | 88 | return err; |
| 77 | 89 | ||
| 78 | err = st_press_common_probe(indio_dev); | 90 | err = st_press_common_probe(indio_dev); |
| 79 | if (err < 0) | 91 | if (err < 0) |
| @@ -230,31 +230,13 @@ static int maxim_thermocouple_probe(struct spi_device *spi) · 229 unmodified lines | |||
| 230 | data->spi = spi; | 230 | data->spi = spi; |
| 231 | data->chip = chip; | 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 | maxim_thermocouple_trigger_handler, NULL); | 235 | maxim_thermocouple_trigger_handler, NULL); |
| 235 | if (ret) | 236 | if (ret) |
| 236 | return ret; | 237 | return ret; |
| 237 | 238 | ||
| 238 | ret = iio_device_register(indio_dev); | 239 | return devm_iio_device_register(&spi->dev, 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; | ||
| 258 | } | 240 | } |
| 259 | 241 | ||
| 260 | static const struct spi_device_id maxim_thermocouple_id[] = { | 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 | .of_match_table = maxim_thermocouple_of_match, | 259 | .of_match_table = maxim_thermocouple_of_match, |
| 278 | }, | 260 | }, |
| 279 | .probe = maxim_thermocouple_probe, | 261 | .probe = maxim_thermocouple_probe, |
| 280 | .remove = maxim_thermocouple_remove, | ||
| 281 | .id_table = maxim_thermocouple_id, | 262 | .id_table = maxim_thermocouple_id, |
| 282 | }; | 263 | }; |
| 283 | module_spi_driver(maxim_thermocouple_driver); | 264 | module_spi_driver(maxim_thermocouple_driver); |
| @@ -608,86 +608,6 @@ static const struct iio_enum stm32_enable_mode_enum = { · 607 unmodified lines | |||
| 608 | .get = stm32_get_enable_mode | 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 | static ssize_t stm32_count_get_preset(struct iio_dev *indio_dev, | 611 | static ssize_t stm32_count_get_preset(struct iio_dev *indio_dev, |
| 692 | uintptr_t private, | 612 | uintptr_t private, |
| 693 | const struct iio_chan_spec *chan, | 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 | .read = stm32_count_get_preset, | 648 | .read = stm32_count_get_preset, |
| 729 | .write = stm32_count_set_preset | 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 | IIO_ENUM("enable_mode", IIO_SEPARATE, &stm32_enable_mode_enum), | 651 | IIO_ENUM("enable_mode", IIO_SEPARATE, &stm32_enable_mode_enum), |
| 736 | IIO_ENUM_AVAILABLE("enable_mode", &stm32_enable_mode_enum), | 652 | IIO_ENUM_AVAILABLE("enable_mode", &stm32_enable_mode_enum), |
| 737 | IIO_ENUM("trigger_mode", IIO_SEPARATE, &stm32_trigger_mode_enum), | 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 | {"ad7195", ID_AD7195}, | 809 | {"ad7195", ID_AD7195}, |
| 810 | {} | 810 | {} |
| 811 | }; | 811 | }; |
| 812 | |||
| 812 | MODULE_DEVICE_TABLE(spi, ad7192_id); | 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 | static struct spi_driver ad7192_driver = { | 825 | static struct spi_driver ad7192_driver = { |
| 815 | .driver = { | 826 | .driver = { |
| 816 | .name = "ad7192", | 827 | .name = "ad7192", |
| 828 | .of_match_table = ad7192_of_match, | ||
| 817 | }, | 829 | }, |
| 818 | .probe = ad7192_probe, | 830 | .probe = ad7192_probe, |
| 819 | .remove = ad7192_remove, | 831 | .remove = ad7192_remove, |
| @@ -671,7 +671,7 @@ static int ad2s1210_probe(struct spi_device *spi) · 670 unmodified lines | |||
| 671 | indio_dev->num_channels = ARRAY_SIZE(ad2s1210_channels); | 671 | indio_dev->num_channels = ARRAY_SIZE(ad2s1210_channels); |
| 672 | indio_dev->name = spi_get_device_id(spi)->name; | 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 | if (ret) | 675 | if (ret) |
| 676 | return ret; | 676 | return ret; |
| 677 | 677 | ||
| @@ -683,15 +683,6 @@ static int ad2s1210_probe(struct spi_device *spi) · 5 unmodified lines | |||
| 683 | return 0; | 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 | static const struct of_device_id ad2s1210_of_match[] = { | 686 | static const struct of_device_id ad2s1210_of_match[] = { |
| 696 | { .compatible = "adi,ad2s1210", }, | 687 | { .compatible = "adi,ad2s1210", }, |
| 697 | { } | 688 | { } |
| @@ -710,7 +701,6 @@ static struct spi_driver ad2s1210_driver = { · 12 unmodified lines | |||
| 710 | .of_match_table = of_match_ptr(ad2s1210_of_match), | 701 | .of_match_table = of_match_ptr(ad2s1210_of_match), |
| 711 | }, | 702 | }, |
| 712 | .probe = ad2s1210_probe, | 703 | .probe = ad2s1210_probe, |
| 713 | .remove = ad2s1210_remove, | ||
| 714 | .id_table = ad2s1210_id, | 704 | .id_table = ad2s1210_id, |
| 715 | }; | 705 | }; |
| 716 | module_spi_driver(ad2s1210_driver); | 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 | struct device *i3cdev_to_dev(struct i3c_device *i3cdev); | 188 | struct device *i3cdev_to_dev(struct i3c_device *i3cdev); |
| 189 | struct i3c_device *dev_to_i3cdev(struct device *dev); | 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 | static inline void i3cdev_set_drvdata(struct i3c_device *i3cdev, | 195 | static inline void i3cdev_set_drvdata(struct i3c_device *i3cdev, |
| 192 | void *data) | 196 | void *data) |
| 193 | { | 197 | { |
| @@ -62,14 +62,20 @@ struct cros_ec_sensors_core_state { · 61 unmodified lines | |||
| 62 | enum motionsensor_type type; | 62 | enum motionsensor_type type; |
| 63 | enum motionsensor_location loc; | 63 | enum motionsensor_location loc; |
| 64 | 64 | ||
| 65 | s16 calib[CROS_EC_SENSOR_MAX_AXIS]; | 65 | struct calib_data { |
| 66 | 66 | s16 offset; | |
| 67 | u16 scale; | ||
| 68 | } calib[CROS_EC_SENSOR_MAX_AXIS]; | ||
| 69 | s8 sign[CROS_EC_SENSOR_MAX_AXIS]; | ||
| 67 | u8 samples[CROS_EC_SAMPLE_SIZE]; | 70 | u8 samples[CROS_EC_SAMPLE_SIZE]; |
| 68 | 71 | ||
| 69 | int (*read_ec_sensors_data)(struct iio_dev *indio_dev, | 72 | int (*read_ec_sensors_data)(struct iio_dev *indio_dev, |
| 70 | unsigned long scan_mask, s16 *data); | 73 | unsigned long scan_mask, s16 *data); |
| 71 | 74 | ||
| 72 | int curr_sampl_freq; | 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 | struct iio_chan_spec const *chan, | 156 | struct iio_chan_spec const *chan, |
| 151 | int *val, int *val2, long mask); | 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 | * cros_ec_sensors_core_write() - function to write a value to the sensor | 178 | * cros_ec_sensors_core_write() - function to write a value to the sensor |
| 155 | * @st: pointer to state information for device | 179 | * @st: pointer to state information for device |
| @@ -16,11 +16,16 @@ · 15 unmodified lines | |||
| 16 | #include <linux/iio/trigger.h> | 16 | #include <linux/iio/trigger.h> |
| 17 | #include <linux/bitops.h> | 17 | #include <linux/bitops.h> |
| 18 | #include <linux/regulator/consumer.h> | 18 | #include <linux/regulator/consumer.h> |
| 19 | #include <linux/regmap.h> | ||
| 19 | 20 | ||
| 20 | #include <linux/platform_data/st_sensors_pdata.h> | 21 | #include <linux/platform_data/st_sensors_pdata.h> |
| 21 | 22 | ||
| 22 | #define ST_SENSORS_TX_MAX_LENGTH 2 | 23 | /* |
| 23 | #define ST_SENSORS_RX_MAX_LENGTH 6 | 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 | #define ST_SENSORS_ODR_LIST_MAX 10 | 30 | #define ST_SENSORS_ODR_LIST_MAX 10 |
| 26 | #define ST_SENSORS_FULLSCALE_AVL_MAX 10 | 31 | #define ST_SENSORS_FULLSCALE_AVL_MAX 10 |
| @@ -169,36 +174,6 @@ struct st_sensor_data_ready_irq { · 142 unmodified lines | |||
| 169 | } ig1; | 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 | * struct st_sensor_settings - ST specific sensor settings | 178 | * struct st_sensor_settings - ST specific sensor settings |
| 204 | * @wai: Contents of WhoAmI register. | 179 | * @wai: Contents of WhoAmI register. |
| @@ -242,19 +217,17 @@ struct st_sensor_settings { · 37 unmodified lines | |||
| 242 | * @current_fullscale: Maximum range of measure by the sensor. | 217 | * @current_fullscale: Maximum range of measure by the sensor. |
| 243 | * @vdd: Pointer to sensor's Vdd power supply | 218 | * @vdd: Pointer to sensor's Vdd power supply |
| 244 | * @vdd_io: Pointer to sensor's Vdd-IO power supply | 219 | * @vdd_io: Pointer to sensor's Vdd-IO power supply |
| 220 | * @regmap: Pointer to specific sensor regmap configuration. | ||
| 245 | * @enabled: Status of the sensor (false->off, true->on). | 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 | * @odr: Output data rate of the sensor [Hz]. | 222 | * @odr: Output data rate of the sensor [Hz]. |
| 249 | * num_data_channels: Number of data channels used in buffer. | 223 | * num_data_channels: Number of data channels used in buffer. |
| 250 | * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2). | 224 | * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2). |
| 251 | * @int_pin_open_drain: Set the interrupt/DRDY to open drain. | 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. | 226 | * @irq: the IRQ number. |
| 253 | * @tf: Transfer function structure used by I/O operations. | ||
| 254 | * @tb: Transfer buffers and mutex used by I/O operations. | ||
| 255 | * @edge_irq: the IRQ triggers on edges and need special handling. | 227 | * @edge_irq: the IRQ triggers on edges and need special handling. |
| 256 | * @hw_irq_trigger: if we're using the hardware interrupt on the sensor. | 228 | * @hw_irq_trigger: if we're using the hardware interrupt on the sensor. |
| 257 | * @hw_timestamp: Latest timestamp from the interrupt handler, when in use. | 229 | * @hw_timestamp: Latest timestamp from the interrupt handler, when in use. |
| 230 | * @buffer_data: Data used by buffer part. | ||
| 258 | */ | 231 | */ |
| 259 | struct st_sensor_data { | 232 | struct st_sensor_data { |
| 260 | struct device *dev; | 233 | struct device *dev; |
| @@ -264,26 +237,22 @@ struct st_sensor_data { · 3 unmodified lines | |||
| 264 | struct st_sensor_fullscale_avl *current_fullscale; | 237 | struct st_sensor_fullscale_avl *current_fullscale; |
| 265 | struct regulator *vdd; | 238 | struct regulator *vdd; |
| 266 | struct regulator *vdd_io; | 239 | struct regulator *vdd_io; |
| 240 | struct regmap *regmap; | ||
| 267 | 241 | ||
| 268 | bool enabled; | 242 | bool enabled; |
| 269 | bool multiread_bit; | ||
| 270 | |||
| 271 | char *buffer_data; | ||
| 272 | 243 | ||
| 273 | unsigned int odr; | 244 | unsigned int odr; |
| 274 | unsigned int num_data_channels; | 245 | unsigned int num_data_channels; |
| 275 | 246 | ||
| 276 | u8 drdy_int_pin; | 247 | u8 drdy_int_pin; |
| 277 | bool int_pin_open_drain; | 248 | bool int_pin_open_drain; |
| 278 | 249 | int irq; | |
| 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; | ||
| 283 | 250 | ||
| 284 | bool edge_irq; | 251 | bool edge_irq; |
| 285 | bool hw_irq_trigger; | 252 | bool hw_irq_trigger; |
| 286 | s64 hw_timestamp; | 253 | s64 hw_timestamp; |
| 254 | |||
| 255 | char buffer_data[ST_SENSORS_MAX_BUFFER_SIZE] ____cacheline_aligned; | ||
| 287 | }; | 256 | }; |
| 288 | 257 | ||
| 289 | #ifdef CONFIG_IIO_BUFFER | 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 | int st_sensors_read_info_raw(struct iio_dev *indio_dev, | 303 | int st_sensors_read_info_raw(struct iio_dev *indio_dev, |
| 335 | struct iio_chan_spec const *ch, int *val); | 304 | struct iio_chan_spec const *ch, int *val); |
| 336 | 305 | ||
| 337 | int st_sensors_check_device_support(struct iio_dev *indio_dev, | 306 | int st_sensors_get_settings_index(const char *name, |
| 338 | int num_sensors_list, const struct st_sensor_settings *sensor_settings); | 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 | ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, | 312 | ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, |
| 341 | struct device_attribute *attr, char *buf); | 313 | struct device_attribute *attr, char *buf); |
| @@ -14,8 +14,8 @@ · 13 unmodified lines | |||
| 14 | #include <linux/iio/common/st_sensors.h> | 14 | #include <linux/iio/common/st_sensors.h> |
| 15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
| 16 | 16 | ||
| 17 | void st_sensors_i2c_configure(struct iio_dev *indio_dev, | 17 | int st_sensors_i2c_configure(struct iio_dev *indio_dev, |
| 18 | struct i2c_client *client, struct st_sensor_data *sdata); | 18 | struct i2c_client *client); |
| 19 | 19 | ||
| 20 | #ifdef CONFIG_ACPI | 20 | #ifdef CONFIG_ACPI |
| 21 | int st_sensors_match_acpi_device(struct device *dev); | 21 | int st_sensors_match_acpi_device(struct device *dev); |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/spi/spi.h> | 13 | #include <linux/spi/spi.h> |
| 14 | #include <linux/iio/common/st_sensors.h> | 14 | #include <linux/iio/common/st_sensors.h> |
| 15 | 15 | ||
| 16 | void st_sensors_spi_configure(struct iio_dev *indio_dev, | 16 | int st_sensors_spi_configure(struct iio_dev *indio_dev, |
| 17 | struct spi_device *spi, struct st_sensor_data *sdata); | 17 | struct spi_device *spi); |
| 18 | 18 | ||
| 19 | #endif /* ST_SENSORS_SPI_H */ | 19 | #endif /* ST_SENSORS_SPI_H */ |
| @@ -26,6 +26,7 @@ struct adis_burst; · 25 unmodified lines | |||
| 26 | * struct adis_data - ADIS chip variant specific data | 26 | * struct adis_data - ADIS chip variant specific data |
| 27 | * @read_delay: SPI delay for read operations in us | 27 | * @read_delay: SPI delay for read operations in us |
| 28 | * @write_delay: SPI delay for write operations in us | 28 | * @write_delay: SPI delay for write operations in us |
| 29 | * @cs_change_delay: SPI delay between CS changes in us | ||
| 29 | * @glob_cmd_reg: Register address of the GLOB_CMD register | 30 | * @glob_cmd_reg: Register address of the GLOB_CMD register |
| 30 | * @msc_ctrl_reg: Register address of the MSC_CTRL register | 31 | * @msc_ctrl_reg: Register address of the MSC_CTRL register |
| 31 | * @diag_stat_reg: Register address of the DIAG_STAT register | 32 | * @diag_stat_reg: Register address of the DIAG_STAT register |
| @@ -35,6 +36,7 @@ struct adis_burst; · 3 unmodified lines | |||
| 35 | struct adis_data { | 36 | struct adis_data { |
| 36 | unsigned int read_delay; | 37 | unsigned int read_delay; |
| 37 | unsigned int write_delay; | 38 | unsigned int write_delay; |
| 39 | unsigned int cs_change_delay; | ||
| 38 | 40 | ||
| 39 | unsigned int glob_cmd_reg; | 41 | unsigned int glob_cmd_reg; |
| 40 | unsigned int msc_ctrl_reg; | 42 | unsigned int msc_ctrl_reg; |