static void xiic_clear_rx_fifo(struct xiic_i2c *i2c) { u8 sr; for (sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET); !(sr & XIIC_SR_RX_FIFO_EMPTY_MASK); sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)) xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET); }
static void xiic_start_send(struct xiic_i2c *i2c) { struct i2c_msg *msg = i2c->tx_msg; xiic_irq_clr(i2c, XIIC_INTR_TX_ERROR_MASK); dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d", __func__, msg, msg->len); dev_dbg(i2c->adap.dev.parent, "%s entry, ISR: 0x%x, CR: 0x%x\n", __func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET), xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); if (!(msg->flags & I2C_M_NOSTART)) { /* write the address */ u16 data = ((msg->addr << 1) & 0xfe) | XIIC_WRITE_OPERATION | XIIC_TX_DYN_START_MASK; if ((i2c->nmsgs == 1) && msg->len == 0) /* no data and last message -> add STOP */ data |= XIIC_TX_DYN_STOP_MASK; xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); } xiic_fill_tx_fifo(i2c); /* Clear any pending Tx empty, Tx Error and then enable them. */ xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_BNB_MASK); }
static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { struct xiic_i2c *i2c = i2c_get_adapdata(adap); int err; dev_dbg(adap->dev.parent, "%s entry SR: 0x%x\n", __func__, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)); err = xiic_busy(i2c); if (err) return err; i2c->tx_msg = msgs; i2c->nmsgs = num; xiic_start_xfer(i2c); if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || (i2c->state == STATE_DONE), HZ)) return (i2c->state == STATE_DONE) ? num : -EIO; else { i2c->tx_msg = NULL; i2c->rx_msg = NULL; i2c->nmsgs = 0; return -ETIMEDOUT; } }
static void xiic_deinit(struct xiic_i2c *i2c) { u8 cr; xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); /* Disable IIC Device. */ cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET); xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_ENABLE_DEVICE_MASK); }
static void xiic_read_rx(struct xiic_i2c *i2c) { u8 bytes_in_fifo; int i; bytes_in_fifo = xiic_getreg8(i2c, XIIC_RFO_REG_OFFSET) + 1; dev_dbg(i2c->adap.dev.parent, "%s entry, bytes in fifo: %d, msg: %d, SR: 0x%x, CR: 0x%x\n", __func__, bytes_in_fifo, xiic_rx_space(i2c), xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); if (bytes_in_fifo > xiic_rx_space(i2c)) bytes_in_fifo = xiic_rx_space(i2c); for (i = 0; i < bytes_in_fifo; i++) i2c->rx_msg->buf[i2c->rx_pos++] = xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET); xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, (xiic_rx_space(i2c) > IIC_RX_FIFO_DEPTH) ? IIC_RX_FIFO_DEPTH - 1 : xiic_rx_space(i2c) - 1); }
static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { struct xiic_i2c *i2c = i2c_get_adapdata(adap); int err; dev_dbg(adap->dev.parent, "%s entry SR: 0x%x\n", __func__, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)); err = pm_runtime_get_sync(i2c->dev); if (err < 0) return err; err = xiic_busy(i2c); if (err) goto out; i2c->tx_msg = msgs; i2c->nmsgs = num; xiic_start_xfer(i2c); if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || (i2c->state == STATE_DONE), HZ)) { err = (i2c->state == STATE_DONE) ? num : -EIO; goto out; } else { i2c->tx_msg = NULL; i2c->rx_msg = NULL; i2c->nmsgs = 0; err = -ETIMEDOUT; goto out; } out: pm_runtime_mark_last_busy(i2c->dev); pm_runtime_put_autosuspend(i2c->dev); return err; }
static int xiic_bus_busy(struct xiic_i2c *i2c) { u8 sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET); return (sr & XIIC_SR_BUS_BUSY_MASK) ? -EBUSY : 0; }
static irqreturn_t xiic_process(int irq, void *dev_id) { struct xiic_i2c *i2c = dev_id; u32 pend, isr, ier; u32 clr = 0; /* Get the interrupt Status from the IPIF. There is no clearing of * interrupts in the IPIF. Interrupts must be cleared at the source. * To find which interrupts are pending; AND interrupts pending with * interrupts masked. */ mutex_lock(&i2c->lock); isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); pend = isr & ier; dev_dbg(i2c->adap.dev.parent, "%s: IER: 0x%x, ISR: 0x%x, pend: 0x%x\n", __func__, ier, isr, pend); dev_dbg(i2c->adap.dev.parent, "%s: SR: 0x%x, msg: %p, nmsgs: %d\n", __func__, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), i2c->tx_msg, i2c->nmsgs); /* Service requesting interrupt */ if ((pend & XIIC_INTR_ARB_LOST_MASK) || ((pend & XIIC_INTR_TX_ERROR_MASK) && !(pend & XIIC_INTR_RX_FULL_MASK))) { /* bus arbritration lost, or... * Transmit error _OR_ RX completed * if this happens when RX_FULL is not set * this is probably a TX error */ dev_dbg(i2c->adap.dev.parent, "%s error\n", __func__); /* dynamic mode seem to suffer from problems if we just flushes * fifos and the next message is a TX with len 0 (only addr) * reset the IP instead of just flush fifos */ xiic_reinit(i2c); if (i2c->rx_msg) xiic_wakeup(i2c, STATE_ERROR); if (i2c->tx_msg) xiic_wakeup(i2c, STATE_ERROR); } if (pend & XIIC_INTR_RX_FULL_MASK) { /* Receive register/FIFO is full */ clr |= XIIC_INTR_RX_FULL_MASK; if (!i2c->rx_msg) { dev_dbg(i2c->adap.dev.parent, "%s unexpexted RX IRQ\n", __func__); xiic_clear_rx_fifo(i2c); goto out; } xiic_read_rx(i2c); if (xiic_rx_space(i2c) == 0) { /* this is the last part of the message */ i2c->rx_msg = NULL; /* also clear TX error if there (RX complete) */ clr |= (isr & XIIC_INTR_TX_ERROR_MASK); dev_dbg(i2c->adap.dev.parent, "%s end of message, nmsgs: %d\n", __func__, i2c->nmsgs); /* send next message if this wasn't the last, * otherwise the transfer will be finialise when * receiving the bus not busy interrupt */ if (i2c->nmsgs > 1) { i2c->nmsgs--; i2c->tx_msg++; dev_dbg(i2c->adap.dev.parent, "%s will start next...\n", __func__); __xiic_start_xfer(i2c); } } } if (pend & XIIC_INTR_BNB_MASK) { /* IIC bus has transitioned to not busy */ clr |= XIIC_INTR_BNB_MASK; /* The bus is not busy, disable BusNotBusy interrupt */ xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK); if (!i2c->tx_msg) goto out; if ((i2c->nmsgs == 1) && !i2c->rx_msg && xiic_tx_space(i2c) == 0) xiic_wakeup(i2c, STATE_DONE); else xiic_wakeup(i2c, STATE_ERROR); } if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) { /* Transmit register/FIFO is empty or ½ empty */ clr |= (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)); if (!i2c->tx_msg) { dev_dbg(i2c->adap.dev.parent, "%s unexpexted TX IRQ\n", __func__); goto out; } xiic_fill_tx_fifo(i2c); /* current message sent and there is space in the fifo */ if (!xiic_tx_space(i2c) && xiic_tx_fifo_space(i2c) >= 2) { dev_dbg(i2c->adap.dev.parent, "%s end of message sent, nmsgs: %d\n", __func__, i2c->nmsgs); if (i2c->nmsgs > 1) { i2c->nmsgs--; i2c->tx_msg++; __xiic_start_xfer(i2c); } else { xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); dev_dbg(i2c->adap.dev.parent, "%s Got TX IRQ but no more to do...\n", __func__); } } else if (!xiic_tx_space(i2c) && (i2c->nmsgs == 1)) /* current frame is sent and is last, * make sure to disable tx half */ xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); } out: dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr); xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr); mutex_unlock(&i2c->lock); return IRQ_HANDLED; }
static int xiic_tx_fifo_space(struct xiic_i2c *i2c) { /* return the actual space left in the FIFO */ return IIC_TX_FIFO_DEPTH - xiic_getreg8(i2c, XIIC_TFO_REG_OFFSET) - 1; }