feat(esp_hw_support): support set clock divider for esp32p4 clock output

This commit is contained in:
wuzhenghui 2024-04-12 16:50:26 +08:00
parent 309725fcd0
commit ffd5d1fd66
No known key found for this signature in database
GPG Key ID: 3EFEDECDEBA39BB9
10 changed files with 76 additions and 14 deletions

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -88,7 +88,6 @@ static clkout_channel_handle_t* clkout_channel_alloc(soc_clkout_sig_id_t clk_sig
allocated_channel->mapped_io_bmap |= BIT(gpio_num);
allocated_channel->mapped_clock = clk_sig;
allocated_channel->ref_cnt++;
if (allocated_channel->ref_cnt == 1) {
portENTER_CRITICAL(&s_clkout_lock);
#if SOC_CLOCKOUT_HAS_SOURCE_GATE
@ -219,6 +218,18 @@ esp_err_t esp_clock_output_stop(esp_clock_output_mapping_handle_t clkout_mapping
return ESP_OK;
}
#if SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER
esp_err_t esp_clock_output_set_divider(esp_clock_output_mapping_handle_t clkout_mapping_hdl, uint32_t div_num)
{
ESP_RETURN_ON_FALSE(((div_num > 0) && (div_num <= 256)), ESP_ERR_INVALID_ARG, TAG, "Divider number must be in the range of [1, 256]");
ESP_RETURN_ON_FALSE((clkout_mapping_hdl != NULL), ESP_ERR_INVALID_ARG, TAG, "Clock out mapping handle passed in is invalid");
portENTER_CRITICAL(&clkout_mapping_hdl->clkout_mapping_lock);
clk_hal_clock_output_set_divider(clkout_mapping_hdl->clkout_channel_hdl->channel_id, div_num);
portEXIT_CRITICAL(&clkout_mapping_hdl->clkout_mapping_lock);
return ESP_OK;
}
#endif
#if CONFIG_IDF_TARGET_ESP32
// Due to a hardware bug, PIN_CTRL cannot select 0xf output, whereas 0xf is the default value.
__attribute__((constructor))

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -25,7 +25,7 @@ typedef struct esp_clock_output_mapping *esp_clock_output_mapping_handle_t;
*
* @param[in] clk_src The clock signal source to be mapped to GPIOs
* @param[in] gpio_num GPIO number to be mapped soc_root_clk signal source
* @param[out] clkout_mapping_ret_hdl Clock output controll handler
* @param[out] clkout_mapping_ret_hdl Clock output control handler
* @return
* - ESP_OK: Output specified clock signal to specified GPIO successfully
* - ESP_ERR_INVALID_ARG: Specified GPIO not supported to output internal clock
@ -36,12 +36,26 @@ esp_err_t esp_clock_output_start(soc_clkout_sig_id_t clk_sig, gpio_num_t gpio_nu
/**
* @brief Stop clock signal to GPIO outputting
* @param[in] clkout_mapping_hdl Clock output mapping controll handle
* @param[in] clkout_mapping_hdl Clock output mapping control handle
* @return
* - ESP_OK: Disable the clock output on GPIO successfully
* - ESP_ERR_INVALID_STATE The clock in handle is already in the disabled state
* - ESP_ERR_INVALID_ARG The clock mapping handle is not initialized yet
* - ESP_ERR_INVALID_STATE The clock mapping handle is already in the disabled state
*/
esp_err_t esp_clock_output_stop(esp_clock_output_mapping_handle_t clkout_mapping_hdl);
#if SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER
/**
* @brief Output the mapped clock after frequency division
* @param clkout_mapping_hdl clkout_mapping_hdl Clock output mapping control handle
* @param div_num clock frequency division value, should be in the range of 1 ~ 256
* @return
* - ESP_OK: Disable the clock output on GPIO successfully
* - ESP_ERR_INVALID_ARG The clock mapping handle is not initialized yet or the div_num is in bad range
*/
esp_err_t esp_clock_output_set_divider(esp_clock_output_mapping_handle_t clkout_mapping_hdl, uint32_t div_num);
#endif
#endif // SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX || SOC_GPIO_CLOCKOUT_BY_IO_MUX
#ifdef __cplusplus

View File

@ -35,6 +35,9 @@ void output_clock_1(void *pvParameter)
esp_clock_output_mapping_handle_t clkout_mapping_hdl;
for (int i = 0; i < TEST_LOOPS; ++i) {
TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[0], test_clk_out_io[0], &clkout_mapping_hdl));
#if SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER
TEST_ESP_OK(esp_clock_output_set_divider(clkout_mapping_hdl, 8));
#endif
vTaskDelay(3);
TEST_ESP_OK(esp_clock_output_stop(clkout_mapping_hdl));
vTaskDelay(7);

View File

@ -83,9 +83,15 @@ uint32_t clk_hal_xtal_get_freq_mhz(void)
void clk_hal_clock_output_setup(soc_clkout_sig_id_t clk_sig, clock_out_channel_t channel_id)
{
clk_ll_set_dbg_clk_ctrl(clk_sig, channel_id);
clk_ll_set_dbg_clk_channel_divider(channel_id, 1);
clk_ll_enable_dbg_clk_channel(channel_id, true);
}
void clk_hal_clock_output_set_divider(clock_out_channel_t channel_id, uint32_t div_num)
{
clk_ll_set_dbg_clk_channel_divider(channel_id, div_num);
}
void clk_hal_clock_output_teardown(clock_out_channel_t channel_id)
{
clk_ll_enable_dbg_clk_channel(channel_id, false);

View File

@ -833,15 +833,17 @@ static inline __attribute__((always_inline)) void clk_ll_set_dbg_clk_ctrl(soc_cl
{
if (channel_id == CLKOUT_CHANNEL_1) {
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg_clk_ctrl0, reg_dbg_ch0_sel, clk_sig);
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg_clk_ctrl0, reg_dbg_ch0_div_num, 0);
} else if (channel_id == CLKOUT_CHANNEL_2) {
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg_clk_ctrl0, reg_dbg_ch1_sel, clk_sig);
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg_clk_ctrl1, reg_dbg_ch1_div_num, 0);
} else {
abort();
}
}
/**
* @brief Enable the clock output channel
* @param enable Enable or disable the clock output channel
*/
static inline __attribute__((always_inline)) void clk_ll_enable_dbg_clk_channel(clock_out_channel_t channel_id, bool enable)
{
if (channel_id == CLKOUT_CHANNEL_1) {
@ -853,6 +855,22 @@ static inline __attribute__((always_inline)) void clk_ll_enable_dbg_clk_channel(
}
}
/**
* @brief Output the mapped clock after frequency division
* @param channel_id channel id that need to be configured with frequency division
* @param div_num clock frequency division value
*/
static inline __attribute__((always_inline)) void clk_ll_set_dbg_clk_channel_divider(clock_out_channel_t channel_id, uint32_t div_num)
{
if (channel_id == CLKOUT_CHANNEL_1) {
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg_clk_ctrl0, reg_dbg_ch0_div_num, div_num - 1);
} else if (channel_id == CLKOUT_CHANNEL_2) {
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg_clk_ctrl1, reg_dbg_ch1_div_num, div_num - 1);
} else {
abort();
}
}
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -68,6 +68,15 @@ uint32_t clk_hal_apll_get_freq_hz(void);
*/
void clk_hal_clock_output_setup(soc_clkout_sig_id_t clk_sig, clock_out_channel_t channel_id);
#if SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER
/**
* @brief Output the mapped clock after frequency division
* @param channel_id channel id that need to be configured with frequency division
* @param div_num clock frequency division value
*/
void clk_hal_clock_output_set_divider(clock_out_channel_t channel_id, uint32_t div_num);
#endif
/**
* @brief Teardown clock output channel configuration
* @param channel_id The clock output channel to teardown

View File

@ -199,10 +199,6 @@ config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
bool
default y
config SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX
bool
default y
config SOC_GPIO_CLOCKOUT_CHANNEL_NUM
int
default 3

View File

@ -213,7 +213,7 @@
#define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1)
// The Clock Out signal is route to the pin by GPIO matrix
#define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1)
// #define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1)
#define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3)
/*-------------------------- RTCIO CAPS --------------------------------------*/

View File

@ -563,6 +563,10 @@ config SOC_GPIO_CLOCKOUT_CHANNEL_NUM
int
default 2
config SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER
bool
default y
config SOC_GPIO_SUPPORT_FORCE_HOLD
bool
default y

View File

@ -234,6 +234,7 @@
// The Clock Out signal is route to the pin by GPIO matrix
#define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1)
#define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (2)
#define SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER (1)
// Support to force hold all IOs
#define SOC_GPIO_SUPPORT_FORCE_HOLD (1)