From 4e62312bbcdc41b046286f3ff16cbc1d8918aaac Mon Sep 17 00:00:00 2001 From: Lukasz Stepnicki Date: Wed, 5 Jun 2024 14:59:30 +0200 Subject: [PATCH] modules: hal_nordic: dvfs: added callback when scaling done User can assign callback function to local domain dvfs handler and get notification when scaling process is finished for particular domain. Reworked usage of DVFS_SERV_HDL_FREQ_CHANGE_IN_PROGRESS_BIT_POS which was not initialized properly. Signed-off-by: Lukasz Stepnicki --- .../hal_nordic/nrfs/dvfs/ld_dvfs_handler.c | 32 ++++++++++++++++--- .../hal_nordic/nrfs/dvfs/ld_dvfs_handler.h | 15 +++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c index 20e879c4f737eaa..79c464d667bb6be 100644 --- a/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c +++ b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c @@ -23,6 +23,7 @@ static K_SEM_DEFINE(dvfs_service_idle_sem, 0, 1); static atomic_t dvfs_service_handler_state_bits; static enum dvfs_frequency_setting current_freq_setting; +static dvfs_service_handler_callback dvfs_frequency_change_applied_clb; static void dvfs_service_handler_set_state_bit(uint32_t bit_pos) { @@ -143,7 +144,11 @@ static void dvfs_service_handler_scaling_finish(enum dvfs_frequency_setting oppo dvfs_service_handler_error(err); } } + dvfs_service_handler_clear_state_bit(DVFS_SERV_HDL_FREQ_CHANGE_IN_PROGRESS_BIT_POS); current_freq_setting = oppoint_freq; + if (dvfs_frequency_change_applied_clb) { + dvfs_frequency_change_applied_clb((void *)¤t_freq_setting); + } } /* Function to set hsfll to highest frequency when switched to ABB. */ @@ -196,7 +201,7 @@ static void nrfs_dvfs_evt_handler(nrfs_dvfs_evt_t const *p_evt, void *context) dvfs_service_handler_scaling_background_job(p_evt->freq); LOG_INF("DVFS handler EVT_OPPOINT_SCALING_PREPARE handled"); #if !defined(NRF_SECURE) - current_freq_setting = p_evt->freq; + dvfs_service_handler_scaling_finish(p_evt->freq); } else { LOG_ERR("DVFS handler - unexpected EVT_OPPOINT_SCALING_PREPARE"); } @@ -204,7 +209,6 @@ static void nrfs_dvfs_evt_handler(nrfs_dvfs_evt_t const *p_evt, void *context) break; case NRFS_DVFS_EVT_OPPOINT_SCALING_DONE: LOG_INF("DVFS handler EVT_OPPOINT_SCALING_DONE"); - dvfs_service_handler_clear_state_bit(DVFS_SERV_HDL_FREQ_CHANGE_IN_PROGRESS_BIT_POS); dvfs_service_handler_scaling_finish(p_evt->freq); LOG_INF("DVFS handler EVT_OPPOINT_SCALING_DONE handled"); break; @@ -271,22 +275,42 @@ K_THREAD_DEFINE(dvfs_service_handler_task_id, int32_t dvfs_service_handler_change_freq_setting(enum dvfs_frequency_setting freq_setting) { if (!dvfs_service_handler_init_done()) { - LOG_INF("Init not done!"); + LOG_ERR("Init not done!"); return -EAGAIN; } if (dvfs_service_handler_freq_change_in_progress()) { - LOG_INF("Frequency change in progress."); + LOG_DBG("Frequency change in progress."); return -EBUSY; } if (!dvfs_service_handler_freq_setting_allowed(freq_setting)) { + LOG_ERR("Requested frequency setting %d not supported.", freq_setting); return -ENXIO; } + if (freq_setting == current_freq_setting) { + LOG_DBG("Requested frequency setting %d same as current setting.", freq_setting); + return -EEXIST; + } + nrfs_err_t status = nrfs_dvfs_oppoint_request(freq_setting, get_next_context()); + if (status == NRFS_SUCCESS) { + dvfs_service_handler_set_state_bit(DVFS_SERV_HDL_FREQ_CHANGE_IN_PROGRESS_BIT_POS); + } + dvfs_service_handler_nrfs_error_check(status); return status; } + +void dvfs_service_handler_register_freq_setting_applied_callback(dvfs_service_handler_callback clb) +{ + if (clb) { + LOG_DBG("Registered frequency applied callback"); + dvfs_frequency_change_applied_clb = clb; + } else { + LOG_ERR("Invalid callback function provided!"); + } +} diff --git a/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.h b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.h index b15e630eb2c89fd..22e10cb7cb56a9f 100644 --- a/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.h +++ b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.h @@ -20,12 +20,27 @@ extern "C" { * @return EBUSY Frequency change in progress. * @return EAGAIN DVFS init in progress. * @return ENXIO Not supported frequency settings. + * @return EEXIST Requested same frequency setting as current one. * @return NRFS_SUCCESS Request sent successfully. * @return NRFS_ERR_INVALID_STATE Service is uninitialized. * @return NRFS_ERR_IPC Backend returned error during request sending. */ int32_t dvfs_service_handler_change_freq_setting(enum dvfs_frequency_setting freq_setting); +/** + * @brief Type to use as callback function in dvfs service + * + * @param params *dvfs_frequency_setting current_freq_setting + */ +typedef void (*dvfs_service_handler_callback)(void *params); + +/** + * @brief Register callback function which will be called when new dvfs frequency is applied. + * + * @param clb dvfs_service_handler_callback to register + */ +void dvfs_service_handler_register_freq_setting_applied_callback(dvfs_service_handler_callback clb); + #ifdef __cplusplus } #endif