Skip to content

Commit e29e081

Browse files
[nrf fromlist] soc: nordic: Add LRCCONF management
Due to the possibility of simultaneous accesess to LRCCONF registers, additional management is required. Upstream PR: zephyrproject-rtos/zephyr#79067 Signed-off-by: Adam Kondraciuk <[email protected]>
1 parent 4322f51 commit e29e081

File tree

11 files changed

+165
-74
lines changed

11 files changed

+165
-74
lines changed

drivers/clock_control/clock_control_nrf2_common.c

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
*/
55

66
#include "clock_control_nrf2_common.h"
7-
#include <zephyr/kernel.h>
8-
#include <hal/nrf_lrcconf.h>
97

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

29-
static sys_slist_t poweron_main_list;
30-
static struct k_spinlock poweron_main_lock;
31-
3227
static void update_config(struct clock_config_generic *cfg)
3328
{
3429
atomic_val_t prev_flags = atomic_or(&cfg->flags, FLAG_UPDATE_NEEDED);
@@ -165,34 +160,3 @@ int api_nosys_on_off(const struct device *dev, clock_control_subsys_t sys)
165160

166161
return -ENOSYS;
167162
}
168-
169-
void nrf2_clock_request_lrcconf_poweron_main(struct nrf2_clock_lrcconf_sink *sink)
170-
{
171-
K_SPINLOCK(&poweron_main_lock) {
172-
if (sys_slist_len(&poweron_main_list) == 0) {
173-
LOG_DBG("%s forced on", "main domain");
174-
NRF_LRCCONF010->POWERON &= ~LRCCONF_POWERON_MAIN_Msk;
175-
NRF_LRCCONF010->POWERON |= LRCCONF_POWERON_MAIN_AlwaysOn;
176-
}
177-
178-
sys_slist_find_and_remove(&poweron_main_list, &sink->node);
179-
sys_slist_append(&poweron_main_list, &sink->node);
180-
}
181-
}
182-
183-
void nrf2_clock_release_lrcconf_poweron_main(struct nrf2_clock_lrcconf_sink *sink)
184-
{
185-
K_SPINLOCK(&poweron_main_lock) {
186-
if (!sys_slist_find_and_remove(&poweron_main_list, &sink->node)) {
187-
K_SPINLOCK_BREAK;
188-
}
189-
190-
if (sys_slist_len(&poweron_main_list) > 0) {
191-
K_SPINLOCK_BREAK;
192-
}
193-
194-
LOG_DBG("%s automatic", "main domain");
195-
NRF_LRCCONF010->POWERON &= ~LRCCONF_POWERON_MAIN_Msk;
196-
NRF_LRCCONF010->POWERON |= LRCCONF_POWERON_MAIN_Automatic;
197-
}
198-
}

drivers/clock_control/clock_control_nrf2_common.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,4 @@ void nrf2_clock_config_update_end(void *clk_cfg, int status);
7676

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

79-
struct nrf2_clock_lrcconf_sink {
80-
sys_snode_t node;
81-
};
82-
83-
/**
84-
* @brief Request or release lrcconf main power domain
85-
*/
86-
void nrf2_clock_request_lrcconf_poweron_main(struct nrf2_clock_lrcconf_sink *sink);
87-
void nrf2_clock_release_lrcconf_poweron_main(struct nrf2_clock_lrcconf_sink *sink);
88-
8979
#endif /* ZEPHYR_DRIVERS_CLOCK_CONTROL_NRF2_COMMON_H_ */

drivers/clock_control/clock_control_nrf2_fll16m.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include "clock_control_nrf2_common.h"
99
#include <zephyr/devicetree.h>
1010
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
11-
#include <hal/nrf_lrcconf.h>
11+
#include <soc_lrcconf.h>
1212

