I2C總線協(xié)議學(xué)習(xí)筆記
- static int mpc_write(struct mpc_i2c *i2c, int target,
const u8 * data, int length, int restart) - {
int i; unsigned timeout = i2c->adap.timeout; u32 flags = restart ? CCR_RSTA : 0; //以防萬一,保證I2C模塊使能起來 if (!restart) writeccr(i2c, CCR_MEN); //寫了I2CCR[CCR_MSTA],觸發(fā)CPU發(fā)起START信號(hào) writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags); //CPU發(fā)送一個(gè)字節(jié),slave I2C addr和0 (寫操作bit) writeb((target << 1), i2c->base + MPC_I2C_DR); if (i2c_wait(i2c, timeout, 1) < 0) //等待slave 發(fā)ACK return -1; for (i = 0; i < length; i++) { writeb(data[i], i2c->base + MPC_I2C_DR); //CPU接著發(fā)數(shù)據(jù),包括reg addr和data if (i2c_wait(i2c, timeout, 1) < 0) //等待slave 發(fā)ACK return -1; } return 0; - }
- static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
- {
unsigned long orig_jiffies = jiffies; u32 x; int result = 0; if (i2c->irq == 0) { //循環(huán)讀I2CSR,直到I2CSR[MIF]置1 while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) { schedule(); if (time_after(jiffies, orig_jiffies + timeout)) { pr_debug("I2C: timeoutn"); writeccr(i2c, 0); result = -EIO; break; } } x = readb(i2c->base + MPC_I2C_SR); writeb(0, i2c->base + MPC_I2C_SR); } else { result = wait_event_interruptible_timeout(i2c->queue, (i2c->interrupt & CSR_MIF), timeout * HZ); if (unlikely(result < 0)) { pr_debug("I2C: wait interruptedn"); writeccr(i2c, 0); } else if (unlikely(!(i2c->interrupt & CSR_MIF))) { pr_debug("I2C: wait timeoutn"); writeccr(i2c, 0); result = -ETIMEDOUT; } x = i2c->interrupt; i2c->interrupt = 0; } if (result < 0) return result; if (!(x & CSR_MCF)) { pr_debug("I2C: unfinishedn"); return -EIO; } if (x & CSR_MAL) { //仲裁失敗 pr_debug("I2C: MALn"); return -EIO; } if (writing && (x & CSR_RXAK)) {//寫后沒收到ACK pr_debug("I2C: No RXAKn"); writeccr(i2c, CCR_MEN); return -EIO; } return 0; - }
- static int mpc_read(struct mpc_i2c *i2c, int target,
u8 * data, int length, int restart) - {
unsigned timeout = i2c->adap.timeout; int i; u32 flags = restart ? CCR_RSTA : 0; //以防萬一,保證I2C模塊使能 if (!restart) writeccr(i2c, CCR_MEN); //注意這里,再次把CCR_MSTA置1,再觸發(fā) START writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags); //CPU發(fā)送slave I2C addr和讀操作1 writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
if (i2c_wait(i2c, timeout, 1) < 0) return -1; if (length) { if (length == 1) writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK); else //為什么不置 TXAK writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA); readb(i2c->base + MPC_I2C_DR); } for (i = 0; i < length; i++) { if (i2c_wait(i2c, timeout, 0) < 0) return -1; //注意這里TXAK置1,表示CPU每收到1byte數(shù)據(jù)后,會(huì)發(fā)送ACK if (i == length - 2) writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK); //注意這里CCR_MSTA [1->0] CPU會(huì)觸發(fā)STOP if (i == length - 1) writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK); data[i] = readb(i2c->base + MPC_I2C_DR); } return length; - }
評(píng)論