Commit 6ee6a368 authored by Sean Nyekjaer's avatar Sean Nyekjaer Committed by Jonathan Cameron

iio: imu: st_lsm6dsx: move interrupt thread to core

This prepares the interrupt to be used for other stuff than
fifo reading + event readings.
Signed-off-by: default avatarSean Nyekjaer <sean@geanix.com>
Acked-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent e764fb4e
...@@ -30,8 +30,6 @@ ...@@ -30,8 +30,6 @@
* Denis Ciocca <denis.ciocca@st.com> * Denis Ciocca <denis.ciocca@st.com>
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/iio/kfifo_buf.h> #include <linux/iio/kfifo_buf.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
...@@ -42,10 +40,6 @@ ...@@ -42,10 +40,6 @@
#include "st_lsm6dsx.h" #include "st_lsm6dsx.h"
#define ST_LSM6DSX_REG_HLACTIVE_ADDR 0x12
#define ST_LSM6DSX_REG_HLACTIVE_MASK BIT(5)
#define ST_LSM6DSX_REG_PP_OD_ADDR 0x12
#define ST_LSM6DSX_REG_PP_OD_MASK BIT(4)
#define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a #define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a
#define ST_LSM6DSX_FIFO_MODE_MASK GENMASK(2, 0) #define ST_LSM6DSX_FIFO_MODE_MASK GENMASK(2, 0)
#define ST_LSM6DSX_FIFO_ODR_MASK GENMASK(6, 3) #define ST_LSM6DSX_FIFO_ODR_MASK GENMASK(6, 3)
...@@ -654,25 +648,6 @@ int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable) ...@@ -654,25 +648,6 @@ int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable)
return err; return err;
} }
static irqreturn_t st_lsm6dsx_handler_irq(int irq, void *private)
{
struct st_lsm6dsx_hw *hw = private;
return hw->sip > 0 ? IRQ_WAKE_THREAD : IRQ_NONE;
}
static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private)
{
struct st_lsm6dsx_hw *hw = private;
int count;
mutex_lock(&hw->fifo_lock);
count = hw->settings->fifo_ops.read_fifo(hw);
mutex_unlock(&hw->fifo_lock);
return count ? IRQ_HANDLED : IRQ_NONE;
}
static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev) static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev)
{ {
struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
...@@ -702,59 +677,8 @@ static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = { ...@@ -702,59 +677,8 @@ static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = {
int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
{ {
struct device_node *np = hw->dev->of_node;
struct st_sensors_platform_data *pdata;
struct iio_buffer *buffer; struct iio_buffer *buffer;
unsigned long irq_type; int i;
bool irq_active_low;
int i, err;
irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
irq_active_low = false;
break;
case IRQF_TRIGGER_LOW:
case IRQF_TRIGGER_FALLING:
irq_active_low = true;
break;
default:
dev_info(hw->dev, "mode %lx unsupported\n", irq_type);
return -EINVAL;
}
err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_HLACTIVE_ADDR,
ST_LSM6DSX_REG_HLACTIVE_MASK,
FIELD_PREP(ST_LSM6DSX_REG_HLACTIVE_MASK,
irq_active_low));
if (err < 0)
return err;
pdata = (struct st_sensors_platform_data *)hw->dev->platform_data;
if ((np && of_property_read_bool(np, "drive-open-drain")) ||
(pdata && pdata->open_drain)) {
err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_PP_OD_ADDR,
ST_LSM6DSX_REG_PP_OD_MASK,
FIELD_PREP(ST_LSM6DSX_REG_PP_OD_MASK,
1));
if (err < 0)
return err;
irq_type |= IRQF_SHARED;
}
err = devm_request_threaded_irq(hw->dev, hw->irq,
st_lsm6dsx_handler_irq,
st_lsm6dsx_handler_thread,
irq_type | IRQF_ONESHOT,
"lsm6dsx", hw);
if (err) {
dev_err(hw->dev, "failed to request trigger irq %d\n",
hw->irq);
return err;
}
for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
if (!hw->iio_devs[i]) if (!hw->iio_devs[i])
......
...@@ -50,6 +50,8 @@ ...@@ -50,6 +50,8 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/bitfield.h> #include <linux/bitfield.h>
...@@ -65,6 +67,11 @@ ...@@ -65,6 +67,11 @@
#define ST_LSM6DSX_REG_BDU_ADDR 0x12 #define ST_LSM6DSX_REG_BDU_ADDR 0x12
#define ST_LSM6DSX_REG_BDU_MASK BIT(6) #define ST_LSM6DSX_REG_BDU_MASK BIT(6)
#define ST_LSM6DSX_REG_HLACTIVE_ADDR 0x12
#define ST_LSM6DSX_REG_HLACTIVE_MASK BIT(5)
#define ST_LSM6DSX_REG_PP_OD_ADDR 0x12
#define ST_LSM6DSX_REG_PP_OD_MASK BIT(4)
static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = {
ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x28, IIO_MOD_X, 0), ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x28, IIO_MOD_X, 0),
ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1),
...@@ -1525,6 +1532,83 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw, ...@@ -1525,6 +1532,83 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw,
return iio_dev; return iio_dev;
} }
static irqreturn_t st_lsm6dsx_handler_irq(int irq, void *private)
{
struct st_lsm6dsx_hw *hw = private;
return hw->sip > 0 ? IRQ_WAKE_THREAD : IRQ_NONE;
}
static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private)
{
struct st_lsm6dsx_hw *hw = private;
int count;
mutex_lock(&hw->fifo_lock);
count = hw->settings->fifo_ops.read_fifo(hw);
mutex_unlock(&hw->fifo_lock);
return count ? IRQ_HANDLED : IRQ_NONE;
}
static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw)
{
struct st_sensors_platform_data *pdata;
struct device_node *np = hw->dev->of_node;
unsigned long irq_type;
bool irq_active_low;
int err;
irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
irq_active_low = false;
break;
case IRQF_TRIGGER_LOW:
case IRQF_TRIGGER_FALLING:
irq_active_low = true;
break;
default:
dev_info(hw->dev, "mode %lx unsupported\n", irq_type);
return -EINVAL;
}
err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_HLACTIVE_ADDR,
ST_LSM6DSX_REG_HLACTIVE_MASK,
FIELD_PREP(ST_LSM6DSX_REG_HLACTIVE_MASK,
irq_active_low));
if (err < 0)
return err;
pdata = (struct st_sensors_platform_data *)hw->dev->platform_data;
if ((np && of_property_read_bool(np, "drive-open-drain")) ||
(pdata && pdata->open_drain)) {
err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_PP_OD_ADDR,
ST_LSM6DSX_REG_PP_OD_MASK,
FIELD_PREP(ST_LSM6DSX_REG_PP_OD_MASK,
1));
if (err < 0)
return err;
irq_type |= IRQF_SHARED;
}
err = devm_request_threaded_irq(hw->dev, hw->irq,
st_lsm6dsx_handler_irq,
st_lsm6dsx_handler_thread,
irq_type | IRQF_ONESHOT,
"lsm6dsx", hw);
if (err) {
dev_err(hw->dev, "failed to request trigger irq %d\n",
hw->irq);
return err;
}
return 0;
}
int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
struct regmap *regmap) struct regmap *regmap)
{ {
...@@ -1573,6 +1657,10 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, ...@@ -1573,6 +1657,10 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
} }
if (hw->irq > 0) { if (hw->irq > 0) {
err = st_lsm6dsx_irq_setup(hw);
if (err < 0)
return err;
err = st_lsm6dsx_fifo_setup(hw); err = st_lsm6dsx_fifo_setup(hw);
if (err < 0) if (err < 0)
return err; return 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