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