[etrax] Improve i2c driver slave delay, thanks to Fabrizio Sciarra that provide it
authorclaudio <claudio@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Tue, 6 Oct 2009 09:20:30 +0000 (09:20 +0000)
committerclaudio <claudio@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Tue, 6 Oct 2009 09:20:30 +0000 (09:20 +0000)
  * support for master/slave delay  (provided patch)
  * remove some printk that spam logs
  * introduce new symbols ETRAX_I2C_DYN_ALLOC and ETRAX_I2C_SLAVE_DELAY
  * cleanup a bit the driver
  * dump release number

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@17954 3c298f89-4303-0410-b956-a3cf2f4a3e73

target/linux/etrax/files-2.6.30/arch/cris/arch-v10/drivers/i2c_gvc.c
target/linux/etrax/patches-2.6.30/500-i2c_gvc.patch

index 681712f..e47bc64 100644 (file)
-/*!***************************************************************************\r
-*!\r
-*! FILE NAME  : i2c.c\r
-*!\r
-*!\r
-*! ---------------------------------------------------------------------------\r
-*!\r
-*! ( C ) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN\r
-*!\r
-*!***************************************************************************/\r
-\r
-#define DYNAMIC_MAJOR_I2CDEV_NUMBER_ALLOC\r
-//#undef  DYNAMIC_MAJOR_I2CDEV_NUMBER_ALLOC\r
-\r
-/******************** INCLUDE FILES SECTION ****************************/\r
-\r
-#include <linux/module.h>\r
-#include <linux/fs.h>\r
-\r
-/**GVC**/\r
-#ifdef DYNAMIC_MAJOR_I2CDEV_NUMBER_ALLOC\r
-#include <linux/types.h> /* for dev_t */\r
-#include <linux/cdev.h>  /* for struct cdev */\r
-#endif\r
-/**END GVC**/\r
-\r
-#include "etraxi2c.h"\r
-\r
-/**GVC**/\r
-#include "i2c_errno.h"\r
-/**END GVC**/\r
-\r
-#include <asm/io.h>\r
-#include <asm/delay.h>\r
-#include <asm/arch/io_interface_mux.h>\r
-#include <asm/uaccess.h>\r
-\r
-#include "i2c_gvc.h"\r
-\r
-MODULE_DESCRIPTION( "I2C Device Driver - 1.1" );\r
-\r
-/*!*********************************************************************\r
- *!History I2C driver Geert Vancompernolle\r
- *!---------------------------------------\r
- *!\r
- *! - v1.0:\r
- *!     First official version.\r
- *!\r
- *! - v1.1:\r
- *!     Changes to remove unwanted spikes at ACK/NACK time.\r
- *!\r
- *!*********************************************************************/\r
\r
-MODULE_LICENSE( "GPL" );\r
-\r
-/******************            MACRO's            **********************/\r
-\r
-#define D( x )\r
-\r
-/**GVC**/\r
-#ifndef DYNAMIC_MAJOR_I2CDEV_NUMBER_ALLOC\r
-/**END GVC**/\r
-#define I2C_MAJOR 123                                  /* LOCAL/EXPERIMENTAL */\r
-/**GVC**/\r
-#endif\r
-/**END GVC**/\r
-\r
-/**GVC**/\r
-#define WAITONEUS                 1\r
-/* Following are abbreviations taken from Philips I2C standard */\r
-/* Values are representing time in us and are rounded to next whole number, if relevant */ \r
-#define THDSTA                    4     /* Hold delay time for (repeated) START condition */\r
-#define TLOW                      5     /* LOW period of the SCL clock */\r
-#define THDDAT                   1     /* Hold delay time for DATA: value of 0 is allowed but 1 taken to be sure */\r
-#define TSUDAT                    1     /* Set-up time for DATA */\r
-#define THIGH                     4     /* HIGH period of the SCL clock */\r
-#define TSUSTA                    5     /* Set-up time for a repeated START condition */\r
-#define TSUSTO                    4     /* Set-up time for STOP condition */\r
-#define TBUF                      5     /* Bus-free time between STOP and START condition */\r
-\r
-#define MAXBUSFREERETRIES         5\r
-#define MAXRETRIES                3\r
-#define WRITEADDRESS_MASK         ( 0xFE )\r
-#define READADDRESS_MASK          ( 0x01 )\r
-/**END GVC**/\r
-\r
-#define SCL_HIGH                  1\r
-#define SCL_LOW                   0\r
-#define SDA_HIGH                  1\r
-#define SDA_LOW                   0\r
-\r
-#ifdef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C\r
-/* Use PB and not PB_I2C */\r
-#ifndef CONFIG_ETRAX_I2C_DATA_PORT\r
-#define CONFIG_ETRAX_I2C_DATA_PORT 0\r
-#endif\r
-#ifndef CONFIG_ETRAX_I2C_CLK_PORT\r
-#define CONFIG_ETRAX_I2C_CLK_PORT 1\r
-#endif\r
-\r
-#define SDABIT CONFIG_ETRAX_I2C_DATA_PORT\r
-#define SCLBIT CONFIG_ETRAX_I2C_CLK_PORT\r
-#define i2c_enable() \r
-#define i2c_disable() \r
-\r
-/* enable or disable output-enable, to select output or input on the i2c bus */\r
-#define i2c_sda_dir_out() \\r
-  REG_SHADOW_SET( R_PORT_PB_DIR, port_pb_dir_shadow, SDABIT, 1 )\r
-#define i2c_sda_dir_in()  \\r
-  REG_SHADOW_SET( R_PORT_PB_DIR, port_pb_dir_shadow, SDABIT, 0 )\r
-\r
-/* control the i2c clock and data signals */\r
-#define i2c_set_scl( x ) \\r
-  REG_SHADOW_SET( R_PORT_PB_DATA, port_pb_data_shadow, SCLBIT, x )\r
-#define i2c_set_sda( x ) \\r
-  REG_SHADOW_SET( R_PORT_PB_DATA, port_pb_data_shadow, SDABIT, x )\r
-\r
-/* read status of SDA bit from the i2c interface */\r
-#define i2c_sda_is_high() ( ( ( *R_PORT_PB_READ & ( 1 << SDABIT ) ) ) >> SDABIT )\r
-\r
-/**GVC**/\r
-/* read status of SCL bit from the i2c interface */\r
-#define i2c_scl_is_high() ( ( ( *R_PORT_PB_READ & ( 1 << SCLBIT ) ) ) >> SCLBIT )\r
-/**END GVC**/\r
-\r
-#else\r
-/* enable or disable the i2c interface */\r
-#define i2c_enable() *R_PORT_PB_I2C = ( port_pb_i2c_shadow |= IO_MASK( R_PORT_PB_I2C, i2c_en ) )\r
-#define i2c_disable() *R_PORT_PB_I2C = ( port_pb_i2c_shadow &= ~IO_MASK( R_PORT_PB_I2C, i2c_en ) )\r
-\r
-/* enable or disable output-enable, to select output or input on the i2c bus */\r
-#define i2c_sda_dir_out() \\r
-       *R_PORT_PB_I2C = ( port_pb_i2c_shadow &= ~IO_MASK( R_PORT_PB_I2C, i2c_oe_ ) ); \\r
-       REG_SHADOW_SET( R_PORT_PB_DIR, port_pb_dir_shadow, 0, 1 ); \r
-#define i2c_sda_dir_in() \\r
-       *R_PORT_PB_I2C = ( port_pb_i2c_shadow |= IO_MASK( R_PORT_PB_I2C, i2c_oe_ ) ); \\r
-       REG_SHADOW_SET( R_PORT_PB_DIR, port_pb_dir_shadow, 0, 0 );\r
-\r
-/* control the i2c clock and data signals */\r
-#define i2c_set_scl( x ) \\r
-       *R_PORT_PB_I2C = ( port_pb_i2c_shadow = ( port_pb_i2c_shadow & \\r
-       ~IO_MASK( R_PORT_PB_I2C, i2c_set_scl ) ) | IO_FIELD( R_PORT_PB_I2C, i2c_set_scl, ( x ) ) ); \\r
-       REG_SHADOW_SET( R_PORT_PB_DATA, port_pb_data_shadow, 1, x );\r
-\r
-#define i2c_set_sda( x ) \\r
-       *R_PORT_PB_I2C = ( port_pb_i2c_shadow = ( port_pb_i2c_shadow & \\r
-          ~IO_MASK( R_PORT_PB_I2C, i2c_d ) ) | IO_FIELD( R_PORT_PB_I2C, i2c_d, ( x ) ) ); \\r
-       REG_SHADOW_SET( R_PORT_PB_DATA, port_pb_data_shadow, 0, x );\r
-\r
-/* read a bit from the i2c interface */\r
-#define i2c_sda_is_high() ( *R_PORT_PB_READ & 0x1 )\r
-#endif\r
-\r
-/* use the kernels delay routine */\r
-#define i2c_delay( usecs ) udelay( usecs )\r
-\r
-\r
-/******************           TYPEDEF's           **********************/\r
-\r
-\r
-/****************** STATIC (file scope) VARIABLES **********************/\r
-static DEFINE_SPINLOCK( i2c_lock ); /* Protect directions etc */\r
-/**GVC**/\r
-#ifdef DYNAMIC_MAJOR_I2CDEV_NUMBER_ALLOC\r
-static const char i2c_name[] = "i2cgvc";\r
-#else\r
-static const char i2c_name[] = "i2c";\r
-#endif\r
-/**END GVC**/\r
-\r
-\r
-/******************     PROTOTYPING SECTION     *************************/\r
-static int  i2c_open( struct inode *inode, struct file *filp );\r
-static int  i2c_release( struct inode *inode, struct file *filp );\r
-/**GVC**/\r
-static int  i2c_command( unsigned char  slave\r
-                       , unsigned char* wbuf\r
-                       , unsigned char  wlen\r
-                       , unsigned char* rbuf\r
-                       , unsigned char  rlen\r
-                       );\r
-static int  i2c_bus_free_check( unsigned char maxretries );\r
-static void i2c_finalise( const char* text, unsigned long irqflags );\r
-/**END GVC**/\r
-                           \r
-\r
-/************************************************************************/\r
-/******************         AUXILIARIES         *************************/\r
-/************************************************************************/\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_open\r
- *#\r
- *# DESCRIPTION  : opens an I2C device\r
- *#\r
- *# PARAMETERS   : *inode: reference to inode\r
- *#                *filp : reference to file pointer \r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-static int i2c_open( struct inode *inode, struct file *filp )\r
-{\r
-    return 0;\r
-}   /* i2c_open */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_release\r
- *#\r
- *# DESCRIPTION  : Releases the I2C device\r
- *#\r
- *# PARAMETERS   : *inode: reference to inode\r
- *#                *filp : reference to file pointer \r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-static int i2c_release( struct inode *inode, struct file *filp )\r
-{\r
-    return 0;\r
-}   /* i2c_release */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_ioctl\r
- *#\r
- *# DESCRIPTION  : Main device API: ioctl's to write/read \r
- *#                to/from i2c registers\r
- *#\r
- *# PARAMETERS   : *inode: reference to inode\r
- *#                *filp : reference to file pointer \r
- *#                cmd   : command to be executed during the ioctl call \r
- *#                arg   : pointer to a structure with the data??? \r
- *#\r
- *# RETURN       : result of the ioctl call\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-static int i2c_ioctl( struct inode *inode\r
-                    , struct file *file\r
-                    , unsigned int cmd\r
-                    , unsigned long arg\r
-                    )\r
-{\r
-    /* the acme ioctls */\r
-    I2C_DATA i2cdata;\r
-    int RetVal = EI2CNOERRORS;\r
-    \r
-    if ( _IOC_TYPE( cmd ) != ETRAXI2C_IOCTYPE ) \r
-    {\r
-        return ( -EINVAL );\r
-    }\r
-    \r
-    switch ( _IOC_NR( cmd ) ) \r
-    {\r
-    case I2C_WRITEREG:\r
-        /* write to an i2c slave */\r
-        RetVal = i2c_writereg( I2C_ARGSLAVE( arg )\r
-                             , I2C_ARGREG( arg )\r
-                             , I2C_ARGVALUE( arg )\r
-                             );\r
-        break;                       \r
-\r
-    case I2C_READREG:\r
-        RetVal = i2c_readreg( I2C_ARGSLAVE( arg ), I2C_ARGREG( arg ) );\r
-        break;\r
-    \r
-/**GVC**/\r
-    /* New functions added by GVC */    \r
-    case I2C_READ:\r
-        copy_from_user( (char*)&i2cdata, (char*)arg, sizeof( I2C_DATA ) );\r
-        {\r
-            int RetryCntr = MAXRETRIES;\r
-            \r
-            do\r
-            {\r
-                RetVal = i2c_command( i2cdata.slave\r
-                                    , NULL\r
-                                    , 0 \r
-                                    , i2cdata.rbuf\r
-                                    , i2cdata.rlen\r
-                                    );\r
-             } while ( ( EI2CNOERRORS != RetVal )\r
-                     &&( --RetryCntr )\r
-                     );\r
-        }\r
-        copy_to_user( (char*)arg, (char*)&i2cdata, sizeof( I2C_DATA ) );\r
-        break;\r
-\r
-    case I2C_WRITE:\r
-        copy_from_user( (char*)&i2cdata, (char*)arg, sizeof( I2C_DATA ) );\r
-        {\r
-            int RetryCntr = MAXRETRIES;\r
-            \r
-            do\r
-            {\r
-                RetVal = i2c_command( i2cdata.slave\r
-                                    , i2cdata.wbuf\r
-                                    , i2cdata.wlen\r
-                                    , NULL\r
-                                    , 0 \r
-                                    );\r
-             } while ( ( EI2CNOERRORS != RetVal )\r
-                     &&( --RetryCntr )\r
-                     );\r
-        }\r
-        break;\r
-          \r
-    case I2C_WRITEREAD:\r
-        copy_from_user( (char*)&i2cdata, (char*)arg, sizeof( I2C_DATA ) );\r
-        {\r
-            int RetryCntr = MAXRETRIES;\r
-            \r
-            do\r
-            {\r
-                RetVal = i2c_command( i2cdata.slave\r
-                                    , i2cdata.wbuf\r
-                                    , i2cdata.wlen\r
-                                    , i2cdata.rbuf\r
-                                    , i2cdata.rlen \r
-                                    );\r
-             } while ( ( EI2CNOERRORS != RetVal )\r
-                     &&( --RetryCntr )\r
-                     );\r
-        }\r
-        copy_to_user( (char*)arg, (char*)&i2cdata, sizeof( I2C_DATA ) );\r
-        break;\r
-/**END GVC**/    \r
-    \r
-    default:\r
-        RetVal = -EINVAL;\r
-    }\r
-    \r
-    return ( -RetVal );\r
-}   /* i2c_ioctl */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_command\r
- *#\r
- *# DESCRIPTION  : general routine to read/write bytes from an I2C device\r
- *#                \r
- *#                'i2c_command()' sends wlen bytes to the I2c bus and receives\r
- *#                rlen bytes from the I2c bus.  \r
- *#                The data to be send must be placed in wbuf[ 0 ] upto wbuf[ wlen - 1 ).\r
- *#                The data to be received is assembled in rbuf[ 0 ] upto rbuf[ rlen - 1 ].\r
- *#                 \r
- *#                If no data is to be sent or received, put appropriate buffer parameter\r
- *#                to "NULL" and appropriate length parameter to "0".\r
- *# \r
- *# PARAMETERS   : slave = slave address of the I2C device\r
- *#                wbuf  = address of first element of write buffer (wbuf)\r
- *#                wlen  = number of bytes to be written to slave\r
- *#                rbuf  = address of first element of read buffer (rbuf)\r
- *#                rlen  = number of bytes to be read from slave\r
- *#\r
- *# RETURN       : \r
- *#    EI2CNOERRORS: I2C communication went fine\r
- *#    EI2CBUSNFREE: I2C bus is not free\r
- *#    EI2CWADDRESS: I2C write address failed\r
- *#    EI2CRADDRESS: I2C read address failed\r
- *#    EI2CSENDDATA: I2C send data failed\r
- *#    EI2CRECVDATA: I2C receive data failed\r
- *#    EI2CSTRTCOND: I2C start condition failed\r
- *#    EI2CRSTACOND: I2C repeated start condition failed\r
- *#    EI2CSTOPCOND: I2C stop condition failed\r
- *#    EI2CNOSNDBYT: I2C no bytes to be sent\r
- *#    EI2CNOSNDBUF: I2C no send buffer defined\r
- *#    EI2CNORCVBYT: I2C no bytes to be received\r
- *#    EI2CNORCVBUF: I2C no receive buffer defined\r
- *#    EI2CNOACKNLD: I2C no acknowledge received\r
- *#\r
- *# REMARK       :\r
- *#   First, the send part is completed.  \r
- *#   In the send routine, there is no stop generated.  This is because maybe\r
- *#   a repeated start condition must be generated.\r
- *#   This happens when we want to receive some data from the I2c bus.  If not,\r
- *#   at the end of the general I2c loop the stopcondition is generated.\r
- *#   If, on the contrary, there are a number of bytes to be received, a new\r
- *#   startcondition is generated in the 'if' part of the main I2c routine, \r
- *#   which controls the receiving part.  \r
- *#   Only when the receiving of data is finished, a final stopcondition is \r
- *#   generated.\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-static int i2c_command( unsigned char  slave\r
-                      , unsigned char* wbuf\r
-                      , unsigned char  wlen\r
-                      , unsigned char* rbuf\r
-                      , unsigned char  rlen\r
-                      )\r
-{\r
-    /* Check arguments and report error if relevant... */\r
-    if ( ( wlen > 0 ) && ( wbuf == NULL ) )\r
-    {\r
-        printk( KERN_DEBUG "I2C: EI2CNOSNDBUF\n" );\r
-        return ( EI2CNOSNDBUF );\r
-    }\r
-    else if ( ( wlen == 0 ) && ( wbuf != NULL ) )\r
-    {\r
-        printk( KERN_DEBUG "I2C: EI2CNOSNDBYT\n" );\r
-        return ( EI2CNOSNDBYT );\r
-    }\r
-    else if ( ( rlen > 0 ) && ( rbuf == NULL ) )\r
-    {\r
-        printk( KERN_DEBUG "I2C: EI2CNORCVBUF\n" );\r
-        return ( EI2CNORCVBUF );\r
-    }\r
-    else if ( ( rlen == 0 ) && ( rbuf != NULL ) )\r
-    {\r
-        printk( KERN_DEBUG "I2C: EI2CNORCVBYT\n" );\r
-        return ( EI2CNORCVBYT );\r
-    }\r
-    else if ( EI2CBUSNFREE == i2c_bus_free_check( MAXBUSFREERETRIES ) )\r
-    {\r
-        /* There's no need to try more, since we weren't even\r
-         * able to start the I2C communication.\r
-         * So, no IRQ flags are stored yet, no changes to any other\r
-         * stuff like START, STOP, SENDBYTES...\r
-         * Result, simply write down the error and return the correct error code.\r
-         */\r
-        printk( KERN_DEBUG "I2C: EI2CBUSNFREE\n" );\r
-        return ( EI2CBUSNFREE );\r
-    }\r
-    else\r
-    {\r
-        /* Finally... We made it... */\r
-        unsigned long irqflags = 0;\r
-\r
-        /* we don't like to be interrupted */\r
-        local_irq_save( irqflags );\r
-\r
-        /* Check if there are bytes to be send, \r
-         * or if you immediately want to receive data.\r
-         */\r
-        if ( 0 < wlen )\r
-        {\r
-            /* start I2C communication */        \r
-            if ( EI2CNOERRORS != i2c_start() )\r
-            {\r
-                return ( i2c_finalise( "I2C: EI2CSTRTCOND\n", irqflags  )\r
-                       , EI2CSTRTCOND \r
-                       );\r
-            }\r
-\r
-            /* send slave address: xxxxxxx0B (last bit must be zero) */\r
-            if ( EI2CNOERRORS != i2c_outbyte( slave & WRITEADDRESS_MASK ) )\r
-            {\r
-                return ( i2c_finalise( "I2C: EI2CWADDRESS\n", irqflags  )\r
-                       , EI2CWADDRESS \r
-                       );\r
-            }\r
-\r
-            while ( wlen-- )\r
-            {   \r
-                /* send register data */\r
-                if ( EI2CNOERRORS != i2c_outbyte( *wbuf ) )\r
-                {\r
-                    return ( i2c_finalise( "I2C: EI2CSENDDATA\n", irqflags  )\r
-                           , EI2CSENDDATA \r
-                           );\r
-                }\r
-                \r
-                wbuf++;\r
-            };\r
-                \r
-            i2c_delay( TLOW );\r
-        }\r
-\r
-        /*\r
-         * Receiving data from I2c_bus\r
-         * If there are bytes to be received, a new start condition is\r
-         * generated => Repeated Startcondition.\r
-         * A final stopcondition is generated at the end of the main I2c\r
-         * routine.\r
-         */\r
-        if ( 0 < rlen )\r
-        {\r
-            /*\r
-             * Generate start condition if wlen == 0 \r
-             * or repeated start condition if wlen != 0...\r
-             */\r
-            if ( EI2CNOERRORS != i2c_start() )\r
-            {\r
-                return ( i2c_finalise( ( ( 0 < wlen ) \r
-                                       ? "I2C: EI2CRSTACOND\n"\r
-                                       : "I2C: EI2CSTRTCOND\n"\r
-                                       )\r
-                                     , irqflags\r
-                                     )\r
-                       , ( ( 0 < wlen ) ? EI2CRSTACOND : EI2CSTRTCOND )\r
-                       );\r
-            }\r
-\r
-            /* Send ReadAddress: xxxxxxx1B (last bit must be one) */\r
-            if ( EI2CNOERRORS != i2c_outbyte( slave | READADDRESS_MASK ) )\r
-            {\r
-                return ( i2c_finalise( "I2C: EI2CRADDRESS\n", irqflags )\r
-                       , EI2CRADDRESS\r
-                       );\r
-            }\r
-            \r
-            while ( rlen-- )\r
-            {\r
-                /* fetch register */\r
-                *rbuf = i2c_inbyte();\r
-                rbuf++;\r
-                \r
-                /* last received byte needs to be NACK-ed instead of ACK-ed */\r
-                if ( rlen )\r
-                {\r
-                    i2c_sendack();\r
-                }\r
-                else \r
-                {\r
-                    i2c_sendnack(); \r
-                }\r
-            };\r
-        }\r
-\r
-        /* Generate final stop condition */\r
-        if ( EI2CNOERRORS != i2c_stop() )\r
-        {\r
-            return ( i2c_finalise( "I2C: EI2CSTOPCOND\n", irqflags )\r
-                   , EI2CSTOPCOND\r
-                   );\r
-        } \r
-    \r
-        /* enable interrupt again */\r
-        local_irq_restore( irqflags );\r
-    }\r
-    \r
-    return ( EI2CNOERRORS );\r
-} /*  i2c_command */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_bus_free_check\r
- *#\r
- *# DESCRIPTION  : checks if the I2C bus is free before starting\r
- *#                an I2C communication\r
- *# \r
- *# PARAMETERS   : maxretries, the number of times we will try to release\r
- *#                the I2C bus  \r
- *#\r
- *# RETURN       : I2cStatus_I2cBusNotFreeError in case the bus is not free,\r
- *#                I2cStatus_I2cNoError otherwise \r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-static int i2c_bus_free_check( unsigned char maxretries )\r
-{\r
-    i2c_sda_dir_in();        /* Release SDA line */\r
-    i2c_set_scl( SCL_HIGH ); /* put SCL line high */\r
-    \r
-    i2c_delay( WAITONEUS );\r
-        \r
-    while ( ( !i2c_sda_is_high() || !i2c_scl_is_high() )\r
-          &&( maxretries-- )\r
-          )\r
-    {\r
-        /* Try to release I2C bus by generating STOP conditions */\r
-        i2c_stop();\r
-    }\r
-    \r
-    if ( 0 == maxretries )\r
-    {\r
-        printk( KERN_DEBUG "I2C: EI2CBUSNFREE\n" );\r
-        return ( EI2CBUSNFREE );\r
-    }\r
-    else \r
-    {\r
-        return ( EI2CNOERRORS );\r
-    }\r
-} /* i2c_bus_free_check */\r
-\r
-\r
-static void i2c_finalise( const char* errortxt\r
-                        , unsigned long irqflags\r
-                        )\r
-{\r
-    printk( KERN_DEBUG "%s", errortxt );\r
-    local_irq_restore( irqflags );\r
-    /* The least we can do when things go terribly wrong,\r
-     * is to try to release the bus.\r
-     * If this fails, well, then I don't know\r
-     * what I can do more for the moment...\r
-     */\r
-    (void)i2c_bus_free_check( MAXBUSFREERETRIES );\r
-}   /* i2c_finalise */                         \r
-\r
-\r
-static struct file_operations i2c_fops = \r
-{\r
-    .owner    = THIS_MODULE\r
-,   .ioctl    = i2c_ioctl\r
-,   .open     = i2c_open\r
-,   .release  = i2c_release\r
-};\r
-\r
-\r
-/***********************************************************************/\r
-/************* EXTERNAL FUNCTION DEFINITION SECTION ********************/\r
-/***********************************************************************/\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_init\r
- *#\r
- *# DESCRIPTION  : initialises the I2C device driver\r
- *#\r
- *# PARAMETERS   :\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-int __init i2c_init( void )\r
-{\r
-    static int res = 0;\r
-    static int first = 1;\r
-\r
-    if ( !first ) \r
-    {\r
-        return res;\r
-    }\r
-    \r
-    first = 0;\r
-\r
-    /* Setup and enable the Port B I2C interface */\r
-\r
-#ifndef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C\r
-    /* here, we're using the dedicated I2C pins of FoxBoard */\r
-    if ( ( res = cris_request_io_interface( if_i2c, "I2C" ) ) ) \r
-    {\r
-        printk( KERN_CRIT "i2c_init: Failed to get IO interface\n" );\r
-        return res;\r
-    }\r
-\r
-    *R_PORT_PB_I2C = port_pb_i2c_shadow |= \r
-        IO_STATE( R_PORT_PB_I2C, i2c_en,  on ) |\r
-        IO_FIELD( R_PORT_PB_I2C, i2c_d,   1 )  |\r
-        IO_FIELD( R_PORT_PB_I2C, i2c_set_scl, 1 )  |\r
-        IO_STATE( R_PORT_PB_I2C, i2c_oe_, enable );\r
-\r
-    port_pb_dir_shadow &= ~IO_MASK( R_PORT_PB_DIR, dir0 );\r
-    port_pb_dir_shadow &= ~IO_MASK( R_PORT_PB_DIR, dir1 );\r
-\r
-    *R_PORT_PB_DIR = ( port_pb_dir_shadow |=\r
-              IO_STATE( R_PORT_PB_DIR, dir0, input )  |\r
-              IO_STATE( R_PORT_PB_DIR, dir1, output ) );\r
-#else\r
-        /* If everything goes fine, res = 0, meaning "if" fails => \r
-         * will do the "else" too and as such initialise the clock port...\r
-         * Clever trick! \r
-         */\r
-        if ( ( res = cris_io_interface_allocate_pins( if_i2c\r
-                                                    , 'b'\r
-                                                    , CONFIG_ETRAX_I2C_DATA_PORT\r
-                                                    , CONFIG_ETRAX_I2C_DATA_PORT \r
-                                                    ) \r
-             ) \r
-           ) \r
-        {\r
-            printk( KERN_WARNING "i2c_init: Failed to get IO pin for I2C data port\n" );\r
-            return ( res );\r
-        }\r
-        /* Same here...*/ \r
-        else if ( ( res = cris_io_interface_allocate_pins( if_i2c\r
-                                                         , 'b'\r
-                                                         , CONFIG_ETRAX_I2C_CLK_PORT\r
-                                                         , CONFIG_ETRAX_I2C_CLK_PORT \r
-                                                         ) \r
-                  ) \r
-                ) \r
-        {\r
-            cris_io_interface_free_pins( if_i2c\r
-                                       , 'b'\r
-                                       , CONFIG_ETRAX_I2C_DATA_PORT\r
-                                       , CONFIG_ETRAX_I2C_DATA_PORT \r
-                                       );\r
-            printk( KERN_WARNING "i2c_init: Failed to get IO pin for I2C clk port\n" );\r
-        }\r
-#endif\r
-\r
-    return ( res );\r
-}   /* i2c_init */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_register\r
- *#\r
- *# DESCRIPTION  : this registers the i2c driver as a character device\r
- *#\r
- *# PARAMETERS   :\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-static int __init i2c_register( void )\r
-{\r
-    int res;\r
-/**GVC**/\r
-#ifdef DYNAMIC_MAJOR_I2CDEV_NUMBER_ALLOC\r
-    dev_t devt;\r
-    struct cdev *my_i2cdev = NULL;\r
-#endif\r
-/**END GVC**/\r
-\r
-    res = i2c_init();\r
-    \r
-    if ( res < 0 )\r
-    {\r
-        return res;\r
-    }\r
-    \r
-/**GVC**/\r
-#ifdef DYNAMIC_MAJOR_I2CDEV_NUMBER_ALLOC\r
-    res = alloc_chrdev_region( &devt, 0, 1, i2c_name );\r
-    \r
-    if ( res < 0 )\r
-    {\r
-        printk( KERN_DEBUG "I2C: EI2CNOMNUMBR\n" );\r
-        return ( res );\r
-    }\r
-    \r
-    my_i2cdev = cdev_alloc();\r
-    my_i2cdev->ops = &i2c_fops;\r
-    my_i2cdev->owner = THIS_MODULE;\r
-   \r
-    /* make device "alive" */ \r
-    res = cdev_add( my_i2cdev, devt, 1 );\r
-    \r
-    if ( res < 0 )\r
-    { \r
-        printk( KERN_DEBUG "I2C: EI2CDADDFAIL\n" );\r
-        return ( res );\r
-    }\r
-#else\r
-/**END GVC**/\r
-    res = register_chrdev( I2C_MAJOR, i2c_name, &i2c_fops );\r
-    \r
-    if ( res < 0 ) \r
-    {\r
-        printk( KERN_ERR "i2c: couldn't get a major number.\n" );\r
-        return res;\r
-    }\r
-/**GVC**/\r
-#endif\r
-/**END GVC**/\r
-\r
-    printk( KERN_INFO "I2C driver v2.2, (c) 1999-2004 Axis Communications AB\n" );\r
-\r
-/**GVC**/\r
-    printk( KERN_INFO "  ==> Improvements done by Geert Vancompernolle - December 2006\n" );\r
-\r
-#ifdef DYNAMIC_MAJOR_I2CDEV_NUMBER_ALLOC\r
-    printk( KERN_INFO "I2C Major: %d / I2C Name: %s\n", MAJOR( devt ), i2c_name );\r
-#else\r
-/**END GVC**/\r
-    printk( KERN_INFO "I2C Major: %d / I2C Name: %s\n", I2C_MAJOR, i2c_name );\r
-/**GVC**/\r
-#endif    \r
-/**END GVC**/\r
-    \r
-    return ( 0 );\r
-}   /* i2c_register */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_start\r
- *#\r
- *# DESCRIPTION  : generate i2c start condition\r
- *#\r
- *# PARAMETERS   : none\r
- *#\r
- *# RETURN       : EI2CNOERRORS if OK, EI2CSTRTCOND otherwise\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-int i2c_start( void )\r
-{\r
-    /* Set SCL=1, SDA=1 */\r
-    i2c_sda_dir_out();\r
-    i2c_set_sda( SDA_HIGH );\r
-    i2c_delay( WAITONEUS );\r
-    i2c_set_scl( SCL_HIGH );\r
-    i2c_delay( WAITONEUS );\r
-    \r
-    /* Set SCL=1, SDA=0 */\r
-    i2c_set_sda( SDA_LOW );\r
-    i2c_delay( THDSTA );\r
-    \r
-    /* Set SCL=0, SDA=0 */\r
-    i2c_set_scl( SCL_LOW );\r
-    /* We can take 1 us less than defined in spec (5 us), since the next action\r
-     * will be to set the dataline high or low and this action is 1 us\r
-     * before the clock is put high, so that makes our 5 us.\r
-     */\r
-    i2c_delay( TLOW - WAITONEUS );\r
-    \r
-    if ( i2c_sda_is_high() || i2c_scl_is_high() )\r
-    {\r
-        printk( KERN_DEBUG "I2C: EI2CSTRTCOND\n" );\r
-        return ( EI2CSTRTCOND );\r
-    }\r
-    \r
-    return ( EI2CNOERRORS );\r
-}   /* i2c_start */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_stop\r
- *#\r
- *# DESCRIPTION  : generate i2c stop condition\r
- *#\r
- *# PARAMETERS   : none\r
- *#\r
- *# RETURN       : none\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-int i2c_stop( void )\r
-{\r
-    i2c_sda_dir_out();\r
-\r
-    /* Set SCL=0, SDA=0 */\r
-    /* Don't change order, otherwise you might generate a start condition! */\r
-    i2c_set_scl( SCL_LOW );\r
-    i2c_delay( WAITONEUS );\r
-    i2c_set_sda( SDA_LOW );\r
-    i2c_delay( WAITONEUS );\r
-    \r
-    /* Set SCL=1, SDA=0 */\r
-    i2c_set_scl( SCL_HIGH );\r
-    i2c_delay( TSUSTO );\r
-    \r
-    /* Set SCL=1, SDA=1 */\r
-    i2c_set_sda( SDA_HIGH );\r
-    i2c_delay( TBUF );\r
-\r
-    i2c_sda_dir_in();\r
-    \r
-    if ( !i2c_sda_is_high() || !i2c_scl_is_high() )\r
-    {\r
-        printk( KERN_DEBUG "I2C: EI2CSTOPCOND\n" );\r
-        return ( EI2CSTOPCOND );\r
-    }\r
-    \r
-    return ( EI2CNOERRORS );\r
-}   /* i2c_stop */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_outbyte\r
- *#\r
- *# DESCRIPTION  : write a byte to the i2c interface\r
- *#\r
- *# PARAMETERS   : x: byte to be sent on the I2C bus\r
- *#\r
- *# RETURN       : none\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-int i2c_outbyte( unsigned char x )\r
-{\r
-    int i;\r
-\r
-    i2c_sda_dir_out();\r
-\r
-    for ( i = 0; i < 8; i++ ) \r
-    {\r
-        if ( x & 0x80 ) \r
-        {\r
-            i2c_set_sda( SDA_HIGH );\r
-        } \r
-        else \r
-        {\r
-            i2c_set_sda( SDA_LOW );\r
-        }\r
-        \r
-        i2c_delay( TSUDAT );\r
-        i2c_set_scl( SCL_HIGH );\r
-        i2c_delay( THIGH );\r
-        i2c_set_scl( SCL_LOW );\r
-        i2c_delay( TSUDAT );\r
-        i2c_set_sda( SDA_LOW );\r
-        /* There should be only 5 us between falling edge and new rising\r
-         * edge of clock pulse.\r
-         * Since we spend already 1 us since clock edge was low, there are\r
-         * only ( TLOW - TSUDAT ) us left.\r
-         * Next to this, since the data line will be set up 1 us before the\r
-         * clock line is set up, we can reduce the delay with another us.\r
-         */\r
-        i2c_delay( TLOW - TSUDAT - WAITONEUS );\r
-        x <<= 1;\r
-    }\r
-    \r
-    /* enable input */\r
-    i2c_sda_dir_in();\r
-    \r
-    if ( !i2c_getack() )\r
-    {\r
-        printk( KERN_DEBUG "I2C: EI2CNOACKNLD\n" );\r
-        return( EI2CNOACKNLD );\r
-    }\r
-    \r
-    return ( EI2CNOERRORS );\r
-}   /* i2c_outbyte */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_inbyte\r
- *#\r
- *# DESCRIPTION  : read a byte from the i2c interface\r
- *#\r
- *# PARAMETERS   : none\r
- *#\r
- *# RETURN       : returns the byte read from the I2C device\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-unsigned char i2c_inbyte( void )\r
-{\r
-    unsigned char aBitByte = 0;\r
-    unsigned char Mask     = 0x80;    /* !!! ATTENTION: do NOT use 'char', otherwise shifting is wrong!!! */\r
-                                      /* Must be UNSIGNED, not SIGNED! */\r
-\r
-\r
-    /* Switch off I2C to get bit */\r
-    i2c_disable();\r
-    i2c_sda_dir_in();\r
-\r
-    while ( Mask != 0 )\r
-    {\r
-        i2c_set_scl( SCL_HIGH );\r
-        i2c_delay( THIGH );\r
-\r
-        if ( i2c_sda_is_high() )\r
-        {\r
-            aBitByte |= Mask;\r
-        }\r
-\r
-        i2c_set_scl( SCL_LOW );\r
-\r
-        Mask >>= 1;\r
-\r
-        i2c_delay( TLOW );\r
-    }\r
-\r
-    /*\r
-     * we leave the clock low, getbyte is usually followed\r
-     * by sendack/nack, they assume the clock to be low\r
-     */\r
-    return ( aBitByte );\r
-}   /* i2c_inbyte */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_getack\r
- *#\r
- *# DESCRIPTION  : checks if ack was received from ic2\r
- *#\r
- *# PARAMETERS   : none\r
- *#\r
- *# RETURN       : returns the ack state of the I2C device\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-int i2c_getack( void )\r
-{\r
-    int ack = 1;\r
-\r
-    /* generate ACK clock pulse */\r
-    i2c_set_scl( SCL_HIGH );\r
-    \r
-    /* switch off I2C */\r
-    i2c_disable();\r
-\r
-    /* now wait for ack */\r
-    i2c_delay( THIGH );\r
-    /* check for ack: if SDA is high, then NACK, else ACK */\r
-    if ( i2c_sda_is_high() )\r
-    {\r
-        ack = 0;\r
-    }\r
-    else\r
-    {\r
-        ack = 1;\r
-    }\r
-    \r
-    /* end clock pulse */\r
-    i2c_enable();\r
-    i2c_set_scl( SCL_LOW );\r
-    i2c_sda_dir_out();\r
-    i2c_set_sda( SDA_LOW );\r
-\r
-    /* Since we "lost" already THDDAT time, we can subtract it here... */\r
-    i2c_delay( TLOW  - THDDAT );\r
-    \r
-    return ( ack );\r
-}   /* i2c_getack */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_sendack\r
- *#\r
- *# DESCRIPTION  : sends ACK on received data\r
- *#\r
- *# PARAMETERS   : none\r
- *#\r
- *# RETURN       : none\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-void i2c_sendack( void )\r
-{\r
-    /* enable output */\r
-    /* Clock has been set to TLOW already at end of i2c_inbyte()\r
-     * and i2c_outbyte(), so no need to do it again.\r
-     */\r
-    i2c_sda_dir_out();\r
-    /* set ack pulse low */\r
-    i2c_set_sda( SDA_LOW );\r
-    /* generate clock pulse */\r
-    i2c_delay( TSUDAT );\r
-    i2c_set_scl( SCL_HIGH );\r
-    i2c_delay( THIGH );\r
-    i2c_set_scl( SCL_LOW );\r
-    i2c_delay( THDDAT );\r
-    /* reset data out */\r
-    i2c_set_sda( SDA_HIGH );\r
-    /* Subtract time spend already when waited to put SDA high */\r
-    i2c_delay( TLOW - THDDAT );\r
-\r
-    /* release the SDA line */\r
-    i2c_sda_dir_in();\r
-}   /* i2c_sendack */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_sendnack\r
- *#\r
- *# DESCRIPTION  : sends NACK on received data\r
- *#\r
- *# PARAMETERS   : none\r
- *#\r
- *# RETURN       : none\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-void i2c_sendnack( void )\r
-{\r
-    /* make sure the SDA line is set high prior to activation of the output.\r
-     * this way, you avoid an unnecessary peak to ground when a NACK has to\r
-     * be created.\r
-     */\r
-    /* set data high */\r
-    i2c_set_sda( SDA_HIGH );\r
-    /* enable output */\r
-    i2c_sda_dir_out();\r
-\r
-    /* generate clock pulse */\r
-    i2c_delay( TSUDAT );\r
-    i2c_set_scl( SCL_HIGH );\r
-    i2c_delay( THIGH );\r
-    i2c_set_scl( SCL_LOW );\r
-    i2c_delay( TSUDAT );\r
-    i2c_set_sda( SDA_LOW );\r
-    i2c_delay( TLOW - TSUDAT );\r
-    \r
-    /* There's no need to change the direction of SDA to "in" again,\r
-     * since a NACK is always followed by a stop condition.\r
-     * A STOP condition will put the direction of SDA back to "out"\r
-     * resulting in a useless SDA "dip" on the line...\r
-     */\r
-    /* i2c_sda_dir_in(); */\r
-}   /* i2c_sendnack */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_writereg\r
- *#\r
- *# DESCRIPTION  : writes a value to a register of an I2C device\r
- *#\r
- *# PARAMETERS   : theSlave = slave address of the I2C device\r
- *#                theReg   = register of the I2C device that needs to be written\r
- *#                theValue = value to be written to the register\r
- *#\r
- *# RETURN       : returns OR-ed result of the write action:\r
- *#                  0 = Ok\r
- *#                  1 = Slave_NoAck\r
- *#                  2 = Reg_NoAck\r
- *#                  4 = Val_NoAck\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-int i2c_writereg( unsigned char theSlave\r
-                , unsigned char theReg\r
-                , unsigned char theValue \r
-                )\r
-{\r
-    int error, cntr = 3;\r
-    unsigned long flags;\r
-\r
-    spin_lock( &i2c_lock );\r
-\r
-    do \r
-    {\r
-        error = 0;\r
-        /* we don't like to be interrupted */\r
-        local_irq_save( flags );\r
-\r
-        i2c_start();\r
-        /* send slave address */\r
-        if ( EI2CNOACKNLD == i2c_outbyte( theSlave & 0xfe ) )\r
-        {\r
-            error = 1;\r
-        }\r
-            \r
-        /* now select register */\r
-        if ( EI2CNOACKNLD == i2c_outbyte( theReg ) )\r
-        {\r
-            error |= 2;\r
-        }\r
-        \r
-        /* send register register data */\r
-        if ( EI2CNOACKNLD == i2c_outbyte( theValue ) )\r
-        {\r
-            error |= 4;\r
-        }\r
-             \r
-        /* end byte stream */\r
-        i2c_stop();\r
-        /* enable interrupt again */\r
-        local_irq_restore( flags );\r
-        \r
-    } while ( error && cntr-- );\r
-\r
-    i2c_delay( TLOW );\r
-\r
-    spin_unlock( &i2c_lock );\r
-\r
-    return ( -error );\r
-}   /* i2c_writereg */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_readreg\r
- *#\r
- *# DESCRIPTION  : reads the value from a certain register of an I2C device.\r
- *#                Function first writes the register that it wants to read\r
- *#                later on.\r
- *#  \r
- *# PARAMETERS   : theSlave = slave address of the I2C device\r
- *#                theReg   = register of the I2C device that needs to be written\r
- *#\r
- *# RETURN       : returns OR-ed result of the write action:\r
- *#                  0 = Ok\r
- *#                  1 = Slave_NoAck\r
- *#                  2 = Reg_NoAck\r
- *#                  4 = Val_NoAck\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-unsigned char i2c_readreg( unsigned char theSlave\r
-                         , unsigned char theReg \r
-                         )\r
-{\r
-    unsigned char b = 0;\r
-    int error, cntr = 3;\r
-    unsigned long flags;\r
-\r
-    spin_lock( &i2c_lock );\r
-\r
-    do \r
-    {\r
-        error = 0;\r
-        \r
-        /* we don't like to be interrupted */\r
-        local_irq_save( flags );\r
-        \r
-        /* generate start condition */\r
-        i2c_start();\r
-    \r
-        /* send slave address */\r
-        if ( EI2CNOACKNLD == i2c_outbyte( theSlave & 0xfe ) )\r
-        {\r
-            error = 1;\r
-        }\r
-\r
-        /* now select register */\r
-        i2c_sda_dir_out();\r
-\r
-        if ( EI2CNOACKNLD == i2c_outbyte( theReg ) )\r
-        {\r
-            error |= 2;\r
-        }            \r
-\r
-        /* repeat start condition */\r
-        i2c_delay( TLOW );\r
-        i2c_start();\r
-        \r
-        /* send slave address */\r
-        if ( EI2CNOACKNLD == i2c_outbyte( theSlave | 0x01 ) )\r
-        {\r
-            error |= 1;\r
-        }\r
-            \r
-        /* fetch register */\r
-        b = i2c_inbyte();\r
-        /*\r
-         * last received byte needs to be nacked\r
-         * instead of acked\r
-         */\r
-        i2c_sendnack();\r
-        \r
-        /* end sequence */\r
-        i2c_stop();\r
-        \r
-        /* enable interrupt again */\r
-        local_irq_restore( flags );\r
-        \r
-    } while ( error && cntr-- );\r
-\r
-    spin_unlock( &i2c_lock );\r
-\r
-    return ( b );\r
-}   /* i2c_readreg */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_read\r
- *#\r
- *# DESCRIPTION  :\r
- *#  \r
- *# PARAMETERS   :\r
- *#\r
- *# RETURN       :\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-int i2c_read( unsigned char slave, unsigned char* rbuf, unsigned char rlen )\r
-{\r
-    return ( i2c_command( slave, NULL, 0, rbuf, rlen ) );\r
-}   /* i2c_read */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_write\r
- *#\r
- *# DESCRIPTION  :\r
- *#  \r
- *# PARAMETERS   :\r
- *#\r
- *# RETURN       :\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-int i2c_write( unsigned char slave, unsigned char* wbuf, unsigned char wlen )\r
-{\r
-    return ( i2c_command( slave, wbuf, wlen, NULL, 0 ) );\r
-}   /* i2c_write */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: i2c_writeread\r
- *#\r
- *# DESCRIPTION  :\r
- *#  \r
- *# PARAMETERS   :\r
- *#\r
- *# RETURN       :\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-int i2c_writeread( unsigned char  slave\r
-                 , unsigned char* wbuf\r
-                 , unsigned char  wlen\r
-                 , unsigned char* rbuf\r
-                 , unsigned char  rlen\r
-                 )\r
-{\r
-    return ( i2c_command( slave, wbuf, wlen, rbuf, rlen ) );\r
-}   /* i2c_writeread */\r
-\r
-\r
-/*#---------------------------------------------------------------------------\r
- *#\r
- *# FUNCTION NAME: module_init\r
- *#\r
- *# DESCRIPTION  : this makes sure that i2c_register is called during boot\r
- *#\r
- *# PARAMETERS   :\r
- *#\r
- *#---------------------------------------------------------------------------\r
- */\r
-module_init( i2c_register );\r
-\r
-/****************** END OF FILE i2c.c ********************************/\r
+/*!***************************************************************************
+*!
+*! FILE NAME  : i2c.c
+*!
+*!
+*! ---------------------------------------------------------------------------
+*!
+*! ( C ) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN
+*!
+*!***************************************************************************/
+
+/******************** INCLUDE FILES SECTION ****************************/
+
+#include <linux/module.h>
+#include <linux/fs.h>
+
+#ifdef CONFIG_ETRAX_I2C_DYN_ALLOC
+#include <linux/types.h> /* for dev_t */
+#include <linux/cdev.h>  /* for struct cdev */
+#endif
+
+#include <linux/device.h>
+
+#include "etraxi2c.h"
+
+#include "i2c_errno.h"
+
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/arch/io_interface_mux.h>
+#include <asm/uaccess.h>
+
+#include "i2c_gvc.h"
+
+MODULE_DESCRIPTION( "I2C Device Driver - 2.3" );
+
+/*!*********************************************************************
+ *!History I2C driver Geert Vancompernolle
+ *!---------------------------------------
+ *!
+ *! - v1.0:
+ *!     First official version.
+ *!
+ *! - v1.1:
+ *!     Changes to remove unwanted spikes at ACK/NACK time.
+ *!
+ *!*********************************************************************/
+
+MODULE_LICENSE( "GPL" );
+
+/******************            MACRO's            **********************/
+
+#define D( x )
+
+#ifndef CONFIG_ETRAX_I2C_DYN_ALLOC
+#define I2C_MAJOR 123                                  /* LOCAL/EXPERIMENTAL */
+#endif
+
+#define WAITONEUS                 1
+/* Following are abbreviations taken from Philips I2C standard */
+/* Values are representing time in us and are rounded to next whole number, if relevant */
+#define THDSTA                    4     /* Hold delay time for (repeated) START condition */
+#define TLOW                      5     /* LOW period of the SCL clock */
+#define THDDAT                   1     /* Hold delay time for DATA: value of 0 is allowed but 1 taken to be sure */
+#define TSUDAT                    1     /* Set-up time for DATA */
+#define THIGH                     4     /* HIGH period of the SCL clock */
+#define TSUSTA                    5     /* Set-up time for a repeated START condition */
+#define TSUSTO                    4     /* Set-up time for STOP condition */
+#define TBUF                      5     /* Bus-free time between STOP and START condition */
+
+#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
+#define MAXSCLRETRIES            100
+#endif
+
+#define MAXBUSFREERETRIES         5
+#define MAXRETRIES                3
+#define WRITEADDRESS_MASK         ( 0xFE )
+#define READADDRESS_MASK          ( 0x01 )
+
+#define SCL_HIGH                  1
+#define SCL_LOW                   0
+#define SDA_HIGH                  1
+#define SDA_LOW                   0
+
+#ifdef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C
+/* Use PB and not PB_I2C */
+#ifndef CONFIG_ETRAX_I2C_DATA_PORT
+#define CONFIG_ETRAX_I2C_DATA_PORT 0
+#endif
+#ifndef CONFIG_ETRAX_I2C_CLK_PORT
+#define CONFIG_ETRAX_I2C_CLK_PORT 1
+#endif
+
+#define SDABIT CONFIG_ETRAX_I2C_DATA_PORT
+#define SCLBIT CONFIG_ETRAX_I2C_CLK_PORT
+#define i2c_enable()
+#define i2c_disable()
+
+/* enable or disable output-enable, to select output or input on the i2c bus */
+#define i2c_sda_dir_out() \
+  REG_SHADOW_SET( R_PORT_PB_DIR, port_pb_dir_shadow, SDABIT, 1 )
+#define i2c_sda_dir_in()  \
+  REG_SHADOW_SET( R_PORT_PB_DIR, port_pb_dir_shadow, SDABIT, 0 )
+
+#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
+#define i2c_scl_dir_out() \
+  REG_SHADOW_SET( R_PORT_PB_DIR, port_pb_dir_shadow, SCLBIT, 1 )
+#define i2c_scl_dir_in()  \
+  REG_SHADOW_SET( R_PORT_PB_DIR, port_pb_dir_shadow, SCLBIT, 0 )
+#endif
+
+/* control the i2c clock and data signals */
+#define i2c_set_scl( x ) \
+  REG_SHADOW_SET( R_PORT_PB_DATA, port_pb_data_shadow, SCLBIT, x )
+#define i2c_set_sda( x ) \
+  REG_SHADOW_SET( R_PORT_PB_DATA, port_pb_data_shadow, SDABIT, x )
+
+/* read status of SDA bit from the i2c interface */
+#define i2c_sda_is_high() ( ( ( *R_PORT_PB_READ & ( 1 << SDABIT ) ) ) >> SDABIT )
+
+/* read status of SCL bit from the i2c interface */
+#define i2c_scl_is_high() ( ( ( *R_PORT_PB_READ & ( 1 << SCLBIT ) ) ) >> SCLBIT )
+
+#else
+/* enable or disable the i2c interface */
+#define i2c_enable() *R_PORT_PB_I2C = ( port_pb_i2c_shadow |= IO_MASK( R_PORT_PB_I2C, i2c_en ) )
+#define i2c_disable() *R_PORT_PB_I2C = ( port_pb_i2c_shadow &= ~IO_MASK( R_PORT_PB_I2C, i2c_en ) )
+
+/* enable or disable output-enable, to select output or input on the i2c bus */
+#define i2c_sda_dir_out() \
+       *R_PORT_PB_I2C = ( port_pb_i2c_shadow &= ~IO_MASK( R_PORT_PB_I2C, i2c_oe_ ) ); \
+       REG_SHADOW_SET( R_PORT_PB_DIR, port_pb_dir_shadow, 0, 1 );
+#define i2c_sda_dir_in() \
+       *R_PORT_PB_I2C = ( port_pb_i2c_shadow |= IO_MASK( R_PORT_PB_I2C, i2c_oe_ ) ); \
+       REG_SHADOW_SET( R_PORT_PB_DIR, port_pb_dir_shadow, 0, 0 );
+
+/* control the i2c clock and data signals */
+#define i2c_set_scl( x ) \
+       *R_PORT_PB_I2C = ( port_pb_i2c_shadow = ( port_pb_i2c_shadow & \
+       ~IO_MASK( R_PORT_PB_I2C, i2c_set_scl ) ) | IO_FIELD( R_PORT_PB_I2C, i2c_set_scl, ( x ) ) ); \
+       REG_SHADOW_SET( R_PORT_PB_DATA, port_pb_data_shadow, 1, x );
+
+#define i2c_set_sda( x ) \
+       *R_PORT_PB_I2C = ( port_pb_i2c_shadow = ( port_pb_i2c_shadow & \
+          ~IO_MASK( R_PORT_PB_I2C, i2c_d ) ) | IO_FIELD( R_PORT_PB_I2C, i2c_d, ( x ) ) ); \
+       REG_SHADOW_SET( R_PORT_PB_DATA, port_pb_data_shadow, 0, x );
+
+/* read a bit from the i2c interface */
+#define i2c_sda_is_high() ( *R_PORT_PB_READ & 0x1 )
+#endif
+
+/* use the kernels delay routine */
+#define i2c_delay( usecs ) udelay( usecs )
+
+
+/******************           TYPEDEF's           **********************/
+
+
+/****************** STATIC (file scope) VARIABLES **********************/
+static DEFINE_SPINLOCK( i2c_lock ); /* Protect directions etc */
+static const char i2c_name[] = "i2c";
+
+
+
+/******************     PROTOTYPING SECTION     *************************/
+static int  i2c_open( struct inode *inode, struct file *filp );
+static int  i2c_release( struct inode *inode, struct file *filp );
+static int  i2c_command( unsigned char  slave
+                       , unsigned char* wbuf
+                       , unsigned char  wlen
+                       , unsigned char* rbuf
+                       , unsigned char  rlen
+                       );
+static int  i2c_bus_free_check( unsigned char maxretries );
+static void i2c_finalise( const char* text, unsigned long irqflags );
+
+
+/************************************************************************/
+/******************         AUXILIARIES         *************************/
+/************************************************************************/
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_open
+ *#
+ *# DESCRIPTION  : opens an I2C device
+ *#
+ *# PARAMETERS   : *inode: reference to inode
+ *#                *filp : reference to file pointer
+ *#
+ *#---------------------------------------------------------------------------
+ */
+static int i2c_open( struct inode *inode, struct file *filp )
+{
+    return 0;
+}   /* i2c_open */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_release
+ *#
+ *# DESCRIPTION  : Releases the I2C device
+ *#
+ *# PARAMETERS   : *inode: reference to inode
+ *#                *filp : reference to file pointer
+ *#
+ *#---------------------------------------------------------------------------
+ */
+static int i2c_release( struct inode *inode, struct file *filp )
+{
+    return 0;
+}   /* i2c_release */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_ioctl
+ *#
+ *# DESCRIPTION  : Main device API: ioctl's to write/read
+ *#                to/from i2c registers
+ *#
+ *# PARAMETERS   : *inode: reference to inode
+ *#                *filp : reference to file pointer
+ *#                cmd   : command to be executed during the ioctl call
+ *#                arg   : pointer to a structure with the data???
+ *#
+ *# RETURN       : result of the ioctl call
+ *#
+ *#---------------------------------------------------------------------------
+ */
+static int i2c_ioctl( struct inode *inode
+                    , struct file *file
+                    , unsigned int cmd
+                    , unsigned long arg
+                    )
+{
+    /* the acme ioctls */
+    I2C_DATA i2cdata;
+    int RetVal = EI2CNOERRORS;
+
+    if ( _IOC_TYPE( cmd ) != ETRAXI2C_IOCTYPE )
+    {
+        return ( -EINVAL );
+    }
+
+    switch ( _IOC_NR( cmd ) )
+    {
+    case I2C_WRITEREG:
+        /* write to an i2c slave */
+        RetVal = i2c_writereg( I2C_ARGSLAVE( arg )
+                             , I2C_ARGREG( arg )
+                             , I2C_ARGVALUE( arg )
+                             );
+        break;
+
+    case I2C_READREG:
+        RetVal = i2c_readreg( I2C_ARGSLAVE( arg ), I2C_ARGREG( arg ) );
+        break;
+
+    /* New functions added by GVC */
+    case I2C_READ:
+        copy_from_user( (char*)&i2cdata, (char*)arg, sizeof( I2C_DATA ) );
+        {
+            int RetryCntr = MAXRETRIES;
+
+            do
+            {
+                RetVal = i2c_command( i2cdata.slave
+                                    , NULL
+                                    , 0
+                                    , i2cdata.rbuf
+                                    , i2cdata.rlen
+                                    );
+             } while ( ( EI2CNOERRORS != RetVal )
+                     &&( --RetryCntr )
+                     );
+        }
+        copy_to_user( (char*)arg, (char*)&i2cdata, sizeof( I2C_DATA ) );
+        break;
+
+    case I2C_WRITE:
+        copy_from_user( (char*)&i2cdata, (char*)arg, sizeof( I2C_DATA ) );
+        {
+            int RetryCntr = MAXRETRIES;
+
+            do
+            {
+                RetVal = i2c_command( i2cdata.slave
+                                    , i2cdata.wbuf
+                                    , i2cdata.wlen
+                                    , NULL
+                                    , 0
+                                    );
+             } while ( ( EI2CNOERRORS != RetVal )
+                     &&( --RetryCntr )
+                     );
+        }
+        break;
+
+    case I2C_WRITEREAD:
+        copy_from_user( (char*)&i2cdata, (char*)arg, sizeof( I2C_DATA ) );
+        {
+            int RetryCntr = MAXRETRIES;
+
+            do
+            {
+                RetVal = i2c_command( i2cdata.slave
+                                    , i2cdata.wbuf
+                                    , i2cdata.wlen
+                                    , i2cdata.rbuf
+                                    , i2cdata.rlen
+                                    );
+             } while ( ( EI2CNOERRORS != RetVal )
+                     &&( --RetryCntr )
+                     );
+        }
+        copy_to_user( (char*)arg, (char*)&i2cdata, sizeof( I2C_DATA ) );
+        break;
+
+    default:
+        RetVal = -EINVAL;
+    }
+
+    return ( -RetVal );
+}   /* i2c_ioctl */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_command
+ *#
+ *# DESCRIPTION  : general routine to read/write bytes from an I2C device
+ *#
+ *#                'i2c_command()' sends wlen bytes to the I2c bus and receives
+ *#                rlen bytes from the I2c bus.
+ *#                The data to be send must be placed in wbuf[ 0 ] upto wbuf[ wlen - 1 ).
+ *#                The data to be received is assembled in rbuf[ 0 ] upto rbuf[ rlen - 1 ].
+ *#
+ *#                If no data is to be sent or received, put appropriate buffer parameter
+ *#                to "NULL" and appropriate length parameter to "0".
+ *#
+ *# PARAMETERS   : slave = slave address of the I2C device
+ *#                wbuf  = address of first element of write buffer (wbuf)
+ *#                wlen  = number of bytes to be written to slave
+ *#                rbuf  = address of first element of read buffer (rbuf)
+ *#                rlen  = number of bytes to be read from slave
+ *#
+ *# RETURN       :
+ *#    EI2CNOERRORS: I2C communication went fine
+ *#    EI2CBUSNFREE: I2C bus is not free
+ *#    EI2CWADDRESS: I2C write address failed
+ *#    EI2CRADDRESS: I2C read address failed
+ *#    EI2CSENDDATA: I2C send data failed
+ *#    EI2CRECVDATA: I2C receive data failed
+ *#    EI2CSTRTCOND: I2C start condition failed
+ *#    EI2CRSTACOND: I2C repeated start condition failed
+ *#    EI2CSTOPCOND: I2C stop condition failed
+ *#    EI2CNOSNDBYT: I2C no bytes to be sent
+ *#    EI2CNOSNDBUF: I2C no send buffer defined
+ *#    EI2CNORCVBYT: I2C no bytes to be received
+ *#    EI2CNORCVBUF: I2C no receive buffer defined
+ *#    EI2CNOACKNLD: I2C no acknowledge received
+ *#
+ *# REMARK       :
+ *#   First, the send part is completed.
+ *#   In the send routine, there is no stop generated.  This is because maybe
+ *#   a repeated start condition must be generated.
+ *#   This happens when we want to receive some data from the I2c bus.  If not,
+ *#   at the end of the general I2c loop the stopcondition is generated.
+ *#   If, on the contrary, there are a number of bytes to be received, a new
+ *#   startcondition is generated in the 'if' part of the main I2c routine,
+ *#   which controls the receiving part.
+ *#   Only when the receiving of data is finished, a final stopcondition is
+ *#   generated.
+ *#
+ *#---------------------------------------------------------------------------
+ */
+static int i2c_command( unsigned char  slave
+                      , unsigned char* wbuf
+                      , unsigned char  wlen
+                      , unsigned char* rbuf
+                      , unsigned char  rlen
+                      )
+{
+    /* Check arguments and report error if relevant... */
+    if ( ( wlen > 0 ) && ( wbuf == NULL ) )
+    {
+        printk( KERN_DEBUG "I2C: EI2CNOSNDBUF\n" );
+        return ( EI2CNOSNDBUF );
+    }
+    else if ( ( wlen == 0 ) && ( wbuf != NULL ) )
+    {
+        printk( KERN_DEBUG "I2C: EI2CNOSNDBYT\n" );
+        return ( EI2CNOSNDBYT );
+    }
+    else if ( ( rlen > 0 ) && ( rbuf == NULL ) )
+    {
+        printk( KERN_DEBUG "I2C: EI2CNORCVBUF\n" );
+        return ( EI2CNORCVBUF );
+    }
+    else if ( ( rlen == 0 ) && ( rbuf != NULL ) )
+    {
+        printk( KERN_DEBUG "I2C: EI2CNORCVBYT\n" );
+        return ( EI2CNORCVBYT );
+    }
+    else if ( EI2CBUSNFREE == i2c_bus_free_check( MAXBUSFREERETRIES ) )
+    {
+        /* There's no need to try more, since we weren't even
+         * able to start the I2C communication.
+         * So, no IRQ flags are stored yet, no changes to any other
+         * stuff like START, STOP, SENDBYTES...
+         * Result, simply write down the error and return the correct error code.
+         */
+        printk( KERN_DEBUG "I2C: EI2CBUSNFREE\n" );
+        return ( EI2CBUSNFREE );
+    }
+    else
+    {
+        /* Finally... We made it... */
+        unsigned long irqflags = 0;
+
+        /* we don't like to be interrupted */
+        local_irq_save( irqflags );
+
+        /* Check if there are bytes to be send,
+         * or if you immediately want to receive data.
+         */
+        if ( 0 < wlen )
+        {
+            /* start I2C communication */
+            if ( EI2CNOERRORS != i2c_start() )
+            {
+                return ( i2c_finalise( "I2C: EI2CSTRTCOND\n", irqflags  )
+                       , EI2CSTRTCOND
+                       );
+            }
+
+            /* send slave address: xxxxxxx0B (last bit must be zero) */
+            if ( EI2CNOERRORS != i2c_outbyte( slave & WRITEADDRESS_MASK ) )
+            {
+                return ( i2c_finalise( "I2C: EI2CWADDRESS\n", irqflags  )
+                       , EI2CWADDRESS
+                       );
+            }
+
+            while ( wlen-- )
+            {
+                /* send register data */
+                if ( EI2CNOERRORS != i2c_outbyte( *wbuf ) && wlen )
+                {
+                    return ( i2c_finalise( "I2C: EI2CSENDDATA\n", irqflags  )
+                           , EI2CSENDDATA
+                           );
+                }
+
+                wbuf++;
+            };
+
+            i2c_delay( TLOW );
+        }
+
+        /*
+         * Receiving data from I2c_bus
+         * If there are bytes to be received, a new start condition is
+         * generated => Repeated Startcondition.
+         * A final stopcondition is generated at the end of the main I2c
+         * routine.
+         */
+        if ( 0 < rlen )
+        {
+            /*
+             * Generate start condition if wlen == 0
+             * or repeated start condition if wlen != 0...
+             */
+            if ( EI2CNOERRORS != i2c_start() )
+            {
+                return ( i2c_finalise( ( ( 0 < wlen )
+                                       ? "I2C: EI2CRSTACOND\n"
+                                       : "I2C: EI2CSTRTCOND\n"
+                                       )
+                                     , irqflags
+                                     )
+                       , ( ( 0 < wlen ) ? EI2CRSTACOND : EI2CSTRTCOND )
+                       );
+            }
+
+            /* Send ReadAddress: xxxxxxx1B (last bit must be one) */
+            if ( EI2CNOERRORS != i2c_outbyte( slave | READADDRESS_MASK ) )
+            {
+                return ( i2c_finalise( "I2C: EI2CRADDRESS\n", irqflags )
+                       , EI2CRADDRESS
+                       );
+            }
+
+            while ( rlen-- )
+            {
+                /* fetch register */
+                *rbuf = i2c_inbyte();
+                rbuf++;
+
+                /* last received byte needs to be NACK-ed instead of ACK-ed */
+                if ( rlen )
+                {
+                    i2c_sendack();
+                }
+                else
+                {
+                    i2c_sendnack();
+                }
+            };
+        }
+
+        /* Generate final stop condition */
+        if ( EI2CNOERRORS != i2c_stop() )
+        {
+            return ( i2c_finalise( "I2C CMD: EI2CSTOPCOND\n", irqflags )
+                   , EI2CSTOPCOND
+                   );
+        }
+
+        /* enable interrupt again */
+        local_irq_restore( irqflags );
+    }
+
+    return ( EI2CNOERRORS );
+} /*  i2c_command */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_bus_free_check
+ *#
+ *# DESCRIPTION  : checks if the I2C bus is free before starting
+ *#                an I2C communication
+ *#
+ *# PARAMETERS   : maxretries, the number of times we will try to release
+ *#                the I2C bus
+ *#
+ *# RETURN       : I2cStatus_I2cBusNotFreeError in case the bus is not free,
+ *#                I2cStatus_I2cNoError otherwise
+ *#
+ *#---------------------------------------------------------------------------
+ */
+static int i2c_bus_free_check( unsigned char maxretries )
+{
+    i2c_sda_dir_in();        /* Release SDA line */
+    i2c_set_scl( SCL_HIGH ); /* put SCL line high */
+
+    i2c_delay( WAITONEUS );
+
+    while ( ( !i2c_sda_is_high() || !i2c_scl_is_high() )
+          &&( maxretries-- )
+          )
+    {
+        /* Try to release I2C bus by generating STOP conditions */
+        i2c_stop();
+    }
+
+    if ( 0 == maxretries )
+    {
+        printk( KERN_DEBUG "I2C: EI2CBUSNFREE\n" );
+        return ( EI2CBUSNFREE );
+    }
+    else
+    {
+        return ( EI2CNOERRORS );
+    }
+} /* i2c_bus_free_check */
+
+
+static void i2c_finalise( const char* errortxt
+                        , unsigned long irqflags
+                        )
+{
+    printk( KERN_DEBUG "%s", errortxt );
+    local_irq_restore( irqflags );
+    /* The least we can do when things go terribly wrong,
+     * is to try to release the bus.
+     * If this fails, well, then I don't know
+     * what I can do more for the moment...
+     */
+    (void)i2c_bus_free_check( MAXBUSFREERETRIES );
+}   /* i2c_finalise */
+
+
+static struct file_operations i2c_fops =
+{
+    .owner    = THIS_MODULE
+,   .ioctl    = i2c_ioctl
+,   .open     = i2c_open
+,   .release  = i2c_release
+};
+
+
+/***********************************************************************/
+/************* EXTERNAL FUNCTION DEFINITION SECTION ********************/
+/***********************************************************************/
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_init
+ *#
+ *# DESCRIPTION  : initialises the I2C device driver
+ *#
+ *# PARAMETERS   :
+ *#
+ *#---------------------------------------------------------------------------
+ */
+int __init i2c_init( void )
+{
+    static int res = 0;
+    static int first = 1;
+
+    if ( !first )
+    {
+        return res;
+    }
+
+    first = 0;
+
+    /* Setup and enable the Port B I2C interface */
+
+#ifndef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C
+    /* here, we're using the dedicated I2C pins of FoxBoard */
+    if ( ( res = cris_request_io_interface( if_i2c, "I2C" ) ) )
+    {
+        printk( KERN_CRIT "i2c_init: Failed to get IO interface\n" );
+        return res;
+    }
+
+    *R_PORT_PB_I2C = port_pb_i2c_shadow |=
+        IO_STATE( R_PORT_PB_I2C, i2c_en,  on ) |
+        IO_FIELD( R_PORT_PB_I2C, i2c_d,   1 )  |
+        IO_FIELD( R_PORT_PB_I2C, i2c_set_scl, 1 )  |
+        IO_STATE( R_PORT_PB_I2C, i2c_oe_, enable );
+
+    port_pb_dir_shadow &= ~IO_MASK( R_PORT_PB_DIR, dir0 );
+    port_pb_dir_shadow &= ~IO_MASK( R_PORT_PB_DIR, dir1 );
+
+    *R_PORT_PB_DIR = ( port_pb_dir_shadow |=
+              IO_STATE( R_PORT_PB_DIR, dir0, input )  |
+              IO_STATE( R_PORT_PB_DIR, dir1, output ) );
+#else
+        /* If everything goes fine, res = 0, meaning "if" fails =>
+         * will do the "else" too and as such initialise the clock port...
+         * Clever trick!
+         */
+        if ( ( res = cris_io_interface_allocate_pins( if_i2c
+                                                    , 'b'
+                                                    , CONFIG_ETRAX_I2C_DATA_PORT
+                                                    , CONFIG_ETRAX_I2C_DATA_PORT
+                                                    )
+             )
+           )
+        {
+            printk( KERN_WARNING "i2c_init: Failed to get IO pin for I2C data port\n" );
+            return ( res );
+        }
+        /* Same here...*/
+        else if ( ( res = cris_io_interface_allocate_pins( if_i2c
+                                                         , 'b'
+                                                         , CONFIG_ETRAX_I2C_CLK_PORT
+                                                         , CONFIG_ETRAX_I2C_CLK_PORT
+                                                         )
+                  )
+                )
+        {
+            cris_io_interface_free_pins( if_i2c
+                                       , 'b'
+                                       , CONFIG_ETRAX_I2C_DATA_PORT
+                                       , CONFIG_ETRAX_I2C_DATA_PORT
+                                       );
+            printk( KERN_WARNING "i2c_init: Failed to get IO pin for I2C clk port\n" );
+        }
+#endif
+
+    return ( res );
+}   /* i2c_init */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_register
+ *#
+ *# DESCRIPTION  : this registers the i2c driver as a character device
+ *#
+ *# PARAMETERS   :
+ *#
+ *#---------------------------------------------------------------------------
+ */
+
+static struct class *i2c_class;
+
+static int __init i2c_register( void )
+{
+    int res;
+#ifdef CONFIG_ETRAX_I2C_DYN_ALLOC
+    dev_t devt;
+    struct cdev *my_i2cdev = NULL;
+#endif
+
+    res = i2c_init();
+
+    if ( res < 0 )
+    {
+        return res;
+    }
+
+#ifdef CONFIG_ETRAX_I2C_DYN_ALLOC
+    res = alloc_chrdev_region( &devt, 0, 1, i2c_name );
+
+    if ( res < 0 )
+    {
+        printk( KERN_DEBUG "I2C: EI2CNOMNUMBR\n" );
+        return ( res );
+    }
+
+    my_i2cdev = cdev_alloc();
+    my_i2cdev->ops = &i2c_fops;
+    my_i2cdev->owner = THIS_MODULE;
+
+    /* make device "alive" */
+    res = cdev_add( my_i2cdev, devt, 1 );
+
+    if ( res < 0 )
+    {
+        printk( KERN_DEBUG "I2C: EI2CDADDFAIL\n" );
+        return ( res );
+    }
+
+    int i2c_major = MAJOR( devt );
+#else
+    res = register_chrdev( I2C_MAJOR, i2c_name, &i2c_fops );
+
+    if ( res < 0 )
+    {
+        printk( KERN_ERR "i2c: couldn't get a major number.\n" );
+        return res;
+    }
+   
+    int i2c_major = I2C_MAJOR;
+#endif
+
+    printk( KERN_INFO "I2C: driver v2.3, (c) 1999-2004 Axis Communications AB\n" );
+    printk( KERN_INFO "I2C: Improvements by Geert Vancompernolle, Positive Going, BK srl\n" );
+
+#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
+    printk( KERN_INFO "I2C: with master/slave delay patch\n" );
+#endif
+
+    i2c_class = class_create (THIS_MODULE, "i2c_etrax");
+    device_create (i2c_class, NULL,
+                  MKDEV(i2c_major,0), NULL, i2c_name);
+
+    return ( 0 );
+}   /* i2c_register */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_start
+ *#
+ *# DESCRIPTION  : generate i2c start condition
+ *#
+ *# PARAMETERS   : none
+ *#
+ *# RETURN       : EI2CNOERRORS if OK, EI2CSTRTCOND otherwise
+ *#
+ *#---------------------------------------------------------------------------
+ */
+int i2c_start( void )
+{
+  /* Set SCL=1, SDA=1 */
+  i2c_sda_dir_out();
+  i2c_set_sda( SDA_HIGH );
+  i2c_delay( WAITONEUS );
+  i2c_set_scl( SCL_HIGH );
+  i2c_delay( WAITONEUS );
+  
+  /* Set SCL=1, SDA=0 */
+  i2c_set_sda( SDA_LOW );
+  i2c_delay( THDSTA );
+  
+  /* Set SCL=0, SDA=0 */
+  i2c_set_scl( SCL_LOW );
+  /* We can take 1 us less than defined in spec (5 us), since the next action
+   * will be to set the dataline high or low and this action is 1 us
+   * before the clock is put high, so that makes our 5 us.
+   */
+  i2c_delay( TLOW - WAITONEUS );
+  
+  if ( i2c_sda_is_high() || i2c_scl_is_high() )
+    {
+      printk( KERN_DEBUG "I2C: EI2CSTRTCOND\n" );
+      return ( EI2CSTRTCOND );
+    }
+  
+  return ( EI2CNOERRORS );
+}   /* i2c_start */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_stop
+ *#
+ *# DESCRIPTION  : generate i2c stop condition
+ *#
+ *# PARAMETERS   : none
+ *#
+ *# RETURN       : none
+ *#
+ *#---------------------------------------------------------------------------
+ */
+int i2c_stop( void )
+{
+#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
+    int n=MAXSCLRETRIES;
+#endif
+    i2c_sda_dir_out();
+    
+    /* Set SCL=0, SDA=0 */
+    /* Don't change order, otherwise you might generate a start condition! */
+    i2c_set_scl( SCL_LOW );
+    i2c_delay( WAITONEUS );
+    i2c_set_sda( SDA_LOW );
+    i2c_delay( WAITONEUS );
+    
+    /* Set SCL=1, SDA=0 */
+    
+#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
+    i2c_set_scl( SCL_HIGH );
+    i2c_scl_dir_in();
+    for( ; n>0; n-- )
+      {
+       if( i2c_scl_is_high() )
+         break;
+       i2c_delay( TSUSTO );
+      }
+    
+    i2c_scl_dir_out();
+#else
+    i2c_set_scl( SCL_HIGH );
+#endif
+    i2c_delay( TSUSTO );
+    
+    /* Set SCL=1, SDA=1 */
+    i2c_set_sda( SDA_HIGH );
+    i2c_delay( TBUF );
+    
+    i2c_sda_dir_in();
+    
+    if ( !i2c_sda_is_high() || !i2c_scl_is_high() )
+      {
+       return ( EI2CSTOPCOND );
+      }
+    
+    return ( EI2CNOERRORS );
+}   /* i2c_stop */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_outbyte
+ *#
+ *# DESCRIPTION  : write a byte to the i2c interface
+ *#
+ *# PARAMETERS   : x: byte to be sent on the I2C bus
+ *#
+ *# RETURN       : none
+ *#
+ *#---------------------------------------------------------------------------
+ */
+int i2c_outbyte( unsigned char x )
+{
+    int i;
+
+    i2c_sda_dir_out();
+
+    for ( i = 0; i < 8; i++ )
+    {
+        if ( x & 0x80 )
+        {
+            i2c_set_sda( SDA_HIGH );
+        }
+        else
+        {
+            i2c_set_sda( SDA_LOW );
+        }
+
+        i2c_delay( TSUDAT );
+        i2c_set_scl( SCL_HIGH );
+        i2c_delay( THIGH );
+        i2c_set_scl( SCL_LOW );
+        i2c_delay( TSUDAT );
+        i2c_set_sda( SDA_LOW );
+        /* There should be only 5 us between falling edge and new rising
+         * edge of clock pulse.
+         * Since we spend already 1 us since clock edge was low, there are
+         * only ( TLOW - TSUDAT ) us left.
+         * Next to this, since the data line will be set up 1 us before the
+         * clock line is set up, we can reduce the delay with another us.
+         */
+        i2c_delay( TLOW - TSUDAT - WAITONEUS );
+        x <<= 1;
+    }
+
+    /* enable input */
+    i2c_sda_dir_in();
+
+    if ( !i2c_getack() )
+      {
+        return( EI2CNOACKNLD );
+      }
+
+    return ( EI2CNOERRORS );
+}   /* i2c_outbyte */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_inbyte
+ *#
+ *# DESCRIPTION  : read a byte from the i2c interface
+ *#
+ *# PARAMETERS   : none
+ *#
+ *# RETURN       : returns the byte read from the I2C device
+ *#
+ *#---------------------------------------------------------------------------
+ */
+unsigned char i2c_inbyte( void )
+{
+#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
+    int n=MAXSCLRETRIES;
+#endif
+    unsigned char aBitByte = 0;
+    unsigned char Mask     = 0x80;    /* !!! ATTENTION: do NOT use 'char', otherwise shifting is wrong!!! */
+                                      /* Must be UNSIGNED, not SIGNED! */
+
+
+    /* Switch off I2C to get bit */
+    i2c_disable();
+    i2c_sda_dir_in();
+
+    while ( Mask != 0 )
+    {
+#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
+       i2c_scl_dir_in();
+       for( ; n>0; n-- )
+       {       
+               if( i2c_scl_is_high() )
+                       break;
+               i2c_delay( THIGH );
+       }
+
+        i2c_set_scl( SCL_HIGH );
+       i2c_scl_dir_out();
+#else
+        i2c_set_scl( SCL_HIGH );
+#endif
+        i2c_delay( THIGH );
+
+        if ( i2c_sda_is_high() )
+        {
+            aBitByte |= Mask;
+        }
+
+        i2c_set_scl( SCL_LOW );
+
+        Mask >>= 1;
+
+        i2c_delay( TLOW );
+    }
+
+    /*
+     * we leave the clock low, getbyte is usually followed
+     * by sendack/nack, they assume the clock to be low
+     */
+    return ( aBitByte );
+}   /* i2c_inbyte */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_getack
+ *#
+ *# DESCRIPTION  : checks if ack was received from ic2
+ *#
+ *# PARAMETERS   : none
+ *#
+ *# RETURN       : returns the ack state of the I2C device
+ *#
+ *#---------------------------------------------------------------------------
+ */
+int i2c_getack( void )
+{
+    int ack = 1;
+#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
+    int n=MAXSCLRETRIES;
+#endif
+
+    /* generate ACK clock pulse */
+    i2c_set_scl( SCL_HIGH );
+
+    /* switch off I2C */
+    i2c_disable();
+
+#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
+    /* set clock low */
+    i2c_set_scl( SCL_LOW );
+
+    /* now wait for ack */
+    i2c_delay( THIGH );
+
+    /* set clock as input */
+    i2c_scl_dir_in();
+
+    /* wait for clock to rise (n=MAXSCLRETRIES) */
+    for( ; n>0; n-- )
+    {
+       if( i2c_scl_is_high() )
+            break;
+       i2c_delay( THIGH );
+    }
+
+    i2c_set_scl( SCL_HIGH );
+
+    i2c_scl_dir_out();
+
+    i2c_delay( THIGH );
+#else
+    /* now wait for ack */
+    i2c_delay( THIGH );
+#endif
+
+    /* check for ack: if SDA is high, then NACK, else ACK */
+    if ( i2c_sda_is_high() )
+    {
+        ack = 0;
+    }
+    else
+    {
+        ack = 1;
+    }
+
+    /* end clock pulse */
+    i2c_enable();
+    i2c_set_scl( SCL_LOW );
+    i2c_sda_dir_out();
+    i2c_set_sda( SDA_LOW );
+
+    /* Since we "lost" already THDDAT time, we can subtract it here... */
+    i2c_delay( TLOW  - THDDAT );
+
+    return ( ack );
+}   /* i2c_getack */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_sendack
+ *#
+ *# DESCRIPTION  : sends ACK on received data
+ *#
+ *# PARAMETERS   : none
+ *#
+ *# RETURN       : none
+ *#
+ *#---------------------------------------------------------------------------
+ */
+void i2c_sendack( void )
+{
+#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
+    int n=MAXSCLRETRIES;
+#endif
+
+    /* enable output */
+    /* Clock has been set to TLOW already at end of i2c_inbyte()
+     * and i2c_outbyte(), so no need to do it again.
+     */
+    i2c_sda_dir_out();
+    /* set ack pulse low */
+    i2c_set_sda( SDA_LOW );
+    /* generate clock pulse */
+    i2c_delay( TSUDAT );
+
+#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
+    i2c_scl_dir_in();
+    /* wait for clock to rise (n=MAXSCLRETRIES) */
+    for( ; n>0; n-- )
+    {
+       if( i2c_scl_is_high() )
+            break;
+       i2c_delay( THIGH );
+    }
+
+    i2c_set_scl( SCL_HIGH );
+    i2c_scl_dir_out();
+    i2c_delay( THIGH );
+#else
+    i2c_set_scl( SCL_HIGH );
+
+    i2c_delay( THIGH );
+#endif
+    i2c_set_scl( SCL_LOW );
+    i2c_delay( THDDAT );
+    /* reset data out */
+    i2c_set_sda( SDA_HIGH );
+    /* Subtract time spend already when waited to put SDA high */
+    i2c_delay( TLOW - THDDAT );
+
+    /* release the SDA line */
+    i2c_sda_dir_in();
+}   /* i2c_sendack */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_sendnack
+ *#
+ *# DESCRIPTION  : sends NACK on received data
+ *#
+ *# PARAMETERS   : none
+ *#
+ *# RETURN       : none
+ *#
+ *#---------------------------------------------------------------------------
+ */
+void i2c_sendnack( void )
+{
+#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
+    int n=MAXSCLRETRIES;
+#endif
+
+    /* make sure the SDA line is set high prior to activation of the output.
+     * this way, you avoid an unnecessary peak to ground when a NACK has to
+     * be created.
+     */
+    /* set data high */
+    i2c_set_sda( SDA_HIGH );
+    /* enable output */
+    i2c_sda_dir_out();
+
+    /* generate clock pulse */
+    i2c_delay( TSUDAT );
+
+#ifdef CONFIG_ETRAX_I2C_SLAVE_DELAY
+    i2c_scl_dir_in();
+    /* wait for clock to rise (n=MAXSCLRETRIES) */
+    for( ; n>0; n-- )
+    {
+       if( i2c_scl_is_high() )
+            break;
+       i2c_delay( THIGH );
+    }
+
+    i2c_set_scl( SCL_HIGH );
+    i2c_scl_dir_out();
+    i2c_delay( THIGH );
+#else
+    i2c_set_scl( SCL_HIGH );
+
+    i2c_delay( THIGH );
+#endif
+    i2c_set_scl( SCL_LOW );
+    i2c_delay( TSUDAT );
+    i2c_set_sda( SDA_LOW );
+    i2c_delay( TLOW - TSUDAT );
+
+    /* There's no need to change the direction of SDA to "in" again,
+     * since a NACK is always followed by a stop condition.
+     * A STOP condition will put the direction of SDA back to "out"
+     * resulting in a useless SDA "dip" on the line...
+     */
+    /* i2c_sda_dir_in(); */
+}   /* i2c_sendnack */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_writereg
+ *#
+ *# DESCRIPTION  : writes a value to a register of an I2C device
+ *#
+ *# PARAMETERS   : theSlave = slave address of the I2C device
+ *#                theReg   = register of the I2C device that needs to be written
+ *#                theValue = value to be written to the register
+ *#
+ *# RETURN       : returns OR-ed result of the write action:
+ *#                  0 = Ok
+ *#                  1 = Slave_NoAck
+ *#                  2 = Reg_NoAck
+ *#                  4 = Val_NoAck
+ *#
+ *#---------------------------------------------------------------------------
+ */
+int i2c_writereg( unsigned char theSlave
+                , unsigned char theReg
+                , unsigned char theValue
+                )
+{
+    int error, cntr = 3;
+    unsigned long flags;
+
+    spin_lock( &i2c_lock );
+
+    do
+    {
+        error = 0;
+        /* we don't like to be interrupted */
+        local_irq_save( flags );
+
+        i2c_start();
+        /* send slave address */
+        if ( EI2CNOACKNLD == i2c_outbyte( theSlave & 0xfe ) )
+        {
+            error = 1;
+        }
+
+        /* now select register */
+        if ( EI2CNOACKNLD == i2c_outbyte( theReg ) )
+        {
+            error |= 2;
+        }
+
+        /* send register register data */
+        if ( EI2CNOACKNLD == i2c_outbyte( theValue ) )
+        {
+            error |= 4;
+        }
+
+        /* end byte stream */
+        i2c_stop();
+        /* enable interrupt again */
+        local_irq_restore( flags );
+
+    } while ( error && cntr-- );
+
+    i2c_delay( TLOW );
+
+    spin_unlock( &i2c_lock );
+
+    return ( -error );
+}   /* i2c_writereg */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_readreg
+ *#
+ *# DESCRIPTION  : reads the value from a certain register of an I2C device.
+ *#                Function first writes the register that it wants to read
+ *#                later on.
+ *#
+ *# PARAMETERS   : theSlave = slave address of the I2C device
+ *#                theReg   = register of the I2C device that needs to be written
+ *#
+ *# RETURN       : returns OR-ed result of the write action:
+ *#                  0 = Ok
+ *#                  1 = Slave_NoAck
+ *#                  2 = Reg_NoAck
+ *#                  4 = Val_NoAck
+ *#
+ *#---------------------------------------------------------------------------
+ */
+unsigned char i2c_readreg( unsigned char theSlave
+                         , unsigned char theReg
+                         )
+{
+    unsigned char b = 0;
+    int error, cntr = 3;
+    unsigned long flags;
+
+    spin_lock( &i2c_lock );
+
+    do
+    {
+        error = 0;
+
+        /* we don't like to be interrupted */
+        local_irq_save( flags );
+
+        /* generate start condition */
+        i2c_start();
+
+        /* send slave address */
+        if ( EI2CNOACKNLD == i2c_outbyte( theSlave & 0xfe ) )
+        {
+            error = 1;
+        }
+
+        /* now select register */
+        i2c_sda_dir_out();
+
+        if ( EI2CNOACKNLD == i2c_outbyte( theReg ) )
+        {
+            error |= 2;
+        }
+
+        /* repeat start condition */
+        i2c_delay( TLOW );
+        i2c_start();
+
+        /* send slave address */
+        if ( EI2CNOACKNLD == i2c_outbyte( theSlave | 0x01 ) )
+        {
+            error |= 1;
+        }
+
+        /* fetch register */
+        b = i2c_inbyte();
+        /*
+         * last received byte needs to be nacked
+         * instead of acked
+         */
+        i2c_sendnack();
+
+        /* end sequence */
+        i2c_stop();
+
+        /* enable interrupt again */
+        local_irq_restore( flags );
+
+    } while ( error && cntr-- );
+
+    spin_unlock( &i2c_lock );
+
+    return ( b );
+}   /* i2c_readreg */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_read
+ *#
+ *# DESCRIPTION  :
+ *#
+ *# PARAMETERS   :
+ *#
+ *# RETURN       :
+ *#
+ *#---------------------------------------------------------------------------
+ */
+int i2c_read( unsigned char slave, unsigned char* rbuf, unsigned char rlen )
+{
+    return ( i2c_command( slave, NULL, 0, rbuf, rlen ) );
+}   /* i2c_read */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_write
+ *#
+ *# DESCRIPTION  :
+ *#
+ *# PARAMETERS   :
+ *#
+ *# RETURN       :
+ *#
+ *#---------------------------------------------------------------------------
+ */
+int i2c_write( unsigned char slave, unsigned char* wbuf, unsigned char wlen )
+{
+    return ( i2c_command( slave, wbuf, wlen, NULL, 0 ) );
+}   /* i2c_write */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: i2c_writeread
+ *#
+ *# DESCRIPTION  :
+ *#
+ *# PARAMETERS   :
+ *#
+ *# RETURN       :
+ *#
+ *#---------------------------------------------------------------------------
+ */
+int i2c_writeread( unsigned char  slave
+                 , unsigned char* wbuf
+                 , unsigned char  wlen
+                 , unsigned char* rbuf
+                 , unsigned char  rlen
+                 )
+{
+    return ( i2c_command( slave, wbuf, wlen, rbuf, rlen ) );
+}   /* i2c_writeread */
+
+
+/*#---------------------------------------------------------------------------
+ *#
+ *# FUNCTION NAME: module_init
+ *#
+ *# DESCRIPTION  : this makes sure that i2c_register is called during boot
+ *#
+ *# PARAMETERS   :
+ *#
+ *#---------------------------------------------------------------------------
+ */
+module_init( i2c_register );
+
+/****************** END OF FILE i2c.c ********************************/
index dc63165..115fd1c 100644 (file)
@@ -1,6 +1,8 @@
---- a/arch/cris/arch-v10/drivers/Kconfig
-+++ b/arch/cris/arch-v10/drivers/Kconfig
-@@ -450,11 +450,18 @@ config ETRAX_I2C
+Index: linux-2.6.30.8/arch/cris/arch-v10/drivers/Kconfig
+===================================================================
+--- linux-2.6.30.8.orig/arch/cris/arch-v10/drivers/Kconfig     2009-10-02 11:31:49.000000000 +0200
++++ linux-2.6.30.8/arch/cris/arch-v10/drivers/Kconfig  2009-10-06 10:36:23.000000000 +0200
+@@ -450,11 +450,31 @@
          i2c_arg = I2C_READARG(STA013_READ_ADDR, reg);
          val = ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_READREG), i2c_arg);
  
 +      help
 +        Enables an I2C driver with Geert Vancompernolle improvement.
 +
