From e0b9f7be6ddcaf99c5d4700c959011cebde19505 Mon Sep 17 00:00:00 2001 From: morris Date: Fri, 10 Apr 2020 16:09:07 +0800 Subject: [PATCH] periph_clk_gating: add reference counter --- components/driver/include/driver/periph_ctrl.h | 8 ++++++++ components/driver/periph_ctrl.c | 15 +++++++++++++-- .../soc/soc/esp32/include/soc/periph_defs.h | 1 + .../soc/soc/esp32s2/include/soc/periph_defs.h | 1 + 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/components/driver/include/driver/periph_ctrl.h b/components/driver/include/driver/periph_ctrl.h index a659e793f..b61477223 100644 --- a/components/driver/include/driver/periph_ctrl.h +++ b/components/driver/include/driver/periph_ctrl.h @@ -28,6 +28,10 @@ extern "C" { * * Clock for the module will be ungated, and reset de-asserted. * + * @note If periph_module_enable is called a number of times, + * periph_module_disable has to be called the same number of times + * in order to put the peripheral into disabled state. + * * @return NULL * */ @@ -40,6 +44,10 @@ void periph_module_enable(periph_module_t periph); * * Clock for the module will be gated, reset asserted. * + * @note If periph_module_enable is called a number of times, + * periph_module_disable has to be called the same number of times + * in order to put the peripheral into disabled state. + * * @return NULL * */ diff --git a/components/driver/periph_ctrl.c b/components/driver/periph_ctrl.c index 9be821e57..0cc747ef0 100644 --- a/components/driver/periph_ctrl.c +++ b/components/driver/periph_ctrl.c @@ -17,22 +17,33 @@ static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED; +static uint8_t ref_counts[PERIPH_MODULE_MAX] = {0}; + void periph_module_enable(periph_module_t periph) { + assert(periph < PERIPH_MODULE_MAX); portENTER_CRITICAL_SAFE(&periph_spinlock); - periph_ll_enable_clk_clear_rst(periph); + if (ref_counts[periph] == 0) { + periph_ll_enable_clk_clear_rst(periph); + } + ref_counts[periph]++; portEXIT_CRITICAL_SAFE(&periph_spinlock); } void periph_module_disable(periph_module_t periph) { + assert(periph < PERIPH_MODULE_MAX); portENTER_CRITICAL_SAFE(&periph_spinlock); - periph_ll_disable_clk_set_rst(periph); + ref_counts[periph]--; + if (ref_counts[periph] == 0) { + periph_ll_disable_clk_set_rst(periph); + } portEXIT_CRITICAL_SAFE(&periph_spinlock); } void periph_module_reset(periph_module_t periph) { + assert(periph < PERIPH_MODULE_MAX); portENTER_CRITICAL_SAFE(&periph_spinlock); periph_ll_reset(periph); portEXIT_CRITICAL_SAFE(&periph_spinlock); diff --git a/components/soc/soc/esp32/include/soc/periph_defs.h b/components/soc/soc/esp32/include/soc/periph_defs.h index c4ad589c9..98dce3962 100644 --- a/components/soc/soc/esp32/include/soc/periph_defs.h +++ b/components/soc/soc/esp32/include/soc/periph_defs.h @@ -55,6 +55,7 @@ typedef enum { PERIPH_AES_MODULE, PERIPH_SHA_MODULE, PERIPH_RSA_MODULE, + PERIPH_MODULE_MAX } periph_module_t; #ifdef __cplusplus diff --git a/components/soc/soc/esp32s2/include/soc/periph_defs.h b/components/soc/soc/esp32s2/include/soc/periph_defs.h index cbd9af557..d890f74f5 100644 --- a/components/soc/soc/esp32s2/include/soc/periph_defs.h +++ b/components/soc/soc/esp32s2/include/soc/periph_defs.h @@ -54,6 +54,7 @@ typedef enum { PERIPH_CRYPTO_DMA_MODULE, //this DMA is shared between AES and SHA PERIPH_AES_DMA_MODULE, PERIPH_SHA_DMA_MODULE, + PERIPH_MODULE_MAX } periph_module_t; typedef enum {