ath10k-firmware: remove dependency on kmod-ath10k so that it can be selected instead
[15.05/openwrt.git] / package / kernel / mac80211 / patches / 366-brcmfmac-Reset-PCIE-devices-after-recognition.patch
1 From: Hante Meuleman <meuleman@broadcom.com>
2 Date: Thu, 27 Aug 2015 16:14:06 +0200
3 Subject: [PATCH] brcmfmac: Reset PCIE devices after recognition.
4
5 When PCIE type devices are being FW reloaded without being properly
6 reset then the device ends up in a locked state, requiring the
7 device to be completely powered down. This patch adds a reset
8 through watchdog at the moment the device (cores) has been
9 recognized. This will solve warm reboot issues.
10
11 Cc: Rafal Milecki <zajec5@gmail.com>
12 Reviewed-by: Arend Van Spriel <arend@broadcom.com>
13 Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
14 Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
15 Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
16 Signed-off-by: Arend van Spriel <arend@broadcom.com>
17 ---
18
19 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
20 +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
21 @@ -101,6 +101,9 @@
22  /* ARM Cortex M3 core, ID 0x82a */
23  #define BCM4329_CORE_ARM_BASE          0x18002000
24  
25 +/* Max possibly supported memory size (limited by IO mapped memory) */
26 +#define BRCMF_CHIP_MAX_MEMSIZE         (4 * 1024 * 1024)
27 +
28  #define CORE_SB(base, field) \
29                 (base + SBCONFIGOFF + offsetof(struct sbconfig, field))
30  #define        SBCOREREV(sbidh) \
31 @@ -687,6 +690,12 @@ static int brcmf_chip_get_raminfo(struct
32                 brcmf_err("RAM size is undetermined\n");
33                 return -ENOMEM;
34         }
35 +
36 +       if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) {
37 +               brcmf_err("RAM size is incorrect\n");
38 +               return -ENOMEM;
39 +       }
40 +
41         return 0;
42  }
43  
44 @@ -899,6 +908,15 @@ static int brcmf_chip_recognition(struct
45  
46         /* assure chip is passive for core access */
47         brcmf_chip_set_passive(&ci->pub);
48 +
49 +       /* Call bus specific reset function now. Cores have been determined
50 +        * but further access may require a chip specific reset at this point.
51 +        */
52 +       if (ci->ops->reset) {
53 +               ci->ops->reset(ci->ctx, &ci->pub);
54 +               brcmf_chip_set_passive(&ci->pub);
55 +       }
56 +
57         return brcmf_chip_get_raminfo(ci);
58  }
59  
60 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h
61 +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h
62 @@ -73,6 +73,7 @@ struct brcmf_buscore_ops {
63         u32 (*read32)(void *ctx, u32 addr);
64         void (*write32)(void *ctx, u32 addr, u32 value);
65         int (*prepare)(void *ctx);
66 +       int (*reset)(void *ctx, struct brcmf_chip *chip);
67         int (*setup)(void *ctx, struct brcmf_chip *chip);
68         void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
69  };
70 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
71 +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
72 @@ -74,6 +74,8 @@ enum brcmf_pcie_state {
73  #define BRCMF_PCIE_REG_INTMASK                 0x94
74  #define BRCMF_PCIE_REG_SBMBX                   0x98
75  
76 +#define BRCMF_PCIE_REG_LINK_STATUS_CTRL                0xBC
77 +
78  #define BRCMF_PCIE_PCIE2REG_INTMASK            0x24
79  #define BRCMF_PCIE_PCIE2REG_MAILBOXINT         0x48
80  #define BRCMF_PCIE_PCIE2REG_MAILBOXMASK                0x4C
81 @@ -466,6 +468,7 @@ brcmf_pcie_select_core(struct brcmf_pcie
82  
83  static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
84  {
85 +       struct brcmf_core *core;
86         u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD,
87                              BRCMF_PCIE_CFGREG_PM_CSR,
88                              BRCMF_PCIE_CFGREG_MSI_CAP,
89 @@ -484,32 +487,38 @@ static void brcmf_pcie_reset_device(stru
90         if (!devinfo->ci)
91                 return;
92  
93 +       /* Disable ASPM */
94         brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
95 -       brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
96 -                              BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
97 -       lsc = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
98 +       pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
99 +                             &lsc);
100         val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB);
101 -       brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, val);
102 +       pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
103 +                              val);
104  
105 +       /* Watchdog reset */
106         brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);
107         WRITECC32(devinfo, watchdog, 4);
108         msleep(100);
109  
110 +       /* Restore ASPM */
111         brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
112 -       brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
113 -                              BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
114 -       brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, lsc);
115 +       pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
116 +                              lsc);
117  
118 -       brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
119 -       for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
120 -               brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
121 -                                      cfg_offset[i]);
122 -               val = brcmf_pcie_read_reg32(devinfo,
123 -                                           BRCMF_PCIE_PCIE2REG_CONFIGDATA);
124 -               brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
125 -                         cfg_offset[i], val);
126 -               brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA,
127 -                                      val);
128 +       core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
129 +       if (core->rev <= 13) {
130 +               for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
131 +                       brcmf_pcie_write_reg32(devinfo,
132 +                                              BRCMF_PCIE_PCIE2REG_CONFIGADDR,
133 +                                              cfg_offset[i]);
134 +                       val = brcmf_pcie_read_reg32(devinfo,
135 +                               BRCMF_PCIE_PCIE2REG_CONFIGDATA);
136 +                       brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
137 +                                 cfg_offset[i], val);
138 +                       brcmf_pcie_write_reg32(devinfo,
139 +                                              BRCMF_PCIE_PCIE2REG_CONFIGDATA,
140 +                                              val);
141 +               }
142         }
143  }
144  
145 @@ -519,8 +528,6 @@ static void brcmf_pcie_attach(struct brc
146         u32 config;
147  
148         brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
149 -       if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0)
150 -               brcmf_pcie_reset_device(devinfo);
151         /* BAR1 window may not be sized properly */
152         brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
153         brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
154 @@ -1636,6 +1643,23 @@ static int brcmf_pcie_buscoreprep(void *
155  }
156  
157  
158 +static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
159 +{
160 +       struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
161 +       u32 val;
162 +
163 +       devinfo->ci = chip;
164 +       brcmf_pcie_reset_device(devinfo);
165 +
166 +       val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
167 +       if (val != 0xffffffff)
168 +               brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
169 +                                      val);
170 +
171 +       return 0;
172 +}
173 +
174 +
175  static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip,
176                                         u32 rstvec)
177  {
178 @@ -1647,6 +1671,7 @@ static void brcmf_pcie_buscore_activate(
179  
180  static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
181         .prepare = brcmf_pcie_buscoreprep,
182 +       .reset = brcmf_pcie_buscore_reset,
183         .activate = brcmf_pcie_buscore_activate,
184         .read32 = brcmf_pcie_buscore_read32,
185         .write32 = brcmf_pcie_buscore_write32,
186 @@ -1814,7 +1839,6 @@ brcmf_pcie_remove(struct pci_dev *pdev)
187                 brcmf_pcie_intr_disable(devinfo);
188  
189         brcmf_detach(&pdev->dev);
190 -       brcmf_pcie_reset_device(devinfo);
191  
192         kfree(bus->bus_priv.pcie);
193         kfree(bus->msgbuf->flowrings);