]> Git Repo - esp-hosted.git/blame - host/linux/host_driver/esp32/spi/esp_spi.c
Merge branch 'feature/spi_redesign_stm_new' into 'master'
[esp-hosted.git] / host / linux / host_driver / esp32 / spi / esp_spi.c
CommitLineData
5e72bc8b
MM
1/*
2 * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
3 *
4 * This software file (the "File") is distributed by Espressif Systems (Shanghai)
5 * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
6 * (the "License"). You may use, redistribute and/or modify this File in
7 * accordance with the terms and conditions of the License, a copy of which
8 * is available by writing to the Free Software Foundation, Inc.,
9 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
10 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
11 *
12 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
13 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
14 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
15 * this warranty disclaimer.
16 */
17#include <linux/device.h>
18#include <linux/spi/spi.h>
19#include <linux/gpio.h>
a9096fbc
MM
20#include <linux/mutex.h>
21#include <linux/delay.h>
5e72bc8b
MM
22#include "esp_spi.h"
23#include "esp_if.h"
24#include "esp_api.h"
25#include "esp_bt_api.h"
26#ifdef CONFIG_SUPPORT_ESP_SERIAL
27#include "esp_serial.h"
28#endif
29
30static struct sk_buff * read_packet(struct esp_adapter *adapter);
31static int write_packet(struct esp_adapter *adapter, u8 *buf, u32 size);
32static void spi_exit(void);
33
c746d295
MM
34volatile u8 data_path = 0;
35static struct esp_spi_context spi_context;
36
5e72bc8b
MM
37static struct esp_if_ops if_ops = {
38 .read = read_packet,
39 .write = write_packet,
40};
41
a9096fbc 42static DEFINE_MUTEX(spi_lock);
c746d295
MM
43
44static void open_data_path(void)
45{
46 msleep(200);
47 data_path = OPEN_DATAPATH;
48}
49
50static void close_data_path(void)
51{
52 data_path = CLOSE_DATAPATH;
53 msleep(200);
54}
5e72bc8b 55
a9096fbc
MM
56static irqreturn_t spi_data_ready_interrupt_handler(int irq, void * dev)
57{
58 /* ESP peripheral has queued buffer for transmission */
59 if (spi_context.spi_workqueue)
60 queue_work(spi_context.spi_workqueue, &spi_context.spi_work);
61
62 return IRQ_HANDLED;
63 }
64
5e72bc8b
MM
65static irqreturn_t spi_interrupt_handler(int irq, void * dev)
66{
a9096fbc 67 /* ESP peripheral is ready for next SPI transaction */
5e72bc8b
MM
68 if (spi_context.spi_workqueue)
69 queue_work(spi_context.spi_workqueue, &spi_context.spi_work);
70
71 return IRQ_HANDLED;
72}
73
74static struct sk_buff * read_packet(struct esp_adapter *adapter)
75{
76 struct esp_spi_context *context;
77 struct sk_buff *skb = NULL;
78
c746d295
MM
79 if (!data_path) {
80 return NULL;
81 }
82
5e72bc8b
MM
83 if (!adapter || !adapter->if_context) {
84 printk (KERN_ERR "%s: Invalid args\n", __func__);
85 return NULL;
86 }
87
88 context = adapter->if_context;
89
90 if (context->esp_spi_dev) {
91 skb = skb_dequeue(&(context->rx_q));
92 } else {
93 printk (KERN_ERR "%s: Invalid args\n", __func__);
94 return NULL;
95 }
96
97 return skb;
98}
99
100static int write_packet(struct esp_adapter *adapter, u8 *buf, u32 size)
101{
102 struct esp_spi_context *context;
103 struct sk_buff *skb;
104 u8 *tx_buf = NULL;
105
106 if (!adapter || !adapter->if_context || !buf || !size || (size > SPI_BUF_SIZE)) {
107 printk (KERN_ERR "%s: Invalid args\n", __func__);
108 return -EINVAL;
109 }
110
c746d295
MM
111 if (!data_path) {
112 return -EPERM;
113 }
114
5e72bc8b
MM
115 /* Adjust length to make it multiple of 4 bytes */
116 size += 4 - (size & 3);
117
118 context = adapter->if_context;
119
120 skb = esp_alloc_skb(size);
121
122 if (!skb)
123 return -ENOMEM;
124
125 tx_buf = skb_put(skb, size);
126
127 if (!tx_buf) {
128 dev_kfree_skb(skb);
129 return -ENOMEM;
130 }
131
132 /* TODO: This memecpy can be avoided if this function receives SKB as an argument */
133 memcpy(tx_buf, buf, size);
134
135 /* Enqueue SKB in tx_q */
136 skb_queue_tail(&spi_context.tx_q, skb);
137
a9096fbc
MM
138 if (spi_context.spi_workqueue)
139 queue_work(spi_context.spi_workqueue, &spi_context.spi_work);
140
5e72bc8b
MM
141 return 0;
142}
143
062be972
MM
144static void process_capabilities(u8 cap)
145{
a9096fbc 146 printk (KERN_INFO "ESP32 capabilities: 0x%x\n", cap);
062be972
MM
147
148 /* Reset BT */
149 esp_deinit_bt(spi_context.adapter);
150
151 if ((cap & ESP_BT_SPI_SUPPORT) || (cap & ESP_BT_SDIO_SUPPORT)) {
152 msleep(200);
153 esp_init_bt(spi_context.adapter);
154 }
155}
156
157static void process_init_event(u8 *evt_buf, u8 len)
158{
159 u8 len_left = len, tag_len;
160 u8 *pos;
161
162 if (!evt_buf)
163 return;
164
165 pos = evt_buf;
166
167 while (len_left) {
168 tag_len = *(pos + 1);
169 if (*pos == ESP_PRIV_CAPABILITY) {
170 process_capabilities(*(pos + 2));
171 } else {
172 printk (KERN_WARNING "Unsupported tag in event");
173 }
174 len_left = len_left - (tag_len + 2);
175 }
176}
177
178static void process_event(u8 *evt_buf, u16 len)
179{
180 struct esp_priv_event *event;
181
182 if (!evt_buf || !len)
183 return;
184
185 event = (struct esp_priv_event *) evt_buf;
186
187 if (event->event_type == ESP_PRIV_EVENT_INIT) {
188 printk (KERN_INFO "Received INIT event from esp32");
189 process_init_event(event->event_data, event->event_len);
190 } else {
191 printk (KERN_WARNING "Drop unknown event");
192 }
193}
194
195static void process_priv_communication(struct sk_buff *skb)
196{
197 struct esp_payload_header *header;
198 u8 *payload;
199 u16 len;
200
201 if (!skb || !skb->data)
202 return;
203
204 header = (struct esp_payload_header *) skb->data;
205
206 payload = skb->data + le16_to_cpu(header->offset);
207 len = le16_to_cpu(header->len);
208
209 if (header->priv_pkt_type == ESP_PACKET_TYPE_EVENT) {
210 process_event(payload, len);
211 }
212
213 dev_kfree_skb(skb);
214}
215
5e72bc8b
MM
216static int process_rx_buf(struct sk_buff *skb)
217{
218 struct esp_payload_header *header;
219 u16 len = 0;
220 u16 offset = 0;
221
222 if (!skb)
223 return -EINVAL;
224
225 header = (struct esp_payload_header *) skb->data;
226
a9096fbc
MM
227 if (header->if_type >= ESP_MAX_IF) {
228 return -EINVAL;
229 }
230
5e72bc8b
MM
231 offset = le16_to_cpu(header->offset);
232
233 /* Validate received SKB. Check len and offset fields */
a9096fbc 234 if (offset != sizeof(struct esp_payload_header)) {
5e72bc8b 235 return -EINVAL;
a9096fbc 236 }
5e72bc8b
MM
237
238 len = le16_to_cpu(header->len);
a9096fbc 239 if (!len) {
5e72bc8b 240 return -EINVAL;
a9096fbc 241 }
5e72bc8b
MM
242
243 len += sizeof(struct esp_payload_header);
244
a9096fbc 245 if (len > SPI_BUF_SIZE) {
5e72bc8b 246 return -EINVAL;
a9096fbc
MM
247 }
248
5e72bc8b
MM
249 /* Trim SKB to actual size */
250 skb_trim(skb, len);
251
062be972
MM
252 if (header->if_type == ESP_PRIV_IF) {
253 process_priv_communication(skb);
254 return 0;
255 }
256
257 if (!data_path)
258 return -EPERM;
259
5e72bc8b
MM
260 /* enqueue skb for read_packet to pick it */
261 skb_queue_tail(&spi_context.rx_q, skb);
262
263 /* indicate reception of new packet */
264 esp_process_new_packet_intr(spi_context.adapter);
265
266 return 0;
267}
268
269static void esp_spi_work(struct work_struct *work)
270{
271 struct spi_transfer trans;
a9096fbc 272 struct sk_buff *tx_skb = NULL, *rx_skb = NULL;
5e72bc8b
MM
273 u8 *rx_buf;
274 int ret = 0;
a9096fbc 275 int trans_ready, rx_pending;
5e72bc8b 276
a9096fbc 277 mutex_lock(&spi_lock);
5e72bc8b 278
a9096fbc
MM
279 trans_ready = gpio_get_value(HANDSHAKE_PIN);
280 rx_pending = gpio_get_value(SPI_DATA_READY_PIN);
5e72bc8b 281
5e72bc8b 282
a9096fbc
MM
283 if (trans_ready) {
284 if (data_path)
285 tx_skb = skb_dequeue(&spi_context.tx_q);
5e72bc8b 286
a9096fbc
MM
287 if (rx_pending || tx_skb) {
288 memset(&trans, 0, sizeof(trans));
5e72bc8b 289
a9096fbc
MM
290 /* Setup and execute SPI transaction
291 * Tx_buf: Check if tx_q has valid buffer for transmission,
292 * else keep it blank
293 *
294 * Rx_buf: Allocate memory for incoming data. This will be freed
295 * immediately if received buffer is invalid.
296 * If it is a valid buffer, upper layer will free it.
297 * */
5e72bc8b 298
a9096fbc 299 /* Configure TX buffer if available */
5e72bc8b 300
a9096fbc
MM
301 if (tx_skb) {
302 trans.tx_buf = tx_skb->data;
303 } else {
304 tx_skb = esp_alloc_skb(SPI_BUF_SIZE);
305 trans.tx_buf = skb_put(tx_skb, SPI_BUF_SIZE);
306 }
5e72bc8b 307
a9096fbc
MM
308 /* Configure RX buffer */
309 rx_skb = esp_alloc_skb(SPI_BUF_SIZE);
310 rx_buf = skb_put(rx_skb, SPI_BUF_SIZE);
311
312 memset(rx_buf, 0, SPI_BUF_SIZE);
313
314 trans.rx_buf = rx_buf;
315 trans.len = SPI_BUF_SIZE;
316
317 ret = spi_sync_transfer(spi_context.esp_spi_dev, &trans, 1);
318
319 if (ret) {
320 printk(KERN_ERR "SPI Transaction failed: %d", ret);
321 dev_kfree_skb(rx_skb);
322 dev_kfree_skb(tx_skb);
323 } else {
324
325 /* Free rx_skb if received data is not valid */
326 if (process_rx_buf(rx_skb)) {
327 dev_kfree_skb(rx_skb);
328 }
5e72bc8b 329
a9096fbc
MM
330 if (tx_skb)
331 dev_kfree_skb(tx_skb);
332 }
333 }
5e72bc8b
MM
334 }
335
a9096fbc 336 mutex_unlock(&spi_lock);
5e72bc8b
MM
337}
338
339static int spi_init(void)
340{
341 int status = 0;
342 struct spi_board_info esp_board = {{0}};
343 struct spi_master *master = NULL;
344
345 strlcpy(esp_board.modalias, "esp_spi", sizeof(esp_board.modalias));
a9096fbc 346 esp_board.mode = SPI_MODE_2;
5e72bc8b 347 /* 10MHz */
a9096fbc 348 esp_board.max_speed_hz = 10000000;
5e72bc8b
MM
349 esp_board.bus_num = 0;
350 esp_board.chip_select = 0;
351
352 spi_context.spi_workqueue = create_workqueue("ESP_SPI_WORK_QUEUE");
353
354 if (!spi_context.spi_workqueue) {
355 spi_exit();
356 return -EFAULT;
357 }
358
359 INIT_WORK(&spi_context.spi_work, esp_spi_work);
360
361 skb_queue_head_init(&spi_context.tx_q);
362 skb_queue_head_init(&spi_context.rx_q);
363
364 master = spi_busnum_to_master(esp_board.bus_num);
365
366 if (!master) {
367 printk(KERN_ERR "Failed to obtain SPI master handle\n");
368 spi_exit();
369 return -ENODEV;
370 }
371
372 spi_context.esp_spi_dev = spi_new_device(master, &esp_board);
373
374 if (!spi_context.esp_spi_dev) {
375 printk(KERN_ERR "Failed to add new SPI device\n");
376 spi_exit();
377 return -ENODEV;
378 }
379
380 status = spi_setup(spi_context.esp_spi_dev);
381
382 if (status) {
383 printk (KERN_ERR "Failed to setup new SPI device");
384 spi_exit();
385 return status;
386 }
387
388 printk (KERN_INFO "ESP32 device is registered to SPI bus [%d]"
389 ",chip select [%d]\n", esp_board.bus_num,
390 esp_board.chip_select);
391
392 status = gpio_request(HANDSHAKE_PIN, "SPI_HANDSHAKE_PIN");
393
394 if (status) {
395 printk (KERN_ERR "Failed to obtain GPIO");
396 spi_exit();
397 return status;
398 }
399
400 status = gpio_direction_input(HANDSHAKE_PIN);
401
402 if (status) {
403 printk (KERN_ERR "Failed to set GPIO direction");
404 spi_exit();
405 return status;
406 }
407
408 status = request_irq(SPI_IRQ, spi_interrupt_handler,
409 IRQF_SHARED | IRQF_TRIGGER_RISING,
410 "ESP_SPI", spi_context.esp_spi_dev);
411 if (status) {
412 printk (KERN_ERR "Failed to request IRQ");
413 spi_exit();
414 return status;
415 }
416
a9096fbc
MM
417 status = gpio_request(SPI_DATA_READY_PIN, "SPI_DATA_READY_PIN");
418 if (status) {
419 printk (KERN_ERR "Failed to obtain GPIO");
420 spi_exit();
421 return status;
422 }
423
424 status = gpio_direction_input(SPI_DATA_READY_PIN);
425 if (status) {
426 printk (KERN_ERR "Failed to set GPIO direction");
427 spi_exit();
428 return status;
429 }
430
431 status = request_irq(SPI_DATA_READY_IRQ, spi_data_ready_interrupt_handler,
432 IRQF_SHARED | IRQF_TRIGGER_RISING,
433 "ESP_SPI_DATA_READY", spi_context.esp_spi_dev);
434 if (status) {
435 printk (KERN_ERR "Failed to request IRQ");
436 spi_exit();
437 return status;
438 }
439
c746d295 440 open_data_path();
5e72bc8b
MM
441
442#ifdef CONFIG_SUPPORT_ESP_SERIAL
443 status = esp_serial_init((void *) spi_context.adapter);
444 if (status != 0) {
445 spi_exit();
446 printk(KERN_ERR "Error initialising serial interface\n");
447 return status;
448 }
449#endif
450
451 status = esp_add_card(spi_context.adapter);
452 if (status) {
453 spi_exit();
454 printk (KERN_ERR "Failed to add card\n");
455 return status;
456 }
457
5e72bc8b
MM
458 msleep(200);
459
460 return status;
461}
462
463static void spi_exit(void)
464{
c746d295 465 disable_irq(SPI_IRQ);
a9096fbc 466 disable_irq(SPI_DATA_READY_IRQ);
c746d295
MM
467 close_data_path();
468 msleep(200);
469
470 skb_queue_purge(&spi_context.tx_q);
471 skb_queue_purge(&spi_context.rx_q);
472
5e72bc8b
MM
473 if (spi_context.spi_workqueue) {
474 destroy_workqueue(spi_context.spi_workqueue);
c746d295 475 spi_context.spi_workqueue = NULL;
5e72bc8b
MM
476 }
477
478 esp_serial_cleanup();
479 esp_remove_card(spi_context.adapter);
480
481 if (spi_context.adapter->hcidev)
482 esp_deinit_bt(spi_context.adapter);
483
c746d295 484 free_irq(SPI_IRQ, spi_context.esp_spi_dev);
a9096fbc 485 free_irq(SPI_DATA_READY_IRQ, spi_context.esp_spi_dev);
c746d295 486
5e72bc8b 487 gpio_free(HANDSHAKE_PIN);
a9096fbc 488 gpio_free(SPI_DATA_READY_PIN);
5e72bc8b
MM
489
490 if (spi_context.esp_spi_dev)
491 spi_unregister_device(spi_context.esp_spi_dev);
492
493 memset(&spi_context, 0, sizeof(spi_context));
494}
495
496int esp_init_interface_layer(struct esp_adapter *adapter)
497{
498 if (!adapter)
499 return -EINVAL;
500
501 memset(&spi_context, 0, sizeof(spi_context));
502
503 adapter->if_context = &spi_context;
504 adapter->if_ops = &if_ops;
062be972 505 adapter->if_type = ESP_IF_TYPE_SPI;
5e72bc8b
MM
506 spi_context.adapter = adapter;
507
508 return spi_init();
509}
510
511void esp_deinit_interface_layer(void)
512{
513 spi_exit();
514}
This page took 0.089379 seconds and 4 git commands to generate.