#include <common.h>
#ifdef CONFIG_LPC32XX_I2C
#ifdef CONFIG_HARD_I2C
#include <command.h>
#include <i2c.h> /* Functional interface */
#include <asm/io.h>
//#include /* HW definitions */
#include <lpc3250.h>
#include "lpc32xx_i2c.h"
#define I2C_READ_BIT 1
#define I2C_WRITE_BIT 0
#define I2C_START_BIT (1<<8)
#define I2C_STOP_BIT (1<<9)
#define WAIT_RESET 0x300000
#define WAIT_TIME 0x300000
DECLARE_GLOBAL_DATA_PTR;
void i2c_reset(void)
{
int wait = 0;
while((I2C1->i2c_stat & mstatus_active) != 0) {
if ((++wait) > WAIT_RESET) {
printf("%s wait timeout\n", __FUNCTION__);
break;
}
}
I2C1->i2c_ctrl = (mcntrl_tdie | mcntrl_afie); //0x03
//reset i2c1 clock
I2C1->i2c_ctrl = mcntrl_reset;//1<<8;
wait = 0;
while((I2C1->i2c_stat & mstatus_rff) != 0) {
if ((++wait) > WAIT_RESET) {
printf("%s FAILED\n", __FUNCTION__);
return 1;
}
}
I2C1->i2c_ctrl = (mcntrl_tdie | mcntrl_afie); //0x03
}
void i2c_init(int speed, int slaveadd)
{
// printf("####ABING in %s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
CLKPWR->clkpwr_i2c_clk_ctrl |= 1; //enable I2C1 clock
/* Fscl = 100kHz */
I2C1->i2c_clk_hi = 520;
I2C1->i2c_clk_lo = 520;
i2c_reset();
}
int i2c_probe(uchar chip)
{
printf("####ABING in %s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
}
int i2c_set_bus_speed(unsigned int speed)
{
printf("####ABING in %s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
}
unsigned int i2c_get_bus_speed(void)
{
printf("####ABING in %s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
}
#if 0
static int i2c_read_byte (u8 sla, u8 suba, u8 * value)
{
printf("####ABING in %s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
}
static int i2c_write_byte (u8 sla, u8 suba, u8 value)
{
printf("####ABING in %s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
}
#endif
int i2c_read (uchar sla, uint suba, int alen, uchar *buf, int len)
{
int wait = 0;
int stat;
char data;
printf("sla = 0x%0x, suba=0x%0x, len=0x%0x\n", sla, suba, len);
if (suba + len > 256) {
printf ("I2C read: address out of range\n");
return 1;
}
i2c_reset();
I2C1->i2c_ctrl = 0;
I2C1->i2c_txrx = ((sla & 0xfe) | I2C_START_BIT | I2C_WRITE_BIT);
//waiting for transmit OK
wait = 0;
while((I2C1->i2c_stat & mstatus_tfe) == 0) {
if (++wait > WAIT_TIME) {
i2c_reset();
return 1;
}
}
I2C1->i2c_txrx = suba;
//waiting for transmit OK
wait = 0;
while((I2C1->i2c_stat & mstatus_tfe) == 0) {
if (++wait > WAIT_TIME) {
i2c_reset();
return 1;
}
}
I2C1->i2c_txrx = ((sla & 0xfe) | I2C_START_BIT | I2C_READ_BIT);
//waiting for transmit OK
wait = 0;
while((I2C1->i2c_stat & mstatus_tfe) == 0) {
if (++wait > WAIT_TIME) {
i2c_reset();
return 1;
}
}
if (len == 1) {
printf("len=%d\n", len);
I2C1->i2c_txrx = 0xFF; //write a dummy byte
//waiting for transmit OK
wait = 0;
while((I2C1->i2c_stat & mstatus_tfe) == 0) {
if (++wait > WAIT_TIME) {
i2c_reset();
return 1;
}
}
//waiting for receive data
wait = 0;
while((I2C1->i2c_stat & mstatus_rfe) == 1) {
if (++wait > WAIT_TIME) {
i2c_reset();
return 1;
}
}
//put data into buf
stat= ((I2C1->i2c_stat) & mstatus_rfe);
//if (((I2C1->i2c_stat) & (1<<9) == 0)) {
if (stat==0) {
data = (unsigned char)(I2C1->i2c_txrx);
*buf++ = data;
// printf("read1 0x%0x\n", data);
len--;
}
I2C1->i2c_txrx = (0xFF | I2C_STOP_BIT);
//waiting for trasmit OK
wait = 0;
while((I2C1->i2c_stat & mstatus_tfe) == 0) {
if (++wait > WAIT_TIME) {
i2c_reset();
return 1;
}
}
//waiting for receive data
wait = 0;
while((I2C1->i2c_stat & mstatus_rfe) == 1) {
if (++wait > WAIT_TIME) {
break;
}
}
if ((I2C1->i2c_stat & mstatus_rfe) == 0) {
I2C1->i2c_txrx;
}
//waiting until bus is idle
wait = 0;
while((I2C1->i2c_stat & mstatus_active) == 1) {
if (++wait > 2*WAIT_TIME) {
i2c_reset();
break;
}
}
//i2c_reset();
return 0;
}
while(len > 0) {
if (len == 1) {
I2C1->i2c_txrx = 0xFF | I2C_STOP_BIT;
} else {
I2C1->i2c_txrx = 0xFF;
}
//waiting for transmit OK
wait = 0;
while((I2C1->i2c_stat & mstatus_tfe) == 0) {
if (++wait > WAIT_TIME) {
i2c_reset();
return 1;
}
}
//waiting for receive
wait = 0;
while((I2C1->i2c_stat & mstatus_rfe) == 1) {
if (++wait > WAIT_TIME) {
i2c_reset();
return 1;
}
}
//put data to buf
stat = ((I2C1->i2c_stat) & mstatus_rfe);
//if (I2C1->i2c_stat & mstatus_rfe == 0) {
if (stat == 0) {
data = (unsigned char)(I2C1->i2c_txrx);
*buf++ = data;
//printf("read2 0x%0x", data);
len--;
//printf("len=%d\n", len);
}
// waiting until bus is idle
wait = 0;
while((I2C1->i2c_stat & mstatus_active) == 1) {
if (++wait > 2*WAIT_TIME) {
i2c_reset();
break;
}
}
}
//i2c_reset();
return 0;
}
int i2c_write (uchar sla, uint suba, int alen, uchar *buf, int len)
{
int wait = 0;
int stat = 0;
// printf("####ABING in %s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
//i2c_reset();
if (suba + len > 256) {
printf ("I2C read: address out of range\n");
return 1;
}
I2C1->i2c_ctrl = 0;
I2C1->i2c_txrx=((sla & 0xfe) | I2C_START_BIT | I2C_WRITE_BIT);
//waiting for transmit OK
wait = 0;
while((I2C1->i2c_stat & mstatus_tfe) == 0) {
if ((++wait) > WAIT_TIME) {
i2c_reset();
return 1;
}
}
I2C1->i2c_txrx = suba;
//waiting for transmit OK
wait = 0;
while((I2C1->i2c_stat & mstatus_tfe) == 0) {
if ((++wait) > WAIT_TIME) {
i2c_reset();
return 1;
}
}
while (len > 0)
{
if (len == 1) {
I2C1->i2c_txrx = (*buf | I2C_STOP_BIT);
} else {
I2C1->i2c_txrx = *buf;
}
//waiting for transmit OK
wait = 0;
while((I2C1->i2c_stat & mstatus_tfe) == 0) {
if ((++wait) > WAIT_TIME) {
i2c_reset();
return 1;
}
}
//see if error happen
stat = (I2C1->i2c_stat & (mstatus_afi | mstatus_nai));
//if ((I2C1->i2c_stat & (mstatus_afi | mstatus_nai)) != 0) {
if (stat != 0) {
printf("write error!\n");
i2c_reset();
return 1;
}
buf++;
len--;
//waiting for transmit OK
wait = 0;
while((I2C1->i2c_stat & mstatus_tdi) == 0) {
if ((++wait) > WAIT_TIME) {
i2c_reset();
break;
}
}
}
return 0;
}
#endif /* CONFIG_HARD_I2C */
#endif /* CONFIG_LPC32XX_I2C */
|