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: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 11 Nov 2022 12:26:54 +0100
From:   Mitja Spes <mitja@...av.com>
To:     Jonathan Cameron <jic23@...nel.org>,
        Lars-Peter Clausen <lars@...afoo.de>,
        Mitja Spes <mitja@...av.com>,
        Angelo Compagnucci <angelo.compagnucci@...il.com>,
        linux-iio@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH 2/4] iio: adc: mcp3422: allow setting gain and sampling per channel

General improvements:
- allow setting gain and sampling per channel
- setting scale can also set sampling rate (combined setting)
- use per channel config setting
- do not update mcp register on setting write (we might be reading it...)
  instead it's updated on next value read
- output all scale values (sample rates x gain)

Signed-off-by: Mitja Spes <mitja@...av.com>
---
 drivers/iio/adc/mcp3422.c | 119 ++++++++++++++++++++------------------
 1 file changed, 64 insertions(+), 55 deletions(-)

diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c
index 3d53de300c89..cfb629b964af 100644
--- a/drivers/iio/adc/mcp3422.c
+++ b/drivers/iio/adc/mcp3422.c
@@ -28,14 +28,19 @@
 #define MCP3422_CHANNEL_MASK	0x60
 #define MCP3422_PGA_MASK	0x03
 #define MCP3422_SRATE_MASK	0x0C
-#define MCP3422_SRATE_240	0x0
-#define MCP3422_SRATE_60	0x1
-#define MCP3422_SRATE_15	0x2
-#define MCP3422_SRATE_3	0x3
-#define MCP3422_PGA_1	0
-#define MCP3422_PGA_2	1
-#define MCP3422_PGA_4	2
-#define MCP3422_PGA_8	3
+
+#define MCP3422_SRATE_240	0
+#define MCP3422_SRATE_60	1
+#define MCP3422_SRATE_15	2
+#define MCP3422_SRATE_3		3
+#define MCP3422_SRATE_COUNT	4
+
+#define MCP3422_PGA_1		0
+#define MCP3422_PGA_2		1
+#define MCP3422_PGA_4		2
+#define MCP3422_PGA_8		3
+#define MCP3422_PGA_COUNT	4
+
 #define MCP3422_CONT_SAMPLING	0x10
 
 #define MCP3422_CHANNEL(config)	(((config) & MCP3422_CHANNEL_MASK) >> 5)
@@ -52,32 +57,32 @@
 		.indexed = 1, \
 		.channel = _index, \
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \
-				| BIT(IIO_CHAN_INFO_SCALE), \
-		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+				| BIT(IIO_CHAN_INFO_SCALE) \
+				| BIT(IIO_CHAN_INFO_SAMP_FREQ), \
 	}
 
