]> www.infradead.org Git - users/rw/ppcboot.git/commitdiff
405GP I2C ehancements
authorwdenk <wdenk>
Mon, 1 Apr 2002 19:35:39 +0000 (19:35 +0000)
committerwdenk <wdenk>
Mon, 1 Apr 2002 19:35:39 +0000 (19:35 +0000)
Patch by Andrew May, 29 Mar 2002

CHANGELOG
cpu/ppc4xx/i2c.c
include/405gp_i2c.h

index 8fc625da41a0cbcb47947e9c963ffef4833d4f25..0fc78aab76bddc8a4bc72a7091d9c2d6d8766955 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -14,6 +14,9 @@
 Modifications for 1.1.6:
 ======================================================================
 
+* 405GP I2C ehancements
+  Patch by Andrew May, 29 Mar 2002
+
 * Fix for I2C problems on Sandpoint824x
   Patch by Jerry Van Baren, 29 Mar 2002
 
index 4ee8ef24a0d84443f44930b8975aa8ec063c276b..dfc37c73b4ff333129e24529ac34c5b8244f9889 100644 (file)
 
 #ifdef CONFIG_HARD_I2C
 
-/*
- * PPC405GP I2C interface definitions.
- */
-#define           I2C_REGISTERS_BASE_ADDRESS 0xEF600500
-#define    IIC_MDBUF   (I2C_REGISTERS_BASE_ADDRESS+IICMDBUF)
-#define    IIC_SDBUF   (I2C_REGISTERS_BASE_ADDRESS+IICSDBUF)
-#define    IIC_LMADR   (I2C_REGISTERS_BASE_ADDRESS+IICLMADR)
-#define    IIC_HMADR   (I2C_REGISTERS_BASE_ADDRESS+IICHMADR)
-#define    IIC_CNTL    (I2C_REGISTERS_BASE_ADDRESS+IICCNTL)
-#define    IIC_MDCNTL  (I2C_REGISTERS_BASE_ADDRESS+IICMDCNTL)
-#define    IIC_STS     (I2C_REGISTERS_BASE_ADDRESS+IICSTS)
-#define    IIC_EXTSTS  (I2C_REGISTERS_BASE_ADDRESS+IICEXTSTS)
-#define    IIC_LSADR   (I2C_REGISTERS_BASE_ADDRESS+IICLSADR)
-#define    IIC_HSADR   (I2C_REGISTERS_BASE_ADDRESS+IICHSADR)
-#define    IIC_CLKDIV  (I2C_REGISTERS_BASE_ADDRESS+IICCLKDIV)
-#define    IIC_INTRMSK (I2C_REGISTERS_BASE_ADDRESS+IICINTRMSK)
-#define    IIC_XFRCNT  (I2C_REGISTERS_BASE_ADDRESS+IICXFRCNT)
-#define    IIC_XTCNTLSS        (I2C_REGISTERS_BASE_ADDRESS+IICXTCNTLSS)
-#define    IIC_DIRECTCNTL (I2C_REGISTERS_BASE_ADDRESS+IICDIRECTCNTL)
-
-/* MDCNTL Register Bit definition */
-#define    IIC_MDCNTL_HSCL 0x01
-#define    IIC_MDCNTL_EUBS 0x02
-#define    IIC_MDCNTL_FMDB 0x40
-#define    IIC_MDCNTL_FSDB 0x80
-
-/* CNTL Register Bit definition */
-#define    IIC_CNTL_PT     0x01
-#define    IIC_CNTL_READ   0x02
-#define    IIC_CNTL_CHT    0x04
-
-/* STS Register Bit definition */
-#define    IIC_STS_PT     0X01
-#define    IIC_STS_ERR    0X04
-#define    IIC_STS_MDBS    0X20
-
-/* EXTSTS Register Bit definition */
-#define    IIC_EXTSTS_XFRA 0X01
-#define    IIC_EXTSTS_ICT  0X02
-#define    IIC_EXTSTS_LA   0X04
-
-
 #define IIC_OK         0
 #define IIC_NOK                1
 #define IIC_NOK_LA     2               /* Lost arbitration */
 
 #define IIC_TIMEOUT 1                  /* 1 seconde */
 
