brcmfmac: Update pcie reset device routine.
authorHante Meuleman <meuleman@broadcom.com>
Wed, 30 Jul 2014 11:20:05 +0000 (13:20 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 31 Jul 2014 17:45:27 +0000 (13:45 -0400)
When a pcie device gets reset then the low power modes l1 and l2
should be temporarily disabled.

Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/brcm80211/brcmfmac/pcie.c

index 89be96d3b6e964665ff4e649478d2b3053a1de0b..bc972c0ba5f89a2e4a9f0ca44902bf40e4de16cf 100644 (file)
@@ -168,6 +168,20 @@ enum brcmf_pcie_state {
 
 #define BRCMF_PCIE_MBDATA_TIMEOUT              2000
 
+#define BRCMF_PCIE_CFGREG_STATUS_CMD           0x4
+#define BRCMF_PCIE_CFGREG_PM_CSR               0x4C
+#define BRCMF_PCIE_CFGREG_MSI_CAP              0x58
+#define BRCMF_PCIE_CFGREG_MSI_ADDR_L           0x5C
+#define BRCMF_PCIE_CFGREG_MSI_ADDR_H           0x60
+#define BRCMF_PCIE_CFGREG_MSI_DATA             0x64
+#define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL     0xBC
+#define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2    0xDC
+#define BRCMF_PCIE_CFGREG_RBAR_CTRL            0x228
+#define BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1       0x248
+#define BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG      0x4E0
+#define BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG      0x4F4
+#define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB  3
+
 
 MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME);
 MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME);
@@ -423,21 +437,42 @@ brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid)
 }
 
 
-static void brcmf_pcie_detach(struct brcmf_pciedev_info *devinfo)
+static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
 {
-       u16 cfg_offset[] = { 0x4,  0x4C, 0x58, 0x5C, 0x60, 0x64, 0xDC, 0x228,
-                            0x248,  0x4e0, 0x4f4 };
+       u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD,
+                            BRCMF_PCIE_CFGREG_PM_CSR,
+                            BRCMF_PCIE_CFGREG_MSI_CAP,
+                            BRCMF_PCIE_CFGREG_MSI_ADDR_L,
+                            BRCMF_PCIE_CFGREG_MSI_ADDR_H,
+                            BRCMF_PCIE_CFGREG_MSI_DATA,
+                            BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2,
+                            BRCMF_PCIE_CFGREG_RBAR_CTRL,
+                            BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1,
+                            BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG,
+                            BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG };
        u32 i;
        u32 val;
+       u32 lsc;
 
        if (!devinfo->ci)
                return;
 
-       brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);
-       WRITECC32(devinfo, watchdog, 0x4e0);
+       brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+       brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+                              BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
+       lsc = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+       val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB);
+       brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, val);
 
+       brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);
+       WRITECC32(devinfo, watchdog, 4);
        msleep(100);
 
+       brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+       brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+                              BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
+       brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, lsc);
+
        brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
        for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
                brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
@@ -458,7 +493,7 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
 
        brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
        if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0)
-               brcmf_pcie_detach(devinfo);
+               brcmf_pcie_reset_device(devinfo);
        /* BAR1 window may not be sized properly */
        brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
        brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
@@ -1686,7 +1721,7 @@ brcmf_pcie_remove(struct pci_dev *pdev)
        brcmf_pcie_release_irq(devinfo);
        brcmf_pcie_release_scratchbuffers(devinfo);
        brcmf_pcie_release_ringbuffers(devinfo);
-       brcmf_pcie_detach(devinfo);
+       brcmf_pcie_reset_device(devinfo);
        brcmf_pcie_release_resource(devinfo);
 
        if (devinfo->ci)