]> Pileus Git - ~andy/linux/blob - drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
brcmfmac: remove WL_TRACE() macro
[~andy/linux] / 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 }