Re: [PATCH v5 1/3] hwmon: (ads7871) Fix endianness bug in 16-bit register reads

From: Guenter Roeck

Date: Fri May 01 2026 - 01:45:59 EST


On 4/30/26 19:35, Tabrez Ahmed wrote:
The ads7871_read_reg16() function relies on spi_w8r16() to read the
16-bit sensor output. The ADS7871 device transmits the Least Significant
Byte (LSB) first.

On Little-Endian architectures, spi_w8r16() correctly reconstructs the
16-bit value. However, on Big-Endian architectures, the byte swapping
causes the first received byte (LSB) to be placed in the most significant
byte of the u16, resulting in corrupted voltage readings.

Replace spi_w8r16() with a manual spi_write_then_read() into a byte array,
and safely reconstruct the integer using get_unaligned_le16() to ensure
correct behavior across all architectures. Additionally, use a u8
variable for the command byte to ensure the correct instruction is
transmitted on Big-Endian systems.

Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Closes: https://sashiko.dev/#/patchset/20260418034601.90226-1-tabreztalks@xxxxxxxxx
Signed-off-by: Tabrez Ahmed <tabreztalks@xxxxxxxxx>
---
drivers/hwmon/ads7871.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c
index 9bfdf9e6bcd77..d77eff430935b 100644
--- a/drivers/hwmon/ads7871.c
+++ b/drivers/hwmon/ads7871.c
@@ -59,9 +59,9 @@
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/delay.h>
+#include <linux/unaligned.h>
#define DEVICE_NAME "ads7871"
-
struct ads7871_data {
struct spi_device *spi;
};
@@ -77,9 +77,17 @@ static int ads7871_read_reg8(struct spi_device *spi, int reg)
static int ads7871_read_reg16(struct spi_device *spi, int reg)
{
int ret;
+ u8 tx_cmd;
+ u8 rx_buf[2];
+
reg = reg | INST_READ_BM | INST_16BIT_BM;
- ret = spi_w8r16(spi, reg);
- return ret;
+ tx_cmd = reg;

This can be combined into

tx_cmd = reg | INST_READ_BM | INST_16BIT_BM;

Thanks,
Guenter

+
+ ret = spi_write_then_read(spi, &tx_cmd, 1, rx_buf, 2);
+ if (ret < 0)
+ return ret;
+
+ return get_unaligned_le16(rx_buf);
}
static int ads7871_write_reg8(struct spi_device *spi, int reg, u8 val)