mt76: update to the latest version
[oweals/openwrt.git] / package / kernel / mac80211 / patches / 311-v4.16-0007-brcmfmac-Remove-brcmf_sdiod_request_data.patch
1 From 993a98a42e6e790fd0d2bf7d55a031513c7ba7dc Mon Sep 17 00:00:00 2001
2 From: Ian Molton <ian@mnementh.co.uk>
3 Date: Mon, 13 Nov 2017 21:35:44 +0100
4 Subject: [PATCH] brcmfmac: Remove brcmf_sdiod_request_data()
5
6 This function is obfuscating how IO works on this chip. Remove it
7 and push its logic into brcmf_sdiod_reg_{read,write}().
8
9 Handling of -ENOMEDIUM is altered, but as that's pretty much broken anyway
10 we can ignore that.
11
12 Signed-off-by: Ian Molton <ian@mnementh.co.uk>
13 Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
14 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
15 ---
16  .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c  | 237 ++++++++-------------
17  .../wireless/broadcom/brcm80211/brcmfmac/sdio.h    |   2 +-
18  2 files changed, 87 insertions(+), 152 deletions(-)
19
20 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
21 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
22 @@ -230,6 +230,43 @@ void brcmf_sdiod_change_state(struct brc
23         sdiodev->state = state;
24  }
25  
26 +static int brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev,
27 +                                        u32 address)
28 +{
29 +       int err = 0, i;
30 +       u32 addr;
31 +
32 +       if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
33 +               return -ENOMEDIUM;
34 +
35 +       addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
36 +
37 +       for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
38 +               brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
39 +                                 addr & 0xff, &err);
40 +
41 +       return err;
42 +}
43 +
44 +static int brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
45 +{
46 +       uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
47 +       int err = 0;
48 +
49 +       if (bar0 != sdiodev->sbwad) {
50 +               err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
51 +               if (err)
52 +                       return err;
53 +
54 +               sdiodev->sbwad = bar0;
55 +       }
56 +
57 +       *addr &= SBSDIO_SB_OFT_ADDR_MASK;
58 +       *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
59 +
60 +       return 0;
61 +}
62 +
63  static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte,
64                                         uint regaddr)
65  {
66 @@ -249,173 +286,84 @@ static inline int brcmf_sdiod_f0_writeb(
67         return err_ret;
68  }
69  
70 -static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn,
71 -                                   u32 addr, u8 regsz, void *data, bool write)
72 -{
73 -       struct sdio_func *func;
74 -       int ret = -EINVAL;
75 -
76 -       brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
77 -                 write, fn, addr, regsz);
78 -
79 -       /* only allow byte access on F0 */
80 -       if (WARN_ON(regsz > 1 && !fn))
81 -               return -EINVAL;
82 -       func = sdiodev->func[fn];
83 -
84 -       switch (regsz) {
85 -       case 1:
86 -               if (write) {
87 -                       if (fn)
88 -                               sdio_writeb(func, *(u8 *)data, addr, &ret);
89 -                       else
90 -                               ret = brcmf_sdiod_f0_writeb(func, *(u8 *)data,
91 -                                                           addr);
92 -               } else {
93 -                       if (fn)
94 -                               *(u8 *)data = sdio_readb(func, addr, &ret);
95 -                       else
96 -                               *(u8 *)data = sdio_f0_readb(func, addr, &ret);
97 -               }
98 -               break;
99 -       case 2:
100 -               if (write)
101 -                       sdio_writew(func, *(u16 *)data, addr, &ret);
102 -               else
103 -                       *(u16 *)data = sdio_readw(func, addr, &ret);
104 -               break;
105 -       case 4:
106 -               if (write)
107 -                       sdio_writel(func, *(u32 *)data, addr, &ret);
108 -               else
109 -                       *(u32 *)data = sdio_readl(func, addr, &ret);
110 -               break;
111 -       default:
112 -               brcmf_err("invalid size: %d\n", regsz);
113 -               break;
114 -       }
115 -
116 -       if (ret)
117 -               brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n",
118 -                         write ? "write" : "read", fn, addr, ret);
119 -
120 -       return ret;
121 -}
122 -
123  static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr,
124                                  u8 regsz, void *data)
125  {
126 -       u8 func;
127 -       s32 retry = 0;
128         int ret;
129  
130 -       if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
131 -               return -ENOMEDIUM;
132 -
133         /*
134          * figure out how to read the register based on address range
135          * 0x00 ~ 0x7FF: function 0 CCCR and FBR
136          * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
137          * The rest: function 1 silicon backplane core registers
138 +        * f0 writes must be bytewise
139          */
140 -       if ((addr & ~REG_F0_REG_MASK) == 0)
141 -               func = SDIO_FUNC_0;
142 -       else
143 -               func = SDIO_FUNC_1;
144  
145 -       do {
146 -               /* for retry wait for 1 ms till bus get settled down */
147 -               if (retry)
148 -                       usleep_range(1000, 2000);
149 -
150 -               ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
151 -                                              data, true);
152 -
153 -       } while (ret != 0 && ret != -ENOMEDIUM &&
154 -                retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
155 +       if ((addr & ~REG_F0_REG_MASK) == 0) {
156 +               if (WARN_ON(regsz > 1))
157 +                       return -EINVAL;
158 +               ret = brcmf_sdiod_f0_writeb(sdiodev->func[0],
159 +                                           *(u8 *)data, addr);
160 +       } else {
161 +               switch (regsz) {
162 +               case 1:
163 +                       sdio_writeb(sdiodev->func[1], *(u8 *)data, addr, &ret);
164 +                       break;
165 +               case 4:
166 +                       ret = brcmf_sdiod_addrprep(sdiodev, &addr);
167 +                       if (ret)
168 +                               goto done;
169  
170 -       if (ret == -ENOMEDIUM)
171 -               brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
172 +                       sdio_writel(sdiodev->func[1], *(u32 *)data, addr, &ret);
173 +                       break;
174 +               default:
175 +                       WARN(1, "Invalid reg size\n");
176 +                       ret = -EINVAL;
177 +                       break;
178 +               }
179 +       }
180  
181 +done:
182         return ret;
183  }
184  
185  static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr,
186                                 u8 regsz, void *data)
187  {
188 -       u8 func;
189 -       s32 retry = 0;
190         int ret;
191  
192 -       if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
193 -               return -ENOMEDIUM;
194 -
195         /*
196          * figure out how to read the register based on address range
197          * 0x00 ~ 0x7FF: function 0 CCCR and FBR
198          * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
199          * The rest: function 1 silicon backplane core registers
200 +        * f0 reads must be bytewise
201          */
202 -       if ((addr & ~REG_F0_REG_MASK) == 0)
203 -               func = SDIO_FUNC_0;
204 -       else
205 -               func = SDIO_FUNC_1;
206 -
207 -       do {
208 -               memset(data, 0, regsz);
209 -
210 -               /* for retry wait for 1 ms till bus get settled down */
211 -               if (retry)
212 -                       usleep_range(1000, 2000);
213 -
214 -               ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
215 -                                              data, false);
216 -
217 -       } while (ret != 0 && ret != -ENOMEDIUM &&
218 -                retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
219 -
220 -       if (ret == -ENOMEDIUM)
221 -               brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
222 -
223 -       return ret;
224 -}
225 -
226 -static int
227 -brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
228 -{
229 -       int err = 0, i;
230 -       u32 addr;
231 -
232 -       if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
233 -               return -ENOMEDIUM;
234 -
235 -       addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
236 -
237 -       for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
238 -               brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
239 -                                 addr & 0xff, &err);
240 -
241 -       return err;
242 -}
243 -
244 -static int
245 -brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
246 -{
247 -       uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
248 -       int err = 0;
249 -
250 -       if (bar0 != sdiodev->sbwad) {
251 -               err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
252 -               if (err)
253 -                       return err;
254 +       if ((addr & ~REG_F0_REG_MASK) == 0) {
255 +               if (WARN_ON(regsz > 1))
256 +                       return -EINVAL;
257 +               *(u8 *)data = sdio_f0_readb(sdiodev->func[0], addr, &ret);
258 +       } else {
259 +               switch (regsz) {
260 +               case 1:
261 +                       *(u8 *)data = sdio_readb(sdiodev->func[1], addr, &ret);
262 +                       break;
263 +               case 4:
264 +                       ret = brcmf_sdiod_addrprep(sdiodev, &addr);
265 +                       if (ret)
266 +                               goto done;
267  
268 -               sdiodev->sbwad = bar0;
269 +                       *(u32 *)data = sdio_readl(sdiodev->func[1], addr, &ret);
270 +                       break;
271 +               default:
272 +                       WARN(1, "Invalid reg size\n");
273 +                       ret = -EINVAL;
274 +                       break;
275 +               }
276         }
277  
278 -       *addr &= SBSDIO_SB_OFT_ADDR_MASK;
279 -       *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
280 -
281 -       return 0;
282 +done:
283 +       return ret;
284  }
285  
286  u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
287 @@ -439,15 +387,9 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
288         int retval;
289  
290         brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
291 -       retval = brcmf_sdiod_addrprep(sdiodev, &addr);
292 -       if (retval)
293 -               goto done;
294 -
295         retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data);
296 -
297         brcmf_dbg(SDIO, "data:0x%08x\n", data);
298  
299 -done:
300         if (ret)
301                 *ret = retval;
302  
303 @@ -472,13 +414,8 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
304         int retval;
305  
306         brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
307 -       retval = brcmf_sdiod_addrprep(sdiodev, &addr);
308 -       if (retval)
309 -               goto done;
310 -
311         retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data);
312  
313 -done:
314         if (ret)
315                 *ret = retval;
316  }
317 @@ -886,14 +823,12 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
318         return bcmerror;
319  }
320  
321 -int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
322 +int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn)
323  {
324 -       char t_func = (char)fn;
325         brcmf_dbg(SDIO, "Enter\n");
326  
327         /* issue abort cmd52 command through F0 */
328 -       brcmf_sdiod_request_data(sdiodev, SDIO_FUNC_0, SDIO_CCCR_ABORT,
329 -                                1, &t_func, true);
330 +       brcmf_sdiod_reg_write(sdiodev, SDIO_CCCR_ABORT, 1, &fn);
331  
332         brcmf_dbg(SDIO, "Exit\n");
333         return 0;
334 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
335 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
336 @@ -339,7 +339,7 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_
337                       u8 *data, uint size);
338  
339  /* Issue an abort to the specified function */
340 -int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
341 +int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn);
342  void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
343  void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
344                               enum brcmf_sdiod_state state);