mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 00:14:22 +08:00
Merge branch 'master' into l432kc
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
************************************************************************************/
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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, ®, 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 *)®, 4);
|
||||
}
|
||||
|
||||
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCMF_CORE_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user