++config ETRAX_I2C_SLAVE_DELAY
++      bool "I2C Slave delay support"
++      depends on ETRAX_I2C_GVC  && EXPERIMENTAL
++      help
++        Enable this to enhanced master/slave dialog
++        Improvement by Positive Going (www.positivegoing.it) and BK srl (www.b-k.it)
++
++config ETRAX_I2C_DYN_ALLOC
++      bool "I2C major device dynamic alloc"
++      depends on ETRAX_I2C_GVC && EXPERIMENTAL
++      help
++        Enable this to dynamicaly alloc major i2c device number
++
  # this is true for most products since PB-I2C seems to be somewhat
  # flawed..
  config ETRAX_I2C_USES_PB_NOT_PB_I2C
@@ -20,7 +35,7 @@
        help
          Select whether to use the special I2C mode in the PB I/O register or
          not.  This option needs to be selected in order to use some drivers
-@@ -478,7 +485,7 @@ config ETRAX_I2C_CLK_PORT
+@@ -478,7 +498,7 @@
  
  config ETRAX_I2C_EEPROM
        bool "I2C EEPROM (non-volatile RAM) support"
        help
          Enables I2C EEPROM (non-volatile RAM) on PB0 and PB1 using the I2C
          driver.  Select size option: Probed, 2k, 8k, 16k.
---- a/arch/cris/arch-v10/drivers/Makefile
-+++ b/arch/cris/arch-v10/drivers/Makefile
+Index: linux-2.6.30.8/arch/cris/arch-v10/drivers/Makefile
+===================================================================
+--- linux-2.6.30.8.orig/arch/cris/arch-v10/drivers/Makefile    2009-10-02 11:31:14.000000000 +0200
++++ linux-2.6.30.8/arch/cris/arch-v10/drivers/Makefile 2009-10-02 11:31:50.000000000 +0200
 @@ -4,6 +4,7 @@
  
  obj-$(CONFIG_ETRAX_AXISFLASHMAP)      += axisflashmap.o