Revert "Merge commit 'main-jb-2012.08.03-B4' into t114-0806"
[linux-2.6.git] / drivers / net / wireless / bcmdhd / bcmsdh_sdmmc.c
1 /*
2  * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
3  *
4  * Copyright (C) 1999-2012, Broadcom Corporation
5  * 
6  *      Unless you and Broadcom execute a separate written software license
7  * agreement governing use of this software, this software is licensed to you
8  * under the terms of the GNU General Public License version 2 (the "GPL"),
9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10  * following added to such license:
11  * 
12  *      As a special exception, the copyright holders of this software give you
13  * permission to link this software with independent modules, and to copy and
14  * distribute the resulting executable under terms of your choice, provided that
15  * you also meet, for each linked independent module, the terms and conditions of
16  * the license of that module.  An independent module is a module which is not
17  * derived from this software.  The special exception does not apply to any
18  * modifications of the software.
19  * 
20  *      Notwithstanding the above, under no circumstances may you combine this
21  * software in any way with any other Broadcom software provided under a license
22  * other than the GPL, without Broadcom's express prior written consent.
23  *
24  * $Id: bcmsdh_sdmmc.c 337979 2012-06-09 08:33:23Z $
25  */
26 #include <typedefs.h>
27
28 #include <bcmdevs.h>
29 #include <bcmendian.h>
30 #include <bcmutils.h>
31 #include <osl.h>
32 #include <sdio.h>       /* SDIO Device and Protocol Specs */
33 #include <sdioh.h>      /* Standard SDIO Host Controller Specification */
34 #include <bcmsdbus.h>   /* bcmsdh to/from specific controller APIs */
35 #include <sdiovar.h>    /* ioctl/iovars */
36
37 #include <linux/mmc/core.h>
38 #include <linux/mmc/card.h>
39 #include <linux/mmc/sdio_func.h>
40 #include <linux/mmc/sdio_ids.h>
41
42 #include <dngl_stats.h>
43 #include <dhd.h>
44
45 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
46 #include <linux/suspend.h>
47 extern volatile bool dhd_mmc_suspend;
48 #endif
49 #include "bcmsdh_sdmmc.h"
50
51 #ifndef BCMSDH_MODULE
52 extern int sdio_function_init(void);
53 extern void sdio_function_cleanup(void);
54 #endif /* BCMSDH_MODULE */
55
56 #if !defined(OOB_INTR_ONLY)
57 static void IRQHandler(struct sdio_func *func);
58 static void IRQHandlerF2(struct sdio_func *func);
59 #endif /* !defined(OOB_INTR_ONLY) */
60 static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr);
61 extern int sdio_reset_comm(struct mmc_card *card);
62
63 extern PBCMSDH_SDMMC_INSTANCE gInstance;
64
65 uint sd_sdmode = SDIOH_MODE_SD4;        /* Use SD4 mode by default */
66 #if defined(SDIO_F2_BLKSIZE)
67 uint sd_f2_blocksize = SDIO_F2_BLKSIZE;
68 #else
69 uint sd_f2_blocksize = 512;             /* Default blocksize */
70 #endif
71 uint sd_divisor = 2;                    /* Default 48MHz/2 = 24MHz */
72
73 uint sd_power = 1;              /* Default to SD Slot powered ON */
74 uint sd_clock = 1;              /* Default to SD Clock turned ON */
75 uint sd_hiok = FALSE;   /* Don't use hi-speed mode by default */
76 uint sd_msglevel = 0x01;
77 uint sd_use_dma = TRUE;
78 DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
79 DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
80 DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
81 DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
82
83 #define DMA_ALIGN_MASK  0x03
84
85 int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data);
86
87 static int
88 sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
89 {
90         int err_ret;
91         uint32 fbraddr;
92         uint8 func;
93
94         sd_trace(("%s\n", __FUNCTION__));
95
96         /* Get the Card's common CIS address */
97         sd->com_cis_ptr = sdioh_sdmmc_get_cisaddr(sd, SDIOD_CCCR_CISPTR_0);
98         sd->func_cis_ptr[0] = sd->com_cis_ptr;
99         sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr));
100
101         /* Get the Card's function CIS (for each function) */
102         for (fbraddr = SDIOD_FBR_STARTADDR, func = 1;
103              func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
104                 sd->func_cis_ptr[func] = sdioh_sdmmc_get_cisaddr(sd, SDIOD_FBR_CISPTR_0 + fbraddr);
105                 sd_info(("%s: Function %d CIS Ptr = 0x%x\n",
106                          __FUNCTION__, func, sd->func_cis_ptr[func]));
107         }
108
109         sd->func_cis_ptr[0] = sd->com_cis_ptr;
110         sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr));
111
112         /* Enable Function 1 */
113         sdio_claim_host(gInstance->func[1]);
114         err_ret = sdio_enable_func(gInstance->func[1]);
115         sdio_release_host(gInstance->func[1]);
116         if (err_ret) {
117                 sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x", err_ret));
118         }
119
120         return FALSE;
121 }
122
123 /*
124  *      Public entry points & extern's
125  */
126 extern sdioh_info_t *
127 sdioh_attach(osl_t *osh, void *bar0, uint irq)
128 {
129         sdioh_info_t *sd;
130         int err_ret;
131
132         sd_trace(("%s\n", __FUNCTION__));
133
134         if (gInstance == NULL) {
135                 sd_err(("%s: SDIO Device not present\n", __FUNCTION__));
136                 return NULL;
137         }
138
139         if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) {
140                 sd_err(("sdioh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh)));
141                 return NULL;
142         }
143         bzero((char *)sd, sizeof(sdioh_info_t));
144         sd->osh = osh;
145         if (sdioh_sdmmc_osinit(sd) != 0) {
146                 sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __FUNCTION__));
147                 MFREE(sd->osh, sd, sizeof(sdioh_info_t));
148                 return NULL;
149         }
150
151         sd->num_funcs = 2;
152         sd->sd_blockmode = TRUE;
153         sd->use_client_ints = TRUE;
154         sd->client_block_size[0] = 64;
155         sd->use_rxchain = FALSE;
156
157         gInstance->sd = sd;
158
159         /* Claim host controller */
160         if (gInstance->func[1]) {
161                 sdio_claim_host(gInstance->func[1]);
162
163                 sd->client_block_size[1] = 64;
164                 err_ret = sdio_set_block_size(gInstance->func[1], 64);
165                 if (err_ret) {
166                         sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n"));
167                 }
168
169                 /* Release host controller F1 */
170                 sdio_release_host(gInstance->func[1]);
171         } else {
172                 sd_err(("%s:gInstance->func[1] is null\n", __FUNCTION__));
173                 MFREE(sd->osh, sd, sizeof(sdioh_info_t));
174                 return NULL;
175         }
176
177         if (gInstance->func[2]) {
178                 /* Claim host controller F2 */
179                 sdio_claim_host(gInstance->func[2]);
180
181                 sd->client_block_size[2] = sd_f2_blocksize;
182                 err_ret = sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
183                 if (err_ret) {
184                         sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize to %d\n",
185                                 sd_f2_blocksize));
186                 }
187
188                 /* Release host controller F2 */
189                 sdio_release_host(gInstance->func[2]);
190         } else {
191                 sd_err(("%s:gInstance->func[2] is null\n", __FUNCTION__));
192                 MFREE(sd->osh, sd, sizeof(sdioh_info_t));
193                 return NULL;
194         }
195
196         sdioh_sdmmc_card_enablefuncs(sd);
197
198         sd_trace(("%s: Done\n", __FUNCTION__));
199         return sd;
200 }
201
202
203 extern SDIOH_API_RC
204 sdioh_detach(osl_t *osh, sdioh_info_t *sd)
205 {
206         sd_trace(("%s\n", __FUNCTION__));
207
208         if (sd) {
209
210                 /* Disable Function 2 */
211                 sdio_claim_host(gInstance->func[2]);
212                 sdio_disable_func(gInstance->func[2]);
213                 sdio_release_host(gInstance->func[2]);
214
215                 /* Disable Function 1 */
216                 if (gInstance->func[1]) {
217                         sdio_claim_host(gInstance->func[1]);
218                         sdio_disable_func(gInstance->func[1]);
219                         sdio_release_host(gInstance->func[1]);
220                 }
221
222                 gInstance->func[1] = NULL;
223                 gInstance->func[2] = NULL;
224
225                 /* deregister irq */
226                 sdioh_sdmmc_osfree(sd);
227
228                 MFREE(sd->osh, sd, sizeof(sdioh_info_t));
229         }
230         return SDIOH_API_RC_SUCCESS;
231 }
232
233 #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
234
235 extern SDIOH_API_RC
236 sdioh_enable_func_intr(void)
237 {
238         uint8 reg;
239         int err;
240
241         if (gInstance->func[0]) {
242                 sdio_claim_host(gInstance->func[0]);
243
244                 reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &err);
245                 if (err) {
246                         sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
247                         sdio_release_host(gInstance->func[0]);
248                         return SDIOH_API_RC_FAIL;
249                 }
250
251                 /* Enable F1 and F2 interrupts, set master enable */
252                 reg |= (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN | INTR_CTL_MASTER_EN);
253
254                 sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err);
255                 sdio_release_host(gInstance->func[0]);
256
257                 if (err) {
258                         sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
259                         return SDIOH_API_RC_FAIL;
260                 }
261         }
262
263         return SDIOH_API_RC_SUCCESS;
264 }
265
266 #endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
267
268 extern SDIOH_API_RC
269 sdioh_disable_func_intr(int func)
270 {
271         uint8 reg;
272         int err;
273
274         if (gInstance->func[func]) {
275                 sdio_claim_host(gInstance->func[func]);
276                 reg = sdio_readb(gInstance->func[func], SDIOD_CCCR_INTEN, &err);
277                 if (err) {
278                         sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
279                         sdio_release_host(gInstance->func[func]);
280                         return SDIOH_API_RC_FAIL;
281                 }
282 #if defined(HW_OOB)
283                 reg &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN);
284 #else
285                 reg &= ~(1 << func);
286 #endif
287                 /* Disable master interrupt with the last function interrupt */
288                 if (!(reg & 0xFE))
289                         reg = 0;
290                 sdio_writeb(gInstance->func[func], reg, SDIOD_CCCR_INTEN, &err);
291
292                 sdio_release_host(gInstance->func[func]);
293                 if (err) {
294                         sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
295                         return SDIOH_API_RC_FAIL;
296                 }
297         }
298         return SDIOH_API_RC_SUCCESS;
299 }
300
301
302 /* Configure callback to client when we recieve client interrupt */
303 extern SDIOH_API_RC
304 sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
305 {
306         sd_trace(("%s: Entering\n", __FUNCTION__));
307         if (fn == NULL) {
308                 sd_err(("%s: interrupt handler is NULL, not registering\n", __FUNCTION__));
309                 return SDIOH_API_RC_FAIL;
310         }
311 #if !defined(OOB_INTR_ONLY)
312         sd->intr_handler = fn;
313         sd->intr_handler_arg = argh;
314         sd->intr_handler_valid = TRUE;
315
316         /* register and unmask irq */
317         if (gInstance->func[2]) {
318                 sdio_claim_host(gInstance->func[2]);
319                 sdio_claim_irq(gInstance->func[2], IRQHandlerF2);
320                 sdio_release_host(gInstance->func[2]);
321         }
322
323         if (gInstance->func[1]) {
324                 sdio_claim_host(gInstance->func[1]);
325                 sdio_claim_irq(gInstance->func[1], IRQHandler);
326                 sdio_release_host(gInstance->func[1]);
327         }
328 #elif defined(HW_OOB)
329         sdioh_enable_func_intr();
330 #endif /* !defined(OOB_INTR_ONLY) */
331
332         return SDIOH_API_RC_SUCCESS;
333 }
334
335 extern SDIOH_API_RC
336 sdioh_interrupt_deregister(sdioh_info_t *sd)
337 {
338         sd_trace(("%s: Entering\n", __FUNCTION__));
339
340 #if !defined(OOB_INTR_ONLY)
341         if (gInstance->func[1]) {
342                 sdioh_disable_func_intr(1);
343                 /*Wait for the pending interrupts to be cleared*/
344                 msleep(300);
345                 /* register and unmask irq */
346                 sdio_claim_host(gInstance->func[1]);
347                 sdio_release_irq(gInstance->func[1]);
348                 sdio_release_host(gInstance->func[1]);
349         }
350
351         if (gInstance->func[2]) {
352                 sdioh_disable_func_intr(2);
353                 /*Wait for the pending interrupts to be cleared*/
354                 msleep(300);
355                 /* Claim host controller F2 */
356                 sdio_claim_host(gInstance->func[2]);
357                 sdio_release_irq(gInstance->func[2]);
358                 /* Release host controller F2 */
359                 sdio_release_host(gInstance->func[2]);
360         }
361
362         sd->intr_handler_valid = FALSE;
363         sd->intr_handler = NULL;
364         sd->intr_handler_arg = NULL;
365 #elif defined(HW_OOB)
366         sdioh_disable_func_intr(0);
367 #endif /* !defined(OOB_INTR_ONLY) */
368         return SDIOH_API_RC_SUCCESS;
369 }
370
371 extern SDIOH_API_RC
372 sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
373 {
374         sd_trace(("%s: Entering\n", __FUNCTION__));
375         *onoff = sd->client_intr_enabled;
376         return SDIOH_API_RC_SUCCESS;
377 }
378
379 #if defined(DHD_DEBUG)
380 extern bool
381 sdioh_interrupt_pending(sdioh_info_t *sd)
382 {
383         return (0);
384 }
385 #endif
386
387 uint
388 sdioh_query_iofnum(sdioh_info_t *sd)
389 {
390         return sd->num_funcs;
391 }
392
393 /* IOVar table */
394 enum {
395         IOV_MSGLEVEL = 1,
396         IOV_BLOCKMODE,
397         IOV_BLOCKSIZE,
398         IOV_DMA,
399         IOV_USEINTS,
400         IOV_NUMINTS,
401         IOV_NUMLOCALINTS,
402         IOV_HOSTREG,
403         IOV_DEVREG,
404         IOV_DIVISOR,
405         IOV_SDMODE,
406         IOV_HISPEED,
407         IOV_HCIREGS,
408         IOV_POWER,
409         IOV_CLOCK,
410         IOV_RXCHAIN
411 };
412
413 const bcm_iovar_t sdioh_iovars[] = {
414         {"sd_msglevel", IOV_MSGLEVEL,   0,      IOVT_UINT32,    0 },
415         {"sd_blockmode", IOV_BLOCKMODE, 0,      IOVT_BOOL,      0 },
416         {"sd_blocksize", IOV_BLOCKSIZE, 0,      IOVT_UINT32,    0 }, /* ((fn << 16) | size) */
417         {"sd_dma",      IOV_DMA,        0,      IOVT_BOOL,      0 },
418         {"sd_ints",     IOV_USEINTS,    0,      IOVT_BOOL,      0 },
419         {"sd_numints",  IOV_NUMINTS,    0,      IOVT_UINT32,    0 },
420         {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32,   0 },
421         {"sd_hostreg",  IOV_HOSTREG,    0,      IOVT_BUFFER,    sizeof(sdreg_t) },
422         {"sd_devreg",   IOV_DEVREG,     0,      IOVT_BUFFER,    sizeof(sdreg_t) },
423         {"sd_divisor",  IOV_DIVISOR,    0,      IOVT_UINT32,    0 },
424         {"sd_power",    IOV_POWER,      0,      IOVT_UINT32,    0 },
425         {"sd_clock",    IOV_CLOCK,      0,      IOVT_UINT32,    0 },
426         {"sd_mode",     IOV_SDMODE,     0,      IOVT_UINT32,    100},
427         {"sd_highspeed", IOV_HISPEED,   0,      IOVT_UINT32,    0 },
428         {"sd_rxchain",  IOV_RXCHAIN,    0,      IOVT_BOOL,      0 },
429         {NULL, 0, 0, 0, 0 }
430 };
431
432 int
433 sdioh_iovar_op(sdioh_info_t *si, const char *name,
434                            void *params, int plen, void *arg, int len, bool set)
435 {
436         const bcm_iovar_t *vi = NULL;
437         int bcmerror = 0;
438         int val_size;
439         int32 int_val = 0;
440         bool bool_val;
441         uint32 actionid;
442
443         ASSERT(name);
444         ASSERT(len >= 0);
445
446         /* Get must have return space; Set does not take qualifiers */
447         ASSERT(set || (arg && len));
448         ASSERT(!set || (!params && !plen));
449
450         sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name));
451
452         if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) {
453                 bcmerror = BCME_UNSUPPORTED;
454                 goto exit;
455         }
456
457         if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0)
458                 goto exit;
459
460         /* Set up params so get and set can share the convenience variables */
461         if (params == NULL) {
462                 params = arg;
463                 plen = len;
464         }
465
466         if (vi->type == IOVT_VOID)
467                 val_size = 0;
468         else if (vi->type == IOVT_BUFFER)
469                 val_size = len;
470         else
471                 val_size = sizeof(int);
472
473         if (plen >= (int)sizeof(int_val))
474                 bcopy(params, &int_val, sizeof(int_val));
475
476         bool_val = (int_val != 0) ? TRUE : FALSE;
477         BCM_REFERENCE(bool_val);
478
479         actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
480         switch (actionid) {
481         case IOV_GVAL(IOV_MSGLEVEL):
482                 int_val = (int32)sd_msglevel;
483                 bcopy(&int_val, arg, val_size);
484                 break;
485
486         case IOV_SVAL(IOV_MSGLEVEL):
487                 sd_msglevel = int_val;
488                 break;
489
490         case IOV_GVAL(IOV_BLOCKMODE):
491                 int_val = (int32)si->sd_blockmode;
492                 bcopy(&int_val, arg, val_size);
493                 break;
494
495         case IOV_SVAL(IOV_BLOCKMODE):
496                 si->sd_blockmode = (bool)int_val;
497                 /* Haven't figured out how to make non-block mode with DMA */
498                 break;
499
500         case IOV_GVAL(IOV_BLOCKSIZE):
501                 if ((uint32)int_val > si->num_funcs) {
502                         bcmerror = BCME_BADARG;
503                         break;
504                 }
505                 int_val = (int32)si->client_block_size[int_val];
506                 bcopy(&int_val, arg, val_size);
507                 break;
508
509         case IOV_SVAL(IOV_BLOCKSIZE):
510         {
511                 uint func = ((uint32)int_val >> 16);
512                 uint blksize = (uint16)int_val;
513                 uint maxsize;
514
515                 if (func > si->num_funcs) {
516                         bcmerror = BCME_BADARG;
517                         break;
518                 }
519
520                 switch (func) {
521                 case 0: maxsize = 32; break;
522                 case 1: maxsize = BLOCK_SIZE_4318; break;
523                 case 2: maxsize = BLOCK_SIZE_4328; break;
524                 default: maxsize = 0;
525                 }
526                 if (blksize > maxsize) {
527                         bcmerror = BCME_BADARG;
528                         break;
529                 }
530                 if (!blksize) {
531                         blksize = maxsize;
532                 }
533
534                 /* Now set it */
535                 si->client_block_size[func] = blksize;
536
537                 break;
538         }
539
540         case IOV_GVAL(IOV_RXCHAIN):
541                 int_val = (int32)si->use_rxchain;
542                 bcopy(&int_val, arg, val_size);
543                 break;
544
545         case IOV_GVAL(IOV_DMA):
546                 int_val = (int32)si->sd_use_dma;
547                 bcopy(&int_val, arg, val_size);
548                 break;
549
550         case IOV_SVAL(IOV_DMA):
551                 si->sd_use_dma = (bool)int_val;
552                 break;
553
554         case IOV_GVAL(IOV_USEINTS):
555                 int_val = (int32)si->use_client_ints;
556                 bcopy(&int_val, arg, val_size);
557                 break;
558
559         case IOV_SVAL(IOV_USEINTS):
560                 si->use_client_ints = (bool)int_val;
561                 if (si->use_client_ints)
562                         si->intmask |= CLIENT_INTR;
563                 else
564                         si->intmask &= ~CLIENT_INTR;
565
566                 break;
567
568         case IOV_GVAL(IOV_DIVISOR):
569                 int_val = (uint32)sd_divisor;
570                 bcopy(&int_val, arg, val_size);
571                 break;
572
573         case IOV_SVAL(IOV_DIVISOR):
574                 sd_divisor = int_val;
575                 break;
576
577         case IOV_GVAL(IOV_POWER):
578                 int_val = (uint32)sd_power;
579                 bcopy(&int_val, arg, val_size);
580                 break;
581
582         case IOV_SVAL(IOV_POWER):
583                 sd_power = int_val;
584                 break;
585
586         case IOV_GVAL(IOV_CLOCK):
587                 int_val = (uint32)sd_clock;
588                 bcopy(&int_val, arg, val_size);
589                 break;
590
591         case IOV_SVAL(IOV_CLOCK):
592                 sd_clock = int_val;
593                 break;
594
595         case IOV_GVAL(IOV_SDMODE):
596                 int_val = (uint32)sd_sdmode;
597                 bcopy(&int_val, arg, val_size);
598                 break;
599
600         case IOV_SVAL(IOV_SDMODE):
601                 sd_sdmode = int_val;
602                 break;
603
604         case IOV_GVAL(IOV_HISPEED):
605                 int_val = (uint32)sd_hiok;
606                 bcopy(&int_val, arg, val_size);
607                 break;
608
609         case IOV_SVAL(IOV_HISPEED):
610                 sd_hiok = int_val;
611                 break;
612
613         case IOV_GVAL(IOV_NUMINTS):
614                 int_val = (int32)si->intrcount;
615                 bcopy(&int_val, arg, val_size);
616                 break;
617
618         case IOV_GVAL(IOV_NUMLOCALINTS):
619                 int_val = (int32)0;
620                 bcopy(&int_val, arg, val_size);
621                 break;
622
623         case IOV_GVAL(IOV_HOSTREG):
624         {
625                 sdreg_t *sd_ptr = (sdreg_t *)params;
626
627                 if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) {
628                         sd_err(("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset));
629                         bcmerror = BCME_BADARG;
630                         break;
631                 }
632
633                 sd_trace(("%s: rreg%d at offset %d\n", __FUNCTION__,
634                                   (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32),
635                                   sd_ptr->offset));
636                 if (sd_ptr->offset & 1)
637                         int_val = 8; /* sdioh_sdmmc_rreg8(si, sd_ptr->offset); */
638                 else if (sd_ptr->offset & 2)
639                         int_val = 16; /* sdioh_sdmmc_rreg16(si, sd_ptr->offset); */
640                 else
641                         int_val = 32; /* sdioh_sdmmc_rreg(si, sd_ptr->offset); */
642
643                 bcopy(&int_val, arg, sizeof(int_val));
644                 break;
645         }
646
647         case IOV_SVAL(IOV_HOSTREG):
648         {
649                 sdreg_t *sd_ptr = (sdreg_t *)params;
650
651                 if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) {
652                         sd_err(("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset));
653                         bcmerror = BCME_BADARG;
654                         break;
655                 }
656
657                 sd_trace(("%s: wreg%d value 0x%08x at offset %d\n", __FUNCTION__, sd_ptr->value,
658                                   (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32),
659                                   sd_ptr->offset));
660                 break;
661         }
662
663         case IOV_GVAL(IOV_DEVREG):
664         {
665                 sdreg_t *sd_ptr = (sdreg_t *)params;
666                 uint8 data = 0;
667
668                 if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) {
669                         bcmerror = BCME_SDIO_ERROR;
670                         break;
671                 }
672
673                 int_val = (int)data;
674                 bcopy(&int_val, arg, sizeof(int_val));
675                 break;
676         }
677
678         case IOV_SVAL(IOV_DEVREG):
679         {
680                 sdreg_t *sd_ptr = (sdreg_t *)params;
681                 uint8 data = (uint8)sd_ptr->value;
682
683                 if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) {
684                         bcmerror = BCME_SDIO_ERROR;
685                         break;
686                 }
687                 break;
688         }
689
690         default:
691                 bcmerror = BCME_UNSUPPORTED;
692                 break;
693         }
694 exit:
695
696         return bcmerror;
697 }
698
699 #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
700
701 SDIOH_API_RC
702 sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
703 {
704         SDIOH_API_RC status;
705         uint8 data;
706
707         if (enable)
708                 data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE | SDIO_SEPINT_ACT_HI;
709         else
710                 data = SDIO_SEPINT_ACT_HI;      /* disable hw oob interrupt */
711
712         status = sdioh_request_byte(sd, SDIOH_WRITE, 0, SDIOD_CCCR_BRCM_SEPINT, &data);
713         return status;
714 }
715 #endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
716
717 extern SDIOH_API_RC
718 sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
719 {
720         SDIOH_API_RC status;
721         /* No lock needed since sdioh_request_byte does locking */
722         status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
723         return status;
724 }
725
726 extern SDIOH_API_RC
727 sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
728 {
729         /* No lock needed since sdioh_request_byte does locking */
730         SDIOH_API_RC status;
731         status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
732         return status;
733 }
734
735 static int
736 sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr)
737 {
738         /* read 24 bits and return valid 17 bit addr */
739         int i;
740         uint32 scratch, regdata;
741         uint8 *ptr = (uint8 *)&scratch;
742         for (i = 0; i < 3; i++) {
743                 if ((sdioh_sdmmc_card_regread (sd, 0, regaddr, 1, &regdata)) != SUCCESS)
744                         sd_err(("%s: Can't read!\n", __FUNCTION__));
745
746                 *ptr++ = (uint8) regdata;
747                 regaddr++;
748         }
749
750         /* Only the lower 17-bits are valid */
751         scratch = ltoh32(scratch);
752         scratch &= 0x0001FFFF;
753         return (scratch);
754 }
755
756 extern SDIOH_API_RC
757 sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length)
758 {
759         uint32 count;
760         int offset;
761         uint32 foo;
762         uint8 *cis = cisd;
763
764         sd_trace(("%s: Func = %d\n", __FUNCTION__, func));
765
766         if (!sd->func_cis_ptr[func]) {
767                 bzero(cis, length);
768                 sd_err(("%s: no func_cis_ptr[%d]\n", __FUNCTION__, func));
769                 return SDIOH_API_RC_FAIL;
770         }
771
772         sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __FUNCTION__, func, sd->func_cis_ptr[func]));
773
774         for (count = 0; count < length; count++) {
775                 offset =  sd->func_cis_ptr[func] + count;
776                 if (sdioh_sdmmc_card_regread (sd, 0, offset, 1, &foo) < 0) {
777                         sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__));
778                         return SDIOH_API_RC_FAIL;
779                 }
780
781                 *cis = (uint8)(foo & 0xff);
782                 cis++;
783         }
784
785         return SDIOH_API_RC_SUCCESS;
786 }
787
788 extern SDIOH_API_RC
789 sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte)
790 {
791         int err_ret;
792
793         sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr));
794
795         DHD_PM_RESUME_WAIT(sdioh_request_byte_wait);
796         DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
797         if(rw) { /* CMD52 Write */
798                 if (func == 0) {
799                         /* Can only directly write to some F0 registers.  Handle F2 enable
800                          * as a special case.
801                          */
802                         if (regaddr == SDIOD_CCCR_IOEN) {
803                                 if (gInstance->func[2]) {
804                                         sdio_claim_host(gInstance->func[2]);
805                                         if (*byte & SDIO_FUNC_ENABLE_2) {
806                                                 /* Enable Function 2 */
807                                                 err_ret = sdio_enable_func(gInstance->func[2]);
808                                                 if (err_ret) {
809                                                         sd_err(("bcmsdh_sdmmc: enable F2 failed:%d",
810                                                                 err_ret));
811                                                 }
812                                         } else {
813                                                 /* Disable Function 2 */
814                                                 err_ret = sdio_disable_func(gInstance->func[2]);
815                                                 if (err_ret) {
816                                                         sd_err(("bcmsdh_sdmmc: Disab F2 failed:%d",
817                                                                 err_ret));
818                                                 }
819                                         }
820                                         sdio_release_host(gInstance->func[2]);
821                                 }
822                         }
823 #if defined(MMC_SDIO_ABORT)
824                         /* to allow abort command through F1 */
825                         else if (regaddr == SDIOD_CCCR_IOABORT) {
826                                 if (gInstance->func[func]) {
827                                         sdio_claim_host(gInstance->func[func]);
828                                         /*
829                                         * this sdio_f0_writeb() can be replaced with another api
830                                         * depending upon MMC driver change.
831                                         * As of this time, this is temporaray one
832                                         */
833                                         sdio_writeb(gInstance->func[func],
834                                                 *byte, regaddr, &err_ret);
835                                         sdio_release_host(gInstance->func[func]);
836                                 }
837                         }
838 #endif /* MMC_SDIO_ABORT */
839                         else if (regaddr < 0xF0) {
840                                 sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr));
841                         } else {
842                                 /* Claim host controller, perform F0 write, and release */
843                                 if (gInstance->func[func]) {
844                                         sdio_claim_host(gInstance->func[func]);
845                                         sdio_f0_writeb(gInstance->func[func],
846                                                 *byte, regaddr, &err_ret);
847                                         sdio_release_host(gInstance->func[func]);
848                                 }
849                         }
850                 } else {
851                         /* Claim host controller, perform Fn write, and release */
852                         if (gInstance->func[func]) {
853                                 sdio_claim_host(gInstance->func[func]);
854                                 sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
855                                 sdio_release_host(gInstance->func[func]);
856                         }
857                 }
858         } else { /* CMD52 Read */
859                 /* Claim host controller, perform Fn read, and release */
860                 if (gInstance->func[func]) {
861                         sdio_claim_host(gInstance->func[func]);
862                         if (func == 0) {
863                                 *byte = sdio_f0_readb(gInstance->func[func], regaddr, &err_ret);
864                         } else {
865                                 *byte = sdio_readb(gInstance->func[func], regaddr, &err_ret);
866                         }
867                         sdio_release_host(gInstance->func[func]);
868                 }
869         }
870
871         if (err_ret) {
872                 sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
873                                         rw ? "Write" : "Read", func, regaddr, *byte, err_ret));
874         }
875
876         return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
877 }
878
879 extern SDIOH_API_RC
880 sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr,
881                                    uint32 *word, uint nbytes)
882 {
883         int err_ret = SDIOH_API_RC_FAIL;
884
885         if (func == 0) {
886                 sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__));
887                 return SDIOH_API_RC_FAIL;
888         }
889
890         sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
891                  __FUNCTION__, cmd_type, rw, func, addr, nbytes));
892
893         DHD_PM_RESUME_WAIT(sdioh_request_word_wait);
894         DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
895         /* Claim host controller */
896         sdio_claim_host(gInstance->func[func]);
897
898         if(rw) { /* CMD52 Write */
899                 if (nbytes == 4) {
900                         sdio_writel(gInstance->func[func], *word, addr, &err_ret);
901                 } else if (nbytes == 2) {
902                         sdio_writew(gInstance->func[func], (*word & 0xFFFF), addr, &err_ret);
903                 } else {
904                         sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes));
905                 }
906         } else { /* CMD52 Read */
907                 if (nbytes == 4) {
908                         *word = sdio_readl(gInstance->func[func], addr, &err_ret);
909                 } else if (nbytes == 2) {
910                         *word = sdio_readw(gInstance->func[func], addr, &err_ret) & 0xFFFF;
911                 } else {
912                         sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes));
913                 }
914         }
915
916         /* Release host controller */
917         sdio_release_host(gInstance->func[func]);
918
919         if (err_ret) {
920                 sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x",
921                                         rw ? "Write" : "Read", err_ret));
922         }
923
924         return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
925 }
926
927 static SDIOH_API_RC
928 sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
929                      uint addr, void *pkt)
930 {
931         bool fifo = (fix_inc == SDIOH_DATA_FIX);
932         uint32  SGCount = 0;
933         int err_ret = 0;
934         void *pnext, *pprev;
935         uint ttl_len, dma_len, lft_len, xfred_len, pkt_len;
936         uint blk_num;
937         struct mmc_request mmc_req;
938         struct mmc_command mmc_cmd;
939         struct mmc_data mmc_dat;
940
941         sd_trace(("%s: Enter\n", __FUNCTION__));
942
943         ASSERT(pkt);
944         DHD_PM_RESUME_WAIT(sdioh_request_packet_wait);
945         DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
946
947         ttl_len = xfred_len = 0;
948         /* at least 4 bytes alignment of skb buff is guaranteed */
949         for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext))
950                 ttl_len += PKTLEN(sd->osh, pnext);
951
952         if (!sd->use_rxchain || ttl_len <= sd->client_block_size[func]) {
953                 blk_num = 0;
954                 dma_len = 0;
955         } else {
956                 blk_num = ttl_len / sd->client_block_size[func];
957                 dma_len = blk_num * sd->client_block_size[func];
958         }
959         lft_len = ttl_len - dma_len;
960
961         sd_trace(("%s: %s %dB to func%d:%08x, %d blks with DMA, %dB leftover\n",
962                 __FUNCTION__, write ? "W" : "R",
963                 ttl_len, func, addr, blk_num, lft_len));
964
965         if (0 != dma_len) {
966                 memset(&mmc_req, 0, sizeof(struct mmc_request));
967                 memset(&mmc_cmd, 0, sizeof(struct mmc_command));
968                 memset(&mmc_dat, 0, sizeof(struct mmc_data));
969
970                 /* Set up DMA descriptors */
971                 pprev = pkt;
972                 for (pnext = pkt;
973                      pnext && dma_len;
974                      pnext = PKTNEXT(sd->osh, pnext)) {
975                         pkt_len = PKTLEN(sd->osh, pnext);
976
977                         if (dma_len > pkt_len)
978                                 dma_len -= pkt_len;
979                         else {
980                                 pkt_len = xfred_len = dma_len;
981                                 dma_len = 0;
982                                 pkt = pnext;
983                         }
984
985                         sg_set_buf(&sd->sg_list[SGCount++],
986                                 (uint8*)PKTDATA(sd->osh, pnext),
987                                 pkt_len);
988
989                         if (SGCount >= SDIOH_SDMMC_MAX_SG_ENTRIES) {
990                                 sd_err(("%s: sg list entries exceed limit\n",
991                                         __FUNCTION__));
992                                 return (SDIOH_API_RC_FAIL);
993                         }
994                 }
995
996                 mmc_dat.sg = sd->sg_list;
997                 mmc_dat.sg_len = SGCount;
998                 mmc_dat.blksz = sd->client_block_size[func];
999                 mmc_dat.blocks = blk_num;
1000                 mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
1001
1002                 mmc_cmd.opcode = 53;            /* SD_IO_RW_EXTENDED */
1003                 mmc_cmd.arg = write ? 1<<31 : 0;
1004                 mmc_cmd.arg |= (func & 0x7) << 28;
1005                 mmc_cmd.arg |= 1<<27;
1006                 mmc_cmd.arg |= fifo ? 0 : 1<<26;
1007                 mmc_cmd.arg |= (addr & 0x1FFFF) << 9;
1008                 mmc_cmd.arg |= blk_num & 0x1FF;
1009                 mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
1010
1011                 mmc_req.cmd = &mmc_cmd;
1012                 mmc_req.data = &mmc_dat;
1013
1014                 sdio_claim_host(gInstance->func[func]);
1015                 mmc_set_data_timeout(&mmc_dat, gInstance->func[func]->card);
1016                 mmc_wait_for_req(gInstance->func[func]->card->host, &mmc_req);
1017                 sdio_release_host(gInstance->func[func]);
1018
1019                 err_ret = mmc_cmd.error? mmc_cmd.error : mmc_dat.error;
1020                 if (0 != err_ret) {
1021                         sd_err(("%s:CMD53 %s failed with code %d\n",
1022                                __FUNCTION__,
1023                                write ? "write" : "read",
1024                                err_ret));
1025                         sd_err(("%s:Disabling rxchain and fire it with PIO\n",
1026                                __FUNCTION__));
1027                         sd->use_rxchain = FALSE;
1028                         pkt = pprev;
1029                         lft_len = ttl_len;
1030                 } else if (!fifo) {
1031                         addr = addr + ttl_len - lft_len - dma_len;
1032                 }
1033         }
1034
1035         /* PIO mode */
1036         if (0 != lft_len) {
1037                 /* Claim host controller */
1038                 sdio_claim_host(gInstance->func[func]);
1039                 for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) {
1040                         uint8 *buf = (uint8*)PKTDATA(sd->osh, pnext) +
1041                                 xfred_len;
1042                         pkt_len = PKTLEN(sd->osh, pnext);
1043                         if (0 != xfred_len) {
1044                                 pkt_len -= xfred_len;
1045                                 xfred_len = 0;
1046                         }
1047
1048                         /* Align Patch
1049                          *  read or small packet(ex:BDC header) skip 32 byte align
1050                          *  otherwise, padding DHD_SDALIGN for performance
1051                          */
1052                         if (write == 0 || pkt_len < 32)
1053                                 pkt_len = (pkt_len + 3) & 0xFFFFFFFC;
1054                         else if (pkt_len % DHD_SDALIGN)
1055                                 pkt_len += DHD_SDALIGN - (pkt_len % DHD_SDALIGN);
1056
1057 #ifdef CONFIG_MMC_MSM7X00A
1058                         if ((pkt_len % 64) == 32) {
1059                                 sd_trace(("%s: Rounding up TX packet +=32\n", __FUNCTION__));
1060                                 pkt_len += 32;
1061                         }
1062 #endif /* CONFIG_MMC_MSM7X00A */
1063
1064                         if ((write) && (!fifo))
1065                                 err_ret = sdio_memcpy_toio(
1066                                                 gInstance->func[func],
1067                                                 addr, buf, pkt_len);
1068                         else if (write)
1069                                 err_ret = sdio_memcpy_toio(
1070                                                 gInstance->func[func],
1071                                                 addr, buf, pkt_len);
1072                         else if (fifo)
1073                                 err_ret = sdio_readsb(
1074                                                 gInstance->func[func],
1075                                                 buf, addr, pkt_len);
1076                         else
1077                                 err_ret = sdio_memcpy_fromio(
1078                                                 gInstance->func[func],
1079                                                 buf, addr, pkt_len);
1080
1081                         if (err_ret)
1082                                 sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=%d\n",
1083                                        __FUNCTION__,
1084                                        (write) ? "TX" : "RX",
1085                                        pnext, SGCount, addr, pkt_len, err_ret));
1086                         else
1087                                 sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n",
1088                                         __FUNCTION__,
1089                                         (write) ? "TX" : "RX",
1090                                         pnext, SGCount, addr, pkt_len));
1091
1092                         if (!fifo)
1093                                 addr += pkt_len;
1094                         SGCount ++;
1095                 }
1096                 sdio_release_host(gInstance->func[func]);
1097         }
1098
1099         sd_trace(("%s: Exit\n", __FUNCTION__));
1100         return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
1101 }
1102
1103
1104 /*
1105  * This function takes a buffer or packet, and fixes everything up so that in the
1106  * end, a DMA-able packet is created.
1107  *
1108  * A buffer does not have an associated packet pointer, and may or may not be aligned.
1109  * A packet may consist of a single packet, or a packet chain.  If it is a packet chain,
1110  * then all the packets in the chain must be properly aligned.  If the packet data is not
1111  * aligned, then there may only be one packet, and in this case, it is copied to a new
1112  * aligned packet.
1113  *
1114  */
1115 extern SDIOH_API_RC
1116 sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, uint func,
1117                      uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt)
1118 {
1119         SDIOH_API_RC Status;
1120         void *mypkt = NULL;
1121
1122         sd_trace(("%s: Enter\n", __FUNCTION__));
1123
1124         DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait);
1125         DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
1126         /* Case 1: we don't have a packet. */
1127         if (pkt == NULL) {
1128                 sd_data(("%s: Creating new %s Packet, len=%d\n",
1129                          __FUNCTION__, write ? "TX" : "RX", buflen_u));
1130 #ifdef CONFIG_DHD_USE_STATIC_BUF
1131                 if (!(mypkt = PKTGET_STATIC(sd->osh, buflen_u, write ? TRUE : FALSE))) {
1132 #else
1133                 if (!(mypkt = PKTGET(sd->osh, buflen_u, write ? TRUE : FALSE))) {
1134 #endif /* CONFIG_DHD_USE_STATIC_BUF */
1135                         sd_err(("%s: PKTGET failed: len %d\n",
1136                                    __FUNCTION__, buflen_u));
1137                         return SDIOH_API_RC_FAIL;
1138                 }
1139
1140                 /* For a write, copy the buffer data into the packet. */
1141                 if (write) {
1142                         bcopy(buffer, PKTDATA(sd->osh, mypkt), buflen_u);
1143                 }
1144
1145                 Status = sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
1146
1147                 /* For a read, copy the packet data back to the buffer. */
1148                 if (!write) {
1149                         bcopy(PKTDATA(sd->osh, mypkt), buffer, buflen_u);
1150                 }
1151 #ifdef CONFIG_DHD_USE_STATIC_BUF
1152                 PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE);
1153 #else
1154                 PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE);
1155 #endif /* CONFIG_DHD_USE_STATIC_BUF */
1156         } else if (((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) != 0) {
1157                 /* Case 2: We have a packet, but it is unaligned. */
1158
1159                 /* In this case, we cannot have a chain. */
1160                 ASSERT(PKTNEXT(sd->osh, pkt) == NULL);
1161
1162                 sd_data(("%s: Creating aligned %s Packet, len=%d\n",
1163                          __FUNCTION__, write ? "TX" : "RX", PKTLEN(sd->osh, pkt)));
1164 #ifdef CONFIG_DHD_USE_STATIC_BUF
1165                 if (!(mypkt = PKTGET_STATIC(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) {
1166 #else
1167                 if (!(mypkt = PKTGET(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) {
1168 #endif /* CONFIG_DHD_USE_STATIC_BUF */
1169                         sd_err(("%s: PKTGET failed: len %d\n",
1170                                    __FUNCTION__, PKTLEN(sd->osh, pkt)));
1171                         return SDIOH_API_RC_FAIL;
1172                 }
1173
1174                 /* For a write, copy the buffer data into the packet. */
1175                 if (write) {
1176                         bcopy(PKTDATA(sd->osh, pkt),
1177                               PKTDATA(sd->osh, mypkt),
1178                               PKTLEN(sd->osh, pkt));
1179                 }
1180
1181                 Status = sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
1182
1183                 /* For a read, copy the packet data back to the buffer. */
1184                 if (!write) {
1185                         bcopy(PKTDATA(sd->osh, mypkt),
1186                               PKTDATA(sd->osh, pkt),
1187                               PKTLEN(sd->osh, mypkt));
1188                 }
1189 #ifdef CONFIG_DHD_USE_STATIC_BUF
1190                 PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE);
1191 #else
1192                 PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE);
1193 #endif /* CONFIG_DHD_USE_STATIC_BUF */
1194         } else { /* case 3: We have a packet and it is aligned. */
1195                 sd_data(("%s: Aligned %s Packet, direct DMA\n",
1196                          __FUNCTION__, write ? "Tx" : "Rx"));
1197                 Status = sdioh_request_packet(sd, fix_inc, write, func, addr, pkt);
1198         }
1199
1200         return (Status);
1201 }
1202
1203 /* this function performs "abort" for both of host & device */
1204 extern int
1205 sdioh_abort(sdioh_info_t *sd, uint func)
1206 {
1207 #if defined(MMC_SDIO_ABORT)
1208         char t_func = (char) func;
1209 #endif /* defined(MMC_SDIO_ABORT) */
1210         sd_trace(("%s: Enter\n", __FUNCTION__));
1211
1212 #if defined(MMC_SDIO_ABORT)
1213         /* issue abort cmd52 command through F1 */
1214         sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT, &t_func);
1215 #endif /* defined(MMC_SDIO_ABORT) */
1216
1217         sd_trace(("%s: Exit\n", __FUNCTION__));
1218         return SDIOH_API_RC_SUCCESS;
1219 }
1220
1221 /* Reset and re-initialize the device */
1222 int sdioh_sdio_reset(sdioh_info_t *si)
1223 {
1224         sd_trace(("%s: Enter\n", __FUNCTION__));
1225         sd_trace(("%s: Exit\n", __FUNCTION__));
1226         return SDIOH_API_RC_SUCCESS;
1227 }
1228
1229 /* Disable device interrupt */
1230 void
1231 sdioh_sdmmc_devintr_off(sdioh_info_t *sd)
1232 {
1233         sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints));
1234         sd->intmask &= ~CLIENT_INTR;
1235 }
1236
1237 /* Enable device interrupt */
1238 void
1239 sdioh_sdmmc_devintr_on(sdioh_info_t *sd)
1240 {
1241         sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints));
1242         sd->intmask |= CLIENT_INTR;
1243 }
1244
1245 /* Read client card reg */
1246 int
1247 sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
1248 {
1249
1250         if ((func == 0) || (regsize == 1)) {
1251                 uint8 temp = 0;
1252
1253                 sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
1254                 *data = temp;
1255                 *data &= 0xff;
1256                 sd_data(("%s: byte read data=0x%02x\n",
1257                          __FUNCTION__, *data));
1258         } else {
1259                 sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data, regsize);
1260                 if (regsize == 2)
1261                         *data &= 0xffff;
1262
1263                 sd_data(("%s: word read data=0x%08x\n",
1264                          __FUNCTION__, *data));
1265         }
1266
1267         return SUCCESS;
1268 }
1269
1270 #if !defined(OOB_INTR_ONLY)
1271 /* bcmsdh_sdmmc interrupt handler */
1272 static void IRQHandler(struct sdio_func *func)
1273 {
1274         sdioh_info_t *sd;
1275
1276         sd_trace(("bcmsdh_sdmmc: ***IRQHandler\n"));
1277         sd = gInstance->sd;
1278
1279         ASSERT(sd != NULL);
1280         sdio_release_host(gInstance->func[0]);
1281
1282         if (sd->use_client_ints) {
1283                 sd->intrcount++;
1284                 ASSERT(sd->intr_handler);
1285                 ASSERT(sd->intr_handler_arg);
1286                 (sd->intr_handler)(sd->intr_handler_arg);
1287         } else {
1288                 sd_err(("bcmsdh_sdmmc: ***IRQHandler\n"));
1289
1290                 sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
1291                         __FUNCTION__, sd->client_intr_enabled, sd->intr_handler));
1292         }
1293
1294         sdio_claim_host(gInstance->func[0]);
1295 }
1296
1297 /* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */
1298 static void IRQHandlerF2(struct sdio_func *func)
1299 {
1300         sdioh_info_t *sd;
1301
1302         sd_trace(("bcmsdh_sdmmc: ***IRQHandlerF2\n"));
1303
1304         sd = gInstance->sd;
1305
1306         ASSERT(sd != NULL);
1307         BCM_REFERENCE(sd);
1308 }
1309 #endif /* !defined(OOB_INTR_ONLY) */
1310
1311 #ifdef NOTUSED
1312 /* Write client card reg */
1313 static int
1314 sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data)
1315 {
1316
1317         if ((func == 0) || (regsize == 1)) {
1318                 uint8 temp;
1319
1320                 temp = data & 0xff;
1321                 sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
1322                 sd_data(("%s: byte write data=0x%02x\n",
1323                          __FUNCTION__, data));
1324         } else {
1325                 if (regsize == 2)
1326                         data &= 0xffff;
1327
1328                 sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, &data, regsize);
1329
1330                 sd_data(("%s: word write data=0x%08x\n",
1331                          __FUNCTION__, data));
1332         }
1333
1334         return SUCCESS;
1335 }
1336 #endif /* NOTUSED */
1337
1338 int
1339 sdioh_start(sdioh_info_t *si, int stage)
1340 {
1341         int ret;
1342         sdioh_info_t *sd = gInstance->sd;
1343
1344         /* Need to do this stages as we can't enable the interrupt till
1345                 downloading of the firmware is complete, other wise polling
1346                 sdio access will come in way
1347         */
1348         if (gInstance->func[0]) {
1349                         if (stage == 0) {
1350                 /* Since the power to the chip is killed, we will have
1351                         re enumerate the device again. Set the block size
1352                         and enable the fucntion 1 for in preparation for
1353                         downloading the code
1354                 */
1355                 /* sdio_reset_comm() - has been fixed in latest kernel/msm.git for Linux
1356                    2.6.27. The implementation prior to that is buggy, and needs broadcom's
1357                    patch for it
1358                 */
1359                 if ((ret = sdio_reset_comm(gInstance->func[0]->card))) {
1360                         sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret));
1361                         return ret;
1362                 }
1363                 else {
1364                         sd->num_funcs = 2;
1365                         sd->sd_blockmode = TRUE;
1366                         sd->use_client_ints = TRUE;
1367                         sd->client_block_size[0] = 64;
1368
1369                         if (gInstance->func[1]) {
1370                                 /* Claim host controller */
1371                                 sdio_claim_host(gInstance->func[1]);
1372
1373                                 sd->client_block_size[1] = 64;
1374                                 if (sdio_set_block_size(gInstance->func[1], 64)) {
1375                                         sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n"));
1376                                 }
1377
1378                                 /* Release host controller F1 */
1379                                 sdio_release_host(gInstance->func[1]);
1380                         }
1381
1382                         if (gInstance->func[2]) {
1383                                 /* Claim host controller F2 */
1384                                 sdio_claim_host(gInstance->func[2]);
1385
1386                                 sd->client_block_size[2] = sd_f2_blocksize;
1387                                 if (sdio_set_block_size(gInstance->func[2],
1388                                         sd_f2_blocksize)) {
1389                                         sd_err(("bcmsdh_sdmmc: Failed to set F2 "
1390                                                 "blocksize to %d\n", sd_f2_blocksize));
1391                                 }
1392
1393                                 /* Release host controller F2 */
1394                                 sdio_release_host(gInstance->func[2]);
1395                         }
1396
1397                         sdioh_sdmmc_card_enablefuncs(sd);
1398                         }
1399                 } else {
1400 #if !defined(OOB_INTR_ONLY)
1401                         sdio_claim_host(gInstance->func[0]);
1402                         if (gInstance->func[2])
1403                                 sdio_claim_irq(gInstance->func[2], IRQHandlerF2);
1404                         if (gInstance->func[1])
1405                                 sdio_claim_irq(gInstance->func[1], IRQHandler);
1406                         sdio_release_host(gInstance->func[0]);
1407 #else /* defined(OOB_INTR_ONLY) */
1408 #if defined(HW_OOB)
1409                         sdioh_enable_func_intr();
1410 #endif
1411                         bcmsdh_oob_intr_set(TRUE);
1412 #endif /* !defined(OOB_INTR_ONLY) */
1413                 }
1414         }
1415         else
1416                 sd_err(("%s Failed\n", __FUNCTION__));
1417
1418         return (0);
1419 }
1420
1421 int
1422 sdioh_stop(sdioh_info_t *si)
1423 {
1424         /* MSM7201A Android sdio stack has bug with interrupt
1425                 So internaly within SDIO stack they are polling
1426                 which cause issue when device is turned off. So
1427                 unregister interrupt with SDIO stack to stop the
1428                 polling
1429         */
1430         if (gInstance->func[0]) {
1431 #if !defined(OOB_INTR_ONLY)
1432                 sdio_claim_host(gInstance->func[0]);
1433                 if (gInstance->func[1])
1434                         sdio_release_irq(gInstance->func[1]);
1435                 if (gInstance->func[2])
1436                         sdio_release_irq(gInstance->func[2]);
1437                 sdio_release_host(gInstance->func[0]);
1438 #else /* defined(OOB_INTR_ONLY) */
1439 #if defined(HW_OOB)
1440                 sdioh_disable_func_intr(0);
1441 #endif
1442                 bcmsdh_oob_intr_set(FALSE);
1443 #endif /* !defined(OOB_INTR_ONLY) */
1444         }
1445         else
1446                 sd_err(("%s Failed\n", __FUNCTION__));
1447         return (0);
1448 }
1449
1450 int
1451 sdioh_waitlockfree(sdioh_info_t *sd)
1452 {
1453         return (1);
1454 }
1455
1456
1457 SDIOH_API_RC
1458 sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio)
1459 {
1460         return SDIOH_API_RC_FAIL;
1461 }
1462
1463 SDIOH_API_RC
1464 sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab)
1465 {
1466         return SDIOH_API_RC_FAIL;
1467 }
1468
1469 bool
1470 sdioh_gpioin(sdioh_info_t *sd, uint32 gpio)
1471 {
1472         return FALSE;
1473 }
1474
1475 SDIOH_API_RC
1476 sdioh_gpio_init(sdioh_info_t *sd)
1477 {
1478         return SDIOH_API_RC_FAIL;
1479 }