コード例 #1
0
ファイル: msm_i2c.c プロジェクト: sndnvaps/HTC-leo-cLK
static enum handler_return msm_i2c_isr(void *arg) {
	enter_critical_section();
	msm_i2c_interrupt_locked();
	exit_critical_section();
	
	return INT_RESCHEDULE;
}
コード例 #2
0
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;
}
コード例 #3
0
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;
}
コード例 #4
0
ファイル: msm_i2c.c プロジェクト: sndnvaps/HTC-leo-cLK
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;
}