Commit 2cfb2180 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Jonathan Cameron

iio: imu: st_lsm6dsx: introduce sw trigger support

There are some hw configuration where irq0 and/or irq1 pins are not
connected to the SPI or I2C/I3C controller. In order to avoid polling
the output register introduce iio-sw trigger support when irq line is
not available (or hw FIFO is not supported).
Suggested-by: default avatarMario Tesi <mario.tesi@st.com>
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Link: https://lore.kernel.org/r/93ae6ff1150b531a9d7a4d3d1b1adb8383613717.1666955685.git.lorenzo@kernel.orgSigned-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent ea4b79e9
...@@ -424,7 +424,7 @@ struct st_lsm6dsx_hw { ...@@ -424,7 +424,7 @@ struct st_lsm6dsx_hw {
struct { struct {
__le16 channels[3]; __le16 channels[3];
s64 ts __aligned(8); s64 ts __aligned(8);
} scan[3]; } scan[ST_LSM6DSX_ID_MAX];
}; };
static __maybe_unused const struct iio_event_spec st_lsm6dsx_event = { static __maybe_unused const struct iio_event_spec st_lsm6dsx_event = {
...@@ -456,6 +456,7 @@ int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw); ...@@ -456,6 +456,7 @@ int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw);
int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val); int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val);
int st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name); int st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name);
int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable); int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable);
int st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data, int len);
int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable); int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable);
static inline int static inline int
......
...@@ -53,6 +53,8 @@ ...@@ -53,6 +53,8 @@
#include <linux/iio/events.h> #include <linux/iio/events.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/minmax.h> #include <linux/minmax.h>
...@@ -2117,6 +2119,32 @@ static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) ...@@ -2117,6 +2119,32 @@ static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private)
return fifo_len || event ? IRQ_HANDLED : IRQ_NONE; return fifo_len || event ? IRQ_HANDLED : IRQ_NONE;
} }
static irqreturn_t st_lsm6dsx_sw_trigger_handler_thread(int irq,
void *private)
{
struct iio_poll_func *pf = private;
struct iio_dev *iio_dev = pf->indio_dev;
struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
struct st_lsm6dsx_hw *hw = sensor->hw;
if (sensor->id == ST_LSM6DSX_ID_EXT0 ||
sensor->id == ST_LSM6DSX_ID_EXT1 ||
sensor->id == ST_LSM6DSX_ID_EXT2)
st_lsm6dsx_shub_read_output(hw,
(u8 *)hw->scan[sensor->id].channels,
sizeof(hw->scan[sensor->id].channels));
else
st_lsm6dsx_read_locked(hw, iio_dev->channels[0].address,
hw->scan[sensor->id].channels,
sizeof(hw->scan[sensor->id].channels));
iio_push_to_buffers_with_timestamp(iio_dev, &hw->scan[sensor->id],
iio_get_time_ns(iio_dev));
iio_trigger_notify_done(iio_dev->trig);
return IRQ_HANDLED;
}
static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw) static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw)
{ {
struct st_sensors_platform_data *pdata; struct st_sensors_platform_data *pdata;
...@@ -2175,6 +2203,46 @@ static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw) ...@@ -2175,6 +2203,46 @@ static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw)
return 0; return 0;
} }
static int st_lsm6dsx_sw_buffer_preenable(struct iio_dev *iio_dev)
{
struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
return st_lsm6dsx_device_set_enable(sensor, true);
}
static int st_lsm6dsx_sw_buffer_postdisable(struct iio_dev *iio_dev)
{
struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
return st_lsm6dsx_device_set_enable(sensor, false);
}
static const struct iio_buffer_setup_ops st_lsm6dsx_sw_buffer_ops = {
.preenable = st_lsm6dsx_sw_buffer_preenable,
.postdisable = st_lsm6dsx_sw_buffer_postdisable,
};
static int st_lsm6dsx_sw_buffers_setup(struct st_lsm6dsx_hw *hw)
{
int i;
for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
int err;
if (!hw->iio_devs[i])
continue;
err = devm_iio_triggered_buffer_setup(hw->dev,
hw->iio_devs[i], NULL,
st_lsm6dsx_sw_trigger_handler_thread,
&st_lsm6dsx_sw_buffer_ops);
if (err)
return err;
}
return 0;
}
static int st_lsm6dsx_init_regulators(struct device *dev) static int st_lsm6dsx_init_regulators(struct device *dev)
{ {
/* vdd-vddio power regulators */ /* vdd-vddio power regulators */
...@@ -2255,6 +2323,16 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, ...@@ -2255,6 +2323,16 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
return err; return err;
} }
if (!hw->irq || !hw->settings->fifo_ops.read_fifo) {
/*
* Rely on sw triggers (e.g. hr-timers) if irq pin is not
* connected of if the device does not support HW FIFO
*/
err = st_lsm6dsx_sw_buffers_setup(hw);
if (err)
return err;
}
err = iio_read_mount_matrix(hw->dev, &hw->orientation); err = iio_read_mount_matrix(hw->dev, &hw->orientation);
if (err) if (err)
return err; return err;
......
...@@ -170,9 +170,7 @@ static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw) ...@@ -170,9 +170,7 @@ static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw)
* *
* Read st_lsm6dsx i2c controller register * Read st_lsm6dsx i2c controller register
*/ */
static int int st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data, int len)
st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data,
int len)
{ {
const struct st_lsm6dsx_shub_settings *hub_settings; const struct st_lsm6dsx_shub_settings *hub_settings;
int err; int err;
......
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