drivers/media/pci/ddbridge/ddbridge-i2c.c

Source file repositories/reference/linux-study-clean/drivers/media/pci/ddbridge/ddbridge-i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/media/pci/ddbridge/ddbridge-i2c.c
Extension
.c
Size
5420 bytes
Lines
226
Domain
Driver Families
Bucket
drivers/media
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

if (i2c->link) {
				u32 listat = ddbreadl(dev,
					DDB_LINK_TAG(i2c->link) |
					INTERRUPT_STATUS);

				dev_err(dev->dev, "DDBridge link %u IRS %08x\n",
					i2c->link, listat);
			}
			if (istat & 1) {
				ddbwritel(dev, istat & 1, INTERRUPT_ACK);
			} else {
				u32 mon = ddbreadl(dev,
					i2c->regs + I2C_MONITOR);

				dev_err(dev->dev, "I2C cmd=%08x mon=%08x\n",
					val, mon);
			}
		}
		return -EIO;
	}
	val &= 0x70000;
	if (val == 0x20000)
		dev_err(dev->dev, "I2C bus error\n");
	if (val)
		return -EIO;
	return 0;
}

static int ddb_i2c_master_xfer(struct i2c_adapter *adapter,
			       struct i2c_msg msg[], int num)
{
	struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter);
	struct ddb *dev = i2c->dev;
	u8 addr = 0;

	addr = msg[0].addr;
	if (msg[0].len > i2c->bsize)
		return -EIO;
	switch (num) {
	case 1:
		if (msg[0].flags & I2C_M_RD) {
			ddbwritel(dev, msg[0].len << 16,
				  i2c->regs + I2C_TASKLENGTH);
			if (ddb_i2c_cmd(i2c, addr, 3))
				break;
			ddbcpyfrom(dev, msg[0].buf,
				   i2c->rbuf, msg[0].len);
			return num;
		}
		ddbcpyto(dev, i2c->wbuf, msg[0].buf, msg[0].len);
		ddbwritel(dev, msg[0].len, i2c->regs + I2C_TASKLENGTH);
		if (ddb_i2c_cmd(i2c, addr, 2))
			break;
		return num;
	case 2:
		if ((msg[0].flags & I2C_M_RD) == I2C_M_RD)
			break;
		if ((msg[1].flags & I2C_M_RD) != I2C_M_RD)
			break;
		if (msg[1].len > i2c->bsize)
			break;
		ddbcpyto(dev, i2c->wbuf, msg[0].buf, msg[0].len);
		ddbwritel(dev, msg[0].len | (msg[1].len << 16),
			  i2c->regs + I2C_TASKLENGTH);
		if (ddb_i2c_cmd(i2c, addr, 1))
			break;
		ddbcpyfrom(dev, msg[1].buf,
			   i2c->rbuf,
			   msg[1].len);
		return num;
	default:
		break;
	}
	return -EIO;
}

static u32 ddb_i2c_functionality(struct i2c_adapter *adap)
{
	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}

static const struct i2c_algorithm ddb_i2c_algo = {
	.master_xfer   = ddb_i2c_master_xfer,
	.functionality = ddb_i2c_functionality,
};

void ddb_i2c_release(struct ddb *dev)
{
	int i;
	struct ddb_i2c *i2c;

Annotation

Implementation Notes