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
1519LOG_MODULE_REGISTER (mpsl_pm_utils , CONFIG_MPSL_LOG_LEVEL );
@@ -28,6 +32,19 @@ static uint32_t m_prev_lat_value_us;
2832static struct pm_policy_latency_request m_latency_req ;
2933static 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
3249static 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+
104204void mpsl_pm_utils_work_handler (void )
105205{
106206 m_register_event ();
0 commit comments