mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 21:36:28 +08:00
arch/srm/src/stm32f7: add PM hooks to ADC, I2C and SPI.
This commit is contained in:
committed by
Gregory Nutt
parent
d8311b6493
commit
8b57b7771f
@@ -62,6 +62,7 @@
|
|||||||
#include <nuttx/irq.h>
|
#include <nuttx/irq.h>
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
#include <nuttx/fs/ioctl.h>
|
#include <nuttx/fs/ioctl.h>
|
||||||
|
#include <nuttx/power/pm.h>
|
||||||
#include <nuttx/analog/adc.h>
|
#include <nuttx/analog/adc.h>
|
||||||
#include <nuttx/analog/ioctl.h>
|
#include <nuttx/analog/ioctl.h>
|
||||||
|
|
||||||
@@ -226,6 +227,11 @@ struct stm32_dev_s
|
|||||||
uint32_t pclck; /* The PCLK frequency that drives this timer */
|
uint32_t pclck; /* The PCLK frequency that drives this timer */
|
||||||
uint32_t freq; /* The desired frequency of conversions */
|
uint32_t freq; /* The desired frequency of conversions */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
struct pm_callback_s pm_callback;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ADC_HAVE_DMA
|
#ifdef ADC_HAVE_DMA
|
||||||
DMA_HANDLE dma; /* Allocated DMA channel */
|
DMA_HANDLE dma; /* Allocated DMA channel */
|
||||||
|
|
||||||
@@ -297,6 +303,11 @@ static void adc_dmaconvcallback(DMA_HANDLE handle, uint8_t isr,
|
|||||||
|
|
||||||
static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable);
|
static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int adc_pm_prepare(struct pm_callback_s *cb, int domain,
|
||||||
|
enum pm_state_e state);
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -333,6 +344,12 @@ static struct stm32_dev_s g_adcpriv1 =
|
|||||||
.dmachan = ADC1_DMA_CHAN,
|
.dmachan = ADC1_DMA_CHAN,
|
||||||
.hasdma = true,
|
.hasdma = true,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.pm_callback =
|
||||||
|
{
|
||||||
|
.prepare = adc_pm_prepare,
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct adc_dev_s g_adcdev1 =
|
static struct adc_dev_s g_adcdev1 =
|
||||||
@@ -362,6 +379,12 @@ static struct stm32_dev_s g_adcpriv2 =
|
|||||||
.dmachan = ADC2_DMA_CHAN,
|
.dmachan = ADC2_DMA_CHAN,
|
||||||
.hasdma = true,
|
.hasdma = true,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.pm_callback =
|
||||||
|
{
|
||||||
|
.prepare = adc_pm_prepare,
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct adc_dev_s g_adcdev2 =
|
static struct adc_dev_s g_adcdev2 =
|
||||||
@@ -391,6 +414,12 @@ static struct stm32_dev_s g_adcpriv3 =
|
|||||||
.dmachan = ADC3_DMA_CHAN,
|
.dmachan = ADC3_DMA_CHAN,
|
||||||
.hasdma = true,
|
.hasdma = true,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.pm_callback =
|
||||||
|
{
|
||||||
|
.prepare = adc_pm_prepare,
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct adc_dev_s g_adcdev3 =
|
static struct adc_dev_s g_adcdev3 =
|
||||||
@@ -982,6 +1011,33 @@ static int adc_timinit(FAR struct stm32_dev_s *priv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: adc_pm_prepare
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Called by power management framework when it wants to enter low power
|
||||||
|
* states. Check if ADC is in progress and if so prevent from entering STOP.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int adc_pm_prepare(struct pm_callback_s *cb, int domain,
|
||||||
|
enum pm_state_e state)
|
||||||
|
{
|
||||||
|
struct stm32_dev_s *priv =
|
||||||
|
(struct stm32_dev_s *)((char *)cb -
|
||||||
|
offsetof(struct stm32_dev_s, pm_callback));
|
||||||
|
uint32_t regval;
|
||||||
|
|
||||||
|
regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
|
||||||
|
if ((state >= PM_IDLE) && (regval & ADC_CR2_SWSTART))
|
||||||
|
{
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: adc_startconv
|
* Name: adc_startconv
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -232,6 +232,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
@@ -241,6 +242,7 @@
|
|||||||
#include <nuttx/semaphore.h>
|
#include <nuttx/semaphore.h>
|
||||||
#include <nuttx/kmalloc.h>
|
#include <nuttx/kmalloc.h>
|
||||||
#include <nuttx/clock.h>
|
#include <nuttx/clock.h>
|
||||||
|
#include <nuttx/power/pm.h>
|
||||||
#include <nuttx/i2c/i2c_master.h>
|
#include <nuttx/i2c/i2c_master.h>
|
||||||
|
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
@@ -446,6 +448,10 @@ struct stm32_i2c_priv_s
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t status; /* End of transfer SR2|SR1 status */
|
uint32_t status; /* End of transfer SR2|SR1 status */
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
struct pm_callback_s pm_cb; /* PM callbacks */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* I2C Device, Instance */
|
/* I2C Device, Instance */
|
||||||
@@ -504,6 +510,10 @@ static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
|
|||||||
#ifdef CONFIG_I2C_RESET
|
#ifdef CONFIG_I2C_RESET
|
||||||
static int stm32_i2c_reset(FAR struct i2c_master_s * dev);
|
static int stm32_i2c_reset(FAR struct i2c_master_s * dev);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int stm32_i2c_pm_prepare(FAR struct pm_callback_s *cb, int domain,
|
||||||
|
enum pm_state_e pmstate);
|
||||||
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
@@ -512,116 +522,128 @@ static int stm32_i2c_reset(FAR struct i2c_master_s * dev);
|
|||||||
#ifdef CONFIG_STM32F7_I2C1
|
#ifdef CONFIG_STM32F7_I2C1
|
||||||
static const struct stm32_i2c_config_s stm32_i2c1_config =
|
static const struct stm32_i2c_config_s stm32_i2c1_config =
|
||||||
{
|
{
|
||||||
.base = STM32_I2C1_BASE,
|
.base = STM32_I2C1_BASE,
|
||||||
.clk_bit = RCC_APB1ENR_I2C1EN,
|
.clk_bit = RCC_APB1ENR_I2C1EN,
|
||||||
.reset_bit = RCC_APB1RSTR_I2C1RST,
|
.reset_bit = RCC_APB1RSTR_I2C1RST,
|
||||||
.scl_pin = GPIO_I2C1_SCL,
|
.scl_pin = GPIO_I2C1_SCL,
|
||||||
.sda_pin = GPIO_I2C1_SDA,
|
.sda_pin = GPIO_I2C1_SDA,
|
||||||
#ifndef CONFIG_I2C_POLLED
|
#ifndef CONFIG_I2C_POLLED
|
||||||
.ev_irq = STM32_IRQ_I2C1EV,
|
.ev_irq = STM32_IRQ_I2C1EV,
|
||||||
.er_irq = STM32_IRQ_I2C1ER
|
.er_irq = STM32_IRQ_I2C1ER
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct stm32_i2c_priv_s stm32_i2c1_priv =
|
static struct stm32_i2c_priv_s stm32_i2c1_priv =
|
||||||
{
|
{
|
||||||
.config = &stm32_i2c1_config,
|
.config = &stm32_i2c1_config,
|
||||||
.refs = 0,
|
.refs = 0,
|
||||||
.intstate = INTSTATE_IDLE,
|
.intstate = INTSTATE_IDLE,
|
||||||
.msgc = 0,
|
.msgc = 0,
|
||||||
.msgv = NULL,
|
.msgv = NULL,
|
||||||
.ptr = NULL,
|
.ptr = NULL,
|
||||||
.frequency = 0,
|
.frequency = 0,
|
||||||
.dcnt = 0,
|
.dcnt = 0,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.status = 0
|
.status = 0,
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.pm_cb.prepare = stm32_i2c_pm_prepare,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_STM32F7_I2C2
|
#ifdef CONFIG_STM32F7_I2C2
|
||||||
static const struct stm32_i2c_config_s stm32_i2c2_config =
|
static const struct stm32_i2c_config_s stm32_i2c2_config =
|
||||||
{
|
{
|
||||||
.base = STM32_I2C2_BASE,
|
.base = STM32_I2C2_BASE,
|
||||||
.clk_bit = RCC_APB1ENR_I2C2EN,
|
.clk_bit = RCC_APB1ENR_I2C2EN,
|
||||||
.reset_bit = RCC_APB1RSTR_I2C2RST,
|
.reset_bit = RCC_APB1RSTR_I2C2RST,
|
||||||
.scl_pin = GPIO_I2C2_SCL,
|
.scl_pin = GPIO_I2C2_SCL,
|
||||||
.sda_pin = GPIO_I2C2_SDA,
|
.sda_pin = GPIO_I2C2_SDA,
|
||||||
#ifndef CONFIG_I2C_POLLED
|
#ifndef CONFIG_I2C_POLLED
|
||||||
.ev_irq = STM32_IRQ_I2C2EV,
|
.ev_irq = STM32_IRQ_I2C2EV,
|
||||||
.er_irq = STM32_IRQ_I2C2ER
|
.er_irq = STM32_IRQ_I2C2ER
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct stm32_i2c_priv_s stm32_i2c2_priv =
|
static struct stm32_i2c_priv_s stm32_i2c2_priv =
|
||||||
{
|
{
|
||||||
.config = &stm32_i2c2_config,
|
.config = &stm32_i2c2_config,
|
||||||
.refs = 0,
|
.refs = 0,
|
||||||
.intstate = INTSTATE_IDLE,
|
.intstate = INTSTATE_IDLE,
|
||||||
.msgc = 0,
|
.msgc = 0,
|
||||||
.msgv = NULL,
|
.msgv = NULL,
|
||||||
.ptr = NULL,
|
.ptr = NULL,
|
||||||
.frequency = 0,
|
.frequency = 0,
|
||||||
.dcnt = 0,
|
.dcnt = 0,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.status = 0
|
.status = 0,
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.pm_cb.prepare = stm32_i2c_pm_prepare,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_STM32F7_I2C3
|
#ifdef CONFIG_STM32F7_I2C3
|
||||||
static const struct stm32_i2c_config_s stm32_i2c3_config =
|
static const struct stm32_i2c_config_s stm32_i2c3_config =
|
||||||
{
|
{
|
||||||
.base = STM32_I2C3_BASE,
|
.base = STM32_I2C3_BASE,
|
||||||
.clk_bit = RCC_APB1ENR_I2C3EN,
|
.clk_bit = RCC_APB1ENR_I2C3EN,
|
||||||
.reset_bit = RCC_APB1RSTR_I2C3RST,
|
.reset_bit = RCC_APB1RSTR_I2C3RST,
|
||||||
.scl_pin = GPIO_I2C3_SCL,
|
.scl_pin = GPIO_I2C3_SCL,
|
||||||
.sda_pin = GPIO_I2C3_SDA,
|
.sda_pin = GPIO_I2C3_SDA,
|
||||||
#ifndef CONFIG_I2C_POLLED
|
#ifndef CONFIG_I2C_POLLED
|
||||||
.ev_irq = STM32_IRQ_I2C3EV,
|
.ev_irq = STM32_IRQ_I2C3EV,
|
||||||
.er_irq = STM32_IRQ_I2C3ER
|
.er_irq = STM32_IRQ_I2C3ER
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct stm32_i2c_priv_s stm32_i2c3_priv =
|
static struct stm32_i2c_priv_s stm32_i2c3_priv =
|
||||||
{
|
{
|
||||||
.config = &stm32_i2c3_config,
|
.config = &stm32_i2c3_config,
|
||||||
.refs = 0,
|
.refs = 0,
|
||||||
.intstate = INTSTATE_IDLE,
|
.intstate = INTSTATE_IDLE,
|
||||||
.msgc = 0,
|
.msgc = 0,
|
||||||
.msgv = NULL,
|
.msgv = NULL,
|
||||||
.ptr = NULL,
|
.ptr = NULL,
|
||||||
.frequency = 0,
|
.frequency = 0,
|
||||||
.dcnt = 0,
|
.dcnt = 0,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.status = 0
|
.status = 0,
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.pm_cb.prepare = stm32_i2c_pm_prepare,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_STM32F7_I2C4
|
#ifdef CONFIG_STM32F7_I2C4
|
||||||
static const struct stm32_i2c_config_s stm32_i2c4_config =
|
static const struct stm32_i2c_config_s stm32_i2c4_config =
|
||||||
{
|
{
|
||||||
.base = STM32_I2C4_BASE,
|
.base = STM32_I2C4_BASE,
|
||||||
.clk_bit = RCC_APB1ENR_I2C4EN,
|
.clk_bit = RCC_APB1ENR_I2C4EN,
|
||||||
.reset_bit = RCC_APB1RSTR_I2C4RST,
|
.reset_bit = RCC_APB1RSTR_I2C4RST,
|
||||||
.scl_pin = GPIO_I2C4_SCL,
|
.scl_pin = GPIO_I2C4_SCL,
|
||||||
.sda_pin = GPIO_I2C4_SDA,
|
.sda_pin = GPIO_I2C4_SDA,
|
||||||
#ifndef CONFIG_I2C_POLLED
|
#ifndef CONFIG_I2C_POLLED
|
||||||
.ev_irq = STM32_IRQ_I2C4EV,
|
.ev_irq = STM32_IRQ_I2C4EV,
|
||||||
.er_irq = STM32_IRQ_I2C4ER
|
.er_irq = STM32_IRQ_I2C4ER
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct stm32_i2c_priv_s stm32_i2c4_priv =
|
static struct stm32_i2c_priv_s stm32_i2c4_priv =
|
||||||
{
|
{
|
||||||
.config = &stm32_i2c4_config,
|
.config = &stm32_i2c4_config,
|
||||||
.refs = 0,
|
.refs = 0,
|
||||||
.intstate = INTSTATE_IDLE,
|
.intstate = INTSTATE_IDLE,
|
||||||
.msgc = 0,
|
.msgc = 0,
|
||||||
.msgv = NULL,
|
.msgv = NULL,
|
||||||
.ptr = NULL,
|
.ptr = NULL,
|
||||||
.frequency = 0,
|
.frequency = 0,
|
||||||
.dcnt = 0,
|
.dcnt = 0,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.status = 0
|
.status = 0,
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.pm_cb.prepare = stm32_i2c_pm_prepare,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -629,9 +651,9 @@ static struct stm32_i2c_priv_s stm32_i2c4_priv =
|
|||||||
|
|
||||||
static const struct i2c_ops_s stm32_i2c_ops =
|
static const struct i2c_ops_s stm32_i2c_ops =
|
||||||
{
|
{
|
||||||
.transfer = stm32_i2c_transfer
|
.transfer = stm32_i2c_transfer,
|
||||||
#ifdef CONFIG_I2C_RESET
|
#ifdef CONFIG_I2C_RESET
|
||||||
, .reset = stm32_i2c_reset
|
.reset = stm32_i2c_reset,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2640,12 +2662,82 @@ out:
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_I2C_RESET */
|
#endif /* CONFIG_I2C_RESET */
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: stm32_i2c_pm_prepare
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Request the driver to prepare for a new power state. This is a
|
||||||
|
* warning that the system is about to enter into a new power state. The
|
||||||
|
* driver should begin whatever operations that may be required to enter
|
||||||
|
* power state. The driver may abort the state change mode by returning
|
||||||
|
* a non-zero value from the callback function.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* cb - Returned to the driver. The driver version of the callback
|
||||||
|
* structure may include additional, driver-specific state
|
||||||
|
* data at the end of the structure.
|
||||||
|
* domain - Identifies the activity domain of the state change
|
||||||
|
* pmstate - Identifies the new PM state
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* 0 (OK) means the event was successfully processed and that the driver
|
||||||
|
* is prepared for the PM state change. Non-zero means that the driver
|
||||||
|
* is not prepared to perform the tasks needed achieve this power setting
|
||||||
|
* and will cause the state change to be aborted. NOTE: The prepare
|
||||||
|
* method will also be recalled when reverting from lower back to higher
|
||||||
|
* power consumption modes (say because another driver refused a lower
|
||||||
|
* power state change). Drivers are not permitted to return non-zero
|
||||||
|
* values when reverting back to higher power consumption modes!
|
||||||
|
*
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int stm32_i2c_pm_prepare(FAR struct pm_callback_s *cb, int domain,
|
||||||
|
enum pm_state_e pmstate)
|
||||||
|
{
|
||||||
|
struct stm32_i2c_priv_s *priv =
|
||||||
|
(struct stm32_i2c_priv_s *)((char *)cb -
|
||||||
|
offsetof(struct stm32_i2c_priv_s, pm_cb));
|
||||||
|
int sval;
|
||||||
|
|
||||||
|
/* Logic to prepare for a reduced power state goes here. */
|
||||||
|
|
||||||
|
switch (pmstate)
|
||||||
|
{
|
||||||
|
case PM_NORMAL:
|
||||||
|
case PM_IDLE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PM_STANDBY:
|
||||||
|
case PM_SLEEP:
|
||||||
|
/* Check if exclusive lock for I2C bus is held. */
|
||||||
|
|
||||||
|
if (nxsem_getvalue(&priv->sem_excl, &sval) < 0)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(false);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sval <= 0)
|
||||||
|
{
|
||||||
|
/* Exclusive lock is held, do not allow entry to deeper PM states. */
|
||||||
|
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: up_i2cinitialize
|
* Name: stm32_i2cbus_initialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Initialize one I2C bus
|
* Initialize one I2C bus
|
||||||
@@ -2656,7 +2748,10 @@ FAR struct i2c_master_s *stm32_i2cbus_initialize(int port)
|
|||||||
{
|
{
|
||||||
struct stm32_i2c_priv_s * priv = NULL; /* private data of device with multiple instances */
|
struct stm32_i2c_priv_s * priv = NULL; /* private data of device with multiple instances */
|
||||||
struct stm32_i2c_inst_s * inst = NULL; /* device, single instance */
|
struct stm32_i2c_inst_s * inst = NULL; /* device, single instance */
|
||||||
int irqs;
|
irqstate_t irqs;
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
int ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if STM32_HSI_FREQUENCY != 16000000 || defined(INVALID_CLOCK_SOURCE)
|
#if STM32_HSI_FREQUENCY != 16000000 || defined(INVALID_CLOCK_SOURCE)
|
||||||
# warning STM32_I2C_INIT: Peripheral clock is HSI and it must be 16mHz or the speed/timing calculations need to be redone.
|
# warning STM32_I2C_INIT: Peripheral clock is HSI and it must be 16mHz or the speed/timing calculations need to be redone.
|
||||||
@@ -2713,6 +2808,14 @@ FAR struct i2c_master_s *stm32_i2cbus_initialize(int port)
|
|||||||
{
|
{
|
||||||
stm32_i2c_sem_init((struct i2c_master_s *)inst);
|
stm32_i2c_sem_init((struct i2c_master_s *)inst);
|
||||||
stm32_i2c_init(priv);
|
stm32_i2c_init(priv);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
/* Register to receive power management callbacks */
|
||||||
|
|
||||||
|
ret = pm_register(&priv->pm_cb);
|
||||||
|
DEBUGASSERT(ret == OK);
|
||||||
|
UNUSED(ret);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_critical_section(irqs);
|
leave_critical_section(irqs);
|
||||||
@@ -2720,7 +2823,7 @@ FAR struct i2c_master_s *stm32_i2cbus_initialize(int port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: up_i2cuninitialize
|
* Name: stm32_i2cbus_uninitialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Uninitialize an I2C bus
|
* Uninitialize an I2C bus
|
||||||
@@ -2729,7 +2832,7 @@ FAR struct i2c_master_s *stm32_i2cbus_initialize(int port)
|
|||||||
|
|
||||||
int stm32_i2cbus_uninitialize(FAR struct i2c_master_s * dev)
|
int stm32_i2cbus_uninitialize(FAR struct i2c_master_s * dev)
|
||||||
{
|
{
|
||||||
int irqs;
|
irqstate_t irqs;
|
||||||
|
|
||||||
ASSERT(dev);
|
ASSERT(dev);
|
||||||
|
|
||||||
@@ -2751,6 +2854,12 @@ int stm32_i2cbus_uninitialize(FAR struct i2c_master_s * dev)
|
|||||||
|
|
||||||
leave_critical_section(irqs);
|
leave_critical_section(irqs);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
/* Unregister power management callbacks */
|
||||||
|
|
||||||
|
pm_unregister(&priv->pm_cb);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Disable power and other HW resource (GPIO's) */
|
/* Disable power and other HW resource (GPIO's) */
|
||||||
|
|
||||||
stm32_i2c_deinit(((struct stm32_i2c_inst_s *)dev)->priv);
|
stm32_i2c_deinit(((struct stm32_i2c_inst_s *)dev)->priv);
|
||||||
@@ -2763,4 +2872,5 @@ int stm32_i2cbus_uninitialize(FAR struct i2c_master_s * dev)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_STM32F7_I2C1 || CONFIG_STM32F7_I2C2 || CONFIG_STM32F7_I2C3 */
|
#endif /* CONFIG_STM32F7_I2C1 || CONFIG_STM32F7_I2C2 || \
|
||||||
|
CONFIG_STM32F7_I2C3 || CONFIG_STM32F7_I2C4 */
|
||||||
|
|||||||
@@ -66,6 +66,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
@@ -74,6 +75,7 @@
|
|||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
#include <nuttx/semaphore.h>
|
#include <nuttx/semaphore.h>
|
||||||
#include <nuttx/spi/spi.h>
|
#include <nuttx/spi/spi.h>
|
||||||
|
#include <nuttx/power/pm.h>
|
||||||
|
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
|
|
||||||
@@ -165,6 +167,9 @@ struct stm32_spidev_s
|
|||||||
uint32_t actual; /* Actual clock frequency */
|
uint32_t actual; /* Actual clock frequency */
|
||||||
int8_t nbits; /* Width of word in bits */
|
int8_t nbits; /* Width of word in bits */
|
||||||
uint8_t mode; /* Mode 0,1,2,3 */
|
uint8_t mode; /* Mode 0,1,2,3 */
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
struct pm_callback_s pm_cb; /* PM callbacks */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
@@ -221,6 +226,13 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer,
|
|||||||
|
|
||||||
static void spi_bus_initialize(FAR struct stm32_spidev_s *priv);
|
static void spi_bus_initialize(FAR struct stm32_spidev_s *priv);
|
||||||
|
|
||||||
|
/* PM interface */
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int spi_pm_prepare(FAR struct pm_callback_s *cb, int domain,
|
||||||
|
enum pm_state_e pmstate);
|
||||||
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
@@ -266,6 +278,9 @@ static struct stm32_spidev_s g_spi1dev =
|
|||||||
.rxch = DMAMAP_SPI1_RX,
|
.rxch = DMAMAP_SPI1_RX,
|
||||||
.txch = DMAMAP_SPI1_TX,
|
.txch = DMAMAP_SPI1_TX,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.pm_cb.prepare = spi_pm_prepare,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -310,6 +325,9 @@ static struct stm32_spidev_s g_spi2dev =
|
|||||||
.rxch = DMAMAP_SPI2_RX,
|
.rxch = DMAMAP_SPI2_RX,
|
||||||
.txch = DMAMAP_SPI2_TX,
|
.txch = DMAMAP_SPI2_TX,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.pm_cb.prepare = spi_pm_prepare,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -354,6 +372,9 @@ static struct stm32_spidev_s g_spi3dev =
|
|||||||
.rxch = DMAMAP_SPI3_RX,
|
.rxch = DMAMAP_SPI3_RX,
|
||||||
.txch = DMAMAP_SPI3_TX,
|
.txch = DMAMAP_SPI3_TX,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.pm_cb.prepare = spi_pm_prepare,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -398,6 +419,9 @@ static struct stm32_spidev_s g_spi4dev =
|
|||||||
.rxch = DMAMAP_SPI4_RX,
|
.rxch = DMAMAP_SPI4_RX,
|
||||||
.txch = DMAMAP_SPI4_TX,
|
.txch = DMAMAP_SPI4_TX,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.pm_cb.prepare = spi_pm_prepare,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -442,6 +466,9 @@ static struct stm32_spidev_s g_spi5dev =
|
|||||||
.rxch = DMAMAP_SPI5_RX,
|
.rxch = DMAMAP_SPI5_RX,
|
||||||
.txch = DMAMAP_SPI5_TX,
|
.txch = DMAMAP_SPI5_TX,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.pm_cb.prepare = spi_pm_prepare,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -486,6 +513,9 @@ static struct stm32_spidev_s g_spi6dev =
|
|||||||
.rxch = DMAMAP_SPI6_RX,
|
.rxch = DMAMAP_SPI6_RX,
|
||||||
.txch = DMAMAP_SPI6_TX,
|
.txch = DMAMAP_SPI6_TX,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.pm_cb.prepare = spi_pm_prepare,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1693,6 +1723,76 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer, size_t
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: spi_pm_prepare
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Request the driver to prepare for a new power state. This is a
|
||||||
|
* warning that the system is about to enter into a new power state. The
|
||||||
|
* driver should begin whatever operations that may be required to enter
|
||||||
|
* power state. The driver may abort the state change mode by returning
|
||||||
|
* a non-zero value from the callback function.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* cb - Returned to the driver. The driver version of the callback
|
||||||
|
* structure may include additional, driver-specific state
|
||||||
|
* data at the end of the structure.
|
||||||
|
* domain - Identifies the activity domain of the state change
|
||||||
|
* pmstate - Identifies the new PM state
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* 0 (OK) means the event was successfully processed and that the driver
|
||||||
|
* is prepared for the PM state change. Non-zero means that the driver
|
||||||
|
* is not prepared to perform the tasks needed achieve this power setting
|
||||||
|
* and will cause the state change to be aborted. NOTE: The prepare
|
||||||
|
* method will also be recalled when reverting from lower back to higher
|
||||||
|
* power consumption modes (say because another driver refused a lower
|
||||||
|
* power state change). Drivers are not permitted to return non-zero
|
||||||
|
* values when reverting back to higher power consumption modes!
|
||||||
|
*
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int spi_pm_prepare(FAR struct pm_callback_s *cb, int domain,
|
||||||
|
enum pm_state_e pmstate)
|
||||||
|
{
|
||||||
|
struct stm32_spidev_s *priv =
|
||||||
|
(struct stm32_spidev_s *)((char *)cb -
|
||||||
|
offsetof(struct stm32_spidev_s, pm_cb));
|
||||||
|
int sval;
|
||||||
|
|
||||||
|
/* Logic to prepare for a reduced power state goes here. */
|
||||||
|
|
||||||
|
switch (pmstate)
|
||||||
|
{
|
||||||
|
case PM_NORMAL:
|
||||||
|
case PM_IDLE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PM_STANDBY:
|
||||||
|
case PM_SLEEP:
|
||||||
|
/* Check if exclusive lock for SPI bus is held. */
|
||||||
|
|
||||||
|
if (nxsem_getvalue(&priv->exclsem, &sval) < 0)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(false);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sval <= 0)
|
||||||
|
{
|
||||||
|
/* Exclusive lock is held, do not allow entry to deeper PM states. */
|
||||||
|
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: spi_bus_initialize
|
* Name: spi_bus_initialize
|
||||||
*
|
*
|
||||||
@@ -1707,10 +1807,13 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer, size_t
|
|||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static void spi_bus_initialize(FAR struct stm32_spidev_s *priv)
|
static void spi_bus_initialize(struct stm32_spidev_s *priv)
|
||||||
{
|
{
|
||||||
uint16_t setbits;
|
uint16_t setbits;
|
||||||
uint16_t clrbits;
|
uint16_t clrbits;
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
int ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Configure CR1 and CR2. Default configuration:
|
/* Configure CR1 and CR2. Default configuration:
|
||||||
* Mode 0: CR1.CPHA=0 and CR1.CPOL=0
|
* Mode 0: CR1.CPHA=0 and CR1.CPOL=0
|
||||||
@@ -1776,6 +1879,14 @@ static void spi_bus_initialize(FAR struct stm32_spidev_s *priv)
|
|||||||
/* Enable spi */
|
/* Enable spi */
|
||||||
|
|
||||||
spi_modifycr1(priv, SPI_CR1_SPE, 0);
|
spi_modifycr1(priv, SPI_CR1_SPE, 0);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
/* Register to receive power management callbacks */
|
||||||
|
|
||||||
|
ret = pm_register(&priv->pm_cb);
|
||||||
|
DEBUGASSERT(ret == OK);
|
||||||
|
UNUSED(ret);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
|
|||||||
Reference in New Issue
Block a user