Skip to content

Commit 1c30da4

Browse files
committed
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 02868b7 commit 1c30da4

File tree

1 file changed

+104
-4
lines changed

1 file changed

+104
-4
lines changed

drivers/bluetooth/hci/hci_stm32wb0.c

Lines changed: 104 additions & 4 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"
@@ -49,10 +51,30 @@ LOG_MODULE_REGISTER(bt_driver);
4951
#define EVT_VENDOR_CODE_LSB 3
5052
#define EVT_VENDOR_CODE_MSB 4
5153

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

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+
5678
static struct net_buf *get_rx(uint8_t *msg);
5779
static PKA_HandleTypeDef hpka;
5880

@@ -70,11 +92,40 @@ int BLEPLAT_NvmGet(void)
7092
return 0;
7193
}
7294

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+
73121
uint8_t BLEPLAT_SetRadioTimerValue(uint32_t Time, uint8_t EventType, uint8_t CalReq)
74122
{
75123
uint8_t retval;
76124

77125
retval = HAL_RADIO_TIMER_SetRadioTimerValue(Time, EventType, CalReq);
126+
#if CONFIG_PM_DEVICE
127+
register_radio_event(Time, false);
128+
#endif /* CONFIG_PM_DEVICE */
78129
return retval;
79130
}
80131

@@ -192,9 +243,24 @@ void send_event(uint8_t *buffer_out, uint16_t buffer_out_length, int8_t overflow
192243

193244
const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0));
194245
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;
197247

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);
198264
if (buf) {
199265
/* Handle the received HCI data */
200266
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)
250316
IRQ_CONNECT(PKA_IRQn, PKA_PRIO, _PKA_IRQHandler, NULL, PKA_FLAGS);
251317
}
252318

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+
253349
static void rng_get_random(void *num, size_t size)
254350
{
255351
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)
449545
#endif /* CONFIG_BT_EXT_ADV */
450546

451547
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 */
453551
data->recv = recv;
454552
k_work_init_delayable(&ble_stack_work, blestack_process);
455553
k_work_schedule(&ble_stack_work, K_NO_WAIT);
@@ -462,10 +560,12 @@ static DEVICE_API(bt_hci, drv) = {
462560
.send = bt_hci_stm32wb0_send,
463561
};
464562

563+
PM_DEVICE_DT_INST_DEFINE(0, ble_pm_action);
564+
465565
#define HCI_DEVICE_INIT(inst) \
466566
static struct hci_data hci_data_##inst = { \
467567
}; \
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, \
469569
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv)
470570

471571
/* Only one instance supported */

0 commit comments

Comments
 (0)