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"
@@ -48,14 +50,35 @@ LOG_MODULE_REGISTER(bt_driver);
48
50
#define EVT_VENDOR_CODE_LSB 3
49
51
#define EVT_VENDOR_CODE_MSB 4
50
52
53
+ #if (defined(CONFIG_SOC_STM32WB06XX ) || defined(CONFIG_SOC_STM32WB07XX )) && defined(CONFIG_PM )
54
+ #error "PM is not supported yet for WB06/WB07"
55
+ #endif /* (CONFIG_SOC_STM32WB06XX || CONFIG_SOC_STM32WB07XX) && CONFIG_PM */
56
+
51
57
static uint32_t __noinit dyn_alloc_a [BLE_DYN_ALLOC_SIZE >> 2 ];
52
58
static uint8_t buffer_out_mem [MAX_EVENT_SIZE ];
53
59
static struct k_work_delayable ble_stack_work ;
54
60
61
+ #if defined(CONFIG_PM_DEVICE )
62
+ /* ST Proprietary extended event */
63
+ #define STM32_HCI_EXT_EVT 0x82
64
+ #define ACI_HAL_END_OF_RADIO_ACTIVITY_VSEVT_CODE 0x0004
65
+ #define STM32_STATE_ALL_BITMASK 0xFFFF
66
+ #define STM32_STATE_IDLE 0x00
67
+
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
+
55
78
static struct net_buf * get_rx (uint8_t * msg );
56
79
static PKA_HandleTypeDef hpka ;
57
80
58
- #if CONFIG_BT_EXT_ADV
81
+ #if defined( CONFIG_BT_EXT_ADV )
59
82
static uint32_t __noinit aci_adv_nwk_buffer [CFG_BLE_ADV_NWK_BUFFER_SIZE >> 2 ];
60
83
#endif /* CONFIG_BT_EXT_ADV */
61
84
@@ -69,11 +92,38 @@ int BLEPLAT_NvmGet(void)
69
92
return 0 ;
70
93
}
71
94
95
+ /* Inform Zephyr PM about wakeup event from radio */
96
+ static void register_radio_event (uint32_t time , bool unregister )
97
+ {
98
+ int64_t value_ms , ticks ;
99
+ static struct pm_policy_event radio_evt ;
100
+ static bool first_time = true;
101
+
102
+ if (unregister ) {
103
+ if (!first_time ) {
104
+ first_time = true;
105
+ pm_policy_event_unregister (& radio_evt );
106
+ }
107
+ } else {
108
+ value_ms = HAL_RADIO_TIMER_DiffSysTimeMs (time , HAL_RADIO_TIMER_GetCurrentSysTime ());
109
+ ticks = k_ms_to_ticks_floor64 (value_ms ) + k_uptime_ticks ();
110
+ if (first_time ) {
111
+ pm_policy_event_register (& radio_evt , ticks );
112
+ first_time = false;
113
+ } else {
114
+ pm_policy_event_update (& radio_evt , ticks );
115
+ }
116
+ }
117
+ }
118
+
72
119
uint8_t BLEPLAT_SetRadioTimerValue (uint32_t Time , uint8_t EventType , uint8_t CalReq )
73
120
{
74
121
uint8_t retval ;
75
122
76
123
retval = HAL_RADIO_TIMER_SetRadioTimerValue (Time , EventType , CalReq );
124
+ if (IS_ENABLED (CONFIG_PM_DEVICE )) {
125
+ register_radio_event (Time , false);
126
+ }
77
127
return retval ;
78
128
}
79
129
@@ -191,9 +241,22 @@ void send_event(uint8_t *buffer_out, uint16_t buffer_out_length, int8_t overflow
191
241
192
242
const struct device * dev = DEVICE_DT_GET (DT_DRV_INST (0 ));
193
243
struct hci_data * hci = dev -> data ;
194
- /* Construct net_buf from event data */
195
- struct net_buf * buf = get_rx (buffer_out );
244
+ struct net_buf * buf ;
245
+
246
+ #if defined(CONFIG_PM_DEVICE )
247
+ struct bt_hci_ext_evt_hdr * vs_evt = (struct bt_hci_ext_evt_hdr * )(buffer_out );
196
248
249
+ if ((vs_evt -> type == STM32_HCI_EXT_EVT ) && (vs_evt -> evt == BT_HCI_EVT_VENDOR )) {
250
+ if ((vs_evt -> vs_code == ACI_HAL_END_OF_RADIO_ACTIVITY_VSEVT_CODE ) &&
251
+ (vs_evt -> next_state == STM32_STATE_IDLE )) {
252
+ register_radio_event (0 , true);
253
+ }
254
+ return ;
255
+ }
256
+ #endif /* CONFIG_PM_DEVICE */
257
+
258
+ /* Construct net_buf from event data */
259
+ buf = get_rx (buffer_out );
197
260
if (buf ) {
198
261
/* Handle the received HCI data */
199
262
LOG_DBG ("New event %p len %u type %u" , buf , buf -> len , buf -> data [0 ]);
@@ -249,6 +312,35 @@ static void ble_isr_installer(void)
249
312
IRQ_CONNECT (PKA_IRQn , PKA_PRIO , _PKA_IRQHandler , NULL , PKA_FLAGS );
250
313
}
251
314
315
+ #if defined(CONFIG_PM_DEVICE )
316
+ static int ble_pm_action (const struct device * dev ,
317
+ enum pm_device_action action )
318
+ {
319
+ static uint32_t pka_cr_vr ;
320
+
321
+ switch (action ) {
322
+ case PM_DEVICE_ACTION_SUSPEND :
323
+ LL_PWR_EnableWU_EWBLE ();
324
+ pka_cr_vr = PKA -> CR ;
325
+ /* TBD: Manage PKA save for WB06 & WB07 */
326
+ break ;
327
+ case PM_DEVICE_ACTION_RESUME :
328
+ LL_PWR_DisableWU_EWBLE ();
329
+ /* TBD: Manage PKA restore for WB06 & WB07 */
330
+ PKA -> CLRFR = PKA_CLRFR_PROCENDFC | PKA_CLRFR_RAMERRFC | PKA_CLRFR_ADDRERRFC ;
331
+ PKA -> CR = pka_cr_vr ;
332
+ irq_enable (RADIO_TXRX_IRQn );
333
+ irq_enable (RADIO_TXRX_SEQ_IRQn );
334
+ irq_enable (PKA_IRQn );
335
+ break ;
336
+ default :
337
+ return - ENOTSUP ;
338
+ }
339
+
340
+ return 0 ;
341
+ }
342
+ #endif /* CONFIG_PM_DEVICE */
343
+
252
344
static void rng_get_random (void * num , size_t size )
253
345
{
254
346
const struct device * dev = DEVICE_DT_GET (DT_DRV_INST (0 ));
@@ -442,12 +534,14 @@ static int bt_hci_stm32wb0_open(const struct device *dev, bt_hci_recv_t recv)
442
534
return - EIO ;
443
535
}
444
536
445
- #if CONFIG_BT_EXT_ADV
537
+ #if defined( CONFIG_BT_EXT_ADV )
446
538
dm_init (CFG_BLE_ADV_NWK_BUFFER_SIZE , aci_adv_nwk_buffer );
447
539
#endif /* CONFIG_BT_EXT_ADV */
448
540
449
541
aci_adv_nwk_init ();
450
-
542
+ #if defined(CONFIG_PM_DEVICE )
543
+ aci_hal_set_radio_activity_mask (STM32_STATE_ALL_BITMASK );
544
+ #endif /* CONFIG_PM_DEVICE */
451
545
data -> recv = recv ;
452
546
k_work_init_delayable (& ble_stack_work , blestack_process );
453
547
k_work_schedule (& ble_stack_work , K_NO_WAIT );
@@ -461,9 +555,10 @@ static DEVICE_API(bt_hci, drv) = {
461
555
};
462
556
463
557
#define HCI_DEVICE_INIT (inst ) \
558
+ PM_DEVICE_DT_INST_DEFINE(inst, ble_pm_action); \
464
559
static struct hci_data hci_data_##inst = { \
465
560
}; \
466
- DEVICE_DT_INST_DEFINE(inst, NULL, NULL , &hci_data_##inst, NULL, \
561
+ DEVICE_DT_INST_DEFINE(inst, NULL, PM_DEVICE_DT_INST_GET(inst) , &hci_data_##inst, NULL, \
467
562
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv)
468
563
469
564
/* Only one instance supported */
0 commit comments