Linux IIO development
 help / color / mirror / Atom feed
From: "Mårten Lindahl" <marten.lindahl@axis.com>
To: Jonathan Cameron <jic23@kernel.org>
Cc: "Lars-Peter Clausen" <lars@metafoo.de>,
	linux-iio@vger.kernel.org, kernel@axis.com,
	"Mårten Lindahl" <marten.lindahl@axis.com>
Subject: [PATCH 1/2] iio: light: vcnl4000: Make irq handling more generic
Date: Tue, 20 Dec 2022 22:49:58 +0100	[thread overview]
Message-ID: <20221220214959.2289330-2-marten.lindahl@axis.com> (raw)
In-Reply-To: <20221220214959.2289330-1-marten.lindahl@axis.com>

This driver supports 4 chips, by which only one (vcnl4010) handles
interrupts and has support for triggered buffer. The setup of these
functions is hardcoded for vcnl4010 inside the generic vcnl4000_probe,
and thus ignores the chip specific configuration structure where all
other chip specific functions are specified.

This complicates adding interrupt handler and triggered buffer support
to chips which may have support for it.

Add members for irq threads and iio_buffer_setup_ops to the generic
vcnl4000_chip_spec struct, so that instead of checking a chip specific
boolean irq support, we check for a chip specific triggered buffer
handler, and/or a chip specific irq thread handler.

Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
---
 drivers/iio/light/vcnl4000.c | 66 +++++++++++++++++++++---------------
 1 file changed, 38 insertions(+), 28 deletions(-)

diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index cc1a2062e76d..142d1760f65d 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -150,11 +150,13 @@ struct vcnl4000_chip_spec {
 	struct iio_chan_spec const *channels;
 	const int num_channels;
 	const struct iio_info *info;
-	bool irq_support;
+	const struct iio_buffer_setup_ops *buffer_setup_ops;
 	int (*init)(struct vcnl4000_data *data);
 	int (*measure_light)(struct vcnl4000_data *data, int *val);
 	int (*measure_proximity)(struct vcnl4000_data *data, int *val);
 	int (*set_power_state)(struct vcnl4000_data *data, bool on);
+	irqreturn_t (*irq_thread)(int irq, void *priv);
+	irqreturn_t (*trig_buffer_func)(int irq, void *priv);
 };
 
 static const struct i2c_device_id vcnl4000_id[] = {
@@ -167,6 +169,11 @@ static const struct i2c_device_id vcnl4000_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, vcnl4000_id);
 
+static irqreturn_t vcnl4010_irq_thread(int irq, void *p);
+static irqreturn_t vcnl4010_trigger_handler(int irq, void *p);
+static int vcnl4010_buffer_postenable(struct iio_dev *indio_dev);
+static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev);
+
 static int vcnl4000_set_power_state(struct vcnl4000_data *data, bool on)
 {
 	/* no suspend op */
@@ -983,6 +990,11 @@ static const struct iio_info vcnl4040_info = {
 	.read_avail = vcnl4040_read_avail,
 };
 
+static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = {
+	.postenable = &vcnl4010_buffer_postenable,
+	.predisable = &vcnl4010_buffer_predisable,
+};
+
 static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
 	[VCNL4000] = {
 		.prod = "VCNL4000",
@@ -993,7 +1005,6 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
 		.channels = vcnl4000_channels,
 		.num_channels = ARRAY_SIZE(vcnl4000_channels),
 		.info = &vcnl4000_info,
-		.irq_support = false,
 	},
 	[VCNL4010] = {
 		.prod = "VCNL4010/4020",
@@ -1004,7 +1015,9 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
 		.channels = vcnl4010_channels,
 		.num_channels = ARRAY_SIZE(vcnl4010_channels),
 		.info = &vcnl4010_info,
-		.irq_support = true,
+		.irq_thread = vcnl4010_irq_thread,
+		.trig_buffer_func = vcnl4010_trigger_handler,
+		.buffer_setup_ops = &vcnl4010_buffer_ops,
 	},
 	[VCNL4040] = {
 		.prod = "VCNL4040",
@@ -1015,7 +1028,6 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
 		.channels = vcnl4040_channels,
 		.num_channels = ARRAY_SIZE(vcnl4040_channels),
 		.info = &vcnl4040_info,
-		.irq_support = false,
 	},
 	[VCNL4200] = {
 		.prod = "VCNL4200",
@@ -1026,7 +1038,6 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
 		.channels = vcnl4000_channels,
 		.num_channels = ARRAY_SIZE(vcnl4000_channels),
 		.info = &vcnl4000_info,
-		.irq_support = false,
 	},
 };
 