1313
#include <zephyr/logging/log.h>
1414
LOG_MODULE_DECLARE(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
@@ -64,7 +64,7 @@ static const struct clock_options {
6464
struct fll16m_dev_data {
6565
NRF2_STRUCT_CLOCK_CONFIG(fll16m, ARRAY_SIZE(clock_options)) clk_cfg;
6666
struct onoff_client hfxo_cli;
67-
struct nrf2_clock_lrcconf_sink lrcconf_sink;
67+
sys_snode_t lrcconf_client_node;
6868
};
6969

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

7878
if (mode != FLL16M_MODE_DEFAULT) {
79-
nrf2_clock_request_lrcconf_poweron_main(&dev_data->lrcconf_sink);
79+
soc_lrcconf_poweron_request(&dev_data->lrcconf_client_node, NRF_LRCCONF_POWER_MAIN);
8080
}
8181

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

8484
if (mode == FLL16M_MODE_DEFAULT) {
85-
nrf2_clock_release_lrcconf_poweron_main(&dev_data->lrcconf_sink);
85+
soc_lrcconf_poweron_release(&dev_data->lrcconf_client_node, NRF_LRCCONF_POWER_MAIN);
8686
}
8787

8888
nrf_lrcconf_task_trigger(NRF_LRCCONF010, NRF_LRCCONF_TASK_CLKSTART_0);

drivers/clock_control/clock_control_nrf2_hfxo.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include <zephyr/logging/log.h>
1212
LOG_MODULE_DECLARE(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
1313

14-
#include <hal/nrf_lrcconf.h>
14+
#include <soc_lrcconf.h>
1515

1616
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
1717
"multiple instances not supported");
@@ -20,7 +20,7 @@ struct dev_data_hfxo {
2020
struct onoff_manager mgr;
2121
onoff_notify_fn notify;
2222
struct k_timer timer;
23-
struct nrf2_clock_lrcconf_sink lrcconf_sink;
23+
sys_snode_t lrcconf_client_node;
2424
};
2525

2626
struct dev_config_hfxo {
@@ -58,7 +58,7 @@ static void onoff_start_hfxo(struct onoff_manager *mgr, onoff_notify_fn notify)
5858
dev_data->notify = notify;
5959

6060
nrf_lrcconf_event_clear(NRF_LRCCONF010, NRF_LRCCONF_EVENT_HFXOSTARTED);
61-
nrf2_clock_request_lrcconf_poweron_main(&dev_data->lrcconf_sink);
61+
soc_lrcconf_poweron_request(&dev_data->lrcconf_client_node, NRF_LRCCONF_POWER_MAIN);
6262
nrf_lrcconf_task_trigger(NRF_LRCCONF010, NRF_LRCCONF_TASK_REQHFXO);
6363

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

7676
nrf_lrcconf_task_trigger(NRF_LRCCONF010, NRF_LRCCONF_TASK_STOPREQHFXO);
77-
nrf2_clock_release_lrcconf_poweron_main(&dev_data->lrcconf_sink);
77+
soc_lrcconf_poweron_release(&dev_data->lrcconf_client_node, NRF_LRCCONF_POWER_MAIN);
7878
notify(mgr, 0);
7979
}
8080

soc/nordic/common/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ add_subdirectory_ifdef(CONFIG_RISCV_CORE_NORDIC_VPR vpr)
66
zephyr_linker_sources_ifdef(CONFIG_ARM SECTIONS arm_platform_init.ld)
77

88
zephyr_library_sources_ifdef(CONFIG_POWEROFF poweroff.c)
9+
if(CONFIG_ARM)
10+
zephyr_library_sources_ifdef(CONFIG_NRF_PLATFORM_HALTIUM soc_lrcconf.c)
11+
endif()
912

1013
if((CONFIG_SOC_SERIES_NRF54HX OR CONFIG_SOC_SERIES_NRF92X) AND CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS)
1114
zephyr_library_sources(nrf54hx_nrf92x_mpu_regions.c)

soc/nordic/common/soc_lrcconf.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <soc_lrcconf.h>
8+
#include <zephyr/kernel.h>
9+
10+
static struct k_spinlock lock;
11+
static sys_slist_t poweron_main_list;
12+
static sys_slist_t poweron_active_list;
13+
14+
void soc_lrcconf_poweron_request(sys_snode_t *node, nrf_lrcconf_power_domain_mask_t domain)
15+
{
16+
__ASSERT(is_power_of_two(domain),
17+
"Only one bit can be set for the domain parameter");
18+
19+
sys_slist_t *poweron_list;
20+
21+
if (domain == NRF_LRCCONF_POWER_MAIN) {
22+
poweron_list = &poweron_main_list;
23+
} else if (domain == NRF_LRCCONF_POWER_DOMAIN_0) {
24+
poweron_list = &poweron_active_list;
25+
} else {
26+
return;
27+
}
28+
K_SPINLOCK(&lock) {
29+
if (sys_slist_len(poweron_list) == 0) {
30+
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, domain, true);
31+
}
32+
33+
sys_slist_find_and_remove(poweron_list, node);
34+
sys_slist_append(poweron_list, node);
35+
}
36+
}
37+
38+
void soc_lrcconf_poweron_release(sys_snode_t *node, nrf_lrcconf_power_domain_mask_t domain)
39+
{
40+
__ASSERT(is_power_of_two(domain),
41+
"Only one bit can be set for the domain parameter");
42+
43+
sys_slist_t *poweron_list;
44+
45+
if (domain == NRF_LRCCONF_POWER_MAIN) {
46+
poweron_list = &poweron_main_list;
47+
} else if (domain == NRF_LRCCONF_POWER_DOMAIN_0) {
48+
poweron_list = &poweron_active_list;
49+
} else {
50+
return;
51+
}
52+
53+
K_SPINLOCK(&lock) {
54+
if (!sys_slist_find_and_remove(poweron_list, node)) {
55+
K_SPINLOCK_BREAK;
56+
}
57+
58+
if (sys_slist_len(poweron_list) > 0) {
59+
K_SPINLOCK_BREAK;
60+
}
61+
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, domain, false);
62+
}
63+
}

