brcmfmac: add out of band interrupt support
[deliverable/linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / bcmsdh_sdmmc.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
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19 #include <linux/types.h>
20 #include <linux/netdevice.h>
21 #include <linux/mmc/sdio.h>
22 #include <linux/mmc/core.h>
23 #include <linux/mmc/sdio_func.h>
24 #include <linux/mmc/sdio_ids.h>
25 #include <linux/mmc/card.h>
26 #include <linux/suspend.h>
27 #include <linux/errno.h>
28 #include <linux/sched.h> /* request_irq() */
29 #include <linux/module.h>
30 #include <linux/platform_device.h>
31 #include <net/cfg80211.h>
32
33 #include <defs.h>
34 #include <brcm_hw_ids.h>
35 #include <brcmu_utils.h>
36 #include <brcmu_wifi.h>
37 #include "sdio_host.h"
38 #include "dhd_dbg.h"
39 #include "dhd_bus.h"
40
41 #define SDIO_VENDOR_ID_BROADCOM 0x02d0
42
43 #define DMA_ALIGN_MASK 0x03
44
45 #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
46 #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330
47
48 #define SDIO_FUNC1_BLOCKSIZE 64
49 #define SDIO_FUNC2_BLOCKSIZE 512
50
51 /* devices we support, null terminated */
52 static const struct sdio_device_id brcmf_sdmmc_ids[] = {
53 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
54 {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
55 { /* end: all zeroes */ },
56 };
57 MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
58
59 #ifdef CONFIG_BRCMFMAC_SDIO_OOB
60 static struct list_head oobirq_lh;
61 struct brcmf_sdio_oobirq {
62 unsigned int irq;
63 unsigned long flags;
64 struct list_head list;
65 };
66 #endif /* CONFIG_BRCMFMAC_SDIO_OOB */
67
68 static bool
69 brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
70 {
71 bool is_err = false;
72 #ifdef CONFIG_PM_SLEEP
73 is_err = atomic_read(&sdiodev->suspend);
74 #endif
75 return is_err;
76 }
77
78 static void
79 brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, wait_queue_head_t *wq)
80 {
81 #ifdef CONFIG_PM_SLEEP
82 int retry = 0;
83 while (atomic_read(&sdiodev->suspend) && retry++ != 30)
84 wait_event_timeout(*wq, false, HZ/100);
85 #endif
86 }
87
88 static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
89 uint regaddr, u8 *byte)
90 {
91 struct sdio_func *sdfunc = sdiodev->func[0];
92 int err_ret;
93
94 /*
95 * Can only directly write to some F0 registers.
96 * Handle F2 enable/disable and Abort command
97 * as a special case.
98 */
99 if (regaddr == SDIO_CCCR_IOEx) {
100 sdfunc = sdiodev->func[2];
101 if (sdfunc) {
102 sdio_claim_host(sdfunc);
103 if (*byte & SDIO_FUNC_ENABLE_2) {
104 /* Enable Function 2 */
105 err_ret = sdio_enable_func(sdfunc);
106 if (err_ret)
107 brcmf_dbg(ERROR,
108 "enable F2 failed:%d\n",
109 err_ret);
110 } else {
111 /* Disable Function 2 */
112 err_ret = sdio_disable_func(sdfunc);
113 if (err_ret)
114 brcmf_dbg(ERROR,
115 "Disable F2 failed:%d\n",
116 err_ret);
117 }
118 sdio_release_host(sdfunc);
119 }
120 } else if ((regaddr == SDIO_CCCR_ABORT) ||
121 (regaddr == SDIO_CCCR_IENx)) {
122 sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func),
123 GFP_KERNEL);
124 if (!sdfunc)
125 return -ENOMEM;
126 sdfunc->num = 0;
127 sdio_claim_host(sdfunc);
128 sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
129 sdio_release_host(sdfunc);
130 kfree(sdfunc);
131 } else if (regaddr < 0xF0) {
132 brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr);
133 err_ret = -EPERM;
134 } else {
135 sdio_claim_host(sdfunc);
136 sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret);
137 sdio_release_host(sdfunc);
138 }
139
140 return err_ret;
141 }
142
143 int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
144 uint regaddr, u8 *byte)
145 {
146 int err_ret;
147
148 brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr);
149
150 brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait);
151 if (brcmf_pm_resume_error(sdiodev))
152 return -EIO;
153
154 if (rw && func == 0) {
155 /* handle F0 separately */
156 err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte);
157 } else {
158 sdio_claim_host(sdiodev->func[func]);
159 if (rw) /* CMD52 Write */
160 sdio_writeb(sdiodev->func[func], *byte, regaddr,
161 &err_ret);
162 else if (func == 0) {
163 *byte = sdio_f0_readb(sdiodev->func[func], regaddr,
164 &err_ret);
165 } else {
166 *byte = sdio_readb(sdiodev->func[func], regaddr,
167 &err_ret);
168 }
169 sdio_release_host(sdiodev->func[func]);
170 }
171
172 if (err_ret)
173 brcmf_dbg(ERROR, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
174 rw ? "write" : "read", func, regaddr, *byte, err_ret);
175
176 return err_ret;
177 }
178
179 int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
180 uint rw, uint func, uint addr, u32 *word,
181 uint nbytes)
182 {
183 int err_ret = -EIO;
184
185 if (func == 0) {
186 brcmf_dbg(ERROR, "Only CMD52 allowed to F0\n");
187 return -EINVAL;
188 }
189
190 brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
191 rw, func, addr, nbytes);
192
193 brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
194 if (brcmf_pm_resume_error(sdiodev))
195 return -EIO;
196 /* Claim host controller */
197 sdio_claim_host(sdiodev->func[func]);
198
199 if (rw) { /* CMD52 Write */
200 if (nbytes == 4)
201 sdio_writel(sdiodev->func[func], *word, addr,
202 &err_ret);
203 else if (nbytes == 2)
204 sdio_writew(sdiodev->func[func], (*word & 0xFFFF),
205 addr, &err_ret);
206 else
207 brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
208 } else { /* CMD52 Read */
209 if (nbytes == 4)
210 *word = sdio_readl(sdiodev->func[func], addr, &err_ret);
211 else if (nbytes == 2)
212 *word = sdio_readw(sdiodev->func[func], addr,
213 &err_ret) & 0xFFFF;
214 else
215 brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
216 }
217
218 /* Release host controller */
219 sdio_release_host(sdiodev->func[func]);
220
221 if (err_ret)
222 brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n",
223 rw ? "write" : "read", err_ret);
224
225 return err_ret;
226 }
227
228 /* precondition: host controller is claimed */
229 static int
230 brcmf_sdioh_request_data(struct brcmf_sdio_dev *sdiodev, uint write, bool fifo,
231 uint func, uint addr, struct sk_buff *pkt, uint pktlen)
232 {
233 int err_ret = 0;
234
235 if ((write) && (!fifo)) {
236 err_ret = sdio_memcpy_toio(sdiodev->func[func], addr,
237 ((u8 *) (pkt->data)), pktlen);
238 } else if (write) {
239 err_ret = sdio_memcpy_toio(sdiodev->func[func], addr,
240 ((u8 *) (pkt->data)), pktlen);
241 } else if (fifo) {
242 err_ret = sdio_readsb(sdiodev->func[func],
243 ((u8 *) (pkt->data)), addr, pktlen);
244 } else {
245 err_ret = sdio_memcpy_fromio(sdiodev->func[func],
246 ((u8 *) (pkt->data)),
247 addr, pktlen);
248 }
249
250 return err_ret;
251 }
252
253 /*
254 * This function takes a queue of packets. The packets on the queue
255 * are assumed to be properly aligned by the caller.
256 */
257 int
258 brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
259 uint write, uint func, uint addr,
260 struct sk_buff_head *pktq)
261 {
262 bool fifo = (fix_inc == SDIOH_DATA_FIX);
263 u32 SGCount = 0;
264 int err_ret = 0;
265
266 struct sk_buff *pkt;
267
268 brcmf_dbg(TRACE, "Enter\n");
269
270 brcmf_pm_resume_wait(sdiodev, &sdiodev->request_chain_wait);
271 if (brcmf_pm_resume_error(sdiodev))
272 return -EIO;
273
274 /* Claim host controller */
275 sdio_claim_host(sdiodev->func[func]);
276
277 skb_queue_walk(pktq, pkt) {
278 uint pkt_len = pkt->len;
279 pkt_len += 3;
280 pkt_len &= 0xFFFFFFFC;
281
282 err_ret = brcmf_sdioh_request_data(sdiodev, write, fifo, func,
283 addr, pkt, pkt_len);
284 if (err_ret) {
285 brcmf_dbg(ERROR, "%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
286 write ? "TX" : "RX", pkt, SGCount, addr,
287 pkt_len, err_ret);
288 } else {
289 brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n",
290 write ? "TX" : "RX", pkt, SGCount, addr,
291 pkt_len);
292 }
293 if (!fifo)
294 addr += pkt_len;
295
296 SGCount++;
297 }
298
299 /* Release host controller */
300 sdio_release_host(sdiodev->func[func]);
301
302 brcmf_dbg(TRACE, "Exit\n");
303 return err_ret;
304 }
305
306 /*
307 * This function takes a single DMA-able packet.
308 */
309 int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
310 uint fix_inc, uint write, uint func, uint addr,
311 struct sk_buff *pkt)
312 {
313 int status;
314 uint pkt_len;
315 bool fifo = (fix_inc == SDIOH_DATA_FIX);
316
317 brcmf_dbg(TRACE, "Enter\n");
318
319 if (pkt == NULL)
320 return -EINVAL;
321 pkt_len = pkt->len;
322
323 brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
324 if (brcmf_pm_resume_error(sdiodev))
325 return -EIO;
326
327 /* Claim host controller */
328 sdio_claim_host(sdiodev->func[func]);
329
330 pkt_len += 3;
331 pkt_len &= (uint)~3;
332
333 status = brcmf_sdioh_request_data(sdiodev, write, fifo, func,
334 addr, pkt, pkt_len);
335 if (status) {
336 brcmf_dbg(ERROR, "%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
337 write ? "TX" : "RX", pkt, addr, pkt_len, status);
338 } else {
339 brcmf_dbg(TRACE, "%s xfr'd %p, addr=0x%05x, len=%d\n",
340 write ? "TX" : "RX", pkt, addr, pkt_len);
341 }
342
343 /* Release host controller */
344 sdio_release_host(sdiodev->func[func]);
345
346 return status;
347 }
348
349 /* Read client card reg */
350 static int
351 brcmf_sdioh_card_regread(struct brcmf_sdio_dev *sdiodev, int func, u32 regaddr,
352 int regsize, u32 *data)
353 {
354
355 if ((func == 0) || (regsize == 1)) {
356 u8 temp = 0;
357
358 brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, func, regaddr,
359 &temp);
360 *data = temp;
361 *data &= 0xff;
362 brcmf_dbg(DATA, "byte read data=0x%02x\n", *data);
363 } else {
364 brcmf_sdioh_request_word(sdiodev, SDIOH_READ, func, regaddr,
365 data, regsize);
366 if (regsize == 2)
367 *data &= 0xffff;
368
369 brcmf_dbg(DATA, "word read data=0x%08x\n", *data);
370 }
371
372 return SUCCESS;
373 }
374
375 static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr)
376 {
377 /* read 24 bits and return valid 17 bit addr */
378 int i;
379 u32 scratch, regdata;
380 __le32 scratch_le;
381 u8 *ptr = (u8 *)&scratch_le;
382
383 for (i = 0; i < 3; i++) {
384 if ((brcmf_sdioh_card_regread(sdiodev, 0, regaddr, 1,
385 &regdata)) != SUCCESS)
386 brcmf_dbg(ERROR, "Can't read!\n");
387
388 *ptr++ = (u8) regdata;
389 regaddr++;
390 }
391
392 /* Only the lower 17-bits are valid */
393 scratch = le32_to_cpu(scratch_le);
394 scratch &= 0x0001FFFF;
395 return scratch;
396 }
397
398 static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
399 {
400 int err_ret;
401 u32 fbraddr;
402 u8 func;
403
404 brcmf_dbg(TRACE, "\n");
405
406 /* Get the Card's common CIS address */
407 sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev,
408 SDIO_CCCR_CIS);
409 brcmf_dbg(INFO, "Card's Common CIS Ptr = 0x%x\n",
410 sdiodev->func_cis_ptr[0]);
411
412 /* Get the Card's function CIS (for each function) */
413 for (fbraddr = SDIO_FBR_BASE(1), func = 1;
414 func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
415 sdiodev->func_cis_ptr[func] =
416 brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr);
417 brcmf_dbg(INFO, "Function %d CIS Ptr = 0x%x\n",
418 func, sdiodev->func_cis_ptr[func]);
419 }
420
421 /* Enable Function 1 */
422 sdio_claim_host(sdiodev->func[1]);
423 err_ret = sdio_enable_func(sdiodev->func[1]);
424 sdio_release_host(sdiodev->func[1]);
425 if (err_ret)
426 brcmf_dbg(ERROR, "Failed to enable F1 Err: 0x%08x\n", err_ret);
427
428 return false;
429 }
430
431 /*
432 * Public entry points & extern's
433 */
434 int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
435 {
436 int err_ret = 0;
437
438 brcmf_dbg(TRACE, "\n");
439
440 sdiodev->num_funcs = 2;
441
442 sdio_claim_host(sdiodev->func[1]);
443 err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE);
444 sdio_release_host(sdiodev->func[1]);
445 if (err_ret) {
446 brcmf_dbg(ERROR, "Failed to set F1 blocksize\n");
447 goto out;
448 }
449
450 sdio_claim_host(sdiodev->func[2]);
451 err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE);
452 sdio_release_host(sdiodev->func[2]);
453 if (err_ret) {
454 brcmf_dbg(ERROR, "Failed to set F2 blocksize\n");
455 goto out;
456 }
457
458 brcmf_sdioh_enablefuncs(sdiodev);
459
460 out:
461 brcmf_dbg(TRACE, "Done\n");
462 return err_ret;
463 }
464
465 void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
466 {
467 brcmf_dbg(TRACE, "\n");
468
469 /* Disable Function 2 */
470 sdio_claim_host(sdiodev->func[2]);
471 sdio_disable_func(sdiodev->func[2]);
472 sdio_release_host(sdiodev->func[2]);
473
474 /* Disable Function 1 */
475 sdio_claim_host(sdiodev->func[1]);
476 sdio_disable_func(sdiodev->func[1]);
477 sdio_release_host(sdiodev->func[1]);
478
479 }
480
481 #ifdef CONFIG_BRCMFMAC_SDIO_OOB
482 static int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
483 {
484 struct brcmf_sdio_oobirq *oobirq_entry;
485
486 if (list_empty(&oobirq_lh)) {
487 brcmf_dbg(ERROR, "no valid oob irq resource\n");
488 return -ENXIO;
489 }
490
491 oobirq_entry = list_first_entry(&oobirq_lh, struct brcmf_sdio_oobirq,
492 list);
493
494 sdiodev->irq = oobirq_entry->irq;
495 sdiodev->irq_flags = oobirq_entry->flags;
496 list_del(&oobirq_entry->list);
497 kfree(oobirq_entry);
498
499 return 0;
500 }
501 #else
502 static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
503 {
504 return 0;
505 }
506 #endif /* CONFIG_BRCMFMAC_SDIO_OOB */
507
508 static int brcmf_ops_sdio_probe(struct sdio_func *func,
509 const struct sdio_device_id *id)
510 {
511 int ret = 0;
512 struct brcmf_sdio_dev *sdiodev;
513 struct brcmf_bus *bus_if;
514
515 brcmf_dbg(TRACE, "Enter\n");
516 brcmf_dbg(TRACE, "func->class=%x\n", func->class);
517 brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor);
518 brcmf_dbg(TRACE, "sdio_device: 0x%04x\n", func->device);
519 brcmf_dbg(TRACE, "Function#: 0x%04x\n", func->num);
520
521 if (func->num == 1) {
522 if (dev_get_drvdata(&func->card->dev)) {
523 brcmf_dbg(ERROR, "card private drvdata occupied\n");
524 return -ENXIO;
525 }
526 bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL);
527 if (!bus_if)
528 return -ENOMEM;
529 sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
530 if (!sdiodev) {
531 kfree(bus_if);
532 return -ENOMEM;
533 }
534 sdiodev->func[0] = func;
535 sdiodev->func[1] = func;
536 sdiodev->bus_if = bus_if;
537 bus_if->bus_priv.sdio = sdiodev;
538 bus_if->type = SDIO_BUS;
539 bus_if->align = BRCMF_SDALIGN;
540 dev_set_drvdata(&func->card->dev, sdiodev);
541
542 atomic_set(&sdiodev->suspend, false);
543 init_waitqueue_head(&sdiodev->request_byte_wait);
544 init_waitqueue_head(&sdiodev->request_word_wait);
545 init_waitqueue_head(&sdiodev->request_chain_wait);
546 init_waitqueue_head(&sdiodev->request_buffer_wait);
547 }
548
549 if (func->num == 2) {
550 sdiodev = dev_get_drvdata(&func->card->dev);
551 if ((!sdiodev) || (sdiodev->func[1]->card != func->card))
552 return -ENODEV;
553
554 ret = brcmf_sdio_getintrcfg(sdiodev);
555 if (ret)
556 return ret;
557 sdiodev->func[2] = func;
558
559 bus_if = sdiodev->bus_if;
560 sdiodev->dev = &func->dev;
561 dev_set_drvdata(&func->dev, bus_if);
562
563 brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
564 ret = brcmf_sdio_probe(sdiodev);
565 }
566
567 return ret;
568 }
569
570 static void brcmf_ops_sdio_remove(struct sdio_func *func)
571 {
572 struct brcmf_bus *bus_if;
573 struct brcmf_sdio_dev *sdiodev;
574 brcmf_dbg(TRACE, "Enter\n");
575 brcmf_dbg(INFO, "func->class=%x\n", func->class);
576 brcmf_dbg(INFO, "sdio_vendor: 0x%04x\n", func->vendor);
577 brcmf_dbg(INFO, "sdio_device: 0x%04x\n", func->device);
578 brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num);
579
580 if (func->num == 2) {
581 bus_if = dev_get_drvdata(&func->dev);
582 sdiodev = bus_if->bus_priv.sdio;
583 brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n");
584 brcmf_sdio_remove(sdiodev);
585 dev_set_drvdata(&func->card->dev, NULL);
586 dev_set_drvdata(&func->dev, NULL);
587 kfree(bus_if);
588 kfree(sdiodev);
589 }
590 }
591
592 #ifdef CONFIG_PM_SLEEP
593 static int brcmf_sdio_suspend(struct device *dev)
594 {
595 mmc_pm_flag_t sdio_flags;
596 struct sdio_func *func = dev_to_sdio_func(dev);
597 struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
598 int ret = 0;
599
600 brcmf_dbg(TRACE, "\n");
601
602 atomic_set(&sdiodev->suspend, true);
603
604 sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]);
605 if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
606 brcmf_dbg(ERROR, "Host can't keep power while suspended\n");
607 return -EINVAL;
608 }
609
610 ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER);
611 if (ret) {
612 brcmf_dbg(ERROR, "Failed to set pm_flags\n");
613 return ret;
614 }
615
616 brcmf_sdio_wdtmr_enable(sdiodev, false);
617
618 return ret;
619 }
620
621 static int brcmf_sdio_resume(struct device *dev)
622 {
623 struct sdio_func *func = dev_to_sdio_func(dev);
624 struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
625
626 brcmf_sdio_wdtmr_enable(sdiodev, true);
627 atomic_set(&sdiodev->suspend, false);
628 return 0;
629 }
630
631 static const struct dev_pm_ops brcmf_sdio_pm_ops = {
632 .suspend = brcmf_sdio_suspend,
633 .resume = brcmf_sdio_resume,
634 };
635 #endif /* CONFIG_PM_SLEEP */
636
637 static struct sdio_driver brcmf_sdmmc_driver = {
638 .probe = brcmf_ops_sdio_probe,
639 .remove = brcmf_ops_sdio_remove,
640 .name = "brcmfmac",
641 .id_table = brcmf_sdmmc_ids,
642 #ifdef CONFIG_PM_SLEEP
643 .drv = {
644 .pm = &brcmf_sdio_pm_ops,
645 },
646 #endif /* CONFIG_PM_SLEEP */
647 };
648
649 #ifdef CONFIG_BRCMFMAC_SDIO_OOB
650 static int brcmf_sdio_pd_probe(struct platform_device *pdev)
651 {
652 struct resource *res;
653 struct brcmf_sdio_oobirq *oobirq_entry;
654 int i, ret;
655
656 INIT_LIST_HEAD(&oobirq_lh);
657
658 for (i = 0; ; i++) {
659 res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
660 if (!res)
661 break;
662
663 oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq),
664 GFP_KERNEL);
665 oobirq_entry->irq = res->start;
666 oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK;
667 list_add_tail(&oobirq_entry->list, &oobirq_lh);
668 }
669 if (i == 0)
670 return -ENXIO;
671
672 ret = sdio_register_driver(&brcmf_sdmmc_driver);
673
674 if (ret)
675 brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
676
677 return ret;
678 }
679
680 static struct platform_driver brcmf_sdio_pd = {
681 .probe = brcmf_sdio_pd_probe,
682 .driver = {
683 .name = "brcmf_sdio_pd"
684 }
685 };
686
687 void brcmf_sdio_exit(void)
688 {
689 brcmf_dbg(TRACE, "Enter\n");
690
691 sdio_unregister_driver(&brcmf_sdmmc_driver);
692
693 platform_driver_unregister(&brcmf_sdio_pd);
694 }
695
696 void brcmf_sdio_init(void)
697 {
698 int ret;
699
700 brcmf_dbg(TRACE, "Enter\n");
701
702 ret = platform_driver_register(&brcmf_sdio_pd);
703
704 if (ret)
705 brcmf_dbg(ERROR, "platform_driver_register failed: %d\n", ret);
706 }
707 #else
708 void brcmf_sdio_exit(void)
709 {
710 brcmf_dbg(TRACE, "Enter\n");
711
712 sdio_unregister_driver(&brcmf_sdmmc_driver);
713 }
714
715 void brcmf_sdio_init(void)
716 {
717 int ret;
718
719 brcmf_dbg(TRACE, "Enter\n");
720
721 ret = sdio_register_driver(&brcmf_sdmmc_driver);
722
723 if (ret)
724 brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
725 }
726 #endif /* CONFIG_BRCMFMAC_SDIO_OOB */
This page took 0.058726 seconds and 5 git commands to generate.