drivers/iio/magnetometer/tmag5273.c

Source file repositories/reference/linux-study-clean/drivers/iio/magnetometer/tmag5273.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/magnetometer/tmag5273.c
Extension
.c
Size
19680 bytes
Lines
736
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 tmag5273_data {
	struct device *dev;
	unsigned int devid;
	unsigned int version;
	char name[16];
	unsigned int conv_avg;
	enum tmag5273_scale_index scale_index;
	unsigned int angle_measurement;
	struct regmap *map;

	/*
	 * Locks the sensor for exclusive use during a measurement (which
	 * involves several register transactions so the regmap lock is not
	 * enough) so that measurements get serialized in a
	 * first-come-first-serve manner.
	 */
	struct mutex lock;
};

static const char *const tmag5273_angle_names[] = { "off", "x-y", "y-z", "x-z" };

/*
 * Averaging enables additional sampling of the sensor data to reduce the noise
 * effect, but also increases conversion time.
 */
static const unsigned int tmag5273_avg_table[] = {
	1, 2, 4, 8, 16, 32,
};

/*
 * Magnetic resolution in Gauss for different TMAG5273 versions.
 * Scale[Gauss] = Range[mT] * 1000 / 2^15 * 10, (1 mT = 10 Gauss)
 * Only version 1 and 2 are valid, version 0 and 3 are reserved.
 */
static const struct iio_val_int_plus_micro tmag5273_scale[][MAGN_RANGE_NUM] = {
	{ { 0,     0 }, { 0,     0 } },
	{ { 0, 12200 }, { 0, 24400 } },
	{ { 0, 40600 }, { 0, 81200 } },
	{ { 0,     0 }, { 0,     0 } },
};

static int tmag5273_get_measure(struct tmag5273_data *data, s16 *t, s16 *x,
				s16 *y, s16 *z, u16 *angle, u16 *magnitude)
{
	unsigned int status, val;
	__be16 reg_data[4];
	int ret;

	mutex_lock(&data->lock);

	/*
	 * Max. conversion time is 2425 us in 32x averaging mode for all three
	 * channels. Since we are in continuous measurement mode, a measurement
	 * may already be there, so poll for completed measurement with
	 * timeout.
	 */
	ret = regmap_read_poll_timeout(data->map, TMAG5273_CONV_STATUS, status,
				       status & TMAG5273_CONV_STATUS_COMPLETE,
				       100, 10000);
	if (ret) {
		dev_err(data->dev, "timeout waiting for measurement\n");
		goto out_unlock;
	}

	ret = regmap_bulk_read(data->map, TMAG5273_T_MSB_RESULT, reg_data,
			       sizeof(reg_data));
	if (ret)
		goto out_unlock;
	*t = be16_to_cpu(reg_data[0]);
	*x = be16_to_cpu(reg_data[1]);
	*y = be16_to_cpu(reg_data[2]);
	*z = be16_to_cpu(reg_data[3]);

	ret = regmap_bulk_read(data->map, TMAG5273_ANGLE_RESULT_MSB,
			       &reg_data[0], sizeof(reg_data[0]));
	if (ret)
		goto out_unlock;
	/*
	 * angle has 9 bits integer value and 4 bits fractional part
	 * 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0
	 * 0  0  0  a  a  a  a  a  a  a  a  a  f  f  f  f
	 */
	*angle = be16_to_cpu(reg_data[0]);

	ret = regmap_read(data->map, TMAG5273_MAGNITUDE_RESULT, &val);
	if (ret < 0)
		goto out_unlock;
	*magnitude = val;

out_unlock:

Annotation

Implementation Notes