1 /**
2  * Copyright (c) 2018 Linaro
3  * Copyright (c) 2020 ATL Electronics
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT inventek_eswifi_uart
9 
10 #include "eswifi_log.h"
11 LOG_MODULE_DECLARE(LOG_MODULE_NAME);
12 
13 #include <zephyr/kernel.h>
14 #include <zephyr/device.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <zephyr/sys/ring_buffer.h>
18 #include <zephyr/drivers/gpio.h>
19 #include <zephyr/drivers/uart.h>
20 
21 #include "eswifi.h"
22 
23 #define ESWIFI_RING_BUF_SIZE 2048
24 
25 enum eswifi_uart_fsm {
26 	ESWIFI_UART_FSM_WAIT_CR,
27 	ESWIFI_UART_FSM_WAIT_LF,
28 	ESWIFI_UART_FSM_WAIT_MARK,
29 	ESWIFI_UART_FSM_WAIT_SPACE,
30 	ESWIFI_UART_FSM_END,
31 };
32 
33 struct eswifi_uart_data {
34 	const struct device *dev;
35 	enum eswifi_uart_fsm fsm;
36 	size_t rx_count;
37 	size_t rx_buf_size;
38 	char *rx_buf;
39 
40 	/* RX Ring Buf */
41 	uint8_t iface_rb_buf[ESWIFI_RING_BUF_SIZE];
42 	struct ring_buf rx_rb;
43 };
44 
45 static struct eswifi_uart_data eswifi_uart0; /* Static instance */
46 
eswifi_iface_uart_flush(struct eswifi_uart_data * uart)47 static void eswifi_iface_uart_flush(struct eswifi_uart_data *uart)
48 {
49 	uint8_t c;
50 
51 	while (uart_fifo_read(uart->dev, &c, 1) > 0) {
52 		continue;
53 	}
54 }
55 
eswifi_iface_uart_isr(const struct device * uart_dev,void * user_data)56 static void eswifi_iface_uart_isr(const struct device *uart_dev,
57 				  void *user_data)
58 {
59 	struct eswifi_uart_data *uart = &eswifi_uart0; /* Static instance */
60 	int rx = 0;
61 	uint8_t *dst;
62 	uint32_t partial_size = 0;
63 	uint32_t total_size = 0;
64 
65 	ARG_UNUSED(user_data);
66 
67 	while (uart_irq_update(uart->dev) &&
68 	       uart_irq_rx_ready(uart->dev)) {
69 		if (!partial_size) {
70 			partial_size = ring_buf_put_claim(&uart->rx_rb, &dst,
71 							  UINT32_MAX);
72 		}
73 		if (!partial_size) {
74 			LOG_ERR("Rx buffer doesn't have enough space");
75 			eswifi_iface_uart_flush(uart);
76 			break;
77 		}
78 
79 		rx = uart_fifo_read(uart->dev, dst, partial_size);
80 		if (rx <= 0) {
81 			continue;
82 		}
83 
84 		dst += rx;
85 		total_size += rx;
86 		partial_size -= rx;
87 	}
88 
89 	ring_buf_put_finish(&uart->rx_rb, total_size);
90 }
91 
get_fsm_char(int fsm)92 static char get_fsm_char(int fsm)
93 {
94 	switch (fsm) {
95 	case ESWIFI_UART_FSM_WAIT_CR:
96 		return('C');
97 	case ESWIFI_UART_FSM_WAIT_LF:
98 		return('L');
99 	case ESWIFI_UART_FSM_WAIT_MARK:
100 		return('M');
101 	case ESWIFI_UART_FSM_WAIT_SPACE:
102 		return('S');
103 	case ESWIFI_UART_FSM_END:
104 		return('E');
105 	}
106 
107 	return('?');
108 }
109 
eswifi_uart_get_resp(struct eswifi_uart_data * uart)110 static int eswifi_uart_get_resp(struct eswifi_uart_data *uart)
111 {
112 	uint8_t c;
113 
114 	while (ring_buf_get(&uart->rx_rb, &c, 1) > 0) {
115 		LOG_DBG("FSM: %c, RX: 0x%02x : %c",
116 			get_fsm_char(uart->fsm), c, c);
117 
118 		if (uart->rx_buf_size > 0) {
119 			uart->rx_buf[uart->rx_count++] = c;
120 
121 			if (uart->rx_count == uart->rx_buf_size) {
122 				return -ENOMEM;
123 			}
124 		}
125 
126 		switch (uart->fsm) {
127 		case ESWIFI_UART_FSM_WAIT_CR:
128 			if (c == '\r') {
129 				uart->fsm = ESWIFI_UART_FSM_WAIT_LF;
130 			}
131 			break;
132 		case ESWIFI_UART_FSM_WAIT_LF:
133 			if (c == '\n') {
134 				uart->fsm = ESWIFI_UART_FSM_WAIT_MARK;
135 			} else if (c != '\r') {
136 				uart->fsm = ESWIFI_UART_FSM_WAIT_CR;
137 			}
138 			break;
139 		case ESWIFI_UART_FSM_WAIT_MARK:
140 			if (c == '>') {
141 				uart->fsm = ESWIFI_UART_FSM_WAIT_SPACE;
142 			} else if (c == '\r') {
143 				uart->fsm = ESWIFI_UART_FSM_WAIT_LF;
144 			} else {
145 				uart->fsm = ESWIFI_UART_FSM_WAIT_CR;
146 			}
147 			break;
148 		case ESWIFI_UART_FSM_WAIT_SPACE:
149 			if (c == ' ') {
150 				uart->fsm = ESWIFI_UART_FSM_END;
151 			} else if (c == '\r') {
152 				uart->fsm = ESWIFI_UART_FSM_WAIT_LF;
153 			} else {
154 				uart->fsm = ESWIFI_UART_FSM_WAIT_CR;
155 			}
156 			break;
157 		default:
158 			break;
159 		}
160 	}
161 
162 	return 0;
163 }
164 
eswifi_uart_wait_prompt(struct eswifi_uart_data * uart)165 static int eswifi_uart_wait_prompt(struct eswifi_uart_data *uart)
166 {
167 	unsigned int max_retries = 60 * 1000; /* 1 minute */
168 	int err;
169 
170 	while (--max_retries) {
171 		err = eswifi_uart_get_resp(uart);
172 		if (err) {
173 			LOG_DBG("Err: 0x%08x - %d", err, err);
174 			return err;
175 		}
176 
177 		if (uart->fsm == ESWIFI_UART_FSM_END) {
178 			LOG_DBG("Success!");
179 			return uart->rx_count;
180 		}
181 
182 		/* allow other threads to be scheduled */
183 		k_sleep(K_MSEC(1));
184 	}
185 
186 	LOG_DBG("Timeout");
187 	return -ETIMEDOUT;
188 }
189 
eswifi_uart_request(struct eswifi_dev * eswifi,char * cmd,size_t clen,char * rsp,size_t rlen)190 static int eswifi_uart_request(struct eswifi_dev *eswifi, char *cmd,
191 			       size_t clen, char *rsp, size_t rlen)
192 {
193 	struct eswifi_uart_data *uart = eswifi->bus_data;
194 	int count;
195 	int err;
196 
197 	LOG_DBG("cmd=%p (%u byte), rsp=%p (%u byte)", cmd, clen, rsp, rlen);
198 
199 	/* Send CMD */
200 	for (count = 0; count < clen; count++) {
201 		uart_poll_out(uart->dev, cmd[count]);
202 	}
203 
204 	uart->fsm = ESWIFI_UART_FSM_WAIT_CR;
205 	uart->rx_count = 0;
206 	uart->rx_buf = rsp;
207 	uart->rx_buf_size = rlen;
208 
209 	err = eswifi_uart_wait_prompt(uart);
210 
211 	if (err > 0) {
212 		LOG_HEXDUMP_DBG(uart->rx_buf, uart->rx_count, "Stream");
213 	}
214 
215 	return err;
216 }
217 
eswifi_uart_init(struct eswifi_dev * eswifi)218 int eswifi_uart_init(struct eswifi_dev *eswifi)
219 {
220 	struct eswifi_uart_data *uart = &eswifi_uart0; /* Static instance */
221 
222 	uart->dev = DEVICE_DT_GET(DT_INST_BUS(0));
223 	if (!device_is_ready(uart->dev)) {
224 		LOG_ERR("Bus device is not ready");
225 		return -ENODEV;
226 	}
227 
228 	eswifi->bus_data = uart;
229 
230 	uart_irq_rx_disable(uart->dev);
231 	uart_irq_tx_disable(uart->dev);
232 	eswifi_iface_uart_flush(uart);
233 	uart_irq_callback_set(uart->dev, eswifi_iface_uart_isr);
234 	uart_irq_rx_enable(uart->dev);
235 
236 	ring_buf_init(&uart->rx_rb, sizeof(uart->iface_rb_buf),
237 		      uart->iface_rb_buf);
238 
239 	LOG_DBG("success");
240 
241 	return 0;
242 }
243 
244 static struct eswifi_bus_ops eswifi_bus_ops_uart = {
245 	.init = eswifi_uart_init,
246 	.request = eswifi_uart_request,
247 };
248 
eswifi_get_bus(void)249 struct eswifi_bus_ops *eswifi_get_bus(void)
250 {
251 	return &eswifi_bus_ops_uart;
252 }
253