static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg) { if (usr_msg->len == 0 && (usr_msg->flags & I2C_M_RD)) { dev_err(pd->dev, "Unsupported zero length i2c read\n"); return -EIO; } /* Initialize channel registers */ iic_set_clr(pd, ICCR, 0, ICCR_ICE); /* Enable channel and configure rx ack */ iic_set_clr(pd, ICCR, ICCR_ICE, 0); /* Set the clock */ iic_wr(pd, ICCL, pd->iccl); iic_wr(pd, ICCH, pd->icch); pd->msg = usr_msg; pd->pos = -1; pd->sr = 0; /* Enable all interrupts to begin with */ iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); return 0; }
//8 bits register address only static int write_eeprom(U8 slvAddr, U8 addr, U8 data) { int i; U8 ch[3]; ch[1] = addr; ch[2] = data; rIICDS = slvAddr; rIICSTAT = 0xf0; //MasTx,Start for(i=0; i<3; i++) if(iic_wr(ch[i], i)) break; rIICSTAT = 0xd0; //Stop MasTx condition if(i<3) return -1; i = 200; //200ms while(i--) { Delay(1); rIICDS = slvAddr; rIICSTAT = 0xf0; if(!iic_wr(0, 0)) break; } rIICSTAT = 0xd0; return i?0:-1; }
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 = iic_rd(pd, ICSR); 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 */ iic_wr(pd, ICSR, sr & ~(ICSR_AL | ICSR_TACK)); 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 */ iic_wr(pd, ICSR, sr & ~ICSR_WAIT); if (wakeup) { pd->sr |= SW_DONE; wake_up(&pd->wait); } return IRQ_HANDLED; }
static void start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg, bool do_init) { if (do_init) { /* Initialize channel registers */ iic_wr(pd, ICCR, ICCR_SCP); /* Enable channel and configure rx ack */ iic_wr(pd, ICCR, ICCR_ICE | ICCR_SCP); /* Set the clock */ iic_wr(pd, ICCL, pd->iccl & 0xff); iic_wr(pd, ICCH, pd->icch & 0xff); } pd->msg = usr_msg; pd->pos = -1; pd->sr = 0; pd->dma_buf = i2c_get_dma_safe_msg_buf(pd->msg, 8); if (pd->dma_buf) sh_mobile_i2c_xfer_dma(pd); /* Enable all interrupts to begin with */ iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); }
//8 bits register address only static int read_eeprom(U8 slvAddr, U8 addr, U8 *pBuf) { int i; U8 ch[2]; ch[1] = addr; rIICDS = slvAddr; rIICSTAT = 0xf0; //MasTx,Start for(i=0; i<2; i++) if(iic_wr(ch[i], i)) break; if(i<2) { rIICSTAT = 0xd0; //Stop MasTx condition return -1; } rIICDS = slvAddr; rIICSTAT = 0xb0; //Master Rx,Start if(!iic_wr(0, 0)) //wait ack i = iic_rd(pBuf); rIICSTAT = 0x90; //Stop MaxRx condition return i; }
static void deactivate_ch(struct sh_mobile_i2c_data *pd) { /* Clear/disable interrupts */ iic_wr(pd, ICSR, 0); iic_wr(pd, ICIC, 0); /* Disable channel */ iic_set_clr(pd, ICCR, 0, ICCR_ICE); /* Disable clock and mark device as idle */ clk_disable(pd->clk); pm_runtime_put_sync(pd->dev); }
static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, enum sh_mobile_i2c_op op, unsigned char data) { unsigned char ret = 0; unsigned long flags; dev_dbg(pd->dev, "op %d, data in 0x%02x\n", op, data); spin_lock_irqsave(&pd->lock, flags); switch (op) { case OP_START: /* issue start and trigger DTE interrupt */ iic_wr(pd, ICCR, ICCR_ICE | ICCR_TRS | ICCR_BBSY); break; case OP_TX_FIRST: /* disable DTE interrupt and write data */ iic_wr(pd, ICIC, ICIC_WAITE | ICIC_ALE | ICIC_TACKE); iic_wr(pd, ICDR, data); break; case OP_TX: /* write data */ iic_wr(pd, ICDR, data); break; case OP_TX_STOP: /* issue a stop (or rep_start) */ iic_wr(pd, ICCR, pd->send_stop ? ICCR_ICE | ICCR_TRS : ICCR_ICE | ICCR_TRS | ICCR_BBSY); break; case OP_TX_TO_RX: /* select read mode */ iic_wr(pd, ICCR, ICCR_ICE | ICCR_SCP); break; case OP_RX: /* just read data */ ret = iic_rd(pd, ICDR); break; case OP_RX_STOP: /* enable DTE interrupt, issue stop */ iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK); break; case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */ iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); ret = iic_rd(pd, ICDR); iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK); break; } spin_unlock_irqrestore(&pd->lock, flags); dev_dbg(pd->dev, "op %d, data out 0x%02x\n", op, ret); return ret; }
static void activate_ch(struct sh_mobile_i2c_data *pd) { /* Wake up device and enable clock */ pm_runtime_get_sync(pd->dev); clk_prepare_enable(pd->clk); /* Enable channel and configure rx ack */ iic_set_clr(pd, ICCR, ICCR_ICE, 0); /* Mask all interrupts */ iic_wr(pd, ICIC, 0); /* Set the clock */ iic_wr(pd, ICCL, pd->iccl & 0xff); iic_wr(pd, ICCH, pd->icch & 0xff); }
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; }
static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) { struct sh_mobile_i2c_data *pd = dev_id; unsigned char sr; int wakeup = 0; sr = iic_rd(pd, ICSR); 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); /* Kick off TxDMA after preface was done */ if (pd->dma_direction == DMA_TO_DEVICE && pd->pos == 0) iic_set_clr(pd, ICIC, ICIC_TDMAE, 0); else if (sr & (ICSR_AL | ICSR_TACK)) /* don't interrupt transaction - continue to issue stop */ iic_wr(pd, ICSR, sr & ~(ICSR_AL | ICSR_TACK)); else if (pd->msg->flags & I2C_M_RD) wakeup = sh_mobile_i2c_isr_rx(pd); else wakeup = sh_mobile_i2c_isr_tx(pd); /* Kick off RxDMA after preface was done */ if (pd->dma_direction == DMA_FROM_DEVICE && pd->pos == 1) iic_set_clr(pd, ICIC, ICIC_RDMAE, 0); if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */ iic_wr(pd, ICSR, sr & ~ICSR_WAIT); if (wakeup) { pd->sr |= SW_DONE; wake_up(&pd->wait); } /* defeat write posting to avoid spurious WAIT interrupts */ iic_rd(pd, ICSR); return IRQ_HANDLED; }
/* * r8a7740 chip has lasting errata on I2C I/O pad reset. * this is work-around for it. */ static int sh_mobile_i2c_r8a7740_workaround(struct sh_mobile_i2c_data *pd) { iic_set_clr(pd, ICCR, ICCR_ICE, 0); iic_rd(pd, ICCR); /* dummy read */ iic_set_clr(pd, ICSTART, ICSTART_ICSTART, 0); iic_rd(pd, ICSTART); /* dummy read */ udelay(10); iic_wr(pd, ICCR, ICCR_SCP); iic_wr(pd, ICSTART, 0); udelay(10); iic_wr(pd, ICCR, ICCR_TRS); udelay(10); iic_wr(pd, ICCR, 0); udelay(10); iic_wr(pd, ICCR, ICCR_TRS); udelay(10); return sh_mobile_i2c_init(pd); }
static int seek_iic_device(U8 slvAddr) { int i; i = 40; //400ms while(i--) { rIICDS = slvAddr; rIICSTAT = 0xf0; //MasTx,Start if(!iic_wr(0, 0)) break; Delay(10); } rIICSTAT = 0xd0; //Stop MasTx condition return i<40; }
static void activate_ch(struct sh_mobile_i2c_data *pd) { unsigned long i2c_clk; u_int32_t num; u_int32_t denom; u_int32_t tmp; /* Wake up device and enable clock */ pm_runtime_get_sync(pd->dev); clk_enable(pd->clk); /* Get clock rate after clock is enabled */ i2c_clk = clk_get_rate(pd->clk); /* Calculate the value for iccl. From the data sheet: * iccl = (p clock / transfer rate) * (L / (L + H)) * where L and H are the SCL low/high ratio (5/4 in this case). * We also round off the result. */ num = i2c_clk * 5; denom = NORMAL_SPEED * 9; tmp = num * 10 / denom; if (tmp % 10 >= 5) pd->iccl = (u_int8_t)((num/denom) + 1); else pd->iccl = (u_int8_t)(num/denom); /* one more bit of ICCL in ICIC */ if (pd->flags & IIC_FLAG_HAS_ICIC67) { if ((num/denom) > 0xff) pd->icic |= ICIC_ICCLB8; else pd->icic &= ~ICIC_ICCLB8; } /* Calculate the value for icch. From the data sheet: icch = (p clock / transfer rate) * (H / (L + H)) */ num = i2c_clk * 4; tmp = num * 10 / denom; if (tmp % 10 >= 5) pd->icch = (u_int8_t)((num/denom) + 1); else pd->icch = (u_int8_t)(num/denom); /* one more bit of ICCH in ICIC */ if (pd->flags & IIC_FLAG_HAS_ICIC67) { if ((num/denom) > 0xff) pd->icic |= ICIC_ICCHB8; else pd->icic &= ~ICIC_ICCHB8; } /* Enable channel and configure rx ack */ iic_set_clr(pd, ICCR, ICCR_ICE, 0); /* Mask all interrupts */ iic_wr(pd, ICIC, 0); /* Set the clock */ iic_wr(pd, ICCL, pd->iccl); iic_wr(pd, ICCH, pd->icch); }
static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs, unsigned char set, unsigned char clr) { iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr); }