static int i2c_read(RkI2cReg *reg_addr, I2cSeg segment) { int res = 0; uint8_t *data = segment.buf; int timeout = I2C_TIMEOUT_US; unsigned int bytes_remaining = segment.len; unsigned int bytes_transfered = 0; unsigned int words_transfered = 0; unsigned int rxdata = 0; unsigned int con = 0; unsigned int i, j; writel(I2C_8BIT | segment.chip << 1 | 1, ®_addr->i2c_mrxaddr); writel(0, ®_addr->i2c_mrxraddr); con = I2C_MODE_TRX | I2C_EN | I2C_ACT2NAK; while (bytes_remaining) { bytes_transfered = MIN(bytes_remaining, 32); bytes_remaining -= bytes_transfered; if(!bytes_remaining) con |= I2C_EN | I2C_NAK; words_transfered = ALIGN_UP(bytes_transfered, 4) / 4; writel(I2C_CLEANI, ®_addr->i2c_ipd); writel(con, ®_addr->i2c_con); writel(bytes_transfered, ®_addr->i2c_mrxcnt); timeout = I2C_TIMEOUT_US; while (timeout--) { if (readl(®_addr->i2c_ipd) & I2C_NAKRCVI) { writel(0, ®_addr->i2c_mrxcnt); writel(0, ®_addr->i2c_con); return I2C_NOACK; } if (readl(®_addr->i2c_ipd) & I2C_MBRFI) break; udelay(1); } if (timeout <= 0) { i2c_err("I2C Read::Recv Data Timeout\n"); writel(0, ®_addr->i2c_mrxcnt); writel(0, ®_addr->i2c_con); return I2C_TIMEOUT; } for (i = 0; i < words_transfered; i++) { rxdata = readl(®_addr->rxdata[i]); i2c_info("I2c Read::RXDATA[%d] = 0x%x\n", i, rxdata); for (j = 0; j < 4; j++) { if ((i * 4 + j) == bytes_transfered) break; *data++ = (rxdata >> (j * 8)) & 0xff; } } con = I2C_MODE_RX | I2C_EN | I2C_ACT2NAK; } return res; }
// send repeated start condition void i2cf_rstart() { if( (TWSR & 0xF8) == 0x28 ) { TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA) | (1<<TWIE); i2c_next = i2cf_raddress; i2c_state = 8; } else { i2c_err(); } }
// write i2c address void i2cf_address() { if( (TWSR & 0xF8) == 0x08 ) { TWDR = i2c_address; TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE); i2c_next = i2cf_register; i2c_state = 13; } else { i2c_err(); } }
// send i2c read address void i2cf_raddress() { if( (TWSR & 0xF8) == 0x10 ) { TWDR = i2c_address | 1; TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE); i2c_next = i2cf_read; i2c_state = 7; } else { i2c_err(); } }
static int i2c_write(RkI2cReg *reg_addr, I2cSeg segment) { int res = 0; uint8_t *data = segment.buf; int timeout = I2C_TIMEOUT_US; int bytes_remaining = segment.len + 1; int bytes_transfered = 0; int words_transfered = 0; unsigned int i; unsigned int j = 1; u32 txdata = 0; txdata |= (segment.chip << 1); while (bytes_remaining) { bytes_transfered = MIN(bytes_remaining, 32); words_transfered = ALIGN_UP(bytes_transfered, 4) / 4; for (i = 0; i < words_transfered; i++) { do { if ((i * 4 + j) == bytes_transfered) break; txdata |= (*data++) << (j * 8); } while (++j < 4); writel(txdata, ®_addr->txdata[i]); j = 0; i2c_info("I2c Write::TXDATA[%d] = 0x%x\n", i, txdata); txdata = 0; } writel(I2C_CLEANI, ®_addr->i2c_ipd); writel(I2C_EN | I2C_MODE_TX | I2C_ACT2NAK, ®_addr->i2c_con); writel(bytes_transfered, ®_addr->i2c_mtxcnt); timeout = I2C_TIMEOUT_US; while (timeout--) { if (readl(®_addr->i2c_ipd) & I2C_NAKRCVI) { writel(0, ®_addr->i2c_mtxcnt); writel(0, ®_addr->i2c_con); return I2C_NOACK; } if (readl(®_addr->i2c_ipd) & I2C_MBTFI) break; udelay(1); } if (timeout <= 0) { i2c_err("I2C Write::Send Data Timeout\n"); writel(0, ®_addr->i2c_mtxcnt); writel(0, ®_addr->i2c_con); return I2C_TIMEOUT; } bytes_remaining -= bytes_transfered; } return res; }
// write i2c data void i2cf_wdata() { if( (TWSR & 0xF8) == 0x28 ) { TWDR = *i2c_data; ++i2c_data; --i2c_data_sz; if( i2c_data_sz == 0 ) { i2c_next = i2cf_wstop; i2c_state = 10; } TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE); } else { i2c_err(); } }
static int rk29_wait_event(struct rk29_i2c_data *i2c, enum rk29_event mr_event) { int ret = 0; if(unlikely(irqs_disabled())) { i2c_err(i2c->dev, "irqs are disabled on this system!\n"); return -EIO; } i2c->cmd_err = RK29_ERROR_NONE; i2c->cmd_event = mr_event; rk29_i2c_enable_irqs(i2c); if(i2c->mode == I2C_MODE_IRQ) { ret = wait_for_completion_interruptible_timeout(&i2c->cmd_complete, usecs_to_jiffies(i2c->ack_timeout)); } else { i2c->poll_status = 0; ret = wait_for_completion_poll_timeout(i2c); } if(ret < 0) { i2c_err(i2c->dev, "i2c wait for event %04x, retrun %d \n", mr_event, ret); return ret; } if(ret == 0) { i2c_err(i2c->dev, "i2c wait for envent timeout, but not return -ETIMEDOUT\n"); return 0; //return -ETIMEDOUT; } return 0; }
// write i2c register void i2cf_register() { if( (TWSR & 0xF8) == 0x18 ) { TWDR = i2c_register; TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE); if( i2c_mode == WRITE ) { i2c_next = i2cf_wdata; i2c_state = 11; } else { i2c_next = i2cf_rstart; i2c_state = 12; } } else { i2c_err(); } }
static int i2c_send_stop(RkI2cReg *reg_addr) { int res = 0; int timeout = I2C_TIMEOUT_US; i2c_info("I2c Stop::Send Stop bit\n"); writel(I2C_CLEANI, ®_addr->i2c_ipd); writel(I2C_EN | I2C_STOP, ®_addr->i2c_con); while (timeout--) { if (readl(®_addr->i2c_ipd) & I2C_STOPI) break; udelay(1); } writel(0, ®_addr->i2c_con); if (timeout <= 0) { i2c_err("I2C Stop::Send Stop Bit Timeout\n"); res = I2C_TIMEOUT; } return res; }
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; }
void i2cf_read() { if( (TWSR & 0xF8) == 0x40 ) { // if we sent an address, wait for data --i2c_data_sz; if( i2c_data_sz > 0 ) { // we want more data; transmit ack TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA) | (1<<TWIE); } else { // the next byte will be the last TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE); } i2c_next = i2cf_read; i2c_state = 3; } else if( (TWSR & 0xF8) == 0x50 ) { // if we received data, wait for more data or nak i2c_data[i2c_data_pos++] = TWDR; --i2c_data_sz; if( i2c_data_sz > 0 ) { // we want more data; transmit ack TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA) | (1<<TWIE); } else { // the next byte will be the last TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE); } i2c_next = i2cf_read; i2c_state = 4; } else if( (TWSR & 0xF8) == 0x58 ) { // we got our last byte and sent nak i2c_data[i2c_data_pos] = TWDR; TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO) | (1<<TWIE); i2c_ready = 1; i2c_next = i2c_none; i2c_state = 5; sei(); if(i2c_r_callback) { void (*tmp_callback)(uint8_t*) = i2c_r_callback; i2c_r_callback = 0; tmp_callback(i2c_data); } else { i2c_err(); } } else if( (TWSR & 0xF8) == 0x08 ) { // Start sent. shouldn't happen i2c_err(); } else if( (TWSR & 0xF8) == 0x10 ) { // repeated start sent. shouldn't happen //led_on(); i2c_err(); } else if( (TWSR & 0xF8) == 0x38 ) { // arbitration lost or NAK i2c_err(); } else if( (TWSR & 0xF8) == 0x48 ) { // SLA+R sent; NAK received // generate a stop condition //TWCR = (1<<TWSTA) | (1<<TWSTO) | (1<<TWINT); //i2c_next = i2cf_address; i2c_err(); i2c_state = 6; } else { i2c_err(); } }
static int __init i2c_davinci_init(void) { int status; struct device *dev = NULL; DEB0("%s %s", __TIME__, __DATE__); DEB1("i2c_davinci_init()\n"); davinci_i2c_fix_ths7353_lockup( ); #if 0 if (i2c_davinci_busFreq > 200) i2c_davinci_busFreq = 400; /*Fast mode */ else i2c_davinci_busFreq = 100; /*Standard mode */ #endif i2c_clock = clk_get (dev, "I2CCLK"); if (i2c_clock == NULL) return -1; clk_use (i2c_clock); clk_enable (i2c_clock); i2c_davinci_inputClock = clk_get_rate (i2c_clock); DEB1 ("IP CLOCK = %ld\n", i2c_davinci_inputClock); memset(&i2c_davinci_dev, 0, sizeof(i2c_davinci_dev)); i2c_davinci_dev.regs = (davinci_i2cregsovly)I2C_BASE; status = (int)request_region(I2C_BASE, I2C_IOSIZE, MODULE_NAME); if (!status) { i2c_err("I2C is already in use\n"); return -ENODEV; } status = request_irq(IRQ_I2C, i2c_davinci_isr, 0, MODULE_NAME, &i2c_davinci_dev); if (status) { i2c_err("failed to request I2C IRQ"); goto do_release_region; } i2c_set_adapdata(&i2c_davinci_adap, &i2c_davinci_dev); status = i2c_add_adapter(&i2c_davinci_adap); if (status) { i2c_err("failed to add adapter"); goto do_free_irq; return status; } i2c_davinci_reset(&i2c_davinci_dev); if (driver_register(&davinci_i2c_driver) != 0) printk(KERN_ERR "Driver register failed for davinci_i2c\n"); if (platform_device_register(&davinci_i2c_device) != 0) { printk(KERN_ERR "Device register failed for i2c\n"); driver_unregister(&davinci_i2c_driver); } return 0; do_free_irq: free_irq(IRQ_I2C, &i2c_davinci_dev); do_release_region: release_region(I2C_BASE, I2C_IOSIZE); return status; }
static int __init i2c_davinci_init(void) { int status; struct device *dev = NULL; DEB0("%s %s", __TIME__, __DATE__); DEB1("i2c_davinci_init()"); if (cpu_is_davinci_dm6467()) davinci_i2c_expander_op (0x3A, I2C_INT_DM646X, 0); /* * NOTE: On DaVinci EVM, the i2c bus frequency is set to 20kHz * so that the MSP430, which is doing software i2c, has * some extra processing time */ if (machine_is_davinci_evm()) i2c_davinci_busFreq = 20; else if (machine_is_davinci_dm6467_evm()) i2c_davinci_busFreq = 100; else if (i2c_davinci_busFreq > 200) i2c_davinci_busFreq = 400; /*Fast mode */ else i2c_davinci_busFreq = 100; /*Standard mode */ i2c_clock = clk_get (dev, "I2CCLK"); if (IS_ERR(i2c_clock)) return -1; clk_use (i2c_clock); clk_enable (i2c_clock); i2c_davinci_inputClock = clk_get_rate (i2c_clock); DEB1 ("IP CLOCK = %ld", i2c_davinci_inputClock); memset(&i2c_davinci_dev, 0, sizeof(i2c_davinci_dev)); init_waitqueue_head(&i2c_davinci_dev.cmd_wait); i2c_davinci_dev.regs = (davinci_i2cregsovly)I2C_BASE; status = (int)request_region(I2C_BASE, I2C_IOSIZE, MODULE_NAME); if (!status) { i2c_err("I2C is already in use\n"); return -ENODEV; } status = request_irq(IRQ_I2C, i2c_davinci_isr, 0, "i2c", &i2c_davinci_dev); if (status) { i2c_err("failed to request I2C IRQ"); goto do_release_region; } i2c_set_adapdata(&i2c_davinci_adap, &i2c_davinci_dev); status = i2c_add_adapter(&i2c_davinci_adap); if (status) { i2c_err("failed to add adapter"); goto do_free_irq; } i2c_davinci_reset(&i2c_davinci_dev); if (driver_register(&davinci_i2c_driver) != 0) printk(KERN_ERR "Driver register failed for davinci_i2c\n"); if (platform_device_register(&davinci_i2c_device) != 0) { printk(KERN_ERR "Device register failed for i2c\n"); driver_unregister(&davinci_i2c_driver); } return 0; do_free_irq: free_irq(IRQ_I2C, &i2c_davinci_dev); do_release_region: release_region(I2C_BASE, I2C_IOSIZE); return status; }
/** \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; }