Exemple #1
0
static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
{
	unsigned long timeout = jiffies + HZ;
	unsigned int offset;
	u32 mask, val;

	if (i2c_dev->hw->has_mst_fifo) {
		mask = I2C_MST_FIFO_CONTROL_TX_FLUSH |
		       I2C_MST_FIFO_CONTROL_RX_FLUSH;
		offset = I2C_MST_FIFO_CONTROL;
	} else {
		mask = I2C_FIFO_CONTROL_TX_FLUSH |
		       I2C_FIFO_CONTROL_RX_FLUSH;
		offset = I2C_FIFO_CONTROL;
	}

	val = i2c_readl(i2c_dev, offset);
	val |= mask;
	i2c_writel(i2c_dev, val, offset);

	while (i2c_readl(i2c_dev, offset) & mask) {
		if (time_after(jiffies, timeout)) {
			dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n");
			return -ETIMEDOUT;
		}
		msleep(1);
	}
	return 0;
}
Exemple #2
0
static void i2c_jz_reset(struct i2c_jz *i2c)
{
    i2c_readl(i2c, I2C_CTXABRT);
    i2c_readl(i2c, I2C_INTST);

    i2c_jz_disable(i2c);
    udelay(10);
    i2c_jz_enable(i2c);
}
static int i2c_lpc2k_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
	int msg_num)
{
	int ret, i;
	unsigned long stat;
	struct lpc2k_i2c *i2c = adap->algo_data;

	/* Check for bus idle condition */
	stat = i2c_readl(i2c->reg_base + LPC24XX_I2STAT);
	if (stat != m_i2c_idle) {
		/* Something is holding the bus, try to clear it */
		ret = i2c_lpc2k_clear_arb(i2c);
		if (ret) {
			dev_err(&i2c->adap.dev, "Bus is not idle\n");
			return ret;
		}
	}

	dev_dbg(&i2c->adap.dev, "Processing total messages = %d\n", msg_num);

	/* Process a single message at a time */
	for (i = 0; i < msg_num; i++) {
		/* Save message pointer and current message data index */
		i2c->msg = &msgs[i];
		i2c->msg_idx = 0;
		i2c->msg_status = -EBUSY;
		i2c->is_last = (i == (msg_num - 1));

		ret = lpc2k_process_msg(i2c, i);
		if (ret)
			return ret;
	}

	return msg_num;
}
static inline void rk30_i2c_clean_stop(struct rk30_i2c *i2c)
{
    unsigned int con = i2c_readl(i2c->regs + I2C_CON);

    con &= ~I2C_CON_STOP;
    i2c_writel(con, i2c->regs + I2C_CON);
}
static irqreturn_t rk30_i2c_irq(int irq, void *dev_id)
{
        struct rk30_i2c *i2c = dev_id;
        unsigned int ipd;

        spin_lock(&i2c->lock);
        ipd = i2c_readl(i2c->regs + I2C_IPD);
        if(i2c->state == STATE_IDLE){
                dev_info(i2c->dev, "Addr[0x%02x]  irq in STATE_IDLE, ipd = 0x%x\n", i2c->addr, ipd);
                i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
                goto out;
        }

#if defined(CONFIG_MFD_TRS65910)	//for trs65910 Trsilicon peter
	if(ipd & I2C_NAKRCVIPD && i2c->addr == 0x2d){
		i2c_writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD);
		goto out;
	}else  if(ipd & I2C_NAKRCVIPD){
		i2c_writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD);
		i2c->error = -EAGAIN;
		goto out;
	}
#else
	if(ipd & I2C_NAKRCVIPD){
		i2c_writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD);
		i2c->error = -EAGAIN;
		goto out;
	}
#endif
        rk30_i2c_irq_nextblock(i2c, ipd);
