mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-18 09:34:38 +00:00
feat(spi_slave): add api for pm lock control
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdatomic.h>
|
||||
#include "esp_types.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_check.h"
|
||||
@@ -59,6 +60,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
_Atomic spi_bus_fsm_t fsm;
|
||||
spi_bus_config_t bus_config;
|
||||
spi_dma_ctx_t *dma_ctx;
|
||||
spi_slave_interface_config_t cfg;
|
||||
@@ -177,6 +179,7 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
|
||||
memcpy(&spihost[host]->cfg, slave_config, sizeof(spi_slave_interface_config_t));
|
||||
memcpy(&spihost[host]->bus_config, bus_config, sizeof(spi_bus_config_t));
|
||||
spihost[host]->id = host;
|
||||
atomic_store(&spihost[host]->fsm, SPI_BUS_FSM_ENABLED);
|
||||
spi_slave_hal_context_t *hal = &spihost[host]->hal;
|
||||
|
||||
spihost[host]->dma_enabled = (dma_chan != SPI_DMA_DISABLED);
|
||||
@@ -224,8 +227,7 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_slave",
|
||||
&spihost[host]->pm_lock);
|
||||
err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_slave", &spihost[host]->pm_lock);
|
||||
if (err != ESP_OK) {
|
||||
ret = err;
|
||||
goto cleanup;
|
||||
@@ -351,6 +353,46 @@ esp_err_t spi_slave_free(spi_host_device_t host)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t spi_slave_enable(spi_host_device_t host)
|
||||
{
|
||||
SPI_CHECK(is_valid_host(host), "invalid host", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(spihost[host], "host not slave or not initialized", ESP_ERR_INVALID_ARG);
|
||||
spi_bus_fsm_t curr_sta = SPI_BUS_FSM_DISABLED;
|
||||
SPI_CHECK(atomic_compare_exchange_strong(&spihost[host]->fsm, &curr_sta, SPI_BUS_FSM_ENABLED), "host already enabled", ESP_ERR_INVALID_STATE);
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_acquire(spihost[host]->pm_lock);
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
// If going to TOP_PD power down, the bus_clock is required during reg_dma, and will be disabled by sleep flow then
|
||||
#if !CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
SPI_COMMON_RCC_CLOCK_ATOMIC() {
|
||||
spi_ll_enable_bus_clock(host, true);
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t spi_slave_disable(spi_host_device_t host)
|
||||
{
|
||||
SPI_CHECK(is_valid_host(host), "invalid host", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(spihost[host], "host not slave or not initialized", ESP_ERR_INVALID_ARG);
|
||||
spi_bus_fsm_t curr_sta = SPI_BUS_FSM_ENABLED;
|
||||
SPI_CHECK(atomic_compare_exchange_strong(&spihost[host]->fsm, &curr_sta, SPI_BUS_FSM_DISABLED), "host already disabled", ESP_ERR_INVALID_STATE);
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_release(spihost[host]->pm_lock);
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
// same as above
|
||||
#if !CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
SPI_COMMON_RCC_CLOCK_ATOMIC() {
|
||||
spi_ll_enable_bus_clock(host, false);
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void SPI_SLAVE_ISR_ATTR spi_slave_uninstall_priv_trans(spi_host_device_t host, spi_slave_trans_priv_t *priv_trans)
|
||||
{
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
|
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include "esp_compiler.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
@@ -38,6 +39,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
spi_host_device_t host_id;
|
||||
_Atomic spi_bus_fsm_t fsm;
|
||||
spi_dma_ctx_t *dma_ctx;
|
||||
uint16_t internal_mem_align_size;
|
||||
int max_transfer_sz;
|
||||
@@ -117,6 +119,7 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b
|
||||
host->host_id = host_id;
|
||||
host->int_spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
host->append_mode = append_mode;
|
||||
atomic_store(&host->fsm, SPI_BUS_FSM_ENABLED);
|
||||
|
||||
ret = spicommon_dma_chan_alloc(host_id, config->dma_chan, &host->dma_ctx);
|
||||
if (ret != ESP_OK) {
|
||||
@@ -178,7 +181,7 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b
|
||||
spi_slave_hd_hal_init(&host->hal, &hal_config);
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_slave", &host->pm_lock);
|
||||
ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_slave_hd", &host->pm_lock);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -343,6 +346,46 @@ esp_err_t spi_slave_hd_deinit(spi_host_device_t host_id)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t spi_slave_hd_enable(spi_host_device_t host_id)
|
||||
{
|
||||
SPIHD_CHECK(VALID_HOST(host_id), "invalid host", ESP_ERR_INVALID_ARG);
|
||||
SPIHD_CHECK(spihost[host_id], "host not slave or not initialized", ESP_ERR_INVALID_ARG);
|
||||
spi_bus_fsm_t curr_sta = SPI_BUS_FSM_DISABLED;
|
||||
SPIHD_CHECK(atomic_compare_exchange_strong(&spihost[host_id]->fsm, &curr_sta, SPI_BUS_FSM_ENABLED), "host already enabled", ESP_ERR_INVALID_STATE);
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_acquire(spihost[host_id]->pm_lock);
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
// If going to TOP_PD power down, the bus_clock is required during reg_dma, and will be disabled by sleep flow then
|
||||
#if !CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
SPI_COMMON_RCC_CLOCK_ATOMIC() {
|
||||
spi_ll_enable_bus_clock(host_id, true);
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t spi_slave_hd_disable(spi_host_device_t host_id)
|
||||
{
|
||||
SPIHD_CHECK(VALID_HOST(host_id), "invalid host", ESP_ERR_INVALID_ARG);
|
||||
SPIHD_CHECK(spihost[host_id], "host not slave or not initialized", ESP_ERR_INVALID_ARG);
|
||||
spi_bus_fsm_t curr_sta = SPI_BUS_FSM_ENABLED;
|
||||
SPIHD_CHECK(atomic_compare_exchange_strong(&spihost[host_id]->fsm, &curr_sta, SPI_BUS_FSM_DISABLED), "host already disabled", ESP_ERR_INVALID_STATE);
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_release(spihost[host_id]->pm_lock);
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
// same as above
|
||||
#if !CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
SPI_COMMON_RCC_CLOCK_ATOMIC() {
|
||||
spi_ll_enable_bus_clock(host_id, false);
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void tx_invoke(spi_slave_hd_slot_t *host)
|
||||
{
|
||||
portENTER_CRITICAL(&host->int_spinlock);
|
||||
|
Reference in New Issue
Block a user