static enum handler_return msm_i2c_isr(void *arg) { enter_critical_section(); msm_i2c_interrupt_locked(); exit_critical_section(); return INT_RESCHEDULE; }
static irqreturn_t msm_i2c_interrupt(int irq, void *devid) { struct msm_i2c_dev *dev = devid; spin_lock(&dev->lock); msm_i2c_interrupt_locked(dev); spin_unlock(&dev->lock); return IRQ_HANDLED; }
static int msm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { DECLARE_COMPLETION_ONSTACK(complete); struct msm_i2c_dev *dev = i2c_get_adapdata(adap); int ret; long timeout; unsigned long flags; /* * If there is an i2c_xfer after driver has been suspended, * grab wakelock to abort suspend. */ if (dev->is_suspended) wake_lock(&dev->wakelock); clk_enable(dev->clk); enable_irq(dev->irq); ret = msm_i2c_poll_notbusy(dev, 1); if (ret) { dev_err(dev->dev, "Still busy in starting xfer(%02X)\n", msgs->addr); if (!dev->skip_recover) { ret = msm_i2c_recover_bus_busy(dev); if (ret) goto err; } } spin_lock_irqsave(&dev->lock, flags); if (dev->flush_cnt) { dev_warn(dev->dev, "%d unrequested bytes read\n", dev->flush_cnt); } dev->msg = msgs; dev->rem = num; dev->pos = -1; dev->ret = num; dev->need_flush = false; dev->flush_cnt = 0; dev->cnt = msgs->len; dev->complete = &complete; msm_i2c_interrupt_locked(dev); spin_unlock_irqrestore(&dev->lock, flags); /* * Now that we've setup the xfer, the ISR will transfer the data * and wake us up with dev->err set if there was an error */ timeout = wait_for_completion_timeout(&complete, HZ); if (msm_i2c_poll_notbusy(dev, 0)) /* Read may not have stopped in time */ dev_err(dev->dev, "Still busy after xfer completion (%02X)\n", msgs->addr); spin_lock_irqsave(&dev->lock, flags); if (dev->flush_cnt) { dev_warn(dev->dev, "%d unrequested bytes read\n", dev->flush_cnt); } ret = dev->ret; dev->complete = NULL; dev->msg = NULL; dev->rem = 0; dev->pos = 0; dev->ret = 0; dev->flush_cnt = 0; dev->cnt = 0; spin_unlock_irqrestore(&dev->lock, flags); if (!timeout) { dev_err(dev->dev, "Transaction timed out\n"); ret = -ETIMEDOUT; } if (ret < 0) { dev_err(dev->dev, "Error during data xfer (%d) (%02X)\n", ret, msgs->addr); if (!dev->skip_recover) msm_i2c_recover_bus_busy(dev); } err: disable_irq(dev->irq); clk_disable(dev->clk); if (dev->is_suspended) wake_unlock(&dev->wakelock); return ret; }
int msm_i2c_xfer(struct i2c_msg msgs[], int num) { int ret, ret_wait; clk_enable(dev.pdata->clk_nr); unmask_interrupt(dev.pdata->irq_nr); ret = msm_i2c_poll_notbusy(1); if (ret) { ret = msm_i2c_recover_bus_busy(); if (ret) goto err; } enter_critical_section(); if (dev.flush_cnt) { I2C_DBG(DEBUGLEVEL, "%d unrequested bytes read\n", dev.flush_cnt); } dev.msg = msgs; dev.rem = num; dev.pos = -1; dev.ret = num; dev.need_flush = false; dev.flush_cnt = 0; dev.cnt = msgs->len; msm_i2c_interrupt_locked(); exit_critical_section(); /* * Now that we've setup the xfer, the ISR will transfer the data * and wake us up with dev.err set if there was an error */ ret_wait = msm_i2c_poll_notbusy(0); /* Read may not have stopped in time */ enter_critical_section(); if (dev.flush_cnt) { I2C_DBG(DEBUGLEVEL, "%d unrequested bytes read\n", dev.flush_cnt); } ret = dev.ret; dev.msg = NULL; dev.rem = 0; dev.pos = 0; dev.ret = 0; dev.flush_cnt = 0; dev.cnt = 0; exit_critical_section(); if (ret_wait) { I2C_DBG(DEBUGLEVEL, "Still busy after xfer completion\n"); ret_wait = msm_i2c_recover_bus_busy(); if (ret_wait) goto err; } if (timeout == ERR_TIMED_OUT) { I2C_DBG(DEBUGLEVEL, "Transaction timed out\n"); ret = ERR_TIMED_OUT; } if (ret < 0) { I2C_ERR("Error during data xfer (%d)\n", ret); msm_i2c_recover_bus_busy(); } /* if (timeout == ERR_TIMED_OUT) { I2C_DBG(DEBUGLEVEL, "Transaction timed out\n"); ret = 2; msm_i2c_recover_bus_busy(); } if (timeout == ERR_TIMED_OUT) { I2C_DBG(DEBUGLEVEL, "Transaction timed out\n"); ret = ERR_TIMED_OUT; } if (ret < 0) { I2C_ERR("Error during data xfer (%d)\n", ret); msm_i2c_recover_bus_busy(); } */ err: mask_interrupt(dev.pdata->irq_nr); clk_disable(dev.pdata->clk_nr); return ret; }