Skip to content

Commit 42cd2d1

Browse files
ppryga-nordicnordicjm
authored andcommitted
mpsl: pm: Add MRAM low latency request and response handling
There is no MRAM latency service integrated in Zephyrs PM for nRF54h20. To make sure the radio protocols doesn't suffer from long instructions fetch from MRAM, which by default is in auto-power-down mode, we must request MRAM to be always-on for duration of REM events. The commit integrates use of MRAM latency service with MPLS PM to handle described use case. Signed-off-by: Piotr Pryga <[email protected]>
1 parent 73a2c95 commit 42cd2d1

File tree

3 files changed

+118
-4
lines changed

3 files changed

+118
-4
lines changed

subsys/bluetooth/controller/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ config BT_LL_SOFTDEVICE
4242
select BT_CTLR_LE_PATH_LOSS_MONITORING_SUPPORT
4343
select BT_CTLR_SUBRATING_SUPPORT
4444
select BT_LL_SOFTDEVICE_HEADERS_INCLUDE
45-
select MRAM_LATENCY if SOC_NRF54H20_CPURAD
46-
select MRAM_LATENCY_AUTO_REQ if SOC_NRF54H20_CPURAD
45+
select MRAM_LATENCY if (SOC_NRF54H20_CPURAD && !MPSL_PM_USE_MRAM_LATENCY_SERVICE)
46+
select MRAM_LATENCY_AUTO_REQ if (SOC_NRF54H20_CPURAD && !MPSL_PM_USE_MRAM_LATENCY_SERVICE)
4747
depends on (SOC_SERIES_BSIM_NRFXX || SOC_SERIES_NRF52X || SOC_COMPATIBLE_NRF5340_CPUNET ||\
4848
SOC_NRF54H20_CPURAD || SOC_SERIES_NRF54LX)
4949
depends on DT_HAS_NORDIC_BT_HCI_SDC_ENABLED

subsys/mpsl/pm/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,17 @@ config MPSL_USE_ZEPHYR_PM
1111
depends on PM
1212
help
1313
This option configures MPSL to use Zephyr's Power Management.
14+
15+
if MPSL_USE_ZEPHYR_PM
16+
17+
config MPSL_PM_USE_MRAM_LATENCY_SERVICE
18+
bool "Use Zephyr's MRAM latency service"
19+
select MRAM_LATENCY
20+
default y
21+
help
22+
This option enables MPSL PM integration with MRAM latency service.
23+
Use of MRAM latency service ensures there is no latency due to code
24+
fetching from disabled MRAM in REM events. It decreases power consumption
25+
on nRF54H20 SoC.
26+
27+
endif # MPSL_USE_ZEPHYR_PM

subsys/mpsl/pm/mpsl_pm_utils.c

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
#include <zephyr/pm/policy.h>
1111
#include <zephyr/logging/log.h>
1212

13+
#if defined(MPSL_PM_USE_MRAM_LATENCY_SERVICE)
14+
#include <mram_latency.h>
15+
#endif /* MPSL_PM_USE_MRAM_LATENCY_SERVICE */
16+
1317
#include <mpsl/mpsl_pm_utils.h>
1418

1519
LOG_MODULE_REGISTER(mpsl_pm_utils, CONFIG_MPSL_LOG_LEVEL);
@@ -28,6 +32,19 @@ static uint32_t m_prev_lat_value_us;
2832
static struct pm_policy_latency_request m_latency_req;
2933
static struct pm_policy_event m_evt;
3034

35+
#if defined(MPSL_PM_USE_MRAM_LATENCY_SERVICE)
36+
#define LOW_LATENCY_ATOMIC_BITS_NUM 2
37+
#define LOW_LATENCY_PM_BIT 0
38+
#define LOW_LATENCY_MRAM_BIT 0
39+
#define LOW_LATENCY_BITS_MASK 0x3
40+
41+
static ATOMIC_DEFINE(m_low_latency_req_state, LOW_LATENCY_ATOMIC_BITS_NUM);
42+
/* Variable must be global to use it in on-off service cancel or release API */
43+
struct onoff_client m_mram_req_cli;
44+
45+
static void m_mram_low_latency_request(void);
46+
static void m_mram_low_latency_release(void);
47+
#endif /* MPSL_PM_USE_MRAM_LATENCY_SERVICE */
3148

3249
static void m_update_latency_request(uint32_t lat_value_us)
3350
{
@@ -37,7 +54,7 @@ static void m_update_latency_request(uint32_t lat_value_us)
3754
}
3855
}
3956

