1 /*
2  * Copyright (c) 2023 Antmicro <www.antmicro.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/drivers/bluetooth/hci_driver.h>
8 
9 #include <sl_btctrl_linklayer.h>
10 #include <sl_hci_common_transport.h>
11 #include <pa_conversions_efr32.h>
12 #include <sl_bt_ll_zephyr.h>
13 #include <rail.h>
14 
15 #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_REGISTER(bt_hci_driver_slz);
18 
19 #define SL_BT_CONFIG_ACCEPT_LIST_SIZE				1
20 #define SL_BT_CONFIG_MAX_CONNECTIONS				1
21 #define SL_BT_CONFIG_USER_ADVERTISERS				1
22 #define SL_BT_CONTROLLER_BUFFER_MEMORY				CONFIG_BT_SILABS_HCI_BUFFER_MEMORY
23 #define SL_BT_CONTROLLER_LE_BUFFER_SIZE_MAX			CONFIG_BT_BUF_ACL_TX_COUNT
24 #define SL_BT_CONTROLLER_COMPLETED_PACKETS_THRESHOLD		1
25 #define SL_BT_CONTROLLER_COMPLETED_PACKETS_EVENTS_TIMEOUT	3
26 #define SL_BT_SILABS_LL_STACK_SIZE				1024
27 
28 static K_KERNEL_STACK_DEFINE(slz_ll_stack, SL_BT_SILABS_LL_STACK_SIZE);
29 static struct k_thread slz_ll_thread;
30 
rail_isr_installer(void)31 void rail_isr_installer(void)
32 {
33 #ifdef CONFIG_SOC_SERIES_EFR32MG24
34 	IRQ_CONNECT(SYNTH_IRQn, 0, SYNTH_IRQHandler, NULL, 0);
35 #else
36 	IRQ_CONNECT(RDMAILBOX_IRQn, 0, RDMAILBOX_IRQHandler, NULL, 0);
37 #endif
38 	IRQ_CONNECT(RAC_SEQ_IRQn, 0, RAC_SEQ_IRQHandler, NULL, 0);
39 	IRQ_CONNECT(RAC_RSM_IRQn, 0, RAC_RSM_IRQHandler, NULL, 0);
40 	IRQ_CONNECT(PROTIMER_IRQn, 0, PROTIMER_IRQHandler, NULL, 0);
41 	IRQ_CONNECT(MODEM_IRQn, 0, MODEM_IRQHandler, NULL, 0);
42 	IRQ_CONNECT(FRC_IRQn, 0, FRC_IRQHandler, NULL, 0);
43 	IRQ_CONNECT(BUFC_IRQn, 0, BUFC_IRQHandler, NULL, 0);
44 	IRQ_CONNECT(AGC_IRQn, 0, AGC_IRQHandler, NULL, 0);
45 }
46 
47 /**
48  * @brief Transmit HCI message using the currently used transport layer.
49  * The HCI calls this function to transmit a full HCI message.
50  * @param[in] data Packet type followed by HCI packet data.
51  * @param[in] len Length of the `data` parameter
52  * @return 0 - on success, or non-zero on failure.
53  */
hci_common_transport_transmit(uint8_t * data,int16_t len)54 uint32_t hci_common_transport_transmit(uint8_t *data, int16_t len)
55 {
56 	struct net_buf *buf;
57 	uint8_t packet_type = data[0];
58 	uint8_t flags;
59 	uint8_t event_code;
60 
61 	LOG_HEXDUMP_DBG(data, len, "host packet data:");
62 
63 	/* drop packet type from the frame buffer - it is no longer needed */
64 	data = &data[1];
65 	len -= 1;
66 
67 	switch (packet_type) {
68 	case h4_event:
69 		event_code = data[0];
70 		flags = bt_hci_evt_get_flags(event_code);
71 		buf = bt_buf_get_evt(event_code, false, K_FOREVER);
72 		break;
73 	case h4_acl:
74 		buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_FOREVER);
75 		break;
76 	default:
77 		LOG_ERR("Unknown HCI type: %d", packet_type);
78 		return -EINVAL;
79 	}
80 
81 	net_buf_add_mem(buf, data, len);
82 	if (IS_ENABLED(CONFIG_BT_RECV_BLOCKING) &&
83 	    (packet_type == h4_event) && (flags & BT_HCI_EVT_FLAG_RECV_PRIO)) {
84 		bt_recv_prio(buf);
85 	} else {
86 		bt_recv(buf);
87 	}
88 
89 	sl_btctrl_hci_transmit_complete(0);
90 
91 	return 0;
92 }
93 
slz_bt_send(struct net_buf * buf)94 static int slz_bt_send(struct net_buf *buf)
95 {
96 	int rv = 0;
97 
98 	switch (bt_buf_get_type(buf)) {
99 	case BT_BUF_ACL_OUT:
100 		net_buf_push_u8(buf, h4_acl);
101 		break;
102 	case BT_BUF_CMD:
103 		net_buf_push_u8(buf, h4_command);
104 		break;
105 	default:
106 		rv = -EINVAL;
107 		goto done;
108 	}
109 
110 	rv = hci_common_transport_receive(buf->data, buf->len, true);
111 	if (!rv) {
112 		goto done;
113 	}
114 
115 done:
116 	net_buf_unref(buf);
117 	return rv;
118 }
119 
slz_bt_open(void)120 static int slz_bt_open(void)
121 {
122 	int ret;
123 
124 	/* Start RX thread */
125 	k_thread_create(&slz_ll_thread, slz_ll_stack,
126 			K_KERNEL_STACK_SIZEOF(slz_ll_stack),
127 			(k_thread_entry_t)slz_ll_thread_func, NULL, NULL, NULL,
128 			K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0,
129 			K_NO_WAIT);
130 
131 	rail_isr_installer();
132 	sl_rail_util_pa_init();
133 
134 	/* sl_btctrl_init_mem returns the number of memory buffers allocated */
135 	ret = sl_btctrl_init_mem(SL_BT_CONTROLLER_BUFFER_MEMORY);
136 	if (!ret) {
137 		LOG_ERR("Failed to allocate memory %d", ret);
138 		return -ENOMEM;
139 	}
140 
141 	sl_btctrl_configure_le_buffer_size(SL_BT_CONTROLLER_LE_BUFFER_SIZE_MAX);
142 
143 	ret = sl_btctrl_init_ll();
144 	if (ret) {
145 		LOG_ERR("Bluetooth link layer init failed %d", ret);
146 		goto deinit;
147 	}
148 
149 	sl_btctrl_init_adv();
150 	sl_btctrl_init_scan();
151 	sl_btctrl_init_conn();
152 	sl_btctrl_init_adv_ext();
153 	sl_btctrl_init_scan_ext();
154 
155 	ret = sl_btctrl_init_basic(SL_BT_CONFIG_MAX_CONNECTIONS,
156 			SL_BT_CONFIG_USER_ADVERTISERS,
157 			SL_BT_CONFIG_ACCEPT_LIST_SIZE);
158 	if (ret) {
159 		LOG_ERR("Failed to initialize the controller %d", ret);
160 		goto deinit;
161 	}
162 
163 	sl_btctrl_configure_completed_packets_reporting(
164 		SL_BT_CONTROLLER_COMPLETED_PACKETS_THRESHOLD,
165 		SL_BT_CONTROLLER_COMPLETED_PACKETS_EVENTS_TIMEOUT);
166 
167 	sl_bthci_init_upper();
168 	sl_btctrl_hci_parser_init_default();
169 	sl_btctrl_hci_parser_init_conn();
170 	sl_btctrl_hci_parser_init_adv();
171 	sl_btctrl_hci_parser_init_phy();
172 
173 #ifdef CONFIG_PM
174 	{
175 		RAIL_Status_t status = RAIL_InitPowerManager();
176 
177 		if (status != RAIL_STATUS_NO_ERROR) {
178 			LOG_ERR("RAIL: failed to initialize power management, status=%d",
179 					status);
180 			ret = -EIO;
181 			goto deinit;
182 		}
183 	}
184 #endif
185 
186 	LOG_DBG("SiLabs BT HCI started");
187 
188 	return 0;
189 deinit:
190 	sli_btctrl_deinit_mem();
191 	return ret;
192 }
193 
194 static const struct bt_hci_driver drv = {
195 	.name           = "sl:bt",
196 	.bus            = BT_HCI_DRIVER_BUS_UART,
197 	.open           = slz_bt_open,
198 	.send           = slz_bt_send,
199 	.quirks         = BT_QUIRK_NO_RESET
200 };
201 
slz_bt_init(void)202 static int slz_bt_init(void)
203 {
204 	int ret;
205 
206 	ret = bt_hci_driver_register(&drv);
207 	if (ret) {
208 		LOG_ERR("Failed to register SiLabs BT HCI %d", ret);
209 	}
210 
211 	return ret;
212 }
213 
214 SYS_INIT(slz_bt_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
215