Merge branch 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[pandora-kernel.git] / drivers / staging / 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 /* ****************** BCMSDH Interface Functions *************************** */
17
18 #include <linux/types.h>
19 #include <linux/netdevice.h>
20 #include <bcmdefs.h>
21 #include <bcmdevs.h>
22 #include <bcmendian.h>
23 #include <osl.h>
24 #include <bcmutils.h>
25 #include <hndsoc.h>
26 #include <siutils.h>
27
28 #include <bcmsdh.h>             /* BRCM API for SDIO
29                          clients (such as wl, dhd) */
30 #include <bcmsdbus.h>           /* common SDIO/controller interface */
31 #include <sbsdio.h>             /* BRCM sdio device core */
32
33 #include <sdio.h>               /* sdio spec */
34
35 #define SDIOH_API_ACCESS_RETRY_LIMIT    2
36 const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL;
37
38 struct bcmsdh_info {
39         bool init_success;      /* underlying driver successfully attached */
40         void *sdioh;            /* handler for sdioh */
41         u32 vendevid;   /* Target Vendor and Device ID on SD bus */
42         struct osl_info *osh;
43         bool regfail;           /* Save status of last
44                                  reg_read/reg_write call */
45         u32 sbwad;              /* Save backplane window address */
46 };
47 /* local copy of bcm sd handler */
48 bcmsdh_info_t *l_bcmsdh;
49
50 #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
51 extern int sdioh_enable_hw_oob_intr(void *sdioh, bool enable);
52
53 void bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable)
54 {
55         sdioh_enable_hw_oob_intr(sdh->sdioh, enable);
56 }
57 #endif
58
59 bcmsdh_info_t *bcmsdh_attach(struct osl_info *osh, void *cfghdl,
60                                 void **regsva, uint irq)
61 {
62         bcmsdh_info_t *bcmsdh;
63
64         bcmsdh = kzalloc(sizeof(bcmsdh_info_t), GFP_ATOMIC);
65         if (bcmsdh == NULL) {
66                 BCMSDH_ERROR(("bcmsdh_attach: out of memory"));
67                 return NULL;
68         }
69
70         /* save the handler locally */
71         l_bcmsdh = bcmsdh;
72
73         bcmsdh->sdioh = sdioh_attach(osh, cfghdl, irq);
74         if (!bcmsdh->sdioh) {
75                 bcmsdh_detach(osh, bcmsdh);
76                 return NULL;
77         }
78
79         bcmsdh->osh = osh;
80         bcmsdh->init_success = true;
81
82         *regsva = (u32 *) SI_ENUM_BASE;
83
84         /* Report the BAR, to fix if needed */
85         bcmsdh->sbwad = SI_ENUM_BASE;
86         return bcmsdh;
87 }
88
89 int bcmsdh_detach(struct osl_info *osh, void *sdh)
90 {
91         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
92
93         if (bcmsdh != NULL) {
94                 if (bcmsdh->sdioh) {
95                         sdioh_detach(osh, bcmsdh->sdioh);
96                         bcmsdh->sdioh = NULL;
97                 }
98                 kfree(bcmsdh);
99         }
100
101         l_bcmsdh = NULL;
102         return 0;
103 }
104
105 int
106 bcmsdh_iovar_op(void *sdh, const char *name,
107                 void *params, int plen, void *arg, int len, bool set)
108 {
109         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
110         return sdioh_iovar_op(bcmsdh->sdioh, name, params, plen, arg, len, set);
111 }
112
113 bool bcmsdh_intr_query(void *sdh)
114 {
115         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
116         SDIOH_API_RC status;
117         bool on;
118
119         ASSERT(bcmsdh);
120         status = sdioh_interrupt_query(bcmsdh->sdioh, &on);
121         if (SDIOH_API_SUCCESS(status))
122                 return false;
123         else
124                 return on;
125 }
126
127 int bcmsdh_intr_enable(void *sdh)
128 {
129         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
130         SDIOH_API_RC status;
131         ASSERT(bcmsdh);
132
133         status = sdioh_interrupt_set(bcmsdh->sdioh, true);
134         return SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR;
135 }
136
137 int bcmsdh_intr_disable(void *sdh)
138 {
139         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
140         SDIOH_API_RC status;
141         ASSERT(bcmsdh);
142
143         status = sdioh_interrupt_set(bcmsdh->sdioh, false);
144         return SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR;
145 }
146
147 int bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
148 {
149         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
150         SDIOH_API_RC status;
151         ASSERT(bcmsdh);
152
153         status = sdioh_interrupt_register(bcmsdh->sdioh, fn, argh);
154         return SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR;
155 }
156
157 int bcmsdh_intr_dereg(void *sdh)
158 {
159         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
160         SDIOH_API_RC status;
161         ASSERT(bcmsdh);
162
163         status = sdioh_interrupt_deregister(bcmsdh->sdioh);
164         return SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR;
165 }
166
167 #if defined(DHD_DEBUG)
168 bool bcmsdh_intr_pending(void *sdh)
169 {
170         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
171
172         ASSERT(sdh);
173         return sdioh_interrupt_pending(bcmsdh->sdioh);
174 }
175 #endif
176
177 int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
178 {
179         ASSERT(sdh);
180
181         /* don't support yet */
182         return BCME_UNSUPPORTED;
183 }
184
185 u8 bcmsdh_cfg_read(void *sdh, uint fnc_num, u32 addr, int *err)
186 {
187         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
188         SDIOH_API_RC status;
189 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
190         s32 retry = 0;
191 #endif
192         u8 data = 0;
193
194         if (!bcmsdh)
195                 bcmsdh = l_bcmsdh;
196
197         ASSERT(bcmsdh->init_success);
198
199 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
200         do {
201                 if (retry)      /* wait for 1 ms till bus get settled down */
202                         udelay(1000);
203 #endif
204                 status =
205                     sdioh_cfg_read(bcmsdh->sdioh, fnc_num, addr,
206                                    (u8 *) &data);
207 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
208         } while (!SDIOH_API_SUCCESS(status)
209                  && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
210 #endif
211         if (err)
212                 *err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
213
214         BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
215                      __func__, fnc_num, addr, data));
216
217         return data;
218 }
219
220 void
221 bcmsdh_cfg_write(void *sdh, uint fnc_num, u32 addr, u8 data, int *err)
222 {
223         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
224         SDIOH_API_RC status;
225 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
226         s32 retry = 0;
227 #endif
228
229         if (!bcmsdh)
230                 bcmsdh = l_bcmsdh;
231
232         ASSERT(bcmsdh->init_success);
233
234 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
235         do {
236                 if (retry)      /* wait for 1 ms till bus get settled down */
237                         udelay(1000);
238 #endif
239                 status =
240                     sdioh_cfg_write(bcmsdh->sdioh, fnc_num, addr,
241                                     (u8 *) &data);
242 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
243         } while (!SDIOH_API_SUCCESS(status)
244                  && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
245 #endif
246         if (err)
247                 *err = SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR;
248
249         BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
250                      __func__, fnc_num, addr, data));
251 }
252
253 u32 bcmsdh_cfg_read_word(void *sdh, uint fnc_num, u32 addr, int *err)
254 {
255         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
256         SDIOH_API_RC status;
257         u32 data = 0;
258
259         if (!bcmsdh)
260                 bcmsdh = l_bcmsdh;
261
262         ASSERT(bcmsdh->init_success);
263
264         status =
265             sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_READ,
266                                fnc_num, addr, &data, 4);
267
268         if (err)
269                 *err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
270
271         BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
272                      __func__, fnc_num, addr, data));
273
274         return data;
275 }
276
277 void
278 bcmsdh_cfg_write_word(void *sdh, uint fnc_num, u32 addr, u32 data,
279                       int *err)
280 {
281         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
282         SDIOH_API_RC status;
283
284         if (!bcmsdh)
285                 bcmsdh = l_bcmsdh;
286
287         ASSERT(bcmsdh->init_success);
288
289         status =
290             sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
291                                SDIOH_WRITE, fnc_num, addr, &data, 4);
292
293         if (err)
294                 *err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
295
296         BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
297                      __func__, fnc_num, addr, data));
298 }
299
300 int bcmsdh_cis_read(void *sdh, uint func, u8 * cis, uint length)
301 {
302         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
303         SDIOH_API_RC status;
304
305         u8 *tmp_buf, *tmp_ptr;
306         u8 *ptr;
307         bool ascii = func & ~0xf;
308         func &= 0x7;
309
310         if (!bcmsdh)
311                 bcmsdh = l_bcmsdh;
312
313         ASSERT(bcmsdh->init_success);
314         ASSERT(cis);
315         ASSERT(length <= SBSDIO_CIS_SIZE_LIMIT);
316
317         status = sdioh_cis_read(bcmsdh->sdioh, func, cis, length);
318
319         if (ascii) {
320                 /* Move binary bits to tmp and format them
321                          into the provided buffer. */
322                 tmp_buf = kmalloc(length, GFP_ATOMIC);
323                 if (tmp_buf == NULL) {
324                         BCMSDH_ERROR(("%s: out of memory\n", __func__));
325                         return BCME_NOMEM;
326                 }
327                 bcopy(cis, tmp_buf, length);
328                 for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4);
329                      tmp_ptr++) {
330                         ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff);
331                         if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
332                                 ptr += sprintf((char *)ptr, "\n");
333                 }
334                 kfree(tmp_buf);
335         }
336
337         return SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR;
338 }
339
340 static int bcmsdhsdio_set_sbaddr_window(void *sdh, u32 address)
341 {
342         int err = 0;
343         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
344         bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
345                          (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
346         if (!err)
347                 bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
348                                  (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
349         if (!err)
350                 bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
351                                  (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
352                                  &err);
353
354         return err;
355 }
356
357 u32 bcmsdh_reg_read(void *sdh, u32 addr, uint size)
358 {
359         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
360         SDIOH_API_RC status;
361         u32 word = 0;
362         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
363
364         BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
365
366         if (!bcmsdh)
367                 bcmsdh = l_bcmsdh;
368
369         ASSERT(bcmsdh->init_success);
370
371         if (bar0 != bcmsdh->sbwad) {
372                 if (bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0))
373                         return 0xFFFFFFFF;
374
375                 bcmsdh->sbwad = bar0;
376         }
377
378         addr &= SBSDIO_SB_OFT_ADDR_MASK;
379         if (size == 4)
380                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
381
382         status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
383                                     SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
384
385         bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
386
387         BCMSDH_INFO(("u32data = 0x%x\n", word));
388
389         /* if ok, return appropriately masked word */
390         if (SDIOH_API_SUCCESS(status)) {
391                 switch (size) {
392                 case sizeof(u8):
393                         return word & 0xff;
394                 case sizeof(u16):
395                         return word & 0xffff;
396                 case sizeof(u32):
397                         return word;
398                 default:
399                         bcmsdh->regfail = true;
400
401                 }
402         }
403
404         /* otherwise, bad sdio access or invalid size */
405         BCMSDH_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
406                       addr, size));
407         return 0xFFFFFFFF;
408 }
409
410 u32 bcmsdh_reg_write(void *sdh, u32 addr, uint size, u32 data)
411 {
412         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
413         SDIOH_API_RC status;
414         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
415         int err = 0;
416
417         BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
418                      __func__, addr, size * 8, data));
419
420         if (!bcmsdh)
421                 bcmsdh = l_bcmsdh;
422
423         ASSERT(bcmsdh->init_success);
424
425         if (bar0 != bcmsdh->sbwad) {
426                 err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0);
427                 if (err)
428                         return err;
429
430                 bcmsdh->sbwad = bar0;
431         }
432
433         addr &= SBSDIO_SB_OFT_ADDR_MASK;
434         if (size == 4)
435                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
436         status =
437             sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
438                                SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size);
439         bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
440
441         if (SDIOH_API_SUCCESS(status))
442                 return 0;
443
444         BCMSDH_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
445                       __func__, data, addr, size));
446         return 0xFFFFFFFF;
447 }
448
449 bool bcmsdh_regfail(void *sdh)
450 {
451         return ((bcmsdh_info_t *) sdh)->regfail;
452 }
453
454 int
455 bcmsdh_recv_buf(void *sdh, u32 addr, uint fn, uint flags,
456                 u8 *buf, uint nbytes, struct sk_buff *pkt,
457                 bcmsdh_cmplt_fn_t complete, void *handle)
458 {
459         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
460         SDIOH_API_RC status;
461         uint incr_fix;
462         uint width;
463         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
464         int err = 0;
465
466         ASSERT(bcmsdh);
467         ASSERT(bcmsdh->init_success);
468
469         BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
470                      __func__, fn, addr, nbytes));
471
472         /* Async not implemented yet */
473         ASSERT(!(flags & SDIO_REQ_ASYNC));
474         if (flags & SDIO_REQ_ASYNC)
475                 return BCME_UNSUPPORTED;
476
477         if (bar0 != bcmsdh->sbwad) {
478                 err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0);
479                 if (err)
480                         return err;
481
482                 bcmsdh->sbwad = bar0;
483         }
484
485         addr &= SBSDIO_SB_OFT_ADDR_MASK;
486
487         incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
488         width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
489         if (width == 4)
490                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
491
492         status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
493                                       SDIOH_READ, fn, addr, width, nbytes, buf,
494                                       pkt);
495
496         return SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR;
497 }
498
499 int
500 bcmsdh_send_buf(void *sdh, u32 addr, uint fn, uint flags,
501                 u8 *buf, uint nbytes, void *pkt,
502                 bcmsdh_cmplt_fn_t complete, void *handle)
503 {
504         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
505         SDIOH_API_RC status;
506         uint incr_fix;
507         uint width;
508         uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
509         int err = 0;
510
511         ASSERT(bcmsdh);
512         ASSERT(bcmsdh->init_success);
513
514         BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
515                      __func__, fn, addr, nbytes));
516
517         /* Async not implemented yet */
518         ASSERT(!(flags & SDIO_REQ_ASYNC));
519         if (flags & SDIO_REQ_ASYNC)
520                 return BCME_UNSUPPORTED;
521
522         if (bar0 != bcmsdh->sbwad) {
523                 err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0);
524                 if (err)
525                         return err;
526
527                 bcmsdh->sbwad = bar0;
528         }
529
530         addr &= SBSDIO_SB_OFT_ADDR_MASK;
531
532         incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
533         width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
534         if (width == 4)
535                 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
536
537         status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
538                                       SDIOH_WRITE, fn, addr, width, nbytes, buf,
539                                       pkt);
540
541         return SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR;
542 }
543
544 int bcmsdh_rwdata(void *sdh, uint rw, u32 addr, u8 *buf, uint nbytes)
545 {
546         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
547         SDIOH_API_RC status;
548
549         ASSERT(bcmsdh);
550         ASSERT(bcmsdh->init_success);
551         ASSERT((addr & SBSDIO_SBWINDOW_MASK) == 0);
552
553         addr &= SBSDIO_SB_OFT_ADDR_MASK;
554         addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
555
556         status =
557             sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, SDIOH_DATA_INC,
558                                  (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
559                                  addr, 4, nbytes, buf, NULL);
560
561         return SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR;
562 }
563
564 int bcmsdh_abort(void *sdh, uint fn)
565 {
566         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
567
568         return sdioh_abort(bcmsdh->sdioh, fn);
569 }
570
571 int bcmsdh_start(void *sdh, int stage)
572 {
573         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
574
575         return sdioh_start(bcmsdh->sdioh, stage);
576 }
577
578 int bcmsdh_stop(void *sdh)
579 {
580         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
581
582         return sdioh_stop(bcmsdh->sdioh);
583 }
584
585 int bcmsdh_query_device(void *sdh)
586 {
587         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
588         bcmsdh->vendevid = (VENDOR_BROADCOM << 16) | 0;
589         return bcmsdh->vendevid;
590 }
591
592 uint bcmsdh_query_iofnum(void *sdh)
593 {
594         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
595
596         if (!bcmsdh)
597                 bcmsdh = l_bcmsdh;
598
599         return sdioh_query_iofnum(bcmsdh->sdioh);
600 }
601
602 int bcmsdh_reset(bcmsdh_info_t *sdh)
603 {
604         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
605
606         return sdioh_sdio_reset(bcmsdh->sdioh);
607 }
608
609 void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh)
610 {
611         ASSERT(sdh);
612         return sdh->sdioh;
613 }
614
615 /* Function to pass device-status bits to DHD. */
616 u32 bcmsdh_get_dstatus(void *sdh)
617 {
618         return 0;
619 }
620
621 u32 bcmsdh_cur_sbwad(void *sdh)
622 {
623         bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
624
625         if (!bcmsdh)
626                 bcmsdh = l_bcmsdh;
627
628         return bcmsdh->sbwad;
629 }
630
631 void bcmsdh_chipinfo(void *sdh, u32 chip, u32 chiprev)
632 {
633         return;
634 }