40-
void m_register_event(void)
57+
static void m_register_event(void)
4158
{
4259
mpsl_pm_params_t params = {0};
4360
bool pm_param_valid = mpsl_pm_params_get(&params);
@@ -85,14 +102,42 @@ static void m_register_latency(void)
85102
case MPSL_PM_LOW_LATENCY_STATE_OFF:
86103
if (mpsl_pm_low_latency_requested()) {
87104
mpsl_pm_low_latency_state_set(MPSL_PM_LOW_LATENCY_STATE_REQUESTING);
105+
106+
#if defined(MPSL_PM_USE_MRAM_LATENCY_SERVICE)
107+
/* Request MRAM latency first because the call goes to system controller */
108+
m_mram_low_latency_request();
109+
#endif /* MPSL_PM_USE_MRAM_LATENCY_SERVICE */
110+
88111
m_update_latency_request(0);
89-
mpsl_pm_low_latency_state_set(MPSL_PM_LOW_LATENCY_STATE_ON);
112+
#if defined(MPSL_PM_USE_MRAM_LATENCY_SERVICE)
113+
atomic_set_bit(m_low_latency_req_state, LOW_LATENCY_PM_BIT);
114+
115+
/* Attempt to notify MPLS about change. Most likely it will happen later
116+
* when MRAM low latency request is handled.
117+
*/
118+
if (atomic_test_bit(m_low_latency_req_state, LOW_LATENCY_MRAM_BIT)) {
119+
#else
120+
if (true) {
121+
#endif /* MPSL_PM_USE_MRAM_LATENCY_SERVICE*/
122+
mpsl_pm_low_latency_state_set(MPSL_PM_LOW_LATENCY_STATE_ON);
123+
}
90124
}
91125
break;
92126
case MPSL_PM_LOW_LATENCY_STATE_ON:
93127
if (!mpsl_pm_low_latency_requested()) {
94128
mpsl_pm_low_latency_state_set(MPSL_PM_LOW_LATENCY_STATE_RELEASING);
129+
130+
#if defined(MPSL_PM_USE_MRAM_LATENCY_SERVICE)
131+
m_mram_low_latency_release();
132+
#endif /* MPSL_PM_USE_MRAM_LATENCY_SERVICE */
95133
m_update_latency_request(PM_MAX_LATENCY_HCI_COMMANDS_US);
134+
#if defined(MPSL_PM_USE_MRAM_LATENCY_SERVICE)
135+
atomic_clear_bit(m_low_latency_req_state, LOW_LATENCY_PM_BIT);
136+
#endif /* MPSL_PM_USE_MRAM_LATENCY_SERVICE*/
137+
138+
/* MRAM low release is handled sunchronously, hence the MPLS notification
139+
* happens here.
140+
*/
96141
mpsl_pm_low_latency_state_set(MPSL_PM_LOW_LATENCY_STATE_OFF);
97142
}
98143
break;
@@ -101,6 +146,61 @@ static void m_register_latency(void)
101146
}
102147
}
103148

149+
#if defined(MPSL_PM_USE_MRAM_LATENCY_SERVICE)
150+
static void m_mram_request_cb(struct onoff_manager *mgr, struct onoff_client *cli, uint32_t state,
151+
int res)
152+
{
153+
if (res < 0) {
154+
/* Possible failure reasons:
155+
* # -ERRTIMEDOUT - nRFS service timeout
156+
* # -EIO - nRFS service error
157+
* # -ENXIO - request rejected
158+
* All these mean failure for MPSL.
159+
*/
160+
__ASSERT(false, "MRAM low latency request could not be handled, reason: %d", res);
161+
return;
162+
}
163+
164+
atomic_set_bit(m_low_latency_req_state, LOW_LATENCY_MRAM_BIT);
165+
166+
if ((mpsl_pm_low_latency_state_get() == MPSL_PM_LOW_LATENCY_STATE_REQUESTING) &&
167+
(atomic_test_bit(m_low_latency_req_state, LOW_LATENCY_PM_BIT))) {
168+
mpsl_pm_low_latency_state_set(MPSL_PM_LOW_LATENCY_STATE_ON);
169+
}
170+
}
171+
172+
static void m_mram_low_latency_request(void)
173+
{
174+
int err;
175+
176+
sys_notify_init_callback(&m_mram_req_cli.notify, m_mram_request_cb);
177+
178+
err = mram_no_latency_request(&m_mram_req_cli);
179+
180+
if (err < 0) {
181+
__ASSERT(false, "MPSL MRAM low latency request failed, err: %d\n", err);
182+
return;
183+
}
184+
}
185+
186+
static void m_mram_low_latency_release(void)
187+
{
188+
int err;
189+
190+
err = mram_no_latency_cancel_or_release(&m_mram_req_cli);
191+
if (err < 0) {
192+
__ASSERT(false, "MPSL MRAM low latency release failed, err: %d\n", err);
193+
return;
194+
}
195+
196+
/* The mram_no_latency_cancel_or_release() is sunchronous. There is no ansynchronous way to
197+
* release an MRAM low latency request, due for lack of such support in on-off Zephyr's
198+
* service.
199+
*/
200+
atomic_clear_bit(m_low_latency_req_state, LOW_LATENCY_MRAM_BIT);
201+
}
202+
#endif /* MPSL_PM_USE_MRAM_LATENCY_SERVICE */
203+
104204
void mpsl_pm_utils_work_handler(void)
105205
{
106206
m_register_event();

0 commit comments

Comments
 (0)