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