Skip to content

Commit

Permalink
soc: nrf54h: gpd: use callback to fetch nrfs async result
Browse files Browse the repository at this point in the history
Busy-waiting for the result of the nrfs service calls can stall, so
let's use a callback that flags a semaphore instead. Since the API is
supposed to be callable in the context of pre-kernel, fallback to
busy-wait on that scenario.

Signed-off-by: Gerard Marull-Paretas <[email protected]>
  • Loading branch information
gmarull committed Nov 4, 2024
1 parent 23fb3b7 commit 0f7f989
Showing 1 changed file with 51 additions and 6 deletions.
57 changes: 51 additions & 6 deletions soc/nordic/nrf54h/gpd/gpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ struct gpd_onoff_manager {
struct onoff_manager mgr;
onoff_notify_fn notify;
uint8_t id;
struct k_mutex lock;
struct k_sem sem;
int res;
};

static void start(struct onoff_manager *mgr, onoff_notify_fn notify);
Expand All @@ -41,9 +44,21 @@ static void stop(struct onoff_manager *mgr, onoff_notify_fn notify);
#define GPD_SERVICE_REQ_ERR BIT(3)
static atomic_t gpd_service_status = ATOMIC_INIT(0);

static struct gpd_onoff_manager fast_active1 = {.id = NRF_GPD_FAST_ACTIVE1};
static struct gpd_onoff_manager slow_active = {.id = NRF_GPD_SLOW_ACTIVE};
static struct gpd_onoff_manager slow_main = {.id = NRF_GPD_SLOW_MAIN};
static struct gpd_onoff_manager fast_active1 = {
.id = NRF_GPD_FAST_ACTIVE1,
.lock = Z_MUTEX_INITIALIZER(fast_active1.lock),
.sem = Z_SEM_INITIALIZER(fast_active1.sem, 0, 1),
};
static struct gpd_onoff_manager slow_active = {
.id = NRF_GPD_SLOW_ACTIVE,
.lock = Z_MUTEX_INITIALIZER(slow_active.lock),
.sem = Z_SEM_INITIALIZER(slow_active.sem, 0, 1),
};
static struct gpd_onoff_manager slow_main = {
.id = NRF_GPD_SLOW_MAIN,
.lock = Z_MUTEX_INITIALIZER(slow_main.lock),
.sem = Z_SEM_INITIALIZER(slow_main.sem, 0, 1),
};

static const struct onoff_transitions transitions =
ONOFF_TRANSITIONS_INITIALIZER(start, stop, NULL);
Expand All @@ -62,6 +77,18 @@ static struct gpd_onoff_manager *get_mgr(uint8_t id)
}
}

static void request_cb(struct onoff_manager *mgr_, struct onoff_client *cli, uint32_t state,
int res)
{
ARG_UNUSED(cli);
ARG_UNUSED(state);

struct gpd_onoff_manager *gpd_mgr = CONTAINER_OF(mgr_, struct gpd_onoff_manager, mgr);

gpd_mgr->res = res;
k_sem_give(&gpd_mgr->sem);
}

static int nrf_gpd_sync(struct gpd_onoff_manager *gpd_mgr)
{
int64_t start;
Expand Down Expand Up @@ -181,11 +208,29 @@ int nrf_gpd_request(uint8_t id)
return -EIO;
}

sys_notify_init_spinwait(&client.notify);
if (k_is_pre_kernel()) {
sys_notify_init_spinwait(&client.notify);
} else {
sys_notify_init_callback(&client.notify, request_cb);
k_mutex_lock(&gpd_mgr->lock, K_FOREVER);
}

ret = onoff_request(&gpd_mgr->mgr, &client);
if (ret < 0) {
goto unlock;
}

onoff_request(&gpd_mgr->mgr, &client);
if (k_is_pre_kernel()) {
while (sys_notify_fetch_result(&client.notify, &ret) == -EAGAIN) {
}
} else {
(void)k_sem_take(&gpd_mgr->sem, K_FOREVER);
ret = gpd_mgr->res;
}

while (sys_notify_fetch_result(&client.notify, &ret) == -EAGAIN) {
unlock:
if (!k_is_pre_kernel()) {
k_mutex_unlock(&gpd_mgr->lock);
}

return ret;
Expand Down

0 comments on commit 0f7f989

Please sign in to comment.