2017-03-26 17:42:53 +02:00
|
|
|
/****************************************************************************
|
2021-03-08 22:39:04 +01:00
|
|
|
* drivers/wireless/ieee80211/bcm43xxx/bcmf_core.c
|
2017-03-26 17:42:53 +02:00
|
|
|
*
|
2021-05-27 11:12:43 +02:00
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
|
|
* this work for additional information regarding copyright ownership. The
|
|
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
|
|
* "License"); you may not use this file except in compliance with the
|
|
|
|
* License. You may obtain a copy of the License at
|
2017-03-26 17:42:53 +02:00
|
|
|
*
|
2021-05-27 11:12:43 +02:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2017-03-26 17:42:53 +02:00
|
|
|
*
|
2021-05-27 11:12:43 +02:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
* under the License.
|
2017-03-26 17:42:53 +02:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Included Files
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <nuttx/compiler.h>
|
|
|
|
|
2022-06-14 06:05:39 +02:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
#include <assert.h>
|
2017-03-26 17:42:53 +02:00
|
|
|
#include <debug.h>
|
|
|
|
#include <errno.h>
|
2018-10-07 18:03:39 +02:00
|
|
|
#include <fcntl.h>
|
2020-12-04 14:24:07 +01:00
|
|
|
#include <inttypes.h>
|
2019-07-29 00:20:33 +02:00
|
|
|
#include <string.h>
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
#include <nuttx/arch.h>
|
2018-10-07 23:00:13 +02:00
|
|
|
#include <nuttx/kmalloc.h>
|
2022-06-16 14:16:32 +02:00
|
|
|
#include <nuttx/signal.h>
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
#include "bcmf_core.h"
|
|
|
|
#include "bcmf_sdio.h"
|
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
#include "bcmf_sdio_regs.h"
|
|
|
|
|
2017-03-26 17:42:53 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Pre-processor Definitions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/* Agent registers (common for every core) */
|
2018-04-26 16:10:23 +02:00
|
|
|
|
2017-03-26 17:42:53 +02:00
|
|
|
#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
|
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
/* ARM CR4 core specific control flag bits */
|
|
|
|
|
|
|
|
#define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
|
|
|
|
|
2017-03-26 17:42:53 +02:00
|
|
|
#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
|
|
|
|
|
2018-04-26 16:10:23 +02:00
|
|
|
/* SOCSRAM core registers */
|
|
|
|
|
|
|
|
#define SOCSRAM_BANKX_INDEX ((uint32_t) (0x18004000 + 0x10) )
|
|
|
|
#define SOCSRAM_BANKX_PDA ((uint32_t) (0x18004000 + 0x44) )
|
|
|
|
|
2017-03-26 17:42:53 +02:00
|
|
|
/* Transfer size properties */
|
2018-04-26 16:10:23 +02:00
|
|
|
|
|
|
|
#define BCMF_UPLOAD_TRANSFER_SIZE (64 * 256)
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2019-07-29 00:20:33 +02:00
|
|
|
/* Define this to validate uploaded materials */
|
|
|
|
|
|
|
|
/* #define DBG_VALIDATE_UPLOAD */
|
|
|
|
|
2017-03-26 17:42:53 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Private Types
|
|
|
|
****************************************************************************/
|
|
|
|
|
2019-07-29 00:20:33 +02:00
|
|
|
#ifdef DBG_VALIDATE_UPLOAD
|
|
|
|
static uint8_t compare_buffer[BCMF_UPLOAD_TRANSFER_SIZE];
|
|
|
|
#endif
|
|
|
|
|
2017-03-26 17:42:53 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Private Function Prototypes
|
|
|
|
****************************************************************************/
|
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
static int bcmf_core_set_backplane_window(FAR struct bcmf_sdio_dev_s *sbus,
|
2017-03-26 17:42:53 +02:00
|
|
|
uint32_t address);
|
2017-04-23 22:17:43 +02:00
|
|
|
static int bcmf_upload_binary(FAR struct bcmf_sdio_dev_s *sbusv,
|
2018-04-26 16:10:23 +02:00
|
|
|
uint32_t address, uint8_t *buf,
|
|
|
|
unsigned int len);
|
2017-04-23 22:17:43 +02:00
|
|
|
static int bcmf_upload_nvram(FAR struct bcmf_sdio_dev_s *sbus);
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
int bcmf_core_set_backplane_window(FAR struct bcmf_sdio_dev_s *sbus,
|
|
|
|
uint32_t address)
|
2017-03-26 17:42:53 +02:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
address &= ~SBSDIO_SB_OFT_ADDR_MASK;
|
|
|
|
|
|
|
|
for (i = 1; i < 4; i++)
|
|
|
|
{
|
|
|
|
uint8_t addr_part = (address >> (8*i)) & 0xff;
|
2017-04-23 22:17:43 +02:00
|
|
|
uint8_t cur_addr_part = (sbus->backplane_current_addr >> (8*i)) & 0xff;
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
if (addr_part != cur_addr_part)
|
|
|
|
{
|
|
|
|
/* Update current backplane base address */
|
|
|
|
|
2019-07-29 00:20:33 +02:00
|
|
|
ret = bcmf_write_reg(sbus, 1, SBSDIO_FUNC1_SBADDRLOW + i - 1,
|
2017-03-26 17:42:53 +02:00
|
|
|
addr_part);
|
|
|
|
|
|
|
|
if (ret != OK)
|
|
|
|
{
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
sbus->backplane_current_addr &= ~(0xff << (8*i));
|
|
|
|
sbus->backplane_current_addr |= addr_part << (8*i);
|
2017-03-26 17:42:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
int bcmf_upload_binary(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
|
2017-03-26 17:42:53 +02:00
|
|
|
uint8_t *buf, unsigned int len)
|
|
|
|
{
|
|
|
|
unsigned int size;
|
|
|
|
|
2019-07-29 00:20:33 +02:00
|
|
|
#ifdef DBG_VALIDATE_UPLOAD
|
|
|
|
uint32_t validate_address = address;
|
|
|
|
uint8_t *validate_buffer = buf;
|
|
|
|
unsigned int validate_len = len;
|
|
|
|
#endif
|
|
|
|
|
2017-03-26 17:42:53 +02:00
|
|
|
while (len > 0)
|
|
|
|
{
|
|
|
|
/* Set the backplane window to include the start address */
|
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
int ret = bcmf_core_set_backplane_window(sbus, address);
|
2017-03-26 17:42:53 +02:00
|
|
|
if (ret != OK)
|
|
|
|
{
|
2020-12-04 14:24:07 +01:00
|
|
|
wlerr("Backplane setting failed at %08" PRIx32 "\n", address);
|
2017-03-26 17:42:53 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len > BCMF_UPLOAD_TRANSFER_SIZE)
|
|
|
|
{
|
|
|
|
size = BCMF_UPLOAD_TRANSFER_SIZE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
size = len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Transfer firmware data */
|
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
ret = bcmf_transfer_bytes(sbus, true, 1,
|
2020-12-04 14:22:17 +01:00
|
|
|
address & SBSDIO_SB_OFT_ADDR_MASK, buf,
|
|
|
|
size);
|
2017-03-26 17:42:53 +02:00
|
|
|
if (ret != OK)
|
|
|
|
{
|
2020-12-04 14:24:07 +01:00
|
|
|
wlerr("transfer failed %d %" PRIx32 " %d\n", ret, address, size);
|
2019-07-29 00:20:33 +02:00
|
|
|
return ret;
|
2017-03-26 17:42:53 +02:00
|
|
|
}
|
|
|
|
|
2019-07-29 00:20:33 +02:00
|
|
|
len -= size;
|
|
|
|
address += size;
|
|
|
|
buf += size;
|
2017-03-26 17:42:53 +02:00
|
|
|
}
|
2018-04-26 16:10:23 +02:00
|
|
|
|
2019-07-29 00:20:33 +02:00
|
|
|
#ifdef DBG_VALIDATE_UPLOAD
|
|
|
|
wlwarn("Validating....\n");
|
|
|
|
while (validate_len > 0)
|
|
|
|
{
|
|
|
|
/* Set the backplane window to include the start address */
|
|
|
|
|
|
|
|
int ret = bcmf_core_set_backplane_window(sbus, validate_address);
|
|
|
|
if (ret != OK)
|
|
|
|
{
|
|
|
|
wlerr("Backplane setting failed at %08x\n", validate_address);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (validate_len > BCMF_UPLOAD_TRANSFER_SIZE)
|
|
|
|
{
|
|
|
|
size = BCMF_UPLOAD_TRANSFER_SIZE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
size = validate_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Transfer firmware data */
|
|
|
|
|
|
|
|
ret = bcmf_transfer_bytes(sbus, false, 1,
|
|
|
|
validate_address & SBSDIO_SB_OFT_ADDR_MASK,
|
|
|
|
compare_buffer, size);
|
|
|
|
if (ret != OK)
|
|
|
|
{
|
|
|
|
wlerr("validate transfer failed %d %x %d\n", ret, validate_address,
|
|
|
|
size);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (memcmp(validate_buffer, compare_buffer, size))
|
|
|
|
{
|
|
|
|
wlerr("Match failed at address base %08x\n", validate_address);
|
|
|
|
return -EILSEQ;
|
|
|
|
}
|
|
|
|
|
|
|
|
validate_len -= size;
|
|
|
|
validate_address += size;
|
|
|
|
validate_buffer += size;
|
|
|
|
}
|
|
|
|
|
|
|
|
wlwarn("Validation passed\n");
|
|
|
|
#endif
|
|
|
|
|
2017-03-26 17:42:53 +02:00
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
2018-10-07 18:03:39 +02:00
|
|
|
#ifdef CONFIG_IEEE80211_BROADCOM_FWFILES
|
|
|
|
int bcmf_upload_file(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
|
|
|
|
FAR const char *path)
|
|
|
|
{
|
|
|
|
struct file finfo;
|
|
|
|
FAR uint8_t *buf;
|
|
|
|
size_t total_read;
|
|
|
|
ssize_t nread;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Open the file in the detached state */
|
|
|
|
|
2022-06-02 18:23:24 +02:00
|
|
|
ret = file_open(&finfo, path, O_RDONLY);
|
2019-07-29 00:20:33 +02:00
|
|
|
if (ret < 0)
|
2018-10-07 18:03:39 +02:00
|
|
|
{
|
2019-07-29 00:20:33 +02:00
|
|
|
wlerr("ERROR: Failed to open the FILE MTD file %s: %d\n", path, ret);
|
|
|
|
return ret;
|
2018-10-07 18:03:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate an I/O buffer */
|
|
|
|
|
|
|
|
buf = (FAR uint8_t *)kmm_malloc(BCMF_UPLOAD_TRANSFER_SIZE);
|
|
|
|
if (buf == NULL)
|
|
|
|
{
|
2019-07-29 00:20:33 +02:00
|
|
|
wlerr("ERROR: Failed allocate an I/O buffer\n");
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto errout_with_file;
|
2018-10-07 18:03:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Loop until the firmware has been loaded */
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
/* Set the backplane window to include the start address */
|
|
|
|
|
|
|
|
nread = file_read(&finfo, buf, BCMF_UPLOAD_TRANSFER_SIZE);
|
|
|
|
if (nread < 0)
|
|
|
|
{
|
|
|
|
ret = (int)nread;
|
|
|
|
wlerr("ERROR: Failed to read file: %d\n", ret);
|
|
|
|
goto errout_with_buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nread == 0)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
wlinfo("Read %ld bytes\n", (long)nread);
|
|
|
|
|
|
|
|
ret = bcmf_core_set_backplane_window(sbus, address);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
wlerr("ERROR: bcmf_core_set_backplane_window() failed: %d\n", ret);
|
|
|
|
goto errout_with_buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
total_read = nread;
|
|
|
|
|
|
|
|
/* Transfer firmware data */
|
|
|
|
|
|
|
|
ret = bcmf_transfer_bytes(sbus, true, 1,
|
|
|
|
address & SBSDIO_SB_OFT_ADDR_MASK, buf,
|
|
|
|
total_read);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
wlerr("ERROR: Transfer failed address=%lx total_read=%lu: %d\n",
|
|
|
|
(unsigned long)address, (unsigned long)total_read, ret);
|
|
|
|
goto errout_with_buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
address += total_read;
|
|
|
|
}
|
|
|
|
while (nread == BCMF_UPLOAD_TRANSFER_SIZE);
|
|
|
|
|
2018-10-07 23:00:13 +02:00
|
|
|
file_close(&finfo);
|
2018-10-07 18:03:39 +02:00
|
|
|
kmm_free(buf);
|
|
|
|
|
|
|
|
wlinfo("Upload complete\n");
|
|
|
|
return OK;
|
|
|
|
|
|
|
|
errout_with_buf:
|
|
|
|
kmm_free(buf);
|
|
|
|
|
|
|
|
errout_with_file:
|
2018-10-07 23:00:13 +02:00
|
|
|
file_close(&finfo);
|
2018-10-07 18:03:39 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
int bcmf_upload_nvram(FAR struct bcmf_sdio_dev_s *sbus)
|
2017-03-26 17:42:53 +02:00
|
|
|
{
|
2022-06-14 06:05:39 +02:00
|
|
|
FAR uint8_t *nvram_buf = sbus->chip->nvram_image;
|
|
|
|
uint32_t nvram_sz = *sbus->chip->nvram_image_size;
|
2017-03-26 17:42:53 +02:00
|
|
|
uint32_t token;
|
2022-06-14 06:05:39 +02:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
#ifdef CONFIG_IEEE80211_BROADCOM_FWFILES
|
|
|
|
FAR const char *nvfile = CONFIG_IEEE80211_BROADCOM_NVFILENAME;
|
|
|
|
bool skipline = false;
|
|
|
|
struct file finfo;
|
|
|
|
struct stat stat;
|
|
|
|
FAR uint8_t *buf;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (strlen(nvfile) <= 0)
|
|
|
|
{
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = file_open(&finfo, nvfile, O_RDONLY);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = file_fstat(&finfo, &stat);
|
|
|
|
if (ret < 0 || stat.st_size <= 0)
|
|
|
|
{
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Round up the ram buffer size */
|
|
|
|
|
|
|
|
stat.st_size = (stat.st_size + 63) & (~63);
|
|
|
|
|
|
|
|
buf = (FAR uint8_t *)kmm_malloc(stat.st_size);
|
|
|
|
if (buf == NULL)
|
|
|
|
{
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert text pattern:
|
|
|
|
* 1. Remove the comment line (Prefix with '#')
|
|
|
|
* 2. Convert LF('\n') to NULL'\0'
|
|
|
|
*/
|
|
|
|
|
|
|
|
ret = file_read(&finfo, buf, stat.st_size);
|
|
|
|
if (ret <= 0)
|
|
|
|
{
|
|
|
|
kmm_free(buf);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
nvram_buf = buf;
|
|
|
|
|
|
|
|
for (i = 0; i < ret; i++)
|
|
|
|
{
|
|
|
|
if (nvram_buf[i] == '\n')
|
|
|
|
{
|
|
|
|
if (buf != nvram_buf && *(buf - 1) != '\0')
|
|
|
|
{
|
|
|
|
*buf++ = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
skipline = false;
|
|
|
|
}
|
|
|
|
else if (nvram_buf[i] == '#')
|
|
|
|
{
|
|
|
|
skipline = true;
|
|
|
|
}
|
|
|
|
else if (!skipline && (nvram_buf + i) != buf)
|
|
|
|
{
|
|
|
|
*buf++ = nvram_buf[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nvram_sz = buf - nvram_buf;
|
|
|
|
|
|
|
|
out:
|
|
|
|
file_close(&finfo);
|
|
|
|
#endif
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
/* Round up the size of the image */
|
|
|
|
|
2022-06-14 06:05:39 +02:00
|
|
|
nvram_sz = (nvram_sz + 63) & (~63);
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2022-06-14 06:05:39 +02:00
|
|
|
wlinfo("nvram size is %" PRId32 " bytes\n", nvram_sz);
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
/* Write image */
|
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
ret = bcmf_upload_binary(sbus,
|
|
|
|
sbus->chip->ram_size - 4 - nvram_sz
|
|
|
|
+ sbus->chip->ram_base,
|
2022-06-14 06:05:39 +02:00
|
|
|
nvram_buf, nvram_sz);
|
|
|
|
|
|
|
|
#ifdef CONFIG_IEEE80211_BROADCOM_FWFILES
|
|
|
|
if (nvram_buf != sbus->chip->nvram_image)
|
|
|
|
{
|
|
|
|
kmm_free(nvram_buf);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-05-04 02:20:57 +02:00
|
|
|
if (ret != OK)
|
|
|
|
{
|
2017-03-26 17:42:53 +02:00
|
|
|
return ret;
|
2017-05-04 02:20:57 +02:00
|
|
|
}
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2017-05-04 02:20:57 +02:00
|
|
|
/* Generate length token */
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
token = nvram_sz / 4;
|
2019-07-29 00:20:33 +02:00
|
|
|
token = (~token << 16) | (token & 0x0000ffff);
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
/* Write the length token to the last word */
|
|
|
|
|
2022-06-14 06:05:39 +02:00
|
|
|
return bcmf_write_sbreg(sbus,
|
|
|
|
sbus->chip->ram_size - 4 + sbus->chip->ram_base,
|
|
|
|
(FAR uint8_t *)&token, 4);
|
2017-03-26 17:42:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: bcmf_read_sbreg
|
|
|
|
****************************************************************************/
|
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
int bcmf_read_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
|
2018-04-26 16:10:23 +02:00
|
|
|
FAR uint8_t *reg, unsigned int len)
|
2017-03-26 17:42:53 +02:00
|
|
|
{
|
2017-04-23 22:17:43 +02:00
|
|
|
int ret = bcmf_core_set_backplane_window(sbus, address);
|
2017-03-26 17:42:53 +02:00
|
|
|
if (ret != OK)
|
|
|
|
{
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-10-25 14:52:02 +02:00
|
|
|
address &= SBSDIO_SB_OFT_ADDR_MASK;
|
|
|
|
|
2018-04-26 16:10:23 +02:00
|
|
|
/* Map to 32-bit access if len == 4 */
|
|
|
|
|
|
|
|
if (len == 4)
|
|
|
|
{
|
|
|
|
address |= SBSDIO_SB_ACCESS_2_4B_FLAG;
|
|
|
|
}
|
|
|
|
|
2018-10-25 14:52:02 +02:00
|
|
|
return bcmf_transfer_bytes(sbus, false, 1, address, reg, len);
|
2017-03-26 17:42:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: bcmf_write_sbreg
|
|
|
|
****************************************************************************/
|
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
int bcmf_write_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address,
|
2018-04-26 16:10:23 +02:00
|
|
|
FAR uint8_t *reg, unsigned int len)
|
2017-03-26 17:42:53 +02:00
|
|
|
{
|
2017-04-23 22:17:43 +02:00
|
|
|
int ret = bcmf_core_set_backplane_window(sbus, address);
|
2017-03-26 17:42:53 +02:00
|
|
|
if (ret != OK)
|
|
|
|
{
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-10-25 14:52:02 +02:00
|
|
|
address &= SBSDIO_SB_OFT_ADDR_MASK;
|
|
|
|
|
2018-04-26 16:10:23 +02:00
|
|
|
/* Map to 32-bit access if len == 4 */
|
|
|
|
|
|
|
|
if (len == 4)
|
|
|
|
{
|
|
|
|
address |= SBSDIO_SB_ACCESS_2_4B_FLAG;
|
|
|
|
}
|
|
|
|
|
2018-10-25 14:52:02 +02:00
|
|
|
return bcmf_transfer_bytes(sbus, true, 1, address, reg, len);
|
2017-03-26 17:42:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: bcmf_core_upload_firmware
|
|
|
|
****************************************************************************/
|
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus)
|
2017-03-26 17:42:53 +02:00
|
|
|
{
|
|
|
|
int ret;
|
2021-12-29 15:02:46 +01:00
|
|
|
#if defined(CONFIG_IEEE80211_BROADCOM_BCM43455)
|
|
|
|
uint32_t base;
|
|
|
|
uint32_t value;
|
|
|
|
#endif
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2017-04-24 00:24:47 +02:00
|
|
|
wlinfo("upload firmware\n");
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
switch (sbus->cur_chip_id)
|
|
|
|
{
|
2022-06-14 08:36:58 +02:00
|
|
|
#if defined(CONFIG_IEEE80211_BROADCOM_BCM4301X) || \
|
2022-06-13 11:01:49 +02:00
|
|
|
defined(CONFIG_IEEE80211_BROADCOM_BCM43362) || \
|
2021-12-29 15:02:46 +01:00
|
|
|
defined(CONFIG_IEEE80211_BROADCOM_BCM43438)
|
|
|
|
|
2022-06-14 08:36:58 +02:00
|
|
|
case SDIO_DEVICE_ID_BROADCOM_43012:
|
|
|
|
case SDIO_DEVICE_ID_BROADCOM_43013:
|
2021-12-29 15:02:46 +01:00
|
|
|
case SDIO_DEVICE_ID_BROADCOM_43362:
|
|
|
|
case SDIO_DEVICE_ID_BROADCOM_43430:
|
|
|
|
/* Disable ARMCM3 core and reset SOCRAM core to set device in
|
|
|
|
* firmware upload mode
|
|
|
|
*/
|
|
|
|
|
|
|
|
bcmf_core_disable(sbus, WLAN_ARMCM3_CORE_ID, 0, 0);
|
|
|
|
bcmf_core_reset(sbus, SOCSRAM_CORE_ID, 0, 0, 0);
|
|
|
|
|
|
|
|
#ifdef CONFIG_IEEE80211_BROADCOM_BCM43438
|
|
|
|
if (sbus->cur_chip_id == SDIO_DEVICE_ID_BROADCOM_43430)
|
|
|
|
{
|
|
|
|
/* Disable remap for SRAM_3. Only for 4343x */
|
|
|
|
|
|
|
|
bcmf_write_sbregw(sbus, SOCSRAM_BANKX_INDEX, 0x3);
|
|
|
|
bcmf_write_sbregw(sbus, SOCSRAM_BANKX_PDA, 0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
#endif
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
#if defined(CONFIG_IEEE80211_BROADCOM_BCM43455)
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
case SDIO_DEVICE_ID_BROADCOM_43455:
|
2018-04-26 16:10:23 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
/* Clear all IOCTL bits except HALT bit */
|
|
|
|
|
|
|
|
base = sbus->chip->core_base[WLAN_ARMCR4_CORE_ID];
|
|
|
|
bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value);
|
|
|
|
value &= ARMCR4_BCMA_IOCTL_CPUHALT;
|
|
|
|
bcmf_core_reset(sbus,
|
|
|
|
WLAN_ARMCR4_CORE_ID,
|
|
|
|
value,
|
|
|
|
ARMCR4_BCMA_IOCTL_CPUHALT,
|
|
|
|
ARMCR4_BCMA_IOCTL_CPUHALT);
|
|
|
|
break;
|
|
|
|
#endif
|
2018-04-26 16:10:23 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
default:
|
|
|
|
DEBUGASSERT(false);
|
2018-04-26 16:10:23 +02:00
|
|
|
}
|
|
|
|
|
2022-06-16 14:16:32 +02:00
|
|
|
nxsig_usleep(50 * 1000);
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
/* Flash chip firmware */
|
|
|
|
|
2018-10-07 18:03:39 +02:00
|
|
|
#ifdef CONFIG_IEEE80211_BROADCOM_FWFILES
|
2021-12-29 15:02:46 +01:00
|
|
|
ret = bcmf_upload_file(sbus,
|
|
|
|
sbus->chip->ram_base,
|
|
|
|
CONFIG_IEEE80211_BROADCOM_FWFILENAME);
|
2018-10-07 18:03:39 +02:00
|
|
|
#else
|
2017-04-24 00:24:47 +02:00
|
|
|
wlinfo("firmware size is %d bytes\n", *sbus->chip->firmware_image_size);
|
2018-10-07 18:03:39 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
ret = bcmf_upload_binary(sbus,
|
|
|
|
sbus->chip->ram_base,
|
|
|
|
sbus->chip->firmware_image,
|
2017-04-23 22:17:43 +02:00
|
|
|
*sbus->chip->firmware_image_size);
|
2018-10-07 18:03:39 +02:00
|
|
|
#endif
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2018-10-07 18:03:39 +02:00
|
|
|
if (ret < 0)
|
2017-03-26 17:42:53 +02:00
|
|
|
{
|
2018-10-07 18:03:39 +02:00
|
|
|
wlerr("ERROR: Failed to upload firmware\n");
|
|
|
|
return ret;
|
2017-03-26 17:42:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Flash NVRAM configuration file */
|
|
|
|
|
2017-04-24 00:24:47 +02:00
|
|
|
wlinfo("upload nvram configuration\n");
|
2017-04-23 22:17:43 +02:00
|
|
|
ret = bcmf_upload_nvram(sbus);
|
2018-10-07 18:03:39 +02:00
|
|
|
if (ret < 0)
|
2017-03-26 17:42:53 +02:00
|
|
|
{
|
2018-10-07 18:03:39 +02:00
|
|
|
wlerr("ERROR: Failed to upload NVRAM\n");
|
|
|
|
return ret;
|
2017-03-26 17:42:53 +02:00
|
|
|
}
|
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
/* Firmware upload done, restart ARM CM3/CR4 core */
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
switch (sbus->cur_chip_id)
|
|
|
|
{
|
2022-06-14 08:36:58 +02:00
|
|
|
#if defined(CONFIG_IEEE80211_BROADCOM_BCM4301X) || \
|
2022-06-13 11:01:49 +02:00
|
|
|
defined(CONFIG_IEEE80211_BROADCOM_BCM43362) || \
|
2021-12-29 15:02:46 +01:00
|
|
|
defined(CONFIG_IEEE80211_BROADCOM_BCM43438)
|
|
|
|
|
2022-06-14 08:36:58 +02:00
|
|
|
case SDIO_DEVICE_ID_BROADCOM_43012:
|
|
|
|
case SDIO_DEVICE_ID_BROADCOM_43013:
|
2021-12-29 15:02:46 +01:00
|
|
|
case SDIO_DEVICE_ID_BROADCOM_43362:
|
|
|
|
case SDIO_DEVICE_ID_BROADCOM_43430:
|
2022-06-16 14:16:32 +02:00
|
|
|
nxsig_usleep(10 * 1000);
|
2021-12-29 15:02:46 +01:00
|
|
|
bcmf_core_reset(sbus, WLAN_ARMCM3_CORE_ID, 0, 0, 0);
|
|
|
|
|
|
|
|
/* Check ARMCM3 core is running */
|
|
|
|
|
2022-06-16 14:16:32 +02:00
|
|
|
nxsig_usleep(10 * 1000);
|
2021-12-29 15:02:46 +01:00
|
|
|
if (!bcmf_core_isup(sbus, WLAN_ARMCM3_CORE_ID))
|
|
|
|
{
|
|
|
|
wlerr("Cannot start ARMCM3 core\n");
|
|
|
|
return -ETIMEDOUT;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
#if defined(CONFIG_IEEE80211_BROADCOM_BCM43455)
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
case SDIO_DEVICE_ID_BROADCOM_43455:
|
|
|
|
|
|
|
|
/* Clear all interrupts */
|
|
|
|
|
|
|
|
bcmf_write_sbregw(
|
|
|
|
sbus,
|
|
|
|
CORE_BUS_REG(sbus->chip->core_base[SDIOD_CORE_ID], intstatus),
|
|
|
|
0xffffffff);
|
|
|
|
|
|
|
|
/* Write reset vector to address 0 */
|
|
|
|
|
|
|
|
ret = bcmf_upload_binary(sbus,
|
|
|
|
0,
|
|
|
|
sbus->chip->firmware_image,
|
|
|
|
4);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bcmf_core_reset(sbus,
|
|
|
|
WLAN_ARMCR4_CORE_ID,
|
|
|
|
ARMCR4_BCMA_IOCTL_CPUHALT,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
|
|
|
|
/* Check ARMCR4 core is running */
|
|
|
|
|
2022-06-16 14:16:32 +02:00
|
|
|
nxsig_usleep(10 * 1000);
|
2021-12-29 15:02:46 +01:00
|
|
|
if (!bcmf_core_isup(sbus, WLAN_ARMCR4_CORE_ID))
|
|
|
|
{
|
|
|
|
wlerr("Cannot start ARMCR4 core\n");
|
|
|
|
return -ETIMEDOUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
default:
|
|
|
|
DEBUGASSERT(false);
|
2017-03-26 17:42:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
bool bcmf_core_isup(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core)
|
2017-03-26 17:42:53 +02:00
|
|
|
{
|
|
|
|
uint32_t value = 0;
|
2019-10-29 23:56:24 +01:00
|
|
|
uint32_t base;
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
if (core >= MAX_CORE_ID)
|
|
|
|
{
|
2017-04-24 00:24:47 +02:00
|
|
|
wlerr("Invalid core id %d\n", core);
|
2017-04-23 22:17:43 +02:00
|
|
|
return false;
|
|
|
|
}
|
2019-10-29 23:56:24 +01:00
|
|
|
|
|
|
|
base = sbus->chip->core_base[core];
|
2017-04-23 22:17:43 +02:00
|
|
|
|
|
|
|
bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value);
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
if ((value & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) != BCMA_IOCTL_CLK)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
bcmf_read_sbregw(sbus, base + BCMA_RESET_CTL, &value);
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
return (value & BCMA_RESET_CTL_RESET) == 0;
|
|
|
|
}
|
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
void bcmf_core_disable(FAR struct bcmf_sdio_dev_s *sbus,
|
|
|
|
unsigned int core,
|
|
|
|
uint32_t prereset,
|
|
|
|
uint32_t reset)
|
2017-03-26 17:42:53 +02:00
|
|
|
{
|
2021-12-29 15:02:46 +01:00
|
|
|
uint32_t value;
|
2017-04-23 22:17:43 +02:00
|
|
|
|
|
|
|
if (core >= MAX_CORE_ID)
|
|
|
|
{
|
2017-04-24 00:24:47 +02:00
|
|
|
wlerr("Invalid core id %d\n", core);
|
2017-04-23 22:17:43 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-05-04 02:30:40 +02:00
|
|
|
|
2017-04-23 22:17:43 +02:00
|
|
|
uint32_t base = sbus->chip->core_base[core];
|
2017-05-04 02:30:40 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
/* Check if core is already in reset state.
|
|
|
|
* If core is already in reset state, skip reset.
|
|
|
|
*/
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
bcmf_read_sbregw(sbus, base + BCMA_RESET_CTL, &value);
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
if ((value & BCMA_RESET_CTL_RESET) == 0)
|
2017-03-26 17:42:53 +02:00
|
|
|
{
|
2021-12-29 15:02:46 +01:00
|
|
|
/* Core is not in reset state */
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
/* Ensure no backplane operation is pending */
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2022-06-16 14:16:32 +02:00
|
|
|
nxsig_usleep(10 * 1000);
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
bcmf_write_sbregw(sbus,
|
|
|
|
base + BCMA_IOCTL,
|
|
|
|
prereset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
|
|
|
|
bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value);
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
/* Set core in reset state */
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
bcmf_write_sbregw(sbus, base + BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
|
|
|
|
up_udelay(1);
|
|
|
|
}
|
2017-03-26 17:42:53 +02:00
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
bcmf_write_sbregw(sbus,
|
|
|
|
base + BCMA_IOCTL,
|
|
|
|
reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
|
|
|
|
bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value);
|
2017-03-26 17:42:53 +02:00
|
|
|
up_udelay(10);
|
|
|
|
}
|
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
void bcmf_core_reset(FAR struct bcmf_sdio_dev_s *sbus,
|
|
|
|
unsigned int core,
|
|
|
|
uint32_t prereset,
|
|
|
|
uint32_t reset,
|
|
|
|
uint32_t postreset)
|
2017-03-26 17:42:53 +02:00
|
|
|
{
|
|
|
|
uint32_t value;
|
2019-10-29 23:56:24 +01:00
|
|
|
uint32_t base;
|
2017-04-23 22:17:43 +02:00
|
|
|
|
|
|
|
if (core >= MAX_CORE_ID)
|
|
|
|
{
|
2017-04-24 00:24:47 +02:00
|
|
|
wlerr("Invalid core id %d\n", core);
|
2017-04-23 22:17:43 +02:00
|
|
|
return;
|
|
|
|
}
|
2019-10-29 23:56:24 +01:00
|
|
|
|
|
|
|
base = sbus->chip->core_base[core];
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
/* Put core in reset state */
|
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
bcmf_core_disable(sbus, core, prereset, reset);
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
/* Run initialization sequence */
|
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
bcmf_write_sbregw(sbus, base + BCMA_RESET_CTL, 0);
|
2017-04-23 22:17:43 +02:00
|
|
|
bcmf_read_sbregw(sbus, base + BCMA_RESET_CTL, &value);
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
up_udelay(1);
|
|
|
|
|
2021-12-29 15:02:46 +01:00
|
|
|
bcmf_write_sbregw(sbus, base + BCMA_IOCTL, postreset | BCMA_IOCTL_CLK);
|
2017-04-23 22:17:43 +02:00
|
|
|
bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value);
|
2017-03-26 17:42:53 +02:00
|
|
|
|
|
|
|
up_udelay(1);
|
|
|
|
}
|