drivers/wiresless/ieee80211: Correct some initialization problems with BCM43362 chip. Adds BCM43428 support. arch/arm/src: Add support for SDIO card to SDIO driver.

Squashed commit of the following:

Author: Gregory Nutt <gnutt@nuttx.org>
    include/nuttx/wireless/ieee80211:  Cosmetic, coding standard changes from review of last merge.
    drivers/wireless/ieee80211:  Cosmetic, coding standard changes from review of last merge.
    configs/photon:  Cosmetic, coding standard changes from review of last merge.
    arch/arm/src/stm32:  SDIO changes from last review:  Fix a few long lines and other coding standard issues; Make additions for SDIO card support dependent on a configuration option.

Author: hhuysqt <hyq9606@126.com>
    Return IEEE 802.11 MAC address just as ethernet does
    Modifyed bcmf_board_setup_oob_irq declaration
    Modified OOB ISR function types
    Add some logic according to WICED SDK
    Bug fixed: data_offset counts in 4-bytes
    Add BCM43438 logic for future developement
    Add tips on using telnet
    Use SDIO in-band interrupt instead of OOB interrupt, because Photon seems to unconnect the OOB interrupt line...
    add SDIO in-band interrupt logic
This commit is contained in:
hhuysqt 2018-04-26 08:10:23 -06:00 committed by Gregory Nutt
parent 0c963449d6
commit 144e335b85
19 changed files with 641 additions and 126 deletions

View File

@ -7595,6 +7595,13 @@ endmenu
menu "SDIO Configuration"
depends on STM32_SDIO
config STM32_SDIO_CARD
bool "SDIO Card support"
default n
---help---
Build in additional support needed only for SDIO cards (vs. SD
memory cards)
config STM32_SDIO_DMA
bool "Support DMA data transfers"
default y if STM32_DMA2

View File

@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/stm32/stm32_sdio.c
*
* Copyright (C) 2009, 2011-2014, 2016-2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2009, 2011-2014, 2016-2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -335,6 +335,14 @@ struct stm32_dev_s
size_t remaining; /* Number of bytes remaining in the transfer */
uint32_t xfrmask; /* Interrupt enables for data transfer */
#ifdef CONFIG_STM32_SDIO_CARD
/* Interrupt at SDIO_D1 pin, only for SDIO cards */
uint32_t sdiointmask; /* STM32 SDIO register mask */
int (*do_sdio_card)(void *); /* SDIO card ISR */
void *do_sdio_arg; /* arg for SDIO card ISR */
#endif
/* Fixed transfer block size support */
#ifdef CONFIG_SDIO_BLOCKSETUP
@ -703,7 +711,14 @@ static void stm32_configwaitints(struct stm32_dev_s *priv, uint32_t waitmask,
#ifdef CONFIG_STM32_SDIO_DMA
priv->xfrflags = 0;
#endif
#ifdef CONFIG_STM32_SDIO_CARD
putreg32(priv->xfrmask | priv->waitmask | priv->sdiointmask,
STM32_SDIO_MASK);
#else
putreg32(priv->xfrmask | priv->waitmask, STM32_SDIO_MASK);
#endif
leave_critical_section(flags);
}
@ -725,9 +740,15 @@ static void stm32_configwaitints(struct stm32_dev_s *priv, uint32_t waitmask,
static void stm32_configxfrints(struct stm32_dev_s *priv, uint32_t xfrmask)
{
irqstate_t flags;
flags = enter_critical_section();
priv->xfrmask = xfrmask;
#ifdef CONFIG_STM32_SDIO_CARD
putreg32(priv->xfrmask | priv->waitmask | priv->sdiointmask,
STM32_SDIO_MASK);
#else
putreg32(priv->xfrmask | priv->waitmask, STM32_SDIO_MASK);
#endif
leave_critical_section(flags);
}
@ -1534,6 +1555,23 @@ static int stm32_interrupt(int irq, void *context, FAR void *arg)
}
}
}
#ifdef CONFIG_STM32_SDIO_CARD
/* Handle SDIO card interrupt */
pending = enabled & priv->sdiointmask;
if (pending != 0)
{
putreg32(SDIO_STA_SDIOIT, STM32_SDIO_ICR);
/* Perform callback */
if (priv->do_sdio_card)
{
priv->do_sdio_card(priv->do_sdio_arg);
}
}
#endif
}
return OK;
@ -1617,6 +1655,10 @@ static void stm32_reset(FAR struct sdio_dev_s *dev)
priv->remaining = 0; /* Number of bytes remaining in the transfer */
priv->xfrmask = 0; /* Interrupt enables for data transfer */
#ifdef CONFIG_STM32_SDIO_CARD
priv->sdiointmask = 0; /* SDIO card in-band interrupt mask */
#endif
/* DMA data transfer support */
priv->widebus = false; /* Required for DMA support */
@ -3100,4 +3142,44 @@ void sdio_wrprotect(FAR struct sdio_dev_s *dev, bool wrprotect)
mcinfo("cdstatus: %02x\n", priv->cdstatus);
leave_critical_section(flags);
}
/****************************************************************************
* Name: sdio_set_sdio_card_isr
*
* Description:
* SDIO card generates interrupt via SDIO_DATA_1 pin.
* Called by board-specific logic to register an ISR for SDIO card.
*
* Input Parameters:
* func - callback function.
* arg - arg to be passed to the function.
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_STM32_SDIO_CARD
void sdio_set_sdio_card_isr(FAR struct sdio_dev_s *dev,
int (*func)(void *), void *arg)
{
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
priv->do_sdio_card = func;
if (func != NULL)
{
priv->sdiointmask = SDIO_STA_SDIOIT;
priv->do_sdio_arg = arg;
}
else
{
priv->sdiointmask = 0;
}
putreg32(priv->xfrmask | priv->waitmask | priv->sdiointmask,
STM32_SDIO_MASK);
}
#endif
#endif /* CONFIG_STM32_SDIO */

View File

