| 
 | 
Pls refer I2C source code, It work on Uboot and If you want to work on kernel , pls set specify register as correct value. 
#include <common.h> 
#include <asm/io.h> 
#include <asm/arch/twi.h> 
#include <asm/arch/ccmu.h> 
#include <asm/arch/gpio.h> 
#define I2C_WRITE  0 
#define I2C_READ  1 
#define I2C_OK   0 
#define I2C_NOK   1 
#define I2C_NACK  2 
#define I2C_NOK_LA  3 /* Lost arbitration */ 
#define I2C_NOK_TOUT 4 /* time out */ 
#define I2C_START_TRANSMIT     0x08 
#define I2C_RESTART_TRANSMIT   0x10 
#define I2C_ADDRWRITE_ACK    0x18 
#define I2C_ADDRREAD_ACK    0x40 
#define I2C_DATAWRITE_ACK      0x28 
#define I2C_READY      0xf8 
#define I2C_DATAREAD_NACK    0x58 
#define I2C_DATAREAD_ACK    0x50 
/* status or interrupt source */ 
/*------------------------------------------------------------------------------ 
* Code   Status 
* 00h    Bus error 
* 08h    START condition transmitted 
* 10h    Repeated START condition transmitted 
* 18h    Address + Write bit transmitted, ACK received 
* 20h    Address + Write bit transmitted, ACK not received 
* 28h    Data byte transmitted in master mode, ACK received 
* 30h    Data byte transmitted in master mode, ACK not received 
* 38h    Arbitration lost in address or data byte 
* 40h    Address + Read bit transmitted, ACK received 
* 48h    Address + Read bit transmitted, ACK not received 
* 50h    Data byte received in master mode, ACK transmitted 
* 58h    Data byte received in master mode, not ACK transmitted 
* 60h    Slave address + Write bit received, ACK transmitted 
* 68h    Arbitration lost in address as master, slave address + Write bit received, ACK transmitted 
* 70h    General Call address received, ACK transmitted 
* 78h    Arbitration lost in address as master, General Call address received, ACK transmitted 
* 80h    Data byte received after slave address received, ACK transmitted 
* 88h    Data byte received after slave address received, not ACK transmitted 
* 90h    Data byte received after General Call received, ACK transmitted 
* 98h    Data byte received after General Call received, not ACK transmitted 
* A0h    STOP or repeated START condition received in slave mode 
* A8h    Slave address + Read bit received, ACK transmitted 
* B0h    Arbitration lost in address as master, slave address + Read bit received, ACK transmitted 
* B8h    Data byte transmitted in slave mode, ACK received 
* C0h    Data byte transmitted in slave mode, ACK not received 
* C8h    Last byte transmitted in slave mode, ACK received 
* D0h    Second Address byte + Write bit transmitted, ACK received 
* D8h    Second Address byte + Write bit transmitted, ACK not received 
* F8h    No relevant status information or no interrupt 
*-----------------------------------------------------------------------------*/ 
 
/* OrangePi 8106 */ 
#define   BOOT_8106_VERSION                (0x01) 
#define   BOOT_8106_DCDOUT_VOL             (0x15) 
 
