static int s3c24x0_do_msg(struct s3c24x0_i2c_bus *i2c_bus, struct i2c_msg *msg, int seq) { struct s3c24x0_i2c *i2c = i2c_bus->regs; bool is_read = msg->flags & I2C_M_RD; uint status; uint addr; int ret, i; if (!seq) setbits_le32(&i2c->iiccon, I2CCON_ACKGEN); /* Get the slave chip address going */ addr = msg->addr << 1; writel(addr, &i2c->iicds); status = I2C_TXRX_ENA | I2C_START_STOP; if (is_read) status |= I2C_MODE_MR; else status |= I2C_MODE_MT; writel(status, &i2c->iicstat); if (seq) read_write_byte(i2c); /* Wait for chip address to transmit */ ret = WaitForXfer(i2c); if (ret) goto err; if (is_read) { for (i = 0; !ret && i < msg->len; i++) { /* disable ACK for final READ */ if (i == msg->len - 1) clrbits_le32(&i2c->iiccon, I2CCON_ACKGEN); read_write_byte(i2c); ret = WaitForXfer(i2c); msg->buf[i] = readl(&i2c->iicds); } if (ret == I2C_NACK) ret = I2C_OK; /* Normal terminated read */ } else { for (i = 0; !ret && i < msg->len; i++) { writel(msg->buf[i], &i2c->iicds); read_write_byte(i2c); ret = WaitForXfer(i2c); } } err: return ret; }
static int fci_i2c_transfer (HANDLE hDevice, u8 cmd_type, u8 chip, u8 addr[], u8 addr_len, u8 data[], u8 data_len) { int i; int result = I2C_OK; #ifdef FEATURE_SIMPLE_INTERFACE u16 cmd; #endif switch (cmd_type) { case I2C_WRITE: #ifdef FEATURE_SIMPLE_INTERFACE cmd = (I2C_CR_STA | I2C_CR_WR); cmd = (cmd<<8) | (chip | cmd_type); bbm_word_write(hDevice, BBM_I2C_TXR, cmd); #else bbm_write(hDevice, BBM_I2C_TXR, chip | cmd_type); bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STA | I2C_CR_WR /*0x90*/); #endif result = WaitForXfer(hDevice); if(result != I2C_OK) return result; if (addr && addr_len) { i = 0; while ((i < addr_len) && (result == I2C_OK)) { #ifdef FEATURE_SIMPLE_INTERFACE cmd = (I2C_CR_WR); cmd = (cmd<<8) | (addr[i]); bbm_word_write(hDevice, BBM_I2C_TXR, cmd); #else bbm_write(hDevice, BBM_I2C_TXR, addr[i]); bbm_write(hDevice, BBM_I2C_CR, I2C_CR_WR /*0x10*/); #endif result = WaitForXfer(hDevice); if(result != I2C_OK) return result; i++; } } i = 0; while ((i < data_len) && (result == I2C_OK)) { #ifdef FEATURE_SIMPLE_INTERFACE cmd = (I2C_CR_WR); cmd = (cmd<<8) | (data[i]); bbm_word_write(hDevice, BBM_I2C_TXR, cmd); #else bbm_write(hDevice, BBM_I2C_TXR, data[i]); bbm_write(hDevice, BBM_I2C_CR, I2C_CR_WR /*0x10*/); #endif result = WaitForXfer(hDevice); if(result != I2C_OK) return result; i++; } bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STO /*0x40*/); result = WaitForXfer(hDevice); if(result != I2C_OK) return result; break; case I2C_READ: if (addr && addr_len) { #ifdef FEATURE_SIMPLE_INTERFACE cmd = (I2C_CR_STA | I2C_CR_WR); cmd = (cmd<<8) | (chip | I2C_WRITE); bbm_word_write(hDevice, BBM_I2C_TXR, cmd); #else bbm_write(hDevice, BBM_I2C_TXR, chip | I2C_WRITE); bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STA | I2C_CR_WR /*0x90*/); // send start #endif result = WaitForXfer(hDevice); if(result != I2C_OK) { return result; } i = 0; while ((i < addr_len) && (result == I2C_OK)) { #ifdef FEATURE_SIMPLE_INTERFACE cmd = (I2C_CR_WR); cmd = (cmd<<8) | (addr[i]); bbm_word_write(hDevice, BBM_I2C_TXR, cmd); #else bbm_write(hDevice, BBM_I2C_TXR, addr[i]); bbm_write(hDevice, BBM_I2C_CR, I2C_CR_WR /*0x10*/); #endif result = WaitForXfer(hDevice); if(result != I2C_OK) { return result; } i++; } } #ifdef FEATURE_SIMPLE_INTERFACE cmd = (I2C_CR_STA | I2C_CR_WR); cmd = (cmd<<8) | (chip | I2C_READ); bbm_word_write(hDevice, BBM_I2C_TXR, cmd); #else bbm_write(hDevice, BBM_I2C_TXR, chip | I2C_READ); bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STA | I2C_CR_WR /*0x90*/); // resend start #endif result = WaitForXfer(hDevice); if(result != I2C_OK) { return result; } i = 0; while ((i < data_len) && (result == I2C_OK)) { if (i == data_len - 1) { bbm_write(hDevice, BBM_I2C_CR, I2C_CR_RD|I2C_CR_NACK/*0x28*/); // No Ack Read result = WaitForXfer(hDevice); if((result != I2C_NACK) && (result != I2C_OK)){ PRINTF(hDevice, "NACK4-0[%02x]\n", result); return result; } } else { bbm_write(hDevice, BBM_I2C_CR, I2C_CR_RD /*0x20*/); // Ack Read result = WaitForXfer(hDevice); if(result != I2C_OK){ PRINTF(hDevice, "NACK4-1[%02x]\n", result); return result; } } bbm_read(hDevice, BBM_I2C_RXR, &data[i]); i++; } bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STO /*0x40*/); // send stop result = WaitForXfer(hDevice); if((result != I2C_NACK) && (result != I2C_OK)) { PRINTF(hDevice, "NACK5[%02X]\n", result); return result; } break; default: return I2C_NOK; } return I2C_OK; }
/* * cmd_type is 0 for write, 1 for read. * * addr_len can take any value from 0-255, it is only limited * by the char, we could make it larger if needed. If it is * 0 we skip the address write cycle. */ static int i2c_transfer(struct s3c24x0_i2c *i2c, unsigned char cmd_type, unsigned char chip, unsigned char addr[], unsigned char addr_len, unsigned char data[], unsigned short data_len) { int i = 0, result; ulong start_time = get_timer(0); if (data == 0 || data_len == 0) { /*Don't support data transfer of no length or to address 0 */ debug("i2c_transfer: bad call\n"); return I2C_NOK; } while (readl(&i2c->iicstat) & I2CSTAT_BSY) { if (get_timer(start_time) > I2C_TIMEOUT_MS) return I2C_NOK_TOUT; } writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon); /* Get the slave chip address going */ writel(chip, &i2c->iicds); if ((cmd_type == I2C_WRITE) || (addr && addr_len)) writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, &i2c->iicstat); else writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP, &i2c->iicstat); /* Wait for chip address to transmit. */ result = WaitForXfer(i2c); if (result != I2C_OK) goto bailout; /* If register address needs to be transmitted - do it now. */ if (addr && addr_len) { while ((i < addr_len) && (result == I2C_OK)) { writel(addr[i++], &i2c->iicds); read_write_byte(i2c); result = WaitForXfer(i2c); } i = 0; if (result != I2C_OK) goto bailout; } switch (cmd_type) { case I2C_WRITE: while ((i < data_len) && (result == I2C_OK)) { writel(data[i++], &i2c->iicds); read_write_byte(i2c); result = WaitForXfer(i2c); } break; case I2C_READ: if (addr && addr_len) { /* * Register address has been sent, now send slave chip * address again to start the actual read transaction. */ writel(chip, &i2c->iicds); /* Generate a re-START. */ writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP, &i2c->iicstat); read_write_byte(i2c); result = WaitForXfer(i2c); if (result != I2C_OK) goto bailout; } while ((i < data_len) && (result == I2C_OK)) { /* disable ACK for final READ */ if (i == data_len - 1) writel(readl(&i2c->iiccon) & ~I2CCON_ACKGEN, &i2c->iiccon); read_write_byte(i2c); result = WaitForXfer(i2c); data[i++] = readl(&i2c->iicds); } if (result == I2C_NACK) result = I2C_OK; /* Normal terminated read. */ break; default: debug("i2c_transfer: bad call\n"); result = I2C_NOK; break; } bailout: /* Send STOP. */ writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat); read_write_byte(i2c); return result; }
static int fci_i2c_transfer (HANDLE hDevice, fci_u8 cmd_type, fci_u8 chip, fci_u8 addr[], fci_u8 addr_len, fci_u8 data[], fci_u8 data_len) { int i; int result = I2C_OK; switch (cmd_type) { case I2C_WRITE: bbm_write(hDevice, BBM_I2C_TXR, chip | cmd_type); bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STA | I2C_CR_WR /*0x90*/); result = WaitForXfer(hDevice); if(result != I2C_OK) return result; if (addr && addr_len) { i = 0; while ((i < addr_len) && (result == I2C_OK)) { bbm_write(hDevice, BBM_I2C_TXR, addr[i]); bbm_write(hDevice, BBM_I2C_CR, I2C_CR_WR /*0x10*/); result = WaitForXfer(hDevice); if(result != I2C_OK) return result; i++; } } i = 0; while ((i < data_len) && (result == I2C_OK)) { bbm_write(hDevice, BBM_I2C_TXR, data[i]); bbm_write(hDevice, BBM_I2C_CR, I2C_CR_WR /*0x10*/); result = WaitForXfer(hDevice); if(result != I2C_OK) return result; i++; } bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STO /*0x40*/); result = WaitForXfer(hDevice); if(result != I2C_OK) return result; break; case I2C_READ: if (addr && addr_len) { bbm_write(hDevice, BBM_I2C_TXR, chip | I2C_WRITE); bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STA | I2C_CR_WR /*0x90*/); // send start result = WaitForXfer(hDevice); if(result != I2C_OK) { return result; } i = 0; while ((i < addr_len) && (result == I2C_OK)) { bbm_write(hDevice, BBM_I2C_TXR, addr[i]); bbm_write(hDevice, BBM_I2C_CR, I2C_CR_WR /*0x10*/); result = WaitForXfer(hDevice); if(result != I2C_OK) { return result; } i++; } } bbm_write(hDevice, BBM_I2C_TXR, chip | I2C_READ); bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STA | I2C_CR_WR /*0x90*/); // resend start result = WaitForXfer(hDevice); if(result != I2C_OK) { return result; } i = 0; while ((i < data_len) && (result == I2C_OK)) { if (i == data_len - 1) { bbm_write(hDevice, BBM_I2C_CR, I2C_CR_RD|I2C_CR_NACK/*0x28*/); // No Ack Read result = WaitForXfer(hDevice); if((result != I2C_NACK) && (result != I2C_OK)){ PRINTF(hDevice, "NACK4-0[%02x]\n\r", result); return result; } } else { bbm_write(hDevice, BBM_I2C_CR, I2C_CR_RD /*0x20*/); // Ack Read result = WaitForXfer(hDevice); if(result != I2C_OK){ PRINTF(hDevice, "NACK4-1[%02x]\n\r", result); return result; } } bbm_read(hDevice, BBM_I2C_RXR, &data[i]); i++; } bbm_write(hDevice, BBM_I2C_CR, I2C_CR_STO /*0x40*/); // send stop result = WaitForXfer(hDevice); if((result != I2C_NACK) && (result != I2C_OK)) { PRINTF(hDevice, "NACK5[%02X]\n\r", result); return result; } break; default: return I2C_NOK; } return I2C_OK; }