drivers/iio/adc/ti-ads7138.c

Source file repositories/reference/linux-study-clean/drivers/iio/adc/ti-ads7138.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/adc/ti-ads7138.c
Extension
.c
Size
19645 bytes
Lines
750
Domain
Driver Families
Bucket
drivers/iio
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 ads7138_chip_data {
	const char *name;
	const int channel_num;
};

struct ads7138_data {
	/* Protects RMW access to the I2C interface */
	struct mutex lock;
	struct i2c_client *client;
	struct regulator *vref_regu;
	const struct ads7138_chip_data *chip_data;
};

/*
 * 2D array of available sampling frequencies and the corresponding register
 * values. Structured like this to be easily usable in read_avail function.
 */
static const int ads7138_samp_freqs_bits[2][26] = {
	{
		163, 244, 326, 488, 651, 977, 1302, 1953,
		2604, 3906, 5208, 7813, 10417, 15625, 20833, 31250,
		41667, 62500, 83333, 125000, 166667, 250000, 333333, 500000,
		666667, 1000000
	}, {
		0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18,
		0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
		/* Here is a hole, due to duplicate frequencies */
		0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02,
		0x01, 0x00
	}
};

static const int ads7138_oversampling_ratios[] = {
	1, 2, 4, 8, 16, 32, 64, 128
};

static int ads7138_i2c_write_block(const struct i2c_client *client, u8 reg,
				   u8 *values, u8 length)
{
	int ret;
	int len = length + 2; /* "+ 2" for OPCODE and reg */

	u8 *buf __free(kfree) = kmalloc(len, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	buf[0] = ADS7138_OPCODE_BLOCK_WRITE;
	buf[1] = reg;
	memcpy(&buf[2], values, length);

	ret = i2c_master_send(client, buf, len);
	if (ret < 0)
		return ret;
	if (ret != len)
		return -EIO;

	return 0;
}

static int ads7138_i2c_write_with_opcode(const struct i2c_client *client,
					 u8 reg, u8 regval, u8 opcode)
{
	u8 buf[3] = { opcode, reg, regval };
	int ret;

	ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
	if (ret < 0)
		return ret;
	if (ret != ARRAY_SIZE(buf))
		return -EIO;

	return 0;
}

static int ads7138_i2c_write(const struct i2c_client *client, u8 reg, u8 value)
{
	return ads7138_i2c_write_with_opcode(client, reg, value,
					     ADS7138_OPCODE_SINGLE_WRITE);
}

static int ads7138_i2c_set_bit(const struct i2c_client *client, u8 reg, u8 bits)
{
	return ads7138_i2c_write_with_opcode(client, reg, bits,
					     ADS7138_OPCODE_SET_BIT);
}

static int ads7138_i2c_clear_bit(const struct i2c_client *client, u8 reg, u8 bits)
{
	return ads7138_i2c_write_with_opcode(client, reg, bits,
					     ADS7138_OPCODE_CLEAR_BIT);

Annotation

Implementation Notes