drivers/i2c/busses/i2c-pca-platform.c

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

File Facts

System
Linux kernel
Corpus path
drivers/i2c/busses/i2c-pca-platform.c
Extension
.c
Size
5934 bytes
Lines
253
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 i2c_pca_pf_data {
	void __iomem			*reg_base;
	int				irq;	/* if 0, use polling */
	struct gpio_desc		*gpio;
	wait_queue_head_t		wait;
	struct i2c_adapter		adap;
	struct i2c_algo_pca_data	algo_data;
};

/* Read/Write functions for different register alignments */

static int i2c_pca_pf_readbyte8(void *pd, int reg)
{
	struct i2c_pca_pf_data *i2c = pd;
	return ioread8(i2c->reg_base + reg);
}

static int i2c_pca_pf_readbyte16(void *pd, int reg)
{
	struct i2c_pca_pf_data *i2c = pd;
	return ioread8(i2c->reg_base + reg * 2);
}

static int i2c_pca_pf_readbyte32(void *pd, int reg)
{
	struct i2c_pca_pf_data *i2c = pd;
	return ioread8(i2c->reg_base + reg * 4);
}

static void i2c_pca_pf_writebyte8(void *pd, int reg, int val)
{
	struct i2c_pca_pf_data *i2c = pd;
	iowrite8(val, i2c->reg_base + reg);
}

static void i2c_pca_pf_writebyte16(void *pd, int reg, int val)
{
	struct i2c_pca_pf_data *i2c = pd;
	iowrite8(val, i2c->reg_base + reg * 2);
}

static void i2c_pca_pf_writebyte32(void *pd, int reg, int val)
{
	struct i2c_pca_pf_data *i2c = pd;
	iowrite8(val, i2c->reg_base + reg * 4);
}


static int i2c_pca_pf_waitforcompletion(void *pd)
{
	struct i2c_pca_pf_data *i2c = pd;
	unsigned long timeout;
	long ret;

	if (i2c->irq) {
		ret = wait_event_timeout(i2c->wait,
			i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
			& I2C_PCA_CON_SI, i2c->adap.timeout);
	} else {
		/* Do polling */
		timeout = jiffies + i2c->adap.timeout;
		do {
			ret = time_before(jiffies, timeout);
			if (i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
					& I2C_PCA_CON_SI)
				break;
			udelay(100);
		} while (ret);
	}

	return ret > 0;
}

static void i2c_pca_pf_dummyreset(void *pd)
{
	struct i2c_pca_pf_data *i2c = pd;

	dev_warn(&i2c->adap.dev, "No reset-pin found. Chip may get stuck!\n");
}

static void i2c_pca_pf_resetchip(void *pd)
{
	struct i2c_pca_pf_data *i2c = pd;

	gpiod_set_value(i2c->gpio, 1);
	ndelay(100);
	gpiod_set_value(i2c->gpio, 0);
}

static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id)

Annotation

Implementation Notes