This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 20930383158fd62c9b61b02d53a20d2215d81fa9 Author: Shoukui Zhang <[email protected]> AuthorDate: Thu Nov 23 21:06:50 2023 +0800 add setup and shutdown for i2c master and slave Signed-off-by: Shoukui Zhang <[email protected]> --- drivers/i2c/i2c_driver.c | 28 +++++++++++++++++++-- drivers/i2c/i2c_slave_driver.c | 57 ++++++++++++++++++++++++++++++++++++------ include/nuttx/i2c/i2c_master.h | 34 +++++++++++++++++++++++++ include/nuttx/i2c/i2c_slave.h | 34 +++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/i2c_driver.c b/drivers/i2c/i2c_driver.c index 06e7a99ee5..1a78a64b2d 100644 --- a/drivers/i2c/i2c_driver.c +++ b/drivers/i2c/i2c_driver.c @@ -135,13 +135,25 @@ static int i2cdrvr_open(FAR struct file *filep) 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 */ priv->crefs++; DEBUGASSERT(priv->crefs > 0); +out: nxmutex_unlock(&priv->lock); - return OK; + return ret; } #endif @@ -171,6 +183,17 @@ static int i2cdrvr_close(FAR struct file *filep) 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 */ DEBUGASSERT(priv->crefs > 0); @@ -187,8 +210,9 @@ static int i2cdrvr_close(FAR struct file *filep) return OK; } +out: nxmutex_unlock(&priv->lock); - return OK; + return ret; } #endif diff --git a/drivers/i2c/i2c_slave_driver.c b/drivers/i2c/i2c_slave_driver.c index 44160017dd..6403847077 100644 --- a/drivers/i2c/i2c_slave_driver.c +++ b/drivers/i2c/i2c_slave_driver.c @@ -103,6 +103,14 @@ struct i2c_slave_driver_s int16_t crefs; + /* I2C Slave address */ + + int addr; + + /* The number of address bits provided (7 or 10) */ + + int nbits; + #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS bool unlinked; /* Indicates if the driver has been unlinked */ #endif @@ -150,6 +158,7 @@ static const struct file_operations g_i2cslavefops = static int i2c_slave_open(FAR struct file *filep) { FAR struct i2c_slave_driver_s *priv; + int ret; DEBUGASSERT(filep->f_inode->i_private != NULL); @@ -161,13 +170,36 @@ static int i2c_slave_open(FAR struct file *filep) 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 */ priv->crefs++; DEBUGASSERT(priv->crefs > 0); +out: 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) { FAR struct i2c_slave_driver_s *priv; + int ret = OK; DEBUGASSERT(filep->f_inode->i_private != NULL); @@ -199,6 +232,17 @@ static int i2c_slave_close(FAR struct file *filep) 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 */ DEBUGASSERT(priv->crefs > 0); @@ -213,8 +257,9 @@ static int i2c_slave_close(FAR struct file *filep) } #endif +out: 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); nxmutex_init(&priv->lock); priv->dev = dev; - - ret = I2CS_SETOWNADDRESS(priv->dev, addr, nbits); - if (ret < 0) - { - goto out; - } + priv->addr = addr; + priv->nbits = nbits; ret = I2CS_READ(priv->dev, priv->read_buffer, CONFIG_I2C_SLAVE_READBUFSIZE); diff --git a/include/nuttx/i2c/i2c_master.h b/include/nuttx/i2c/i2c_master.h index 39ba782f8b..da74c9faa2 100644 --- a/include/nuttx/i2c/i2c_master.h +++ b/include/nuttx/i2c/i2c_master.h @@ -171,6 +171,38 @@ # define I2C_RESET(d) ((d)->ops->reset(d)) #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 ****************************************************************************/ @@ -186,6 +218,8 @@ struct i2c_ops_s #ifdef CONFIG_I2C_RESET CODE int (*reset)(FAR struct i2c_master_s *dev); #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 diff --git a/include/nuttx/i2c/i2c_slave.h b/include/nuttx/i2c/i2c_slave.h index ee33157958..dd1c6c39c1 100644 --- a/include/nuttx/i2c/i2c_slave.h +++ b/include/nuttx/i2c/i2c_slave.h @@ -170,6 +170,38 @@ #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 ****************************************************************************/ @@ -198,6 +230,8 @@ struct i2c_slaveops_s int (*registercallback)(FAR struct i2c_slave_s *dev, i2c_slave_callback_t *callback, 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