out:
        spin_unlock(&i2c->lock);
        return IRQ_HANDLED;
}
Exemple #6
0
static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
{
	u32 int_mask;

	int_mask = i2c_readl(i2c_dev, I2C_INT_MASK) | mask;
	i2c_writel(i2c_dev, int_mask, I2C_INT_MASK);
}
Exemple #7
0
static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
{
	unsigned long timeout = jiffies + HZ;
	u32 val = i2c_readl(i2c_dev, I2C_FIFO_CONTROL);
	val |= I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH;
	i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);

	while (i2c_readl(i2c_dev, I2C_FIFO_CONTROL) &
		(I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH)) {
		if (time_after(jiffies, timeout)) {
			dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n");
			return -ETIMEDOUT;
		}
		msleep(1);
	}
	return 0;
}
static inline void rk30_i2c_send_stop(struct rk30_i2c *i2c)
{
    unsigned int con = i2c_readl(i2c->regs + I2C_CON);

    con |= I2C_CON_STOP;
    if(con & I2C_CON_START)
        dev_warn(i2c->dev, "I2C_CON: start bit is set\n");

    i2c_writel(con, i2c->regs + I2C_CON);
}
static inline void rk30_set_rx_mode(struct rk30_i2c *i2c, unsigned int lastnak)
{
    unsigned long con = i2c_readl(i2c->regs + I2C_CON);

    con &= (~I2C_CON_MASK);
    con |= (I2C_CON_MOD_RX << 1);
    if(lastnak)
        con |= I2C_CON_LASTACK;
    i2c_writel(con, i2c->regs + I2C_CON);
}
Exemple #10
0
static int i2c_disable_clk(struct i2c_jz *i2c)
{
    int timeout = 10;
    int tmp = i2c_readl(i2c, I2C_STA);

    while ((tmp & I2C_STA_MSTACT) && (--timeout > 0)) {
        udelay(90);
        tmp = i2c_readl(i2c, I2C_STA);
    }
    if (timeout > 0) {
        clk_disable(i2c->clk);
        return 0;
    } else {
        dev_err(&(i2c->adap.dev),
                "--I2C disable clk timeout, I2C_STA = 0x%x\n", tmp);
        i2c_jz_reset(i2c);
        clk_disable(i2c->clk);
        return -ETIMEDOUT;
    }
}
static irqreturn_t i2c_lpc2k_handler(int this_irq, void *dev_id)
{
	struct lpc2k_i2c *i2c = (struct lpc2k_i2c *) dev_id;

	if (i2c_readl(i2c->reg_base + LPC24XX_I2CONSET) & LPC24XX_SI) {
		i2c_lpc2k_pump_msg(i2c);
		return IRQ_HANDLED;
	} else {
		return IRQ_NONE;
	}
}
Exemple #12
0
static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
{
	u32 val;
	int rx_fifo_avail;
	u8 *buf = i2c_dev->msg_buf;
	size_t buf_remaining = i2c_dev->msg_buf_remaining;
	int words_to_transfer;

	if (i2c_dev->hw->has_mst_fifo) {
		val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
		rx_fifo_avail = (val & I2C_MST_FIFO_STATUS_RX_MASK) >>
			I2C_MST_FIFO_STATUS_RX_SHIFT;
	} else {
Exemple #13
0
static int i2c_jz_disable(struct i2c_jz *i2c)
{
    int timeout = TIMEOUT;
    i2c_writel(i2c, I2C_ENB, 0);
    while ((i2c_readl(i2c, I2C_ENSTA) & I2C_ENB_I2CENB) && (--timeout > 0))
        msleep(1);

    if (timeout)
        return 0;

    printk("enable i2c%d failed\n", i2c->adap.nr);
    return -ETIMEDOUT;
}
static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
{
	u32 val;
	int rx_fifo_avail;
	int word;
	u8 *buf = i2c_dev->msg_buf;
	size_t buf_remaining = i2c_dev->msg_buf_remaining;
	int words_to_transfer;

	val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
	rx_fifo_avail = (val & I2C_FIFO_STATUS_RX_MASK) >>
		I2C_FIFO_STATUS_RX_SHIFT;

	words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
	if (words_to_transfer > rx_fifo_avail)
		words_to_transfer = rx_fifo_avail;

	for (word = 0; word < words_to_transfer; word++) {
		val = i2c_readl(i2c_dev, I2C_RX_FIFO);
		put_unaligned_le32(val, buf);
		buf += BYTES_PER_FIFO_WORD;
		buf_remaining -= BYTES_PER_FIFO_WORD;
		rx_fifo_avail--;
	}

	if (rx_fifo_avail > 0 && buf_remaining > 0) {
		int bytes_to_transfer = buf_remaining;
		int byte;
		BUG_ON(bytes_to_transfer > 3);
		val = i2c_readl(i2c_dev, I2C_RX_FIFO);
		for (byte = 0; byte < bytes_to_transfer; byte++) {
			*buf++ = val & 0xFF;
			val >>= 8;
		}
		buf_remaining -= bytes_to_transfer;
		rx_fifo_avail--;
	}
static void rk30_irq_read_get_data(struct rk30_i2c *i2c)
{
    unsigned int i, len = i2c->msg->len - i2c->msg_ptr;
    unsigned int p;

    len = (len >= 32)?32:len;

    for(i = 0; i < len; i++) {
        if(i%4 == 0)
            p = i2c_readl(i2c->regs + I2C_RXDATA_BASE +  (i/4) * 4);
        i2c->msg->buf[i2c->msg_ptr++] = (p >>((i%4) * 8)) & 0xff;
    }

    return;
}
static int i2c_lpc2k_clear_arb(struct lpc2k_i2c *i2c)
{
	long timeout = jiffies + HZ;
	int ret = 0;

	/*
	 * If the transfer needs to abort for some reason, we'll try to
	 * force a stop condition to clear any pending bus conditions
	 */
	i2c_writel(LPC24XX_STO, i2c->reg_base + LPC24XX_I2CONSET);

	/* Wait for status change */
	while (jiffies < timeout &&
		(i2c_readl(i2c->reg_base + LPC24XX_I2STAT) != m_i2c_idle))
		cpu_relax();

	if (i2c_readl(i2c->reg_base + LPC24XX_I2STAT) != m_i2c_idle) {
		/* Bus was not idle, try to reset adapter */
		i2c_lpc2k_reset(i2c);
		ret = -EBUSY;
	}

	return ret;
}
/* SCL Divisor = 8 * (CLKDIVL + CLKDIVH)
 * SCL = i2c_rate/ SCLK Divisor
*/
static void  rk30_i2c_set_clk(struct rk30_i2c *i2c, unsigned long scl_rate)
{
    unsigned long i2c_rate = clk_get_rate(i2c->clk);

    unsigned int div, divl, divh;

    if((scl_rate == i2c->scl_rate) && (i2c_rate == i2c->i2c_rate))
        return;
    i2c->i2c_rate = i2c_rate;
    i2c->scl_rate = scl_rate;
    div = rk30_ceil(i2c_rate, scl_rate * 8);
    divh = divl = rk30_ceil(div, 2);
    i2c_writel(I2C_CLKDIV_VAL(divl, divh), i2c->regs + I2C_CLKDIV);
    i2c_dbg(i2c->dev, "set clk(I2C_CLKDIV: 0x%08x)\n", i2c_readl(i2c->regs + I2C_CLKDIV));
    return;
}
void isp1301_update(struct reg_list *list)
{
        for (; list && list->name; list++) {
                //TRACE_MSG1(TCD, "list: %s", list->name);
                memmove(list->values + 1, list->values, sizeof(list->values) - sizeof(u32));
                switch(list->size) {
                case 1: 
                        list->values[0] = i2c_readb(list->reg); 
                        break;
                case 2: 
                        list->values[0] = i2c_readw(list->reg); 
                        break;
                case 4: 
                        list->values[0] = i2c_readl(list->reg); 
                        break;
                }
        }
}
static irqreturn_t rk30_i2c_irq(int irq, void *dev_id)
{
    struct rk30_i2c *i2c = dev_id;
    unsigned int ipd;

    spin_lock(&i2c->lock);
    ipd = i2c_readl(i2c->regs + I2C_IPD);
    if(i2c->state == STATE_IDLE) {
        dev_info(i2c->dev, "Addr[0x%02x]  irq in STATE_IDLE, ipd = 0x%x\n", i2c->addr, ipd);
        i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
        goto out;
    }

    if(ipd & I2C_NAKRCVIPD) {
        i2c_writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD);
        i2c->error = -EAGAIN;
        goto out;
    }
    rk30_i2c_irq_nextblock(i2c, ipd);
out:
    spin_unlock(&i2c->lock);
    return IRQ_HANDLED;
}
Exemple #20
0
/* function: send read command
 * return:	0, successful
 *		1, txfifo valid entry is more than receive fifo, before send read command,
 *			must be read.
 *		2, txfifo count is 0 or rxfifo count is 0.
 * */
static inline unsigned int i2c_send_rcmd(struct i2c_jz *i2c)
{
    unsigned int tx_count, rx_count, count, tx_valid, rx_valid;

    tx_valid = i2c_readl(i2c, I2C_TXFLR);
    rx_valid = i2c_readl(i2c, I2C_RXFLR);
    tx_count = I2C_FIFO_LEN - tx_valid;
    rx_count = I2C_FIFO_LEN - rx_valid;

#ifdef CONFIG_I2C_DEBUG_INFO
    if(i2c->debug > DEBUG_INFO)
        dev_info(&(i2c->adap.dev),
                 "%s, tx_valid = %d, rx_valid = %d,"
                 " tx_count = %d, rx_count = %d\n",
                 __func__, tx_valid, rx_valid, tx_count, rx_count);
#endif

    if (tx_valid > rx_count) {
        dev_warn(&(i2c->adap.dev),
                 "\n\n###Warrning: I2C transfer fifo valid entry is more receive fifo, "
                 "before send read cmd, please read data from "
                 "the read fifo.\n\n");
        return 1;
    }

    if (!tx_count || !rx_count) {
        dev_warn(&(i2c->adap.dev),
                 "\n\n###Warrning: I2C receive fifo or transfer fifo is full, "
                 "before send read cmd, please read data from "
                 "the read fifo or wait some time.\n\n");
        return 2;
    }

    count = min3(i2c->rd_len, tx_count, rx_count);

#ifdef CONFIG_I2C_DEBUG_INFO
    if (i2c->debug > DEBUG_INFO)
        dev_info(&(i2c->adap.dev),
                 "%s, Before send read cmd, "
                 "need_send = %d, left_send = %d\n",
                 __func__, count ,i2c->rd_len);
#endif

    i2c->rd_len -= count;

    if (!i2c->rd_len) {
        while (count > 1) {
            i2c_writel(i2c, I2C_DC, I2C_DC_READ);
            count--;
        }
        if (i2c->r_end_type == MSG_END_STOP) {
            i2c_writel(i2c, I2C_DC, I2C_DC_READ | I2C_DC_STP);
        } else {
            i2c_writel(i2c, I2C_DC, I2C_DC_READ);
        }
    } else {
        while (count > 0) {
            i2c_writel(i2c, I2C_DC, I2C_DC_READ);
            count--;
        }
    }

#ifdef CONFIG_I2C_DEBUG_INFO
    if(i2c->debug > DEBUG_INFO)
        dev_info(&(i2c->adap.dev),
                 "%s, After send read cmd, "
                 "left_send = %d\n",
                 __func__, i2c->rd_len);
#endif
    return 0;
}
Exemple #21
0
static irqreturn_t i2c_jz_irq(int irqno, void *dev_id)
{
    unsigned short tmp, intst, intmsk;
    struct i2c_jz *i2c = dev_id;

    intst = i2c_readl(i2c, I2C_INTST);
    intmsk = i2c_readl(i2c, I2C_INTM);

#ifdef CONFIG_I2C_DEBUG_INFO
    if (i2c->debug > DEBUG_INFO)
        dev_info(&(i2c->adap.dev), "--I2C irq register INTST:0x%08x\n", intst);
#endif

    if ((intst & I2C_INTST_TXABT) && (intmsk & I2C_INTM_MTXABT)) {
        dev_err(&(i2c->adap.dev),
                "%s %d, I2C transfer error, ABORT interrupt\n",
                __func__, __LINE__);
        goto END_TRSF_IRQ_HND;
    }

    if ((intst & I2C_INTST_ISTP) && (intmsk & I2C_INTM_MISTP)) {
        i2c_readl(i2c, I2C_CSTP);	/* clear STP bit */
#ifdef CONFIG_I2C_DEBUG_INFO
        if (i2c->debug > DEBUG_INFO) {
            dev_info(&(i2c->adap.dev),
                     "%s, Now stop condition has occurred,"
                     "and left data length is %d\n",
                     __func__, i2c->len);
        }
#endif

        if (i2c->len == 0)
            goto END_TRSF_IRQ_HND;
    }

    if ((intmsk & I2C_INTM_MTXEMP) && (intst & I2C_INTST_TXEMP)) {
        if (!i2c->len) {
            if (i2c->w_end_type == MSG_END_REPEAT_START) {
                goto END_TRSF_IRQ_HND;
            } else {
                tmp = i2c_readl(i2c, I2C_INTM);
                tmp &= ~I2C_INTM_MTXEMP;
                i2c_writel(i2c, I2C_INTM, tmp);
            }
        } else {
            while ((i2c->len > 0) &&
                    (i2c_readl(i2c, I2C_STA) & I2C_STA_TFNF)) {
                tmp = *i2c->wbuf++;
                if (i2c->len == 1) {
                    if (i2c->w_end_type == MSG_END_STOP)
                        tmp |= I2C_DC_STP;
                }

                i2c_writel(i2c, I2C_DC, tmp);
                i2c->len -= 1;
            }

            if (i2c->len == 0) {
                i2c_writel(i2c, I2C_TXTL, 0);
            }
        }
    }

    if ((intst & I2C_INTST_RXFL) && (intmsk & I2C_INTM_MRXFL)) {
#ifdef CONFIG_I2C_DEBUG_INFO
        if (i2c->debug >= DEBUG_INFO) {
            dev_info(&(i2c->adap.dev),
                     "%s, Before read I2C_DC, "
                     "left_send_cmd = %d, left_read_cnt = %d,"
                     " rx_valid = %d, tx_valid = %d\n",
                     __func__, i2c->rd_len, i2c->len,
                     i2c_readl(i2c, I2C_RXFLR), i2c_readl(i2c, I2C_TXFLR));
        }
#endif

        while ((i2c_readl(i2c, I2C_STA) & I2C_STA_RFNE) &&
                (i2c->len > 0)) {
            tmp = i2c_readl(i2c, I2C_DC) & 0xff;
            *i2c->rbuf++ = tmp;
            i2c->len--;
        }

#ifdef CONFIG_I2C_DEBUG_INFO
        if (i2c->debug >= DEBUG_INFO)
            dev_info(&(i2c->adap.dev),
                     "%s, After read I2C_DC, "
                     "left_read_cnt = %d,"
                     " rx_valid = %d, tx_valid = %d\n",
                     __func__, i2c->len,
                     i2c_readl(i2c, I2C_RXFLR), i2c_readl(i2c, I2C_TXFLR));
#endif

        if (i2c->len == 0) {
            goto END_RECE_IRQ_HND;
        }

        if (i2c->len <= I2C_FIFO_LEN) {
            i2c_writel(i2c, I2C_RXTL, i2c->len - 1);
        }

        if (i2c_send_rcmd(i2c)) {
            dev_err(&(i2c->adap.dev),
                    "%s %d, I2C controller has BUG,"
                    " RXFLR or TXFLR can not clear\n",
                    __func__, __LINE__);
            BUG();
        }

#ifdef CONFIG_I2C_DEBUG_INFO
        if (i2c->debug > DEBUG_INFO)
            dev_info(&(i2c->adap.dev),
                     "%s, After send read command, "
                     "left_send_cmd = %d, "
                     "left_read_cnt = %d\n",
                     __func__, i2c->rd_len, i2c->len);
#endif
    }

    if ((intst & I2C_INTST_RXOF) && (intmsk & I2C_INTM_MRXOF)) {
        dev_err(&(i2c->adap.dev),
                "%s %d, I2C transfer error, RXFIFO over full\n",
                __func__, __LINE__);
        i2c_readl(i2c, I2C_CRXOF);	/* clear RXOF bit */
    }

    if ((intst & I2C_INTST_TXOF) && (intmsk & I2C_INTM_MTXOF)) {
        dev_err(&(i2c->adap.dev),
                "%s %d, I2C transfer error, TXFIFO over full\n",
                __func__, __LINE__);
        i2c_readl(i2c, I2C_CTXOF);	/* clear TXOF bit */
        goto END_TRSF_IRQ_HND;
    }

    return IRQ_HANDLED;
END_RECE_IRQ_HND:
END_TRSF_IRQ_HND:
    i2c_writel(i2c, I2C_INTM, 0);
    complete(&i2c->complete);
    return IRQ_HANDLED;
}
Exemple #22
0
static inline int xfer_read(struct i2c_jz *i2c, unsigned char *buf, int len,
                            enum msg_end_type end_type)
{
    int ret = 0;
    long timeout;
    unsigned short tmp;
    unsigned int wait_complete_timeout_ms;

    wait_complete_timeout_ms =
        len * 1000 * 9 * 2 / i2c->rate + CONFIG_I2C_JZV10_WAIT_MS;

#ifdef CONFIG_I2C_DEBUG_INFO
    if (i2c->debug > DEBUG_WARN)
        dev_info(&(i2c->adap.dev),
                 "%s, Begin read msg, want to read length is %d\n",
                 __func__, len);
#endif

    memset(buf, 0, len);

    i2c->rd_len = len;
    i2c->len = len;
    i2c->rbuf = buf;
    i2c->r_end_type = end_type;

    i2c_readl(i2c, I2C_CSTP);	/* clear STP bit */
    i2c_readl(i2c, I2C_CTXOF);	/* clear TXOF bit */
    i2c_readl(i2c, I2C_CTXABRT);	/* clear TXABRT bit */

    if (len <= I2C_FIFO_LEN) {
        i2c_writel(i2c, I2C_RXTL, len - 1);
    } else {
        i2c_writel(i2c, I2C_RXTL, RX_LEVEL);
    }

    while (i2c_readl(i2c, I2C_STA) & I2C_STA_RFNE) {
        i2c_readl(i2c, I2C_DC);
    }
    if (i2c_send_rcmd(i2c))
        BUG();

    tmp = I2C_INTM_MRXFL | I2C_INTM_MTXABT;
    if (end_type == MSG_END_STOP)
        tmp |= I2C_INTM_MISTP;
    i2c_writel(i2c, I2C_INTM, tmp);

    timeout = wait_for_completion_timeout(&i2c->complete,
                                          msecs_to_jiffies
                                          (wait_complete_timeout_ms));
    if (!timeout) {
        dev_err(&(i2c->adap.dev), "--I2C irq read timeout\n");
#ifdef I2C_DEBUG
        i2c_jz_dump_regs(i2c);
#endif
        ret = -ETIMEDOUT;
    }

    tmp = i2c_readl(i2c, I2C_TXABRT);
    if (tmp) {
        txabrt(i2c, tmp);
        if (tmp > 0x1 && tmp < 0x10)
            ret = -ENXIO;
        else
            ret = -EIO;
        // ABRT_GCALL_READ
        if (tmp & (1 << 5)) {
            ret = -EAGAIN;
        }
        i2c_readl(i2c, I2C_CTXABRT);
    }
    if (ret < 0)
        i2c_jz_reset(i2c);

#ifdef CONFIG_I2C_DEBUG_INFO
    if (i2c->debug > DEBUG_WARN)
        dev_info(&(i2c->adap.dev),
                 "%s, Reading msg over\n", __func__);
#endif

    return ret;
}
Exemple #23
0
static inline int xfer_write(struct i2c_jz *i2c, unsigned char *buf, int len,
                             enum msg_end_type end_type)
{
    int ret = 0;
    long timeout = TIMEOUT;
    unsigned short reg_tmp;
    unsigned int wait_complete_timeout_ms;

    wait_complete_timeout_ms =
        len * 1000 * 9 * 2 / i2c->rate + CONFIG_I2C_JZV10_WAIT_MS;

#ifdef CONFIG_I2C_DEBUG_INFO
    if (i2c->debug > DEBUG_WARN)
        dev_info(&(i2c->adap.dev),
                 "%s, Begin write msg, want to write length is %d\n",
                 __func__, len);
#endif

    i2c->wbuf = buf;
    i2c->len = len;

    i2c_writel(i2c, I2C_TXTL, TX_LEVEL);

    i2c_readl(i2c, I2C_CSTP);	/* clear STP bit */
    i2c_readl(i2c, I2C_CTXOF);	/* clear TXOF bit */
    i2c_readl(i2c, I2C_CTXABRT);	/* clear TXABRT bit */

    i2c->w_end_type = end_type;
    while ((i2c_readl(i2c, I2C_STA) & I2C_STA_TFNF) && (i2c->len > 0)) {
        reg_tmp = *i2c->wbuf++;
        if (i2c->len == 1) {
            if (end_type == MSG_END_STOP) {
                reg_tmp |= I2C_DC_STP;
            }
        }
        i2c_writel(i2c, I2C_DC, reg_tmp);

        i2c->len -= 1;
    }

    if (i2c->len == 0) {
        i2c_writel(i2c, I2C_TXTL, 0);
    }

    reg_tmp = I2C_INTM_MTXEMP | I2C_INTM_MTXABT | I2C_INTM_MTXOF;
    if (end_type == MSG_END_STOP)
        reg_tmp |= I2C_INTM_MISTP;

    i2c_writel(i2c, I2C_INTM, reg_tmp);

    timeout = wait_for_completion_timeout(&i2c->complete,
                                          msecs_to_jiffies
                                          (wait_complete_timeout_ms));

    if (!timeout) {
        dev_err(&(i2c->adap.dev), "--I2C pio write wait timeout\n");
#ifdef I2C_DEBUG
        i2c_jz_dump_regs(i2c);
#endif
        ret = -ETIMEDOUT;
    }

    reg_tmp = i2c_readl(i2c, I2C_TXABRT);
    if (reg_tmp) {
        txabrt(i2c, reg_tmp);
        if (reg_tmp > 0x1 && reg_tmp < 0x10)
            ret = -ENXIO;
        else
            ret = -EIO;
        //after I2C_TXABRT_ABRT_XDATA_NOACK error,this required core to resend
        if (reg_tmp & 8) {
            ret = -EAGAIN;
        }
        i2c_readl(i2c, I2C_CTXABRT);
    }

    if (ret < 0)
        i2c_jz_reset(i2c);

#ifdef CONFIG_I2C_DEBUG_INFO
    if (i2c->debug > DEBUG_WARN)
        dev_info(&(i2c->adap.dev),
                 "%s, Write msg over\n", __func__);
#endif
    return ret;
}
Exemple #24
0
static int i2c_jz_probe(struct platform_device *dev)
{
    int ret = 0;
    struct i2c_jz *i2c;
    struct resource *res;
    unsigned int reg_tmp;

    i2c = kzalloc(sizeof(struct i2c_jz), GFP_KERNEL);
    if (!i2c) {
        printk("Error: Now we can not malloc memory for I2C!\n");
        ret = -ENOMEM;
        goto ERR0;
    }

    i2c->adap.owner = THIS_MODULE;
    i2c->adap.algo = &i2c_jz_algorithm;
    i2c->adap.retries = 5;
    i2c->adap.timeout = 5;
    i2c->adap.algo_data = i2c;
    i2c->adap.dev.parent = &dev->dev;
    i2c->adap.nr = dev->id;
    sprintf(i2c->adap.name, "i2c%u", dev->id);

    i2c->clk = clk_get(&dev->dev, i2c->adap.name);
    if (!i2c->clk) {
        printk("Error: Now we can not get i2c%d clock!\n", dev->id);
        ret = -ENODEV;
        goto clk_failed;
    }

    res = platform_get_resource(dev, IORESOURCE_MEM, 0);
    i2c->iomem = ioremap(res->start, resource_size(res));
    if (!i2c->iomem) {
        printk("Error: Now we can remap IO for I2C%d!\n", dev->id);
        ret = -ENOMEM;
        goto io_failed;
    }

    i2c->irq = platform_get_irq(dev, 0);
    ret =
        request_irq(i2c->irq, i2c_jz_irq, IRQF_DISABLED,
                    dev_name(&dev->dev), i2c);
    if (ret) {
        printk("Error: Now we can request irq for I2C%d!\n", dev->id);
        ret = -ENODEV;
        goto irq_failed;
    }

    clk_enable(i2c->clk);

    res = platform_get_resource(dev, IORESOURCE_BUS, 0);

    i2c_set_speed(i2c, res->start * 1000);

#if 0
    reg_tmp = i2c_readl(i2c, I2C_DC);
    reg_tmp &= ~I2C_DC_STP;
    i2c_writel(i2c, I2C_DC, reg_tmp);
#endif

    reg_tmp = i2c_readl(i2c, I2C_CTRL);
    reg_tmp |= I2C_CTRL_REST;
    i2c_writel(i2c, I2C_CTRL, reg_tmp);

    // for jgao WHY?
    //  i2c_writel(i2c, I2C_FLT, 0xF);      /*set filter*/

    i2c_writel(i2c, I2C_INTM, 0x0);

    init_completion(&i2c->complete);

    ret = i2c_add_numbered_adapter(&i2c->adap);
    if (ret < 0) {
        dev_err(&(i2c->adap.dev), KERN_INFO "I2C: Failed to add bus\n");
        goto adapt_failed;
    }

    platform_set_drvdata(dev, i2c);

    i2c_jz_enable(i2c);

    clk_disable(i2c->clk);

#ifdef CONFIG_I2C_DEBUG_INFO
    ret = create_debug_sysfs_interface(&dev->dev);
    if (ret < 0)
        dev_err(&i2c->adap.dev, "create debug sysfs interface failed\n");
#endif

    return 0;

adapt_failed:
    free_irq(i2c->irq, i2c);
irq_failed:
    iounmap(i2c->iomem);
io_failed:
    clk_put(i2c->clk);
clk_failed:
    kfree(i2c);
ERR0:
    return ret;
}
/* rk30_i2c_doxfer
 *
 * this starts an i2c transfer
*/
static int rk30_i2c_doxfer(struct rk30_i2c *i2c,
                           struct i2c_msg *msgs, int num)
{
    unsigned long timeout, flags;
    int error = 0;
    /* 32 -- max transfer bytes
     * 2 -- addr bytes * 2
     * 3 -- max reg addr bytes
     * 9 -- cycles per bytes
     * max cycles: (32 + 2 + 3) * 9 --> 400 cycles
     */
    int msleep_time = 400 * 1000/ i2c->scl_rate; // ms

    if (i2c->suspended) {
        dev_err(i2c->dev, "i2c is suspended\n");
        return -EIO;
    }

    spin_lock_irqsave(&i2c->lock, flags);
    if(rk30_i2c_set_master(i2c, msgs, num) < 0) {
        spin_unlock_irqrestore(&i2c->lock, flags);
        dev_err(i2c->dev, "addr[0x%02x] set master error\n", msgs[0].addr);
        return -EIO;
    }
    i2c->addr = msgs[0].addr;
    i2c->msg_ptr = 0;
    i2c->error = 0;
    i2c->is_busy = 1;
    i2c->state = STATE_START;
    i2c->complete_what = 0;
    i2c_writel(I2C_STARTIEN, i2c->regs + I2C_IEN);
    spin_unlock_irqrestore(&i2c->lock, flags);

    rk30_i2c_enable(i2c, (i2c->count > 32)?0:1); //if count > 32,  byte(32) send ack

    if (in_atomic()) {
        int tmo = I2C_WAIT_TIMEOUT * USEC_PER_MSEC;
        while(tmo-- && i2c->is_busy != 0)
            udelay(1);
        timeout = (tmo <= 0)?0:1;
    } else
        timeout = wait_event_timeout(i2c->wait, (i2c->is_busy == 0), msecs_to_jiffies(I2C_WAIT_TIMEOUT));

    spin_lock_irqsave(&i2c->lock, flags);
    i2c->state = STATE_IDLE;
    error = i2c->error;
    spin_unlock_irqrestore(&i2c->lock, flags);

    if (timeout == 0) {
        if(error < 0)
            i2c_dbg(i2c->dev, "error = %d\n", error);
        else if((i2c->complete_what !=COMPLETE_READ  && i2c->complete_what != COMPLETE_WRITE)) {
            dev_err(i2c->dev, "Addr[0x%02x] wait event timeout, state: %d, is_busy: %d, error: %d, complete_what: 0x%x, ipd: 0x%x\n",
                    msgs[0].addr, i2c->state, i2c->is_busy, error, i2c->complete_what, i2c_readl(i2c->regs + I2C_IPD));
            //rk30_show_regs(i2c);
            error = -ETIMEDOUT;
            msleep(msleep_time);
            rk30_i2c_send_stop(i2c);
            msleep(1);
        }
        else
            i2c_dbg(i2c->dev, "Addr[0x%02x] wait event timeout, but transfer complete\n", i2c->addr);
    }
    i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD);
    rk30_i2c_disable_irq(i2c);
    rk30_i2c_disable(i2c);

    if(error == -EAGAIN)
        i2c_dbg(i2c->dev, "No ack(complete_what: 0x%x), Maybe slave(addr: 0x%02x) not exist or abnormal power-on\n",
                i2c->complete_what, i2c->addr);
    return error;
}
static void rk30_show_regs(struct rk30_i2c *i2c)
{
    int i;
    dev_info(i2c->dev, "i2c->clk = %lu\n", clk_get_rate(i2c->clk));
    dev_info(i2c->dev, "i2c->start = %d\n", i2c->state);
    dev_info(i2c->dev, "I2C_CON: 0x%08x\n", i2c_readl(i2c->regs + I2C_CON));
    dev_info(i2c->dev, "I2C_CLKDIV: 0x%08x\n", i2c_readl(i2c->regs + I2C_CLKDIV));
    dev_info(i2c->dev, "I2C_MRXADDR: 0x%08x\n", i2c_readl(i2c->regs + I2C_MRXADDR));
    dev_info(i2c->dev, "I2C_MRXRADDR: 0x%08x\n", i2c_readl(i2c->regs + I2C_MRXRADDR));
    dev_info(i2c->dev, "I2C_MTXCNT: 0x%08x\n", i2c_readl(i2c->regs + I2C_MTXCNT));
    dev_info(i2c->dev, "I2C_MRXCNT: 0x%08x\n", i2c_readl(i2c->regs + I2C_MRXCNT));
    dev_info(i2c->dev, "I2C_IEN: 0x%08x\n", i2c_readl(i2c->regs + I2C_IEN));
    dev_info(i2c->dev, "I2C_IPD: 0x%08x\n", i2c_readl(i2c->regs + I2C_IPD));
    dev_info(i2c->dev, "I2C_FCNT: 0x%08x\n", i2c_readl(i2c->regs + I2C_FCNT));
    for( i = 0; i < 8; i ++)
        dev_info(i2c->dev, "I2C_TXDATA%d: 0x%08x\n", i, i2c_readl(i2c->regs + I2C_TXDATA_BASE + i * 4));
    for( i = 0; i < 8; i ++)
        dev_info(i2c->dev, "I2C_RXDATA%d: 0x%08x\n", i, i2c_readl(i2c->regs + I2C_RXDATA_BASE + i * 4));
}
static void i2c_lpc2k_pump_msg(struct lpc2k_i2c *i2c)
{
	unsigned long status;
	unsigned char data;

	/*
	 * I2C in the LPC2xxx series is basically a state machine.
	 * Just run through the steps based on the current status.
	 */
	status = i2c_readl(i2c->reg_base + LPC24XX_I2STAT);

	switch (status) {
	case m_start:
	case m_repstart:
		/* Start bit was just sent out, send out addr and dir */
		data = (i2c->msg->addr << 1);
		if (i2c->msg->flags & I2C_M_RD)
			data |= 1;

		i2c_writel((unsigned long) data,
			i2c->reg_base + LPC24XX_I2DAT);
		i2c_writel(LPC24XX_STA,
			i2c->reg_base + LPC24XX_I2CONCLR);

		dev_dbg(&i2c->adap.dev, "Start sent, sending address "
			"0x%02x\n", data);
		break;

	case mx_addr_w_ack:
	case mx_data_w_ack:
		/*
		 * Address or data was sent out with an ACK. If there is more
		 * data to send, send it now
		 */
		if (i2c->msg_idx < i2c->msg->len) {
			i2c_writel((unsigned long)
				i2c->msg->buf[i2c->msg_idx],
				i2c->reg_base + LPC24XX_I2DAT);
			dev_dbg(&i2c->adap.dev, "ACK ok, sending "
				"(0x%02x)\n", i2c->msg->buf[i2c->msg_idx]);
		} else if (i2c->is_last) {
			/* Last message, send stop */
			i2c_writel(LPC24XX_STO | LPC24XX_AA,
				i2c->reg_base + LPC24XX_I2CONSET);
			i2c_writel(LPC24XX_SI, i2c->reg_base + LPC24XX_I2CONCLR);
			i2c->msg_status = 0;
			dev_dbg(&i2c->adap.dev, "ACK ok, sending stop\n");
			disable_irq_nosync(i2c->irq);
		} else {
			i2c->msg_status = 0;
			dev_dbg(&i2c->adap.dev, "ACK ok, idling until "
				"next message start\n");
			disable_irq_nosync(i2c->irq);
		}

		i2c->msg_idx++;
		break;

	case mr_addr_r_ack:
		/*
		 * Receive first byte from slave
		 */
		if (i2c->msg->len == 1) {
			/* Last byte, return NACK */
			i2c_writel(LPC24XX_AA,
				i2c->reg_base + LPC24XX_I2CONCLR);
		} else {
			/* Not last byte, return ACK */
			i2c_writel(LPC24XX_AA,
				i2c->reg_base + LPC24XX_I2CONSET);
		}

		i2c_writel(LPC24XX_STA, i2c->reg_base + LPC24XX_I2CONCLR);
		break;

	case mr_data_r_nack:
		/*
		 * The I2C shows NACK status on reads, so we need to accept
		 * the NACK as an ACK here. This should be ok, as the real
		 * BACK would of been caught on the address write.
		 */
	case mr_data_r_ack:
		/*
		 * Data was received
		 */
		if (i2c->msg_idx < i2c->msg->len) {
			i2c->msg->buf[i2c->msg_idx] =
				i2c_readl(i2c->reg_base + LPC24XX_I2DAT);
			dev_dbg(&i2c->adap.dev, "ACK ok, received "
				"(0x%02x)\n", i2c->msg->buf[i2c->msg_idx]);
		}

		/*
		 * If transfer is done, send STOP
		 */
		if (i2c->msg_idx >= i2c->msg->len - 1 && i2c->is_last) {
			i2c_writel(LPC24XX_STO | LPC24XX_AA,
				i2c->reg_base + LPC24XX_I2CONSET);
			i2c_writel(LPC24XX_SI, i2c->reg_base + LPC24XX_I2CONCLR);
			i2c->msg_status = 0;
			dev_dbg(&i2c->adap.dev, "ACK ok, sending stop\n");
		}

		/*
		 * Message is done
		 */
		if (i2c->msg_idx >= i2c->msg->len - 1) {
			i2c->msg_status = 0;
			dev_dbg(&i2c->adap.dev, "ACK ok, idling until "
				"next message start\n");
			disable_irq_nosync(i2c->irq);
		}

		/*
		 * One pre-last data input, send NACK to tell the slave that
		 * this is going to be the last data byte to be transferred.
		 */
		if (i2c->msg_idx >= i2c->msg->len - 2) {
			/* One byte left to receive - NACK */
			i2c_writel(LPC24XX_AA,
				i2c->reg_base + LPC24XX_I2CONCLR);
		} else {
			/* More than one byte left to receive - ACK */
			i2c_writel(LPC24XX_AA,
				i2c->reg_base + LPC24XX_I2CONSET);
		}

		i2c_writel(LPC24XX_STA,
			i2c->reg_base + LPC24XX_I2CONCLR);
		i2c->msg_idx++;
		break;

	case mx_addr_w_nack:
	case mx_data_w_nack:
	case mr_addr_r_nack:
		/*
		 * NACK! Processing is done
		 */
		i2c_writel(LPC24XX_STO | LPC24XX_AA,
			i2c->reg_base + LPC24XX_I2CONSET);
		i2c->msg_status = -ENODEV;
		dev_dbg(&i2c->adap.dev, "Device NACKed, error\n");
		disable_irq_nosync(i2c->irq);
		break;

	case m_data_arb_lost:
		/*
		 * Arbitration lost
		 */
		i2c->msg_status = -EIO;
		dev_dbg(&i2c->adap.dev, "Arbitration lost, error\n");

		/*
		 * Release the I2C bus
		 */
		i2c_writel(LPC24XX_STA | LPC24XX_STO,
			i2c->reg_base + LPC24XX_I2CONCLR);
		disable_irq_nosync(i2c->irq);
		break;

	default:
		/* Unexpected statuses */
		i2c->msg_status = -EIO;
		dev_err(&i2c->adap.dev, "Unexpected status, error (%x)\n",
			(unsigned int) status);
		disable_irq_nosync(i2c->irq);
		break;
	}

	/* Exit on failure or all bytes transferred */
	if (i2c->msg_status != -EBUSY)
		wake_up(&i2c->wait);

	/*
	 * If `msg_status` is zero, then `lpc2k_process_msg()` is responsible
	 * for clearing the SI flag.
	 */
	if (i2c->msg_status != 0)
		i2c_writel(LPC24XX_SI, i2c->reg_base + LPC24XX_I2CONCLR);
}