-/*
- * Handle page write settings.
- */
-#ifndef CFG_EEPROM_PAGE_WRITE_BITS
-#define CFG_EEPROM_PAGE_WRITE_BITS 0
-#endif
-
-/* Ensure I/O operations complete */
-/* __asm__ volatile("eieio"); */
-
 
 static void _i2c_bus_reset (void)
 {
        int i, status;
 
-       /* Reset status register */
-       /* write 1 in SCMP and IRQA to clear these fields */
-       out8 (IIC_STS, 0x0A);
-
-       /* write 1 in IRQP IRQD LA ICT XFRA to clear these fields */
-       out8 (IIC_EXTSTS, 0x8F);
-       __asm__ volatile ("eieio");
-
        /*
         * Get current state, reset bus
         * only if no transfers are pending.
@@ -100,7 +40,7 @@ static void _i2c_bus_reset (void)
        } while ((status & IIC_STS_PT) && (i > 0));
        /* Soft reset controller */
        status = in8 (IIC_XTCNTLSS);
-       out8 (IIC_XTCNTLSS, (status | 0x1));
+       out8 (IIC_XTCNTLSS, (status | IIC_XTCNTLSS_SRST));
        __asm__ volatile ("eieio");
 
        /* make sure where in initial state, data hi, clock hi */
@@ -123,7 +63,7 @@ static void _i2c_bus_reset (void)
        out8 (IIC_DIRECTCNTL, 0xC);
        udelay (1000);                          /* 1ms */
        /* Unreset controller */
-       out8 (IIC_XTCNTLSS, (status & ~0x1));
+       out8 (IIC_XTCNTLSS, (status & ~IIC_XTCNTLSS_SRST));
        udelay (1000);                          /* 1ms */
 }
 
@@ -173,135 +113,202 @@ void i2c_init (int speed, int slaveadd)
        out8 (IIC_MDCNTL, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB);
        __asm__ volatile ("eieio");
 
-       /* Ignore General Call, 100kHz, slave transfers are ignored,
-          disable interrupts, exit unknown bus state, enable hold
-          SCL
-        */
-       val = in8 (IIC_MDCNTL) | IIC_MDCNTL_EUBS | IIC_MDCNTL_HSCL;
-       __asm__ volatile ("eieio");
 
+        val = in8(IIC_MDCNTL);
+        __asm__ volatile ("eieio");
+
+        /* Ignore General Call, slave transfers are ignored,
+           disable interrupts, exit unknown bus state, enable hold
+           SCL
+           100kHz normaly or FastMode for 400kHz and above
+        */
+        
+        val |= IIC_MDCNTL_EUBS|IIC_MDCNTL_HSCL;
+        if( speed >= 400000 ){
+                val |= IIC_MDCNTL_FSM;
+        }
        out8 (IIC_MDCNTL, val);
 
        /* clear control reg */
        out8 (IIC_CNTL, 0x00);
        __asm__ volatile ("eieio");
+        
 }
 
-static
-int i2c_transfer (unsigned char command_is_reading, unsigned char address,
-                 unsigned short size_to_transfer, unsigned char data[])
-{
-       int bytes_transfered;
-       int result;
-       int status;
-       int i;
+/*
+  This code tries to use the features of the 405GP i2c
+  controller. It will transfer up to 4 bytes in one pass
+  on the loop. It only does out8(lbz) to the buffer when it 
+  is possible to do out16(lhz) transfers.
 
-       result = IIC_OK;
-       bytes_transfered = 0;
+  cmd_type is 0 for write 1 for read.
 
-       /* Check init */
-       i = 10;
-       do {
-               /* Get status */
-               status = in8 (IIC_STS);
-               i--;
-       } while ((status & IIC_STS_PT) && (i > 0));
-       if (status & IIC_STS_PT) {
-               result = IIC_NOK_TOUT;
-               return (result);
-       }
+  addr_len can take any value from 0-255, it is only limited
+  by the char, we could make it larger if needed. If it is
+  0 we skip the address write cycle.
 
-       /* 7-bit adressing */
-       out8 (IIC_HMADR, 0);
-       out8 (IIC_LMADR, address);
-
-       while ((bytes_transfered < size_to_transfer) && (result == IIC_OK)) {
-               /* Control register =
-                  Normal transfer, 7-bits adressing, Transfer 1 byte, Normal start,
-                  Transfer is a sequence of transfers
-                  Write/Read, Start transfer */
-
-               /* ACTION => Start - Transfer - Ack - pause */
-               /* ACTION - LAST BYTE => Start - Transfer - Nack  - Stop */
-               if (command_is_reading) {
-                       /* issue read command */
-                       if (bytes_transfered == size_to_transfer - 1) {
-                               out8 (IIC_CNTL, IIC_CNTL_READ | IIC_CNTL_PT);
-                       } else {
-                               out8 (IIC_CNTL, IIC_CNTL_READ | 
-                                               IIC_CNTL_CHT  |
-                                               IIC_CNTL_PT);
-                       }
-               } else {
-                       /* Set buffer */
-                       out8 (IIC_MDBUF, data[bytes_transfered]);
-                       udelay (1);
-                       /* issue write command */
-                       if (bytes_transfered == size_to_transfer - 1) {
-                               out8 (IIC_CNTL, IIC_CNTL_PT);
-                       } else {
-                               out8 (IIC_CNTL, IIC_CNTL_CHT | IIC_CNTL_PT);
-                       }
-               }
-               __asm__ volatile ("eieio");
-
-               /* Transfer is in progress */
-               i = 20;
-               do {
-                       /* Get status */
-                       status = in8 (IIC_STS);
-                       udelay (10);
-                       i--;
-               } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR)
-                                && (i > 0));
-
-               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 ((command_is_reading) && (result == IIC_OK)) {
-                       /* Are there data in buffer */
-                       if (status & IIC_STS_MDBS) {
-                               udelay (1);
-                               data[bytes_transfered] = in8 (IIC_MDBUF);
-                       } else
-                               result = IIC_NOK_DATA;
-               }
-               bytes_transfered++;
-       }
-       return (result);
-}
+  Typical case is a Write of an addr followd by a Read. The
+  IBM FAQ does not cover this. On the last byte of the write
+  we don't set the creg CHT bit, and on the first bytes of the
+  read we set the RPST bit.
 
