drivers/i2c/busses/i2c-octeon-core.c

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

File Facts

System
Linux kernel
Corpus path
drivers/i2c/busses/i2c-octeon-core.c
Extension
.c
Size
25934 bytes
Lines
1003
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

octeon_i2c_test_iflg(i2c)) {
		dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n");
		i2c->broken_irq_mode = true;
		return 0;
	}

	if (!time_left)
		return -ETIMEDOUT;

	return 0;
}

static bool octeon_i2c_hlc_test_valid(struct octeon_i2c *i2c)
{
	return (__raw_readq(i2c->twsi_base + OCTEON_REG_SW_TWSI(i2c)) & SW_TWSI_V) == 0;
}

static void octeon_i2c_hlc_int_clear(struct octeon_i2c *i2c)
{
	/* clear ST/TS events, listen for neither */
	octeon_i2c_write_int(i2c, TWSI_INT_ST_INT | TWSI_INT_TS_INT);
}

/*
 * Cleanup low-level state & enable high-level controller.
 */
static void octeon_i2c_hlc_enable(struct octeon_i2c *i2c)
{
	int try = 0;
	u64 val;

	if (i2c->hlc_enabled)
		return;
	i2c->hlc_enabled = true;

	while (1) {
		val = octeon_i2c_ctl_read(i2c);
		if (!(val & (TWSI_CTL_STA | TWSI_CTL_STP)))
			break;

		/* clear IFLG event */
		if (val & TWSI_CTL_IFLG)
			octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);

		if (try++ > 100) {
			pr_err("%s: giving up\n", __func__);
			break;
		}

		/* spin until any start/stop has finished */
		udelay(10);
	}
	octeon_i2c_ctl_write(i2c, TWSI_CTL_CE | TWSI_CTL_AAK | TWSI_CTL_ENAB);
}

static void octeon_i2c_hlc_disable(struct octeon_i2c *i2c)
{
	if (!i2c->hlc_enabled)
		return;

	i2c->hlc_enabled = false;
	octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
}

static void octeon_i2c_block_enable(struct octeon_i2c *i2c)
{
	u64 mode;

	if (i2c->block_enabled || !OCTEON_REG_BLOCK_CTL(i2c))
		return;

	i2c->block_enabled = true;
	mode = __raw_readq(i2c->twsi_base + OCTEON_REG_MODE(i2c));
	mode |= TWSX_MODE_BLOCK_MODE;
	octeon_i2c_writeq_flush(mode, i2c->twsi_base + OCTEON_REG_MODE(i2c));
}

static void octeon_i2c_block_disable(struct octeon_i2c *i2c)
{
	u64 mode;

	if (!i2c->block_enabled || !OCTEON_REG_BLOCK_CTL(i2c))
		return;

	i2c->block_enabled = false;
	mode = __raw_readq(i2c->twsi_base + OCTEON_REG_MODE(i2c));
	mode &= ~TWSX_MODE_BLOCK_MODE;
	octeon_i2c_writeq_flush(mode, i2c->twsi_base + OCTEON_REG_MODE(i2c));
}

Annotation

Implementation Notes