2 * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
4 * Copyright (C) 1999-2017, Broadcom Corporation
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:
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.
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.
25 * <<Broadcom-WL-IPTag/Proprietary,Open:>>
27 * $Id: bcmsdh_sdmmc.c 710913 2017-07-14 10:17:51Z $
32 #include <bcmendian.h>
35 #include <sdio.h> /* SDIO Device and Protocol Specs */
36 #include <sdioh.h> /* Standard SDIO Host Controller Specification */
37 #include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
38 #include <sdiovar.h> /* ioctl/iovars */
40 #include <linux/mmc/core.h>
41 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 0, 0))
42 #include <drivers/mmc/core/host.h>
44 mmc_host_clk_hold(struct mmc_host
*host
)
51 mmc_host_clk_release(struct mmc_host
*host
)
56 #elif (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 0, 8))
57 #include <drivers/mmc/core/host.h>
59 #include <linux/mmc/host.h>
60 #endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 0, 0)) */
61 #include <linux/mmc/card.h>
62 #include <linux/mmc/sdio_func.h>
63 #include <linux/mmc/sdio_ids.h>
65 #include <dngl_stats.h>
69 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
70 #include <linux/suspend.h>
71 extern volatile bool dhd_mmc_suspend
;
73 #include "bcmsdh_sdmmc.h"
76 extern int sdio_function_init(void);
77 extern void sdio_function_cleanup(void);
78 #endif /* BCMSDH_MODULE */
80 #if !defined(OOB_INTR_ONLY)
81 static void IRQHandler(struct sdio_func
*func
);
82 static void IRQHandlerF2(struct sdio_func
*func
);
83 #endif /* !defined(OOB_INTR_ONLY) */
84 static int sdioh_sdmmc_get_cisaddr(sdioh_info_t
*sd
, uint32 regaddr
);
85 #if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(BUS_POWER_RESTORE)
86 extern int sdio_reset_comm(struct mmc_card
*card
);
88 int sdio_reset_comm(struct mmc_card
*card
)
93 #ifdef GLOBAL_SDMMC_INSTANCE
94 extern PBCMSDH_SDMMC_INSTANCE gInstance
;
97 #define DEFAULT_SDIO_F2_BLKSIZE 512
98 #ifndef CUSTOM_SDIO_F2_BLKSIZE
99 #define CUSTOM_SDIO_F2_BLKSIZE DEFAULT_SDIO_F2_BLKSIZE
102 #define DEFAULT_SDIO_F1_BLKSIZE 64
103 #ifndef CUSTOM_SDIO_F1_BLKSIZE
104 #define CUSTOM_SDIO_F1_BLKSIZE DEFAULT_SDIO_F1_BLKSIZE
107 #define MAX_IO_RW_EXTENDED_BLK 511
109 uint sd_sdmode
= SDIOH_MODE_SD4
; /* Use SD4 mode by default */
110 uint sd_f2_blocksize
= CUSTOM_SDIO_F2_BLKSIZE
;
111 uint sd_f1_blocksize
= CUSTOM_SDIO_F1_BLKSIZE
;
113 #if defined(BT_OVER_SDIO)
114 uint sd_f3_blocksize
= 64;
115 #endif /* defined (BT_OVER_SDIO) */
117 uint sd_divisor
= 2; /* Default 48MHz/2 = 24MHz */
119 uint sd_power
= 1; /* Default to SD Slot powered ON */
120 uint sd_clock
= 1; /* Default to SD Clock turned ON */
121 uint sd_hiok
= FALSE
; /* Don't use hi-speed mode by default */
122 uint sd_msglevel
= 0x01;
123 uint sd_use_dma
= TRUE
;
125 #ifndef CUSTOM_RXCHAIN
126 #define CUSTOM_RXCHAIN 0
129 DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait
);
130 DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait
);
131 DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait
);
132 DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait
);
134 #define DMA_ALIGN_MASK 0x03
135 #define MMC_SDIO_ABORT_RETRY_LIMIT 5
137 int sdioh_sdmmc_card_regread(sdioh_info_t
*sd
, int func
, uint32 regaddr
, int regsize
, uint32
*data
);
139 void sdmmc_set_clock_rate(sdioh_info_t
*sd
, uint hz
);
140 uint
sdmmc_get_clock_rate(sdioh_info_t
*sd
);
141 void sdmmc_set_clock_divisor(sdioh_info_t
*sd
, uint sd_div
);
142 #if defined(BT_OVER_SDIO)
144 void sdioh_sdmmc_card_enable_func_f3(sdioh_info_t
*sd
, struct sdio_func
*func
)
147 sd_info(("%s sd->func[3] %p\n", __FUNCTION__
, sd
->func
[3]));
149 #endif /* defined (BT_OVER_SDIO) */
152 sdioh_sdmmc_card_enablefuncs(sdioh_info_t
*sd
)
158 sd_trace(("%s\n", __FUNCTION__
));
160 /* Get the Card's common CIS address */
161 sd
->com_cis_ptr
= sdioh_sdmmc_get_cisaddr(sd
, SDIOD_CCCR_CISPTR_0
);
162 sd
->func_cis_ptr
[0] = sd
->com_cis_ptr
;
163 sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__
, sd
->com_cis_ptr
));
165 /* Get the Card's function CIS (for each function) */
166 for (fbraddr
= SDIOD_FBR_STARTADDR
, func
= 1;
167 func
<= sd
->num_funcs
; func
++, fbraddr
+= SDIOD_FBR_SIZE
) {
168 sd
->func_cis_ptr
[func
] = sdioh_sdmmc_get_cisaddr(sd
, SDIOD_FBR_CISPTR_0
+ fbraddr
);
169 sd_info(("%s: Function %d CIS Ptr = 0x%x\n",
170 __FUNCTION__
, func
, sd
->func_cis_ptr
[func
]));
173 sd
->func_cis_ptr
[0] = sd
->com_cis_ptr
;
174 sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__
, sd
->com_cis_ptr
));
176 /* Enable Function 1 */
177 sdio_claim_host(sd
->func
[1]);
178 err_ret
= sdio_enable_func(sd
->func
[1]);
179 sdio_release_host(sd
->func
[1]);
181 sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x\n", err_ret
));
188 * Public entry points & extern's
190 extern sdioh_info_t
*
191 sdioh_attach(osl_t
*osh
, struct sdio_func
*func
)
193 sdioh_info_t
*sd
= NULL
;
196 sd_trace(("%s\n", __FUNCTION__
));
199 sd_err(("%s: sdio function device is NULL\n", __FUNCTION__
));
203 if ((sd
= (sdioh_info_t
*)MALLOC(osh
, sizeof(sdioh_info_t
))) == NULL
) {
204 sd_err(("sdioh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh
)));
207 bzero((char *)sd
, sizeof(sdioh_info_t
));
209 sd
->fake_func0
.num
= 0;
210 sd
->fake_func0
.card
= func
->card
;
211 sd
->func
[0] = &sd
->fake_func0
;
212 #ifdef GLOBAL_SDMMC_INSTANCE
214 sd
->func
[1] = gInstance
->func
[1];
216 sd
->func
[1] = func
->card
->sdio_func
[0];
218 sd
->func
[2] = func
->card
->sdio_func
[1];
219 #ifdef GLOBAL_SDMMC_INSTANCE
220 sd
->func
[func
->num
] = func
;
223 #if defined(BT_OVER_SDIO)
225 #endif /* defined (BT_OVER_SDIO) */
228 sd
->sd_blockmode
= TRUE
;
229 sd
->use_client_ints
= TRUE
;
230 sd
->client_block_size
[0] = 64;
231 sd
->use_rxchain
= CUSTOM_RXCHAIN
;
232 if (sd
->func
[1] == NULL
|| sd
->func
[2] == NULL
) {
233 sd_err(("%s: func 1 or 2 is null \n", __FUNCTION__
));
236 sdio_set_drvdata(sd
->func
[1], sd
);
238 sdio_claim_host(sd
->func
[1]);
239 sd
->client_block_size
[1] = sd_f1_blocksize
;
240 err_ret
= sdio_set_block_size(sd
->func
[1], sd_f1_blocksize
);
241 sdio_release_host(sd
->func
[1]);
243 sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize(%d)\n", err_ret
));
247 sdio_claim_host(sd
->func
[2]);
248 sd
->client_block_size
[2] = sd_f2_blocksize
;
249 printf("%s: set sd_f2_blocksize %d\n", __FUNCTION__
, sd_f2_blocksize
);
250 err_ret
= sdio_set_block_size(sd
->func
[2], sd_f2_blocksize
);
251 sdio_release_host(sd
->func
[2]);
253 sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize to %d(%d)\n",
254 sd_f2_blocksize
, err_ret
));
258 sd
->sd_clk_rate
= sdmmc_get_clock_rate(sd
);
259 printf("%s: sd clock rate = %u\n", __FUNCTION__
, sd
->sd_clk_rate
);
260 sdioh_sdmmc_card_enablefuncs(sd
);
262 sd_trace(("%s: Done\n", __FUNCTION__
));
266 MFREE(sd
->osh
, sd
, sizeof(sdioh_info_t
));
272 sdioh_detach(osl_t
*osh
, sdioh_info_t
*sd
)
274 sd_trace(("%s\n", __FUNCTION__
));
278 /* Disable Function 2 */
280 sdio_claim_host(sd
->func
[2]);
281 sdio_disable_func(sd
->func
[2]);
282 sdio_release_host(sd
->func
[2]);
285 /* Disable Function 1 */
287 sdio_claim_host(sd
->func
[1]);
288 sdio_disable_func(sd
->func
[1]);
289 sdio_release_host(sd
->func
[1]);
295 MFREE(sd
->osh
, sd
, sizeof(sdioh_info_t
));
297 return SDIOH_API_RC_SUCCESS
;
300 #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
303 sdioh_enable_func_intr(sdioh_info_t
*sd
)
308 if (sd
->func
[0] == NULL
) {
309 sd_err(("%s: function 0 pointer is NULL\n", __FUNCTION__
));
310 return SDIOH_API_RC_FAIL
;
313 sdio_claim_host(sd
->func
[0]);
314 reg
= sdio_readb(sd
->func
[0], SDIOD_CCCR_INTEN
, &err
);
316 sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__
, err
));
317 sdio_release_host(sd
->func
[0]);
318 return SDIOH_API_RC_FAIL
;
320 /* Enable F1 and F2 interrupts, clear master enable */
321 reg
&= ~INTR_CTL_MASTER_EN
;
322 reg
|= (INTR_CTL_FUNC1_EN
| INTR_CTL_FUNC2_EN
);
323 #if defined(BT_OVER_SDIO)
324 reg
|= (INTR_CTL_FUNC3_EN
);
325 #endif /* defined (BT_OVER_SDIO) */
326 sdio_writeb(sd
->func
[0], reg
, SDIOD_CCCR_INTEN
, &err
);
327 sdio_release_host(sd
->func
[0]);
330 sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__
, err
));
331 return SDIOH_API_RC_FAIL
;
334 return SDIOH_API_RC_SUCCESS
;
338 sdioh_disable_func_intr(sdioh_info_t
*sd
)
343 if (sd
->func
[0] == NULL
) {
344 sd_err(("%s: function 0 pointer is NULL\n", __FUNCTION__
));
345 return SDIOH_API_RC_FAIL
;
348 sdio_claim_host(sd
->func
[0]);
349 reg
= sdio_readb(sd
->func
[0], SDIOD_CCCR_INTEN
, &err
);
351 sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__
, err
));
352 sdio_release_host(sd
->func
[0]);
353 return SDIOH_API_RC_FAIL
;
355 reg
&= ~(INTR_CTL_FUNC1_EN
| INTR_CTL_FUNC2_EN
);
356 #if defined(BT_OVER_SDIO)
357 reg
&= ~INTR_CTL_FUNC3_EN
;
359 /* Disable master interrupt with the last function interrupt */
362 sdio_writeb(sd
->func
[0], reg
, SDIOD_CCCR_INTEN
, &err
);
363 sdio_release_host(sd
->func
[0]);
366 sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__
, err
));
367 return SDIOH_API_RC_FAIL
;
370 return SDIOH_API_RC_SUCCESS
;
372 #endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
374 /* Configure callback to client when we recieve client interrupt */
376 sdioh_interrupt_register(sdioh_info_t
*sd
, sdioh_cb_fn_t fn
, void *argh
)
378 sd_trace(("%s: Entering\n", __FUNCTION__
));
380 sd_err(("%s: interrupt handler is NULL, not registering\n", __FUNCTION__
));
381 return SDIOH_API_RC_FAIL
;
383 #if !defined(OOB_INTR_ONLY)
384 sd
->intr_handler
= fn
;
385 sd
->intr_handler_arg
= argh
;
386 sd
->intr_handler_valid
= TRUE
;
388 /* register and unmask irq */
390 sdio_claim_host(sd
->func
[2]);
391 sdio_claim_irq(sd
->func
[2], IRQHandlerF2
);
392 sdio_release_host(sd
->func
[2]);
396 sdio_claim_host(sd
->func
[1]);
397 sdio_claim_irq(sd
->func
[1], IRQHandler
);
398 sdio_release_host(sd
->func
[1]);
400 #elif defined(HW_OOB)
401 sdioh_enable_func_intr(sd
);
402 #endif /* !defined(OOB_INTR_ONLY) */
404 return SDIOH_API_RC_SUCCESS
;
408 sdioh_interrupt_deregister(sdioh_info_t
*sd
)
410 sd_trace(("%s: Entering\n", __FUNCTION__
));
412 #if !defined(OOB_INTR_ONLY)
414 /* register and unmask irq */
415 sdio_claim_host(sd
->func
[1]);
416 sdio_release_irq(sd
->func
[1]);
417 sdio_release_host(sd
->func
[1]);
421 /* Claim host controller F2 */
422 sdio_claim_host(sd
->func
[2]);
423 sdio_release_irq(sd
->func
[2]);
424 /* Release host controller F2 */
425 sdio_release_host(sd
->func
[2]);
428 sd
->intr_handler_valid
= FALSE
;
429 sd
->intr_handler
= NULL
;
430 sd
->intr_handler_arg
= NULL
;
431 #elif defined(HW_OOB)
432 if (dhd_download_fw_on_driverload
)
433 sdioh_disable_func_intr(sd
);
434 #endif /* !defined(OOB_INTR_ONLY) */
435 return SDIOH_API_RC_SUCCESS
;
439 sdioh_interrupt_query(sdioh_info_t
*sd
, bool *onoff
)
441 sd_trace(("%s: Entering\n", __FUNCTION__
));
442 *onoff
= sd
->client_intr_enabled
;
443 return SDIOH_API_RC_SUCCESS
;
446 #if defined(DHD_DEBUG)
448 sdioh_interrupt_pending(sdioh_info_t
*sd
)
455 sdioh_query_iofnum(sdioh_info_t
*sd
)
457 return sd
->num_funcs
;
480 const bcm_iovar_t sdioh_iovars
[] = {
481 {"sd_msglevel", IOV_MSGLEVEL
, 0, 0, IOVT_UINT32
, 0 },
482 {"sd_blockmode", IOV_BLOCKMODE
, 0, 0, IOVT_BOOL
, 0 },
483 {"sd_blocksize", IOV_BLOCKSIZE
, 0, 0, IOVT_UINT32
, 0 }, /* ((fn << 16) | size) */
484 {"sd_dma", IOV_DMA
, 0, 0, IOVT_BOOL
, 0 },
485 {"sd_ints", IOV_USEINTS
, 0, 0, IOVT_BOOL
, 0 },
486 {"sd_numints", IOV_NUMINTS
, 0, 0, IOVT_UINT32
, 0 },
487 {"sd_numlocalints", IOV_NUMLOCALINTS
, 0, 0, IOVT_UINT32
, 0 },
488 {"sd_divisor", IOV_DIVISOR
, 0, 0, IOVT_UINT32
, 0 },
489 {"sd_power", IOV_POWER
, 0, 0, IOVT_UINT32
, 0 },
490 {"sd_clock", IOV_CLOCK
, 0, 0, IOVT_UINT32
, 0 },
491 {"sd_mode", IOV_SDMODE
, 0, 0, IOVT_UINT32
, 100},
492 {"sd_highspeed", IOV_HISPEED
, 0, 0, IOVT_UINT32
, 0 },
493 {"sd_rxchain", IOV_RXCHAIN
, 0, 0, IOVT_BOOL
, 0 },
494 {NULL
, 0, 0, 0, 0, 0 }
498 sdioh_iovar_op(sdioh_info_t
*si
, const char *name
,
499 void *params
, int plen
, void *arg
, int len
, bool set
)
501 const bcm_iovar_t
*vi
= NULL
;
511 /* Get must have return space; Set does not take qualifiers */
512 ASSERT(set
|| (arg
&& len
));
513 ASSERT(!set
|| (!params
&& !plen
));
515 sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__
, (set
? "set" : "get"), name
));
517 if ((vi
= bcm_iovar_lookup(sdioh_iovars
, name
)) == NULL
) {
518 bcmerror
= BCME_UNSUPPORTED
;
522 if ((bcmerror
= bcm_iovar_lencheck(vi
, arg
, len
, set
)) != 0)
525 /* Set up params so get and set can share the convenience variables */
526 if (params
== NULL
) {
531 if (vi
->type
== IOVT_VOID
)
533 else if (vi
->type
== IOVT_BUFFER
)
536 val_size
= sizeof(int);
538 if (plen
>= (int)sizeof(int_val
))
539 bcopy(params
, &int_val
, sizeof(int_val
));
541 bool_val
= (int_val
!= 0) ? TRUE
: FALSE
;
542 BCM_REFERENCE(bool_val
);
544 actionid
= set
? IOV_SVAL(vi
->varid
) : IOV_GVAL(vi
->varid
);
546 case IOV_GVAL(IOV_MSGLEVEL
):
547 int_val
= (int32
)sd_msglevel
;
548 bcopy(&int_val
, arg
, val_size
);
551 case IOV_SVAL(IOV_MSGLEVEL
):
552 sd_msglevel
= int_val
;
555 case IOV_GVAL(IOV_BLOCKMODE
):
556 int_val
= (int32
)si
->sd_blockmode
;
557 bcopy(&int_val
, arg
, val_size
);
560 case IOV_SVAL(IOV_BLOCKMODE
):
561 si
->sd_blockmode
= (bool)int_val
;
562 /* Haven't figured out how to make non-block mode with DMA */
565 case IOV_GVAL(IOV_BLOCKSIZE
):
566 if ((uint32
)int_val
> si
->num_funcs
) {
567 bcmerror
= BCME_BADARG
;
570 int_val
= (int32
)si
->client_block_size
[int_val
];
571 bcopy(&int_val
, arg
, val_size
);
574 case IOV_SVAL(IOV_BLOCKSIZE
):
576 uint func
= ((uint32
)int_val
>> 16);
577 uint blksize
= (uint16
)int_val
;
580 if (func
> si
->num_funcs
) {
581 bcmerror
= BCME_BADARG
;
586 case 0: maxsize
= 32; break;
587 case 1: maxsize
= BLOCK_SIZE_4318
; break;
588 case 2: maxsize
= BLOCK_SIZE_4328
; break;
589 default: maxsize
= 0;
591 if (blksize
> maxsize
) {
592 bcmerror
= BCME_BADARG
;
600 si
->client_block_size
[func
] = blksize
;
602 if (si
->func
[func
] == NULL
) {
603 sd_err(("%s: SDIO Device not present\n", __FUNCTION__
));
604 bcmerror
= BCME_NORESOURCE
;
607 sdio_claim_host(si
->func
[func
]);
608 bcmerror
= sdio_set_block_size(si
->func
[func
], blksize
);
610 sd_err(("%s: Failed to set F%d blocksize to %d(%d)\n",
611 __FUNCTION__
, func
, blksize
, bcmerror
));
612 sdio_release_host(si
->func
[func
]);
616 case IOV_GVAL(IOV_RXCHAIN
):
617 int_val
= (int32
)si
->use_rxchain
;
618 bcopy(&int_val
, arg
, val_size
);
621 case IOV_GVAL(IOV_DMA
):
622 int_val
= (int32
)si
->sd_use_dma
;
623 bcopy(&int_val
, arg
, val_size
);
626 case IOV_SVAL(IOV_DMA
):
627 si
->sd_use_dma
= (bool)int_val
;
630 case IOV_GVAL(IOV_USEINTS
):
631 int_val
= (int32
)si
->use_client_ints
;
632 bcopy(&int_val
, arg
, val_size
);
635 case IOV_SVAL(IOV_USEINTS
):
636 si
->use_client_ints
= (bool)int_val
;
637 if (si
->use_client_ints
)
638 si
->intmask
|= CLIENT_INTR
;
640 si
->intmask
&= ~CLIENT_INTR
;
644 case IOV_GVAL(IOV_DIVISOR
):
645 int_val
= (uint32
)sd_divisor
;
646 bcopy(&int_val
, arg
, val_size
);
649 case IOV_SVAL(IOV_DIVISOR
):
650 /* set the clock to divisor, if value is non-zero & power of 2 */
651 if (int_val
&& !(int_val
& (int_val
- 1))) {
652 sd_divisor
= int_val
;
653 sdmmc_set_clock_divisor(si
, sd_divisor
);
655 DHD_ERROR(("%s: Invalid sd_divisor value, should be power of 2!\n",
660 case IOV_GVAL(IOV_POWER
):
661 int_val
= (uint32
)sd_power
;
662 bcopy(&int_val
, arg
, val_size
);
665 case IOV_SVAL(IOV_POWER
):
669 case IOV_GVAL(IOV_CLOCK
):
670 int_val
= (uint32
)sd_clock
;
671 bcopy(&int_val
, arg
, val_size
);
674 case IOV_SVAL(IOV_CLOCK
):
678 case IOV_GVAL(IOV_SDMODE
):
679 int_val
= (uint32
)sd_sdmode
;
680 bcopy(&int_val
, arg
, val_size
);
683 case IOV_SVAL(IOV_SDMODE
):
687 case IOV_GVAL(IOV_HISPEED
):
688 int_val
= (uint32
)sd_hiok
;
689 bcopy(&int_val
, arg
, val_size
);
692 case IOV_SVAL(IOV_HISPEED
):
696 case IOV_GVAL(IOV_NUMINTS
):
697 int_val
= (int32
)si
->intrcount
;
698 bcopy(&int_val
, arg
, val_size
);
701 case IOV_GVAL(IOV_NUMLOCALINTS
):
703 bcopy(&int_val
, arg
, val_size
);
706 bcmerror
= BCME_UNSUPPORTED
;
714 #if (defined(OOB_INTR_ONLY) && defined(HW_OOB)) || defined(FORCE_WOWLAN)
715 #ifdef CUSTOMER_HW_AMLOGIC
716 #include <linux/amlogic/aml_gpio_consumer.h>
717 extern int wifi_irq_trigger_level(void);
720 sdioh_enable_hw_oob_intr(sdioh_info_t
*sd
, bool enable
)
726 if (wifi_irq_trigger_level() == GPIO_IRQ_LOW
)
727 data
= SDIO_SEPINT_MASK
| SDIO_SEPINT_OE
;
729 data
= SDIO_SEPINT_MASK
| SDIO_SEPINT_OE
| SDIO_SEPINT_ACT_HI
;
732 data
= SDIO_SEPINT_ACT_HI
; /* disable hw oob interrupt */
734 status
= sdioh_request_byte(sd
, SDIOH_WRITE
, 0, SDIOD_CCCR_BRCM_SEPINT
, &data
);
737 #endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
740 sdioh_cfg_read(sdioh_info_t
*sd
, uint fnc_num
, uint32 addr
, uint8
*data
)
743 /* No lock needed since sdioh_request_byte does locking */
744 status
= sdioh_request_byte(sd
, SDIOH_READ
, fnc_num
, addr
, data
);
749 sdioh_cfg_write(sdioh_info_t
*sd
, uint fnc_num
, uint32 addr
, uint8
*data
)
751 /* No lock needed since sdioh_request_byte does locking */
753 status
= sdioh_request_byte(sd
, SDIOH_WRITE
, fnc_num
, addr
, data
);
758 sdioh_sdmmc_get_cisaddr(sdioh_info_t
*sd
, uint32 regaddr
)
760 /* read 24 bits and return valid 17 bit addr */
762 uint32 scratch
, regdata
;
763 uint8
*ptr
= (uint8
*)&scratch
;
764 for (i
= 0; i
< 3; i
++) {
765 if ((sdioh_sdmmc_card_regread (sd
, 0, regaddr
, 1, ®data
)) != SUCCESS
)
766 sd_err(("%s: Can't read!\n", __FUNCTION__
));
768 *ptr
++ = (uint8
) regdata
;
772 /* Only the lower 17-bits are valid */
773 scratch
= ltoh32(scratch
);
774 scratch
&= 0x0001FFFF;
779 sdioh_cis_read(sdioh_info_t
*sd
, uint func
, uint8
*cisd
, uint32 length
)
786 sd_trace(("%s: Func = %d\n", __FUNCTION__
, func
));
788 if (!sd
->func_cis_ptr
[func
]) {
790 sd_err(("%s: no func_cis_ptr[%d]\n", __FUNCTION__
, func
));
791 return SDIOH_API_RC_FAIL
;
794 sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __FUNCTION__
, func
, sd
->func_cis_ptr
[func
]));
796 for (count
= 0; count
< length
; count
++) {
797 offset
= sd
->func_cis_ptr
[func
] + count
;
798 if (sdioh_sdmmc_card_regread (sd
, 0, offset
, 1, &foo
) < 0) {
799 sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__
));
800 return SDIOH_API_RC_FAIL
;
803 *cis
= (uint8
)(foo
& 0xff);
807 return SDIOH_API_RC_SUCCESS
;
811 sdioh_cisaddr_read(sdioh_info_t
*sd
, uint func
, uint8
*cisd
, uint32 offset
)
815 sd_trace(("%s: Func = %d\n", __FUNCTION__
, func
));
817 if (!sd
->func_cis_ptr
[func
]) {
818 sd_err(("%s: no func_cis_ptr[%d]\n", __FUNCTION__
, func
));
819 return SDIOH_API_RC_FAIL
;
822 sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __FUNCTION__
, func
, sd
->func_cis_ptr
[func
]));
824 if (sdioh_sdmmc_card_regread (sd
, 0, sd
->func_cis_ptr
[func
]+offset
, 1, &foo
) < 0) {
825 sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__
));
826 return SDIOH_API_RC_FAIL
;
829 *cisd
= (uint8
)(foo
& 0xff);
831 return SDIOH_API_RC_SUCCESS
;
835 sdioh_request_byte(sdioh_info_t
*sd
, uint rw
, uint func
, uint regaddr
, uint8
*byte
)
838 #if defined(MMC_SDIO_ABORT)
839 int sdio_abort_retry
= MMC_SDIO_ABORT_RETRY_LIMIT
;
841 struct timespec now
, before
;
843 if (sd_msglevel
& SDH_COST_VAL
)
844 getnstimeofday(&before
);
846 sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__
, rw
, func
, regaddr
));
848 DHD_PM_RESUME_WAIT(sdioh_request_byte_wait
);
849 DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL
);
850 if(rw
) { /* CMD52 Write */
852 /* Can only directly write to some F0 registers. Handle F2 enable
855 if (regaddr
== SDIOD_CCCR_IOEN
) {
856 #if defined(BT_OVER_SDIO)
859 sd_info(("bcmsdh_sdmmc F3: *byte 0x%x\n", *byte
));
861 if (*byte
& SDIO_FUNC_ENABLE_3
) {
862 sdio_claim_host(sd
->func
[3]);
864 /* Set Function 3 Block Size */
865 err_ret
= sdio_set_block_size(sd
->func
[3],
868 sd_err(("F3 blocksize set err%d\n",
872 /* Enable Function 3 */
873 sd_info(("bcmsdh_sdmmc F3: enable F3 fn %p\n",
875 err_ret
= sdio_enable_func(sd
->func
[3]);
877 sd_err(("bcmsdh_sdmmc: enable F3 err:%d\n",
881 sdio_release_host(sd
->func
[3]);
884 } else if (*byte
& SDIO_FUNC_DISABLE_3
) {
885 sdio_claim_host(sd
->func
[3]);
887 /* Disable Function 3 */
888 sd_info(("bcmsdh_sdmmc F3: disable F3 fn %p\n",
890 err_ret
= sdio_disable_func(sd
->func
[3]);
892 sd_err(("bcmsdh_sdmmc: Disable F3 err:%d\n",
895 sdio_release_host(sd
->func
[3]);
901 #endif /* defined (BT_OVER_SDIO) */
903 sdio_claim_host(sd
->func
[2]);
904 if (*byte
& SDIO_FUNC_ENABLE_2
) {
905 /* Enable Function 2 */
906 err_ret
= sdio_enable_func(sd
->func
[2]);
908 sd_err(("bcmsdh_sdmmc: enable F2 failed:%d\n",
912 /* Disable Function 2 */
913 err_ret
= sdio_disable_func(sd
->func
[2]);
915 sd_err(("bcmsdh_sdmmc: Disab F2 failed:%d\n",
919 sdio_release_host(sd
->func
[2]);
921 #if defined(BT_OVER_SDIO)
923 #endif /* defined (BT_OVER_SDIO) */
925 #if defined(MMC_SDIO_ABORT)
926 /* to allow abort command through F1 */
927 else if (regaddr
== SDIOD_CCCR_IOABORT
) {
928 while (sdio_abort_retry
--) {
929 if (sd
->func
[func
]) {
930 sdio_claim_host(sd
->func
[func
]);
932 * this sdio_f0_writeb() can be replaced with
933 * another api depending upon MMC driver change.
934 * As of this time, this is temporaray one
936 sdio_writeb(sd
->func
[func
],
937 *byte
, regaddr
, &err_ret
);
938 sdio_release_host(sd
->func
[func
]);
944 #endif /* MMC_SDIO_ABORT */
945 else if (regaddr
< 0xF0) {
946 sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr
));
948 /* Claim host controller, perform F0 write, and release */
949 if (sd
->func
[func
]) {
950 sdio_claim_host(sd
->func
[func
]);
951 sdio_f0_writeb(sd
->func
[func
],
952 *byte
, regaddr
, &err_ret
);
953 sdio_release_host(sd
->func
[func
]);
957 /* Claim host controller, perform Fn write, and release */
958 if (sd
->func
[func
]) {
959 sdio_claim_host(sd
->func
[func
]);
960 sdio_writeb(sd
->func
[func
], *byte
, regaddr
, &err_ret
);
961 sdio_release_host(sd
->func
[func
]);
964 } else { /* CMD52 Read */
965 /* Claim host controller, perform Fn read, and release */
966 if (sd
->func
[func
]) {
967 sdio_claim_host(sd
->func
[func
]);
969 *byte
= sdio_f0_readb(sd
->func
[func
], regaddr
, &err_ret
);
971 *byte
= sdio_readb(sd
->func
[func
], regaddr
, &err_ret
);
973 sdio_release_host(sd
->func
[func
]);
978 if ((regaddr
== 0x1001F) && ((err_ret
== -ETIMEDOUT
) || (err_ret
== -EILSEQ
)
979 || (err_ret
== -EIO
))) {
981 sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
982 rw
? "Write" : "Read", func
, regaddr
, *byte
, err_ret
));
986 if (sd_msglevel
& SDH_COST_VAL
) {
987 getnstimeofday(&now
);
988 sd_cost(("%s: rw=%d len=1 cost=%lds %luus\n", __FUNCTION__
,
989 rw
, now
.tv_sec
-before
.tv_sec
, now
.tv_nsec
/1000-before
.tv_nsec
/1000));
992 return ((err_ret
== 0) ? SDIOH_API_RC_SUCCESS
: SDIOH_API_RC_FAIL
);
996 sdioh_set_mode(sdioh_info_t
*sd
, uint mode
)
998 if (mode
== SDPCM_TXGLOM_CPY
)
999 sd
->txglom_mode
= mode
;
1000 else if (mode
== SDPCM_TXGLOM_MDESC
)
1001 sd
->txglom_mode
= mode
;
1003 return (sd
->txglom_mode
);
1007 sdioh_request_word(sdioh_info_t
*sd
, uint cmd_type
, uint rw
, uint func
, uint addr
,
1008 uint32
*word
, uint nbytes
)
1010 int err_ret
= SDIOH_API_RC_FAIL
;
1011 int err_ret2
= SDIOH_API_RC_SUCCESS
; // terence 20130621: prevent dhd_dpc in dead lock
1012 #if defined(MMC_SDIO_ABORT)
1013 int sdio_abort_retry
= MMC_SDIO_ABORT_RETRY_LIMIT
;
1015 struct timespec now
, before
;
1017 if (sd_msglevel
& SDH_COST_VAL
)
1018 getnstimeofday(&before
);
1021 sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__
));
1022 return SDIOH_API_RC_FAIL
;
1025 sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
1026 __FUNCTION__
, cmd_type
, rw
, func
, addr
, nbytes
));
1028 DHD_PM_RESUME_WAIT(sdioh_request_word_wait
);
1029 DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL
);
1030 /* Claim host controller */
1031 sdio_claim_host(sd
->func
[func
]);
1033 if(rw
) { /* CMD52 Write */
1035 sdio_writel(sd
->func
[func
], *word
, addr
, &err_ret
);
1036 } else if (nbytes
== 2) {
1037 sdio_writew(sd
->func
[func
], (*word
& 0xFFFF), addr
, &err_ret
);
1039 sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__
, nbytes
));
1041 } else { /* CMD52 Read */
1043 *word
= sdio_readl(sd
->func
[func
], addr
, &err_ret
);
1044 } else if (nbytes
== 2) {
1045 *word
= sdio_readw(sd
->func
[func
], addr
, &err_ret
) & 0xFFFF;
1047 sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__
, nbytes
));
1051 /* Release host controller */
1052 sdio_release_host(sd
->func
[func
]);
1055 #if defined(MMC_SDIO_ABORT)
1056 /* Any error on CMD53 transaction should abort that function using function 0. */
1057 while (sdio_abort_retry
--) {
1059 sdio_claim_host(sd
->func
[0]);
1061 * this sdio_f0_writeb() can be replaced with another api
1062 * depending upon MMC driver change.
1063 * As of this time, this is temporaray one
1065 sdio_writeb(sd
->func
[0],
1066 func
, SDIOD_CCCR_IOABORT
, &err_ret2
);
1067 sdio_release_host(sd
->func
[0]);
1073 #endif /* MMC_SDIO_ABORT */
1075 sd_err(("bcmsdh_sdmmc: Failed to %s word F%d:@0x%05x=%02x, Err: 0x%08x\n",
1076 rw
? "Write" : "Read", func
, addr
, *word
, err_ret
));
1080 if (sd_msglevel
& SDH_COST_VAL
) {
1081 getnstimeofday(&now
);
1082 sd_cost(("%s: rw=%d, len=%d cost=%lds %luus\n", __FUNCTION__
,
1083 rw
, nbytes
, now
.tv_sec
-before
.tv_sec
, now
.tv_nsec
/1000 - before
.tv_nsec
/1000));
1086 return (((err_ret
== 0)&&(err_ret2
== 0)) ? SDIOH_API_RC_SUCCESS
: SDIOH_API_RC_FAIL
);
1089 #ifdef BCMSDIOH_TXGLOM
1091 sdioh_request_packet_chain(sdioh_info_t
*sd
, uint fix_inc
, uint write
, uint func
,
1092 uint addr
, void *pkt
)
1094 bool fifo
= (fix_inc
== SDIOH_DATA_FIX
);
1097 uint ttl_len
, pkt_offset
;
1102 struct mmc_request mmc_req
;
1103 struct mmc_command mmc_cmd
;
1104 struct mmc_data mmc_dat
;
1106 struct sdio_func
*sdio_func
= sd
->func
[func
];
1107 struct mmc_host
*host
= sdio_func
->card
->host
;
1108 uint8
*localbuf
= NULL
;
1109 uint local_plen
= 0;
1111 struct timespec now
, before
;
1113 sd_trace(("%s: Enter\n", __FUNCTION__
));
1115 DHD_PM_RESUME_WAIT(sdioh_request_packet_wait
);
1116 DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL
);
1118 if (sd_msglevel
& SDH_COST_VAL
)
1119 getnstimeofday(&before
);
1121 blk_size
= sd
->client_block_size
[func
];
1122 max_blk_count
= min(host
->max_blk_count
, (uint
)MAX_IO_RW_EXTENDED_BLK
);
1123 max_req_size
= min(max_blk_count
* blk_size
, host
->max_req_size
);
1130 if(sd
->txglom_mode
== SDPCM_TXGLOM_MDESC
) {
1131 while (pnext
!= NULL
) {
1134 memset(&mmc_req
, 0, sizeof(struct mmc_request
));
1135 memset(&mmc_cmd
, 0, sizeof(struct mmc_command
));
1136 memset(&mmc_dat
, 0, sizeof(struct mmc_data
));
1137 sg_init_table(sd
->sg_list
, ARRAYSIZE(sd
->sg_list
));
1139 /* Set up scatter-gather DMA descriptors. this loop is to find out the max
1140 * data we can transfer with one command 53. blocks per command is limited by
1141 * host max_req_size and 9-bit max block number. when the total length of this
1142 * packet chain is bigger than max_req_size, use multiple SD_IO_RW_EXTENDED
1143 * commands (each transfer is still block aligned)
1145 while (pnext
!= NULL
&& ttl_len
< max_req_size
) {
1148 uint8
*pdata
= (uint8
*)PKTDATA(sd
->osh
, pnext
);
1150 ASSERT(pdata
!= NULL
);
1151 pkt_len
= PKTLEN(sd
->osh
, pnext
);
1152 sd_trace(("%s[%d] data=%p, len=%d\n", __FUNCTION__
, write
, pdata
, pkt_len
));
1153 /* sg_count is unlikely larger than the array size, and this is
1154 * NOT something we can handle here, but in case it happens, PLEASE put
1155 * a restriction on max tx/glom count (based on host->max_segs).
1157 if (sg_count
>= ARRAYSIZE(sd
->sg_list
)) {
1158 sd_err(("%s: sg list entries exceed limit %d\n", __FUNCTION__
, sg_count
));
1159 return (SDIOH_API_RC_FAIL
);
1161 pdata
+= pkt_offset
;
1163 sg_data_size
= pkt_len
- pkt_offset
;
1164 if (sg_data_size
> max_req_size
- ttl_len
)
1165 sg_data_size
= max_req_size
- ttl_len
;
1166 /* some platforms put a restriction on the data size of each scatter-gather
1167 * DMA descriptor, use multiple sg buffers when xfer_size is bigger than
1170 if (sg_data_size
> host
->max_seg_size
)
1171 sg_data_size
= host
->max_seg_size
;
1172 sg_set_buf(&sd
->sg_list
[sg_count
++], pdata
, sg_data_size
);
1174 ttl_len
+= sg_data_size
;
1175 pkt_offset
+= sg_data_size
;
1176 if (pkt_offset
== pkt_len
) {
1177 pnext
= PKTNEXT(sd
->osh
, pnext
);
1182 if (ttl_len
% blk_size
!= 0) {
1183 sd_err(("%s, data length %d not aligned to block size %d\n",
1184 __FUNCTION__
, ttl_len
, blk_size
));
1185 return SDIOH_API_RC_FAIL
;
1187 blk_num
= ttl_len
/ blk_size
;
1188 mmc_dat
.sg
= sd
->sg_list
;
1189 mmc_dat
.sg_len
= sg_count
;
1190 mmc_dat
.blksz
= blk_size
;
1191 mmc_dat
.blocks
= blk_num
;
1192 mmc_dat
.flags
= write
? MMC_DATA_WRITE
: MMC_DATA_READ
;
1193 mmc_cmd
.opcode
= 53; /* SD_IO_RW_EXTENDED */
1194 mmc_cmd
.arg
= write
? 1<<31 : 0;
1195 mmc_cmd
.arg
|= (func
& 0x7) << 28;
1196 mmc_cmd
.arg
|= 1<<27;
1197 mmc_cmd
.arg
|= fifo
? 0 : 1<<26;
1198 mmc_cmd
.arg
|= (addr
& 0x1FFFF) << 9;
1199 mmc_cmd
.arg
|= blk_num
& 0x1FF;
1200 mmc_cmd
.flags
= MMC_RSP_SPI_R5
| MMC_RSP_R5
| MMC_CMD_ADTC
;
1201 mmc_req
.cmd
= &mmc_cmd
;
1202 mmc_req
.data
= &mmc_dat
;
1206 sdio_claim_host(sdio_func
);
1207 mmc_set_data_timeout(&mmc_dat
, sdio_func
->card
);
1208 mmc_wait_for_req(host
, &mmc_req
);
1209 sdio_release_host(sdio_func
);
1211 err_ret
= mmc_cmd
.error
? mmc_cmd
.error
: mmc_dat
.error
;
1213 sd_err(("%s:CMD53 %s failed with code %d\n",
1214 __FUNCTION__
, write
? "write" : "read", err_ret
));
1215 return SDIOH_API_RC_FAIL
;
1218 } else if(sd
->txglom_mode
== SDPCM_TXGLOM_CPY
) {
1219 for (pnext
= pkt
; pnext
; pnext
= PKTNEXT(sd
->osh
, pnext
)) {
1220 ttl_len
+= PKTLEN(sd
->osh
, pnext
);
1222 /* Claim host controller */
1223 sdio_claim_host(sd
->func
[func
]);
1224 for (pnext
= pkt
; pnext
; pnext
= PKTNEXT(sd
->osh
, pnext
)) {
1225 uint8
*buf
= (uint8
*)PKTDATA(sd
->osh
, pnext
);
1226 pkt_len
= PKTLEN(sd
->osh
, pnext
);
1229 localbuf
= (uint8
*)MALLOC(sd
->osh
, ttl_len
);
1230 if (localbuf
== NULL
) {
1231 sd_err(("%s: %s TXGLOM: localbuf malloc FAILED\n",
1232 __FUNCTION__
, (write
) ? "TX" : "RX"));
1237 bcopy(buf
, (localbuf
+ local_plen
), pkt_len
);
1238 local_plen
+= pkt_len
;
1239 if (PKTNEXT(sd
->osh
, pnext
))
1243 pkt_len
= local_plen
;
1246 if (!write
|| pkt_len
< 32)
1247 pkt_len
= (pkt_len
+ 3) & 0xFFFFFFFC;
1248 else if (pkt_len
% blk_size
)
1249 pkt_len
+= blk_size
- (pkt_len
% blk_size
);
1251 if ((write
) && (!fifo
))
1252 err_ret
= sdio_memcpy_toio(
1254 addr
, buf
, pkt_len
);
1256 err_ret
= sdio_memcpy_toio(
1258 addr
, buf
, pkt_len
);
1260 err_ret
= sdio_readsb(
1262 buf
, addr
, pkt_len
);
1264 err_ret
= sdio_memcpy_fromio(
1266 buf
, addr
, pkt_len
);
1269 sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=%d\n",
1271 (write
) ? "TX" : "RX",
1272 pnext
, sg_count
, addr
, pkt_len
, err_ret
));
1274 sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n",
1276 (write
) ? "TX" : "RX",
1277 pnext
, sg_count
, addr
, pkt_len
));
1283 sdio_release_host(sd
->func
[func
]);
1285 sd_err(("%s: set to wrong glom mode %d\n", __FUNCTION__
, sd
->txglom_mode
));
1286 return SDIOH_API_RC_FAIL
;
1290 MFREE(sd
->osh
, localbuf
, ttl_len
);
1292 if (sd_msglevel
& SDH_COST_VAL
) {
1293 getnstimeofday(&now
);
1294 sd_cost(("%s: rw=%d, ttl_len=%d, cost=%lds %luus\n", __FUNCTION__
,
1295 write
, ttl_len
, now
.tv_sec
-before
.tv_sec
, now
.tv_nsec
/1000-before
.tv_nsec
/1000));
1298 sd_trace(("%s: Exit\n", __FUNCTION__
));
1299 return SDIOH_API_RC_SUCCESS
;
1301 #endif /* BCMSDIOH_TXGLOM */
1304 sdioh_buffer_tofrom_bus(sdioh_info_t
*sd
, uint fix_inc
, uint write
, uint func
,
1305 uint addr
, uint8
*buf
, uint len
)
1307 bool fifo
= (fix_inc
== SDIOH_DATA_FIX
);
1309 struct timespec now
, before
;
1311 sd_trace(("%s: Enter\n", __FUNCTION__
));
1314 if (sd_msglevel
& SDH_COST_VAL
)
1315 getnstimeofday(&before
);
1318 * For all writes, each packet length is aligned to 32 (or 4)
1319 * bytes in dhdsdio_txpkt_preprocess, and for glom the last packet length
1320 * is aligned to block boundary. If you want to align each packet to
1321 * a custom size, please do it in dhdsdio_txpkt_preprocess, NOT here
1323 * For reads, the alignment is doen in sdioh_request_buffer.
1326 sdio_claim_host(sd
->func
[func
]);
1328 if ((write
) && (!fifo
))
1329 err_ret
= sdio_memcpy_toio(sd
->func
[func
], addr
, buf
, len
);
1331 err_ret
= sdio_memcpy_toio(sd
->func
[func
], addr
, buf
, len
);
1333 err_ret
= sdio_readsb(sd
->func
[func
], buf
, addr
, len
);
1335 err_ret
= sdio_memcpy_fromio(sd
->func
[func
], buf
, addr
, len
);
1337 sdio_release_host(sd
->func
[func
]);
1340 sd_err(("%s: %s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=%d\n", __FUNCTION__
,
1341 (write
) ? "TX" : "RX", buf
, addr
, len
, err_ret
));
1343 sd_trace(("%s: %s xfr'd %p, addr=0x%05x, len=%d\n", __FUNCTION__
,
1344 (write
) ? "TX" : "RX", buf
, addr
, len
));
1346 sd_trace(("%s: Exit\n", __FUNCTION__
));
1348 if (sd_msglevel
& SDH_COST_VAL
) {
1349 getnstimeofday(&now
);
1350 sd_cost(("%s: rw=%d, len=%d cost=%lds %luus\n", __FUNCTION__
,
1351 write
, len
, now
.tv_sec
-before
.tv_sec
, now
.tv_nsec
/1000 - before
.tv_nsec
/1000));
1354 return ((err_ret
== 0) ? SDIOH_API_RC_SUCCESS
: SDIOH_API_RC_FAIL
);
1359 * This function takes a buffer or packet, and fixes everything up so that in the
1360 * end, a DMA-able packet is created.
1362 * A buffer does not have an associated packet pointer, and may or may not be aligned.
1363 * A packet may consist of a single packet, or a packet chain. If it is a packet chain,
1364 * then all the packets in the chain must be properly aligned. If the packet data is not
1365 * aligned, then there may only be one packet, and in this case, it is copied to a new
1370 sdioh_request_buffer(sdioh_info_t
*sd
, uint pio_dma
, uint fix_inc
, uint write
, uint func
,
1371 uint addr
, uint reg_width
, uint buf_len
, uint8
*buffer
, void *pkt
)
1373 SDIOH_API_RC status
;
1375 struct timespec now
, before
;
1377 sd_trace(("%s: Enter\n", __FUNCTION__
));
1378 DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait
);
1379 DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL
);
1381 if (sd_msglevel
& SDH_COST_VAL
)
1382 getnstimeofday(&before
);
1385 #ifdef BCMSDIOH_TXGLOM
1386 /* packet chain, only used for tx/rx glom, all packets length
1387 * are aligned, total length is a block multiple
1389 if (PKTNEXT(sd
->osh
, pkt
))
1390 return sdioh_request_packet_chain(sd
, fix_inc
, write
, func
, addr
, pkt
);
1391 #endif /* BCMSDIOH_TXGLOM */
1392 /* non-glom mode, ignore the buffer parameter and use the packet pointer
1393 * (this shouldn't happen)
1395 buffer
= PKTDATA(sd
->osh
, pkt
);
1396 buf_len
= PKTLEN(sd
->osh
, pkt
);
1401 /* buffer and length are aligned, use it directly so we can avoid memory copy */
1402 if (((ulong
)buffer
& DMA_ALIGN_MASK
) == 0 && (buf_len
& DMA_ALIGN_MASK
) == 0)
1403 return sdioh_buffer_tofrom_bus(sd
, fix_inc
, write
, func
, addr
, buffer
, buf_len
);
1405 sd_trace(("%s: [%d] doing memory copy buf=%p, len=%d\n",
1406 __FUNCTION__
, write
, buffer
, buf_len
));
1408 /* otherwise, a memory copy is needed as the input buffer is not aligned */
1409 tmppkt
= PKTGET_STATIC(sd
->osh
, buf_len
+ DEFAULT_SDIO_F2_BLKSIZE
, write
? TRUE
: FALSE
);
1410 if (tmppkt
== NULL
) {
1411 sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__
, buf_len
));
1412 return SDIOH_API_RC_FAIL
;
1416 bcopy(buffer
, PKTDATA(sd
->osh
, tmppkt
), buf_len
);
1418 status
= sdioh_buffer_tofrom_bus(sd
, fix_inc
, write
, func
, addr
,
1419 PKTDATA(sd
->osh
, tmppkt
), ROUNDUP(buf_len
, (DMA_ALIGN_MASK
+1)));
1422 bcopy(PKTDATA(sd
->osh
, tmppkt
), buffer
, buf_len
);
1424 PKTFREE_STATIC(sd
->osh
, tmppkt
, write
? TRUE
: FALSE
);
1426 if (sd_msglevel
& SDH_COST_VAL
) {
1427 getnstimeofday(&now
);
1428 sd_cost(("%s: len=%d cost=%lds %luus\n", __FUNCTION__
,
1429 buf_len
, now
.tv_sec
-before
.tv_sec
, now
.tv_nsec
/1000 - before
.tv_nsec
/1000));
1435 /* this function performs "abort" for both of host & device */
1437 sdioh_abort(sdioh_info_t
*sd
, uint func
)
1439 #if defined(MMC_SDIO_ABORT)
1440 char t_func
= (char) func
;
1441 #endif /* defined(MMC_SDIO_ABORT) */
1442 sd_trace(("%s: Enter\n", __FUNCTION__
));
1444 #if defined(MMC_SDIO_ABORT)
1445 /* issue abort cmd52 command through F1 */
1446 sdioh_request_byte(sd
, SD_IO_OP_WRITE
, SDIO_FUNC_0
, SDIOD_CCCR_IOABORT
, &t_func
);
1447 #endif /* defined(MMC_SDIO_ABORT) */
1449 sd_trace(("%s: Exit\n", __FUNCTION__
));
1450 return SDIOH_API_RC_SUCCESS
;
1453 /* Reset and re-initialize the device */
1454 int sdioh_sdio_reset(sdioh_info_t
*si
)
1456 sd_trace(("%s: Enter\n", __FUNCTION__
));
1457 sd_trace(("%s: Exit\n", __FUNCTION__
));
1458 return SDIOH_API_RC_SUCCESS
;
1461 /* Disable device interrupt */
1463 sdioh_sdmmc_devintr_off(sdioh_info_t
*sd
)
1465 sd_trace(("%s: %d\n", __FUNCTION__
, sd
->use_client_ints
));
1466 sd
->intmask
&= ~CLIENT_INTR
;
1469 /* Enable device interrupt */
1471 sdioh_sdmmc_devintr_on(sdioh_info_t
*sd
)
1473 sd_trace(("%s: %d\n", __FUNCTION__
, sd
->use_client_ints
));
1474 sd
->intmask
|= CLIENT_INTR
;
1477 /* Read client card reg */
1479 sdioh_sdmmc_card_regread(sdioh_info_t
*sd
, int func
, uint32 regaddr
, int regsize
, uint32
*data
)
1482 if ((func
== 0) || (regsize
== 1)) {
1485 sdioh_request_byte(sd
, SDIOH_READ
, func
, regaddr
, &temp
);
1488 sd_data(("%s: byte read data=0x%02x\n",
1489 __FUNCTION__
, *data
));
1491 if (sdioh_request_word(sd
, 0, SDIOH_READ
, func
, regaddr
, data
, regsize
)) {
1492 return BCME_SDIO_ERROR
;
1498 sd_data(("%s: word read data=0x%08x\n",
1499 __FUNCTION__
, *data
));
1505 #if !defined(OOB_INTR_ONLY)
1506 /* bcmsdh_sdmmc interrupt handler */
1507 static void IRQHandler(struct sdio_func
*func
)
1511 sd
= sdio_get_drvdata(func
);
1514 sdio_release_host(sd
->func
[0]);
1516 if (sd
->use_client_ints
) {
1518 ASSERT(sd
->intr_handler
);
1519 ASSERT(sd
->intr_handler_arg
);
1520 (sd
->intr_handler
)(sd
->intr_handler_arg
);
1522 sd_err(("bcmsdh_sdmmc: ***IRQHandler\n"));
1524 sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
1525 __FUNCTION__
, sd
->client_intr_enabled
, sd
->intr_handler
));
1528 sdio_claim_host(sd
->func
[0]);
1531 /* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */
1532 static void IRQHandlerF2(struct sdio_func
*func
)
1534 sd_trace(("bcmsdh_sdmmc: ***IRQHandlerF2\n"));
1536 #endif /* !defined(OOB_INTR_ONLY) */
1539 /* Write client card reg */
1541 sdioh_sdmmc_card_regwrite(sdioh_info_t
*sd
, int func
, uint32 regaddr
, int regsize
, uint32 data
)
1544 if ((func
== 0) || (regsize
== 1)) {
1548 sdioh_request_byte(sd
, SDIOH_READ
, func
, regaddr
, &temp
);
1549 sd_data(("%s: byte write data=0x%02x\n",
1550 __FUNCTION__
, data
));
1555 sdioh_request_word(sd
, 0, SDIOH_READ
, func
, regaddr
, &data
, regsize
);
1557 sd_data(("%s: word write data=0x%08x\n",
1558 __FUNCTION__
, data
));
1563 #endif /* NOTUSED */
1566 sdioh_start(sdioh_info_t
*sd
, int stage
)
1571 sd_err(("%s Failed, sd is NULL\n", __FUNCTION__
));
1575 /* Need to do this stages as we can't enable the interrupt till
1576 downloading of the firmware is complete, other wise polling
1577 sdio access will come in way
1581 /* Since the power to the chip is killed, we will have
1582 re enumerate the device again. Set the block size
1583 and enable the fucntion 1 for in preparation for
1584 downloading the code
1586 /* sdio_reset_comm() - has been fixed in latest kernel/msm.git for Linux
1587 2.6.27. The implementation prior to that is buggy, and needs broadcom's
1590 if ((ret
= sdio_reset_comm(sd
->func
[0]->card
))) {
1591 sd_err(("%s Failed, error = %d\n", __FUNCTION__
, ret
));
1596 sd
->sd_blockmode
= TRUE
;
1597 sd
->use_client_ints
= TRUE
;
1598 sd
->client_block_size
[0] = 64;
1601 /* Claim host controller */
1602 sdio_claim_host(sd
->func
[1]);
1604 sd
->client_block_size
[1] = 64;
1605 ret
= sdio_set_block_size(sd
->func
[1], 64);
1607 sd_err(("bcmsdh_sdmmc: Failed to set F1 "
1608 "blocksize(%d)\n", ret
));
1611 /* Release host controller F1 */
1612 sdio_release_host(sd
->func
[1]);
1616 /* Claim host controller F2 */
1617 sdio_claim_host(sd
->func
[2]);
1619 sd
->client_block_size
[2] = sd_f2_blocksize
;
1620 printf("%s: set sd_f2_blocksize %d\n", __FUNCTION__
, sd_f2_blocksize
);
1621 ret
= sdio_set_block_size(sd
->func
[2], sd_f2_blocksize
);
1623 sd_err(("bcmsdh_sdmmc: Failed to set F2 "
1624 "blocksize to %d(%d)\n", sd_f2_blocksize
, ret
));
1627 /* Release host controller F2 */
1628 sdio_release_host(sd
->func
[2]);
1631 sdioh_sdmmc_card_enablefuncs(sd
);
1634 #if !defined(OOB_INTR_ONLY)
1635 sdio_claim_host(sd
->func
[0]);
1637 sdio_claim_irq(sd
->func
[2], IRQHandlerF2
);
1639 sdio_claim_irq(sd
->func
[1], IRQHandler
);
1640 sdio_release_host(sd
->func
[0]);
1641 #else /* defined(OOB_INTR_ONLY) */
1643 sdioh_enable_func_intr(sd
);
1645 bcmsdh_oob_intr_set(sd
->bcmsdh
, TRUE
);
1646 #endif /* !defined(OOB_INTR_ONLY) */
1650 sd_err(("%s Failed\n", __FUNCTION__
));
1656 sdioh_stop(sdioh_info_t
*sd
)
1658 /* MSM7201A Android sdio stack has bug with interrupt
1659 So internaly within SDIO stack they are polling
1660 which cause issue when device is turned off. So
1661 unregister interrupt with SDIO stack to stop the
1665 #if !defined(OOB_INTR_ONLY)
1666 sdio_claim_host(sd
->func
[0]);
1668 sdio_release_irq(sd
->func
[1]);
1670 sdio_release_irq(sd
->func
[2]);
1671 sdio_release_host(sd
->func
[0]);
1672 #else /* defined(OOB_INTR_ONLY) */
1674 sdioh_disable_func_intr(sd
);
1676 bcmsdh_oob_intr_set(sd
->bcmsdh
, FALSE
);
1677 #endif /* !defined(OOB_INTR_ONLY) */
1680 sd_err(("%s Failed\n", __FUNCTION__
));
1685 sdioh_waitlockfree(sdioh_info_t
*sd
)
1692 sdioh_gpioouten(sdioh_info_t
*sd
, uint32 gpio
)
1694 return SDIOH_API_RC_FAIL
;
1698 sdioh_gpioout(sdioh_info_t
*sd
, uint32 gpio
, bool enab
)
1700 return SDIOH_API_RC_FAIL
;
1704 sdioh_gpioin(sdioh_info_t
*sd
, uint32 gpio
)
1710 sdioh_gpio_init(sdioh_info_t
*sd
)
1712 return SDIOH_API_RC_FAIL
;
1716 sdmmc_get_clock_rate(sdioh_info_t
*sd
)
1718 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
1721 struct sdio_func
*sdio_func
= sd
->func
[0];
1722 struct mmc_host
*host
= sdio_func
->card
->host
;
1723 return mmc_host_clk_rate(host
);
1729 sdmmc_set_clock_rate(sdioh_info_t
*sd
, uint hz
)
1731 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
1734 struct sdio_func
*sdio_func
= sd
->func
[0];
1735 struct mmc_host
*host
= sdio_func
->card
->host
;
1736 struct mmc_ios
*ios
= &host
->ios
;
1738 mmc_host_clk_hold(host
);
1739 DHD_INFO(("%s: Before change: sd clock rate is %u\n", __FUNCTION__
, ios
->clock
));
1740 if (hz
< host
->f_min
) {
1741 DHD_ERROR(("%s: Intended rate is below min rate, setting to min\n", __FUNCTION__
));
1745 if (hz
> host
->f_max
) {
1746 DHD_ERROR(("%s: Intended rate exceeds max rate, setting to max\n", __FUNCTION__
));
1750 host
->ops
->set_ios(host
, ios
);
1751 DHD_ERROR(("%s: After change: sd clock rate is %u\n", __FUNCTION__
, ios
->clock
));
1752 mmc_host_clk_release(host
);
1757 sdmmc_set_clock_divisor(sdioh_info_t
*sd
, uint sd_div
)
1760 uint old_div
= sdmmc_get_clock_rate(sd
);
1761 if (old_div
== sd_div
) {
1765 hz
= sd
->sd_clk_rate
/ sd_div
;
1766 sdmmc_set_clock_rate(sd
, hz
);