-static
-int i2c_receive (unsigned char address,
-                unsigned short size_to_expect, unsigned char datain[])
-{
-       int status;
+  It does not support address only transfers, there must be
+  a data part. If you want to write the address yourself, put
+  it in the data pointer.
 
-       status = i2c_transfer (1, address, size_to_expect, datain);
-       return status;
-}
+  It does not support transfer to/from address 0.
 
+  It does not check XFRCNT.
+*/
 static
-int i2c_send (unsigned char address,
-             unsigned short size_to_send, unsigned char dataout[])
+int i2c_transfer(unsigned char cmd_type,
+                 unsigned char chip,
+                 unsigned char addr[],
+                 unsigned char addr_len,
+                 unsigned char data[],
+                unsigned short data_len )
 {
-       int status;
-
-       status = i2c_transfer (0, address, size_to_send, dataout);
-       return status;
+        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.
+                 */
+                i=2*5*8;
+                do {
+                        /* Get status */
+                        status = in8(IIC_STS);
+                        __asm__ volatile("eieio");
+                        udelay (10);
+                        i--;
+                } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR)
+                        && (i>0));
+
+                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.
+                                 */
+                                udelay (1);
+                                for(j=0;j<bc;j++) {
+                                        ptr[tran+j] = in8(IIC_MDBUF);
+                                        __asm__ volatile("eieio");
+                                }
+                        } else
+                                result = IIC_NOK_DATA;
+                }
+                creg = 0;
+                tran+=bc;
+                if( ptr == addr && tran == cnt ) {
+                        ptr = data;
+                        cnt = data_len;
+                        tran = 0;
+                        reading = cmd_type;
+                        if( reading )
+                                creg = IIC_CNTL_RPST;
+                }
+        }
+        return (result);
 }
 
 int i2c_probe (uchar chip)
@@ -310,62 +317,34 @@ int i2c_probe (uchar chip)
 
        buf[0] = 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_send (chip << 1, 1, buf) != 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);
 }
 
 