@@ -1153,11 +1164,6 @@ static int vcnl4010_buffer_predisable(struct iio_dev *indio_dev)
 	return i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0);
 }
 
-static const struct iio_buffer_setup_ops vcnl4010_buffer_ops = {
-	.postenable = &vcnl4010_buffer_postenable,
-	.predisable = &vcnl4010_buffer_predisable,
-};
-
 static const struct iio_trigger_ops vcnl4010_trigger_ops = {
 	.validate_device = iio_trigger_validate_own_device,
 };
@@ -1214,26 +1220,30 @@ static int vcnl4000_probe(struct i2c_client *client)
 	indio_dev->name = VCNL4000_DRV_NAME;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	if (client->irq && data->chip_spec->irq_support) {
-		ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
-						      NULL,
-						      vcnl4010_trigger_handler,
-						      &vcnl4010_buffer_ops);
-		if (ret < 0) {
-			dev_err(&client->dev,
-				"unable to setup iio triggered buffer\n");
-			return ret;
+	if (client->irq) {
+		if (data->chip_spec->trig_buffer_func) {
+			ret = devm_iio_triggered_buffer_setup(&client->dev,
+							      indio_dev, NULL,
+							      data->chip_spec->trig_buffer_func,
+							      data->chip_spec->buffer_setup_ops);
+			if (ret < 0) {
+				dev_err(&client->dev,
+					"unable to setup iio triggered buffer\n");
+				return ret;
+			}
 		}
 
-		ret = devm_request_threaded_irq(&client->dev, client->irq,
-						NULL, vcnl4010_irq_thread,
-						IRQF_TRIGGER_FALLING |
-						IRQF_ONESHOT,
-						"vcnl4010_irq",
-						indio_dev);
-		if (ret < 0) {
-			dev_err(&client->dev, "irq request failed\n");
-			return ret;
+		if (data->chip_spec->irq_thread) {
+			ret = devm_request_threaded_irq(&client->dev,
+							client->irq, NULL,
+							data->chip_spec->irq_thread,
+							IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+							"vcnl4000_irq",
+							indio_dev);
+			if (ret < 0) {
+				dev_err(&client->dev, "irq request failed\n");
+				return ret;
+			}
 		}
 
 		ret = vcnl4010_probe_trigger(indio_dev);
-- 
2.30.2


  reply	other threads:[~2022-12-20 21:50 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-20 21:49 [PATCH 0/2] iio: light: vcnl4000: Add vcnl4040 interrupt support Mårten Lindahl
2022-12-20 21:49 ` Mårten Lindahl [this message]
2022-12-23 15:53   ` [PATCH 1/2] iio: light: vcnl4000: Make irq handling more generic Jonathan Cameron
2023-01-09 11:32     ` Marten Lindahl
2023-01-09 15:30       ` Jonathan Cameron
2023-01-10 12:24         ` Marten Lindahl
2022-12-20 21:49 ` [PATCH 2/2] iio: light: vcnl4000: Add interrupt support for vcnl4040 Mårten Lindahl
2022-12-23 16:00   ` Jonathan Cameron
2023-01-09 11:41     ` Marten Lindahl

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221220214959.2289330-2-marten.lindahl@axis.com \
    --to=marten.lindahl@axis.com \
    --cc=jic23@kernel.org \
    --cc=kernel@axis.com \
    --cc=lars@metafoo.de \
    --cc=linux-iio@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox