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