You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/08/15 02:31:42 UTC

[incubator-nuttx] branch master updated: Add gSPI mode support for Infineon CYW43539

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new e247eaf3e8 Add gSPI mode support for Infineon CYW43539
e247eaf3e8 is described below

commit e247eaf3e894f2f3ff173b0732b8fc6712c5334d
Author: curuvar <58...@users.noreply.github.com>
AuthorDate: Sun Aug 14 15:04:18 2022 -0400

    Add gSPI mode support for Infineon CYW43539
---
 drivers/leds/Kconfig                               |    2 +-
 drivers/wireless/ieee80211/bcm43xxx/Kconfig        |   26 +
 drivers/wireless/ieee80211/bcm43xxx/Make.defs      |   14 +
 drivers/wireless/ieee80211/bcm43xxx/bcmf_bdc.c     |    5 +-
 drivers/wireless/ieee80211/bcm43xxx/bcmf_cdc.c     |   30 +-
 .../wireless/ieee80211/bcm43xxx/bcmf_chip_4301x.c  |    4 +-
 .../wireless/ieee80211/bcm43xxx/bcmf_chip_43362.c  |    4 +-
 .../wireless/ieee80211/bcm43xxx/bcmf_chip_43438.c  |    4 +-
 .../wireless/ieee80211/bcm43xxx/bcmf_chip_43455.c  |    4 +-
 .../wireless/ieee80211/bcm43xxx/bcmf_chip_data.h   |   82 ++
 drivers/wireless/ieee80211/bcm43xxx/bcmf_core.c    |  173 +--
 drivers/wireless/ieee80211/bcm43xxx/bcmf_core.h    |   36 +-
 drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c  |  343 ++++--
 drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h  |    5 +
 .../bcm43xxx/{bcmf_chip_43362.c => bcmf_gpio.c}    |   87 +-
 drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi.c    | 1135 ++++++++++++++++++++
 drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi.h    |  114 ++
 .../ieee80211/bcm43xxx/bcmf_gspi_f2_frame.c        |  394 +++++++
 .../{bcmf_chip_4301x.c => bcmf_gspi_f2_frame.h}    |   83 +-
 .../wireless/ieee80211/bcm43xxx/bcmf_interface.c   |  144 +++
 .../wireless/ieee80211/bcm43xxx/bcmf_interface.h   |  154 +++
 drivers/wireless/ieee80211/bcm43xxx/bcmf_ioctl.h   |    6 +
 drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c  |    6 +-
 drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.c    |  329 +++---
 drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.h    |   65 +-
 .../wireless/ieee80211/bcm43xxx/bcmf_sdio_core.h   |   18 +-
 drivers/wireless/ieee80211/bcm43xxx/bcmf_sdpcm.c   |  192 ++--
 .../{bcmf_chip_43438.c => cyw_chip_43439.c}        |   32 +-
 drivers/wireless/ieee80211/bcm43xxx/cyw_reg_def.h  |  165 +++
 .../nuttx/wireless/ieee80211/bcmf_gpio.h           |   63 +-
 include/nuttx/wireless/ieee80211/bcmf_gspi.h       |  133 +++
 31 files changed, 3140 insertions(+), 712 deletions(-)

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index f2525a81ea..0c45a2623e 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -106,7 +106,7 @@ config WS2812
 	---help---
 		Enable support for the Worldsemi WS2812 LED driver which commonly
 		found in LED strips.
-		NOTE: Depening on the board slected this device may require
+		NOTE: Depending on the board selected, this device may require
 		exclusive use of an SPI bus as ws2812 LEDs have no CS or
 		RESET line.
 
diff --git a/drivers/wireless/ieee80211/bcm43xxx/Kconfig b/drivers/wireless/ieee80211/bcm43xxx/Kconfig
index 9463b5e9bf..2929a67313 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/Kconfig
+++ b/drivers/wireless/ieee80211/bcm43xxx/Kconfig
@@ -34,6 +34,12 @@ config IEEE80211_BROADCOM_BCM43455
 	default n
 	select IEEE80211_BROADCOM_HAVE_CLM
 
+config IEEE80211_INFINEON_CYW43439
+	bool "Infineon 43439 chip support"
+	depends on IEEE80211_BROADCOM_FULLMAC
+	default n
+	select IEEE80211_BROADCOM_HAVE_CLM
+
 config IEEE80211_BROADCOM_FWFILES
 	bool "Firmware files"
 	default y
@@ -118,8 +124,25 @@ config IEEE80211_BROADCOM_FULLMAC_SDIO
 		This selection enables support for broadcom
 		FullMAC-compliant devices using SDIO bus.
 
+config IEEE80211_BROADCOM_FULLMAC_GSPI
+	bool "Broadcom FullMAC driver on gSPI bus"
+	select IEEE80211_BROADCOM_FULLMAC
+	default n
+	---help---
+		This selection enables support for broadcom
+		FullMAC-compliant devices using gSPI bus.
+
+config IEEE80211_BROADCOM_FULLMAC_GSPI_MAX_FRAME
+	int "Broadcom FullMAC driver on gSPI bus"
+	default 2048
+	depends on IEEE80211_BROADCOM_FULLMAC_GSPI
+	---help---
+		This is the maximum frame size for data transfers
+		with the chip.
+
 config IEEE80211_BROADCOM_SCHED_PRIORITY
 	int "Broadcom BCMF daemon thread schedule priority"
+	depends on IEEE80211_BROADCOM_FULLMAC
 	default SCHED_HPWORKPRIORITY if SCHED_HPWORK
 	default 255
 	---help---
@@ -128,18 +151,21 @@ config IEEE80211_BROADCOM_SCHED_PRIORITY
 
 config IEEE80211_BROADCOM_SCAN_RESULT_ENTRIES
 	int "Broadcom BCMF escan result entries"
+	depends on IEEE80211_BROADCOM_FULLMAC
 	default 10
 	---help---
 		This parameter should be set the bcmf escan result buffer entries
 
 config IEEE80211_BROADCOM_LOWPOWER
 	bool "Broadcom BCMF lower power"
+	depends on IEEE80211_BROADCOM_FULLMAC
 	default n
 	---help---
 		This parameter should be enable the bcmf lower power mode
 
 config IEEE80211_BROADCOM_DEFAULT_COUNTRY
 	string "Broadcom BCMF default country code"
+	depends on IEEE80211_BROADCOM_FULLMAC
 	default ""
 	---help---
 		This parameter should be set the default country code
diff --git a/drivers/wireless/ieee80211/bcm43xxx/Make.defs b/drivers/wireless/ieee80211/bcm43xxx/Make.defs
index 42e345e912..0041d73e88 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/Make.defs
+++ b/drivers/wireless/ieee80211/bcm43xxx/Make.defs
@@ -26,9 +26,19 @@ ifeq ($(CONFIG_IEEE80211_BROADCOM_FULLMAC),y)
   CSRCS += bcmf_bdc.c
   CSRCS += bcmf_utils.c
   CSRCS += bcmf_netdev.c
+  CSRCS += bcmf_gpio.c
 
 ifeq ($(CONFIG_IEEE80211_BROADCOM_FULLMAC_SDIO),y)
   CSRCS += bcmf_sdio.c
+  CSRCS += bcmf_interface.c
+  CSRCS += bcmf_core.c
+  CSRCS += bcmf_sdpcm.c
+endif
+
+ifeq ($(CONFIG_IEEE80211_BROADCOM_FULLMAC_GSPI),y)
+  CSRCS += bcmf_gspi.c
+  CSRCS += bcmf_gspi_f2_frame.c
+  CSRCS += bcmf_interface.c
   CSRCS += bcmf_core.c
   CSRCS += bcmf_sdpcm.c
 endif
@@ -49,6 +59,10 @@ ifeq ($(CONFIG_IEEE80211_BROADCOM_BCM43455),y)
 CSRCS += bcmf_chip_43455.c
 endif
 
