public inbox for linux-iio@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] iio: adc: mcp320x: refactor driver to use bitfield API
@ 2026-04-20 21:49 Gustavo Pagnotta Faria
  2026-04-21 14:32 ` Jonathan Cameron
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Gustavo Pagnotta Faria @ 2026-04-20 21:49 UTC (permalink / raw)
  To: jic23, dlechner, nuno.sa, andy
  Cc: Gustavo Pagnotta Faria, Eduardo Augusto, Christian Barry,
	linux-iio

Update the mcp320x driver to use the standard Linux bitfield
API (<linux/bitfield.h>) instead of manual bitwise shifts and masks.

This replaces the hardcoded shift operations in the TX data
preparation (mcp320x_channel_to_tx_data) with FIELD_PREP()
and replaces the manual masking in the RX data extraction
(mcp320x_adc_conversion) with FIELD_GET(). Explicit masks
using GENMASK() and BIT() were also introduced for both transmit
configurations and receive extractions.

Signed-off-by: Gustavo Pagnotta Faria <gustavo.pagnotta@ime.usp.br>
Co-developed-by: Eduardo Augusto <eduardoaugustoabc@ime.usp.br>
Signed-off-by: Eduardo Augusto <eduardoaugustoabc@ime.usp.br>
Co-developed-by: Christian Barry <christian.barry@ime.usp.br>
Signed-off-by: Christian Barry <christian.barry@ime.usp.br>
---
 drivers/iio/adc/mcp320x.c | 58 +++++++++++++++++++++++++++------------
 1 file changed, 41 insertions(+), 17 deletions(-)

diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c
index 57cff3772ebe..b7523e5ea903 100644
--- a/drivers/iio/adc/mcp320x.c
+++ b/drivers/iio/adc/mcp320x.c
@@ -44,6 +44,29 @@
 #include <linux/mod_devicetable.h>
 #include <linux/iio/iio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+
+/* MCP3x02/04/08 Tx Data configuration */
+#define MCP3X02_START_BIT	BIT(4)
+#define MCP3X02_SGL_DIFF	BIT(3)
+#define MCP3X02_CH_MASK		BIT(2)
+
+#define MCP3X04_08_START_BIT	BIT(6)
+#define MCP3X04_08_SGL_DIFF	BIT(5)
+#define MCP3X04_08_CH_MASK	GENMASK(4, 2)
+
+/* MCP Rx Data extraction masks */
+#define MCP3001_DATA_MASK	GENMASK(12, 3)
+#define MCP300X_DATA_MASK	GENMASK(15, 6)
+#define MCP3201_DATA_MASK	GENMASK(12, 1)
+#define MCP320X_DATA_MASK	GENMASK(15, 4)
+#define MCP3301_DATA_MASK	GENMASK(12, 0)
+
+/* MCP355X Data and Status bits */
+#define MCP355X_DATA_MASK	GENMASK(31, 8)
+#define MCP355X_SGN		BIT(23)
+#define MCP355X_OVR		BIT(22)
 
 enum {
 	mcp3001,
@@ -99,19 +122,19 @@ struct mcp320x {
 static int mcp320x_channel_to_tx_data(int device_index,
 			const unsigned int channel, bool differential)
 {
-	int start_bit = 1;
-
 	switch (device_index) {
 	case mcp3002:
 	case mcp3202:
-		return ((start_bit << 4) | (!differential << 3) |
-							(channel << 2));
+		return FIELD_PREP(MCP3X02_START_BIT, 1) |
+		       FIELD_PREP(MCP3X02_SGL_DIFF, !differential) |
+		       FIELD_PREP(MCP3X02_CH_MASK, channel);
 	case mcp3004:
 	case mcp3204:
 	case mcp3008:
 	case mcp3208:
-		return ((start_bit << 6) | (!differential << 5) |
-							(channel << 2));
+		return FIELD_PREP(MCP3X04_08_START_BIT, 1) |
+		       FIELD_PREP(MCP3X04_08_SGL_DIFF, !differential) |
+		       FIELD_PREP(MCP3X04_08_CH_MASK, channel);
 	default:
 		return -EINVAL;
 	}
@@ -140,26 +163,27 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
 	if (ret < 0)
 		return ret;
 
+	u16 raw16 = be16_to_cpup((__be16 *)adc->rx_buf);
+
 	switch (device_index) {
 	case mcp3001:
-		*val = (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3);
+		*val = FIELD_GET(MCP3001_DATA_MASK, raw16);
 		return 0;
 	case mcp3002:
 	case mcp3004:
 	case mcp3008:
-		*val = (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6);
+		*val = FIELD_GET(MCP300X_DATA_MASK, raw16);
 		return 0;
 	case mcp3201:
-		*val = (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1);
+		*val = FIELD_GET(MCP3201_DATA_MASK, raw16);
 		return 0;
 	case mcp3202:
 	case mcp3204:
 	case mcp3208:
-		*val = (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4);
+		*val = FIELD_GET(MCP320X_DATA_MASK, raw16);
 		return 0;
 	case mcp3301:
-		*val = sign_extend32((adc->rx_buf[0] & 0x1f) << 8
-				    | adc->rx_buf[1], 12);
+		*val = sign_extend32(FIELD_GET(MCP3301_DATA_MASK, raw16), 12);
 		return 0;
 	case mcp3550_50:
 	case mcp3550_60:
@@ -170,17 +194,17 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
 		if (!(adc->spi->mode & SPI_CPOL))
 			raw <<= 1; /* strip Data Ready bit in SPI mode 0,0 */
 
+		raw = FIELD_GET(MCP355X_DATA_MASK, raw);
 		/*
 		 * If the input is within -vref and vref, bit 21 is the sign.
 		 * Up to 12% overrange or underrange are allowed, in which case
 		 * bit 23 is the sign and bit 0 to 21 is the value.
 		 */
-		raw >>= 8;
-		if (raw & BIT(22) && raw & BIT(23))
+		if ((raw & MCP355X_OVR) && (raw & MCP355X_SGN))
 			return -EIO; /* cannot have overrange AND underrange */
-		else if (raw & BIT(22))
-			raw &= ~BIT(22); /* overrange */
-		else if (raw & BIT(23) || raw & BIT(21))
+		else if (raw & MCP355X_OVR)
+			raw &= MCP355X_OVR; /* overrange */
+		else if ((raw & MCP355X_SGN) || (raw & BIT(21)))
 			raw |= GENMASK(31, 22); /* underrange or negative */
 
 		*val = (s32)raw;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread
* [PATCH] iio: adc: mcp320x: refactor driver to use bitfield API
@ 2026-04-20 21:23 Gustavo Pagnotta Faria
  0 siblings, 0 replies; 5+ messages in thread
From: Gustavo Pagnotta Faria @ 2026-04-20 21:23 UTC (permalink / raw)
  To: jic23, dlechner, nuno.sa, andy
  Cc: Gustavo Pagnotta Faria, Eduardo Augusto, Christian Barry,
	linux-iio

From: Gustavo Pagnotta Faria <gustavo.pangotta@ime.usp.br>

Update the mcp320x driver to use the standard Linux bitfield
API (<linux/bitfield.h>) instead of manual bitwise shifts and masks.

This replaces the hardcoded shift operations in the TX data
preparation (mcp320x_channel_to_tx_data) with FIELD_PREP()
and replaces the manual masking in the RX data extraction
(mcp320x_adc_conversion) with FIELD_GET(). Explicit masks
using GENMASK() and BIT() were also introduced for both transmit
configurations and receive extractions.

Signed-off-by: Gustavo Pagnotta Faria <gustavo.pangotta@ime.usp.br>
Co-developed-by: Eduardo Augusto <eduardoaugustoabc@ime.usp.br>
Signed-off-by: Eduardo Augusto <eduardoaugustoabc@ime.usp.br>
Co-developed-by: Christian Barry <christian.barry@ime.usp.br>
Signed-off-by: Christian Barry <christian.barry@ime.usp.br>
---
 drivers/iio/adc/mcp320x.c | 58 +++++++++++++++++++++++++++------------
 1 file changed, 41 insertions(+), 17 deletions(-)

diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c
index 57cff3772ebe..b7523e5ea903 100644
--- a/drivers/iio/adc/mcp320x.c
+++ b/drivers/iio/adc/mcp320x.c
@@ -44,6 +44,29 @@
 #include <linux/mod_devicetable.h>
 #include <linux/iio/iio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+
+/* MCP3x02/04/08 Tx Data configuration */
+#define MCP3X02_START_BIT	BIT(4)
+#define MCP3X02_SGL_DIFF	BIT(3)
+#define MCP3X02_CH_MASK		BIT(2)
+
+#define MCP3X04_08_START_BIT	BIT(6)
+#define MCP3X04_08_SGL_DIFF	BIT(5)
+#define MCP3X04_08_CH_MASK	GENMASK(4, 2)
+
+/* MCP Rx Data extraction masks */
+#define MCP3001_DATA_MASK	GENMASK(12, 3)
+#define MCP300X_DATA_MASK	GENMASK(15, 6)
+#define MCP3201_DATA_MASK	GENMASK(12, 1)
+#define MCP320X_DATA_MASK	GENMASK(15, 4)
+#define MCP3301_DATA_MASK	GENMASK(12, 0)
+
+/* MCP355X Data and Status bits */
+#define MCP355X_DATA_MASK	GENMASK(31, 8)
+#define MCP355X_SGN		BIT(23)
+#define MCP355X_OVR		BIT(22)
 
 enum {
 	mcp3001,
@@ -99,19 +122,19 @@ struct mcp320x {
 static int mcp320x_channel_to_tx_data(int device_index,
 			const unsigned int channel, bool differential)
 {
-	int start_bit = 1;
-
 	switch (device_index) {
 	case mcp3002:
 	case mcp3202:
-		return ((start_bit << 4) | (!differential << 3) |
-							(channel << 2));
+		return FIELD_PREP(MCP3X02_START_BIT, 1) |
+		       FIELD_PREP(MCP3X02_SGL_DIFF, !differential) |
+		       FIELD_PREP(MCP3X02_CH_MASK, channel);
 	case mcp3004:
 	case mcp3204:
 	case mcp3008:
 	case mcp3208:
-		return ((start_bit << 6) | (!differential << 5) |
-							(channel << 2));
+		return FIELD_PREP(MCP3X04_08_START_BIT, 1) |
+		       FIELD_PREP(MCP3X04_08_SGL_DIFF, !differential) |
+		       FIELD_PREP(MCP3X04_08_CH_MASK, channel);
 	default:
 		return -EINVAL;
 	}
@@ -140,26 +163,27 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
 	if (ret < 0)
 		return ret;
 
+	u16 raw16 = be16_to_cpup((__be16 *)adc->rx_buf);
+
 	switch (device_index) {
 	case mcp3001:
-		*val = (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3);
+		*val = FIELD_GET(MCP3001_DATA_MASK, raw16);
 		return 0;
 	case mcp3002:
 	case mcp3004:
 	case mcp3008:
-		*val = (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6);
+		*val = FIELD_GET(MCP300X_DATA_MASK, raw16);
 		return 0;
 	case mcp3201:
-		*val = (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1);
+		*val = FIELD_GET(MCP3201_DATA_MASK, raw16);
 		return 0;
 	case mcp3202:
 	case mcp3204:
 	case mcp3208:
-		*val = (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4);
+		*val = FIELD_GET(MCP320X_DATA_MASK, raw16);
 		return 0;
 	case mcp3301:
-		*val = sign_extend32((adc->rx_buf[0] & 0x1f) << 8
-				    | adc->rx_buf[1], 12);
+		*val = sign_extend32(FIELD_GET(MCP3301_DATA_MASK, raw16), 12);
 		return 0;
 	case mcp3550_50:
 	case mcp3550_60:
@@ -170,17 +194,17 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
 		if (!(adc->spi->mode & SPI_CPOL))
 			raw <<= 1; /* strip Data Ready bit in SPI mode 0,0 */
 
+		raw = FIELD_GET(MCP355X_DATA_MASK, raw);
 		/*
 		 * If the input is within -vref and vref, bit 21 is the sign.
 		 * Up to 12% overrange or underrange are allowed, in which case
 		 * bit 23 is the sign and bit 0 to 21 is the value.
 		 */
-		raw >>= 8;
-		if (raw & BIT(22) && raw & BIT(23))
+		if ((raw & MCP355X_OVR) && (raw & MCP355X_SGN))
 			return -EIO; /* cannot have overrange AND underrange */
-		else if (raw & BIT(22))
-			raw &= ~BIT(22); /* overrange */
-		else if (raw & BIT(23) || raw & BIT(21))
+		else if (raw & MCP355X_OVR)
+			raw &= MCP355X_OVR; /* overrange */
+		else if ((raw & MCP355X_SGN) || (raw & BIT(21)))
 			raw |= GENMASK(31, 22); /* underrange or negative */
 
 		*val = (s32)raw;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-04-22  6:48 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-20 21:49 [PATCH] iio: adc: mcp320x: refactor driver to use bitfield API Gustavo Pagnotta Faria
2026-04-21 14:32 ` Jonathan Cameron
2026-04-21 15:51 ` Jonathan Cameron
2026-04-22  6:48 ` Andy Shevchenko
  -- strict thread matches above, loose matches on Subject: below --
2026-04-20 21:23 Gustavo Pagnotta Faria

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox