コード例 #1
0
ファイル: i2c-sh_mobile.c プロジェクト: johnny/CobraDroidBeta
static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
{
	struct platform_device *dev = dev_id;
	struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
	unsigned char sr;
	int wakeup;

	sr = ioread8(ICSR(pd));
	pd->sr |= sr; /* remember state */

	dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr,
	       (pd->msg->flags & I2C_M_RD) ? "read" : "write",
	       pd->pos, pd->msg->len);

	if (sr & (ICSR_AL | ICSR_TACK)) {
		/* don't interrupt transaction - continue to issue stop */
		iowrite8(sr & ~(ICSR_AL | ICSR_TACK), ICSR(pd));
		wakeup = 0;
	} else if (pd->msg->flags & I2C_M_RD)
		wakeup = sh_mobile_i2c_isr_rx(pd);
	else
		wakeup = sh_mobile_i2c_isr_tx(pd);

	if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */
		iowrite8(sr & ~ICSR_WAIT, ICSR(pd));

	if (wakeup) {
		pd->sr |= SW_DONE;
		wake_up(&pd->wait);
	}

	return IRQ_HANDLED;
}
コード例 #2
0
ファイル: i2c-sh_mobile.c プロジェクト: johnny/CobraDroidBeta
static void deactivate_ch(struct sh_mobile_i2c_data *pd)
{
	/* Clear/disable interrupts */
	iowrite8(0, ICSR(pd));
	iowrite8(0, ICIC(pd));

	/* Disable channel */
	iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));

	/* Disable clock */
	clk_disable(pd->clk);
}
コード例 #3
0
static void deactivate_ch(struct sh_mobile_i2c_data *pd)
{
	/* Clear/disable interrupts */
	iowrite8(0, ICSR(pd));
	iowrite8(0, ICIC(pd));

	/* Disable channel */
	iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));

	/* Disable clock and mark device as idle */
	clk_disable(pd->clk);
	pm_runtime_put_sync(pd->dev);
}
コード例 #4
0
ファイル: i2c-sh_mobile.c プロジェクト: johnny/CobraDroidBeta
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;
	u_int8_t val;
	int i, k, retry_count;

	activate_ch(pd);

	/* Process all messages */
	for (i = 0; i < num; i++) {
		msg = &msgs[i];

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

		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");

		retry_count = 1000;
again:
		val = ioread8(ICSR(pd));

		dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr);

		/* the interrupt handler may wake us up before the
		 * transfer is finished, so poll the hardware
		 * until we're done.
		 */
		if (val & ICSR_BUSY) {
			udelay(10);
			if (retry_count--)
				goto again;

			err = -EIO;
			dev_err(pd->dev, "Polling timed out\n");
			break;
		}

		/* handle missing acknowledge and arbitration lost */
		if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) {
			err = -EIO;
			break;
		}
	}

	deactivate_ch(pd);

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