drivers/i2c/busses/i2c-rcar.c

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

File Facts

System
Linux kernel
Corpus path
drivers/i2c/busses/i2c-rcar.c
Extension
.c
Size
34792 bytes
Lines
1292
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 rcar_i2c_priv {
	u32 flags;
	void __iomem *io;
	struct i2c_adapter adap;
	struct i2c_msg *msg;
	int msgs_left;
	struct clk *clk;

	wait_queue_head_t wait;

	int pos;
	u32 icccr;
	u16 schd;
	u16 scld;
	u8 smd;
	u8 recovery_icmcr;	/* protected by adapter lock */
	enum rcar_i2c_type devtype;
	struct i2c_client *slave;

	struct resource *res;
	struct dma_chan *dma_tx;
	struct dma_chan *dma_rx;
	struct scatterlist sg;
	enum dma_data_direction dma_direction;

	struct reset_control *rstc;
	int irq;

	struct i2c_client *host_notify_client;
	u8 slave_flags;
};

#define rcar_i2c_priv_to_dev(p)		((p)->adap.dev.parent)
#define rcar_i2c_is_recv(p)		((p)->msg->flags & I2C_M_RD)

static void rcar_i2c_write(struct rcar_i2c_priv *priv, int reg, u32 val)
{
	writel(val, priv->io + reg);
}

static u32 rcar_i2c_read(struct rcar_i2c_priv *priv, int reg)
{
	return readl(priv->io + reg);
}

static void rcar_i2c_clear_irq(struct rcar_i2c_priv *priv, u32 val)
{
	writel(~val & 0x7f, priv->io + ICMSR);
}

static int rcar_i2c_get_scl(struct i2c_adapter *adap)
{
	struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);

	return !!(rcar_i2c_read(priv, ICMCR) & FSCL);
}

static void rcar_i2c_set_scl(struct i2c_adapter *adap, int val)
{
	struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);

	if (val)
		priv->recovery_icmcr |= FSCL;
	else
		priv->recovery_icmcr &= ~FSCL;

	rcar_i2c_write(priv, ICMCR, priv->recovery_icmcr);
}

static void rcar_i2c_set_sda(struct i2c_adapter *adap, int val)
{
	struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);

	if (val)
		priv->recovery_icmcr |= FSDA;
	else
		priv->recovery_icmcr &= ~FSDA;

	rcar_i2c_write(priv, ICMCR, priv->recovery_icmcr);
}

static int rcar_i2c_get_bus_free(struct i2c_adapter *adap)
{
	struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);

	return !(rcar_i2c_read(priv, ICMCR) & FSDA);
}

static struct i2c_bus_recovery_info rcar_i2c_bri = {
	.get_scl = rcar_i2c_get_scl,

Annotation

Implementation Notes