mirror of
https://github.com/apache/nuttx.git
synced 2026-05-21 04:52:02 +08:00
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 <liaoao@xiaomi.com>
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user