-static const int mcp3422_scales[4][4] = {
+static const int mcp3422_scales[MCP3422_SRATE_COUNT][MCP3422_PGA_COUNT] = {
 	{ 1000000, 500000, 250000, 125000 },
 	{ 250000,  125000, 62500,  31250  },
 	{ 62500,   31250,  15625,  7812   },
 	{ 15625,   7812,   3906,   1953   } };
 
 /* Constant msleep times for data acquisitions */
-static const int mcp3422_read_times[4] = {
+static const int mcp3422_read_times[MCP3422_SRATE_COUNT] = {
 	[MCP3422_SRATE_240] = 1000 / 240,
 	[MCP3422_SRATE_60] = 1000 / 60,
 	[MCP3422_SRATE_15] = 1000 / 15,
 	[MCP3422_SRATE_3] = 1000 / 3 };
 
 /* sample rates to integer conversion table */
-static const int mcp3422_sample_rates[4] = {
+static const int mcp3422_sample_rates[MCP3422_SRATE_COUNT] = {
 	[MCP3422_SRATE_240] = 240,
 	[MCP3422_SRATE_60] = 60,
 	[MCP3422_SRATE_15] = 15,
 	[MCP3422_SRATE_3] = 3 };
 
 /* sample rates to sign extension table */
-static const int mcp3422_sign_extend[4] = {
+static const int mcp3422_sign_extend[MCP3422_SRATE_COUNT] = {
 	[MCP3422_SRATE_240] = 11,
 	[MCP3422_SRATE_60] = 13,
 	[MCP3422_SRATE_15] = 15,
@@ -87,8 +92,8 @@ static const int mcp3422_sign_extend[4] = {
 struct mcp3422 {
 	struct i2c_client *i2c;
 	u8 id;
-	u8 config;
-	u8 pga[4];
+	u8 active_config; // config currently set on mcp
+	u8 ch_config[4];  // per channel config
 	struct mutex lock;
 };
 
@@ -98,7 +103,7 @@ static int mcp3422_update_config(struct mcp3422 *adc, u8 newconfig)
 
 	ret = i2c_master_send(adc->i2c, &newconfig, 1);
 	if (ret > 0) {
-		adc->config = newconfig;
+		adc->active_config = newconfig;
 		ret = 0;
 	}
 
@@ -108,7 +113,7 @@ static int mcp3422_update_config(struct mcp3422 *adc, u8 newconfig)
 static int mcp3422_read(struct mcp3422 *adc, int *value, u8 *config)
 {
 	int ret = 0;
-	u8 sample_rate = MCP3422_SAMPLE_RATE(adc->config);
+	u8 sample_rate = MCP3422_SAMPLE_RATE(adc->active_config);
 	u8 buf[4] = {0, 0, 0, 0};
 	u32 temp;
 
@@ -136,18 +141,13 @@ static int mcp3422_read_channel(struct mcp3422 *adc,
 
 	mutex_lock(&adc->lock);
 
-	if (req_channel != MCP3422_CHANNEL(adc->config)) {
-		config = adc->config;
-		config &= ~MCP3422_CHANNEL_MASK;
-		config |= MCP3422_CHANNEL_VALUE(req_channel);
-		config &= ~MCP3422_PGA_MASK;
-		config |= MCP3422_PGA_VALUE(adc->pga[req_channel]);
-		ret = mcp3422_update_config(adc, config);
+	if (adc->ch_config[req_channel] != adc->active_config) {
+		ret = mcp3422_update_config(adc, adc->ch_config[req_channel]);
 		if (ret < 0) {
 			mutex_unlock(&adc->lock);
 			return ret;
 		}
-		msleep(mcp3422_read_times[MCP3422_SAMPLE_RATE(adc->config)]);
+		msleep(mcp3422_read_times[MCP3422_SAMPLE_RATE(adc->active_config)]);
 	}
 
 	ret = mcp3422_read(adc, value, &config);
@@ -164,9 +164,9 @@ static int mcp3422_read_raw(struct iio_dev *iio,
 	struct mcp3422 *adc = iio_priv(iio);
 	int err;
 
-	u8 req_channel = channel->channel;
-	u8 sample_rate = MCP3422_SAMPLE_RATE(adc->config);
-	u8 pga		 = adc->pga[req_channel];
+	u8 config = adc->ch_config[channel->channel];
+	u8 sample_rate = MCP3422_SAMPLE_RATE(config);
+	u8 pga = MCP3422_PGA(config);
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
@@ -181,7 +181,7 @@ static int mcp3422_read_raw(struct iio_dev *iio,
 		return IIO_VAL_INT_PLUS_NANO;
 
 	case IIO_CHAN_INFO_SAMP_FREQ:
-		*val1 = mcp3422_sample_rates[MCP3422_SAMPLE_RATE(adc->config)];
+		*val1 = mcp3422_sample_rates[sample_rate];
 		return IIO_VAL_INT;
 
 	default:
@@ -197,26 +197,25 @@ static int mcp3422_write_raw(struct iio_dev *iio,
 {
 	struct mcp3422 *adc = iio_priv(iio);
 	u8 temp;
-	u8 config = adc->config;
 	u8 req_channel = channel->channel;
-	u8 sample_rate = MCP3422_SAMPLE_RATE(config);
-	u8 i;
+	u8 config = adc->ch_config[req_channel];
+	u8 i, j;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_SCALE:
 		if (val1 != 0)
 			return -EINVAL;
 
-		for (i = 0; i < ARRAY_SIZE(mcp3422_scales[0]); i++) {
-			if (val2 == mcp3422_scales[sample_rate][i]) {
-				adc->pga[req_channel] = i;
-
-				config &= ~MCP3422_CHANNEL_MASK;
-				config |= MCP3422_CHANNEL_VALUE(req_channel);
-				config &= ~MCP3422_PGA_MASK;
-				config |= MCP3422_PGA_VALUE(adc->pga[req_channel]);
-
-				return mcp3422_update_config(adc, config);
+		for (j = 0; j < MCP3422_SRATE_COUNT; j++) {
+			for (i = 0; i < MCP3422_PGA_COUNT; i++) {
+				if (val2 == mcp3422_scales[j][i]) {
+					config &= ~MCP3422_PGA_MASK;
+					config |= MCP3422_PGA_VALUE(i);
+					config &= ~MCP3422_SRATE_MASK;
+					config |= MCP3422_SAMPLE_RATE_VALUE(j);
+					adc->ch_config[req_channel] = config;
+					return 0;
+				}
 			}
 		}
 		return -EINVAL;
@@ -241,12 +240,10 @@ static int mcp3422_write_raw(struct iio_dev *iio,
 			return -EINVAL;
 		}
 
-		config &= ~MCP3422_CHANNEL_MASK;
-		config |= MCP3422_CHANNEL_VALUE(req_channel);
 		config &= ~MCP3422_SRATE_MASK;
 		config |= MCP3422_SAMPLE_RATE_VALUE(temp);
-
-		return mcp3422_update_config(adc, config);
+		adc->ch_config[req_channel] = config;
+		return 0;
 
 	default:
 		break;
@@ -282,14 +279,18 @@ static ssize_t mcp3422_show_samp_freqs(struct device *dev,
 static ssize_t mcp3422_show_scales(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct mcp3422 *adc = iio_priv(dev_to_iio_dev(dev));
-	u8 sample_rate = MCP3422_SAMPLE_RATE(adc->config);
-
-	return sprintf(buf, "0.%09u 0.%09u 0.%09u 0.%09u\n",
-		mcp3422_scales[sample_rate][0],
-		mcp3422_scales[sample_rate][1],
-		mcp3422_scales[sample_rate][2],
-		mcp3422_scales[sample_rate][3]);
+	ssize_t count = 0;
+	int i;
+
+	for (i = 0; i < MCP3422_SRATE_COUNT; i++) {
+		count += sprintf(buf + count, "0.%09u 0.%09u 0.%09u 0.%09u%s",
+			mcp3422_scales[i][0],
+			mcp3422_scales[i][1],
+			mcp3422_scales[i][2],
+			mcp3422_scales[i][3],
+			(i < MCP3422_SRATE_COUNT - 1 ? " " : "\n"));
+	}
+	return count;
 }
 
 static IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO,
@@ -336,6 +337,7 @@ static int mcp3422_probe(struct i2c_client *client,
 	struct iio_dev *indio_dev;
 	struct mcp3422 *adc;
 	int err;
+	int i;
 	u8 config;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
@@ -376,6 +378,13 @@ static int mcp3422_probe(struct i2c_client *client,
 	}
 
 	/* meaningful default configuration */
+	for (i = 0; i < 4; i++) {
+		adc->ch_config[i] = (MCP3422_CONT_SAMPLING
+		| MCP3422_CHANNEL_VALUE(i)
+		| MCP3422_PGA_VALUE(MCP3422_PGA_1)
+		| MCP3422_SAMPLE_RATE_VALUE(MCP3422_SRATE_240));
+	}
+
 	config = (MCP3422_CONT_SAMPLING
 		| MCP3422_CHANNEL_VALUE(0)
 		| MCP3422_PGA_VALUE(MCP3422_PGA_1)
-- 
2.34.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