From 76bb5f5a6119df3ef799e73fc3711c505d220edc Mon Sep 17 00:00:00 2001 From: Alexander Lunev Date: Wed, 29 Dec 2021 17:02:46 +0300 Subject: [PATCH] bcm43xxx: supported ARM CR4 core and bcm43455 chip in particular --- drivers/wireless/ieee80211/bcm43xxx/Kconfig | 10 +- drivers/wireless/ieee80211/bcm43xxx/Make.defs | 4 + .../ieee80211/bcm43xxx/bcmf_chip_43362.c | 1 + .../ieee80211/bcm43xxx/bcmf_chip_43438.c | 1 + .../ieee80211/bcm43xxx/bcmf_chip_43455.c | 87 +++++++ .../wireless/ieee80211/bcm43xxx/bcmf_core.c | 217 +++++++++++++----- .../wireless/ieee80211/bcm43xxx/bcmf_core.h | 11 +- .../wireless/ieee80211/bcm43xxx/bcmf_sdio.c | 10 + .../wireless/ieee80211/bcm43xxx/bcmf_sdio.h | 1 + .../ieee80211/bcm43xxx/bcmf_sdio_core.h | 7 + 10 files changed, 291 insertions(+), 58 deletions(-) create mode 100644 drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43455.c diff --git a/drivers/wireless/ieee80211/bcm43xxx/Kconfig b/drivers/wireless/ieee80211/bcm43xxx/Kconfig index 7f00ef9880..9badda82f3 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/Kconfig +++ b/drivers/wireless/ieee80211/bcm43xxx/Kconfig @@ -22,10 +22,18 @@ config IEEE80211_BROADCOM_BCM43438 default n select IEEE80211_BROADCOM_HAVE_CLM +config IEEE80211_BROADCOM_BCM43455 + bool "Broadcom 43455 chip support" + depends on IEEE80211_BROADCOM_FULLMAC + default n + select IEEE80211_BROADCOM_HAVE_CLM + config IEEE80211_BROADCOM_FWFILES bool "Firmware files" default y - depends on IEEE80211_BROADCOM_BCM43362 || IEEE80211_BROADCOM_BCM43438 + depends on IEEE80211_BROADCOM_BCM43362 || \ + IEEE80211_BROADCOM_BCM43438 || \ + IEEE80211_BROADCOM_BCM43455 ---help--- By default, firmware and CLM files are provided in memory. This selection enables an option to load the firmware and CLM diff --git a/drivers/wireless/ieee80211/bcm43xxx/Make.defs b/drivers/wireless/ieee80211/bcm43xxx/Make.defs index d364da45ce..959457fd73 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/Make.defs +++ b/drivers/wireless/ieee80211/bcm43xxx/Make.defs @@ -42,6 +42,10 @@ ifeq ($(CONFIG_IEEE80211_BROADCOM_BCM43438),y) CSRCS += bcmf_chip_43438.c endif +ifeq ($(CONFIG_IEEE80211_BROADCOM_BCM43455),y) +CSRCS += bcmf_chip_43455.c +endif + # Include BCM43xxx build support DEPPATH += --dep-path wireless$(DELIM)ieee80211$(DELIM)bcm43xxx diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43362.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43362.c index 22531e790d..ab77418f46 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43362.c +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43362.c @@ -49,6 +49,7 @@ const struct bcmf_sdio_chip bcmf_43362_config_sdio = { /* General chip stats */ + .ram_base = 0, .ram_size = 0x3c000, /* Backplane architecture */ diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43438.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43438.c index 97a341e79c..2592b92c23 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43438.c +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43438.c @@ -52,6 +52,7 @@ const struct bcmf_sdio_chip bcmf_43438_config_sdio = { /* General chip stats */ + .ram_base = 0, .ram_size = 512 * 1024, /* Backplane architecture */ diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43455.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43455.c new file mode 100644 index 0000000000..92adb03fce --- /dev/null +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43455.c @@ -0,0 +1,87 @@ +/**************************************************************************** + * drivers/wireless/ieee80211/bcm43xxx/bcmf_chip_43455.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "bcmf_sdio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define WRAPPER_REGISTER_OFFSET 0x100000 + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern const char bcm43455_nvram_image[]; +extern const unsigned int bcm43455_nvram_image_len; + +#ifndef CONFIG_IEEE80211_BROADCOM_FWFILES +extern const uint8_t bcm43455_firmware_image[]; +extern const unsigned int bcm43455_firmware_len; + +extern const uint8_t bcm43455_clm_blob[]; +extern const unsigned int bcm43455_clm_blob_len; +#endif + +const struct bcmf_sdio_chip bcmf_43455_config_sdio = +{ + /* General chip stats */ + + .ram_base = 0x198000, + .ram_size = 800 * 1024, + + /* Backplane architecture */ + + .core_base = + { + [CHIPCOMMON_CORE_ID] = 0x18000000, /* Chipcommon core register base */ + [DOT11MAC_CORE_ID] = 0x18001000, /* dot11mac core register base */ + [WLAN_ARMCR4_CORE_ID] = 0x18002000 /* ARMCR4 core register base */ + + WRAPPER_REGISTER_OFFSET, + [SDIOD_CORE_ID] = 0x18004000 /* SDIOD Device core register base */ + }, + + /* Firmware images */ + + /* TODO find something smarter than using image_len references */ + + .nvram_image = (FAR uint8_t *)bcm43455_nvram_image, + .nvram_image_size = (FAR unsigned int *)&bcm43455_nvram_image_len, + +#ifndef CONFIG_IEEE80211_BROADCOM_FWFILES + .firmware_image = (FAR uint8_t *)bcm43455_firmware_image, + .firmware_image_size = (FAR unsigned int *)&bcm43455_firmware_len, + + .clm_blob_image = (FAR uint8_t *)bcm43455_clm_blob, + .clm_blob_image_size = (FAR unsigned int *)&bcm43455_clm_blob_len, +#endif +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.c index cdd37cabd7..10b3aacd73 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.c +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -56,6 +57,10 @@ #define BCMA_IOCTL_PME_EN 0x4000 #define BCMA_IOCTL_BIST_EN 0x8000 +/* ARM CR4 core specific control flag bits */ + +#define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020 + #define BCMA_IOST_CORE_BITS 0x0FFF #define BCMA_IOST_DMA64 0x1000 #define BCMA_IOST_GATED_CLK 0x2000 @@ -336,7 +341,9 @@ int bcmf_upload_nvram(FAR struct bcmf_sdio_dev_s *sbus) /* Write image */ - ret = bcmf_upload_binary(sbus, sbus->chip->ram_size - 4 - nvram_sz, + ret = bcmf_upload_binary(sbus, + sbus->chip->ram_size - 4 - nvram_sz + + sbus->chip->ram_base, sbus->chip->nvram_image, *sbus->chip->nvram_image_size); if (ret != OK) @@ -351,7 +358,8 @@ int bcmf_upload_nvram(FAR struct bcmf_sdio_dev_s *sbus) /* Write the length token to the last word */ - ret = bcmf_write_sbreg(sbus, sbus->chip->ram_size - 4, + ret = bcmf_write_sbreg(sbus, + sbus->chip->ram_size - 4 + sbus->chip->ram_base, (FAR uint8_t *)&token, 4); if (ret != OK) { @@ -422,24 +430,58 @@ int bcmf_write_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address, int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus) { int ret; +#if defined(CONFIG_IEEE80211_BROADCOM_BCM43455) + uint32_t base; + uint32_t value; +#endif 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); - - /* Do chip specific initialization */ - - if (sbus->cur_chip_id == SDIO_DEVICE_ID_BROADCOM_43430) + switch (sbus->cur_chip_id) { - /* Disable remap for SRAM_3. Only for 4343x */ +#if defined(CONFIG_IEEE80211_BROADCOM_BCM43362) || \ + defined(CONFIG_IEEE80211_BROADCOM_BCM43438) - bcmf_write_sbregw(sbus, SOCSRAM_BANKX_INDEX, 0x3); - bcmf_write_sbregw(sbus, SOCSRAM_BANKX_PDA, 0); + 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 + +#if defined(CONFIG_IEEE80211_BROADCOM_BCM43455) + + case SDIO_DEVICE_ID_BROADCOM_43455: + + /* 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 + + default: + DEBUGASSERT(false); } up_mdelay(50); @@ -447,11 +489,15 @@ int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus) /* Flash chip firmware */ #ifdef CONFIG_IEEE80211_BROADCOM_FWFILES - ret = bcmf_upload_file(sbus, 0, CONFIG_IEEE80211_BROADCOM_FWFILENAME); + ret = bcmf_upload_file(sbus, + sbus->chip->ram_base, + CONFIG_IEEE80211_BROADCOM_FWFILENAME); #else wlinfo("firmware size is %d bytes\n", *sbus->chip->firmware_image_size); - ret = bcmf_upload_binary(sbus, 0, sbus->chip->firmware_image, + ret = bcmf_upload_binary(sbus, + sbus->chip->ram_base, + sbus->chip->firmware_image, *sbus->chip->firmware_image_size); #endif @@ -471,18 +517,71 @@ int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus) return ret; } - /* Firmware upload done, restart ARMCM3 core */ + /* Firmware upload done, restart ARM CM3/CR4 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)) + switch (sbus->cur_chip_id) { - wlerr("Cannot start ARMCM3 core\n"); - return -ETIMEDOUT; +#if defined(CONFIG_IEEE80211_BROADCOM_BCM43362) || \ + defined(CONFIG_IEEE80211_BROADCOM_BCM43438) + + case SDIO_DEVICE_ID_BROADCOM_43362: + case SDIO_DEVICE_ID_BROADCOM_43430: + up_mdelay(10); + bcmf_core_reset(sbus, WLAN_ARMCM3_CORE_ID, 0, 0, 0); + + /* 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; + } + break; +#endif + +#if defined(CONFIG_IEEE80211_BROADCOM_BCM43455) + + 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 */ + + up_mdelay(10); + if (!bcmf_core_isup(sbus, WLAN_ARMCR4_CORE_ID)) + { + wlerr("Cannot start ARMCR4 core\n"); + return -ETIMEDOUT; + } + + break; +#endif + + default: + DEBUGASSERT(false); } return OK; @@ -513,9 +612,12 @@ bool bcmf_core_isup(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core) return (value & BCMA_RESET_CTL_RESET) == 0; } -void bcmf_core_disable(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core) +void bcmf_core_disable(FAR struct bcmf_sdio_dev_s *sbus, + unsigned int core, + uint32_t prereset, + uint32_t reset) { - uint8_t value; + uint32_t value; if (core >= MAX_CORE_ID) { @@ -525,34 +627,43 @@ void bcmf_core_disable(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core) uint32_t base = sbus->chip->core_base[core]; - /* Check if core is already in reset state */ + /* Check if core is already in reset state. + * If core is already in reset state, skip reset. + */ - bcmf_read_sbregb(sbus, base + BCMA_RESET_CTL, &value); + bcmf_read_sbregw(sbus, base + BCMA_RESET_CTL, &value); - if ((value & BCMA_RESET_CTL_RESET) != 0) + if ((value & BCMA_RESET_CTL_RESET) == 0) { - /* Core already disabled */ + /* Core is not in reset state */ - return; + /* Ensure no backplane operation is pending */ + + up_mdelay(10); + + bcmf_write_sbregw(sbus, + base + BCMA_IOCTL, + prereset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK); + bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value); + + /* Set core in reset state */ + + bcmf_write_sbregw(sbus, base + BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); + up_udelay(1); } - /* 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); + bcmf_write_sbregw(sbus, + base + BCMA_IOCTL, + reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK); + bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value); up_udelay(10); } -void bcmf_core_reset(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core) +void bcmf_core_reset(FAR struct bcmf_sdio_dev_s *sbus, + unsigned int core, + uint32_t prereset, + uint32_t reset, + uint32_t postreset) { uint32_t value; uint32_t base; @@ -567,20 +678,16 @@ void bcmf_core_reset(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core) /* Put core in reset state */ - bcmf_core_disable(sbus, core); + bcmf_core_disable(sbus, core, prereset, reset); /* 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_write_sbregw(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_write_sbregw(sbus, base + BCMA_IOCTL, postreset | BCMA_IOCTL_CLK); bcmf_read_sbregw(sbus, base + BCMA_IOCTL, &value); up_udelay(1); diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.h index ae4c4348b0..1c428dfa9d 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.h +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_core.h @@ -42,9 +42,16 @@ int bcmf_write_sbreg(FAR struct bcmf_sdio_dev_s *sbus, uint32_t address, 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_disable(FAR struct bcmf_sdio_dev_s *sbus, + unsigned int core, + uint32_t prereset, + uint32_t reset); -void bcmf_core_reset(FAR struct bcmf_sdio_dev_s *sbus, unsigned int core); +void bcmf_core_reset(FAR struct bcmf_sdio_dev_s *sbus, + unsigned int core, + uint32_t prereset, + uint32_t reset, + uint32_t postreset); int bcmf_core_upload_firmware(FAR struct bcmf_sdio_dev_s *sbus); diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.c index 4b4a410925..d602f52c33 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.c +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.c @@ -81,6 +81,9 @@ #ifdef CONFIG_IEEE80211_BROADCOM_BCM43438 extern const struct bcmf_sdio_chip bcmf_43438_config_sdio; #endif +#ifdef CONFIG_IEEE80211_BROADCOM_BCM43455 + extern const struct bcmf_sdio_chip bcmf_43455_config_sdio; +#endif /**************************************************************************** * Private Function Prototypes @@ -824,6 +827,13 @@ int bcmf_chipinitialize(FAR struct bcmf_sdio_dev_s *sbus) break; #endif +#ifdef CONFIG_IEEE80211_BROADCOM_BCM43455 + case SDIO_DEVICE_ID_BROADCOM_43455: + wlinfo("bcm43455 chip detected\n"); + sbus->chip = (struct bcmf_sdio_chip *)&bcmf_43455_config_sdio; + break; +#endif + default: wlerr("chip 0x%x is not supported\n", chipid); return -ENODEV; diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.h index ba5af0b958..470ea8bd77 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.h +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio.h @@ -53,6 +53,7 @@ struct bcmf_sdio_chip { + uint32_t ram_base; uint32_t ram_size; uint32_t core_base[MAX_CORE_ID]; diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio_core.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio_core.h index db3d7e2640..641e7493ae 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio_core.h +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_sdio_core.h @@ -44,6 +44,7 @@ #define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335 #define SDIO_DEVICE_ID_BROADCOM_43362 43362 #define SDIO_DEVICE_ID_BROADCOM_43430 43430 +#define SDIO_DEVICE_ID_BROADCOM_43455 0x4345 /* Core reg address translation. * Both macro's returns a 32 bits byte address on the backplane bus. @@ -84,8 +85,14 @@ enum CHIPCOMMON_CORE_ID = 0, DOT11MAC_CORE_ID, SDIOD_CORE_ID, +#if defined(CONFIG_IEEE80211_BROADCOM_BCM43362) || \ + defined(CONFIG_IEEE80211_BROADCOM_BCM43438) WLAN_ARMCM3_CORE_ID, SOCSRAM_CORE_ID, +#endif +#if defined(CONFIG_IEEE80211_BROADCOM_BCM43455) + WLAN_ARMCR4_CORE_ID, +#endif MAX_CORE_ID };