add setup and shutdown for i2c master and slave

Signed-off-by: Shoukui Zhang <zhangshoukui@xiaomi.com>
This commit is contained in:
Shoukui Zhang 2023-11-23 21:06:50 +08:00 committed by Alan Carvalho de Assis
parent 1ea19e7c54
commit 2093038315
4 changed files with 143 additions and 10 deletions

View File

@ -135,13 +135,25 @@ static int i2cdrvr_open(FAR struct file *filep)
return ret; return ret;
} }
/* I2c master initialize */
if (priv->i2c->ops->setup != NULL && priv->crefs == 0)
{
ret = I2C_SETUP(priv->i2c);
if (ret < 0)
{
goto out;
}
}
/* Increment the count of open references on the driver */ /* Increment the count of open references on the driver */
priv->crefs++; priv->crefs++;
DEBUGASSERT(priv->crefs > 0); DEBUGASSERT(priv->crefs > 0);
out:
nxmutex_unlock(&priv->lock); nxmutex_unlock(&priv->lock);
return OK; return ret;
} }
#endif #endif
@ -171,6 +183,17 @@ static int i2cdrvr_close(FAR struct file *filep)
return ret; return ret;
} }
/* I2c master uninitialize */
if (priv->i2c->ops->shutdown != NULL && priv->crefs == 1)
{
ret = I2C_SHUTDOWN(priv->i2c);
if (ret < 0)
{
goto out;
}
}
/* Decrement the count of open references on the driver */ /* Decrement the count of open references on the driver */
DEBUGASSERT(priv->crefs > 0); DEBUGASSERT(priv->crefs > 0);
@ -187,8 +210,9 @@ static int i2cdrvr_close(FAR struct file *filep)
return OK; return OK;
} }
out:
nxmutex_unlock(&priv->lock); nxmutex_unlock(&priv->lock);
return OK; return ret;
} }
#endif #endif

View File

