2018-08-01 23:32:31 +05:30
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Actions Semiconductor Owl SoC ' s I2C driver
*
* Copyright ( c ) 2014 Actions Semi Inc .
* Author : David Liu < liuwei @ actions - semi . com >
*
* Copyright ( c ) 2018 Linaro Ltd .
* Author : Manivannan Sadhasivam < manivannan . sadhasivam @ linaro . org >
*/
# include <linux/clk.h>
# include <linux/delay.h>
# include <linux/i2c.h>
# include <linux/interrupt.h>
# include <linux/io.h>
2020-10-09 00:44:40 +03:00
# include <linux/iopoll.h>
2018-08-01 23:32:31 +05:30
# include <linux/module.h>
# include <linux/of_device.h>
/* I2C registers */
# define OWL_I2C_REG_CTL 0x0000
# define OWL_I2C_REG_CLKDIV 0x0004
# define OWL_I2C_REG_STAT 0x0008
# define OWL_I2C_REG_ADDR 0x000C
# define OWL_I2C_REG_TXDAT 0x0010
# define OWL_I2C_REG_RXDAT 0x0014
# define OWL_I2C_REG_CMD 0x0018
# define OWL_I2C_REG_FIFOCTL 0x001C
# define OWL_I2C_REG_FIFOSTAT 0x0020
# define OWL_I2C_REG_DATCNT 0x0024
# define OWL_I2C_REG_RCNT 0x0028
/* I2Cx_CTL Bit Mask */
# define OWL_I2C_CTL_RB BIT(1)
# define OWL_I2C_CTL_GBCC(x) (((x) & 0x3) << 2)
# define OWL_I2C_CTL_GBCC_NONE OWL_I2C_CTL_GBCC(0)
# define OWL_I2C_CTL_GBCC_START OWL_I2C_CTL_GBCC(1)
# define OWL_I2C_CTL_GBCC_STOP OWL_I2C_CTL_GBCC(2)
# define OWL_I2C_CTL_GBCC_RSTART OWL_I2C_CTL_GBCC(3)
# define OWL_I2C_CTL_IRQE BIT(5)
# define OWL_I2C_CTL_EN BIT(7)
# define OWL_I2C_CTL_AE BIT(8)
# define OWL_I2C_CTL_SHSM BIT(10)
# define OWL_I2C_DIV_FACTOR(x) ((x) & 0xff)
/* I2Cx_STAT Bit Mask */
# define OWL_I2C_STAT_RACK BIT(0)
# define OWL_I2C_STAT_BEB BIT(1)
# define OWL_I2C_STAT_IRQP BIT(2)
# define OWL_I2C_STAT_LAB BIT(3)
# define OWL_I2C_STAT_STPD BIT(4)
# define OWL_I2C_STAT_STAD BIT(5)
# define OWL_I2C_STAT_BBB BIT(6)
# define OWL_I2C_STAT_TCB BIT(7)
# define OWL_I2C_STAT_LBST BIT(8)
# define OWL_I2C_STAT_SAMB BIT(9)
# define OWL_I2C_STAT_SRGC BIT(10)
/* I2Cx_CMD Bit Mask */
# define OWL_I2C_CMD_SBE BIT(0)
# define OWL_I2C_CMD_RBE BIT(4)
# define OWL_I2C_CMD_DE BIT(8)
# define OWL_I2C_CMD_NS BIT(9)
# define OWL_I2C_CMD_SE BIT(10)
# define OWL_I2C_CMD_MSS BIT(11)
# define OWL_I2C_CMD_WRS BIT(12)
# define OWL_I2C_CMD_SECL BIT(15)
# define OWL_I2C_CMD_AS(x) (((x) & 0x7) << 1)
# define OWL_I2C_CMD_SAS(x) (((x) & 0x7) << 5)
/* I2Cx_FIFOCTL Bit Mask */
# define OWL_I2C_FIFOCTL_NIB BIT(0)
# define OWL_I2C_FIFOCTL_RFR BIT(1)
# define OWL_I2C_FIFOCTL_TFR BIT(2)
/* I2Cc_FIFOSTAT Bit Mask */
2020-10-09 00:44:40 +03:00
# define OWL_I2C_FIFOSTAT_CECB BIT(0)
2018-08-01 23:32:31 +05:30
# define OWL_I2C_FIFOSTAT_RNB BIT(1)
# define OWL_I2C_FIFOSTAT_RFE BIT(2)
# define OWL_I2C_FIFOSTAT_TFF BIT(5)
# define OWL_I2C_FIFOSTAT_TFD GENMASK(23, 16)
# define OWL_I2C_FIFOSTAT_RFD GENMASK(15, 8)
/* I2C bus timeout */
2020-10-09 00:44:40 +03:00
# define OWL_I2C_TIMEOUT_MS (4 * 1000)
# define OWL_I2C_TIMEOUT msecs_to_jiffies(OWL_I2C_TIMEOUT_MS)
2018-08-01 23:32:31 +05:30
# define OWL_I2C_MAX_RETRIES 50
struct owl_i2c_dev {
struct i2c_adapter adap ;
struct i2c_msg * msg ;
struct completion msg_complete ;
struct clk * clk ;
spinlock_t lock ;
void __iomem * base ;
unsigned long clk_rate ;
u32 bus_freq ;
u32 msg_ptr ;
int err ;
} ;
static void owl_i2c_update_reg ( void __iomem * reg , unsigned int val , bool state )
{
unsigned int regval ;
regval = readl ( reg ) ;
if ( state )
regval | = val ;
else
regval & = ~ val ;
writel ( regval , reg ) ;
}
static void owl_i2c_reset ( struct owl_i2c_dev * i2c_dev )
{
owl_i2c_update_reg ( i2c_dev - > base + OWL_I2C_REG_CTL ,
OWL_I2C_CTL_EN , false ) ;
mdelay ( 1 ) ;
owl_i2c_update_reg ( i2c_dev - > base + OWL_I2C_REG_CTL ,
OWL_I2C_CTL_EN , true ) ;
/* Clear status registers */
writel ( 0 , i2c_dev - > base + OWL_I2C_REG_STAT ) ;
}
static int owl_i2c_reset_fifo ( struct owl_i2c_dev * i2c_dev )
{
unsigned int val , timeout = 0 ;
/* Reset FIFO */
owl_i2c_update_reg ( i2c_dev - > base + OWL_I2C_REG_FIFOCTL ,
OWL_I2C_FIFOCTL_RFR | OWL_I2C_FIFOCTL_TFR ,
true ) ;
/* Wait 50ms for FIFO reset complete */
do {
val = readl ( i2c_dev - > base + OWL_I2C_REG_FIFOCTL ) ;
if ( ! ( val & ( OWL_I2C_FIFOCTL_RFR | OWL_I2C_FIFOCTL_TFR ) ) )
break ;
usleep_range ( 500 , 1000 ) ;
} while ( timeout + + < OWL_I2C_MAX_RETRIES ) ;
if ( timeout > OWL_I2C_MAX_RETRIES ) {
dev_err ( & i2c_dev - > adap . dev , " FIFO reset timeout \n " ) ;
return - ETIMEDOUT ;
}
return 0 ;
}
static void owl_i2c_set_freq ( struct owl_i2c_dev * i2c_dev )
{
unsigned int val ;
val = DIV_ROUND_UP ( i2c_dev - > clk_rate , i2c_dev - > bus_freq * 16 ) ;
/* Set clock divider factor */
writel ( OWL_I2C_DIV_FACTOR ( val ) , i2c_dev - > base + OWL_I2C_REG_CLKDIV ) ;
}
2020-10-09 00:44:40 +03:00
static void owl_i2c_xfer_data ( struct owl_i2c_dev * i2c_dev )
2018-08-01 23:32:31 +05:30
{
struct i2c_msg * msg = i2c_dev - > msg ;
unsigned int stat , fifostat ;
i2c_dev - > err = 0 ;
/* Handle NACK from slave */
fifostat = readl ( i2c_dev - > base + OWL_I2C_REG_FIFOSTAT ) ;
if ( fifostat & OWL_I2C_FIFOSTAT_RNB ) {
i2c_dev - > err = - ENXIO ;
2020-10-09 00:44:39 +03:00
/* Clear NACK error bit by writing "1" */
owl_i2c_update_reg ( i2c_dev - > base + OWL_I2C_REG_FIFOSTAT ,
OWL_I2C_FIFOSTAT_RNB , true ) ;
2020-10-09 00:44:40 +03:00
return ;
2018-08-01 23:32:31 +05:30
}
/* Handle bus error */
stat = readl ( i2c_dev - > base + OWL_I2C_REG_STAT ) ;
if ( stat & OWL_I2C_STAT_BEB ) {
i2c_dev - > err = - EIO ;
2020-10-09 00:44:39 +03:00
/* Clear BUS error bit by writing "1" */
owl_i2c_update_reg ( i2c_dev - > base + OWL_I2C_REG_STAT ,
OWL_I2C_STAT_BEB , true ) ;
2020-10-09 00:44:40 +03:00
return ;
2018-08-01 23:32:31 +05:30
}
/* Handle FIFO read */
if ( msg - > flags & I2C_M_RD ) {
while ( ( readl ( i2c_dev - > base + OWL_I2C_REG_FIFOSTAT ) &
OWL_I2C_FIFOSTAT_RFE ) & & i2c_dev - > msg_ptr < msg - > len ) {
msg - > buf [ i2c_dev - > msg_ptr + + ] = readl ( i2c_dev - > base +
OWL_I2C_REG_RXDAT ) ;
}
} else {
/* Handle the remaining bytes which were not sent */
while ( ! ( readl ( i2c_dev - > base + OWL_I2C_REG_FIFOSTAT ) &
OWL_I2C_FIFOSTAT_TFF ) & & i2c_dev - > msg_ptr < msg - > len ) {
writel ( msg - > buf [ i2c_dev - > msg_ptr + + ] ,
i2c_dev - > base + OWL_I2C_REG_TXDAT ) ;
}
}
2020-10-09 00:44:40 +03:00
}
static irqreturn_t owl_i2c_interrupt ( int irq , void * _dev )
{
struct owl_i2c_dev * i2c_dev = _dev ;
spin_lock ( & i2c_dev - > lock ) ;
owl_i2c_xfer_data ( i2c_dev ) ;
2018-08-01 23:32:31 +05:30
/* Clear pending interrupts */
owl_i2c_update_reg ( i2c_dev - > base + OWL_I2C_REG_STAT ,
OWL_I2C_STAT_IRQP , true ) ;
complete_all ( & i2c_dev - > msg_complete ) ;
2020-09-09 16:10:01 +12:00
spin_unlock ( & i2c_dev - > lock ) ;
2018-08-01 23:32:31 +05:30
return IRQ_HANDLED ;
}
static u32 owl_i2c_func ( struct i2c_adapter * adap )
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL ;
}
static int owl_i2c_check_bus_busy ( struct i2c_adapter * adap )
{
struct owl_i2c_dev * i2c_dev = i2c_get_adapdata ( adap ) ;
unsigned long timeout ;
/* Check for Bus busy */
timeout = jiffies + OWL_I2C_TIMEOUT ;
while ( readl ( i2c_dev - > base + OWL_I2C_REG_STAT ) & OWL_I2C_STAT_BBB ) {
if ( time_after ( jiffies , timeout ) ) {
dev_err ( & adap - > dev , " Bus busy timeout \n " ) ;
return - ETIMEDOUT ;
}
}
return 0 ;
}
2020-10-09 00:44:40 +03:00
static int owl_i2c_xfer_common ( struct i2c_adapter * adap , struct i2c_msg * msgs ,
int num , bool atomic )
2018-08-01 23:32:31 +05:30
{
struct owl_i2c_dev * i2c_dev = i2c_get_adapdata ( adap ) ;
struct i2c_msg * msg ;
unsigned long time_left , flags ;
unsigned int i2c_cmd , val ;
unsigned int addr ;
int ret , idx ;
spin_lock_irqsave ( & i2c_dev - > lock , flags ) ;
/* Reset I2C controller */
owl_i2c_reset ( i2c_dev ) ;
/* Set bus frequency */
owl_i2c_set_freq ( i2c_dev ) ;
/*
* Spinlock should be released before calling reset FIFO and
* bus busy check since those functions may sleep
*/
spin_unlock_irqrestore ( & i2c_dev - > lock , flags ) ;
/* Reset FIFO */
ret = owl_i2c_reset_fifo ( i2c_dev ) ;
if ( ret )
goto unlocked_err_exit ;
/* Check for bus busy */
ret = owl_i2c_check_bus_busy ( adap ) ;
if ( ret )
goto unlocked_err_exit ;
spin_lock_irqsave ( & i2c_dev - > lock , flags ) ;
/* Check for Arbitration lost */
val = readl ( i2c_dev - > base + OWL_I2C_REG_STAT ) ;
if ( val & OWL_I2C_STAT_LAB ) {
val & = ~ OWL_I2C_STAT_LAB ;
writel ( val , i2c_dev - > base + OWL_I2C_REG_STAT ) ;
ret = - EAGAIN ;
goto err_exit ;
}
2020-10-09 00:44:40 +03:00
if ( ! atomic )
reinit_completion ( & i2c_dev - > msg_complete ) ;
2018-08-01 23:32:31 +05:30
2020-10-09 00:44:40 +03:00
/* Enable/disable I2C controller interrupt */
2018-08-01 23:32:31 +05:30
owl_i2c_update_reg ( i2c_dev - > base + OWL_I2C_REG_CTL ,
2020-10-09 00:44:40 +03:00
OWL_I2C_CTL_IRQE , ! atomic ) ;
2018-08-01 23:32:31 +05:30
/*
* Select : FIFO enable , Master mode , Stop enable , Data count enable ,
* Send start bit
*/
i2c_cmd = OWL_I2C_CMD_SECL | OWL_I2C_CMD_MSS | OWL_I2C_CMD_SE |
OWL_I2C_CMD_NS | OWL_I2C_CMD_DE | OWL_I2C_CMD_SBE ;
/* Handle repeated start condition */
if ( num > 1 ) {
/* Set internal address length and enable repeated start */
i2c_cmd | = OWL_I2C_CMD_AS ( msgs [ 0 ] . len + 1 ) |
OWL_I2C_CMD_SAS ( 1 ) | OWL_I2C_CMD_RBE ;
/* Write slave address */
addr = i2c_8bit_addr_from_msg ( & msgs [ 0 ] ) ;
writel ( addr , i2c_dev - > base + OWL_I2C_REG_TXDAT ) ;
/* Write internal register address */
for ( idx = 0 ; idx < msgs [ 0 ] . len ; idx + + )
writel ( msgs [ 0 ] . buf [ idx ] ,
i2c_dev - > base + OWL_I2C_REG_TXDAT ) ;
msg = & msgs [ 1 ] ;
} else {
/* Set address length */
i2c_cmd | = OWL_I2C_CMD_AS ( 1 ) ;
msg = & msgs [ 0 ] ;
}
i2c_dev - > msg = msg ;
i2c_dev - > msg_ptr = 0 ;
/* Set data count for the message */
writel ( msg - > len , i2c_dev - > base + OWL_I2C_REG_DATCNT ) ;
addr = i2c_8bit_addr_from_msg ( msg ) ;
writel ( addr , i2c_dev - > base + OWL_I2C_REG_TXDAT ) ;
if ( ! ( msg - > flags & I2C_M_RD ) ) {
/* Write data to FIFO */
for ( idx = 0 ; idx < msg - > len ; idx + + ) {
/* Check for FIFO full */
if ( readl ( i2c_dev - > base + OWL_I2C_REG_FIFOSTAT ) &
OWL_I2C_FIFOSTAT_TFF )
break ;
writel ( msg - > buf [ idx ] ,
i2c_dev - > base + OWL_I2C_REG_TXDAT ) ;
}
i2c_dev - > msg_ptr = idx ;
}
/* Ignore the NACK if needed */
if ( msg - > flags & I2C_M_IGNORE_NAK )
owl_i2c_update_reg ( i2c_dev - > base + OWL_I2C_REG_FIFOCTL ,
OWL_I2C_FIFOCTL_NIB , true ) ;
else
owl_i2c_update_reg ( i2c_dev - > base + OWL_I2C_REG_FIFOCTL ,
OWL_I2C_FIFOCTL_NIB , false ) ;
/* Start the transfer */
writel ( i2c_cmd , i2c_dev - > base + OWL_I2C_REG_CMD ) ;
spin_unlock_irqrestore ( & i2c_dev - > lock , flags ) ;
2020-10-09 00:44:40 +03:00
if ( atomic ) {
/* Wait for Command Execute Completed or NACK Error bits */
ret = readl_poll_timeout_atomic ( i2c_dev - > base + OWL_I2C_REG_FIFOSTAT ,
val , val & ( OWL_I2C_FIFOSTAT_CECB |
OWL_I2C_FIFOSTAT_RNB ) ,
10 , OWL_I2C_TIMEOUT_MS * 1000 ) ;
} else {
time_left = wait_for_completion_timeout ( & i2c_dev - > msg_complete ,
adap - > timeout ) ;
if ( ! time_left )
ret = - ETIMEDOUT ;
}
2018-08-01 23:32:31 +05:30
spin_lock_irqsave ( & i2c_dev - > lock , flags ) ;
2020-10-09 00:44:40 +03:00
if ( ret ) {
2018-08-01 23:32:31 +05:30
dev_err ( & adap - > dev , " Transaction timed out \n " ) ;
/* Send stop condition and release the bus */
owl_i2c_update_reg ( i2c_dev - > base + OWL_I2C_REG_CTL ,
OWL_I2C_CTL_GBCC_STOP | OWL_I2C_CTL_RB ,
true ) ;
goto err_exit ;
}
2020-10-09 00:44:40 +03:00
if ( atomic )
owl_i2c_xfer_data ( i2c_dev ) ;
2018-08-01 23:32:31 +05:30
ret = i2c_dev - > err < 0 ? i2c_dev - > err : num ;
err_exit :
spin_unlock_irqrestore ( & i2c_dev - > lock , flags ) ;
unlocked_err_exit :
/* Disable I2C controller */
owl_i2c_update_reg ( i2c_dev - > base + OWL_I2C_REG_CTL ,
OWL_I2C_CTL_EN , false ) ;
return ret ;
}
2020-10-09 00:44:40 +03:00
static int owl_i2c_xfer ( struct i2c_adapter * adap , struct i2c_msg * msgs ,
int num )
{
return owl_i2c_xfer_common ( adap , msgs , num , false ) ;
}
static int owl_i2c_xfer_atomic ( struct i2c_adapter * adap ,
struct i2c_msg * msgs , int num )
{
return owl_i2c_xfer_common ( adap , msgs , num , true ) ;
}
2018-08-01 23:32:31 +05:30
static const struct i2c_algorithm owl_i2c_algorithm = {
2020-10-09 00:44:40 +03:00
. master_xfer = owl_i2c_xfer ,
. master_xfer_atomic = owl_i2c_xfer_atomic ,
. functionality = owl_i2c_func ,
2018-08-01 23:32:31 +05:30
} ;
static const struct i2c_adapter_quirks owl_i2c_quirks = {
. flags = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST ,
. max_read_len = 240 ,
. max_write_len = 240 ,
. max_comb_1st_msg_len = 6 ,
. max_comb_2nd_msg_len = 240 ,
} ;
static int owl_i2c_probe ( struct platform_device * pdev )
{
struct device * dev = & pdev - > dev ;
struct owl_i2c_dev * i2c_dev ;
int ret , irq ;
i2c_dev = devm_kzalloc ( dev , sizeof ( * i2c_dev ) , GFP_KERNEL ) ;
if ( ! i2c_dev )
return - ENOMEM ;
2020-04-09 21:52:24 +08:00
i2c_dev - > base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2018-08-01 23:32:31 +05:30
if ( IS_ERR ( i2c_dev - > base ) )
return PTR_ERR ( i2c_dev - > base ) ;
irq = platform_get_irq ( pdev , 0 ) ;
2020-04-16 23:23:45 +08:00
if ( irq < 0 )
2018-08-01 23:32:31 +05:30
return irq ;
if ( of_property_read_u32 ( dev - > of_node , " clock-frequency " ,
& i2c_dev - > bus_freq ) )
2020-03-24 14:32:16 +02:00
i2c_dev - > bus_freq = I2C_MAX_STANDARD_MODE_FREQ ;
2018-08-01 23:32:31 +05:30
/* We support only frequencies of 100k and 400k for now */
2020-03-24 14:32:16 +02:00
if ( i2c_dev - > bus_freq ! = I2C_MAX_STANDARD_MODE_FREQ & &
i2c_dev - > bus_freq ! = I2C_MAX_FAST_MODE_FREQ ) {
2018-08-01 23:32:31 +05:30
dev_err ( dev , " invalid clock-frequency %d \n " , i2c_dev - > bus_freq ) ;
return - EINVAL ;
}
i2c_dev - > clk = devm_clk_get ( dev , NULL ) ;
if ( IS_ERR ( i2c_dev - > clk ) ) {
dev_err ( dev , " failed to get clock \n " ) ;
return PTR_ERR ( i2c_dev - > clk ) ;
}
ret = clk_prepare_enable ( i2c_dev - > clk ) ;
if ( ret )
return ret ;
i2c_dev - > clk_rate = clk_get_rate ( i2c_dev - > clk ) ;
if ( ! i2c_dev - > clk_rate ) {
dev_err ( dev , " input clock rate should not be zero \n " ) ;
ret = - EINVAL ;
goto disable_clk ;
}
init_completion ( & i2c_dev - > msg_complete ) ;
spin_lock_init ( & i2c_dev - > lock ) ;
i2c_dev - > adap . owner = THIS_MODULE ;
i2c_dev - > adap . algo = & owl_i2c_algorithm ;
i2c_dev - > adap . timeout = OWL_I2C_TIMEOUT ;
i2c_dev - > adap . quirks = & owl_i2c_quirks ;
i2c_dev - > adap . dev . parent = dev ;
i2c_dev - > adap . dev . of_node = dev - > of_node ;
snprintf ( i2c_dev - > adap . name , sizeof ( i2c_dev - > adap . name ) ,
" %s " , " OWL I2C adapter " ) ;
i2c_set_adapdata ( & i2c_dev - > adap , i2c_dev ) ;
platform_set_drvdata ( pdev , i2c_dev ) ;
ret = devm_request_irq ( dev , irq , owl_i2c_interrupt , 0 , pdev - > name ,
i2c_dev ) ;
if ( ret ) {
dev_err ( dev , " failed to request irq %d \n " , irq ) ;
goto disable_clk ;
}
return i2c_add_adapter ( & i2c_dev - > adap ) ;
disable_clk :
clk_disable_unprepare ( i2c_dev - > clk ) ;
return ret ;
}
static const struct of_device_id owl_i2c_of_match [ ] = {
2020-11-20 01:56:06 +02:00
{ . compatible = " actions,s500-i2c " } ,
2018-12-11 09:04:47 +01:00
{ . compatible = " actions,s700-i2c " } ,
2018-08-01 23:32:31 +05:30
{ . compatible = " actions,s900-i2c " } ,
{ /* sentinel */ }
} ;
MODULE_DEVICE_TABLE ( of , owl_i2c_of_match ) ;
static struct platform_driver owl_i2c_driver = {
. probe = owl_i2c_probe ,
. driver = {
. name = " owl-i2c " ,
. of_match_table = of_match_ptr ( owl_i2c_of_match ) ,
2020-10-09 00:44:41 +03:00
. probe_type = PROBE_PREFER_ASYNCHRONOUS ,
2018-08-01 23:32:31 +05:30
} ,
} ;
module_platform_driver ( owl_i2c_driver ) ;
MODULE_AUTHOR ( " David Liu <liuwei@actions-semi.com> " ) ;
MODULE_AUTHOR ( " Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> " ) ;
MODULE_DESCRIPTION ( " Actions Semiconductor Owl SoC's I2C driver " ) ;
MODULE_LICENSE ( " GPL " ) ;