soc/nordic/common/soc_lrcconf.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @file nRF SoC specific helpers for lrcconf management
9+
*/
10+
11+
#ifndef ZEPHYR_SOC_NORDIC_COMMON_LRCCONF_H_
12+
#define ZEPHYR_SOC_NORDIC_COMMON_LRCCONF_H_
13+
14+
#include <hal/nrf_lrcconf.h>
15+
16+
/**
17+
* @brief Request lrcconf power domain
18+
*
19+
* @param node Pointer to the @ref sys_snode_t structure which is the ID of the
20+
* requesting module.
21+
* @param domain The mask that represents the power domain ID.
22+
*/
23+
void soc_lrcconf_poweron_request(sys_snode_t *node, nrf_lrcconf_power_domain_mask_t domain);
24+
25+
/**
26+
* @brief Release lrcconf power domain
27+
*
28+
* @param node Pointer to the @ref sys_snode_t structure which is the ID of the
29+
* requesting module.
30+
* @param domain The mask that represents the power domain ID.
31+
*/
32+
void soc_lrcconf_poweron_release(sys_snode_t *node, nrf_lrcconf_power_domain_mask_t domain);
33+
34+
#endif /* ZEPHYR_SOC_NORDIC_COMMON_LRCCONF_H_ */

soc/nordic/nrf54h/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ config SOC_NRF54H20_CPUAPP
2828
select NRFS_HAS_VBUS_DETECTOR_SERVICE
2929
select HAS_PM
3030
select HAS_POWEROFF
31+
select ARM_ON_ENTER_CPU_IDLE_HOOK if PM || POWEROFF
3132

3233
config SOC_NRF54H20_CPURAD
3334
select ARM

soc/nordic/nrf54h/power.c

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@
99
#include <zephyr/pm/policy.h>
1010
#include <zephyr/arch/common/pm_s2ram.h>
1111
#include <hal/nrf_resetinfo.h>
12-
#include <hal/nrf_lrcconf.h>
1312
#include <hal/nrf_memconf.h>
1413
#include <zephyr/cache.h>
1514
#include <power.h>
15+
#include <soc_lrcconf.h>
1616
#include "pm_s2ram.h"
1717

18+
#if !defined(CONFIG_SOC_NRF54H20_CPURAD)
19+
static sys_snode_t pm_node;
20+
#endif
21+
1822
static void suspend_common(void)
1923
{
2024

@@ -31,21 +35,21 @@ static void suspend_common(void)
3135
RAMBLOCK_CONTROL_BIT_ICACHE, false);
3236
}
3337

38+
#if !defined(CONFIG_SOC_NRF54H20_CPURAD)
39+
soc_lrcconf_poweron_release(&pm_node, NRF_LRCCONF_POWER_DOMAIN_0);
3440
/* Disable retention */
3541
nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, false);
36-
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, false);
42+
#endif
3743
}
3844