static  struct sunxi_twi_reg *i2c  = NULL; 
static __s32 i2c_sendbyteaddr(__u32 byteaddr) 
{ 
 __s32  time = 0xffff; 
 __u32  tmp_val; 
 i2c->data = byteaddr & 0xff; 
        i2c->ctl |= (0x01<<3);//write 1 to clean int flag 
        while( (time--) && (!(i2c->ctl & 0x08)) ); 
 if(time <= 0) 
 { 
  return -I2C_NOK_TOUT; 
 } 
 tmp_val = i2c->status; 
 if(tmp_val != I2C_DATAWRITE_ACK) 
 { 
  return -I2C_DATAWRITE_ACK; 
 } 
 return I2C_OK; 
} 
static __s32 i2c_sendstart(void) 
{ 
    __s32  time = 0xfffff; 
    __u32  tmp_val; 
    i2c->eft  = 0; 
    i2c->srst = 1; 
    i2c->ctl |= 0x20; 
    while((time--)&&(!(i2c->ctl & 0x08))); 
 if(time <= 0) 
 { 
  return -I2C_NOK_TOUT; 
 } 
 tmp_val = i2c->status; 
    if(tmp_val != I2C_START_TRANSMIT) 
    { 
  return -I2C_START_TRANSMIT; 
    } 
    return I2C_OK; 
} 
static __s32 i2c_sendslaveaddr(__u32 saddr,  __u32 rw) 
{ 
 __s32  time = 0xffff; 
 __u32  tmp_val; 
 rw &= 1; 
 i2c->data = ((saddr & 0xff) << 1)| rw; 
        i2c->ctl  |= (0x01<<3);//write 1 to clean int flag 
 while(( time-- ) && (!( i2c->ctl & 0x08 ))); 
 if(time <= 0) 
 { 
  printf("I2C_NOK_TOUT\n"); 
  return -I2C_NOK_TOUT; 
 } 
 tmp_val = i2c->status; 
 if(rw == I2C_WRITE)//+write 
 { 
  if(tmp_val != I2C_ADDRWRITE_ACK) 
  { 
   printf("I2C_ADDRWRITE_ACK\n"); 
   return -I2C_ADDRWRITE_ACK; 
  } 
 } 
 else//+read 
 { 
  if(tmp_val != I2C_ADDRREAD_ACK) 
  { 
   return -I2C_ADDRREAD_ACK; 
  } 
 } 
 return I2C_OK; 
} 
static __s32 i2c_sendRestart(void) 
{ 
 __s32  time = 0xffff; 
 __u32  tmp_val; 
 tmp_val = i2c->ctl; 
 tmp_val |= 0x20; 
 i2c->ctl = tmp_val; 
 while( (time--) && (!(i2c->ctl & 0x08)) ); 
 if(time <= 0) 
 { 
  return -I2C_NOK_TOUT; 
 } 
 tmp_val = i2c->status; 
 if(tmp_val != I2C_RESTART_TRANSMIT) 
 { 
  return -I2C_RESTART_TRANSMIT; 
 } 
 return I2C_OK; 
} 
static __s32 i2c_stop(void) 
{ 
 __s32  time = 0xffff; 
 __u32  tmp_val; 
 i2c->ctl |= (0x01 << 4); 
        i2c->ctl |= (0x01 << 3); 
        while( (time--) && (i2c->ctl & 0x10) ); 
 if(time <= 0) 
 { 
  return -I2C_NOK_TOUT; 
 } 
 time = 0xffff; 
 while( (time--) && (i2c->status != I2C_READY) ); 
 tmp_val = i2c->status; 
 if(tmp_val != I2C_READY) 
 { 
  return -I2C_NOK_TOUT; 
 } 
 return I2C_OK; 
} 
static __s32 i2c_getdata(__u8 *data_addr, __u32 data_count) 
{ 
 __s32  time = 0xffff; 
 __u32  tmp_val; 
 __u32  i; 
 if(data_count == 1) 
 { 
         i2c->ctl |= (0x01<<3); 
         while( (time--) && (!(i2c->ctl & 0x08)) ); 
  if(time <= 0) 
  { 
             return -I2C_NOK_TOUT; 
  } 
  for(time=0;time<100;time++); 
  *data_addr = i2c->data; 
  tmp_val = i2c->status; 
  if(tmp_val != I2C_DATAREAD_NACK) 
  { 
             return -I2C_DATAREAD_NACK; 
  } 
 } 
 else 
 { 
  for(i=0; i< data_count - 1; i++) 
  { 
   time = 0xffff; 
   //host should send ack every time when a data packet finished 
   tmp_val = i2c->ctl | (0x01<<2); 
                        tmp_val = i2c->ctl | (0x01<<3); 
          tmp_val |= 0x04; 
                        i2c->ctl = tmp_val; 
    //i2c->ctl |=(0x01<<3); 
   while( (time--) && (!(i2c->ctl & 0x08)) ); 
   if(time <= 0) 
   { 
    return -I2C_NOK_TOUT; 
   } 
   for(time=0;time<100;time++); 
   time = 0xffff; 
   data_addr[i] = i2c->data; 
   while( (time--) && (i2c->status != I2C_DATAREAD_ACK) ); 
   if(time <= 0) 
   { 
                            return -I2C_NOK_TOUT; 
   } 
  } 
  time = 0xffff; 
                i2c->ctl &= 0xFb;  //the last data packet,not send ack 
                i2c->ctl |= (0x01<<3); 
  while( (time--) && (!(i2c->ctl & 0x08)) ); 
  if(time <= 0) 
  { 
                    return -I2C_NOK_TOUT; 
  } 
  for(time=0;time<100;time++); 
  data_addr[data_count - 1] = i2c->data; 
  while( (time--) && (i2c->status != I2C_DATAREAD_NACK) ); 
  if(time <= 0) 
  { 
                    return -I2C_NOK_TOUT; 
  } 
 } 
 return I2C_OK; 
} 
static int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) 
{ 
 int   i, ret, ret0, addrlen; 
 char  *slave_reg; 
 ret0 = -1; 
 ret = i2c_sendstart(); 
 if(ret) 
 { 
  goto i2c_read_err_occur; 
 } 
 ret = i2c_sendslaveaddr(chip, I2C_WRITE); 
 if(ret) 
 { 
  goto i2c_read_err_occur; 
 } 
 //send byte address 
 if(alen >= 3) 
 { 
  addrlen = 2; 
 } 
 else if(alen <= 1) 
 { 
  addrlen = 0; 
 } 
 else 
 { 
  addrlen = 1; 
 } 
 slave_reg = (char *)&addr; 
 for (i = addrlen; i>=0; i--) 
 { 
  ret = i2c_sendbyteaddr(slave_reg[i] & 0xff); 
  if(ret) 
  { 
   goto i2c_read_err_occur; 
  } 
 } 
 ret = i2c_sendRestart(); 
 if(ret) 
 { 
  goto i2c_read_err_occur; 
 } 
 ret = i2c_sendslaveaddr(chip, I2C_READ); 
 if(ret) 
 { 
  goto i2c_read_err_occur; 
 } 
 //get data 
 ret = i2c_getdata(buffer, len); 
 if(ret) 
 { 
  goto i2c_read_err_occur; 
 } 
 ret0 = 0; 
i2c_read_err_occur: 
 i2c_stop(); 
 return ret0; 
} 
 
 
static __s32 i2c_senddata(__u8  *data_addr, __u32 data_count) 
{ 
    __s32  time = 0xffff; 
    __u32  i; 
 for(i=0; i< data_count; i++) 
 { 
  time = 0xffff; 
         i2c->data = data_addr[i]; 
#if defined(CONFIG_ARCH_SUN5I)|defined(CONFIG_ARCH_SUN7I) 
  i2c->ctl &= 0xF7; 
#else 
                i2c->ctl |= (0x01<<3); 
#endif 
                while( (time--) && (!(i2c->ctl & 0x08)) ); 
  if(time <= 0) 
  { 
                    return -I2C_NOK_TOUT; 
  } 
  time = 0xffff; 
  while( (time--) && (i2c->status != I2C_DATAWRITE_ACK) ); 
                if(time <= 0) 
  { 
                    return -I2C_NOK_TOUT; 
  } 
 } 
 return I2C_OK; 
} 
 
