Esempio n. 1
0
static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
			      struct i2c_msg *msgs,
			      int num)
{
	struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);
	struct i2c_msg	*msg;
	int err = 0;
	int i;
	long timeout;

	/* Wake up device and enable clock */
	pm_runtime_get_sync(pd->dev);

	/* Process all messages */
	for (i = 0; i < num; i++) {
		bool do_start = pd->send_stop || !i;
		msg = &msgs[i];
		pd->send_stop = i == num - 1 || msg->flags & I2C_M_STOP;
		pd->stop_after_dma = false;

		start_ch(pd, msg, do_start);

		if (do_start)
			i2c_op(pd, OP_START, 0);

		/* The interrupt handler takes care of the rest... */
		timeout = wait_event_timeout(pd->wait,
				       pd->sr & (ICSR_TACK | SW_DONE),
				       adapter->timeout);

		/* 'stop_after_dma' tells if DMA transfer was complete */
		i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg, pd->stop_after_dma);

		if (!timeout) {
			dev_err(pd->dev, "Transfer request timed out\n");
			if (pd->dma_direction != DMA_NONE)
				sh_mobile_i2c_cleanup_dma(pd);

			err = -ETIMEDOUT;
			break;
		}

		if (pd->send_stop)
			err = poll_busy(pd);
		else
			err = poll_dte(pd);
		if (err < 0)
			break;
	}

	/* Disable channel */
	iic_wr(pd, ICCR, ICCR_SCP);

	/* Disable clock and mark device as idle */
	pm_runtime_put_sync(pd->dev);

	return err ?: num;
}
Esempio n. 2
0
static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
			      struct i2c_msg *msgs,
			      int num)
{
	struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);
	struct i2c_msg	*msg;
	int err = 0;
	int i, k;

	activate_ch(pd);

	/* Process all messages */
	for (i = 0; i < num; i++) {
		bool do_start = pd->send_stop || !i;
		msg = &msgs[i];
		pd->send_stop = i == num - 1 || msg->flags & I2C_M_STOP;

		err = start_ch(pd, msg, do_start);
		if (err)
			break;

		if (do_start)
			i2c_op(pd, OP_START, 0);

		/* The interrupt handler takes care of the rest... */
		k = wait_event_timeout(pd->wait,
				       pd->sr & (ICSR_TACK | SW_DONE),
				       5 * HZ);
		if (!k) {
			dev_err(pd->dev, "Transfer request timed out\n");
			err = -ETIMEDOUT;
			break;
		}

		if (pd->send_stop)
			err = poll_busy(pd);
		else
			err = poll_dte(pd);
		if (err < 0)
			break;
	}

	deactivate_ch(pd);

	if (!err)
		err = num;
	return err;
}