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