drivers/iio/proximity/rfd77402.c

Source file repositories/reference/linux-study-clean/drivers/iio/proximity/rfd77402.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/proximity/rfd77402.c
Extension
.c
Size
10979 bytes
Lines
462
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 rfd77402_data {
	struct i2c_client *client;
	struct mutex lock;
	struct completion completion;
	bool irq_en;
};

static const struct iio_chan_spec rfd77402_channels[] = {
	{
		.type = IIO_DISTANCE,
		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
				      BIT(IIO_CHAN_INFO_SCALE),
	},
};

static irqreturn_t rfd77402_interrupt_handler(int irq, void *pdata)
{
	struct rfd77402_data *data = pdata;
	int ret;

	ret = i2c_smbus_read_byte_data(data->client, RFD77402_ICSR);
	if (ret < 0)
		return IRQ_NONE;

	/* Check if the interrupt is from our device */
	if (!(ret & RFD77402_ICSR_RESULT))
		return IRQ_NONE;

	/* Signal completion of measurement */
	complete(&data->completion);
	return IRQ_HANDLED;
}

static int rfd77402_wait_for_irq(struct rfd77402_data *data)
{
	int ret;

	/*
	 * According to RFD77402 Datasheet v1.8,
	 * Section 3.1.1 "Single Measure" (Figure: Single Measure Flow Chart),
	 * the suggested timeout for single measure is 100 ms.
	 */
	ret = wait_for_completion_timeout(&data->completion,
					  msecs_to_jiffies(100));
	if (ret == 0)
		return -ETIMEDOUT;

	return 0;
}

static int rfd77402_set_state(struct i2c_client *client, u8 state, u16 check)
{
	int ret;

	ret = i2c_smbus_write_byte_data(client, RFD77402_CMD_R,
					state | RFD77402_CMD_VALID);
	if (ret < 0)
		return ret;

	usleep_range(10000, 20000);

	ret = i2c_smbus_read_word_data(client, RFD77402_STATUS_R);
	if (ret < 0)
		return ret;
	if ((ret & RFD77402_STATUS_PM_MASK) != check)
		return -ENODEV;

	return 0;
}

static int rfd77402_wait_for_result(struct rfd77402_data *data)
{
	struct i2c_client *client = data->client;
	int val, ret;

	if (data->irq_en)
		return rfd77402_wait_for_irq(data);

	/*
	 * As per RFD77402 datasheet section '3.1.1 Single Measure', the
	 * suggested timeout value for single measure is 100ms.
	 */
	ret = read_poll_timeout(i2c_smbus_read_byte_data, val,
				 (val < 0) || (val & RFD77402_ICSR_RESULT),
				 10 * USEC_PER_MSEC,
				 10 * 10 * USEC_PER_MSEC,
				 false,
				 client, RFD77402_ICSR);
	if (val < 0)
		return val;

Annotation

Implementation Notes