static int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) 
{ 
 int   i, ret, ret0, addrlen; 
 char  *slave_reg; 
 ret0 = -1; 
 ret = i2c_sendstart(); 
 if(ret) 
 { 
  printf("BAD Send start\n"); 
  goto i2c_write_err_occur; 
 } 
retry: 
 ret = i2c_sendslaveaddr(chip, I2C_WRITE); 
 if(ret) 
 { 
  printf("BAD Send slavaddr\n"); 
  goto retry; 
//  goto i2c_write_err_occur; 
 } 
 //send byte address 
 if(alen >= 3) 
 { 
  addrlen = 2; 
 } 
 else if(alen <= 1) 
 { 
  addrlen = 0; 
 } 
 else 
 { 
  addrlen = 1; 
 } 
 slave_reg = (char *)&addr; 
 for (i = addrlen; i>=0; i--) 
 { 
  ret = i2c_sendbyteaddr(slave_reg[i] & 0xff); 
  if(ret) 
  { 
   goto i2c_write_err_occur; 
  } 
 } 
 ret = i2c_senddata(buffer, len); 
 if(ret) 
 { 
  goto i2c_write_err_occur; 
 } 
 ret0 = 0; 
 i2c_write_err_occur: 
 i2c_stop(); 
 return ret0; 
} 
int orangepi_i2c_write(unsigned char chip, unsigned char addr, unsigned char data) 
{ 
 int ret = i2c_write(chip, addr, 1, &data, 1); 
 if (ret != 0) 
  printf("BAD I2C WRITE\n"); 
 else 
  printf("SUCCEED I2C WRITE\n"); 
 return ret; 
} 
int orangepi_i2c_read(unsigned char chip, unsigned char addr, unsigned char *buffer) 
{ 
 int ret = i2c_read(chip, addr, 1, buffer, 1); 
  
 if (ret != 0) 
  printf("BAD I2C READ\n"); 
 else 
  printf("SUCCEED I2C READ\n"); 
 return ret; 
} 
 
