[PATCH 2/4] iio: adc: mcp3422: allow setting gain and sampling per channel

From: Mitja Spes
Date: Fri Nov 11 2022 - 06:28:32 EST


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@xxxxxxxxx>
---
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