Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion drivers/clock_control/clock_control_nrf2_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@
notify(mgr, 0);
}

static void onoff_reset_option(struct onoff_manager *mgr,
onoff_notify_fn notify)
{

Check notice on line 86 in drivers/clock_control/clock_control_nrf2_common.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/clock_control/clock_control_nrf2_common.c:86 -static void onoff_reset_option(struct onoff_manager *mgr, - onoff_notify_fn notify) +static void onoff_reset_option(struct onoff_manager *mgr, onoff_notify_fn notify)
notify(mgr, 0);
}

static inline uint8_t get_index_of_highest_bit(uint32_t value)
{
return value ? (uint8_t)(31 - __builtin_clz(value)) : 0;
Expand Down Expand Up @@ -129,7 +135,8 @@
for (int i = 0; i < onoff_cnt; ++i) {
static const struct onoff_transitions transitions = {
.start = onoff_start_option,
.stop = onoff_stop_option
.stop = onoff_stop_option,
.reset = onoff_reset_option,

Check notice on line 139 in drivers/clock_control/clock_control_nrf2_common.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/clock_control/clock_control_nrf2_common.c:139 - .stop = onoff_stop_option, + .stop = onoff_stop_option,
};
int rc;

Expand All @@ -148,6 +155,22 @@
return 0;
}

int clock_config_request(struct onoff_manager *mgr, struct onoff_client *cli)
{
/* If the on-off service recorded earlier an error, its state must be
* reset before a new request is made, otherwise the request would fail
* immediately.
*/
if (onoff_has_error(mgr)) {
struct onoff_client reset_cli;

sys_notify_init_spinwait(&reset_cli.notify);
onoff_reset(mgr, &reset_cli);
}

return onoff_request(mgr, cli);
}

uint8_t clock_config_update_begin(struct k_work *work)
{
struct clock_config_generic *cfg =
Expand Down
14 changes: 14 additions & 0 deletions drivers/clock_control/clock_control_nrf2_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ int lfosc_get_accuracy(uint16_t *accuracy);
*/
int clock_config_init(void *clk_cfg, uint8_t onoff_cnt, k_work_handler_t update_work_handler);

/**
* @brief Helper function for requesting a clock configuration handled by
* a given on-off manager.
*
* If needed, the function resets the on-off service prior to making the new
* request.
*
* @param mgr pointer to the manager for which the request is to be done.
* @param cli pointer to a client state structure to be used for the request.
*
* @return result returned by onoff_request().
*/
int clock_config_request(struct onoff_manager *mgr, struct onoff_client *cli);

/**
* @brief Starts a clock configuration update.
*
Expand Down
2 changes: 1 addition & 1 deletion drivers/clock_control/clock_control_nrf2_fll16m.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ static int api_request_fll16m(const struct device *dev,
struct onoff_manager *mgr = fll16m_find_mgr(dev, spec);

if (mgr) {
return onoff_request(mgr, cli);
return clock_config_request(mgr, cli);
}

return -EINVAL;
Expand Down
2 changes: 1 addition & 1 deletion drivers/clock_control/clock_control_nrf2_global_hsfll.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ static int api_request_global_hsfll(const struct device *dev,
struct onoff_manager *mgr = global_hsfll_find_mgr(dev, spec);

if (mgr) {
return onoff_request(mgr, cli);
return clock_config_request(mgr, cli);
}

return -EINVAL;
Expand Down
2 changes: 1 addition & 1 deletion drivers/clock_control/clock_control_nrf2_hsfll.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ static int api_request_hsfll(const struct device *dev,
struct onoff_manager *mgr = hsfll_find_mgr(dev, spec);

if (mgr) {
return onoff_request(mgr, cli);
return clock_config_request(mgr, cli);
}

return -EINVAL;
Expand Down
2 changes: 1 addition & 1 deletion drivers/clock_control/clock_control_nrf2_lfclk.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ static int api_request_lfclk(const struct device *dev,
struct onoff_manager *mgr = lfclk_find_mgr(dev, spec);

if (mgr) {
return onoff_request(mgr, cli);
return clock_config_request(mgr, cli);
}

return -EINVAL;
Expand Down
66 changes: 62 additions & 4 deletions tests/drivers/clock_control/nrf_clock_control/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@
clk_dev = clk_context->clk_dev;
clk_spec = &clk_context->clk_specs[u];

zassert_true(device_is_ready(clk_dev),
"%s is not ready", clk_dev->name);

Check notice on line 199 in tests/drivers/clock_control/nrf_clock_control/src/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

tests/drivers/clock_control/nrf_clock_control/src/main.c:199 - zassert_true(device_is_ready(clk_dev), - "%s is not ready", clk_dev->name); + zassert_true(device_is_ready(clk_dev), "%s is not ready", clk_dev->name);
TC_PRINT("Applying clock (%s) spec: frequency %d, accuracy %d, precision "
"%d\n",
clk_dev->name, clk_spec->frequency, clk_spec->accuracy,
Expand All @@ -206,10 +209,7 @@
#if CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP
ZTEST(nrf2_clock_control, test_cpuapp_hsfll_control)
{

TC_PRINT("APPLICATION DOMAIN HSFLL test\n");
/* Wait for the DVFS init to complete */
k_msleep(3000);
test_clock_control_request(cpuapp_hsfll_test_clk_contexts,
ARRAY_SIZE(cpuapp_hsfll_test_clk_contexts));
}
Expand Down Expand Up @@ -240,6 +240,9 @@
clk_dev = clk_context->clk_dev;
clk_spec = &clk_context->clk_specs[u];

zassert_true(device_is_ready(clk_dev),
"%s is not ready", clk_dev->name);

Check notice on line 245 in tests/drivers/clock_control/nrf_clock_control/src/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

tests/drivers/clock_control/nrf_clock_control/src/main.c:245 - zassert_true(device_is_ready(clk_dev), - "%s is not ready", clk_dev->name); + zassert_true(device_is_ready(clk_dev), "%s is not ready", clk_dev->name);
TC_PRINT("Applying clock (%s) spec: frequency %d, accuracy %d, precision "
"%d\n",
clk_dev->name, clk_spec->frequency, clk_spec->accuracy,
Expand Down Expand Up @@ -285,6 +288,9 @@
const struct device *clk_dev = clk_context->clk_dev;
const struct nrf_clock_spec *clk_spec = &test_clk_specs_lfclk[0];

zassert_true(device_is_ready(clk_dev),
"%s is not ready", clk_dev->name);

Check notice on line 293 in tests/drivers/clock_control/nrf_clock_control/src/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

tests/drivers/clock_control/nrf_clock_control/src/main.c:293 - zassert_true(device_is_ready(clk_dev), - "%s is not ready", clk_dev->name); + zassert_true(device_is_ready(clk_dev), "%s is not ready", clk_dev->name);
TC_PRINT("Safe clock request cancellation\n");
TC_PRINT("Clock under test: %s\n", clk_dev->name);
sys_notify_init_spinwait(&cli.notify);
Expand All @@ -298,4 +304,56 @@
zassert_between_inclusive(ret, ONOFF_STATE_ON, ONOFF_STATE_TO_ON);
}

ZTEST_SUITE(nrf2_clock_control, NULL, NULL, NULL, NULL, NULL);
static void *setup(void)
{
#if defined(CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP)
const struct device *clk_dev = DEVICE_DT_GET(DT_NODELABEL(cpuapp_hsfll));
const struct nrf_clock_spec clk_spec = {
.frequency = MHZ(64),
};
struct onoff_client cli;
uint32_t start_uptime;
const uint32_t timeout_ms = 3000;

zassert_true(device_is_ready(clk_dev),
"%s is not ready", clk_dev->name);

Check notice on line 320 in tests/drivers/clock_control/nrf_clock_control/src/main.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

tests/drivers/clock_control/nrf_clock_control/src/main.c:320 - zassert_true(device_is_ready(clk_dev), - "%s is not ready", clk_dev->name); + zassert_true(device_is_ready(clk_dev), "%s is not ready", clk_dev->name);
/* Constantly make requests to DVFS until one is successful (what also
* means that the service has finished its initialization). This loop
* also verifies that the clock control driver is able to recover after
* an unsuccesful attempt to start a clock (at least one initial request
* is expected to fail here due to DFVS not being initialized yet).
*/
TC_PRINT("Polling DVFS until it is ready\n");
start_uptime = k_uptime_get_32();
while (1) {
int status;
int ret;

sys_notify_init_spinwait(&cli.notify);
ret = nrf_clock_control_request(clk_dev, &clk_spec, &cli);
/* The on-off manager for this clock controller is expected to
* always be in the off state when a request is done (its error
* state is expected to be cleared by the clock control driver).
*/
zassert_equal(ret, ONOFF_STATE_OFF, "request result: %d", ret);
do {
ret = sys_notify_fetch_result(&cli.notify, &status);
k_yield();
} while (ret == -EAGAIN);

if (status == 0) {
TC_PRINT("DVFS is ready\n");
break;
} else if ((k_uptime_get_32() - start_uptime) >= timeout_ms) {
TC_PRINT("DVFS is not ready after %u ms\n", timeout_ms);
ztest_test_fail();
break;
}
}
#endif

return NULL;
}

ZTEST_SUITE(nrf2_clock_control, NULL, setup, NULL, NULL, NULL);
Loading