drivers/w1/slaves/w1_ds28e17.c

Source file repositories/reference/linux-study-clean/drivers/w1/slaves/w1_ds28e17.c

File Facts

System
Linux kernel
Corpus path
drivers/w1/slaves/w1_ds28e17.c
Extension
.c
Size
18182 bytes
Lines
756
Domain
Driver Families
Bucket
drivers/w1
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 w1_f19_data {
	u8 speed;
	u8 stretch;
	struct i2c_adapter adapter;
};


/* Wait a while until the busy flag clears. */
static int w1_f19_i2c_busy_wait(struct w1_slave *sl, size_t count)
{
	const unsigned long timebases[3] = W1_F19_BUSY_TIMEBASES;
	struct w1_f19_data *data = sl->family_data;
	unsigned int checks;

	/* Check the busy flag first in any case.*/
	if (w1_touch_bit(sl->master, 1) == 0)
		return 0;

	/*
	 * Do a generously long sleep in the beginning,
	 * as we have to wait at least this time for all
	 * the I2C bytes at the given speed to be transferred.
	 */
	usleep_range(timebases[data->speed] * (data->stretch) * count,
		timebases[data->speed] * (data->stretch) * count
		+ W1_F19_BUSY_GRATUITY);

	/* Now continusly check the busy flag sent by the DS28E17. */
	checks = W1_F19_BUSY_CHECKS;
	while ((checks--) > 0) {
		/* Return success if the busy flag is cleared. */
		if (w1_touch_bit(sl->master, 1) == 0)
			return 0;

		/* Wait one non-streched byte timeslot. */
		udelay(timebases[data->speed]);
	}

	/* Timeout. */
	dev_warn(&sl->dev, "busy timeout\n");
	return -ETIMEDOUT;
}


/* Utility function: result. */
static size_t w1_f19_error(struct w1_slave *sl, u8 w1_buf[])
{
	/* Warnings. */
	if (w1_buf[0] & W1_F19_STATUS_CRC)
		dev_warn(&sl->dev, "crc16 mismatch\n");
	if (w1_buf[0] & W1_F19_STATUS_ADDRESS)
		dev_warn(&sl->dev, "i2c device not responding\n");
	if ((w1_buf[0] & (W1_F19_STATUS_CRC | W1_F19_STATUS_ADDRESS)) == 0
			&& w1_buf[1] != 0) {
		dev_warn(&sl->dev, "i2c short write, %d bytes not acknowledged\n",
			w1_buf[1]);
	}

	/* Check error conditions. */
	if (w1_buf[0] & W1_F19_STATUS_ADDRESS)
		return -ENXIO;
	if (w1_buf[0] & W1_F19_STATUS_START)
		return -EAGAIN;
	if (w1_buf[0] != 0 || w1_buf[1] != 0)
		return -EIO;

	/* All ok. */
	return 0;
}


/* Utility function: write data to I2C slave, single chunk. */
static int __w1_f19_i2c_write(struct w1_slave *sl,
	const u8 *command, size_t command_count,
	const u8 *buffer, size_t count)
{
	u16 crc;
	int error;
	u8 w1_buf[2];

	/* Send command and I2C data to DS28E17. */
	crc = crc16(CRC16_INIT, command, command_count);
	w1_write_block(sl->master, command, command_count);

	w1_buf[0] = count;
	crc = crc16(crc, w1_buf, 1);
	w1_write_8(sl->master, w1_buf[0]);

	crc = crc16(crc, buffer, count);
	w1_write_block(sl->master, buffer, count);

Annotation

Implementation Notes