static int set_cpus_i2c_clock(unsigned int onoff) 
{ 
 int reg_value = 0; 
 //opne CPUS PIO 
 volatile unsigned int reg_val; 
 // R_GPIO reset deassert 
 reg_val = readl(SUNXI_RPRCM_BASE+0xb0); 
 reg_val |= 1; 
 writel(reg_val, SUNXI_RPRCM_BASE+0xb0); 
 // R_GPIO GATING open 
 reg_val = readl(SUNXI_RPRCM_BASE+0x28); 
 reg_val |= 1; 
 writel(reg_val, SUNXI_RPRCM_BASE+0x28); 
 //R_GPIO: PL0,PL1 cfg 2 
 writel(readl(0x01F02C00)& ~0xff,0x01F02C00); 
 writel(readl(0x01F02C00)|0x22,0x01F02C00); 
 //PL0,PL1 pull up 1 
 writel(readl(0x01F02C00+0x1C)& ~0xf,0x01F02C00+0x1C); 
 writel(readl(0x01F02C00+0x1C)|0x5,0x01F02C00+0x1C); 
 //PL0,PL1 drv 2 
 writel(readl(0x01F02C00+0x14)& ~0xf,0x01F02C00+0x14); 
 writel(readl(0x01F02C00+0x14)|0xa,0x01F02C00+0x14); 
 //deassert twi reset 
 reg_value = readl(SUNXI_RPRCM_BASE + 0xb0); 
 reg_value &= ~(0x01 << 6); 
 writel(reg_value,SUNXI_RPRCM_BASE + 0xb0); 
 reg_value = readl(SUNXI_RPRCM_BASE + 0xb0); 
 reg_value |= 0x01 << 6; 
 writel(reg_value,SUNXI_RPRCM_BASE + 0xb0); 
 __usdelay(10); 
 //open twi gating 
 reg_value = readl(SUNXI_RPRCM_BASE + 0x28); 
 if(onoff) 
  reg_value |= 0x01 << 6; 
 else 
  reg_value &= ~(0x01 << 6); 
 writel(reg_value,SUNXI_RPRCM_BASE + 0x28); 
 __usdelay(10); 
 return 0; 
} 
 
