/* * Prepare controller for a transaction and call i2c_davinci_xfer_msg */ static int i2c_davinci_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], int num) { struct davinci_i2c_dev *dev = bus->priv; int i; int ret; i2c_dbg("%s: msgs: %d\n", __func__, num); ret = i2c_davinci_wait_bus_not_busy(dev, 1); if (ret < 0) { i2c_dbg("timeout waiting for bus ready\n"); return ret; } for (i = 0; i < num; i++) { ret = i2c_davinci_xfer_msg(bus, &msgs[i], (i == (num - 1))); i2c_dbg("%s [%d/%d] ret: %d\n", __func__, i + 1, num, ret); if (ret < 0) return ret; } return num; }
rt_size_t rt_i2c_transfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num) { rt_size_t ret; if (bus->ops->master_xfer) { #ifdef RT_I2C_DEBUG for (ret = 0; ret < num; ret++) { i2c_dbg("msgs[%d] %c, addr=0x%02x, len=%d%s\n", ret, (msgs[ret].flags & RT_I2C_RD) ? 'R' : 'W', msgs[ret].addr, msgs[ret].len); } #endif rt_mutex_take(&bus->lock, RT_WAITING_FOREVER); ret = bus->ops->master_xfer(bus, msgs, num); rt_mutex_release(&bus->lock); return ret; } else { i2c_dbg("I2C bus operation not supported\n"); return 0; } }
/* * This function configures I2C and brings I2C out of reset. * This function is called during I2C init function. This function * also gets called if I2C encounters any errors. */ static int i2c_davinci_init(struct davinci_i2c_dev *dev) { /* put I2C into reset */ davinci_i2c_reset_ctrl(dev, 0); /* compute clock dividers */ i2c_davinci_calc_clk_dividers(dev); /* Respond at reserved "SMBus Host" slave address" (and zero); * we seem to have no option to not respond... */ davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08); i2c_dbg("PSC = %d\n", davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); i2c_dbg("CLKL = %d\n", davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG)); i2c_dbg("CLKH = %d\n", davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG)); i2c_dbg("bus_freq = %dkHz, bus_delay = %d\n", dev->bus_freq, dev->bus_delay); /* Take the I2C module out of reset: */ davinci_i2c_reset_ctrl(dev, 1); /* Enable interrupts */ davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, I2C_DAVINCI_INTR_ALL); return 0; }
static int rk30_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { int ret = 0, state, retry = 10; unsigned long scl_rate; struct rk30_i2c *i2c = (struct rk30_i2c *)adap->algo_data; clk_enable(i2c->clk); #ifdef I2C_CHECK_IDLE printk("wax->%d\n",__LINE__); //add by nition for test while(retry-- && ((state = rk30_i2c_check_idle(i2c)) != I2C_IDLE)){ printk("wax->%d\n",__LINE__); //add by nition for test msleep(10); printk("wax->%d\n",__LINE__); //add by nition for test } printk("wax->%d\n",__LINE__); //add by nition for test if(retry == 0){ printk("wax->%d\n",__LINE__); //add by nition for test dev_err(i2c->dev, "i2c is not in idle(state = %d)\n", state); return -EIO; } #endif if(msgs[0].scl_rate <= 400000 && msgs[0].scl_rate >= 10000) scl_rate = msgs[0].scl_rate; else if(msgs[0].scl_rate > 400000){ dev_warn(i2c->dev, "Warning: addr[0x%x] msg[0].scl_rate( = %dKhz) is too high!", msgs[0].addr, msgs[0].scl_rate/1000); scl_rate = 400000; } else{ dev_warn(i2c->dev, "Warning: addr[0x%x] msg[0].scl_rate( = %dKhz) is too low!", msgs[0].addr, msgs[0].scl_rate/1000); scl_rate = 10000; } if(i2c->is_div_from_arm[i2c->adap.nr]){ mutex_lock(&i2c->m_lock); } rk30_i2c_set_clk(i2c, scl_rate); i2c_dbg(i2c->dev, "i2c transfer start: addr: 0x%x, scl_reate: %ldKhz, len: %d\n", msgs[0].addr, scl_rate/1000, num); ret = rk30_i2c_doxfer(i2c, msgs, num); i2c_dbg(i2c->dev, "i2c transfer stop: addr: 0x%x, state: %d, ret: %d\n", msgs[0].addr, ret, i2c->state); if(i2c->is_div_from_arm[i2c->adap.nr]){ mutex_unlock(&i2c->m_lock); } clk_disable(i2c->clk); return (ret < 0)?ret:num; }
/* set i2c bus scl rate */ static void rk29_i2c_clockrate(struct rk29_i2c_data *i2c) { struct rk29_i2c_platform_data *pdata = i2c->dev->platform_data; unsigned int rem = 0, exp = 0; unsigned long scl_rate, real_rate = 0, tmp; i2c->i2c_rate = clk_get_rate(i2c->clk); scl_rate = (i2c->scl_rate) ? i2c->scl_rate : ((pdata->scl_rate)? pdata->scl_rate:100000); rk29_i2c_calcdivisor(i2c->i2c_rate, scl_rate, &real_rate, &rem, &exp); tmp = readl(i2c->regs + I2C_OPR); tmp &= ~0x3f; tmp |= exp; tmp |= rem<<I2CCDVR_EXP_BITS; writel(tmp, i2c->regs + I2C_OPR); if(real_rate > 400000) dev_warn(i2c->dev, "i2c_rate[%luKhz], scl_rate[%luKhz], real_rate[%luKhz] > 400Khz\n", i2c->i2c_rate/1000, scl_rate/1000, real_rate/1000); else i2c_dbg(i2c->dev, "i2c_rate[%luKhz], scl_rate[%luKhz], real_rate[%luKhz]\n", i2c->i2c_rate/1000, scl_rate/1000, real_rate/1000); return; }
static inline int i2c_send_byte(struct saa7134_dev *dev, enum i2c_attr attr, unsigned char data) { enum i2c_status status; __u32 dword; /* have to write both attr + data in one 32bit word */ dword = saa_readl(SAA7134_I2C_ATTR_STATUS >> 2); dword &= 0x0f; dword |= (attr << 6); dword |= ((__u32)data << 8); dword |= 0x00 << 16; /* 100 kHz */ // dword |= 0x40 << 16; /* 400 kHz */ dword |= 0xf0 << 24; saa_writel(SAA7134_I2C_ATTR_STATUS >> 2, dword); i2c_dbg(2, "i2c data => 0x%x\n", data); if (!i2c_is_busy_wait(dev)) return -EIO; status = i2c_get_status(dev); if (i2c_is_error(status)) return -EIO; return 0; }
static int i2c_reset(struct saa7134_dev *dev) { enum i2c_status status; int count; i2c_dbg(2, "i2c reset\n"); status = i2c_get_status(dev); if (!i2c_is_error(status)) return true; i2c_set_status(dev,status); for (count = 0; count < I2C_WAIT_RETRY; count++) { status = i2c_get_status(dev); if (!i2c_is_error(status)) break; udelay(I2C_WAIT_DELAY); } if (I2C_WAIT_RETRY == count) return false; if (!i2c_is_idle(status)) return false; i2c_set_attr(dev,NOP); return true; }
static inline enum i2c_status i2c_get_status(struct saa7134_dev *dev) { enum i2c_status status; status = saa_readb(SAA7134_I2C_ATTR_STATUS) & 0x0f; i2c_dbg(2, "i2c stat <= %s\n", str_i2c_status[status]); return status; }
static void terminate_write(struct davinci_i2c_dev *dev) { rt_uint16_t w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); w |= DAVINCI_I2C_MDR_RM | DAVINCI_I2C_MDR_STP; davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); if (!dev->terminate) i2c_dbg("TDR IRQ while no data to send\n"); }
static rt_size_t i2c_bus_device_read (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t count) { struct rt_i2c_bus* bus; struct rt_i2c_device *i2c_device = dev->user_data; bus = i2c_device->bus; RT_ASSERT(bus != RT_NULL); RT_ASSERT(i2c_device != RT_NULL); RT_ASSERT(buffer != RT_NULL); i2c_dbg("I2C bus dev [%s] reading %u bytes.\n", bus->name, count); return rt_i2c_master_recv(i2c_device, buffer, count); }
static rt_size_t i2c_bus_device_write (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) { struct rt_i2c_bus* bus; struct rt_i2c_device *i2c_device = dev->user_data; bus = i2c_device->bus; RT_ASSERT(bus != RT_NULL); RT_ASSERT(i2c_device != RT_NULL); RT_ASSERT(buffer != RT_NULL); i2c_dbg("I2C bus dev writing %u bytes.\n", bus->name, size); return rt_i2c_master_send(i2c_device, buffer, size); }
static inline int i2c_recv_byte(struct saa7134_dev *dev) { enum i2c_status status; unsigned char data; i2c_set_attr(dev,CONTINUE); if (!i2c_is_busy_wait(dev)) return -EIO; status = i2c_get_status(dev); if (i2c_is_error(status)) return -EIO; data = saa_readb(SAA7134_I2C_DATA); i2c_dbg(2, "i2c data <= 0x%x\n", data); return data; }
rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, const char *bus_name) { rt_err_t res = RT_EOK; rt_mutex_init(&bus->lock, "i2c_bus_lock", RT_IPC_FLAG_FIFO); if (bus->timeout == 0) bus->timeout = RT_TICK_PER_SECOND; res = rt_i2c_bus_device_device_init(bus, bus_name); i2c_dbg("I2C bus [%s] registered\n", bus_name); return res; }
struct rt_i2c_bus_device *rt_i2c_bus_device_find(const char *bus_name) { struct rt_i2c_bus_device *bus; rt_device_t dev = rt_device_find(bus_name); if (dev == RT_NULL || dev->type != RT_Device_Class_I2CBUS) { i2c_dbg("I2C bus %s not exist\n", bus_name); return RT_NULL; } bus = (struct rt_i2c_bus_device *)dev->user_data; return bus; }
/* 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; }
/* This routine does i2c bus recovery as specified in the * i2c protocol Rev. 03 section 3.16 titled "Bus clear" */ static void i2c_recover_bus(struct davinci_i2c_dev *dev) { rt_uint32_t flag = 0; i2c_dbg("initiating i2c bus recovery\n"); /* Send NACK to the slave */ flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); flag |= DAVINCI_I2C_MDR_NACK; /* write the data into mode register */ davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); #if 0 if (pdata) generic_i2c_clock_pulse(pdata->scl_pin); #endif /* Send STOP */ flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); flag |= DAVINCI_I2C_MDR_STP; davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); }
static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) { rt_uint16_t psc; rt_uint32_t clk; rt_uint32_t d; rt_uint32_t clkh; rt_uint32_t clkl; rt_uint32_t input_clock = clk_get_rate(dev->clk); /* NOTE: I2C Clock divider programming info * As per I2C specs the following formulas provide prescaler * and low/high divider values * input clk --> PSC Div -----------> ICCL/H Div --> output clock * module clk * * output clk = module clk / (PSC + 1) [ (ICCL + d) + (ICCH + d) ] * * Thus, * (ICCL + ICCH) = clk = (input clk / ((psc +1) * output clk)) - 2d; * * where if PSC == 0, d = 7, * if PSC == 1, d = 6 * if PSC > 1 , d = 5 */ /* get minimum of 7 MHz clock, but max of 12 MHz */ psc = (input_clock / 7000000) - 1; if ((input_clock / (psc + 1)) > 12000000) psc++; /* better to run under spec than over */ d = (psc >= 2) ? 5 : 7 - psc; clk = ((input_clock / (psc + 1)) / (dev->bus_freq * 1000)) - (d << 1); clkh = clk >> 1; clkl = clk - clkh; davinci_i2c_write_reg(dev, DAVINCI_I2C_PSC_REG, psc); davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); i2c_dbg("input_clock = %d, CLK = %d\n", input_clock, clk); }
static int rk29_event_occurred(struct rk29_i2c_data *i2c) { unsigned long isr, lsr; isr = readl(i2c->regs + I2C_ISR); lsr = readl(i2c->regs + I2C_LSR); i2c_dbg(i2c->dev,"event occurred, isr = %lx, lsr = %lx\n", isr, lsr); if(isr & I2C_ISR_ARBITR_LOSE) { writel(0, i2c->regs + I2C_ISR); i2c->cmd_err = RK29_ERROR_ARBITR_LOSE; i2c_err(i2c->dev, "<error>arbitration loss\n"); return 0; } switch(i2c->cmd_event) { case RK29_EVENT_MTX_RCVD_ACK: if(isr & I2C_ISR_MTX_RCVD_ACK) { isr &= ~I2C_ISR_MTX_RCVD_ACK; writel(isr, i2c->regs + I2C_ISR); return 1; } break; case RK29_EVENT_MRX_NEED_ACK: if(isr & I2C_ISR_MRX_NEED_ACK) { isr &= ~I2C_ISR_MRX_NEED_ACK; writel(isr, i2c->regs + I2C_ISR); return 1; } break; default: break; } writel(0, i2c->regs + I2C_ISR); i2c->cmd_err = RK29_ERROR_UNKNOWN; return 0; }
static int rk29_send_2nd_addr(struct rk29_i2c_data *i2c, struct i2c_msg *msg, int start) { int ret = 0; unsigned long lsr; unsigned long addr_2nd = msg->addr & 0xff; i2c_dbg(i2c->dev, "i2c send addr_2nd: %lx\n", addr_2nd); writel(addr_2nd, i2c->regs + I2C_MTXR); if(i2c->mode == I2C_MODE_IRQ) INIT_COMPLETION(i2c->cmd_complete); writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR); rk29_set_ack(i2c); if((ret = rk29_wait_event(i2c, RK29_EVENT_MTX_RCVD_ACK)) != 0) { i2c_err(i2c->dev, "after sent addr_2nd, i2c wait for ACK timeout\n"); return ret; } lsr = readl(i2c->regs + I2C_LSR); if((lsr & I2C_LSR_RCV_NAK) && !(msg->flags & I2C_M_IGNORE_NAK)) return -EINVAL; return ret; }
/** \brief set system time(date not modify). * * \param rt_uint32_t hour e.g: 0~23. * \param rt_uint32_t minute e.g: 0~59. * \param rt_uint32_t second e.g: 0~59. * \return rt_err_t if set success, return RT_EOK. * */ rt_err_t i2c(rt_uint8_t wr, rt_uint32_t addr, rt_uint32_t reg, rt_uint32_t data) { struct rt_i2c_priv_data i2c_priv_data; struct rt_i2c_msg i2c_msg[2]; rt_uint8_t i2c_data[10]; rt_device_t device; rt_err_t ret = -RT_ERROR; device = rt_device_find("I2C"); if (device == RT_NULL) { i2c_err("Can't find I2C device.\n"); return -RT_ERROR; } if(!wr) { // Write Action i2c_msg[0].addr=addr; i2c_msg[0].flags=RT_I2C_WR ; i2c_msg[0].len=2; i2c_data[0]=reg; i2c_data[1]=data; i2c_msg[0].buf=i2c_data; i2c_priv_data.msgs=i2c_msg; i2c_priv_data.number=1; if (rt_device_open(device, 0) == RT_EOK) { i2c_dbg("write msg addr=0x%x, len=%d, reg=0x%d, data=0x%x\n",i2c_msg[0].addr, i2c_msg[0].len, i2c_data[0], i2c_data[1]); rt_device_control(device, RT_I2C_DEV_CTRL_RW, &i2c_priv_data); rt_device_close(device); } else { i2c_err("open:w err\n"); goto l_err; } } else { // Read Action // Write reg addr msg i2c_msg[0].addr=addr; i2c_msg[0].flags=RT_I2C_WR; i2c_msg[0].len=1; i2c_data[0]=reg; i2c_msg[0].buf=i2c_data; // Read data msg i2c_msg[1].addr=addr; i2c_msg[1].flags=RT_I2C_RD; i2c_msg[1].len=1; i2c_data[1]=0; i2c_msg[1].buf=&i2c_data[1]; i2c_priv_data.msgs=i2c_msg; i2c_priv_data.number=2; if (rt_device_open(device, 0) == RT_EOK) { rt_device_control(device, RT_I2C_DEV_CTRL_RW, &i2c_priv_data); i2c_dbg("read msg addr=0x%x, len=%d, addr=0x%d, data=0x%x\n",i2c_msg[0].addr, i2c_msg[0].len, i2c_data[0], i2c_data[1]); rt_device_close(device); } else { i2c_err("open:r err\n"); goto l_err; } } l_err: return ret; }
static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) { struct saa7134_dev *dev = i2c_adap->algo_data; enum i2c_status status; unsigned char data; int addr,rc,i,byte; status = i2c_get_status(dev); if (!i2c_is_idle(status)) if (!i2c_reset(dev)) return -EIO; i2c_dbg(2, "start xfer\n"); i2c_dbg(1, "i2c xfer:"); for (i = 0; i < num; i++) { if (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) { /* send address */ i2c_dbg(2, "send address\n"); addr = msgs[i].addr << 1; if (msgs[i].flags & I2C_M_RD) addr |= 1; if (i > 0 && msgs[i].flags & I2C_M_RD && msgs[i].addr != 0x40 && msgs[i].addr != 0x41 && msgs[i].addr != 0x19) { /* workaround for a saa7134 i2c bug * needed to talk to the mt352 demux * thanks to pinnacle for the hint */ int quirk = 0xfe; i2c_cont(1, " [%02x quirk]", quirk); i2c_send_byte(dev,START,quirk); i2c_recv_byte(dev); } i2c_cont(1, " < %02x", addr); rc = i2c_send_byte(dev,START,addr); if (rc < 0) goto err; } if (msgs[i].flags & I2C_M_RD) { /* read bytes */ i2c_dbg(2, "read bytes\n"); for (byte = 0; byte < msgs[i].len; byte++) { i2c_cont(1, " ="); rc = i2c_recv_byte(dev); if (rc < 0) goto err; i2c_cont(1, "%02x", rc); msgs[i].buf[byte] = rc; } /* discard mysterious extra byte when reading from Samsung S5H1411. i2c bus gets error if we do not. */ if (0x19 == msgs[i].addr) { i2c_cont(1, " ?"); rc = i2c_recv_byte(dev); if (rc < 0) goto err; i2c_cont(1, "%02x", rc); } } else { /* write bytes */ i2c_dbg(2, "write bytes\n"); for (byte = 0; byte < msgs[i].len; byte++) { data = msgs[i].buf[byte]; i2c_cont(1, " %02x", data); rc = i2c_send_byte(dev,CONTINUE,data); if (rc < 0) goto err; } } } i2c_dbg(2, "xfer done\n"); i2c_cont(1, " >"); i2c_set_attr(dev,STOP); rc = -EIO; if (!i2c_is_busy_wait(dev)) goto err; status = i2c_get_status(dev); if (i2c_is_error(status)) goto err; /* ensure that the bus is idle for at least one bit slot */ msleep(1); i2c_cont(1, "\n"); return num; err: if (1 == i2c_debug) { status = i2c_get_status(dev); i2c_cont(1, " ERROR: %s\n", str_i2c_status[status]); } return rc; }
static inline void i2c_set_attr(struct saa7134_dev *dev, enum i2c_attr attr) { i2c_dbg(2, "i2c attr => %s\n", str_i2c_attr[attr]); saa_andorb(SAA7134_I2C_ATTR_STATUS,0xc0,attr << 6); }
/* 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; }
rt_size_t i2c1_master_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num) {int de=0; struct rt_i2c_msg *msg; rt_int32_t i, ret; rt_tick_t tick=rt_tick_get(); GPIO_SetBits(GPIOB,GPIO_Pin_8|GPIO_Pin_9); while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) CHECKTIME(tick); I2C_GenerateSTART(I2Cx, ENABLE); /* Test on EV5 and clear it */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) CHECKTIME(tick); for (i = 0; i < num; i++) {de=0; msg = &msgs[i]; if (!(msg->flags & RT_I2C_NO_START)) { if (i) { I2C_GenerateSTART(I2Cx, ENABLE); while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) CHECKTIME(tick); }de=1; if (msg->flags & RT_I2C_RD) { I2C_Send7bitAddress(I2Cx, msg->addr, I2C_Direction_Receiver); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) CHECKTIME(tick); } else { I2C_Send7bitAddress(I2Cx, msg->addr, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) CHECKTIME(tick); } I2C_Cmd(I2Cx, ENABLE); } if (msg->flags & RT_I2C_RD) { ret = i2c1_recv_bytes(msg); if (ret >= 1) i2c_dbg("read %d byte%s\n", ret, ret == 1 ? "" : "s"); if (ret < msg->len) { if (ret >= 0) ret = -RT_EIO; goto out; } } else { nostart=(i+1<num && (msg[i+1].flags & RT_I2C_NO_START)) ||(msg[i].flags & I2C_RA); ret = stm32_i2c_send_bytes(msg); if (ret >= 1) i2c_dbg("write %d byte%s\n", ret, ret == 1 ? "" : "s"); if (ret < msg->len) { if (ret >= 0) ret = -RT_ERROR; goto out; } } } ret = i; return ret; out: de=-1; if(de==0)GPIO_ResetBits(GPIOB,GPIO_Pin_8);else if(de==1)GPIO_ResetBits(GPIOB,GPIO_Pin_9); i2c_dbg("error on stage %d\n",de); // I2C_GenerateSTOP(I2Cx, ENABLE); return ret; }
static inline void i2c_set_status(struct saa7134_dev *dev, enum i2c_status status) { i2c_dbg(2, "i2c stat => %s\n", str_i2c_status[status]); saa_andorb(SAA7134_I2C_ATTR_STATUS,0x0f,status); }
static rt_size_t stm32_i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num) { struct rt_i2c_msg *msg; rt_int32_t i, ret; I2C_GenerateSTART(I2C1, ENABLE); /* Test on EV5 and clear it */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); for (i = 0; i < num; i++) { msg = &msgs[i]; if (!(msg->flags & RT_I2C_NO_START)) { if (i) { I2C_GenerateSTART(I2C1, ENABLE); } I2C_SendAddress(I2C1, msg); if (msg->flags & RT_I2C_RD) while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); else while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); } if (msg->flags & RT_I2C_RD) { if (!(msg->flags & RT_I2C_NO_READ_ACK)) I2C_AcknowledgeConfig(I2C1,ENABLE); else I2C_AcknowledgeConfig(I2C1,DISABLE); ret = stm32_i2c_recv_bytes(I2C1, msg); if (ret >= 1) i2c_dbg("read %d byte%s\n", ret, ret == 1 ? "" : "s"); if (ret < msg->len) { if (ret >= 0) ret = -RT_EIO; goto out; } } else { ret = stm32_i2c_send_bytes(I2C1, msg); if (ret >= 1) i2c_dbg("write %d byte%s\n", ret, ret == 1 ? "" : "s"); if (ret < msg->len) { if (ret >= 0) ret = -RT_ERROR; goto out; } } } ret = i; out: i2c_dbg("send stop condition\n"); I2C_GenerateSTOP(I2C1, ENABLE); return ret; }
/* * Interrupt service routine. This gets called whenever an I2C interrupt * occurs. */ static void i2c_davinci_isr(int irq, void *param) { struct davinci_i2c_dev *dev = (struct davinci_i2c_dev *)param; rt_uint32_t stat; int count = 0; rt_uint16_t w; while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) { i2c_dbg("%s: stat=0x%x\n", __func__, stat); if (count++ == 100) { rt_kprintf("Too much work in one IRQ\n"); break; } switch (stat) { case DAVINCI_I2C_IVR_AL: /* Arbitration lost, must retry */ dev->cmd_err |= DAVINCI_I2C_STR_AL; dev->buf_len = 0; rt_sem_release(&dev->completion); break; case DAVINCI_I2C_IVR_NACK: dev->cmd_err |= DAVINCI_I2C_STR_NACK; dev->buf_len = 0; rt_sem_release(&dev->completion); break; case DAVINCI_I2C_IVR_ARDY: davinci_i2c_write_reg(dev, DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_ARDY); if (((dev->buf_len == 0) && (dev->stop != 0)) || (dev->cmd_err & DAVINCI_I2C_STR_NACK)) { w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); w |= DAVINCI_I2C_MDR_STP; davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); } rt_sem_release(&dev->completion); break; case DAVINCI_I2C_IVR_RDR: if (dev->buf_len) { *dev->buf++ = davinci_i2c_read_reg(dev, DAVINCI_I2C_DRR_REG); dev->buf_len--; if (dev->buf_len) continue; davinci_i2c_write_reg(dev, DAVINCI_I2C_STR_REG, DAVINCI_I2C_IMR_RRDY); } else { /* signal can terminate transfer */ terminate_read(dev); } break; case DAVINCI_I2C_IVR_XRDY: if (dev->buf_len) { davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); dev->buf_len--; if (dev->buf_len) continue; w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); w &= ~DAVINCI_I2C_IMR_XRDY; davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w); } else { /* signal can terminate transfer */ terminate_write(dev); } break; case DAVINCI_I2C_IVR_SCD: davinci_i2c_write_reg(dev, DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_SCD); rt_sem_release(&dev->completion); break; case DAVINCI_I2C_IVR_AAS: i2c_dbg("Address as slave interrupt\n"); break; default: i2c_dbg("Unrecognized irq stat %d\n", stat); break; } } }