1 /**
2  * Copyright (c) 2018 Linaro
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT inventek_eswifi
8 #include "eswifi_log.h"
9 LOG_MODULE_DECLARE(LOG_MODULE_NAME);
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/device.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <zephyr/drivers/gpio.h>
16 #include <zephyr/drivers/spi.h>
17 
18 #include "eswifi.h"
19 
20 #define ESWIFI_SPI_THREAD_STACK_SIZE 1024
21 K_KERNEL_STACK_MEMBER(eswifi_spi_poll_stack, ESWIFI_SPI_THREAD_STACK_SIZE);
22 
23 #define SPI_READ_CHUNK_SIZE 32
24 
25 struct eswifi_spi_config {
26 	struct gpio_dt_spec dr;
27 	struct spi_dt_spec bus;
28 };
29 
30 struct eswifi_spi_data {
31 	const struct eswifi_spi_config *cfg;
32 	struct k_thread poll_thread;
33 };
34 
35 static const struct eswifi_spi_config eswifi_config_spi0 = {
36 	.dr = GPIO_DT_SPEC_INST_GET(0, data_gpios),
37 	.bus = SPI_DT_SPEC_INST_GET(0, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB |
38 				    SPI_WORD_SET(16) | SPI_HOLD_ON_CS |
39 				    SPI_LOCK_ON, 1000U),
40 };
41 
42 static struct eswifi_spi_data eswifi_spi0;
43 
eswifi_spi_cmddata_ready(struct eswifi_spi_data * spi)44 static bool eswifi_spi_cmddata_ready(struct eswifi_spi_data *spi)
45 {
46 	return gpio_pin_get_dt(&spi->cfg->dr) > 0;
47 }
48 
eswifi_spi_wait_cmddata_ready(struct eswifi_spi_data * spi)49 static int eswifi_spi_wait_cmddata_ready(struct eswifi_spi_data *spi)
50 {
51 	unsigned int max_retries = 60 * 1000; /* 1 minute */
52 
53 	do {
54 		/* allow other threads to be scheduled */
55 		k_sleep(K_MSEC(1));
56 	} while (!eswifi_spi_cmddata_ready(spi) && --max_retries);
57 
58 	return max_retries ? 0 : -ETIMEDOUT;
59 }
60 
eswifi_spi_write(struct eswifi_dev * eswifi,char * data,size_t dlen)61 static int eswifi_spi_write(struct eswifi_dev *eswifi, char *data, size_t dlen)
62 {
63 	struct eswifi_spi_data *spi = eswifi->bus_data;
64 	struct spi_buf spi_tx_buf[1];
65 	struct spi_buf_set spi_tx;
66 	int status;
67 
68 	spi_tx_buf[0].buf = data;
69 	spi_tx_buf[0].len = dlen;
70 	spi_tx.buffers = spi_tx_buf;
71 	spi_tx.count = ARRAY_SIZE(spi_tx_buf);
72 
73 	status = spi_write_dt(&spi->cfg->bus, &spi_tx);
74 	if (status) {
75 		LOG_ERR("SPI write error %d", status);
76 	} else {
77 		status = dlen;
78 	}
79 
80 	return status;
81 }
82 
eswifi_spi_read(struct eswifi_dev * eswifi,char * data,size_t dlen)83 static int eswifi_spi_read(struct eswifi_dev *eswifi, char *data, size_t dlen)
84 {
85 	struct eswifi_spi_data *spi = eswifi->bus_data;
86 	struct spi_buf spi_rx_buf[1];
87 	struct spi_buf_set spi_rx;
88 	int status;
89 
90 	spi_rx_buf[0].buf = data;
91 	spi_rx_buf[0].len = dlen;
92 	spi_rx.buffers = spi_rx_buf;
93 	spi_rx.count = ARRAY_SIZE(spi_rx_buf);
94 
95 	status = spi_read_dt(&spi->cfg->bus, &spi_rx);
96 	if (status) {
97 		LOG_ERR("SPI read error %d", status);
98 	} else {
99 		status = dlen;
100 	}
101 
102 	return status;
103 }
104 
eswifi_spi_request(struct eswifi_dev * eswifi,char * cmd,size_t clen,char * rsp,size_t rlen)105 static int eswifi_spi_request(struct eswifi_dev *eswifi, char *cmd, size_t clen,
106 			      char *rsp, size_t rlen)
107 {
108 	struct eswifi_spi_data *spi = eswifi->bus_data;
109 	unsigned int offset = 0U, to_read = SPI_READ_CHUNK_SIZE;
110 	char tmp[2];
111 	int err;
112 
113 	LOG_DBG("cmd=%p (%u byte), rsp=%p (%u byte)", cmd, clen, rsp, rlen);
114 
115 	/*
116 	 * CMD/DATA protocol:
117 	 * 1. Module raises data-ready when ready for **command phase**
118 	 * 2. Host announces command start by lowering chip-select
119 	 * 3. Host write the command (possibly several spi transfers)
120 	 * 4. Host announces end of command by raising chip-select
121 	 * 5. Module lowers data-ready signal
122 	 * 6. Module raises data-ready to signal start of the **data phase**
123 	 * 7. Host lowers chip-select
124 	 * 8. Host fetch data as long as data-ready pin is up
125 	 * 9. Module lowers data-ready to signal the end of the data Phase
126 	 * 10. Host raises chip-select
127 	 *
128 	 * Note:
129 	 * All commands to the eS-WiFi module must be post-padded with
130 	 * 0x0A (Line Feed) to an even number of bytes.
131 	 * All data from eS-WiFi module are post-padded with 0x15(NAK) to an
132 	 * even number of bytes.
133 	 */
134 
135 	if (!cmd) {
136 		goto data;
137 	}
138 
139 	/* CMD/DATA READY signals the Command Phase */
140 	err = eswifi_spi_wait_cmddata_ready(spi);
141 	if (err) {
142 		LOG_ERR("CMD ready timeout\n");
143 		return err;
144 	}
145 
146 	if (clen % 2) { /* Add post-padding if necessary */
147 		/* cmd is a string so cmd[clen] is 0x00 */
148 		cmd[clen] = 0x0a;
149 		clen++;
150 	}
151 
152 	eswifi_spi_write(eswifi, cmd, clen);
153 
154 	/* Our device is flagged with SPI_HOLD_ON_CS|SPI_LOCK_ON, release */
155 	spi_release_dt(&spi->cfg->bus);
156 
157 data:
158 	/* CMD/DATA READY signals the Data Phase */
159 	err = eswifi_spi_wait_cmddata_ready(spi);
160 	if (err) {
161 		LOG_ERR("DATA ready timeout\n");
162 		return err;
163 	}
164 
165 	while (eswifi_spi_cmddata_ready(spi) && to_read) {
166 		to_read = MIN(rlen - offset, to_read);
167 		memset(rsp + offset, 0, to_read);
168 		eswifi_spi_read(eswifi, rsp + offset, to_read);
169 		offset += to_read;
170 		k_yield();
171 	}
172 
173 	/* Flush remaining data if receiving buffer not large enough */
174 	while (eswifi_spi_cmddata_ready(spi)) {
175 		eswifi_spi_read(eswifi, tmp, 2);
176 		k_sleep(K_MSEC(1));
177 	}
178 
179 	/* Our device is flagged with SPI_HOLD_ON_CS|SPI_LOCK_ON, release */
180 	spi_release_dt(&spi->cfg->bus);
181 
182 	LOG_DBG("success");
183 
184 	return offset;
185 }
186 
eswifi_spi_read_msg(struct eswifi_dev * eswifi)187 static void eswifi_spi_read_msg(struct eswifi_dev *eswifi)
188 {
189 	const char startstr[] = "[SOMA]";
190 	const char endstr[] = "[EOMA]";
191 	char cmd[] = "MR\r";
192 	size_t msg_len;
193 	char *rsp;
194 	int ret;
195 
196 	LOG_DBG("");
197 
198 	eswifi_lock(eswifi);
199 
200 	ret = eswifi_at_cmd_rsp(eswifi, cmd, &rsp);
201 	if (ret < 0) {
202 		LOG_ERR("Unable to read msg %d", ret);
203 		eswifi_unlock(eswifi);
204 		return;
205 	}
206 
207 	if (strncmp(rsp, startstr, sizeof(endstr) - 1)) {
208 		LOG_ERR("Malformed async msg");
209 		eswifi_unlock(eswifi);
210 		return;
211 	}
212 
213 	/* \r\n[SOMA]...[EOMA]\r\nOK\r\n> */
214 	msg_len = ret - (sizeof(startstr) - 1) - (sizeof(endstr) - 1);
215 	if (msg_len > 0) {
216 		eswifi_async_msg(eswifi, rsp + sizeof(endstr) - 1, msg_len);
217 	}
218 
219 	eswifi_unlock(eswifi);
220 }
221 
eswifi_spi_poll_thread(void * p1,void * p2,void * p3)222 static void eswifi_spi_poll_thread(void *p1, void *p2, void *p3)
223 {
224 	ARG_UNUSED(p2);
225 	ARG_UNUSED(p3);
226 
227 	struct eswifi_dev *eswifi = p1;
228 
229 	while (1) {
230 		k_sleep(K_MSEC(1000));
231 		eswifi_spi_read_msg(eswifi);
232 	}
233 }
234 
eswifi_spi_init(struct eswifi_dev * eswifi)235 int eswifi_spi_init(struct eswifi_dev *eswifi)
236 {
237 	struct eswifi_spi_data *spi = &eswifi_spi0; /* Static instance */
238 	const struct eswifi_spi_config *cfg = &eswifi_config_spi0; /* Static instance */
239 
240 	/* SPI DATA READY PIN */
241 	if (!gpio_is_ready_dt(&cfg->dr)) {
242 		LOG_ERR("device %s is not ready", cfg->dr.port->name);
243 		return -ENODEV;
244 	}
245 	gpio_pin_configure_dt(&cfg->dr, GPIO_INPUT);
246 
247 	/* SPI BUS */
248 	if (!spi_is_ready_dt(&cfg->bus)) {
249 		LOG_ERR("SPI bus is not ready");
250 		return -ENODEV;
251 	};
252 
253 	spi->cfg = cfg;
254 
255 	eswifi->bus_data = spi;
256 
257 	LOG_DBG("success");
258 
259 	k_thread_create(&spi->poll_thread, eswifi_spi_poll_stack,
260 			ESWIFI_SPI_THREAD_STACK_SIZE,
261 			eswifi_spi_poll_thread, eswifi, NULL,
262 			NULL, K_PRIO_COOP(CONFIG_WIFI_ESWIFI_THREAD_PRIO), 0,
263 			K_NO_WAIT);
264 
265 	return 0;
266 }
267 
268 static struct eswifi_bus_ops eswifi_bus_ops_spi = {
269 	.init = eswifi_spi_init,
270 	.request = eswifi_spi_request,
271 };
272 
eswifi_get_bus(void)273 struct eswifi_bus_ops *eswifi_get_bus(void)
274 {
275 	return &eswifi_bus_ops_spi;
276 }
277