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

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

File Facts

System
Linux kernel
Corpus path
drivers/i2c/busses/i2c-viai2c-zhaoxin.c
Extension
.c
Size
9640 bytes
Lines
368
Domain
Driver Families
Bucket
drivers/i2c
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 viai2c_zhaoxin {
	u8			hrv;
	u16			tr;
	u16			mcr;
	u16			xfer_len;
};

static int viai2c_fifo_xfer(struct viai2c *i2c)
{
	u16 i;
	u8 tmp;
	struct i2c_msg *msg = i2c->msg;
	void __iomem *base = i2c->base;
	bool read = !!(msg->flags & I2C_M_RD);
	struct viai2c_zhaoxin *priv = i2c->pltfm_priv;

	/* reset fifo buffer */
	tmp = ioread8(base + ZXI2C_REG_HCR);
	iowrite8(tmp | ZXI2C_HCR_RST_FIFO, base + ZXI2C_REG_HCR);

	/* set xfer len */
	priv->xfer_len = min_t(u16, msg->len - i2c->xfered_len, ZXI2C_FIFO_SIZE);
	if (read) {
		iowrite8(priv->xfer_len - 1, base + ZXI2C_REG_HRLR);
	} else {
		iowrite8(priv->xfer_len - 1, base + ZXI2C_REG_HTLR);
		/* set write data */
		for (i = 0; i < priv->xfer_len; i++)
			iowrite8(msg->buf[i2c->xfered_len + i], base + ZXI2C_REG_HTDR);
	}

	/* prepare to stop transmission */
	if (priv->hrv && msg->len == (i2c->xfered_len + priv->xfer_len)) {
		tmp = ioread8(base + VIAI2C_REG_CR);
		tmp |= read ? VIAI2C_CR_RX_END : VIAI2C_CR_TX_END;
		iowrite8(tmp, base + VIAI2C_REG_CR);
	}

	u16 tcr_val = i2c->tcr;

	/* start transmission */
	tcr_val |= read ? VIAI2C_TCR_READ : 0;
	writew(tcr_val | msg->addr, base + VIAI2C_REG_TCR);

	return 0;
}

static int viai2c_fifo_irq_xfer(struct viai2c *i2c)
{
	u16 i;
	u8 tmp;
	struct i2c_msg *msg = i2c->msg;
	void __iomem *base = i2c->base;
	bool read = !!(msg->flags & I2C_M_RD);
	struct viai2c_zhaoxin *priv = i2c->pltfm_priv;

	/* get the received data */
	if (read)
		for (i = 0; i < priv->xfer_len; i++)
			msg->buf[i2c->xfered_len + i] = ioread8(base + ZXI2C_REG_HRDR);

	i2c->xfered_len += priv->xfer_len;
	if (i2c->xfered_len == msg->len)
		return 1;

	/* reset fifo buffer */
	tmp = ioread8(base + ZXI2C_REG_HCR);
	iowrite8(tmp | ZXI2C_HCR_RST_FIFO, base + ZXI2C_REG_HCR);

	/* set xfer len */
	priv->xfer_len = min_t(u16, msg->len - i2c->xfered_len, ZXI2C_FIFO_SIZE);
	if (read) {
		iowrite8(priv->xfer_len - 1, base + ZXI2C_REG_HRLR);
	} else {
		iowrite8(priv->xfer_len - 1, base + ZXI2C_REG_HTLR);
		/* set write data */
		for (i = 0; i < priv->xfer_len; i++)
			iowrite8(msg->buf[i2c->xfered_len + i], base + ZXI2C_REG_HTDR);
	}

	/* prepare to stop transmission */
	if (priv->hrv && msg->len == (i2c->xfered_len + priv->xfer_len)) {
		tmp = ioread8(base + VIAI2C_REG_CR);
		tmp |= read ? VIAI2C_CR_RX_END : VIAI2C_CR_TX_END;
		iowrite8(tmp, base + VIAI2C_REG_CR);
	}

	/* continue transmission */
	tmp = ioread8(base + VIAI2C_REG_CR);
	iowrite8(tmp |= VIAI2C_CR_CPU_RDY, base + VIAI2C_REG_CR);

Annotation

Implementation Notes