You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
409 lines
6.8 KiB
409 lines
6.8 KiB
#ifdef DEVBD2F_SM502
|
|
static volatile char *mmio = 0;
|
|
|
|
#define GPIO_DIR_REG (volatile unsigned int *)(mmio + 0x1000c)
|
|
#define GPIO_DATA_REG (volatile unsigned int *)(mmio + 0x10004)
|
|
#define G_OUTPUT 1
|
|
#define G_INPUT 0
|
|
#define GPIO_SDA_DIR_SHIFT 15
|
|
#define GPIO_SCL_DIR_SHIFT 14
|
|
#define GPIO_SDA_DATA_SHIFT 15
|
|
#define GPIO_SCL_DATA_SHIFT 14
|
|
|
|
#elif defined(DEVBD2F_FIREWALL)
|
|
|
|
#define GPIO_DIR_REG (volatile unsigned int *)(0xbfe00120)
|
|
#define GPIO_DATA_REG (volatile unsigned int *)(0xbfe0011c)
|
|
|
|
#define G_OUTPUT 0
|
|
#define G_INPUT 1
|
|
#define GPIO_SDA_DIR_SHIFT 2
|
|
#define GPIO_SCL_DIR_SHIFT 3
|
|
#define GPIO_SDA_DATA_SHIFT 2
|
|
#define GPIO_SCL_DATA_SHIFT 3
|
|
//extern int word_addr = 0;
|
|
|
|
#endif
|
|
|
|
static void i2c_sleep(int ntime)
|
|
{
|
|
int i,j=0;
|
|
for(i=0; i<300*ntime; i++)
|
|
{
|
|
j=i;
|
|
j+=i;
|
|
}
|
|
}
|
|
|
|
void sda_dir(int ivalue)
|
|
{
|
|
int tmp;
|
|
tmp = *GPIO_DIR_REG;
|
|
if(ivalue == 1)
|
|
*GPIO_DIR_REG = tmp|(0x1<<GPIO_SDA_DIR_SHIFT);
|
|
else
|
|
*GPIO_DIR_REG = tmp&(~(0x1<<GPIO_SDA_DIR_SHIFT));
|
|
}
|
|
void scl_dir(int ivalue)
|
|
{
|
|
int tmp;
|
|
tmp = *GPIO_DIR_REG;
|
|
if(ivalue == 1)
|
|
*GPIO_DIR_REG = tmp|(0x1<<GPIO_SCL_DIR_SHIFT);
|
|
else
|
|
*GPIO_DIR_REG = tmp&(~(0x1<<GPIO_SCL_DIR_SHIFT));
|
|
}
|
|
|
|
void sda_bit(int ivalue)
|
|
{
|
|
int tmp;
|
|
tmp = *GPIO_DATA_REG;
|
|
if(ivalue == 1)
|
|
*GPIO_DATA_REG = tmp|(0x1<<GPIO_SDA_DATA_SHIFT);
|
|
else
|
|
*GPIO_DATA_REG = tmp&(~(0x1<<GPIO_SDA_DATA_SHIFT));
|
|
}
|
|
void scl_bit(int ivalue)
|
|
{
|
|
int tmp;
|
|
tmp = *GPIO_DATA_REG;
|
|
if(ivalue == 1)
|
|
*GPIO_DATA_REG = tmp|(0x1<<GPIO_SCL_DATA_SHIFT);
|
|
else
|
|
*GPIO_DATA_REG = tmp&(~(0x1<<GPIO_SCL_DATA_SHIFT));
|
|
}
|
|
|
|
|
|
static void i2c_start(void)
|
|
{
|
|
sda_dir(G_OUTPUT);
|
|
scl_dir(G_OUTPUT);
|
|
scl_bit(0);
|
|
i2c_sleep(1);
|
|
sda_bit(1);
|
|
i2c_sleep(1);
|
|
scl_bit(1);
|
|
i2c_sleep(5);
|
|
sda_bit(0);
|
|
i2c_sleep(5);
|
|
scl_bit(0);
|
|
i2c_sleep(2);
|
|
|
|
}
|
|
static void i2c_stop(void)
|
|
{
|
|
sda_dir(G_OUTPUT);
|
|
scl_dir(G_OUTPUT);
|
|
scl_bit(0);
|
|
i2c_sleep(1);
|
|
sda_bit(0);
|
|
i2c_sleep(1);
|
|
scl_bit(1);
|
|
i2c_sleep(5);
|
|
sda_bit(1);
|
|
i2c_sleep(5);
|
|
scl_bit(0);
|
|
i2c_sleep(2);
|
|
|
|
|
|
}
|
|
|
|
static void i2c_send_ack(int ack)
|
|
{
|
|
sda_dir(G_OUTPUT);
|
|
sda_bit(ack);
|
|
i2c_sleep(3);
|
|
scl_bit(1);
|
|
i2c_sleep(5);
|
|
scl_bit(0);
|
|
i2c_sleep(2);
|
|
}
|
|
|
|
static char i2c_rec_ack()
|
|
{
|
|
char res = 1;
|
|
int num=10;
|
|
int tmp;
|
|
sda_dir(G_INPUT);
|
|
i2c_sleep(3);
|
|
scl_bit(1);
|
|
i2c_sleep(5);
|
|
#ifdef DEVBD2F_SM502
|
|
tmp = ((*GPIO_DATA_REG)&(0x1<<GPIO_SDA_DATA_SHIFT));
|
|
#elif DEVBD2F_FIREWALL
|
|
tmp = ((*GPIO_DATA_REG)&(0x1<<(GPIO_SDA_DATA_SHIFT+16)));
|
|
#endif
|
|
//wait for a ack signal from slave
|
|
|
|
while(tmp)
|
|
{
|
|
i2c_sleep(1);
|
|
num--;
|
|
if(!num)
|
|
{
|
|
res = 0;
|
|
break;
|
|
}
|
|
#ifdef DEVBD2F_SM502
|
|
tmp = ((*GPIO_DATA_REG)&(0x1<<GPIO_SDA_DATA_SHIFT));
|
|
#elif DEVBD2F_FIREWALL
|
|
tmp = ((*GPIO_DATA_REG)&(0x1<<(GPIO_SDA_DATA_SHIFT+16)));
|
|
#endif
|
|
}
|
|
scl_bit(0);
|
|
i2c_sleep(3);
|
|
return res;
|
|
}
|
|
|
|
|
|
static unsigned char i2c_rec()
|
|
{
|
|
int i;
|
|
int tmp;
|
|
unsigned char or_char;
|
|
unsigned char value = 0x00;
|
|
sda_dir(G_INPUT);
|
|
for(i=7;i>=0;i--)
|
|
{
|
|
i2c_sleep(5);
|
|
scl_bit(1);
|
|
i2c_sleep(3);
|
|
#ifdef DEVBD2F_SM502
|
|
tmp = ((*GPIO_DATA_REG)&(0x1<<GPIO_SDA_DATA_SHIFT));
|
|
#elif DEVBD2F_FIREWALL
|
|
tmp = ((*GPIO_DATA_REG)&(0x1<<(GPIO_SDA_DATA_SHIFT+16)));
|
|
#endif
|
|
if(tmp)
|
|
or_char=0x1;
|
|
else
|
|
or_char=0x0;
|
|
or_char<<=i;
|
|
value|=or_char;
|
|
i2c_sleep(3);
|
|
scl_bit(0);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
static unsigned char i2c_send(unsigned char value)
|
|
{//we assume that now scl is 0
|
|
int i;
|
|
unsigned char and_char;
|
|
sda_dir(G_OUTPUT);
|
|
for(i=7;i>=0;i--)
|
|
{
|
|
and_char = value;
|
|
and_char>>=i;
|
|
and_char&=0x1;
|
|
if(and_char)
|
|
sda_bit(1);
|
|
else
|
|
sda_bit(0);
|
|
i2c_sleep(1);
|
|
scl_bit(1);
|
|
i2c_sleep(5);
|
|
scl_bit(0);
|
|
i2c_sleep(1);
|
|
}
|
|
sda_bit(1);
|
|
return 1;
|
|
}
|
|
|
|
unsigned char i2c_rec_s(unsigned char *addr,int addrlen,unsigned char reg,unsigned char* buf ,int count)
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
|
|
unsigned char value;
|
|
//start signal
|
|
for(i=0;i<count;i++)
|
|
{
|
|
i2c_start();
|
|
for(j=0;j<addrlen;j++)
|
|
{
|
|
//write slave_addr
|
|
i2c_send(addr[j]);
|
|
if(!i2c_rec_ack())
|
|
return 0;
|
|
}
|
|
|
|
i2c_send(reg);
|
|
if(!i2c_rec_ack())
|
|
return 0;
|
|
|
|
//repeat start
|
|
i2c_start();
|
|
//write slave_addr+1
|
|
i2c_send(addr[0]|0x1);
|
|
if(!i2c_rec_ack())
|
|
return 0;
|
|
//read data
|
|
buf[i]=i2c_rec();
|
|
// i2c_send_ack(1);//***add in***//
|
|
i2c_stop();
|
|
|
|
reg++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
unsigned char i2c_send_s(unsigned char *addr,int addrlen,unsigned char reg,unsigned char * buf ,int count)
|
|
{
|
|
int i;
|
|
int j;
|
|
for(i=0;i<count;i++)
|
|
{
|
|
i2c_start();
|
|
for(j=0;j<addrlen;j++)
|
|
{
|
|
//write slave_addr
|
|
i2c_send(addr[j]);
|
|
if(!i2c_rec_ack())
|
|
return 0;
|
|
}
|
|
|
|
i2c_send(reg);
|
|
if(!i2c_rec_ack())
|
|
return 0;
|
|
|
|
i2c_send(buf[i]);
|
|
if(!i2c_rec_ack())
|
|
return 0;
|
|
i2c_stop();
|
|
reg++;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
unsigned char i2c_rec_b(unsigned char *addr,int addrlen,unsigned char reg,unsigned char* buf ,int count)
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
|
|
unsigned char value;
|
|
//start signal
|
|
i2c_start();
|
|
for(j=0;j<addrlen;j++)
|
|
{
|
|
//write slave_addr
|
|
i2c_send(addr[j]);
|
|
if(!i2c_rec_ack())
|
|
return 0;
|
|
}
|
|
|
|
i2c_send(reg);
|
|
if(!i2c_rec_ack())
|
|
return 0;
|
|
|
|
//repeat start
|
|
i2c_start();
|
|
//write slave_addr+1
|
|
i2c_send(addr[0]|0x1);
|
|
if(!i2c_rec_ack())
|
|
return 0;
|
|
|
|
for(i=0;i<count;i++)
|
|
{
|
|
//read data
|
|
buf[i]=i2c_rec();
|
|
// i2c_send_ack(1);//***add in***//
|
|
|
|
}
|
|
i2c_stop();
|
|
|
|
return count;
|
|
}
|
|
unsigned char i2c_send_b(unsigned char *addr,int addrlen,unsigned char reg,unsigned char * buf ,int count)
|
|
{
|
|
int i;
|
|
int j;
|
|
i2c_start();
|
|
for(j=0;j<addrlen;j++)
|
|
{
|
|
//write slave_addr
|
|
i2c_send(addr[j]);
|
|
if(!i2c_rec_ack())
|
|
return 0;
|
|
}
|
|
|
|
i2c_send(reg);
|
|
if(!i2c_rec_ack())
|
|
return 0;
|
|
|
|
for(i=0;i<count;i++)
|
|
{
|
|
|
|
i2c_send(buf[i]);
|
|
if(!i2c_rec_ack())
|
|
return 0;
|
|
}
|
|
i2c_stop();
|
|
return count;
|
|
}
|
|
//----------------------
|
|
/*
|
|
* 0 single: ÿ?ζ?һ??
|
|
* 1 smb block
|
|
*/
|
|
int tgt_i2cread(int type,unsigned char *addr,int addrlen,unsigned char reg,unsigned char *buf,int count)
|
|
{
|
|
int i;
|
|
tgt_i2cinit();
|
|
memset(buf,-1,count);
|
|
switch(type)
|
|
{
|
|
case I2C_SINGLE:
|
|
return i2c_rec_s(addr,addrlen,reg,buf,count);
|
|
break;
|
|
case I2C_BLOCK:
|
|
return i2c_rec_b(addr,addrlen,reg,buf,count);
|
|
break;
|
|
|
|
default: return 0;break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int tgt_i2cwrite(int type,unsigned char *addr,int addrlen,unsigned char reg,unsigned char *buf,int count)
|
|
{
|
|
tgt_i2cinit();
|
|
switch(type&0xff)
|
|
{
|
|
case I2C_SINGLE:
|
|
i2c_send_s(addr,addrlen,reg,buf,count);
|
|
break;
|
|
case I2C_BLOCK:
|
|
return i2c_send_b(addr,addrlen,reg,buf,count);
|
|
break;
|
|
case I2C_SMB_BLOCK:
|
|
break;
|
|
default:return -1;break;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
int tgt_i2cinit()
|
|
{
|
|
#if defined(DEVBD2F_SM502)
|
|
pcitag_t tag;
|
|
static int inited=0;
|
|
int tmp;
|
|
if(!inited)
|
|
{
|
|
tag=_pci_make_tag(0,14,0);
|
|
|
|
mmio = _pci_conf_readn(tag,0x14,4);
|
|
mmio =(int)mmio|(0xb0000000);
|
|
tmp = *(volatile int *)(mmio + 0x40);
|
|
*(volatile int *)(mmio + 0x40) =tmp|0x40;
|
|
|
|
// tgt_printf("clock enable bit 40 = %x\n", *(volatile int *)(mmio + 0x40));
|
|
inited=1;
|
|
}
|
|
#endif
|
|
}
|
|
|