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