Commit 6aed51d8 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-5.4a' of...

Merge tag 'iio-for-5.4a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

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
  ...
parents 1aee09b8 ef19ee60
......@@ -91,29 +91,6 @@ Description:
When counting down the counter start from preset value
and fire event when reach 0.
What: /sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available
KernelVersion: 4.12
Contact: benjamin.gaignard@st.com
Description:
Reading returns the list possible quadrature modes.
What: /sys/bus/iio/devices/iio:deviceX/in_count0_quadrature_mode
KernelVersion: 4.12
Contact: benjamin.gaignard@st.com
Description:
Configure the device counter quadrature modes:
channel_A:
Encoder A input servers as the count input and B as
the UP/DOWN direction control input.
channel_B:
Encoder B input serves as the count input and A as
the UP/DOWN direction control input.
quadrature:
Encoder A and B inputs are mixed to get direction
and count with a scale of 0.25.
What: /sys/bus/iio/devices/iio:deviceX/in_count_enable_mode_available
KernelVersion: 4.12
Contact: benjamin.gaignard@st.com
......
......@@ -47,6 +47,12 @@ Required properties:
Optional properties:
- A pinctrl state named "default" for each ADC channel may be defined to set
inX ADC pins in mode of operation for analog input on external pin.
- booster-supply: Phandle to the embedded booster regulator that can be used
to supply ADC analog input switches on stm32h7 and stm32mp1.
- vdd-supply: Phandle to the vdd input voltage. It can be used to supply ADC
analog input switches on stm32mp1.
- st,syscfg: Phandle to system configuration controller. It can be used to
control the analog circuitry on stm32mp1.
Contents of a stm32 adc child node:
-----------------------------------
......
* Plantower PMS7003 particulate matter sensor
Required properties:
- compatible: must one of:
"plantower,pms1003"
"plantower,pms3003"
"plantower,pms5003"
"plantower,pms6003"
"plantower,pms7003"
"plantower,pmsa003"
- vcc-supply: phandle to the regulator that provides power to the sensor
Optional properties:
- plantower,set-gpios: phandle to the GPIO connected to the SET line
- reset-gpios: phandle to the GPIO connected to the RESET line
Refer to serial/slave-device.txt for generic serial attached device bindings.
Example:
&uart0 {
air-pollution-sensor {
compatible = "plantower,pms7003";
vcc-supply = <&reg_vcc5v0>;
};
};
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/chemical/plantower,pms7003.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Plantower PMS7003 air pollution sensor
maintainers:
- Tomasz Duszynski <tduszyns@gmail.com>
description: |
Air pollution sensor capable of measuring mass concentration of dust
particles.
properties:
compatible:
enum:
- plantower,pms1003
- plantower,pms3003
- plantower,pms5003
- plantower,pms6003
- plantower,pms7003
- plantower,pmsa003
vcc-supply:
description: regulator that provides power to the sensor
maxItems: 1
plantower,set-gpios:
description: GPIO connected to the SET line
maxItems: 1
reset-gpios:
description: GPIO connected to the RESET line
maxItems: 1
required:
- compatible
- vcc-supply
examples:
- |
serial {
air-pollution-sensor {
compatible = "plantower,pms7003";
vcc-supply = <&reg_vcc5v0>;
};
};
...
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/imu/adi,adis16460.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices ADIS16460 and similar IMUs
maintainers:
- Dragos Bogdan <dragos.bogdan@analog.com>
description: |
Analog Devices ADIS16460 and similar IMUs
https://www.analog.com/media/en/technical-documentation/data-sheets/ADIS16460.pdf
properties:
compatible:
enum:
- adi,adis16460
reg:
maxItems: 1
spi-cpha: true
spi-cpol: true
interrupts:
maxItems: 1
required:
- compatible
- reg
- interrupts
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
spi0 {
#address-cells = <1>;
#size-cells = <0>;
imu@0 {
compatible = "adi,adis16460";
reg = <0>;
spi-max-frequency = <5000000>;
spi-cpol;
spi-cpha;
interrupt-parent = <&gpio0>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
};
};
......@@ -11,6 +11,8 @@ Required properties:
"st,asm330lhh"
"st,lsm6dsox"
"st,lsm6dsr"
"st,lsm6ds3tr-c"
"st,ism330dhcx"
- reg: i2c address of the sensor / spi cs line
Optional properties:
......
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/light/noa1305.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ON Semiconductor NOA1305 Ambient Light Sensor
maintainers:
- Martyn Welch <martyn.welch@collabora.com>
description: |
Ambient sensing with an i2c interface.
https://www.onsemi.com/pub/Collateral/NOA1305-D.PDF
properties:
compatible:
enum:
- onnn,noa1305
reg:
maxItems: 1
vin-supply:
description: Regulator that provides power to the sensor
required:
- compatible
- reg
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
light@39 {
compatible = "onnn,noa1305";
reg = <0x39>;
};
};
...
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/light/stk33xx.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: |
Sensortek STK33xx I2C Ambient Light and Proximity sensor
maintainers:
- Jonathan Cameron <jic23@kernel.org>
description: |
Ambient light and proximity sensor over an i2c interface.
properties:
compatible:
enum:
- sensortek,stk3310
- sensortek,stk3311
- sensortek,stk3335
reg:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
stk3310@48 {
compatible = "sensortek,stk3310";
reg = <0x48>;
interrupt-parent = <&gpio1>;
interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
};
};
...
For discussion. Unclear are:
* is the definition of +/- values practical or counterintuitive?
* are the definitions unambiguous and easy to follow?
* are the examples correct?
* should we have HOWTO engineer a correct matrix for a new device (without comparing to a different one)?
====
Mounting matrix
The mounting matrix is a device tree property used to orient any device
that produce three-dimensional data in relation to the world where it is
deployed.
The purpose of the mounting matrix is to translate the sensor frame of
reference into the device frame of reference using a translation matrix as
defined in linear algebra.
The typical usecase is that where a component has an internal representation
of the (x,y,z) triplets, such as different registers to read these coordinates,
and thus implying that the component should be mounted in a certain orientation
relative to some specific device frame of reference.
For example a device with some kind of screen, where the user is supposed to
interact with the environment using an accelerometer, gyroscope or magnetometer
mounted on the same chassis as this screen, will likely take the screen as
reference to (x,y,z) orientation, with (x,y) corresponding to these axes on the
screen and (z) being depth, the axis perpendicular to the screen.
For a screen you probably want (x) coordinates to go from negative on the left
to positive on the right, (y) from negative on the bottom to positive on top
and (z) depth to be negative under the screen and positive in front of it,
toward the face of the user.
A sensor can be mounted in any angle along the axes relative to the frame of
reference. This means that the sensor may be flipped upside-down, left-right,
or tilted at any angle relative to the frame of reference.
Another frame of reference is how the device with its sensor relates to the
external world, the environment where the device is deployed. Usually the data
from the sensor is used to figure out how the device is oriented with respect
to this world. When using the mounting matrix, the sensor and device orientation
becomes identical and we can focus on the data as it relates to the surrounding
world.
Device-to-world examples for some three-dimensional sensor types:
- Accelerometers have their world frame of reference toward the center of
gravity, usually to the core of the planet. A reading of the (x,y,z) values
from the sensor will give a projection of the gravity vector through the
device relative to the center of the planet, i.e. relative to its surface at
this point. Up and down in the world relative to the device frame of
reference can thus be determined. and users would likely expect a value of
9.81 m/s^2 upwards along the (z) axis, i.e. out of the screen when the device
is held with its screen flat on the planets surface and 0 on the other axes,
as the gravity vector is projected 1:1 onto the sensors (z)-axis.
If you tilt the device, the g vector virtually coming out of the display
is projected onto the (x,y) plane of the display panel.
Example:
^ z: +g ^ z: > 0
! /!
! x=y=0 / ! x: > 0
+--------+ +--------+
! ! ! !
+--------+ +--------+
! /
! /
v v
center of center of
gravity gravity
If the device is tilted to the left, you get a positive x value. If you point
its top towards surface, you get a negative y axis.
(---------)
! ! y: -g
! ! ^
! ! !
! !
! ! x: +g <- z: +g -> x: -g
! 1 2 3 !
! 4 5 6 ! !
! 7 8 9 ! v
! * 0 # ! y: +g
(---------)
- Magnetometers (compasses) have their world frame of reference relative to the
geomagnetic field. The system orientation vis-a-vis the world is defined with
respect to the local earth geomagnetic reference frame where (y) is in the
ground plane and positive towards magnetic North, (x) is in the ground plane,
perpendicular to the North axis and positive towards the East and (z) is
perpendicular to the ground plane and positive upwards.
^^^ North: y > 0
(---------)
! !
! !
! !
! ! >
! ! > North: x > 0
! 1 2 3 ! >
! 4 5 6 !
! 7 8 9 !
! * 0 # !
(---------)
Since the geomagnetic field is not uniform this definition fails if we come
closer to the poles.
Sensors and driver can not and should not take care of this because there
are complex calculations and empirical data to be taken care of. We leave
this up to user space.
The definition we take:
If the device is placed at the equator and the top is pointing north, the
display is readable by a person standing upright on the earth surface, this
defines a positive y value.
- Gyroscopes detects the movement relative the device itself. The angular
velocity is defined as orthogonal to the plane of rotation, so if you put the
device on a flat surface and spin it around the z axis (such as rotating a
device with a screen lying flat on a table), you should get a negative value
along the (z) axis if rotated clockwise, and a positive value if rotated
counter-clockwise according to the right-hand rule.
(---------) y > 0
! ! v---\
! !
! !
! ! <--\
! ! ! z > 0
! 1 2 3 ! --/
! 4 5 6 !
! 7 8 9 !
! * 0 # !
(---------)
So unless the sensor is ideally mounted, we need a means to indicate the
relative orientation of any given sensor of this type with respect to the
frame of reference.
To achieve this, use the device tree property "mount-matrix" for the sensor.
This supplies a 3x3 rotation matrix in the strict linear algebraic sense,
to orient the senor axes relative to a desired point of reference. This means
the resulting values from the sensor, after scaling to proper units, should be
multiplied by this matrix to give the proper vectors values in three-dimensional
space, relative to the device or world point of reference.
For more information, consult:
https://en.wikipedia.org/wiki/Rotation_matrix
The mounting matrix has the layout:
(mxx, myx, mzx)
(mxy, myy, mzy)
(mxz, myz, mzz)
Values are intended to be multiplied as:
x' = mxx * x + myx * y + mzx * z
y' = mxy * x + myy * y + mzy * z
z' = mxz * x + myz * y + mzz * z
It is represented as an array of strings containing the real values for
producing the transformation matrix.
Examples:
Identity matrix (nothing happens to the coordinates, which means the device was
mechanically mounted in an ideal way and we need no transformation):
mount-matrix = "1", "0", "0",
"0", "1", "0",
"0", "0", "1";
The sensor is mounted 30 degrees (Pi/6 radians) tilted along the X axis, so we
compensate by performing a -30 degrees rotation around the X axis:
mount-matrix = "1", "0", "0",
"0", "0.866", "0.5",
"0", "-0.5", "0.866";
The sensor is flipped 180 degrees (Pi radians) around the Z axis, i.e. mounted
upside-down:
mount-matrix = "0.998", "0.054", "0",
"-0.054", "0.998", "0",
"0", "0", "1";
???: this does not match "180 degrees" - factors indicate ca. 3 degrees compensation
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/potentiometer/max5432.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim Integrated MAX5432-MAX5435 Digital Potentiometers
maintainers:
- Martin Kaiser <martin@kaiser.cx>
description: |
Maxim Integrated MAX5432-MAX5435 Digital Potentiometers connected via I2C
Datasheet:
https://datasheets.maximintegrated.com/en/ds/MAX5432-MAX5435.pdf
properties:
compatible:
enum:
- maxim,max5432
- maxim,max5433
- maxim,max5434
- maxim,max5435
reg:
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
max5434@28 {
compatible = "maxim,max5434";
reg = <0x28>;
};
};
......@@ -813,6 +813,8 @@ patternProperties:
description: Semtech Corporation
"^sensirion,.*":
description: Sensirion AG
"^sensortek,.*":
description: Sensortek Technology Corporation
"^sff,.*":
description: Small Form Factor Committee
"^sgd,.*":
......
......@@ -945,6 +945,14 @@ L: linux-iio@vger.kernel.org
F: include/linux/iio/imu/adis.h
F: drivers/iio/imu/adis.c
ANALOG DEVICES INC ADIS16460 DRIVER
M: Dragos Bogdan <dragos.bogdan@analog.com>
S: Supported
L: linux-iio@vger.kernel.org
W: http://ez.analog.com/community/linux-device-drivers
F: drivers/iio/imu/adis16460.c
F: Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml
ANALOG DEVICES INC ADP5061 DRIVER
M: Stefan Popa <stefan.popa@analog.com>
L: linux-pm@vger.kernel.org
......@@ -12776,6 +12784,12 @@ F: drivers/i2c/busses/i2c-puv3.c
F: drivers/video/fbdev/fb-puv3.c
F: drivers/rtc/rtc-puv3.c
PLANTOWER PMS7003 AIR POLLUTION SENSOR DRIVER
M: Tomasz Duszynski <tduszyns@gmail.com>
S: Maintained
F: drivers/iio/chemical/pms7003.c
F: Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml
PMBUS HARDWARE MONITORING DRIVERS
M: Guenter Roeck <linux@roeck-us.net>
L: linux-hwmon@vger.kernel.org
......
......@@ -100,16 +100,18 @@ static void ftm_quaddec_init(struct ftm_quaddec *ftm)
ftm_set_write_protection(ftm);
}
static void ftm_quaddec_disable(struct ftm_quaddec *ftm)
static void ftm_quaddec_disable(void *ftm)
{
ftm_clear_write_protection(ftm);
ftm_write(ftm, FTM_MODE, 0);
ftm_write(ftm, FTM_QDCTRL, 0);
struct ftm_quaddec *ftm_qua = ftm;
ftm_clear_write_protection(ftm_qua);
ftm_write(ftm_qua, FTM_MODE, 0);
ftm_write(ftm_qua, FTM_QDCTRL, 0);
/*
* This is enough to disable the counter. No clock has been
* selected by writing to FTM_SC in init()
*/
ftm_set_write_protection(ftm);
ftm_set_write_protection(ftm_qua);
}
static int ftm_quaddec_get_prescaler(struct counter_device *counter,
......@@ -317,20 +319,13 @@ static int ftm_quaddec_probe(struct platform_device *pdev)
ftm_quaddec_init(ftm);
ret = counter_register(&ftm->counter);
ret = devm_add_action_or_reset(&pdev->dev, ftm_quaddec_disable, ftm);
if (ret)
ftm_quaddec_disable(ftm);
return ret;
}
static int ftm_quaddec_remove(struct platform_device *pdev)
{
struct ftm_quaddec *ftm = platform_get_drvdata(pdev);
counter_unregister(&ftm->counter);
ftm_quaddec_disable(ftm);
ret = devm_counter_register(&pdev->dev, &ftm->counter);
if (ret)
return ret;
return 0;
}
......@@ -346,7 +341,6 @@ static struct platform_driver ftm_quaddec_driver = {
.of_match_table = ftm_quaddec_match,
},
.probe = ftm_quaddec_probe,
.remove = ftm_quaddec_remove,
};
module_platform_driver(ftm_quaddec_driver);
......
......@@ -200,6 +200,59 @@ struct i3c_device *dev_to_i3cdev(struct device *dev)
}
EXPORT_SYMBOL_GPL(dev_to_i3cdev);
/**
* i3c_device_match_id() - Returns the i3c_device_id entry matching @i3cdev
* @i3cdev: I3C device
* @id_table: I3C device match table
*
* Return: a pointer to an i3c_device_id object or NULL if there's no match.
*/
const struct i3c_device_id *
i3c_device_match_id(struct i3c_device *i3cdev,
const struct i3c_device_id *id_table)
{
struct i3c_device_info devinfo;
const struct i3c_device_id *id;
i3c_device_get_info(i3cdev, &devinfo);
/*
* The lower 32bits of the provisional ID is just filled with a random
* value, try to match using DCR info.
*/
if (!I3C_PID_RND_LOWER_32BITS(devinfo.pid)) {
u16 manuf = I3C_PID_MANUF_ID(devinfo.pid);
u16 part = I3C_PID_PART_ID(devinfo.pid);
u16 ext_info = I3C_PID_EXTRA_INFO(devinfo.pid);
/* First try to match by manufacturer/part ID. */
for (id = id_table; id->match_flags != 0; id++) {
if ((id->match_flags & I3C_MATCH_MANUF_AND_PART) !=
I3C_MATCH_MANUF_AND_PART)
continue;
if (manuf != id->manuf_id || part != id->part_id)
continue;
if ((id->match_flags & I3C_MATCH_EXTRA_INFO) &&
ext_info != id->extra_info)
continue;
return id;
}
}
/* Fallback to DCR match. */
for (id = id_table; id->match_flags != 0; id++) {
if ((id->match_flags & I3C_MATCH_DCR) &&
id->dcr == devinfo.dcr)
return id;
}
return NULL;
}
EXPORT_SYMBOL_GPL(i3c_device_match_id);
/**
* i3c_driver_register_with_owner() - register an I3C device driver
*
......
......@@ -276,51 +276,6 @@ static const struct device_type i3c_device_type = {
.uevent = i3c_device_uevent,
};
static const struct i3c_device_id *
i3c_device_match_id(struct i3c_device *i3cdev,
const struct i3c_device_id *id_table)
{
struct i3c_device_info devinfo;
const struct i3c_device_id *id;
i3c_device_get_info(i3cdev, &devinfo);
/*
* The lower 32bits of the provisional ID is just filled with a random
* value, try to match using DCR info.
*/
if (!I3C_PID_RND_LOWER_32BITS(devinfo.pid)) {
u16 manuf = I3C_PID_MANUF_ID(devinfo.pid);
u16 part = I3C_PID_PART_ID(devinfo.pid);
u16 ext_info = I3C_PID_EXTRA_INFO(devinfo.pid);
/* First try to match by manufacturer/part ID. */
for (id = id_table; id->match_flags != 0; id++) {
if ((id->match_flags & I3C_MATCH_MANUF_AND_PART) !=
I3C_MATCH_MANUF_AND_PART)
continue;
if (manuf != id->manuf_id || part != id->part_id)
continue;
if ((id->match_flags & I3C_MATCH_EXTRA_INFO) &&
ext_info != id->extra_info)
continue;
return id;
}
}
/* Fallback to DCR match. */
for (id = id_table; id->match_flags != 0; id++) {
if ((id->match_flags & I3C_MATCH_DCR) &&
id->dcr == devinfo.dcr)
return id;
}
return NULL;
}
static int i3c_device_match(struct device *dev, struct device_driver *drv)
{
struct i3c_device *i3cdev;
......
......@@ -202,9 +202,7 @@ config HID_SENSOR_ACCEL_3D
config IIO_CROS_EC_ACCEL_LEGACY
tristate "ChromeOS EC Legacy Accelerometer Sensor"
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select CROS_EC_LPC_REGISTER_DEVICE
depends on IIO_CROS_EC_SENSORS_CORE
help
Say yes here to get support for accelerometers on Chromebook using
legacy EC firmware.
......
This diff is collapsed.
......@@ -424,7 +424,7 @@ static int mxc4005_probe(struct i2c_client *client,
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &mxc4005_info;
ret = iio_triggered_buffer_setup(indio_dev,
ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
iio_pollfunc_store_time,
mxc4005_trigger_handler,
NULL);
......@@ -452,7 +452,7 @@ static int mxc4005_probe(struct i2c_client *client,
if (ret) {
dev_err(&client->dev,
"failed to init threaded irq\n");
goto err_buffer_cleanup;
return ret;
}
data->dready_trig->dev.parent = &client->dev;
......@@ -460,43 +460,16 @@ static int mxc4005_probe(struct i2c_client *client,
iio_trigger_set_drvdata(data->dready_trig, indio_dev);
indio_dev->trig = data->dready_trig;
iio_trigger_get(indio_dev->trig);
ret = iio_trigger_register(data->dready_trig);
ret = devm_iio_trigger_register(&client->dev,
data->dready_trig);
if (ret) {
dev_err(&client->dev,
"failed to register trigger\n");
goto err_trigger_unregister;
}
return ret;
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev,
"unable to register iio device %d\n", ret);
goto err_buffer_cleanup;
}
return 0;
err_trigger_unregister:
iio_trigger_unregister(data->dready_trig);
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
static int mxc4005_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct mxc4005_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
if (data->dready_trig)
iio_trigger_unregister(data->dready_trig);
return 0;
return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct acpi_device_id mxc4005_acpi_match[] = {
......@@ -517,7 +490,6 @@ static struct i2c_driver mxc4005_driver = {
.acpi_match_table = ACPI_PTR(mxc4005_acpi_match),
},
.probe = mxc4005_probe,
.remove = mxc4005_remove,
.id_table = mxc4005_id,
};
......
......@@ -111,7 +111,7 @@
/* Currently unsupported */
#define SCA3000_MD_CTRL_AND_Y BIT(3)
#define SCA3000_MD_CTRL_AND_X BIT(4)
#define SAC3000_MD_CTRL_AND_Z BIT(5)
#define SCA3000_MD_CTRL_AND_Z BIT(5)
/*
* 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 = {
.drdy_int_pin = 1,
};
const struct st_sensor_settings *st_accel_get_settings(const char *name);
int st_accel_common_probe(struct iio_dev *indio_dev);
void st_accel_common_remove(struct iio_dev *indio_dev);
......
......@@ -29,65 +29,51 @@ int st_accel_trig_set_state(struct iio_trigger *trig, bool state)
return st_sensors_set_dataready_irq(indio_dev, state);
}
static int st_accel_buffer_preenable(struct iio_dev *indio_dev)
{
return st_sensors_set_enable(indio_dev, true);
}
static int st_accel_buffer_postenable(struct iio_dev *indio_dev)
{
int err;
struct st_sensor_data *adata = iio_priv(indio_dev);
adata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (adata->buffer_data == NULL) {
err = -ENOMEM;
goto allocate_memory_error;
}
err = iio_triggered_buffer_postenable(indio_dev);
if (err < 0)
goto st_accel_buffer_postenable_error;
return err;
err = st_sensors_set_axis_enable(indio_dev,
(u8)indio_dev->active_scan_mask[0]);
if (err < 0)
goto st_sensors_set_axis_enable_error;
goto st_accel_buffer_predisable;
return err;
err = st_sensors_set_enable(indio_dev, true);
if (err < 0)
goto st_accel_buffer_enable_all_axis;
st_sensors_set_axis_enable_error:
return 0;
st_accel_buffer_enable_all_axis:
st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
st_accel_buffer_predisable:
iio_triggered_buffer_predisable(indio_dev);
st_accel_buffer_postenable_error:
kfree(adata->buffer_data);
allocate_memory_error:
return err;
}
static int st_accel_buffer_predisable(struct iio_dev *indio_dev)
{
int err, err2;
struct st_sensor_data *adata = iio_priv(indio_dev);
err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
if (err < 0)
goto st_accel_buffer_predisable_error;
err = st_sensors_set_enable(indio_dev, false);
if (err < 0)
goto st_accel_buffer_predisable_error;
goto st_accel_buffer_predisable;
err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
st_accel_buffer_predisable_error:
st_accel_buffer_predisable:
err2 = iio_triggered_buffer_predisable(indio_dev);
if (!err)
err = err2;
kfree(adata->buffer_data);
return err;
}
static const struct iio_buffer_setup_ops st_accel_buffer_setup_ops = {
.preenable = &st_accel_buffer_preenable,
.postenable = &st_accel_buffer_postenable,
.predisable = &st_accel_buffer_predisable,
};
......
......@@ -13,7 +13,6 @@
#include <linux/acpi.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
......@@ -1147,32 +1146,45 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev,
#endif
}
/*
* st_accel_get_settings() - get sensor settings from device name
* @name: device name buffer reference.
*
* Return: valid reference on success, NULL otherwise.
*/
const struct st_sensor_settings *st_accel_get_settings(const char *name)
{
int index = st_sensors_get_settings_index(name,
st_accel_sensors_settings,
ARRAY_SIZE(st_accel_sensors_settings));
if (index < 0)
return NULL;
return &st_accel_sensors_settings[index];
}
EXPORT_SYMBOL(st_accel_get_settings);
int st_accel_common_probe(struct iio_dev *indio_dev)
{
struct st_sensor_data *adata = iio_priv(indio_dev);
struct st_sensors_platform_data *pdata =
(struct st_sensors_platform_data *)adata->dev->platform_data;
int irq = adata->get_irq_data_ready(indio_dev);
struct iio_chan_spec *channels;
size_t channels_size;
int err;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &accel_info;
mutex_init(&adata->tb.buf_lock);
err = st_sensors_power_enable(indio_dev);
if (err)
return err;
err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_accel_sensors_settings),
st_accel_sensors_settings);
err = st_sensors_verify_id(indio_dev);
if (err < 0)
goto st_accel_power_off;
adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS;
adata->multiread_bit = adata->sensor_settings->multi_read_bit;
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
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)
if (err < 0)
goto st_accel_power_off;
if (irq > 0) {
if (adata->irq > 0) {
err = st_sensors_allocate_trigger(indio_dev,
ST_ACCEL_TRIGGER_OPS);
if (err < 0)
......@@ -1221,7 +1233,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
return 0;
st_accel_device_register_error:
if (irq > 0)
if (adata->irq > 0)
st_sensors_deallocate_trigger(indio_dev);
st_accel_probe_trigger_error:
st_accel_deallocate_ring(indio_dev);
......@@ -1239,7 +1251,7 @@ void st_accel_common_remove(struct iio_dev *indio_dev)
st_sensors_power_disable(indio_dev);
iio_device_unregister(indio_dev);
if (adata->get_irq_data_ready(indio_dev) > 0)
if (adata->irq > 0)
st_sensors_deallocate_trigger(indio_dev);
st_accel_deallocate_ring(indio_dev);
......
......@@ -150,22 +150,33 @@ MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
static int st_accel_i2c_probe(struct i2c_client *client)
{
struct iio_dev *indio_dev;
const struct st_sensor_settings *settings;
struct st_sensor_data *adata;
struct iio_dev *indio_dev;
const char *match;
int ret;
match = device_get_match_data(&client->dev);
if (match)
strlcpy(client->name, match, sizeof(client->name));
settings = st_accel_get_settings(client->name);
if (!settings) {
dev_err(&client->dev, "device name %s not recognized.\n",
client->name);
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*adata));
if (!indio_dev)
return -ENOMEM;
adata = iio_priv(indio_dev);
adata->sensor_settings = (struct st_sensor_settings *)settings;
match = device_get_match_data(&client->dev);
if (match)
strlcpy(client->name, match, sizeof(client->name));
st_sensors_i2c_configure(indio_dev, client, adata);
ret = st_sensors_i2c_configure(indio_dev, client);
if (ret < 0)
return ret;
ret = st_accel_common_probe(indio_dev);
if (ret < 0)
......
......@@ -102,19 +102,31 @@ MODULE_DEVICE_TABLE(of, st_accel_of_match);
static int st_accel_spi_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
const struct st_sensor_settings *settings;
struct st_sensor_data *adata;
struct iio_dev *indio_dev;
int err;
st_sensors_of_name_probe(&spi->dev, st_accel_of_match,
spi->modalias, sizeof(spi->modalias));
settings = st_accel_get_settings(spi->modalias);
if (!settings) {
dev_err(&spi->dev, "device name %s not recognized.\n",
spi->modalias);
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adata));
if (!indio_dev)
return -ENOMEM;
adata = iio_priv(indio_dev);
adata->sensor_settings = (struct st_sensor_settings *)settings;
st_sensors_of_name_probe(&spi->dev, st_accel_of_match,
spi->modalias, sizeof(spi->modalias));
st_sensors_spi_configure(indio_dev, spi, adata);
err = st_sensors_spi_configure(indio_dev, spi);
if (err < 0)
return err;
err = st_accel_common_probe(indio_dev);
if (err < 0)
......
......@@ -35,6 +35,11 @@ static const unsigned int ad7606_scale_avail[2] = {
152588, 305176
};
static const unsigned int ad7616_sw_scale_avail[3] = {
76293, 152588, 305176
};
static const unsigned int ad7606_oversampling_avail[7] = {
1, 2, 4, 8, 16, 32, 64,
};
......@@ -55,6 +60,29 @@ static int ad7606_reset(struct ad7606_state *st)
return -ENODEV;
}
static int ad7606_reg_access(struct iio_dev *indio_dev,
unsigned int reg,
unsigned int writeval,
unsigned int *readval)
{
struct ad7606_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&st->lock);
if (readval) {
ret = st->bops->reg_read(st, reg);
if (ret < 0)
goto err_unlock;
*readval = ret;
ret = 0;
} else {
ret = st->bops->reg_write(st, reg, writeval);
}
err_unlock:
mutex_unlock(&st->lock);
return ret;
}
static int ad7606_read_samples(struct ad7606_state *st)
{
unsigned int num = st->chip_info->num_channels;
......@@ -308,29 +336,6 @@ static const struct attribute_group ad7606_attribute_group_range = {
.attrs = ad7606_attributes_range,
};
#define AD760X_CHANNEL(num, mask) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = num, \
.address = num, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
.info_mask_shared_by_all = mask, \
.scan_index = num, \
.scan_type = { \
.sign = 's', \
.realbits = 16, \
.storagebits = 16, \
.endianness = IIO_CPU, \
}, \
}
#define AD7605_CHANNEL(num) \
AD760X_CHANNEL(num, 0)
#define AD7606_CHANNEL(num) \
AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO))
static const struct iio_chan_spec ad7605_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(4),
AD7605_CHANNEL(0),
......@@ -519,6 +524,14 @@ static const struct iio_info ad7606_info_os_and_range = {
.validate_trigger = &ad7606_validate_trigger,
};
static const struct iio_info ad7606_info_os_range_and_debug = {
.read_raw = &ad7606_read_raw,
.write_raw = &ad7606_write_raw,
.debugfs_reg_access = &ad7606_reg_access,
.attrs = &ad7606_attribute_group_os_and_range,
.validate_trigger = &ad7606_validate_trigger,
};
static const struct iio_info ad7606_info_os = {
.read_raw = &ad7606_read_raw,
.write_raw = &ad7606_write_raw,
......@@ -617,35 +630,27 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
if (ret)
dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n");
/* AD7616 requires al least 15ms to reconfigure after a reset */
if (msleep_interruptible(15))
return -ERESTARTSYS;
st->write_scale = ad7606_write_scale_hw;
st->write_os = ad7606_write_os_hw;
if (st->chip_info->sw_mode_config)
if (st->bops->sw_mode_config)
st->sw_mode_en = device_property_present(st->dev,
"adi,sw-mode");
if (st->sw_mode_en) {
/* Scale of 0.076293 is only available in sw mode */
st->scale_avail = ad7616_sw_scale_avail;
st->num_scales = ARRAY_SIZE(ad7616_sw_scale_avail);
/* After reset, in software mode, ±10 V is set by default */
memset32(st->range, 2, ARRAY_SIZE(st->range));
indio_dev->info = &ad7606_info_os_and_range;
/*
* In software mode, the range gpio has no longer its function.
* Instead, the scale can be configured individually for each
* channel from the range registers.
*/
if (st->chip_info->write_scale_sw)
st->write_scale = st->chip_info->write_scale_sw;
/*
* In software mode, the oversampling is no longer configured
* with GPIO pins. Instead, the oversampling can be configured
* in configuratiion register.
*/
if (st->chip_info->write_os_sw)
st->write_os = st->chip_info->write_os_sw;
indio_dev->info = &ad7606_info_os_range_and_debug;
ret = st->chip_info->sw_mode_config(indio_dev);
ret = st->bops->sw_mode_config(indio_dev);
if (ret < 0)
return ret;
}
......
......@@ -8,6 +8,36 @@
#ifndef IIO_ADC_AD7606_H_
#define IIO_ADC_AD7606_H_
#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = num, \
.address = num, \
.info_mask_separate = mask_sep, \
.info_mask_shared_by_type = mask_type, \
.info_mask_shared_by_all = mask_all, \
.scan_index = num, \
.scan_type = { \
.sign = 's', \
.realbits = 16, \
.storagebits = 16, \
.endianness = IIO_CPU, \
}, \
}
#define AD7605_CHANNEL(num) \
AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \
BIT(IIO_CHAN_INFO_SCALE), 0)
#define AD7606_CHANNEL(num) \
AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \
BIT(IIO_CHAN_INFO_SCALE), \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO))
#define AD7616_CHANNEL(num) \
AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),\
0, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO))
/**
* struct ad7606_chip_info - chip specific information
* @channels: channel specification
......@@ -16,12 +46,6 @@
* oversampling ratios.
* @oversampling_num number of elements stored in oversampling_avail array
* @os_req_reset some devices require a reset to update oversampling
* @write_scale_sw pointer to the function which writes the scale via spi
in software mode
* @write_os_sw pointer to the function which writes the os via spi
in software mode
* @sw_mode_config: pointer to a function which configured the device
* for software mode
*/
struct ad7606_chip_info {
const struct iio_chan_spec *channels;
......@@ -29,9 +53,6 @@ struct ad7606_chip_info {
const unsigned int *oversampling_avail;
unsigned int oversampling_num;
bool os_req_reset;
int (*write_scale_sw)(struct iio_dev *indio_dev, int ch, int val);
int (*write_os_sw)(struct iio_dev *indio_dev, int val);
int (*sw_mode_config)(struct iio_dev *indio_dev);
};
/**
......@@ -63,6 +84,7 @@ struct ad7606_chip_info {
* @complete completion to indicate end of conversion
* @trig The IIO trigger associated with the device.
* @data buffer for reading data from the device
* @d16 be16 buffer for reading data from the device
*/
struct ad7606_state {
struct device *dev;
......@@ -96,15 +118,32 @@ struct ad7606_state {
* 16 * 16-bit samples + 64-bit timestamp
*/
unsigned short data[20] ____cacheline_aligned;
__be16 d16[2];
};
/**
* struct ad7606_bus_ops - driver bus operations
* @read_block function pointer for reading blocks of data
* @sw_mode_config: pointer to a function which configured the device
* for software mode
* @reg_read function pointer for reading spi register
* @reg_write function pointer for writing spi register
* @write_mask function pointer for write spi register with mask
* @rd_wr_cmd pointer to the function which calculates the spi address
*/
struct ad7606_bus_ops {
/* more methods added in future? */
int (*read_block)(struct device *dev, int num, void *data);
int (*sw_mode_config)(struct iio_dev *indio_dev);
int (*reg_read)(struct ad7606_state *st, unsigned int addr);
int (*reg_write)(struct ad7606_state *st,
unsigned int addr,
unsigned int val);
int (*write_mask)(struct ad7606_state *st,
unsigned int addr,
unsigned long mask,
unsigned int val);
u16 (*rd_wr_cmd)(int addr, char isWriteOp);
};
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)
int irq;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "no irq: %d\n", irq);
if (irq < 0)
return irq;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
addr = devm_ioremap_resource(&pdev->dev, res);
......
......@@ -15,6 +15,51 @@
#define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */
#define AD7616_CONFIGURATION_REGISTER 0x02
#define AD7616_OS_MASK GENMASK(4, 2)
#define AD7616_BURST_MODE BIT(6)
#define AD7616_SEQEN_MODE BIT(5)
#define AD7616_RANGE_CH_A_ADDR_OFF 0x04
#define AD7616_RANGE_CH_B_ADDR_OFF 0x06
/*
* Range of channels from a group are stored in 2 registers.
* 0, 1, 2, 3 in a register followed by 4, 5, 6, 7 in second register.
* For channels from second group(8-15) the order is the same, only with
* an offset of 2 for register address.
*/
#define AD7616_RANGE_CH_ADDR(ch) ((ch) >> 2)
/* The range of the channel is stored on 2 bits*/
#define AD7616_RANGE_CH_MSK(ch) (0b11 << (((ch) & 0b11) * 2))
#define AD7616_RANGE_CH_MODE(ch, mode) ((mode) << ((((ch) & 0b11)) * 2))
static const struct iio_chan_spec ad7616_sw_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(16),
AD7616_CHANNEL(0),
AD7616_CHANNEL(1),
AD7616_CHANNEL(2),
AD7616_CHANNEL(3),
AD7616_CHANNEL(4),
AD7616_CHANNEL(5),
AD7616_CHANNEL(6),
AD7616_CHANNEL(7),
AD7616_CHANNEL(8),
AD7616_CHANNEL(9),
AD7616_CHANNEL(10),
AD7616_CHANNEL(11),
AD7616_CHANNEL(12),
AD7616_CHANNEL(13),
AD7616_CHANNEL(14),
AD7616_CHANNEL(15),
};
static u16 ad7616_spi_rd_wr_cmd(int addr, char isWriteOp)
{
/*
* The address of register consist of one w/r bit
* 6 bits of address followed by one reserved bit.
*/
return ((addr & 0x7F) << 1) | ((isWriteOp & 0x1) << 7);
}
static int ad7606_spi_read_block(struct device *dev,
int count, void *buf)
{
......@@ -35,17 +80,145 @@ static int ad7606_spi_read_block(struct device *dev,
return 0;
}
static int ad7606_spi_reg_read(struct ad7606_state *st, unsigned int addr)
{
struct spi_device *spi = to_spi_device(st->dev);
struct spi_transfer t[] = {
{
.tx_buf = &st->d16[0],
.len = 2,
.cs_change = 0,
}, {
.rx_buf = &st->d16[1],
.len = 2,
},
};
int ret;
st->d16[0] = cpu_to_be16(st->bops->rd_wr_cmd(addr, 0) << 8);
ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t));
if (ret < 0)
return ret;
return be16_to_cpu(st->d16[1]);
}
static int ad7606_spi_reg_write(struct ad7606_state *st,
unsigned int addr,
unsigned int val)
{
struct spi_device *spi = to_spi_device(st->dev);
st->d16[0] = cpu_to_be16((st->bops->rd_wr_cmd(addr, 1) << 8) |
(val & 0x1FF));
return spi_write(spi, &st->d16[0], sizeof(st->d16[0]));
}
static int ad7606_spi_write_mask(struct ad7606_state *st,
unsigned int addr,
unsigned long mask,
unsigned int val)
{
int readval;
readval = st->bops->reg_read(st, addr);
if (readval < 0)
return readval;
readval &= ~mask;
readval |= val;
return st->bops->reg_write(st, addr, readval);
}
static int ad7616_write_scale_sw(struct iio_dev *indio_dev, int ch, int val)
{
struct ad7606_state *st = iio_priv(indio_dev);
unsigned int ch_addr, mode, ch_index;
/*
* Ad7616 has 16 channels divided in group A and group B.
* The range of channels from A are stored in registers with address 4
* while channels from B are stored in register with address 6.
* The last bit from channels determines if it is from group A or B
* because the order of channels in iio is 0A, 0B, 1A, 1B...
*/
ch_index = ch >> 1;
ch_addr = AD7616_RANGE_CH_ADDR(ch_index);
if ((ch & 0x1) == 0) /* channel A */
ch_addr += AD7616_RANGE_CH_A_ADDR_OFF;
else /* channel B */
ch_addr += AD7616_RANGE_CH_B_ADDR_OFF;
/* 0b01 for 2.5v, 0b10 for 5v and 0b11 for 10v */
mode = AD7616_RANGE_CH_MODE(ch_index, ((val + 1) & 0b11));
return st->bops->write_mask(st, ch_addr, AD7616_RANGE_CH_MSK(ch_index),
mode);
}
static int ad7616_write_os_sw(struct iio_dev *indio_dev, int val)
{
struct ad7606_state *st = iio_priv(indio_dev);
return st->bops->write_mask(st, AD7616_CONFIGURATION_REGISTER,
AD7616_OS_MASK, val << 2);
}
static int ad7616_sw_mode_config(struct iio_dev *indio_dev)
{
struct ad7606_state *st = iio_priv(indio_dev);
/*
* Scale can be configured individually for each channel
* in software mode.
*/
indio_dev->channels = ad7616_sw_channels;
st->write_scale = ad7616_write_scale_sw;
st->write_os = &ad7616_write_os_sw;
/* Activate Burst mode and SEQEN MODE */
return st->bops->write_mask(st,
AD7616_CONFIGURATION_REGISTER,
AD7616_BURST_MODE | AD7616_SEQEN_MODE,
AD7616_BURST_MODE | AD7616_SEQEN_MODE);
}
static const struct ad7606_bus_ops ad7606_spi_bops = {
.read_block = ad7606_spi_read_block,
};
static const struct ad7606_bus_ops ad7616_spi_bops = {
.read_block = ad7606_spi_read_block,
.reg_read = ad7606_spi_reg_read,
.reg_write = ad7606_spi_reg_write,
.write_mask = ad7606_spi_write_mask,
.rd_wr_cmd = ad7616_spi_rd_wr_cmd,
.sw_mode_config = ad7616_sw_mode_config,
};
static int ad7606_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
const struct ad7606_bus_ops *bops;
switch (id->driver_data) {
case ID_AD7616:
bops = &ad7616_spi_bops;
break;
default:
bops = &ad7606_spi_bops;
break;
}
return ad7606_probe(&spi->dev, spi->irq, NULL,
id->name, id->driver_data,
&ad7606_spi_bops);
bops);
}
static const struct spi_device_id ad7606_id_table[] = {
......
......@@ -1179,10 +1179,8 @@ static int at91_adc_probe(struct platform_device *pdev)
idev->info = &at91_adc_info;
st->irq = platform_get_irq(pdev, 0);
if (st->irq < 0) {
dev_err(&pdev->dev, "No IRQ ID is designated\n");
if (st->irq < 0)
return -ENODEV;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......
......@@ -225,10 +225,8 @@ static int axp288_adc_probe(struct platform_device *pdev)
info = iio_priv(indio_dev);
info->irq = platform_get_irq(pdev, 0);
if (info->irq < 0) {
dev_err(&pdev->dev, "no irq resource?\n");
if (info->irq < 0)
return info->irq;
}
platform_set_drvdata(pdev, indio_dev);
info->regmap = axp20x->regmap;
/*
......
......@@ -540,11 +540,8 @@ static int iproc_adc_probe(struct platform_device *pdev)
}
adc_priv->irqno = platform_get_irq(pdev, 0);
if (adc_priv->irqno <= 0) {
dev_err(&pdev->dev, "platform_get_irq failed\n");
ret = -ENODEV;
return ret;
}
if (adc_priv->irqno <= 0)
return -ENODEV;
ret = regmap_update_bits(adc_priv->regmap, IPROC_REGCTL2,
IPROC_ADC_AUXIN_SCAN_ENA, 0);
......
......@@ -337,10 +337,8 @@ static int da9150_gpadc_probe(struct platform_device *pdev)
init_completion(&gpadc->complete);
irq = platform_get_irq_byname(pdev, "GPADC");
if (irq < 0) {
dev_err(dev, "Failed to get IRQ: %d\n", irq);
if (irq < 0)
return irq;
}
ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq,
IRQF_ONESHOT, "GPADC", gpadc);
......
......@@ -357,11 +357,8 @@ static int envelope_detector_probe(struct platform_device *pdev)
}
env->comp_irq = platform_get_irq_byname(pdev, "comp");
if (env->comp_irq < 0) {
if (env->comp_irq != -EPROBE_DEFER)
dev_err(dev, "failed to get compare interrupt\n");
if (env->comp_irq < 0)
return env->comp_irq;
}
ret = devm_request_irq(dev, env->comp_irq, envelope_detector_comp_isr,
0, "envelope-detector", env);
......
......@@ -805,10 +805,8 @@ static int exynos_adc_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "no irq resource?\n");
if (irq < 0)
return irq;
}
info->irq = irq;
irq = platform_get_irq(pdev, 1);
......
......@@ -340,7 +340,6 @@ static int mx25_gcq_probe(struct platform_device *pdev)
priv->irq = platform_get_irq(pdev, 0);
if (priv->irq <= 0) {
dev_err(dev, "Failed to get IRQ\n");
ret = priv->irq;
if (!ret)
ret = -ENXIO;
......
......@@ -456,6 +456,11 @@ static irqreturn_t hi8435_trigger_handler(int irq, void *private)
return IRQ_HANDLED;
}
static void hi8435_triggered_event_cleanup(void *data)
{
iio_triggered_event_cleanup(data);
}
static int hi8435_probe(struct spi_device *spi)
{
struct iio_dev *idev;
......@@ -477,7 +482,7 @@ static int hi8435_probe(struct spi_device *spi)
hi8435_writeb(priv, HI8435_CTRL_REG, 0);
} else {
udelay(5);
gpiod_set_value(reset_gpio, 1);
gpiod_set_value_cansleep(reset_gpio, 1);
}
spi_set_drvdata(spi, idev);
......@@ -513,27 +518,13 @@ static int hi8435_probe(struct spi_device *spi)
if (ret)
return ret;
ret = iio_device_register(idev);
if (ret < 0) {
dev_err(&spi->dev, "unable to register device\n");
goto unregister_triggered_event;
}
return 0;
unregister_triggered_event:
iio_triggered_event_cleanup(idev);
ret = devm_add_action_or_reset(&spi->dev,
hi8435_triggered_event_cleanup,
idev);
if (ret)
return ret;
}
static int hi8435_remove(struct spi_device *spi)
{
struct iio_dev *idev = spi_get_drvdata(spi);
iio_device_unregister(idev);
iio_triggered_event_cleanup(idev);
return 0;
return devm_iio_device_register(&spi->dev, idev);
}
static const struct of_device_id hi8435_dt_ids[] = {
......@@ -554,7 +545,6 @@ static struct spi_driver hi8435_driver = {
.of_match_table = of_match_ptr(hi8435_dt_ids),
},
.probe = hi8435_probe,
.remove = hi8435_remove,
.id_table = hi8435_id,
};
module_spi_driver(hi8435_driver);
......
......@@ -492,10 +492,8 @@ static int imx7d_adc_probe(struct platform_device *pdev)
return PTR_ERR(info->regs);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "No irq resource?\n");
if (irq < 0)
return irq;
}
info->clk = devm_clk_get(dev, "adc");
if (IS_ERR(info->clk)) {
......
......@@ -172,10 +172,8 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(&pdev->dev, "failed getting interrupt resource\n");
if (irq <= 0)
return -ENXIO;
}
retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0,
LPC32XXAD_NAME, st);
......
......@@ -225,7 +225,6 @@ static int npcm_adc_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(dev, "failed getting interrupt resource\n");
ret = -EINVAL;
goto err_disable_clk;
}
......
......@@ -244,10 +244,8 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
init_completion(&info->completion);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "no irq resource?\n");
if (irq < 0)
return irq;
}
ret = devm_request_irq(&pdev->dev, irq, rockchip_saradc_isr,
0, dev_name(&pdev->dev), info);
......
......@@ -504,88 +504,85 @@ static void sc27xx_adc_free_hwlock(void *_data)
static int sc27xx_adc_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct sc27xx_adc_data *sc27xx_data;
struct iio_dev *indio_dev;
int ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*sc27xx_data));
indio_dev = devm_iio_device_alloc(dev, sizeof(*sc27xx_data));
if (!indio_dev)
return -ENOMEM;
sc27xx_data = iio_priv(indio_dev);
sc27xx_data->regmap = dev_get_regmap(pdev->dev.parent, NULL);
sc27xx_data->regmap = dev_get_regmap(dev->parent, NULL);
if (!sc27xx_data->regmap) {
dev_err(&pdev->dev, "failed to get ADC regmap\n");
dev_err(dev, "failed to get ADC regmap\n");
return -ENODEV;
}
ret = of_property_read_u32(np, "reg", &sc27xx_data->base);
if (ret) {
dev_err(&pdev->dev, "failed to get ADC base address\n");
dev_err(dev, "failed to get ADC base address\n");
return ret;
}
sc27xx_data->irq = platform_get_irq(pdev, 0);
if (sc27xx_data->irq < 0) {
dev_err(&pdev->dev, "failed to get ADC irq number\n");
if (sc27xx_data->irq < 0)
return sc27xx_data->irq;
}
ret = of_hwspin_lock_get_id(np, 0);
if (ret < 0) {
dev_err(&pdev->dev, "failed to get hwspinlock id\n");
dev_err(dev, "failed to get hwspinlock id\n");
return ret;
}
sc27xx_data->hwlock = hwspin_lock_request_specific(ret);
if (!sc27xx_data->hwlock) {
dev_err(&pdev->dev, "failed to request hwspinlock\n");
dev_err(dev, "failed to request hwspinlock\n");
return -ENXIO;
}
ret = devm_add_action(&pdev->dev, sc27xx_adc_free_hwlock,
ret = devm_add_action_or_reset(dev, sc27xx_adc_free_hwlock,
sc27xx_data->hwlock);
if (ret) {
sc27xx_adc_free_hwlock(sc27xx_data->hwlock);
dev_err(&pdev->dev, "failed to add hwspinlock action\n");
dev_err(dev, "failed to add hwspinlock action\n");
return ret;
}
init_completion(&sc27xx_data->completion);
sc27xx_data->dev = &pdev->dev;
sc27xx_data->dev = dev;
ret = sc27xx_adc_enable(sc27xx_data);
if (ret) {
dev_err(&pdev->dev, "failed to enable ADC module\n");
dev_err(dev, "failed to enable ADC module\n");
return ret;
}
ret = devm_add_action(&pdev->dev, sc27xx_adc_disable, sc27xx_data);
ret = devm_add_action_or_reset(dev, sc27xx_adc_disable, sc27xx_data);
if (ret) {
sc27xx_adc_disable(sc27xx_data);
dev_err(&pdev->dev, "failed to add ADC disable action\n");
dev_err(dev, "failed to add ADC disable action\n");
return ret;
}
ret = devm_request_threaded_irq(&pdev->dev, sc27xx_data->irq, NULL,
ret = devm_request_threaded_irq(dev, sc27xx_data->irq, NULL,
sc27xx_adc_isr, IRQF_ONESHOT,
pdev->name, sc27xx_data);
if (ret) {
dev_err(&pdev->dev, "failed to request ADC irq\n");
dev_err(dev, "failed to request ADC irq\n");
return ret;
}
indio_dev->dev.parent = &pdev->dev;
indio_dev->name = dev_name(&pdev->dev);
indio_dev->dev.parent = dev;
indio_dev->name = dev_name(dev);
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &sc27xx_info;
indio_dev->channels = sc27xx_channels;
indio_dev->num_channels = ARRAY_SIZE(sc27xx_channels);
ret = devm_iio_device_register(&pdev->dev, indio_dev);
ret = devm_iio_device_register(dev, indio_dev);
if (ret)
dev_err(&pdev->dev, "could not register iio (ADC)");
dev_err(dev, "could not register iio (ADC)");
return ret;
}
......
......@@ -301,7 +301,6 @@ static int spear_adc_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(dev, "failed getting interrupt resource\n");
ret = -EINVAL;
goto errout2;
}
......
......@@ -14,9 +14,11 @@
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdesc.h>
#include <linux/irqdomain.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
......@@ -51,6 +53,17 @@
#define STM32_ADC_CORE_SLEEP_DELAY_MS 2000
/* SYSCFG registers */
#define STM32MP1_SYSCFG_PMCSETR 0x04
#define STM32MP1_SYSCFG_PMCCLRR 0x44
/* SYSCFG bit fields */
#define STM32MP1_SYSCFG_ANASWVDD_MASK BIT(9)
/* SYSCFG capability flags */
#define HAS_VBOOSTER BIT(0)
#define HAS_ANASWVDD BIT(1)
/**
* stm32_adc_common_regs - stm32 common registers, compatible dependent data
* @csr: common status register offset
......@@ -74,11 +87,13 @@ struct stm32_adc_priv;
* @regs: common registers for all instances
* @clk_sel: clock selection routine
* @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet)
* @has_syscfg: SYSCFG capability flags
*/
struct stm32_adc_priv_cfg {
const struct stm32_adc_common_regs *regs;
int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *);
u32 max_clk_rate_hz;
unsigned int has_syscfg;
};
/**
......@@ -87,22 +102,32 @@ struct stm32_adc_priv_cfg {
* @domain: irq domain reference
* @aclk: clock reference for the analog circuitry
* @bclk: bus clock common for all ADCs, depends on part used
* @booster: booster supply reference
* @vdd: vdd supply reference
* @vdda: vdda analog supply reference
* @vref: regulator reference
* @vdd_uv: vdd supply voltage (microvolts)
* @vdda_uv: vdda supply voltage (microvolts)
* @cfg: compatible configuration data
* @common: common data for all ADC instances
* @ccr_bak: backup CCR in low power mode
* @syscfg: reference to syscon, system control registers
*/
struct stm32_adc_priv {
int irq[STM32_ADC_MAX_ADCS];
struct irq_domain *domain;
struct clk *aclk;
struct clk *bclk;
struct regulator *booster;
struct regulator *vdd;
struct regulator *vdda;
struct regulator *vref;
int vdd_uv;
int vdda_uv;
const struct stm32_adc_priv_cfg *cfg;
struct stm32_adc_common common;
u32 ccr_bak;
struct regmap *syscfg;
};
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,
*/
if (i && priv->irq[i] == -ENXIO)
continue;
dev_err(&pdev->dev, "failed to get irq\n");
return priv->irq[i];
}
......@@ -390,6 +414,82 @@ static void stm32_adc_irq_remove(struct platform_device *pdev,
}
}
static int stm32_adc_core_switches_supply_en(struct stm32_adc_priv *priv,
struct device *dev)
{
int ret;
/*
* On STM32H7 and STM32MP1, the ADC inputs are multiplexed with analog
* switches (via PCSEL) which have reduced performances when their
* supply is below 2.7V (vdda by default):
* - Voltage booster can be used, to get full ADC performances
* (increases power consumption).
* - Vdd can be used to supply them, if above 2.7V (STM32MP1 only).
*
* Recommended settings for ANASWVDD and EN_BOOSTER:
* - vdda < 2.7V but vdd > 2.7V: ANASWVDD = 1, EN_BOOSTER = 0 (stm32mp1)
* - vdda < 2.7V and vdd < 2.7V: ANASWVDD = 0, EN_BOOSTER = 1
* - vdda >= 2.7V: ANASWVDD = 0, EN_BOOSTER = 0 (default)
*/
if (priv->vdda_uv < 2700000) {
if (priv->syscfg && priv->vdd_uv > 2700000) {
ret = regulator_enable(priv->vdd);
if (ret < 0) {
dev_err(dev, "vdd enable failed %d\n", ret);
return ret;
}
ret = regmap_write(priv->syscfg,
STM32MP1_SYSCFG_PMCSETR,
STM32MP1_SYSCFG_ANASWVDD_MASK);
if (ret < 0) {
regulator_disable(priv->vdd);
dev_err(dev, "vdd select failed, %d\n", ret);
return ret;
}
dev_dbg(dev, "analog switches supplied by vdd\n");
return 0;
}
if (priv->booster) {
/*
* This is optional, as this is a trade-off between
* analog performance and power consumption.
*/
ret = regulator_enable(priv->booster);
if (ret < 0) {
dev_err(dev, "booster enable failed %d\n", ret);
return ret;
}
dev_dbg(dev, "analog switches supplied by booster\n");
return 0;
}
}
/* Fallback using vdda (default), nothing to do */
dev_dbg(dev, "analog switches supplied by vdda (%d uV)\n",
priv->vdda_uv);
return 0;
}
static void stm32_adc_core_switches_supply_dis(struct stm32_adc_priv *priv)
{
if (priv->vdda_uv < 2700000) {
if (priv->syscfg && priv->vdd_uv > 2700000) {
regmap_write(priv->syscfg, STM32MP1_SYSCFG_PMCCLRR,
STM32MP1_SYSCFG_ANASWVDD_MASK);
regulator_disable(priv->vdd);
return;
}
if (priv->booster)
regulator_disable(priv->booster);
}
}
static int stm32_adc_core_hw_start(struct device *dev)
{
struct stm32_adc_common *common = dev_get_drvdata(dev);
......@@ -402,10 +502,21 @@ static int stm32_adc_core_hw_start(struct device *dev)
return ret;
}
ret = regulator_get_voltage(priv->vdda);
if (ret < 0) {
dev_err(dev, "vdda get voltage failed, %d\n", ret);
goto err_vdda_disable;
}
priv->vdda_uv = ret;
ret = stm32_adc_core_switches_supply_en(priv, dev);
if (ret < 0)
goto err_vdda_disable;
ret = regulator_enable(priv->vref);
if (ret < 0) {
dev_err(dev, "vref enable failed\n");
goto err_vdda_disable;
goto err_switches_dis;
}
if (priv->bclk) {
......@@ -433,6 +544,8 @@ static int stm32_adc_core_hw_start(struct device *dev)
clk_disable_unprepare(priv->bclk);
err_regulator_disable:
regulator_disable(priv->vref);
err_switches_dis:
stm32_adc_core_switches_supply_dis(priv);
err_vdda_disable:
regulator_disable(priv->vdda);
......@@ -451,9 +564,80 @@ static void stm32_adc_core_hw_stop(struct device *dev)
if (priv->bclk)
clk_disable_unprepare(priv->bclk);
regulator_disable(priv->vref);
stm32_adc_core_switches_supply_dis(priv);
regulator_disable(priv->vdda);
}
static int stm32_adc_core_switches_probe(struct device *dev,
struct stm32_adc_priv *priv)
{
struct device_node *np = dev->of_node;
int ret;
/* Analog switches supply can be controlled by syscfg (optional) */
priv->syscfg = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
if (IS_ERR(priv->syscfg)) {
ret = PTR_ERR(priv->syscfg);
if (ret != -ENODEV) {
if (ret != -EPROBE_DEFER)
dev_err(dev, "Can't probe syscfg: %d\n", ret);
return ret;
}
priv->syscfg = NULL;
}
/* Booster can be used to supply analog switches (optional) */
if (priv->cfg->has_syscfg & HAS_VBOOSTER &&
of_property_read_bool(np, "booster-supply")) {
priv->booster = devm_regulator_get_optional(dev, "booster");
if (IS_ERR(priv->booster)) {
ret = PTR_ERR(priv->booster);
if (ret != -ENODEV) {
if (ret != -EPROBE_DEFER)
dev_err(dev, "can't get booster %d\n",
ret);
return ret;
}
priv->booster = NULL;
}
}
/* Vdd can be used to supply analog switches (optional) */
if (priv->cfg->has_syscfg & HAS_ANASWVDD &&
of_property_read_bool(np, "vdd-supply")) {
priv->vdd = devm_regulator_get_optional(dev, "vdd");
if (IS_ERR(priv->vdd)) {
ret = PTR_ERR(priv->vdd);
if (ret != -ENODEV) {
if (ret != -EPROBE_DEFER)
dev_err(dev, "can't get vdd %d\n", ret);
return ret;
}
priv->vdd = NULL;
}
}
if (priv->vdd) {
ret = regulator_enable(priv->vdd);
if (ret < 0) {
dev_err(dev, "vdd enable failed %d\n", ret);
return ret;
}
ret = regulator_get_voltage(priv->vdd);
if (ret < 0) {
dev_err(dev, "vdd get voltage failed %d\n", ret);
regulator_disable(priv->vdd);
return ret;
}
priv->vdd_uv = ret;
regulator_disable(priv->vdd);
}
return 0;
}
static int stm32_adc_probe(struct platform_device *pdev)
{
struct stm32_adc_priv *priv;
......@@ -514,6 +698,10 @@ static int stm32_adc_probe(struct platform_device *pdev)
priv->bclk = NULL;
}
ret = stm32_adc_core_switches_probe(dev, priv);
if (ret)
return ret;
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
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 = {
.regs = &stm32h7_adc_common_regs,
.clk_sel = stm32h7_adc_clk_sel,
.max_clk_rate_hz = 36000000,
.has_syscfg = HAS_VBOOSTER,
};
static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = {
.regs = &stm32h7_adc_common_regs,
.clk_sel = stm32h7_adc_clk_sel,
.max_clk_rate_hz = 40000000,
.has_syscfg = HAS_VBOOSTER | HAS_ANASWVDD,
};
static const struct of_device_id stm32_adc_of_match[] = {
......
......@@ -1919,10 +1919,8 @@ static int stm32_adc_probe(struct platform_device *pdev)
}
adc->irq = platform_get_irq(pdev, 0);
if (adc->irq < 0) {
dev_err(&pdev->dev, "failed to get irq\n");
if (adc->irq < 0)
return adc->irq;
}
ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr,
0, pdev->name, adc);
......
......@@ -1601,11 +1601,8 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
* So IRQ associated to filter instance 0 is dedicated to the Filter 0.
*/
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
if (irq != -EPROBE_DEFER)
dev_err(dev, "Failed to get IRQ: %d\n", irq);
if (irq < 0)
return irq;
}
ret = devm_request_irq(dev, irq, stm32_dfsdm_irq,
0, pdev->name, adc);
......
......@@ -460,10 +460,8 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name,
atomic_set(atomic, 1);
ret = platform_get_irq_byname(pdev, name);
if (ret < 0) {
dev_err(&pdev->dev, "no %s interrupt registered\n", name);
if (ret < 0)
return ret;
}
ret = regmap_irq_get_virq(mfd_dev->regmap_irqc, ret);
if (ret < 0) {
......
......@@ -905,10 +905,8 @@ static int twl6030_gpadc_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "failed to get irq\n");
if (irq < 0)
return irq;
}
ret = devm_request_threaded_irq(dev, irq, NULL,
twl6030_gpadc_irq_handler,
......
......@@ -821,10 +821,8 @@ static int vf610_adc_probe(struct platform_device *pdev)
return PTR_ERR(info->regs);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "no irq resource?\n");
if (irq < 0)
return irq;
}
ret = devm_request_irq(info->dev, irq,
vf610_adc_isr, 0,
......
......@@ -63,10 +63,35 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev,
/* Save values */
for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
st->core.calib[i] =
st->core.calib[i].offset =
st->core.resp->sensor_offset.offset[i];
ret = IIO_VAL_INT;
*val = st->core.calib[idx];
*val = st->core.calib[idx].offset;
break;
case IIO_CHAN_INFO_CALIBSCALE:
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE;
st->core.param.sensor_offset.flags = 0;
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
if (ret == -EPROTO) {
/* Reading calibscale is not supported on older EC. */
*val = 1;
*val2 = 0;
ret = IIO_VAL_INT_PLUS_MICRO;
break;
} else if (ret) {
break;
}
/* Save values */
for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
st->core.calib[i].scale =
st->core.resp->sensor_scale.scale[i];
*val = st->core.calib[idx].scale >> 15;
*val2 = ((st->core.calib[idx].scale & 0x7FFF) * 1000000LL) /
MOTION_SENSE_DEFAULT_SCALE;
ret = IIO_VAL_INT_PLUS_MICRO;
break;
case IIO_CHAN_INFO_SCALE:
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
......@@ -134,7 +159,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
st->core.calib[idx] = val;
st->core.calib[idx].offset = val;
/* Send to EC for each axis, even if not complete */
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
......@@ -142,10 +167,25 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
MOTION_SENSE_SET_OFFSET;
for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
st->core.param.sensor_offset.offset[i] =
st->core.calib[i];
st->core.calib[i].offset;
st->core.param.sensor_offset.temp =
EC_MOTION_SENSE_INVALID_CALIB_TEMP;
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
break;
case IIO_CHAN_INFO_CALIBSCALE:
st->core.calib[idx].scale = val;
/* Send to EC for each axis, even if not complete */
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE;
st->core.param.sensor_offset.flags =
MOTION_SENSE_SET_OFFSET;
for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
st->core.param.sensor_scale.scale[i] =
st->core.calib[i].scale;
st->core.param.sensor_scale.temp =
EC_MOTION_SENSE_INVALID_CALIB_TEMP;
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
break;
case IIO_CHAN_INFO_SCALE:
......@@ -175,6 +215,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
static const struct iio_info ec_sensors_info = {
.read_raw = &cros_ec_sensors_read,
.write_raw = &cros_ec_sensors_write,
.read_avail = &cros_ec_sensors_core_read_avail,
};
static int cros_ec_sensors_probe(struct platform_device *pdev)
......@@ -206,11 +247,14 @@ static int cros_ec_sensors_probe(struct platform_device *pdev)
/* Common part */
channel->info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_CALIBBIAS);
BIT(IIO_CHAN_INFO_CALIBBIAS) |
BIT(IIO_CHAN_INFO_CALIBSCALE);
channel->info_mask_shared_by_all =
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_FREQUENCY) |
BIT(IIO_CHAN_INFO_SAMP_FREQ);
channel->info_mask_shared_by_all_available =
BIT(IIO_CHAN_INFO_SAMP_FREQ);
channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
channel->scan_index = i;
......
......@@ -25,6 +25,62 @@ static char *cros_ec_loc[] = {
[MOTIONSENSE_LOC_MAX] = "unknown",
};
static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev,
u16 cmd_offset, u16 cmd, u32 *mask)
{
int ret;
struct {
struct cros_ec_command msg;
union {
struct ec_params_get_cmd_versions params;
struct ec_response_get_cmd_versions resp;
};
} __packed buf = {
.msg = {
.command = EC_CMD_GET_CMD_VERSIONS + cmd_offset,
.insize = sizeof(struct ec_response_get_cmd_versions),
.outsize = sizeof(struct ec_params_get_cmd_versions)
},
.params = {.cmd = cmd}
};
ret = cros_ec_cmd_xfer_status(ec_dev, &buf.msg);
if (ret >= 0)
*mask = buf.resp.version_mask;
return ret;
}
static void get_default_min_max_freq(enum motionsensor_type type,
u32 *min_freq,
u32 *max_freq)
{
switch (type) {
case MOTIONSENSE_TYPE_ACCEL:
case MOTIONSENSE_TYPE_GYRO:
*min_freq = 12500;
*max_freq = 100000;
break;
case MOTIONSENSE_TYPE_MAG:
*min_freq = 5000;
*max_freq = 25000;
break;
case MOTIONSENSE_TYPE_PROX:
case MOTIONSENSE_TYPE_LIGHT:
*min_freq = 100;
*max_freq = 50000;
break;
case MOTIONSENSE_TYPE_BARO:
*min_freq = 250;
*max_freq = 20000;
break;
case MOTIONSENSE_TYPE_ACTIVITY:
default:
*min_freq = 0;
*max_freq = 0;
break;
}
}
int cros_ec_sensors_core_init(struct platform_device *pdev,
struct iio_dev *indio_dev,
bool physical_device)
......@@ -33,6 +89,8 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
struct cros_ec_sensors_core_state *state = iio_priv(indio_dev);
struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent);
struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
u32 ver_mask;
int ret;
platform_set_drvdata(pdev, indio_dev);
......@@ -47,8 +105,15 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
mutex_init(&state->cmd_lock);
ret = cros_ec_get_host_cmd_version_mask(state->ec,
ec->cmd_offset,
EC_CMD_MOTION_SENSE_CMD,
&ver_mask);
if (ret < 0)
return ret;
/* Set up the host command structure. */
state->msg->version = 2;
state->msg->version = fls(ver_mask) - 1;
state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
state->msg->outsize = sizeof(struct ec_params_motion_sense);
......@@ -60,12 +125,29 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
state->param.cmd = MOTIONSENSE_CMD_INFO;
state->param.info.sensor_num = sensor_platform->sensor_num;
if (cros_ec_motion_send_host_cmd(state, 0)) {
ret = cros_ec_motion_send_host_cmd(state, 0);
if (ret) {
dev_warn(dev, "Can not access sensor info\n");
return -EIO;
return ret;
}
state->type = state->resp->info.type;
state->loc = state->resp->info.location;
/* Set sign vector, only used for backward compatibility. */
memset(state->sign, 1, CROS_EC_SENSOR_MAX_AXIS);
/* 0 is a correct value used to stop the device */
state->frequencies[0] = 0;
if (state->msg->version < 3) {
get_default_min_max_freq(state->resp->info.type,
&state->frequencies[1],
&state->frequencies[2]);
} else {
state->frequencies[1] =
state->resp->info_3.min_frequency;
state->frequencies[2] =
state->resp->info_3.max_frequency;
}
}
return 0;
......@@ -86,7 +168,7 @@ int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state,
ret = cros_ec_cmd_xfer_status(state->ec, state->msg);
if (ret < 0)
return -EIO;
return ret;
if (ret &&
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,
} else {
/* Save values */
for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
st->calib[i] = st->resp->perform_calib.offset[i];
st->calib[i].offset = st->resp->perform_calib.offset[i];
}
mutex_unlock(&st->cmd_lock);
......@@ -268,6 +350,7 @@ static int cros_ec_sensors_read_data_unsafe(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
*data *= st->sign[i];
data++;
}
......@@ -396,7 +479,7 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
int ret = IIO_VAL_INT;
int ret;
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
......@@ -404,22 +487,27 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
st->param.ec_rate.data =
EC_MOTION_SENSE_NO_VALUE;
if (cros_ec_motion_send_host_cmd(st, 0))
ret = -EIO;
else
ret = cros_ec_motion_send_host_cmd(st, 0);
if (ret)
break;
*val = st->resp->ec_rate.ret;
ret = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_FREQUENCY:
st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
st->param.sensor_odr.data =
EC_MOTION_SENSE_NO_VALUE;
if (cros_ec_motion_send_host_cmd(st, 0))
ret = -EIO;
else
ret = cros_ec_motion_send_host_cmd(st, 0);
if (ret)
break;
*val = st->resp->sensor_odr.ret;
ret = IIO_VAL_INT;
break;
default:
ret = -EINVAL;
break;
}
......@@ -427,11 +515,32 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
}
EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read);
int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
const int **vals,
int *type,
int *length,
long mask)
{
struct cros_ec_sensors_core_state *state = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
*length = ARRAY_SIZE(state->frequencies);
*vals = (const int *)&state->frequencies;
*type = IIO_VAL_INT;
return IIO_AVAIL_LIST;
}
return -EINVAL;
}
EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read_avail);
int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
int ret = 0;
int ret;
switch (mask) {
case IIO_CHAN_INFO_FREQUENCY:
......@@ -441,16 +550,15 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
/* Always roundup, so caller gets at least what it asks for. */
st->param.sensor_odr.roundup = 1;
if (cros_ec_motion_send_host_cmd(st, 0))
ret = -EIO;
ret = cros_ec_motion_send_host_cmd(st, 0);
break;
case IIO_CHAN_INFO_SAMP_FREQ:
st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
st->param.ec_rate.data = val;
if (cros_ec_motion_send_host_cmd(st, 0))
ret = -EIO;
else
ret = cros_ec_motion_send_host_cmd(st, 0);
if (ret)
break;
st->curr_sampl_freq = val;
break;
default:
......
......@@ -17,15 +17,16 @@
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/irqreturn.h>
#include <linux/regmap.h>
#include <linux/iio/common/st_sensors.h>
static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
{
int i;
struct st_sensor_data *sdata = iio_priv(indio_dev);
unsigned int num_data_channels = sdata->num_data_channels;
int i;
for_each_set_bit(i, indio_dev->active_scan_mask, num_data_channels) {
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)
channel->scan_type.storagebits >> 3;
buf = PTR_ALIGN(buf, storage_bytes);
if (sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
channel->address,
bytes_to_read, buf,
sdata->multiread_bit) <
bytes_to_read)
if (regmap_bulk_read(sdata->regmap, channel->address,
buf, bytes_to_read) < 0)
return -EIO;
/* Advance the buffer pointer */
......
......@@ -15,6 +15,7 @@
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <asm/unaligned.h>
#include <linux/iio/common/st_sensors.h>
......@@ -28,19 +29,10 @@ static inline u32 st_sensors_get_unaligned_le24(const u8 *p)
int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
u8 reg_addr, u8 mask, u8 data)
{
int err;
u8 new_data;
struct st_sensor_data *sdata = iio_priv(indio_dev);
err = sdata->tf->read_byte(&sdata->tb, sdata->dev, reg_addr, &new_data);
if (err < 0)
goto st_sensors_write_data_with_mask_error;
new_data = ((new_data & (~mask)) | ((data << __ffs(mask)) & mask));
err = sdata->tf->write_byte(&sdata->tb, sdata->dev, reg_addr, new_data);
st_sensors_write_data_with_mask_error:
return err;
return regmap_update_bits(sdata->regmap,
reg_addr, mask, data << __ffs(mask));
}
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,
unsigned *readval)
{
struct st_sensor_data *sdata = iio_priv(indio_dev);
u8 readdata;
int err;
if (!readval)
return sdata->tf->write_byte(&sdata->tb, sdata->dev,
(u8)reg, (u8)writeval);
return regmap_write(sdata->regmap, reg, writeval);
err = sdata->tf->read_byte(&sdata->tb, sdata->dev, (u8)reg, &readdata);
err = regmap_read(sdata->regmap, reg, readval);
if (err < 0)
return err;
*readval = (unsigned)readdata;
return 0;
}
EXPORT_SYMBOL(st_sensors_debugfs_reg_access);
......@@ -554,13 +542,12 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits +
ch->scan_type.shift, 8);
outdata = kmalloc(byte_for_channel, GFP_KERNEL);
outdata = kmalloc(byte_for_channel, GFP_DMA | GFP_KERNEL);
if (!outdata)
return -ENOMEM;
err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
ch->address, byte_for_channel,
outdata, sdata->multiread_bit);
err = regmap_bulk_read(sdata->regmap, ch->address,
outdata, byte_for_channel);
if (err < 0)
goto st_sensors_free_memory;
......@@ -608,69 +595,55 @@ int st_sensors_read_info_raw(struct iio_dev *indio_dev,
}
EXPORT_SYMBOL(st_sensors_read_info_raw);
static int st_sensors_init_interface_mode(struct iio_dev *indio_dev,
const struct st_sensor_settings *sensor_settings)
/*
* st_sensors_get_settings_index() - get index of the sensor settings for a
* specific device from list of settings
* @name: device name buffer reference.
* @list: sensor settings list.
* @list_length: length of sensor settings list.
*
* Return: non negative number on success (valid index),
* negative error code otherwise.
*/
int st_sensors_get_settings_index(const char *name,
const struct st_sensor_settings *list,
const int list_length)
{
struct st_sensor_data *sdata = iio_priv(indio_dev);
struct device_node *np = sdata->dev->of_node;
struct st_sensors_platform_data *pdata;
int i, n;
pdata = (struct st_sensors_platform_data *)sdata->dev->platform_data;
if (((np && of_property_read_bool(np, "spi-3wire")) ||
(pdata && pdata->spi_3wire)) && sensor_settings->sim.addr) {
int err;
err = sdata->tf->write_byte(&sdata->tb, sdata->dev,
sensor_settings->sim.addr,
sensor_settings->sim.value);
if (err < 0) {
dev_err(&indio_dev->dev,
"failed to init interface mode\n");
return err;
for (i = 0; i < list_length; i++) {
for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) {
if (strcmp(name, list[i].sensors_supported[n]) == 0)
return i;
}
}
return 0;
return -ENODEV;
}
EXPORT_SYMBOL(st_sensors_get_settings_index);
int st_sensors_check_device_support(struct iio_dev *indio_dev,
int num_sensors_list,
const struct st_sensor_settings *sensor_settings)
/*
* st_sensors_verify_id() - verify sensor ID (WhoAmI) is matching with the
* expected value
* @indio_dev: IIO device reference.
*
* Return: 0 on success (valid sensor ID), else a negative error code.
*/
int st_sensors_verify_id(struct iio_dev *indio_dev)
{
int i, n, err = 0;
u8 wai;
struct st_sensor_data *sdata = iio_priv(indio_dev);
int wai, err;
for (i = 0; i < num_sensors_list; i++) {
for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) {
if (strcmp(indio_dev->name,
sensor_settings[i].sensors_supported[n]) == 0) {
break;
}
}
if (n < ST_SENSORS_MAX_4WAI)
break;
}
if (i == num_sensors_list) {
dev_err(&indio_dev->dev, "device name %s not recognized.\n",
indio_dev->name);
return -ENODEV;
}
err = st_sensors_init_interface_mode(indio_dev, &sensor_settings[i]);
if (err < 0)
return err;
if (sensor_settings[i].wai_addr) {
err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
sensor_settings[i].wai_addr, &wai);
if (sdata->sensor_settings->wai_addr) {
err = regmap_read(sdata->regmap,
sdata->sensor_settings->wai_addr, &wai);
if (err < 0) {
dev_err(&indio_dev->dev,
"failed to read Who-Am-I register.\n");
return err;
}
if (sensor_settings[i].wai != wai) {
if (sdata->sensor_settings->wai != wai) {
dev_err(&indio_dev->dev,
"%s: WhoAmI mismatch (0x%x).\n",
indio_dev->name, wai);
......@@ -678,12 +651,9 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev,
}
}
sdata->sensor_settings =
(struct st_sensor_settings *)&sensor_settings[i];
return i;
return 0;
}
EXPORT_SYMBOL(st_sensors_check_device_support);
EXPORT_SYMBOL(st_sensors_verify_id);
ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
struct device_attribute *attr, char *buf)
......
......@@ -13,68 +13,58 @@
#include <linux/iio/iio.h>
#include <linux/of_device.h>
#include <linux/acpi.h>
#include <linux/regmap.h>
#include <linux/iio/common/st_sensors_i2c.h>
#define ST_SENSORS_I2C_MULTIREAD 0x80
static unsigned int st_sensors_i2c_get_irq(struct iio_dev *indio_dev)
{
struct st_sensor_data *sdata = iio_priv(indio_dev);
return to_i2c_client(sdata->dev)->irq;
}
static int st_sensors_i2c_read_byte(struct st_sensor_transfer_buffer *tb,
struct device *dev, u8 reg_addr, u8 *res_byte)
{
int err;
err = i2c_smbus_read_byte_data(to_i2c_client(dev), reg_addr);
if (err < 0)
goto st_accel_i2c_read_byte_error;
*res_byte = err & 0xff;
st_accel_i2c_read_byte_error:
return err < 0 ? err : 0;
}
static int st_sensors_i2c_read_multiple_byte(
struct st_sensor_transfer_buffer *tb, struct device *dev,
u8 reg_addr, int len, u8 *data, bool multiread_bit)
{
if (multiread_bit)
reg_addr |= ST_SENSORS_I2C_MULTIREAD;
return i2c_smbus_read_i2c_block_data_or_emulated(to_i2c_client(dev),
reg_addr, len, data);
}
static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb,
struct device *dev, u8 reg_addr, u8 data)
{
return i2c_smbus_write_byte_data(to_i2c_client(dev), reg_addr, data);
}
static const struct regmap_config st_sensors_i2c_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static const struct st_sensor_transfer_function st_sensors_tf_i2c = {
.read_byte = st_sensors_i2c_read_byte,
.write_byte = st_sensors_i2c_write_byte,
.read_multiple_byte = st_sensors_i2c_read_multiple_byte,
static const struct regmap_config st_sensors_i2c_regmap_multiread_bit_config = {
.reg_bits = 8,
.val_bits = 8,
.read_flag_mask = ST_SENSORS_I2C_MULTIREAD,
};
void st_sensors_i2c_configure(struct iio_dev *indio_dev,
struct i2c_client *client, struct st_sensor_data *sdata)
/*
* st_sensors_i2c_configure() - configure I2C interface
* @indio_dev: IIO device reference.
* @client: i2c client reference.
*
* Return: 0 on success, else a negative error code.
*/
int st_sensors_i2c_configure(struct iio_dev *indio_dev,
struct i2c_client *client)
{
struct st_sensor_data *sdata = iio_priv(indio_dev);
const struct regmap_config *config;
if (sdata->sensor_settings->multi_read_bit)
config = &st_sensors_i2c_regmap_multiread_bit_config;
else
config = &st_sensors_i2c_regmap_config;
sdata->regmap = devm_regmap_init_i2c(client, config);
if (IS_ERR(sdata->regmap)) {
dev_err(&client->dev, "Failed to register i2c regmap (%d)\n",
(int)PTR_ERR(sdata->regmap));
return PTR_ERR(sdata->regmap);
}
i2c_set_clientdata(client, indio_dev);
indio_dev->dev.parent = &client->dev;
indio_dev->name = client->name;
sdata->dev = &client->dev;
sdata->tf = &st_sensors_tf_i2c;
sdata->get_irq_data_ready = st_sensors_i2c_get_irq;
sdata->irq = client->irq;
return 0;
}
EXPORT_SYMBOL(st_sensors_i2c_configure);
......
......@@ -11,108 +11,108 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/iio/iio.h>
#include <linux/regmap.h>
#include <linux/iio/common/st_sensors_spi.h>
#include "st_sensors_core.h"
#define ST_SENSORS_SPI_MULTIREAD 0xc0
#define ST_SENSORS_SPI_READ 0x80
static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev)
{
struct st_sensor_data *sdata = iio_priv(indio_dev);
static const struct regmap_config st_sensors_spi_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
return to_spi_device(sdata->dev)->irq;
}
static const struct regmap_config st_sensors_spi_regmap_multiread_bit_config = {
.reg_bits = 8,
.val_bits = 8,
.read_flag_mask = ST_SENSORS_SPI_MULTIREAD,
};
static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb,
struct device *dev, u8 reg_addr, int len, u8 *data, bool multiread_bit)
/*
* st_sensors_is_spi_3_wire() - check if SPI 3-wire mode has been selected
* @spi: spi device reference.
*
* Return: true if SPI 3-wire mode is selected, false otherwise.
*/
static bool st_sensors_is_spi_3_wire(struct spi_device *spi)
{
int err;
struct device_node *np = spi->dev.of_node;
struct st_sensors_platform_data *pdata;
struct spi_transfer xfers[] = {
{
.tx_buf = tb->tx_buf,
.bits_per_word = 8,
.len = 1,
},
{
.rx_buf = tb->rx_buf,
.bits_per_word = 8,
.len = len,
pdata = (struct st_sensors_platform_data *)spi->dev.platform_data;
if ((np && of_property_read_bool(np, "spi-3wire")) ||
(pdata && pdata->spi_3wire)) {
return true;
}
};
mutex_lock(&tb->buf_lock);
if ((multiread_bit) && (len > 1))
tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_MULTIREAD;
else
tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_READ;
err = spi_sync_transfer(to_spi_device(dev), xfers, ARRAY_SIZE(xfers));
if (err)
goto acc_spi_read_error;
memcpy(data, tb->rx_buf, len);
mutex_unlock(&tb->buf_lock);
return len;
acc_spi_read_error:
mutex_unlock(&tb->buf_lock);
return err;
return false;
}
static int st_sensors_spi_read_byte(struct st_sensor_transfer_buffer *tb,
struct device *dev, u8 reg_addr, u8 *res_byte)
/*
* st_sensors_configure_spi_3_wire() - configure SPI 3-wire if needed
* @spi: spi device reference.
* @settings: sensor specific settings reference.
*
* Return: 0 on success, else a negative error code.
*/
static int st_sensors_configure_spi_3_wire(struct spi_device *spi,
struct st_sensor_settings *settings)
{
return st_sensors_spi_read(tb, dev, reg_addr, 1, res_byte, false);
}
if (settings->sim.addr) {
u8 buffer[] = {
settings->sim.addr,
settings->sim.value
};
static int st_sensors_spi_read_multiple_byte(
struct st_sensor_transfer_buffer *tb, struct device *dev,
u8 reg_addr, int len, u8 *data, bool multiread_bit)
{
return st_sensors_spi_read(tb, dev, reg_addr, len, data, multiread_bit);
return spi_write(spi, buffer, 2);
}
return 0;
}
static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb,
struct device *dev, u8 reg_addr, u8 data)
/*
* st_sensors_spi_configure() - configure SPI interface
* @indio_dev: IIO device reference.
* @spi: spi device reference.
*
* Return: 0 on success, else a negative error code.
*/
int st_sensors_spi_configure(struct iio_dev *indio_dev,
struct spi_device *spi)
{
struct st_sensor_data *sdata = iio_priv(indio_dev);
const struct regmap_config *config;
int err;
struct spi_transfer xfers = {
.tx_buf = tb->tx_buf,
.bits_per_word = 8,
.len = 2,
};
mutex_lock(&tb->buf_lock);
tb->tx_buf[0] = reg_addr;
tb->tx_buf[1] = data;
err = spi_sync_transfer(to_spi_device(dev), &xfers, 1);
mutex_unlock(&tb->buf_lock);
if (st_sensors_is_spi_3_wire(spi)) {
err = st_sensors_configure_spi_3_wire(spi,
sdata->sensor_settings);
if (err < 0)
return err;
}
}
static const struct st_sensor_transfer_function st_sensors_tf_spi = {
.read_byte = st_sensors_spi_read_byte,
.write_byte = st_sensors_spi_write_byte,
.read_multiple_byte = st_sensors_spi_read_multiple_byte,
};
if (sdata->sensor_settings->multi_read_bit)
config = &st_sensors_spi_regmap_multiread_bit_config;
else
config = &st_sensors_spi_regmap_config;
sdata->regmap = devm_regmap_init_spi(spi, config);
if (IS_ERR(sdata->regmap)) {
dev_err(&spi->dev, "Failed to register spi regmap (%d)\n",
(int)PTR_ERR(sdata->regmap));
return PTR_ERR(sdata->regmap);
}
void st_sensors_spi_configure(struct iio_dev *indio_dev,
struct spi_device *spi, struct st_sensor_data *sdata)
{
spi_set_drvdata(spi, indio_dev);
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi->modalias;
sdata->dev = &spi->dev;
sdata->tf = &st_sensors_tf_spi;
sdata->get_irq_data_ready = st_sensors_spi_get_irq;
sdata->irq = spi->irq;
return 0;
}
EXPORT_SYMBOL(st_sensors_spi_configure);
......
......@@ -13,6 +13,7 @@
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
#include <linux/interrupt.h>
#include <linux/regmap.h>
#include <linux/iio/common/st_sensors.h>
#include "st_sensors_core.h"
......@@ -26,8 +27,7 @@
static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
struct st_sensor_data *sdata)
{
u8 status;
int ret;
int ret, status;
/* How would I know if I can't check it? */
if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr)
......@@ -37,7 +37,7 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
if (!indio_dev->active_scan_mask)
return 0;
ret = sdata->tf->read_byte(&sdata->tb, sdata->dev,
ret = regmap_read(sdata->regmap,
sdata->sensor_settings->drdy_irq.stat_drdy.addr,
&status);
if (ret < 0) {
......@@ -121,9 +121,9 @@ static irqreturn_t st_sensors_irq_thread(int irq, void *p)
int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
const struct iio_trigger_ops *trigger_ops)
{
int err, irq;
struct st_sensor_data *sdata = iio_priv(indio_dev);
unsigned long irq_trig;
int err;
sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name);
if (sdata->trig == NULL) {
......@@ -135,8 +135,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
sdata->trig->ops = trigger_ops;
sdata->trig->dev.parent = sdata->dev;
irq = sdata->get_irq_data_ready(indio_dev);
irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
irq_trig = irqd_get_trigger_type(irq_get_irq_data(sdata->irq));
/*
* If the IRQ is triggered on falling edge, we need to mark the
* interrupt as active low, if the hardware supports this.
......@@ -206,7 +205,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
sdata->sensor_settings->drdy_irq.stat_drdy.addr)
irq_trig |= IRQF_SHARED;
err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev),
err = request_threaded_irq(sdata->irq,
st_sensors_irq_handler,
st_sensors_irq_thread,
irq_trig,
......@@ -227,7 +226,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
return 0;
iio_trigger_register_error:
free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig);
free_irq(sdata->irq, sdata->trig);
iio_trigger_free:
iio_trigger_free(sdata->trig);
return err;
......@@ -239,7 +238,7 @@ void st_sensors_deallocate_trigger(struct iio_dev *indio_dev)
struct st_sensor_data *sdata = iio_priv(indio_dev);
iio_trigger_unregister(sdata->trig);
free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig);
free_irq(sdata->irq, sdata->trig);
iio_trigger_free(sdata->trig);
}
EXPORT_SYMBOL(st_sensors_deallocate_trigger);
......
......@@ -32,6 +32,7 @@ static const struct st_sensors_platform_data gyro_pdata = {
.drdy_int_pin = 2,
};
const struct st_sensor_settings *st_gyro_get_settings(const char *name);
int st_gyro_common_probe(struct iio_dev *indio_dev);
void st_gyro_common_remove(struct iio_dev *indio_dev);
......
......@@ -29,61 +29,51 @@ int st_gyro_trig_set_state(struct iio_trigger *trig, bool state)
return st_sensors_set_dataready_irq(indio_dev, state);
}
static int st_gyro_buffer_preenable(struct iio_dev *indio_dev)
{
return st_sensors_set_enable(indio_dev, true);
}
static int st_gyro_buffer_postenable(struct iio_dev *indio_dev)
{
int err;
struct st_sensor_data *gdata = iio_priv(indio_dev);
gdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (gdata->buffer_data == NULL) {
err = -ENOMEM;
goto allocate_memory_error;
}
err = iio_triggered_buffer_postenable(indio_dev);
if (err < 0)
return err;
err = st_sensors_set_axis_enable(indio_dev,
(u8)indio_dev->active_scan_mask[0]);
if (err < 0)
goto st_gyro_buffer_postenable_error;
goto st_gyro_buffer_predisable;
err = iio_triggered_buffer_postenable(indio_dev);
err = st_sensors_set_enable(indio_dev, true);
if (err < 0)
goto st_gyro_buffer_postenable_error;
goto st_gyro_buffer_enable_all_axis;
return err;
return 0;
st_gyro_buffer_postenable_error:
kfree(gdata->buffer_data);
allocate_memory_error:
st_gyro_buffer_enable_all_axis:
st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
st_gyro_buffer_predisable:
iio_triggered_buffer_predisable(indio_dev);
return err;
}
static int st_gyro_buffer_predisable(struct iio_dev *indio_dev)
{
int err;
struct st_sensor_data *gdata = iio_priv(indio_dev);
int err, err2;
err = iio_triggered_buffer_predisable(indio_dev);
err = st_sensors_set_enable(indio_dev, false);
if (err < 0)
goto st_gyro_buffer_predisable_error;
goto st_gyro_buffer_predisable;
err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
if (err < 0)
goto st_gyro_buffer_predisable_error;
err = st_sensors_set_enable(indio_dev, false);
st_gyro_buffer_predisable:
err2 = iio_triggered_buffer_predisable(indio_dev);
if (!err)
err = err2;
st_gyro_buffer_predisable_error:
kfree(gdata->buffer_data);
return err;
}
static const struct iio_buffer_setup_ops st_gyro_buffer_setup_ops = {
.preenable = &st_gyro_buffer_preenable,
.postenable = &st_gyro_buffer_postenable,
.predisable = &st_gyro_buffer_predisable,
};
......
......@@ -12,7 +12,6 @@
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
......@@ -368,28 +367,41 @@ static const struct iio_trigger_ops st_gyro_trigger_ops = {
#define ST_GYRO_TRIGGER_OPS NULL
#endif
/*
* st_gyro_get_settings() - get sensor settings from device name
* @name: device name buffer reference.
*
* Return: valid reference on success, NULL otherwise.
*/
const struct st_sensor_settings *st_gyro_get_settings(const char *name)
{
int index = st_sensors_get_settings_index(name,
st_gyro_sensors_settings,
ARRAY_SIZE(st_gyro_sensors_settings));
if (index < 0)
return NULL;
return &st_gyro_sensors_settings[index];
}
EXPORT_SYMBOL(st_gyro_get_settings);
int st_gyro_common_probe(struct iio_dev *indio_dev)
{
struct st_sensor_data *gdata = iio_priv(indio_dev);
int irq = gdata->get_irq_data_ready(indio_dev);
int err;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &gyro_info;
mutex_init(&gdata->tb.buf_lock);
err = st_sensors_power_enable(indio_dev);
if (err)
return err;
err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_gyro_sensors_settings),
st_gyro_sensors_settings);
err = st_sensors_verify_id(indio_dev);
if (err < 0)
goto st_gyro_power_off;
gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS;
gdata->multiread_bit = gdata->sensor_settings->multi_read_bit;
indio_dev->channels = gdata->sensor_settings->ch;
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
......@@ -406,7 +418,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
if (err < 0)
goto st_gyro_power_off;
if (irq > 0) {
if (gdata->irq > 0) {
err = st_sensors_allocate_trigger(indio_dev,
ST_GYRO_TRIGGER_OPS);
if (err < 0)
......@@ -423,7 +435,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
return 0;
st_gyro_device_register_error:
if (irq > 0)
if (gdata->irq > 0)
st_sensors_deallocate_trigger(indio_dev);
st_gyro_probe_trigger_error:
st_gyro_deallocate_ring(indio_dev);
......@@ -441,7 +453,7 @@ void st_gyro_common_remove(struct iio_dev *indio_dev)
st_sensors_power_disable(indio_dev);
iio_device_unregister(indio_dev);
if (gdata->get_irq_data_ready(indio_dev) > 0)
if (gdata->irq > 0)
st_sensors_deallocate_trigger(indio_dev);
st_gyro_deallocate_ring(indio_dev);
......
......@@ -65,19 +65,31 @@ MODULE_DEVICE_TABLE(of, st_gyro_of_match);
static int st_gyro_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
const struct st_sensor_settings *settings;
struct st_sensor_data *gdata;
struct iio_dev *indio_dev;
int err;
st_sensors_of_name_probe(&client->dev, st_gyro_of_match,
client->name, sizeof(client->name));
settings = st_gyro_get_settings(client->name);
if (!settings) {
dev_err(&client->dev, "device name %s not recognized.\n",
client->name);
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*gdata));
if (!indio_dev)
return -ENOMEM;
gdata = iio_priv(indio_dev);
st_sensors_of_name_probe(&client->dev, st_gyro_of_match,
client->name, sizeof(client->name));
gdata->sensor_settings = (struct st_sensor_settings *)settings;
st_sensors_i2c_configure(indio_dev, client, gdata);
err = st_sensors_i2c_configure(indio_dev, client);
if (err < 0)
return err;
err = st_gyro_common_probe(indio_dev);
if (err < 0)
......
......@@ -69,19 +69,31 @@ MODULE_DEVICE_TABLE(of, st_gyro_of_match);
static int st_gyro_spi_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
const struct st_sensor_settings *settings;
struct st_sensor_data *gdata;
struct iio_dev *indio_dev;
int err;
st_sensors_of_name_probe(&spi->dev, st_gyro_of_match,
spi->modalias, sizeof(spi->modalias));
settings = st_gyro_get_settings(spi->modalias);
if (!settings) {
dev_err(&spi->dev, "device name %s not recognized.\n",
spi->modalias);
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*gdata));
if (!indio_dev)
return -ENOMEM;
gdata = iio_priv(indio_dev);
gdata->sensor_settings = (struct st_sensor_settings *)settings;
st_sensors_of_name_probe(&spi->dev, st_gyro_of_match,
spi->modalias, sizeof(spi->modalias));
st_sensors_spi_configure(indio_dev, spi, gdata);
err = st_sensors_spi_configure(indio_dev, spi);
if (err < 0)
return err;
err = st_gyro_common_probe(indio_dev);
if (err < 0)
......
......@@ -240,32 +240,15 @@ static int am2315_probe(struct i2c_client *client,
indio_dev->channels = am2315_channels;
indio_dev->num_channels = ARRAY_SIZE(am2315_channels);
ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time,
ret = devm_iio_triggered_buffer_setup(&client->dev,
indio_dev, iio_pollfunc_store_time,
am2315_trigger_handler, NULL);
if (ret < 0) {
dev_err(&client->dev, "iio triggered buffer setup failed\n");
return ret;
}
ret = iio_device_register(indio_dev);
if (ret < 0)
goto err_buffer_cleanup;
return 0;
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
static int am2315_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
return 0;
return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id am2315_i2c_id[] = {
......@@ -287,7 +270,6 @@ static struct i2c_driver am2315_driver = {
.acpi_match_table = ACPI_PTR(am2315_acpi_id),
},
.probe = am2315_probe,
.remove = am2315_remove,
.id_table = am2315_i2c_id,
};
......
......@@ -385,28 +385,16 @@ static int hdc100x_probe(struct i2c_client *client,
hdc100x_set_it_time(data, 1, hdc100x_int_time[1][0]);
hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0);
ret = iio_triggered_buffer_setup(indio_dev, NULL,
ret = devm_iio_triggered_buffer_setup(&client->dev,
indio_dev, NULL,
hdc100x_trigger_handler,
&hdc_buffer_setup_ops);
if (ret < 0) {
dev_err(&client->dev, "iio triggered buffer setup failed\n");
return ret;
}
ret = iio_device_register(indio_dev);
if (ret < 0)
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
static int hdc100x_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
return 0;
return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id hdc100x_id[] = {
......@@ -436,7 +424,6 @@ static struct i2c_driver hdc100x_driver = {
.of_match_table = of_match_ptr(hdc100x_dt_ids),
},
.probe = hdc100x_probe,
.remove = hdc100x_remove,
.id_table = hdc100x_id,
};
module_i2c_driver(hdc100x_driver);
......
......@@ -17,6 +17,18 @@ config ADIS16400
adis16365, adis16400 and adis16405 triaxial inertial sensors
(adis16400 series also have magnetometers).
config ADIS16460
tristate "Analog Devices ADIS16460 and similar IMU driver"
depends on SPI
select IIO_ADIS_LIB
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for Analog Devices ADIS16460 inertial
sensor.
To compile this driver as a module, choose M here: the module will be
called adis16460.
config ADIS16480
tristate "Analog Devices ADIS16480 and similar IMU driver"
depends on SPI
......
......@@ -5,6 +5,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ADIS16400) += adis16400.o
obj-$(CONFIG_ADIS16460) += adis16460.o
obj-$(CONFIG_ADIS16480) += adis16480.o
adis_lib-y += adis.o
......
......@@ -39,18 +39,24 @@ int adis_write_reg(struct adis *adis, unsigned int reg,
.len = 2,
.cs_change = 1,
.delay_usecs = adis->data->write_delay,
.cs_change_delay = adis->data->cs_change_delay,
.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
}, {
.tx_buf = adis->tx + 2,
.bits_per_word = 8,
.len = 2,
.cs_change = 1,
.delay_usecs = adis->data->write_delay,
.cs_change_delay = adis->data->cs_change_delay,
.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
}, {
.tx_buf = adis->tx + 4,
.bits_per_word = 8,
.len = 2,
.cs_change = 1,
.delay_usecs = adis->data->write_delay,
.cs_change_delay = adis->data->cs_change_delay,
.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
}, {
.tx_buf = adis->tx + 6,
.bits_per_word = 8,
......@@ -133,12 +139,16 @@ int adis_read_reg(struct adis *adis, unsigned int reg,
.len = 2,
.cs_change = 1,
.delay_usecs = adis->data->write_delay,
.cs_change_delay = adis->data->cs_change_delay,
.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
}, {
.tx_buf = adis->tx + 2,
.bits_per_word = 8,
.len = 2,
.cs_change = 1,
.delay_usecs = adis->data->read_delay,
.cs_change_delay = adis->data->cs_change_delay,
.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
}, {
.tx_buf = adis->tx + 4,
.rx_buf = adis->rx,
......@@ -146,6 +156,8 @@ int adis_read_reg(struct adis *adis, unsigned int reg,
.len = 2,
.cs_change = 1,
.delay_usecs = adis->data->read_delay,
.cs_change_delay = adis->data->cs_change_delay,
.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
}, {
.rx_buf = adis->rx + 2,
.bits_per_word = 8,
......
This diff is collapsed.
......@@ -14,8 +14,9 @@ config INV_MPU6050_I2C
select INV_MPU6050_IIO
select REGMAP_I2C
help
This driver supports the Invensense MPU6050/6500/9150 and
ICM20608/20602 motion tracking devices over I2C.
This driver supports the Invensense MPU6000/6050/6500/6515,
MPU9150/9250/9255 and ICM20608/20602 motion tracking devices
over I2C.
This driver can be built as a module. The module will be called
inv-mpu6050-i2c.
......@@ -25,7 +26,8 @@ config INV_MPU6050_SPI
select INV_MPU6050_IIO
select REGMAP_SPI
help
This driver supports the Invensense MPU6050/6500/9150 and
ICM20608/20602 motion tracking devices over SPI.
This driver supports the Invensense MPU6000/6050/6500/6515,
MPU9150/9250/9255 and ICM20608/20602 motion tracking devices
over SPI.
This driver can be built as a module. The module will be called
inv-mpu6050-spi.
......@@ -1137,10 +1137,9 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
if (result)
return result;
result = devm_add_action(dev, inv_mpu_core_disable_regulator_action,
result = devm_add_action_or_reset(dev, inv_mpu_core_disable_regulator_action,
st);
if (result) {
inv_mpu_core_disable_regulator_action(st);
dev_err(dev, "Failed to setup regulator cleanup action %d\n",
result);
return result;
......
......@@ -2,15 +2,17 @@
config IIO_ST_LSM6DSX
tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors"
depends on (I2C || SPI)
depends on (I2C || SPI || I3C)
select IIO_BUFFER
select IIO_KFIFO_BUF
select IIO_ST_LSM6DSX_I2C if (I2C)
select IIO_ST_LSM6DSX_SPI if (SPI_MASTER)
select IIO_ST_LSM6DSX_I3C if (I3C)
help
Say yes here to build support for STMicroelectronics LSM6DSx imu
sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm,
ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr
ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr, lsm6ds3tr-c,
ism330dhcx
To compile this driver as a module, choose M here: the module
will be called st_lsm6dsx.
......@@ -24,3 +26,8 @@ config IIO_ST_LSM6DSX_SPI
tristate
depends on IIO_ST_LSM6DSX
select REGMAP_SPI
config IIO_ST_LSM6DSX_I3C
tristate
depends on IIO_ST_LSM6DSX
select REGMAP_I3C
......@@ -5,3 +5,4 @@ st_lsm6dsx-y := st_lsm6dsx_core.o st_lsm6dsx_buffer.o \
obj-$(CONFIG_IIO_ST_LSM6DSX) += st_lsm6dsx.o
obj-$(CONFIG_IIO_ST_LSM6DSX_I2C) += st_lsm6dsx_i2c.o
obj-$(CONFIG_IIO_ST_LSM6DSX_SPI) += st_lsm6dsx_spi.o
obj-$(CONFIG_IIO_ST_LSM6DSX_I3C) += st_lsm6dsx_i3c.o
......@@ -22,6 +22,8 @@
#define ST_ASM330LHH_DEV_NAME "asm330lhh"
#define ST_LSM6DSOX_DEV_NAME "lsm6dsox"
#define ST_LSM6DSR_DEV_NAME "lsm6dsr"
#define ST_LSM6DS3TRC_DEV_NAME "lsm6ds3tr-c"
#define ST_ISM330DHCX_DEV_NAME "ism330dhcx"
enum st_lsm6dsx_hw_id {
ST_LSM6DS3_ID,
......@@ -33,6 +35,8 @@ enum st_lsm6dsx_hw_id {
ST_ASM330LHH_ID,
ST_LSM6DSOX_ID,
ST_LSM6DSR_ID,
ST_LSM6DS3TRC_ID,
ST_ISM330DHCX_ID,
ST_LSM6DSX_MAX_ID,
};
......@@ -54,8 +58,8 @@ enum st_lsm6dsx_hw_id {
.address = addr, \
.modified = 1, \
.channel2 = mod, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.scan_index = scan_idx, \
.scan_type = { \
......@@ -198,6 +202,9 @@ struct st_lsm6dsx_ext_dev_settings {
* @wai: Sensor WhoAmI default value.
* @max_fifo_size: Sensor max fifo length in FIFO words.
* @id: List of hw id/device name supported by the driver configuration.
* @channels: IIO channels supported by the device.
* @odr_table: Hw sensors odr table (Hz + val).
* @fs_table: Hw sensors gain table (gain + val).
* @decimator: List of decimator register info (addr + mask).
* @batch: List of FIFO batching register info (addr + mask).
* @fifo_ops: Sensor hw FIFO parameters.
......@@ -211,6 +218,12 @@ struct st_lsm6dsx_settings {
enum st_lsm6dsx_hw_id hw_id;
const char *name;
} id[ST_LSM6DSX_MAX_ID];
struct {
const struct iio_chan_spec *chan;
int len;
} channels[2];
struct st_lsm6dsx_odr_table_entry odr_table[2];
struct st_lsm6dsx_fs_table_entry fs_table[2];
struct st_lsm6dsx_reg decimator[ST_LSM6DSX_MAX_ID];
struct st_lsm6dsx_reg batch[ST_LSM6DSX_MAX_ID];
struct st_lsm6dsx_fifo_ops fifo_ops;
......
......@@ -2,10 +2,10 @@
/*
* STMicroelectronics st_lsm6dsx FIFO buffer library driver
*
* LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC: The FIFO buffer can be
* configured to store data from gyroscope and accelerometer. Samples are
* queued without any tag according to a specific pattern based on
* 'FIFO data sets' (6 bytes each):
* LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C:
* The FIFO buffer can be configured to store data from gyroscope and
* accelerometer. Samples are queued without any tag according to a
* specific pattern based on 'FIFO data sets' (6 bytes each):
* - 1st data set is reserved for gyroscope data
* - 2nd data set is reserved for accelerometer data
* The FIFO pattern changes depending on the ODRs and decimation factors
......@@ -14,9 +14,10 @@
* (e.g. Gx, Gy, Gz, Ax, Ay, Az), then data are repeated depending on the
* value of the decimation factor and ODR set for each FIFO data set.
*
* LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR: The FIFO buffer can be configured to
* store data from gyroscope and accelerometer. Each sample is queued with
* a tag (1B) indicating data source (gyroscope, accelerometer, hw timer).
* LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX: The FIFO buffer can be
* configured to store data from gyroscope and accelerometer. Each sample
* is queued with a tag (1B) indicating data source (gyroscope, accelerometer,
* hw timer).
*
* FIFO supported modes:
* - BYPASS: FIFO disabled
......@@ -670,7 +671,7 @@ static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private)
count = hw->settings->fifo_ops.read_fifo(hw);
mutex_unlock(&hw->fifo_lock);
return !count ? IRQ_NONE : IRQ_HANDLED;
return count ? IRQ_HANDLED : IRQ_NONE;
}
static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev)
......
......@@ -75,6 +75,14 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = {
.compatible = "st,lsm6dsr",
.data = (void *)ST_LSM6DSR_ID,
},
{
.compatible = "st,lsm6ds3tr-c",
.data = (void *)ST_LSM6DS3TRC_ID,
},
{
.compatible = "st,ism330dhcx",
.data = (void *)ST_ISM330DHCX_ID,
},
{},
};
MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match);
......@@ -89,6 +97,8 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = {
{ ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID },
{ ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID },
{ ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID },
{ ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID },
{ ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID },
{},
};
MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table);
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 Synopsys, Inc. and/or its affiliates.
*
* Author: Vitor Soares <vitor.soares@synopsys.com>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i3c/device.h>
#include <linux/i3c/master.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include "st_lsm6dsx.h"
static const struct i3c_device_id st_lsm6dsx_i3c_ids[] = {
I3C_DEVICE(0x0104, 0x006C, (void *)ST_LSM6DSO_ID),
I3C_DEVICE(0x0104, 0x006B, (void *)ST_LSM6DSR_ID),
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(i3c, st_lsm6dsx_i3c_ids);
static int st_lsm6dsx_i3c_probe(struct i3c_device *i3cdev)
{
struct regmap_config st_lsm6dsx_i3c_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
const struct i3c_device_id *id = i3c_device_match_id(i3cdev,
st_lsm6dsx_i3c_ids);
struct regmap *regmap;
regmap = devm_regmap_init_i3c(i3cdev, &st_lsm6dsx_i3c_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&i3cdev->dev, "Failed to register i3c regmap %d\n",
(int)PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return st_lsm6dsx_probe(&i3cdev->dev, 0, (uintptr_t)id->data, regmap);
}
static struct i3c_driver st_lsm6dsx_driver = {
.driver = {
.name = "st_lsm6dsx_i3c",
.pm = &st_lsm6dsx_pm_ops,
},
.probe = st_lsm6dsx_i3c_probe,
.id_table = st_lsm6dsx_i3c_ids,
};
module_i3c_driver(st_lsm6dsx_driver);
MODULE_AUTHOR("Vitor Soares <vitor.soares@synopsys.com>");
MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx i3c driver");
MODULE_LICENSE("GPL v2");
......@@ -75,6 +75,14 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = {
.compatible = "st,lsm6dsr",
.data = (void *)ST_LSM6DSR_ID,
},
{
.compatible = "st,lsm6ds3tr-c",
.data = (void *)ST_LSM6DS3TRC_ID,
},
{
.compatible = "st,ism330dhcx",
.data = (void *)ST_ISM330DHCX_ID,
},
{},
};
MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match);
......@@ -89,6 +97,8 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = {
{ ST_ASM330LHH_DEV_NAME, ST_ASM330LHH_ID },
{ ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID },
{ ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID },
{ ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID },
{ ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID },
{},
};
MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table);
......
......@@ -303,6 +303,7 @@ config MAX44000
config MAX44009
tristate "MAX44009 Ambient Light Sensor"
depends on I2C
select REGMAP_I2C
help
Say Y here if you want to build support for Maxim Integrated's
MAX44009 ambient light sensor device.
......@@ -310,6 +311,16 @@ config MAX44009
To compile this driver as a module, choose M here:
the module will be called max44009.
config NOA1305
tristate "ON Semiconductor NOA1305 ambient light sensor"
depends on I2C
help
Say Y here if you want to build support for the ON Semiconductor
NOA1305 ambient light sensor.
To compile this driver as a module, choose M here:
The module will be called noa1305.
config OPT3001
tristate "Texas Instruments OPT3001 Light Sensor"
depends on I2C
......
......@@ -29,6 +29,7 @@ obj-$(CONFIG_LTR501) += ltr501.o
obj-$(CONFIG_LV0104CS) += lv0104cs.o
obj-$(CONFIG_MAX44000) += max44000.o
obj-$(CONFIG_MAX44009) += max44009.o
obj-$(CONFIG_NOA1305) += noa1305.o
obj-$(CONFIG_OPT3001) += opt3001.o
obj-$(CONFIG_PA12203001) += pa12203001.o
obj-$(CONFIG_RPR0521) += rpr0521.o
......
......@@ -1135,5 +1135,5 @@ static struct i2c_driver apds9960_driver = {
module_i2c_driver(apds9960_driver);
MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
MODULE_DESCRIPTION("ADPS9960 Gesture/RGB/ALS/Proximity sensor");
MODULE_DESCRIPTION("APDS9960 Gesture/RGB/ALS/Proximity sensor");
MODULE_LICENSE("GPL");
......@@ -101,15 +101,16 @@ static int cm3323_init(struct iio_dev *indio_dev)
return 0;
}
static void cm3323_disable(struct iio_dev *indio_dev)
static void cm3323_disable(void *data)
{
int ret;
struct cm3323_data *data = iio_priv(indio_dev);
struct iio_dev *indio_dev = data;
struct cm3323_data *cm_data = iio_priv(indio_dev);
ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF,
ret = i2c_smbus_write_word_data(cm_data->client, CM3323_CMD_CONF,
CM3323_CONF_SD_BIT);
if (ret < 0)
dev_err(&data->client->dev, "Error writing reg_conf\n");
dev_err(&cm_data->client->dev, "Error writing reg_conf\n");
}
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,
return ret;
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "failed to register iio dev\n");
goto err_init;
}
return 0;
err_init:
cm3323_disable(indio_dev);
ret = devm_add_action_or_reset(&client->dev, cm3323_disable, indio_dev);
if (ret < 0)
return ret;
}
static int cm3323_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
cm3323_disable(indio_dev);
return 0;
return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id cm3323_id[] = {
......@@ -276,7 +262,6 @@ static struct i2c_driver cm3323_driver = {
.name = CM3323_DRV_NAME,
},
.probe = cm3323_probe,
.remove = cm3323_remove,
.id_table = cm3323_id,
};
......
......@@ -646,18 +646,18 @@ static int cm36651_probe(struct i2c_client *client,
i2c_set_clientdata(client, indio_dev);
cm36651->client = client;
cm36651->ps_client = i2c_new_dummy(client->adapter,
cm36651->ps_client = i2c_new_dummy_device(client->adapter,
CM36651_I2C_ADDR_PS);
if (!cm36651->ps_client) {
if (IS_ERR(cm36651->ps_client)) {
dev_err(&client->dev, "%s: new i2c device failed\n", __func__);
ret = -ENODEV;
ret = PTR_ERR(cm36651->ps_client);
goto error_disable_reg;
}
cm36651->ara_client = i2c_new_dummy(client->adapter, CM36651_ARA);
if (!cm36651->ara_client) {
cm36651->ara_client = i2c_new_dummy_device(client->adapter, CM36651_ARA);
if (IS_ERR(cm36651->ara_client)) {
dev_err(&client->dev, "%s: new i2c device failed\n", __func__);
ret = -ENODEV;
ret = PTR_ERR(cm36651->ara_client);
goto error_i2c_unregister_ps;
}
......
......@@ -42,7 +42,7 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev,
struct cros_ec_light_prox_state *st = iio_priv(indio_dev);
u16 data = 0;
s64 val64;
int ret = IIO_VAL_INT;
int ret;
int idx = chan->scan_index;
mutex_lock(&st->core.cmd_lock);
......@@ -50,23 +50,22 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (chan->type == IIO_PROXIMITY) {
if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx,
(s16 *)&data) < 0) {
ret = -EIO;
ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx,
(s16 *)&data);
if (ret)
break;
}
*val = data;
ret = IIO_VAL_INT;
} else {
ret = -EINVAL;
}
break;
case IIO_CHAN_INFO_PROCESSED:
if (chan->type == IIO_LIGHT) {
if (cros_ec_sensors_read_cmd(indio_dev, 1 << idx,
(s16 *)&data) < 0) {
ret = -EIO;
ret = cros_ec_sensors_read_cmd(indio_dev, 1 << idx,
(s16 *)&data);
if (ret)
break;
}
/*
* The data coming from the light sensor is
* pre-processed and represents the ambient light
......@@ -82,15 +81,16 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev,
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
st->core.param.sensor_offset.flags = 0;
if (cros_ec_motion_send_host_cmd(&st->core, 0)) {
ret = -EIO;
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
if (ret)
break;
}
/* Save values */
st->core.calib[0] = st->core.resp->sensor_offset.offset[0];
st->core.calib[0].offset =
st->core.resp->sensor_offset.offset[0];
*val = st->core.calib[idx];
*val = st->core.calib[idx].offset;
ret = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_CALIBSCALE:
/*
......@@ -101,10 +101,9 @@ static int cros_ec_light_prox_read(struct iio_dev *indio_dev,
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;
if (cros_ec_motion_send_host_cmd(&st->core, 0)) {
ret = -EIO;
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
if (ret)
break;
}
val64 = st->core.resp->sensor_range.ret;
*val = val64 >> 16;
......@@ -127,28 +126,27 @@ static int cros_ec_light_prox_write(struct iio_dev *indio_dev,
int val, int val2, long mask)
{
struct cros_ec_light_prox_state *st = iio_priv(indio_dev);
int ret = 0;
int ret;
int idx = chan->scan_index;
mutex_lock(&st->core.cmd_lock);
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
st->core.calib[idx] = val;
st->core.calib[idx].offset = val;
/* Send to EC for each axis, even if not complete */
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
st->core.param.sensor_offset.flags = MOTION_SENSE_SET_OFFSET;
st->core.param.sensor_offset.offset[0] = st->core.calib[0];
st->core.param.sensor_offset.offset[0] =
st->core.calib[0].offset;
st->core.param.sensor_offset.temp =
EC_MOTION_SENSE_INVALID_CALIB_TEMP;
if (cros_ec_motion_send_host_cmd(&st->core, 0))
ret = -EIO;
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
break;
case IIO_CHAN_INFO_CALIBSCALE:
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
st->core.param.sensor_range.data = (val << 16) | (val2 / 100);
if (cros_ec_motion_send_host_cmd(&st->core, 0))
ret = -EIO;
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
break;
default:
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,
static const struct iio_info cros_ec_light_prox_info = {
.read_raw = &cros_ec_light_prox_read,
.write_raw = &cros_ec_light_prox_write,
.read_avail = &cros_ec_sensors_core_read_avail,
};
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)
channel->info_mask_shared_by_all =
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_FREQUENCY);
channel->info_mask_shared_by_all_available =
BIT(IIO_CHAN_INFO_SAMP_FREQ);
channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
channel->scan_type.shift = 0;
......@@ -205,8 +206,6 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev)
channel->ext_info = cros_ec_sensors_ext_info;
channel->scan_type.sign = 'u';
state->core.calib[0] = 0;
/* Sensor specific */
switch (state->core.type) {
case MOTIONSENSE_TYPE_LIGHT:
......
This diff is collapsed.
......@@ -1261,7 +1261,7 @@ static int si1145_probe_trigger(struct iio_dev *indio_dev)
return ret;
}
ret = iio_trigger_register(trig);
ret = devm_iio_trigger_register(&client->dev, trig);
if (ret)
return ret;
......@@ -1271,16 +1271,6 @@ static int si1145_probe_trigger(struct iio_dev *indio_dev)
return 0;
}
static void si1145_remove_trigger(struct iio_dev *indio_dev)
{
struct si1145_data *data = iio_priv(indio_dev);
if (data->trig) {
iio_trigger_unregister(data->trig);
data->trig = NULL;
}
}
static int si1145_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
......@@ -1332,7 +1322,8 @@ static int si1145_probe(struct i2c_client *client,
if (ret < 0)
return ret;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
ret = devm_iio_triggered_buffer_setup(&client->dev,
indio_dev, NULL,
si1145_trigger_handler, &si1145_buffer_setup_ops);
if (ret < 0)
return ret;
......@@ -1340,23 +1331,12 @@ static int si1145_probe(struct i2c_client *client,
if (client->irq) {
ret = si1145_probe_trigger(indio_dev);
if (ret < 0)
goto error_free_buffer;
return ret;
} else {
dev_info(&client->dev, "no irq, using polling\n");
}
ret = iio_device_register(indio_dev);
if (ret < 0)
goto error_free_trigger;
return 0;
error_free_trigger:
si1145_remove_trigger(indio_dev);
error_free_buffer:
iio_triggered_buffer_cleanup(indio_dev);
return ret;
return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id si1145_ids[] = {
......@@ -1371,23 +1351,11 @@ static const struct i2c_device_id si1145_ids[] = {
};
MODULE_DEVICE_TABLE(i2c, si1145_ids);
static int si1145_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
si1145_remove_trigger(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
return 0;
}
static struct i2c_driver si1145_driver = {
.driver = {
.name = "si1145",
},
.probe = si1145_probe,
.remove = si1145_remove,
.id_table = si1145_ids,
};
......
......@@ -679,9 +679,18 @@ static const struct acpi_device_id stk3310_acpi_id[] = {
MODULE_DEVICE_TABLE(acpi, stk3310_acpi_id);
static const struct of_device_id stk3310_of_match[] = {
{ .compatible = "sensortek,stk3310", },
{ .compatible = "sensortek,stk3311", },
{ .compatible = "sensortek,stk3335", },
{}
};
MODULE_DEVICE_TABLE(of, stk3310_of_match);
static struct i2c_driver stk3310_driver = {
.driver = {
.name = "stk3310",
.of_match_table = stk3310_of_match,
.pm = STK3310_PM_OPS,
.acpi_match_table = ACPI_PTR(stk3310_acpi_id),
},
......
This diff is collapsed.
......@@ -158,10 +158,10 @@ static int veml6070_probe(struct i2c_client *client,
indio_dev->name = VEML6070_DRV_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
data->client2 = i2c_new_dummy(client->adapter, VEML6070_ADDR_DATA_LSB);
if (!data->client2) {
data->client2 = i2c_new_dummy_device(client->adapter, VEML6070_ADDR_DATA_LSB);
if (IS_ERR(data->client2)) {
dev_err(&client->dev, "i2c device for second chip address failed\n");
return -ENODEV;
return PTR_ERR(data->client2);
}
data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD |
......
......@@ -53,7 +53,7 @@
#define MMC35240_CTRL1_BW_SHIFT 0
#define MMC35240_WAIT_CHARGE_PUMP 50000 /* us */
#define MMC53240_WAIT_SET_RESET 1000 /* us */
#define MMC35240_WAIT_SET_RESET 1000 /* us */
/*
* Memsic OTP process code piece is put here for reference:
......@@ -225,7 +225,7 @@ static int mmc35240_init(struct mmc35240_data *data)
ret = mmc35240_hw_set(data, true);
if (ret < 0)
return ret;
usleep_range(MMC53240_WAIT_SET_RESET, MMC53240_WAIT_SET_RESET + 1);
usleep_range(MMC35240_WAIT_SET_RESET, MMC35240_WAIT_SET_RESET + 1);
ret = mmc35240_hw_set(data, false);
if (ret < 0)
......
......@@ -22,6 +22,7 @@
#define LIS2MDL_MAGN_DEV_NAME "lis2mdl"
#define LSM9DS1_MAGN_DEV_NAME "lsm9ds1_magn"
const struct st_sensor_settings *st_magn_get_settings(const char *name);
int st_magn_common_probe(struct iio_dev *indio_dev);
void st_magn_common_remove(struct iio_dev *indio_dev);
......
This diff is collapsed.
This diff is collapsed.
......@@ -57,19 +57,31 @@ MODULE_DEVICE_TABLE(of, st_magn_of_match);
static int st_magn_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
const struct st_sensor_settings *settings;
struct st_sensor_data *mdata;
struct iio_dev *indio_dev;
int err;
st_sensors_of_name_probe(&client->dev, st_magn_of_match,
client->name, sizeof(client->name));
settings = st_magn_get_settings(client->name);
if (!settings) {
dev_err(&client->dev, "device name %s not recognized.\n",
client->name);
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*mdata));
if (!indio_dev)
return -ENOMEM;
mdata = iio_priv(indio_dev);
st_sensors_of_name_probe(&client->dev, st_magn_of_match,
client->name, sizeof(client->name));
mdata->sensor_settings = (struct st_sensor_settings *)settings;
st_sensors_i2c_configure(indio_dev, client, mdata);
err = st_sensors_i2c_configure(indio_dev, client);
if (err < 0)
return err;
err = st_magn_common_probe(indio_dev);
if (err < 0)
......
This diff is collapsed.
This diff is collapsed.
......@@ -6,6 +6,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AD5272) += ad5272.o
obj-$(CONFIG_DS1803) += ds1803.o
obj-$(CONFIG_MAX5432) += max5432.o
obj-$(CONFIG_MAX5481) += max5481.o
obj-$(CONFIG_MAX5487) += max5487.o
obj-$(CONFIG_MCP4018) += mcp4018.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment