- /* Ignore General Call, slave transfers are ignored,
- disable interrupts, exit unknown bus state, enable hold
- SCL
- 100kHz normaly or FastMode for 400kHz and above
- */
+ /* Ignore General Call, slave transfers are ignored,
+ disable interrupts, exit unknown bus state, enable hold
+ SCL
+ 100kHz normaly or FastMode for 400kHz and above
+ */
- unsigned char* ptr;
- int reading;
- int tran,cnt;
- int result;
- int status;
- int i;
- uchar creg;
-
- if( data == 0 || data_len == 0 ){
- /*Don't support data transfer of no length or to address 0*/
- printf( "i2c_transfer: bad call\n" );
- return IIC_NOK;
- }
- if( addr && addr_len ){
- ptr = addr;
- cnt = addr_len;
- reading = 0;
- }else{
- ptr = data;
- cnt = data_len;
- reading = cmd_type;
- }
-
- /*Clear Stop Complete Bit*/
- out8(IIC_STS,IIC_STS_SCMP);
- /* Check init */
- i=10;
- do {
- /* Get status */
- status = in8(IIC_STS);
- __asm__ volatile("eieio");
- i--;
- } while ((status & IIC_STS_PT) && (i>0));
-
- if (status & IIC_STS_PT) {
- result = IIC_NOK_TOUT;
- return(result);
- }
- /*flush the Master/Slave Databuffers*/
- out8(IIC_MDCNTL, ((in8(IIC_MDCNTL))|IIC_MDCNTL_FMDB|IIC_MDCNTL_FSDB));
- /*need to wait 4 OPB clocks? code below should take that long*/
-
- /* 7-bit adressing */
- out8(IIC_HMADR,0);
- out8(IIC_LMADR, chip);
- __asm__ volatile("eieio");
-
- tran = 0;
- result = IIC_OK;
- creg = 0;
-
- while ( tran != cnt && (result == IIC_OK)) {
- int bc,j;
-
- /* Control register =
- Normal transfer, 7-bits adressing, Transfer up to bc bytes, Normal start,
- Transfer is a sequence of transfers
- */
- creg |= IIC_CNTL_PT;
-
- bc = (cnt - tran) > 4 ? 4 :
- cnt - tran;
- creg |= (bc-1)<<4;
- /* if the real cmd type is write continue trans*/
- if ( (!cmd_type && (ptr == addr)) || ((tran+bc) != cnt) )
- creg |= IIC_CNTL_CHT;
-
- if (reading)
- creg |= IIC_CNTL_READ;
- else {
- for(j=0; j<bc; j++) {
- /* Set buffer */
- out8(IIC_MDBUF,ptr[tran+j]);
- __asm__ volatile("eieio");
- }
- }
- out8(IIC_CNTL, creg );
- __asm__ volatile("eieio");
-
- /* Transfer is in progress
- we have to wait for upto 5 bytes of data
- 1 byte chip address+r/w bit then bc bytes
- of data.
- udelay(10) is 1 bit time at 100khz
- Doubled for slop. 20 is too small.
+ unsigned char* ptr;
+ int reading;
+ int tran,cnt;
+ int result;
+ int status;
+ int i;
+ uchar creg;
+
+ if( data == 0 || data_len == 0 ){
+ /*Don't support data transfer of no length or to address 0*/
+ printf( "i2c_transfer: bad call\n" );
+ return IIC_NOK;
+ }
+ if( addr && addr_len ){
+ ptr = addr;
+ cnt = addr_len;
+ reading = 0;
+ }else{
+ ptr = data;
+ cnt = data_len;
+ reading = cmd_type;
+ }
+
+ /*Clear Stop Complete Bit*/
+ out8(IIC_STS,IIC_STS_SCMP);
+ /* Check init */
+ i=10;
+ do {
+ /* Get status */
+ status = in8(IIC_STS);
+ __asm__ volatile("eieio");
+ i--;
+ } while ((status & IIC_STS_PT) && (i>0));
+
+ if (status & IIC_STS_PT) {
+ result = IIC_NOK_TOUT;
+ return(result);
+ }
+ /*flush the Master/Slave Databuffers*/
+ out8(IIC_MDCNTL, ((in8(IIC_MDCNTL))|IIC_MDCNTL_FMDB|IIC_MDCNTL_FSDB));
+ /*need to wait 4 OPB clocks? code below should take that long*/
+
+ /* 7-bit adressing */
+ out8(IIC_HMADR,0);
+ out8(IIC_LMADR, chip);
+ __asm__ volatile("eieio");
+
+ tran = 0;
+ result = IIC_OK;
+ creg = 0;
+
+ while ( tran != cnt && (result == IIC_OK)) {
+ int bc,j;
+
+ /* Control register =
+ Normal transfer, 7-bits adressing, Transfer up to bc bytes, Normal start,
+ Transfer is a sequence of transfers
+ */
+ creg |= IIC_CNTL_PT;
+
+ bc = (cnt - tran) > 4 ? 4 :
+ cnt - tran;
+ creg |= (bc-1)<<4;
+ /* if the real cmd type is write continue trans*/
+ if ( (!cmd_type && (ptr == addr)) || ((tran+bc) != cnt) )
+ creg |= IIC_CNTL_CHT;
+
+ if (reading)
+ creg |= IIC_CNTL_READ;
+ else {
+ for(j=0; j<bc; j++) {
+ /* Set buffer */
+ out8(IIC_MDBUF,ptr[tran+j]);
+ __asm__ volatile("eieio");
+ }
+ }
+ out8(IIC_CNTL, creg );
+ __asm__ volatile("eieio");
+
+ /* Transfer is in progress
+ we have to wait for upto 5 bytes of data
+ 1 byte chip address+r/w bit then bc bytes
+ of data.
+ udelay(10) is 1 bit time at 100khz
+ Doubled for slop. 20 is too small.
- if (status & IIC_STS_ERR) {
- result = IIC_NOK;
- status = in8 (IIC_EXTSTS);
- /* Lost arbitration? */
- if (status & IIC_EXTSTS_LA)
- result = IIC_NOK_LA;
- /* Incomplete transfer? */
- if (status & IIC_EXTSTS_ICT)
- result = IIC_NOK_ICT;
- /* Transfer aborted? */
- if (status & IIC_EXTSTS_XFRA)
- result = IIC_NOK_XFRA;
- } else if ( status & IIC_STS_PT) {
- result = IIC_NOK_TOUT;
- }
- /* Command is reading => get buffer */
- if ((reading) && (result == IIC_OK)) {
- /* Are there data in buffer */
- if (status & IIC_STS_MDBS) {
- /*
- even if we have data we have to wait 4OPB clocks
- for it to hit the front of the FIFO, after that
- we can just read. We should check XFCNT here and
- if the FIFO is full there is no need to wait.
+ if (status & IIC_STS_ERR) {
+ result = IIC_NOK;
+ status = in8 (IIC_EXTSTS);
+ /* Lost arbitration? */
+ if (status & IIC_EXTSTS_LA)
+ result = IIC_NOK_LA;
+ /* Incomplete transfer? */
+ if (status & IIC_EXTSTS_ICT)
+ result = IIC_NOK_ICT;
+ /* Transfer aborted? */
+ if (status & IIC_EXTSTS_XFRA)
+ result = IIC_NOK_XFRA;
+ } else if ( status & IIC_STS_PT) {
+ result = IIC_NOK_TOUT;
+ }
+ /* Command is reading => get buffer */
+ if ((reading) && (result == IIC_OK)) {
+ /* Are there data in buffer */
+ if (status & IIC_STS_MDBS) {
+ /*
+ even if we have data we have to wait 4OPB clocks
+ for it to hit the front of the FIFO, after that
+ we can just read. We should check XFCNT here and
+ if the FIFO is full there is no need to wait.
- /*
- * What is needed is to send the chip address and verify that the
- * address was <ACK>ed (i.e. there was a chip at that address which
- * drove the data line low).
- */
- return(i2c_transfer (1, chip << 1, 0,0, buf, 1) != 0);
+ /*
+ * What is needed is to send the chip address and verify that the
+ * address was <ACK>ed (i.e. there was a chip at that address which
+ * drove the data line low).
+ */
+ return(i2c_transfer (1, chip << 1, 0,0, buf, 1) != 0);
- if( (ret = i2c_transfer( 1, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) {
- printf( "I2c read: failed %d\n", ret);
- return 1;
- }
- return 0;
+ if( (ret = i2c_transfer( 1, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) {
+ if (gd->have_console)
+ printf( "I2c read: failed %d\n", ret);
+ return 1;
+ }
+ return 0;
- return (i2c_transfer( 0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0);
+ return (i2c_transfer( 0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0);
+}
+
+/*-----------------------------------------------------------------------
+ * Read a register
+ */
+uchar i2c_reg_read(uchar i2c_addr, uchar reg)
+{
+ uchar buf;
+
+ i2c_read(i2c_addr, reg, 1, &buf, 1);
+
+ return(buf);