drivers/i2c/busses/i2c-viai2c-common.c

Source file repositories/reference/linux-study-clean/drivers/i2c/busses/i2c-viai2c-common.c

File Facts

System
Linux kernel
Corpus path
drivers/i2c/busses/i2c-viai2c-common.c
Extension
.c
Size
5159 bytes
Lines
204
Domain
Driver Families
Bucket
drivers/i2c
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

if (time_after(jiffies, timeout)) {
			dev_warn(i2c->dev, "timeout waiting for bus ready\n");
			return -EBUSY;
		}
		msleep(20);
	}

	return 0;
}
EXPORT_SYMBOL_GPL(viai2c_wait_bus_not_busy);

static int viai2c_write(struct viai2c *i2c, struct i2c_msg *pmsg, int last)
{
	u16 val, tcr_val = i2c->tcr;

	i2c->last = last;

	if (pmsg->len == 0) {
		/*
		 * We still need to run through the while (..) once, so
		 * start at -1 and break out early from the loop
		 */
		i2c->xfered_len = -1;
		writew(0, i2c->base + VIAI2C_REG_CDR);
	} else {
		writew(pmsg->buf[0] & 0xFF, i2c->base + VIAI2C_REG_CDR);
	}

	if (i2c->platform == VIAI2C_PLAT_WMT && !(pmsg->flags & I2C_M_NOSTART)) {
		val = readw(i2c->base + VIAI2C_REG_CR);
		val &= ~VIAI2C_CR_TX_END;
		val |= VIAI2C_CR_CPU_RDY;
		writew(val, i2c->base + VIAI2C_REG_CR);
	}

	reinit_completion(&i2c->complete);

	tcr_val |= pmsg->addr & VIAI2C_TCR_ADDR_MASK;

	writew(tcr_val, i2c->base + VIAI2C_REG_TCR);

	if (i2c->platform == VIAI2C_PLAT_WMT && pmsg->flags & I2C_M_NOSTART) {
		val = readw(i2c->base + VIAI2C_REG_CR);
		val |= VIAI2C_CR_CPU_RDY;
		writew(val, i2c->base + VIAI2C_REG_CR);
	}

	if (!wait_for_completion_timeout(&i2c->complete, VIAI2C_TIMEOUT))
		return -ETIMEDOUT;

	return i2c->ret;
}

static int viai2c_read(struct viai2c *i2c, struct i2c_msg *pmsg, bool first)
{
	u16 val, tcr_val = i2c->tcr;

	val = readw(i2c->base + VIAI2C_REG_CR);
	val &= ~(VIAI2C_CR_TX_END | VIAI2C_CR_RX_END);

	if (i2c->platform == VIAI2C_PLAT_WMT && !(pmsg->flags & I2C_M_NOSTART))
		val |= VIAI2C_CR_CPU_RDY;

	if (pmsg->len == 1)
		val |= VIAI2C_CR_RX_END;

	writew(val, i2c->base + VIAI2C_REG_CR);

	reinit_completion(&i2c->complete);

	tcr_val |= VIAI2C_TCR_READ | (pmsg->addr & VIAI2C_TCR_ADDR_MASK);

	writew(tcr_val, i2c->base + VIAI2C_REG_TCR);

	if ((i2c->platform == VIAI2C_PLAT_WMT && (pmsg->flags & I2C_M_NOSTART)) ||
	    (i2c->platform == VIAI2C_PLAT_ZHAOXIN && !first)) {
		val = readw(i2c->base + VIAI2C_REG_CR);
		val |= VIAI2C_CR_CPU_RDY;
		writew(val, i2c->base + VIAI2C_REG_CR);
	}

	if (!wait_for_completion_timeout(&i2c->complete, VIAI2C_TIMEOUT))
		return -ETIMEDOUT;

	return i2c->ret;
}

int viai2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{
	struct i2c_msg *pmsg;

Annotation

Implementation Notes