PWD := $(shell pwd)
obj-m := $(MODULE_NAME).o
-$(MODULE_NAME)-y := esp_bt.o main.o esp_cmd.o esp_wpa_utils.o esp_cfg80211.o esp_stats.o $(module_objects)
+$(MODULE_NAME)-y := esp_bt.o main.o esp_cmd.o esp_utils.o esp_cfg80211.o esp_stats.o $(module_objects)
all: clean
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNEL) M=$(PWD) modules
hdev->dev_type = HCI_PRIMARY;
- if (adapter->if_type == ESP_IF_TYPE_SDIO)
- SET_HCIDEV_DEV(hdev, adapter->dev);
+ SET_HCIDEV_DEV(hdev, adapter->dev);
ret = hci_register_dev(hdev);
if (ret < 0) {
}
}
-int esp_cfg80211_register(struct esp_adapter *adapter)
+int esp_add_wiphy(struct esp_adapter *adapter)
{
struct wiphy *wiphy;
struct esp_device *esp_dev;
int ret = 0;
+ if (!adapter) {
+ esp_info("adapter not yet initialized\n");
+ return -EINVAL;
+ }
+
wiphy = wiphy_new(&esp_cfg80211_ops, sizeof(struct esp_device));
if (!wiphy) {
return ret;
}
-int esp_mark_disconnect(struct esp_wifi_device *priv, uint16_t reason,
- uint8_t locally_disconnect)
+int esp_remove_wiphy(struct esp_adapter *adapter)
+{
+ if (adapter && adapter->wiphy) {
+ wiphy_unregister(adapter->wiphy);
+ wiphy_free(adapter->wiphy);
+ adapter->wiphy = NULL;
+ }
+
+ return 0;
+}
+
+int esp_mark_disconnect(struct esp_wifi_device *priv, uint16_t reason, uint8_t locally_disconnect)
{
- if (priv && priv->ndev)
- if (priv->ndev->reg_state == NETREG_REGISTERED)
- CFG80211_DISCONNECTED(priv->ndev, reason, NULL, 0, locally_disconnect,
- GFP_KERNEL);
+ if (priv && priv->ndev && wireless_dev_current_bss_exists(&priv->wdev))
+ CFG80211_DISCONNECTED(priv->ndev, reason, NULL, 0, locally_disconnect, GFP_KERNEL);
+
return 0;
}
-int esp_mark_scan_done_and_disconnect(struct esp_wifi_device *priv,
- uint8_t locally_disconnect)
+int esp_mark_scan_done_and_disconnect(struct esp_wifi_device *priv, uint8_t locally_disconnect)
{
if (!priv)
return -EINVAL;
- ESP_MARK_SCAN_DONE(priv, true);
+ if (priv->wdev.iftype != NL80211_IFTYPE_STATION)
+ return 0;
+ ESP_MARK_SCAN_DONE(priv, true);
ESP_CANCEL_SCHED_SCAN();
-
- esp_mark_disconnect(priv, 0, locally_disconnect);
-
- return 0;
+ return esp_mark_disconnect(priv, 0, locally_disconnect);
}
#include "utils.h"
#include "esp_cmd.h"
#include "esp_api.h"
-#include "esp_wpa_utils.h"
+#include "esp_utils.h"
#include "esp.h"
#include "esp_cfg80211.h"
#include "esp_kernel_port.h"
esp_err("unsupported command code\n");
return NULL;
}
+ if (!test_bit(ESP_CMD_INIT_DONE, &adapter->state_flags)) {
+ esp_err("command queue init is not done yet\n");
+ return NULL;
+ }
node = get_free_cmd_node(adapter);
int esp_commands_teardown(struct esp_adapter *adapter)
{
-#define MAX_DEINIT_RETRY 5
uint8_t iface_idx = 0;
- struct esp_wifi_device *priv = NULL;
if (!adapter) {
return -EINVAL;
}
set_bit(ESP_CLEANUP_IN_PROGRESS, &adapter->state_flags);
-
- if (!test_bit(ESP_CMD_INIT_DONE, &adapter->state_flags))
- return 0;
-
+ clear_bit(ESP_CMD_INIT_DONE, &adapter->state_flags);
for (iface_idx = 0; iface_idx < ESP_MAX_INTERFACE; iface_idx++) {
-
- priv = adapter->priv[iface_idx];
-
- if (!priv)
- continue;
-
- esp_mark_scan_done_and_disconnect(priv, false);
-
- esp_port_close(priv);
+ esp_mark_scan_done_and_disconnect(adapter->priv[iface_idx], false);
+ esp_port_close(adapter->priv[iface_idx]);
}
destroy_cmd_wq(adapter);
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Espressif Systems Wireless LAN device driver
+ *
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ */
+#include "utils.h"
+#include "esp_wpa_utils.h"
+
+
+int wpa_cipher_to_alg(int cipher)
+{
+ switch (cipher) {
+ case WLAN_CIPHER_SUITE_CCMP:
+ return WIFI_WPA_ALG_CCMP;
+#ifdef CONFIG_GCMP
+ case WLAN_CIPHER_SUITE_GCMP_256:
+ case WLAN_CIPHER_SUITE_GCMP:
+ return WIFI_WPA_ALG_GCMP;
+#endif
+ case WLAN_CIPHER_SUITE_TKIP:
+ return WIFI_WPA_ALG_TKIP;
+ case WLAN_CIPHER_SUITE_WEP104:
+ return WIFI_WPA_ALG_WEP104;
+ case WLAN_CIPHER_SUITE_WEP40:
+ return WIFI_WPA_ALG_WEP40;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ return WIFI_WPA_ALG_IGTK;
+ }
+ return WIFI_WPA_ALG_NONE;
+}
+
+char * esp_chipname_from_id(int chipset_id)
+{
+ if (chipset_id == ESP_FIRMWARE_CHIP_ESP32)
+ return "ESP32";
+ if (chipset_id == ESP_FIRMWARE_CHIP_ESP32S2)
+ return "ESP32-S2";
+ if (chipset_id == ESP_FIRMWARE_CHIP_ESP32S3)
+ return "ESP32-S3";
+ if (chipset_id == ESP_FIRMWARE_CHIP_ESP32C2)
+ return "ESP32-C2";
+ if (chipset_id == ESP_FIRMWARE_CHIP_ESP32C3)
+ return "ESP32-C3";
+ if (chipset_id == ESP_FIRMWARE_CHIP_ESP32C6)
+ return "ESP32-C6";
+
+ return "Unknown Chip";
+}
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Espressif Systems Wireless LAN device driver
- *
- * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
- *
- */
-#include "utils.h"
-#include "esp_wpa_utils.h"
-
-
-int wpa_cipher_to_alg(int cipher)
-{
- switch (cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- return WIFI_WPA_ALG_CCMP;
-#ifdef CONFIG_GCMP
- case WLAN_CIPHER_SUITE_GCMP_256:
- case WLAN_CIPHER_SUITE_GCMP:
- return WIFI_WPA_ALG_GCMP;
-#endif
- case WLAN_CIPHER_SUITE_TKIP:
- return WIFI_WPA_ALG_TKIP;
- case WLAN_CIPHER_SUITE_WEP104:
- return WIFI_WPA_ALG_WEP104;
- case WLAN_CIPHER_SUITE_WEP40:
- return WIFI_WPA_ALG_WEP40;
- case WLAN_CIPHER_SUITE_AES_CMAC:
- return WIFI_WPA_ALG_IGTK;
- }
- return WIFI_WPA_ALG_NONE;
-}
-
-int wpa_cipher_key_len(int cipher)
-{
- switch (cipher) {
- case WLAN_CIPHER_SUITE_TKIP:
-#ifdef CONFIG_GCMP
- case WLAN_CIPHER_GCMP_SUITE_256:
-#endif
-#ifdef CONFIG_GMAC
- case WLAN_CIPHER_BIP_GMAC_SUITE_256:
-#endif
- return 32;
- case WLAN_CIPHER_SUITE_CCMP:
-#ifdef CONFIG_GCMP
- case WLAN_CIPHER_SUITE_GCMP:
-#endif
-#ifdef CONFIG_GMAC
- case WLAN_CIPHER_SUITE_BIP_GMAC_128:
-#endif
-#if 0
- case WLAN_CIPHER_SUITE_AES_128_CMAC:
- return 16;
-#endif
- case WLAN_CIPHER_SUITE_WEP104:
- return 13;
- case WLAN_CIPHER_SUITE_WEP40:
- return 5;
- }
-
- return 0;
-}
struct work_struct events_work;
unsigned long state_flags;
+ int chipset;
};
struct esp_device {
do { \
int ret = (x); \
if (!!(ret)) { \
- esp_err("esp32: %s failure, ret: %d\n", #x, ret); \
+ esp_err("%s failure, ret: %d\n", #x, ret); \
return ret; \
} \
} while (0); \
u8 esp_is_bt_supported_over_sdio(u32 cap);
void esp_tx_pause(struct esp_wifi_device *priv);
void esp_tx_resume(struct esp_wifi_device *priv);
-void process_event_esp_bootup(struct esp_adapter *adapter, u8 *evt_buf, u8 len);
-int process_fw_data(struct fw_data *fw_p);
void esp_init_priv(struct net_device *ndev);
void esp_port_open(struct esp_wifi_device *priv);
void esp_port_close(struct esp_wifi_device *priv);
void process_capabilities(struct esp_adapter *adapter);
void process_test_capabilities(u8 cap);
int esp_is_tx_queue_paused(struct esp_wifi_device *priv);
+int esp_deinit_module(struct esp_adapter *adapter);
+int esp_validate_chipset(struct esp_adapter *adapter, u8 chipset);
+int esp_adjust_spi_clock(struct esp_adapter *adapter, u8 spi_clk_mhz);
#endif
unsigned char name_assign_type,
enum nl80211_iftype type,
struct vif_params *params);
-int esp_cfg80211_register(struct esp_adapter *adapter);
-
+int esp_add_wiphy(struct esp_adapter *adapter);
+int esp_remove_wiphy(struct esp_adapter *adapter);
int esp_mark_disconnect(struct esp_wifi_device *priv, uint16_t reason,
uint8_t locally_disconnect);
int esp_mark_scan_done_and_disconnect(struct esp_wifi_device *priv,
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Espressif Systems Wireless LAN device driver
+ *
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ */
+#ifndef __esp_utils_h_
+#define __esp_utils_h_
+
+#include "esp.h"
+
+#define WPA_CIPHER_NONE BIT(0)
+#define WPA_CIPHER_WEP40 BIT(7)
+#define WPA_CIPHER_WEP104 BIT(8)
+#define WPA_CIPHER_TKIP BIT(1)
+#define WPA_CIPHER_CCMP BIT(3)
+#define WPA_CIPHER_AES_128_CMAC BIT(5)
+#define WPA_CIPHER_SMS4 BIT(10)
+#define WPA_CIPHER_GCMP BIT(11)
+#define WPA_CIPHER_GCMP_256 BIT(12)
+#define WPA_CIPHER_BIP_GMAC_128 BIT(13)
+#define WPA_CIPHER_BIP_GMAC_256 BIT(14)
+
+enum wpa_alg {
+ WIFI_WPA_ALG_NONE = 0,
+ WIFI_WPA_ALG_WEP40 = 1,
+ WIFI_WPA_ALG_TKIP = 2,
+ WIFI_WPA_ALG_CCMP = 3,
+ WIFI_WAPI_ALG_SMS4 = 4,
+ WIFI_WPA_ALG_WEP104 = 5,
+ WIFI_WPA_ALG_WEP = 6,
+ WIFI_WPA_ALG_IGTK = 7,
+ WIFI_WPA_ALG_PMK = 8,
+ WIFI_WPA_ALG_GCMP = 9,
+};
+
+int wpa_cipher_to_alg(int cipher);
+
+char * esp_chipname_from_id(int chipset_id);
+
+#endif
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Espressif Systems Wireless LAN device driver
- *
- * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
- *
- */
-#ifndef __esp_wpa_utils_h_
-#define __esp_wpa_utils_h_
-
-#include "esp.h"
-
-#define WPA_CIPHER_NONE BIT(0)
-#define WPA_CIPHER_WEP40 BIT(7)
-#define WPA_CIPHER_WEP104 BIT(8)
-#define WPA_CIPHER_TKIP BIT(1)
-#define WPA_CIPHER_CCMP BIT(3)
-#define WPA_CIPHER_AES_128_CMAC BIT(5)
-#define WPA_CIPHER_SMS4 BIT(10)
-#define WPA_CIPHER_GCMP BIT(11)
-#define WPA_CIPHER_GCMP_256 BIT(12)
-#define WPA_CIPHER_BIP_GMAC_128 BIT(13)
-#define WPA_CIPHER_BIP_GMAC_256 BIT(14)
-
-enum wpa_alg {
- WIFI_WPA_ALG_NONE = 0,
- WIFI_WPA_ALG_WEP40 = 1,
- WIFI_WPA_ALG_TKIP = 2,
- WIFI_WPA_ALG_CCMP = 3,
- WIFI_WAPI_ALG_SMS4 = 4,
- WIFI_WPA_ALG_WEP104 = 5,
- WIFI_WPA_ALG_WEP = 6,
- WIFI_WPA_ALG_IGTK = 7,
- WIFI_WPA_ALG_PMK = 8,
- WIFI_WPA_ALG_GCMP = 9,
-};
-
-int wpa_cipher_to_alg(int cipher);
-
-
-#endif
}
}
-void process_capabilities(struct esp_adapter *adapter)
+void init_bt(struct esp_adapter *adapter)
{
- esp_info("ESP peripheral capabilities: 0x%x\n", adapter->capabilities);
-
- /* Reset BT */
- esp_deinit_bt(adapter);
if ((adapter->capabilities & ESP_BT_SPI_SUPPORT) ||
(adapter->capabilities & ESP_BT_SDIO_SUPPORT)) {
static int check_esp_version(struct fw_version *ver)
{
- esp_info("esp32: ESP Firmware version: %u.%u.%u\n",
+ esp_info("ESP Firmware version: %u.%u.%u\n",
ver->major1, ver->major2, ver->minor);
if (!ver->major1) {
esp_err("Incompatible ESP firmware release detected, Please use correct ESP-Hosted branch/compatible release\n");
}
}
-int process_fw_data(struct fw_data *fw_p)
+static int process_fw_data(struct fw_data *fw_p, int tag_len)
{
- if (!fw_p) {
- esp_err("Incomplete/incorrect bootup event received\n");
+ if (tag_len != sizeof(struct fw_data)) {
+ esp_err("Length not matching to firmware data size\n");
return -1;
}
esp_info("ESP chipset's last reset cause:\n");
print_reset_reason(le32_to_cpu(fw_p->last_reset_reason));
+
return check_esp_version(&fw_p->version);
}
+int process_event_esp_bootup(struct esp_adapter *adapter, u8 *evt_buf, u8 len)
+{
+ int len_left = len, tag_len, ret = 0;
+ u8 *pos;
+
+ if (!adapter || !evt_buf)
+ return -1;
+
+ if (len_left >= 64) {
+ esp_info("ESP init event len looks unexpected: %u (>=64)\n", len_left);
+ esp_info("You probably facing timing mismatch at transport layer\n");
+ }
+
+ clear_bit(ESP_INIT_DONE, &adapter->state_flags);
+ /* Deinit module if already initialized */
+ esp_deinit_module(adapter);
+
+ pos = evt_buf;
+
+ while (len_left > 0) {
+ tag_len = *(pos + 1);
+
+ esp_info("Bootup Event tag: %d\n", *pos);
+
+ switch (*pos) {
+ case ESP_BOOTUP_CAPABILITY:
+ adapter->capabilities = *(pos + 2);
+ break;
+ case ESP_BOOTUP_FIRMWARE_CHIP_ID:
+ ret = esp_validate_chipset(adapter, *(pos + 2));
+ break;
+ case ESP_BOOTUP_FW_DATA:
+ ret = process_fw_data((struct fw_data *)(pos + 2), tag_len);
+ break;
+ case ESP_BOOTUP_SPI_CLK_MHZ:
+ ret = esp_adjust_spi_clock(adapter, *(pos + 2));
+ break;
+ default:
+ esp_warn("Unsupported tag=%x in bootup event\n", *pos);
+ }
+
+ if (ret < 0) {
+ esp_err("failed to process tag=%x in bootup event\n", *pos);
+ return -1;
+ }
+ pos += (tag_len + 2);
+ len_left -= (tag_len + 2);
+ }
+
+ if (esp_add_card(adapter)) {
+ esp_err("network iterface init failed\n");
+ return -1;
+ }
+ init_bt(adapter);
+ set_bit(ESP_INIT_DONE, &adapter->state_flags);
+ print_capabilities(adapter->capabilities);
+
+ return 0;
+}
+
static int esp_open(struct net_device *ndev)
{
return 0;
static int esp_stop(struct net_device *ndev)
{
- struct esp_wifi_device *priv = netdev_priv(ndev);
-
- ESP_MARK_SCAN_DONE(priv, true);
- return 0;
+ return esp_mark_scan_done_and_disconnect(netdev_priv(ndev), false);
}
static struct net_device_stats *esp_get_stats(struct net_device *ndev)
INTERFACE_HEADER_PADDING, 4);
}
-static int add_network_iface(void)
+static int esp_add_network_ifaces(struct esp_adapter *adapter)
{
- int ret = 0;
- struct esp_adapter *adapter = esp_get_adapter();
struct wireless_dev *wdev = NULL;
if (!adapter) {
return -EINVAL;
}
- ret = esp_cfg80211_register(adapter);
- if (ret) {
- esp_err("Failed to register with cfg80211 (err code 0x%x)\n", ret);
- return ret;
- }
-
rtnl_lock();
wdev = esp_cfg80211_add_iface(adapter->wiphy, "espsta%d", 1, NL80211_IFTYPE_STATION, NULL);
rtnl_unlock();
int esp_add_card(struct esp_adapter *adapter)
{
RET_ON_FAIL(esp_commands_setup(adapter));
-
- RET_ON_FAIL(add_network_iface());
+ RET_ON_FAIL(esp_add_wiphy(adapter));
+ RET_ON_FAIL(esp_add_network_ifaces(adapter));
return 0;
}
-void esp_remove_network_interfaces(struct esp_adapter *adapter)
+static int esp_remove_network_ifaces(struct esp_adapter *adapter)
{
uint8_t iface_idx = 0;
struct net_device *ndev = NULL;
struct esp_wifi_device *priv = NULL;
+ rtnl_lock();
+ if (adapter->wiphy)
+ cfg80211_shutdown_all_interfaces(adapter->wiphy);
+
for (iface_idx = 0; iface_idx < ESP_MAX_INTERFACE; iface_idx++) {
priv = adapter->priv[iface_idx];
-
if (!priv)
continue;
-
if (!test_bit(ESP_NETWORK_UP, &priv->priv_flags))
continue;
- /* stop and unregister network */
ndev = priv->ndev;
+ if (ndev)
+ ndev->needs_free_netdev = true;
+ wiphy_lock(adapter->wiphy);
+ cfg80211_unregister_wdev(&priv->wdev);
+ wiphy_unlock(adapter->wiphy);
+ adapter->priv[iface_idx] = NULL;
+ }
+ rtnl_unlock();
- if (ndev) {
+ return 0;
+}
- if (netif_carrier_ok(ndev))
- netif_carrier_off(ndev);
+static int stop_network_iface(struct esp_wifi_device *priv)
+{
+ struct net_device *ndev;
- netif_device_detach(ndev);
+ if (!priv)
+ return 0;
- if (ndev->reg_state == NETREG_REGISTERED) {
- unregister_inetaddr_notifier(&(adapter->priv[0]->nb));
- unregister_netdev(ndev);
- free_netdev(ndev);
- ndev = NULL;
- }
- }
- clear_bit(ESP_NETWORK_UP, &priv->priv_flags);
- }
+ if (!test_bit(ESP_NETWORK_UP, &priv->priv_flags))
+ return 0;
+
+ esp_port_close(priv);
- if (adapter->wiphy) {
+ /* stop and unregister network */
+ ndev = priv->ndev;
- wiphy_unregister(adapter->wiphy);
- wiphy_free(adapter->wiphy);
- adapter->wiphy = NULL;
+ if (ndev) {
+ netif_carrier_off(ndev);
+ netif_device_detach(ndev);
+
+ unregister_inetaddr_notifier(&(priv->nb));
}
+
+ return 0;
}
-int esp_remove_card(struct esp_adapter *adapter)
+int esp_stop_network_ifaces(struct esp_adapter *adapter)
{
uint8_t iface_idx = 0;
+ for (iface_idx = 0; iface_idx < ESP_MAX_INTERFACE; iface_idx++) {
+ stop_network_iface(adapter->priv[iface_idx]);
+ }
+
+ return 0;
+}
+
+int esp_remove_card(struct esp_adapter *adapter)
+{
if (!adapter) {
return 0;
}
+ esp_stop_network_ifaces(adapter);
+ /* BT may have been initialized after fw bootup event, deinit it */
esp_deinit_bt(adapter);
-
esp_commands_teardown(adapter);
-
- esp_remove_network_interfaces(adapter);
-
- for (iface_idx = 0; iface_idx < ESP_MAX_INTERFACE; iface_idx++) {
- esp_port_close(adapter->priv[iface_idx]);
- adapter->priv[iface_idx] = NULL;
- }
+ esp_remove_network_ifaces(adapter);
+ esp_remove_wiphy(adapter);
return 0;
}
return;
}
- esp_info("\nReceived ESP bootup event\n");
+ esp_info("Received ESP bootup event\n");
process_event_esp_bootup(adapter, evt->data, evt->len);
}
struct event_header *header = NULL;
if (!skb || !adapter) {
- esp_err("esp32: Incorrect event data!\n");
+ esp_err("Incorrect event data!\n");
return -1;
}
#include "esp_bt_api.h"
#include <linux/kthread.h>
#include "esp_stats.h"
+#include "esp_utils.h"
#include "include/esp_kernel_port.h"
#define MAX_WRITE_RETRIES 2
return ret;
}
+int esp_deinit_module(struct esp_adapter *adapter)
+{
+ /* Second & onward bootup cleanup is not required for SDIO:
+ * As Removal of SDIO triggers complete Deinit and SDIO insertion/
+ * detection, triggers probing which does initialization.
+ */
+
+ return 0;
+}
+
static int esp_get_len_from_slave(struct esp_sdio_context *context, u32 *rx_size, u8 is_lock_needed)
{
u32 *len;
}
memset(context, 0, sizeof(struct esp_sdio_context));
}
+ esp_debug("ESP SDIO cleanup completed\n");
}
static struct esp_if_ops if_ops = {
return ret;
}
- tx_thread = kthread_run(tx_process, context->adapter, "esp32_TX");
+ tx_thread = kthread_run(tx_process, context->adapter, "esp_TX");
if (!tx_thread)
- esp_err("Failed to create esp32_sdio TX thread\n");
+ esp_err("Failed to create esp_sdio TX thread\n");
context->adapter->dev = &func->dev;
generate_slave_intr(context, BIT(ESP_OPEN_DATA_PATH));
esp_err("Failed to create monitor thread\n");
#endif
+ esp_debug("ESP SDIO probe completed\n");
+
return ret;
}
return sdio_register_driver(&esp_sdio_driver);
}
-void process_event_esp_bootup(struct esp_adapter *adapter, u8 *evt_buf, u8 len)
+int esp_validate_chipset(struct esp_adapter *adapter, u8 chipset)
{
- u8 len_left = len, tag_len;
- u8 *pos;
- struct esp_sdio_context *context = &sdio_context;
-
- if (!adapter)
- return;
-
- if (!evt_buf)
- return;
+ int ret = 0;
- if (len_left >= 64) {
- esp_info("ESP init event len looks unexpected: %u (>=64)\n", len_left);
- esp_info("You probably facing timing mismatch at transport layer\n");
+ switch(chipset) {
+ case ESP_FIRMWARE_CHIP_ESP32:
+ case ESP_FIRMWARE_CHIP_ESP32C6:
+ adapter->chipset = chipset;
+ esp_info("Chipset=%s ID=%02x detected over SDIO\n", esp_chipname_from_id(chipset), chipset);
+ break;
+ case ESP_FIRMWARE_CHIP_ESP32S2:
+ case ESP_FIRMWARE_CHIP_ESP32S3:
+ case ESP_FIRMWARE_CHIP_ESP32C2:
+ case ESP_FIRMWARE_CHIP_ESP32C3:
+ esp_err("Chipset=%s ID=%02x not supported for SDIO\n", esp_chipname_from_id(chipset), chipset);
+ adapter->chipset = ESP_FIRMWARE_CHIP_UNRECOGNIZED;
+ break;
+ default:
+ esp_err("Unrecognized Chipset ID=%02x\n", chipset);
+ adapter->chipset = ESP_FIRMWARE_CHIP_UNRECOGNIZED;
+ break;
}
- pos = evt_buf;
-
- clear_bit(ESP_INIT_DONE, &adapter->state_flags);
- while (len_left) {
- tag_len = *(pos + 1);
-
- esp_info("EVENT: %d\n", *pos);
-
- if (*pos == ESP_BOOTUP_CAPABILITY) {
-
- adapter->capabilities = *(pos + 2);
-
- } else if (*pos == ESP_BOOTUP_FIRMWARE_CHIP_ID) {
-
- esp_info("ESP chipset detected [%s]\n",
- *(pos+2) == ESP_FIRMWARE_CHIP_ESP32 ? "esp32" :
- *(pos+2) == ESP_FIRMWARE_CHIP_ESP32S2 ? "esp32-s2" :
- *(pos+2) == ESP_FIRMWARE_CHIP_ESP32S3 ? "esp32-s3" :
- *(pos+2) == ESP_FIRMWARE_CHIP_ESP32C2 ? "esp32-c2" :
- *(pos+2) == ESP_FIRMWARE_CHIP_ESP32C3 ? "esp32-c3" :
- *(pos+2) == ESP_FIRMWARE_CHIP_ESP32C6 ? "esp32-c6" :
- "unknown");
-
- if ((*(pos+2) != ESP_FIRMWARE_CHIP_ESP32) && (*(pos+2) != ESP_FIRMWARE_CHIP_ESP32C6))
- esp_err("SDIO is only supported with ESP32/ESP32C6\n");
-
- } else if (*pos == ESP_BOOTUP_TEST_RAW_TP) {
- process_test_capabilities(*(pos + 2));
-
- } else if (*pos == ESP_BOOTUP_FW_DATA) {
-
- if (tag_len != sizeof(struct fw_data))
- esp_info("Length not matching to firmware data size\n");
- else
- if (process_fw_data((struct fw_data *)(pos + 2))) {
- if (context->func) {
- generate_slave_intr(context, BIT(ESP_CLOSE_DATA_PATH));
- return;
- }
- }
-
- } else {
- esp_warn("Unsupported tag in event");
- }
-
- pos += (tag_len+2);
- len_left -= (tag_len+2);
- }
+ return ret;
+}
- if (esp_add_card(adapter)) {
- esp_err("network iterface init failed\n");
- generate_slave_intr(context, BIT(ESP_CLOSE_DATA_PATH));
- } else {
- set_bit(ESP_INIT_DONE, &adapter->state_flags);
- process_capabilities(adapter);
- print_capabilities(adapter->capabilities);
- }
+int esp_adjust_spi_clock(struct esp_adapter *adapter, u8 spi_clk_mhz)
+{
+ /* SPI bus specific call, silently discard */
+ return 0;
}
void esp_deinit_interface_layer(void)
#include "esp_bt_api.h"
#include "esp_kernel_port.h"
#include "esp_stats.h"
+#include "esp_utils.h"
+#include "esp_cfg80211.h"
#define SPI_INITIAL_CLK_MHZ 10
#define TX_MAX_PENDING_COUNT 100
static struct esp_spi_context spi_context;
static char hardware_type = ESP_FIRMWARE_CHIP_UNRECOGNIZED;
static atomic_t tx_pending;
-static uint8_t esp_reset_after_module_load;
static struct esp_if_ops if_ops = {
.read = read_packet,
return 0;
}
-void process_event_esp_bootup(struct esp_adapter *adapter, u8 *evt_buf, u8 len)
+int esp_validate_chipset(struct esp_adapter *adapter, u8 chipset)
{
- /* Bootup event will be received whenever ESP is booted.
- * It is termed 'First bootup' when this event is received
- * the first time module loaded. It is termed 'Second & onward bootup' when
- * there is ESP reset (reason may be manual reset of ESP or any crash at ESP)
- */
- u8 len_left = len, tag_len;
- u8 *pos;
- uint8_t iface_idx = 0;
- uint8_t prio_q_idx = 0;
-
- if (!adapter)
- return;
-
- if (!evt_buf)
- return;
-
- /* Second & onward bootup, cleanup and re-init the driver */
- if (esp_reset_after_module_load)
- set_bit(ESP_CLEANUP_IN_PROGRESS, &adapter->state_flags);
-
- pos = evt_buf;
-
- while (len_left) {
-
- tag_len = *(pos + 1);
-
- esp_info("EVENT: %d\n", *pos);
-
- if (*pos == ESP_BOOTUP_CAPABILITY) {
-
- adapter->capabilities = *(pos + 2);
-
- } else if (*pos == ESP_BOOTUP_FW_DATA) {
-
- if (tag_len != sizeof(struct fw_data))
- esp_info("Length not matching to firmware data size\n");
- else
- if (process_fw_data((struct fw_data *)(pos + 2))) {
- esp_remove_card(spi_context.adapter);
- return;
- }
-
- } else if (*pos == ESP_BOOTUP_SPI_CLK_MHZ) {
-
- adjust_spi_clock(*(pos + 2));
- adapter->dev = &spi_context.esp_spi_dev->dev;
-
- } else if (*pos == ESP_BOOTUP_FIRMWARE_CHIP_ID) {
-
- hardware_type = *(pos+2);
-
- } else if (*pos == ESP_BOOTUP_TEST_RAW_TP) {
- process_test_capabilities(*(pos + 2));
- } else {
- esp_warn("Unsupported tag in event");
- }
-
- pos += (tag_len+2);
- len_left -= (tag_len+2);
- }
-
- if ((hardware_type != ESP_FIRMWARE_CHIP_ESP32) &&
- (hardware_type != ESP_FIRMWARE_CHIP_ESP32S2) &&
- (hardware_type != ESP_FIRMWARE_CHIP_ESP32C3) &&
- (hardware_type != ESP_FIRMWARE_CHIP_ESP32C2) &&
- (hardware_type != ESP_FIRMWARE_CHIP_ESP32C6) &&
- (hardware_type != ESP_FIRMWARE_CHIP_ESP32S3)) {
- esp_info("ESP chipset not recognized, ignoring [%d]\n", hardware_type);
- hardware_type = ESP_FIRMWARE_CHIP_UNRECOGNIZED;
- } else {
- esp_info("ESP chipset detected [%s]\n",
- hardware_type == ESP_FIRMWARE_CHIP_ESP32 ? "esp32" :
- hardware_type == ESP_FIRMWARE_CHIP_ESP32S2 ? "esp32-s2" :
- hardware_type == ESP_FIRMWARE_CHIP_ESP32C3 ? "esp32-c3" :
- hardware_type == ESP_FIRMWARE_CHIP_ESP32C2 ? "esp32-c2" :
- hardware_type == ESP_FIRMWARE_CHIP_ESP32S3 ? "esp32-s3" :
- hardware_type == ESP_FIRMWARE_CHIP_ESP32C6 ? "esp32-c6" :
- "unknown");
- }
-
- if (esp_reset_after_module_load) {
-
- /* Second & onward bootup:
- *
- * SPI is software and not a hardware based module.
- * When bootup event is received, we should discard all prior commands,
- * old messages pending at network and re-initialize everything.
- *
- * Such handling is not required
- * 1. for SDIO
- * as Removal of SDIO triggers complete Deinit and on SDIO insertion/
- * detection, i.e., after probing, initialization is triggered
- *
- * 2. On first bootup (if counterpart of this else)
- * First bootup event is received immediately after module insertion.
- * As all network or cmds are init and clean for the first time,
- * there is no need to re-init them
- */
-
- for (prio_q_idx = 0; prio_q_idx < MAX_PRIORITY_QUEUES; prio_q_idx++) {
- skb_queue_purge(&spi_context.tx_q[prio_q_idx]);
- }
-
- for (iface_idx = 0; iface_idx < ESP_MAX_INTERFACE; iface_idx++) {
-
- struct esp_wifi_device *priv = adapter->priv[iface_idx];
-
- if (!priv)
- continue;
-
- if (priv->scan_in_progress)
- ESP_MARK_SCAN_DONE(priv, true);
+ int ret = 0;
- if (priv->ndev &&
- wireless_dev_current_bss_exists(&priv->wdev)) {
- CFG80211_DISCONNECTED(priv->ndev,
- 0, NULL, 0, false, GFP_KERNEL);
- }
- }
+ switch(chipset) {
+ case ESP_FIRMWARE_CHIP_ESP32:
+ case ESP_FIRMWARE_CHIP_ESP32S2:
+ case ESP_FIRMWARE_CHIP_ESP32S3:
+ case ESP_FIRMWARE_CHIP_ESP32C2:
+ case ESP_FIRMWARE_CHIP_ESP32C3:
+ case ESP_FIRMWARE_CHIP_ESP32C6:
+ adapter->chipset = chipset;
+ esp_info("Chipset=%s ID=%02x detected over SPI\n", esp_chipname_from_id(chipset), chipset);
+ break;
+ default:
+ esp_err("Unrecognized chipset ID=%02x\n", chipset);
+ adapter->chipset = ESP_FIRMWARE_CHIP_UNRECOGNIZED;
+ break;
+ }
+
+ return ret;
+}
- esp_remove_card(adapter);
+int esp_deinit_module(struct esp_adapter *adapter)
+{
+ /* Second & onward bootup cleanup:
+ *
+ * SPI is software and not a hardware based module.
+ * When bootup event is received, we should discard all prior commands,
+ * old messages pending at network and re-initialize everything.
+ */
+ uint8_t prio_q_idx, iface_idx;
- for (prio_q_idx = 0; prio_q_idx < MAX_PRIORITY_QUEUES; prio_q_idx++) {
- skb_queue_head_init(&spi_context.tx_q[prio_q_idx]);
- }
+ for (prio_q_idx = 0; prio_q_idx < MAX_PRIORITY_QUEUES; prio_q_idx++) {
+ skb_queue_purge(&spi_context.tx_q[prio_q_idx]);
}
- if (esp_add_card(adapter)) {
- esp_err("network iterface init failed\n");
- } else {
- set_bit(ESP_INIT_DONE, &adapter->state_flags);
+ for (iface_idx = 0; iface_idx < ESP_MAX_INTERFACE; iface_idx++) {
+ struct esp_wifi_device *priv = adapter->priv[iface_idx];
+ esp_mark_scan_done_and_disconnect(priv, true);
}
- process_capabilities(adapter);
- print_capabilities(adapter->capabilities);
+ esp_remove_card(adapter);
+ for (prio_q_idx = 0; prio_q_idx < MAX_PRIORITY_QUEUES; prio_q_idx++) {
+ skb_queue_head_init(&spi_context.tx_q[prio_q_idx]);
+ }
- esp_reset_after_module_load = 1;
+ return 0;
}
-
static int process_rx_buf(struct sk_buff *skb)
{
struct esp_payload_header *header;
}
}
+int esp_adjust_spi_clock(struct esp_adapter *adapter, u8 spi_clk_mhz)
+{
+ adjust_spi_clock(spi_clk_mhz);
+
+ return 0;
+}
+
int esp_init_interface_layer(struct esp_adapter *adapter, u32 speed)
{
if (!adapter)