This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit de5ec3be6cab5d18c6055bef6a2c1fcf8d393334
Author: liaoao <[email protected]>
AuthorDate: Fri Feb 7 17:14:52 2025 +0800

    drivers/rpmsg_port_spi/slave: notify remote core when reboot
    
    Now rpmsg_port_spi/slave support send shutdown command to remote
    core to notify then local core will reboot, so remote core can
    notify all the rpmsg services to do the unregister.
    
    Signed-off-by: liaoao <[email protected]>
---
 drivers/rpmsg/rpmsg_port_spi.c       | 54 ++++++++++++++++++++++++++++++++++--
 drivers/rpmsg/rpmsg_port_spi_slave.c | 54 ++++++++++++++++++++++++++++++++++--
 2 files changed, 104 insertions(+), 4 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_port_spi.c b/drivers/rpmsg/rpmsg_port_spi.c
index 8f355e86560..ad74cbcb475 100644
--- a/drivers/rpmsg/rpmsg_port_spi.c
+++ b/drivers/rpmsg/rpmsg_port_spi.c
@@ -35,6 +35,7 @@
 #include <nuttx/power/pm.h>
 #include <nuttx/irq.h>
 #include <nuttx/mutex.h>
+#include <nuttx/reboot_notifier.h>
 #include <nuttx/spinlock.h>
 
 #include "rpmsg_port.h"
@@ -50,6 +51,8 @@
 #  define rpmsg_port_spi_crc16(hdr) 0
 #endif
 
+#define RPMSG_PORT_SPI_CMD_TIMEOUT  1000
+
 #define BYTES2WORDS(s,b)            ((b) / ((s)->nbits >> 3))
 
 /****************************************************************************
@@ -110,6 +113,8 @@ struct rpmsg_port_spi_s
   struct wdog_s                  wdog;
   struct pm_wakelock_s           wakelock;
 #endif
+  volatile bool                  shutdown;
+  struct notifier_block          nb;
 
   /* Used for flow control */
 
@@ -312,13 +317,17 @@ static void rpmsg_port_spi_exchange(FAR struct 
rpmsg_port_spi_s *rpspi)
       return;
     }
 
+  txhdr = rpspi->cmdhdr;
   if (rpspi->state == RPMSG_PORT_SPI_STATE_UNCONNECTED)
     {
-      txhdr = rpspi->cmdhdr;
       txhdr->cmd = RPMSG_PORT_SPI_CMD_CONNECT;
       strlcpy((FAR char *)(txhdr + 1), rpspi->port.rpmsg.cpuname,
               RPMSG_NAME_SIZE);
     }
+  else if (rpspi->shutdown)
+    {
+      txhdr->cmd = RPMSG_PORT_SPI_CMD_SHUTDOWN;
+    }
   else if (rpspi->txavail > 0 &&
            rpmsg_port_queue_nused(&rpspi->port.txq) > 0)
     {
@@ -330,7 +339,6 @@ static void rpmsg_port_spi_exchange(FAR struct 
rpmsg_port_spi_s *rpspi)
     }
   else
     {
-      txhdr = rpspi->cmdhdr;
       txhdr->cmd = RPMSG_PORT_SPI_CMD_AVAIL;
     }
 
@@ -367,6 +375,10 @@ static void rpmsg_port_spi_complete_handler(FAR void *arg)
       rpmsg_port_queue_return_buffer(&rpspi->port.txq, rpspi->txhdr);
       rpspi->txhdr = NULL;
     }
