@ -14,8 +14,8 @@
# include <asm/io.h>
/*
* i nclude a file that will provide CONFIG_I2C_MVTWSI_BASE *
* and possibly other settings
* I nclude a file that will provide CONFIG_I2C_MVTWSI_BASE * , and possibly other
* settings
*/
# if defined(CONFIG_ORION5X)
@ -51,8 +51,8 @@ struct mvtwsi_registers {
u32 data ;
u32 control ;
union {
u32 status ; /* w hen reading */
u32 baudrate ; /* w hen writing */
u32 status ; /* W hen reading */
u32 baudrate ; /* W hen writing */
} ;
u32 xtnd_slave_addr ;
u32 reserved [ 2 ] ;
@ -81,8 +81,8 @@ enum mvtwsi_ctrl_register_fields {
} ;
/*
* On sun6i and newer IFLG is a write - clear bit which is cleared by writing 1 ,
* on other platforms it is a normal r / w bit which is cleared by writing 0.
* On sun6i and newer , IFLG is a write - clear bit , which is cleared by writing 1 ;
* on other platforms , it is a normal r / w bit , which is cleared by writing 0.
*/
# ifdef CONFIG_SUNXI_GEN_SUN6I
@ -194,8 +194,8 @@ inline uint mvtwsi_error(uint ec, uint lc, uint ls, uint es)
}
/*
* Wait for IFLG to raise , or return ' timeout ' ; then if status is as expected ,
* return 0 ( ok ) or return ' wrong status ' .
* Wait for IFLG to raise , or return ' timeout . ' Then , if the status is as
* expected , return 0 ( ok ) or ' wrong status ' otherwise .
*/
static int twsi_wait ( struct i2c_adapter * adap , int expected_status )
{
@ -214,7 +214,7 @@ static int twsi_wait(struct i2c_adapter *adap, int expected_status)
MVTWSI_ERROR_WRONG_STATUS ,
control , status , expected_status ) ;
}
udelay ( 10 ) ; /* o ne clock cycle at 100 kHz */
udelay ( 10 ) ; /* O ne clock cycle at 100 kHz */
} while ( timeout - - ) ;
status = readl ( & twsi - > status ) ;
return mvtwsi_error ( MVTWSI_ERROR_TIMEOUT , control , status ,
@ -229,12 +229,12 @@ static int twsi_start(struct i2c_adapter *adap, int expected_status, u8 *flags)
{
struct mvtwsi_registers * twsi = twsi_get_base ( adap ) ;
/* globally set TWSIEN in case it was not */
/* Set TWSIEN */
* flags | = MVTWSI_CONTROL_TWSIEN ;
/* a ssert START */
/* A ssert START */
writel ( * flags | MVTWSI_CONTROL_START |
MVTWSI_CONTROL_CLEAR_IFLG , & twsi - > control ) ;
/* w ait for controller to process START */
MVTWSI_CONTROL_CLEAR_IFLG , & twsi - > control ) ;
/* W ait for controller to process START */
return twsi_wait ( adap , expected_status ) ;
}
@ -246,42 +246,40 @@ static int twsi_send(struct i2c_adapter *adap, u8 byte, int expected_status,
{
struct mvtwsi_registers * twsi = twsi_get_base ( adap ) ;
/* put byte in data register for sending */
/* Write byte to data register for sending */
writel ( byte , & twsi - > data ) ;
/* clear any pending interrupt -- that' ll cause sending */
/* Clear any pending interrupt -- that wi ll cause sending */
writel ( * flags | MVTWSI_CONTROL_CLEAR_IFLG , & twsi - > control ) ;
/* wait for controller to receive byte and check ACK */
/* Wait for controller to receive byte, and check ACK */
return twsi_wait ( adap , expected_status ) ;
}
/*
* Receive a byte .
* Global mvtwsi_control_flags variable says if we should ack or nak .
*/
static int twsi_recv ( struct i2c_adapter * adap , u8 * byte , u8 * flags )
{
struct mvtwsi_registers * twsi = twsi_get_base ( adap ) ;
int expected_status , status ;
/* compute expected status based on ACK bit in global control flags */
/* Compute expected status based on ACK bit in passed control flags */
if ( * flags & MVTWSI_CONTROL_ACK )
expected_status = MVTWSI_STATUS_DATA_R_ACK ;
else
expected_status = MVTWSI_STATUS_DATA_R_NAK ;
/* acknowledge *previous state* and launch receive */
/* Acknowledge *previous state*, and launch receive */
writel ( * flags | MVTWSI_CONTROL_CLEAR_IFLG , & twsi - > control ) ;
/* wait for controller to receive byte and assert ACK or NAK */
/* Wait for controller to receive byte, and assert ACK or NAK */
status = twsi_wait ( adap , expected_status ) ;
/* if we did receive expected byte then store it */
/* If we did receive the expected byte, store it */
if ( status = = 0 )
* byte = readl ( & twsi - > data ) ;
/* return status */
return status ;
}
/*
* Assert the STOP condition .
* This is also used to force the bus back in idle ( SDA = SCL = 1 ) .
* This is also used to force the bus back to idle ( SDA = SCL = 1 ) .
*/
static int twsi_stop ( struct i2c_adapter * adap , int status )
{
@ -289,15 +287,15 @@ static int twsi_stop(struct i2c_adapter *adap, int status)
int control , stop_status ;
int timeout = 1000 ;
/* a ssert STOP */
/* A ssert STOP */
control = MVTWSI_CONTROL_TWSIEN | MVTWSI_CONTROL_STOP ;
writel ( control | MVTWSI_CONTROL_CLEAR_IFLG , & twsi - > control ) ;
/* wait for IDLE; IFLG won't rise so twsi_wait() is no use. */
/* Wait for IDLE; IFLG won't rise, so we can't use twsi_wait() */
do {
stop_status = readl ( & twsi - > status ) ;
if ( stop_status = = MVTWSI_STATUS_IDLE )
break ;
udelay ( 10 ) ; /* o ne clock cycle at 100 kHz */
udelay ( 10 ) ; /* O ne clock cycle at 100 kHz */
} while ( timeout - - ) ;
control = readl ( & twsi - > control ) ;
if ( stop_status ! = MVTWSI_STATUS_IDLE )
@ -326,26 +324,26 @@ static void twsi_reset(struct i2c_adapter *adap)
{
struct mvtwsi_registers * twsi = twsi_get_base ( adap ) ;
/* r eset controller */
/* R eset controller */
writel ( 0 , & twsi - > soft_reset ) ;
/* w ait 2 ms -- this is what the Marvell LSP does */
/* W ait 2 ms -- this is what the Marvell LSP does */
udelay ( 20000 ) ;
}
/*
* I2C init called by cmd_i2c when doing ' i2c reset ' .
* Sets baud to the highest possible value not exceeding requested one .
* Sets baud to the highest possible value not exceeding the requested one .
*/
static unsigned int twsi_i2c_set_bus_speed ( struct i2c_adapter * adap ,
unsigned int requested_speed )
{
struct mvtwsi_registers * twsi = twsi_get_base ( adap ) ;
unsigned int tmp_speed , highest_speed , n , m ;
unsigned int baud = 0x44 ; /* baudrate at controller reset */
unsigned int baud = 0x44 ; /* Baud rate after controller reset */
/* use actual speed to collect progressively higher values */
highest_speed = 0 ;
/* compute m, n setting for highest speed not above requested speed */
/* Successively try m, n combinations, and use the combination
* resulting in the largest speed that ' s not above the requested
* speed */
for ( n = 0 ; n < 8 ; n + + ) {
for ( m = 0 ; m < 16 ; m + + ) {
tmp_speed = twsi_calc_freq ( n , m ) ;
@ -364,20 +362,19 @@ static void twsi_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
{
struct mvtwsi_registers * twsi = twsi_get_base ( adap ) ;
/* r eset controller */
/* R eset controller */
twsi_reset ( adap ) ;
/* s et speed */
/* S et speed */
twsi_i2c_set_bus_speed ( adap , speed ) ;
/* set slave address even though we don't use it */
/* Set slave address; even though we don't use it */
writel ( slaveadd , & twsi - > slave_address ) ;
writel ( 0 , & twsi - > xtnd_slave_addr ) ;
/* assert STOP but don't care for the result */
/* Assert STOP, but don't care for the result */
( void ) twsi_stop ( adap , 0 ) ;
}
/*
* Begin I2C transaction with expected start status , at given address .
* Common to i2c_probe , i2c_read and i2c_write .
* Expected address status will derive from direction bit ( bit 0 ) in addr .
*/
static int i2c_begin ( struct i2c_adapter * adap , int expected_start_status ,
@ -385,23 +382,23 @@ static int i2c_begin(struct i2c_adapter *adap, int expected_start_status,
{
int status , expected_addr_status ;
/* compute expected address status from direction bit in addr */
if ( addr & 1 ) /* reading */
/* Compute the expected address status from the direction bit in
* the address byte */
if ( addr & 1 ) /* Reading */
expected_addr_status = MVTWSI_STATUS_ADDR_R_ACK ;
else /* w riting */
else /* W riting */
expected_addr_status = MVTWSI_STATUS_ADDR_W_ACK ;
/* a ssert START */
/* A ssert START */
status = twsi_start ( adap , expected_start_status , flags ) ;
/* s end out the address if the start went well */
/* S end out the address if the start went well */
if ( status = = 0 )
status = twsi_send ( adap , addr , expected_addr_status ,
flags ) ;
/* return ok or status of first failure to caller */
/* Return 0, or the status of the first failure */
return status ;
}
/*
* I2C probe called by cmd_i2c when doing ' i2c probe ' .
* Begin read , nak data byte , end .
*/
static int twsi_i2c_probe ( struct i2c_adapter * adap , uchar chip )
@ -410,26 +407,24 @@ static int twsi_i2c_probe(struct i2c_adapter *adap, uchar chip)
u8 flags = 0 ;
int status ;
/* b egin i2c read */
/* B egin i2c read */
status = i2c_begin ( adap , MVTWSI_STATUS_START , ( chip < < 1 ) | 1 , & flags ) ;
/* dummy read was accepted: receive byte but NAK it. */
/* Dummy read was accepted: receive byte, but NAK it. */
if ( status = = 0 )
status = twsi_recv ( adap , & dummy_byte , & flags ) ;
/* Stop transaction */
twsi_stop ( adap , 0 ) ;
/* return 0 or status of first failure */
/* Return 0, or the status of the first failure */
return status ;
}
/*
* I2C read called by cmd_i2c when doing ' i2c read ' and by cmd_eeprom . c
* Begin write , send address byte ( s ) , begin read , receive data bytes , end .
*
* NOTE : some EEPROMS want a stop right before the second start , while
* some will choke if it is there . Deciding which we should do is eeprom
* stuff , not i2c , but at the moment the APIs won ' t let us put it in
* cmd_eeprom , so we have to choose here , and for the moment that ' ll be
* a repeated start without a preceding stop .
* NOTE : Some devices want a stop right before the second start , while some
* will choke if it is there . Since deciding this is not yet supported in
* higher level APIs , we need to make a decision here , and for the moment that
* will be a repeated start without a preceding stop .
*/
static int twsi_i2c_read ( struct i2c_adapter * adap , uchar chip , uint addr ,
int alen , uchar * data , int length )
@ -437,35 +432,34 @@ static int twsi_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
int status ;
u8 flags = 0 ;
/* b egin i2c write to send the address bytes */
/* B egin i2c write to send the address bytes */
status = i2c_begin ( adap , MVTWSI_STATUS_START , ( chip < < 1 ) , & flags ) ;
/* send addr bytes */
/* Send address bytes */
while ( ( status = = 0 ) & & alen - - )
status = twsi_send ( adap , addr > > ( 8 * alen ) ,
MVTWSI_STATUS_DATA_W_ACK , & flags ) ;
/* begin i2c read to receive eeprom data bytes */
/* Begin i2c read to receive data bytes */
if ( status = = 0 )
status = i2c_begin ( adap , MVTWSI_STATUS_REPEATED_START ,
( chip < < 1 ) | 1 , & flags ) ;
/* p repare ACK if at least one byte must be received */
/* P repare ACK if at least one byte must be received */
if ( length > 0 )
flags | = MVTWSI_CONTROL_ACK ;
/* now receive actual bytes */
/* Receive actual data bytes */
while ( ( status = = 0 ) & & length - - ) {
/* reset NAK if we if no more to read now */
/* Set NAK if we if we have nothing more to read */
if ( length = = 0 )
flags & = ~ MVTWSI_CONTROL_ACK ;
/* r ead current byte */
/* R ead current byte */
status = twsi_recv ( adap , data + + , & flags ) ;
}
/* Stop transaction */
status = twsi_stop ( adap , status ) ;
/* return 0 or status of first failure */
/* Return 0, or the status of the first failure */
return status ;
}
/*
* I2C write called by cmd_i2c when doing ' i2c write ' and by cmd_eeprom . c
* Begin write , send address byte ( s ) , send data bytes , end .
*/
static int twsi_i2c_write ( struct i2c_adapter * adap , uchar chip , uint addr ,
@ -474,19 +468,20 @@ static int twsi_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
int status ;
u8 flags = 0 ;
/* begin i2c write to send the eeprom adress bytes then data bytes */
/* Begin i2c write to send first the address bytes, then the
* data bytes */
status = i2c_begin ( adap , MVTWSI_STATUS_START , ( chip < < 1 ) , & flags ) ;
/* send addr bytes */
/* Send address bytes */
while ( ( status = = 0 ) & & alen - - )
status = twsi_send ( adap , addr > > ( 8 * alen ) ,
MVTWSI_STATUS_DATA_W_ACK , & flags ) ;
/* s end data bytes */
/* S end data bytes */
while ( ( status = = 0 ) & & ( length - - > 0 ) )
status = twsi_send ( adap , * ( data + + ) , MVTWSI_STATUS_DATA_W_ACK ,
& flags ) ;
/* Stop transaction */
status = twsi_stop ( adap , status ) ;
/* return 0 or status of first failure */
/* Return 0, or the status of the first failure */
return status ;
}