@ -118,6 +118,27 @@ void sdio_mediachange(FAR struct sdio_dev_s *dev, bool cardinslot);
void sdio_wrprotect(FAR struct sdio_dev_s *dev, bool wrprotect);
/****************************************************************************
* Name: sdio_set_sdio_card_isr
*
* Description:
* SDIO card generates interrupt via SDIO_DATA_1 pin.
* Called by board-specific logic to register an ISR for SDIO card.
*
* Input Parameters:
* func - callback function.
* arg - arg to be passed to the function.
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_STM32_SDIO_CARD
void sdio_set_sdio_card_isr(FAR struct sdio_dev_s *dev,
int (*func)(void *), void *arg);
#endif
#undef EXTERN
#if defined(__cplusplus)
}

View File

@ -114,6 +114,29 @@ Flashing NuttX in the Photon board
Download done.
File downloaded successfully
3) Restore the original firmware
If you config to use the stock bootloader of Photon, you may
reload the original firmware with dfu-utils as you like. Otherwize
you must have backuped the whole image beforehand, and reload it
via SWD debug port.
NSH via telnet
==============
After you successfully downloaded nuttx.bin, reset the board and it
automatically connects to the corresponding wifi AP. You may login
your router to see its IP address. Assume that it's 192.168.1.111
Open a terminal on your computer and telnet your Photon:
$ telnet 192.168.1.111
Trying 192.168.1.111...
Connected to 192.168.1.111.
Escape character is '^]'
NuttShell (NSH) NuttX-7.24
nsh>
Serial console configuration
============================

View File

@ -1,7 +1,7 @@
/****************************************************************************
* configs/photon/src/stm32_wlan.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
* Author: Simon Piriou <spiriou31@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
@ -51,6 +51,12 @@
#include "photon.h"
/****************************************************************************
* Private Data
****************************************************************************/
static struct sdio_dev_s *g_sdio_dev;
/****************************************************************************
* Public Functions
****************************************************************************/
@ -102,18 +108,19 @@ void bcmf_board_initialize(int minor)
* Name: bcmf_board_setup_oob_irq
****************************************************************************/
void bcmf_board_setup_oob_irq(int minor, xcpt_t func, void *arg)
void bcmf_board_setup_oob_irq(int minor, int (*func)(void *), void *arg)
{
if (minor != SDIO_WLAN0_MINOR)
{
return;
}
/* Configure interrupt pin */
/* Configure SDIO card in-band interrupt callback */
stm32_configgpio(GPIO_WLAN0_OOB_INT);
stm32_gpiosetevent(GPIO_WLAN0_OOB_INT, true, false, false, func, arg);
if (g_sdio_dev != NULL)
{
sdio_set_sdio_card_isr(g_sdio_dev, func, arg);
}
}
/****************************************************************************
@ -123,15 +130,14 @@ void bcmf_board_setup_oob_irq(int minor, xcpt_t func, void *arg)
int photon_wlan_initialize()
{
int ret;
struct sdio_dev_s *sdio_dev;
/* Initialize sdio interface */
wlinfo("Initializing SDIO slot %d\n", SDIO_WLAN0_SLOTNO);
sdio_dev = sdio_initialize(SDIO_WLAN0_SLOTNO);
g_sdio_dev = sdio_initialize(SDIO_WLAN0_SLOTNO);
if (!sdio_dev)
if (!g_sdio_dev)
{
wlerr("ERROR: Failed to initialize SDIO with slot %d\n",
SDIO_WLAN0_SLOTNO);
@ -140,7 +146,7 @@ int photon_wlan_initialize()
/* Bind the SDIO interface to the bcmf driver */
ret = bcmf_sdio_initialize(SDIO_WLAN0_MINOR, sdio_dev);
ret = bcmf_sdio_initialize(SDIO_WLAN0_MINOR, g_sdio_dev);
if (ret != OK)
{

View File

@ -13,6 +13,11 @@ config IEEE80211_BROADCOM_BCM43362
depends on IEEE80211_BROADCOM_FULLMAC
default n
config IEEE80211_BROADCOM_BCM43438
bool "Broadcom 43438 chip support"
depends on IEEE80211_BROADCOM_FULLMAC
default n
config IEEE80211_BROADCOM_FULLMAC_SDIO
bool "Broadcom FullMAC driver on SDIO bus"
depends on ARCH_HAVE_SDIO

View File

@ -58,6 +58,10 @@ ifeq ($(CONFIG_IEEE80211_BROADCOM_BCM43362),y)
CSRCS += bcmf_chip_43362.c
endif
ifeq ($(CONFIG_IEEE80211_BROADCOM_BCM43438),y)
CSRCS += bcmf_chip_43438.c
endif
endif # CONFIG_IEEE80211_BROADCOM_FULLMAC
# Include IEEE 802.11 build support

View File

@ -1,7 +1,7 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_bdc.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
* Author: Simon Piriou <spiriou31@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
@ -66,8 +66,8 @@ struct __attribute__((packed)) bcmf_bdc_header
{
uint8_t flags; /* bdc frame flags */
uint8_t priority; /* bdc frame priority */
uint8_t flags2; /* bdc frame additionnal flags */
uint8_t data_offset; /* Offset from end of header to payload data */
uint8_t flags2; /* bdc frame additional flags */
uint8_t data_offset; /* Offset from end of header to payload data, in 4-bytes count */
};
struct __attribute__((packed)) bcmf_eth_header
@ -138,7 +138,7 @@ int bcmf_bdc_process_event_frame(FAR struct bcmf_dev_s *priv,
header = (struct bcmf_bdc_header *)frame->data;
data_size -= sizeof(struct bcmf_bdc_header) + header->data_offset;
data_size -= sizeof(struct bcmf_bdc_header) + header->data_offset * 4;
if (data_size < sizeof(struct bcmf_event_msg))
{
@ -151,7 +151,7 @@ int bcmf_bdc_process_event_frame(FAR struct bcmf_dev_s *priv,
event_msg = (struct bcmf_event_msg *)(frame->data +
sizeof(struct bcmf_bdc_header) +
header->data_offset);
header->data_offset * 4);
if (event_msg->eth.ether_type != BCMF_EVENT_ETHER_TYPE ||
memcmp(event_msg->bcm_eth.oui, bcmf_broadcom_oui, 3))
@ -258,6 +258,7 @@ struct bcmf_frame_s *bcmf_bdc_rx_frame(FAR struct bcmf_dev_s *priv)
{
unsigned int frame_len;
struct bcmf_frame_s *frame = priv->bus->rxframe(priv);
struct bcmf_bdc_header *header;
/* Process bdc header */
@ -272,6 +273,7 @@ struct bcmf_frame_s *bcmf_bdc_rx_frame(FAR struct bcmf_dev_s *priv)
/* Transmit frame to upper layer */
frame->data += sizeof(struct bcmf_bdc_header);
header = (struct bcmf_bdc_header*)frame->data;
frame->data += sizeof(struct bcmf_bdc_header) + header->data_offset * 4;
return frame;
}

View File

@ -33,15 +33,19 @@
*
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE80211_BCMF_BDC_H
#define __DRIVERS_WIRELESS_IEEE80211_BCMF_BDC_H
/****************************************************************************
* Included Files
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE80211_BCMF_BDC_H
#define __DRIVERS_WIRELESS_IEEE80211_BCMF_BDC_H
#include "bcmf_driver.h"
/****************************************************************************
* Public Types
****************************************************************************/
/* Event frame content */
struct __attribute__((packed)) bcmf_event_s

View File

@ -0,0 +1,89 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_chip_43438.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Simon Piriou <spiriou31@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#include "bcmf_sdio.h"
#include <stdint.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define WRAPPER_REGISTER_OFFSET 0x100000
/****************************************************************************
* Public Data
****************************************************************************/
extern const char ap6212_nvram_image[];
extern const unsigned int ap6212_nvram_image_len;
extern const uint8_t ap6212_firmware_image[];
extern const unsigned int ap6212_firmware_len;
extern const uint8_t ap6212_clm_blob[];
extern const unsigned int ap6212_clm_blob_len;
const struct bcmf_sdio_chip bcmf_43438_config_sdio =
{
/* General chip stats */
.ram_size = 512*1024,
/* 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 */
.firmware_image = (uint8_t *)ap6212_firmware_image,
.firmware_image_size = (unsigned int *)&ap6212_firmware_len,
.nvram_image = (uint8_t *)ap6212_nvram_image,
.nvram_image_size = (unsigned int *)&ap6212_nvram_image_len,
.clm_blob_image = (uint8_t *)ap6212_clm_blob,
.clm_blob_image_size = (unsigned int *)&ap6212_clm_blob_len,
};

View File

@ -1,7 +1,7 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_core.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
* Author: Simon Piriou <spiriou31@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
@ -55,6 +55,7 @@
****************************************************************************/
/* Agent registers (common for every core) */
#define BCMA_IOCTL 0x0408 /* IO control */
#define BCMA_IOST 0x0500 /* IO status */
#define BCMA_RESET_CTL 0x0800 /* Reset control */
@ -74,8 +75,14 @@
#define BCMA_RESET_CTL_RESET 0x0001
/* SOCSRAM core registers */
#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 BCMF_UPLOAD_TRANSFER_SIZE (64 * 256)
/****************************************************************************
* Private Types
@ -87,11 +94,9 @@
static int bcmf_core_set_backplane_window(FAR struct bcmf_sdio_dev_s *sbus,
uint32_t address);
static int bcmf_upload_binary(FAR struct bcmf_sdio_dev_s *sbusv,
uint32_t address, uint8_t *buf,
unsigned int len);
uint32_t address, uint8_t *buf,
unsigned int len);
static int bcmf_upload_nvram(FAR struct bcmf_sdio_dev_s *sbus);
/****************************************************************************
@ -169,6 +174,7 @@ int bcmf_upload_binary(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
address += size;
buf += size;
}
return OK;
}
@ -202,7 +208,8 @@ int bcmf_upload_nvram(FAR struct bcmf_sdio_dev_s *sbus)
/* Write the length token to the last word */
ret = bcmf_write_sbreg(sbus, sbus->chip->ram_size - 4, (uint8_t *)&token, 4);
ret = bcmf_write_sbreg(sbus, sbus->chip->ram_size - 4,
(FAR uint8_t *)&token, 4);
if (ret != OK)
{
return ret;
@ -220,7 +227,7 @@ int bcmf_upload_nvram(FAR struct bcmf_sdio_dev_s *sbus)
****************************************************************************/
int bcmf_read_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
uint8_t *reg, unsigned int len)
FAR uint8_t *reg, unsigned int len)
{
int ret = bcmf_core_set_backplane_window(sbus, address);
if (ret != OK)
@ -228,6 +235,13 @@ int bcmf_read_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
return ret;
}
/* Map to 32-bit access if len == 4 */
if (len == 4)
{
address |= SBSDIO_SB_ACCESS_2_4B_FLAG;
}
return bcmf_transfer_bytes(sbus, false, 1,
address & SBSDIO_SB_OFT_ADDR_MASK, reg, len);
}
@ -237,7 +251,7 @@ int bcmf_read_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
****************************************************************************/
int bcmf_write_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
uint8_t *reg, unsigned int len)
FAR uint8_t *reg, unsigned int len)
{
int ret = bcmf_core_set_backplane_window(sbus, address);
@ -246,6 +260,13 @@ int bcmf_write_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
return ret;
}
/* Map to 32-bit access if len == 4 */
if (len == 4)
{
address |= SBSDIO_SB_ACCESS_2_4B_FLAG;
}
return bcmf_transfer_bytes(sbus, true, 1, address & SBSDIO_SB_OFT_ADDR_MASK,
reg, len);
}
@ -260,12 +281,23 @@ int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus)
wlinfo("upload firmware\n");
/* Disable ARMCM3 core and reset SOCRAM core
* to set device in firmware upload mode */
/* Disable ARMCM3 core and reset SOCRAM core to set device in firmware
* upload mode
*/
bcmf_core_disable(sbus, WLAN_ARMCM3_CORE_ID);
bcmf_core_reset(sbus, SOCSRAM_CORE_ID);
/* Do chip specific initialization */
if (sbus->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);
}
up_mdelay(50);
/* Flash chip firmware */

