/* set SDA and SCL as GPIO */ #define DAVINCI_I2C_FUNC_PFUNC0 BIT(0)
/* set SCL as output when used as GPIO*/ #define DAVINCI_I2C_DIR_PDIR0 BIT(0) /* set SDA as output when used as GPIO*/ #define DAVINCI_I2C_DIR_PDIR1 BIT(1)
staticinlinevoid davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev, int val)
{
u16 w;
w = davinci_i2c_read_reg(i2c_dev, DAVINCI_I2C_MDR_REG); if (!val) /* put I2C into reset */
w &= ~DAVINCI_I2C_MDR_IRS; else/* take I2C out of reset */
w |= DAVINCI_I2C_MDR_IRS;
do { if (!(davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) & DAVINCI_I2C_STR_BB)) return0;
schedule_timeout_uninterruptible(1);
} while (time_before_eq(jiffies, timeout));
dev_warn(dev->dev, "timeout waiting for bus ready\n");
i2c_recover_bus(&dev->adapter);
/* Take I2C out of reset and configure it as controller */
flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST;
if (msg->flags & I2C_M_TEN)
flag |= DAVINCI_I2C_MDR_XA; if (!(msg->flags & I2C_M_RD))
flag |= DAVINCI_I2C_MDR_TRX; if (msg->len == 0)
flag |= DAVINCI_I2C_MDR_RM;
/* Enable receive or transmit interrupts */
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); if (msg->flags & I2C_M_RD)
w |= DAVINCI_I2C_IMR_RRDY; else
w |= DAVINCI_I2C_IMR_XRDY;
davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w);
/* Set STT to begin transmit now DXR is loaded */
flag |= DAVINCI_I2C_MDR_STT; if (stop && msg->len != 0)
flag |= DAVINCI_I2C_MDR_STP;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
time_left = wait_for_completion_timeout(&dev->cmd_complete,
dev->adapter.timeout); if (!time_left) {
i2c_recover_bus(adap);
dev->buf_len = 0; return -ETIMEDOUT;
} if (dev->buf_len) { /* This should be 0 if all bytes were transferred *ordev->cmd_errdenotesanerror.
*/
dev_err(dev->dev, "abnormal termination buf_len=%zu\n",
dev->buf_len);
dev->terminate = 1;
wmb();
dev->buf_len = 0; return -EREMOTEIO;
}
/* no error */ if (likely(!dev->cmd_err)) return msg->len;
/* We have an error */ if (dev->cmd_err & DAVINCI_I2C_STR_AL) {
i2c_davinci_init(dev); return -EIO;
}
if (dev->cmd_err & DAVINCI_I2C_STR_NACK) { if (msg->flags & I2C_M_IGNORE_NAK) return msg->len;
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
w |= DAVINCI_I2C_MDR_STP;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); return -EREMOTEIO;
} return -EIO;
}
/* *Preparecontrollerforatransactionandcalli2c_davinci_xfer_msg
*/ staticint
i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{ struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); int i; int ret;
staticvoid terminate_read(struct davinci_i2c_dev *dev)
{
u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
w |= DAVINCI_I2C_MDR_NACK;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
/* Throw away data */
davinci_i2c_read_reg(dev, DAVINCI_I2C_DRR_REG); if (!dev->terminate)
dev_err(dev->dev, "RDR IRQ while no data requested\n");
} staticvoid terminate_write(struct davinci_i2c_dev *dev)
{
u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
w |= DAVINCI_I2C_MDR_RM | DAVINCI_I2C_MDR_STP;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
if (!dev->terminate)
dev_dbg(dev->dev, "TDR IRQ while no data to send\n");
}
if (pm_runtime_suspended(dev->dev)) return IRQ_NONE;
while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) {
dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat); if (count++ == 100) {
dev_warn(dev->dev, "Too much work in one IRQ\n"); break;
}
switch (stat) { case DAVINCI_I2C_IVR_AL: /* Arbitration lost, must retry */
dev->cmd_err |= DAVINCI_I2C_STR_AL;
dev->buf_len = 0;
complete(&dev->cmd_complete); break;
case DAVINCI_I2C_IVR_NACK:
dev->cmd_err |= DAVINCI_I2C_STR_NACK;
dev->buf_len = 0;
complete(&dev->cmd_complete); break;
case DAVINCI_I2C_IVR_ARDY:
davinci_i2c_write_reg(dev,
DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_ARDY); if (((dev->buf_len == 0) && (dev->stop != 0)) ||
(dev->cmd_err & DAVINCI_I2C_STR_NACK)) {
w = davinci_i2c_read_reg(dev,
DAVINCI_I2C_MDR_REG);
w |= DAVINCI_I2C_MDR_STP;
davinci_i2c_write_reg(dev,
DAVINCI_I2C_MDR_REG, w);
}
complete(&dev->cmd_complete); break;
case DAVINCI_I2C_IVR_RDR: if (dev->buf_len) {
*dev->buf++ =
davinci_i2c_read_reg(dev,
DAVINCI_I2C_DRR_REG);
dev->buf_len--; if (dev->buf_len) continue;
davinci_i2c_write_reg(dev,
DAVINCI_I2C_STR_REG,
DAVINCI_I2C_IMR_RRDY);
} else { /* signal can terminate transfer */
terminate_read(dev);
} break;
case DAVINCI_I2C_IVR_XRDY: if (dev->buf_len) {
davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG,
*dev->buf++);
dev->buf_len--; if (dev->buf_len) continue;
w = davinci_i2c_read_reg(dev,
DAVINCI_I2C_IMR_REG);
w &= ~DAVINCI_I2C_IMR_XRDY;
davinci_i2c_write_reg(dev,
DAVINCI_I2C_IMR_REG,
w);
} else { /* signal can terminate transfer */
terminate_write(dev);
} break;
case DAVINCI_I2C_IVR_SCD:
davinci_i2c_write_reg(dev,
DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_SCD);
complete(&dev->cmd_complete); break;
case DAVINCI_I2C_IVR_AAS:
dev_dbg(dev->dev, "Address as target interrupt\n"); break;
default:
dev_warn(dev->dev, "Unrecognized irq stat %d\n", stat); break;
}
}
/* I2C may be needed to bring up other drivers */ staticint __init davinci_i2c_init_driver(void)
{ return platform_driver_register(&davinci_i2c_driver);
}
subsys_initcall(davinci_i2c_init_driver);
MODULE_AUTHOR("Texas Instruments India");
MODULE_DESCRIPTION("TI DaVinci I2C bus adapter");
MODULE_LICENSE("GPL");
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.23Bemerkung:
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.