Skip to content

Commit 52b2c2a

Browse files
marcanjannau
authored andcommitted
wifi: brcmfmac: Support exchanging power mailbox messages via commonring
Newer firmwares have switched from using the hardware mailbox to commonring messages for power mailbox data. Implement this, which makes D3 work on WiFi chipsets in Apple devices. This is only enabled on v6 or newer, iff BRCMF_PCIE_SHARED_USE_MAILBOX is not set in the flags. Signed-off-by: Hector Martin <marcan@marcan.st>
1 parent fbcc6bf commit 52b2c2a

1 file changed

Lines changed: 55 additions & 20 deletions

File tree

  • drivers/net/wireless/broadcom/brcm80211/brcmfmac

drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ struct brcmf_pcie_shared_info {
375375
void *ringupd;
376376
dma_addr_t ringupd_dmahandle;
377377
u8 version;
378+
bool mb_via_ctl;
378379
};
379380

380381
#define BRCMF_OTP_MAX_PARAM_LEN 16
@@ -824,6 +825,19 @@ brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)
824825
u32 i;
825826

826827
shared = &devinfo->shared;
828+
829+
if (shared->mb_via_ctl) {
830+
struct pci_dev *pdev = devinfo->pdev;
831+
struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
832+
int ret;
833+
834+
ret = brcmf_msgbuf_h2d_mb_write(bus->drvr, htod_mb_data);
835+
if (ret < 0)
836+
brcmf_err(bus, "Failed to send H2D mailbox data (%d)\n",
837+
ret);
838+
return ret;
839+
}
840+
827841
addr = shared->htod_mb_data_addr;
828842
cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
829843

@@ -851,8 +865,29 @@ brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)
851865
return 0;
852866
}
853867

868+
static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo, u32 data)
869+
{
870+
brcmf_dbg(PCIE, "D2H_MB_DATA: 0x%04x\n", data);
871+
if (data & BRCMF_D2H_DEV_DS_ENTER_REQ) {
872+
brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP REQ\n");
873+
brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_DS_ACK);
874+
brcmf_dbg(PCIE, "D2H_MB_DATA: sent DEEP SLEEP ACK\n");
875+
}
876+
if (data & BRCMF_D2H_DEV_DS_EXIT_NOTE)
877+
brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP EXIT\n");
878+
if (data & BRCMF_D2H_DEV_D3_ACK) {
879+
brcmf_dbg(PCIE, "D2H_MB_DATA: D3 ACK\n");
880+
devinfo->mbdata_completed = true;
881+
wake_up(&devinfo->mbdata_resp_wait);
882+
}
883+
if (data & BRCMF_D2H_DEV_FWHALT) {
884+
brcmf_dbg(PCIE, "D2H_MB_DATA: FW HALT\n");
885+
brcmf_fw_crashed(&devinfo->pdev->dev);
886+
}
887+
}
888+
854889

855-
static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo)
890+
static void brcmf_pcie_poll_mb_data(struct brcmf_pciedev_info *devinfo)
856891
{
857892
struct brcmf_pcie_shared_info *shared;
858893
u32 addr;
@@ -867,23 +902,16 @@ static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo)
867902

868903
brcmf_pcie_write_tcm32(devinfo, addr, 0);
869904

870-
brcmf_dbg(PCIE, "D2H_MB_DATA: 0x%04x\n", dtoh_mb_data);
871-
if (dtoh_mb_data & BRCMF_D2H_DEV_DS_ENTER_REQ) {
872-
brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP REQ\n");
873-
brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_DS_ACK);
874-
brcmf_dbg(PCIE, "D2H_MB_DATA: sent DEEP SLEEP ACK\n");
875-
}
876-
if (dtoh_mb_data & BRCMF_D2H_DEV_DS_EXIT_NOTE)
877-
brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP EXIT\n");
878-
if (dtoh_mb_data & BRCMF_D2H_DEV_D3_ACK) {
879-
brcmf_dbg(PCIE, "D2H_MB_DATA: D3 ACK\n");
880-
devinfo->mbdata_completed = true;
881-
wake_up(&devinfo->mbdata_resp_wait);
882-
}
883-
if (dtoh_mb_data & BRCMF_D2H_DEV_FWHALT) {
884-
brcmf_dbg(PCIE, "D2H_MB_DATA: FW HALT\n");
885-
brcmf_fw_crashed(&devinfo->pdev->dev);
886-
}
905+
brcmf_pcie_handle_mb_data(devinfo, dtoh_mb_data);
906+
}
907+
908+
909+
static void brcmf_pcie_d2h_mb_rx(struct device *dev, u32 data)
910+
{
911+
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
912+
struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
913+
914+
brcmf_pcie_handle_mb_data(buspub->devinfo, data);
887915
}
888916

889917

@@ -1013,7 +1041,7 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
10131041
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint,
10141042
status);
10151043
if (status & devinfo->reginfo->int_fn0)
1016-
brcmf_pcie_handle_mb_data(devinfo);
1044+
brcmf_pcie_poll_mb_data(devinfo);
10171045
}
10181046
if (devinfo->have_msi || status & devinfo->reginfo->int_d2h_db) {
10191047
if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
@@ -1658,6 +1686,7 @@ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
16581686
.get_blob = brcmf_pcie_get_blob,
16591687
.reset = brcmf_pcie_reset,
16601688
.debugfs_create = brcmf_pcie_debugfs_create,
1689+
.d2h_mb_rx = brcmf_pcie_d2h_mb_rx,
16611690
};
16621691

16631692

@@ -1748,6 +1777,10 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
17481777
shared->flags3 = brcmf_pcie_read_tcm32(devinfo, sharedram_addr +
17491778
BRCMF_SHARED_FLAGS3_OFFSET);
17501779

1780+
/* Check which mailbox mechanism to use */
1781+
if (!(shared->flags & BRCMF_PCIE_SHARED_USE_MAILBOX))
1782+
shared->mb_via_ctl = true;
1783+
17511784
/* Update host support flags */
17521785
host_cap = shared->version;
17531786
host_cap2 = 0;
@@ -2770,10 +2803,11 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev)
27702803
/* Check if device is still up and running, if so we are ready */
27712804
if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->intmask) != 0) {
27722805
brcmf_dbg(PCIE, "Try to wakeup device....\n");
2806+
/* Set the device up, so we can write the MB data message in ring mode */
2807+
devinfo->state = BRCMFMAC_PCIE_STATE_UP;
27732808
if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM))
27742809
goto cleanup;
27752810
brcmf_dbg(PCIE, "Hot resume, continue....\n");
2776-
devinfo->state = BRCMFMAC_PCIE_STATE_UP;
27772811
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
27782812
brcmf_bus_change_state(bus, BRCMF_BUS_UP);
27792813
brcmf_pcie_intr_enable(devinfo);
@@ -2783,6 +2817,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev)
27832817
}
27842818

27852819
cleanup:
2820+
devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;
27862821
brcmf_chip_detach(devinfo->ci);
27872822
devinfo->ci = NULL;
27882823
pdev = devinfo->pdev;

0 commit comments

Comments
 (0)