1 /* ipm_stm32wb.c - HCI driver for stm32wb shared ram */
2
3 /*
4 * Copyright (c) 2019-2022 Linaro Ltd.
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #define DT_DRV_COMPAT st_stm32wb_rf
10
11 #include <zephyr/init.h>
12 #include <zephyr/sys/util.h>
13 #include <zephyr/bluetooth/hci.h>
14 #include <zephyr/drivers/bluetooth/hci_driver.h>
15 #include <zephyr/bluetooth/addr.h>
16 #include <zephyr/drivers/clock_control/stm32_clock_control.h>
17 #include <zephyr/irq.h>
18
19 #include "app_conf.h"
20 #include "stm32_wpan_common.h"
21 #include "shci.h"
22 #include "shci_tl.h"
23
24 static const struct stm32_pclken clk_cfg[] = STM32_DT_CLOCKS(DT_NODELABEL(ble_rf));
25
26 #define POOL_SIZE (CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * \
27 DIVC((sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE), 4))
28
29 /* Private variables ---------------------------------------------------------*/
30 PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static TL_CmdPacket_t BleCmdBuffer;
31 PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t EvtPool[POOL_SIZE];
32 PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t SystemCmdBuffer;
33 PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t
34 SystemSpareEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255];
35 PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t
36 BleSpareEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255];
37 PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t
38 HciAclDataBuffer[sizeof(TL_PacketHeader_t) + 5 + 251];
39
40 static void syscmd_status_not(SHCI_TL_CmdStatus_t status);
41 static void sysevt_received(void *pdata);
42
43 #include "common/bt_str.h"
44
45 #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL
46 #include <zephyr/logging/log.h>
47 LOG_MODULE_REGISTER(hci_ipm);
48
49 #define HCI_CMD 0x01
50 #define HCI_ACL 0x02
51 #define HCI_SCO 0x03
52 #define HCI_EVT 0x04
53
54 #define STM32WB_C2_LOCK_TIMEOUT K_MSEC(500)
55
56 static K_SEM_DEFINE(c2_started, 0, 1);
57 static K_SEM_DEFINE(ble_sys_wait_cmd_rsp, 0, 1);
58 static K_SEM_DEFINE(acl_data_ack, 1, 1);
59 static K_SEM_DEFINE(ipm_busy, 1, 1);
60
61 struct aci_set_tx_power {
62 uint8_t cmd;
63 uint8_t value[2];
64 };
65
66 struct aci_set_ble_addr {
67 uint8_t config_offset;
68 uint8_t length;
69 uint8_t value[6];
70 } __packed;
71
72 #ifdef CONFIG_BT_HCI_HOST
73 #define ACI_WRITE_SET_TX_POWER_LEVEL BT_OP(BT_OGF_VS, 0xFC0F)
74 #define ACI_HAL_WRITE_CONFIG_DATA BT_OP(BT_OGF_VS, 0xFC0C)
75 #define ACI_HAL_STACK_RESET BT_OP(BT_OGF_VS, 0xFC3B)
76
77 #define HCI_CONFIG_DATA_PUBADDR_OFFSET 0
78 static bt_addr_t bd_addr_udn;
79 #endif /* CONFIG_BT_HCI_HOST */
80
81 /* Rx thread definitions */
82 K_FIFO_DEFINE(ipm_rx_events_fifo);
83 static K_KERNEL_STACK_DEFINE(ipm_rx_stack, CONFIG_BT_DRV_RX_STACK_SIZE);
84 static struct k_thread ipm_rx_thread_data;
85
86 static bool c2_started_flag;
87
stm32wb_start_ble(uint32_t rf_clock)88 static void stm32wb_start_ble(uint32_t rf_clock)
89 {
90 SHCI_C2_Ble_Init_Cmd_Packet_t ble_init_cmd_packet = {
91 { { 0, 0, 0 } }, /**< Header unused */
92 { 0, /** pBleBufferAddress not used */
93 0, /** BleBufferSize not used */
94 CFG_BLE_NUM_GATT_ATTRIBUTES,
95 CFG_BLE_NUM_GATT_SERVICES,
96 CFG_BLE_ATT_VALUE_ARRAY_SIZE,
97 CFG_BLE_NUM_LINK,
98 CFG_BLE_DATA_LENGTH_EXTENSION,
99 CFG_BLE_PREPARE_WRITE_LIST_SIZE,
100 CFG_BLE_MBLOCK_COUNT,
101 CFG_BLE_MAX_ATT_MTU,
102 CFG_BLE_PERIPHERAL_SCA,
103 CFG_BLE_CENTRAL_SCA,
104 (rf_clock == STM32_SRC_LSE) ? CFG_BLE_LS_SOURCE : 0,
105 CFG_BLE_MAX_CONN_EVENT_LENGTH,
106 CFG_BLE_HSE_STARTUP_TIME,
107 CFG_BLE_VITERBI_MODE,
108 CFG_BLE_OPTIONS,
109 0 }
110 };
111
112 /**
113 * Starts the BLE Stack on CPU2
114 */
115 SHCI_C2_BLE_Init(&ble_init_cmd_packet);
116 }
117
sysevt_received(void * pdata)118 static void sysevt_received(void *pdata)
119 {
120 k_sem_give(&c2_started);
121 }
122
syscmd_status_not(SHCI_TL_CmdStatus_t status)123 static void syscmd_status_not(SHCI_TL_CmdStatus_t status)
124 {
125 LOG_DBG("status:%d", status);
126 }
127
128 /*
129 * https://github.com/zephyrproject-rtos/zephyr/issues/19509
130 * Tested on nucleo_wb55rg (stm32wb55rg) BLE stack (v1.2.0)
131 * Unresolved Resolvable Private Addresses (RPA)
132 * is reported in the peer_rpa field, and not in the peer address,
133 * as it should, when this happens the peer address is set to all FFs
134 * 0A 00 01 08 01 01 FF FF FF FF FF FF 00 00 00 00 00 00 0C AA C5 B3 3D 6B ...
135 * If such message is passed to HCI core than pairing will essentially fail.
136 * Solution: Rewrite the event with the RPA in the PEER address field
137 */
tryfix_event(TL_Evt_t * tev)138 static void tryfix_event(TL_Evt_t *tev)
139 {
140 struct bt_hci_evt_le_meta_event *mev = (void *)&tev->payload;
141
142 if (tev->evtcode != BT_HCI_EVT_LE_META_EVENT ||
143 mev->subevent != BT_HCI_EVT_LE_ENH_CONN_COMPLETE) {
144 return;
145 }
146
147 struct bt_hci_evt_le_enh_conn_complete *evt =
148 (void *)((uint8_t *)mev + (sizeof(*mev)));
149
150 if (bt_addr_eq(&evt->peer_addr.a, BT_ADDR_NONE)) {
151 LOG_WRN("Invalid peer addr %s", bt_addr_le_str(&evt->peer_addr));
152 bt_addr_copy(&evt->peer_addr.a, &evt->peer_rpa);
153 evt->peer_addr.type = BT_ADDR_LE_RANDOM;
154 }
155 }
156
TM_EvtReceivedCb(TL_EvtPacket_t * hcievt)157 void TM_EvtReceivedCb(TL_EvtPacket_t *hcievt)
158 {
159 k_fifo_put(&ipm_rx_events_fifo, hcievt);
160 }
161
bt_ipm_rx_thread(void * p1,void * p2,void * p3)162 static void bt_ipm_rx_thread(void *p1, void *p2, void *p3)
163 {
164 ARG_UNUSED(p1);
165 ARG_UNUSED(p2);
166 ARG_UNUSED(p3);
167
168 while (true) {
169 bool discardable = false;
170 k_timeout_t timeout = K_FOREVER;
171 static TL_EvtPacket_t *hcievt;
172 struct net_buf *buf = NULL;
173 struct bt_hci_acl_hdr acl_hdr;
174 TL_AclDataSerial_t *acl;
175 struct bt_hci_evt_le_meta_event *mev;
176 size_t buf_tailroom;
177 size_t buf_add_len;
178
179 hcievt = k_fifo_get(&ipm_rx_events_fifo, K_FOREVER);
180
181 k_sem_take(&ipm_busy, K_FOREVER);
182
183 switch (hcievt->evtserial.type) {
184 case HCI_EVT:
185 LOG_DBG("EVT: hcievt->evtserial.evt.evtcode: 0x%02x",
186 hcievt->evtserial.evt.evtcode);
187 switch (hcievt->evtserial.evt.evtcode) {
188 case BT_HCI_EVT_VENDOR:
189 /* Vendor events are currently unsupported */
190 LOG_ERR("Unknown evtcode type 0x%02x",
191 hcievt->evtserial.evt.evtcode);
192 TL_MM_EvtDone(hcievt);
193 goto end_loop;
194 default:
195 mev = (void *)&hcievt->evtserial.evt.payload;
196 if (hcievt->evtserial.evt.evtcode == BT_HCI_EVT_LE_META_EVENT &&
197 (mev->subevent == BT_HCI_EVT_LE_ADVERTISING_REPORT)) {
198 discardable = true;
199 timeout = K_NO_WAIT;
200 }
201
202 buf = bt_buf_get_evt(
203 hcievt->evtserial.evt.evtcode,
204 discardable, timeout);
205 if (!buf) {
206 LOG_DBG("Discard adv report due to insufficient buf");
207 goto end_loop;
208 }
209 }
210
211 tryfix_event(&hcievt->evtserial.evt);
212
213 buf_tailroom = net_buf_tailroom(buf);
214 buf_add_len = hcievt->evtserial.evt.plen + 2;
215 if (buf_tailroom < buf_add_len) {
216 LOG_ERR("Not enough space in buffer %zu/%zu", buf_add_len,
217 buf_tailroom);
218 net_buf_unref(buf);
219 goto end_loop;
220 }
221
222 net_buf_add_mem(buf, &hcievt->evtserial.evt,
223 buf_add_len);
224 break;
225 case HCI_ACL:
226 acl = &(((TL_AclDataPacket_t *)hcievt)->AclDataSerial);
227 buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
228 acl_hdr.handle = acl->handle;
229 acl_hdr.len = acl->length;
230 LOG_DBG("ACL: handle %x, len %x", acl_hdr.handle, acl_hdr.len);
231 net_buf_add_mem(buf, &acl_hdr, sizeof(acl_hdr));
232
233 buf_tailroom = net_buf_tailroom(buf);
234 buf_add_len = acl_hdr.len;
235 if (buf_tailroom < buf_add_len) {
236 LOG_ERR("Not enough space in buffer %zu/%zu", buf_add_len,
237 buf_tailroom);
238 net_buf_unref(buf);
239 goto end_loop;
240 }
241
242 net_buf_add_mem(buf, (uint8_t *)&acl->acl_data,
243 buf_add_len);
244 break;
245 default:
246 LOG_ERR("Unknown BT buf type %d", hcievt->evtserial.type);
247 TL_MM_EvtDone(hcievt);
248 goto end_loop;
249 }
250
251 TL_MM_EvtDone(hcievt);
252
253 bt_recv(buf);
254 end_loop:
255 k_sem_give(&ipm_busy);
256 }
257
258 }
259
TM_AclDataAck(void)260 static void TM_AclDataAck(void)
261 {
262 k_sem_give(&acl_data_ack);
263 }
264
shci_notify_asynch_evt(void * pdata)265 void shci_notify_asynch_evt(void *pdata)
266 {
267 shci_user_evt_proc();
268 }
269
shci_cmd_resp_release(uint32_t flag)270 void shci_cmd_resp_release(uint32_t flag)
271 {
272 k_sem_give(&ble_sys_wait_cmd_rsp);
273 }
274
shci_cmd_resp_wait(uint32_t timeout)275 void shci_cmd_resp_wait(uint32_t timeout)
276 {
277 k_sem_take(&ble_sys_wait_cmd_rsp, K_MSEC(timeout));
278 }
279
ipcc_reset(void)280 void ipcc_reset(void)
281 {
282 LL_C1_IPCC_ClearFlag_CHx(
283 IPCC,
284 LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 |
285 LL_IPCC_CHANNEL_4 | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
286
287 LL_C2_IPCC_ClearFlag_CHx(
288 IPCC,
289 LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 |
290 LL_IPCC_CHANNEL_4 | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
291
292 LL_C1_IPCC_DisableTransmitChannel(
293 IPCC,
294 LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 |
295 LL_IPCC_CHANNEL_4 | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
296
297 LL_C2_IPCC_DisableTransmitChannel(
298 IPCC,
299 LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 |
300 LL_IPCC_CHANNEL_4 | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
301
302 LL_C1_IPCC_DisableReceiveChannel(
303 IPCC,
304 LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 |
305 LL_IPCC_CHANNEL_4 | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
306
307 LL_C2_IPCC_DisableReceiveChannel(
308 IPCC,
309 LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 |
310 LL_IPCC_CHANNEL_4 | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
311
312 /* Set IPCC default IRQ handlers */
313 IRQ_CONNECT(IPCC_C1_RX_IRQn, 0, HW_IPCC_Rx_Handler, NULL, 0);
314 IRQ_CONNECT(IPCC_C1_TX_IRQn, 0, HW_IPCC_Tx_Handler, NULL, 0);
315 }
316
transport_init(void)317 void transport_init(void)
318 {
319 TL_MM_Config_t tl_mm_config;
320 TL_BLE_InitConf_t tl_ble_config;
321 SHCI_TL_HciInitConf_t shci_init_config;
322
323 LOG_DBG("BleCmdBuffer: %p", (void *)&BleCmdBuffer);
324 LOG_DBG("HciAclDataBuffer: %p", (void *)&HciAclDataBuffer);
325 LOG_DBG("SystemCmdBuffer: %p", (void *)&SystemCmdBuffer);
326 LOG_DBG("EvtPool: %p", (void *)&EvtPool);
327 LOG_DBG("SystemSpareEvtBuffer: %p", (void *)&SystemSpareEvtBuffer);
328 LOG_DBG("BleSpareEvtBuffer: %p", (void *)&BleSpareEvtBuffer);
329
330 /**< Reference table initialization */
331 TL_Init();
332
333 /**< System channel initialization */
334 shci_init_config.p_cmdbuffer = (uint8_t *)&SystemCmdBuffer;
335 shci_init_config.StatusNotCallBack = syscmd_status_not;
336 shci_init(sysevt_received, (void *) &shci_init_config);
337
338 /**< Memory Manager channel initialization */
339 tl_mm_config.p_BleSpareEvtBuffer = BleSpareEvtBuffer;
340 tl_mm_config.p_SystemSpareEvtBuffer = SystemSpareEvtBuffer;
341 tl_mm_config.p_AsynchEvtPool = EvtPool;
342 tl_mm_config.AsynchEvtPoolSize = POOL_SIZE;
343 TL_MM_Init(&tl_mm_config);
344
345 /**< BLE channel initialization */
346 tl_ble_config.p_cmdbuffer = (uint8_t *)&BleCmdBuffer;
347 tl_ble_config.p_AclDataBuffer = HciAclDataBuffer;
348 tl_ble_config.IoBusEvtCallBack = TM_EvtReceivedCb;
349 tl_ble_config.IoBusAclDataTxAck = TM_AclDataAck;
350 TL_BLE_Init((void *)&tl_ble_config);
351
352 TL_Enable();
353 }
354
bt_ipm_send(struct net_buf * buf)355 static int bt_ipm_send(struct net_buf *buf)
356 {
357 TL_CmdPacket_t *ble_cmd_buff = &BleCmdBuffer;
358
359 k_sem_take(&ipm_busy, K_FOREVER);
360
361 switch (bt_buf_get_type(buf)) {
362 case BT_BUF_ACL_OUT:
363 LOG_DBG("ACL: buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
364 k_sem_take(&acl_data_ack, K_FOREVER);
365 net_buf_push_u8(buf, HCI_ACL);
366 memcpy((void *)
367 &((TL_AclDataPacket_t *)HciAclDataBuffer)->AclDataSerial,
368 buf->data, buf->len);
369 TL_BLE_SendAclData(NULL, 0);
370 break;
371 case BT_BUF_CMD:
372 LOG_DBG("CMD: buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len);
373 ble_cmd_buff->cmdserial.type = HCI_CMD;
374 ble_cmd_buff->cmdserial.cmd.plen = buf->len;
375 memcpy((void *)&ble_cmd_buff->cmdserial.cmd, buf->data,
376 buf->len);
377 TL_BLE_SendCmd(NULL, 0);
378 break;
379 default:
380 k_sem_give(&ipm_busy);
381 LOG_ERR("Unsupported type");
382 return -EINVAL;
383 }
384
385 k_sem_give(&ipm_busy);
386
387 net_buf_unref(buf);
388
389 return 0;
390 }
391
392 #ifdef CONFIG_BT_HCI_HOST
bt_get_ble_addr(void)393 bt_addr_t *bt_get_ble_addr(void)
394 {
395 bt_addr_t *bd_addr;
396 uint32_t udn;
397 uint32_t company_id;
398 uint32_t device_id;
399
400 /* Get the 64 bit Unique Device Number UID */
401 /* The UID is used by firmware to derive */
402 /* 48-bit Device Address EUI-48 */
403 udn = LL_FLASH_GetUDN();
404
405 if (udn != 0xFFFFFFFF) {
406 /* Get the ST Company ID */
407 company_id = LL_FLASH_GetSTCompanyID();
408 /* Get the STM32 Device ID */
409 device_id = LL_FLASH_GetDeviceID();
410 bd_addr_udn.val[0] = (uint8_t)(udn & 0x000000FF);
411 bd_addr_udn.val[1] = (uint8_t)((udn & 0x0000FF00) >> 8);
412 bd_addr_udn.val[2] = (uint8_t)((udn & 0x00FF0000) >> 16);
413 bd_addr_udn.val[3] = (uint8_t)device_id;
414 bd_addr_udn.val[4] = (uint8_t)(company_id & 0x000000FF);
415 bd_addr_udn.val[5] = (uint8_t)((company_id & 0x0000FF00) >> 8);
416 bd_addr = &bd_addr_udn;
417 } else {
418 bd_addr = NULL;
419 }
420
421 return bd_addr;
422 }
423
bt_ipm_set_addr(void)424 static int bt_ipm_set_addr(void)
425 {
426 bt_addr_t *uid_addr;
427 struct aci_set_ble_addr *param;
428 struct net_buf *buf, *rsp;
429 int err;
430
431 uid_addr = bt_get_ble_addr();
432 if (!uid_addr) {
433 return -ENOMSG;
434 }
435
436 buf = bt_hci_cmd_create(ACI_HAL_WRITE_CONFIG_DATA, sizeof(*param));
437
438 if (!buf) {
439 return -ENOBUFS;
440 }
441
442 param = net_buf_add(buf, sizeof(*param));
443 param->config_offset = HCI_CONFIG_DATA_PUBADDR_OFFSET;
444 param->length = 6;
445 param->value[0] = uid_addr->val[0];
446 param->value[1] = uid_addr->val[1];
447 param->value[2] = uid_addr->val[2];
448 param->value[3] = uid_addr->val[3];
449 param->value[4] = uid_addr->val[4];
450 param->value[5] = uid_addr->val[5];
451
452 err = bt_hci_cmd_send_sync(ACI_HAL_WRITE_CONFIG_DATA, buf, &rsp);
453 if (err) {
454 return err;
455 }
456 net_buf_unref(rsp);
457 return 0;
458 }
459
bt_ipm_ble_init(void)460 static int bt_ipm_ble_init(void)
461 {
462 struct aci_set_tx_power *param;
463 struct net_buf *buf, *rsp;
464 int err;
465
466 err = bt_ipm_set_addr();
467 if (err) {
468 LOG_ERR("Can't set BLE UID addr");
469 }
470 /* Send ACI_WRITE_SET_TX_POWER_LEVEL */
471 buf = bt_hci_cmd_create(ACI_WRITE_SET_TX_POWER_LEVEL, 3);
472 if (!buf) {
473 return -ENOBUFS;
474 }
475 param = net_buf_add(buf, sizeof(*param));
476 param->cmd = 0x0F;
477 param->value[0] = 0x18;
478 param->value[1] = 0x01;
479
480 err = bt_hci_cmd_send_sync(ACI_WRITE_SET_TX_POWER_LEVEL, buf, &rsp);
481 if (err) {
482 return err;
483 }
484 net_buf_unref(rsp);
485
486 return 0;
487 }
488 #endif /* CONFIG_BT_HCI_HOST */
489
c2_reset(void)490 static int c2_reset(void)
491 {
492 const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
493 int err;
494
495 if (!device_is_ready(clk)) {
496 LOG_ERR("clock control device not ready");
497 return -ENODEV;
498 }
499
500 err = clock_control_configure(clk, (clock_control_subsys_t) &clk_cfg[1],
501 NULL);
502 if (err < 0) {
503 LOG_ERR("Could not configure RF Wake up clock");
504 return err;
505 }
506
507 /* HSI48 clock and CLK48 clock source are enabled using the device tree */
508 #if !STM32_HSI48_ENABLED
509 /* Deprecated: enable HSI48 using device tree */
510 #warning Bluetooth IPM requires HSI48 clock to be enabled using device tree
511 /* Keeping this sequence for legacy: */
512 LL_RCC_HSI48_Enable();
513 while (!LL_RCC_HSI48_IsReady()) {
514 }
515
516 #endif /* !STM32_HSI48_ENABLED */
517
518 err = clock_control_on(clk, (clock_control_subsys_t) &clk_cfg[0]);
519 if (err < 0) {
520 LOG_ERR("Could not enable IPCC clock");
521 return err;
522 }
523
524 /* Take BLE out of reset */
525 ipcc_reset();
526
527 transport_init();
528
529 /* Device will let us know when it's ready */
530 if (k_sem_take(&c2_started, STM32WB_C2_LOCK_TIMEOUT)) {
531 return -ETIMEDOUT;
532 }
533 LOG_DBG("C2 unlocked");
534
535 stm32wb_start_ble(clk_cfg[1].bus);
536
537 c2_started_flag = true;
538
539 return 0;
540 }
541
bt_ipm_open(void)542 static int bt_ipm_open(void)
543 {
544 int err;
545
546 if (!c2_started_flag) {
547 /* C2 has been teared down. Reinit required */
548 SHCI_C2_Reinit();
549 while (LL_PWR_IsActiveFlag_C2DS() == 0) {
550 };
551
552 err = c2_reset();
553 if (err) {
554 return err;
555 }
556 }
557
558 /* Start RX thread */
559 k_thread_create(&ipm_rx_thread_data, ipm_rx_stack,
560 K_KERNEL_STACK_SIZEOF(ipm_rx_stack),
561 bt_ipm_rx_thread, NULL, NULL, NULL,
562 K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO),
563 0, K_NO_WAIT);
564
565 #ifdef CONFIG_BT_HCI_HOST
566 err = bt_ipm_ble_init();
567 if (err) {
568 return err;
569 }
570 #endif /* CONFIG_BT_HCI_HOST */
571
572 LOG_DBG("IPM Channel Open Completed");
573
574 return 0;
575 }
576
577 #ifdef CONFIG_BT_HCI_HOST
bt_ipm_close(void)578 static int bt_ipm_close(void)
579 {
580 int err;
581 struct net_buf *rsp;
582
583 err = bt_hci_cmd_send_sync(ACI_HAL_STACK_RESET, NULL, &rsp);
584 if (err) {
585 LOG_ERR("IPM Channel Close Issue");
586 return err;
587 }
588 net_buf_unref(rsp);
589
590 /* Wait till C2DS set */
591 while (LL_PWR_IsActiveFlag_C2DS() == 0) {
592 };
593
594 c2_started_flag = false;
595
596 k_thread_abort(&ipm_rx_thread_data);
597
598 LOG_DBG("IPM Channel Close Completed");
599
600 return err;
601 }
602 #endif /* CONFIG_BT_HCI_HOST */
603
604 static const struct bt_hci_driver drv = {
605 .name = "BT IPM",
606 .bus = BT_HCI_DRIVER_BUS_IPM,
607 .open = bt_ipm_open,
608 #ifdef CONFIG_BT_HCI_HOST
609 .close = bt_ipm_close,
610 #endif
611 .send = bt_ipm_send,
612 };
613
_bt_ipm_init(void)614 static int _bt_ipm_init(void)
615 {
616 int err;
617
618
619 bt_hci_driver_register(&drv);
620
621 err = c2_reset();
622 if (err) {
623 return err;
624 }
625
626 return 0;
627 }
628
629 SYS_INIT(_bt_ipm_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
630