]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
brcmfmac: error messages should not be suppressed
[mirror_ubuntu-artful-kernel.git] / drivers / net / wireless / brcm80211 / brcmfmac / bcmsdh.c
1 /*
2 * Copyright (c) 2010 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16 /* ****************** SDIO CARD Interface Functions **************************/
17
18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
20 #include <linux/types.h>
21 #include <linux/netdevice.h>
22 #include <linux/export.h>
23 #include <linux/pci.h>
24 #include <linux/pci_ids.h>
25 #include <linux/sched.h>
26 #include <linux/completion.h>
27 #include <linux/mmc/sdio.h>
28 #include <linux/mmc/sdio_func.h>
29 #include <linux/mmc/card.h>
30
31 #include <defs.h>
32 #include <brcm_hw_ids.h>
33 #include <brcmu_utils.h>
34 #include <brcmu_wifi.h>
35 #include <soc.h>
36 #include "dhd_bus.h"
37 #include "dhd_dbg.h"
38 #include "sdio_host.h"
39
40 #define SDIOH_API_ACCESS_RETRY_LIMIT 2
41
42 #ifdef CONFIG_BRCMFMAC_SDIO_OOB
43 static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
44 {
45 struct brcmf_bus *bus_if = dev_get_drvdata(dev_id);
46 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
47
48 brcmf_dbg(INTR, "oob intr triggered\n");
49
50 /*
51 * out-of-band interrupt is level-triggered which won't
52 * be cleared until dpc
53 */
54 if (sdiodev->irq_en) {
55 disable_irq_nosync(irq);
56 sdiodev->irq_en = false;
57 }
58
59 brcmf_sdbrcm_isr(sdiodev->bus);
60
61 return IRQ_HANDLED;
62 }
63
64 int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
65 {
66 int ret = 0;
67 u8 data;
68 unsigned long flags;
69
70 brcmf_dbg(TRACE, "Entering: irq %d\n", sdiodev->irq);
71
72 ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
73 sdiodev->irq_flags, "brcmf_oob_intr",
74 &sdiodev->func[1]->dev);
75 if (ret != 0)
76 return ret;
77 spin_lock_init(&sdiodev->irq_en_lock);
78 spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
79 sdiodev->irq_en = true;
80 spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
81
82 ret = enable_irq_wake(sdiodev->irq);
83 if (ret != 0)
84 return ret;
85 sdiodev->irq_wake = true;
86
87 sdio_claim_host(sdiodev->func[1]);
88
89 /* must configure SDIO_CCCR_IENx to enable irq */
90 data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
91 data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
92 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
93
94 /* redirect, configure and enable io for interrupt signal */
95 data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
96 if (sdiodev->irq_flags & IRQF_TRIGGER_HIGH)
97 data |= SDIO_SEPINT_ACT_HI;
98 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
99
100 sdio_release_host(sdiodev->func[1]);
101
102 return 0;
103 }
104
105 int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
106 {
107 brcmf_dbg(TRACE, "Entering\n");
108
109 sdio_claim_host(sdiodev->func[1]);
110 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
111 brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
112 sdio_release_host(sdiodev->func[1]);
113
114 if (sdiodev->irq_wake) {
115 disable_irq_wake(sdiodev->irq);
116 sdiodev->irq_wake = false;
117 }
118 free_irq(sdiodev->irq, &sdiodev->func[1]->dev);
119 sdiodev->irq_en = false;
120
121 return 0;
122 }
123 #else /* CONFIG_BRCMFMAC_SDIO_OOB */
124 static void brcmf_sdio_irqhandler(struct sdio_func *func)
125 {
126 struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev);
127 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
128
129 brcmf_dbg(INTR, "ib intr triggered\n");
130
131 brcmf_sdbrcm_isr(sdiodev->bus);
132 }
133
134 /* dummy handler for SDIO function 2 interrupt */
135 static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func)
136 {
137 }
138
139 int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
140 {
141 brcmf_dbg(TRACE, "Entering\n");
142
143 sdio_claim_host(sdiodev->func[1]);
144 sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler);
145 sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler);
146 sdio_release_host(sdiodev->func[1]);
147
148 return 0;
149 }
150
151 int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
152 {
153 brcmf_dbg(TRACE, "Entering\n");
154
155 sdio_claim_host(sdiodev->func[1]);
156 sdio_release_irq(sdiodev->func[2]);
157 sdio_release_irq(sdiodev->func[1]);
158 sdio_release_host(sdiodev->func[1]);
159
160 return 0;
161 }
162 #endif /* CONFIG_BRCMFMAC_SDIO_OOB */
163
164 int
165 brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
166 {
167 int err = 0, i;
168 u8 addr[3];
169 s32 retry;
170
171 addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK;
172 addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK;
173 addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK;
174
175 for (i = 0; i < 3; i++) {
176 retry = 0;
177 do {
178 if (retry)
179 usleep_range(1000, 2000);
180 err = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE,
181 SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW + i,
182 &addr[i]);
183 } while (err != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
184
185 if (err) {
186 brcmf_err("failed at addr:0x%0x\n",
187 SBSDIO_FUNC1_SBADDRLOW + i);
188 break;
189 }
190 }
191
192 return err;
193 }
194
195 int
196 brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
197 void *data, bool write)
198 {
199 u8 func_num, reg_size;
200 u32 bar;
201 s32 retry = 0;
202 int ret;
203
204 /*
205 * figure out how to read the register based on address range
206 * 0x00 ~ 0x7FF: function 0 CCCR and FBR
207 * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
208 * The rest: function 1 silicon backplane core registers
209 */
210 if ((addr & ~REG_F0_REG_MASK) == 0) {
211 func_num = SDIO_FUNC_0;
212 reg_size = 1;
213 } else if ((addr & ~REG_F1_MISC_MASK) == 0) {
214 func_num = SDIO_FUNC_1;
215 reg_size = 1;
216 } else {
217 func_num = SDIO_FUNC_1;
218 reg_size = 4;
219
220 /* Set the window for SB core register */
221 bar = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
222 if (bar != sdiodev->sbwad) {
223 ret = brcmf_sdcard_set_sbaddr_window(sdiodev, bar);
224 if (ret != 0) {
225 memset(data, 0xFF, reg_size);
226 return ret;
227 }
228 sdiodev->sbwad = bar;
229 }
230 addr &= SBSDIO_SB_OFT_ADDR_MASK;
231 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
232 }
233
234 do {
235 if (!write)
236 memset(data, 0, reg_size);
237 if (retry) /* wait for 1 ms till bus get settled down */
238 usleep_range(1000, 2000);
239 if (reg_size == 1)
240 ret = brcmf_sdioh_request_byte(sdiodev, write,
241 func_num, addr, data);
242 else
243 ret = brcmf_sdioh_request_word(sdiodev, write,
244 func_num, addr, data, 4);
245 } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
246
247 if (ret != 0)
248 brcmf_err("failed with %d\n", ret);
249
250 return ret;
251 }
252
253 u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
254 {
255 u8 data;
256 int retval;
257
258 brcmf_dbg(INFO, "addr:0x%08x\n", addr);
259 retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
260 brcmf_dbg(INFO, "data:0x%02x\n", data);
261
262 if (ret)
263 *ret = retval;
264
265 return data;
266 }
267
268 u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
269 {
270 u32 data;
271 int retval;
272
273 brcmf_dbg(INFO, "addr:0x%08x\n", addr);
274 retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
275 brcmf_dbg(INFO, "data:0x%08x\n", data);
276
277 if (ret)
278 *ret = retval;
279
280 return data;
281 }
282
283 void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
284 u8 data, int *ret)
285 {
286 int retval;
287
288 brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data);
289 retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
290
291 if (ret)
292 *ret = retval;
293 }
294
295 void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
296 u32 data, int *ret)
297 {
298 int retval;
299
300 brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data);
301 retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
302
303 if (ret)
304 *ret = retval;
305 }
306
307 static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn,
308 uint flags, uint width, u32 *addr)
309 {
310 uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
311 int err = 0;
312
313 /* Async not implemented yet */
314 if (flags & SDIO_REQ_ASYNC)
315 return -ENOTSUPP;
316
317 if (bar0 != sdiodev->sbwad) {
318 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
319 if (err)
320 return err;
321
322 sdiodev->sbwad = bar0;
323 }
324
325 *addr &= SBSDIO_SB_OFT_ADDR_MASK;
326
327 if (width == 4)
328 *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
329
330 return 0;
331 }
332
333 int
334 brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
335 uint flags, u8 *buf, uint nbytes)
336 {
337 struct sk_buff *mypkt;
338 int err;
339
340 mypkt = brcmu_pkt_buf_get_skb(nbytes);
341 if (!mypkt) {
342 brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
343 nbytes);
344 return -EIO;
345 }
346
347 err = brcmf_sdcard_recv_pkt(sdiodev, addr, fn, flags, mypkt);
348 if (!err)
349 memcpy(buf, mypkt->data, nbytes);
350
351 brcmu_pkt_buf_free_skb(mypkt);
352 return err;
353 }
354
355 int
356 brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
357 uint flags, struct sk_buff *pkt)
358 {
359 uint incr_fix;
360 uint width;
361 int err = 0;
362
363 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
364 fn, addr, pkt->len);
365
366 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
367 err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
368 if (err)
369 goto done;
370
371 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
372 err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ,
373 fn, addr, pkt);
374
375 done:
376 return err;
377 }
378
379 int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
380 uint flags, struct sk_buff_head *pktq)
381 {
382 uint incr_fix;
383 uint width;
384 int err = 0;
385
386 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
387 fn, addr, pktq->qlen);
388
389 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
390 err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
391 if (err)
392 goto done;
393
394 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
395 err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr,
396 pktq);
397
398 done:
399 return err;
400 }
401
402 int
403 brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
404 uint flags, u8 *buf, uint nbytes)
405 {
406 struct sk_buff *mypkt;
407 int err;
408
409 mypkt = brcmu_pkt_buf_get_skb(nbytes);
410 if (!mypkt) {
411 brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
412 nbytes);
413 return -EIO;
414 }
415
416 memcpy(mypkt->data, buf, nbytes);
417 err = brcmf_sdcard_send_pkt(sdiodev, addr, fn, flags, mypkt);
418
419 brcmu_pkt_buf_free_skb(mypkt);
420 return err;
421
422 }
423
424 int
425 brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
426 uint flags, struct sk_buff *pkt)
427 {
428 uint incr_fix;
429 uint width;
430 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
431 int err = 0;
432
433 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
434 fn, addr, pkt->len);
435
436 /* Async not implemented yet */
437 if (flags & SDIO_REQ_ASYNC)
438 return -ENOTSUPP;
439
440 if (bar0 != sdiodev->sbwad) {
441 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
442 if (err)
443 goto done;
444
445 sdiodev->sbwad = bar0;
446 }
447
448 addr &= SBSDIO_SB_OFT_ADDR_MASK;
449
450 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
451 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
452 if (width == 4)
453 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
454
455 err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
456 addr, pkt);
457
458 done:
459 return err;
460 }
461
462 int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
463 u8 *buf, uint nbytes)
464 {
465 struct sk_buff *mypkt;
466 bool write = rw ? SDIOH_WRITE : SDIOH_READ;
467 int err;
468
469 addr &= SBSDIO_SB_OFT_ADDR_MASK;
470 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
471
472 mypkt = brcmu_pkt_buf_get_skb(nbytes);
473 if (!mypkt) {
474 brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
475 nbytes);
476 return -EIO;
477 }
478
479 /* For a write, copy the buffer data into the packet. */
480 if (write)
481 memcpy(mypkt->data, buf, nbytes);
482
483 err = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC, write,
484 SDIO_FUNC_1, addr, mypkt);
485
486 /* For a read, copy the packet data back to the buffer. */
487 if (!err && !write)
488 memcpy(buf, mypkt->data, nbytes);
489
490 brcmu_pkt_buf_free_skb(mypkt);
491 return err;
492 }
493
494 int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
495 {
496 char t_func = (char)fn;
497 brcmf_dbg(TRACE, "Enter\n");
498
499 /* issue abort cmd52 command through F0 */
500 brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
501 SDIO_CCCR_ABORT, &t_func);
502
503 brcmf_dbg(TRACE, "Exit\n");
504 return 0;
505 }
506
507 int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
508 {
509 u32 regs = 0;
510 int ret = 0;
511
512 ret = brcmf_sdioh_attach(sdiodev);
513 if (ret)
514 goto out;
515
516 regs = SI_ENUM_BASE;
517
518 /* try to attach to the target device */
519 sdiodev->bus = brcmf_sdbrcm_probe(regs, sdiodev);
520 if (!sdiodev->bus) {
521 brcmf_err("device attach failed\n");
522 ret = -ENODEV;
523 goto out;
524 }
525
526 out:
527 if (ret)
528 brcmf_sdio_remove(sdiodev);
529
530 return ret;
531 }
532 EXPORT_SYMBOL(brcmf_sdio_probe);
533
534 int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
535 {
536 sdiodev->bus_if->state = BRCMF_BUS_DOWN;
537
538 if (sdiodev->bus) {
539 brcmf_sdbrcm_disconnect(sdiodev->bus);
540 sdiodev->bus = NULL;
541 }
542
543 brcmf_sdioh_detach(sdiodev);
544
545 sdiodev->sbwad = 0;
546
547 return 0;
548 }
549 EXPORT_SYMBOL(brcmf_sdio_remove);
550
551 void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
552 {
553 if (enable)
554 brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
555 else
556 brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);
557 }