1 /******************************************************************************
2  * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************/
18 
19 #include <zephyr.h>
20 #undef irq_enable
21 #undef irq_disable
22 #undef ARRAY_SIZE
23 
24 #include "b91_bt.h"
25 #include "b91_bt_init.h"
26 #include "compiler.h"
27 #include "plic.h"
28 #include "stack/ble/controller/ble_controller.h"
29 
30 /* Module defines */
31 #define BLE_THREAD_STACK_SIZE CONFIG_B91_BLE_CTRL_THREAD_STACK_SIZE
32 #define BLE_THREAD_PRIORITY CONFIG_B91_BLE_CTRL_THREAD_PRIORITY
33 #define BLE_THREAD_PERIOD_MS CONFIG_B91_BLE_CTRL_THREAD_PERIOD_MS
34 
35 #define BYTES_TO_UINT16(n, p)                                                                      \
36 	{                                                                                          \
37 		n = ((u16)(p)[0] + ((u16)(p)[1] << 8));                                            \
38 	}
39 #define BSTREAM_TO_UINT16(n, p)                                                                    \
40 	{                                                                                          \
41 		BYTES_TO_UINT16(n, p);                                                             \
42 		p += 2;                                                                            \
43 	}
44 
45 static void b91_bt_controller_thread();
46 
47 K_THREAD_DEFINE(ZephyrBleController, BLE_THREAD_STACK_SIZE, b91_bt_controller_thread, NULL, NULL,
48 		NULL, BLE_THREAD_PRIORITY, 0, -1);
49 
50 static struct b91_ctrl_t {
51 	b91_bt_host_callback_t callbacks;
52 } b91_ctrl;
53 
54 /**
55  * @brief    RF driver interrupt handler
56  */
rf_irq_handler(void)57 _attribute_ram_code_ void rf_irq_handler(void) { blc_sdk_irq_handler(); }
58 
59 /**
60  * @brief    System Timer interrupt handler
61  */
stimer_irq_handler(void)62 _attribute_ram_code_ void stimer_irq_handler(void) { blc_sdk_irq_handler(); }
63 
64 /**
65  * @brief    BLE Controller HCI Tx callback implementation
66  */
b91_bt_hci_tx_handler(void)67 static int b91_bt_hci_tx_handler(void)
68 {
69 	/* check for data available */
70 	if (bltHci_txfifo.wptr == bltHci_txfifo.rptr) {
71 		return 0;
72 	}
73 
74 	/* Get HCI data */
75 	u8 *p = bltHci_txfifo.p + (bltHci_txfifo.rptr & bltHci_txfifo.mask) * bltHci_txfifo.size;
76 	if (p) {
77 		u32 len;
78 		BSTREAM_TO_UINT16(len, p);
79 		bltHci_txfifo.rptr++;
80 
81 		/* Send data to the host */
82 		if (b91_ctrl.callbacks.host_read_packet) {
83 			b91_ctrl.callbacks.host_read_packet(p, len);
84 		}
85 	}
86 
87 	return 0;
88 }
89 
90 /**
91  * @brief    BLE Controller HCI Rx callback implementation
92  */
b91_bt_hci_rx_handler(void)93 static int b91_bt_hci_rx_handler(void)
94 {
95 	/* Check for data available */
96 	if (bltHci_rxfifo.wptr == bltHci_rxfifo.rptr) {
97 		/* No data to process, send host_send_available message to the host */
98 		if (b91_ctrl.callbacks.host_send_available) {
99 			b91_ctrl.callbacks.host_send_available();
100 		}
101 
102 		return 0;
103 	}
104 
105 	/* Get HCI data */
106 	u8 *p = bltHci_rxfifo.p + (bltHci_rxfifo.rptr & bltHci_rxfifo.mask) * bltHci_rxfifo.size;
107 	if (p) {
108 		/* Send data to the controller */
109 		blc_hci_handler(&p[0], 0);
110 		bltHci_rxfifo.rptr++;
111 	}
112 
113 	return 0;
114 }
115 
116 /**
117  * @brief    Telink B91 BLE Controller thread
118  */
b91_bt_controller_thread()119 static void b91_bt_controller_thread()
120 {
121 	while (1) {
122 		blc_sdk_main_loop();
123 #ifndef CONFIG_PM
124 		k_msleep(CONFIG_B91_BLE_CTRL_THREAD_PERIOD_MS);
125 #endif /* !CONFIG_PM */
126 	}
127 }
128 
129 /**
130  * @brief    BLE Controller IRQs initialization
131  */
b91_bt_irq_init()132 static void b91_bt_irq_init()
133 {
134 	/* Init STimer IRQ */
135 	IRQ_CONNECT(IRQ1_SYSTIMER, 0, stimer_irq_handler, 0, 0);
136 
137 	/* Init RF IRQ */
138 	IRQ_CONNECT(IRQ15_ZB_RT, 0, rf_irq_handler, 0, 0);
139 }
140 
141 /**
142  * @brief    Telink B91 BLE Controller initialization
143  * @return   Status - 0: command succeeded; -1: command failed
144  */
b91_bt_controller_init()145 int b91_bt_controller_init()
146 {
147 	int status;
148 
149 	/* Init IRQs */
150 	b91_bt_irq_init();
151 
152 	/* Init RF driver */
153 	rf_drv_ble_init();
154 
155 	/* Init BLE Controller stack */
156 	status = b91_bt_blc_init(b91_bt_hci_rx_handler, b91_bt_hci_tx_handler);
157 	if (status != INIT_OK) {
158 		return status;
159 	}
160 
161 	/* Start BLE thread */
162 	k_thread_start(ZephyrBleController);
163 
164 	return status;
165 }
166 
167 /**
168  * @brief      Host send HCI packet to controller
169  * @param      data the packet point
170  * @param      len the packet length
171  */
b91_bt_host_send_packet(uint8_t type,uint8_t * data,uint16_t len)172 void b91_bt_host_send_packet(uint8_t type, uint8_t *data, uint16_t len)
173 {
174 	u8 *p = bltHci_rxfifo.p + (bltHci_rxfifo.wptr & bltHci_rxfifo.mask) * bltHci_rxfifo.size;
175 	*p++ = type;
176 	memcpy(p, data, len);
177 	bltHci_rxfifo.wptr++;
178 }
179 
180 /**
181  * @brief Register the vhci reference callback
182  */
b91_bt_host_callback_register(const b91_bt_host_callback_t * pcb)183 void b91_bt_host_callback_register(const b91_bt_host_callback_t *pcb)
184 {
185 	b91_ctrl.callbacks.host_read_packet = pcb->host_read_packet;
186 	b91_ctrl.callbacks.host_send_available = pcb->host_send_available;
187 }
188