View File

@ -1,7 +1,7 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_driver.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
* Author: Simon Piriou <spiriou31@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
@ -69,15 +69,43 @@
#define BCMF_AUTH_TIMEOUT_MS 10000
#define BCMF_SCAN_RESULT_SIZE 1024
/* clm file is cut into pieces of MAX_CHUNK_LEN.
* It is relatively small because dongles (FW) have a small maximum size input
* payload restriction for ioctl's ... something like 1900'ish bytes. So chunk
* len should not exceed 1400 bytes
*/
#define MAX_CHUNK_LEN (CONFIG_NET_ETH_MTU > 1500 ? 1400 : CONFIG_NET_ETH_MTU - 100)
/* Helper to get iw_event size */
#define BCMF_IW_EVENT_SIZE(field) \
(offsetof(struct iw_event, u)+sizeof(((union iwreq_data*)0)->field))
/* Clm blob marcos */
#define DLOAD_HANDLER_VER 1 /* Downloader version */
#define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */
#define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */
#define DL_CRC_NOT_INUSE 0x0001
#define DL_BEGIN 0x0002
#define DL_END 0x0004
/****************************************************************************
* Private Types
****************************************************************************/
/* clm blob download head */
struct wl_dload_data
{
uint16_t flag;
uint16_t dload_type;
uint32_t len;
uint32_t crc;
};
/* AP scan state machine status */
enum
@ -88,6 +116,14 @@ enum
BCMF_SCAN_DONE
};
/* Generic download types & flags */
enum
{
DL_TYPE_UCODE = 1,
DL_TYPE_CLM = 2
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@ -97,6 +133,8 @@ static void bcmf_free_device(FAR struct bcmf_dev_s *priv);
static int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv);
static int bcmf_driver_download_clm(FAR struct bcmf_dev_s *priv);
// FIXME only for debug purpose
static void bcmf_wl_default_event_handler(FAR struct bcmf_dev_s *priv,
@ -213,6 +251,73 @@ int bcmf_wl_set_mac_address(FAR struct bcmf_dev_s *priv, struct ifreq *req)
return OK;
}
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 uint8_t *downloadbuff;
unsigned int datalen = *sbus->chip->clm_blob_image_size;
uint16_t dl_flag;
int ret = 0;
if (srcbuff == NULL || datalen <= 0)
{
wlinfo("Skip clm blob...\n");
return 0;
}
else
{
wlinfo("Download %d bytes @ 0x%08x\n", datalen, srcbuff);
}
/* Divide clm blob into chunks */
downloadbuff = kmm_malloc(sizeof(struct wl_dload_data) + MAX_CHUNK_LEN);
if (!downloadbuff)
{
wlerr("No memory for clm data\n");
return -ENOMEM;
}
dl_flag = DL_BEGIN;
do
{
FAR struct wl_dload_data *dlhead;
unsigned int chunk_len = datalen >= MAX_CHUNK_LEN ? MAX_CHUNK_LEN : datalen;
uint32_t out_len;
memcpy(downloadbuff + sizeof(struct wl_dload_data), srcbuff, chunk_len);
datalen -= chunk_len;
srcbuff += chunk_len;
if (datalen <= 0)
{
dl_flag |= DL_END;
}
/* clm header */
dlhead = (struct wl_dload_data *)downloadbuff;
dlhead->flag = (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT) | dl_flag;
dlhead->dload_type = DL_TYPE_CLM;
dlhead->len = chunk_len;
dlhead->crc = 0;
out_len = chunk_len + sizeof(struct wl_dload_data);
out_len = (out_len + 7) & ~0x7U;
ret = bcmf_cdc_iovar_request(priv, CHIP_STA_INTERFACE, true,
IOVAR_STR_CLMLOAD, downloadbuff,
&out_len);
dl_flag &= (uint16_t)~DL_BEGIN;
}
while ((datalen > 0) && (ret == OK));
kmm_free(downloadbuff);
return ret;
}
int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
{
int ret;
@ -221,11 +326,19 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
uint8_t tmp_buf[64];
int interface = CHIP_STA_INTERFACE;
/* Download clm blob if needed */
ret = bcmf_driver_download_clm(priv);
if (ret != OK)
{
return -EIO;
}
/* Disable TX Gloming feature */
out_len = 4;
*(uint32_t *)tmp_buf = 0;
ret = bcmf_cdc_iovar_request(priv, interface, false,
*(FAR uint32_t *)tmp_buf = 0;
ret = bcmf_cdc_iovar_request(priv, interface, true,
IOVAR_STR_TX_GLOM, tmp_buf,
&out_len);
if (ret != OK)
@ -236,9 +349,9 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
/* FIXME disable power save mode */
out_len = 4;
value = 0;
ret = bcmf_cdc_ioctl(priv, interface, true, WLC_SET_PM,
(uint8_t *)&value, &out_len);
value = 0;
ret = bcmf_cdc_ioctl(priv, interface, true, WLC_SET_PM,
(uint8_t *)&value, &out_len);
if (ret != OK)
{
return ret;
@ -258,16 +371,17 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
/* TODO configure roaming if needed. Disable for now */
out_len = 4;
value = 1;
ret = bcmf_cdc_iovar_request(priv, interface, true, IOVAR_STR_ROAM_OFF,
(uint8_t *)&value,
&out_len);
value = 1;
ret = bcmf_cdc_iovar_request(priv, interface, true,
IOVAR_STR_ROAM_OFF,
(FAR uint8_t *)&value,
&out_len);
/* TODO configure EAPOL version to default */
out_len = 8;
((uint32_t *)tmp_buf)[0] = interface;
((uint32_t *)tmp_buf)[1] = (uint32_t)-1;
((FAR uint32_t *)tmp_buf)[0] = interface;
((FAR uint32_t *)tmp_buf)[1] = (uint32_t)-1;
if (bcmf_cdc_iovar_request(priv, interface, true,
"bsscfg:"IOVAR_STR_SUP_WPA2_EAPVER, tmp_buf,
@ -279,9 +393,9 @@ int bcmf_driver_initialize(FAR struct bcmf_dev_s *priv)
/* Query firmware version string */
out_len = sizeof(tmp_buf);
ret = bcmf_cdc_iovar_request(priv, interface, false,
IOVAR_STR_VERSION, tmp_buf,
&out_len);
ret = bcmf_cdc_iovar_request(priv, interface, false,
IOVAR_STR_VERSION, tmp_buf,
&out_len);
if (ret != OK)
{
return -EIO;

View File

@ -712,6 +712,7 @@ typedef struct wlc_iov_trx_s
#define IOVAR_STR_AMPDU_MPDU "ampdu_mpdu"
#define IOVAR_STR_AMPDU_RX_FACTOR "ampdu_rx_factor"
#define IOVAR_STR_MIMO_BW_CAP "mimo_bw_cap"
#define IOVAR_STR_CLMLOAD "clmload"
#define WLC_IOCTL_MAGIC ( 0x14e46c77 )
#define WLC_IOCTL_VERSION ( 1 )

View File

@ -1,7 +1,7 @@
/****************************************************************************
* drivers/wireless/bcmf_netdev.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -110,22 +110,14 @@
#define BUF ((struct eth_hdr_s *)priv->bc_dev.d_buf)
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* Common TX logic */
static int bcmf_transmit(FAR struct bcmf_dev_s *priv,
struct bcmf_frame_s *frame);
static int bcmf_transmit(FAR struct bcmf_dev_s *priv,
FAR struct bcmf_frame_s *frame);
static void bcmf_receive(FAR struct bcmf_dev_s *priv);
static int bcmf_txpoll(FAR struct net_driver_s *dev);
static void bcmf_rxpoll(FAR void *arg);
@ -145,10 +137,10 @@ static int bcmf_txavail(FAR struct net_driver_s *dev);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
static int bcmf_addmac(FAR struct net_driver_s *dev,
FAR const uint8_t *mac);
FAR const uint8_t *mac);
#ifdef CONFIG_NET_IGMP
static int bcmf_rmmac(FAR struct net_driver_s *dev,
FAR const uint8_t *mac);
FAR const uint8_t *mac);
#endif
#ifdef CONFIG_NET_ICMPv6
static void bcmf_ipv6multicast(FAR struct bcmf_dev_s *priv);
@ -156,7 +148,7 @@ static void bcmf_ipv6multicast(FAR struct bcmf_dev_s *priv);
#endif
#ifdef CONFIG_NETDEV_IOCTL
static int bcmf_ioctl(FAR struct net_driver_s *dev, int cmd,
unsigned long arg);
unsigned long arg);
#endif
/****************************************************************************
@ -244,7 +236,7 @@ static int bcmf_transmit(FAR struct bcmf_dev_s *priv,
static void bcmf_receive(FAR struct bcmf_dev_s *priv)
{
struct bcmf_frame_s *frame;
// wlinfo("Entry\n");
do
{
/* Request frame buffer from bus interface */
@ -254,12 +246,14 @@ static void bcmf_receive(FAR struct bcmf_dev_s *priv)
if (frame == NULL)
{
/* No more frame to process */
break;
}
if (!priv->bc_bifup)
{
/* Interface down, drop frame */
priv->bus->free_frame(priv, frame);
continue;
}
@ -275,6 +269,24 @@ static void bcmf_receive(FAR struct bcmf_dev_s *priv)
pkt_input(&priv->bc_dev);
#endif
/* Check if this is an 802.1Q VLAN tagged packet */
if (BUF->type == HTONS(TPID_8021QVLAN))
{
/* Need to remove the 4 octet VLAN Tag, by moving src and dest
* addresses 4 octets to the right, and then read the actual
* ethertype. The VLAN ID and priority fields are currently
* ignored.
*/
uint8_t temp_buffer[12];
memcpy( temp_buffer, frame->data, 12);
memcpy( frame->data + 4, temp_buffer, 12);
priv->bc_dev.d_buf = frame->data = frame->data + 4;
priv->bc_dev.d_len -= 4;
}
/* We only accept IP packets of the configured type and ARP packets */
#ifdef CONFIG_NET_IPv4
@ -392,7 +404,11 @@ static void bcmf_receive(FAR struct bcmf_dev_s *priv)
else
#endif
{
wlerr("ERROR: RX dropped\n");
/* On some routers, it may constantly receive mysterious packet...
* https://www.wireshark.org/docs/wsar_html/epan/etypes_8h.html
* for more etypes definitions.
*/
NETDEV_RXDROPPED(&priv->bc_dev);
priv->bus->free_frame(priv, frame);
}

View File

@ -1,7 +1,7 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_sdio.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
* Author: Simon Piriou <spiriou31@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
@ -67,9 +67,13 @@
#include "bcmf_sdio_regs.h"
/* Supported chip configurations */
#ifdef CONFIG_IEEE80211_BROADCOM_BCM43362
extern const struct bcmf_sdio_chip bcmf_43362_config_sdio;
#endif
#ifdef CONFIG_IEEE80211_BROADCOM_BCM43438
extern const struct bcmf_sdio_chip bcmf_43438_config_sdio;
#endif
/****************************************************************************
* Pre-processor Definitions
@ -84,6 +88,12 @@
#define BCMF_WAITDOG_TIMEOUT_TICK (5*CLOCKS_PER_SEC)
/* Chipcommon registers */
#define CHIPCOMMON_GPIO_CONTROL ((uint32_t)(0x18000000 + 0x6C) )
#define CHIPCOMMON_SR_CONTROL0 ((uint32_t)(0x18000000 + 0x504) )
#define CHIPCOMMON_SR_CONTROL1 ((uint32_t)(0x18000000 + 0x508) )
/****************************************************************************
* Private Types
****************************************************************************/
@ -97,7 +107,7 @@ static int bcmf_hwinitialize(FAR struct bcmf_sdio_dev_s *sbus);
static void bcmf_hwuninitialize(FAR struct bcmf_sdio_dev_s *sbus);
static int bcmf_chipinitialize(FAR struct bcmf_sdio_dev_s *sbus);
static int bcmf_oob_irq(int irq, FAR void *context, FAR void *arg);
static int bcmf_oob_irq(FAR void *arg);
static int bcmf_sdio_bus_sleep(FAR struct bcmf_sdio_dev_s *sbus, bool sleep);
@ -106,11 +116,15 @@ static int bcmf_sdio_thread(int argc, char **argv);
static int bcmf_sdio_find_block_size(unsigned int size);
static int bcmf_sdio_sr_init(FAR struct bcmf_sdio_dev_s *sbus);
static bool brcm_chip_sr_capable(FAR struct bcmf_sdio_dev_s *sbus);
/****************************************************************************
* Private Data
****************************************************************************/
/* FIXME remove */
FAR struct bcmf_dev_s *g_sdio_priv;
/* Buffer pool for SDIO bus interface
@ -125,18 +139,18 @@ static struct bcmf_sdio_frame g_pktframes[BCMF_PKT_POOL_SIZE];
* Private Functions
****************************************************************************/
int bcmf_oob_irq(int irq, FAR void *context, FAR void *arg)
int bcmf_oob_irq(FAR void *arg)
{
FAR struct bcmf_sdio_dev_s *sbus = (struct bcmf_sdio_dev_s *)arg;
FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)arg;
if (sbus->ready)
{
/* Signal bmcf thread */
/* Signal bmcf thread */
sbus->irq_pending = true;
nxsem_post(&sbus->thread_signal);
}
return OK;
}
@ -158,22 +172,22 @@ int bcmf_sdio_bus_sleep(FAR struct bcmf_sdio_dev_s *sbus, bool sleep)
}
else
{
/* Request HT Avail */
ret = bcmf_write_reg(sbus, 1, SBSDIO_FUNC1_CHIPCLKCSR,
SBSDIO_HT_AVAIL_REQ | SBSDIO_FORCE_HT);
if (ret != OK)
{
wlerr("HT Avail request failed %d\n", ret);
return ret;
}
/* Wait for High Troughput clock */
loops = 20;
loops = 200;
while (--loops > 0)
{
up_mdelay(1);
/* Request HT Avail */
ret = bcmf_write_reg(sbus, 1, SBSDIO_FUNC1_CHIPCLKCSR,
SBSDIO_HT_AVAIL_REQ | SBSDIO_FORCE_HT);
if (ret != OK)
{
wlerr("HT Avail request failed %d\n", ret);
return ret;
}
/* Wait for High Throughput clock */
up_mdelay(100);
ret = bcmf_read_reg(sbus, 1, SBSDIO_FUNC1_CHIPCLKCSR, &value);
if (ret != OK)
@ -184,6 +198,7 @@ int bcmf_sdio_bus_sleep(FAR struct bcmf_sdio_dev_s *sbus, bool sleep)
if (value & SBSDIO_HT_AVAIL)
{
/* High Throughput clock is ready */
break;
}
}
@ -246,7 +261,8 @@ int bcmf_probe(FAR struct bcmf_sdio_dev_s *sbus)
}
/* Default device clock speed is up to 25 Mhz
* We could set EHS bit to operate at a clock rate up to 50 Mhz */
* We could set EHS bit to operate at a clock rate up to 50 Mhz.
*/
SDIO_CLOCK(sbus->sdio_dev, CLOCK_SD_TRANSFER_4BIT);
up_mdelay(BCMF_CLOCK_SETUP_DELAY_MS);
@ -280,9 +296,9 @@ int bcmf_businitialize(FAR struct bcmf_sdio_dev_s *sbus)
/* Send Active Low-Power clock request */
ret = bcmf_write_reg(sbus, 1, SBSDIO_FUNC1_CHIPCLKCSR,
SBSDIO_FORCE_HW_CLKREQ_OFF |
SBSDIO_ALP_AVAIL_REQ |
SBSDIO_FORCE_ALP);
SBSDIO_FORCE_HW_CLKREQ_OFF |
SBSDIO_ALP_AVAIL_REQ |
SBSDIO_FORCE_ALP);
if (ret != OK)
{
@ -303,6 +319,7 @@ int bcmf_businitialize(FAR struct bcmf_sdio_dev_s *sbus)
if (value & SBSDIO_ALP_AVAIL)
{
/* Active Low-Power clock is ready */
break;
}
}
@ -371,20 +388,24 @@ int bcmf_bus_setup_interrupts(FAR struct bcmf_sdio_dev_s *sbus)
{
return ret;
}
ret = sdio_enable_interrupt(sbus->sdio_dev, 2);
if (ret != OK)
{
return ret;
}
#ifndef CONFIG_BCMFMAC_NO_OOB
/* Redirect, configure and enable io for out-of-band interrupt signal */
ret = bcmf_write_reg(sbus, 0, SDIO_CCCR_BRCM_SEPINT,
SDIO_SEPINT_MASK | SDIO_SEPINT_OE | SDIO_SEPINT_ACT_HI);
SDIO_SEPINT_MASK | SDIO_SEPINT_OE |
SDIO_SEPINT_ACT_HI);
if (ret != OK)
{
return ret;
}
#endif
/* Wake up chip to be sure function 2 is running */
@ -404,8 +425,9 @@ int bcmf_bus_setup_interrupts(FAR struct bcmf_sdio_dev_s *sbus)
CORE_BUS_REG(sbus->chip->core_base[SDIOD_CORE_ID],
funcintmask), 2);
bcmf_write_reg(sbus, 1, SBSDIO_WATERMARK, 8);
/* Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped. */
bcmf_write_reg(sbus, 1, SBSDIO_WATERMARK, 8);
return OK;
}
@ -457,6 +479,7 @@ int bcmf_sdio_find_block_size(unsigned int size)
{
int ret = 0;
int size_copy = size;
while (size_copy)
{
size_copy >>= 1;
@ -471,6 +494,65 @@ int bcmf_sdio_find_block_size(unsigned int size)
return 1 << (ret - 1);
}
/* Init save-restore if the firmware support it: */
static int bcmf_sdio_sr_init(FAR struct bcmf_sdio_dev_s *sbus)
{
uint8_t data;
if (brcm_chip_sr_capable(sbus))
{
/* Configure WakeupCtrl register to set HtAvail request bit in
* chipClockCSR register after the sdiod core is powered on.
*/
bcmf_read_reg(sbus, 1, SBSDIO_FUNC1_WAKEUPCTRL, &data);
data |= SBSDIO_FUNC1_WCTRL_HTWAIT_MASK;
bcmf_write_reg(sbus, 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(sbus, 0, SDIO_CCCR_BRCM_CARDCAP, SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC);
bcmf_write_reg(sbus, 1, SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_FORCE_HT);
/* Enable KeepSdioOn (KSO) bit for normal operation */
bcmf_read_reg(sbus, 1, SBSDIO_FUNC1_SLEEPCSR, &data);
if((data & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK) == 0)
{
data |= SBSDIO_FUNC1_SLEEPCSR_KSO_MASK;
bcmf_write_reg(sbus, 1, SBSDIO_FUNC1_SLEEPCSR, data);
}
}
return OK;
}
/* Check if the firmware supports save restore feature.
* TODO: Add more chip specific logic, and move it to a new bcmf_chip.c file.
*/
static bool brcm_chip_sr_capable(FAR struct bcmf_sdio_dev_s *sbus)
{
uint32_t srctrl = 0;
int ret;
/* Check if fw initialized sr engine */
ret = bcmf_read_sbregw(sbus, CHIPCOMMON_SR_CONTROL1, &srctrl);
if (ret != OK)
{
return false;
}
else
{
return (srctrl != 0);
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -500,6 +582,7 @@ int bcmf_transfer_bytes(FAR struct bcmf_sdio_dev_s *sbus, bool write,
return sdio_io_rw_direct(sbus->sdio_dev, write,
function, address, *buf, NULL);
}
return sdio_io_rw_direct(sbus->sdio_dev, write,
function, address, 0, buf);
}
@ -551,7 +634,7 @@ int bcmf_write_reg(FAR struct bcmf_sdio_dev_s *sbus, uint8_t function,
****************************************************************************/
int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
int minor, FAR struct sdio_dev_s *dev)
int minor, FAR struct sdio_dev_s *dev)
{
int ret;
FAR struct bcmf_sdio_dev_s *sbus;
@ -568,16 +651,16 @@ int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
/* Initialize sdio bus device structure */
memset(sbus, 0, sizeof(*sbus));
sbus->sdio_dev = dev;
sbus->minor = minor;
sbus->ready = false;
sbus->sleeping = true;
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.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
sbus->bus.free_frame = bcmf_sdpcm_free_frame;
sbus->bus.stop = NULL; // TODO
/* Init transmit frames queue */
@ -591,8 +674,8 @@ int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
sq_init(&sbus->free_queue);
/* Setup free buffer list */
// FIXME this should be static to driver
for (ret = 0; ret < BCMF_PKT_POOL_SIZE; ret++)
{
bcmf_dqueue_push(&sbus->free_queue, &g_pktframes[ret].list_entry);
@ -622,7 +705,6 @@ int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
/* Initialize device hardware */
ret = bcmf_hwinitialize(sbus);
if (ret != OK)
{
goto exit_free_waitdog;
@ -631,7 +713,6 @@ int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
/* Probe device */
ret = bcmf_probe(sbus);
if (ret != OK)
{
goto exit_uninit_hw;
@ -640,7 +721,6 @@ int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
/* Initialize device bus */
ret = bcmf_businitialize(sbus);
if (ret != OK)
{
goto exit_uninit_hw;
@ -656,7 +736,14 @@ int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
goto exit_uninit_hw;
}
ret = bcmf_sdio_sr_init(sbus);
if (ret != OK)
{
goto exit_uninit_hw;
}
/* FIXME global variable for now */
g_sdio_priv = priv;
/* Register sdio bus */
@ -683,14 +770,16 @@ int bcmf_bus_sdio_initialize(FAR struct bcmf_dev_s *priv,
sbus->thread_id = ret;
/* sdio bus is up and running */
/* SDIO bus is up and running */
return OK;
exit_uninit_hw:
bcmf_hwuninitialize(sbus);
exit_free_waitdog:
wd_delete(sbus->waitdog);
exit_free_bus:
kmm_free(sbus);
priv->bus = NULL;
@ -699,8 +788,9 @@ exit_free_bus:
int bcmf_chipinitialize(FAR struct bcmf_sdio_dev_s *sbus)
{
int ret;
uint32_t value = 0;
int chipid;
int ret;
ret = bcmf_read_sbregw(sbus, SI_ENUM_BASE, &value);
if (ret != OK)
@ -708,7 +798,9 @@ int bcmf_chipinitialize(FAR struct bcmf_sdio_dev_s *sbus)
return ret;
}
int chipid = value & 0xffff;
chipid = value & 0xffff;
sbus->cur_chip_id = chipid;
switch (chipid)
{
#ifdef CONFIG_IEEE80211_BROADCOM_BCM43362
@ -717,10 +809,19 @@ int bcmf_chipinitialize(FAR struct bcmf_sdio_dev_s *sbus)
sbus->chip = (struct bcmf_sdio_chip *)&bcmf_43362_config_sdio;
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;
break;
#endif
default:
wlerr("chip 0x%x is not supported\n", chipid);
return -ENODEV;
}
}
return OK;
}
@ -741,7 +842,7 @@ int bcmf_sdio_thread(int argc, char **argv)
FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
int ret;
wlinfo("Enter\n");
wlinfo(" Enter\n");
/* FIXME wait for the chip to be ready to receive commands */
@ -774,23 +875,20 @@ int bcmf_sdio_thread(int argc, char **argv)
sbus->irq_pending = false;
bcmf_read_sbregw(sbus,
CORE_BUS_REG(sbus->chip->core_base[SDIOD_CORE_ID],
intstatus), &sbus->intstatus);
CORE_BUS_REG(sbus->chip->core_base[SDIOD_CORE_ID],
intstatus), &sbus->intstatus);
/* Clear interrupts */
bcmf_write_sbregw(sbus,
CORE_BUS_REG(sbus->chip->core_base[SDIOD_CORE_ID],
intstatus), sbus->intstatus);
// wlinfo("intstatus %x\n", sbus->intstatus);
CORE_BUS_REG(sbus->chip->core_base[SDIOD_CORE_ID],
intstatus), sbus->intstatus);
}
/* On frame indication, read available frames */
if (sbus->intstatus & I_HMB_FRAME_IND)
{
// wlinfo("Frames available\n");
do
{
ret = bcmf_sdpcm_readframe(priv);
@ -830,7 +928,6 @@ int bcmf_sdio_thread(int argc, char **argv)
}
wlinfo("Exit\n");
return 0;
}
@ -843,7 +940,7 @@ struct bcmf_sdio_frame *bcmf_sdio_allocate_frame(FAR struct bcmf_dev_s *priv,
while (1)
{
if (nxsem_wait(&sbus->queue_mutex < 0))
if (nxsem_wait(&sbus->queue_mutex) < 0)
{
PANIC();
}
@ -867,27 +964,28 @@ struct bcmf_sdio_frame *bcmf_sdio_allocate_frame(FAR struct bcmf_dev_s *priv,
if (block)
{
// TODO use signaling semaphore
wlinfo("alloc failed %d\n", tx);
up_mdelay(100);
continue;
}
wlinfo("No avail buffer\n");
return NULL;
}
sframe = container_of(entry, struct bcmf_sdio_frame, list_entry);
sframe->header.len = HEADER_SIZE + MAX_NET_DEV_MTU;
sframe->header.len = HEADER_SIZE + MAX_NET_DEV_MTU;
sframe->header.base = sframe->data;
sframe->header.data = sframe->data;
sframe->tx = tx;
sframe->tx = tx;
return sframe;
}
void bcmf_sdio_free_frame(FAR struct bcmf_dev_s *priv,
struct bcmf_sdio_frame *sframe)
{
// wlinfo("free %p\n", sframe);
FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
if (nxsem_wait(&sbus->queue_mutex) < 0)
@ -901,5 +999,6 @@ void bcmf_sdio_free_frame(FAR struct bcmf_dev_s *priv,
{
sbus->tx_queue_count -= 1;
}
nxsem_post(&sbus->queue_mutex);
}

View File

@ -1,7 +1,7 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_sdio.h
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
* Author: Simon Piriou <spiriou31@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
@ -69,6 +69,9 @@ struct bcmf_sdio_chip
uint8_t *nvram_image;
unsigned int *nvram_image_size;
uint8_t *clm_blob_image;
unsigned int *clm_blob_image_size;
};
/* sdio bus structure extension */
@ -79,6 +82,7 @@ struct bcmf_sdio_dev_s
FAR struct sdio_dev_s *sdio_dev; /* The SDIO device bound to this instance */
int minor; /* Device minor number */
int cur_chip_id; /* Chip ID read from the card */
struct bcmf_sdio_chip *chip; /* Chip specific configuration */
volatile bool ready; /* Current device status */
@ -144,4 +148,4 @@ struct bcmf_sdio_frame *bcmf_sdio_allocate_frame(FAR struct bcmf_dev_s *priv,
void bcmf_sdio_free_frame(FAR struct bcmf_dev_s *priv,
struct bcmf_sdio_frame *sframe);
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_SDIO_H */
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_SDIO_H */

View File

@ -30,11 +30,12 @@
#define SDIO_DEVICE_ID_BROADCOM_43143 43143
#define SDIO_DEVICE_ID_BROADCOM_43241 0x4324
#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330
#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334
#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330
#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334
#define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335
#define SDIO_DEVICE_ID_BROADCOM_43362 43362
#define SDIO_DEVICE_ID_BROADCOM_43430 43430
/* Core reg address translation.
* Both macro's returns a 32 bits byte address on the backplane bus.

View File

@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/wireless/ieee80211/bcmf_board.h
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
* Author: Simon Piriou <spiriou31@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
@ -69,6 +69,7 @@ extern "C"
* Input Parameters:
* minor - zero based minor device number which is unique
* for each wlan device.
*
************************************************************************************/
void bcmf_board_initialize(int minor);
@ -84,6 +85,7 @@ void bcmf_board_initialize(int minor);
* minor - zero based minor device number which is unique
* for each wlan device.
* power - true to power WLAN chip else false
*
************************************************************************************/
void bcmf_board_power(int minor, bool power);
@ -99,6 +101,7 @@ void bcmf_board_power(int minor, bool power);
* minor - zero based minor device number which is unique
* for each wlan device.
* reset - true to set WLAN chip in reset state else false
*
************************************************************************************/
void bcmf_board_reset(int minor, bool reset);
@ -115,9 +118,10 @@ void bcmf_board_reset(int minor, bool reset);
* for each wlan device.
* func - WLAN chip callback function that must be called on gpio event
* arg - WLAN chip internal structure that must be passed to callback
*
************************************************************************************/
void bcmf_board_setup_oob_irq(int minor, xcpt_t func, void *arg);
void bcmf_board_setup_oob_irq(int minor, int (*func)(void *), void *arg);
#undef EXTERN
#ifdef __cplusplus

View File

@ -958,7 +958,8 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd,
if (dev)
{
#ifdef CONFIG_NET_ETHERNET
if (dev->d_lltype == NET_LL_ETHERNET)
if (dev->d_lltype == NET_LL_ETHERNET ||
dev->d_lltype == NET_LL_IEEE80211)
{
req->ifr_hwaddr.sa_family = AF_INETX;
memcpy(req->ifr_hwaddr.sa_data,