@ -62,15 +62,23 @@ struct mvtwsi_registers {
# endif
/*
* Control register fields
* enum mvtwsi_ctrl_register_fields - Bit masks for flags in the control
* register
*/
# define MVTWSI_CONTROL_ACK 0x00000004
# define MVTWSI_CONTROL_IFLG 0x00000008
# define MVTWSI_CONTROL_STOP 0x00000010
# define MVTWSI_CONTROL_START 0x00000020
# define MVTWSI_CONTROL_TWSIEN 0x00000040
# define MVTWSI_CONTROL_INTEN 0x00000080
enum mvtwsi_ctrl_register_fields {
/* Acknowledge bit */
MVTWSI_CONTROL_ACK = 0x00000004 ,
/* Interrupt flag */
MVTWSI_CONTROL_IFLG = 0x00000008 ,
/* Stop bit */
MVTWSI_CONTROL_STOP = 0x00000010 ,
/* Start bit */
MVTWSI_CONTROL_START = 0x00000020 ,
/* I2C enable */
MVTWSI_CONTROL_TWSIEN = 0x00000040 ,
/* Interrupt enable */
MVTWSI_CONTROL_INTEN = 0x00000080 ,
} ;
/*
* On sun6i and newer IFLG is a write - clear bit which is cleared by writing 1 ,
@ -84,22 +92,36 @@ struct mvtwsi_registers {
# endif
/*
* Status register values - - only those expected in normal master
* operation on non - 10 - bit - address devices ; whatever status we don ' t
* expect in nominal conditions ( bus errors , arbitration losses ,
* missing ACKs . . . ) we just pass back to the caller as an error
* enum mvstwsi_status_values - Possible values of I2C controller ' s status
* register
*
* Only those statuses expected in normal master operation on
* non - 10 - bit - address devices are specified .
*
* Every status that ' s unexpected during normal operation ( bus errors ,
* arbitration losses , missing ACKs . . . ) is passed back to the caller as an error
* code .
*/
# define MVTWSI_STATUS_START 0x08
# define MVTWSI_STATUS_REPEATED_START 0x10
# define MVTWSI_STATUS_ADDR_W_ACK 0x18
# define MVTWSI_STATUS_DATA_W_ACK 0x28
# define MVTWSI_STATUS_ADDR_R_ACK 0x40
# define MVTWSI_STATUS_ADDR_R_NAK 0x48
# define MVTWSI_STATUS_DATA_R_ACK 0x50
# define MVTWSI_STATUS_DATA_R_NAK 0x58
# define MVTWSI_STATUS_IDLE 0xF8
enum mvstwsi_status_values {
/* START condition transmitted */
MVTWSI_STATUS_START = 0x08 ,
/* Repeated START condition transmitted */
MVTWSI_STATUS_REPEATED_START = 0x10 ,
/* Address + write bit transmitted, ACK received */
MVTWSI_STATUS_ADDR_W_ACK = 0x18 ,
/* Data transmitted, ACK received */
MVTWSI_STATUS_DATA_W_ACK = 0x28 ,
/* Address + read bit transmitted, ACK received */
MVTWSI_STATUS_ADDR_R_ACK = 0x40 ,
/* Address + read bit transmitted, ACK not received */
MVTWSI_STATUS_ADDR_R_NAK = 0x48 ,
/* Data received, ACK transmitted */
MVTWSI_STATUS_DATA_R_ACK = 0x50 ,
/* Data received, ACK not transmitted */
MVTWSI_STATUS_DATA_R_NAK = 0x58 ,
/* No relevant status */
MVTWSI_STATUS_IDLE = 0xF8 ,
} ;
/*
* MVTWSI controller base
@ -141,20 +163,35 @@ static struct mvtwsi_registers *twsi_get_base(struct i2c_adapter *adap)
}
/*
* Returned statuses are 0 for success and nonzero otherwise .
* Currently , cmd_i2c and cmd_eeprom do not interpret an error status .
* Thus to ease debugging , the return status contains some debug info :
* - bits 31. .24 are error class : 1 is timeout , 2 is ' status mismatch ' .
* - bits 23. .16 are the last value of the control register .
* - bits 15. .8 are the last value of the status register .
* - bits 7. .0 are the expected value of the status register .
* enum mvtwsi_error_class - types of I2C errors
*/
enum mvtwsi_error_class {
/* The controller returned a different status than expected */
MVTWSI_ERROR_WRONG_STATUS = 0x01 ,
/* The controller timed out */
MVTWSI_ERROR_TIMEOUT = 0x02 ,
} ;
# define MVTWSI_ERROR_WRONG_STATUS 0x01
# define MVTWSI_ERROR_TIMEOUT 0x02
# define MVTWSI_ERROR(ec, lc, ls, es) (((ec << 24) & 0xFF000000) | \
( ( lc < < 16 ) & 0x00FF0000 ) | ( ( ls < < 8 ) & 0x0000FF00 ) | ( es & 0xFF ) )
/*
* mvtwsi_error ( ) - Build I2C return code from error information
*
* For debugging purposes , this function packs some information of an occurred
* error into a return code . These error codes are returned from I2C API
* functions ( i2c_ { read , write } , dm_i2c_ { read , write } , etc . ) .
*
* @ ec : The error class of the error ( enum mvtwsi_error_class ) .
* @ lc : The last value of the control register .
* @ ls : The last value of the status register .
* @ es : The expected value of the status register .
* @ return The generated error code .
*/
inline uint mvtwsi_error ( uint ec , uint lc , uint ls , uint es )
{
return ( ( ec < < 24 ) & 0xFF000000 )
| ( ( lc < < 16 ) & 0x00FF0000 )
| ( ( ls < < 8 ) & 0x0000FF00 )
| ( es & 0xFF ) ;
}
/*
* Wait for IFLG to raise , or return ' timeout ' ; then if status is as expected ,
@ -173,15 +210,15 @@ static int twsi_wait(struct i2c_adapter *adap, int expected_status)
if ( status = = expected_status )
return 0 ;
else
return MVTWSI_ERROR (
return mvtwsi_error (
MVTWSI_ERROR_WRONG_STATUS ,
control , status , expected_status ) ;
}
udelay ( 10 ) ; /* one clock cycle at 100 kHz */
} while ( timeout - - ) ;
status = readl ( & twsi - > status ) ;
return MVTWSI_ERROR (
MVTWSI_ERROR_TIMEOUT , control , status , expected_status ) ;
return mvtwsi_error ( MVTWSI_ERROR_TIMEOUT , control , status ,
expected_status ) ;
}
/*
@ -265,7 +302,7 @@ static int twsi_stop(struct i2c_adapter *adap, int status)
control = readl ( & twsi - > control ) ;
if ( stop_status ! = MVTWSI_STATUS_IDLE )
if ( status = = 0 )
status = MVTWSI_ERROR (
status = mvtwsi_error (
MVTWSI_ERROR_TIMEOUT ,
control , status , MVTWSI_STATUS_IDLE ) ;
return status ;