+
 int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
 {
-       uchar xaddr[4];
-       int rcode = 0;
+        uchar xaddr[4];
+        int ret;
 
-       if ((alen < 1) || (alen > 2)) {
+       if ( alen > 4 ) {
                printf ("I2C read: addr len %d not supported\n", alen);
                return 1;
        }
 
-       xaddr[0] = (addr >> 24) & 0xFF;
-       xaddr[1] = (addr >> 16) & 0xFF;
-       xaddr[2] = (addr >> 8) & 0xFF;
-       xaddr[3] = addr & 0xFF;
-
-#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
-       /*
-         * EEPROM chips that implement "address overflow" are ones
-         * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
-         * address and the extra bits end up in the "chip address"
-         * bit slots. This makes a 24WC08 (1Kbyte) chip look like
-         * four 256 byte chips.
-        *
-         * Note that we consider the length of the address field to
-         * still be one byte because the extra address bits are
-         * hidden in the chip address.
-        */
-       chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
-#endif
-
-       if (i2c_send (chip << 1, alen, &xaddr[4 - alen]) != 0)
-               rcode = 1;
-       if (i2c_receive ((chip << 1) | 0x01, len, buffer) != 0)
-               rcode = 1;
-       return rcode;
-}
+        if ( alen > 0 ) {
+                xaddr[0] = (addr >> 24) & 0xFF;
+                xaddr[1] = (addr >> 16) & 0xFF;
+                xaddr[2] = (addr >> 8) & 0xFF;
+                xaddr[3] = addr & 0xFF;
+        }
 
-#ifndef CFG_EEPROM_PAGE_WRITE_ENABLE
 
-int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
-{
-       uchar xbuf[3];
-
-       if ((alen < 1) || (alen > 2)) {
-               printf ("I2C write: addr len %d not supported\n", alen);
-               return 1;
-       }
 #ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
        /*
          * EEPROM chips that implement "address overflow" are ones
@@ -378,43 +357,31 @@ int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
          * still be one byte because the extra address bits are
          * hidden in the chip address.
         */
-       chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
+        if( alen > 0 )
+                chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
 #endif
-
-       /* write with ack polling */
-       while (len-- > 0) {
-               xbuf[0] = (addr >> 8) & 0xFF;   /* High addr (if used) */
-               xbuf[1] = addr & 0xFF;  /* Low  addr */
-               xbuf[2] = *buffer++;
-               addr++;                 /* increase write offset */
-               /* single write + ack polling */
-               while (i2c_send (chip << 1, alen + 1, &xbuf[2 - alen]) != 0) {
-                       udelay (100);
-               }
-       }
-       return 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;
 }
 
-#else  /* CFG_EEPROM_PAGE_WRITE_ENABLE */
-
 int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
 {
-       /* buffer for one page + addresses */
-       uchar wbuffer[(1 << CFG_EEPROM_PAGE_WRITE_BITS) + 2];
-       int i;
+        uchar xaddr[4];
 
-       if ((alen < 1) || (alen > 2)) {
-               printf ("I2C read: addr len %d not supported\n", alen);
+       if ( alen > 4 ) {
+               printf ("I2C write: addr len %d not supported\n", alen);
                return 1;
-       }
-
-       /* fill in the address first */
-       wbuffer[0] = (addr >> 8) & 0xFF;        /* High addr (if used) */
-       wbuffer[1] = addr & 0xFF;       /* Low  addr */
 
-       for (i = 2; i < len + 2; i++) {
-               wbuffer[i] = *buffer++; /* copy data */
        }
+        if ( alen > 0 ) {
+                xaddr[0] = (addr >> 24) & 0xFF;
+                xaddr[1] = (addr >> 16) & 0xFF;
+                xaddr[2] = (addr >> 8) & 0xFF;
+                xaddr[3] = addr & 0xFF;
+        }
 
 #ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
        /*
@@ -428,16 +395,11 @@ int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
          * still be one byte because the extra address bits are
          * hidden in the chip address.
         */
-       chip |= ((addr >> alen) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
+        if( alen > 0 )
+                chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
 #endif
 
-       /* write page + ack polling */
-       while (i2c_send (chip << 1, alen + len, &wbuffer[2 - alen]) != 0) {
-               udelay (100);
-       }
-
-       return 0;
+        return (i2c_transfer( 0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0);
 }
-#endif /* CFG_EEPROM_PAGE_WRITE_ENABLE */
 
 #endif /* CONFIG_HARD_I2C */
index 4babc047bd31f739c62c2e1044dbbe6fcaa20fcd..5a9a4975367443687aa421f7fc13e8f278fc83a0 100644 (file)
 /* MDCNTL Register Bit definition */
 #define    IIC_MDCNTL_HSCL 0x01
 #define    IIC_MDCNTL_EUBS 0x02
+#define    IIC_MDCNTL_EINT 0x04
+#define    IIC_MDCNTL_ESM  0x08
+#define    IIC_MDCNTL_FSM  0x10
+#define    IIC_MDCNTL_EGC  0x20
 #define    IIC_MDCNTL_FMDB 0x40
 #define    IIC_MDCNTL_FSDB 0x80
 
 #define    IIC_CNTL_PT     0x01
 #define    IIC_CNTL_READ   0x02
 #define    IIC_CNTL_CHT    0x04
+#define    IIC_CNTL_RPST   0x08
+/* bit 2/3 for Transfer count*/
+#define    IIC_CNTL_AMD    0x40
+#define    IIC_CNTL_HMT    0x80
 
 /* STS Register Bit definition */
 #define    IIC_STS_PT     0X01
+#define    IIC_STS_IRQA    0x02
 #define    IIC_STS_ERR    0X04
+#define    IIC_STS_SCMP    0x08
+#define    IIC_STS_MDBF    0x10
 #define    IIC_STS_MDBS    0X20
+#define    IIC_STS_SLPR    0x40
+#define    IIC_STS_SSS     0x80
 
 /* EXTSTS Register Bit definition */
 #define    IIC_EXTSTS_XFRA 0X01
 #define    IIC_EXTSTS_ICT  0X02
 #define    IIC_EXTSTS_LA   0X04
 
+/* XTCNTLSS Register Bit definition */
+#define    IIC_XTCNTLSS_SRST  0x01
+#define    IIC_XTCNTLSS_EPI   0x02
+#define    IIC_XTCNTLSS_SDBF  0x04
+#define    IIC_XTCNTLSS_SBDD  0x08
+#define    IIC_XTCNTLSS_SWS   0x10
+#define    IIC_XTCNTLSS_SWC   0x20
+#define    IIC_XTCNTLSS_SRS   0x40
+#define    IIC_XTCNTLSS_SRC   0x80
 #endif