static void i2c_set_clock(int speed, int slaveaddr) 
{ 
 int i, clk_n, clk_m; 
     /* reset i2c control  */ 
 i = 0xffff; 
 i2c->srst = 1; 
 while((i2c->srst) && (i)) 
 { 
     i --; 
 } 
 if((i2c->lcr & 0x30) != 0x30 ) 
 { 
     /* toggle I2CSCL until bus idle */ 
     i2c->lcr = 0x05; 
     __usdelay(500); 
     i = 10; 
      while ((i > 0) && ((i2c->lcr & 0x02) != 2)) 
      { 
       i2c->lcr |= 0x08; 
       __usdelay(1000); 
       i2c->lcr &= ~0x08; 
       __usdelay(1000); 
       i--; 
      } 
      i2c->lcr = 0x0; 
      __usdelay(500); 
 } 
 if(speed < 100) 
 { 
     speed = 100; 
 } 
 else if(speed > 400) 
 { 
     speed = 400; 
 } 
 clk_n = 1; 
 clk_m = (24000/10)/((2^clk_n) * speed) - 1; 
 i2c->clk = (clk_m<<3) | clk_n; 
 i2c->ctl = 0x40; 
 i2c->eft = 0; 
} 
void orangepi_i2c_init_cpus(int speed, int slaveaddr) 
{ 
 i2c = (struct sunxi_twi_reg *)SUNXI_RTWI_BASE; 
 set_cpus_i2c_clock(1); 
 i2c_set_clock(speed,slaveaddr); 
 return ; 
} 
 This snippet was truncated for display: see it in full. 
 wrap 
Today at 2:18 PM • 11KB C snippet • Shared in common Unshare from #common 
bug Today at 2:18 PM   
static int set_cpus_i2c_clock(unsigned int onoff) 
{ 
   int reg_value = 0; 
   //opne CPUS PIO 
   volatile unsigned int reg_val; 
   // R_GPIO reset deassert 
   reg_val = readl(SUNXI_RPRCM_BASE+0xb0); 
   reg_val |= 1; 
   writel(reg_val, SUNXI_RPRCM_BASE+0xb0); 
   // R_GPIO GATING open 
   reg_val = readl(SUNXI_RPRCM_BASE+0x28); 
   reg_val |= 1; 
   writel(reg_val, SUNXI_RPRCM_BASE+0x28); 
   //R_GPIO: PL0,PL1 cfg 2 
   writel(readl(0x01F02C00)& ~0xff,0x01F02C00); 
   writel(readl(0x01F02C00)|0x22,0x01F02C00); 
   //PL0,PL1 pull up 1 
   writel(readl(0x01F02C00+0x1C)& ~0xf,0x01F02C00+0x1C); 
   writel(readl(0x01F02C00+0x1C)|0x5,0x01F02C00+0x1C); 
   //PL0,PL1 drv 2 
   writel(readl(0x01F02C00+0x14)& ~0xf,0x01F02C00+0x14); 
   writel(readl(0x01F02C00+0x14)|0xa,0x01F02C00+0x14); 
   //deassert twi reset 
   reg_value = readl(SUNXI_RPRCM_BASE + 0xb0); 
   reg_value &= ~(0x01 << 6); 
   writel(reg_value,SUNXI_RPRCM_BASE + 0xb0); 
   reg_value = readl(SUNXI_RPRCM_BASE + 0xb0); 
   reg_value |= 0x01 << 6; 
   writel(reg_value,SUNXI_RPRCM_BASE + 0xb0); 
   __usdelay(10); 
   //open twi gating 
   reg_value = readl(SUNXI_RPRCM_BASE + 0x28); 
   if(onoff) 
       reg_value |= 0x01 << 6; 
   else 
       reg_value &= ~(0x01 << 6); 
   writel(reg_value,SUNXI_RPRCM_BASE + 0x28); 
   __usdelay(10); 
   return 0; 
} 
 |   
 
 
 
 |