1 /*
2  * Copyright (c) 2023 Ambiq Micro Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @brief Ambiq Apollox Blue SoC extended driver for SPI based HCI.
9  */
10 
11 #define DT_DRV_COMPAT ambiq_bt_hci_spi
12 
13 #include <zephyr/init.h>
14 #include <zephyr/sys/byteorder.h>
15 #include <zephyr/drivers/gpio.h>
16 #include <zephyr/drivers/pinctrl.h>
17 #include <zephyr/drivers/bluetooth.h>
18 #include <zephyr/bluetooth/hci.h>
19 #include <zephyr/bluetooth/hci_raw.h>
20 
21 #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL
22 #include <zephyr/logging/log.h>
23 LOG_MODULE_REGISTER(bt_apollox_driver);
24 
25 #include <zephyr/drivers/clock_control.h>
26 #include <zephyr/drivers/clock_control/clock_control_ambiq.h>
27 
28 #include <am_mcu_apollo.h>
29 #include "apollox_blue.h"
30 #if (CONFIG_SOC_SERIES_APOLLO4X)
31 #include "am_devices_cooper.h"
32 #elif (CONFIG_SOC_SERIES_APOLLO3X)
33 #include "am_apollo3_bt_support.h"
34 #endif /* CONFIG_SOC_SERIES_APOLLO4X */
35 
36 #define HCI_SPI_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(ambiq_bt_hci_spi)
37 #define SPI_DEV_NODE DT_BUS(HCI_SPI_NODE)
38 #define CLK_32M_NODE DT_NODELABEL(xo32m)
39 #define CLK_32K_NODE DT_NODELABEL(xo32k)
40 
41 /* Command/response for SPI operation */
42 #define SPI_WRITE   0x80
43 #define SPI_READ    0x04
44 #define READY_BYTE0 0x68
45 #define READY_BYTE1 0xA8
46 
47 /* Maximum attempts of SPI write */
48 #define SPI_WRITE_TIMEOUT 200
49 
50 #define SPI_MAX_RX_MSG_LEN 258
51 
52 #if (CONFIG_SOC_SERIES_APOLLO4X)
53 static const struct gpio_dt_spec irq_gpio = GPIO_DT_SPEC_GET(HCI_SPI_NODE, irq_gpios);
54 static const struct gpio_dt_spec rst_gpio = GPIO_DT_SPEC_GET(HCI_SPI_NODE, reset_gpios);
55 static const struct gpio_dt_spec cs_gpio = GPIO_DT_SPEC_GET(SPI_DEV_NODE, cs_gpios);
56 static const struct gpio_dt_spec clkreq_gpio = GPIO_DT_SPEC_GET(HCI_SPI_NODE, clkreq_gpios);
57 
58 static struct gpio_callback irq_gpio_cb;
59 static struct gpio_callback clkreq_gpio_cb;
60 
61 static const struct device *clk32m_dev = DEVICE_DT_GET(CLK_32M_NODE);
62 static const struct device *clk32k_dev = DEVICE_DT_GET(CLK_32K_NODE);
63 #endif /* CONFIG_SOC_SERIES_APOLLO4X */
64 
65 extern void bt_packet_irq_isr(const struct device *unused1, struct gpio_callback *unused2,
66 			      uint32_t unused3);
67 
bt_apollo_rcv_isr_preprocess(void)68 void bt_apollo_rcv_isr_preprocess(void)
69 {
70 #if (CONFIG_SOC_SERIES_APOLLO3X)
71 	am_apollo3_bt_isr_pre();
72 #endif /* CONFIG_SOC_SERIES_APOLLO3X */
73 }
74 
75 #if (CONFIG_SOC_SERIES_APOLLO4X)
irq_pin_state(void)76 static bool irq_pin_state(void)
77 {
78 	int pin_state;
79 
80 	pin_state = gpio_pin_get_dt(&irq_gpio);
81 	LOG_DBG("IRQ Pin: %d", pin_state);
82 	return pin_state > 0;
83 }
84 
clkreq_pin_state(void)85 static bool clkreq_pin_state(void)
86 {
87 	int pin_state;
88 
89 	pin_state = gpio_pin_get_dt(&clkreq_gpio);
90 	LOG_DBG("CLKREQ Pin: %d", pin_state);
91 	return pin_state > 0;
92 }
93 
bt_clkreq_isr(const struct device * unused1,struct gpio_callback * unused2,uint32_t unused3)94 static void bt_clkreq_isr(const struct device *unused1, struct gpio_callback *unused2,
95 			  uint32_t unused3)
96 {
97 	if (clkreq_pin_state()) {
98 		/* Enable XO32MHz */
99 		clock_control_on(clk32m_dev,
100 				 (clock_control_subsys_t)CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_BLE);
101 		gpio_pin_interrupt_configure_dt(&clkreq_gpio, GPIO_INT_EDGE_FALLING);
102 	} else {
103 		/* Disable XO32MHz */
104 		clock_control_off(clk32m_dev,
105 				  (clock_control_subsys_t)CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_BLE);
106 		gpio_pin_interrupt_configure_dt(&clkreq_gpio, GPIO_INT_EDGE_RISING);
107 	}
108 }
109 
bt_apollo_controller_ready_wait(void)110 static void bt_apollo_controller_ready_wait(void)
111 {
112 	/* The CS pin is used to wake up the controller as well. If the controller is not ready
113 	 * to receive the SPI packet, need to inactivate the CS at first and reconfigure the pin
114 	 * to CS function again before next sending attempt.
115 	 */
116 	gpio_pin_configure_dt(&cs_gpio, GPIO_OUTPUT_INACTIVE);
117 	k_busy_wait(200);
118 	PINCTRL_DT_DEFINE(SPI_DEV_NODE);
119 	pinctrl_apply_state(PINCTRL_DT_DEV_CONFIG_GET(SPI_DEV_NODE), PINCTRL_STATE_DEFAULT);
120 	k_busy_wait(2000);
121 }
122 
bt_apollo_controller_reset(void)123 static void bt_apollo_controller_reset(void)
124 {
125 	/* Reset the controller*/
126 	gpio_pin_set_dt(&rst_gpio, 1);
127 
128 	/* Take controller out of reset */
129 	k_sleep(K_MSEC(10));
130 	gpio_pin_set_dt(&rst_gpio, 0);
131 
132 	/* Give the controller some time to boot */
133 	k_sleep(K_MSEC(500));
134 }
135 #endif /* CONFIG_SOC_SERIES_APOLLO4X */
136 
bt_apollo_spi_send(uint8_t * data,uint16_t len,bt_spi_transceive_fun transceive)137 int bt_apollo_spi_send(uint8_t *data, uint16_t len, bt_spi_transceive_fun transceive)
138 {
139 	int ret = -ENOTSUP;
140 
141 #if (CONFIG_SOC_SERIES_APOLLO4X)
142 	uint8_t command[1] = {SPI_WRITE};
143 	uint8_t response[2] = {0, 0};
144 	uint16_t fail_count = 0;
145 
146 	do {
147 		/* Check if the controller is ready to receive the HCI packets. */
148 		ret = transceive(command, 1, response, 2);
149 		if ((response[0] != READY_BYTE0) || (response[1] != READY_BYTE1) || ret) {
150 			bt_apollo_controller_ready_wait();
151 		} else {
152 			/* Transmit the message */
153 			ret = transceive(data, len, NULL, 0);
154 			if (ret) {
155 				LOG_ERR("SPI write error %d", ret);
156 			}
157 			break;
158 		}
159 	} while (fail_count++ < SPI_WRITE_TIMEOUT);
160 #elif (CONFIG_SOC_SERIES_APOLLO3X)
161 	ret = transceive(data, len, NULL, 0);
162 	if ((ret) && (ret != AM_HAL_BLE_STATUS_SPI_NOT_READY)) {
163 		LOG_ERR("SPI write error %d", ret);
164 	}
165 #endif /* CONFIG_SOC_SERIES_APOLLO4X */
166 
167 	return ret;
168 }
169 
bt_apollo_spi_rcv(uint8_t * data,uint16_t * len,bt_spi_transceive_fun transceive)170 int bt_apollo_spi_rcv(uint8_t *data, uint16_t *len, bt_spi_transceive_fun transceive)
171 {
172 	int ret = -ENOTSUP;
173 	uint8_t response[2] = {0, 0};
174 	uint16_t read_size = 0;
175 
176 	do {
177 #if (CONFIG_SOC_SERIES_APOLLO4X)
178 		/* Skip if the IRQ pin is not in high state */
179 		if (!irq_pin_state()) {
180 			ret = -1;
181 			break;
182 		}
183 
184 		/* Check the available packet bytes */
185 		uint8_t command[1] = {SPI_READ};
186 		ret = transceive(command, 1, response, 2);
187 		if (ret) {
188 			break;
189 		}
190 #elif (CONFIG_SOC_SERIES_APOLLO3X)
191 		/* Skip if the IRQ bit is not set */
192 		if (!BLEIFn(0)->BSTATUS_b.BLEIRQ) {
193 			ret = -1;
194 			break;
195 		}
196 
197 		/* Check the available packet bytes */
198 		ret = transceive(NULL, 0, response, 2);
199 		if (ret) {
200 			break;
201 		}
202 #else
203 		break;
204 #endif /* CONFIG_SOC_SERIES_APOLLO4X */
205 
206 		/* Check if the read size is acceptable */
207 		read_size = (uint16_t)(response[0] | response[1] << 8);
208 		if ((read_size == 0) || (read_size > SPI_MAX_RX_MSG_LEN)) {
209 			ret = -1;
210 			break;
211 		}
212 
213 		*len = read_size;
214 
215 		/* Read the HCI data from controller */
216 		ret = transceive(NULL, 0, data, read_size);
217 
218 		if (ret) {
219 			LOG_ERR("SPI read error %d", ret);
220 			break;
221 		}
222 	} while (0);
223 
224 	return ret;
225 }
226 
bt_apollo_vnd_rcv_ongoing(uint8_t * data,uint16_t len)227 bool bt_apollo_vnd_rcv_ongoing(uint8_t *data, uint16_t len)
228 {
229 #if (CONFIG_SOC_SERIES_APOLLO4X)
230 	/* The vendor specific handshake command/response is incompatible with
231 	 * standard Bluetooth HCI format, need to handle the received packets
232 	 * specifically.
233 	 */
234 	if (am_devices_cooper_get_initialize_state() != AM_DEVICES_COOPER_STATE_INITIALIZED) {
235 		am_devices_cooper_handshake_recv(data, len);
236 		return true;
237 	} else {
238 		return false;
239 	}
240 #else
241 	return false;
242 #endif /* CONFIG_SOC_SERIES_APOLLO4X */
243 }
244 
bt_hci_transport_setup(const struct device * dev)245 int bt_hci_transport_setup(const struct device *dev)
246 {
247 	ARG_UNUSED(dev);
248 
249 	int ret = 0;
250 
251 #if (CONFIG_SOC_SERIES_APOLLO4X)
252 	/* Configure the XO32MHz and XO32kHz clocks.*/
253 	clock_control_configure(clk32k_dev, NULL, NULL);
254 	clock_control_configure(clk32m_dev, NULL, NULL);
255 
256 	/* Enable XO32kHz for Controller */
257 	clock_control_on(clk32k_dev, (clock_control_subsys_t)CLOCK_CONTROL_AMBIQ_TYPE_LFXTAL);
258 
259 	/* Enable XO32MHz for Controller */
260 	clock_control_on(clk32m_dev, (clock_control_subsys_t)CLOCK_CONTROL_AMBIQ_TYPE_HFXTAL_BLE);
261 
262 	/* Configure RST pin and hold BLE in Reset */
263 	ret = gpio_pin_configure_dt(&rst_gpio, GPIO_OUTPUT_ACTIVE);
264 	if (ret) {
265 		return ret;
266 	}
267 
268 	/* Configure IRQ pin and register the callback */
269 	ret = gpio_pin_configure_dt(&irq_gpio, GPIO_INPUT);
270 	if (ret) {
271 		return ret;
272 	}
273 
274 	gpio_init_callback(&irq_gpio_cb, bt_packet_irq_isr, BIT(irq_gpio.pin));
275 	ret = gpio_add_callback(irq_gpio.port, &irq_gpio_cb);
276 	if (ret) {
277 		return ret;
278 	}
279 
280 	/* Configure CLKREQ pin and register the callback */
281 	ret = gpio_pin_configure_dt(&clkreq_gpio, GPIO_INPUT);
282 	if (ret) {
283 		return ret;
284 	}
285 
286 	gpio_init_callback(&clkreq_gpio_cb, bt_clkreq_isr, BIT(clkreq_gpio.pin));
287 	ret = gpio_add_callback(clkreq_gpio.port, &clkreq_gpio_cb);
288 	if (ret) {
289 		return ret;
290 	}
291 
292 	/* Configure the interrupt edge for CLKREQ pin */
293 	gpio_pin_interrupt_configure_dt(&clkreq_gpio, GPIO_INT_EDGE_RISING);
294 
295 	/* Take controller out of reset */
296 	k_sleep(K_MSEC(10));
297 	gpio_pin_set_dt(&rst_gpio, 0);
298 
299 	/* Give the controller some time to boot */
300 	k_sleep(K_MSEC(500));
301 
302 	/* Configure the interrupt edge for IRQ pin */
303 	gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_EDGE_RISING);
304 #elif (CONFIG_SOC_SERIES_APOLLO3X)
305 	IRQ_CONNECT(DT_IRQN(SPI_DEV_NODE), DT_IRQ(SPI_DEV_NODE, priority), bt_packet_irq_isr, 0, 0);
306 #endif /* CONFIG_SOC_SERIES_APOLLO4X */
307 
308 	return ret;
309 }
310 
bt_apollo_controller_init(spi_transmit_fun transmit)311 int bt_apollo_controller_init(spi_transmit_fun transmit)
312 {
313 	int ret = 0;
314 
315 #if (CONFIG_SOC_SERIES_APOLLO4X)
316 	am_devices_cooper_callback_t cb = {
317 		.write = transmit,
318 		.reset = bt_apollo_controller_reset,
319 	};
320 
321 	/* Initialize the BLE controller */
322 	ret = am_devices_cooper_init(&cb);
323 	if (ret == AM_DEVICES_COOPER_STATUS_SUCCESS) {
324 		am_devices_cooper_set_initialize_state(AM_DEVICES_COOPER_STATE_INITIALIZED);
325 		LOG_INF("BT controller initialized");
326 	} else {
327 		am_devices_cooper_set_initialize_state(AM_DEVICES_COOPER_STATE_INITIALIZE_FAIL);
328 		LOG_ERR("BT controller initialization fail");
329 	}
330 #elif (CONFIG_SOC_SERIES_APOLLO3X)
331 	ret = am_apollo3_bt_controller_init();
332 	if (ret == AM_HAL_STATUS_SUCCESS) {
333 		LOG_INF("BT controller initialized");
334 	} else {
335 		LOG_ERR("BT controller initialization fail");
336 	}
337 
338 	irq_enable(DT_IRQN(SPI_DEV_NODE));
339 #endif /* CONFIG_SOC_SERIES_APOLLO4X */
340 
341 	return ret;
342 }
343 
bt_apollo_controller_deinit(void)344 int bt_apollo_controller_deinit(void)
345 {
346 	int ret = -ENOTSUP;
347 
348 #if (CONFIG_SOC_SERIES_APOLLO3X)
349 	irq_disable(DT_IRQN(SPI_DEV_NODE));
350 
351 	ret = am_apollo3_bt_controller_deinit();
352 	if (ret == AM_HAL_STATUS_SUCCESS) {
353 		LOG_INF("BT controller deinitialized");
354 	} else {
355 		ret = -EPERM;
356 		LOG_ERR("BT controller deinitialization fails");
357 	}
358 #endif /* CONFIG_SOC_SERIES_APOLLO3X */
359 
360 	return ret;
361 }
362 
363 #if (CONFIG_SOC_SERIES_APOLLO4X)
bt_apollo_set_nvds(void)364 static int bt_apollo_set_nvds(void)
365 {
366 	int ret;
367 	struct net_buf *buf;
368 
369 #if defined(CONFIG_BT_HCI_RAW)
370 	struct bt_hci_cmd_hdr hdr;
371 
372 	hdr.opcode = sys_cpu_to_le16(HCI_VSC_UPDATE_NVDS_CFG_CMD_OPCODE);
373 	hdr.param_len = HCI_VSC_UPDATE_NVDS_CFG_CMD_LENGTH;
374 	buf = bt_buf_get_tx(BT_BUF_CMD, K_NO_WAIT, &hdr, sizeof(hdr));
375 	if (!buf) {
376 		return -ENOBUFS;
377 	}
378 
379 	net_buf_add_mem(buf, &am_devices_cooper_nvds[0], HCI_VSC_UPDATE_NVDS_CFG_CMD_LENGTH);
380 	ret = bt_send(buf);
381 
382 	if (!ret) {
383 		/* Give some time to make NVDS take effect in BLE controller */
384 		k_sleep(K_MSEC(5));
385 
386 		/* Need to send reset command to make the NVDS take effect */
387 		hdr.opcode = sys_cpu_to_le16(BT_HCI_OP_RESET);
388 		hdr.param_len = 0;
389 		buf = bt_buf_get_tx(BT_BUF_CMD, K_NO_WAIT, &hdr, sizeof(hdr));
390 		if (!buf) {
391 			return -ENOBUFS;
392 		}
393 
394 		ret = bt_send(buf);
395 	}
396 #else
397 	uint8_t *p;
398 
399 	buf = bt_hci_cmd_create(HCI_VSC_UPDATE_NVDS_CFG_CMD_OPCODE,
400 				HCI_VSC_UPDATE_NVDS_CFG_CMD_LENGTH);
401 	if (!buf) {
402 		return -ENOBUFS;
403 	}
404 
405 	p = net_buf_add(buf, HCI_VSC_UPDATE_NVDS_CFG_CMD_LENGTH);
406 	memcpy(p, &am_devices_cooper_nvds[0], HCI_VSC_UPDATE_NVDS_CFG_CMD_LENGTH);
407 	ret = bt_hci_cmd_send_sync(HCI_VSC_UPDATE_NVDS_CFG_CMD_OPCODE, buf, NULL);
408 
409 	if (!ret) {
410 		/* Give some time to make NVDS take effect in BLE controller */
411 		k_sleep(K_MSEC(5));
412 	}
413 #endif /* defined(CONFIG_BT_HCI_RAW) */
414 
415 	return ret;
416 }
417 #endif /* CONFIG_SOC_SERIES_APOLLO4X */
418 
bt_apollo_vnd_setup(void)419 int bt_apollo_vnd_setup(void)
420 {
421 	int ret = 0;
422 
423 #if (CONFIG_SOC_SERIES_APOLLO4X)
424 	/* Set the NVDS parameters to BLE controller */
425 	ret = bt_apollo_set_nvds();
426 #endif /* CONFIG_SOC_SERIES_APOLLO4X */
427 
428 	return ret;
429 }
430 
bt_apollo_dev_init(void)431 int bt_apollo_dev_init(void)
432 {
433 #if (CONFIG_SOC_SERIES_APOLLO4X)
434 	if (!gpio_is_ready_dt(&irq_gpio)) {
435 		LOG_ERR("IRQ GPIO device not ready");
436 		return -ENODEV;
437 	}
438 
439 	if (!gpio_is_ready_dt(&rst_gpio)) {
440 		LOG_ERR("Reset GPIO device not ready");
441 		return -ENODEV;
442 	}
443 
444 	if (!gpio_is_ready_dt(&clkreq_gpio)) {
445 		LOG_ERR("CLKREQ GPIO device not ready");
446 		return -ENODEV;
447 	}
448 #endif /* CONFIG_SOC_SERIES_APOLLO4X */
449 
450 	return 0;
451 }
452