+  else if (rpspi->cmdhdr->cmd == RPMSG_PORT_SPI_CMD_SHUTDOWN)
+    {
+      rpspi->shutdown = false;
+    }
 
   if (rpspi->rxhdr->crc != 0)
     {
@@ -710,6 +722,41 @@ rpmsg_port_spi_init_hardware(FAR struct rpmsg_port_spi_s 
*rpspi,
   return 0;
 }
 
+/****************************************************************************
+ * Name: rpmsg_port_spi_reboot_handler
+ ****************************************************************************/
+
+static int
+rpmsg_port_spi_reboot_handler(FAR struct notifier_block *nb,
+                              unsigned long action, FAR void *data)
+{
+  FAR struct rpmsg_port_spi_s *rpspi =
+    container_of(nb, struct rpmsg_port_spi_s, nb);
+  int timeout = RPMSG_PORT_SPI_CMD_TIMEOUT / 10;
+
+  if ((action == SYS_POWER_OFF || action == SYS_RESTART) &&
+      rpspi->state == RPMSG_PORT_SPI_STATE_CONNECTED)
+    {
+      rpspi->shutdown = true;
+      IOEXP_WRITEPIN(rpspi->ioe, rpspi->mreq, 1);
+
+      /* Wait until shutdown cmd has been sent done. */
+
+      while (timeout >= 0 && rpspi->shutdown)
+        {
+          usleep(10000);
+          timeout--;
+        }
+
+      if (timeout < 0)
+        {
+          rpmsgerr("send cmd shutdown cmd timedout\n");
+        }
+    }
+
+  return 0;
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -792,6 +839,9 @@ rpmsg_port_spi_initialize(FAR const struct 
rpmsg_port_config_s *cfg,
                    PM_IDLE_DOMAIN, PM_NORMAL);
 #endif
 
+  rpspi->nb.notifier_call = rpmsg_port_spi_reboot_handler;
+  register_reboot_notifier(&rpspi->nb);
+
   return 0;
 
 out:
diff --git a/drivers/rpmsg/rpmsg_port_spi_slave.c 
b/drivers/rpmsg/rpmsg_port_spi_slave.c
index 71495b3254b..46c527abce3 100644
--- a/drivers/rpmsg/rpmsg_port_spi_slave.c
+++ b/drivers/rpmsg/rpmsg_port_spi_slave.c
@@ -35,6 +35,7 @@
 #include <nuttx/power/pm.h>
 #include <nuttx/irq.h>
 #include <nuttx/mutex.h>
+#include <nuttx/reboot_notifier.h>
 #include <nuttx/spinlock.h>
 
 #include "rpmsg_port.h"
@@ -50,6 +51,8 @@
 #  define rpmsg_port_spi_crc16(hdr) 0
 #endif
 
+#define RPMSG_PORT_SPI_CMD_TIMEOUT  1000
+
 #define BYTES2WORDS(s,b)            ((b) / ((s)->nbits >> 3))
 
 /****************************************************************************
@@ -111,6 +114,8 @@ struct rpmsg_port_spi_s
   struct wdog_s                  wdog;
   struct pm_wakelock_s           wakelock;
 #endif
+  volatile bool                  shutdown;
+  struct notifier_block          nb;
 
   /* Used for flow control */
 
@@ -274,13 +279,17 @@ static void rpmsg_port_spi_exchange(FAR struct 
rpmsg_port_spi_s *rpspi)
       return;
     }
 
+  txhdr = rpspi->cmdhdr;
   if (rpspi->state == RPMSG_PORT_SPI_STATE_UNCONNECTED)
     {
-      txhdr = rpspi->cmdhdr;
       txhdr->cmd = RPMSG_PORT_SPI_CMD_CONNECT;
       strlcpy((FAR char *)(txhdr + 1), rpspi->port.rpmsg.cpuname,
               RPMSG_NAME_SIZE);
     }
+  else if (rpspi->shutdown)
+    {
+      txhdr->cmd = RPMSG_PORT_SPI_CMD_SHUTDOWN;
+    }
   else if (rpspi->txavail > 0 &&
            rpmsg_port_queue_nused(&rpspi->port.txq) > 0)
     {
@@ -292,7 +301,6 @@ static void rpmsg_port_spi_exchange(FAR struct 
rpmsg_port_spi_s *rpspi)
     }
   else
     {
-      txhdr = rpspi->cmdhdr;
       txhdr->cmd = RPMSG_PORT_SPI_CMD_AVAIL;
     }
 
@@ -428,6 +436,10 @@ static void rpmsg_port_spi_slave_notify(FAR struct 
spi_slave_dev_s *dev,
       rpmsg_port_queue_return_buffer(&rpspi->port.txq, rpspi->txhdr);
       rpspi->txhdr = NULL;
     }
+  else if (rpspi->cmdhdr->cmd == RPMSG_PORT_SPI_CMD_SHUTDOWN)
+    {
+      rpspi->shutdown = false;
+    }
 
   if (rpspi->rxhdr->crc != 0)
     {
@@ -743,6 +755,41 @@ rpmsg_port_spi_init_hardware(FAR struct rpmsg_port_spi_s 
*rpspi,
   return 0;
 }
 
+/****************************************************************************
+ * Name: rpmsg_port_spi_reboot_handler
+ ****************************************************************************/
+
+static int
+rpmsg_port_spi_reboot_handler(FAR struct notifier_block *nb,
+                              unsigned long action, FAR void *data)
+{
+  FAR struct rpmsg_port_spi_s *rpspi =
+    container_of(nb, struct rpmsg_port_spi_s, nb);
+  int timeout = RPMSG_PORT_SPI_CMD_TIMEOUT / 10;
+
+  if ((action == SYS_POWER_OFF || action == SYS_RESTART) &&
+      rpspi->state == RPMSG_PORT_SPI_STATE_CONNECTED)
+    {
+      rpspi->shutdown = true;
+      rpmsg_port_spi_exchange(rpspi);
+
+      /* Wait until shutdown cmd has been sent done. */
+
+      while (timeout >= 0 && rpspi->shutdown)
+        {
+          usleep(10000);
+          timeout--;
+        }
+
+      if (timeout < 0)
+        {
+          rpmsgerr("send cmd shutdown cmd timedout\n");
+        }
+    }
+
+  return 0;
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -818,6 +865,9 @@ rpmsg_port_spi_slave_initialize(FAR const struct 
rpmsg_port_config_s *cfg,
                    PM_IDLE_DOMAIN, PM_NORMAL);
 #endif
 
+  rpspi->nb.notifier_call = rpmsg_port_spi_reboot_handler;
+  register_reboot_notifier(&rpspi->nb);
+
   return 0;
 
 out:

Reply via email to