11
11
#include <zephyr/bluetooth/hci_types.h>
12
12
#include <zephyr/drivers/bluetooth.h>
13
13
#include <zephyr/drivers/entropy.h>
14
+ #include <zephyr/pm/policy.h>
15
+ #include <zephyr/pm/device.h>
14
16
#include "bleplat_cntr.h"
15
17
#include "ble_stack.h"
16
18
#include "stm32wb0x_hal_radio_timer.h"
@@ -49,10 +51,30 @@ LOG_MODULE_REGISTER(bt_driver);
49
51
#define EVT_VENDOR_CODE_LSB 3
50
52
#define EVT_VENDOR_CODE_MSB 4
51
53
54
+ #if (defined(CONFIG_SOC_STM32WB06 ) || defined(CONFIG_SOC_STM32WB07 )) && defined(CONFIG_PM )
55
+ #error "At the moment, PM is not supported for WB06 & WB07"
56
+ #endif /* (CONFIG_SOC_STM32WB06 || CONFIG_SOC_STM32WB07) && CONFIG_PM */
57
+
52
58
static uint32_t __noinit dyn_alloc_a [BLE_DYN_ALLOC_SIZE >> 2 ];
53
59
static uint8_t buffer_out_mem [MAX_EVENT_SIZE ];
54
60
static struct k_work_delayable ble_stack_work ;
55
61
62
+ #if CONFIG_PM_DEVICE
63
+ /* ST Proprietary extended event */
64
+ #define HCI_EXT_EVT 0x82
65
+ #define ACI_HAL_END_OF_RADIO_ACTIVITY_VSEVT_CODE 0x0004
66
+ #define STATE_ALL_BITMASK 0xFFFF
67
+ #define STATE_IDLE 0x00
68
+ struct bt_hci_ext_evt_hdr {
69
+ uint8_t type ;
70
+ uint8_t evt ;
71
+ uint16_t len ;
72
+ uint16_t vs_code ;
73
+ uint8_t last_state ;
74
+ uint8_t next_state ;
75
+ } __packed ;
76
+ #endif /* CONFIG_PM_DEVICE */
77
+
56
78
static struct net_buf * get_rx (uint8_t * msg );
57
79
static PKA_HandleTypeDef hpka ;
58
80
@@ -70,11 +92,40 @@ int BLEPLAT_NvmGet(void)
70
92
return 0 ;
71
93
}
72
94
95
+ #if CONFIG_PM_DEVICE
96
+ /* Inform Zephyr PM about wakeup event from radio */
97
+ static void register_radio_event (uint32_t time , bool unregister )
98
+ {
99
+ int64_t value_ms , ticks ;
100
+ static struct pm_policy_event radio_evt ;
101
+ static bool first_time = true;
102
+
103
+ if (unregister ) {
104
+ if (!first_time ) {
105
+ first_time = true;
106
+ pm_policy_event_unregister (& radio_evt );
107
+ }
108
+ } else {
109
+ value_ms = HAL_RADIO_TIMER_DiffSysTimeMs (time , HAL_RADIO_TIMER_GetCurrentSysTime ());
110
+ ticks = k_ms_to_ticks_floor64 (value_ms ) + k_uptime_ticks ();
111
+ if (first_time ) {
112
+ pm_policy_event_register (& radio_evt , ticks );
113
+ first_time = false;
114
+ } else {
115
+ pm_policy_event_update (& radio_evt , ticks );
116
+ }
117
+ }
118
+ }
119
+ #endif /* CONFIG_PM_DEVICE */
120
+
73
121
uint8_t BLEPLAT_SetRadioTimerValue (uint32_t Time , uint8_t EventType , uint8_t CalReq )
74
122
{
75
123
uint8_t retval ;
76
124
77
125
retval = HAL_RADIO_TIMER_SetRadioTimerValue (Time , EventType , CalReq );
126
+ #if CONFIG_PM_DEVICE
127
+ register_radio_event (Time , false);
128
+ #endif /* CONFIG_PM_DEVICE */
78
129
return retval ;
79
130
}
80
131
@@ -192,9 +243,24 @@ void send_event(uint8_t *buffer_out, uint16_t buffer_out_length, int8_t overflow
192
243
193
244
const struct device * dev = DEVICE_DT_GET (DT_DRV_INST (0 ));
194
245
struct hci_data * hci = dev -> data ;
195
- /* Construct net_buf from event data */
196
- struct net_buf * buf = get_rx (buffer_out );
246
+ struct net_buf * buf ;
197
247
248
+ #if CONFIG_PM_DEVICE
249
+ struct bt_hci_ext_evt_hdr * vs_evt = (struct bt_hci_ext_evt_hdr * )(buffer_out );
250
+
251
+ if (vs_evt -> type == HCI_EXT_EVT ) {
252
+ if (vs_evt -> evt == BT_HCI_EVT_VENDOR ) {
253
+ if ((vs_evt -> vs_code == ACI_HAL_END_OF_RADIO_ACTIVITY_VSEVT_CODE ) &&
254
+ (vs_evt -> next_state == STATE_IDLE )) {
255
+ register_radio_event (0 , true);
256
+ }
257
+ return ;
258
+ }
259
+ }
260
+ #endif /* CONFIG_PM_DEVICE */
261
+
262
+ /* Construct net_buf from event data */
263
+ buf = get_rx (buffer_out );
198
264
if (buf ) {
199
265
/* Handle the received HCI data */
200
266
LOG_DBG ("New event %p len %u type %u" , buf , buf -> len , buf -> data [0 ]);
@@ -250,6 +316,36 @@ static void ble_isr_installer(void)
250
316
IRQ_CONNECT (PKA_IRQn , PKA_PRIO , _PKA_IRQHandler , NULL , PKA_FLAGS );
251
317
}
252
318
319
+ #if defined(CONFIG_PM_DEVICE )
320
+ static int ble_pm_action (const struct device * dev ,
321
+ enum pm_device_action action )
322
+ {
323
+ static uint32_t PKA_CR_vr ;
324
+
325
+ switch (action ) {
326
+ case PM_DEVICE_ACTION_SUSPEND :
327
+ LL_PWR_EnableWU_EWBLE ();
328
+ PKA_CR_vr = PKA -> CR ;
329
+ /* TBD: Manage PKA save for WB06 & WB07 */
330
+ break ;
331
+ case PM_DEVICE_ACTION_RESUME :
332
+ LL_PWR_DisableWU_EWBLE ();
333
+ /* TBD: Manage PKA restore for WB06 & WB07 */
334
+ PKA -> CLRFR = PKA_CLRFR_PROCENDFC | PKA_CLRFR_RAMERRFC | PKA_CLRFR_ADDRERRFC ;
335
+ PKA -> CR = PKA_CR_vr ;
336
+ ble_isr_installer ();
337
+ irq_enable (RADIO_TXRX_IRQn );
338
+ irq_enable (RADIO_TXRX_SEQ_IRQn );
339
+ irq_enable (PKA_IRQn );
340
+ break ;
341
+ default :
342
+ return - ENOTSUP ;
343
+ }
344
+
345
+ return 0 ;
346
+ }
347
+ #endif /* CONFIG_PM_DEVICE */
348
+
253
349
static void rng_get_random (void * num , size_t size )
254
350
{
255
351
const struct device * dev = DEVICE_DT_GET (DT_DRV_INST (0 ));
@@ -449,7 +545,9 @@ static int bt_hci_stm32wb0_open(const struct device *dev, bt_hci_recv_t recv)
449
545
#endif /* CONFIG_BT_EXT_ADV */
450
546
451
547
aci_adv_nwk_init ();
452
-
548
+ #if CONFIG_PM_DEVICE
549
+ aci_hal_set_radio_activity_mask (STATE_ALL_BITMASK );
550
+ #endif /* CONFIG_PM_DEVICE */
453
551
data -> recv = recv ;
454
552
k_work_init_delayable (& ble_stack_work , blestack_process );
455
553
k_work_schedule (& ble_stack_work , K_NO_WAIT );
@@ -462,10 +560,12 @@ static DEVICE_API(bt_hci, drv) = {
462
560
.send = bt_hci_stm32wb0_send ,
463
561
};
464
562
563
+ PM_DEVICE_DT_INST_DEFINE (0 , ble_pm_action );
564
+
465
565
#define HCI_DEVICE_INIT (inst ) \
466
566
static struct hci_data hci_data_##inst = { \
467
567
}; \
468
- DEVICE_DT_INST_DEFINE(inst, NULL, NULL , &hci_data_##inst, NULL, \
568
+ DEVICE_DT_INST_DEFINE(inst, NULL, PM_DEVICE_DT_INST_GET(0) , &hci_data_##inst, NULL, \
469
569
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv)
470
570
471
571
/* Only one instance supported */
0 commit comments