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

Reply via email to