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; }
static void rk30_irq_write_prepare(struct rk30_i2c *i2c) { unsigned int data = 0, cnt = 0, i, j; unsigned char byte; if(is_msgend(i2c)) { rk30_i2c_stop(i2c, i2c->error); return; } for(i = 0; i < 8; i++) { data = 0; for(j = 0; j < 4; j++) { if(is_msgend(i2c)) break; if(i2c->msg_ptr == 0 && cnt == 0) byte = (i2c->addr & 0x7f) << 1; else byte = i2c->msg->buf[i2c->msg_ptr++]; cnt++; data |= (byte << (j * 8)); } i2c_writel(data, i2c->regs + I2C_TXDATA_BASE + 4 * i); if(is_msgend(i2c)) break; } i2c_writel(cnt, i2c->regs + I2C_MTXCNT); }
static void i2c_lpc2k_reset(struct lpc2k_i2c *i2c) { /* Will force clear all statuses */ i2c_writel(0x7C, i2c->reg_base + LPC24XX_I2CONCLR); i2c_writel(0, i2c->reg_base + LPC24XX_I2ADDR); i2c_writel(LPC24XX_I2EN, i2c->reg_base + LPC24XX_I2CONSET); }
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; }
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 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); }
static int i2c_jz_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int count) { int i, ret = 0; struct i2c_jz *i2c = adap->algo_data; #ifdef CONFIG_I2C_DEBUG_INFO if (i2c->debug > DEBUG_WARN) { printk("\n\n\n"); dev_info(&(i2c->adap.dev), "%s, Begin master xfer, want to transfer msg count is %d\n", __func__, count); } #endif clk_enable(i2c->clk); i2c_writel(i2c, I2C_TAR, msg->addr); for (i = 0; i < count; i++, msg++) { enum msg_end_type end_type = MSG_END_STOP; if (i < (count - 1)) { if (msg[i + 1].flags & I2C_M_NOSTART) { end_type = MSG_END_CONTINUE; /* have no STOP and START */ } else { end_type = MSG_END_REPEAT_START; /* have no STOP but have RESTART */ } } INIT_COMPLETION(i2c->complete); #ifdef CONFIG_I2C_DEBUG_INFO if (i2c->debug > DEBUG_WARN) dev_info(&(i2c->adap.dev), "%s, Now transfer msg: %d\n", __func__, i); #endif if (msg->flags & I2C_M_RD) { ret = xfer_read(i2c, msg->buf, msg->len, end_type); } else { ret = xfer_write(i2c, msg->buf, msg->len, end_type); } if (ret < 0) { clk_disable(i2c->clk); goto ERR; } } if (i2c_disable_clk(i2c)) { ret = -ETIMEDOUT; goto ERR; } #ifdef CONFIG_I2C_DEBUG_INFO if (i2c->debug > DEBUG_WARN) dev_info(&(i2c->adap.dev), "%s, Transfer msg over\n\n\n", __func__); #endif ERR: return ret ? : i; }
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); }
static inline void rk30_i2c_enable(struct rk30_i2c *i2c, unsigned int lastnak) { unsigned int con = 0; con |= I2C_CON_EN; con |= I2C_CON_MOD(i2c->mode); if(lastnak) con |= I2C_CON_LASTACK; con |= I2C_CON_START; i2c_writel(con, i2c->regs + I2C_CON); }
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 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; }
/* 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; }
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 void rk30_i2c_stop(struct rk30_i2c *i2c, int ret) { i2c->msg_ptr = 0; i2c->msg = NULL; if(ret == -EAGAIN) { i2c->state = STATE_IDLE; i2c->is_busy = 0; wake_up(&i2c->wait); return; } i2c->error = ret; i2c_writel(I2C_STOPIEN, i2c->regs + I2C_IEN); i2c->state = STATE_STOP; rk30_i2c_send_stop(i2c); return; }
static void rk30_irq_read_prepare(struct rk30_i2c *i2c) { unsigned int cnt, len = i2c->msg->len - i2c->msg_ptr; if(len <= 32 && i2c->msg_ptr != 0) rk30_set_rx_mode(i2c, 1); else if(i2c->msg_ptr != 0) rk30_set_rx_mode(i2c, 0); if(is_msgend(i2c)) { rk30_i2c_stop(i2c, i2c->error); return; } if(len > 32) cnt = 32; else cnt = len; i2c_writel(cnt, i2c->regs + I2C_MRXCNT); }
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; }
/* 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 int rk30_i2c_set_master(struct rk30_i2c *i2c, struct i2c_msg *msgs, int num) { unsigned int addr = (msgs[0].addr & 0x7f) << 1; unsigned int reg_valid_bits = 0; unsigned int reg_addr = 0; if(num == 1) { i2c->count = msgs[0].len; if(!(msgs[0].flags & I2C_M_RD)) { i2c->msg = &msgs[0]; i2c->mode = I2C_CON_MOD_TX; } else { addr |= 1; i2c->msg = &msgs[0]; i2c_writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); i2c_writel(0, i2c->regs + I2C_MRXRADDR); i2c->mode = I2C_CON_MOD_TRX; //i2c->mode = I2C_CON_MOD_RX; } } else if(num == 2) { i2c->count = msgs[1].len; switch(msgs[0].len) { case 1: reg_addr = msgs[0].buf[0]; reg_valid_bits |= I2C_MRXADDR_LOW; break; case 2: reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8); reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID; break; case 3: reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8) | (msgs[0].buf[2] << 16); reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID | I2C_MRXADDR_HIGH; break; default: return -EIO; } if((msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) { addr |= 1; i2c->msg = &msgs[1]; i2c_writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); i2c_writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR); i2c->mode = I2C_CON_MOD_RRX; } else if(!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) { i2c->msg = &msgs[1]; i2c_writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); i2c_writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR); i2c->mode = I2C_CON_MOD_TRX; } else return -EIO; } else { dev_err(i2c->dev, "This case(num > 2) has not been support now\n"); return -EIO; } return 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; }
static void rk30_i2c_irq_nextblock(struct rk30_i2c *i2c, unsigned int ipd) { switch (i2c->state) { case STATE_START: if(!(ipd & I2C_STARTIPD)) { rk30_i2c_stop(i2c, -ENXIO); dev_err(i2c->dev, "Addr[0x%02x] no start irq in STATE_START\n", i2c->addr); rk30_show_regs(i2c); i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); goto out; } i2c->complete_what |= 1<<i2c->state; i2c_writel(I2C_STARTIPD, i2c->regs + I2C_IPD); rk30_i2c_clean_start(i2c); if(i2c->mode == I2C_CON_MOD_TX) { i2c_writel(I2C_MBTFIEN | I2C_NAKRCVIEN, i2c->regs + I2C_IEN); i2c->state = STATE_WRITE; goto prepare_write; } else { i2c_writel(I2C_MBRFIEN | I2C_NAKRCVIEN, i2c->regs + I2C_IEN); i2c->state = STATE_READ; goto prepare_read; } case STATE_WRITE: if(!(ipd & I2C_MBTFIPD)) { rk30_i2c_stop(i2c, -ENXIO); dev_err(i2c->dev, "Addr[0x%02x] no mbtf irq in STATE_WRITE\n", i2c->addr); rk30_show_regs(i2c); i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); goto out; } i2c->complete_what |= 1<<i2c->state; i2c_writel(I2C_MBTFIPD, i2c->regs + I2C_IPD); prepare_write: rk30_irq_write_prepare(i2c); break; case STATE_READ: if(!(ipd & I2C_MBRFIPD)) { rk30_i2c_stop(i2c, -ENXIO); dev_err(i2c->dev, "Addr[0x%02x] no mbrf irq in STATE_READ, ipd = 0x%x\n", i2c->addr, ipd); rk30_show_regs(i2c); i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); goto out; } i2c->complete_what |= 1<<i2c->state; i2c_writel(I2C_MBRFIPD, i2c->regs + I2C_IPD); rk30_irq_read_get_data(i2c); prepare_read: rk30_irq_read_prepare(i2c); break; case STATE_STOP: if(!(ipd & I2C_STOPIPD)) { rk30_i2c_stop(i2c, -ENXIO); dev_err(i2c->dev, "Addr[0x%02x] no stop irq in STATE_STOP\n", i2c->addr); rk30_show_regs(i2c); i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); goto out; } rk30_i2c_clean_stop(i2c); i2c_writel(I2C_STOPIPD, i2c->regs + I2C_IPD); i2c->is_busy = 0; i2c->complete_what |= 1<<i2c->state; i2c->state = STATE_IDLE; wake_up(&i2c->wait); break; default: break; } out: return; }
static int i2c_set_speed(struct i2c_jz *i2c, int rate) { /*ns */ long dev_clk = clk_get_rate(i2c->clk); long cnt_high = 0; /* HIGH period count of the SCL clock */ long cnt_low = 0; /* LOW period count of the SCL clock */ long setup_time = 0; long hold_time = 0; unsigned short tmp; i2c->rate = rate; if (i2c_jz_disable(i2c)) dev_info(&(i2c->adap.dev), "i2c not disable\n"); if (rate <= 100000) { tmp = 0x43 | (1 << 5); /* standard speed mode */ i2c_writel(i2c, I2C_CTRL, tmp); } else { tmp = 0x45 | (1 << 5); /* fast speed mode */ i2c_writel(i2c, I2C_CTRL, tmp); } /* high * ____ ____ ____ ____ * clk __| | |___| |____| |____| |___ * | | | * | | | * |_|_| _________ ____ * data __/ | |\___/ \____/ \____ * setup->| |<| * ->| |<-hold */ //setup_time = (10 000 000/(rate*4)) + 1; setup_time = (dev_clk / (rate * 4)); if (setup_time > 1) setup_time -= 1; //hold_time = (10000000/(rate*4)) - 1; hold_time = (dev_clk / (rate * 4)); /* high * ____ ____ * clk __| |___| |____ * low * |<--period--->| * */ cnt_high = dev_clk / (rate * 2); cnt_low = dev_clk / (rate * 2); dev_info(&(i2c->adap.dev), "set:%ld hold:%ld dev=%ld h=%ld l=%ld\n", setup_time, hold_time, dev_clk, cnt_high, cnt_low); if (setup_time > 255) setup_time = 255; if (setup_time <= 0) setup_time = 1; if (hold_time > 0xFFFF) hold_time = 0xFFFF; if (rate <= 100000) { i2c_writel(i2c, I2C_SHCNT, I2CSHCNT_ADJUST(cnt_high)); i2c_writel(i2c, I2C_SLCNT, I2CSLCNT_ADJUST(cnt_low)); } else { i2c_writel(i2c, I2C_FHCNT, I2CFHCNT_ADJUST(cnt_high)); i2c_writel(i2c, I2C_FLCNT, I2CFLCNT_ADJUST(cnt_low)); } i2c_writel(i2c, I2C_SDASU, setup_time & 0xff); i2c_writel(i2c, I2C_SDAHD, hold_time); return 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; }
int __init i2c_61_init(void) { int rc = 0; int i2c_clk = 0; int gcr_kdv; unsigned long gcr; printk(KERN_INFO "Initialize Prolific I2C adapter module v%s\n", VERSION); i2c_adapt_data.base = DEFAULT_BASE; i2c_adapt_data.irq = DEFAULT_IRQ; i2c_adapt_data.clock = DEFAULT_CLOCK; i2c_adapt_data.own = DEFAULT_OWN; i2c_algo_data.data = (void *)&i2c_adapt_data; init_waitqueue_head(&i2c_adapt_data.i2c_wait); atomic_set(&i2c_adapt_data.irq_done, 0); if (i2c_clk_setup) { i2c_cd = i2c_cd & 0x7; writeb(i2c_cd, PL_CLK_I2C); i2c_clk = pl_get_dev_hz() / 8; /* jedy should be modified */ gcr_kdv = i2c_kdv; } else if (pl_get_dev_hz() == 96000000) { /* dclk = 96MHz */ writeb(6, PL_CLK_I2C); /* program i2c dev clk to 24MHz */ gcr_kdv = 10; /* program i2c data rate = i2c_dev_clk/(20*(10+2)) */ i2c_clk = 96000000/4; } else if (pl_get_dev_hz() == 32000000) { /* dclk = 32MHz */ writeb(5, PL_CLK_I2C); /* target 16MHz */ gcr_kdv = 6; i2c_clk = 32000000/2; } else if (pl_get_dev_hz() == 120000000) { /* dclk = 120MHz */ writeb(6, PL_CLK_I2C); /* program i2c dev clk to 30MHz */ gcr_kdv = 13; i2c_clk = 120000000/4; } else { writeb(7, PL_CLK_I2C); gcr_kdv = 32; i2c_clk = pl_get_dev_hz()/8; } i2c_adapt_data.clock = i2c_clk / (20 * (gcr_kdv + 2)); #if 0 gcr = PL_GCR_I2CEN | PL_GCR_MCR_IEN | PL_GCR_SCR_IEN | PL_GCR_KDV(gcr_kdv) | PL_GCR_XSCL_PU | PL_GCR_XSCL_6MA | PL_GCR_XSDA_PU | PL_GCR_XSDA_6MA; #endif gcr = PL_GCR_I2CEN | PL_GCR_MCR_IEN | PL_GCR_KDV(gcr_kdv); i2c_writel(&i2c_adapt_data, I2C_GCR, gcr); rc = request_irq(i2c_adapt_data.irq, i2c_handler, 0, "I2C ADAPT", &i2c_adapt_data); if (rc < 0) { printk("Failed to enable i2c irq %d\n", i2c_adapt_data.irq); rc = -ENODEV; goto EXIT; } /* enable_irq(i2c_adapt_data.irq); */ // it's redundant init_timer(&i2c_adapt_data.wait_timeout); i2c_adapt_data.wait_timeout.function = i2c_timeout_handler; i2c_adapt_data.wait_timeout.data = (unsigned long) &i2c_adapt_data; if (i2c_61_add_bus(&i2c_61_ops) < 0) { rc = -ENODEV; goto EXIT; } printk(KERN_INFO " found i2c adapter at %#x irq %d. Data tranfer clock is %dHz\n", i2c_adapt_data.base, i2c_adapt_data.irq, i2c_adapt_data.clock); EXIT: return rc; }
static inline void rk30_i2c_enable_irq(struct rk30_i2c *i2c) { i2c_writel(IRQ_MST_ENABLE, i2c->regs + I2C_IEN); }
static inline void rk30_i2c_disable_irq(struct rk30_i2c *i2c) { i2c_writel(IRQ_ALL_DISABLE, i2c->regs + I2C_IEN); }
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); }
static inline void rk30_i2c_disable(struct rk30_i2c *i2c) { i2c_writel( 0, i2c->regs + I2C_CON); }
static int lpc2k_process_msg(struct lpc2k_i2c *i2c, int msgidx) { int ret; dev_dbg(&i2c->adap.dev, "Processing message %d (len=%d) (flags=%x)\n", msgidx, i2c->msg->len, i2c->msg->flags); /* * A new transfer is kicked off by initiating a start condition */ if (!msgidx) { dev_dbg(&i2c->adap.dev, "Start sent\n"); i2c_writel(LPC24XX_STA, i2c->reg_base + LPC24XX_I2CONSET); } else { /* * A multi-message I2C transfer continues where the previous * I2C transfer left off and uses the current condition of the * I2C adapter. */ if (unlikely(i2c->msg->flags & I2C_M_NOSTART)) { WARN_ON(i2c->msg->len == 0); if (!(i2c->msg->flags & I2C_M_RD)) { /* Start transmit of data */ i2c_writel((unsigned long) i2c->msg->buf[0], i2c->reg_base + LPC24XX_I2DAT); i2c->msg_idx++; dev_dbg(&i2c->adap.dev, "New data sent\n"); } else dev_dbg(&i2c->adap.dev, "New data incoming\n"); } else { /* Start or repeated start */ dev_dbg(&i2c->adap.dev, "Repeated start sent\n"); i2c_writel(LPC24XX_STA, i2c->reg_base + LPC24XX_I2CONSET); } i2c_writel(LPC24XX_SI, i2c->reg_base + LPC24XX_I2CONCLR); } enable_irq(i2c->irq); /* Wait for transfer completion */ if (wait_event_timeout(i2c->wait, i2c->msg_status != -EBUSY, HZ) == 0) { disable_irq_nosync(i2c->irq); dev_dbg(&i2c->adap.dev, "Transfer timed out!\n"); ret = -ETIMEDOUT; } else { ret = i2c->msg_status; if (ret == 0) dev_dbg(&i2c->adap.dev, "Transfer successful\n"); else dev_dbg(&i2c->adap.dev, "Transfer failed (%d)\n", ret); } return ret; }
static int i2c_lpc2k_probe(struct platform_device *dev) { struct lpc2k_i2c *i2c; struct resource *res; int ret, irq; unsigned long clkrate; res = platform_get_resource(dev, IORESOURCE_MEM, 0); irq = platform_get_irq(dev, 0); if (res == NULL || irq < 0) { dev_err(&dev->dev, "No resource data!\n"); return -ENODEV; } if (dev->id < 0 || dev->id >= LPC24XX_MAX_ADAPTERS) { dev_err(&dev->dev, "I2C bus number invalid (%d)\n", dev->id); return -ENODEV; } if (!request_mem_region(res->start, resource_size(res), res->name)) { dev_err(&dev->dev, "Memory region already used!\n"); return -ENOMEM; } i2c = kzalloc(sizeof(struct lpc2k_i2c), GFP_KERNEL); if (!i2c) { dev_err(&dev->dev, "Error allocating memory!\n"); ret = -ENOMEM; goto emalloc; } i2c->adap.owner = THIS_MODULE; init_waitqueue_head(&i2c->wait); i2c->adap.nr = dev->id; snprintf(i2c->adap.name, sizeof(i2c->adap.name), MODULE_NAME ".%u", i2c->adap.nr); i2c->clk = clk_get(&dev->dev, NULL); if (IS_ERR(i2c->clk)) { dev_err(&dev->dev, "Error getting clock!\n"); ret = PTR_ERR(i2c->clk); goto eclk; } i2c->reg_base = ioremap(res->start, resource_size(res)); if (!i2c->reg_base) { dev_err(&dev->dev, "Error mapping memory!\n"); ret = -EIO; goto eremap; } i2c->iobase = res->start; i2c->iosize = resource_size(res); i2c->irq = irq; clk_enable(i2c->clk); i2c->adap.algo = &i2c_lpc2k_algorithm; ret = request_irq(irq, i2c_lpc2k_handler, IRQF_DISABLED, i2c->adap.name, i2c); if (ret) goto ereqirq; disable_irq_nosync(irq); i2c_lpc2k_reset(i2c); i2c->adap.algo_data = i2c; i2c->adap.dev.parent = &dev->dev; ret = i2c_add_numbered_adapter(&i2c->adap); if (ret < 0) { dev_err(&dev->dev, "Failed to add bus!\n"); goto eadapt; } platform_set_drvdata(dev, i2c); printk(KERN_INFO "I2C: %s: LPC2K I2C adapter\n", dev_name(&i2c->adap.dev)); /* Place controller is a known state */ i2c_lpc2k_reset(i2c); /* Get I2C base clock rate */ clkrate = clk_get_rate(i2c->clk); if (!clkrate) { dev_warn(&dev->dev, "Can't get I2C base clock, using " "12MHz!\n"); clkrate = 12000000; } /* Setup I2C dividers to generate clock rate with 50% duty cycle */ clkrate = (clkrate / scl_frequency) / 2; i2c_writel(clkrate, i2c->reg_base + LPC24XX_I2SCLL); i2c_writel(clkrate, i2c->reg_base + LPC24XX_I2SCLH); return 0; eadapt: free_irq(irq, i2c); ereqirq: clk_disable(i2c->clk); iounmap(i2c->reg_base); eremap: clk_put(i2c->clk); eclk: kfree(i2c); emalloc: release_mem_region(res->start, resource_size(res)); return ret; }