Fix common misspellings
[linux-flexiantxendom0.git] / drivers / staging / 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 <bcmdefs.h>
19 #include <bcmdevs.h>
20 #include <bcmutils.h>
21 #include <sdio.h>               /* SDIO Device and Protocol Specs */
22 #include <sdioh.h>              /* SDIO Host Controller Specification */
23 #include <bcmsdbus.h>           /* bcmsdh to/from specific controller APIs */
24 #include <sdiovar.h>            /* ioctl/iovars */
25
26 #include <linux/mmc/core.h>
27 #include <linux/mmc/sdio_func.h>
28 #include <linux/mmc/sdio_ids.h>
29
30 #include <dngl_stats.h>
31 #include <dhd.h>
32
33 #if defined(CONFIG_PM_SLEEP)
34 #include <linux/suspend.h>
35 extern volatile bool dhd_mmc_suspend;
36 #endif
37 #include "bcmsdh_sdmmc.h"
38
39 extern int sdio_function_init(void);
40 extern void sdio_function_cleanup(void);
41
42 #if !defined(OOB_INTR_ONLY)
43 static void IRQHandler(struct sdio_func *func);
44 static void IRQHandlerF2(struct sdio_func *func);
45 #endif                          /* !defined(OOB_INTR_ONLY) */
46 static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, u32 regaddr);
47 extern int sdio_reset_comm(struct mmc_card *card);
48
49 extern PBCMSDH_SDMMC_INSTANCE gInstance;
50
51 uint sd_sdmode = SDIOH_MODE_SD4;        /* Use SD4 mode by default */
52 uint sd_f2_blocksize = 512;     /* Default blocksize */
53
54 uint sd_divisor = 2;            /* Default 48MHz/2 = 24MHz */
55
56 uint sd_power = 1;              /* Default to SD Slot powered ON */
57 uint sd_clock = 1;              /* Default to SD Clock turned ON */
58 uint sd_hiok = false;           /* Don't use hi-speed mode by default */
59 uint sd_msglevel = 0x01;
60 uint sd_use_dma = true;
61 DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
62 DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
63 DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
64 DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
65
66 #define DMA_ALIGN_MASK  0x03
67
68 int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, u32 regaddr,
69                              int regsize, u32 *data);
70
71 static int sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
72 {
73         int err_ret;
74         u32 fbraddr;
75         u8 func;
76
77         sd_trace(("%s\n", __func__));
78
79         /* Get the Card's common CIS address */
80         sd->com_cis_ptr = sdioh_sdmmc_get_cisaddr(sd, SDIOD_CCCR_CISPTR_0);
81         sd->func_cis_ptr[0] = sd->com_cis_ptr;
82         sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
83                  sd->com_cis_ptr));
84
85         /* Get the Card's function CIS (for each function) */
86         for (fbraddr = SDIOD_FBR_STARTADDR, func = 1;
87              func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
88                 sd->func_cis_ptr[func] =
89                     sdioh_sdmmc_get_cisaddr(sd, SDIOD_FBR_CISPTR_0 + fbraddr);
90                 sd_info(("%s: Function %d CIS Ptr = 0x%x\n", __func__, func,
91                          sd->func_cis_ptr[func]));
92         }
93
94         sd->func_cis_ptr[0] = sd->com_cis_ptr;
95         sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
96                  sd->com_cis_ptr));
97
98         /* Enable Function 1 */
99         sdio_claim_host(gInstance->func[1]);
100         err_ret = sdio_enable_func(gInstance->func[1]);
101         sdio_release_host(gInstance->func[1]);
102         if (err_ret) {
103                 sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x",
104                         err_ret));
105         }
106
107         return false;
108 }
109
110 /*
111  *      Public entry points & extern's
112  */
113 sdioh_info_t *sdioh_attach(void *bar0, uint irq)
114 {
115         sdioh_info_t *sd;
116         int err_ret;
117
118         sd_trace(("%s\n", __func__));
119
120         if (gInstance == NULL) {
121                 sd_err(("%s: SDIO Device not present\n", __func__));
122                 return NULL;
123         }
124
125         sd = kzalloc(sizeof(sdioh_info_t), GFP_ATOMIC);
126         if (sd == NULL) {
127                 sd_err(("sdioh_attach: out of memory\n"));
128                 return NULL;
129         }
130         if (sdioh_sdmmc_osinit(sd) != 0) {
131                 sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__));
132                 kfree(sd);
133                 return NULL;
134         }
135
136         sd->num_funcs = 2;
137         sd->sd_blockmode = true;
138         sd->use_client_ints = true;
139         sd->client_block_size[0] = 64;
140
141         gInstance->sd = sd;
142
143         /* Claim host controller */
144         sdio_claim_host(gInstance->func[1]);
145
146         sd->client_block_size[1] = 64;
147         err_ret = sdio_set_block_size(gInstance->func[1], 64);
148         if (err_ret)
149                 sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n"));
150
151         /* Release host controller F1 */
152         sdio_release_host(gInstance->func[1]);
153
154         if (gInstance->func[2]) {
155                 /* Claim host controller F2 */
156                 sdio_claim_host(gInstance->func[2]);
157
158                 sd->client_block_size[2] = sd_f2_blocksize;
159                 err_ret =
160                     sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
161                 if (err_ret)
162                         sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize "
163                                 "to %d\n", sd_f2_blocksize));
164
165                 /* Release host controller F2 */
166                 sdio_release_host(gInstance->func[2]);
167         }
168
169         sdioh_sdmmc_card_enablefuncs(sd);
170
171         sd_trace(("%s: Done\n", __func__));
172         return sd;
173 }
174
175 extern SDIOH_API_RC sdioh_detach(sdioh_info_t *sd)
176 {
177         sd_trace(("%s\n", __func__));
178
179         if (sd) {
180
181                 /* Disable Function 2 */
182                 sdio_claim_host(gInstance->func[2]);
183                 sdio_disable_func(gInstance->func[2]);
184                 sdio_release_host(gInstance->func[2]);
185
186                 /* Disable Function 1 */
187                 sdio_claim_host(gInstance->func[1]);
188                 sdio_disable_func(gInstance->func[1]);
189                 sdio_release_host(gInstance->func[1]);
190
191                 /* deregister irq */
192                 sdioh_sdmmc_osfree(sd);
193
194                 kfree(sd);
195         }
196         return SDIOH_API_RC_SUCCESS;
197 }
198
199 #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
200
201 extern SDIOH_API_RC sdioh_enable_func_intr(void)
202 {
203         u8 reg;
204         int err;
205
206         if (gInstance->func[0]) {
207                 sdio_claim_host(gInstance->func[0]);
208
209                 reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &err);
210                 if (err) {
211                         sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n",
212                                 __func__, err));
213                         sdio_release_host(gInstance->func[0]);
214                         return SDIOH_API_RC_FAIL;
215                 }
216
217                 /* Enable F1 and F2 interrupts, set master enable */
218                 reg |=
219                     (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN |
220                      INTR_CTL_MASTER_EN);
221
222                 sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err);
223                 sdio_release_host(gInstance->func[0]);
224
225                 if (err) {
226                         sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n",
227                                 __func__, err));
228                         return SDIOH_API_RC_FAIL;
229                 }
230         }
231
232         return SDIOH_API_RC_SUCCESS;
233 }
234
235 extern SDIOH_API_RC sdioh_disable_func_intr(void)
236 {
237         u8 reg;
238         int err;
239
240         if (gInstance->func[0]) {
241                 sdio_claim_host(gInstance->func[0]);
242                 reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &err);
243                 if (err) {
244                         sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n",
245                                 __func__, err));
246                         sdio_release_host(gInstance->func[0]);
247                         return SDIOH_API_RC_FAIL;
248                 }
249
250                 reg &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN);
251                 /* Disable master interrupt with the last function interrupt */
252                 if (!(reg & 0xFE))
253                         reg = 0;
254                 sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err);
255
256                 sdio_release_host(gInstance->func[0]);
257                 if (err) {
258                         sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n",
259                                 __func__, err));
260                         return SDIOH_API_RC_FAIL;
261                 }
262         }
263         return SDIOH_API_RC_SUCCESS;
264 }
265 #endif                          /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
266
267 /* Configure callback to client when we receive client interrupt */
268 extern SDIOH_API_RC
269 sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
270 {
271         sd_trace(("%s: Entering\n", __func__));
272         if (fn == NULL) {
273                 sd_err(("%s: interrupt handler is NULL, not registering\n",
274                         __func__));
275                 return SDIOH_API_RC_FAIL;
276         }
277 #if !defined(OOB_INTR_ONLY)
278         sd->intr_handler = fn;
279         sd->intr_handler_arg = argh;
280         sd->intr_handler_valid = true;
281
282         /* register and unmask irq */
283         if (gInstance->func[2]) {
284                 sdio_claim_host(gInstance->func[2]);
285                 sdio_claim_irq(gInstance->func[2], IRQHandlerF2);
286                 sdio_release_host(gInstance->func[2]);
287         }
288
289         if (gInstance->func[1]) {
290                 sdio_claim_host(gInstance->func[1]);
291                 sdio_claim_irq(gInstance->func[1], IRQHandler);
292                 sdio_release_host(gInstance->func[1]);
293         }
294 #elif defined(HW_OOB)
295         sdioh_enable_func_intr();
296 #endif                          /* defined(OOB_INTR_ONLY) */
297         return SDIOH_API_RC_SUCCESS;
298 }
299
300 extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *sd)
301 {
302         sd_trace(("%s: Entering\n", __func__));
303
304 #if !defined(OOB_INTR_ONLY)
305         if (gInstance->func[1]) {
306                 /* register and unmask irq */
307                 sdio_claim_host(gInstance->func[1]);
308                 sdio_release_irq(gInstance->func[1]);
309                 sdio_release_host(gInstance->func[1]);
310         }
311
312         if (gInstance->func[2]) {
313                 /* Claim host controller F2 */
314                 sdio_claim_host(gInstance->func[2]);
315                 sdio_release_irq(gInstance->func[2]);
316                 /* Release host controller F2 */
317                 sdio_release_host(gInstance->func[2]);
318         }
319
320         sd->intr_handler_valid = false;
321         sd->intr_handler = NULL;
322         sd->intr_handler_arg = NULL;
323 #elif defined(HW_OOB)
324         sdioh_disable_func_intr();
325 #endif                          /*  !defined(OOB_INTR_ONLY) */
326         return SDIOH_API_RC_SUCCESS;
327 }
328
329 extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
330 {
331         sd_trace(("%s: Entering\n", __func__));
332         *onoff = sd->client_intr_enabled;
333         return SDIOH_API_RC_SUCCESS;
334 }
335
336 #if defined(DHD_DEBUG)
337 extern bool sdioh_interrupt_pending(sdioh_info_t *sd)
338 {
339         return 0;
340 }
341 #endif
342
343 uint sdioh_query_iofnum(sdioh_info_t *sd)
344 {
345         return sd->num_funcs;
346 }
347
348 /* IOVar table */
349 enum {
350         IOV_MSGLEVEL = 1,
351         IOV_BLOCKMODE,
352         IOV_BLOCKSIZE,
353         IOV_DMA,
354         IOV_USEINTS,
355         IOV_NUMINTS,
356         IOV_NUMLOCALINTS,
357         IOV_HOSTREG,
358         IOV_DEVREG,
359         IOV_DIVISOR,
360         IOV_SDMODE,
361         IOV_HISPEED,
362         IOV_HCIREGS,
363         IOV_POWER,
364         IOV_CLOCK,
365         IOV_RXCHAIN
366 };
367
368 const bcm_iovar_t sdioh_iovars[] = {
369         {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0},
370         {"sd_blockmode", IOV_BLOCKMODE, 0, IOVT_BOOL, 0},
371         {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0},/* ((fn << 16) |
372                                                                  size) */
373         {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0},
374         {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0},
375         {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0},
376         {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0},
377         {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
378         ,
379         {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
380         ,
381         {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0}
382         ,
383         {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0}
384         ,
385         {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0}
386         ,
387         {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100}
388         ,
389         {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0}
390         ,
391         {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0}
392         ,
393         {NULL, 0, 0, 0, 0}
394 };
395
396 int
397 sdioh_iovar_op(sdioh_info_t *si, const char *name,
398                void *params, int plen, void *arg, int len, bool set)
399 {
400         const bcm_iovar_t *vi = NULL;
401         int bcmerror = 0;
402         int val_size;
403         s32 int_val = 0;
404         bool bool_val;
405         u32 actionid;
406
407         ASSERT(name);
408         ASSERT(len >= 0);
409
410         /* Get must have return space; Set does not take qualifiers */
411         ASSERT(set || (arg && len));
412         ASSERT(!set || (!params && !plen));
413
414         sd_trace(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"),
415                   name));
416
417         vi = bcm_iovar_lookup(sdioh_iovars, name);
418         if (vi == NULL) {
419                 bcmerror = BCME_UNSUPPORTED;
420                 goto exit;
421         }
422
423         bcmerror = bcm_iovar_lencheck(vi, arg, len, set);
424         if (bcmerror != 0)
425                 goto exit;
426
427         /* Set up params so get and set can share the convenience variables */
428         if (params == NULL) {
429                 params = arg;
430                 plen = len;
431         }
432
433         if (vi->type == IOVT_VOID)
434                 val_size = 0;
435         else if (vi->type == IOVT_BUFFER)
436                 val_size = len;
437         else
438                 val_size = sizeof(int);
439
440         if (plen >= (int)sizeof(int_val))
441                 memcpy(&int_val, params, sizeof(int_val));
442
443         bool_val = (int_val != 0) ? true : false;
444
445         actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
446         switch (actionid) {
447         case IOV_GVAL(IOV_MSGLEVEL):
448                 int_val = (s32) sd_msglevel;
449                 memcpy(arg, &int_val, val_size);
450                 break;
451
452         case IOV_SVAL(IOV_MSGLEVEL):
453                 sd_msglevel = int_val;
454                 break;
455
456         case IOV_GVAL(IOV_BLOCKMODE):
457                 int_val = (s32) si->sd_blockmode;
458                 memcpy(arg, &int_val, val_size);
459                 break;
460
461         case IOV_SVAL(IOV_BLOCKMODE):
462                 si->sd_blockmode = (bool) int_val;
463                 /* Haven't figured out how to make non-block mode with DMA */
464                 break;
465
466         case IOV_GVAL(IOV_BLOCKSIZE):
467                 if ((u32) int_val > si->num_funcs) {
468                         bcmerror = BCME_BADARG;
469                         break;
470                 }
471                 int_val = (s32) si->client_block_size[int_val];
472                 memcpy(arg, &int_val, val_size);
473                 break;
474
475         case IOV_SVAL(IOV_BLOCKSIZE):
476                 {
477                         uint func = ((u32) int_val >> 16);
478                         uint blksize = (u16) int_val;
479                         uint maxsize;
480
481                         if (func > si->num_funcs) {
482                                 bcmerror = BCME_BADARG;
483                                 break;
484                         }
485
486                         switch (func) {
487                         case 0:
488                                 maxsize = 32;
489                                 break;
490                         case 1:
491                                 maxsize = BLOCK_SIZE_4318;
492                                 break;
493                         case 2:
494                                 maxsize = BLOCK_SIZE_4328;
495                                 break;
496                         default:
497                                 maxsize = 0;
498                         }
499                         if (blksize > maxsize) {
500                                 bcmerror = BCME_BADARG;
501                                 break;
502                         }
503                         if (!blksize)
504                                 blksize = maxsize;
505
506                         /* Now set it */
507                         si->client_block_size[func] = blksize;
508
509                         break;
510                 }
511
512         case IOV_GVAL(IOV_RXCHAIN):
513                 int_val = false;
514                 memcpy(arg, &int_val, val_size);
515                 break;
516
517         case IOV_GVAL(IOV_DMA):
518                 int_val = (s32) si->sd_use_dma;
519                 memcpy(arg, &int_val, val_size);
520                 break;
521
522         case IOV_SVAL(IOV_DMA):
523                 si->sd_use_dma = (bool) int_val;
524                 break;
525
526         case IOV_GVAL(IOV_USEINTS):
527                 int_val = (s32) si->use_client_ints;
528                 memcpy(arg, &int_val, val_size);
529                 break;
530
531         case IOV_SVAL(IOV_USEINTS):
532                 si->use_client_ints = (bool) int_val;
533                 if (si->use_client_ints)
534                         si->intmask |= CLIENT_INTR;
535                 else
536                         si->intmask &= ~CLIENT_INTR;
537
538                 break;
539
540         case IOV_GVAL(IOV_DIVISOR):
541                 int_val = (u32) sd_divisor;
542                 memcpy(arg, &int_val, val_size);
543                 break;
544
545         case IOV_SVAL(IOV_DIVISOR):
546                 sd_divisor = int_val;
547                 break;
548
549         case IOV_GVAL(IOV_POWER):
550                 int_val = (u32) sd_power;
551                 memcpy(arg, &int_val, val_size);
552                 break;
553
554         case IOV_SVAL(IOV_POWER):
555                 sd_power = int_val;
556                 break;
557
558         case IOV_GVAL(IOV_CLOCK):
559                 int_val = (u32) sd_clock;
560                 memcpy(arg, &int_val, val_size);
561                 break;
562
563         case IOV_SVAL(IOV_CLOCK):
564                 sd_clock = int_val;
565                 break;
566
567         case IOV_GVAL(IOV_SDMODE):
568                 int_val = (u32) sd_sdmode;
569                 memcpy(arg, &int_val, val_size);
570                 break;
571
572         case IOV_SVAL(IOV_SDMODE):
573                 sd_sdmode = int_val;
574                 break;
575
576         case IOV_GVAL(IOV_HISPEED):
577                 int_val = (u32) sd_hiok;
578                 memcpy(arg, &int_val, val_size);
579                 break;
580
581         case IOV_SVAL(IOV_HISPEED):
582                 sd_hiok = int_val;
583                 break;
584
585         case IOV_GVAL(IOV_NUMINTS):
586                 int_val = (s32) si->intrcount;
587                 memcpy(arg, &int_val, val_size);
588                 break;
589
590         case IOV_GVAL(IOV_NUMLOCALINTS):
591                 int_val = (s32) 0;
592                 memcpy(arg, &int_val, val_size);
593                 break;
594
595         case IOV_GVAL(IOV_HOSTREG):
596                 {
597                         sdreg_t *sd_ptr = (sdreg_t *) params;
598
599                         if (sd_ptr->offset < SD_SysAddr
600                             || sd_ptr->offset > SD_MaxCurCap) {
601                                 sd_err(("%s: bad offset 0x%x\n", __func__,
602                                         sd_ptr->offset));
603                                 bcmerror = BCME_BADARG;
604                                 break;
605                         }
606
607                         sd_trace(("%s: rreg%d at offset %d\n", __func__,
608                                   (sd_ptr->offset & 1) ? 8
609                                   : ((sd_ptr->offset & 2) ? 16 : 32),
610                                   sd_ptr->offset));
611                         if (sd_ptr->offset & 1)
612                                 int_val = 8;    /* sdioh_sdmmc_rreg8(si,
613                                                  sd_ptr->offset); */
614                         else if (sd_ptr->offset & 2)
615                                 int_val = 16;   /* sdioh_sdmmc_rreg16(si,
616                                                  sd_ptr->offset); */
617                         else
618                                 int_val = 32;   /* sdioh_sdmmc_rreg(si,
619                                                  sd_ptr->offset); */
620
621                         memcpy(arg, &int_val, sizeof(int_val));
622                         break;
623                 }
624
625         case IOV_SVAL(IOV_HOSTREG):
626                 {
627                         sdreg_t *sd_ptr = (sdreg_t *) params;
628
629                         if (sd_ptr->offset < SD_SysAddr
630                             || sd_ptr->offset > SD_MaxCurCap) {
631                                 sd_err(("%s: bad offset 0x%x\n", __func__,
632                                         sd_ptr->offset));
633                                 bcmerror = BCME_BADARG;
634                                 break;
635                         }
636
637                         sd_trace(("%s: wreg%d value 0x%08x at offset %d\n",
638                                   __func__, sd_ptr->value,
639                                   (sd_ptr->offset & 1) ? 8
640                                   : ((sd_ptr->offset & 2) ? 16 : 32),
641                                   sd_ptr->offset));
642                         break;
643                 }
644
645         case IOV_GVAL(IOV_DEVREG):
646                 {
647                         sdreg_t *sd_ptr = (sdreg_t *) params;
648                         u8 data = 0;
649
650                         if (sdioh_cfg_read
651                             (si, sd_ptr->func, sd_ptr->offset, &data)) {
652                                 bcmerror = BCME_SDIO_ERROR;
653                                 break;
654                         }
655
656                         int_val = (int)data;
657                         memcpy(arg, &int_val, sizeof(int_val));
658                         break;
659                 }
660
661         case IOV_SVAL(IOV_DEVREG):
662                 {
663                         sdreg_t *sd_ptr = (sdreg_t *) params;
664                         u8 data = (u8) sd_ptr->value;
665
666                         if (sdioh_cfg_write
667                             (si, sd_ptr->func, sd_ptr->offset, &data)) {
668                                 bcmerror = BCME_SDIO_ERROR;
669                                 break;
670                         }
671                         break;
672                 }
673
674         default:
675                 bcmerror = BCME_UNSUPPORTED;
676                 break;
677         }
678 exit:
679
680         return bcmerror;
681 }
682
683 #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
684
685 SDIOH_API_RC sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
686 {
687         SDIOH_API_RC status;
688         u8 data;
689
690         if (enable)
691                 data = 3;       /* enable hw oob interrupt */
692         else
693                 data = 4;       /* disable hw oob interrupt */
694         data |= 4;              /* Active HIGH */
695
696         status = sdioh_request_byte(sd, SDIOH_WRITE, 0, 0xf2, &data);
697         return status;
698 }
699 #endif                          /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
700
701 extern SDIOH_API_RC
702 sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, u32 addr, u8 *data)
703 {
704         SDIOH_API_RC status;
705         /* No lock needed since sdioh_request_byte does locking */
706         status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
707         return status;
708 }
709
710 extern SDIOH_API_RC
711 sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, u32 addr, u8 *data)
712 {
713         /* No lock needed since sdioh_request_byte does locking */
714         SDIOH_API_RC status;
715         status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
716         return status;
717 }
718
719 static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, u32 regaddr)
720 {
721         /* read 24 bits and return valid 17 bit addr */
722         int i;
723         u32 scratch, regdata;
724         u8 *ptr = (u8 *)&scratch;
725         for (i = 0; i < 3; i++) {
726                 if ((sdioh_sdmmc_card_regread(sd, 0, regaddr, 1, &regdata)) !=
727                     SUCCESS)
728                         sd_err(("%s: Can't read!\n", __func__));
729
730                 *ptr++ = (u8) regdata;
731                 regaddr++;
732         }
733
734         /* Only the lower 17-bits are valid */
735         scratch = le32_to_cpu(scratch);
736         scratch &= 0x0001FFFF;
737         return scratch;
738 }
739
740 extern SDIOH_API_RC
741 sdioh_cis_read(sdioh_info_t *sd, uint func, u8 *cisd, u32 length)
742 {
743         u32 count;
744         int offset;
745         u32 foo;
746         u8 *cis = cisd;
747
748         sd_trace(("%s: Func = %d\n", __func__, func));
749
750         if (!sd->func_cis_ptr[func]) {
751                 memset(cis, 0, length);
752                 sd_err(("%s: no func_cis_ptr[%d]\n", __func__, func));
753                 return SDIOH_API_RC_FAIL;
754         }
755
756         sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __func__, func,
757                 sd->func_cis_ptr[func]));
758
759         for (count = 0; count < length; count++) {
760                 offset = sd->func_cis_ptr[func] + count;
761                 if (sdioh_sdmmc_card_regread(sd, 0, offset, 1, &foo) < 0) {
762                         sd_err(("%s: regread failed: Can't read CIS\n",
763                                 __func__));
764                         return SDIOH_API_RC_FAIL;
765                 }
766
767                 *cis = (u8) (foo & 0xff);
768                 cis++;
769         }
770
771         return SDIOH_API_RC_SUCCESS;
772 }
773
774 extern SDIOH_API_RC
775 sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr,
776                    u8 *byte)
777 {
778         int err_ret;
779
780         sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __func__, rw, func,
781                  regaddr));
782
783         DHD_PM_RESUME_WAIT(sdioh_request_byte_wait);
784         DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
785         if (rw) {               /* CMD52 Write */
786                 if (func == 0) {
787                         /* Can only directly write to some F0 registers.
788                          * Handle F2 enable
789                          * as a special case.
790                          */
791                         if (regaddr == SDIOD_CCCR_IOEN) {
792                                 if (gInstance->func[2]) {
793                                         sdio_claim_host(gInstance->func[2]);
794                                         if (*byte & SDIO_FUNC_ENABLE_2) {
795                                                 /* Enable Function 2 */
796                                                 err_ret =
797                                                     sdio_enable_func
798                                                     (gInstance->func[2]);
799                                                 if (err_ret)
800                                                         sd_err(("bcmsdh_sdmmc: enable F2 failed:%d",
801                                                                  err_ret));
802                                         } else {
803                                                 /* Disable Function 2 */
804                                                 err_ret =
805                                                     sdio_disable_func
806                                                     (gInstance->func[2]);
807                                                 if (err_ret)
808                                                         sd_err(("bcmsdh_sdmmc: Disab F2 failed:%d",
809                                                                  err_ret));
810                                         }
811                                         sdio_release_host(gInstance->func[2]);
812                                 }
813                         }
814 #if defined(MMC_SDIO_ABORT)
815                         /* to allow abort command through F1 */
816                         else if (regaddr == SDIOD_CCCR_IOABORT) {
817                                 sdio_claim_host(gInstance->func[func]);
818                                 /*
819                                  * this sdio_f0_writeb() can be replaced
820                                  * with another api
821                                  * depending upon MMC driver change.
822                                  * As of this time, this is temporaray one
823                                  */
824                                 sdio_writeb(gInstance->func[func], *byte,
825                                             regaddr, &err_ret);
826                                 sdio_release_host(gInstance->func[func]);
827                         }
828 #endif                          /* MMC_SDIO_ABORT */
829                         else if (regaddr < 0xF0) {
830                                 sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write "
831                                         "disallowed\n", regaddr));
832                         } else {
833                                 /* Claim host controller, perform F0 write,
834                                  and release */
835                                 sdio_claim_host(gInstance->func[func]);
836                                 sdio_f0_writeb(gInstance->func[func], *byte,
837                                                regaddr, &err_ret);
838                                 sdio_release_host(gInstance->func[func]);
839                         }
840                 } else {
841                         /* Claim host controller, perform Fn write,
842                          and release */
843                         sdio_claim_host(gInstance->func[func]);
844                         sdio_writeb(gInstance->func[func], *byte, regaddr,
845                                     &err_ret);
846                         sdio_release_host(gInstance->func[func]);
847                 }
848         } else {                /* CMD52 Read */
849                 /* Claim host controller, perform Fn read, and release */
850                 sdio_claim_host(gInstance->func[func]);
851
852                 if (func == 0) {
853                         *byte =
854                             sdio_f0_readb(gInstance->func[func], regaddr,
855                                           &err_ret);
856                 } else {
857                         *byte =
858                             sdio_readb(gInstance->func[func], regaddr,
859                                        &err_ret);
860                 }
861
862                 sdio_release_host(gInstance->func[func]);
863         }
864
865         if (err_ret)
866                 sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, "
867                         "Err: %d\n", rw ? "Write" : "Read", func, regaddr,
868                         *byte, err_ret));
869
870         return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
871 }
872
873 extern SDIOH_API_RC
874 sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func,
875                    uint addr, u32 *word, uint nbytes)
876 {
877         int err_ret = SDIOH_API_RC_FAIL;
878
879         if (func == 0) {
880                 sd_err(("%s: Only CMD52 allowed to F0.\n", __func__));
881                 return SDIOH_API_RC_FAIL;
882         }
883
884         sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
885                  __func__, cmd_type, rw, func, addr, nbytes));
886
887         DHD_PM_RESUME_WAIT(sdioh_request_word_wait);
888         DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
889         /* Claim host controller */
890         sdio_claim_host(gInstance->func[func]);
891
892         if (rw) {               /* CMD52 Write */
893                 if (nbytes == 4) {
894                         sdio_writel(gInstance->func[func], *word, addr,
895                                     &err_ret);
896                 } else if (nbytes == 2) {
897                         sdio_writew(gInstance->func[func], (*word & 0xFFFF),
898                                     addr, &err_ret);
899                 } else {
900                         sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
901                 }
902         } else {                /* CMD52 Read */
903                 if (nbytes == 4) {
904                         *word =
905                             sdio_readl(gInstance->func[func], addr, &err_ret);
906                 } else if (nbytes == 2) {
907                         *word =
908                             sdio_readw(gInstance->func[func], addr,
909                                        &err_ret) & 0xFFFF;
910                 } else {
911                         sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
912                 }
913         }
914
915         /* Release host controller */
916         sdio_release_host(gInstance->func[func]);
917
918         if (err_ret) {
919                 sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x",
920                         rw ? "Write" : "Read", err_ret));
921         }
922
923         return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
924 }
925
926 static SDIOH_API_RC
927 sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
928                      uint addr, struct sk_buff *pkt)
929 {
930         bool fifo = (fix_inc == SDIOH_DATA_FIX);
931         u32 SGCount = 0;
932         int err_ret = 0;
933
934         struct sk_buff *pnext;
935
936         sd_trace(("%s: Enter\n", __func__));
937
938         ASSERT(pkt);
939         DHD_PM_RESUME_WAIT(sdioh_request_packet_wait);
940         DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
941
942         /* Claim host controller */
943         sdio_claim_host(gInstance->func[func]);
944         for (pnext = pkt; pnext; pnext = pnext->next) {
945                 uint pkt_len = pnext->len;
946                 pkt_len += 3;
947                 pkt_len &= 0xFFFFFFFC;
948
949 #ifdef CONFIG_MMC_MSM7X00A
950                 if ((pkt_len % 64) == 32) {
951                         sd_trace(("%s: Rounding up TX packet +=32\n",
952                                   __func__));
953                         pkt_len += 32;
954                 }
955 #endif                          /* CONFIG_MMC_MSM7X00A */
956                 /* Make sure the packet is aligned properly.
957                  * If it isn't, then this
958                  * is the fault of sdioh_request_buffer() which
959                  * is supposed to give
960                  * us something we can work with.
961                  */
962                 ASSERT(((u32) (pkt->data) & DMA_ALIGN_MASK) == 0);
963
964                 if ((write) && (!fifo)) {
965                         err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
966                                                    ((u8 *) (pnext->data)),
967                                                    pkt_len);
968                 } else if (write) {
969                         err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
970                                                    ((u8 *) (pnext->data)),
971                                                    pkt_len);
972                 } else if (fifo) {
973                         err_ret = sdio_readsb(gInstance->func[func],
974                                               ((u8 *) (pnext->data)),
975                                               addr, pkt_len);
976                 } else {
977                         err_ret = sdio_memcpy_fromio(gInstance->func[func],
978                                                      ((u8 *) (pnext->data)),
979                                                      addr, pkt_len);
980                 }
981
982                 if (err_ret) {
983                         sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d,"
984                                  "ERR=0x%08x\n", __func__,
985                                  (write) ? "TX" : "RX",
986                                  pnext, SGCount, addr, pkt_len, err_ret));
987                 } else {
988                         sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n",
989                                   __func__,
990                                   (write) ? "TX" : "RX",
991                                   pnext, SGCount, addr, pkt_len));
992                 }
993
994                 if (!fifo)
995                         addr += pkt_len;
996                 SGCount++;
997
998         }
999
1000         /* Release host controller */
1001         sdio_release_host(gInstance->func[func]);
1002
1003         sd_trace(("%s: Exit\n", __func__));
1004         return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
1005 }
1006
1007 /*
1008  * This function takes a buffer or packet, and fixes everything up
1009  * so that in the
1010  * end, a DMA-able packet is created.
1011  *
1012  * A buffer does not have an associated packet pointer,
1013  * and may or may not be aligned.
1014  * A packet may consist of a single packet, or a packet chain.
1015  * If it is a packet chain,
1016  * then all the packets in the chain must be properly aligned.
1017  * If the packet data is not
1018  * aligned, then there may only be one packet, and in this case,
1019  * it is copied to a new
1020  * aligned packet.
1021  *
1022  */
1023 extern SDIOH_API_RC
1024 sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write,
1025                      uint func, uint addr, uint reg_width, uint buflen_u,
1026                      u8 *buffer, struct sk_buff *pkt)
1027 {
1028         SDIOH_API_RC Status;
1029         struct sk_buff *mypkt = NULL;
1030
1031         sd_trace(("%s: Enter\n", __func__));
1032
1033         DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait);
1034         DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
1035         /* Case 1: we don't have a packet. */
1036         if (pkt == NULL) {
1037                 sd_data(("%s: Creating new %s Packet, len=%d\n",
1038                          __func__, write ? "TX" : "RX", buflen_u));
1039                 mypkt = pkt_buf_get_skb(buflen_u);
1040                 if (!mypkt) {
1041                         sd_err(("%s: pkt_buf_get_skb failed: len %d\n",
1042                                 __func__, buflen_u));
1043                         return SDIOH_API_RC_FAIL;
1044                 }
1045
1046                 /* For a write, copy the buffer data into the packet. */
1047                 if (write)
1048                         memcpy(mypkt->data, buffer, buflen_u);
1049
1050                 Status =
1051                     sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
1052
1053                 /* For a read, copy the packet data back to the buffer. */
1054                 if (!write)
1055                         memcpy(buffer, mypkt->data, buflen_u);
1056
1057                 pkt_buf_free_skb(mypkt);
1058         } else if (((u32) (pkt->data) & DMA_ALIGN_MASK) != 0) {
1059                 /* Case 2: We have a packet, but it is unaligned. */
1060
1061                 /* In this case, we cannot have a chain. */
1062                 ASSERT(pkt->next == NULL);
1063
1064                 sd_data(("%s: Creating aligned %s Packet, len=%d\n",
1065                          __func__, write ? "TX" : "RX", pkt->len));
1066                 mypkt = pkt_buf_get_skb(pkt->len);
1067                 if (!mypkt) {
1068                         sd_err(("%s: pkt_buf_get_skb failed: len %d\n",
1069                                 __func__, pkt->len));
1070                         return SDIOH_API_RC_FAIL;
1071                 }
1072
1073                 /* For a write, copy the buffer data into the packet. */
1074                 if (write)
1075                         memcpy(mypkt->data, pkt->data, pkt->len);
1076
1077                 Status =
1078                     sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
1079
1080                 /* For a read, copy the packet data back to the buffer. */
1081                 if (!write)
1082                         memcpy(pkt->data, mypkt->data, mypkt->len);
1083
1084                 pkt_buf_free_skb(mypkt);
1085         } else {                /* case 3: We have a packet and
1086                                  it is aligned. */
1087                 sd_data(("%s: Aligned %s Packet, direct DMA\n",
1088                          __func__, write ? "Tx" : "Rx"));
1089                 Status =
1090                     sdioh_request_packet(sd, fix_inc, write, func, addr, pkt);
1091         }
1092
1093         return Status;
1094 }
1095
1096 /* this function performs "abort" for both of host & device */
1097 extern int sdioh_abort(sdioh_info_t *sd, uint func)
1098 {
1099 #if defined(MMC_SDIO_ABORT)
1100         char t_func = (char)func;
1101 #endif                          /* defined(MMC_SDIO_ABORT) */
1102         sd_trace(("%s: Enter\n", __func__));
1103
1104 #if defined(MMC_SDIO_ABORT)
1105         /* issue abort cmd52 command through F1 */
1106         sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT,
1107                            &t_func);
1108 #endif                          /* defined(MMC_SDIO_ABORT) */
1109
1110         sd_trace(("%s: Exit\n", __func__));
1111         return SDIOH_API_RC_SUCCESS;
1112 }
1113
1114 /* Reset and re-initialize the device */
1115 int sdioh_sdio_reset(sdioh_info_t *si)
1116 {
1117         sd_trace(("%s: Enter\n", __func__));
1118         sd_trace(("%s: Exit\n", __func__));
1119         return SDIOH_API_RC_SUCCESS;
1120 }
1121
1122 /* Disable device interrupt */
1123 void sdioh_sdmmc_devintr_off(sdioh_info_t *sd)
1124 {
1125         sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
1126         sd->intmask &= ~CLIENT_INTR;
1127 }
1128
1129 /* Enable device interrupt */
1130 void sdioh_sdmmc_devintr_on(sdioh_info_t *sd)
1131 {
1132         sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
1133         sd->intmask |= CLIENT_INTR;
1134 }
1135
1136 /* Read client card reg */
1137 int
1138 sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, u32 regaddr,
1139                          int regsize, u32 *data)
1140 {
1141
1142         if ((func == 0) || (regsize == 1)) {
1143                 u8 temp = 0;
1144
1145                 sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
1146                 *data = temp;
1147                 *data &= 0xff;
1148                 sd_data(("%s: byte read data=0x%02x\n", __func__, *data));
1149         } else {
1150                 sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data,
1151                                    regsize);
1152                 if (regsize == 2)
1153                         *data &= 0xffff;
1154
1155                 sd_data(("%s: word read data=0x%08x\n", __func__, *data));
1156         }
1157
1158         return SUCCESS;
1159 }
1160
1161 #if !defined(OOB_INTR_ONLY)
1162 /* bcmsdh_sdmmc interrupt handler */
1163 static void IRQHandler(struct sdio_func *func)
1164 {
1165         sdioh_info_t *sd;
1166
1167         sd_trace(("bcmsdh_sdmmc: ***IRQHandler\n"));
1168         sd = gInstance->sd;
1169
1170         ASSERT(sd != NULL);
1171         sdio_release_host(gInstance->func[0]);
1172
1173         if (sd->use_client_ints) {
1174                 sd->intrcount++;
1175                 ASSERT(sd->intr_handler);
1176                 ASSERT(sd->intr_handler_arg);
1177                 (sd->intr_handler) (sd->intr_handler_arg);
1178         } else {
1179                 sd_err(("bcmsdh_sdmmc: ***IRQHandler\n"));
1180
1181                 sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
1182                         __func__, sd->client_intr_enabled, sd->intr_handler));
1183         }
1184
1185         sdio_claim_host(gInstance->func[0]);
1186 }
1187
1188 /* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */
1189 static void IRQHandlerF2(struct sdio_func *func)
1190 {
1191         sdioh_info_t *sd;
1192
1193         sd_trace(("bcmsdh_sdmmc: ***IRQHandlerF2\n"));
1194
1195         sd = gInstance->sd;
1196
1197         ASSERT(sd != NULL);
1198 }
1199 #endif                          /* !defined(OOB_INTR_ONLY) */
1200
1201 #ifdef NOTUSED
1202 /* Write client card reg */
1203 static int
1204 sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, u32 regaddr,
1205                           int regsize, u32 data)
1206 {
1207
1208         if ((func == 0) || (regsize == 1)) {
1209                 u8 temp;
1210
1211                 temp = data & 0xff;
1212                 sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
1213                 sd_data(("%s: byte write data=0x%02x\n", __func__, data));
1214         } else {
1215                 if (regsize == 2)
1216                         data &= 0xffff;
1217
1218                 sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, &data,
1219                                    regsize);
1220
1221                 sd_data(("%s: word write data=0x%08x\n", __func__, data));
1222         }
1223
1224         return SUCCESS;
1225 }
1226 #endif                          /* NOTUSED */
1227
1228 int sdioh_start(sdioh_info_t *si, int stage)
1229 {
1230         return 0;
1231 }
1232
1233 int sdioh_stop(sdioh_info_t *si)
1234 {
1235         return 0;
1236 }