+ifeq ($(CONFIG_IEEE80211_INFINEON_CYW43439),y)
+CSRCS += cyw_chip_43439.c
+endif
+
 # Include BCM43xxx build support
 
 DEPPATH += --dep-path wireless$(DELIM)ieee80211$(DELIM)bcm43xxx
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_bdc.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_bdc.c
index 458d8a1e50..de1f1b78ea 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_bdc.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_bdc.c
@@ -123,6 +123,7 @@ int bcmf_bdc_process_event_frame(FAR struct bcmf_dev_s *priv,
 
   if (data_size < sizeof(struct bcmf_bdc_header))
     {
+      wlerr("invalid event frame -- way too small\n");
       goto exit_invalid_frame;
     }
 
@@ -132,6 +133,7 @@ int bcmf_bdc_process_event_frame(FAR struct bcmf_dev_s *priv,
 
   if (data_size < sizeof(struct bcmf_event_msg))
     {
+      wlerr("invalid event frame -- too small\n");
       goto exit_invalid_frame;
     }
 
@@ -146,6 +148,8 @@ int bcmf_bdc_process_event_frame(FAR struct bcmf_dev_s *priv,
   if (event_msg->eth.ether_type != BCMF_EVENT_ETHER_TYPE ||
       memcmp(event_msg->bcm_eth.oui, bcmf_broadcom_oui, 3))
     {
+      wlerr("invalid event frame -- bad data\n");
+
       goto exit_invalid_frame;
     }
 
@@ -168,7 +172,6 @@ int bcmf_bdc_process_event_frame(FAR struct bcmf_dev_s *priv,
   return OK;
 
 exit_invalid_frame:
-  wlerr("Invalid event frame\n");
   bcmf_hexdump(frame->base, frame->len, (unsigned long)frame->base);
   return -EINVAL;
 }
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_cdc.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_cdc.c
index 6e7bda541e..e0bb291785 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_cdc.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_cdc.c
@@ -48,7 +48,7 @@
 #define BCMF_CONTROL_INTERFACE_SHIFT 12
 #define BCMF_CONTROL_REQID_SHIFT     16
 
-#define BCMF_CONTROL_TIMEOUT_MS 1000
+#define BCMF_CONTROL_TIMEOUT_MS 2000
 
 /****************************************************************************
  * Private Types
@@ -198,6 +198,29 @@ int bcmf_cdc_control_request_unsafe(FAR struct bcmf_dev_s *priv,
       return -ENOMEM;
     }
 
+#ifdef CONFIG_DEBUG_WIRELESS_INFO
+  if (cmd == WLC_SET_VAR  ||  cmd == WLC_GET_VAR)
+    {
+      wlinfo(">>> Sending control %d %d 0x%08lX [%d] %s %s \n",
+             ifidx,
+             set,
+             cmd,
+             out_len,
+             set ? "set" : "get",
+             name);
+    }
+  else
+    {
+      wlinfo(">>> Sending control %d %d 0x%08lX [%d] %s cmd: %d\n",
+             ifidx,
+             set,
+             cmd,
+             out_len,
+             set ? "set" : "get",
+             cmd);
+    }
+#endif
+
   /* Setup buffer to store response */
 
   priv->control_rxdata = set ? NULL : data;
@@ -210,6 +233,7 @@ int bcmf_cdc_control_request_unsafe(FAR struct bcmf_dev_s *priv,
     {
       /* Free allocated iovar buffer */
 
+      wlerr("cdc send frame failed: %d\n", ret);
       priv->bus->free_frame(priv, frame);
       return ret;
     }
@@ -263,6 +287,10 @@ int bcmf_cdc_ioctl(FAR struct bcmf_dev_s *priv,
   return bcmf_cdc_control_request(priv, ifidx, set, cmd, NULL, data, len);
 }
 
+/****************************************************************************
+ * Name: bcmf_cdc_process_control_frame
+ ****************************************************************************/
+
 int bcmf_cdc_process_control_frame(FAR struct bcmf_dev_s *priv,
                    struct bcmf_frame_s *frame)
 {
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_4301x.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_4301x.c
index 7fdbea81ef..5d5f2bf180 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_4301x.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_4301x.c
@@ -25,7 +25,7 @@
 #include <nuttx/config.h>
 #include <stdint.h>
 
-#include "bcmf_sdio.h"
+#include "bcmf_interface.h"
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -45,7 +45,7 @@ extern const uint8_t bcm4301x_firmware_image[];
 extern const unsigned int bcm4301x_firmware_image_len;
 #endif
 
-const struct bcmf_sdio_chip bcmf_4301x_config_sdio =
+const struct bcmf_chip_data bcmf_4301x_config_data =
 {
   /* General chip stats */
 
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43362.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43362.c
index ab77418f46..12e9f682aa 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43362.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43362.c
@@ -25,7 +25,7 @@
 #include <nuttx/config.h>
 #include <stdint.h>
 
-#include "bcmf_sdio.h"
+#include "bcmf_interface.h"
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -45,7 +45,7 @@ extern const uint8_t bcm43362_firmware_image[];
 extern const unsigned int bcm43362_firmware_image_len;
 #endif
 
-const struct bcmf_sdio_chip bcmf_43362_config_sdio =
+const struct bcmf_chip_data bcmf_43362_config_data =
 {
   /* General chip stats */
 
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43438.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43438.c
index 2592b92c23..281de11f04 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43438.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43438.c
@@ -25,7 +25,7 @@
 #include <nuttx/config.h>
 #include <stdint.h>
 
-#include "bcmf_sdio.h"
+#include "bcmf_interface.h"
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -48,7 +48,7 @@ extern const uint8_t ap6212_clm_blob[];
 extern const unsigned int ap6212_clm_blob_len;
 #endif
 
-const struct bcmf_sdio_chip bcmf_43438_config_sdio =
+const struct bcmf_chip_data bcmf_43438_config_data =
 {
   /* General chip stats */
 
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43455.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43455.c
index 92adb03fce..449bf6a479 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43455.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43455.c
@@ -25,7 +25,7 @@
 #include <nuttx/config.h>
 #include <stdint.h>
 
-#include "bcmf_sdio.h"
+#include "bcmf_interface.h"
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -48,7 +48,7 @@ extern const uint8_t bcm43455_clm_blob[];
 extern const unsigned int bcm43455_clm_blob_len;
 #endif
 
-const struct bcmf_sdio_chip bcmf_43455_config_sdio =
+const struct bcmf_chip_data bcmf_43455_config_data =
 {
   /* General chip stats */
 
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_data.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_data.h
new file mode 100644
index 0000000000..703e7bbf27
--- /dev/null
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_data.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+ * drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_data.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_CHIP_DATA_H
+#define __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_CHIP_DATA_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+enum
+{
+  CHIPCOMMON_CORE_ID = 0,
+  DOT11MAC_CORE_ID,
+  SDIOD_CORE_ID,
+#if defined(CONFIG_IEEE80211_BROADCOM_BCM4301X) || \
+    defined(CONFIG_IEEE80211_BROADCOM_BCM43362) || \
+    defined(CONFIG_IEEE80211_BROADCOM_BCM43438) || \
+    defined(CONFIG_IEEE80211_INFINEON_CYW43439)
+  WLAN_ARMCM3_CORE_ID,
+  SOCSRAM_CORE_ID,
+#endif
+#if defined(CONFIG_IEEE80211_BROADCOM_BCM43455)
+  WLAN_ARMCR4_CORE_ID,
+#endif
+  MAX_CORE_ID
+};
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* SDIO chip configuration structure */
+
+struct bcmf_chip_data
+{
+  uint32_t ram_base;
+  uint32_t ram_size;
+  uint32_t core_base[MAX_CORE_ID];
+
+  /* In-memory file images */
+
+  FAR uint8_t      *nvram_image;
+  FAR unsigned int *nvram_image_size;
+
+#ifndef CONFIG_IEEE80211_BROADCOM_FWFILES
+  FAR uint8_t      *firmware_image;
+  FAR unsigned int *firmware_image_size;
+
+#ifdef CONFIG_IEEE80211_BROADCOM_HAVE_CLM
+  FAR uint8_t      *clm_blob_image;
+  FAR unsigned int *clm_blob_image_size;
+#endif
+#endif
+};
+
+#endif /* __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_CHIP_DATA_H */
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.c
index dc6da7f45d..cd32015550 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.c
@@ -40,8 +40,7 @@
 #include <nuttx/signal.h>
 
 #include "bcmf_core.h"
-#include "bcmf_sdio.h"
-
+#include "bcmf_interface.h"
 #include "bcmf_sdio_regs.h"
 
 /****************************************************************************
@@ -78,10 +77,6 @@
 #define SOCSRAM_BANKX_INDEX  ((uint32_t) (0x18004000 + 0x10) )
 #define SOCSRAM_BANKX_PDA    ((uint32_t) (0x18004000 + 0x44) )
 
-/* Transfer size properties */
-
-#define BCMF_UPLOAD_TRANSFER_SIZE  (64 * 256)
-
 /* Define this to validate uploaded materials */
 
 /*  #define DBG_VALIDATE_UPLOAD */
@@ -98,18 +93,18 @@ static uint8_t compare_buffer[BCMF_UPLOAD_TRANSFER_SIZE];
  * Private Function Prototypes
  ****************************************************************************/
 
-static int bcmf_core_set_backplane_window(FAR struct bcmf_sdio_dev_s *sbus,
+static int bcmf_core_set_backplane_window(FAR bcmf_interface_dev_t *ibus,
                                           uint32_t address);
-static int bcmf_upload_binary(FAR struct bcmf_sdio_dev_s *sbusv,
+static int bcmf_upload_binary(FAR bcmf_interface_dev_t *ibus,
                               uint32_t address, uint8_t *buf,
                               unsigned int len);
-static int bcmf_upload_nvram(FAR struct bcmf_sdio_dev_s *sbus);
+static int bcmf_upload_nvram(FAR bcmf_interface_dev_t *ibus);
 
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
 
-int bcmf_core_set_backplane_window(FAR struct bcmf_sdio_dev_s *sbus,
+int bcmf_core_set_backplane_window(FAR bcmf_interface_dev_t *ibus,
                                    uint32_t address)
 {
   int ret;
@@ -120,13 +115,13 @@ int bcmf_core_set_backplane_window(FAR struct bcmf_sdio_dev_s *sbus,
   for (i = 1; i < 4; i++)
     {
       uint8_t addr_part = (address >> (8*i)) & 0xff;
-      uint8_t cur_addr_part = (sbus->backplane_current_addr >> (8*i)) & 0xff;
+      uint8_t cur_addr_part = (ibus->backplane_current_addr >> (8*i)) & 0xff;
 
       if (addr_part != cur_addr_part)
         {
           /* Update current backplane base address */
 
-          ret = bcmf_write_reg(sbus, 1, SBSDIO_FUNC1_SBADDRLOW + i - 1,
+          ret = bcmf_write_reg(ibus, 1, SBSDIO_FUNC1_SBADDRLOW + i - 1,
                   addr_part);
 
           if (ret != OK)
@@ -134,15 +129,15 @@ int bcmf_core_set_backplane_window(FAR struct bcmf_sdio_dev_s *sbus,
               return ret;
             }
 
-          sbus->backplane_current_addr &= ~(0xff << (8*i));
-          sbus->backplane_current_addr |= addr_part << (8*i);
+          ibus->backplane_current_addr &= ~(0xff << (8*i));
+          ibus->backplane_current_addr |= addr_part << (8*i);
         }
     }
 
   return OK;
 }
 
-int bcmf_upload_binary(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
+int bcmf_upload_binary(FAR bcmf_interface_dev_t *ibus, uint32_t address,
                        uint8_t *buf, unsigned int len)
 {
   unsigned int size;
@@ -157,7 +152,7 @@ int bcmf_upload_binary(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
     {
       /* Set the backplane window to include the start address */
 
-      int ret = bcmf_core_set_backplane_window(sbus, address);
+      int ret = bcmf_core_set_backplane_window(ibus, address);
       if (ret != OK)
         {
           wlerr("Backplane setting failed at %08" PRIx32 "\n", address);
@@ -175,7 +170,7 @@ int bcmf_upload_binary(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
 
       /* Transfer firmware data */
 
-      ret = bcmf_transfer_bytes(sbus, true, 1,
+      ret = bcmf_transfer_bytes(ibus, true, 1,
                                 address & SBSDIO_SB_OFT_ADDR_MASK, buf,
                                 size);
       if (ret != OK)
@@ -195,7 +190,7 @@ int bcmf_upload_binary(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
     {
       /* Set the backplane window to include the start address */
 
-      int ret = bcmf_core_set_backplane_window(sbus, validate_address);
+      int ret = bcmf_core_set_backplane_window(ibus, validate_address);
       if (ret != OK)
         {
           wlerr("Backplane setting failed at %08x\n", validate_address);
@@ -213,7 +208,7 @@ int bcmf_upload_binary(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
 
       /* Transfer firmware data */
 
-      ret = bcmf_transfer_bytes(sbus, false, 1,
+      ret = bcmf_transfer_bytes(ibus, false, 1,
                                 validate_address & SBSDIO_SB_OFT_ADDR_MASK,
                                 compare_buffer, size);
       if (ret != OK)
@@ -241,7 +236,7 @@ int bcmf_upload_binary(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
 }
 
 #ifdef CONFIG_IEEE80211_BROADCOM_FWFILES
-int bcmf_upload_file(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
+int bcmf_upload_file(FAR bcmf_interface_dev_t *ibus, uint32_t address,
                      FAR const char *path)
 {
   struct file finfo;
@@ -290,7 +285,7 @@ int bcmf_upload_file(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
 
       wlinfo("Read %ld bytes\n", (long)nread);
 
-      ret = bcmf_core_set_backplane_window(sbus, address);
+      ret = bcmf_core_set_backplane_window(ibus, address);
       if (ret < 0)
         {
           wlerr("ERROR: bcmf_core_set_backplane_window() failed: %d\n", ret);
@@ -301,7 +296,7 @@ int bcmf_upload_file(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
 
       /* Transfer firmware data */
 
-      ret = bcmf_transfer_bytes(sbus, true, 1,
+      ret = bcmf_transfer_bytes(ibus, true, 1,
                                 address & SBSDIO_SB_OFT_ADDR_MASK, buf,
                                 total_read);
       if (ret < 0)
@@ -330,10 +325,10 @@ errout_with_file:
 }
 #endif
 
-int bcmf_upload_nvram(FAR struct bcmf_sdio_dev_s *sbus)
+int bcmf_upload_nvram(FAR bcmf_interface_dev_t *ibus)
 {
-  FAR uint8_t *nvram_buf = sbus->chip->nvram_image;
-  uint32_t nvram_sz = *sbus->chip->nvram_image_size;
+  FAR uint8_t *nvram_buf = ibus->chip->nvram_image;
+  uint32_t nvram_sz = *ibus->chip->nvram_image_size;
   uint32_t token;
   int ret;
 
@@ -421,13 +416,13 @@ out:
 
   /* Write image */
 
-  ret = bcmf_upload_binary(sbus,
-                           sbus->chip->ram_size - 4 - nvram_sz
-                           + sbus->chip->ram_base,
+  ret = bcmf_upload_binary(ibus,
+                           ibus->chip->ram_size - 4 - nvram_sz
+                           + ibus->chip->ram_base,
                            nvram_buf, nvram_sz);
 
 #ifdef CONFIG_IEEE80211_BROADCOM_FWFILES
-  if (nvram_buf != sbus->chip->nvram_image)
+  if (nvram_buf != ibus->chip->nvram_image)
     {
       kmm_free(nvram_buf);
     }
@@ -445,8 +440,8 @@ out:
 
   /* Write the length token to the last word */
 
-  return bcmf_write_sbreg(sbus,
-                          sbus->chip->ram_size - 4 + sbus->chip->ram_base,
+  return bcmf_write_sbreg(ibus,
+                          ibus->chip->ram_size - 4 + ibus->chip->ram_base,
                           (FAR uint8_t *)&token, 4);
 }
 
@@ -458,10 +453,10 @@ out:
  * Name: bcmf_read_sbreg
  ****************************************************************************/
 
-int bcmf_read_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
+int bcmf_read_sbreg(FAR bcmf_interface_dev_t *ibus, uint32_t address,
                     FAR uint8_t *reg, unsigned int len)
 {
-  int ret = bcmf_core_set_backplane_window(sbus, address);
+  int ret = bcmf_core_set_backplane_window(ibus, address);
   if (ret != OK)
     {
       return ret;
@@ -476,17 +471,17 @@ int bcmf_read_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
       address |= SBSDIO_SB_ACCESS_2_4B_FLAG;
     }
 
-  return bcmf_transfer_bytes(sbus, false, 1, address, reg, len);
+  return bcmf_transfer_bytes(ibus, false, 1, address, reg, len);
 }
 
 /****************************************************************************
  * Name: bcmf_write_sbreg
  ****************************************************************************/
 
-int bcmf_write_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
+int bcmf_write_sbreg(FAR bcmf_interface_dev_t *ibus, uint32_t address,
                      FAR uint8_t *reg, unsigned int len)
 {
-  int ret = bcmf_core_set_backplane_window(sbus, address);
+  int ret = bcmf_core_set_backplane_window(ibus, address);
   if (ret != OK)
     {
       return ret;
@@ -501,14 +496,14 @@ int bcmf_write_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
       address |= SBSDIO_SB_ACCESS_2_4B_FLAG;
     }
 
-  return bcmf_transfer_bytes(sbus, true, 1, address, reg, len);
+  return bcmf_transfer_bytes(ibus, true, 1, address, reg, len);
 }
 
 /****************************************************************************
  * Name: bcmf_core_upload_firmware
  ****************************************************************************/
 
-int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus)
+int bcmf_core_upload_firmware(FAR bcmf_interface_dev_t *ibus)
 {
   int ret;
 #if defined(CONFIG_IEEE80211_BROADCOM_BCM43455)
@@ -518,30 +513,34 @@ int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus)
 
   wlinfo("upload firmware\n");
 
-  switch (sbus->cur_chip_id)
+  switch (ibus->cur_chip_id)
     {
 #if defined(CONFIG_IEEE80211_BROADCOM_BCM4301X) || \
     defined(CONFIG_IEEE80211_BROADCOM_BCM43362) || \
-    defined(CONFIG_IEEE80211_BROADCOM_BCM43438)
+    defined(CONFIG_IEEE80211_BROADCOM_BCM43438) || \
+    defined(CONFIG_IEEE80211_INFINEON_CYW43439)
 
       case SDIO_DEVICE_ID_BROADCOM_43012:
       case SDIO_DEVICE_ID_BROADCOM_43013:
       case SDIO_DEVICE_ID_BROADCOM_43362:
       case SDIO_DEVICE_ID_BROADCOM_43430:
+      case SDIO_DEVICE_ID_INFINEON_CYW43439:
         /* Disable ARMCM3 core and reset SOCRAM core to set device in
          * firmware upload mode
          */
 
-        bcmf_core_disable(sbus, WLAN_ARMCM3_CORE_ID, 0, 0);
-        bcmf_core_reset(sbus, SOCSRAM_CORE_ID, 0, 0, 0);
+        bcmf_core_disable(ibus, WLAN_ARMCM3_CORE_ID, 0, 0);
+        bcmf_core_reset(ibus, SOCSRAM_CORE_ID, 0, 0, 0);
+
+#if    defined(CONFIG_IEEE80211_BROADCOM_BCM43438)    \
+    || defined(CONFIG_IEEE80211_INFINEON_CYW43439)
 
-#ifdef CONFIG_IEEE80211_BROADCOM_BCM43438
-        if (sbus->cur_chip_id == SDIO_DEVICE_ID_BROADCOM_43430)
+        if (ibus->cur_chip_id == SDIO_DEVICE_ID_BROADCOM_43430)
           {
             /* Disable remap for SRAM_3. Only for 4343x */
 
-            bcmf_write_sbregw(sbus, SOCSRAM_BANKX_INDEX, 0x3);
-            bcmf_write_sbregw(sbus, SOCSRAM_BANKX_PDA, 0);
+            bcmf_write_sbregw(ibus, SOCSRAM_BANKX_INDEX, 0x3);
+            bcmf_write_sbregw(ibus, SOCSRAM_BANKX_PDA, 0);
           }
 #endif
         break;
@@ -553,10 +552,10 @@ int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus)
 
         /* Clear all IOCTL bits except HALT bit */
 
-        base = sbus->chip->core_base[WLAN_ARMCR4_CORE_ID];
-        bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value);
+        base = ibus->chip->core_base[WLAN_ARMCR4_CORE_ID];
+        bcmf_read_sbregw(ibus, base + BCMA_IOCTL, &value);
         value &= ARMCR4_BCMA_IOCTL_CPUHALT;
-        bcmf_core_reset(sbus,
+        bcmf_core_reset(ibus,
                         WLAN_ARMCR4_CORE_ID,
                         value,
                         ARMCR4_BCMA_IOCTL_CPUHALT,
@@ -573,16 +572,16 @@ int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus)
   /* Flash chip firmware */
 
 #ifdef CONFIG_IEEE80211_BROADCOM_FWFILES
-  ret = bcmf_upload_file(sbus,
-                         sbus->chip->ram_base,
+  ret = bcmf_upload_file(ibus,
+                         ibus->chip->ram_base,
                          CONFIG_IEEE80211_BROADCOM_FWFILENAME);
 #else
-  wlinfo("firmware size is %d bytes\n", *sbus->chip->firmware_image_size);
+  wlinfo("firmware size is %d bytes\n", *ibus->chip->firmware_image_size);
 
-  ret = bcmf_upload_binary(sbus,
-                           sbus->chip->ram_base,
-                           sbus->chip->firmware_image,
-                           *sbus->chip->firmware_image_size);
+  ret = bcmf_upload_binary(ibus,
+                           ibus->chip->ram_base,
+                           ibus->chip->firmware_image,
+                           *ibus->chip->firmware_image_size);
 #endif
 
   if (ret < 0)
@@ -594,7 +593,7 @@ int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus)
   /* Flash NVRAM configuration file */
 
   wlinfo("upload nvram configuration\n");
-  ret = bcmf_upload_nvram(sbus);
+  ret = bcmf_upload_nvram(ibus);
   if (ret < 0)
     {
       wlerr("ERROR: Failed to upload NVRAM\n");
@@ -603,23 +602,25 @@ int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus)
 
   /* Firmware upload done, restart ARM CM3/CR4 core */
 
-  switch (sbus->cur_chip_id)
+  switch (ibus->cur_chip_id)
     {
 #if defined(CONFIG_IEEE80211_BROADCOM_BCM4301X) || \
     defined(CONFIG_IEEE80211_BROADCOM_BCM43362) || \
-    defined(CONFIG_IEEE80211_BROADCOM_BCM43438)
+    defined(CONFIG_IEEE80211_BROADCOM_BCM43438) || \
+    defined(CONFIG_IEEE80211_INFINEON_CYW43439)
 
       case SDIO_DEVICE_ID_BROADCOM_43012:
       case SDIO_DEVICE_ID_BROADCOM_43013:
       case SDIO_DEVICE_ID_BROADCOM_43362:
       case SDIO_DEVICE_ID_BROADCOM_43430:
+      case SDIO_DEVICE_ID_INFINEON_CYW43439:
         nxsig_usleep(10 * 1000);
-        bcmf_core_reset(sbus, WLAN_ARMCM3_CORE_ID, 0, 0, 0);
+        bcmf_core_reset(ibus, WLAN_ARMCM3_CORE_ID, 0, 0, 0);
 
         /* Check ARMCM3 core is running */
 
         nxsig_usleep(10 * 1000);
-        if (!bcmf_core_isup(sbus, WLAN_ARMCM3_CORE_ID))
+        if (!bcmf_core_isup(ibus, WLAN_ARMCM3_CORE_ID))
           {
             wlerr("Cannot start ARMCM3 core\n");
             return -ETIMEDOUT;
@@ -634,22 +635,22 @@ int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus)
         /* Clear all interrupts */
 
         bcmf_write_sbregw(
-          sbus,
-          CORE_BUS_REG(sbus->chip->core_base[SDIOD_CORE_ID], intstatus),
+          ibus,
+          CORE_BUS_REG(ibus->chip->core_base[SDIOD_CORE_ID], intstatus),
           0xffffffff);
 
         /* Write reset vector to address 0 */
 
-        ret = bcmf_upload_binary(sbus,
+        ret = bcmf_upload_binary(ibus,
                                  0,
-                                 sbus->chip->firmware_image,
+                                 ibus->chip->firmware_image,
                                  4);
         if (ret < 0)
           {
             return ret;
           }
 
-        bcmf_core_reset(sbus,
+        bcmf_core_reset(ibus,
                         WLAN_ARMCR4_CORE_ID,
                         ARMCR4_BCMA_IOCTL_CPUHALT,
                         0,
@@ -658,7 +659,7 @@ int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus)
         /* Check ARMCR4 core is running */
 
         nxsig_usleep(10 * 1000);
-        if (!bcmf_core_isup(sbus, WLAN_ARMCR4_CORE_ID))
+        if (!bcmf_core_isup(ibus, WLAN_ARMCR4_CORE_ID))
           {
             wlerr("Cannot start ARMCR4 core\n");
             return -ETIMEDOUT;
@@ -674,7 +675,7 @@ int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus)
   return OK;
 }
 
-bool bcmf_core_isup(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core)
+bool bcmf_core_isup(FAR bcmf_interface_dev_t *ibus, unsigned int core)
 {
   uint32_t value = 0;
   uint32_t base;
@@ -685,21 +686,21 @@ bool bcmf_core_isup(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core)
       return false;
     }
 
-  base = sbus->chip->core_base[core];
+  base = ibus->chip->core_base[core];
 
-  bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value);
+  bcmf_read_sbregw(ibus, base + BCMA_IOCTL, &value);
 
   if ((value & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) != BCMA_IOCTL_CLK)
     {
       return false;
     }
 
-  bcmf_read_sbregw(sbus, base + BCMA_RESET_CTL, &value);
+  bcmf_read_sbregw(ibus, base + BCMA_RESET_CTL, &value);
 
   return (value & BCMA_RESET_CTL_RESET) == 0;
 }
 
-void bcmf_core_disable(FAR struct bcmf_sdio_dev_s *sbus,
+void bcmf_core_disable(FAR bcmf_interface_dev_t *ibus,
                        unsigned int core,
                        uint32_t prereset,
                        uint32_t reset)
@@ -712,13 +713,13 @@ void bcmf_core_disable(FAR struct bcmf_sdio_dev_s *sbus,
       return;
     }
 
-  uint32_t base = sbus->chip->core_base[core];
+  uint32_t base = ibus->chip->core_base[core];
 
   /* Check if core is already in reset state.
    * If core is already in reset state, skip reset.
    */
 
-  bcmf_read_sbregw(sbus, base + BCMA_RESET_CTL, &value);
+  bcmf_read_sbregw(ibus, base + BCMA_RESET_CTL, &value);
 
   if ((value & BCMA_RESET_CTL_RESET) == 0)
     {
@@ -728,25 +729,25 @@ void bcmf_core_disable(FAR struct bcmf_sdio_dev_s *sbus,
 
       nxsig_usleep(10 * 1000);
 
-      bcmf_write_sbregw(sbus,
+      bcmf_write_sbregw(ibus,
                         base + BCMA_IOCTL,
                         prereset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
-      bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value);
+      bcmf_read_sbregw(ibus, base + BCMA_IOCTL, &value);
 
       /* Set core in reset state */
 
-      bcmf_write_sbregw(sbus, base + BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
+      bcmf_write_sbregw(ibus, base + BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
       up_udelay(1);
     }
 
-  bcmf_write_sbregw(sbus,
+  bcmf_write_sbregw(ibus,
                     base + BCMA_IOCTL,
                     reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
-  bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value);
+  bcmf_read_sbregw(ibus, base + BCMA_IOCTL, &value);
   up_udelay(10);
 }
 
-void bcmf_core_reset(FAR struct bcmf_sdio_dev_s *sbus,
+void bcmf_core_reset(FAR bcmf_interface_dev_t *ibus,
                      unsigned int core,
                      uint32_t prereset,
                      uint32_t reset,
@@ -761,21 +762,21 @@ void bcmf_core_reset(FAR struct bcmf_sdio_dev_s *sbus,
       return;
     }
 
-  base = sbus->chip->core_base[core];
+  base = ibus->chip->core_base[core];
 
   /* Put core in reset state */
 
-  bcmf_core_disable(sbus, core, prereset, reset);
+  bcmf_core_disable(ibus, core, prereset, reset);
 
   /* Run initialization sequence */
 
-  bcmf_write_sbregw(sbus, base + BCMA_RESET_CTL, 0);
-  bcmf_read_sbregw(sbus, base + BCMA_RESET_CTL, &value);
+  bcmf_write_sbregw(ibus, base + BCMA_RESET_CTL, 0);
+  bcmf_read_sbregw(ibus, base + BCMA_RESET_CTL, &value);
 
   up_udelay(1);
 
-  bcmf_write_sbregw(sbus, base + BCMA_IOCTL, postreset | BCMA_IOCTL_CLK);
-  bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value);
+  bcmf_write_sbregw(ibus, base + BCMA_IOCTL, postreset | BCMA_IOCTL_CLK);
+  bcmf_read_sbregw(ibus, base + BCMA_IOCTL, &value);
 
   up_udelay(1);
 }
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.h
index 3709f464ae..e891117dba 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.h
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.h
@@ -28,55 +28,57 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-#include "bcmf_sdio.h"
+#include "bcmf_interface.h"
 
 /****************************************************************************
  * Public Functions Prototypes
  ****************************************************************************/
 
-int bcmf_read_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
+int bcmf_read_sbreg(FAR bcmf_interface_dev_t *ibus, uint32_t address,
                           uint8_t *reg, unsigned int len);
 
-int bcmf_write_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
+int bcmf_write_sbreg(FAR bcmf_interface_dev_t *ibus, uint32_t address,
                           uint8_t *reg, unsigned int len);
 
-bool bcmf_core_isup(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core);
+bool bcmf_core_isup(FAR bcmf_interface_dev_t *ibus, unsigned int core);
 
-void bcmf_core_disable(FAR struct bcmf_sdio_dev_s *sbus,
+void bcmf_core_disable(FAR bcmf_interface_dev_t *ibus,
                        unsigned int core,
                        uint32_t prereset,
                        uint32_t reset);
 
-void bcmf_core_reset(FAR struct bcmf_sdio_dev_s *sbus,
+void bcmf_core_reset(FAR bcmf_interface_dev_t *ibus,
                      unsigned int core,
                      uint32_t prereset,
                      uint32_t reset,
                      uint32_t postreset);
 
-int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus);
+int bcmf_core_upload_firmware(FAR bcmf_interface_dev_t *ibus);
 
-static inline int bcmf_read_sbregb(FAR struct bcmf_sdio_dev_s *sbus,
-                                   uint32_t address, uint8_t *reg)
+static inline int bcmf_read_sbregb(FAR bcmf_interface_dev_t *ibus,
+                                   uint32_t                  address,
+                                   uint8_t                  *value)
 {
-    return bcmf_read_sbreg(sbus, address, reg, 1);
+  return bcmf_read_sbreg(ibus, address, value, 1);
 }
 
-static inline int bcmf_read_sbregw(FAR struct bcmf_sdio_dev_s *sbus,
-                                   uint32_t address, uint32_t *reg)
+static inline int bcmf_read_sbregw(FAR bcmf_interface_dev_t *ibus,
+                                   uint32_t                  address,
+                                   void                     *value)
 {
-    return bcmf_read_sbreg(sbus, address, (uint8_t *)reg, 4);
+  return bcmf_read_sbreg(ibus, address, (uint8_t *)value, 4);
 }
 
-static inline int bcmf_write_sbregb(FAR struct bcmf_sdio_dev_s *sbus,
+static inline int bcmf_write_sbregb(FAR bcmf_interface_dev_t *ibus,
                                     uint32_t address, uint8_t reg)
 {
-    return bcmf_write_sbreg(sbus, address, &reg, 1);
+    return bcmf_write_sbreg(ibus, address, &reg, 1);
 }
 
-static inline int bcmf_write_sbregw(FAR struct bcmf_sdio_dev_s *sbus,
+static inline int bcmf_write_sbregw(FAR bcmf_interface_dev_t *ibus,
                                     uint32_t address, uint32_t reg)
 {
-    return bcmf_write_sbreg(sbus, address, (uint8_t *)&reg, 4);
+    return bcmf_write_sbreg(ibus, address, (uint8_t *)&reg, 4);
 }
 
 #endif /* __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_CORE_H */
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c
index 40f08a44fd..ad93876780 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c
@@ -47,7 +47,7 @@
 #include "bcmf_ioctl.h"
 #include "bcmf_utils.h"
 #include "bcmf_netdev.h"
-#include "bcmf_sdio.h"
+#include "bcmf_core.h"
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -118,11 +118,6 @@ enum
  * Private Function Prototypes
  ****************************************************************************/
 
-static FAR struct bcmf_dev_s *bcmf_allocate_device(void);
-static void bcmf_free_device(FAR struct bcmf_dev_s *priv);
-
-static int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv);
-
 #ifdef CONFIG_IEEE80211_BROADCOM_HAVE_CLM
 static int bcmf_driver_download_clm(FAR struct bcmf_dev_s *priv);
 #endif
@@ -148,6 +143,10 @@ static int bcmf_wl_get_interface(FAR struct bcmf_dev_s *priv,
  * Private Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: bcmf_wl_channel_to_frequency
+ ****************************************************************************/
+
 static int bcmf_wl_channel_to_frequency(int chan)
 {
   if (chan <= 0)
@@ -174,70 +173,9 @@ static int bcmf_wl_channel_to_frequency(int chan)
   return 0; /* not supported */
 }
 
-FAR struct bcmf_dev_s *bcmf_allocate_device(void)
-{
-  int ret;
-  FAR struct bcmf_dev_s *priv;
-
-  /* Allocate a bcmf device structure */
-
-  priv = (FAR struct bcmf_dev_s *)kmm_malloc(sizeof(*priv));
-  if (!priv)
-    {
-      return NULL;
-    }
-
-  /* Initialize bcmf device structure */
-
-  memset(priv, 0, sizeof(*priv));
-
-  /* Init control frames mutex and timeout signal */
-
-  if ((ret = nxsem_init(&priv->control_mutex, 0, 1)) != OK)
-    {
-      goto exit_free_priv;
-    }
-
-  if ((ret = nxsem_init(&priv->control_timeout, 0, 0)) != OK)
-    {
-      goto exit_free_priv;
-    }
-
-  if ((ret = nxsem_set_protocol(&priv->control_timeout, SEM_PRIO_NONE)) !=
-      OK)
-    {
-      goto exit_free_priv;
-    }
-
-  /* Init authentication signal semaphore */
-
-  if ((ret = nxsem_init(&priv->auth_signal, 0, 0)) != OK)
-    {
-      goto exit_free_priv;
-    }
-
-  if ((ret = nxsem_set_protocol(&priv->auth_signal, SEM_PRIO_NONE)) != OK)
-    {
-      goto exit_free_priv;
-    }
-
-  /* Init scan timeout timer */
-
-  priv->scan_status = BCMF_SCAN_DISABLED;
-
-  return priv;
-
-exit_free_priv:
-  kmm_free(priv);
-  return NULL;
-}
-
-void bcmf_free_device(FAR struct bcmf_dev_s *priv)
-{
-  /* TODO deinitialize device structures */
-
-  kmm_free(priv);
-}
+/****************************************************************************
+ * Name: bcmf_wl_set_mac_address
+ ****************************************************************************/
 
 int bcmf_wl_set_mac_address(FAR struct bcmf_dev_s *priv, struct ifreq *req)
 {
@@ -264,6 +202,10 @@ int bcmf_wl_set_mac_address(FAR struct bcmf_dev_s *priv, struct ifreq *req)
   return OK;
 }
 
+/****************************************************************************
+ * Name: bcmf_driver_download_clm
+ ****************************************************************************/
+
 #ifdef CONFIG_IEEE80211_BROADCOM_HAVE_CLM
 #ifdef CONFIG_IEEE80211_BROADCOM_FWFILES
 int bcmf_driver_download_clm(FAR struct bcmf_dev_s *priv)
@@ -356,10 +298,10 @@ errout_with_file:
 #else
 int bcmf_driver_download_clm(FAR struct bcmf_dev_s *priv)
 {
-  FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
-  FAR uint8_t *srcbuff = sbus->chip->clm_blob_image;
+  FAR bcmf_interface_dev_t *ibus = (FAR bcmf_interface_dev_t *)priv->bus;
+  FAR uint8_t *srcbuff = ibus->chip->clm_blob_image;
   FAR uint8_t *downloadbuff;
-  unsigned int datalen = *sbus->chip->clm_blob_image_size;
+  unsigned int datalen = *ibus->chip->clm_blob_image_size;
   uint16_t dl_flag;
   int ret = 0;
 
@@ -426,6 +368,10 @@ int bcmf_driver_download_clm(FAR struct bcmf_dev_s *priv)
 #endif
 #endif /* CONFIG_IEEE80211_BROADCOM_HAVE_CLM */
 
+/****************************************************************************
+ * Name: bcmf_wl_active
+ ****************************************************************************/
+
 int bcmf_wl_active(FAR struct bcmf_dev_s *priv, bool active)
 {
   int interface = CHIP_STA_INTERFACE;
@@ -434,12 +380,16 @@ int bcmf_wl_active(FAR struct bcmf_dev_s *priv, bool active)
   uint32_t value;
   int ret;
 
-  ret = bcmf_bus_sdio_active(priv, active);
+  ninfo("Entered\n");
+
+  ret = bcmf_bus_interface_active(priv, active);
   if (ret != OK || !active)
     {
       return ret;
     }
 
+  ninfo("Interface activated\n");
+
 #ifdef CONFIG_IEEE80211_BROADCOM_HAVE_CLM
   /* Download CLM blob if needed */
 
@@ -539,12 +489,16 @@ int bcmf_wl_active(FAR struct bcmf_dev_s *priv, bool active)
 errout_in_sdio_active:
   if (ret != OK)
     {
-      bcmf_bus_sdio_active(priv, false);
+      bcmf_bus_interface_active(priv, false);
     }
 
   return ret;
 }
 
+/****************************************************************************
+ * Name: bcmf_driver_initialize
+ ****************************************************************************/
+
 int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
 {
   int i;
@@ -592,21 +546,34 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
   return bcmf_netdev_register(priv);
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_default_event_handler
+ ****************************************************************************/
+
 void bcmf_wl_default_event_handler(FAR struct bcmf_dev_s *priv,
                                    struct bcmf_event_s *event,
                                    unsigned int len)
 {
-  wlinfo("Got event %" PRId32 " from <%s>\n",
+  wlinfo("Unhandled event %" PRId32 " from <%s>\n",
          bcmf_getle32(&event->type),
          event->src_name);
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_radio_event_handler
+ ****************************************************************************/
+
 void bcmf_wl_radio_event_handler(FAR struct bcmf_dev_s *priv,
                                  struct bcmf_event_s *event,
                                  unsigned int len)
 {
+  wlinfo("Unhandled radio event from <%s>\n", event->src_name);
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_auth_event_handler
+ ****************************************************************************/
+
 void bcmf_wl_auth_event_handler(FAR struct bcmf_dev_s *priv,
                                 struct bcmf_event_s *event,
                                 unsigned int len)
@@ -642,6 +609,10 @@ void bcmf_wl_auth_event_handler(FAR struct bcmf_dev_s *priv,
     }
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_scan_event_handler
+ ****************************************************************************/
+
 /* bcmf_wl_scan_event_handler must run at high priority else
  * race condition may occur on priv->scan_result field
  */
@@ -669,6 +640,8 @@ void bcmf_wl_scan_event_handler(FAR struct bcmf_dev_s *priv,
       goto exit_invalid_frame;
     }
 
+  wlinfo("Scan event from <%s>\n", event->src_name);
+
   status = bcmf_getle32(&event->status);
   escan_result_len = bcmf_getle32(&event->len);
 
@@ -809,6 +782,10 @@ exit_invalid_frame:
   bcmf_hexdump((FAR uint8_t *)event, event_len, (unsigned long)event);
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_scan_format_results
+ ****************************************************************************/
+
 static int bcmf_wl_scan_format_results(FAR struct bcmf_dev_s *priv,
                                        FAR struct iwreq *iwr)
 {
@@ -926,6 +903,10 @@ static int bcmf_wl_scan_format_results(FAR struct bcmf_dev_s *priv,
   return OK;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_scan_timeout
+ ****************************************************************************/
+
 void bcmf_wl_scan_timeout(wdparm_t arg)
 {
   FAR struct bcmf_dev_s *priv = (FAR struct bcmf_dev_s *)arg;
@@ -944,6 +925,10 @@ void bcmf_wl_scan_timeout(wdparm_t arg)
   nxsem_post(&priv->control_mutex);
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_get_interface
+ ****************************************************************************/
+
 int bcmf_wl_get_interface(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   /* TODO resolve interface using iwr->ifr_name */
@@ -955,37 +940,83 @@ int bcmf_wl_get_interface(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
  * Public Functions
  ****************************************************************************/
 
-int bcmf_sdio_initialize(int minor, FAR struct sdio_dev_s *dev)
+/****************************************************************************
+ * Name: bcmf_allocate_device
+ ****************************************************************************/
+
+FAR struct bcmf_dev_s *bcmf_allocate_device(void)
 {
   int ret;
   FAR struct bcmf_dev_s *priv;
 
-  wlinfo("minor: %d\n", minor);
+  /* Allocate a bcmf device structure */
 
-  priv = bcmf_allocate_device();
+  priv = (FAR struct bcmf_dev_s *)kmm_malloc(sizeof(*priv));
   if (!priv)
     {
-      return -ENOMEM;
+      return NULL;
     }
 
-  /* Init sdio bus */
+  /* Initialize bcmf device structure */
 
-  ret = bcmf_bus_sdio_initialize(priv, minor, dev);
-  if (ret != OK)
+  memset(priv, 0, sizeof(*priv));
+
+  /* Init control frames mutex and timeout signal */
+
+  if ((ret = nxsem_init(&priv->control_mutex, 0, 1)) != OK)
     {
-      ret = -EIO;
-      goto exit_free_device;
+      goto exit_free_priv;
     }
 
-  /* Bus initialized, register network driver */
+  if ((ret = nxsem_init(&priv->control_timeout, 0, 0)) != OK)
+    {
+      goto exit_free_priv;
+    }
 
-  return bcmf_driver_initialize(priv);
+  if ((ret = nxsem_set_protocol(&priv->control_timeout, SEM_PRIO_NONE)) !=
+      OK)
+    {
+      goto exit_free_priv;
+    }
 
-exit_free_device:
-  bcmf_free_device(priv);
-  return ret;
+  /* Init authentication signal semaphore */
+
+  if ((ret = nxsem_init(&priv->auth_signal, 0, 0)) != OK)
+    {
+      goto exit_free_priv;
+    }
+
+  if ((ret = nxsem_set_protocol(&priv->auth_signal, SEM_PRIO_NONE)) != OK)
+    {
+      goto exit_free_priv;
+    }
+
+  /* Init scan timeout timer */
+
+  priv->scan_status = BCMF_SCAN_DISABLED;
+
+  return priv;
+
+exit_free_priv:
+  kmm_free(priv);
+  return NULL;
 }
 
+/****************************************************************************
+ * Name: bcmf_free_device
+ ****************************************************************************/
+
+void bcmf_free_device(FAR struct bcmf_dev_s *priv)
+{
+  /* ## TODO ## deinitialize device structures */
+
+  kmm_free(priv);
+}
+
+/****************************************************************************
+ * Name: bcmf_wl_enable
+ ****************************************************************************/
+
 int bcmf_wl_enable(FAR struct bcmf_dev_s *priv, bool enable)
 {
   int ret;
@@ -1009,6 +1040,13 @@ int bcmf_wl_enable(FAR struct bcmf_dev_s *priv, bool enable)
   return ret;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_start_scan
+ *
+ * Description:
+ *   Start a WiFi scan.
+ ****************************************************************************/
+
 int bcmf_wl_start_scan(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   int ret;
@@ -1130,11 +1168,20 @@ exit_sem_post:
   priv->scan_status = BCMF_SCAN_DISABLED;
   nxsem_post(&priv->control_mutex);
 
+  wlinfo("scan complete\n");
+
 exit_failed:
   wlinfo("Failed\n");
   return ret;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_get_scan_results
+ *
+ * Description:
+ *   Get the results of a WiFi scan.
+ ****************************************************************************/
+
 int bcmf_wl_get_scan_results(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   int ret = OK;
@@ -1189,6 +1236,13 @@ exit_failed:
   return ret;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_set_auth_param
+ *
+ * Description:
+ *   Set the authorization parameters for the device
+ ****************************************************************************/
+
 int bcmf_wl_set_auth_param(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   int ret = -ENOSYS;
@@ -1322,6 +1376,13 @@ int bcmf_wl_set_auth_param(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
   return ret;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_set_mode
+ *
+ * Description:
+ *   Set the mode for the device
+ ****************************************************************************/
+
 int bcmf_wl_set_mode(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   uint32_t out_len;
@@ -1342,6 +1403,13 @@ int bcmf_wl_set_mode(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
                         WLC_SET_INFRA, (uint8_t *)&value, &out_len);
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_get_mode
+ *
+ * Description:
+ *   Get the mode for the device
+ ****************************************************************************/
+
 int bcmf_wl_get_mode(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   uint32_t out_len;
@@ -1386,6 +1454,13 @@ int bcmf_wl_get_mode(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
   return ret;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_set_bssid
+ *
+ * Description:
+ *   Set the bssid for the device
+ ****************************************************************************/
+
 int bcmf_wl_set_bssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   uint32_t out_len;
@@ -1423,6 +1498,13 @@ int bcmf_wl_set_bssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
   return ret;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_get_bssid
+ *
+ * Description:
+ *   Get the bssid for the device
+ ****************************************************************************/
+
 int bcmf_wl_get_bssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   uint32_t out_len;
@@ -1442,6 +1524,13 @@ int bcmf_wl_get_bssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
                         (uint8_t *)iwr->u.ap_addr.sa_data, &out_len);
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_get_channel
+ *
+ * Description:
+ *   Get the channel for the device
+ ****************************************************************************/
+
 int bcmf_wl_get_channel(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   channel_info_t ci;
@@ -1467,6 +1556,13 @@ int bcmf_wl_get_channel(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
   return ret;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_get_rate
+ *
+ * Description:
+ *   Get the data rate for the device
+ ****************************************************************************/
+
 int bcmf_wl_get_rate(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   uint32_t out_len;
@@ -1493,6 +1589,13 @@ int bcmf_wl_get_rate(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
   return ret;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_get_txpower
+ *
+ * Description:
+ *   Get the tranmit power for the device
+ ****************************************************************************/
+
 int bcmf_wl_get_txpower(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   uint32_t out_len;
@@ -1531,6 +1634,13 @@ int bcmf_wl_get_txpower(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
   return ret;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_get_iwrange
+ *
+ * Description:
+ *   Get the iwrange for the device
+ ****************************************************************************/
+
 int bcmf_wl_get_iwrange(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   struct iw_range *range;
@@ -1568,6 +1678,13 @@ int bcmf_wl_get_iwrange(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
   return OK;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_get_rssi
+ *
+ * Description:
+ *   Get the RSSI for the device
+ ****************************************************************************/
+
 int bcmf_wl_get_rssi(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   wl_sta_rssi_t rssi;
@@ -1595,6 +1712,13 @@ int bcmf_wl_get_rssi(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
   return ret;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_set_encode_ext
+ *
+ * Description:
+ *   Set the encoding scheme for a device based on iwreq structure.
+ ****************************************************************************/
+
 int bcmf_wl_set_encode_ext(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   int interface;
@@ -1634,6 +1758,13 @@ int bcmf_wl_set_encode_ext(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
                         WLC_SET_WSEC_PMK, (uint8_t *)&psk, &out_len);
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_set_ssid
+ *
+ * Description:
+ *   Get the SSID for a device based on iwreq structure.
+ ****************************************************************************/
+
 int bcmf_wl_set_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   int ret;
@@ -1698,6 +1829,13 @@ int bcmf_wl_set_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
   return OK;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_get_ssid
+ *
+ * Description:
+ *   Get the SSID for a device.
+ ****************************************************************************/
+
 int bcmf_wl_get_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
 {
   uint32_t out_len;
@@ -1727,6 +1865,13 @@ int bcmf_wl_get_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
   return ret;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_set_country_code
+ *
+ * Description:
+ *   Set a new country code.
+ ****************************************************************************/
+
 int bcmf_wl_set_country_code(FAR struct bcmf_dev_s *priv,
                              int interface, FAR void *code)
 {
@@ -1750,6 +1895,13 @@ int bcmf_wl_set_country_code(FAR struct bcmf_dev_s *priv,
                                 &out_len);
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_set_country
+ *
+ * Description:
+ *   Set a new country code based on data in an iwreq structure.
+ ****************************************************************************/
+
 int bcmf_wl_set_country(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr)
 {
   int interface;
@@ -1764,6 +1916,13 @@ int bcmf_wl_set_country(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr)
   return bcmf_wl_set_country_code(priv, interface, iwr->u.data.pointer);
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_get_country
+ *
+ * Description:
+ *   Get the current country code.
+ ****************************************************************************/
+
 int bcmf_wl_get_country(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr)
 {
   uint8_t country[4] =
@@ -1795,6 +1954,10 @@ int bcmf_wl_get_country(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr)
   return ret;
 }
 
+/****************************************************************************
+ * Name: bcmf_wl_set_dtim
+ ****************************************************************************/
+
 #ifdef CONFIG_IEEE80211_BROADCOM_LOWPOWER
 
 int bcmf_wl_set_dtim(FAR struct bcmf_dev_s *priv,
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h
index 5433a0382e..ac1847304b 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h
@@ -139,6 +139,11 @@ struct bcmf_frame_s
  * Public Function Prototypes
  ****************************************************************************/
 
+FAR struct bcmf_dev_s *bcmf_allocate_device(void);
+void bcmf_free_device(FAR struct bcmf_dev_s *priv);
+
+int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv);
+
 /* IOCTLs network interface implementation */
 
 int bcmf_wl_set_mac_address(FAR struct bcmf_dev_s *priv, struct ifreq *req);
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43362.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_gpio.c
similarity index 51%
copy from drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43362.c
copy to drivers/wireless/ieee80211/bcm43xxx/bcmf_gpio.c
index ab77418f46..7fdd0de542 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43362.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_gpio.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43362.c
+ * drivers/wireless/ieee80211/bcm43xxx/bcmf_gpio.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -22,62 +22,65 @@
  * Included Files
  ****************************************************************************/
 
-#include <nuttx/config.h>
-#include <stdint.h>
+#include <stdbool.h>
 
-#include "bcmf_sdio.h"
+#include <nuttx/wireless/ieee80211/bcmf_gpio.h>
+
+#include "bcmf_cdc.h"
+#include "bcmf_interface.h"
 
 /****************************************************************************
- * Pre-processor Definitions
+ * Public Functions
  ****************************************************************************/
 
-#define WRAPPER_REGISTER_OFFSET  0x100000
-
 /****************************************************************************
- * Public Data
+ * Name: bcmf_set_gpio
  ****************************************************************************/
 
-extern const char bcm43362_nvram_image[];
-extern const unsigned int bcm43362_nvram_image_len;
+int bcmf_set_gpio(FAR struct bcmf_dev_s *priv, int pin, bool value)
+{
+  struct
+    {
+      uint32_t mask;
+      uint32_t value;
+    } buffer;
 
-#ifndef CONFIG_IEEE80211_BROADCOM_FWFILES
-extern const uint8_t bcm43362_firmware_image[];
-extern const unsigned int bcm43362_firmware_image_len;
-#endif
+  uint32_t buf_len = sizeof(buffer);
 
-const struct bcmf_sdio_chip bcmf_43362_config_sdio =
-{
-  /* General chip stats */
+  if (!(((FAR bcmf_interface_dev_t *)priv->bus)->ready)) return -EIO;
 
-  .ram_base = 0,
-  .ram_size = 0x3c000,
+  buffer.mask  = 1 << pin;
+  buffer.value = value ? (1 << pin) : 0;
 
-  /* Backplane architecture */
+  return bcmf_cdc_iovar_request(priv,
+                                CHIP_STA_INTERFACE,
+                                true,
+                                IOVAR_STR_GPIOOUT,
+                                (uint8_t *)&buffer,
+                                &buf_len);
+}
 
-  .core_base =
-  {
-    [CHIPCOMMON_CORE_ID]  = 0x18000000,  /* Chipcommon core register base   */
-    [DOT11MAC_CORE_ID]    = 0x18001000,  /* dot11mac core register base     */
-    [SDIOD_CORE_ID]       = 0x18002000,  /* SDIOD Device core register base */
-    [WLAN_ARMCM3_CORE_ID] = 0x18003000 + /* ARMCM3 core register base       */
-                            WRAPPER_REGISTER_OFFSET,
-    [SOCSRAM_CORE_ID]     = 0x18004000 + /* SOCSRAM core register base      */
-                            WRAPPER_REGISTER_OFFSET
-  },
+/****************************************************************************
+ * Name: bcmf_get_gpio
+ ****************************************************************************/
 
-  /* Firmware images */
+int bcmf_get_gpio(FAR struct bcmf_dev_s *priv, int pin, bool *value)
+{
+  uint8_t  buffer;
+  uint32_t buf_len = sizeof(buffer);
+  int      ret;
 
-  /* TODO find something smarter than using image_len references */
+  if (!(((FAR bcmf_interface_dev_t *)priv->bus)->ready)) return -EIO;
 
-  .nvram_image         = (FAR uint8_t *)bcm43362_nvram_image,
-  .nvram_image_size    = (FAR unsigned int *)&bcm43362_nvram_image_len,
+  ret = bcmf_cdc_iovar_request(priv,
+                               CHIP_STA_INTERFACE,
+                               false,
+                               IOVAR_STR_CCGPIOIN,
+                               (uint8_t *)&buffer,
+                               &buf_len);
+  if (ret != OK) return ret;
 
-#ifndef CONFIG_IEEE80211_BROADCOM_FWFILES
-  .firmware_image      = (FAR uint8_t *)bcm43362_firmware_image,
-  .firmware_image_size = (FAR unsigned int *)&bcm43362_firmware_image_len,
-#endif
-};
+  *value = (buffer & (1 << pin)) != 0;
 
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
+  return OK;
+}
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi.c
new file mode 100644
index 0000000000..8e64025874
--- /dev/null
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi.c
@@ -0,0 +1,1135 @@
+/****************************************************************************
+ * drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/compiler.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+#include <debug.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/arch.h>
+#include <nuttx/kthread.h>
+#include <nuttx/wdog.h>
+#include <nuttx/signal.h>
+
+#include <nuttx/wireless/ieee80211/bcmf_board.h>
+
+#include "bcmf_gspi.h"
+#include "bcmf_gspi_f2_frame.h"
+#include "bcmf_core.h"
+#include "bcmf_sdpcm.h"
+#include "bcmf_utils.h"
+
+#include "bcmf_sdio_core.h"
+#include "bcmf_sdio_regs.h"
+#include "cyw_reg_def.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define BCMF_GSPI_READY_TRYS            10
+#define BCMF_GSPI_THREAD_NAME           "bcmf-gspi-thread"
+#define BCMF_GSPI_THREAD_STACK_SIZE     2048
+#define BCMF_GSPI_LOWPOWER_TIMEOUT_TICK SEC2TICK(2)
+
+#ifdef CONFIG_IEEE80211_INFINEON_CYW43439
+extern const struct bcmf_chip_data cyw43439_config_data;
+#endif
+
+#define REV16(x) (((x & 0x000000ff) << 8)   \
+                | ((x & 0x0000ff00) >> 8)   \
+                | ((x & 0x00ff0000) << 8)   \
+                | ((x & 0xff000000) >> 8))
+
+/* Chip-common registers */
+
+#define CHIPCOMMON_GPIO_CONTROL ((uint32_t)(0x18000000 + 0x06c) )
+#define CHIPCOMMON_SR_CONTROL0  ((uint32_t)(0x18000000 + 0x504) )
+#define CHIPCOMMON_SR_CONTROL1  ((uint32_t)(0x18000000 + 0x508) )
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: bcmf_gspi_read_reg_32
+ *
+ * Description:
+ *   Read a 32-bit register
+ *
+ ****************************************************************************/
+
+static inline uint32_t bcmf_gspi_read_reg_32(FAR gspi_dev_t       *gspi,
+                                             enum gspi_cmd_func_e  function,
+                                             uint32_t              address)
+{
+  uint32_t buffer;
+
+  gspi->read(gspi, true, function, address, 4, &buffer);
+
+  return buffer;
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_read_reg_16
+ *
+ * Description:
+ *   Read a 32-bit register
+ *
+ ****************************************************************************/
+
+static inline uint16_t bcmf_gspi_read_reg_16(FAR gspi_dev_t       *gspi,
+                                             enum gspi_cmd_func_e  function,
+                                             uint32_t              address)
+{
+  uint32_t buffer;
+
+  gspi->read(gspi, true, function, address, 2, &buffer);
+
+  return buffer;
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_read_reg_8
+ *
+ * Description:
+ *   Read a 32-bit register
+ *
+ ****************************************************************************/
+
+static inline uint8_t bcmf_gspi_read_reg_8(FAR gspi_dev_t       *gspi,
+                                           enum gspi_cmd_func_e  function,
+                                           uint32_t              address)
+{
+  uint32_t buffer;
+
+  gspi->read(gspi, true, function, address, 1, &buffer);
+
+  return buffer;
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_write_reg_32
+ *
+ * Description:
+ *   Write a 32-bit register
+ *
+ ****************************************************************************/
+
+static inline void bcmf_gspi_write_reg_32(FAR gspi_dev_t       *gspi,
+                                          enum gspi_cmd_func_e  function,
+                                          uint32_t              address,
+                                          uint32_t              value)
+{
+  gspi->write(gspi, true, function, address, 4, &value);
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_write_reg_16
+ *
+ * Description:
+ *   Read a 32-bit register
+ *
+ ****************************************************************************/
+
+static inline void bcmf_gspi_write_reg_16(FAR gspi_dev_t       *gspi,
+                                          enum gspi_cmd_func_e  function,
+                                          uint32_t              address,
+                                          uint32_t              value)
+{
+  gspi->write(gspi, true, function, address, 2, &value);
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_write_reg_8
+ *
+ * Description:
+ *   Write a 8-bit register
+ *
+ ****************************************************************************/
+
+static inline void bcmf_gspi_write_reg_8(FAR gspi_dev_t       *gspi,
+                                         enum gspi_cmd_func_e  function,
+                                         uint32_t              address,
+                                         uint32_t              value)
+{
+  gspi->write(gspi, true, function, address, 1, &value);
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_kso_enable
+ ****************************************************************************/
+
+static int bcmf_gspi_kso_enable(FAR bcmf_gspi_dev_t *gbus, bool enable)
+{
+  FAR gspi_dev_t *gspi = gbus->gspi;
+  uint8_t         value;
+  int             loops;
+
+  if (!gbus->ready)
+    {
+      return -EPERM;
+    }
+
+  if (gbus->kso_enable == enable)
+    {
+      return OK;
+    }
+
+  if (enable)
+    {
+      wlinfo("enable\n");
+
+      loops = 200;
+      while (--loops > 0)
+        {
+          bcmf_gspi_write_reg_8(gspi,
+                                gspi_f1_backplane,
+                                SBSDIO_FUNC1_SLEEPCSR,
+                                  SBSDIO_FUNC1_SLEEPCSR_KSO_MASK
+                                | SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK);
+
+          nxsig_usleep(100 * 1000);
+
+          value = bcmf_gspi_read_reg_8(gspi, 1, SBSDIO_FUNC1_SLEEPCSR);
+
+          if ((value & (SBSDIO_FUNC1_SLEEPCSR_KSO_MASK |
+                        SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)) != 0)
+            {
+              break;
+            }
+        }
+
+      if (loops <= 0)
+        {
+          return -ETIMEDOUT;
+        }
+    }
+  else
+    {
+      wlinfo("disable\n");
+
+      bcmf_gspi_write_reg_8(gspi, 1, SBSDIO_FUNC1_SLEEPCSR, 0);
+    }
+
+  gbus->kso_enable = enable;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_bus_sleep
+ ****************************************************************************/
+
+static int bcmf_gspi_bus_sleep(FAR bcmf_gspi_dev_t *gbus, bool sleep)
+{
+  FAR gspi_dev_t *gspi = gbus->gspi;
+  uint8_t         value;
+  int             loops;
+
+  if (!gbus->ready)
+    {
+      return -EPERM;
+    }
+
+  if (gbus->sleeping == sleep)
+    {
+      return OK;
+    }
+
+  if (sleep)
+    {
+      wlinfo("enable\n");
+
+      gbus->sleeping = true;
+      bcmf_gspi_write_reg_8(gspi,
+                            gspi_f1_backplane,
+                            SBSDIO_FUNC1_CHIPCLKCSR,
+                            0);
+
+      wlinfo("exit\n");
+
+      return OK;
+    }
+  else
+    {
+      wlinfo("disable\n");
+
+      loops = 200;
+      while (--loops > 0)
+        {
+          /* Request HT Avail */
+
+          bcmf_gspi_write_reg_8(gspi,
+                                gspi_f1_backplane,
+                                SBSDIO_FUNC1_CHIPCLKCSR,
+                                  SBSDIO_HT_AVAIL_REQ
+                                | SBSDIO_FORCE_HT);
+
+          /* Wait for High Throughput clock */
+
+          nxsig_usleep(100 * 1000);
+          value = bcmf_gspi_read_reg_8(gspi, 1, SBSDIO_FUNC1_CHIPCLKCSR);
+
+          if (value & SBSDIO_HT_AVAIL)
+            {
+              /* High Throughput clock is ready */
+
+              break;
+            }
+        }
+
+      if (loops <= 0)
+        {
+          wlerr("HT clock not ready\n");
+          return -ETIMEDOUT;
+        }
+
+      gbus->sleeping = false;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_bus_lowpower
+ ****************************************************************************/
+
+static int bcmf_gspi_bus_lowpower(FAR bcmf_gspi_dev_t *gbus, bool enable)
+{
+  return gbus->support_sr ? bcmf_gspi_kso_enable(gbus, !enable)
+                          : bcmf_gspi_bus_sleep(gbus, enable);
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_thread_isr
+ ****************************************************************************/
+
+static int bcmf_gspi_thread_isr(int isr, void *context, void *arg)
+{
+  FAR bcmf_gspi_dev_t *gbus = (FAR bcmf_gspi_dev_t  *) arg;
+  FAR gspi_dev_t      *gspi = gbus->gspi;
+  int                 semcount;
+
+  gbus->irq_pending = true;
+
+  nxsem_get_value(&gbus->thread_signal, &semcount);
+
+  if (semcount < 1)
+    {
+      nxsem_post(&gbus->thread_signal);
+    }
+
+  /* Disable interrupt until bcmf_gspi_thread runs */
+
+  gspi->interrupt_enable(gspi, false);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_thread
+ ****************************************************************************/
+
+static int bcmf_gspi_thread(int argc, char **argv)
+{
+  FAR struct bcmf_dev_s *priv;
+  FAR bcmf_gspi_dev_t   *gbus;
+  FAR gspi_dev_t        *gspi;
+  uint32_t               status;
+  uint16_t               intr_flags;
+  int                    ret;
+  int                    length;
+  int                    wait_count      = 0;
+  bool                   wait_for_event;
+  bool                   enter_low_power = false;
+
+  priv = (FAR struct bcmf_dev_s *)((uintptr_t)strtoul(argv[1], NULL, 16));
+  gbus = (FAR bcmf_gspi_dev_t *)priv->bus;
+  gspi = gbus->gspi;
+
+  wlinfo(">>>> entered\n");
+
+  nxsig_usleep(50 * 1000);
+
+  gbus->thread_run = true;
+
+  bcmf_gspi_bus_lowpower(gbus, false);
+
+  while (gbus->thread_run)
+    {
+      /* Preset the wait for event flag in case we have nothing to do */
+
+      wait_for_event = true;
+
+      /* Get the device status */
+
+      status = bcmf_gspi_read_reg_32(gspi, gspi_f0_bus, CYW_REG_STATUS);
+
+#ifdef CONFIG_DEBUG_WIRELESS_ERROR
+      if (status & (1 << 2))
+        {
+          wlerr("CYW_REG_STATUS_FIFO_OVERFLOW\n");
+        }
+
+      if (status & (1 << 7))
+        {
+          wlerr("CYW_REG_STATUS_CMD_DATA_ERROR\n");
+        }
+#endif
+
+      /* If we were woken by an device interrupt clear the interrupt bits. */
+
+      if (gbus->irq_pending)
+        {
+          gbus->irq_pending = false;
+
+          /* These call also update the status in gspi->status */
+
+          intr_flags = bcmf_gspi_read_reg_16(gspi,
+                                             gspi_f0_bus,
+                                             CYW_REG_INTERRUPT);
+
+          if (intr_flags != 0)
+            {
+              bcmf_gspi_write_reg_16(gspi,
+                                    gspi_f0_bus,
+                                    CYW_REG_INTERRUPT,
+                                    intr_flags);
+            }
+        }
+
+      /* If we have a packet available to read -- read it */
+
+      if (status & CYW_REG_STATUS_F2_PKT_AVAIL)
+        {
+          length   = status & CYW_REG_STATUS_F2_PKT_LEN_MASK;
+          length >>= CYW_REG_STATUS_F2_PKT_LEN_SHIFT;
+
+          /* If we don't have a frame leave the loop */
+
+          if (length == 0) break;
+
+          /* Read and process frame. This updates gspi->status */
+
+          ret = bcmf_gspi_read_f2_frame(priv, length);
+
+          if (ret == OK)
+            {
+              wait_for_event = false;
+            }
+          else
+            {
+              wlerr("error reading f2 frame: %d\n", ret);
+            }
+        }
+      else
+        {
+          /* If we don't have anything to read, try sending a packet */
+
+          while ((status & CYW_REG_STATUS_F2_RECEIVE_RDY) == 0)
+            {
+              /* Oops! no room for a packet.  We'll wait a bit to see
+               * if room shows up.
+               */
+
+              wlinfo(">>>> not ready to receive\n");
+
+              if (++wait_count > 100)
+                {
+                  wlerr("Chip cannot receive F2 frame\n");
+                  break;
+                }
+
+              /* No room at the inn for an f2 frame -- wait a bit */
+
+              usleep(10000);
+
+              status = bcmf_gspi_read_reg_32(gspi,
+                                             gspi_f0_bus,
+                                             CYW_REG_STATUS);
+            }
+
+          /* reset the count for next time  */
+
+          wait_count = 0;
+
+          /* We have space, send the frame */
+
+          ret = bcmf_gspi_send_f2_frame(priv);
+
+          if (ret == OK)
+            {
+              wait_for_event = false;
+            }
+          else
+            {
+#ifdef CONFIG_DEBUG_WIRELESS_ERROR
+              if (ret != -ENODATA)
+                {
+                  wlerr("error sending f2 frame: %d\n", ret);
+                }
+#endif
+            }
+        }
+
+      /* No more transfer requests.  Wait for something to happen. */
+
+      if (wait_for_event)
+        {
+          /* Wait for event (device interrupt or user request) */
+
+          gspi->interrupt_enable(gspi, true);
+
+          if (enter_low_power)
+            {
+              enter_low_power = false;
+
+              bcmf_gspi_bus_lowpower(gbus, true);
+              nxsem_wait_uninterruptible(&gbus->thread_signal);
+              bcmf_gspi_bus_lowpower(gbus, false);
+            }
+          else
+            {
+              ret = nxsem_tickwait_uninterruptible(
+                            &gbus->thread_signal,
+                            BCMF_GSPI_LOWPOWER_TIMEOUT_TICK);
+
+              if (ret == -ETIMEDOUT) enter_low_power = true;
+            }
+        }
+    }
+
+  wlinfo(">>>> exit\n");
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_init_device
+ *
+ * Description:
+ *   Keeps checking the 43439's test register looking for the test pattern.
+ *   When found puts the chip in 32-bit mode.
+ *
+ * Note:
+ *   Some calls to the 43439 in this function uses the "magic" rev16 mode
+ *   to account for the 16-bit mode's default byte ordering.
+ ****************************************************************************/
+
+static int bcmf_gspi_init_device(FAR bcmf_gspi_dev_t *gbus)
+{
+  FAR gspi_dev_t *gspi = gbus->gspi;
+  uint32_t        buffer[2];
+  uint32_t        data;
+  int             ret;
+  int             i;
+
+  wlinfo("entered.\n");
+
+  /* Look for the chip ready pattern. */
+
+  for (i = 0; i < BCMF_GSPI_READY_TRYS; ++i)
+    {
+      ret = gspi->read(gspi,
+                       true,
+                       gspi_f0_bus_rev16,
+                       CYW_REG_TEST_RO,
+                       4,
+                       buffer);
+
+      if (ret != 0)
+        {
+          wlerr("Error looking for \"ready\" pattern: %d\n", ret);
+          return ret;
+        }
+
+      if (REV16(buffer[0]) == CYW_REG_TEST_RO_PATTERN) break;
+    }
+
+  if (i == BCMF_GSPI_READY_TRYS)
+    {
+      wlerr("Could not find cyw43439 \"ready\" pattern\n");
+      return -ENODEV;
+    }
+
+  data =   CYW_REG_SETUP_WORD_LEN_32
+         | CYW_REG_SETUP_BIG_ENDIAN
+         | CYW_REG_SETUP_HIGH_SPEED
+         | CYW_REG_SETUP_INT_POLARITY
+         | CYW_REG_SETUP_WAKE_UP
+         | CYW_REG_STAT_ENA_INTR_STAT;
+
+  data = REV16(data);
+
+  gspi->write(gspi, true, gspi_f0_bus_rev16, CYW_REG_SETUP, 4, &data);
+
+  /* We are now in 32-bit bigendian mode -- we no longer do REV16s. */
+
+  /* Set a 4-byte response delay for F1 packets */
+
+  bcmf_gspi_write_reg_8(gspi, gspi_f0_bus, CYW_REG_RESP_DELAY_F1, 4);
+
+  wlinfo("complete\n");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_probe_chip
+ ****************************************************************************/
+
+static int bcmf_gspi_probe_chip(FAR bcmf_gspi_dev_t *gbus)
+{
+  uint32_t        value;
+  int             chipid;
+  int             ret;
+
+  wlinfo("entered\n");
+
+  ret = bcmf_read_sbregw(gbus, SI_ENUM_BASE, &value);
+  if (ret != OK)
+    {
+      wlerr("bcmf_read_sbregw failed\n");
+      return ret;
+    }
+
+  chipid            = value & 0xffff;
+  gbus->cur_chip_id = chipid;
+
+  switch (chipid)
+    {
+#ifdef CONFIG_IEEE80211_INFINEON_CYW43439
+      case SDIO_DEVICE_ID_INFINEON_CYW43439:
+        wlinfo("cyw%d chip detected\n", chipid);
+        gbus->chip = (struct bcmf_chip_data *)&cyw43439_config_data;
+        break;
+#endif
+
+      default:
+        wlerr("chip 0x%08X is not supported\n", chipid);
+        return -ENODEV;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_setup_interrupts
+ ****************************************************************************/
+
+static int bcmf_gspi_setup_interrupts(FAR bcmf_gspi_dev_t *gbus)
+{
+  FAR gspi_dev_t *gspi = gbus->gspi;
+
+  wlinfo("entered\n");
+
+  /* Set up device interrupt preferences */
+
+  bcmf_gspi_write_reg_16(gspi,
+                         gspi_f0_bus,
+                         CYW_REG_INTERRUPT,
+                         CYW_REG_INTERRUPT_DATA_NOT_AVAIL
+                       | CYW_REG_INTERRUPT_COMMAND_ERROR
+                       | CYW_REG_INTERRUPT_DATA_ERROR
+                       | CYW_REG_INTERRUPT_F1_OVERFLOW);
+
+  /* We only want an interrupt if an F2 packet is available */
+
+  bcmf_gspi_write_reg_16(gspi,
+                         gspi_f0_bus,
+                         CYW_REG_INTR_ENA,
+                         CYW_REG_INTR_ENA_F2_PKT_AVAIL);
+
+  wlinfo("interrupt set up complete\n");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_init_alp_clock
+ ****************************************************************************/
+
+static int bcmf_gspi_init_alp_clock(FAR bcmf_gspi_dev_t *gbus)
+{
+  FAR gspi_dev_t *gspi = gbus->gspi;
+  int             loops;
+  uint8_t         value;
+
+  wlinfo("entered\n");
+
+  /* Send Active Low-Power clock request */
+
+  bcmf_gspi_write_reg_8(gspi,
+                        gspi_f1_backplane,
+                        SBSDIO_FUNC1_CHIPCLKCSR,
+                          SBSDIO_FORCE_HW_CLKREQ_OFF
+                        | SBSDIO_ALP_AVAIL_REQ
+                        | SBSDIO_FORCE_ALP);
+
+  loops = 10;
+  while (--loops > 0)
+    {
+      nxsig_usleep(10 * 1000);
+
+      value = bcmf_gspi_read_reg_8(gspi,
+                                   gspi_f1_backplane,
+                                   SBSDIO_FUNC1_CHIPCLKCSR);
+
+      if (value & SBSDIO_ALP_AVAIL)
+        {
+          /* Active Low-Power clock is ready */
+
+          break;
+        }
+    }
+
+  if (loops <= 0)
+    {
+      wlerr("failed to enable ALP\n");
+      return -ETIMEDOUT;
+    }
+
+  /* Clear Active Low-Power clock request */
+
+  bcmf_gspi_write_reg_8(gspi,
+                        gspi_f1_backplane,
+                        SBSDIO_FUNC1_CHIPCLKCSR,
+                        0);
+
+  wlinfo("ALP initialization complete\n");
+
+  nxsig_usleep(100 * 1000);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_init_save_restore
+ ****************************************************************************/
+
+static int bcmf_gspi_init_save_restore(FAR bcmf_gspi_dev_t *gbus)
+{
+  uint8_t  data;
+  uint32_t srctrl = 0;
+  int      ret;
+
+  wlinfo("entered\n");
+
+  ret = bcmf_read_sbregw(gbus, CHIPCOMMON_SR_CONTROL1, &srctrl);
+  if (ret != OK)
+    {
+      wlinfo("exit -- not SR capable.\n");
+
+      return OK;  /* chip not sr capable */
+    }
+
+  if (srctrl != 0)
+    {
+      /* Configure WakeupCtrl register to set HtAvail request bit in
+       * chipClockCSR register after the sdiod core is powered on.
+       */
+
+      bcmf_read_reg(gbus, 1, SBSDIO_FUNC1_WAKEUPCTRL, &data);
+      data |= SBSDIO_FUNC1_WCTRL_HTWAIT_MASK;
+      bcmf_write_reg(gbus, 1, SBSDIO_FUNC1_WAKEUPCTRL, data);
+
+      /* Set brcmCardCapability to noCmdDecode mode.
+       * It makes sdiod_aos to wakeup host for any activity of cmd line,
+       * even though module won't decode cmd or respond
+       */
+
+      bcmf_write_reg(gbus, 0, SDIO_CCCR_BRCM_CARDCAP,
+                     SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC);
+      bcmf_write_reg(gbus, 1, SBSDIO_FUNC1_CHIPCLKCSR,
+                     SBSDIO_FORCE_HT);
+
+      /* Enable KeepSdioOn (KSO) bit for normal operation */
+
+      bcmf_gspi_kso_enable(gbus, true);
+
+      gbus->support_sr = true;
+    }
+
+  wlinfo("exit\n");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_hw_uninitialize
+ ****************************************************************************/
+
+static int bcmf_gspi_hw_uninitialize(FAR bcmf_gspi_dev_t *gbus)
+{
+  FAR gspi_dev_t *gspi = gbus->gspi;
+
+  wlinfo("entered\n");
+
+  if (gbus->thread_id != 0)
+    {
+      gbus->thread_run = false;
+      nxsem_post(&gbus->thread_signal);
+    }
+
+  gspi->deinit(gspi);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: bcmf_bus_gspi_initialize
+ *
+ * Description:
+ *   Initialize a bcmf device connected via gSPI interface.
+ *
+ ****************************************************************************/
+
+static int bcmf_bus_gspi_initialize(FAR struct bcmf_dev_s  *priv,
+                                    FAR struct gspi_dev_s  *gspi)
+{
+  FAR bcmf_gspi_dev_t *gbus;
+  int                  ret;
+
+  wlinfo("entered.\n");
+
+  /* Allocate gSPI bus structure */
+
+  gbus = (FAR bcmf_gspi_dev_t *)kmm_zalloc(sizeof(*gbus));
+
+  if (!gspi)
+    {
+      return -ENOMEM;
+    }
+
+  /* Initialize sdio bus device structure */
+
+  gbus->gspi               = gspi;
+  gbus->ready              = false;
+  gbus->sleeping           = true;
+
+  /* FIX ME -- The interface needs some room to send F2 packets
+   *           to the device before we've read the first F2
+   *           packet from the device, so we set the max_seq
+   *           to something small;
+   */
+
+  gbus->max_seq            = 4;
+
+  gbus->bus.txframe        = bcmf_sdpcm_queue_frame;
+  gbus->bus.rxframe        = bcmf_sdpcm_get_rx_frame;
+  gbus->bus.allocate_frame = bcmf_sdpcm_alloc_frame;
+  gbus->bus.free_frame     = bcmf_sdpcm_free_frame;
+  gbus->bus.stop           = NULL; /* TODO */
+
+  /* Init transmit frames queue */
+
+  if ((ret = nxsem_init(&gbus->queue_mutex, 0, 1)) != OK)
+    {
+      goto exit_free_bus;
+    }
+
+  list_initialize(&gbus->tx_queue);
+  list_initialize(&gbus->rx_queue);
+
+  /* Setup free buffer list */
+
+  bcmf_initialize_interface_frames();
+
+  /* Init thread semaphore */
+
+  if ((ret = nxsem_init(&gbus->thread_signal, 0, 0)) != OK)
+    {
+      goto exit_free_bus;
+    }
+
+  if ((ret = nxsem_set_protocol(&gbus->thread_signal, SEM_PRIO_NONE)) != OK)
+    {
+      goto exit_free_bus;
+    }
+
+  /* Register sdio bus */
+
+  priv->bus  = &gbus->bus;
+
+  /* Save a back pointer so we can recover driver state */
+
+  gspi->priv = priv;
+
+  wlinfo("complete.\n");
+
+  return OK;
+
+exit_free_bus:
+
+  wlinfo("failed.\n");
+
+  kmm_free(gbus);
+  priv->bus = NULL;
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: bcmf_gspi_initialize
+ *
+ * Description:
+ *   Initialize the drive with a gSPI connection.
+ ****************************************************************************/
+
+int bcmf_gspi_initialize(FAR struct gspi_dev_s *gspi)
+{
+  int ret;
+  FAR struct bcmf_dev_s *priv;
+
+  ninfo("entered.\n");
+
+  priv = bcmf_allocate_device();
+  if (!priv)
+    {
+      return -ENOMEM;
+    }
+
+  /* Init sdio bus */
+
+  ret = bcmf_bus_gspi_initialize(priv, gspi);
+  if (ret != OK)
+    {
+      ret = -EIO;
+      goto exit_free_device;
+    }
+
+  /* Bus initialized, register network driver */
+
+  return bcmf_driver_initialize(priv);
+
+exit_free_device:
+  bcmf_free_device(priv);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: bcmf_bus_gspi_active
+ *
+ * Description:
+ *   Activate (or deactivate) a bcmf device connected via gSPI interface.
+ ****************************************************************************/
+
+int bcmf_bus_gspi_active(FAR struct bcmf_dev_s *priv,
+                         bool                   active)
+{
+  FAR bcmf_gspi_dev_t  *gbus = (FAR bcmf_gspi_dev_t *)priv->bus;
+  FAR gspi_dev_t       *gspi = gbus->gspi;
+  int                   ret  = OK;
+  FAR char             *argv[2];
+  char                  arg1[32];
+
+  wlinfo("entered.  active = %d\n", active);
+
+  if (!active)
+    {
+      goto exit_uninit_hw;
+    }
+
+  /* Initialize device hardware */
+
+  ret = gspi->init(gspi);
+
+  if (ret != OK)
+    {
+      return ret;
+    }
+
+  gbus->ready = active;
+
+  /* Probe device */
+
+  ret = bcmf_gspi_init_device(gbus);
+  if (ret != OK)
+    {
+      goto exit_uninit_hw;
+    }
+
+  /* Detect and configure for specific chip */
+
+  ret = bcmf_gspi_probe_chip(gbus);
+  if (ret != OK)
+    {
+      wlerr("bcmf_gspi_probe_chip failed\n");
+      goto exit_uninit_hw;
+    }
+
+  ret = bcmf_gspi_setup_interrupts(gbus);
+  if (ret != OK)
+    {
+      goto exit_uninit_hw;
+    }
+
+  /* Active the low power clock */
+
+  ret = bcmf_gspi_init_alp_clock(gbus);
+  if (ret != OK)
+    {
+      goto exit_uninit_hw;
+    }
+
+  /* Upload firmware */
+
+  ret = bcmf_core_upload_firmware(gbus);
+  if (ret != OK)
+    {
+      wlerr("bcmf_core_upload_firmware failed\n");
+      goto exit_uninit_hw;
+    }
+
+  /* Spawn bcmf daemon thread */
+
+  snprintf(arg1, sizeof(arg1), "%p", priv);
+  argv[0] = arg1;
+  argv[1] = NULL;
+  ret = kthread_create(BCMF_GSPI_THREAD_NAME,
+                       CONFIG_IEEE80211_BROADCOM_SCHED_PRIORITY,
+                       BCMF_GSPI_THREAD_STACK_SIZE,
+                       bcmf_gspi_thread,
+                       argv);
+  if (ret <= 0)
+    {
+      wlerr("Cannot spawn daemon thread\n");
+      ret = -EBADE;
+      goto exit_uninit_hw;
+    }
+
+  gbus->thread_id = (pid_t)ret;
+
+  ret = gspi->set_isr(gspi, bcmf_gspi_thread_isr, gbus);
+
+  if (ret != OK)
+    {
+      wlerr("set_isr failed\n");
+      goto exit_uninit_hw;
+    }
+
+  ret = bcmf_gspi_init_save_restore(gbus);
+  if (ret != OK)
+    {
+      goto exit_uninit_hw;
+    }
+
+  return OK;
+
+exit_uninit_hw:
+  gbus->ready = false;
+  bcmf_gspi_hw_uninitialize(gbus);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: bcmf_transfer_bytes
+ ****************************************************************************/
+
+/* FIXME: Low level bus data transfer function
+ * To avoid bus error, len will be aligned to:
+ * - upper power of 2 iflen is lesser than 64
+ * - upper 64 bytes block if len is greater than 64
+ */
+
+int bcmf_transfer_bytes(FAR bcmf_gspi_dev_t *gbus,
+                        bool                 write,
+                        uint8_t              function,
+                        uint32_t             address,
+                        uint8_t             *buf,
+                        unsigned int         len)
+{
+  FAR gspi_dev_t *gspi = gbus->gspi;
+  int             ret;
+
+  DEBUGASSERT((((uintptr_t) buf) & 0x03) == 0); /* make sure buf is word aligned */
+
+  if (write)
+    {
+      ret = gspi->write(gspi,
+                        true,
+                        function,
+                        address,
+                        len,
+                        (FAR uint32_t *) buf);
+
+      return ret;
+    }
+
+  /* -- read btytes -- */
+
+  ret = gspi->read(gspi,
+                   true,
+                   function,
+                   address,
+                   len,
+                   (FAR uint32_t *) buf);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: bcmf_read_reg
+ ****************************************************************************/
+
+int bcmf_read_reg(FAR bcmf_gspi_dev_t *gbus,
+                  uint8_t              function,
+                  uint32_t             address,
+                  uint8_t             *reg)
+{
+  *reg = bcmf_gspi_read_reg_8(gbus->gspi, function, address);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: bcmf_write_reg
+ ****************************************************************************/
+
+int bcmf_write_reg(FAR bcmf_gspi_dev_t *gbus,
+                   uint8_t              function,
+                   uint32_t             address,
+                   uint8_t              reg)
+{
+  bcmf_gspi_write_reg_8(gbus->gspi, function, address, reg);
+
+  return OK;
+}
+
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi.h
new file mode 100644
index 0000000000..58cd1d361e
--- /dev/null
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+ * drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_GSPI_H
+#define __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_GSPI_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <nuttx/list.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/wireless/ieee80211/bcmf_gspi.h>
+
+#include "bcmf_chip_data.h"
+#include "bcmf_driver.h"
+#include "bcmf_sdio_core.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define HEADER_SIZE          0x12 /* Default sdpcm + bdc header size */
+#define FIRST_WORD_SIZE      4
+#define FC_UPDATE_PKT_LENGTH 12
+
+#define BCMF_UPLOAD_TRANSFER_SIZE  64
+
+/* gSPI bus structure extension */
+
+typedef struct bcmf_gspi_dev_s
+{
+  struct bcmf_bus_dev_s  bus;      /* Default bcmf bus structure */
+  FAR struct gspi_dev_s *gspi;     /* The gSPI device bound to this instance */
+
+  int  cur_chip_id;                /* Chip ID read from the card */
+  struct bcmf_chip_data *chip;     /* Chip specific configuration */
+
+  volatile bool ready;             /* Current device status */
+  bool sleeping;                   /* Current sleep status */
+  bool kso_enable;                 /* Current Keep sdio on status */
+  bool support_sr;                 /* Firmware support save restore */
+
+  pid_t thread_id;                 /* Processing thread id */
+  sem_t thread_signal;             /* Semaphore for processing thread event */
+  volatile bool  thread_run;       /* Set false to exit processing thread */
+  volatile bool irq_pending;       /* True if interrupt is pending */
+
+  uint32_t backplane_current_addr; /* Current function 1 backplane base addr */
+
+  uint8_t max_seq;                 /* Maximum transmit sequence allowed */
+  uint8_t tx_seq;                  /* Transmit sequence number (next) */
+
+  sem_t queue_mutex;               /* Lock for TX/RX/free queues */
+  struct list_node tx_queue;       /* Queue of frames to transmit */
+  struct list_node rx_queue;       /* Queue of frames used to receive */
+  volatile int tx_queue_count;     /* Count of items in TX queue */
+} bcmf_gspi_dev_t;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+int bcmf_gspi_initialize(FAR struct gspi_dev_s *gspi);
+
+int bcmf_bus_gspi_active(FAR struct bcmf_dev_s *priv,
+                         bool                   active);
+
+/* FIXME: Low level bus data transfer function
+ * To avoid bus error, len will be aligned to:
+ * - upper power of 2 iflen is lesser than 64
+ * - upper 64 bytes block if len is greater than 64
+ */
+
+int bcmf_transfer_bytes(FAR bcmf_gspi_dev_t *gbus,
+                        bool                 write,
+                        uint8_t              function,
+                        uint32_t             address,
+                        uint8_t             *buf,
+                        unsigned int         len);
+
+int bcmf_read_reg(FAR bcmf_gspi_dev_t *gbus,
+                  uint8_t              function,
+                  uint32_t             address,
+                  uint8_t             *reg);
+
+int bcmf_write_reg(FAR bcmf_gspi_dev_t *gbus,
+                   uint8_t              function,
+                   uint32_t             address,
+                   uint8_t              reg);
+
+#endif /* __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_GSPI_H */
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi_f2_frame.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi_f2_frame.c
new file mode 100644
index 0000000000..c534982baa
--- /dev/null
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi_f2_frame.c
@@ -0,0 +1,394 @@
+/****************************************************************************
+ * drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi_f2_frame.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/compiler.h>
+
+#include <debug.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <nuttx/arch.h>
+
+#include <stddef.h>
+#include <string.h>
+
+#include "bcmf_core.h"
+#include "bcmf_sdpcm.h"
+#include "bcmf_cdc.h"
+#include "bcmf_bdc.h"
+#include "bcmf_utils.h"
+
+ #include "bcmf_netdev.h"
+
+#include "bcmf_sdio_regs.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define F2_FRAME_CONTROL_CHANNEL 0  /* Control frame id */
+#define F2_FRAME_EVENT_CHANNEL   1  /* Asynchronous event frame id */
+#define F2_FRAME_DATA_CHANNEL    2  /* Data frame id */
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+begin_packed_struct struct f2_frame_header_s
+{
+  uint16_t size;
+  uint16_t checksum;
+  uint8_t  sequence;
+  uint8_t  channel;
+  uint8_t  next_length;
+  uint8_t  data_offset;
+  uint8_t  flow_control;
+  uint8_t  credit;
+  uint16_t padding;
+} end_packed_struct;
+
+typedef struct f2_frame_header_s f2_frame_header_t;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: f2_frame_rx_fail
+ ****************************************************************************/
+
+static int f2_frame_rx_fail(FAR bcmf_gspi_dev_t *gbus, bool retry)
+{
+  /* issue abort command for F2 through F0 */
+
+  bcmf_bus_io_abort(gbus);
+
+  bcmf_write_reg(gbus, 1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM);
+
+  /* TODO Wait until the packet has been flushed (device/FIFO stable) */
+
+  if (retry)
+    {
+      /* Send NAK to retry to read frame */
+
+      bcmf_write_sbregb(gbus,
+                        CORE_BUS_REG(gbus->chip->core_base[SDIOD_CORE_ID],
+                                     tosbmailbox),
+                        SMB_NAK);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: process_f2_frame_header
+ ****************************************************************************/
+
+int process_f2_frame_header(FAR bcmf_interface_dev_t *gbus,
+                            f2_frame_header_t        *header)
+{
+  if (header->data_offset < sizeof(f2_frame_header_t)
+      || header->data_offset > header->size)
+    {
+      wlerr("Invalid data offset\n");
+      f2_frame_rx_fail(gbus, false);
+      return -ENXIO;
+    }
+
+  /* Update tx credits */
+
+  gbus->max_seq = header->credit;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: read_f2_frame
+ *
+ * Description:
+ *    Read and process an F2 frame.
+ *
+ * Parameters:
+ *    priv         - the device structure
+ *    frame_length - Length of frame we are to read.  (From chip status)
+ *
+ * Returns:
+ *    OK on success, negated error code on failure.
+ ****************************************************************************/
+
+int bcmf_gspi_read_f2_frame(FAR struct bcmf_dev_s *priv,
+                            int                    frame_length)
+{
+  FAR bcmf_gspi_dev_t *gbus = (FAR bcmf_gspi_dev_t *)priv->bus;
+  FAR gspi_dev_t      *gspi = gbus->gspi;
+
+  bcmf_interface_frame_t   *iframe;
+  f2_frame_header_t        *header;
+  int                       ret;
+  uint16_t                  checksum;
+
+  /* Request free frame buffer */
+
+  if (frame_length <= sizeof(f2_frame_header_t))
+    {
+      return -EINVAL;
+    }
+
+  iframe = bcmf_interface_allocate_frame(priv, false, false);
+
+  if (iframe == NULL)
+    {
+      wlinfo("fail alloc\n");
+      return -EAGAIN;
+    }
+
+  if (frame_length > iframe->header.len)
+    {
+      wlerr("Frame is too large, cancel %d > %d\n",
+            frame_length,
+            iframe->header.len);
+
+      ret = -ENOMEM;
+      goto exit_abort;
+    }
+
+  /* Read the frame data (the buffer is DMA aligned here) */
+
+  ret = gspi->read(gspi,
+                   true,
+                   gspi_f2_dma,
+                   0,
+                   frame_length,
+                   (uint32_t *) iframe->data);
+
+  if (ret != OK)
+    {
+      wlinfo("Failed to read frame data\n");
+      ret = -EIO;
+      goto exit_abort;
+    }
+
+  header = (f2_frame_header_t *)iframe->data;
+
+  if (header->size == 0)
+    {
+      ret = OK;
+      goto exit_free_frame;
+    }
+
+  checksum = header->size | header->checksum;
+
+  if (checksum != 0xffff || header->size < sizeof(f2_frame_header_t))
+    {
+      wlerr("Checksum failed: size:.0x%04X checksum: 0x%04X\n",
+            header->size,
+            header->checksum);
+
+      bcmf_hexdump((uint8_t *)header, MIN(header->size, 64), 0);
+
+      f2_frame_rx_fail(gbus, false);
+      return -EINVAL;
+    }
+
+  /* Process and validate header */
+
+  ret = process_f2_frame_header(gbus, header);
+  if (ret != OK)
+    {
+      wlerr("Error while processing header %d\n", ret);
+      ret = -EINVAL;
+      goto exit_free_frame;
+    }
+
+  if (header->size == FC_UPDATE_PKT_LENGTH)
+    {
+      /* Flow control update packet with no data */
+
+      return OK;
+    }
+
+  /* Update frame structure */
+
+  iframe->header.len   = header->size;
+  iframe->header.data += header->data_offset;
+
+  /* Process received frame content */
+
+  switch (header->channel & 0x0f)
+    {
+      case F2_FRAME_CONTROL_CHANNEL:
+        ret = bcmf_cdc_process_control_frame(priv, &iframe->header);
+        goto exit_free_frame;
+
+      case F2_FRAME_EVENT_CHANNEL:
+        if (header->data_offset == header->size)
+          {
+            /* Empty event, ignore */
+
+            ret = OK;
+          }
+        else
+          {
+            ret = bcmf_bdc_process_event_frame(priv, &iframe->header);
+          }
+
+        goto exit_free_frame;
+
+      case F2_FRAME_DATA_CHANNEL:
+
+        /* Queue frame and notify network layer frame is available */
+
+        if (nxsem_wait_uninterruptible(&gbus->queue_mutex) < 0)
+          {
+            DEBUGPANIC();
+          }
+
+        list_add_tail(&gbus->rx_queue, &iframe->list_entry);
+        nxsem_post(&gbus->queue_mutex);
+
+        bcmf_netdev_notify_rx(priv);
+
+        /* Upper layer have to free all received frames */
+
+        ret = OK;
+        break;
+
+      default:
+        wlerr("Got unexpected message type %d\n", header->channel);
+        ret = -EINVAL;
+        goto exit_free_frame;
+    }
+
+  return ret;
+
+exit_abort:
+  f2_frame_rx_fail(gbus, false);
+exit_free_frame:
+  bcmf_interface_free_frame(priv, iframe);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: bcmf_gspi_send_f2_frame
+ *
+ * Description:
+ *    De-queue and send an F2 frame.
+ *
+ * Parameters:
+ *    priv     - the device structure
+ *
+ * Returns:
+ *    OK on success, negated error code on failure.
+ ****************************************************************************/
+
+int bcmf_gspi_send_f2_frame(FAR struct bcmf_dev_s *priv)
+{
+  FAR bcmf_gspi_dev_t      *gbus = (FAR bcmf_gspi_dev_t *)priv->bus;
+  FAR gspi_dev_t           *gspi = gbus->gspi;
+  f2_frame_header_t       *header;
+  bcmf_interface_frame_t  *iframe;
+  int                      ret;
+  bool                     is_txframe;
+
+  if (list_is_empty(&gbus->tx_queue))
+    {
+      /* No more frames to send */
+
+      return -ENODATA;
+    }
+
+  if (gbus->tx_seq == gbus->max_seq)
+    {
+      /* TODO handle this case */
+
+      wlerr("No credit to send frame\n");
+      return -EAGAIN;
+    }
+
+  if (nxsem_wait_uninterruptible(&gbus->queue_mutex) < 0)
+    {
+      DEBUGPANIC();
+    }
+
+  iframe = list_remove_head_type(&gbus->tx_queue,
+                                 bcmf_interface_frame_t,
+                                 list_entry);
+
+  nxsem_post(&gbus->queue_mutex);
+
+  is_txframe = iframe->tx;
+
+  header = (f2_frame_header_t *)iframe->header.base;
+
+  /* Set frame sequence id */
+
+  header->sequence = gbus->tx_seq++;
+
+#if 0
+  wlinfo("\n>>>---> Send frame %p %d\n", iframe, iframe->header.len);
+
+  wlinfo("size:%d  seq: %d, channel: %d  next len: %d\n",
+         header->size,
+         header->sequence,
+         header->channel,
+         header->next_length);
+
+  wlinfo("data offset:0x%02X  flow: %d, credit: %d\n",
+          header->data_offset,
+          header->flow_control,
+          header->credit);
+#endif
+
+#if 0
+  bcmf_hexdump(iframe->header.base, iframe->header.len,
+               (unsigned long)iframe->header.base);
+#endif
+
+  /* Write the frame data (the buffer is DMA aligned here) */
+
+  ret = gspi->write(gspi,
+                    true,
+                    gspi_f2_dma,
+                    0,
+                    iframe->header.len,
+                    (FAR uint32_t *) iframe->header.base);
+
+  /* Free frame buffer */
+
+  bcmf_interface_free_frame(priv, iframe);
+
+  if (ret == OK && is_txframe)
+    {
+      /* Notify upper layer at least one TX buffer is available */
+
+      bcmf_netdev_notify_tx(priv);
+    }
+
+  return ret;
+}
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_4301x.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi_f2_frame.h
similarity index 50%
copy from drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_4301x.c
copy to drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi_f2_frame.h
index 7fdbea81ef..bad14cba45 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_4301x.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi_f2_frame.h
@@ -1,5 +1,5 @@
 /****************************************************************************
- * drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_4301x.c
+ * drivers/wireless/ieee80211/bcm43xxx/bcmf_gspi_f2_frame.h
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -18,66 +18,49 @@
  *
  ****************************************************************************/
 
+#ifndef __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_GSPI_F2_FRAME_H
+#define __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_GSPI_F2_FRAME_H
+
 /****************************************************************************
  * Included Files
  ****************************************************************************/
 
-#include <nuttx/config.h>
-#include <stdint.h>
-
-#include "bcmf_sdio.h"
+#include "bcmf_driver.h"
 
 /****************************************************************************
- * Pre-processor Definitions
+ * Public Function Prototypes
  ****************************************************************************/
 
-#define WRAPPER_REGISTER_OFFSET  0x100000
-
 /****************************************************************************
- * Public Data
+ * Name: read_f2_frame
+ *
+ * Description:
+ *    Read and process an F2 frame.
+ *
+ * Parameters:
+ *    priv         - the device structure
+ *    frame_length - Length of frame we are to read.  (From chip status)
+ *
+ * Returns:
+ *    OK on success, negated error code on failure.
  ****************************************************************************/
 
-extern const char bcm4301x_nvram_image[];
-extern const unsigned int bcm4301x_nvram_image_len;
-
-#ifndef CONFIG_IEEE80211_BROADCOM_FWFILES
-extern const uint8_t bcm4301x_firmware_image[];
-extern const unsigned int bcm4301x_firmware_image_len;
-#endif
-
-const struct bcmf_sdio_chip bcmf_4301x_config_sdio =
-{
-  /* General chip stats */
-
-  .ram_base = 0,
-  .ram_size = 0xa0000,
-
-  /* Backplane architecture */
-
-  .core_base =
-  {
-    [CHIPCOMMON_CORE_ID]  = 0x18000000,  /* Chipcommon core register base   */
-    [DOT11MAC_CORE_ID]    = 0x18001000,  /* dot11mac core register base     */
-    [SDIOD_CORE_ID]       = 0x18002000,  /* SDIOD Device core register base */
-    [WLAN_ARMCM3_CORE_ID] = 0x18003000 + /* ARMCM3 core register base       */
-                            WRAPPER_REGISTER_OFFSET,
-    [SOCSRAM_CORE_ID]     = 0x18004000 + /* SOCSRAM core register base      */
-                            WRAPPER_REGISTER_OFFSET
-  },
-
-  /* Firmware images */
-
-  /* TODO find something smarter than using image_len references */
-
-  .nvram_image         = (FAR uint8_t *)bcm4301x_nvram_image,
-  .nvram_image_size    = (FAR unsigned int *)&bcm4301x_nvram_image_len,
-
-#ifndef CONFIG_IEEE80211_BROADCOM_FWFILES
-  .firmware_image      = (FAR uint8_t *)bcm4301x_firmware_image,
-  .firmware_image_size = (FAR unsigned int *)&bcm4301x_firmware_image_len,
-#endif
-};
+int bcmf_gspi_read_f2_frame(FAR struct bcmf_dev_s *priv,
+                            int                    frame_length);
 
 /****************************************************************************
- * Public Functions
+ * Name: bcmf_gspi_send_f2_frame
+ *
+ * Description:
+ *    De-queue and send an F2 frame.
+ *
+ * Parameters:
+ *    priv     - the device structure
+ *
+ * Returns:
+ *    OK on success, negated error code on failure.
  ****************************************************************************/
+
+int bcmf_gspi_send_f2_frame(FAR struct bcmf_dev_s *priv);
+
+#endif /* __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_GSPI_F2_FRAME_H */
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_interface.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_interface.c
new file mode 100644
index 0000000000..a6aa74f245
--- /dev/null
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_interface.c
@@ -0,0 +1,144 @@
+/****************************************************************************
+ * drivers/wireless/ieee80211/bcm43xxx/bcmf_interface.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/signal.h>
+
+#include "bcmf_interface.h"
+#include "debug.h"
+#include "assert.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static bcmf_interface_frame_t
+g_pktframes[CONFIG_IEEE80211_BROADCOM_FRAME_POOL_SIZE];
+
+static struct list_node free_interface_frames;     /* Queue of available frames */
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: bcmf_initialize_interface_frames
+ ****************************************************************************/
+
+void bcmf_initialize_interface_frames(void)
+{
+  int i;
+
+  list_initialize(&free_interface_frames);
+
+  for (i = 0; i < CONFIG_IEEE80211_BROADCOM_FRAME_POOL_SIZE; ++i)
+    {
+      list_add_tail(&free_interface_frames, &g_pktframes[i].list_entry);
+    }
+}
+
+/****************************************************************************
+ * Name: bcmf_interface_free_frame
+ ****************************************************************************/
+
+void bcmf_interface_free_frame(FAR struct bcmf_dev_s  *priv,
+                               bcmf_interface_frame_t *iframe)
+{
+  FAR bcmf_interface_dev_t *ibus = (FAR bcmf_interface_dev_t *) priv->bus;
+
+  if (nxsem_wait_uninterruptible(&ibus->queue_mutex) < 0)
+    {
+      DEBUGPANIC();
+    }
+
+  list_add_head(&free_interface_frames, &iframe->list_entry);
+
+  if (iframe->tx)
+    {
+      ibus->tx_queue_count--;
+    }
+
+  nxsem_post(&ibus->queue_mutex);
+}
+
+/****************************************************************************
+ * Name: bcmf_interface_allocate_frame
+ ****************************************************************************/
+
+bcmf_interface_frame_t
+*bcmf_interface_allocate_frame(FAR struct bcmf_dev_s *priv,
+                                        bool                   block,
+                                        bool                   tx)
+{
+  FAR bcmf_interface_dev_t *ibus = (FAR bcmf_interface_dev_t *) priv->bus;
+  bcmf_interface_frame_t   *iframe;
+
+  while (1)
+    {
+      if (nxsem_wait_uninterruptible(&ibus->queue_mutex) < 0)
+        {
+          DEBUGPANIC();
+        }
+
+      if (!tx ||
+          ibus->tx_queue_count <
+            CONFIG_IEEE80211_BROADCOM_FRAME_POOL_SIZE / 2)
+        {
+          if ((iframe = list_remove_head_type(&free_interface_frames,
+                                              bcmf_interface_frame_t,
+                                              list_entry)) != NULL)
+            {
+              if (tx)
+                {
+                  ibus->tx_queue_count++;
+                }
+
+              nxsem_post(&ibus->queue_mutex);
+              break;
+            }
+        }
+
+      nxsem_post(&ibus->queue_mutex);
+
+      if (!block)
+        {
+          wlinfo("No avail buffer\n");
+          return NULL;
+        }
+
+      nxsig_usleep(10 * 1000);
+    }
+
+#if defined(CONFIG_IEEE80211_BROADCOM_FULLMAC_GSPI)
+  iframe->header.len  = CONFIG_IEEE80211_BROADCOM_FULLMAC_GSPI_MAX_FRAME;
+#else
+  iframe->header.len  = HEADER_SIZE + MAX_NETDEV_PKTSIZE +
+                        CONFIG_NET_GUARDSIZE;
+#endif
+  iframe->header.base = iframe->data;
+  iframe->header.data = iframe->data;
+  iframe->tx          = tx;
+  return iframe;
+}
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_interface.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_interface.h
new file mode 100644
index 0000000000..e617e880f2
--- /dev/null
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_interface.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+ * drivers/wireless/ieee80211/bcm43xxx/bcmf_interface.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_INTERFACE_H
+#define __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_INTERFACE_H
+
+/* ==== This file contains dispatch between the SDIO & gSPI interface. ==== */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#if defined(CONFIG_IEEE80211_BROADCOM_FULLMAC_SDIO)
+#include "bcmf_sdio.h"
+#elif defined(CONFIG_IEEE80211_BROADCOM_FULLMAC_GSPI)
+#include "bcmf_gspi.h"
+#else
+#error Must define IEEE80211_BROADCOM_FULLMAC_SDIO or IEEE80211_BROADCOM_FULLMAC_GSPI
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct bcmf_dev_s;
+
+#if defined(CONFIG_IEEE80211_BROADCOM_FULLMAC_SDIO)
+typedef struct bcmf_sdio_dev_s bcmf_interface_dev_t;
+#else
+typedef bcmf_gspi_dev_t bcmf_interface_dev_t;
+#endif
+
+/* Note:
+ * The structure referred to above must as its first item:
+ *
+ *  struct bcmf_bus_dev_s  bus;            --- Default bcmf bus structure
+ *
+ * The structure must also contain the following items:
+ *
+ *  int                    cur_chip_id;    --- Chip ID read from the card
+ *  struct bcmf_chip_data *chip;           --- Chip specific configuration
+ *
+ *  sem_t                  thread_signal;  --- Thread event semaphore
+ *
+ *  uint32_t       backplane_current_addr; --- Current F1 backplane base addr
+ *
+ *  uint8_t                max_seq;        --- Maximum TX sequence allowed
+ *  uint8_t                tx_seq;         --- TX sequence number (next)
+ *
+ *  sem_t                  queue_mutex;    --- Lock for TX/RX/free queues
+ *  struct list_node       tx_queue;       --- Queue of frames to transmit
+ *  struct list_node       rx_queue;       --- Queue of frames for receiving
+ *  volatile int           tx_queue_count; --- Count of items in TX queue
+ */
+
+/* Structure used to manage interface frames */
+
+typedef struct bcmf_interface_frame_s
+{
+  struct bcmf_frame_s header;
+  bool                tx;
+  struct list_node    list_entry;
+  uint8_t             pad[CONFIG_IEEE80211_BROADCOM_DMABUF_ALIGNMENT -
+                          FIRST_WORD_SIZE]
+  aligned_data(CONFIG_IEEE80211_BROADCOM_DMABUF_ALIGNMENT);
+
+  /* pad[] array is used and aligned in order to make the following data[]
+   * buffer aligned beginning from the offset of 4 bytes to the address
+   * boundary for SDIO DMA transfers.
+   * The first 4 bytes of data[] buffer are not directly used in DMA
+   * transfers. Instead, they are used as the initial phase just to get
+   * the length of the remaining long data to be read. Thus only
+   * the remaining part of data[] buffer beginning from the offset of 4 bytes
+   * is required to be aligned to the address boundary set by
+   * CONFIG_IEEE80211_BROADCOM_SDIO_DMA_BUF_ALIGNMENT parameter.
+   */
+
+  uint8_t             data[HEADER_SIZE + MAX_NETDEV_PKTSIZE +
+                           CONFIG_NET_GUARDSIZE];
+} bcmf_interface_frame_t;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: bcmf_bus_interface_active
+ ****************************************************************************/
+
+static inline int bcmf_bus_interface_active(FAR struct bcmf_dev_s *priv,
+                                            bool                   active)
+{
+#if defined(CONFIG_IEEE80211_BROADCOM_FULLMAC_SDIO)
+  return bcmf_bus_sdio_active(priv, active);
+#else
+  return bcmf_bus_gspi_active(priv, active);
+#endif
+}
+
+/****************************************************************************
+ * Name: bcmf_bus_io_abort
+ ****************************************************************************/
+
+static inline void bcmf_bus_io_abort(FAR bcmf_interface_dev_t *ibus)
+{
+#if defined(CONFIG_IEEE80211_BROADCOM_FULLMAC_SDIO)
+  bcmf_write_reg(ibus, 0, SDIO_CCCR_IOABORT, 2);
+#else
+  return;
+#endif
+}
+
+/****************************************************************************
+ * Name: bcmf_initialize_interface_frames
+ ****************************************************************************/
+
+void bcmf_initialize_interface_frames(void);
+
+/****************************************************************************
+ * Name: bcmf_interface_free_frame
+ ****************************************************************************/
+
+void bcmf_interface_free_frame(FAR struct bcmf_dev_s  *priv,
+                               bcmf_interface_frame_t *iframe);
+
+/****************************************************************************
+ * Name: bcmf_interface_allocate_frame
+ ****************************************************************************/
+
+bcmf_interface_frame_t
+*bcmf_interface_allocate_frame(FAR struct bcmf_dev_s *priv,
+                              bool                   block,
+                              bool                   tx);
+
+#endif /* __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_INTERFACE_H */
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_ioctl.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_ioctl.h
index ed0710fdc4..a4aa2d6d09 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_ioctl.h
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_ioctl.h
@@ -762,7 +762,13 @@ typedef struct wlc_iov_trx_s
 #define IOVAR_STR_AMPDU_RX_FACTOR        "ampdu_rx_factor"
 #define IOVAR_STR_MIMO_BW_CAP            "mimo_bw_cap"
 #define IOVAR_STR_CLMLOAD                "clmload"
+#define IOVAR_STR_CLVER                  "clmver"
 #define IOVAR_STR_JOIN                   "join"
+#define IOVAR_STR_GPIOOUT                "gpioout"
+#define IOVAR_STR_CCGPIOCTRL             "ccgpioctrl"
+#define IOVAR_STR_CCGPIOIN               "ccgpioin"
+#define IOVAR_STR_CCGPIOOUT              "ccgpioout"
+#define IOVAR_STR_CCGPIOPUTEN            "ccgpioputen"
 
 #define WLC_IOCTL_MAGIC                    ( 0x14e46c77 )
 #define WLC_IOCTL_VERSION                  (          1 )
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c
index d9557f4c02..80ab2897f7 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c
@@ -252,8 +252,6 @@ static void bcmf_receive(FAR struct bcmf_dev_s *priv)
       priv->bc_dev.d_buf = frame->data;
       priv->bc_dev.d_len = frame->len - (frame->data - frame->base);
 
-      wlinfo("Got frame %p %d\n", frame, priv->bc_dev.d_len);
-
 #ifdef CONFIG_NET_PKT
       /* When packet sockets are enabled, feed the frame into the tap */
 
@@ -270,6 +268,8 @@ static void bcmf_receive(FAR struct bcmf_dev_s *priv)
            * ignored.
            */
 
+          /* ### TODO ### Implement VLAN support */
+
           uint8_t temp_buffer[12];
           memcpy(temp_buffer, frame->data, 12);
           memcpy(frame->data + 4, temp_buffer, 12);
@@ -733,6 +733,8 @@ errout_in_critical_section:
 
   leave_critical_section(flags);
 
+  wlinfo("bcmf_ifup done: %d\n", ret);
+
   return ret;
 }
 
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.c
index 53f78ed1d2..66b3259c7f 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.c
@@ -77,16 +77,16 @@
 /* Supported chip configurations */
 
 #ifdef CONFIG_IEEE80211_BROADCOM_BCM4301X
-  extern const struct bcmf_sdio_chip bcmf_4301x_config_sdio;
+  extern const struct bcmf_chip_data bcmf_4301x_config_data;
 #endif
 #ifdef CONFIG_IEEE80211_BROADCOM_BCM43362
-  extern const struct bcmf_sdio_chip bcmf_43362_config_sdio;
+  extern const struct bcmf_chip_data bcmf_43362_config_data;
 #endif
 #ifdef CONFIG_IEEE80211_BROADCOM_BCM43438
-  extern const struct bcmf_sdio_chip bcmf_43438_config_sdio;
+  extern const struct bcmf_chip_data bcmf_43438_config_data;
 #endif
 #ifdef CONFIG_IEEE80211_BROADCOM_BCM43455
-  extern const struct bcmf_sdio_chip bcmf_43455_config_sdio;
+  extern const struct bcmf_chip_data bcmf_43455_config_data;
 #endif
 
 /****************************************************************************
@@ -114,15 +114,6 @@ static bool brcm_chip_sr_capable(FAR struct bcmf_sdio_dev_s *sbus);
  * Private Data
  ****************************************************************************/
 
-/* Buffer pool for SDIO bus interface
- * This pool is shared between all driver devices
- */
-
-static struct bcmf_sdio_frame
-  g_pktframes[CONFIG_IEEE80211_BROADCOM_FRAME_POOL_SIZE];
-
-/* TODO free_queue should be static */
-
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
@@ -647,10 +638,143 @@ static bool brcm_chip_sr_capable(FAR struct bcmf_sdio_dev_s *sbus)
     }
 }
 
+/****************************************************************************
+ * Name: bcmf_bus_sdio_initialize
+ ****************************************************************************/
+
+static int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
+                                    int minor, FAR struct sdio_dev_s *dev)
+{
+  FAR struct bcmf_sdio_dev_s *sbus;
+  FAR char *argv[2];
+  char arg1[32];
+  int ret;
+
+  /* Allocate sdio bus structure */
+
+  sbus = (FAR struct bcmf_sdio_dev_s *)kmm_malloc(sizeof(*sbus));
+
+  if (!sbus)
+    {
+      return -ENOMEM;
+    }
+
+  /* Initialize sdio bus device structure */
+
+  memset(sbus, 0, sizeof(*sbus));
+  sbus->sdio_dev           = dev;
+  sbus->minor              = minor;
+  sbus->ready              = false;
+  sbus->sleeping           = true;
+
+  sbus->bus.txframe        = bcmf_sdpcm_queue_frame;
+  sbus->bus.rxframe        = bcmf_sdpcm_get_rx_frame;
+  sbus->bus.allocate_frame = bcmf_sdpcm_alloc_frame;
+  sbus->bus.free_frame     = bcmf_sdpcm_free_frame;
+  sbus->bus.stop           = NULL; /* TODO */
+
+  /* Init transmit frames queue */
+
+  if ((ret = nxsem_init(&sbus->queue_mutex, 0, 1)) != OK)
+    {
+      goto exit_free_bus;
+    }
+
+  list_initialize(&sbus->tx_queue);
+  list_initialize(&sbus->rx_queue);
+
+  /* Setup free buffer list */
+
+  bcmf_initialize_interface_frames();
+
+  /* Init thread semaphore */
+
+  if ((ret = nxsem_init(&sbus->thread_signal, 0, 0)) != OK)
+    {
+      goto exit_free_bus;
+    }
+
+  if ((ret = nxsem_set_protocol(&sbus->thread_signal, SEM_PRIO_NONE)) != OK)
+    {
+      goto exit_free_bus;
+    }
+
+  /* Configure hardware */
+
+  bcmf_board_initialize(sbus->minor);
+
+  /* Register sdio bus */
+
+  priv->bus = &sbus->bus;
+
+  /* Spawn bcmf daemon thread */
+
+  snprintf(arg1, sizeof(arg1), "%p", priv);
+  argv[0] = arg1;
+  argv[1] = NULL;
+  ret = kthread_create(BCMF_THREAD_NAME,
+                       CONFIG_IEEE80211_BROADCOM_SCHED_PRIORITY,
+                       BCMF_THREAD_STACK_SIZE, bcmf_sdio_thread,
+                       argv);
+  if (ret <= 0)
+    {
+      wlerr("Cannot spawn bcmf thread\n");
+      ret = -EBADE;
+      goto exit_free_bus;
+    }
+
+  sbus->thread_id = (pid_t)ret;
+
+  return OK;
+
+exit_free_bus:
+  kmm_free(sbus);
+  priv->bus = NULL;
+  return ret;
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: bcmf_sdio_initialize
+ *
+ * Description:
+ *   Initialize the drive with a SDIO connection.
+ ****************************************************************************/
+
+int bcmf_sdio_initialize(int minor, FAR struct sdio_dev_s *dev)
+{
+  int ret;
+  FAR struct bcmf_dev_s *priv;
+
+  wlinfo("minor: %d\n", minor);
+
+  priv = bcmf_allocate_device();
+  if (!priv)
+    {
+      return -ENOMEM;
+    }
+
+  /* Init sdio bus */
+
+  ret = bcmf_bus_sdio_initialize(priv, minor, dev);
+  if (ret != OK)
+    {
+      ret = -EIO;
+      goto exit_free_device;
+    }
+
+  /* Bus initialized, register network driver */
+
+  return bcmf_driver_initialize(priv);
+
+exit_free_device:
+  bcmf_free_device(priv);
+  return ret;
+}
+
 /****************************************************************************
  * Name: bcmf_transfer_bytes
  ****************************************************************************/
@@ -789,107 +913,6 @@ exit_uninit_hw:
   return ret;
 }
 
-/****************************************************************************
- * Name: bcmf_bus_sdio_initialize
- ****************************************************************************/
-
-int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
-                             int minor, FAR struct sdio_dev_s *dev)
-{
-  FAR struct bcmf_sdio_dev_s *sbus;
-  FAR char *argv[2];
-  char arg1[32];
-  int ret;
-
-  /* Allocate sdio bus structure */
-
-  sbus = (FAR struct bcmf_sdio_dev_s *)kmm_malloc(sizeof(*sbus));
-
-  if (!sbus)
-    {
-      return -ENOMEM;
-    }
-
-  /* Initialize sdio bus device structure */
-
-  memset(sbus, 0, sizeof(*sbus));
-  sbus->sdio_dev           = dev;
-  sbus->minor              = minor;
-  sbus->ready              = false;
-  sbus->sleeping           = true;
-
-  sbus->bus.txframe        = bcmf_sdpcm_queue_frame;
-  sbus->bus.rxframe        = bcmf_sdpcm_get_rx_frame;
-  sbus->bus.allocate_frame = bcmf_sdpcm_alloc_frame;
-  sbus->bus.free_frame     = bcmf_sdpcm_free_frame;
-  sbus->bus.stop           = NULL; /* TODO */
-
-  /* Init transmit frames queue */
-
-  if ((ret = nxsem_init(&sbus->queue_mutex, 0, 1)) != OK)
-    {
-      goto exit_free_bus;
-    }
-
-  list_initialize(&sbus->tx_queue);
-  list_initialize(&sbus->rx_queue);
-  list_initialize(&sbus->free_queue);
-
-  /* Setup free buffer list */
-
-  /* FIXME this should be static to driver */
-
-  for (ret = 0; ret < CONFIG_IEEE80211_BROADCOM_FRAME_POOL_SIZE; ret++)
-    {
-      list_add_tail(&sbus->free_queue, &g_pktframes[ret].list_entry);
-    }
-
-  /* Init thread semaphore */
-
-  if ((ret = nxsem_init(&sbus->thread_signal, 0, 0)) != OK)
-    {
-      goto exit_free_bus;
-    }
-
-  if ((ret = nxsem_set_protocol(&sbus->thread_signal, SEM_PRIO_NONE)) != OK)
-    {
-      goto exit_free_bus;
-    }
-
-  /* Configure hardware */
-
-  bcmf_board_initialize(sbus->minor);
-
-  /* Register sdio bus */
-
-  priv->bus = &sbus->bus;
-
-  /* Spawn bcmf daemon thread */
-
-  snprintf(arg1, sizeof(arg1), "%p", priv);
-  argv[0] = arg1;
-  argv[1] = NULL;
-  ret = kthread_create(BCMF_THREAD_NAME,
-                       CONFIG_IEEE80211_BROADCOM_SCHED_PRIORITY,
-                       BCMF_THREAD_STACK_SIZE, bcmf_sdio_thread,
-                       argv);
-  if (ret <= 0)
-    {
-      wlerr("Cannot spawn bcmf thread\n");
-      ret = -EBADE;
-      goto exit_free_bus;
-    }
-
-  sbus->thread_id = (pid_t)ret;
-
-  return OK;
-
-exit_free_bus:
-  kmm_free(sbus);
-  priv->bus = NULL;
-  return ret;
-}
-
 int bcmf_chipinitialize(FAR struct bcmf_sdio_dev_s *sbus)
 {
   uint32_t value = 0;
@@ -911,28 +934,28 @@ int bcmf_chipinitialize(FAR struct bcmf_sdio_dev_s *sbus)
       case SDIO_DEVICE_ID_BROADCOM_43012:
       case SDIO_DEVICE_ID_BROADCOM_43013:
         wlinfo("bcm%d chip detected\n", chipid);
-        sbus->chip = (struct bcmf_sdio_chip *)&bcmf_4301x_config_sdio;
+        sbus->chip = (struct bcmf_chip_data *)&bcmf_4301x_config_data;
         break;
 #endif
 
 #ifdef CONFIG_IEEE80211_BROADCOM_BCM43362
       case SDIO_DEVICE_ID_BROADCOM_43362:
         wlinfo("bcm43362 chip detected\n");
-        sbus->chip = (struct bcmf_sdio_chip *)&bcmf_43362_config_sdio;
+        sbus->chip = (struct bcmf_chip_data *)&bcmf_43362_config_data;
         break;
 #endif
 
 #ifdef CONFIG_IEEE80211_BROADCOM_BCM43438
       case SDIO_DEVICE_ID_BROADCOM_43430:
         wlinfo("bcm43438 chip detected\n");
-        sbus->chip = (struct bcmf_sdio_chip *)&bcmf_43438_config_sdio;
+        sbus->chip = (struct bcmf_chip_data *)&bcmf_43438_config_data;
         break;
 #endif
 
 #ifdef CONFIG_IEEE80211_BROADCOM_BCM43455
       case SDIO_DEVICE_ID_BROADCOM_43455:
         wlinfo("bcm43455 chip detected\n");
-        sbus->chip = (struct bcmf_sdio_chip *)&bcmf_43455_config_sdio;
+        sbus->chip = (struct bcmf_chip_data *)&bcmf_43455_config_data;
         break;
 #endif
 
@@ -1048,73 +1071,3 @@ int bcmf_sdio_thread(int argc, char **argv)
   wlinfo("Exit\n");
   return 0;
 }
-
-struct bcmf_sdio_frame *bcmf_sdio_allocate_frame(FAR struct bcmf_dev_s *priv,
-                                                 bool block, bool tx)
-{
-  FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
-  struct bcmf_sdio_frame *sframe;
-
-  while (1)
-    {
-      if (nxsem_wait_uninterruptible(&sbus->queue_mutex) < 0)
-        {
-          DEBUGPANIC();
-        }
-
-      if (!tx ||
-          sbus->tx_queue_count <
-            CONFIG_IEEE80211_BROADCOM_FRAME_POOL_SIZE / 2)
-        {
-          if ((sframe = list_remove_head_type(&sbus->free_queue,
-                                         struct bcmf_sdio_frame,
-                                         list_entry)) != NULL)
-            {
-              if (tx)
-                {
-                  sbus->tx_queue_count++;
-                }
-
-              nxsem_post(&sbus->queue_mutex);
-              break;
-            }
-        }
-
-      nxsem_post(&sbus->queue_mutex);
-
-      if (!block)
-        {
-          wlinfo("No avail buffer\n");
-          return NULL;
-        }
-
-      nxsig_usleep(10 * 1000);
-    }
-
-  sframe->header.len  = HEADER_SIZE + MAX_NETDEV_PKTSIZE +
-                        CONFIG_NET_GUARDSIZE;
-  sframe->header.base = sframe->data;
-  sframe->header.data = sframe->data;
-  sframe->tx          = tx;
-  return sframe;
-}
-
-void bcmf_sdio_free_frame(FAR struct bcmf_dev_s *priv,
-                          struct bcmf_sdio_frame *sframe)
-{
-  FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
-
-  if (nxsem_wait_uninterruptible(&sbus->queue_mutex) < 0)
-    {
-      DEBUGPANIC();
-    }
-
-  list_add_head(&sbus->free_queue, &sframe->list_entry);
-
-  if (sframe->tx)
-    {
-      sbus->tx_queue_count--;
-    }
-
-  nxsem_post(&sbus->queue_mutex);
-}
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.h
index 9fbb78f155..5ee7fee333 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.h
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.h
@@ -34,6 +34,7 @@
 #include <nuttx/sdio.h>
 #include <nuttx/semaphore.h>
 
+#include "bcmf_chip_data.h"
 #include "bcmf_driver.h"
 #include "bcmf_sdio_core.h"
 
@@ -45,34 +46,12 @@
 #define FIRST_WORD_SIZE      4
 #define FC_UPDATE_PKT_LENGTH 12
 
+#define BCMF_UPLOAD_TRANSFER_SIZE (64 * 256)
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
 
-/* SDIO chip configuration structure */
-
-struct bcmf_sdio_chip
-{
-  uint32_t ram_base;
-  uint32_t ram_size;
-  uint32_t core_base[MAX_CORE_ID];
-
-  /* In-memory file images */
-
-  FAR uint8_t *nvram_image;
-  FAR unsigned int *nvram_image_size;
-
-#ifndef CONFIG_IEEE80211_BROADCOM_FWFILES
-  FAR uint8_t *firmware_image;
-  FAR unsigned int *firmware_image_size;
-
-#ifdef CONFIG_IEEE80211_BROADCOM_HAVE_CLM
-  FAR uint8_t *clm_blob_image;
-  FAR unsigned int *clm_blob_image_size;
-#endif
-#endif
-};
-
 /* SDIO bus structure extension */
 
 struct bcmf_sdio_dev_s
@@ -82,7 +61,7 @@ struct bcmf_sdio_dev_s
   int minor;                       /* Device minor number */
 
   int  cur_chip_id;                /* Chip ID read from the card */
-  struct bcmf_sdio_chip *chip;     /* Chip specific configuration */
+  struct bcmf_chip_data *chip;     /* Chip specific configuration */
 
   volatile bool ready;             /* Current device status */
   bool sleeping;                   /* Current sleep status */
@@ -103,44 +82,16 @@ struct bcmf_sdio_dev_s
   bool    flow_ctrl;               /* Current flow control status */
 
   sem_t queue_mutex;               /* Lock for TX/RX/free queues */
-  struct list_node free_queue;     /* Queue of available frames */
   struct list_node tx_queue;       /* Queue of frames to transmit */
   struct list_node rx_queue;       /* Queue of frames used to receive */
   volatile int tx_queue_count;     /* Count of items in TX queue */
 };
 
-/* Structure used to manage SDIO frames */
-
-struct bcmf_sdio_frame
-{
-  struct bcmf_frame_s header;
-  bool                tx;
-  struct list_node    list_entry;
-  uint8_t             pad[CONFIG_IEEE80211_BROADCOM_DMABUF_ALIGNMENT -
-                          FIRST_WORD_SIZE]
-  aligned_data(CONFIG_IEEE80211_BROADCOM_DMABUF_ALIGNMENT);
-
-  /* pad[] array is used and aligned in order to make the following data[]
-   * buffer aligned beginning from the offset of 4 bytes to the address
-   * boundary for SDIO DMA transfers.
-   * The first 4 bytes of data[] buffer are not directly used in DMA
-   * transfers. Instead, they are used as the initial phase just to get
-   * the length of the remaining long data to be read. Thus only
-   * the remaining part of data[] buffer beginning from the offset of 4 bytes
-   * is required to be aligned to the address boundary set by
-   * CONFIG_IEEE80211_BROADCOM_SDIO_DMA_BUF_ALIGNMENT parameter.
-   */
-
-  uint8_t             data[HEADER_SIZE + MAX_NETDEV_PKTSIZE +
-                           CONFIG_NET_GUARDSIZE];
-};
-
 /****************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
 
-int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
-          int minor, FAR struct sdio_dev_s *dev);
+int bcmf_sdio_initialize(int minor, FAR struct sdio_dev_s *dev);
 
 int bcmf_bus_sdio_active(FAR struct bcmf_dev_s *priv, bool active);
 
@@ -160,10 +111,4 @@ int bcmf_read_reg(FAR struct bcmf_sdio_dev_s *sbus, uint8_t function,
 int bcmf_write_reg(FAR struct bcmf_sdio_dev_s *sbus, uint8_t function,
                    uint32_t address, uint8_t reg);
 
-struct bcmf_sdio_frame *bcmf_sdio_allocate_frame(FAR struct bcmf_dev_s *priv,
-                                                 bool block, bool tx);
-
-void bcmf_sdio_free_frame(FAR struct bcmf_dev_s *priv,
-                          struct bcmf_sdio_frame *sframe);
-
 #endif /* __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_SDIO_H */
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio_core.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio_core.h
index 936135d386..cd86afe873 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio_core.h
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio_core.h
@@ -47,6 +47,7 @@
 #define SDIO_DEVICE_ID_BROADCOM_43362        43362
 #define SDIO_DEVICE_ID_BROADCOM_43430        43430
 #define SDIO_DEVICE_ID_BROADCOM_43455        0x4345
+#define SDIO_DEVICE_ID_INFINEON_CYW43439     43439
 
 /* Core reg address translation.
  * Both macro's returns a 32 bits byte address on the backplane bus.
@@ -82,23 +83,6 @@
 #define SMB_USE_OOB (1 << 2)  /* Use OOB Wakeup */
 #define SMB_DEV_INT (1 << 3)  /* Miscellaneous Interrupt */
 
-enum
-{
-  CHIPCOMMON_CORE_ID = 0,
-  DOT11MAC_CORE_ID,
-  SDIOD_CORE_ID,
-#if defined(CONFIG_IEEE80211_BROADCOM_BCM4301X) || \
-    defined(CONFIG_IEEE80211_BROADCOM_BCM43362) || \
-    defined(CONFIG_IEEE80211_BROADCOM_BCM43438)
-  WLAN_ARMCM3_CORE_ID,
-  SOCSRAM_CORE_ID,
-#endif
-#if defined(CONFIG_IEEE80211_BROADCOM_BCM43455)
-  WLAN_ARMCR4_CORE_ID,
-#endif
-  MAX_CORE_ID
-};
-
 struct chip_core_info
 {
   uint16_t id;
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdpcm.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdpcm.c
index 2c2f5fc0c2..eed19c26c0 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdpcm.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdpcm.c
@@ -34,11 +34,11 @@
 #include <stddef.h>
 #include <string.h>
 
-#include "bcmf_sdio.h"
 #include "bcmf_core.h"
 #include "bcmf_sdpcm.h"
 #include "bcmf_cdc.h"
 #include "bcmf_bdc.h"
+#include "bcmf_interface.h"
 #include "bcmf_utils.h"
 
  #include "bcmf_netdev.h"
@@ -74,9 +74,9 @@ begin_packed_struct struct bcmf_sdpcm_header
  * Private Function Prototypes
  ****************************************************************************/
 
-static int bcmf_sdpcm_rxfail(FAR struct bcmf_sdio_dev_s *sbus, bool retry);
+static int bcmf_sdpcm_rxfail(FAR bcmf_interface_dev_t *ibus, bool retry);
 
-static int bcmf_sdpcm_process_header(FAR struct bcmf_sdio_dev_s *sbus,
+static int bcmf_sdpcm_process_header(FAR bcmf_interface_dev_t *ibus,
                               struct bcmf_sdpcm_header *header);
 
 /****************************************************************************
@@ -87,13 +87,13 @@ static int bcmf_sdpcm_process_header(FAR struct bcmf_sdio_dev_s *sbus,
  * Private Functions
  ****************************************************************************/
 
-int bcmf_sdpcm_rxfail(FAR struct bcmf_sdio_dev_s *sbus, bool retry)
+int bcmf_sdpcm_rxfail(FAR bcmf_interface_dev_t *ibus, bool retry)
 {
   /* issue abort command for F2 through F0 */
 
-  bcmf_write_reg(sbus, 0, SDIO_CCCR_IOABORT, 2);
+  bcmf_bus_io_abort(ibus);
 
-  bcmf_write_reg(sbus, 1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM);
+  bcmf_write_reg(ibus, 1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM);
 
   /* TODO Wait until the packet has been flushed (device/FIFO stable) */
 
@@ -101,28 +101,28 @@ int bcmf_sdpcm_rxfail(FAR struct bcmf_sdio_dev_s *sbus, bool retry)
     {
       /* Send NAK to retry to read frame */
 
-      bcmf_write_sbregb(sbus,
-                  CORE_BUS_REG(sbus->chip->core_base[SDIOD_CORE_ID],
+      bcmf_write_sbregb(ibus,
+                  CORE_BUS_REG(ibus->chip->core_base[SDIOD_CORE_ID],
                   tosbmailbox), SMB_NAK);
     }
 
   return 0;
 }
 
-int bcmf_sdpcm_process_header(FAR struct bcmf_sdio_dev_s *sbus,
+int bcmf_sdpcm_process_header(FAR bcmf_interface_dev_t *ibus,
                               struct bcmf_sdpcm_header *header)
 {
   if (header->data_offset < sizeof(struct bcmf_sdpcm_header) ||
       header->data_offset > header->size)
     {
       wlerr("Invalid data offset\n");
-      bcmf_sdpcm_rxfail(sbus, false);
+      bcmf_sdpcm_rxfail(ibus, false);
       return -ENXIO;
     }
 
   /* Update tx credits */
 
-  sbus->max_seq = header->credit;
+  ibus->max_seq = header->credit;
 
   return OK;
 }
@@ -138,20 +138,20 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
   uint16_t checksum;
   struct bcmf_sdpcm_header *header;
   struct bcmf_sdpcm_header tmp_hdr;
-  struct bcmf_sdio_frame *sframe;
-  FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
+  bcmf_interface_frame_t *iframe;
+  FAR bcmf_interface_dev_t *ibus = (FAR bcmf_interface_dev_t *)priv->bus;
 
   /* Read the first 4 bytes of sdpcm header
    * to get the length of the following data to be read
    */
 
-  ret = bcmf_transfer_bytes(sbus, false, 2, 0,
+  ret = bcmf_transfer_bytes(ibus, false, 2, 0,
                             (uint8_t *)&tmp_hdr,
                             FIRST_WORD_SIZE);
   if (ret != OK)
     {
       wlinfo("Failed to read size\n");
-      bcmf_sdpcm_rxfail(sbus, false);
+      bcmf_sdpcm_rxfail(ibus, false);
       return -EIO;
     }
 
@@ -160,15 +160,19 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
 
   /* All zero means no more to read */
 
-  if (!(len | checksum))
+  if (len == 0)
     {
+      wlinfo("No data\n");
+
       return -ENODATA;
     }
 
+  wlinfo("len: %d Header checksum: 0x%04x\n", len, checksum);
+
   if (((~len & 0xffff) ^ checksum) || len < sizeof(struct bcmf_sdpcm_header))
     {
-      wlerr("Invalid header checksum or len %x %x\n", len, checksum);
-      bcmf_sdpcm_rxfail(sbus, false);
+      wlerr("Invalid header checksum or len %d 0x%04x\n", len, checksum);
+      bcmf_sdpcm_rxfail(ibus, false);
       return -EINVAL;
     }
 
@@ -176,17 +180,19 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
     {
       /* Flow control update packet with no data */
 
-      ret = bcmf_transfer_bytes(sbus, false, 2, 0,
+      wlinfo("Flow control\n");
+
+      ret = bcmf_transfer_bytes(ibus, false, 2, 0,
                                 (uint8_t *)&tmp_hdr + FIRST_WORD_SIZE,
                                 FC_UPDATE_PKT_LENGTH - FIRST_WORD_SIZE);
       if (ret != OK)
         {
           wlinfo("Failed to read the rest 8 bytes\n");
-          bcmf_sdpcm_rxfail(sbus, false);
+          bcmf_sdpcm_rxfail(ibus, false);
           return -EIO;
         }
 
-      ret = bcmf_sdpcm_process_header(sbus, &tmp_hdr);
+      ret = bcmf_sdpcm_process_header(ibus, &tmp_hdr);
 
       if (ret != OK)
         {
@@ -199,28 +205,27 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
 
   /* Request free frame buffer */
 
-  sframe = bcmf_sdio_allocate_frame(priv, false, false);
+  iframe = bcmf_interface_allocate_frame(priv, false, false);
 
-  if (sframe == NULL)
+  if (iframe == NULL)
     {
       wlinfo("fail alloc\n");
 
       /* Read out the rest of the header to get the bus credit information */
 
-      ret = bcmf_transfer_bytes(sbus, false, 2, 0,
+      ret = bcmf_transfer_bytes(ibus, false, 2, 0,
                                 (uint8_t *)&tmp_hdr + FIRST_WORD_SIZE,
                                 FC_UPDATE_PKT_LENGTH - FIRST_WORD_SIZE);
-
       if (ret != OK)
         {
           wlinfo("Failed to read the rest 8 bytes\n");
-          bcmf_sdpcm_rxfail(sbus, false);
+          bcmf_sdpcm_rxfail(ibus, false);
           return -EIO;
         }
 
-      bcmf_sdpcm_rxfail(sbus, false);
+      bcmf_sdpcm_rxfail(ibus, false);
 
-      ret = bcmf_sdpcm_process_header(sbus, &tmp_hdr);
+      ret = bcmf_sdpcm_process_header(ibus, &tmp_hdr);
 
       if (ret != OK)
         {
@@ -231,7 +236,7 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
       return -EAGAIN;
     }
 
-  header = (struct bcmf_sdpcm_header *)sframe->data;
+  header = (struct bcmf_sdpcm_header *)iframe->data;
 
   /* Read the remaining frame data (the buffer is DMA aligned here) */
 
@@ -241,9 +246,9 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
       goto exit_free_frame;
     }
 
-  ret = bcmf_transfer_bytes(sbus, false, 2, 0,
-                           (uint8_t *)header + FIRST_WORD_SIZE,
-                           len - FIRST_WORD_SIZE);
+  ret = bcmf_transfer_bytes(ibus, false, 2, 0,
+                            (uint8_t *)header + FIRST_WORD_SIZE,
+                            len - FIRST_WORD_SIZE);
   if (ret != OK)
     {
       wlinfo("Failed to read remaining frame data\n");
@@ -253,22 +258,33 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
 
   memcpy(header, &tmp_hdr, FIRST_WORD_SIZE);
 
-  if (len > sframe->header.len)
+  if (len > iframe->header.len)
     {
-      wlerr("Frame is too large, cancel %d %d\n", len, sframe->header.len);
+      wlerr("Frame is too large, cancel %d %d\n", len, iframe->header.len);
       ret = -ENOMEM;
       goto exit_abort;
     }
 
-#if 0
-  wlinfo("Receive frame %p %d\n", sframe, len);
+#if 1
+  wlinfo("Receive frame %p %d\n", iframe, len);
+
+  wlinfo("size:%d  seq: %d, channel: %d  next len: %d\n",
+         header->size,
+         header->sequence,
+         header->channel,
+         header->next_length);
+
+  wlinfo("data offset:0x%02X  flow: %d, credit: %d\n",
+          header->data_offset,
+          header->flow_control,
+          header->credit);
 
   bcmf_hexdump((uint8_t *)header, header->size, (unsigned int)header);
 #endif
 
   /* Process and validate header */
 
-  ret = bcmf_sdpcm_process_header(sbus, header);
+  ret = bcmf_sdpcm_process_header(ibus, header);
   if (ret != OK)
     {
       wlerr("Error while processing header %d\n", ret);
@@ -278,15 +294,15 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
 
   /* Update frame structure */
 
-  sframe->header.len = header->size;
-  sframe->header.data += header->data_offset;
+  iframe->header.len = header->size;
+  iframe->header.data += header->data_offset;
 
   /* Process received frame content */
 
   switch (header->channel & 0x0f)
     {
       case SDPCM_CONTROL_CHANNEL:
-        ret = bcmf_cdc_process_control_frame(priv, &sframe->header);
+        ret = bcmf_cdc_process_control_frame(priv, &iframe->header);
         goto exit_free_frame;
 
       case SDPCM_EVENT_CHANNEL:
@@ -298,7 +314,7 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
           }
         else
           {
-            ret = bcmf_bdc_process_event_frame(priv, &sframe->header);
+            ret = bcmf_bdc_process_event_frame(priv, &iframe->header);
           }
 
         goto exit_free_frame;
@@ -307,13 +323,13 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
 
         /* Queue frame and notify network layer frame is available */
 
-        if (nxsem_wait_uninterruptible(&sbus->queue_mutex) < 0)
+        if (nxsem_wait_uninterruptible(&ibus->queue_mutex) < 0)
           {
             DEBUGPANIC();
           }
 
-        list_add_tail(&sbus->rx_queue, &sframe->list_entry);
-        nxsem_post(&sbus->queue_mutex);
+        list_add_tail(&ibus->rx_queue, &iframe->list_entry);
+        nxsem_post(&ibus->queue_mutex);
 
         bcmf_netdev_notify_rx(priv);
 
@@ -331,9 +347,9 @@ int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
   return ret;
 
 exit_abort:
-  bcmf_sdpcm_rxfail(sbus, false);
+  bcmf_sdpcm_rxfail(ibus, false);
 exit_free_frame:
-  bcmf_sdio_free_frame(priv, sframe);
+  bcmf_interface_free_frame(priv, iframe);
   return ret;
 }
 
@@ -341,18 +357,18 @@ int bcmf_sdpcm_sendframe(FAR struct bcmf_dev_s *priv)
 {
   int ret;
   bool is_txframe;
-  struct bcmf_sdio_frame *sframe;
+  bcmf_interface_frame_t *iframe;
   struct bcmf_sdpcm_header *header;
-  FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
+  FAR bcmf_interface_dev_t *ibus = (FAR bcmf_interface_dev_t *)priv->bus;
 
-  if (list_is_empty(&sbus->tx_queue))
+  if (list_is_empty(&ibus->tx_queue))
     {
       /* No more frames to send */
 
       return -ENODATA;
     }
 
-  if (sbus->tx_seq == sbus->max_seq)
+  if (ibus->tx_seq == ibus->max_seq)
     {
       /* TODO handle this case */
 
@@ -360,38 +376,38 @@ int bcmf_sdpcm_sendframe(FAR struct bcmf_dev_s *priv)
       return -EAGAIN;
     }
 
-  if (nxsem_wait_uninterruptible(&sbus->queue_mutex) < 0)
+  if (nxsem_wait_uninterruptible(&ibus->queue_mutex) < 0)
     {
       DEBUGPANIC();
     }
 
-  sframe = list_remove_head_type(&sbus->tx_queue, struct bcmf_sdio_frame,
+  iframe = list_remove_head_type(&ibus->tx_queue, bcmf_interface_frame_t,
                                  list_entry);
-  nxsem_post(&sbus->queue_mutex);
+  nxsem_post(&ibus->queue_mutex);
 
-  header = (struct bcmf_sdpcm_header *)sframe->header.base;
+  header = (struct bcmf_sdpcm_header *)iframe->header.base;
 
   /* Set frame sequence id */
 
-  header->sequence = sbus->tx_seq++;
+  header->sequence = ibus->tx_seq++;
 
-#if 0
-  wlinfo("Send frame %p\n", sframe);
+#if 1
+  wlinfo("Send frame %p\n", iframe);
 
-  bcmf_hexdump(sframe->header.base, sframe->header.len,
-               (unsigned long)sframe->header.base);
+  bcmf_hexdump(iframe->header.base, iframe->header.len,
+               (unsigned long)iframe->header.base);
 #endif
 
   /* Write the frame data (the buffer is DMA aligned here) */
 
-  ret = bcmf_transfer_bytes(sbus, true, 2, 0,
-                            sframe->header.base,
-                            sframe->header.len);
-  is_txframe = sframe->tx;
+  ret = bcmf_transfer_bytes(ibus, true, 2, 0,
+                            iframe->header.base,
+                            iframe->header.len);
+  is_txframe = iframe->tx;
 
   /* Free frame buffer */
 
-  bcmf_sdio_free_frame(priv, sframe);
+  bcmf_interface_free_frame(priv, iframe);
 
   if (ret == OK && is_txframe)
     {
@@ -400,16 +416,18 @@ int bcmf_sdpcm_sendframe(FAR struct bcmf_dev_s *priv)
       bcmf_netdev_notify_tx(priv);
     }
 
+  wlinfo("return %d\n", ret);
+
   return ret;
 }
 
 int bcmf_sdpcm_queue_frame(FAR struct bcmf_dev_s *priv,
                            struct bcmf_frame_s *frame, bool control)
 {
-  FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
-  struct bcmf_sdio_frame *sframe = (struct bcmf_sdio_frame *)frame;
+  FAR bcmf_interface_dev_t *ibus = (FAR bcmf_interface_dev_t *)priv->bus;
+  bcmf_interface_frame_t *iframe = (bcmf_interface_frame_t *)frame;
   struct bcmf_sdpcm_header *header =
-    (struct bcmf_sdpcm_header *)sframe->data;
+    (struct bcmf_sdpcm_header *)iframe->data;
   int semcount;
 
   /* Prepare sw header */
@@ -430,21 +448,21 @@ int bcmf_sdpcm_queue_frame(FAR struct bcmf_dev_s *priv,
 
   /* Add frame in tx queue */
 
-  if (nxsem_wait_uninterruptible(&sbus->queue_mutex) < 0)
+  if (nxsem_wait_uninterruptible(&ibus->queue_mutex) < 0)
     {
       DEBUGPANIC();
     }
 
-  list_add_tail(&sbus->tx_queue, &sframe->list_entry);
+  list_add_tail(&ibus->tx_queue, &iframe->list_entry);
 
-  nxsem_post(&sbus->queue_mutex);
+  nxsem_post(&ibus->queue_mutex);
 
   /* Notify bcmf thread tx frame is ready */
 
-  nxsem_get_value(&sbus->thread_signal, &semcount);
+  nxsem_get_value(&ibus->thread_signal, &semcount);
   if (semcount < 1)
     {
-      nxsem_post(&sbus->thread_signal);
+      nxsem_post(&ibus->thread_signal);
     }
 
   return OK;
@@ -454,7 +472,7 @@ struct bcmf_frame_s *bcmf_sdpcm_alloc_frame(FAR struct bcmf_dev_s *priv,
                                             unsigned int len, bool block,
                                             bool control)
 {
-  struct bcmf_sdio_frame *sframe;
+  bcmf_interface_frame_t *iframe;
   unsigned int header_len = sizeof(struct bcmf_sdpcm_header);
 
   if (!control)
@@ -470,44 +488,44 @@ struct bcmf_frame_s *bcmf_sdpcm_alloc_frame(FAR struct bcmf_dev_s *priv,
 
   /* Allocate a frame for RX in case of control frame */
 
-  sframe = bcmf_sdio_allocate_frame(priv, block, !control);
+  iframe = bcmf_interface_allocate_frame(priv, block, !control);
 
-  if (sframe == NULL)
+  if (iframe == NULL)
     {
       return NULL;
     }
 
-  sframe->header.len   = header_len + len;
-  sframe->header.data += header_len;
-  return &sframe->header;
+  iframe->header.len   = header_len + len;
+  iframe->header.data += header_len;
+  return &iframe->header;
 }
 
 void bcmf_sdpcm_free_frame(FAR struct bcmf_dev_s *priv,
                            struct bcmf_frame_s *frame)
 {
-  bcmf_sdio_free_frame(priv, (struct bcmf_sdio_frame *)frame);
+  bcmf_interface_free_frame(priv, (bcmf_interface_frame_t *)frame);
 }
 
 struct bcmf_frame_s *bcmf_sdpcm_get_rx_frame(FAR struct bcmf_dev_s *priv)
 {
-  struct bcmf_sdio_frame *sframe;
-  FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
+  bcmf_interface_frame_t *iframe;
+  FAR bcmf_interface_dev_t *ibus = (FAR bcmf_interface_dev_t *)priv->bus;
 
-  if (nxsem_wait_uninterruptible(&sbus->queue_mutex) < 0)
+  if (nxsem_wait_uninterruptible(&ibus->queue_mutex) < 0)
     {
       DEBUGPANIC();
     }
 
-  sframe = list_remove_head_type(&sbus->rx_queue,
-                                 struct bcmf_sdio_frame,
+  iframe = list_remove_head_type(&ibus->rx_queue,
+                                 bcmf_interface_frame_t,
                                  list_entry);
 
-  nxsem_post(&sbus->queue_mutex);
+  nxsem_post(&ibus->queue_mutex);
 
-  if (sframe == NULL)
+  if (iframe == NULL)
     {
       return NULL;
     }
 
-  return &sframe->header;
+  return &iframe->header;
 }
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43438.c b/drivers/wireless/ieee80211/bcm43xxx/cyw_chip_43439.c
similarity index 74%
copy from drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43438.c
copy to drivers/wireless/ieee80211/bcm43xxx/cyw_chip_43439.c
index 2592b92c23..529b5c5f96 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43438.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/cyw_chip_43439.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43438.c
+ * drivers/wireless/ieee80211/bcm43xxx/cyw_chip_43439.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -25,7 +25,7 @@
 #include <nuttx/config.h>
 #include <stdint.h>
 
-#include "bcmf_sdio.h"
+#include "bcmf_interface.h"
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -37,18 +37,18 @@
  * Public Data
  ****************************************************************************/
 
-extern const char ap6212_nvram_image[];
-extern const unsigned int ap6212_nvram_image_len;
+extern const char cyw43439_nvram_image[];
+extern const unsigned int cyw43439_nvram_image_len;
 
 #ifndef CONFIG_IEEE80211_BROADCOM_FWFILES
-extern const uint8_t ap6212_firmware_image[];
-extern const unsigned int ap6212_firmware_len;
+extern const uint8_t cyw43439_firmware_image[];
+extern const unsigned int cyw43439_firmware_len;
 
-extern const uint8_t ap6212_clm_blob[];
-extern const unsigned int ap6212_clm_blob_len;
+extern const uint8_t cyw43439_clm_blob_image[];
+extern const unsigned int cyw43439_clm_blob_len;
 #endif
 
-const struct bcmf_sdio_chip bcmf_43438_config_sdio =
+const struct bcmf_chip_data cyw43439_config_data =
 {
   /* General chip stats */
 
@@ -72,15 +72,17 @@ const struct bcmf_sdio_chip bcmf_43438_config_sdio =
 
   /* TODO find something smarter than using image_len references */
 
-  .nvram_image         = (FAR uint8_t *)ap6212_nvram_image,
-  .nvram_image_size    = (FAR unsigned int *)&ap6212_nvram_image_len,
+  .nvram_image         = (FAR uint8_t *)cyw43439_nvram_image,
+  .nvram_image_size    = (FAR unsigned int *)&cyw43439_nvram_image_len,
 
 #ifndef CONFIG_IEEE80211_BROADCOM_FWFILES
-  .firmware_image      = (FAR uint8_t *)ap6212_firmware_image,
-  .firmware_image_size = (FAR unsigned int *)&ap6212_firmware_len,
+  .firmware_image      = (FAR uint8_t *)cyw43439_firmware_image,
+  .firmware_image_size = (FAR unsigned int *)&cyw43439_firmware_len,
 
-  .clm_blob_image      = (FAR uint8_t *)ap6212_clm_blob,
-  .clm_blob_image_size = (FAR unsigned int *)&ap6212_clm_blob_len,
+#ifdef CONFIG_IEEE80211_BROADCOM_HAVE_CLM
+  .clm_blob_image      = (FAR uint8_t *)cyw43439_clm_blob_image,
+  .clm_blob_image_size = (FAR unsigned int *)&cyw43439_clm_blob_len
+#endif
 #endif
 };
 
diff --git a/drivers/wireless/ieee80211/bcm43xxx/cyw_reg_def.h b/drivers/wireless/ieee80211/bcm43xxx/cyw_reg_def.h
new file mode 100644
index 0000000000..d309a1bf7a
--- /dev/null
+++ b/drivers/wireless/ieee80211/bcm43xxx/cyw_reg_def.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+ * drivers/wireless/ieee80211/bcm43xxx/cyw_reg_def.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __DRIVERS_WIRELESS_CYW43439_CYW_REG_DEF_H
+#define __DRIVERS_WIRELESS_CYW43439_CYW_REG_DEF_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/spi/spi.h>
+#include <nuttx/irq.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "bcmf_sdio_regs.h"
+
+/****************************************************************************
+ * Pre-Processor Declarations
+ ****************************************************************************/
+
+/* --- gSPI Registers --- */
+
+#define CYW_REG_SETUP          (0x0000)    /* 32-bit register */
+#define CYW_REG_INTERRUPT      (0x0004)    /* 16-bit register */
+#define CYW_REG_INTR_ENA       (0x0006)    /* 16-bit register */
+#define CYW_REG_STATUS         (0x0008)    /* 32-bit register */
+#define CYW_REG_F1_INFO        (0x000c)    /* 16-bit register */
+#define CYW_REG_F2_INFO        (0x000e)    /* 16-bit register */
+#define CYW_REG_TEST_RO        (0x0014)    /* 32-bit register */
+#define CYW_REG_TEST_RW        (0x0018)    /* 32-bit register */
+#define CYW_REG_RESP_DELAY_F0  (0x001c)    /*  8-bit register */
+#define CYW_REG_RESP_DELAY_F1  (0x001d)    /*  8-bit register */
+#define CYW_REG_RESP_DELAY_F2  (0x001e)    /*  8-bit register */
+#define CYW_REG_RESP_DELAY_F3  (0x001f)    /*  8-bit register */
+
+/* --- Registers --- */
+
+#define CYW_REG_SETUP_WORD_LEN_32        (1<<0)
+#define CYW_REG_SETUP_BIG_ENDIAN         (1<<1)
+#define CYW_REG_SETUP_HIGH_SPEED         (1<<4)
+#define CYW_REG_SETUP_INT_POLARITY       (1<<5)
+#define CYW_REG_SETUP_WAKE_UP            (1<<7)
+#define CYW_REG_SETUP_RESP_DELAY_SHIFT   (8)
+#define CYW_REG_SETUP_RESP_DELAY_MASK    (0x00FF << CYW_REG_SETUP_RESP_DELAY_SHIFT)
+#define CYW_REG_STAT_ENA_STAT_ENA        (1<<16)
+#define CYW_REG_STAT_ENA_INTR_STAT       (1<<17)
+
+#define CYW_REG_INTERRUPT_DATA_NOT_AVAIL (1<<0)
+#define CYW_REG_INTERRUPT_FIFO_UNDERFLOW (1<<1)
+#define CYW_REG_INTERRUPT_FIFO_OVERFLOW  (1<<2)
+#define CYW_REG_INTERRUPT_COMMAND_ERROR  (1<<3)
+#define CYW_REG_INTERRUPT_DATA_ERROR     (1<<4)
+#define CYW_REG_INTERRUPT_F2_PKT_AVAIL   (1<<5)
+#define CYW_REG_INTERRUPT_F3_PKT_AVAIL   (1<<6)
+#define CYW_REG_INTERRUPT_F1_OVERFLOW    (1<<7)
+#define CYW_REG_INTERRUPT_F1_INTERRUPT   (1<<13)
+#define CYW_REG_INTERRUPT_F2_INTERRUPT   (1<<14)
+#define CYW_REG_INTERRUPT_F3_INTERRUPT   (1<<15)
+
+#define CYW_REG_INTR_ENA_DATA_NOT_AVAIL  (1<<0)
+#define CYW_REG_INTR_ENA_FIFO_UNDERFLOW  (1<<1)
+#define CYW_REG_INTR_ENA_FIFO_OVERFLOW   (1<<2)
+#define CYW_REG_INTR_ENA_COMMAND_ERROR   (1<<3)
+#define CYW_REG_INTR_ENA_DATA_ERROR      (1<<4)
+#define CYW_REG_INTR_ENA_F2_PKT_AVAIL    (1<<5)
+#define CYW_REG_INTR_ENA_F3_PKT_AVAIL    (1<<6)
+#define CYW_REG_INTR_ENA_F1_OVERFLOW     (1<<7)
+#define CYW_REG_INTR_ENA_F1_INTERRUPT    (1<<13)
+#define CYW_REG_INTR_ENA_F2_INTERRUPT    (1<<14)
+#define CYW_REG_INTR_ENA_F3_INTERRUPT    (1<<15)
+
+#define CYW_REG_STATUS_DATA_NOT_AVAIL    (1<<0)
+#define CYW_REG_STATUS_FIFO_UNDERFLOW    (1<<1)
+#define CYW_REG_STATUS_FIFO_OVERFLOW     (1<<2)
+#define CYW_REG_STATUS_F2_INTERRUPT      (1<<3)
+#define CYW_REG_STATUS_F3_INTERRUPT      (1<<4)
+#define CYW_REG_STATUS_F2_RECEIVE_RDY    (1<<5)
+#define CYW_REG_STATUS_F3_RECEIVE_RDY    (1<<6)
+#define CYW_REG_STATUS_CMD_DATA_ERROR    (1<<7)
+#define CYW_REG_STATUS_F2_PKT_AVAIL      (1<<8)
+#define CYW_REG_STATUS_F2_PKT_LEN_SHIFT  (9)
+#define CYW_REG_STATUS_F2_PKT_LEN_MASK   (0x7FF << CYW_REG_STATUS_F2_PKT_LEN_SHIFT)
+#define CYW_REG_STATUS_F3_PKT_AVAIL      (1<<20)
+#define CYW_REG_STATUS_F3_PKT_LEN_SHIFT  (21)
+#define CYW_REG_STATUS_F3_PKT_LEN_MASK   (0x7FF << CYW_REG_STATUS_F3_PKT_LEN_SHIFT)
+
+#define CYW_REG_F1_INFO_ENABLED          (1<<0)
+#define CYW_REG_F1_INFO_READY            (1<<1)
+#define CYW_REG_F1_INFO_MAX_SIZE_SHIFT   (2)
+#define CYW_REG_F1_INFO_MAX_SIZE_MASK    (0x0FFF << CYW_REG_F1_INFO_MAX_SIZE_SHIFT)
+
+#define CYW_REG_F2_INFO_ENABLED          (1<<0)
+#define CYW_REG_F2_INFO_READY            (1<<1)
+#define CYW_REG_F2_INFO_MAX_SIZE_SHIFT   (2)
+#define CYW_REG_F2_INFO_MAX_SIZE_MASK    (0x0FFF << CYW_REG_F2_INFO_MAX_SIZE_SHIFT)
+
+#define CYW_REG_RESP_DELAY_F0_SHIFT      (0)
+#define CYW_REG_RESP_DELAY_F0_MASK       (0x00FF << CYW_REG_RESP_DELAY_F0_SHIFT)
+#define CYW_REG_RESP_DELAY_F1_SHIFT      (8)
+#define CYW_REG_RESP_DELAY_F1_MASK       (0x00FF << CYW_REG_RESP_DELAY_F1_SHIFT)
+#define CYW_REG_RESP_DELAY_F2_SHIFT      (16)
+#define CYW_REG_RESP_DELAY_F2_MASK       (0x00FF << CYW_REG_RESP_DELAY_F2_SHIFT)
+#define CYW_REG_RESP_DELAY_F3_SHIFT      (24)
+#define CYW_REG_RESP_DELAY_F3_MASK       (0x00FF << CYW_REG_RESP_DELAY_F3_SHIFT)
+
+#define CYW_REG_TEST_RO_PATTERN          (0xfeedbead)
+
+#define CYW_STATUS_DATA_NOT_AVAIL        (1<<0)  /* data not avail on read       */
+#define CYW_STATUS_FIFO_UNDERFLOW        (1<<1)  /* read underflow (F2, F3)      */
+#define CYW_STATUS_FIFO_OVERFLOW         (1<<2)  /* write overflow  (F1, F2, F3) */
+#define CYW_STATUS_F2_INTERRUPT          (1<<3)  /* F2 channel interrupt         */
+#define CYW_STATUS_F3_INTERRUPT          (1<<4)
+#define CYW_STATUS_F2_RECEIVE_RDY        (1<<5)  /* F2 ready to receive data     */
+#define CYW_STATUS_F3_RECEIVE_RDY        (1<<6)
+#define CYW_STATUS_CMD_DATA_ERROR        (1<<7)
+#define CYW_STATUS_F2_PKT_AVAIL          (1<<8)  /* F2 has data to read          */
+#define CYW_STATUS_F2_PKT_LEN_SHIFT      (9)     /* Length of avail F2 data      */
+#define CYW_STATUS_F2_PKT_LEN_MASK       (0x7FF << CYW_REG_STATUS_F2_PKT_LEN_SHIFT)
+#define CYW_STATUS_F3_PKT_AVAIL          (1<<20)
+#define CYW_STATUS_F3_PKT_LEN_SHIFT      (21)
+#define CYW_STATUS_F3_PKT_LEN_MASK       (0x7FF << CYW_REG_STATUS_F3_PKT_LEN_SHIFT)
+
+/****************************************************************************
+ * Public Data Types
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#  define EXTERN extern "C"
+extern "C"
+  {
+#else
+#  define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Functions Prototypes
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __DRIVERS_WIRELESS_CYW43439_CYW_REG_DEF_H */
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_4301x.c b/include/nuttx/wireless/ieee80211/bcmf_gpio.h
similarity index 51%
copy from drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_4301x.c
copy to include/nuttx/wireless/ieee80211/bcmf_gpio.h
index 7fdbea81ef..d466a291a6 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_4301x.c
+++ b/include/nuttx/wireless/ieee80211/bcmf_gpio.h
@@ -1,5 +1,5 @@
 /****************************************************************************
- * drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_4301x.c
+ * include/nuttx/wireless/ieee80211/bcmf_gpio.h
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -18,66 +18,35 @@
  *
  ****************************************************************************/
 
+#ifndef __INCLUDE_NUTTX_WIRELESS_IEEE80211_BCMF_GPIO_H
+#define __INCLUDE_NUTTX_WIRELESS_IEEE80211_BCMF_GPIO_H
+
 /****************************************************************************
  * Included Files
  ****************************************************************************/
 
 #include <nuttx/config.h>
-#include <stdint.h>
-
-#include "bcmf_sdio.h"
 
 /****************************************************************************
- * Pre-processor Definitions
+ * Private Type Definitions
  ****************************************************************************/
 
-#define WRAPPER_REGISTER_OFFSET  0x100000
+typedef struct bcmf_dev_s;
 
 /****************************************************************************
- * Public Data
+ * Public Function Prototypes
  ****************************************************************************/
 
-extern const char bcm4301x_nvram_image[];
-extern const unsigned int bcm4301x_nvram_image_len;
-
-#ifndef CONFIG_IEEE80211_BROADCOM_FWFILES
-extern const uint8_t bcm4301x_firmware_image[];
-extern const unsigned int bcm4301x_firmware_image_len;
-#endif
-
-const struct bcmf_sdio_chip bcmf_4301x_config_sdio =
-{
-  /* General chip stats */
-
-  .ram_base = 0,
-  .ram_size = 0xa0000,
-
-  /* Backplane architecture */
-
-  .core_base =
-  {
-    [CHIPCOMMON_CORE_ID]  = 0x18000000,  /* Chipcommon core register base   */
-    [DOT11MAC_CORE_ID]    = 0x18001000,  /* dot11mac core register base     */
-    [SDIOD_CORE_ID]       = 0x18002000,  /* SDIOD Device core register base */
-    [WLAN_ARMCM3_CORE_ID] = 0x18003000 + /* ARMCM3 core register base       */
-                            WRAPPER_REGISTER_OFFSET,
-    [SOCSRAM_CORE_ID]     = 0x18004000 + /* SOCSRAM core register base      */
-                            WRAPPER_REGISTER_OFFSET
-  },
-
-  /* Firmware images */
-
-  /* TODO find something smarter than using image_len references */
-
-  .nvram_image         = (FAR uint8_t *)bcm4301x_nvram_image,
-  .nvram_image_size    = (FAR unsigned int *)&bcm4301x_nvram_image_len,
+/****************************************************************************
+ * Name: bcmf_set_gpio
+ ****************************************************************************/
 
-#ifndef CONFIG_IEEE80211_BROADCOM_FWFILES
-  .firmware_image      = (FAR uint8_t *)bcm4301x_firmware_image,
-  .firmware_image_size = (FAR unsigned int *)&bcm4301x_firmware_image_len,
-#endif
-};
+int bcmf_set_gpio(FAR struct bcmf_dev_s *priv, int pin, bool value);
 
 /****************************************************************************
- * Public Functions
+ * Name: bcmf_get_gpio
  ****************************************************************************/
+
+int bcmf_get_gpio(FAR struct bcmf_dev_s *priv, int pin, bool *value);
+
+#endif /* __INCLUDE_NUTTX_WIRELESS_IEEE80211_BCMF_GPIO_H */
diff --git a/include/nuttx/wireless/ieee80211/bcmf_gspi.h b/include/nuttx/wireless/ieee80211/bcmf_gspi.h
new file mode 100644
index 0000000000..984d13ef80
--- /dev/null
+++ b/include/nuttx/wireless/ieee80211/bcmf_gspi.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+ * include/nuttx/wireless/ieee80211/bcmf_gspi.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_WIRELESS_IEEE80211_BCMF_GSPI_H
+#define __INCLUDE_NUTTX_WIRELESS_IEEE80211_BCMF_GSPI_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/irq.h>
+
+#include "nuttx/net/net.h"
+#include "nuttx/net/netdev.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+enum gspi_cmd_func_e
+  {
+    gspi_f0_bus       = 0x0,
+    gspi_f1_backplane = 0x1,
+    gspi_f2_dma       = 0x2,
+    gspi_f3_dma       = 0x3,
+    gspi_f0_bus_rev16 = 0x4  /* variant of gspi_f0_bus that does REV16 */
+  };
+
+struct bcmf_dev_s;
+
+/* --- Our extension to struct net_driver_s --- */
+
+typedef struct gspi_dev_s
+{
+  /* --------------------------------------------------------
+   * Each board that implements CYW43439 must initialize the
+   * following fields before calling gspi_register.
+   */
+
+  FAR int  (*init)            (FAR struct gspi_dev_s   *gspi);
+
+  FAR int  (*deinit)          (FAR struct gspi_dev_s   *gspi);
+
+  FAR int  (*set_isr)         (FAR struct gspi_dev_s   *gspi,
+                               xcpt_t                   thread_isr,
+                               FAR void                *thread_isr_arg);
+
+  FAR int  (*interrupt_enable)(FAR struct gspi_dev_s   *gspi,
+                              bool                     enable);
+
+  FAR int  (*write)           (FAR struct gspi_dev_s  *gspi,
+                               bool                    increment,
+                               enum gspi_cmd_func_e    function,
+                               uint32_t                address,
+                               uint16_t                length,
+                               FAR const uint32_t     *data);
+
+  FAR int  (*read)            (FAR struct gspi_dev_s  *gspi,
+                               bool                    increment,
+                               enum gspi_cmd_func_e    function,
+                               uint32_t                address,
+                               uint16_t                length,
+                               FAR uint32_t           *buffer);
+
+  sem_t                exclsem;
+
+  /* --------------------------------------------------------
+   * Other fields must be set to zero.
+   */
+
+  void                  *io_dev;  /* Private data for opened io device. */
+  FAR struct bcmf_dev_s *priv;    /* Back pointer to bus.               */
+} gspi_dev_t;
+
+#ifndef __ASSEMBLY__
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: bcmf_gspi_initialize
+ *
+ * Description:
+ *   Initialize the cyw43439 driver.
+ *
+ ****************************************************************************/
+
+int bcmf_gspi_initialize(FAR gspi_dev_t *gspi);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __INCLUDE_NUTTX_WIRELESS_IEEE80211_BCMF_GSPI_H */