drivers/hwmon/ads7871.c

Source file repositories/reference/linux-study-clean/drivers/hwmon/ads7871.c

File Facts

System
Linux kernel
Corpus path
drivers/hwmon/ads7871.c
Extension
.c
Size
5770 bytes
Lines
232
Domain
Driver Families
Bucket
drivers/hwmon
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ads7871_data {
	struct spi_device *spi;
	u8 tx_buf[2] ____cacheline_aligned;
};

static umode_t ads7871_is_visible(const void *data,
				  enum hwmon_sensor_types type,
				  u32 attr, int channel)
{
	if (type == hwmon_in && attr == hwmon_in_input)
		return 0444;

	return 0;
}

static int ads7871_read_reg8(struct spi_device *spi, int reg)
{
	int ret;
	reg = reg | INST_READ_BM;
	ret = spi_w8r8(spi, reg);
	return ret;
}

static int ads7871_read_reg16(struct spi_device *spi, int reg)
{
	int ret;

	reg = reg | INST_READ_BM | INST_16BIT_BM;
	ret = spi_w8r16(spi, reg);
	if (ret < 0)
		return ret;

	return le16_to_cpu((__force __le16)ret);
}

static int ads7871_write_reg8(struct ads7871_data *pdata, int reg, u8 val)
{
	pdata->tx_buf[0] = reg;
	pdata->tx_buf[1] = val;

	return spi_write(pdata->spi, pdata->tx_buf, 2);
}

static int ads7871_read(struct device *dev, enum hwmon_sensor_types type,
			u32 attr, int channel, long *val)
{
	struct ads7871_data *pdata = dev_get_drvdata(dev);
	struct spi_device *spi = pdata->spi;
	int ret, raw_val, i = 0;
	u8 mux_cnv;

	if (type != hwmon_in || attr != hwmon_in_input)
		return -EOPNOTSUPP;
	/*
	 * TODO: add support for conversions
	 * other than single ended with a gain of 1
	 */
	/*MUX_M3_BM forces single ended*/
	/*This is also where the gain of the PGA would be set*/
	ret = ads7871_write_reg8(pdata, REG_GAIN_MUX,
				 (MUX_CNV_BM | MUX_M3_BM | channel));
	if (ret < 0)
		return ret;

	ret = ads7871_read_reg8(spi, REG_GAIN_MUX);
	if (ret < 0)
		return ret;

	mux_cnv = ((ret & MUX_CNV_BM) >> MUX_CNV_BV);
	/*
	 * on 400MHz arm9 platform the conversion
	 * is already done when we do this test
	 */
	while ((i < 2) && mux_cnv) {
		i++;
		ret = ads7871_read_reg8(spi, REG_GAIN_MUX);
		if (ret < 0)
			return ret;
		mux_cnv = ((ret & MUX_CNV_BM) >> MUX_CNV_BV);
		msleep_interruptible(1);
	}

	if (mux_cnv == 0) {
		raw_val = ads7871_read_reg16(spi, REG_LS_BYTE);
		if (raw_val < 0)
			return raw_val;

		/*
		 * Use (s16) to ensure the sign bit is preserved during the shift.
		 * Report millivolts (2.5V = 2500mV).

Annotation

Implementation Notes