Skip to content

Commit 51fc440

Browse files
HoZHelcfriedt
authored andcommitted
drivers: bluetooth: hci: Add PM support to the STM32WB0x HCI driver
Add PM support to the STM32WB0x Bluetooth HCI driver. Implement PM event register to wake up the device for its BLE events. Signed-off-by: Ali Hozhabri <[email protected]>
1 parent e4a8b27 commit 51fc440

File tree

1 file changed

+101
-6
lines changed

1 file changed

+101
-6
lines changed

drivers/bluetooth/hci/hci_stm32wb0.c

Lines changed: 101 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include <zephyr/bluetooth/hci_types.h>
1212
#include <zephyr/drivers/bluetooth.h>
1313
#include <zephyr/drivers/entropy.h>
14+
#include <zephyr/pm/policy.h>
15+
#include <zephyr/pm/device.h>
1416
#include "bleplat_cntr.h"
1517
#include "ble_stack.h"
1618
#include "stm32wb0x_hal_radio_timer.h"
@@ -48,14 +50,35 @@ LOG_MODULE_REGISTER(bt_driver);
4850
#define EVT_VENDOR_CODE_LSB 3
4951
#define EVT_VENDOR_CODE_MSB 4
5052

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+
5157
static uint32_t __noinit dyn_alloc_a[BLE_DYN_ALLOC_SIZE >> 2];
5258
static uint8_t buffer_out_mem[MAX_EVENT_SIZE];
5359
static struct k_work_delayable ble_stack_work;
5460

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+
5578
static struct net_buf *get_rx(uint8_t *msg);
5679
static PKA_HandleTypeDef hpka;
5780

58-
#if CONFIG_BT_EXT_ADV
81+
#if defined(CONFIG_BT_EXT_ADV)
5982
static uint32_t __noinit aci_adv_nwk_buffer[CFG_BLE_ADV_NWK_BUFFER_SIZE >> 2];
6083
#endif /* CONFIG_BT_EXT_ADV */
6184

@@ -69,11 +92,38 @@ int BLEPLAT_NvmGet(void)
6992
return 0;
7093
}
7194

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+
72119
uint8_t BLEPLAT_SetRadioTimerValue(uint32_t Time, uint8_t EventType, uint8_t CalReq)
73120
{
74121
uint8_t retval;
75122

76123
retval = HAL_RADIO_TIMER_SetRadioTimerValue(Time, EventType, CalReq);
124+
if (IS_ENABLED(CONFIG_PM_DEVICE)) {
125+
register_radio_event(Time, false);
126+
}
77127
return retval;
78128
}
79129

@@ -191,9 +241,22 @@ void send_event(uint8_t *buffer_out, uint16_t buffer_out_length, int8_t overflow
191241

192242
const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0));
193243
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);
196248

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);
197260
if (buf) {
198261
/* Handle the received HCI data */
199262
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)
249312
IRQ_CONNECT(PKA_IRQn, PKA_PRIO, _PKA_IRQHandler, NULL, PKA_FLAGS);
250313
}
251314

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+
252344
static void rng_get_random(void *num, size_t size)
253345
{
254346
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)
442534
return -EIO;
443535
}
444536

445-
#if CONFIG_BT_EXT_ADV
537+
#if defined(CONFIG_BT_EXT_ADV)
446538
dm_init(CFG_BLE_ADV_NWK_BUFFER_SIZE, aci_adv_nwk_buffer);
447539
#endif /* CONFIG_BT_EXT_ADV */
448540

449541
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 */
451545
data->recv = recv;
452546
k_work_init_delayable(&ble_stack_work, blestack_process);
453547
k_work_schedule(&ble_stack_work, K_NO_WAIT);
@@ -461,9 +555,10 @@ static DEVICE_API(bt_hci, drv) = {
461555
};
462556

463557
#define HCI_DEVICE_INIT(inst) \
558+
PM_DEVICE_DT_INST_DEFINE(inst, ble_pm_action); \
464559
static struct hci_data hci_data_##inst = { \
465560
}; \
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, \
467562
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv)
468563

469564
/* Only one instance supported */

0 commit comments

Comments
 (0)