[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251002200206.59824-5-apokusinski01@gmail.com>
Date: Thu, 2 Oct 2025 22:02:05 +0200
From: Antoni Pokusinski <apokusinski01@...il.com>
To: jic23@...nel.org,
dlechner@...libre.com,
nuno.sa@...log.com,
andy@...nel.org,
robh@...nel.org,
krzk+dt@...nel.org,
conor+dt@...nel.org
Cc: linux-kernel@...r.kernel.org,
devicetree@...r.kernel.org,
linux-iio@...r.kernel.org,
linux@...ck-us.net,
rodrigo.gobbi.7@...il.com,
naresh.solanki@...ements.com,
michal.simek@....com,
grantpeltier93@...il.com,
farouk.bouabid@...rry.de,
marcelo.schmitt1@...il.com,
Antoni Pokusinski <apokusinski01@...il.com>
Subject: [PATCH v4 4/5] iio: mpl3115: add support for DRDY interrupt
MPL3115 sensor features a "data ready" interrupt which indicates the
presence of new measurements.
Signed-off-by: Antoni Pokusinski <apokusinski01@...il.com>
---
drivers/iio/pressure/mpl3115.c | 183 +++++++++++++++++++++++++++++++--
1 file changed, 175 insertions(+), 8 deletions(-)
diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c
index 61830edd959b..e1b2c9f2bb43 100644
--- a/drivers/iio/pressure/mpl3115.c
+++ b/drivers/iio/pressure/mpl3115.c
@@ -7,40 +7,66 @@
* (7-bit I2C slave address 0x60)
*
* TODO: FIFO buffer, altimeter mode, oversampling, continuous mode,
- * interrupts, user offset correction, raw mode
+ * user offset correction, raw mode
*/
-#include <linux/module.h>
+#include <linux/cleanup.h>
+#include <linux/delay.h>
#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/property.h>
+
+#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/buffer.h>
#include <linux/iio/triggered_buffer.h>
-#include <linux/delay.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/trigger.h>
#define MPL3115_STATUS 0x00
#define MPL3115_OUT_PRESS 0x01 /* MSB first, 20 bit */
#define MPL3115_OUT_TEMP 0x04 /* MSB first, 12 bit */
#define MPL3115_WHO_AM_I 0x0c
+#define MPL3115_INT_SOURCE 0x12
+#define MPL3115_PT_DATA_CFG 0x13
#define MPL3115_CTRL_REG1 0x26
+#define MPL3115_CTRL_REG3 0x28
+#define MPL3115_CTRL_REG4 0x29
+#define MPL3115_CTRL_REG5 0x2a
#define MPL3115_DEVICE_ID 0xc4
#define MPL3115_STATUS_PRESS_RDY BIT(2)
#define MPL3115_STATUS_TEMP_RDY BIT(1)
+#define MPL3115_INT_SRC_DRDY BIT(7)
+
+#define MPL3115_PT_DATA_EVENT_ALL GENMASK(2, 0)
+
#define MPL3115_CTRL1_RESET BIT(2) /* software reset */
#define MPL3115_CTRL1_OST BIT(1) /* initiate measurement */
#define MPL3115_CTRL1_ACTIVE BIT(0) /* continuous measurement */
#define MPL3115_CTRL1_OS_258MS GENMASK(5, 4) /* 64x oversampling */
+#define MPL3115_CTRL3_IPOL1 BIT(5)
+#define MPL3115_CTRL3_IPOL2 BIT(1)
+
+#define MPL3115_CTRL4_INT_EN_DRDY BIT(7)
+
+#define MPL3115_CTRL5_INT_CFG_DRDY BIT(7)
+
struct mpl3115_data {
struct i2c_client *client;
+ struct iio_trigger *drdy_trig;
struct mutex lock;
u8 ctrl_reg1;
};
+enum mpl3115_irq_pin {
+ MPL3115_IRQ_INT1,
+ MPL3115_IRQ_INT2,
+};
+
static int mpl3115_request(struct mpl3115_data *data)
{
int ret, tries = 15;
@@ -153,9 +179,11 @@ static int mpl3115_fill_trig_buffer(struct iio_dev *indio_dev, u8 *buffer)
struct mpl3115_data *data = iio_priv(indio_dev);
int ret, pos = 0;
- ret = mpl3115_request(data);
- if (ret < 0)
- return ret;
+ if (!(data->ctrl_reg1 & MPL3115_CTRL1_ACTIVE)) {
+ ret = mpl3115_request(data);
+ if (ret < 0)
+ return ret;
+ }
if (test_bit(0, indio_dev->active_scan_mask)) {
ret = i2c_smbus_read_i2c_block_data(data->client,
@@ -234,10 +262,145 @@ static const struct iio_chan_spec mpl3115_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(2),
};
+static irqreturn_t mpl3115_interrupt_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct mpl3115_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, MPL3115_INT_SOURCE);
+ if (ret < 0)
+ return IRQ_HANDLED;
+
+ if (!(ret & MPL3115_INT_SRC_DRDY))
+ return IRQ_NONE;
+
+ iio_trigger_poll_nested(data->drdy_trig);
+
+ return IRQ_HANDLED;
+}
+
+static int mpl3115_config_interrupt(struct mpl3115_data *data,
+ u8 ctrl_reg1, u8 ctrl_reg4)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
+ ctrl_reg1);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG4,
+ ctrl_reg4);
+ if (ret < 0)
+ goto reg1_cleanup;
+
+ data->ctrl_reg1 = ctrl_reg1;
+
+ return 0;
+
+reg1_cleanup:
+ i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
+ data->ctrl_reg1);
+ return ret;
+}
+
+static int mpl3115_set_trigger_state(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct mpl3115_data *data = iio_priv(indio_dev);
+ u8 ctrl_reg1 = data->ctrl_reg1;
+ u8 ctrl_reg4 = state ? MPL3115_CTRL4_INT_EN_DRDY : 0;
+
+ if (state)
+ ctrl_reg1 |= MPL3115_CTRL1_ACTIVE;
+ else
+ ctrl_reg1 &= ~MPL3115_CTRL1_ACTIVE;
+
+ guard(mutex)(&data->lock);
+
+ return mpl3115_config_interrupt(data, ctrl_reg1, ctrl_reg4);
+}
+
+static const struct iio_trigger_ops mpl3115_trigger_ops = {
+ .set_trigger_state = mpl3115_set_trigger_state,
+};
+
static const struct iio_info mpl3115_info = {
.read_raw = &mpl3115_read_raw,
};
+static int mpl3115_trigger_probe(struct mpl3115_data *data,
+ struct iio_dev *indio_dev)
+{
+ struct fwnode_handle *fwnode = dev_fwnode(&data->client->dev);
+ int ret, irq, irq_type, irq_pin = MPL3115_IRQ_INT1;
+
+ irq = fwnode_irq_get_byname(fwnode, "INT1");
+ if (irq < 0) {
+ irq = fwnode_irq_get_byname(fwnode, "INT2");
+ if (irq < 0)
+ return 0;
+
+ irq_pin = MPL3115_IRQ_INT2;
+ }
+
+ irq_type = irq_get_trigger_type(irq);
+ if (irq_type != IRQF_TRIGGER_RISING && irq_type != IRQF_TRIGGER_FALLING)
+ return -EINVAL;
+
+ ret = i2c_smbus_write_byte_data(data->client, MPL3115_PT_DATA_CFG,
+ MPL3115_PT_DATA_EVENT_ALL);
+ if (ret < 0)
+ return ret;
+
+ if (irq_pin == MPL3115_IRQ_INT1) {
+ ret = i2c_smbus_write_byte_data(data->client,
+ MPL3115_CTRL_REG5,
+ MPL3115_CTRL5_INT_CFG_DRDY);
+ if (ret)
+ return ret;
+
+ if (irq_type == IRQF_TRIGGER_RISING) {
+ ret = i2c_smbus_write_byte_data(data->client,
+ MPL3115_CTRL_REG3,
+ MPL3115_CTRL3_IPOL1);
+ if (ret)
+ return ret;
+ }
+ } else if (irq_type == IRQF_TRIGGER_RISING) {
+ ret = i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG3,
+ MPL3115_CTRL3_IPOL2);
+ if (ret)
+ return ret;
+ }
+
+ data->drdy_trig = devm_iio_trigger_alloc(&data->client->dev,
+ "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!data->drdy_trig)
+ return -ENOMEM;
+
+ data->drdy_trig->ops = &mpl3115_trigger_ops;
+ iio_trigger_set_drvdata(data->drdy_trig, indio_dev);
+
+ ret = devm_request_threaded_irq(&data->client->dev, irq, NULL,
+ mpl3115_interrupt_handler,
+ IRQF_ONESHOT,
+ "mpl3115_irq", indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_trigger_register(&data->client->dev, data->drdy_trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(data->drdy_trig);
+
+ return 0;
+}
+
static int mpl3115_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -277,6 +440,10 @@ static int mpl3115_probe(struct i2c_client *client)
if (ret < 0)
return ret;
+ ret = mpl3115_trigger_probe(data, indio_dev);
+ if (ret)
+ return ret;
+
ret = iio_triggered_buffer_setup(indio_dev, NULL,
mpl3115_trigger_handler, NULL);
if (ret < 0)
--
2.25.1
Powered by blists - more mailing lists