Skip to content

Commit

Permalink
applications: nrf_desktop: Use clock api for DVFS
Browse files Browse the repository at this point in the history
Use clock api in nrf_desktop dvfs module.
Use notification handler to notify correct
completion of DVFS.

JIRA: NCSDK-29351

Signed-off-by: Jan Zyczkowski <jan.zyczkowski@nordicsemi.no>
  • Loading branch information
zycz committed Oct 1, 2024
1 parent 9c7c28c commit 9937560
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@
in-polling-rate = <125>;
in-report-size = <64>;
};

aliases {
dvfs-clock = &cpuapp_hsfll;
};
};

&cpusec_cpuapp_ipc {
Expand Down
22 changes: 22 additions & 0 deletions applications/nrf_desktop/src/modules/Kconfig.dvfs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,27 @@
menuconfig DESKTOP_DVFS
bool "DVFS module"
depends on SOC_NRF54H20_CPUAPP
select CLOCK_CONTROL_NRF2
default y
help
This option enable DVFS module which switches frequency and voltage according
to application needs.

if DESKTOP_DVFS

config DESKTOP_DVFS_FREQ_HIGH
int "High frequency"
default 320000000

config DESKTOP_DVFS_FREQ_MED
int "Medium frequency"
default 128000000

config DESKTOP_DVFS_FREQ_LOW
int "Low frequency"
default 64000000


config DESKTOP_DVFS_RETRY_BUSY_TIMEOUT_MS
int "Retry timeout"
default 1
Expand All @@ -40,6 +54,14 @@ config DESKTOP_DVFS_RETRY_COUNT
Number of retries of DVFS frequency change after which DVFS module will report
MODULE_STATE_ERROR.

config DESKTOP_DVFS_CLOCK_ACCURACY_PPM
int "Accuracy specification to request from clock in PPM"
default 0

config DESKTOP_DVFS_CLOCK_PRECISION
int "Precision specification to request from clock"
default 0

module = DESKTOP_DVFS
module-str = DVFS
source "subsys/logging/Kconfig.template.log_config"
Expand Down
76 changes: 52 additions & 24 deletions applications/nrf_desktop/src/modules/dvfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(MODULE, CONFIG_DESKTOP_DVFS_LOG_LEVEL);

#include <ld_dvfs_handler.h>
#include <zephyr/devicetree/clocks.h>
#include <zephyr/drivers/clock_control/nrf_clock_control.h>

#define CLOCK_NODE DT_ALIAS(dvfs_clock)
static const struct device *dvfs_clock_dev = DEVICE_DT_GET(CLOCK_NODE);
static struct onoff_client cli;
static struct nrf_clock_spec spec = {
.accuracy = CONFIG_DESKTOP_DVFS_CLOCK_ACCURACY_PPM,
.precision = CONFIG_DESKTOP_DVFS_CLOCK_PRECISION,
};

#define DVFS_RETRY_INITIALIZATION_TIMEOUT K_MSEC(CONFIG_DESKTOP_DVFS_RETRY_INIT_TIMEOUT_MS)
#define DVFS_RETRY_BUSY_TIMEOUT K_MSEC(CONFIG_DESKTOP_DVFS_RETRY_BUSY_TIMEOUT_MS)
Expand Down Expand Up @@ -72,7 +81,7 @@ static const uint8_t dvfs_medlow_freq_bitmask = INITIALIZE_DVFS_FREQ_MASK(ACTIVE
/* Binary mask tracking which states are requested. */
static uint8_t dfvs_requests_state_bitmask;

static enum dvfs_frequency_setting current_freq = DVFS_FREQ_HIGH;
static uint32_t current_freq = CONFIG_DESKTOP_DVFS_FREQ_HIGH;

BUILD_ASSERT(sizeof(dvfs_high_freq_bitmask) == sizeof(dfvs_requests_state_bitmask));
BUILD_ASSERT(sizeof(dvfs_medlow_freq_bitmask) == sizeof(dfvs_requests_state_bitmask));
Expand All @@ -92,16 +101,6 @@ static struct dvfs_state_timeout dvfs_state_timeouts[DVFS_STATE_COUNT] = {
LIST_FOR_DVFS_STATE(INITIALIZE_DVFS_STATE_TIMEOUT)
};

static const char *get_dvfs_frequency_setting_name(enum dvfs_frequency_setting setting)
{
switch (setting) {
case DVFS_FREQ_HIGH: return "DVFS_FREQ_HIGH";
case DVFS_FREQ_MEDLOW: return "DVFS_FREQ_MEDLOW";
case DVFS_FREQ_LOW: return "DVFS_FREQ_LOW";
default: return "Unknown";
}
}

static const char *get_dvfs_state_name(enum dvfs_state state)
{
switch (state) {
Expand Down Expand Up @@ -145,28 +144,57 @@ static void handle_dvfs_error(int32_t err)
(void) k_work_reschedule(&dvfs_retry.retry_work, timeout);
}

static void set_dvfs_freq(enum dvfs_frequency_setting target_freq)
static void dvfs_notify_cb(void)
{
int res;
int32_t ret = sys_notify_fetch_result(&cli.notify, &res);

if (ret < 0) {
LOG_DBG("work not completed");
return;
}

ret = nrf_clock_control_release(dvfs_clock_dev, &spec);
if (ret < 0) {
LOG_ERR("Failed to release requested clock specs");
module_set_state(MODULE_STATE_ERROR);
module_state = STATE_ERROR;
cancel_dvfs_retry_work();
return;
}

sys_notify_init_callback(&cli.notify, dvfs_notify_cb);

if (res < 0) {
handle_dvfs_error(res);
return;
}

LOG_INF("DVFS completed");
}

static void set_dvfs_freq(uint32_t target_freq)
{
int32_t ret = dvfs_service_handler_change_freq_setting(target_freq);
spec.frequency = target_freq;
int32_t ret = nrf_clock_control_request(dvfs_clock_dev, &spec, &cli);

if (ret) {
handle_dvfs_error(ret);
} else {
current_freq = target_freq;
LOG_INF("Have requested %s frequency",
get_dvfs_frequency_setting_name(target_freq));
LOG_INF("Have requested %d frequency", target_freq);
cancel_dvfs_retry_work();
}
}

static enum dvfs_frequency_setting check_required_frequency(void)
static uint32_t check_required_frequency(void)
{
if (dfvs_requests_state_bitmask & dvfs_high_freq_bitmask) {
return DVFS_FREQ_HIGH;
return CONFIG_DESKTOP_DVFS_FREQ_HIGH;
} else if (dfvs_requests_state_bitmask & dvfs_medlow_freq_bitmask) {
return DVFS_FREQ_MEDLOW;
return CONFIG_DESKTOP_DVFS_FREQ_MED;
} else {
return DVFS_FREQ_LOW;
return CONFIG_DESKTOP_DVFS_FREQ_LOW;
}
}

Expand All @@ -184,7 +212,7 @@ static void process_dvfs_states(enum dvfs_state state, bool turn_on)
LOG_DBG("%s NOT ACTIVE", get_dvfs_state_name(state));
}

enum dvfs_frequency_setting required_freq = check_required_frequency();
uint32_t required_freq = check_required_frequency();

if ((required_freq != current_freq) &&
(!k_work_delayable_is_pending(&dvfs_retry.retry_work))) {
Expand Down Expand Up @@ -226,7 +254,7 @@ static void dvfs_retry_work_handler(struct k_work *work)
{
LOG_DBG("Retrying to change DVFS frequency.");

enum dvfs_frequency_setting required_freq = check_required_frequency();
uint32_t required_freq = check_required_frequency();

__ASSERT_NO_MSG(required_freq != current_freq);

Expand Down Expand Up @@ -260,6 +288,7 @@ static bool app_event_handler(const struct app_event_header *aeh)
k_work_init_delayable(&dvfs_state_timeouts[i].timeout_work,
dvfs_state_timeout_work_handler);
}
sys_notify_init_callback(&cli.notify, dvfs_notify_cb);
module_state = STATE_READY;

if (IS_ENABLED(CONFIG_DESKTOP_DVFS_STATE_INITIALIZING_ENABLE)) {
Expand All @@ -268,8 +297,7 @@ static bool app_event_handler(const struct app_event_header *aeh)
}
get_req_modules(&req_modules_bm);
} else {
enum dvfs_frequency_setting required_freq =
check_required_frequency();
uint32_t required_freq = check_required_frequency();
if (required_freq != current_freq) {
set_dvfs_freq(required_freq);
}
Expand Down

0 comments on commit 9937560

Please sign in to comment.