lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20230614075537.3525194-1-l.goehrs@pengutronix.de>
Date:   Wed, 14 Jun 2023 09:55:36 +0200
From:   Leonard Göhrs <l.goehrs@...gutronix.de>
To:     Leonard Göhrs <l.goehrs@...gutronix.de>,
        kernel@...gutronix.de, Jonathan Cameron <jic23@...nel.org>,
        Lars-Peter Clausen <lars@...afoo.de>
Cc:     linux-iio@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH v1] iio: adc: add buffering support to the TI LMP92064 ADC driver

Enable buffered reading of samples from the LMP92064 ADC.
The main benefit of this change is being able to read out current and
voltage measurements in a single transfer, allowing instantaneous power
measurements.

Reads into the buffer can be triggered by any software triggers, e.g.
the iio-trig-hrtimer:

    $ mkdir /sys/kernel/config/iio/triggers/hrtimer/my-trigger
    $ cat /sys/bus/iio/devices/iio\:device3/name
    lmp92064
    $ iio_readdev -t my-trigger -b 16 iio:device3 | hexdump
    WARNING: High-speed mode not enabled
    0000000 0000 0176 0101 0001 5507 abd5 7645 1768
    0000010 0000 016d 0101 0001 ee1e ac6b 7645 1768
    ...

Signed-off-by: Leonard Göhrs <l.goehrs@...gutronix.de>
---
 drivers/iio/adc/ti-lmp92064.c | 54 +++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/drivers/iio/adc/ti-lmp92064.c b/drivers/iio/adc/ti-lmp92064.c
index c30ed824924f3..03765c4057dda 100644
--- a/drivers/iio/adc/ti-lmp92064.c
+++ b/drivers/iio/adc/ti-lmp92064.c
@@ -16,7 +16,10 @@
 #include <linux/spi/spi.h>
 
 #include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
 #include <linux/iio/driver.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
 
 #define TI_LMP92064_REG_CONFIG_A 0x0000
 #define TI_LMP92064_REG_CONFIG_B 0x0001
@@ -91,6 +94,13 @@ static const struct iio_chan_spec lmp92064_adc_channels[] = {
 		.address = TI_LMP92064_CHAN_INC,
 		.info_mask_separate =
 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 12,
+			.storagebits = 16,
+			.shift = 0,
+		},
 		.datasheet_name = "INC",
 	},
 	{
@@ -98,8 +108,16 @@ static const struct iio_chan_spec lmp92064_adc_channels[] = {
 		.address = TI_LMP92064_CHAN_INV,
 		.info_mask_separate =
 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+		.scan_index = 1,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 12,
+			.storagebits = 16,
+			.shift = 0,
+		},
 		.datasheet_name = "INV",
 	},
+	IIO_CHAN_SOFT_TIMESTAMP(2),
 };
 
 static int lmp92064_read_meas(struct lmp92064_adc_priv *priv, u16 *res)
@@ -171,6 +189,37 @@ static int lmp92064_read_raw(struct iio_dev *indio_dev,
 	}
 }
 
+static irqreturn_t lmp92064_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct lmp92064_adc_priv *priv = iio_priv(indio_dev);
+	int i = 0, j, ret;
+	u16 raw[2];
+	u16 *data;
+
+	ret = lmp92064_read_meas(priv, raw);
+	if (ret < 0)
+		goto done;
+
+	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	if (!data)
+		goto done;
+
+	for_each_set_bit(j, indio_dev->active_scan_mask, indio_dev->masklength)
+		data[i++] = raw[j];
+
+	iio_push_to_buffers_with_timestamp(indio_dev, data,
+					   iio_get_time_ns(indio_dev));
+
+	kfree(data);
+
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
 static int lmp92064_reset(struct lmp92064_adc_priv *priv,
 			  struct gpio_desc *gpio_reset)
 {
@@ -302,6 +351,11 @@ static int lmp92064_adc_probe(struct spi_device *spi)
 	indio_dev->num_channels = ARRAY_SIZE(lmp92064_adc_channels);
 	indio_dev->info = &lmp92064_adc_info;
 
+	ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
+					      lmp92064_trigger_handler, NULL);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to setup buffered read\n");
+
 	return devm_iio_device_register(dev, indio_dev);
 }
 

base-commit: 9561de3a55bed6bdd44a12820ba81ec416e705a7
-- 
2.39.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