From d8c9cb8d892cd0695f69fb7887e17e1abf974d0a Mon Sep 17 00:00:00 2001 From: Gerson Fernando Budke Date: Thu, 22 Oct 2020 21:23:49 -0300 Subject: [PATCH] drivers: wifi: eswifi: Add uart bus interface Add uart bus interface to extended esWIFI driver. This enables all Inventek modules with IWIN AT Commands firmware. Signed-off-by: Gerson Fernando Budke --- CODEOWNERS | 2 +- drivers/wifi/eswifi/CMakeLists.txt | 4 +- drivers/wifi/eswifi/Kconfig.eswifi | 15 ++ drivers/wifi/eswifi/eswifi_bus_uart.c | 253 ++++++++++++++++++++ drivers/wifi/eswifi/eswifi_core.c | 5 + dts/bindings/wifi/inventek,eswifi-uart.yaml | 18 ++ 6 files changed, 295 insertions(+), 2 deletions(-) create mode 100644 drivers/wifi/eswifi/eswifi_bus_uart.c create mode 100644 dts/bindings/wifi/inventek,eswifi-uart.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 3c08d062032..81c1ab59fa9 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -286,7 +286,7 @@ /drivers/watchdog/*gecko* @oanerer /drivers/watchdog/wdt_handlers.c @andrewboie /drivers/wifi/ @jukkar @tbursztyka @pfalcon -/drivers/wifi/eswifi/ @loicpoulain +/drivers/wifi/eswifi/ @loicpoulain @nandojve /drivers/wifi/winc1500/ @kludentwo /dts/arc/ @abrodkin @ruuddw @iriszzw /dts/arm/atmel/sam4e* @nandojve diff --git a/drivers/wifi/eswifi/CMakeLists.txt b/drivers/wifi/eswifi/CMakeLists.txt index 699236578d2..bc647daf0bf 100644 --- a/drivers/wifi/eswifi/CMakeLists.txt +++ b/drivers/wifi/eswifi/CMakeLists.txt @@ -10,11 +10,13 @@ if(CONFIG_WIFI_ESWIFI) zephyr_sources( eswifi_core.c - eswifi_bus_spi.c eswifi_offload.c eswifi_socket.c ) + zephyr_sources_ifdef(CONFIG_WIFI_ESWIFI_BUS_SPI eswifi_bus_spi.c) + zephyr_sources_ifdef(CONFIG_WIFI_ESWIFI_BUS_UART eswifi_bus_uart.c) + zephyr_sources_ifdef(CONFIG_WIFI_ESWIFI_SHELL eswifi_shell.c) zephyr_sources_ifdef(CONFIG_NET_SOCKETS_OFFLOAD eswifi_socket_offload.c) diff --git a/drivers/wifi/eswifi/Kconfig.eswifi b/drivers/wifi/eswifi/Kconfig.eswifi index 2a5b91e97d4..6468b98113a 100644 --- a/drivers/wifi/eswifi/Kconfig.eswifi +++ b/drivers/wifi/eswifi/Kconfig.eswifi @@ -10,9 +10,24 @@ menuconfig WIFI_ESWIFI select NET_OFFLOAD select NET_SOCKETS select NET_SOCKETS_OFFLOAD + select GPIO if WIFI_ESWIFI +choice WIFI_ESWIFI_BUS + bool "Select BUS interface" + default WIFI_ESWIFI_BUS_SPI + +config WIFI_ESWIFI_BUS_SPI + bool "SPI Bus interface" + select SPI + +config WIFI_ESWIFI_BUS_UART + bool "UART Bus interface" + select SERIAL + +endchoice + config WIFI_ESWIFI_THREAD_PRIO int "esWiFi threads priority" default 2 diff --git a/drivers/wifi/eswifi/eswifi_bus_uart.c b/drivers/wifi/eswifi/eswifi_bus_uart.c new file mode 100644 index 00000000000..69f312b34b3 --- /dev/null +++ b/drivers/wifi/eswifi/eswifi_bus_uart.c @@ -0,0 +1,253 @@ +/** + * Copyright (c) 2018 Linaro + * Copyright (c) 2020 ATL Electronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT inventek_eswifi_uart + +#include "eswifi_log.h" +LOG_MODULE_DECLARE(LOG_MODULE_NAME); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "eswifi.h" + +#define ESWIFI_RING_BUF_SIZE 2048 + +enum eswifi_uart_fsm { + ESWIFI_UART_FSM_WAIT_CR, + ESWIFI_UART_FSM_WAIT_LF, + ESWIFI_UART_FSM_WAIT_MARK, + ESWIFI_UART_FSM_WAIT_SPACE, + ESWIFI_UART_FSM_END, +}; + +struct eswifi_uart_data { + const struct device *dev; + enum eswifi_uart_fsm fsm; + size_t rx_count; + size_t rx_buf_size; + char *rx_buf; + + /* RX Ring Buf */ + uint8_t iface_rb_buf[ESWIFI_RING_BUF_SIZE]; + struct ring_buf rx_rb; +}; + +static struct eswifi_uart_data eswifi_uart0; /* Static instance */ + +static void eswifi_iface_uart_flush(struct eswifi_uart_data *uart) +{ + uint8_t c; + + while (uart_fifo_read(uart->dev, &c, 1) > 0) { + continue; + } +} + +static void eswifi_iface_uart_isr(const struct device *uart_dev, + void *user_data) +{ + struct eswifi_uart_data *uart = &eswifi_uart0; /* Static instance */ + int rx = 0; + uint8_t *dst; + uint32_t partial_size = 0; + uint32_t total_size = 0; + + ARG_UNUSED(user_data); + + while (uart_irq_update(uart->dev) && + uart_irq_rx_ready(uart->dev)) { + if (!partial_size) { + partial_size = ring_buf_put_claim(&uart->rx_rb, &dst, + UINT32_MAX); + } + if (!partial_size) { + LOG_ERR("Rx buffer doesn't have enough space"); + eswifi_iface_uart_flush(uart); + break; + } + + rx = uart_fifo_read(uart->dev, dst, partial_size); + if (rx <= 0) { + continue; + } + + dst += rx; + total_size += rx; + partial_size -= rx; + } + + ring_buf_put_finish(&uart->rx_rb, total_size); +} + +static char get_fsm_char(int fsm) +{ + switch (fsm) { + case ESWIFI_UART_FSM_WAIT_CR: + return('C'); + case ESWIFI_UART_FSM_WAIT_LF: + return('L'); + case ESWIFI_UART_FSM_WAIT_MARK: + return('M'); + case ESWIFI_UART_FSM_WAIT_SPACE: + return('S'); + case ESWIFI_UART_FSM_END: + return('E'); + } + + return('?'); +} + +static int eswifi_uart_get_resp(struct eswifi_uart_data *uart) +{ + uint8_t c; + + while (ring_buf_get(&uart->rx_rb, &c, 1) > 0) { + LOG_DBG("FSM: %c, RX: 0x%02x : %c", + get_fsm_char(uart->fsm), c, c); + + if (uart->rx_buf_size > 0) { + uart->rx_buf[uart->rx_count++] = c; + + if (uart->rx_count == uart->rx_buf_size) { + return -ENOMEM; + } + } + + switch (uart->fsm) { + case ESWIFI_UART_FSM_WAIT_CR: + if (c == '\r') { + uart->fsm = ESWIFI_UART_FSM_WAIT_LF; + } + break; + case ESWIFI_UART_FSM_WAIT_LF: + if (c == '\n') { + uart->fsm = ESWIFI_UART_FSM_WAIT_MARK; + } else if (c != '\r') { + uart->fsm = ESWIFI_UART_FSM_WAIT_CR; + } + break; + case ESWIFI_UART_FSM_WAIT_MARK: + if (c == '>') { + uart->fsm = ESWIFI_UART_FSM_WAIT_SPACE; + } else if (c == '\r') { + uart->fsm = ESWIFI_UART_FSM_WAIT_LF; + } else { + uart->fsm = ESWIFI_UART_FSM_WAIT_CR; + } + break; + case ESWIFI_UART_FSM_WAIT_SPACE: + if (c == ' ') { + uart->fsm = ESWIFI_UART_FSM_END; + } else if (c == '\r') { + uart->fsm = ESWIFI_UART_FSM_WAIT_LF; + } else { + uart->fsm = ESWIFI_UART_FSM_WAIT_CR; + } + break; + default: + break; + } + } + + return 0; +} + +static int eswifi_uart_wait_prompt(struct eswifi_uart_data *uart) +{ + unsigned int max_retries = 60 * 1000; /* 1 minute */ + int err; + + while (--max_retries) { + err = eswifi_uart_get_resp(uart); + if (err) { + LOG_DBG("Err: 0x%08x - %d", err, err); + return err; + } + + if (uart->fsm == ESWIFI_UART_FSM_END) { + LOG_DBG("Success!"); + return uart->rx_count; + } + + /* allow other threads to be scheduled */ + k_sleep(K_MSEC(1)); + } + + LOG_DBG("Timeout"); + return -ETIMEDOUT; +} + +static int eswifi_uart_request(struct eswifi_dev *eswifi, char *cmd, + size_t clen, char *rsp, size_t rlen) +{ + struct eswifi_uart_data *uart = eswifi->bus_data; + int count; + int err; + + LOG_DBG("cmd=%p (%u byte), rsp=%p (%u byte)", cmd, clen, rsp, rlen); + + /* Send CMD */ + for (count = 0; count < clen; count++) { + uart_poll_out(uart->dev, cmd[count]); + } + + uart->fsm = ESWIFI_UART_FSM_WAIT_CR; + uart->rx_count = 0; + uart->rx_buf = rsp; + uart->rx_buf_size = rlen; + + err = eswifi_uart_wait_prompt(uart); + + if (err > 0) { + LOG_HEXDUMP_DBG(uart->rx_buf, uart->rx_count, "Stream"); + } + + return err; +} + +int eswifi_uart_init(struct eswifi_dev *eswifi) +{ + struct eswifi_uart_data *uart = &eswifi_uart0; /* Static instance */ + + uart->dev = device_get_binding(DT_INST_BUS_LABEL(0)); + if (!uart->dev) { + LOG_ERR("Failed to initialize uart driver"); + return -ENODEV; + } + + eswifi->bus_data = uart; + + uart_irq_rx_disable(uart->dev); + uart_irq_tx_disable(uart->dev); + eswifi_iface_uart_flush(uart); + uart_irq_callback_set(uart->dev, eswifi_iface_uart_isr); + uart_irq_rx_enable(uart->dev); + + ring_buf_init(&uart->rx_rb, sizeof(uart->iface_rb_buf), + uart->iface_rb_buf); + + LOG_DBG("success"); + + return 0; +} + +static struct eswifi_bus_ops eswifi_bus_ops_uart = { + .init = eswifi_uart_init, + .request = eswifi_uart_request, +}; + +struct eswifi_bus_ops *eswifi_get_bus(void) +{ + return &eswifi_bus_ops_uart; +} diff --git a/drivers/wifi/eswifi/eswifi_core.c b/drivers/wifi/eswifi/eswifi_core.c index ea6ae8ff1f0..a82b2b51ee7 100644 --- a/drivers/wifi/eswifi/eswifi_core.c +++ b/drivers/wifi/eswifi/eswifi_core.c @@ -4,7 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#if defined(CONFIG_WIFI_ESWIFI_BUS_UART) +#define DT_DRV_COMPAT inventek_eswifi_uart +#else #define DT_DRV_COMPAT inventek_eswifi +#endif + #include "eswifi_log.h" LOG_MODULE_REGISTER(LOG_MODULE_NAME); diff --git a/dts/bindings/wifi/inventek,eswifi-uart.yaml b/dts/bindings/wifi/inventek,eswifi-uart.yaml new file mode 100644 index 00000000000..6bf33085704 --- /dev/null +++ b/dts/bindings/wifi/inventek,eswifi-uart.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2018, Linaro Limited +# Copyright (c) 2020, ATL Electronics +# SPDX-License-Identifier: Apache-2.0 + +description: es-WiFi module (uart firmware interface) + +compatible: "inventek,eswifi-uart" + +include: uart-device.yaml + +properties: + resetn-gpios: + type: phandle-array + required: true + + wakeup-gpios: + type: phandle-array + required: false