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