From c005bafc65029805b7205cc8d00ef516d1e768de Mon Sep 17 00:00:00 2001 From: Gaurang Rathod Date: Wed, 15 Feb 2023 04:14:30 -0600 Subject: [PATCH 224/296] brcmfmac: Bootloader host handshake implementation This change is required to bring-up 43022 chip in secure-mode. Here we have introduced new firmware nvram download flow for security. skip the modification in pcie.c as of the commit commit 5d13af8cf77b ("Bootloader host handshake") Signed-off-by: Gaurang Rathod --- .../broadcom/brcm80211/brcmfmac/chip.c | 109 +++++++++-- .../broadcom/brcm80211/brcmfmac/chip.h | 3 + .../broadcom/brcm80211/brcmfmac/firmware.c | 18 +- .../broadcom/brcm80211/brcmfmac/firmware.h | 10 +- .../broadcom/brcm80211/brcmfmac/sdio.c | 179 +++++++++++++++--- .../broadcom/brcm80211/brcmfmac/sdio.h | 1 + 6 files changed, 268 insertions(+), 52 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index d58cd5ae7b4f..37c345da55e5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -251,7 +251,11 @@ struct sbsocramregs { #define BRCMF_BLHS_POLL_INTERVAL 10 /* msec */ #define BRCMF_BLHS_D2H_READY_TIMEOUT 100 /* msec */ #define BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE_TIMEOUT 50 /* msec */ -#define BRCMF_BLHS_D2H_VALDN_DONE_TIMEOUT 450 /* msec */ + +//TODO: original value is 450, check if need assign to specific chip or not. +#define BRCMF_BLHS_D2H_VALDN_DONE_TIMEOUT 250 /* msec */ +#define BRCMF_BLHS_D2H_MV_NVRAM_DONE_TIMEOUT 100 /* msec */ +#define BRCMF_BLHS_D2H_BP_CLK_DISABLE_REQ_TIMEOUT (5 * 1000) /* msec */ /* Bootloader handshake flags - dongle to host */ #define BRCMF_BLHS_D2H_START BIT(0) @@ -261,12 +265,16 @@ struct sbsocramregs { #define BRCMF_BLHS_D2H_VALDN_START BIT(4) #define BRCMF_BLHS_D2H_VALDN_RESULT BIT(5) #define BRCMF_BLHS_D2H_VALDN_DONE BIT(6) +#define BRCMF_BLHS_D2H_MV_NVRAM_DONE BIT(7) +#define BRCMF_BLHS_D2H_BP_CLK_DISABLE_REQ BIT(8) /* Bootloader handshake flags - host to dongle */ #define BRCMF_BLHS_H2D_DL_FW_START BIT(0) #define BRCMF_BLHS_H2D_DL_FW_DONE BIT(1) #define BRCMF_BLHS_H2D_DL_NVRAM_DONE BIT(2) #define BRCMF_BLHS_H2D_BL_RESET_ON_ERROR BIT(3) +#define BRCMF_BLHS_H2D_DL_NVRAM_START BIT(4) +#define BRCMF_BLHS_H2D_BP_CLK_DISABLE_ACK BIT(5) struct brcmf_core_priv { struct brcmf_core pub; @@ -1079,7 +1087,7 @@ static int brcmf_blhs_is_bootloader_ready(struct brcmf_chip_priv *chip) return 0; } -static int brcmf_blhs_prep_fw_download(struct brcmf_chip *pub) +static int brcmf_blhs_pre_nvram_download(struct brcmf_chip *pub) { struct brcmf_chip_priv *chip; u32 addr; @@ -1093,6 +1101,51 @@ static int brcmf_blhs_prep_fw_download(struct brcmf_chip *pub) if (err) return err; + /* Host notification about NVRAM download start */ + addr = pub->blhs->h2d; + pub->blhs->write(chip->ctx, addr, BRCMF_BLHS_H2D_DL_NVRAM_START); + + return 0; +} + +static int brcmf_blhs_ack_wait_dongle_access(struct brcmf_chip *pub) +{ + struct brcmf_chip_priv *chip; + u32 addr, base; + int err; + + chip = container_of(pub, struct brcmf_chip_priv, pub); + + addr = pub->blhs->d2h; + SPINWAIT_MS((pub->blhs->read(chip->ctx, addr) & + BRCMF_BLHS_D2H_BP_CLK_DISABLE_REQ) == 0, + BRCMF_BLHS_D2H_BP_CLK_DISABLE_REQ_TIMEOUT, + BRCMF_BLHS_POLL_INTERVAL); + + addr = pub->blhs->h2d; + pub->blhs->write(chip->ctx, addr, BRCMF_BLHS_H2D_BP_CLK_DISABLE_ACK); + + err = brcmf_get_intr_pending_data(chip->ctx); + + return err; +} + +static int brcmf_blhs_prep_fw_download(struct brcmf_chip *pub) +{ + struct brcmf_chip_priv *chip; + u32 addr; + int err; + + chip = container_of(pub, struct brcmf_chip_priv, pub); + /* Host indication for bootloader to start the init */ + if (!(pub->chip == CY_CC_43022_CHIP_ID)) { + brcmf_blhs_init(pub); + + chip = container_of(pub, struct brcmf_chip_priv, pub); + err = brcmf_blhs_is_bootloader_ready(chip); + if (err) + return err; + } /* Host notification about FW download start */ addr = pub->blhs->h2d; pub->blhs->write(chip->ctx, addr, BRCMF_BLHS_H2D_DL_FW_START); @@ -1105,30 +1158,36 @@ static int brcmf_blhs_post_fw_download(struct brcmf_chip *pub) struct brcmf_chip_priv *chip; u32 addr; u32 regdata; + int err = 0; chip = container_of(pub, struct brcmf_chip_priv, pub); addr = pub->blhs->h2d; pub->blhs->write(chip->ctx, addr, BRCMF_BLHS_H2D_DL_FW_DONE); - addr = pub->blhs->d2h; - SPINWAIT_MS((pub->blhs->read(chip->ctx, addr) & - BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE) == 0, - BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE_TIMEOUT, - BRCMF_BLHS_POLL_INTERVAL); - regdata = pub->blhs->read(chip->ctx, addr); - if (!(regdata & BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE)) { - brcmf_err("TRX header parsing failed\n"); + if (pub->chip == CY_CC_43022_CHIP_ID) { + err = brcmf_blhs_ack_wait_dongle_access(pub); + } else { + addr = pub->blhs->d2h; + SPINWAIT_MS((pub->blhs->read(chip->ctx, addr) & + BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE) == 0, + BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE_TIMEOUT, + BRCMF_BLHS_POLL_INTERVAL); - /* Host indication for bootloader to get reset on error */ - addr = pub->blhs->h2d; regdata = pub->blhs->read(chip->ctx, addr); - regdata |= BRCMF_BLHS_H2D_BL_RESET_ON_ERROR; - pub->blhs->write(chip->ctx, addr, regdata); + if (!(regdata & BRCMF_BLHS_D2H_TRXHDR_PARSE_DONE)) { + brcmf_err("TRX header parsing failed\n"); + + /* Host indication for bootloader to get reset on error */ + addr = pub->blhs->h2d; + regdata = pub->blhs->read(chip->ctx, addr); + regdata |= BRCMF_BLHS_H2D_BL_RESET_ON_ERROR; + pub->blhs->write(chip->ctx, addr, regdata); return -EPERM; + } } - return 0; + return err; } static void brcmf_blhs_post_nvram_download(struct brcmf_chip *pub) @@ -1139,9 +1198,21 @@ static void brcmf_blhs_post_nvram_download(struct brcmf_chip *pub) chip = container_of(pub, struct brcmf_chip_priv, pub); addr = pub->blhs->h2d; - regdata = pub->blhs->read(chip->ctx, addr); - regdata |= BRCMF_BLHS_H2D_DL_NVRAM_DONE; - pub->blhs->write(chip->ctx, addr, regdata); + if (pub->chip == CY_CC_43022_CHIP_ID) { + regdata = pub->blhs->read(chip->ctx, addr); + regdata |= BRCMF_BLHS_H2D_DL_NVRAM_DONE; + pub->blhs->write(chip->ctx, addr, regdata); + + addr = pub->blhs->d2h; + SPINWAIT_MS((pub->blhs->read(chip->ctx, addr) & + BRCMF_BLHS_D2H_MV_NVRAM_DONE) == 0, + BRCMF_BLHS_D2H_MV_NVRAM_DONE_TIMEOUT, + BRCMF_BLHS_POLL_INTERVAL); + } else { + regdata = pub->blhs->read(chip->ctx, addr); + regdata |= BRCMF_BLHS_H2D_DL_NVRAM_DONE; + pub->blhs->write(chip->ctx, addr, regdata); + } } static int brcmf_blhs_chk_validation(struct brcmf_chip *pub) @@ -1390,9 +1461,11 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx, u16 devid, if (blhs) { blhs->init = brcmf_blhs_init; + blhs->pre_nvramdl = brcmf_blhs_pre_nvram_download; blhs->prep_fwdl = brcmf_blhs_prep_fw_download; blhs->post_fwdl = brcmf_blhs_post_fw_download; blhs->post_nvramdl = brcmf_blhs_post_nvram_download; + blhs->bp_clk_ack = brcmf_blhs_ack_wait_dongle_access; blhs->chk_validation = brcmf_blhs_chk_validation; blhs->post_wdreset = brcmf_blhs_post_watchdog_reset; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h index 3d1bf44f2d14..ad0804d7ace1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h @@ -100,9 +100,11 @@ struct brcmf_blhs { u32 d2h; u32 h2d; void (*init)(struct brcmf_chip *pub); + int (*pre_nvramdl)(struct brcmf_chip *pub); int (*prep_fwdl)(struct brcmf_chip *pub); int (*post_fwdl)(struct brcmf_chip *pub); void (*post_nvramdl)(struct brcmf_chip *pub); + int (*bp_clk_ack)(struct brcmf_chip *pub); int (*chk_validation)(struct brcmf_chip *pub); int (*post_wdreset)(struct brcmf_chip *pub); u32 (*read)(void *ctx, u32 addr); @@ -136,5 +138,6 @@ void brcmf_chip_reset_watchdog(struct brcmf_chip *pub); void brcmf_chip_ulp_reset_lhl_regs(struct brcmf_chip *pub); void brcmf_chip_reset_pmu_regs(struct brcmf_chip *pub); void brcmf_chip_set_default_min_res_mask(struct brcmf_chip *pub); +int brcmf_get_intr_pending_data(void *ctx); #endif /* BRCMF_AXIDMP_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index 726430338b9f..aa895df4fe74 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -528,6 +528,7 @@ static void brcmf_fw_free_request(struct brcmf_fw_request *req) for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) { if (item->type == BRCMF_FW_TYPE_BINARY || + item->type == BRCMF_FW_TYPE_TRXS || item->type == BRCMF_FW_TYPE_TRXSE) release_firmware(item->binary); else if (item->type == BRCMF_FW_TYPE_NVRAM) @@ -601,6 +602,7 @@ static int brcmf_fw_complete_request(const struct firmware *fw, break; case BRCMF_FW_TYPE_BINARY: case BRCMF_FW_TYPE_TRXSE: + case BRCMF_FW_TYPE_TRXS: if (fw) cur->binary = fw; else @@ -681,6 +683,14 @@ static void brcmf_fw_request_done(const struct firmware *fw, void *ctx) char alt_path[BRCMF_FW_NAME_LEN]; int ret; + if (!fw && cur->type == BRCMF_FW_TYPE_TRXS) { + strscpy(alt_path, cur->path, BRCMF_FW_NAME_LEN); + /* strip 'se' from .trxse at the end */ + //alt_path[strlen(alt_path) - ] = 0; + ret = request_firmware(&fw, alt_path, fwctx->dev); + if (!ret) + cur->path = alt_path; + } if (!fw && cur->type == BRCMF_FW_TYPE_TRXSE) { strlcpy(alt_path, cur->path, BRCMF_FW_NAME_LEN); /* strip 'se' from .trxse at the end */ @@ -726,9 +736,11 @@ static void brcmf_fw_request_done_alt_path(const struct firmware *fw, void *ctx) if (!alt_path) goto fallback; - ret = request_firmware_nowait(THIS_MODULE, true, alt_path, - fwctx->dev, GFP_KERNEL, fwctx, - brcmf_fw_request_done_alt_path); + if (!fw) { + ret = request_firmware_nowait(THIS_MODULE, true, alt_path, + fwctx->dev, GFP_KERNEL, fwctx, + brcmf_fw_request_done_alt_path); + } kfree(alt_path); if (ret < 0) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h index 4e910f325f4a..2a74e4b00347 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h @@ -43,10 +43,15 @@ static const char BRCM_ ## fw_name ## _FIRMWARE_BASENAME[] = \ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw_base ".bin"); \ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw_base ".clm_blob") +#define CY_FW_BL_DEF(bl_name, fw_base) \ +static const char BRCM_ ## bl_name ## _FIRMWARE_BASENAME[] = \ + CY_FW_DEFAULT_PATH fw_base; \ +MODULE_FIRMWARE(CY_FW_DEFAULT_PATH fw_base ".bin") + #define CY_FW_DEF(fw_name, fw_base) \ static const char BRCM_ ## fw_name ## _FIRMWARE_BASENAME[] = \ CY_FW_DEFAULT_PATH fw_base; \ -MODULE_FIRMWARE(CY_FW_DEFAULT_PATH fw_base ".bin") +MODULE_FIRMWARE(CY_FW_DEFAULT_PATH fw_base ".trxs") #define CY_FW_TRXSE_DEF(fw_name, fw_base) \ static const char BRCM_ ## fw_name ## _FIRMWARE_BASENAME[] = \ @@ -61,7 +66,8 @@ void brcmf_fw_nvram_free(void *nvram); enum brcmf_fw_type { BRCMF_FW_TYPE_BINARY, BRCMF_FW_TYPE_NVRAM, - BRCMF_FW_TYPE_TRXSE + BRCMF_FW_TYPE_TRXSE, + BRCMF_FW_TYPE_TRXS }; struct brcmf_fw_item { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 47612b6c6ad7..b71f48bdcbbb 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -3926,34 +3926,56 @@ brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr, } #endif /* DEBUG */ +/* In 43022:secure-mode TRX header should be copied at 512Kb RAM location + * Because for CM3 based chip rtecdc.bin(fw) should be at starting of RAM + */ +#define TRX_HDR_START_ADDR 0x7fd4c /* TRX header start address */ +#define TRX_HDR_SZ 0x2b4 /* TRX header size */ + static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus, const struct firmware *fw) { struct trx_header_le *trx = (struct trx_header_le *)fw->data; u32 fw_size; u32 address; + u8 *image = NULL; int err; brcmf_dbg(TRACE, "Enter\n"); address = bus->ci->rambase; fw_size = fw->size; - if (trx->magic == cpu_to_le32(TRX_MAGIC)) { - address -= sizeof(struct trx_header_le); - fw_size = le32_to_cpu(trx->len); + + if (bus->ci->blhs && bus->ci->chip == CY_CC_43022_CHIP_ID) { + if (trx->magic == cpu_to_le32(TRX_MAGIC)) { + err = brcmf_sdiod_ramrw(bus->sdiodev, true, TRX_HDR_START_ADDR, + (u8 *)fw->data, sizeof(struct trx_header_le)); + fw_size -= sizeof(struct trx_header_le); + image = fw->data; + image = image + TRX_HDR_SZ; + } + } else { + if (trx->magic == cpu_to_le32(TRX_MAGIC)) { + address -= sizeof(struct trx_header_le); + fw_size = le32_to_cpu(trx->len); + } } + err = brcmf_sdiod_ramrw(bus->sdiodev, true, address, - (u8 *)fw->data, fw_size); + image, fw_size); if (err) brcmf_err("error %d on writing %d membytes at 0x%08x\n", err, (int)fw_size, address); else if (!brcmf_sdio_verifymemory(bus->sdiodev, address, - (u8 *)fw->data, fw_size)) + image, fw_size)) err = -EIO; return err; } +/* In 43022:secure-mode NVRAM should be copied to 512KB RAM area */ +#define NVRAM_DL_ADDR 0x80000 + static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus, void *vars, u32 varsz) { @@ -3991,7 +4013,50 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, rstvec = get_unaligned_le32(fw->data); brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec); - if (bus->ci->blhs) { + if (bus->ci->blhs && bus->ci->chip == CY_CC_43022_CHIP_ID) { + bcmerror = bus->ci->blhs->pre_nvramdl(bus->ci); + if (bcmerror) { + brcmf_err("NVRAM download preparation failed\n"); + goto err; + } + + bcmerror = brcmf_sdio_download_nvram(bus, nvram, nvlen); + if (bcmerror) { + brcmf_err("dongle nvram file download failed\n"); + goto err; + } + + bus->ci->blhs->post_nvramdl(bus->ci); + + bcmerror = bus->ci->blhs->prep_fwdl(bus->ci); + + bcmerror = brcmf_sdio_download_code_file(bus, fw); + release_firmware(fw); + if (bcmerror) { + brcmf_err("dongle image file download failed\n"); + brcmf_fw_nvram_free(nvram); + goto err; + } + + bcmerror = bus->ci->blhs->post_fwdl(bus->ci); + if (bcmerror) { + brcmf_err("FW download failed, err=%d\n", bcmerror); + brcmf_fw_nvram_free(nvram); + goto err; + } + + bcmerror = bus->ci->blhs->chk_validation(bus->ci); + if (bcmerror) { + brcmf_err("FW validation failed, err=%d\n", bcmerror); + brcmf_fw_nvram_free(nvram); + goto err; + } +#ifdef DEBUG + brcmf_sdio_bus_sleep(bus, false, false); + if (brcmf_sdio_readconsole(bus) < 0) + brcmf_err("Console buffer read failed\n"); +#endif /* DEBUG */ + } else if (bus->ci->blhs) { bcmerror = bus->ci->blhs->prep_fwdl(bus->ci); if (bcmerror) { brcmf_err("FW download preparation failed\n"); @@ -4001,15 +4066,17 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, } } - bcmerror = brcmf_sdio_download_code_file(bus, fw); - release_firmware(fw); - if (bcmerror) { - brcmf_err("dongle image file download failed\n"); - brcmf_fw_nvram_free(nvram); - goto err; + if (bus->ci->chip == CY_CC_43022_CHIP_ID && !(bus->ci->blhs)) { + bcmerror = brcmf_sdio_download_code_file(bus, fw); + release_firmware(fw); + if (bcmerror) { + brcmf_err("dongle image file download failed\n"); + brcmf_fw_nvram_free(nvram); + goto err; + } } - if (bus->ci->blhs) { + if (bus->ci->blhs && (!(bus->ci->chip == CY_CC_43022_CHIP_ID))) { bcmerror = bus->ci->blhs->post_fwdl(bus->ci); if (bcmerror) { brcmf_err("FW download failed, err=%d\n", bcmerror); @@ -4024,15 +4091,18 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, goto err; } } - - bcmerror = brcmf_sdio_download_nvram(bus, nvram, nvlen); - brcmf_fw_nvram_free(nvram); - if (bcmerror) { - brcmf_err("dongle nvram file download failed\n"); - goto err; + if (bus->ci->chip == CY_CC_43022_CHIP_ID && !(bus->ci->blhs)) { + bcmerror = brcmf_sdio_download_nvram(bus, nvram, nvlen); + brcmf_fw_nvram_free(nvram); + if (bcmerror) { + brcmf_err("dongle nvram file download failed\n"); + goto err; + } } - if (bus->ci->blhs) { + if (bus->ci->blhs && bus->ci->chip == CY_CC_43022_CHIP_ID) { + brcmf_err("Avoid resetting ARM in 43022 secured chip\n"); + } else if (bus->ci->blhs && (!(bus->ci->chip == CY_CC_43022_CHIP_ID))) { bus->ci->blhs->post_nvramdl(bus->ci); } else { /* Take arm out of reset */ @@ -4041,7 +4111,6 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, goto err; } } - err: brcmf_sdio_clkctl(bus, CLK_SDONLY, false); sdio_release_host(bus->sdiodev->func1); @@ -4667,10 +4736,30 @@ brcmf_sdio_buscore_sec_attach(void *ctx, struct brcmf_blhs **blhs, struct brcmf_ u32 reg_addr; u32 regdata; u8 cardcap; + int err = 0, secure_mode; - if (sdiodev->func1->vendor != SDIO_VENDOR_ID_CYPRESS) + if (sdiodev->func1->vendor != SDIO_VENDOR_ID_CYPRESS && + sdiodev->func1->vendor != SDIO_VENDOR_ID_BROADCOM) return 0; + /* 43022: Secure-mode OTP bit reading */ + secure_mode = !brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_SECURE_MODE, &err); + if (err) + brcmf_err("Failed to read SecureModeRegister = %d\n", err); + + if (secure_mode) { + blhsh = kzalloc(sizeof(*blhsh), GFP_KERNEL); + if (!blhsh) + return -ENOMEM; + /* TODO : Get the address from si_backplane */ + blhsh->d2h = BRCMF_SDIO_REG_D2H_MSG_0; + blhsh->h2d = BRCMF_SDIO_REG_H2D_MSG_0; + blhsh->read = brcmf_sdio_buscore_read32; + blhsh->write = brcmf_sdio_buscore_write32; + + *blhs = blhsh; + } + cardcap = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_BRCM_CARDCAP, NULL); if (cardcap & SDIO_CCCR_BRCM_CARDCAP_SECURE_MODE) { blhsh = kzalloc(sizeof(*blhsh), GFP_KERNEL); @@ -4721,6 +4810,37 @@ static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = { .sec_attach = brcmf_sdio_buscore_sec_attach, }; +#define LOOP_TO_CHECK_FOR_BP_ENABLE 500 /* Wait for 500msec */ + +int brcmf_get_intr_pending_data(void *ctx) +{ + struct brcmf_sdio_dev *sdiodev = (struct brcmf_sdio_dev *)ctx; + int loop = 0, status = 0, err = 0; + u32 reg_val = 0; + + for (loop == 0; loop < LOOP_TO_CHECK_FOR_BP_ENABLE; loop++) { + sdio_claim_host(sdiodev->func1); + reg_val = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_INTx, &err); + sdio_release_host(sdiodev->func1); + status = reg_val & INTR_STATUS_FUNC1; + + if (status) { + brcmf_err("[%d]: Backplane enabled.\n", loop); + break; + } + udelay(10); + } + + /* Bootloader hung after backplane disable */ + if (loop == LOOP_TO_CHECK_FOR_BP_ENABLE) { + err = -EBUSY; + brcmf_err("Device hung, return failure.\n"); + } + + brcmf_err("intr pending err= %d\n", err); + return 0; +} + static bool brcmf_sdio_probe_attach(struct brcmf_sdio *bus) { @@ -5357,14 +5477,11 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus) { struct brcmf_fw_request *fwreq; struct brcmf_fw_name fwnames[] = { - { ".bin", bus->sdiodev->fw_name }, + { ".trxs", bus->sdiodev->fw_name }, { ".txt", bus->sdiodev->nvram_name }, { ".clm_blob", bus->sdiodev->clm_name }, }; - if (bus->ci->blhs) - fwnames[BRCMF_SDIO_FW_CODE].extension = ".trxse"; - fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev, brcmf_sdio_fwnames, ARRAY_SIZE(brcmf_sdio_fwnames), @@ -5372,10 +5489,14 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus) if (!fwreq) return NULL; - if (bus->ci->blhs) - fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_TRXSE; - else + if (bus->ci->blhs) { + if (bus->ci->chip == CY_CC_43022_CHIP_ID) + fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_TRXS; + else + fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_TRXSE; + } else { fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY; + } fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM; fwreq->items[BRCMF_SDIO_FW_CLM].type = BRCMF_FW_TYPE_BINARY; fwreq->items[BRCMF_SDIO_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h index c79f96ad391f..fd7f1c9e223d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h @@ -49,6 +49,7 @@ /* function 0 vendor specific CCCR registers */ +#define SDIO_CCCR_INTR_PND 0x05 #define SDIO_CCCR_BRCM_CARDCAP 0xf0 #define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT BIT(1) #define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT BIT(2) -- 2.25.1