3945
void nrf_poweroff(void)
4046
{
4147
nrf_resetinfo_resetreas_local_set(NRF_RESETINFO, 0);
4248
nrf_resetinfo_restore_valid_set(NRF_RESETINFO, false);
4349

50+
#if !defined(CONFIG_SOC_NRF54H20_CPURAD)
4451
nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, false);
45-
46-
/* TODO: Move it around k_cpu_idle() implementation. */
47-
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, false);
48-
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, false);
52+
#endif
4953

5054
suspend_common();
5155

@@ -59,7 +63,7 @@ void nrf_poweroff(void)
5963
CODE_UNREACHABLE;
6064
}
6165

62-
#if IS_ENABLED(CONFIG_PM_S2RAM)
66+
#if defined(CONFIG_PM_S2RAM)
6367
/* Resume domain after local suspend to RAM. */
6468
static void sys_resume(void)
6569
{
@@ -77,12 +81,10 @@ static void sys_resume(void)
7781
sys_cache_data_enable();
7882
}
7983

84+
#if !defined(CONFIG_SOC_NRF54H20_CPURAD)
8085
/* Re-enable domain retention. */
8186
nrf_lrcconf_retain_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, true);
82-
83-
/* TODO: Move it around k_cpu_idle() implementation. */
84-
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN,
85-
!IS_ENABLED(CONFIG_SOC_NRF54H20_CPURAD));
87+
#endif
8688
}
8789

8890
/* Function called during local domain suspend to RAM. */
@@ -94,8 +96,6 @@ static int sys_suspend_to_ram(void)
9496
nrf_resetinfo_resetreas_local_set(NRF_RESETINFO,
9597
NRF_RESETINFO_RESETREAS_LOCAL_UNRETAINED_MASK);
9698
nrf_resetinfo_restore_valid_set(NRF_RESETINFO, true);
97-
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_DOMAIN_0, false);
98-
nrf_lrcconf_poweron_force_set(NRF_LRCCONF010, NRF_LRCCONF_POWER_MAIN, false);
9999

100100
suspend_common();
101101

@@ -126,20 +126,32 @@ static void do_suspend_to_ram(void)
126126

127127
sys_resume();
128128
}
129-
#endif /* IS_ENABLED(CONFIG_PM_S2RAM) */
129+
#endif /* defined(CONFIG_PM_S2RAM) */
130130

131131
void pm_state_set(enum pm_state state, uint8_t substate_id)
132132
{
133133
if (state != PM_STATE_SUSPEND_TO_RAM) {
134134
k_cpu_idle();
135135
return;
136136
}
137-
#if IS_ENABLED(CONFIG_PM_S2RAM)
137+
#if defined(CONFIG_PM_S2RAM)
138138
do_suspend_to_ram();
139139
#endif
140140
}
141141

142142
void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id)
143143
{
144+
#if !defined(CONFIG_SOC_NRF54H20_CPURAD)
145+
if (state == PM_STATE_SUSPEND_TO_IDLE) {
146+
soc_lrcconf_poweron_release(&pm_node, NRF_LRCCONF_POWER_DOMAIN_0);
147+
}
148+
#endif
144149
irq_unlock(0);
145150
}
151+
152+
#if !defined(CONFIG_SOC_NRF54H20_CPURAD)
153+
void pm_state_enter_idle_prepare(void)
154+
{
155+
soc_lrcconf_poweron_request(&pm_node, NRF_LRCCONF_POWER_DOMAIN_0);
156+
}
157+
#endif

soc/nordic/nrf54h/power.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,20 @@
1010
#ifndef _ZEPHYR_SOC_ARM_NORDIC_NRF_POWER_H_
1111
#define _ZEPHYR_SOC_ARM_NORDIC_NRF_POWER_H_
1212

13+
#include <zephyr/sys/slist.h>
14+
1315
/**
1416
* @brief Perform a power off.
1517
*
1618
* This function performs a power off of the core.
1719
*/
1820
void nrf_poweroff(void);
1921

22+
/**
23+
* @brief Prepare to the idle state.
24+
*
25+
* This function applies the required PM configuration before entering the idle state.
26+
*/
27+
void pm_state_enter_idle_prepare(void);
28+
2029
#endif /* _ZEPHYR_SOC_ARM_NORDIC_NRF_POWER_H_ */

0 commit comments

Comments
 (0)