@ -9,6 +9,7 @@
# include <common.h>
# include <linux/types.h>
# include <linux/io.h>
# include <linux/iopoll.h>
# include <linux/sizes.h>
# include <linux/errno.h>
# include <dm/device.h>
@ -69,26 +70,14 @@ struct uniphier_fi2c_dev {
unsigned long timeout ; /* time out (us) */
} ;
static int poll_status ( u32 __iomem * reg , u32 flag )
{
int wait = 1000000 ; /* 1 sec is long enough */
while ( readl ( reg ) & flag ) {
if ( wait - - < 0 )
return - EREMOTEIO ;
udelay ( 1 ) ;
}
return 0 ;
}
static int reset_bus ( struct uniphier_fi2c_regs __iomem * regs )
{
u32 val ;
int ret ;
/* bus forcible reset */
writel ( I2C_RST_RST , & regs - > rst ) ;
ret = poll_status ( & regs - > rst , I2C_RST_RST ) ;
ret = readl_poll_timeout ( & regs - > rst , val , ! ( val & I2C_RST_RST ) , 1 ) ;
if ( ret < 0 )
debug ( " error: fail to reset I2C controller \n " ) ;
@ -97,9 +86,10 @@ static int reset_bus(struct uniphier_fi2c_regs __iomem *regs)
static int check_device_busy ( struct uniphier_fi2c_regs __iomem * regs )
{
u32 val ;
int ret ;
ret = poll_status ( & regs - > sr , I2C_SR_DB ) ;
ret = readl_poll_timeout ( & regs - > sr , val , ! ( val & I2C_SR_DB ) , 100 ) ;
if ( ret < 0 ) {
debug ( " error: device busy too long. reset... \n " ) ;
ret = reset_bus ( regs ) ;
@ -138,15 +128,11 @@ static int wait_for_irq(struct uniphier_fi2c_dev *dev, u32 flags,
bool * stop )
{
u32 irq ;
unsigned long wait = dev - > timeout ;
int ret = - EREMOTEIO ;
do {
udelay ( 1 ) ;
irq = readl ( & dev - > regs - > intr ) ;
} while ( ! ( irq & flags ) & & wait - - ) ;
int ret ;
if ( wait < 0 ) {
ret = readl_poll_timeout ( & dev - > regs - > intr , irq , irq & flags ,
dev - > timeout ) ;
if ( ret < 0 ) {
debug ( " error: time out \n " ) ;
return ret ;
}
@ -172,7 +158,7 @@ static int issue_stop(struct uniphier_fi2c_dev *dev, int old_ret)
debug ( " stop condition \n " ) ;
writel ( I2C_CR_MST | I2C_CR_STO , & dev - > regs - > cr ) ;
ret = poll_status ( & dev - > regs - > sr , I2C_SR_DB ) ;
ret = check_device_busy ( dev - > regs ) ;
if ( ret < 0 )
debug ( " error: device busy after operation \n " ) ;