@ -6,13 +6,12 @@
* SPDX - License - Identifier : GPL - 2.0 +
*/
# include <common.h>
# include <dm.h>
# include <linux/types.h>
# include <linux/errno.h>
# include <linux/io.h>
# include <linux/iopoll.h>
# include <linux/sizes.h>
# include <linux/errno.h>
# include <linux/types.h>
# include <dm.h>
# include <i2c.h>
# include <fdtdec.h>
@ -64,35 +63,27 @@ struct uniphier_fi2c_regs {
# define FIOCLK 50000000
struct uniphier_fi2c_dev {
struct uniphier_fi2c_priv {
struct udevice * dev ;
struct uniphier_fi2c_regs __iomem * regs ; /* register base */
unsigned long fioclk ; /* internal operation clock */
unsigned long timeout ; /* time out (us) */
} ;
static int reset_bus ( struct uniphier_fi2c_regs __iomem * regs )
static void uniphier_fi2c_reset ( struct uniphier_fi2c_priv * priv )
{
u32 val ;
int ret ;
/* bus forcible reset */
writel ( I2C_RST_RST , & regs - > rst ) ;
ret = readl_poll_timeout ( & regs - > rst , val , ! ( val & I2C_RST_RST ) , 1 ) ;
if ( ret < 0 )
debug ( " error: fail to reset I2C controller \n " ) ;
return ret ;
writel ( I2C_RST_RST , & priv - > regs - > rst ) ;
}
static int check_device_busy ( struct uniphier_fi2c_regs __iomem * regs )
static int uniphier_fi2c_check_bus_busy ( struct uniphier_fi2c_priv * priv )
{
u32 val ;
int ret ;
ret = readl_poll_timeout ( & regs - > sr , val , ! ( val & I2C_SR_DB ) , 100 ) ;
ret = readl_poll_timeout ( & priv - > regs - > sr , val , ! ( val & I2C_SR_DB ) , 100 ) ;
if ( ret < 0 ) {
debu g ( " error: device busy too long. reset... \n " ) ;
ret = reset_bus ( regs ) ;
dev_d bg ( priv - > dev , " error: device busy too long. reset... \n " ) ;
uniphier_fi2c_reset ( priv ) ;
}
return ret ;
@ -101,8 +92,7 @@ static int check_device_busy(struct uniphier_fi2c_regs __iomem *regs)
static int uniphier_fi2c_probe ( struct udevice * dev )
{
fdt_addr_t addr ;
struct uniphier_fi2c_dev * priv = dev_get_priv ( dev ) ;
int ret ;
struct uniphier_fi2c_priv * priv = dev_get_priv ( dev ) ;
addr = devfdt_get_addr ( dev ) ;
if ( addr = = FDT_ADDR_T_NONE )
@ -114,85 +104,85 @@ static int uniphier_fi2c_probe(struct udevice *dev)
priv - > fioclk = FIOCLK ;
priv - > dev = dev ;
/* bus forcible reset */
ret = reset_bus ( priv - > regs ) ;
if ( ret < 0 )
return ret ;
uniphier_fi2c_reset ( priv ) ;
writel ( I2C_BRST_FOEN | I2C_BRST_RSCLO , & priv - > regs - > brst ) ;
return 0 ;
}
static int wait_for_irq ( struct uniphier_fi2c_dev * de v , u32 flags ,
static int wait_for_irq ( struct uniphier_fi2c_priv * pri v , u32 flags ,
bool * stop )
{
u32 irq ;
int ret ;
ret = readl_poll_timeout ( & de v- > regs - > intr , irq , irq & flags ,
de v- > timeout ) ;
ret = readl_poll_timeout ( & pri v- > regs - > intr , irq , irq & flags ,
pri v- > timeout ) ;
if ( ret < 0 ) {
debu g ( " error: time out \n " ) ;
dev_d bg ( priv - > dev , " error: time out \n " ) ;
return ret ;
}
if ( irq & I2C_INT_AL ) {
debu g ( " error: arbitration lost \n " ) ;
dev_d bg ( priv - > dev , " error: arbitration lost \n " ) ;
* stop = false ;
return ret ;
}
if ( irq & I2C_INT_NA ) {
debu g ( " error: no answer \n " ) ;
dev_d bg ( priv - > dev , " error: no answer \n " ) ;
return ret ;
}
return 0 ;
}
static int issue_stop ( struct uniphier_fi2c_dev * de v , int old_ret )
static int issue_stop ( struct uniphier_fi2c_priv * pri v , int old_ret )
{
int ret ;
debu g ( " stop condition \n " ) ;
writel ( I2C_CR_MST | I2C_CR_STO , & de v- > regs - > cr ) ;
dev_d bg ( priv - > dev , " stop condition \n " ) ;
writel ( I2C_CR_MST | I2C_CR_STO , & pri v- > regs - > cr ) ;
ret = check_device_busy ( dev - > regs ) ;
ret = uniphier_fi2c_check_bus_busy ( priv ) ;
if ( ret < 0 )
debu g ( " error: device busy after operation \n " ) ;
dev_d bg ( priv - > dev , " error: device busy after operation \n " ) ;
return old_ret ? old_ret : ret ;
}
static int uniphier_fi2c_transmit ( struct uniphier_fi2c_dev * de v , uint addr ,
static int uniphier_fi2c_transmit ( struct uniphier_fi2c_priv * pri v , uint addr ,
uint len , const u8 * buf , bool * stop )
{
int ret ;
const u32 irq_flags = I2C_INT_TE | I2C_INT_NA | I2C_INT_AL ;
struct uniphier_fi2c_regs __iomem * regs = de v- > regs ;
struct uniphier_fi2c_regs __iomem * regs = pri v- > regs ;
debu g ( " %s: addr = %x, len = %d \n " , __func__ , addr , len ) ;
dev_d bg ( priv - > dev , " %s: addr = %x, len = %d \n " , __func__ , addr , len ) ;
writel ( I2C_DTTX_CMD | addr < < 1 , & regs - > dttx ) ;
writel ( irq_flags , & regs - > ie ) ;
writel ( irq_flags , & regs - > ic ) ;
debu g ( " start condition \n " ) ;
dev_d bg ( priv - > dev , " start condition \n " ) ;
writel ( I2C_CR_MST | I2C_CR_STA , & regs - > cr ) ;
ret = wait_for_irq ( de v, irq_flags , stop ) ;
ret = wait_for_irq ( pri v, irq_flags , stop ) ;
if ( ret < 0 )
goto error ;
while ( len - - ) {
debu g ( " sending %x \n " , * buf ) ;
dev_d bg ( priv - > dev , " sending %x \n " , * buf ) ;
writel ( * buf + + , & regs - > dttx ) ;
writel ( irq_flags , & regs - > ic ) ;
ret = wait_for_irq ( de v, irq_flags , stop ) ;
ret = wait_for_irq ( pri v, irq_flags , stop ) ;
if ( ret < 0 )
goto error ;
}
@ -201,26 +191,26 @@ error:
writel ( irq_flags , & regs - > ic ) ;
if ( * stop )
ret = issue_stop ( de v, ret ) ;
ret = issue_stop ( pri v, ret ) ;
return ret ;
}
static int uniphier_fi2c_receive ( struct uniphier_fi2c_dev * de v , uint addr ,
static int uniphier_fi2c_receive ( struct uniphier_fi2c_priv * pri v , uint addr ,
uint len , u8 * buf , bool * stop )
{
int ret = 0 ;
const u32 irq_flags = I2C_INT_RB | I2C_INT_NA | I2C_INT_AL ;
struct uniphier_fi2c_regs __iomem * regs = de v- > regs ;
struct uniphier_fi2c_regs __iomem * regs = pri v- > regs ;
debu g ( " %s: addr = %x, len = %d \n " , __func__ , addr , len ) ;
dev_d bg ( priv - > dev , " %s: addr = %x, len = %d \n " , __func__ , addr , len ) ;
/*
* In case ' len = = 0 ' , only the slave address should be sent
* for probing , which is covered by the transmit function .
*/
if ( len = = 0 )
return uniphier_fi2c_transmit ( de v, addr , len , buf , stop ) ;
return uniphier_fi2c_transmit ( pri v, addr , len , buf , stop ) ;
writel ( I2C_DTTX_CMD | I2C_DTTX_RD | addr < < 1 , & regs - > dttx ) ;
@ -228,17 +218,17 @@ static int uniphier_fi2c_receive(struct uniphier_fi2c_dev *dev, uint addr,
writel ( irq_flags , & regs - > ie ) ;
writel ( irq_flags , & regs - > ic ) ;
debu g ( " start condition \n " ) ;
dev_d bg ( priv - > dev , " start condition \n " ) ;
writel ( I2C_CR_MST | I2C_CR_STA | ( len = = 1 ? I2C_CR_NACK : 0 ) ,
& regs - > cr ) ;
while ( len - - ) {
ret = wait_for_irq ( de v, irq_flags , stop ) ;
ret = wait_for_irq ( pri v, irq_flags , stop ) ;
if ( ret < 0 )
goto error ;
* buf + + = readl ( & regs - > dtrx ) ;
debu g ( " received %x \n " , * ( buf - 1 ) ) ;
dev_d bg ( priv - > dev , " received %x \n " , * ( buf - 1 ) ) ;
if ( len = = 1 )
writel ( I2C_CR_MST | I2C_CR_NACK , & regs - > cr ) ;
@ -250,7 +240,7 @@ error:
writel ( irq_flags , & regs - > ic ) ;
if ( * stop )
ret = issue_stop ( de v, ret ) ;
ret = issue_stop ( pri v, ret ) ;
return ret ;
}
@ -259,10 +249,10 @@ static int uniphier_fi2c_xfer(struct udevice *bus, struct i2c_msg *msg,
int nmsgs )
{
int ret ;
struct uniphier_fi2c_dev * de v = dev_get_priv ( bus ) ;
struct uniphier_fi2c_priv * pri v = dev_get_priv ( bus ) ;
bool stop ;
ret = check_device_busy ( dev - > regs ) ;
ret = uniphier_fi2c_check_bus_busy ( priv ) ;
if ( ret < 0 )
return ret ;
@ -271,10 +261,10 @@ static int uniphier_fi2c_xfer(struct udevice *bus, struct i2c_msg *msg,
stop = nmsgs > 1 & & msg [ 1 ] . flags & I2C_M_RD ? false : true ;
if ( msg - > flags & I2C_M_RD )
ret = uniphier_fi2c_receive ( de v, msg - > addr , msg - > len ,
ret = uniphier_fi2c_receive ( pri v, msg - > addr , msg - > len ,
msg - > buf , & stop ) ;
else
ret = uniphier_fi2c_transmit ( de v, msg - > addr , msg - > len ,
ret = uniphier_fi2c_transmit ( pri v, msg - > addr , msg - > len ,
msg - > buf , & stop ) ;
if ( ret < 0 )
@ -288,21 +278,21 @@ static int uniphier_fi2c_set_bus_speed(struct udevice *bus, unsigned int speed)
{
int ret ;
unsigned int clk_count ;
struct uniphier_fi2c_dev * de v = dev_get_priv ( bus ) ;
struct uniphier_fi2c_regs __iomem * regs = de v- > regs ;
struct uniphier_fi2c_priv * pri v = dev_get_priv ( bus ) ;
struct uniphier_fi2c_regs __iomem * regs = pri v- > regs ;
/* max supported frequency is 400 kHz */
if ( speed > 400000 )
return - EINVAL ;
ret = check_device_busy ( dev - > regs ) ;
ret = uniphier_fi2c_check_bus_busy ( priv ) ;
if ( ret < 0 )
return ret ;
/* make sure the bus is idle when changing the frequency */
writel ( I2C_BRST_RSCLO , & regs - > brst ) ;
clk_count = de v- > fioclk / speed ;
clk_count = pri v- > fioclk / speed ;
writel ( clk_count , & regs - > cyc ) ;
writel ( clk_count / 2 , & regs - > lctl ) ;
@ -316,7 +306,7 @@ static int uniphier_fi2c_set_bus_speed(struct udevice *bus, unsigned int speed)
* 1000000 * 9 / speed usec .
* This time out value is long enough .
*/
de v- > timeout = 100000000L / speed ;
pri v- > timeout = 100000000L / speed ;
return 0 ;
}
@ -336,6 +326,6 @@ U_BOOT_DRIVER(uniphier_fi2c) = {
. id = UCLASS_I2C ,
. of_match = uniphier_fi2c_of_match ,
. probe = uniphier_fi2c_probe ,
. priv_auto_alloc_size = sizeof ( struct uniphier_fi2c_de v ) ,
. priv_auto_alloc_size = sizeof ( struct uniphier_fi2c_pri v ) ,
. ops = & uniphier_fi2c_ops ,
} ;