@ -103,6 +103,14 @@ struct i2c_slave_driver_s
int16_t crefs; int16_t crefs;
/* I2C Slave address */
int addr;
/* The number of address bits provided (7 or 10) */
int nbits;
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
bool unlinked; /* Indicates if the driver has been unlinked */ bool unlinked; /* Indicates if the driver has been unlinked */
#endif #endif
@ -150,6 +158,7 @@ static const struct file_operations g_i2cslavefops =
static int i2c_slave_open(FAR struct file *filep) static int i2c_slave_open(FAR struct file *filep)
{ {
FAR struct i2c_slave_driver_s *priv; FAR struct i2c_slave_driver_s *priv;
int ret;
DEBUGASSERT(filep->f_inode->i_private != NULL); DEBUGASSERT(filep->f_inode->i_private != NULL);
@ -161,13 +170,36 @@ static int i2c_slave_open(FAR struct file *filep)
nxmutex_lock(&priv->lock); nxmutex_lock(&priv->lock);
/* I2c slave initialize */
if (priv->dev->ops->setup != NULL && priv->crefs == 0)
{
ret = I2CS_SETUP(priv->dev);
if (ret < 0)
{
goto out;
}
}
/* Set i2c slave address */
ret = I2CS_SETOWNADDRESS(priv->dev, priv->addr, priv->nbits);
if (ret < 0)
{
if (priv->dev->ops->shutdown != NULL)
{
ret = I2CS_SHUTDOWN(priv->dev);
}
}
/* Increment the count of open references on the driver */ /* Increment the count of open references on the driver */
priv->crefs++; priv->crefs++;
DEBUGASSERT(priv->crefs > 0); DEBUGASSERT(priv->crefs > 0);
out:
nxmutex_unlock(&priv->lock); nxmutex_unlock(&priv->lock);
return OK; return ret;
} }
/**************************************************************************** /****************************************************************************
@ -188,6 +220,7 @@ static int i2c_slave_open(FAR struct file *filep)
static int i2c_slave_close(FAR struct file *filep) static int i2c_slave_close(FAR struct file *filep)
{ {
FAR struct i2c_slave_driver_s *priv; FAR struct i2c_slave_driver_s *priv;
int ret = OK;
DEBUGASSERT(filep->f_inode->i_private != NULL); DEBUGASSERT(filep->f_inode->i_private != NULL);
@ -199,6 +232,17 @@ static int i2c_slave_close(FAR struct file *filep)
nxmutex_lock(&priv->lock); nxmutex_lock(&priv->lock);
/* I2c slave uninitialize */
if (priv->dev->ops->shutdown != NULL && priv->crefs == 1)
{
ret = I2CS_SHUTDOWN(priv->dev);
if (ret < 0)
{
goto out;
}
}
/* Decrement the count of open references on the driver */ /* Decrement the count of open references on the driver */
DEBUGASSERT(priv->crefs > 0); DEBUGASSERT(priv->crefs > 0);
@ -213,8 +257,9 @@ static int i2c_slave_close(FAR struct file *filep)
} }
#endif #endif
out:
nxmutex_unlock(&priv->lock); nxmutex_unlock(&priv->lock);
return OK; return ret;
} }
/**************************************************************************** /****************************************************************************
@ -494,12 +539,8 @@ int i2c_slave_register(FAR struct i2c_slave_s *dev, int bus, int addr,
nxsem_init(&priv->wait, 0, 0); nxsem_init(&priv->wait, 0, 0);
nxmutex_init(&priv->lock); nxmutex_init(&priv->lock);
priv->dev = dev; priv->dev = dev;
priv->addr = addr;
ret = I2CS_SETOWNADDRESS(priv->dev, addr, nbits); priv->nbits = nbits;
if (ret < 0)
{
goto out;
}
ret = I2CS_READ(priv->dev, priv->read_buffer, ret = I2CS_READ(priv->dev, priv->read_buffer,
CONFIG_I2C_SLAVE_READBUFSIZE); CONFIG_I2C_SLAVE_READBUFSIZE);

View File

@ -171,6 +171,38 @@
# define I2C_RESET(d) ((d)->ops->reset(d)) # define I2C_RESET(d) ((d)->ops->reset(d))
#endif #endif
/****************************************************************************
* Name: I2C_SETUP
*
* Description:
* I2c master initialize.
*
* Input Parameters:
* dev - Device-specific state data
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#define I2C_SETUP(d) ((d)->ops->setup(d))
/****************************************************************************
* Name: I2C_SHUTDOWN
*
* Description:
* I2c master uninitialize.
*
* Input Parameters:
* dev - Device-specific state data
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#define I2C_SHUTDOWN(d) ((d)->ops->shutdown(d))
/**************************************************************************** /****************************************************************************
* Public Types * Public Types
****************************************************************************/ ****************************************************************************/
@ -186,6 +218,8 @@ struct i2c_ops_s
#ifdef CONFIG_I2C_RESET #ifdef CONFIG_I2C_RESET
CODE int (*reset)(FAR struct i2c_master_s *dev); CODE int (*reset)(FAR struct i2c_master_s *dev);
#endif #endif
CODE int (*setup)(FAR struct i2c_master_s *dev);
CODE int (*shutdown)(FAR struct i2c_master_s *dev);
}; };
/* This structure contains the full state of I2C as needed for a specific /* This structure contains the full state of I2C as needed for a specific

View File

@ -170,6 +170,38 @@
#define I2CS_REGISTERCALLBACK(d,c,a) ((d)->ops->registercallback(d,c,a)) #define I2CS_REGISTERCALLBACK(d,c,a) ((d)->ops->registercallback(d,c,a))
/****************************************************************************
* Name: I2CS_SETUP
*
* Description:
* I2c slave initialize.
*
* Input Parameters:
* dev - Device-specific state data
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#define I2CS_SETUP(d) ((d)->ops->setup(d))
/****************************************************************************
* Name: I2CS_SHUTDOWN
*
* Description:
* I2c slave uninitialize.
*
* Input Parameters:
* dev - Device-specific state data
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#define I2CS_SHUTDOWN(d) ((d)->ops->shutdown(d))
/**************************************************************************** /****************************************************************************
* Public Types * Public Types
****************************************************************************/ ****************************************************************************/
@ -198,6 +230,8 @@ struct i2c_slaveops_s
int (*registercallback)(FAR struct i2c_slave_s *dev, int (*registercallback)(FAR struct i2c_slave_s *dev,
i2c_slave_callback_t *callback, i2c_slave_callback_t *callback,
FAR void *arg); FAR void *arg);
int (*setup)(FAR struct i2c_slave_s *dev);
int (*shutdown)(FAR struct i2c_slave_s *dev);
}; };
/* I2C private data. This structure only defines the initial fields of the /* I2C private data. This structure only defines the initial fields of the