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