diff --git a/arch/arm/src/nrf52/Make.defs b/arch/arm/src/nrf52/Make.defs index eeede65a0ba..51d08ea805f 100644 --- a/arch/arm/src/nrf52/Make.defs +++ b/arch/arm/src/nrf52/Make.defs @@ -159,3 +159,7 @@ endif ifeq ($(CONFIG_NRF52_SAADC),y) CHIP_CSRCS += nrf52_adc.c endif + +ifeq ($(CONFIG_PM),y) +CHIP_CSRCS += nrf52_pminitialize.c +endif diff --git a/arch/arm/src/nrf52/nrf52_pminitialize.c b/arch/arm/src/nrf52/nrf52_pminitialize.c new file mode 100644 index 00000000000..edd3c22ffcf --- /dev/null +++ b/arch/arm/src/nrf52/nrf52_pminitialize.c @@ -0,0 +1,55 @@ +/**************************************************************************** + * arch/arm/src/nrf52/nrf52_pminitialize.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_pminitialize + * + * Description: + * This function is called by MCU-specific logic at power-on reset in + * order to provide one-time initialization the power management subsystem. + * This function must be called *very* early in the initialization sequence + * *before* any other device drivers are initialized (since they may + * attempt to register with the power management subsystem). + * + * Input Parameters: + * None. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void arm_pminitialize(void) +{ + /* Then initialize the NuttX power management subsystem proper */ + + pm_initialize(); +} diff --git a/arch/arm/src/nrf52/nrf52_spi.c b/arch/arm/src/nrf52/nrf52_spi.c index 5d59425a41f..57f836b93d2 100644 --- a/arch/arm/src/nrf52/nrf52_spi.c +++ b/arch/arm/src/nrf52/nrf52_spi.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "arm_arch.h" #include "barriers.h" @@ -86,6 +87,7 @@ struct nrf52_spidev_s #ifdef CONFIG_NRF52_SPI_MASTER_INTERRUPTS sem_t sem_isr; /* Interrupt wait semaphore */ #endif + bool initialized; }; /**************************************************************************** @@ -133,12 +135,29 @@ static int nrf52_spi_init(FAR struct nrf52_spidev_s *priv); static void nrf52_spi_pselinit(FAR struct nrf52_spidev_s *priv, uint32_t offset, nrf52_pinset_t pinset); static void nrf52_spi_gpioinit(FAR struct nrf52_spidev_s *priv); + +#ifdef CONFIG_PM +static int nrf52_spi_deinit(FAR struct nrf52_spidev_s *priv); static void nrf52_spi_gpiodeinit(FAR struct nrf52_spidev_s *priv); +static int nrf52_spi_pm_prepare(FAR struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate); +static void nrf52_spi_pm_notify(FAR struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate); +#endif + /**************************************************************************** * Private Data ****************************************************************************/ +#ifdef CONFIG_PM +struct pm_callback_s g_pm_callbacks = +{ + .prepare = nrf52_spi_pm_prepare, + .notify = nrf52_spi_pm_notify +}; +#endif + /* SPI0 */ #ifdef CONFIG_NRF52_SPI0_MASTER @@ -439,7 +458,7 @@ static int nrf52_spi_init(FAR struct nrf52_spidev_s *priv) return OK; } - +#ifdef CONFIG_PM /**************************************************************************** * Name: nrf52_spi_deinit * @@ -471,6 +490,7 @@ static int nrf52_spi_deinit(FAR struct nrf52_spidev_s *priv) return OK; } +#endif /**************************************************************************** * Name: nrf52_spi_pselinit @@ -574,6 +594,7 @@ static void nrf52_spi_gpioinit(FAR struct nrf52_spidev_s *priv) #endif } +#ifdef CONFIG_PM /**************************************************************************** * Name: nrf52_spi_gpioinit * @@ -634,6 +655,7 @@ static void nrf52_spi_gpiodeinit(FAR struct nrf52_spidev_s *priv) } #endif } +#endif /**************************************************************************** * Name: nrf52_spi_lock @@ -1079,7 +1101,7 @@ static void nrf52_spi_exchange(FAR struct spi_dev_s *dev, * in batches */ - if (nwords > 0xFF) + if (nwords > 0xff) { if (rxbuffer != NULL) { @@ -1159,7 +1181,7 @@ static void nrf52_spi_exchange(FAR struct spi_dev_s *dev, /* Clear list mode */ - if (nwords > 0xFF) + if (nwords > 0xff) { nrf52_spi_putreg(priv, NRF52_SPIM_RXDLIST_OFFSET, 0); nrf52_spi_putreg(priv, NRF52_SPIM_TXDLIST_OFFSET, 0); @@ -1251,6 +1273,126 @@ static int nrf52_spi_trigger(FAR struct spi_dev_s *dev) } #endif +#ifdef CONFIG_PM +/**************************************************************************** + * Name: nrf52_spi_pm_prepare + ****************************************************************************/ + +static int nrf52_spi_pm_prepare(FAR struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + if (pmstate == PM_STANDBY || pmstate == PM_SLEEP) + { + bool active = false; + +#ifdef CONFIG_NRF52_SPI0_MASTER + active |= nrf52_spi_getreg(&g_spi0dev, SPIM_EVENTS_STARTED); +#endif +#ifdef CONFIG_NRF52_SPI1_MASTER + active |= nrf52_spi_getreg(&g_spi0dev, SPIM_EVENTS_STARTED); +#endif +#ifdef CONFIG_NRF52_SPI2_MASTER + active |= nrf52_spi_getreg(&g_spi0dev, SPIM_EVENTS_STARTED); +#endif +#ifdef CONFIG_NRF52_SPI3_MASTER + active |= nrf52_spi_getreg(&g_spi0dev, SPIM_EVENTS_STARTED); +#endif + + if (active) + { + /* SPI is being used, cannot disable */ + + return -1; + } + else + { + /* SPI is inactive, can go to sleep */ + + return 0; + } + } + else + { + /* We can always go to any other state */ + + return 0; + } +} + +/**************************************************************************** + * Name: nrf52_spi_pm_notify + ****************************************************************************/ + +static void nrf52_spi_pm_notify(FAR struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + if (pmstate == PM_SLEEP || pmstate == PM_STANDBY) + { + /* Deinit SPI peripheral on each initialized device */ + +#ifdef CONFIG_NRF52_SPI0_MASTER + if (g_spi0dev.initialized) + { + nrf52_spi_deinit(&g_spi0dev); + } +#endif + +#ifdef CONFIG_NRF52_SPI1_MASTER + if (g_spi1dev.initialized) + { + nrf52_spi_deinit(&g_spi1dev); + } +#endif + +#ifdef CONFIG_NRF52_SPI2_MASTER + if (g_spi2dev.initialized) + { + nrf52_spi_deinit(&g_spi2dev); + } +#endif + +#ifdef CONFIG_NRF52_SPI3_MASTER + if (g_spi3dev.initialized) + { + nrf52_spi_deinit(&g_spi3dev); + } +#endif + } + else + { + /* Reinit SPI peripheral on each initialized device */ + +#ifdef CONFIG_NRF52_SPI0_MASTER + if (g_spi0dev.initialized) + { + nrf52_spi_init(&g_spi0dev); + } +#endif + +#ifdef CONFIG_NRF52_SPI1_MASTER + if (g_spi1dev.initialized) + { + nrf52_spi_init(&g_spi1dev); + } +#endif + +#ifdef CONFIG_NRF52_SPI2_MASTER + if (g_spi2dev.initialized) + { + nrf52_spi_init(&g_spi2dev); + } +#endif + +#ifdef CONFIG_NRF52_SPI3_MASTER + if (g_spi3dev.initialized) + { + nrf52_spi_init(&g_spi3dev); + } +#endif + } +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -1319,6 +1461,10 @@ FAR struct spi_dev_s *nrf52_spibus_initialize(int port) nrf52_spi_init(priv); + /* Mark device as initialized */ + + priv->initialized = true; + /* Initialize the SPI semaphore */ nxsem_init(&priv->exclsem, 0, 1); diff --git a/include/nuttx/power/pm.h b/include/nuttx/power/pm.h index 21cfd6156f1..9ab820e6b1f 100644 --- a/include/nuttx/power/pm.h +++ b/include/nuttx/power/pm.h @@ -232,7 +232,7 @@ struct pm_governor_s * * NOTE: since this will be called from pm_initialize(), the system * is in very early boot state when this callback is invoked. Thus, - * only ver basic initialization should be performed (e.g. no memory + * only very basic initialization should be performed (e.g. no memory * should be allocated). * **************************************************************************/