Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nrf fromlist] soc: nordic: nrf54h20: Add LRC around idle #2032

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
36 changes: 0 additions & 36 deletions drivers/clock_control/clock_control_nrf2_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
*/

#include "clock_control_nrf2_common.h"
#include <zephyr/kernel.h>
#include <hal/nrf_lrcconf.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
Expand All @@ -26,9 +24,6 @@ LOG_MODULE_REGISTER(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
*/
NRF2_STRUCT_CLOCK_CONFIG(generic, ONOFF_CNT_MAX);

static sys_slist_t poweron_main_list;
static struct k_spinlock poweron_main_lock;

static void update_config(struct clock_config_generic *cfg)
{
atomic_val_t prev_flags = atomic_or(&cfg->flags, FLAG_UPDATE_NEEDED);
Expand Down Expand Up @@ -165,34 +160,3 @@ int api_nosys_on_off(const struct device *dev, clock_control_subsys_t sys)

return -ENOSYS;
}

void nrf2_clock_request_lrcconf_poweron_main(struct nrf2_clock_lrcconf_sink *sink)
{
K_SPINLOCK(&poweron_main_lock) {
if (sys_slist_len(&poweron_main_list) == 0) {
LOG_DBG("%s forced on", "main domain");
NRF_LRCCONF010->POWERON &= ~LRCCONF_POWERON_MAIN_Msk;
NRF_LRCCONF010->POWERON |= LRCCONF_POWERON_MAIN_AlwaysOn;
}

sys_slist_find_and_remove(&poweron_main_list, &sink->node);
sys_slist_append(&poweron_main_list, &sink->node);
}
}

void nrf2_clock_release_lrcconf_poweron_main(struct nrf2_clock_lrcconf_sink *sink)
{
K_SPINLOCK(&poweron_main_lock) {
if (!sys_slist_find_and_remove(&poweron_main_list, &sink->node)) {
K_SPINLOCK_BREAK;
}

if (sys_slist_len(&poweron_main_list) > 0) {
K_SPINLOCK_BREAK;
}

LOG_DBG("%s automatic", "main domain");
NRF_LRCCONF010->POWERON &= ~LRCCONF_POWERON_MAIN_Msk;
NRF_LRCCONF010->POWERON |= LRCCONF_POWERON_MAIN_Automatic;
}
}
10 changes: 0 additions & 10 deletions drivers/clock_control/clock_control_nrf2_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,4 @@ void nrf2_clock_config_update_end(void *clk_cfg, int status);

int api_nosys_on_off(const struct device *dev, clock_control_subsys_t sys);

struct nrf2_clock_lrcconf_sink {
sys_snode_t node;
};

/**
* @brief Request or release lrcconf main power domain
*/
void nrf2_clock_request_lrcconf_poweron_main(struct nrf2_clock_lrcconf_sink *sink);
void nrf2_clock_release_lrcconf_poweron_main(struct nrf2_clock_lrcconf_sink *sink);

#endif /* ZEPHYR_DRIVERS_CLOCK_CONTROL_NRF2_COMMON_H_ */
8 changes: 4 additions & 4 deletions drivers/clock_control/clock_control_nrf2_fll16m.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include "clock_control_nrf2_common.h"
#include <zephyr/devicetree.h>
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
#include <hal/nrf_lrcconf.h>
#include <soc_lrcconf.h>

#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
Expand Down Expand Up @@ -64,7 +64,7 @@ static const struct clock_options {
struct fll16m_dev_data {
NRF2_STRUCT_CLOCK_CONFIG(fll16m, ARRAY_SIZE(clock_options)) clk_cfg;
struct onoff_client hfxo_cli;
struct nrf2_clock_lrcconf_sink lrcconf_sink;
sys_snode_t fll16m_node;
};

struct fll16m_dev_config {
Expand All @@ -76,13 +76,13 @@ static void activate_fll16m_mode(struct fll16m_dev_data *dev_data, uint8_t mode)
/* TODO: change to nrf_lrcconf_* function when such is available. */

if (mode != FLL16M_MODE_DEFAULT) {
nrf2_clock_request_lrcconf_poweron_main(&dev_data->lrcconf_sink);
soc_lrcconf_poweron_request(&dev_data->fll16m_node, NRF_LRCCONF_POWER_MAIN);
}

NRF_LRCCONF010->CLKCTRL[0].SRC = mode;

if (mode == FLL16M_MODE_DEFAULT) {
nrf2_clock_release_lrcconf_poweron_main(&dev_data->lrcconf_sink);
soc_lrcconf_poweron_release(&dev_data->fll16m_node, NRF_LRCCONF_POWER_MAIN);
}

nrf_lrcconf_task_trigger(NRF_LRCCONF010, NRF_LRCCONF_TASK_CLKSTART_0);
Expand Down
8 changes: 4 additions & 4 deletions drivers/clock_control/clock_control_nrf2_hfxo.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL);

#include <hal/nrf_lrcconf.h>
#include <soc_lrcconf.h>

BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
"multiple instances not supported");
Expand All @@ -20,7 +20,7 @@ struct dev_data_hfxo {
struct onoff_manager mgr;
onoff_notify_fn notify;
struct k_timer timer;
struct nrf2_clock_lrcconf_sink lrcconf_sink;
sys_snode_t hfxo_node;
};

struct dev_config_hfxo {
Expand Down Expand Up @@ -58,7 +58,7 @@ static void onoff_start_hfxo(struct onoff_manager *mgr, onoff_notify_fn notify)
dev_data->notify = notify;

nrf_lrcconf_event_clear(NRF_LRCCONF010, NRF_LRCCONF_EVENT_HFXOSTARTED);
nrf2_clock_request_lrcconf_poweron_main(&dev_data->lrcconf_sink);
soc_lrcconf_poweron_request(&dev_data->hfxo_node, NRF_LRCCONF_POWER_MAIN);
nrf_lrcconf_task_trigger(NRF_LRCCONF010, NRF_LRCCONF_TASK_REQHFXO);

/* Due to a hardware issue, the HFXOSTARTED event is currently
Expand All @@ -74,7 +74,7 @@ static void onoff_stop_hfxo(struct onoff_manager *mgr, onoff_notify_fn notify)
CONTAINER_OF(mgr, struct dev_data_hfxo, mgr);

nrf_lrcconf_task_trigger(NRF_LRCCONF010, NRF_LRCCONF_TASK_STOPREQHFXO);
nrf2_clock_release_lrcconf_poweron_main(&dev_data->lrcconf_sink);
soc_lrcconf_poweron_release(&dev_data->hfxo_node, NRF_LRCCONF_POWER_MAIN);
notify(mgr, 0);
}

Expand Down
18 changes: 18 additions & 0 deletions dts/common/nordic/nrf54h20.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
device_type = "cpu";
clocks = <&cpuapp_hsfll>;
clock-frequency = <DT_FREQ_M(320)>;
cpu-power-states = <&idle_cache_disabled &s2ram>;
};

cpurad: cpu@3 {
Expand All @@ -36,6 +37,7 @@
device_type = "cpu";
clocks = <&cpurad_hsfll>;
clock-frequency = <DT_FREQ_M(256)>;
cpu-power-states = <&idle_cache_disabled>;
};

cpuppr: cpu@d {
Expand Down Expand Up @@ -72,6 +74,22 @@
nordic,tasks-mask = <0xfffffff0>;
};
};

power-states {
// substate-id = <0>; is reserved for "idle", cache powered on
// substate-id = <1>; is reserved for "idle-cache-retained"
idle_cache_disabled: idle_cache_disabled {
compatible = "zephyr,power-state";
power-state-name = "suspend-to-idle";
substate-id = <2>;
min-residency-us = <100000>;
};
s2ram: s2ram {
compatible = "zephyr,power-state";
power-state-name = "suspend-to-ram";
min-residency-us = <800000>;
};
};
};

reserved-memory {
Expand Down
3 changes: 3 additions & 0 deletions soc/nordic/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ add_subdirectory_ifdef(CONFIG_RISCV_CORE_NORDIC_VPR vpr)
zephyr_linker_sources_ifdef(CONFIG_ARM SECTIONS arm_platform_init.ld)

zephyr_library_sources_ifdef(CONFIG_POWEROFF poweroff.c)
if(CONFIG_ARM)
zephyr_library_sources_ifdef(CONFIG_NRF_PLATFORM_HALTIUM soc_lrcconf.c)
endif()

if((CONFIG_SOC_SERIES_NRF54HX OR CONFIG_SOC_SERIES_NRF92X) AND CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS)
zephyr_library_sources(nrf54hx_nrf92x_mpu_regions.c)
Expand Down
63 changes: 63 additions & 0 deletions soc/nordic/common/soc_lrcconf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <soc_lrcconf.h>
#include <zephyr/kernel.h>

static struct k_spinlock lock;
static sys_slist_t poweron_main_list;
static sys_slist_t poweron_active_list;

void soc_lrcconf_poweron_request(sys_snode_t *node, nrf_lrcconf_power_domain_mask_t domain)
{
__ASSERT(is_power_of_two(domain),
"Only one bit can be set for the domain parameter");

sys_slist_t *poweron_list;

if (domain == NRF_LRCCONF_POWER_MAIN) {
poweron_list = &poweron_main_list;
} else if (domain == NRF_LRCCONF_POWER_DOMAIN_0) {
poweron_list = &poweron_active_list;
} else {
return;
}
K_SPINLOCK(&lock) {
if (sys_slist_len(poweron_list) == 0) {
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, domain, true);
}

sys_slist_find_and_remove(poweron_list, node);
sys_slist_append(poweron_list, node);
}
}

void soc_lrcconf_poweron_release(sys_snode_t *node, nrf_lrcconf_power_domain_mask_t domain)
{
__ASSERT(is_power_of_two(domain),
"Only one bit can be set for the domain parameter");

sys_slist_t *poweron_list;

if (domain == NRF_LRCCONF_POWER_MAIN) {
poweron_list = &poweron_main_list;
} else if (domain == NRF_LRCCONF_POWER_DOMAIN_0) {
poweron_list = &poweron_active_list;
} else {
return;
}

K_SPINLOCK(&lock) {
if (!sys_slist_find_and_remove(poweron_list, node)) {
K_SPINLOCK_BREAK;
}

if (sys_slist_len(poweron_list) > 0) {
K_SPINLOCK_BREAK;
}
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, domain, false);
}
}
34 changes: 34 additions & 0 deletions soc/nordic/common/soc_lrcconf.h
hubertmis marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

/**
* @file nRF SoC specific helpers for lrcconf management
*/

#ifndef ZEPHYR_SOC_NORDIC_COMMON_LRCCONF_H_
#define ZEPHYR_SOC_NORDIC_COMMON_LRCCONF_H_

#include <hal/nrf_lrcconf.h>

/**
* @brief Request lrcconf power domain
*
* @param node Pointer to the @ref sys_snode_t structure which is the ID of the
* requesting module.
* @param domain The mask that represents the power domain ID.
*/
void soc_lrcconf_poweron_request(sys_snode_t *node, nrf_lrcconf_power_domain_mask_t domain);

/**
* @brief Release lrcconf power domain
*
* @param node Pointer to the @ref sys_snode_t structure which is the ID of the
* requesting module.
* @param domain The mask that represents the power domain ID.
*/
void soc_lrcconf_poweron_release(sys_snode_t *node, nrf_lrcconf_power_domain_mask_t domain);

#endif /* ZEPHYR_SOC_NORDIC_COMMON_LRCCONF_H_ */
Loading
Loading