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.
 
 
 
 
 
 

297 lines
6.1 KiB

#include <pmon.h>
#include <stdio.h>
#include <target/i2c.h>
//----------------------------------------------------
void i2c_stop()
{
*GS_SOC_I2C_CR = CR_STOP;
*GS_SOC_I2C_SR;
while (*GS_SOC_I2C_SR & SR_BUSY) ;
}
///////////////////////////////////////////////////o
// below added by xqch to make i2c_read like ls3a
unsigned char i2c_read(unsigned char baseaddr, unsigned char regoff)
{
int i, j;
unsigned char ret = 0x5a;
unsigned char addr[2];
addr[0] = baseaddr;
addr[1] = regoff;
printf("base addr = %08x, regoff = %08x\n", baseaddr, regoff);
printf("addr[0] = %08x, addr[1] = %08x\n", addr[0], addr[1]);
tgt_i2cinit();
for (j = 0; j < 32; j++) {
*GS_SOC_I2C_TXR = addr[0] & 0xfe;
*GS_SOC_I2C_CR = CR_START | CR_WRITE;
while (*GS_SOC_I2C_SR & SR_TIP) ;
*GS_SOC_I2C_TXR = j;
*GS_SOC_I2C_CR = CR_STOP | CR_WRITE;
while (*GS_SOC_I2C_SR & SR_TIP) ;
/* why set slave address again */
*GS_SOC_I2C_TXR = addr[0] | 1;
*GS_SOC_I2C_CR = CR_START | CR_WRITE; /* start on first addr */
while (*GS_SOC_I2C_SR & SR_TIP) ;
*GS_SOC_I2C_CR = CR_READ | CR_ACK; /* last read not send ack */
while (*GS_SOC_I2C_SR & SR_TIP) ;
ret = *GS_SOC_I2C_TXR;
printf("%2d: ret = %08x\n", j, ret);
*GS_SOC_I2C_CR = CR_STOP;
*GS_SOC_I2C_SR;
while (*GS_SOC_I2C_SR & SR_BUSY) ;
}
//ret = * GS_SOC_I2C_TXR;
//printf("1: ret = %08x\n", ret);
// i2c_stop();
return ret;
}
////////////////////////////////////////////////////////////////
unsigned char i2c_rec_s(unsigned char *addr, int addrlen, unsigned char *buf,
int count)
{
int i;
int j;
unsigned char value;
for (i = 0; i < count; i++) {
again:
for (j = 0; j < addrlen; j++) {
/*write slave_addr */
*GS_SOC_I2C_TXR = addr[j];
*GS_SOC_I2C_CR =
(j == 0) ? (CR_START | CR_WRITE) : CR_WRITE;
while (*GS_SOC_I2C_SR & SR_TIP) ;
if ((*GS_SOC_I2C_SR) & SR_NOACK) {
printf("j= %d ,read no ack %d\n", j, __LINE__);
i2c_stop();
goto again;
}
}
/*write slave_addr */
*GS_SOC_I2C_TXR = addr[0] | 1;
*GS_SOC_I2C_CR = CR_START | CR_WRITE; /* start on first addr */
while (*GS_SOC_I2C_SR & SR_TIP) ;
if ((*GS_SOC_I2C_SR) & SR_NOACK) {
printf("read no ack %d\n", __LINE__);
i2c_stop();
goto again;
}
*GS_SOC_I2C_CR = CR_READ | CR_ACK; /*last read not send ack */
while (*GS_SOC_I2C_SR & SR_TIP) ;
buf[i] = *GS_SOC_I2C_TXR;
*GS_SOC_I2C_CR = CR_STOP;
*GS_SOC_I2C_SR;
while (*GS_SOC_I2C_SR & SR_BUSY) ;
}
return count;
}
unsigned char i2c_send_s(unsigned char *addr, int addrlen, unsigned char *buf,
int count)
{
int i;
int j;
for (i = 0; i < count; i++) {
again:
for (j = 0; j < addrlen; j++) {
/*write slave_addr */
*GS_SOC_I2C_TXR = addr[j];
*GS_SOC_I2C_CR = j == 0 ? (CR_START | CR_WRITE) : CR_WRITE; /* start on first addr */
while (*GS_SOC_I2C_SR & SR_TIP) ;
if ((*GS_SOC_I2C_SR) & SR_NOACK) {
printf("write no ack %d\n", __LINE__);
i2c_stop();
goto again;
}
}
*GS_SOC_I2C_TXR = buf[i];
*GS_SOC_I2C_CR = CR_WRITE | CR_STOP;
while (*GS_SOC_I2C_SR & SR_TIP) ;
if ((*GS_SOC_I2C_SR) & SR_NOACK) {
printf("write no ack %d\n", __LINE__);
i2c_stop();
goto again;
}
}
while (*GS_SOC_I2C_SR & SR_BUSY) ;
return count;
}
unsigned char i2c_rec_b(unsigned char *addr, int addrlen, unsigned char *buf,
int count)
{
int i;
int j;
unsigned char value;
for (j = 0; j < addrlen; j++) {
/*write slave_addr */
*GS_SOC_I2C_TXR = addr[j];
*GS_SOC_I2C_CR = j == 0 ? (CR_START | CR_WRITE) : CR_WRITE; /* start on first addr */
while (*GS_SOC_I2C_SR & SR_TIP) ;
if ((*GS_SOC_I2C_SR) & SR_NOACK)
return i;
}
*GS_SOC_I2C_TXR = addr[0] | 1;
*GS_SOC_I2C_CR = CR_START | CR_WRITE;
if ((*GS_SOC_I2C_SR) & SR_NOACK)
return i;
for (i = 0; i < count; i++) {
*GS_SOC_I2C_CR = CR_READ;
while (*GS_SOC_I2C_SR & SR_TIP) ;
buf[i] = *GS_SOC_I2C_TXR;
}
*GS_SOC_I2C_CR = CR_STOP;
return count;
}
unsigned char i2c_send_b(unsigned char *addr, int addrlen, unsigned char *buf,
int count)
{
int i;
int j;
for (j = 0; j < addrlen; j++) {
/*write slave_addr */
*GS_SOC_I2C_TXR = addr[j];
*GS_SOC_I2C_CR = j == 0 ? (CR_START | CR_WRITE) : CR_WRITE; /* start on first addr */
while (*GS_SOC_I2C_SR & SR_TIP) ;
if ((*GS_SOC_I2C_SR) & SR_NOACK)
return i;
}
for (i = 0; i < count; i++) {
*GS_SOC_I2C_TXR = buf[i];
*GS_SOC_I2C_CR = CR_WRITE;
while (*GS_SOC_I2C_SR & SR_TIP) ;
if ((*GS_SOC_I2C_SR) & SR_NOACK)
return i;
}
*GS_SOC_I2C_CR = CR_STOP;
while (*GS_SOC_I2C_SR & SR_BUSY) ;
return count;
}
/*
* 0 single
* 1 block
* 2 smb block
*/
int tgt_i2cread(int type, unsigned char *addr, int addrlen, unsigned char *buf,
int count)
{
int i;
tgt_i2cinit();
memset(buf, -1, count);
switch (type) {
case I2C_SINGLE:
return i2c_rec_s(addr, addrlen, buf, count);
break;
case I2C_BLOCK:
return i2c_rec_b(addr, addrlen, buf, count);
break;
default:
return 0;
break;
}
return 0;
}
int tgt_i2cwrite(int type, unsigned char *addr, int addrlen, unsigned char *buf,
int count)
{
tgt_i2cinit();
switch (type & 0xff) {
case I2C_SINGLE:
i2c_send_s(addr, addrlen, buf, count);
break;
case I2C_BLOCK:
return i2c_send_b(addr, addrlen, buf, count);
break;
case I2C_SMB_BLOCK:
break;
default:
return -1;
break;
}
return -1;
}
int tgt_i2cinit()
{
static int inited = 0;
if (inited)
return 0;
inited = 1;
*GS_SOC_I2C_PRER_LO = 0x64;
*GS_SOC_I2C_PRER_HI = 0;
*GS_SOC_I2C_CTR = 0x80;
}
int cmd_i2cread(int ac, char *av[])
{
int i, len = 1;
unsigned char addr[16] = { 0xa3, 0x02, 0x02, 0x02, 0x02, 0x02 };
unsigned char slave = 0xa3;
unsigned char regoff = 0x02;
unsigned char buf[16];
for (i = 0; i < ac; i++)
printf("av[%d] : %s\n", i, av[i]);
slave = strtoul(av[1], NULL, 0);
printf("slave = %08x\n ", slave);
if ((slave & 0x1) == 0) // Fix bad input
slave = 0xa3;
if (ac > 2)
regoff = strtol(av[2], NULL, 0);
printf("regoff = %08x\n", regoff);
printf("%08x\n", i2c_read(slave, regoff));
return 0;
}
static const Cmd Cmds[] = {
{"Misc"},
{"i2cread", "", NULL, "i2cread a address from ls2h chip", cmd_i2cread,
1, 5, 0},
{0, 0}
};
static void init_cmd __P((void)) __attribute__ ((constructor));
void init_cmd()
{
cmdlist_expand(Cmds, 1);
}