]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
e919de210f701527abe34900ad0ceb5467488e61
[karo-tx-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 #include <linux/types.h>
17 #include <linux/netdevice.h>
18 #include <linux/mmc/sdio.h>
19 #include <linux/mmc/core.h>
20 #include <linux/mmc/sdio_func.h>
21 #include <linux/mmc/sdio_ids.h>
22 #include <linux/mmc/card.h>
23 #include <linux/suspend.h>
24 #include <linux/errno.h>
25 #include <linux/sched.h>        /* request_irq() */
26 #include <net/cfg80211.h>
27
28 #include <defs.h>
29 #include <brcm_hw_ids.h>
30 #include <brcmu_utils.h>
31 #include <brcmu_wifi.h>
32 #include "sdio_host.h"
33 #include "dhd.h"
34 #include "dhd_dbg.h"
35 #include "wl_cfg80211.h"
36
37 #define SDIO_VENDOR_ID_BROADCOM         0x02d0
38
39 #define DMA_ALIGN_MASK  0x03
40
41 #define SDIO_DEVICE_ID_BROADCOM_4329    0x4329
42
43 #define SDIO_FUNC1_BLOCKSIZE            64
44 #define SDIO_FUNC2_BLOCKSIZE            512
45
46 /* devices we support, null terminated */
47 static const struct sdio_device_id brcmf_sdmmc_ids[] = {
48         {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
49         { /* end: all zeroes */ },
50 };
51 MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
52
53 static bool
54 brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
55 {
56         bool is_err = false;
57 #ifdef CONFIG_PM_SLEEP
58         is_err = atomic_read(&sdiodev->suspend);
59 #endif
60         return is_err;
61 }
62
63 static void
64 brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, wait_queue_head_t *wq)
65 {
66 #ifdef CONFIG_PM_SLEEP
67         int retry = 0;
68         while (atomic_read(&sdiodev->suspend) && retry++ != 30)
69                 wait_event_timeout(*wq, false, HZ/100);
70 #endif
71 }
72
73 static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
74                                             uint regaddr, u8 *byte)
75 {
76         struct sdio_func *sdfunc = sdiodev->func[0];
77         int err_ret;
78
79         /*
80          * Can only directly write to some F0 registers.
81          * Handle F2 enable/disable and Abort command
82          * as a special case.
83          */
84         if (regaddr == SDIO_CCCR_IOEx) {
85                 sdfunc = sdiodev->func[2];
86                 if (sdfunc) {
87                         sdio_claim_host(sdfunc);
88                         if (*byte & SDIO_FUNC_ENABLE_2) {
89                                 /* Enable Function 2 */
90                                 err_ret = sdio_enable_func(sdfunc);
91                                 if (err_ret)
92                                         brcmf_dbg(ERROR,
93                                                   "enable F2 failed:%d\n",
94                                                   err_ret);
95                         } else {
96                                 /* Disable Function 2 */
97                                 err_ret = sdio_disable_func(sdfunc);
98                                 if (err_ret)
99                                         brcmf_dbg(ERROR,
100                                                   "Disable F2 failed:%d\n",
101                                                   err_ret);
102                         }
103                         sdio_release_host(sdfunc);
104                 }
105         } else if (regaddr == SDIO_CCCR_ABORT) {
106                 sdio_claim_host(sdfunc);
107                 sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
108                 sdio_release_host(sdfunc);
109         } else if (regaddr < 0xF0) {
110                 brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr);
111                 err_ret = -EPERM;
112         } else {
113                 sdio_claim_host(sdfunc);
114                 sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret);
115                 sdio_release_host(sdfunc);
116         }
117
118         return err_ret;
119 }
120
121 int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
122                              uint regaddr, u8 *byte)
123 {
124         int err_ret;
125
126         brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr);
127
128         brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait);
129         if (brcmf_pm_resume_error(sdiodev))
130                 return -EIO;
131
132         if (rw && func == 0) {
133                 /* handle F0 separately */
134                 err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte);
135         } else {
136                 sdio_claim_host(sdiodev->func[func]);
137                 if (rw) /* CMD52 Write */
138                         sdio_writeb(sdiodev->func[func], *byte, regaddr,
139                                     &err_ret);
140                 else if (func == 0) {
141                         *byte = sdio_f0_readb(sdiodev->func[func], regaddr,
142                                               &err_ret);
143                 } else {
144                         *byte = sdio_readb(sdiodev->func[func], regaddr,
145                                            &err_ret);
146                 }
147                 sdio_release_host(sdiodev->func[func]);
148         }
149
150         if (err_ret)
151                 brcmf_dbg(ERROR, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
152                           rw ? "write" : "read", func, regaddr, *byte, err_ret);
153
154         return err_ret;
155 }
156
157 int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
158                              uint rw, uint func, uint addr, u32 *word,
159                              uint nbytes)
160 {
161         int err_ret = -EIO;
162
163         if (func == 0) {
164                 brcmf_dbg(ERROR, "Only CMD52 allowed to F0\n");
165                 return -EINVAL;
166         }
167
168         brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
169                   rw, func, addr, nbytes);
170
171         brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
172         if (brcmf_pm_resume_error(sdiodev))
173                 return -EIO;
174         /* Claim host controller */
175         sdio_claim_host(sdiodev->func[func]);
176
177         if (rw) {               /* CMD52 Write */
178                 if (nbytes == 4)
179                         sdio_writel(sdiodev->func[func], *word, addr,
180                                     &err_ret);
181                 else if (nbytes == 2)
182                         sdio_writew(sdiodev->func[func], (*word & 0xFFFF),
183                                     addr, &err_ret);
184                 else
185                         brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
186         } else {                /* CMD52 Read */
187                 if (nbytes == 4)
188                         *word = sdio_readl(sdiodev->func[func], addr, &err_ret);
189                 else if (nbytes == 2)
190                         *word = sdio_readw(sdiodev->func[func], addr,
191                                            &err_ret) & 0xFFFF;
192                 else
193                         brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
194         }
195
196         /* Release host controller */
197         sdio_release_host(sdiodev->func[func]);
198
199         if (err_ret)
200                 brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n",
201                           rw ? "write" : "read", err_ret);
202
203         return err_ret;
204 }
205
206 static int
207 brcmf_sdioh_request_packet(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
208                            uint write, uint func, uint addr,
209                            struct sk_buff *pkt)
210 {
211         bool fifo = (fix_inc == SDIOH_DATA_FIX);
212         u32 SGCount = 0;
213         int err_ret = 0;
214
215         struct sk_buff *pnext;
216
217         brcmf_dbg(TRACE, "Enter\n");
218
219         brcmf_pm_resume_wait(sdiodev, &sdiodev->request_packet_wait);
220         if (brcmf_pm_resume_error(sdiodev))
221                 return -EIO;
222
223         /* Claim host controller */
224         sdio_claim_host(sdiodev->func[func]);
225         for (pnext = pkt; pnext; pnext = pnext->next) {
226                 uint pkt_len = pnext->len;
227                 pkt_len += 3;
228                 pkt_len &= 0xFFFFFFFC;
229
230                 if ((write) && (!fifo)) {
231                         err_ret = sdio_memcpy_toio(sdiodev->func[func], addr,
232                                                    ((u8 *) (pnext->data)),
233                                                    pkt_len);
234                 } else if (write) {
235                         err_ret = sdio_memcpy_toio(sdiodev->func[func], addr,
236                                                    ((u8 *) (pnext->data)),
237                                                    pkt_len);
238                 } else if (fifo) {
239                         err_ret = sdio_readsb(sdiodev->func[func],
240                                               ((u8 *) (pnext->data)),
241                                               addr, pkt_len);
242                 } else {
243                         err_ret = sdio_memcpy_fromio(sdiodev->func[func],
244                                                      ((u8 *) (pnext->data)),
245                                                      addr, pkt_len);
246                 }
247
248                 if (err_ret) {
249                         brcmf_dbg(ERROR, "%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
250                                   write ? "TX" : "RX", pnext, SGCount, addr,
251                                   pkt_len, err_ret);
252                 } else {
253                         brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n",
254                                   write ? "TX" : "RX", pnext, SGCount, addr,
255                                   pkt_len);
256                 }
257
258                 if (!fifo)
259                         addr += pkt_len;
260                 SGCount++;
261
262         }
263
264         /* Release host controller */
265         sdio_release_host(sdiodev->func[func]);
266
267         brcmf_dbg(TRACE, "Exit\n");
268         return err_ret;
269 }
270
271 /*
272  * This function takes a buffer or packet, and fixes everything up
273  * so that in the end, a DMA-able packet is created.
274  *
275  * A buffer does not have an associated packet pointer,
276  * and may or may not be aligned.
277  * A packet may consist of a single packet, or a packet chain.
278  * If it is a packet chain, then all the packets in the chain
279  * must be properly aligned.
280  *
281  * If the packet data is not aligned, then there may only be
282  * one packet, and in this case,  it is copied to a new
283  * aligned packet.
284  *
285  */
286 int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
287                                uint fix_inc, uint write, uint func, uint addr,
288                                uint reg_width, uint buflen_u, u8 *buffer,
289                                struct sk_buff *pkt)
290 {
291         int Status;
292         struct sk_buff *mypkt = NULL;
293
294         brcmf_dbg(TRACE, "Enter\n");
295
296         brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
297         if (brcmf_pm_resume_error(sdiodev))
298                 return -EIO;
299         /* Case 1: we don't have a packet. */
300         if (pkt == NULL) {
301                 brcmf_dbg(DATA, "Creating new %s Packet, len=%d\n",
302                           write ? "TX" : "RX", buflen_u);
303                 mypkt = brcmu_pkt_buf_get_skb(buflen_u);
304                 if (!mypkt) {
305                         brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
306                                   buflen_u);
307                         return -EIO;
308                 }
309
310                 /* For a write, copy the buffer data into the packet. */
311                 if (write)
312                         memcpy(mypkt->data, buffer, buflen_u);
313
314                 Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write,
315                                                     func, addr, mypkt);
316
317                 /* For a read, copy the packet data back to the buffer. */
318                 if (!write)
319                         memcpy(buffer, mypkt->data, buflen_u);
320
321                 brcmu_pkt_buf_free_skb(mypkt);
322         } else if (((ulong) (pkt->data) & DMA_ALIGN_MASK) != 0) {
323                 /*
324                  * Case 2: We have a packet, but it is unaligned.
325                  * In this case, we cannot have a chain (pkt->next == NULL)
326                  */
327                 brcmf_dbg(DATA, "Creating aligned %s Packet, len=%d\n",
328                           write ? "TX" : "RX", pkt->len);
329                 mypkt = brcmu_pkt_buf_get_skb(pkt->len);
330                 if (!mypkt) {
331                         brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
332                                   pkt->len);
333                         return -EIO;
334                 }
335
336                 /* For a write, copy the buffer data into the packet. */
337                 if (write)
338                         memcpy(mypkt->data, pkt->data, pkt->len);
339
340                 Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write,
341                                                     func, addr, mypkt);
342
343                 /* For a read, copy the packet data back to the buffer. */
344                 if (!write)
345                         memcpy(pkt->data, mypkt->data, mypkt->len);
346
347                 brcmu_pkt_buf_free_skb(mypkt);
348         } else {                /* case 3: We have a packet and
349                                  it is aligned. */
350                 brcmf_dbg(DATA, "Aligned %s Packet, direct DMA\n",
351                           write ? "Tx" : "Rx");
352                 Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write,
353                                                     func, addr, pkt);
354         }
355
356         return Status;
357 }
358
359 /* Read client card reg */
360 static int
361 brcmf_sdioh_card_regread(struct brcmf_sdio_dev *sdiodev, int func, u32 regaddr,
362                          int regsize, u32 *data)
363 {
364
365         if ((func == 0) || (regsize == 1)) {
366                 u8 temp = 0;
367
368                 brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, func, regaddr,
369                                          &temp);
370                 *data = temp;
371                 *data &= 0xff;
372                 brcmf_dbg(DATA, "byte read data=0x%02x\n", *data);
373         } else {
374                 brcmf_sdioh_request_word(sdiodev, SDIOH_READ, func, regaddr,
375                                          data, regsize);
376                 if (regsize == 2)
377                         *data &= 0xffff;
378
379                 brcmf_dbg(DATA, "word read data=0x%08x\n", *data);
380         }
381
382         return SUCCESS;
383 }
384
385 static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr)
386 {
387         /* read 24 bits and return valid 17 bit addr */
388         int i;
389         u32 scratch, regdata;
390         __le32 scratch_le;
391         u8 *ptr = (u8 *)&scratch_le;
392
393         for (i = 0; i < 3; i++) {
394                 if ((brcmf_sdioh_card_regread(sdiodev, 0, regaddr, 1,
395                                 &regdata)) != SUCCESS)
396                         brcmf_dbg(ERROR, "Can't read!\n");
397
398                 *ptr++ = (u8) regdata;
399                 regaddr++;
400         }
401
402         /* Only the lower 17-bits are valid */
403         scratch = le32_to_cpu(scratch_le);
404         scratch &= 0x0001FFFF;
405         return scratch;
406 }
407
408 static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
409 {
410         int err_ret;
411         u32 fbraddr;
412         u8 func;
413
414         brcmf_dbg(TRACE, "\n");
415
416         /* Get the Card's common CIS address */
417         sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev,
418                                                            SDIO_CCCR_CIS);
419         brcmf_dbg(INFO, "Card's Common CIS Ptr = 0x%x\n",
420                   sdiodev->func_cis_ptr[0]);
421
422         /* Get the Card's function CIS (for each function) */
423         for (fbraddr = SDIO_FBR_BASE(1), func = 1;
424              func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
425                 sdiodev->func_cis_ptr[func] =
426                     brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr);
427                 brcmf_dbg(INFO, "Function %d CIS Ptr = 0x%x\n",
428                           func, sdiodev->func_cis_ptr[func]);
429         }
430
431         /* Enable Function 1 */
432         sdio_claim_host(sdiodev->func[1]);
433         err_ret = sdio_enable_func(sdiodev->func[1]);
434         sdio_release_host(sdiodev->func[1]);
435         if (err_ret)
436                 brcmf_dbg(ERROR, "Failed to enable F1 Err: 0x%08x\n", err_ret);
437
438         return false;
439 }
440
441 /*
442  *      Public entry points & extern's
443  */
444 int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
445 {
446         int err_ret = 0;
447
448         brcmf_dbg(TRACE, "\n");
449
450         sdiodev->num_funcs = 2;
451
452         sdio_claim_host(sdiodev->func[1]);
453         err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE);
454         sdio_release_host(sdiodev->func[1]);
455         if (err_ret) {
456                 brcmf_dbg(ERROR, "Failed to set F1 blocksize\n");
457                 goto out;
458         }
459
460         sdio_claim_host(sdiodev->func[2]);
461         err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE);
462         sdio_release_host(sdiodev->func[2]);
463         if (err_ret) {
464                 brcmf_dbg(ERROR, "Failed to set F2 blocksize\n");
465                 goto out;
466         }
467
468         brcmf_sdioh_enablefuncs(sdiodev);
469
470 out:
471         brcmf_dbg(TRACE, "Done\n");
472         return err_ret;
473 }
474
475 void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
476 {
477         brcmf_dbg(TRACE, "\n");
478
479         /* Disable Function 2 */
480         sdio_claim_host(sdiodev->func[2]);
481         sdio_disable_func(sdiodev->func[2]);
482         sdio_release_host(sdiodev->func[2]);
483
484         /* Disable Function 1 */
485         sdio_claim_host(sdiodev->func[1]);
486         sdio_disable_func(sdiodev->func[1]);
487         sdio_release_host(sdiodev->func[1]);
488
489 }
490
491 static int brcmf_ops_sdio_probe(struct sdio_func *func,
492                               const struct sdio_device_id *id)
493 {
494         int ret = 0;
495         struct brcmf_sdio_dev *sdiodev;
496         brcmf_dbg(TRACE, "Enter\n");
497         brcmf_dbg(TRACE, "func->class=%x\n", func->class);
498         brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor);
499         brcmf_dbg(TRACE, "sdio_device: 0x%04x\n", func->device);
500         brcmf_dbg(TRACE, "Function#: 0x%04x\n", func->num);
501
502         if (func->num == 1) {
503                 if (dev_get_drvdata(&func->card->dev)) {
504                         brcmf_dbg(ERROR, "card private drvdata occupied\n");
505                         return -ENXIO;
506                 }
507                 sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
508                 if (!sdiodev)
509                         return -ENOMEM;
510                 sdiodev->func[0] = func->card->sdio_func[0];
511                 sdiodev->func[1] = func;
512                 dev_set_drvdata(&func->card->dev, sdiodev);
513
514                 atomic_set(&sdiodev->suspend, false);
515                 init_waitqueue_head(&sdiodev->request_byte_wait);
516                 init_waitqueue_head(&sdiodev->request_word_wait);
517                 init_waitqueue_head(&sdiodev->request_packet_wait);
518                 init_waitqueue_head(&sdiodev->request_buffer_wait);
519         }
520
521         if (func->num == 2) {
522                 sdiodev = dev_get_drvdata(&func->card->dev);
523                 if ((!sdiodev) || (sdiodev->func[1]->card != func->card))
524                         return -ENODEV;
525                 sdiodev->func[2] = func;
526
527                 brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
528                 ret = brcmf_sdio_probe(sdiodev);
529         }
530
531         return ret;
532 }
533
534 static void brcmf_ops_sdio_remove(struct sdio_func *func)
535 {
536         struct brcmf_sdio_dev *sdiodev;
537         brcmf_dbg(TRACE, "Enter\n");
538         brcmf_dbg(INFO, "func->class=%x\n", func->class);
539         brcmf_dbg(INFO, "sdio_vendor: 0x%04x\n", func->vendor);
540         brcmf_dbg(INFO, "sdio_device: 0x%04x\n", func->device);
541         brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num);
542
543         if (func->num == 2) {
544                 sdiodev = dev_get_drvdata(&func->card->dev);
545                 brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n");
546                 brcmf_sdio_remove(sdiodev);
547                 dev_set_drvdata(&func->card->dev, NULL);
548                 kfree(sdiodev);
549         }
550 }
551
552 #ifdef CONFIG_PM_SLEEP
553 static int brcmf_sdio_suspend(struct device *dev)
554 {
555         mmc_pm_flag_t sdio_flags;
556         struct brcmf_sdio_dev *sdiodev;
557         struct sdio_func *func = dev_to_sdio_func(dev);
558         int ret = 0;
559
560         brcmf_dbg(TRACE, "\n");
561
562         sdiodev = dev_get_drvdata(&func->card->dev);
563
564         atomic_set(&sdiodev->suspend, true);
565
566         sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]);
567         if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
568                 brcmf_dbg(ERROR, "Host can't keep power while suspended\n");
569                 return -EINVAL;
570         }
571
572         ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER);
573         if (ret) {
574                 brcmf_dbg(ERROR, "Failed to set pm_flags\n");
575                 return ret;
576         }
577
578         brcmf_sdio_wdtmr_enable(sdiodev, false);
579
580         return ret;
581 }
582
583 static int brcmf_sdio_resume(struct device *dev)
584 {
585         struct brcmf_sdio_dev *sdiodev;
586         struct sdio_func *func = dev_to_sdio_func(dev);
587
588         sdiodev = dev_get_drvdata(&func->card->dev);
589         brcmf_sdio_wdtmr_enable(sdiodev, true);
590         atomic_set(&sdiodev->suspend, false);
591         return 0;
592 }
593
594 static const struct dev_pm_ops brcmf_sdio_pm_ops = {
595         .suspend        = brcmf_sdio_suspend,
596         .resume         = brcmf_sdio_resume,
597 };
598 #endif  /* CONFIG_PM_SLEEP */
599
600 static struct sdio_driver brcmf_sdmmc_driver = {
601         .probe = brcmf_ops_sdio_probe,
602         .remove = brcmf_ops_sdio_remove,
603         .name = "brcmfmac",
604         .id_table = brcmf_sdmmc_ids,
605 #ifdef CONFIG_PM_SLEEP
606         .drv = {
607                 .pm = &brcmf_sdio_pm_ops,
608         },
609 #endif  /* CONFIG_PM_SLEEP */
610 };
611
612 /* bus register interface */
613 int brcmf_bus_register(void)
614 {
615         brcmf_dbg(TRACE, "Enter\n");
616
617         return sdio_register_driver(&brcmf_sdmmc_driver);
618 }
619
620 void brcmf_bus_unregister(void)
621 {
622         brcmf_dbg(TRACE, "Enter\n");
623
624         sdio_unregister_driver(&brcmf_sdmmc_driver);
625 }