Merge branch 'master' into l432kc

This commit is contained in:
Sebastien Lorquet
2017-05-05 10:54:26 +02:00
54 changed files with 29194 additions and 141 deletions
+19
View File
@@ -313,6 +313,25 @@ config UIMAGE_ENTRY_POINT
hex "uImage entry point"
default 0x0
endif
menuconfig DFU_BINARY
bool "DFU binary format"
select RAW_BINARY
---help---
Create the dfu binary used with dfu-utils.
if DFU_BINARY
config DFU_BASE
hex "Address DFU image is loaded to"
config DFU_VID
hex "VID to use for DFU image"
config DFU_PID
hex "PID to use for DFU image"
endif
endmenu # Binary Output Formats
+2 -2
View File
@@ -1272,7 +1272,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
* device.
*/
#ifndef CONFIG_I2C_POLLED
#ifdef CONFIG_I2C_POLLED
irqstate_t flags = enter_critical_section();
#endif
/* Receive a byte */
@@ -1287,7 +1287,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, 0);
}
#ifndef CONFIG_I2C_POLLED
#ifdef CONFIG_I2C_POLLED
leave_critical_section(flags);
#endif
}
+93 -22
View File
@@ -300,6 +300,8 @@
# endif
#endif
#define STM32_SDIO_USE_DEFAULT_BLOCKSIZE ((uint8_t)-1)
/****************************************************************************
* Private Types
****************************************************************************/
@@ -333,6 +335,12 @@ struct stm32_dev_s
size_t remaining; /* Number of bytes remaining in the transfer */
uint32_t xfrmask; /* Interrupt enables for data transfer */
/* Fixed transfer block size support */
#ifdef CONFIG_SDIO_BLOCKSETUP
uint8_t block_size;
#endif
/* DMA data transfer support */
bool widebus; /* Required for DMA support */
@@ -443,6 +451,10 @@ static int stm32_attach(FAR struct sdio_dev_s *dev);
static int stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t arg);
#ifdef CONFIG_SDIO_BLOCKSETUP
static void stm32_blocksetup(FAR struct sdio_dev_s *dev,
unsigned int blocklen, unsigned int nblocks);
#endif
static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
size_t nbytes);
static int stm32_sendsetup(FAR struct sdio_dev_s *dev,
@@ -456,8 +468,6 @@ static int stm32_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t rlong[4]);
static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t *rshort);
static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t *rnotimpl);
/* EVENT handler */
@@ -507,7 +517,7 @@ struct stm32_dev_s g_sdiodev =
.attach = stm32_attach,
.sendcmd = stm32_sendcmd,
#ifdef CONFIG_SDIO_BLOCKSETUP
.blocksetup = stm32_blocksetup, /* Not implemented yet */
.blocksetup = stm32_blocksetup,
#endif
.recvsetup = stm32_recvsetup,
.sendsetup = stm32_sendsetup,
@@ -516,8 +526,8 @@ struct stm32_dev_s g_sdiodev =
.recvR1 = stm32_recvshortcrc,
.recvR2 = stm32_recvlong,
.recvR3 = stm32_recvshort,
.recvR4 = stm32_recvnotimpl,
.recvR5 = stm32_recvnotimpl,
.recvR4 = stm32_recvshort,
.recvR5 = stm32_recvshortcrc,
.recvR6 = stm32_recvshortcrc,
.recvR7 = stm32_recvshort,
.waitenable = stm32_waitenable,
@@ -1015,7 +1025,7 @@ static void stm32_dataconfig(uint32_t timeout, uint32_t dlen, uint32_t dctrl)
regval = getreg32(STM32_SDIO_DCTRL);
regval &= ~(SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTMODE | SDIO_DCTRL_DBLOCKSIZE_MASK);
dctrl &= (SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTMODE | SDIO_DCTRL_DBLOCKSIZE_MASK);
regval |= (dctrl | SDIO_DCTRL_DTEN);
regval |= (dctrl | SDIO_DCTRL_DTEN | SDIO_DCTRL_SDIOEN);
putreg32(regval, STM32_SDIO_DCTRL);
}
@@ -1865,6 +1875,34 @@ static int stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
return OK;
}
/****************************************************************************
* Name: stm32_blocksetup
*
* Description:
* Configure block size and the number of blocks for next transfer
*
* Input Parameters:
* dev - An instance of the SDIO device interface
* blocklen - The selected block size.
* nblocklen - The number of blocks to transfer
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_SDIO_BLOCKSETUP
static void stm32_blocksetup(FAR struct sdio_dev_s *dev,
unsigned int blocklen, unsigned int nblocks)
{
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
/* Configure block size for next transfer */
priv->block_size = stm32_log2(blocklen);
}
#endif
/****************************************************************************
* Name: stm32_recvsetup
*
@@ -1911,7 +1949,17 @@ static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
/* Then set up the SDIO data path */
dblocksize = stm32_log2(nbytes) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
#ifdef CONFIG_SDIO_BLOCKSETUP
if (priv->block_size != STM32_SDIO_USE_DEFAULT_BLOCKSIZE)
{
dblocksize = priv->block_size << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
}
else
#endif
{
dblocksize = stm32_log2(nbytes) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
}
stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, nbytes, dblocksize | SDIO_DCTRL_DTDIR);
/* And enable interrupts */
@@ -1965,7 +2013,17 @@ static int stm32_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer
/* Then set up the SDIO data path */
dblocksize = stm32_log2(nbytes) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
#ifdef CONFIG_SDIO_BLOCKSETUP
if (priv->block_size != STM32_SDIO_USE_DEFAULT_BLOCKSIZE)
{
dblocksize = priv->block_size << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
}
else
#endif
{
dblocksize = stm32_log2(nbytes) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
}
stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, nbytes, dblocksize);
/* Enable TX interrupts */
@@ -2061,15 +2119,13 @@ static int stm32_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
case MMCSD_R1_RESPONSE:
case MMCSD_R1B_RESPONSE:
case MMCSD_R2_RESPONSE:
case MMCSD_R4_RESPONSE:
case MMCSD_R5_RESPONSE:
case MMCSD_R6_RESPONSE:
events = SDIO_RESPDONE_STA;
timeout = SDIO_LONGTIMEOUT;
break;
case MMCSD_R4_RESPONSE:
case MMCSD_R5_RESPONSE:
return -ENOSYS;
case MMCSD_R3_RESPONSE:
case MMCSD_R7_RESPONSE:
events = SDIO_RESPDONE_STA;
@@ -2161,6 +2217,7 @@ static int stm32_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t
else if ((cmd & MMCSD_RESPONSE_MASK) != MMCSD_R1_RESPONSE &&
(cmd & MMCSD_RESPONSE_MASK) != MMCSD_R1B_RESPONSE &&
(cmd & MMCSD_RESPONSE_MASK) != MMCSD_R5_RESPONSE &&
(cmd & MMCSD_RESPONSE_MASK) != MMCSD_R6_RESPONSE)
{
mcerr("ERROR: Wrong response CMD=%08x\n", cmd);
@@ -2276,6 +2333,7 @@ static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *r
#ifdef CONFIG_DEBUG_MEMCARD_INFO
if ((cmd & MMCSD_RESPONSE_MASK) != MMCSD_R3_RESPONSE &&
(cmd & MMCSD_RESPONSE_MASK) != MMCSD_R4_RESPONSE &&
(cmd & MMCSD_RESPONSE_MASK) != MMCSD_R7_RESPONSE)
{
mcerr("ERROR: Wrong response CMD=%08x\n", cmd);
@@ -2301,17 +2359,10 @@ static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *r
{
*rshort = getreg32(STM32_SDIO_RESP1);
}
return ret;
}
/* MMC responses not supported */
static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rnotimpl)
{
putreg32(SDIO_RESPDONE_ICR | SDIO_CMDDONE_ICR, STM32_SDIO_ICR);
return -ENOSYS;
}
/****************************************************************************
* Name: stm32_waitenable
*
@@ -2670,7 +2721,17 @@ static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
/* Then set up the SDIO data path */
dblocksize = stm32_log2(buflen) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
#ifdef CONFIG_SDIO_BLOCKSETUP
if (priv->block_size != STM32_SDIO_USE_DEFAULT_BLOCKSIZE)
{
dblocksize = priv->block_size << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
}
else
#endif
{
dblocksize = stm32_log2(buflen) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
}
stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, buflen, dblocksize | SDIO_DCTRL_DTDIR);
/* Configure the RX DMA */
@@ -2739,7 +2800,17 @@ static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev,
/* Then set up the SDIO data path */
dblocksize = stm32_log2(buflen) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
#ifdef CONFIG_SDIO_BLOCKSETUP
if (priv->block_size != STM32_SDIO_USE_DEFAULT_BLOCKSIZE)
{
dblocksize = priv->block_size << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
}
else
#endif
{
dblocksize = stm32_log2(buflen) << SDIO_DCTRL_DBLOCKSIZE_SHIFT;
}
stm32_dataconfig(SDIO_DTIMER_DATATIMEOUT, buflen, dblocksize);
/* Configure the TX DMA */
+2 -2
View File
@@ -1332,7 +1332,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
* device.
*/
#ifndef CONFIG_I2C_POLLED
#ifdef CONFIG_I2C_POLLED
irqstate_t flags = enter_critical_section();
#endif
/* Receive a byte */
@@ -1347,7 +1347,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
/* autoend? */
}
#ifndef CONFIG_I2C_POLLED
#ifdef CONFIG_I2C_POLLED
leave_critical_section(flags);
#endif
}
+2 -2
View File
@@ -1306,7 +1306,7 @@ static int stm32f0_i2c_isr_process(struct stm32f0_i2c_priv_s *priv)
* device.
*/
#ifndef CONFIG_I2C_POLLED
#ifdef CONFIG_I2C_POLLED
irqstate_t flags = enter_critical_section();
#endif
/* Receive a byte */
@@ -1321,7 +1321,7 @@ static int stm32f0_i2c_isr_process(struct stm32f0_i2c_priv_s *priv)
/* autoend? */
}
#ifndef CONFIG_I2C_POLLED
#ifdef CONFIG_I2C_POLLED
leave_critical_section(flags);
#endif
}
+12
View File
@@ -1614,6 +1614,18 @@ config UART8_RXDMA
---help---
In high data rate usage, Rx DMA may eliminate Rx overrun errors
config STM32F7_SERIAL_RXDMA_BUFFER_SIZE
int "Rx DMA buffer size"
default 32
depends on USART1_RXDMA || USART2_RXDMA || USART3_RXDMA || UART4_RXDMA || UART5_RXDMA || USART6_RXDMA || UART7_RXDMA || UART8_RXDMA
---help---
The DMA buffer size when using RX DMA to emulate a FIFO.
When streaming data, the generic serial layer will be called
every time the FIFO receives half this number of bytes.
Value given here will be rounded up to next multiple of 32 bytes.
config SERIAL_DISABLE_REORDERING
bool "Disable reordering of ttySx devices."
depends on STM32F7_USART1 || STM32F7_USART2 || STM32F7_USART3 || STM32F7_UART4 || STM32F7_UART5 || STM32F7_USART6 || STM32F7_UART7 || STM32F7_UART8
+4 -4
View File
@@ -1776,7 +1776,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
* sequence. Otherwise, additional bytes may be received.
*/
#ifndef CONFIG_I2C_POLLED
#ifdef CONFIG_I2C_POLLED
irqstate_t state = enter_critical_section();
#endif
/* Receive a byte */
@@ -1793,7 +1793,7 @@ static int stm32_i2c_isr_process(struct stm32_i2c_priv_s *priv)
priv->dcnt--;
#ifndef CONFIG_I2C_POLLED
#ifdef CONFIG_I2C_POLLED
leave_critical_section(state);
#endif
}
@@ -2141,7 +2141,7 @@ static int stm32_i2c_isr(int irq, void *context, FAR void *arg)
struct stm32_i2c_priv_s *priv = (struct stm32_i2c_priv_s *)arg;
DEBUGASSERT(priv != NULL);
return stm32_i2c_isr_process(&stm32_i2c1_priv);
return stm32_i2c_isr_process(priv);
}
#endif
@@ -2189,7 +2189,7 @@ static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv)
* - Provide means to set peripheral clock source via RCC_CFGR3_I2CxSW
* - Set to HSI by default, make Kconfig option
*/
/* Force a frequency update */
priv->frequency = 0;
+20 -5
View File
@@ -159,15 +159,30 @@
/* The DMA buffer size when using RX DMA to emulate a FIFO.
*
* When streaming data, the generic serial layer will be called
* every time the FIFO receives half this number of bytes.
* When streaming data, the generic serial layer will be called every time
* the FIFO receives half this number of bytes.
*
* This buffer size should be an even multiple of the Cortex-M7
* D-Cache line size so that it can be individually invalidated.
* This buffer size should be an even multiple of the Cortex-M7 D-Cache line
* size, ARMV7M_DCACHE_LINESIZE, so that it can be individually invalidated.
*
* Should there be a Cortex-M7 without a D-Cache, ARMV7M_DCACHE_LINESIZE
* would be zero!
*/
# if !defined(ARMV7M_DCACHE_LINESIZE) || ARMV7M_DCACHE_LINESIZE == 0
# undef ARMV7M_DCACHE_LINESIZE
# define ARMV7M_DCACHE_LINESIZE 32
# endif
# if !defined(CONFIG_STM32F7_SERIAL_RXDMA_BUFFER_SIZE) || \
(CONFIG_STM32F7_SERIAL_RXDMA_BUFFER_SIZE < ARMV7M_DCACHE_LINESIZE)
# undef CONFIG_STM32F7_SERIAL_RXDMA_BUFFER_SIZE
# define CONFIG_STM32F7_SERIAL_RXDMA_BUFFER_SIZE ARMV7M_DCACHE_LINESIZE
# endif
# define RXDMA_BUFFER_MASK (ARMV7M_DCACHE_LINESIZE - 1)
# define RXDMA_BUFFER_SIZE ((32 + RXDMA_BUFFER_MASK) & ~RXDMA_BUFFER_MASK)
# define RXDMA_BUFFER_SIZE ((CONFIG_STM32F7_SERIAL_RXDMA_BUFFER_SIZE \
+ RXDMA_BUFFER_MASK) & ~RXDMA_BUFFER_MASK)
/* DMA priority */
+3 -3
View File
@@ -1384,7 +1384,7 @@ static int stm32l4_i2c_isr_process(struct stm32l4_i2c_priv_s *priv)
* device.
*/
#ifndef CONFIG_I2C_POLLED
#ifdef CONFIG_I2C_POLLED
irqstate_t flags = enter_critical_section();
#endif
/* Receive a byte */
@@ -1399,7 +1399,7 @@ static int stm32l4_i2c_isr_process(struct stm32l4_i2c_priv_s *priv)
/* autoend? */
}
#ifndef CONFIG_I2C_POLLED
#ifdef CONFIG_I2C_POLLED
leave_critical_section(flags);
#endif
}
@@ -1532,7 +1532,7 @@ static int stm32l4_i2c_isr_process(struct stm32l4_i2c_priv_s *priv)
*
************************************************************************************/
#ifdef CONFIG_STM32L4_I2C2
#ifndef CONFIG_I2C_POLLED
static int stm32l4_i2c_isr(int irq, void *context, FAR void *arg)
{
struct stm32l4_i2c_priv_s *priv = (struct stm32l4_i2c_priv_s *)arg;
+11
View File
@@ -237,6 +237,17 @@
# define SDIO_SDXFR_CLKDIV (2 << SDIO_CLKCR_CLKDIV_SHIFT)
#endif
/* DMA Channl/Stream Selections *****************************************************/
/* Stream selections are arbitrary for now but might become important in the future
* if we set aside more DMA channels/streams.
*
* SDIO DMA
* DMAMAP_SDIO_1 = Channel 4, Stream 3
* DMAMAP_SDIO_2 = Channel 4, Stream 6
*/
#define DMAMAP_SDIO DMAMAP_SDIO_1
/************************************************************************************
* Public Data
************************************************************************************/
+24 -1
View File
@@ -40,7 +40,7 @@ include ${TOPDIR}/arch/arm/src/armv7-m/Toolchain.defs
ifeq ($(CONFIG_PHOTON_DFU_BOOTLOADER),y)
LDSCRIPT = photon_dfu.ld
else
LDSCRIPT = ld.script
LDSCRIPT = photon_jtag.ld
endif
ifeq ($(WINTOOL),y)
@@ -68,6 +68,11 @@ NM = $(ARCROSSDEV)nm
OBJCOPY = $(CROSSDEV)objcopy
OBJDUMP = $(CROSSDEV)objdump
# See http://dfu-util.sourceforge.net/
DFUSUFFIX = dfu-suffix
DFUUTIL = dfu-util
ARCHCCVERSION = ${shell $(CC) -v 2>&1 | sed -n '/^gcc version/p' | sed -e 's/^gcc version \([0-9\.]\)/\1/g' -e 's/[-\ ].*//g' -e '1q'}
ARCHCCMAJOR = ${shell echo $(ARCHCCVERSION) | cut -d'.' -f1}
@@ -114,3 +119,21 @@ HOSTCC = gcc
HOSTINCLUDES = -I.
HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -Wundef -g -pipe
HOSTLDFLAGS =
ifeq ($(CONFIG_DFU_BINARY),y)
define DOWNLOAD
$(Q) echo "DFUSUFFIX: $(1).dfu"
$(Q) $(OBJCOPY) $(OBJCOPYARGS) -O binary $(1) $(1).dfu
$(Q) $(DFUSUFFIX) -v $(subst 0x,,$(CONFIG_DFU_VID)) -p $(subst 0x,,$(CONFIG_DFU_PID)) -a $(1).dfu
$(Q) $(DFUUTIL) -d $(CONFIG_DFU_VID):$(CONFIG_DFU_PID) -a 0 -s $(CONFIG_DFU_BASE) -D $(1).dfu
endef
else
define DOWNLOAD
$(Q) $(ECHO) "Photon firmware upload through JTAG is not supported"
endef
endif
+11 -1
View File
@@ -33,7 +33,7 @@
****************************************************************************/
/* The STM32F205RG has 1024Kb of FLASH beginning at address 0x0800:0000 and
* 112Kb of SRAM.
* 112Kb of SRAM in main SRAM1 and 16 Kb in auxiliary SRAM2.
*
* Bootloader jumps at 0x0802:0000.
*/
@@ -61,6 +61,16 @@ SECTIONS
*(.text .text.*)
*(.fixup)
*(.gnu.warning)
. = ALIGN(0x4);
wlan_firmware_image_location = .;
*(.wlan_firmware_image .wlan_firmware_image.*)
wlan_firmware_image_end = .;
. = ALIGN(0x4);
wlan_nvram_image_location = .;
*(.wlan_nvram_image .wlan_nvram_image.*)
wlan_nvram_image_end = .;
*(.rodata .rodata.*)
*(.gnu.linkonce.t.*)
*(.glue_7)
@@ -1,5 +1,5 @@
/****************************************************************************
* configs/photon/scripts/ld.script
* configs/photon/scripts/photon_jtag.ld
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
*
@@ -33,7 +33,7 @@
****************************************************************************/
/* The STM32F205RG has 1024Kb of FLASH beginning at address 0x0800:0000 and
* 112Kb of SRAM.
* 112Kb of SRAM in main SRAM1 and 16 Kb in auxiliary SRAM2.
*
* When booting from FLASH, FLASH memory is aliased to address 0x0000:0000
* where the code expects to begin execution by jumping to the entry point in
+1
View File
@@ -61,6 +61,7 @@ endif
ifeq ($(CONFIG_PHOTON_WLAN),y)
CSRCS += stm32_wlan.c
CSRCS += stm32_wlan_firmware.c
endif
ifeq ($(CONFIG_STM32_OTGHS),y)
+18
View File
@@ -98,6 +98,24 @@ void bcmf_board_initialize(int minor)
bcmf_board_reset(minor, true);
}
/****************************************************************************
* Name: bcmf_board_setup_oob_irq
****************************************************************************/
void bcmf_board_setup_oob_irq(int minor, xcpt_t func, void *arg)
{
if (minor != SDIO_WLAN0_MINOR)
{
return;
}
/* Configure interrupt pin */
stm32_configgpio(GPIO_WLAN0_OOB_INT);
stm32_gpiosetevent(GPIO_WLAN0_OOB_INT, true, false, false, func, arg);
}
/****************************************************************************
* Name: photon_wlan_initialize
****************************************************************************/
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -40,7 +40,7 @@ include ${TOPDIR}/arch/arm/src/armv7-m/Toolchain.defs
ifeq ($(CONFIG_PHOTON_DFU_BOOTLOADER),y)
LDSCRIPT = photon_dfu.ld
else
LDSCRIPT = ld.script
LDSCRIPT = photon_jtag.ld
endif
ifeq ($(WINTOOL),y)
+139
View File
@@ -0,0 +1,139 @@
############################################################################
# configs/photon/wlan/Make.defs
#
# Copyright (C) 2017 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# 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 ${TOPDIR}/.config
include ${TOPDIR}/tools/Config.mk
include ${TOPDIR}/arch/arm/src/armv7-m/Toolchain.defs
ifeq ($(CONFIG_PHOTON_DFU_BOOTLOADER),y)
LDSCRIPT = photon_dfu.ld
else
LDSCRIPT = photon_jtag.ld
endif
ifeq ($(WINTOOL),y)
# Windows-native toolchains
DIRLINK = $(TOPDIR)/tools/copydir.sh
DIRUNLINK = $(TOPDIR)/tools/unlink.sh
MKDEP = $(TOPDIR)/tools/mkwindeps.sh
ARCHINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}"
ARCHXXINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" -isystem "${shell cygpath -w $(TOPDIR)/include/cxx}"
ARCHSCRIPT = -T "${shell cygpath -w $(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT)}"
else
# Linux/Cygwin-native toolchain
MKDEP = $(TOPDIR)/tools/mkdeps$(HOSTEXEEXT)
ARCHINCLUDES = -I. -isystem $(TOPDIR)/include
ARCHXXINCLUDES = -I. -isystem $(TOPDIR)/include -isystem $(TOPDIR)/include/cxx
ARCHSCRIPT = -T$(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT)
endif
CC = $(CROSSDEV)gcc
CXX = $(CROSSDEV)g++
CPP = $(CROSSDEV)gcc -E
LD = $(CROSSDEV)ld
AR = $(ARCROSSDEV)ar rcs
NM = $(ARCROSSDEV)nm
OBJCOPY = $(CROSSDEV)objcopy
OBJDUMP = $(CROSSDEV)objdump
# See http://dfu-util.sourceforge.net/
DFUSUFFIX = dfu-suffix
DFUUTIL = dfu-util
ARCHCCVERSION = ${shell $(CC) -v 2>&1 | sed -n '/^gcc version/p' | sed -e 's/^gcc version \([0-9\.]\)/\1/g' -e 's/[-\ ].*//g' -e '1q'}
ARCHCCMAJOR = ${shell echo $(ARCHCCVERSION) | cut -d'.' -f1}
ifeq ($(CONFIG_DEBUG_SYMBOLS),y)
ARCHOPTIMIZATION = -g
endif
ifneq ($(CONFIG_DEBUG_NOOPT),y)
ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer
endif
ARCHCFLAGS = -fno-builtin
ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new -fno-rtti
ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef
ARCHWARNINGSXX = -Wall -Wshadow -Wundef
ARCHDEFINES =
ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10
CFLAGS = $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe
CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS)
CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe
CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS)
CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES)
AFLAGS = $(CFLAGS) -D__ASSEMBLY__
NXFLATLDFLAGS1 = -r -d -warn-common
NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections
LDNXFLATFLAGS = -e main -s 2048
ASMEXT = .S
OBJEXT = .o
LIBEXT = .a
EXEEXT =
ifneq ($(CROSSDEV),arm-nuttx-elf-)
LDFLAGS += -nostartfiles -nodefaultlibs
endif
ifeq ($(CONFIG_DEBUG_SYMBOLS),y)
LDFLAGS += -g
endif
HOSTCC = gcc
HOSTINCLUDES = -I.
HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -Wundef -g -pipe
HOSTLDFLAGS =
ifeq ($(CONFIG_DFU_BINARY),y)
define DOWNLOAD
$(Q) echo "DFUSUFFIX: $(1).dfu"
$(Q) $(OBJCOPY) $(OBJCOPYARGS) -O binary $(1) $(1).dfu
$(Q) $(DFUSUFFIX) -v $(subst 0x,,$(CONFIG_DFU_VID)) -p $(subst 0x,,$(CONFIG_DFU_PID)) -a $(1).dfu
$(Q) $(DFUUTIL) -d $(CONFIG_DFU_VID):$(CONFIG_DFU_PID) -a 0 -s $(CONFIG_DFU_BASE) -D $(1).dfu
endef
else
define DOWNLOAD
$(Q) $(ECHO) "Photon firmware upload through JTAG is not supported"
endef
endif
File diff suppressed because it is too large Load Diff
+34
View File
@@ -8,6 +8,11 @@ if DRIVERS_IEEE80211
config IEEE80211_BROADCOM_FULLMAC
bool
config IEEE80211_BROADCOM_BCM43362
bool "Broadcom 43362 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
@@ -17,4 +22,33 @@ config IEEE80211_BROADCOM_FULLMAC_SDIO
This selection enables support for broadcom
FullMAC-compliant devices using SDIO bus.
if IEEE80211_BROADCOM_FULLMAC
choice
prompt "Broadcom FullMAC driver work queue"
default IEEE80211_BROADCOM_LPWORK if SCHED_LPWORK
default IEEE80211_BROADCOM_HPWORK if !SCHED_LPWORK && SCHED_HPWORK
depends on SCHED_WORKQUEUE
---help---
Work queue support is required to use the loopback driver. If the
low priority work queue is available, then it should be used by the
loopback driver.
config IEEE80211_BROADCOM_HPWORK
bool "High priority"
depends on SCHED_HPWORK
config IEEE80211_BROADCOM_LPWORK
bool "Low priority"
depends on SCHED_LPWORK
endchoice # Work queue
config IEEE80211_BROADCOM_NINTERFACES
int "Number of Broadcom FullMAC interfaces"
default 1
depends on EXPERIMENTAL
endif # IEEE80211_BROADCOM_FULLMAC
endif # DRIVERS_IEEE80211
+16
View File
@@ -40,10 +40,26 @@ ifeq ($(CONFIG_DRIVERS_IEEE80211),y)
# Include IEEE 802.11 drivers into the build
ifeq ($(CONFIG_IEEE80211_BROADCOM_FULLMAC),y)
CSRCS += bcmf_driver.c
CSRCS += bcmf_cdc.c
CSRCS += bcmf_bdc.c
CSRCS += bcmf_utils.c
CSRCS += bcmf_netdev.c
ifeq ($(CONFIG_IEEE80211_BROADCOM_FULLMAC_SDIO),y)
CSRCS += mmc_sdio.c
CSRCS += bcmf_sdio.c
CSRCS += bcmf_core.c
CSRCS += bcmf_sdpcm.c
endif
ifeq ($(CONFIG_IEEE80211_BROADCOM_BCM43362),y)
CSRCS += bcmf_chip_43362.c
endif
endif # CONFIG_IEEE80211_BROADCOM_FULLMAC
# Include IEEE 802.11 build support
DEPPATH += --dep-path wireless$(DELIM)ieee80211
+277
View File
@@ -0,0 +1,277 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_bdc.c
*
* Copyright (C) 2017 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <debug.h>
#include <errno.h>
#include <string.h>
#include <net/ethernet.h>
#include "bcmf_driver.h"
#include "bcmf_ioctl.h"
#include "bcmf_cdc.h"
#include "bcmf_bdc.h"
#include "bcmf_utils.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define BCMF_EVENT_ETHER_TYPE 0x6C88 /* Ether type of event frames */
/****************************************************************************
* Private Types
****************************************************************************/
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 */
};
struct __attribute__((packed)) bcmf_eth_header
{
uint16_t type; /* Vendor specific type */
uint16_t len; /* Event data length */
uint8_t version; /* Protocol version */
uint8_t oui[3]; /* Organizationally unique identifier */
uint16_t usr_type; /* User specific type */
};
struct __attribute__((packed)) bcmf_event_msg
{
struct ether_header eth;
struct bcmf_eth_header bcm_eth;
struct bcmf_event_s event;
uint8_t data[0];
};
/****************************************************************************
* Private Data
****************************************************************************/
static const uint8_t bcmf_broadcom_oui[] = {0x00, 0x10, 0x18};
/****************************************************************************
* Public Functions
****************************************************************************/
struct bcmf_frame_s *bcmf_bdc_allocate_frame(FAR struct bcmf_dev_s *priv,
uint32_t len, bool block)
{
struct bcmf_frame_s *frame;
/* Allocate data frame */
// TODO check for integer overflow
frame = priv->bus->allocate_frame(priv,
sizeof(struct bcmf_bdc_header) + len, block, false);
if (!frame)
{
return NULL;
}
frame->data += sizeof(struct bcmf_bdc_header);
return frame;
}
int bcmf_bdc_process_event_frame(FAR struct bcmf_dev_s *priv,
struct bcmf_frame_s *frame)
{
int data_size;
struct bcmf_bdc_header *header;
struct bcmf_event_msg *event_msg;
uint32_t event_id;
event_handler_t handler;
/* Check frame header */
data_size = frame->len - (int)(frame->data - frame->base);
if (data_size < sizeof(struct bcmf_bdc_header))
{
goto exit_invalid_frame;
}
header = (struct bcmf_bdc_header *)frame->data;
data_size -= sizeof(struct bcmf_bdc_header) + header->data_offset;
if (data_size < sizeof(struct bcmf_event_msg))
{
goto exit_invalid_frame;
}
data_size -= sizeof(struct ether_header) + sizeof(struct bcmf_eth_header);
/* Check ethernet header */
event_msg = (struct bcmf_event_msg *)(frame->data +
sizeof(struct bcmf_bdc_header) +
header->data_offset);
if (event_msg->eth.ether_type != BCMF_EVENT_ETHER_TYPE ||
memcmp(event_msg->bcm_eth.oui, bcmf_broadcom_oui, 3))
{
goto exit_invalid_frame;
}
event_id = bcmf_getle32(&event_msg->event.type);
if (event_id >= BCMF_EVENT_COUNT)
{
wlinfo("Invalid event id %d\n", event_id);
return -EINVAL;
}
/* Dispatch event to registered handler */
handler = priv->event_handlers[event_id];
if (handler != NULL)
{
handler(priv, &event_msg->event, data_size);
}
return OK;
exit_invalid_frame:
wlerr("Invalid event frame\n");
bcmf_hexdump(frame->base, frame->len, (unsigned long)frame->base);
return -EINVAL;
}
int bcmf_event_register(FAR struct bcmf_dev_s *priv, event_handler_t handler,
unsigned int event_id)
{
if (event_id >= BCMF_EVENT_COUNT)
{
/* Invalid event id */
return -EINVAL;
}
priv->event_handlers[event_id] = handler;
return OK;
}
int bcmf_event_unregister(FAR struct bcmf_dev_s *priv,
unsigned int event_id)
{
return bcmf_event_register(priv, NULL, event_id);
}
int bcmf_event_push_config(FAR struct bcmf_dev_s *priv)
{
int i;
uint32_t out_len;
uint8_t event_mask[(BCMF_EVENT_COUNT + 7) >> 3];
memset(event_mask, 0, sizeof(event_mask));
for (i = 0; i < BCMF_EVENT_COUNT; i++)
{
if (priv->event_handlers[i] != NULL)
{
event_mask[i >> 3] |= 1 << (i & 0x7);
}
}
/* Send event mask to chip */
out_len = sizeof(event_mask);
if (bcmf_cdc_iovar_request(priv, CHIP_STA_INTERFACE, true,
IOVAR_STR_EVENT_MSGS, event_mask,
&out_len))
{
return -EIO;
}
return OK;
}
int bcmf_bdc_transmit_frame(FAR struct bcmf_dev_s *priv,
struct bcmf_frame_s *frame)
{
struct bcmf_bdc_header *header;
/* Set frame data for lower layer */
frame->data -= sizeof(struct bcmf_bdc_header);
header = (struct bcmf_bdc_header *)frame->data;
/* Setup data frame header */
header->flags = 0x20; /* Set bdc protocol version */
header->priority = 0; // TODO handle priority
header->flags2 = CHIP_STA_INTERFACE;
header->data_offset = 0;
/* Send frame */
return priv->bus->txframe(priv, frame, false);
}
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);
/* Process bdc header */
frame_len = frame->len - (unsigned int)(frame->data - frame->base);
if (frame_len < sizeof(struct bcmf_bdc_header))
{
wlerr("Data frame too small\n");
priv->bus->free_frame(priv, frame);
return NULL;
}
/* Transmit frame to upper layer */
frame->data += sizeof(struct bcmf_bdc_header);
return frame;
}
+96
View File
@@ -0,0 +1,96 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_bdc.h
*
* Copyright (C) 2017 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE80211_BCMF_BDC_H
#define __DRIVERS_WIRELESS_IEEE80211_BCMF_BDC_H
#include "bcmf_driver.h"
/* Event frame content */
struct __attribute__((packed)) bcmf_event_s
{
uint16_t version; /* Vendor specific type */
uint16_t flags;
uint32_t type; /* Id of received event */
uint32_t status; /* Event status code */
uint32_t reason; /* Reason code */
uint32_t auth_type;
uint32_t len; /* Data size following this header */
struct ether_addr addr; /* AP MAC address */
char src_name[16]; /* Event source interface name */
uint8_t dst_id; /* Event destination interface id */
uint8_t bss_cfg_id;
};
/* Event callback handler */
typedef void (*event_handler_t)(FAR struct bcmf_dev_s *priv,
struct bcmf_event_s *event, unsigned int len);
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/* Function called from lower layer */
int bcmf_bdc_process_event_frame(FAR struct bcmf_dev_s *priv,
struct bcmf_frame_s *frame);
/* Function called from upper layer */
struct bcmf_frame_s *bcmf_bdc_allocate_frame(FAR struct bcmf_dev_s *priv,
uint32_t len, bool block);
int bcmf_bdc_transmit_frame(FAR struct bcmf_dev_s *priv,
struct bcmf_frame_s *frame);
struct bcmf_frame_s *bcmf_bdc_rx_frame(FAR struct bcmf_dev_s *priv);
/* Event frames API */
int bcmf_event_register(FAR struct bcmf_dev_s *priv, event_handler_t handler,
unsigned int event_id);
int bcmf_event_unregister(FAR struct bcmf_dev_s *priv,
unsigned int event_id);
int bcmf_event_push_config(FAR struct bcmf_dev_s *priv);
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_BDC_H */
+330
View File
@@ -0,0 +1,330 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_cdc.c
*
* Copyright (C) 2017 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/arch.h>
#include <stddef.h>
#include <string.h>
#include <semaphore.h>
#include "bcmf_driver.h"
#include "bcmf_ioctl.h"
#include "bcmf_utils.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Control header flags */
#define BCMF_CONTROL_ERROR 0x01 /* Command failure flag */
#define BCMF_CONTROL_SET 0x02 /* Command type: SET = 1, GET = 0 */
#define BCMF_CONTROL_INTERFACE_SHIFT 12
#define BCMF_CONTROL_REQID_SHIFT 16
#define BCMF_CONTROL_TIMEOUT_MS 1000
/****************************************************************************
* Private Types
****************************************************************************/
struct __attribute__((packed)) bcmf_cdc_header {
uint32_t cmd; /* Command to be sent */
uint32_t len; /* Size of command data */
uint32_t flags; /* cdc request flags, see above */
uint32_t status; /* Returned status code from chip */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static struct bcmf_frame_s *bcmf_cdc_allocate_frame(
FAR struct bcmf_dev_s *priv, char *name,
uint8_t *data, uint32_t len);
static int bcmf_cdc_sendframe(FAR struct bcmf_dev_s *priv, uint32_t cmd,
int ifidx, bool set, struct bcmf_frame_s *frame);
static int bcmf_cdc_control_request(FAR struct bcmf_dev_s *priv,
uint32_t ifidx, bool set, uint32_t cmd,
char *name, uint8_t *data, uint32_t *len);
static int bcmf_cdc_control_request_unsafe(FAR struct bcmf_dev_s *priv,
uint32_t ifidx, bool set, uint32_t cmd,
char *name, uint8_t *data, uint32_t *len);
/****************************************************************************
* Private Functions
****************************************************************************/
struct bcmf_frame_s *bcmf_cdc_allocate_frame(FAR struct bcmf_dev_s *priv,
char *name, uint8_t *data,
uint32_t len)
{
uint32_t data_len;
uint16_t name_len;
struct bcmf_frame_s *frame;
if (name)
{
name_len = strlen(name) + 1;
}
else
{
name_len = 0;
}
if (data)
{
data_len = len;
}
else
{
data_len = 0;
}
/* Allocate control frame */
frame = priv->bus->allocate_frame(priv,
sizeof(struct bcmf_cdc_header) + data_len + name_len,
true, true);
if (!frame)
{
return NULL;
}
/* Copy name string and data */
memcpy(frame->data + sizeof(struct bcmf_cdc_header), name, name_len);
memcpy(frame->data + sizeof(struct bcmf_cdc_header)
+ name_len, data, data_len);
return frame;
}
int bcmf_cdc_sendframe(FAR struct bcmf_dev_s *priv, uint32_t cmd,
int ifidx, bool set, struct bcmf_frame_s *frame)
{
struct bcmf_cdc_header *header =
(struct bcmf_cdc_header *)frame->data;
/* Setup control frame header */
uint32_t cdc_data_len = frame->len - (uint32_t)(frame->data-frame->base);
header->cmd = cmd;
header->len = cdc_data_len-sizeof(struct bcmf_cdc_header);
header->status = 0;
header->flags = ++priv->control_reqid << BCMF_CONTROL_REQID_SHIFT;
header->flags |= ifidx << BCMF_CONTROL_INTERFACE_SHIFT;
if (set)
{
header->flags |= BCMF_CONTROL_SET;
}
/* Send frame */
return priv->bus->txframe(priv, frame, true);
}
int bcmf_cdc_control_request(FAR struct bcmf_dev_s *priv,
uint32_t ifidx, bool set, uint32_t cmd,
char *name, uint8_t *data, uint32_t *len)
{
int ret;
/* Take device control mutex */
if ((ret = sem_wait(&priv->control_mutex)) != OK)
{
return ret;
}
ret = bcmf_cdc_control_request_unsafe(priv, ifidx, set, cmd,
name, data, len);
sem_post(&priv->control_mutex);
return ret;
}
int bcmf_cdc_control_request_unsafe(FAR struct bcmf_dev_s *priv,
uint32_t ifidx, bool set, uint32_t cmd,
char *name, uint8_t *data, uint32_t *len)
{
int ret;
struct bcmf_frame_s *frame;
uint32_t out_len = *len;
*len = 0;
/* Prepare control frame */
frame = bcmf_cdc_allocate_frame(priv, name, data, out_len);
if (!frame)
{
wlerr("Cannot allocate cdc frame\n");
return -ENOMEM;
}
/* Setup buffer to store response */
priv->control_rxdata = set ? NULL : data;
priv->control_rxdata_len = out_len;
/* Send control frame. iovar buffer is freed when sent */
ret = bcmf_cdc_sendframe(priv, cmd, ifidx, set, frame);
if (ret != OK)
{
/* Free allocated iovar buffer */
priv->bus->free_frame(priv, frame);
return ret;
}
ret = bcmf_sem_wait(&priv->control_timeout, BCMF_CONTROL_TIMEOUT_MS);
if (ret != OK)
{
wlerr("Error while waiting for control response %d\n", ret);
return ret;
}
*len = priv->control_rxdata_len;
/* Check frame status */
if (priv->control_status != 0)
{
wlerr("Invalid cdc status 0x%x\n", priv->control_status);
return -EINVAL;
}
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
int bcmf_cdc_iovar_request(FAR struct bcmf_dev_s *priv,
uint32_t ifidx, bool set, char *name,
uint8_t *data, uint32_t *len)
{
return bcmf_cdc_control_request(priv, ifidx, set,
set ? WLC_SET_VAR : WLC_GET_VAR, name,
data, len);
}
int bcmf_cdc_iovar_request_unsafe(FAR struct bcmf_dev_s *priv,
uint32_t ifidx, bool set, char *name,
uint8_t *data, uint32_t *len)
{
return bcmf_cdc_control_request_unsafe(priv, ifidx, set,
set ? WLC_SET_VAR : WLC_GET_VAR, name,
data, len);
}
int bcmf_cdc_ioctl(FAR struct bcmf_dev_s *priv,
uint32_t ifidx, bool set, uint32_t cmd,
uint8_t *data, uint32_t *len)
{
return bcmf_cdc_control_request(priv, ifidx, set, cmd, NULL, data, len);
}
int bcmf_cdc_process_control_frame(FAR struct bcmf_dev_s *priv,
struct bcmf_frame_s *frame)
{
unsigned int data_size;
struct bcmf_cdc_header *cdc_header;
/* Check frame */
data_size = frame->len - (unsigned int)(frame->data - frame->base);
if (data_size < sizeof(struct bcmf_cdc_header))
{
wlerr("Control frame too small\n");
return -EINVAL;
}
cdc_header = (struct bcmf_cdc_header *)frame->data;
if (data_size < cdc_header->len ||
data_size < sizeof(struct bcmf_cdc_header) + cdc_header->len)
{
wlerr("Invalid control frame size\n");
return -EINVAL;
}
// TODO check interface ?
if (cdc_header->flags >> BCMF_CONTROL_REQID_SHIFT == priv->control_reqid)
{
/* Expected frame received, send it back to user */
priv->control_status = cdc_header->status;
if (priv->control_rxdata)
{
if (priv->control_rxdata_len > cdc_header->len)
{
wlerr("Not enough data %d %d\n",
priv->control_rxdata_len, cdc_header->len);
priv->control_rxdata_len = cdc_header->len;
}
memcpy(priv->control_rxdata, (uint8_t *)&cdc_header[1],
priv->control_rxdata_len);
}
sem_post(&priv->control_timeout);
return OK;
}
wlinfo("Got unexpected control frame\n");
return -EINVAL;
}
+69
View File
@@ -0,0 +1,69 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_cdc.h
*
* Copyright (C) 2017 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE80211_BCMF_CDC_H
#define __DRIVERS_WIRELESS_IEEE80211_BCMF_CDC_H
#include "bcmf_driver.h"
#include <stdbool.h>
#include <stdint.h>
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/* Send safe cdc request */
int bcmf_cdc_iovar_request(FAR struct bcmf_dev_s *priv, uint32_t ifidx,
bool set, char *name, uint8_t *data, uint32_t *len);
int bcmf_cdc_ioctl(FAR struct bcmf_dev_s *priv, uint32_t ifidx, bool set,
uint32_t cmd, uint8_t *data, uint32_t *len);
/* Send cdc request without locking control_mutex */
int bcmf_cdc_iovar_request_unsafe(FAR struct bcmf_dev_s *priv, uint32_t ifidx,
bool set, char *name, uint8_t *data, uint32_t *len);
/* Callback used by bus layer to notify cdc response frame is available */
int bcmf_cdc_process_control_frame(FAR struct bcmf_dev_s *priv,
struct bcmf_frame_s *frame);
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_CDC_H */
@@ -0,0 +1,76 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_chip_43362.c
*
* Copyright (C) 2017 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>
#define WRAPPER_REGISTER_OFFSET 0x100000
extern const char bcm43362_nvram_image[];
extern const unsigned int bcm43362_nvram_image_len;
extern const uint8_t bcm43362_firmware_image[];
extern const unsigned int bcm43362_firmware_image_len;
const struct bcmf_sdio_chip bcmf_43362_config_sdio =
{
/* General chip stats */
.ram_size = 0x3C000,
/* 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 *)bcm43362_firmware_image,
.firmware_image_size = (unsigned int *)&bcm43362_firmware_image_len,
.nvram_image = (uint8_t *)bcm43362_nvram_image,
.nvram_image_size = (unsigned int *)&bcm43362_nvram_image_len
};
+401
View File
@@ -0,0 +1,401 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_core.c
*
* Copyright (C) 2017 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/arch.h>
#include "bcmf_core.h"
#include "bcmf_sdio.h"
#include "bcmf_sdio_regs.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* 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 */
#define BCMA_RESET_ST 0x0804
#define BCMA_IOCTL_CLK 0x0001
#define BCMA_IOCTL_FGC 0x0002
#define BCMA_IOCTL_CORE_BITS 0x3FFC
#define BCMA_IOCTL_PME_EN 0x4000
#define BCMA_IOCTL_BIST_EN 0x8000
#define BCMA_IOST_CORE_BITS 0x0FFF
#define BCMA_IOST_DMA64 0x1000
#define BCMA_IOST_GATED_CLK 0x2000
#define BCMA_IOST_BIST_ERROR 0x4000
#define BCMA_IOST_BIST_DONE 0x8000
#define BCMA_RESET_CTL_RESET 0x0001
/* Transfer size properties */
#define BCMF_UPLOAD_TRANSFER_SIZE (64 * 256)
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
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);
static int bcmf_upload_nvram(FAR struct bcmf_sdio_dev_s *sbus);
/****************************************************************************
* Private Functions
****************************************************************************/
int bcmf_core_set_backplane_window(FAR struct bcmf_sdio_dev_s *sbus,
uint32_t address)
{
int ret;
int i;
address &= ~SBSDIO_SB_OFT_ADDR_MASK;
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;
if (addr_part != cur_addr_part)
{
/* Update current backplane base address */
ret = bcmf_write_reg(sbus, 1, SBSDIO_FUNC1_SBADDRLOW+i-1,
addr_part);
if (ret != OK)
{
return ret;
}
sbus->backplane_current_addr &= ~(0xff << (8*i));
sbus->backplane_current_addr |= addr_part << (8*i);
}
}
return OK;
}
int bcmf_upload_binary(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
uint8_t *buf, unsigned int len)
{
unsigned int size;
while (len > 0)
{
/* Set the backplane window to include the start address */
int ret = bcmf_core_set_backplane_window(sbus, address);
if (ret != OK)
{
return ret;
}
if (len > BCMF_UPLOAD_TRANSFER_SIZE)
{
size = BCMF_UPLOAD_TRANSFER_SIZE;
}
else
{
size = len;
}
/* Transfer firmware data */
ret = bcmf_transfer_bytes(sbus, true, 1,
address & SBSDIO_SB_OFT_ADDR_MASK, buf, size);
if (ret != OK)
{
wlerr("transfer failed %d %x %d\n", ret, address, size);
return ret;
}
len -= size;
address += size;
buf += size;
}
return OK;
}
int bcmf_upload_nvram(FAR struct bcmf_sdio_dev_s *sbus)
{
int ret;
uint32_t nvram_sz;
uint32_t token;
/* Round up the size of the image */
nvram_sz = (*sbus->chip->nvram_image_size + 63) & (-64);
wlinfo("nvram size is %d %d bytes\n", nvram_sz,
*sbus->chip->nvram_image_size);
/* Write image */
ret = bcmf_upload_binary(sbus, sbus->chip->ram_size - 4 - nvram_sz,
sbus->chip->nvram_image,
*sbus->chip->nvram_image_size);
if (ret != OK)
{
return ret;
}
/* Generate length token */
token = nvram_sz / 4;
token = (~token << 16) | (token & 0x0000FFFF);
/* Write the length token to the last word */
ret = bcmf_write_sbreg(sbus, sbus->chip->ram_size - 4, (uint8_t *)&token, 4);
if (ret != OK)
{
return ret;
}
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bcmf_read_sbreg
****************************************************************************/
int bcmf_read_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
uint8_t *reg, unsigned int len)
{
int ret = bcmf_core_set_backplane_window(sbus, address);
if (ret != OK)
{
return ret;
}
return bcmf_transfer_bytes(sbus, false, 1,
address & SBSDIO_SB_OFT_ADDR_MASK, reg, len);
}
/****************************************************************************
* Name: bcmf_write_sbreg
****************************************************************************/
int bcmf_write_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
uint8_t *reg, unsigned int len)
{
int ret = bcmf_core_set_backplane_window(sbus, address);
if (ret != OK)
{
return ret;
}
return bcmf_transfer_bytes(sbus, true, 1, address & SBSDIO_SB_OFT_ADDR_MASK,
reg, len);
}
/****************************************************************************
* Name: bcmf_core_upload_firmware
****************************************************************************/
int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus)
{
int ret;
wlinfo("upload firmware\n");
/* 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);
up_mdelay(50);
/* Flash chip firmware */
wlinfo("firmware size is %d bytes\n", *sbus->chip->firmware_image_size);
ret = bcmf_upload_binary(sbus, 0, sbus->chip->firmware_image,
*sbus->chip->firmware_image_size);
if (ret != OK)
{
wlerr("Failed to upload firmware\n");
return ret;
}
/* Flash NVRAM configuration file */
wlinfo("upload nvram configuration\n");
ret = bcmf_upload_nvram(sbus);
if (ret != OK)
{
wlerr("Failed to upload nvram\n");
return ret;
}
/* Firmware upload done, restart ARMCM3 core */
up_mdelay(10);
bcmf_core_reset(sbus, WLAN_ARMCM3_CORE_ID);
/* Check ARMCM3 core is running */
up_mdelay(10);
if (!bcmf_core_isup(sbus, WLAN_ARMCM3_CORE_ID))
{
wlerr("Cannot start ARMCM3 core\n");
return -ETIMEDOUT;
}
return OK;
}
bool bcmf_core_isup(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core)
{
uint32_t value = 0;
if (core >= MAX_CORE_ID)
{
wlerr("Invalid core id %d\n", core);
return false;
}
uint32_t base = sbus->chip->core_base[core];
bcmf_read_sbregw(sbus, 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);
return (value & BCMA_RESET_CTL_RESET) == 0;
}
void bcmf_core_disable(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core)
{
uint8_t value;
if (core >= MAX_CORE_ID)
{
wlerr("Invalid core id %d\n", core);
return;
}
uint32_t base = sbus->chip->core_base[core];
/* Check if core is already in reset state */
bcmf_read_sbregb(sbus, base + BCMA_RESET_CTL, &value);
if ((value & BCMA_RESET_CTL_RESET) != 0)
{
/* Core already disabled */
return;
}
/* Ensure no backplane operation is pending */
up_mdelay(10);
/* Set core in reset state */
bcmf_write_sbregb(sbus, base + BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
up_udelay(1);
/* Write 0 to the IO control and read it back */
bcmf_write_sbregb(sbus, base + BCMA_IOCTL, 0);
bcmf_read_sbregb(sbus, base + BCMA_IOCTL, &value);
up_udelay(10);
}
void bcmf_core_reset(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core)
{
uint32_t value;
if (core >= MAX_CORE_ID)
{
wlerr("Invalid core id %d\n", core);
return;
}
uint32_t base = sbus->chip->core_base[core];
/* Put core in reset state */
bcmf_core_disable(sbus, core);
/* Run initialization sequence */
bcmf_write_sbregb(sbus, base + BCMA_IOCTL, BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value);
bcmf_write_sbregb(sbus, base + BCMA_RESET_CTL, 0);
bcmf_read_sbregw(sbus, base + BCMA_RESET_CTL, &value);
up_udelay(1);
bcmf_write_sbregb(sbus, base + BCMA_IOCTL, BCMA_IOCTL_CLK);
bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value);
up_udelay(1);
}
+82
View File
@@ -0,0 +1,82 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_core.h
*
* Copyright (C) 2017 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.
*
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE80211_BCMF_CORE_H
#define __DRIVERS_WIRELESS_IEEE80211_BCMF_CORE_H
#include <stdint.h>
#include <stdbool.h>
#include "bcmf_sdio.h"
int bcmf_read_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
uint8_t *reg, unsigned int len);
int bcmf_write_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
uint8_t *reg, unsigned int len);
bool bcmf_core_isup(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core);
void bcmf_core_disable(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core);
void bcmf_core_reset(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core);
int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus);
static inline int bcmf_read_sbregb(FAR struct bcmf_sdio_dev_s *sbus,
uint32_t address, uint8_t *reg)
{
return bcmf_read_sbreg(sbus, address, reg, 1);
}
static inline int bcmf_read_sbregw(FAR struct bcmf_sdio_dev_s *sbus,
uint32_t address, uint32_t *reg)
{
return bcmf_read_sbreg(sbus, address, (uint8_t *)reg, 4);
}
static inline int bcmf_write_sbregb(FAR struct bcmf_sdio_dev_s *sbus,
uint32_t address, uint8_t reg)
{
return bcmf_write_sbreg(sbus, address, &reg, 1);
}
static inline int bcmf_write_sbregw(FAR struct bcmf_sdio_dev_s *sbus,
uint32_t address, uint32_t reg)
{
return bcmf_write_sbreg(sbus, address, (uint8_t *)&reg, 4);
}
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_CORE_H */
File diff suppressed because it is too large Load Diff
+153
View File
@@ -0,0 +1,153 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_driver.h
*
* Copyright (C) 2017 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.
*
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE80211_BCMF_DRIVER_H
#define __DRIVERS_WIRELESS_IEEE80211_BCMF_DRIVER_H
#include <stdbool.h>
#include <stdint.h>
#include <semaphore.h>
#include <nuttx/net/netdev.h>
#include <net/if.h>
#include <nuttx/wdog.h>
#include <nuttx/wqueue.h>
#include "bcmf_ioctl.h"
struct bcmf_dev_s;
struct bcmf_frame_s;
#include "bcmf_bdc.h"
struct bcmf_bus_dev_s;
/* Chip interfaces */
#define CHIP_STA_INTERFACE 0
#define CHIP_AP_INTERFACE 1
#define CHIP_P2P_INTERFACE 2
/* This structure contains the unique state of the Broadcom FullMAC driver */
struct bcmf_dev_s
{
FAR struct bcmf_bus_dev_s *bus; /* Bus interface structure */
bool bc_bifup; /* true:ifup false:ifdown */
WDOG_ID bc_txpoll; /* TX poll timer */
struct work_s bc_irqwork; /* For deferring interrupt work to the work queue */
struct work_s bc_pollwork; /* For deferring poll work to the work queue */
/* This holds the information visible to the NuttX network */
struct net_driver_s bc_dev; /* Network interface structure */
struct bcmf_frame_s *cur_tx_frame; /* Frame used to interface network layer */
/* Event registration array */
event_handler_t event_handlers[BCMF_EVENT_COUNT];
// FIXME use mutex instead of semaphore
sem_t control_mutex; /* Cannot handle multiple control requests */
sem_t control_timeout; /* Semaphore to wait for control frame rsp */
uint16_t control_reqid; /* Current control request id */
uint16_t control_rxdata_len; /* Received control frame out buffer length */
uint8_t *control_rxdata; /* Received control frame out buffer */
uint32_t control_status; /* Last received frame status */
/* AP Scan state machine.
* During scan, control_mutex is locked to prevent control requests */
int scan_status; /* Current scan status */
WDOG_ID scan_timeout; /* Scan timeout timer */
sem_t auth_signal; /* Authentication notification signal */
int auth_status; /* Authentication status */
};
/* Default bus interface structure */
struct bcmf_bus_dev_s
{
void (*stop)(FAR struct bcmf_dev_s *priv);
int (*txframe)(FAR struct bcmf_dev_s *priv, struct bcmf_frame_s *frame,
bool control);
struct bcmf_frame_s *(*rxframe)(FAR struct bcmf_dev_s *priv);
/* Frame buffer allocation primitives
* len - requested payload length
* control - true if control frame else false
* block - true to block until free frame is available
*/
struct bcmf_frame_s *(*allocate_frame)(FAR struct bcmf_dev_s *priv,
unsigned int len, bool block,
bool control);
void (*free_frame)(FAR struct bcmf_dev_s *priv, struct bcmf_frame_s *frame);
};
/* bcmf frame definition */
struct bcmf_frame_s
{
uint8_t *base; /* Frame base buffer used by low level layer (SDIO) */
uint8_t *data; /* Payload data (Control, data and event messages) */
uint16_t len; /* Frame buffer size */
};
/* IOCTLs network interface implementation */
int bcmf_wl_set_mac_address(FAR struct bcmf_dev_s *priv, struct ifreq *req);
int bcmf_wl_enable(FAR struct bcmf_dev_s *priv, bool enable);
/* IOCTLs AP scan interface implementation */
int bcmf_wl_start_scan(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
int bcmf_wl_get_scan_results(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
/* IOCTLs authentication interface implementation */
int bcmf_wl_set_auth_param(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
int bcmf_wl_set_encode_ext(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
int bcmf_wl_set_mode(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
int bcmf_wl_set_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_DRIVER_H */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+47
View File
@@ -0,0 +1,47 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_netdev.h
*
* Copyright (C) 2017 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.
*
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE80211_BCMF_NETDEV_H
#define __DRIVERS_WIRELESS_IEEE80211_BCMF_NETDEV_H
#include "bcmf_driver.h"
int bcmf_netdev_register(FAR struct bcmf_dev_s *priv);
void bcmf_netdev_notify_rx(FAR struct bcmf_dev_s *priv);
void bcmf_netdev_notify_tx_done(FAR struct bcmf_dev_s *priv);
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_NETDEV_H */
File diff suppressed because it is too large Load Diff
+147
View File
@@ -0,0 +1,147 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_sdio.h
*
* Copyright (C) 2017 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE80211_BCMF_SDIO_H
#define __DRIVERS_WIRELESS_IEEE80211_BCMF_SDIO_H
#include "bcmf_driver.h"
#include <stdint.h>
#include <stdbool.h>
#include <queue.h>
#include <semaphore.h>
#include <nuttx/sdio.h>
#include "bcmf_sdio_core.h"
#define HEADER_SIZE 0x12 /* Default sdpcm + bdc header size */
// TODO move to Kconfig
#define BCMF_PKT_POOL_SIZE 4 /* Frame pool size */
/****************************************************************************
* Public Types
****************************************************************************/
/* sdio chip configuration structure */
struct bcmf_sdio_chip
{
uint32_t ram_size;
uint32_t core_base[MAX_CORE_ID];
uint8_t *firmware_image;
unsigned int *firmware_image_size;
uint8_t *nvram_image;
unsigned int *nvram_image_size;
};
/* sdio bus structure extension */
struct bcmf_sdio_dev_s
{
struct bcmf_bus_dev_s bus; /* Default bcmf bus structure */
FAR struct sdio_dev_s *sdio_dev; /* The SDIO device bound to this instance */
int minor; /* Device minor number */
struct bcmf_sdio_chip *chip; /* Chip specific configuration */
volatile bool ready; /* Current device status */
bool sleeping; /* Current sleep status */
int thread_id; /* Processing thread id */
sem_t thread_signal; /* Semaphore for processing thread event */
struct wdog_s *waitdog; /* Processing thread waitdog */
uint32_t backplane_current_addr; /* Current function 1 backplane base addr */
volatile bool irq_pending; /* True if interrupt is pending */
uint32_t intstatus; /* Copy of device current interrupt status */
uint8_t max_seq; /* Maximum transmit sequence allowed */
uint8_t tx_seq; /* Transmit sequence number (next) */
uint8_t rx_seq; /* Receive sequence number (expected) */
sem_t queue_mutex; /* Lock for TX/RX/free queues */
dq_queue_t free_queue; /* Queue of available frames */
dq_queue_t tx_queue; /* Queue of frames to tramsmit */
dq_queue_t 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;
dq_entry_t list_entry;
uint8_t data[HEADER_SIZE + MAX_NET_DEV_MTU +
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);
/* 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 struct bcmf_sdio_dev_s *sbus, bool write,
uint8_t function, uint32_t address,
uint8_t *buf, unsigned int len);
int bcmf_read_reg(FAR struct bcmf_sdio_dev_s *sbus, uint8_t function,
uint32_t address, uint8_t *reg);
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_BCMF_SDIO_H */
+226
View File
@@ -0,0 +1,226 @@
/****************************************************************************
* Copyright (c) 2011 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE80211_BCMF_SDIO_CORE_H
#define __DRIVERS_WIRELESS_IEEE80211_BCMF_SDIO_CORE_H
#include <stdint.h>
#ifndef PAD
#define _PADLINE(line) pad ## line
#define _XSTR(line) _PADLINE(line)
#define PAD _XSTR(__LINE__)
#endif
/* SDIO device ID */
#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_4335_4339 0x4335
#define SDIO_DEVICE_ID_BROADCOM_43362 43362
/* Core reg address translation.
* Both macro's returns a 32 bits byte address on the backplane bus.
*/
#define CORE_CC_REG(base, field) \
(base + offsetof(struct chipcregs, field))
#define CORE_BUS_REG(base, field) \
(base + offsetof(struct sdpcmd_regs, field))
#define CORE_SB(base, field) \
(base + offsetof(struct sbconfig, field))
#define BRCMF_MAX_CORENUM 6
#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */
/* Target state register description */
#define SSB_TMSLOW_RESET 0x00000001 /* Reset */
#define SSB_TMSLOW_REJECT 0x00000002 /* Reject (Standard Backplane) */
#define SSB_TMSLOW_REJECT_23 0x00000004 /* Reject (Backplane rev 2.3) */
#define SSB_TMSLOW_CLOCK 0x00010000 /* Clock Enable */
#define SSB_TMSLOW_FGC 0x00020000 /* Force Gated Clocks On */
#define SSB_TMSLOW_PE 0x40000000 /* Power Management Enable */
#define SSB_TMSLOW_BE 0x80000000 /* BIST Enable */
#define I_HMB_SW_MASK ( (uint32_t) 0x000000F0 )
#define I_HMB_FRAME_IND ( 1<<6 )
/* tosbmailbox bits corresponding to intstatus bits */
#define SMB_NAK (1 << 0) /* Frame NAK */
#define SMB_INT_ACK (1 << 1) /* Host Interrupt ACK */
#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,
WLAN_ARMCM3_CORE_ID,
SOCSRAM_CORE_ID,
MAX_CORE_ID
};
struct chip_core_info
{
uint16_t id;
uint16_t rev;
uint32_t base;
uint32_t wrapbase;
uint32_t caps;
uint32_t cib;
};
struct sbconfig
{
uint8_t PAD[0xf00];
uint32_t PAD[2];
uint32_t sbipsflag; /* initiator port ocp slave flag */
uint32_t PAD[3];
uint32_t sbtpsflag; /* target port ocp slave flag */
uint32_t PAD[11];
uint32_t sbtmerrloga; /* (sonics >= 2.3) */
uint32_t PAD;
uint32_t sbtmerrlog; /* (sonics >= 2.3) */
uint32_t PAD[3];
uint32_t sbadmatch3; /* address match3 */
uint32_t PAD;
uint32_t sbadmatch2; /* address match2 */
uint32_t PAD;
uint32_t sbadmatch1; /* address match1 */
uint32_t PAD[7];
uint32_t sbimstate; /* initiator agent state */
uint32_t sbintvec; /* interrupt mask */
uint32_t sbtmstatelow; /* target state */
uint32_t sbtmstatehigh; /* target state */
uint32_t sbbwa0; /* bandwidth allocation table0 */
uint32_t PAD;
uint32_t sbimconfiglow; /* initiator configuration */
uint32_t sbimconfighigh; /* initiator configuration */
uint32_t sbadmatch0; /* address match0 */
uint32_t PAD;
uint32_t sbtmconfiglow; /* target configuration */
uint32_t sbtmconfighigh; /* target configuration */
uint32_t sbbconfig; /* broadcast configuration */
uint32_t PAD;
uint32_t sbbstate; /* broadcast state */
uint32_t PAD[3];
uint32_t sbactcnfg; /* activate configuration */
uint32_t PAD[3];
uint32_t sbflagst; /* current sbflags */
uint32_t PAD[3];
uint32_t sbidlow; /* identification */
uint32_t sbidhigh; /* identification */
};
/* sdio core registers */
struct sdpcmd_regs
{
uint32_t corecontrol; /* 0x00, rev8 */
uint32_t corestatus; /* rev8 */
uint32_t PAD[1];
uint32_t biststatus; /* rev8 */
/* PCMCIA access */
uint16_t pcmciamesportaladdr; /* 0x010, rev8 */
uint16_t PAD[1];
uint16_t pcmciamesportalmask; /* rev8 */
uint16_t PAD[1];
uint16_t pcmciawrframebc; /* rev8 */
uint16_t PAD[1];
uint16_t pcmciaunderflowtimer; /* rev8 */
uint16_t PAD[1];
/* interrupt */
uint32_t intstatus; /* 0x020, rev8 */
uint32_t hostintmask; /* rev8 */
uint32_t intmask; /* rev8 */
uint32_t sbintstatus; /* rev8 */
uint32_t sbintmask; /* rev8 */
uint32_t funcintmask; /* rev4 */
uint32_t PAD[2];
uint32_t tosbmailbox; /* 0x040, rev8 */
uint32_t tohostmailbox; /* rev8 */
uint32_t tosbmailboxdata; /* rev8 */
uint32_t tohostmailboxdata; /* rev8 */
/* synchronized access to registers in SDIO clock domain */
uint32_t sdioaccess; /* 0x050, rev8 */
uint32_t PAD[3];
/* PCMCIA frame control */
uint8_t pcmciaframectrl; /* 0x060, rev8 */
uint8_t PAD[3];
uint8_t pcmciawatermark; /* rev8 */
uint8_t PAD[155];
/* interrupt batching control */
uint32_t intrcvlazy; /* 0x100, rev8 */
uint32_t PAD[3];
/* counters */
uint32_t cmd52rd; /* 0x110, rev8 */
uint32_t cmd52wr; /* rev8 */
uint32_t cmd53rd; /* rev8 */
uint32_t cmd53wr; /* rev8 */
uint32_t abort; /* rev8 */
uint32_t datacrcerror; /* rev8 */
uint32_t rdoutofsync; /* rev8 */
uint32_t wroutofsync; /* rev8 */
uint32_t writebusy; /* rev8 */
uint32_t readwait; /* rev8 */
uint32_t readterm; /* rev8 */
uint32_t writeterm; /* rev8 */
uint32_t PAD[40];
uint32_t clockctlstatus; /* rev8 */
uint32_t PAD[7];
uint32_t PAD[128]; /* DMA engines */
/* SDIO/PCMCIA CIS region */
char cis[512]; /* 0x400-0x5ff, rev6 */
/* PCMCIA function control registers */
char pcmciafcr[256]; /* 0x600-6ff, rev6 */
uint16_t PAD[55];
/* PCMCIA backplane access */
uint16_t backplanecsr; /* 0x76E, rev6 */
uint16_t backplaneaddr0; /* rev6 */
uint16_t backplaneaddr1; /* rev6 */
uint16_t backplaneaddr2; /* rev6 */
uint16_t backplaneaddr3; /* rev6 */
uint16_t backplanedata0; /* rev6 */
uint16_t backplanedata1; /* rev6 */
uint16_t backplanedata2; /* rev6 */
uint16_t backplanedata3; /* rev6 */
uint16_t PAD[31];
/* sprom "size" & "blank" info */
uint16_t spromstatus; /* 0x7BE, rev2 */
uint32_t PAD[464];
uint16_t PAD[0x80];
};
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_SDIO_CORE_H */
+248
View File
@@ -0,0 +1,248 @@
/****************************************************************************
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE80211_BCMF_SDIO_REGS_H
#define __DRIVERS_WIRELESS_IEEE80211_BCMF_SDIO_REGS_H
#define SDIO_FUNC_0 0
#define SDIO_FUNC_1 1
#define SDIO_FUNC_2 2
#define SDIOD_FBR_SIZE 0x100
/* io_en */
#define SDIO_FUNC_ENABLE_1 0x02
#define SDIO_FUNC_ENABLE_2 0x04
/* io_rdys */
#define SDIO_FUNC_READY_1 0x02
#define SDIO_FUNC_READY_2 0x04
/* intr_status */
#define INTR_STATUS_FUNC1 0x2
#define INTR_STATUS_FUNC2 0x4
/* Maximum number of I/O funcs */
#define SDIOD_MAX_IOFUNCS 7
/* mask of register map */
#define REG_F0_REG_MASK 0x7FF
#define REG_F1_MISC_MASK 0x1FFFF
/* as of sdiod rev 0, supports 3 functions */
#define SBSDIO_NUM_FUNCTION 3
/* function 0 vendor specific CCCR registers */
#define SDIO_CCCR_BRCM_CARDCAP 0xf0
#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02
#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04
#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08
#define SDIO_CCCR_BRCM_CARDCTRL 0xf1
#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02
#define SDIO_CCCR_BRCM_SEPINT 0xf2
#define SDIO_SEPINT_MASK 0x01
#define SDIO_SEPINT_OE 0x02
#define SDIO_SEPINT_ACT_HI 0x04
/* function 1 miscellaneous registers */
/* sprom command and status */
#define SBSDIO_SPROM_CS 0x10000
/* sprom info register */
#define SBSDIO_SPROM_INFO 0x10001
/* sprom indirect access data byte 0 */
#define SBSDIO_SPROM_DATA_LOW 0x10002
/* sprom indirect access data byte 1 */
#define SBSDIO_SPROM_DATA_HIGH 0x10003
/* sprom indirect access addr byte 0 */
#define SBSDIO_SPROM_ADDR_LOW 0x10004
/* sprom indirect access addr byte 0 */
#define SBSDIO_SPROM_ADDR_HIGH 0x10005
/* xtal_pu (gpio) output */
#define SBSDIO_CHIP_CTRL_DATA 0x10006
/* xtal_pu (gpio) enable */
#define SBSDIO_CHIP_CTRL_EN 0x10007
/* rev < 7, watermark for sdio device */
#define SBSDIO_WATERMARK 0x10008
/* control busy signal generation */
#define SBSDIO_DEVICE_CTL 0x10009
/* SB Address Window Low (b15) */
#define SBSDIO_FUNC1_SBADDRLOW 0x1000A
/* SB Address Window Mid (b23:b16) */
#define SBSDIO_FUNC1_SBADDRMID 0x1000B
/* SB Address Window High (b31:b24) */
#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C
/* Frame Control (frame term/abort) */
#define SBSDIO_FUNC1_FRAMECTRL 0x1000D
/* Read Frame Terminate */
#define SFC_RF_TERM (1 << 0)
/* Write Frame Terminate */
#define SFC_WF_TERM (1 << 1)
/* CRC error for write out of sync */
#define SFC_CRC4WOOS (1 << 2)
/* Abort all in-progress frames */
#define SFC_ABORTALL (1 << 3)
/* ChipClockCSR (ALP/HT ctl/status) */
#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E
/* Force ALP request to backplane */
#define SBSDIO_FORCE_ALP 0x01
/* Force HT request to backplane */
#define SBSDIO_FORCE_HT 0x02
/* Force ILP request to backplane */
#define SBSDIO_FORCE_ILP 0x04
/* Make ALP ready (power up xtal) */
#define SBSDIO_ALP_AVAIL_REQ 0x08
/* Make HT ready (power up PLL) */
#define SBSDIO_HT_AVAIL_REQ 0x10
/* Squelch clock requests from HW */
#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20
/* Status: ALP is ready */
#define SBSDIO_ALP_AVAIL 0x40
/* Status: HT is ready */
#define SBSDIO_HT_AVAIL 0x80
/* SdioPullUp (on cmd, d0-d2) */
#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F
/* Write Frame Byte Count Low */
#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019
/* Write Frame Byte Count High */
#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A
/* Read Frame Byte Count Low */
#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B
/* Read Frame Byte Count High */
#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C
/* MesBusyCtl (rev 11) */
#define SBSDIO_FUNC1_MESBUSYCTRL 0x1001D
/* Sdio Core Rev 12 */
#define SBSDIO_FUNC1_WAKEUPCTRL 0x1001E
#define SBSDIO_FUNC1_WCTRL_ALPWAIT_MASK 0x1
#define SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT 0
#define SBSDIO_FUNC1_WCTRL_HTWAIT_MASK 0x2
#define SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT 1
#define SBSDIO_FUNC1_SLEEPCSR 0x1001F
#define SBSDIO_FUNC1_SLEEPCSR_KSO_MASK 0x1
#define SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT 0
#define SBSDIO_FUNC1_SLEEPCSR_KSO_EN 1
#define SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK 0x2
#define SBSDIO_FUNC1_SLEEPCSR_DEVON_SHIFT 1
#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS)
#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
#define SBSDIO_CLKAV(regval, alponly) \
(SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval)))
#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */
#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001F /* f1 misc register end */
/* function 1 OCP space */
/* sb offset addr is <= 15 bits, 32k */
#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF
#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000
/* with b15, maps to 32-bit SB access */
#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000
/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */
#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */
#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */
/* Address bits from SBADDR regs */
#define SBSDIO_SBWINDOW_MASK 0xffff8000
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_SDIO_REGS_H */
+464
View File
@@ -0,0 +1,464 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_sdpcm.c
*
* Copyright (C) 2017 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.
*
****************************************************************************/
/****************************************************************************
* 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 <queue.h>
#include <semaphore.h>
#include "bcmf_sdio.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 SDPCM_CONTROL_CHANNEL 0 /* Control frame id */
#define SDPCM_EVENT_CHANNEL 1 /* Asynchronous event frame id */
#define SDPCM_DATA_CHANNEL 2 /* Data frame id */
/****************************************************************************
* Private Types
****************************************************************************/
struct __attribute__((packed)) bcmf_sdpcm_header {
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;
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int bcmf_sdpcm_rxfail(FAR struct bcmf_sdio_dev_s *sbus, bool retry);
static int bcmf_sdpcm_process_header(FAR struct bcmf_sdio_dev_s *sbus,
struct bcmf_sdpcm_header *header);
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
int bcmf_sdpcm_rxfail(FAR struct bcmf_sdio_dev_s *sbus, bool retry)
{
/* issue abort command for F2 through F0 */
bcmf_write_reg(sbus, 0, SDIO_CCCR_IOABORT, 2);
bcmf_write_reg(sbus, 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(sbus,
CORE_BUS_REG(sbus->chip->core_base[SDIOD_CORE_ID],
tosbmailbox), SMB_NAK);
}
return 0;
}
int bcmf_sdpcm_process_header(FAR struct bcmf_sdio_dev_s *sbus,
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);
return -ENXIO;
}
/* Update tx credits */
sbus->max_seq = header->credit;
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv)
{
int ret;
uint16_t len, checksum;
struct bcmf_sdpcm_header *header;
struct bcmf_sdio_frame *sframe;
FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
/* Request free frame buffer */
sframe = bcmf_sdio_allocate_frame(priv, false, false);
if (sframe == NULL)
{
wlinfo("fail alloc\n");
return -EAGAIN;
}
header = (struct bcmf_sdpcm_header *)sframe->data;
/* Read header */
ret = bcmf_transfer_bytes(sbus, false, 2, 0, (uint8_t *)header, 4);
if (ret != OK)
{
wlinfo("failread size\n");
ret = -EIO;
goto exit_abort;
}
len = header->size;
checksum = header->checksum;
/* All zero means no more to read */
if (!(len | checksum))
{
ret = -ENODATA;
goto exit_free_frame;
}
if (((~len & 0xffff) ^ checksum) || len < sizeof(struct bcmf_sdpcm_header))
{
wlerr("Invalid header checksum or len %x %x\n", len, checksum);
ret = -EINVAL;
goto exit_abort;
}
if (len > sframe->header.len)
{
wlerr("Frame is too large, cancel %d %d\n", len, sframe->header.len);
ret = -ENOMEM;
goto exit_abort;
}
/* Read remaining frame data */
ret = bcmf_transfer_bytes(sbus, false, 2, 0, (uint8_t *)header + 4, len - 4);
if (ret != OK)
{
ret = -EIO;
goto exit_abort;
}
// wlinfo("Receive frame %p %d\n", sframe, len);
// bcmf_hexdump((uint8_t *)header, header->size, (unsigned int)header);
/* Process and validate header */
ret = bcmf_sdpcm_process_header(sbus, header);
if (ret != OK)
{
wlerr("Error while processing header %d\n", ret);
ret = -EINVAL;
goto exit_free_frame;
}
/* Update frame structure */
sframe->header.len = header->size;
sframe->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);
goto exit_free_frame;
case SDPCM_EVENT_CHANNEL:
if (header->data_offset == header->size)
{
/* Empty event, ignore */
ret = OK;
}
else
{
ret = bcmf_bdc_process_event_frame(priv, &sframe->header);
}
goto exit_free_frame;
case SDPCM_DATA_CHANNEL:
/* Queue frame and notify network layer frame is available */
if (sem_wait(&sbus->queue_mutex))
{
PANIC();
}
bcmf_dqueue_push(&sbus->rx_queue, &sframe->list_entry);
sem_post(&sbus->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:
bcmf_sdpcm_rxfail(sbus, false);
exit_free_frame:
bcmf_sdio_free_frame(priv, sframe);
return ret;
}
int bcmf_sdpcm_sendframe(FAR struct bcmf_dev_s *priv)
{
int ret;
bool is_txframe;
dq_entry_t *entry;
struct bcmf_sdio_frame *sframe;
struct bcmf_sdpcm_header *header;
FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
if (sbus->tx_queue.tail == NULL)
{
/* No more frames to send */
return -ENODATA;
}
if (sbus->tx_seq == sbus->max_seq)
{
// TODO handle this case
wlerr("No credit to send frame\n");
return -EAGAIN;
}
if (sem_wait(&sbus->queue_mutex))
{
PANIC();
}
entry = sbus->tx_queue.tail;
sframe = container_of(entry, struct bcmf_sdio_frame, list_entry);
header = (struct bcmf_sdpcm_header *)sframe->header.base;
/* Set frame sequence id */
header->sequence = sbus->tx_seq++;
// wlinfo("Send frame %p\n", sframe);
// bcmf_hexdump(sframe->header.base, sframe->header.len,
// (unsigned long)sframe->header.base);
ret = bcmf_transfer_bytes(sbus, true, 2, 0, sframe->header.base,
sframe->header.len);
if (ret != OK)
{
wlinfo("fail send frame %d\n", ret);
ret = -EIO;
goto exit_abort;
// TODO handle retry count and remove frame from queue + abort TX
}
/* Frame sent, remove it from queue */
bcmf_dqueue_pop_tail(&sbus->tx_queue);
sem_post(&sbus->queue_mutex);
is_txframe = sframe->tx;
/* Free frame buffer */
bcmf_sdio_free_frame(priv, sframe);
if (is_txframe)
{
/* Notify upper layer at least one TX buffer is available */
bcmf_netdev_notify_tx_done(priv);
}
return OK;
exit_abort:
// bcmf_sdpcm_txfail(sbus, false);
sem_post(&sbus->queue_mutex);
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;
struct bcmf_sdpcm_header *header = (struct bcmf_sdpcm_header *)sframe->data;
/* Prepare sw header */
memset(header, 0, sizeof(struct bcmf_sdpcm_header));
header->size = frame->len;
header->checksum = ~header->size;
header->data_offset = (uint8_t)(frame->data - frame->base);
if (control)
{
header->channel = SDPCM_CONTROL_CHANNEL;
}
else
{
header->channel = SDPCM_DATA_CHANNEL;
}
/* Add frame in tx queue */
if (sem_wait(&sbus->queue_mutex))
{
PANIC();
}
bcmf_dqueue_push(&sbus->tx_queue, &sframe->list_entry);
sem_post(&sbus->queue_mutex);
/* Notify bcmf thread tx frame is ready */
sem_post(&sbus->thread_signal);
return OK;
}
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;
unsigned int header_len = sizeof(struct bcmf_sdpcm_header);
if (!control)
{
header_len += 2; /* Data frames need alignment padding */
}
if (len + header_len > MAX_NET_DEV_MTU + HEADER_SIZE ||
len > len + header_len)
{
wlerr("Invalid size %d\n", len);
return NULL;
}
/* Allocate a frame for RX in case of control frame */
sframe = bcmf_sdio_allocate_frame(priv, block, !control);
if (sframe == NULL)
{
return NULL;
}
sframe->header.len = header_len + len;
sframe->header.data += header_len;
return &sframe->header;
}
void bcmf_sdpcm_free_frame(FAR struct bcmf_dev_s *priv,
struct bcmf_frame_s *frame)
{
return bcmf_sdio_free_frame(priv, (struct bcmf_sdio_frame *)frame);
}
struct bcmf_frame_s *bcmf_sdpcm_get_rx_frame(FAR struct bcmf_dev_s *priv)
{
dq_entry_t *entry;
struct bcmf_sdio_frame *sframe;
FAR struct bcmf_sdio_dev_s *sbus = (FAR struct bcmf_sdio_dev_s *)priv->bus;
if (sem_wait(&sbus->queue_mutex))
{
PANIC();
}
entry = bcmf_dqueue_pop_tail(&sbus->rx_queue);
sem_post(&sbus->queue_mutex);
if (entry == NULL)
{
return NULL;
}
sframe = container_of(entry, struct bcmf_sdio_frame, list_entry);
return &sframe->header;
}
+64
View File
@@ -0,0 +1,64 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_sdpcm.h
*
* Copyright (C) 2017 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.
*
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE80211_BCMF_SDPCM_H
#define __DRIVERS_WIRELESS_IEEE80211_BCMF_SDPCM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "bcmf_driver.h"
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
int bcmf_sdpcm_readframe(FAR struct bcmf_dev_s *priv);
int bcmf_sdpcm_sendframe(FAR struct bcmf_dev_s *priv);
int bcmf_sdpcm_queue_frame(FAR struct bcmf_dev_s *priv,
struct bcmf_frame_s *frame, bool control);
void bcmf_sdpcm_free_frame(FAR struct bcmf_dev_s *priv, struct bcmf_frame_s *frame);
struct bcmf_frame_s *bcmf_sdpcm_alloc_frame(FAR struct bcmf_dev_s *priv,
unsigned int len, bool block,
bool control);
struct bcmf_frame_s *bcmf_sdpcm_get_rx_frame(FAR struct bcmf_dev_s *priv);
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_SDPCM_H */
+167
View File
@@ -0,0 +1,167 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_utils.c
*
* Copyright (C) 2017 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <semaphore.h>
#include <debug.h>
#include <stdio.h>
#include <queue.h>
#include "bcmf_utils.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define LINE_LEN 16
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bcmf_hexdump
****************************************************************************/
void bcmf_hexdump(uint8_t *data, unsigned int len, unsigned long offset)
{
unsigned int i;
unsigned int char_count = 0;
char char_line[20];
char hex_line[64];
for (i = 0; i < len; i++)
{
if (char_count >= LINE_LEN)
{
/* Flush line */
wlinfo("%08x: %s%s\n", offset+i-char_count, hex_line, char_line);
char_count = 0;
}
sprintf(hex_line+3*char_count, "%02x ", data[i]);
sprintf(char_line+char_count, "%c",
data[i] < 0x20 || data[i] >= 0x7f? '.': data[i]);
char_count ++;
}
if (char_count > 0)
{
/* Flush last line */
memset(hex_line+3*char_count, ' ', 3*(LINE_LEN-char_count));
hex_line[3*LINE_LEN] = 0;
wlinfo("%08x: %s%s\n", offset+i-char_count, hex_line, char_line);
}
}
/****************************************************************************
* Name: bcmf_sem_wait
****************************************************************************/
int bcmf_sem_wait(sem_t *sem, unsigned int timeout_ms)
{
struct timespec abstime;
unsigned int timeout_sec;
/* Get the current time */
(void)clock_gettime(CLOCK_REALTIME, &abstime);
timeout_sec = timeout_ms / 1000;
abstime.tv_sec += timeout_sec;
abstime.tv_nsec += 1000 * 1000 * (timeout_ms % 1000);
if (abstime.tv_nsec >= 1000 * 1000 * 1000)
{
abstime.tv_sec++;
abstime.tv_nsec -= 1000 * 1000 * 1000;
}
return sem_timedwait(sem, &abstime);
}
void bcmf_dqueue_push(dq_queue_t *queue, dq_entry_t *entry)
{
if (queue->head == NULL)
{
/* List is empty */
queue->tail = entry;
entry->flink = entry;
entry->blink = entry;
}
else
{
/* Insert entry at list head */
entry->flink = queue->head;
entry->blink = queue->tail;
queue->head->blink = entry;
}
queue->head = entry;
}
dq_entry_t *bcmf_dqueue_pop_tail(dq_queue_t *queue)
{
dq_entry_t *entry = queue->tail;
if (queue->head == queue->tail)
{
/* List is empty */
queue->head = NULL;
queue->tail = NULL;
}
else
{
/* Pop from queue tail */
queue->tail = entry->blink;
entry->blink->flink = queue->head;
}
return entry;
}
+73
View File
@@ -0,0 +1,73 @@
/****************************************************************************
* drivers/wireless/ieee80211/bcmf_utils.h
*
* Copyright (C) 2017 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.
*
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE80211_BCMF_UTILS_H
#define __DRIVERS_WIRELESS_IEEE80211_BCMF_UTILS_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include <semaphore.h>
#include <queue.h>
#define container_of(ptr, type, member) \
(type *)((uint8_t *)(ptr) - offsetof(type, member))
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
void bcmf_hexdump(uint8_t *data, unsigned int len, unsigned long offset);
int bcmf_sem_wait(sem_t *sem, unsigned int timeout_ms);
dq_entry_t *bcmf_dqueue_pop_tail(dq_queue_t *queue);
void bcmf_dqueue_push(dq_queue_t *queue, dq_entry_t *entry);
static inline uint16_t bcmf_getle16(uint16_t *val)
{
uint8_t *valb = (uint8_t *)val;
return (uint16_t)valb[0] << 8 | (uint16_t)valb[1];
}
static inline uint16_t bcmf_getle32(uint32_t *val)
{
uint16_t *valw = (uint16_t *)val;
return (uint32_t)bcmf_getle16(valw) << 16 | bcmf_getle16(valw + 1);
}
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_UTILS_H */
+393
View File
@@ -0,0 +1,393 @@
#include <nuttx/wireless/ieee80211/mmc_sdio.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/arch.h>
#define SDIO_CMD53_TIMEOUT_MS 100
#define SDIO_IDLE_DELAY_MS 50
struct __attribute__((packed)) sdio_cmd52
{
uint32_t write_data : 8;
uint32_t reserved_8 : 1;
uint32_t register_address : 17;
uint32_t reserved_26 : 1;
uint32_t raw_flag : 1;
uint32_t function_number : 3;
uint32_t rw_flag : 1;
};
struct __attribute__((packed)) sdio_cmd53
{
uint32_t byte_block_count : 9;
uint32_t register_address : 17;
uint32_t op_code : 1;
uint32_t block_mode : 1;
uint32_t function_number : 3;
uint32_t rw_flag : 1;
};
struct __attribute__((packed)) sdio_resp_R5
{
uint32_t data : 8;
struct
{
uint32_t out_of_range : 1;
uint32_t function_number : 1;
uint32_t rfu : 1;
uint32_t error : 1;
uint32_t io_current_state : 2;
uint32_t illegal_command : 1;
uint32_t com_crc_error : 1;
} flags;
uint32_t reserved_16 : 16;
};
union sdio_cmd5x
{
uint32_t value;
struct sdio_cmd52 cmd52;
struct sdio_cmd53 cmd53;
};
int sdio_sendcmdpoll(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
{
int ret;
/* Send the command */
ret = SDIO_SENDCMD(dev, cmd, arg);
if (ret == OK)
{
/* Then poll-wait until the response is available */
ret = SDIO_WAITRESPONSE(dev, cmd);
if (ret != OK)
{
wlerr("ERROR: Wait for response to cmd: %08x failed: %d\n",
cmd, ret);
}
}
return ret;
}
int sdio_io_rw_direct(FAR struct sdio_dev_s *dev, bool write,
uint8_t function, uint32_t address,
uint8_t inb, uint8_t *outb)
{
union sdio_cmd5x arg;
struct sdio_resp_R5 resp;
int ret;
/* Setup CMD52 argument */
arg.value = 0;
if (write)
{
arg.cmd52.write_data = inb;
}
else
{
arg.cmd52.write_data = 0;
}
arg.cmd52.register_address = address & 0x1ffff;
arg.cmd52.raw_flag = (write && outb);
arg.cmd52.function_number = function & 7;
arg.cmd52.rw_flag = write;
/* Send CMD52 command */
sdio_sendcmdpoll(dev, SDIO_ACMD52, arg.value);
ret = SDIO_RECVR5(dev, SDIO_ACMD52, (uint32_t *)&resp);
if (ret != OK)
{
wlerr("ERROR: SDIO_RECVR5 failed %d\n", ret);
return ret;
}
/* Check for errors */
if (resp.flags.error)
{
return -EIO;
}
if (resp.flags.function_number || resp.flags.out_of_range)
{
return -EINVAL;
}
/* Write output byte */
if (outb)
{
*outb = resp.data & 0xff;
}
return OK;
}
int sdio_io_rw_extended(FAR struct sdio_dev_s *dev, bool write,
uint8_t function, uint32_t address,
bool inc_addr, uint8_t *buf,
unsigned int blocklen, unsigned int nblocks)
{
union sdio_cmd5x arg;
struct sdio_resp_R5 resp;
int ret;
sdio_eventset_t wkupevent;
/* Setup CMD53 argument */
arg.value = 0;
arg.cmd53.register_address = address & 0x1ffff;
arg.cmd53.op_code = inc_addr;
arg.cmd53.function_number = function & 7;
arg.cmd53.rw_flag = write;
if (nblocks == 0 && blocklen < 512)
{
/* Use byte mode */
// wlinfo("byte mode\n");
arg.cmd53.block_mode = 0;
arg.cmd53.byte_block_count = blocklen;
nblocks = 1;
}
else
{
/* Use block mode */
arg.cmd53.block_mode = 1;
arg.cmd53.byte_block_count = nblocks;
}
/* Send CMD53 command */
SDIO_BLOCKSETUP(dev, blocklen, nblocks);
SDIO_WAITENABLE(dev,
SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR);
if (write)
{
// wlinfo("prep write %d %d\n", blocklen, nblocks);
sdio_sendcmdpoll(dev, SDIO_ACMD53, (uint32_t)arg.value);
ret = SDIO_RECVR5(dev, SDIO_ACMD53, (uint32_t *)&resp);
SDIO_DMASENDSETUP(dev, buf, blocklen * nblocks);
wkupevent = SDIO_EVENTWAIT(dev, SDIO_CMD53_TIMEOUT_MS);
}
else
{
// wlinfo("prep read %d\n", blocklen * nblocks);
SDIO_DMARECVSETUP(dev, buf, blocklen * nblocks);
SDIO_SENDCMD(dev, SDIO_ACMD53, (uint32_t)arg.value);
wkupevent = SDIO_EVENTWAIT(dev, SDIO_CMD53_TIMEOUT_MS);
ret = SDIO_RECVR5(dev, SDIO_ACMD53, (uint32_t *)&resp);
}
if (ret != OK)
{
wlerr("ERROR: SDIO_RECVR5 failed %d\n", ret);
return ret;
}
/* Check for errors */
if (wkupevent & SDIOWAIT_TIMEOUT)
{
wlerr("timeout\n");
return -ETIMEDOUT;
}
if (resp.flags.error || (wkupevent & SDIOWAIT_ERROR))
{
wlerr("error 1\n");
return -EIO;
}
if (resp.flags.function_number || resp.flags.out_of_range)
{
wlerr("error 2\n");
return -EINVAL;
}
return OK;
}
int sdio_set_wide_bus(struct sdio_dev_s *dev)
{
int ret;
uint8_t value;
/* Read Bus Interface Control register */
ret = sdio_io_rw_direct(dev, false, 0, SDIO_CCCR_BUS_IF, 0, &value);
if (ret != OK)
{
return ret;
}
/* Set 4 bits bus width setting */
value &= ~SDIO_CCCR_BUS_IF_WIDTH_MASK;
value |= SDIO_CCCR_BUS_IF_4_BITS;
ret = sdio_io_rw_direct(dev, true, 0, SDIO_CCCR_BUS_IF, value, NULL);
if (ret != OK)
{
return ret;
}
SDIO_WIDEBUS(dev, true);
return OK;
}
int sdio_probe(FAR struct sdio_dev_s *dev)
{
int ret;
uint32_t data = 0;
/* Set device state from reset to idle */
sdio_sendcmdpoll(dev, MMCSD_CMD0, 0);
up_mdelay(SDIO_IDLE_DELAY_MS);
/* Device is SDIO card compatible so we can send CMD5 instead of ACMD41 */
sdio_sendcmdpoll(dev, SDIO_CMD5, 0);
/* Receive R4 response */
ret = SDIO_RECVR4(dev, SDIO_CMD5, &data);
if (ret != OK)
{
return ret;
}
/* Device is in Card Identification Mode, request device RCA */
sdio_sendcmdpoll(dev, SD_CMD3, 0);
ret = SDIO_RECVR6(dev, SD_CMD3, &data);
if (ret != OK)
{
wlerr("ERROR: RCA request failed: %d\n", ret);
return ret;
}
wlinfo("rca is %x\n", data >> 16);
/* Send CMD7 with the argument == RCA in order to select the card
* and put it in Transfer State */
sdio_sendcmdpoll(dev, MMCSD_CMD7S, data & 0xffff0000);
ret = SDIO_RECVR1(dev, MMCSD_CMD7S, &data);
if (ret != OK)
{
wlerr("ERROR: card selection failed: %d\n", ret);
return ret;
}
/* Configure 4 bits bus width */
ret = sdio_set_wide_bus(dev);
if (ret != OK)
{
return ret;
}
return OK;
}
int sdio_set_blocksize(FAR struct sdio_dev_s *dev, uint8_t function,
uint16_t blocksize)
{
int ret;
ret = sdio_io_rw_direct(dev, true, 0,
(function << SDIO_FBR_SHIFT) + SDIO_CCCR_FN0_BLKSIZE_0,
blocksize & 0xff, NULL);
if (ret != OK)
{
return ret;
}
ret = sdio_io_rw_direct(dev, true, 0,
(function << SDIO_FBR_SHIFT) + SDIO_CCCR_FN0_BLKSIZE_1,
(blocksize >> 8), NULL);
if (ret != OK)
{
return ret;
}
return OK;
}
int sdio_enable_function(FAR struct sdio_dev_s *dev, uint8_t function)
{
int ret;
uint8_t value;
/* Read current I/O Enable register */
ret = sdio_io_rw_direct(dev, false, 0, SDIO_CCCR_IOEN, 0, &value);
if (ret != OK)
{
return ret;
}
ret = sdio_io_rw_direct(dev, true, 0, SDIO_CCCR_IOEN, value | (1 << function), NULL);
if (ret != OK)
{
return ret;
}
/* Wait 10ms for function to be enabled */
int loops = 10;
while (loops-- > 0)
{
up_mdelay(1);
ret = sdio_io_rw_direct(dev, false, 0, SDIO_CCCR_IOEN, 0, &value);
if (ret != OK)
{
return ret;
}
if (value & (1 << function))
{
/* Function enabled */
wlinfo("Function %d enabled\n", function);
return OK;
}
}
return -ETIMEDOUT;
}
int sdio_enable_interrupt(FAR struct sdio_dev_s *dev, uint8_t function)
{
int ret;
uint8_t value;
/* Read current Int Enable register */
ret = sdio_io_rw_direct(dev, false, 0, SDIO_CCCR_INTEN, 0, &value);
if (ret != OK)
{
return ret;
}
return sdio_io_rw_direct(dev, true, 0, SDIO_CCCR_INTEN, value | (1 << function), NULL);
}
+36 -7
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* include/fixedmath.h
*
* Copyright (C) 2008 Gregory Nutt. All rights reserved.
* Copyright (C) 2008, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,7 @@
* Included Files
****************************************************************************/
#include <nuttx/compiler.h>
#include <stdint.h>
/****************************************************************************
@@ -124,7 +125,7 @@
#define ub8toi(a) ((a) >> 8) /* Conversion to unsigned integer */
#define itob8(i) (((b8_t)(i)) << 8) /* Conversion from integer */
#define uitoub8(i) (((ub8_t)(i)) << 8) /* Conversion from unsigned integer */
#define b8tof(b) (((float)b)/256.0) /* Conversion to float */
#define b8tof(b) (((float)(b))/256.0) /* Conversion to float */
#define ftob8(f) (b8_t)(((f)*256.0)) /* Conversion from float */
#define b8trunc(a) ((a) & 0xff00) /* Truncate to integer b8 */
#define b8round(a) (((a)+0x0080) & 0xff00) /* Round to integer b8 */
@@ -138,13 +139,13 @@
#define b8addi(a,i) ((a)+itob8(i)) /* Add integer from b16 */
#define b8subb8(a,b) ((a)-(b)) /* Subtraction */
#define b8subi(a,i) ((a)-itob8(i)) /* Subtract integer from b8 */
#define b8mulb8(a,b) b16tob8((b16_t)(a)*(b16_t)(b) /* Muliplication */
#define ub8mulub8(a,b) ub16toub8((ub16_t)(a)*(ub16_t)(b) /* Muliplication */
#define b8mulb8(a,b) (b16tob8((b16_t)(a)*(b16_t)(b)) /* Muliplication */
#define ub8mulub8(a,b) (ub16toub8((ub16_t)(a)*(ub16_t)(b)) /* Muliplication */
#define b8muli(a,i) ((a)*(i)) /* Simple multiplication by integer */
#define b8sqr(a) b8mulb8(a,a) /* Square */
#define ub8sqr(a) ub8mulub8(a,a) /* Square */
#define b8divb8(a,b) b8tob16(a)/(b16_t)(b) /* Division */
#define ub8divub8(a,b) ub8toub16(a)/(ub16_t)(b) /* Division */
#define b8divb8(a,b) (b8tob16(a)/(b16_t)(b)) /* Division */
#define ub8divub8(a,b) (ub8toub16(a)/(ub16_t)(b)) /* Division */
#define b8divi(a,i) ((a)/(i)) /* Simple division by integer */
#define b8idiv(i,j) (((i)<<8)/j) /* Division of integer, b8 result */
@@ -156,7 +157,7 @@
#define ub16toi(a) ((a) >> 16) /* Conversion to unsgined integer */
#define itob16(i) (((b16_t)(i)) << 16) /* Conversion from integer */
#define uitoub16(i) (((ub16_t)(i)) << 16) /* Conversion from unsigned integer */
#define b16tof(b) (((float)b)/65536.0) /* Conversion to float */
#define b16tof(b) (((float)(b))/65536.0) /* Conversion to float */
#define ftob16(f) (b16_t)(((f)*65536.0)) /* Conversion from float */
#define b16trunc(a) ((a) & 0xffff0000) /* Truncate to integer */
#define b16round(a) (((a)+0x00008000) & 0xffff0000)
@@ -189,6 +190,27 @@
# define b16divb16(a,b) (b16_t)(b16tob32(a)/(b32_t)(b))
# define ub16divub16(a,b) (ub16_t)(ub16toub32(a)/(ub32_t)(b))
/* Square root operators */
# define ub16sqrtub16(a) ub32sqrtub16(ub16toub32(a))
#else
# define ub16sqrtub16(a) ub8toub16(ub16sqrtub8(a))
#endif
/* 64-bit values with 32 bits of precision ********************************/
#ifdef CONFIG_HAVE_LONG_LONG
/* Conversions */
#define b32toi(a) ((a) >> 32) /* Conversion to integer */
#define itob32(i) (((b32_t)(i)) << 32) /* Conversion from integer */
#define uitoub32(i) (((ub32_t)(i)) << 32) /* Conversion from unsigned integer */
#define b32tod(b) (((double)(b))/((long long)1 << 32)) /* Conversion to double */
#define dtob32(f) (b32_t)(((f)*(double)((long long)1 << 32))) /* Conversion from double */
#define b32trunc(a) ((a) & 0xffffffff00000000) /* Truncate to integer */
#define b32round(a) (((a)+0x0000000080000000) & 0xffffffff00000000)
#define b32frac(a) ((a) & 0x00000000ffffffff) /* Take fractional part */
#endif
/****************************************************************************
@@ -240,6 +262,13 @@ b16_t b16sin(b16_t rad);
b16_t b16cos(b16_t rad);
b16_t b16atan2(b16_t y, b16_t x);
/* Square root operators */
#ifdef CONFIG_HAVE_LONG_LONG
ub16_t ub32sqrtub16(ub32_t a);
#endif
ub8_t ub16sqrtub8(ub16_t a);
#undef EXTERN
#if defined(__cplusplus)
}
+38
View File
@@ -328,6 +328,44 @@
#define SDIO_ACMD52 (SDIO_ACMDIDX52|MMCSD_R5_RESPONSE |MMCSD_NODATAXFR)
#define SDIO_ACMD53 (SDIO_ACMDIDX53|MMCSD_R5_RESPONSE |MMCSD_NODATAXFR)
/* SDIO Card Common Control Registers definitions
* see https://www.sdcard.org/developers/overview/sdio/
* sdio_spec/Simplified_SDIO_Card_Spec.pdf */
#define SDIO_CCCR_REV 0x00 /* CCCR/SDIO Revision */
#define SDIO_CCCR_SD_SPEC_REV 0x01 /* SD Specification Revision */
#define SDIO_CCCR_IOEN 0x02 /* I/O Enable */
#define SDIO_CCCR_IORDY 0x03 /* I/O Ready */
#define SDIO_CCCR_INTEN 0x04 /* Int Enable */
#define SDIO_CCCR_INTPEND 0x05 /* Int Pending */
#define SDIO_CCCR_IOABORT 0x06 /* I/O Abort */
#define SDIO_CCCR_BUS_IF 0x07 /* Bus Interface Control */
#define SDIO_CCCR_CARD_CAP 0x08 /* Card Capabilitiy */
#define SDIO_CCCR_CCP 0x09 /* Common CIS Pointer */
#define SDIO_CCCR_BUS_SUSP 0x0C /* Bus Suspend */
#define SDIO_CCCR_FUNCSEL 0x0D /* Function Select */
#define SDIO_CCCR_EXEC_FLAGS 0x0E /* Exec Flags */
#define SDIO_CCCR_RDY_FLAGS 0x0F /* Ready Flags */
#define SDIO_CCCR_FN0_BLKSIZE_0 0x10 /* FN0 Block Size */
#define SDIO_CCCR_FN0_BLKSIZE_1 0x11 /* FN0 Block Size */
#define SDIO_CCCR_POWER 0x12 /* Power Control */
#define SDIO_CCCR_HIGHSPEED 0x13 /* High-Speed */
#define SDIO_CCCR_RFU 0x14 /* Reserved for future use */
#define SDIO_CCCR_VENDOR 0xF0 /* Reserved for Vendors */
#define SDIO_CCCR_BUS_IF_WIDTH_MASK 0x03 /* Bus width configuration */
#define SDIO_CCCR_BUS_IF_1_BIT 0x01 /* 1 bit bus width setting */
#define SDIO_CCCR_BUS_IF_4_BITS 0x02 /* 4 bits bus width setting */
#define SDIO_FBR_SHIFT 8 /* FBR bit shift */
#define SDIO_FN1_BR_BASE (1 << SDIO_FBR_SHIFT) /* Func 1 registers base */
#define SDIO_FN2_BR_BASE (2 << SDIO_FBR_SHIFT) /* Func 2 registers base */
#define SDIO_FN3_BR_BASE (3 << SDIO_FBR_SHIFT) /* Func 3 registers base */
#define SDIO_FN4_BR_BASE (4 << SDIO_FBR_SHIFT) /* Func 4 registers base */
#define SDIO_FN5_BR_BASE (5 << SDIO_FBR_SHIFT) /* Func 5 registers base */
#define SDIO_FN6_BR_BASE (6 << SDIO_FBR_SHIFT) /* Func 6 registers base */
#define SDIO_FN7_BR_BASE (7 << SDIO_FBR_SHIFT) /* Func 7 registers base */
/****************************************************************************
* Name: SDIO_LOCK
*
@@ -41,6 +41,7 @@
****************************************************************************/
#include <stdbool.h>
#include <nuttx/irq.h>
#ifdef __cplusplus
#define EXTERN extern "C"
@@ -102,6 +103,22 @@ void bcmf_board_power(int minor, bool power);
void bcmf_board_reset(int minor, bool reset);
/************************************************************************************
* Function: bcmf_board_setup_oob_irq
*
* Description:
* Board specific function called from Broadcom FullMAC driver
* that must be implemented to use WLAN chip interrupt signal
*
* Parameters:
* minor - zero based minor device number which is unique
* 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);
#undef EXTERN
#ifdef __cplusplus
}
@@ -0,0 +1,85 @@
/****************************************************************************
* include/nuttx/wireless/ieee80211/bcmf_netdev.h
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_WIRELESS_IEEE80211_BCMF_NETDEV_H
#define __INCLUDE_NUTTX_WIRELESS_IEEE80211_BCMF_NETDEV_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/mmcsd.h>
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Types
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: bcmf_netdev_register
*
* Description:
* Initialize the Broadcom 43362 controller and driver
*
* Parameters:
* intf - In the case where there are multiple EMACs, this value
* identifies which EMAC is to be initialized.
*
* Returned Value:
* OK on success; Negated errno on failure.
*
* Assumptions:
*
****************************************************************************/
int bcmf_netdev_register(int intf);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __INCLUDE_NUTTX_WIRELESS_IEEE80211_BCMF_NETDEV_H */
@@ -0,0 +1,28 @@
#ifndef caca
#define caca
#include <stdint.h>
#include <nuttx/sdio.h>
int sdio_probe(FAR struct sdio_dev_s *dev);
int sdio_set_wide_bus(struct sdio_dev_s *dev);
int sdio_set_blocksize(FAR struct sdio_dev_s *dev, uint8_t function,
uint16_t blocksize);
int sdio_enable_function(FAR struct sdio_dev_s *dev, uint8_t function);
int sdio_enable_interrupt(FAR struct sdio_dev_s *dev, uint8_t function);
int sdio_sendcmdpoll(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg);
int sdio_io_rw_direct(FAR struct sdio_dev_s *dev, bool write,
uint8_t function, uint32_t address,
uint8_t inb, uint8_t* outb);
int sdio_io_rw_extended(FAR struct sdio_dev_s *dev, bool write,
uint8_t function, uint32_t address,
bool inc_addr, uint8_t *buf,
unsigned int blocklen, unsigned int nblocks);
#endif
+74 -1
View File
@@ -195,7 +195,33 @@
/* Scan-related */
#define IW_SCAN_MAX_DATA 4096 /* Maximum size of returned data */
/* Scanning request flags */
#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */
#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */
#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */
#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */
#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */
#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */
#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */
#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */
#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */
/* struct iw_scan_req scan_type */
#define IW_SCAN_TYPE_ACTIVE 0
#define IW_SCAN_TYPE_PASSIVE 1
/* Maximum size of returned data */
#define IW_SCAN_MAX_DATA 4096 /* In bytes */
/* Scan capability flags - in (struct iw_range *)->scan_capa */
#define IW_SCAN_CAPA_NONE 0x00
#define IW_SCAN_CAPA_ESSID 0x01
#define IW_SCAN_CAPA_BSSID 0x02
#define IW_SCAN_CAPA_CHANNEL 0x04
#define IW_SCAN_CAPA_MODE 0x08
#define IW_SCAN_CAPA_RATE 0x10
#define IW_SCAN_CAPA_TYPE 0x20
#define IW_SCAN_CAPA_TIME 0x40
#define IW_SCAN_MAX_DATA 4096 /* Maximum size of returned data */
/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
@@ -398,5 +424,52 @@ struct iw_encode_ext
uint8_t key[0];
};
/*
* Optional data for scan request
*
* Note: these optional parameters are controlling parameters for the
* scanning behavior, these do not apply to getting scan results
* (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
* provide a merged results with all BSSes even if the previous scan
* request limited scanning to a subset, e.g., by specifying an SSID.
* Especially, scan results are required to include an entry for the
* current BSS if the driver is in Managed mode and associated with an AP.
*/
struct iw_scan_req
{
uint8_t scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
uint8_t essid_len;
uint8_t num_channels; /* num entries in channel_list;
* 0 = scan all allowed channels */
uint8_t flags; /* reserved as padding; use zero, this may
* be used in the future for adding flags
* to request different scan behavior */
struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
* individual address of a specific BSS */
/*
* Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
* the current ESSID. This allows scan requests for specific ESSID
* without having to change the current ESSID and potentially breaking
* the current association.
*/
uint8_t essid[IW_ESSID_MAX_SIZE];
/*
* Optional parameters for changing the default scanning behavior.
* These are based on the MLME-SCAN.request from IEEE Std 802.11.
* TU is 1.024 ms. If these are set to 0, driver is expected to use
* reasonable default values. min_channel_time defines the time that
* will be used to wait for the first reply on each channel. If no
* replies are received, next channel will be scanned after this. If
* replies are received, total time waited on the channel is defined by
* max_channel_time.
*/
uint32_t min_channel_time; /* in TU */
uint32_t max_channel_time; /* in TU */
struct iw_freq channel_list[IW_MAX_FREQUENCIES];
};
#endif /* CONFIG_DRIVERS_WIRELESS */
#endif /* __INCLUDE_NUTTX_WIRELESS_WIRELESS_H */
+1
View File
@@ -36,6 +36,7 @@
# Add the fixed precision math C files to the build
CSRCS += lib_fixedmath.c lib_b16sin.c lib_b16cos.c lib_b16atan2.c
CSRCS += lib_ubsqrt.c
# Add the fixed precision math directory to the build
+136
View File
@@ -0,0 +1,136 @@
/****************************************************************************
* libc/fixedmath/lib_ubsqrt.c
*
* Copyright (C) 2014,2017 Jussi Kivilinna <jussi.kivilinna@haltian.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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <fixedmath.h>
/****************************************************************************
* Public Functions
****************************************************************************/
#ifdef CONFIG_HAVE_LONG_LONG
/****************************************************************************
* Name: ub32sqrtub16
*
* Description:
* ub32sqrtub16 calculates square root for 'a'
*
****************************************************************************/
ub16_t ub32sqrtub16(ub32_t a)
{
uint64_t n = a;
uint64_t xk = n;
/* Direct conversion of ub32_t to uint64_t is same operation as multiplying
* 'a' by 2^32, therefore n = a * 2^32.
*/
if (xk == UINT64_MAX)
{
/* Avoid 'xk + n / xk' overflow on first iteration. */
xk = 1ULL << 63;
}
do
{
uint64_t xk1 = (xk + n / xk) >> 1;
if (xk1 >= xk)
{
break;
}
xk = xk1;
}
while (1);
/* 'xk' now holds 'sqrt(n)' => 'sqrt(a * 2^32)' => 'sqrt(a) * 2^16', thus
* 'xk' holds square root of 'a' in ub16_t format.
*/
return (ub16_t)xk;
}
#endif
/****************************************************************************
* Name: ub16sqrtub8
*
* Description:
* ub16sqrtub8 calculates square root for 'a'
*
****************************************************************************/
ub8_t ub16sqrtub8(ub16_t a)
{
uint32_t n = a;
uint32_t xk = n;
/* Direct conversion of ub16_t to uint32_t is same operation as multiplying
* 'a' by 2^16, therefore n = a * 2^16.
*/
if (xk == UINT32_MAX)
{
/* Avoid 'xk + n / xk' overflow on first iteration. */
xk = 1U << 31;
}
do
{
uint32_t xk1 = (xk + n / xk) >> 1;
if (xk1 >= xk)
{
break;
}
xk = xk1;
}
while (1);
/* 'xk' now holds 'sqrt(n)' => 'sqrt(a * 2^16)' => 'sqrt(a) * 2^8', thus
* 'xk' holds square root of 'a' in ub8_t format.
*/
return (ub8_t)xk;
}

Some files were not shown because too many files have changed in this diff Show More