2 * Copyright (c) 2010 Broadcom Corporation
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.
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.
16 #include <linux/types.h>
17 #include <linux/netdevice.h>
18 #include <linux/mmc/sdio.h>
19 #include <linux/mmc/core.h>
20 #include <linux/mmc/sdio_func.h>
21 #include <linux/mmc/sdio_ids.h>
22 #include <linux/suspend.h>
25 #include <brcm_hw_ids.h>
26 #include <brcmu_utils.h>
27 #include <brcmu_wifi.h>
28 #include "sdio_host.h"
29 #include "bcmsdbus.h" /* bcmsdh to/from specific controller APIs */
30 #include "sdiovar.h" /* ioctl/iovars */
31 #include "dngl_stats.h"
33 #include "bcmsdh_sdmmc.h"
35 extern int brcmf_sdio_function_init(void);
36 extern void brcmf_sdio_function_cleanup(void);
38 static void brcmf_sdioh_irqhandler(struct sdio_func *func);
39 static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func);
40 static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr);
41 extern int brcmf_sdioh_reset_comm(struct mmc_card *card);
43 uint sd_f2_blocksize = 512; /* Default blocksize */
45 uint sd_msglevel = 0x01;
46 DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
47 DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
48 DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
49 DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
51 #define DMA_ALIGN_MASK 0x03
53 int brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
54 int regsize, u32 *data);
56 static int brcmf_sdioh_enablefuncs(struct sdioh_info *sd)
62 sd_trace(("%s\n", __func__));
64 /* Get the Card's common CIS address */
65 sd->com_cis_ptr = brcmf_sdioh_get_cisaddr(sd, SDIO_CCCR_CIS);
66 sd->func_cis_ptr[0] = sd->com_cis_ptr;
67 sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
70 /* Get the Card's function CIS (for each function) */
71 for (fbraddr = SDIO_FBR_BASE(1), func = 1;
72 func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
73 sd->func_cis_ptr[func] =
74 brcmf_sdioh_get_cisaddr(sd, SDIO_FBR_CIS + fbraddr);
75 sd_info(("%s: Function %d CIS Ptr = 0x%x\n", __func__, func,
76 sd->func_cis_ptr[func]));
79 sd->func_cis_ptr[0] = sd->com_cis_ptr;
80 sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
83 /* Enable Function 1 */
84 sdio_claim_host(gInstance->func[1]);
85 err_ret = sdio_enable_func(gInstance->func[1]);
86 sdio_release_host(gInstance->func[1]);
88 sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x",
96 * Public entry points & extern's
98 struct sdioh_info *brcmf_sdioh_attach(void *bar0, uint irq)
100 struct sdioh_info *sd;
103 sd_trace(("%s\n", __func__));
105 if (gInstance == NULL) {
106 sd_err(("%s: SDIO Device not present\n", __func__));
110 sd = kzalloc(sizeof(struct sdioh_info), GFP_ATOMIC);
112 sd_err(("sdioh_attach: out of memory\n"));
115 if (brcmf_sdioh_osinit(sd) != 0) {
116 sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__));
122 sd->use_client_ints = true;
123 sd->client_block_size[0] = 64;
127 /* Claim host controller */
128 sdio_claim_host(gInstance->func[1]);
130 sd->client_block_size[1] = 64;
131 err_ret = sdio_set_block_size(gInstance->func[1], 64);
133 sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n"));
135 /* Release host controller F1 */
136 sdio_release_host(gInstance->func[1]);
138 if (gInstance->func[2]) {
139 /* Claim host controller F2 */
140 sdio_claim_host(gInstance->func[2]);
142 sd->client_block_size[2] = sd_f2_blocksize;
144 sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
146 sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize "
147 "to %d\n", sd_f2_blocksize));
149 /* Release host controller F2 */
150 sdio_release_host(gInstance->func[2]);
153 brcmf_sdioh_enablefuncs(sd);
155 sd_trace(("%s: Done\n", __func__));
159 extern int brcmf_sdioh_detach(struct sdioh_info *sd)
161 sd_trace(("%s\n", __func__));
165 /* Disable Function 2 */
166 sdio_claim_host(gInstance->func[2]);
167 sdio_disable_func(gInstance->func[2]);
168 sdio_release_host(gInstance->func[2]);
170 /* Disable Function 1 */
171 sdio_claim_host(gInstance->func[1]);
172 sdio_disable_func(gInstance->func[1]);
173 sdio_release_host(gInstance->func[1]);
176 brcmf_sdioh_osfree(sd);
180 return SDIOH_API_RC_SUCCESS;
183 /* Configure callback to client when we receive client interrupt */
185 brcmf_sdioh_interrupt_register(struct sdioh_info *sd, sdioh_cb_fn_t fn,
188 sd_trace(("%s: Entering\n", __func__));
190 sd_err(("%s: interrupt handler is NULL, not registering\n",
192 return SDIOH_API_RC_FAIL;
195 sd->intr_handler = fn;
196 sd->intr_handler_arg = argh;
197 sd->intr_handler_valid = true;
199 /* register and unmask irq */
200 if (gInstance->func[2]) {
201 sdio_claim_host(gInstance->func[2]);
202 sdio_claim_irq(gInstance->func[2], brcmf_sdioh_irqhandler_f2);
203 sdio_release_host(gInstance->func[2]);
206 if (gInstance->func[1]) {
207 sdio_claim_host(gInstance->func[1]);
208 sdio_claim_irq(gInstance->func[1], brcmf_sdioh_irqhandler);
209 sdio_release_host(gInstance->func[1]);
212 return SDIOH_API_RC_SUCCESS;
215 extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *sd)
217 sd_trace(("%s: Entering\n", __func__));
219 if (gInstance->func[1]) {
220 /* register and unmask irq */
221 sdio_claim_host(gInstance->func[1]);
222 sdio_release_irq(gInstance->func[1]);
223 sdio_release_host(gInstance->func[1]);
226 if (gInstance->func[2]) {
227 /* Claim host controller F2 */
228 sdio_claim_host(gInstance->func[2]);
229 sdio_release_irq(gInstance->func[2]);
230 /* Release host controller F2 */
231 sdio_release_host(gInstance->func[2]);
234 sd->intr_handler_valid = false;
235 sd->intr_handler = NULL;
236 sd->intr_handler_arg = NULL;
238 return SDIOH_API_RC_SUCCESS;
242 brcmf_sdioh_interrupt_query(struct sdioh_info *sd, bool *onoff)
244 sd_trace(("%s: Entering\n", __func__));
245 *onoff = sd->client_intr_enabled;
246 return SDIOH_API_RC_SUCCESS;
250 extern bool brcmf_sdioh_interrupt_pending(struct sdioh_info *sd)
256 uint brcmf_sdioh_query_iofnum(struct sdioh_info *sd)
258 return sd->num_funcs;
272 const struct brcmu_iovar sdioh_iovars[] = {
273 {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0},
274 {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0},/* ((fn << 16) |
276 {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0},
277 {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0},
278 {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
280 {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0}
286 brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name,
287 void *params, int plen, void *arg, int len, bool set)
289 const struct brcmu_iovar *vi = NULL;
299 /* Get must have return space; Set does not take qualifiers */
300 ASSERT(set || (arg && len));
301 ASSERT(!set || (!params && !plen));
303 sd_trace(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"),
306 vi = brcmu_iovar_lookup(sdioh_iovars, name);
308 bcmerror = -ENOTSUPP;
312 bcmerror = brcmu_iovar_lencheck(vi, arg, len, set);
316 /* Set up params so get and set can share the convenience variables */
317 if (params == NULL) {
322 if (vi->type == IOVT_VOID)
324 else if (vi->type == IOVT_BUFFER)
327 val_size = sizeof(int);
329 if (plen >= (int)sizeof(int_val))
330 memcpy(&int_val, params, sizeof(int_val));
332 bool_val = (int_val != 0) ? true : false;
334 actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
336 case IOV_GVAL(IOV_MSGLEVEL):
337 int_val = (s32) sd_msglevel;
338 memcpy(arg, &int_val, val_size);
341 case IOV_SVAL(IOV_MSGLEVEL):
342 sd_msglevel = int_val;
345 case IOV_GVAL(IOV_BLOCKSIZE):
346 if ((u32) int_val > si->num_funcs) {
350 int_val = (s32) si->client_block_size[int_val];
351 memcpy(arg, &int_val, val_size);
354 case IOV_SVAL(IOV_BLOCKSIZE):
356 uint func = ((u32) int_val >> 16);
357 uint blksize = (u16) int_val;
360 if (func > si->num_funcs) {
370 maxsize = BLOCK_SIZE_4318;
373 maxsize = BLOCK_SIZE_4328;
378 if (blksize > maxsize) {
386 si->client_block_size[func] = blksize;
391 case IOV_GVAL(IOV_RXCHAIN):
393 memcpy(arg, &int_val, val_size);
396 case IOV_GVAL(IOV_USEINTS):
397 int_val = (s32) si->use_client_ints;
398 memcpy(arg, &int_val, val_size);
401 case IOV_SVAL(IOV_USEINTS):
402 si->use_client_ints = (bool) int_val;
403 if (si->use_client_ints)
404 si->intmask |= CLIENT_INTR;
406 si->intmask &= ~CLIENT_INTR;
410 case IOV_GVAL(IOV_NUMINTS):
411 int_val = (s32) si->intrcount;
412 memcpy(arg, &int_val, val_size);
415 case IOV_GVAL(IOV_DEVREG):
417 struct brcmf_sdreg *sd_ptr =
418 (struct brcmf_sdreg *) params;
421 if (brcmf_sdioh_cfg_read
422 (si, sd_ptr->func, sd_ptr->offset, &data)) {
428 memcpy(arg, &int_val, sizeof(int_val));
432 case IOV_SVAL(IOV_DEVREG):
434 struct brcmf_sdreg *sd_ptr =
435 (struct brcmf_sdreg *) params;
436 u8 data = (u8) sd_ptr->value;
438 if (brcmf_sdioh_cfg_write
439 (si, sd_ptr->func, sd_ptr->offset, &data)) {
447 bcmerror = -ENOTSUPP;
456 brcmf_sdioh_cfg_read(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
459 /* No lock needed since brcmf_sdioh_request_byte does locking */
460 status = brcmf_sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
465 brcmf_sdioh_cfg_write(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
467 /* No lock needed since brcmf_sdioh_request_byte does locking */
469 status = brcmf_sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
473 static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr)
475 /* read 24 bits and return valid 17 bit addr */
477 u32 scratch, regdata;
478 u8 *ptr = (u8 *)&scratch;
479 for (i = 0; i < 3; i++) {
480 if ((brcmf_sdioh_card_regread(sd, 0, regaddr, 1, ®data)) !=
482 sd_err(("%s: Can't read!\n", __func__));
484 *ptr++ = (u8) regdata;
488 /* Only the lower 17-bits are valid */
489 scratch = le32_to_cpu(scratch);
490 scratch &= 0x0001FFFF;
495 brcmf_sdioh_cis_read(struct sdioh_info *sd, uint func, u8 *cisd, u32 length)
502 sd_trace(("%s: Func = %d\n", __func__, func));
504 if (!sd->func_cis_ptr[func]) {
505 memset(cis, 0, length);
506 sd_err(("%s: no func_cis_ptr[%d]\n", __func__, func));
507 return SDIOH_API_RC_FAIL;
510 sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __func__, func,
511 sd->func_cis_ptr[func]));
513 for (count = 0; count < length; count++) {
514 offset = sd->func_cis_ptr[func] + count;
515 if (brcmf_sdioh_card_regread(sd, 0, offset, 1, &foo) < 0) {
516 sd_err(("%s: regread failed: Can't read CIS\n",
518 return SDIOH_API_RC_FAIL;
521 *cis = (u8) (foo & 0xff);
525 return SDIOH_API_RC_SUCCESS;
529 brcmf_sdioh_request_byte(struct sdioh_info *sd, uint rw, uint func,
530 uint regaddr, u8 *byte)
534 sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __func__, rw, func,
537 DHD_PM_RESUME_WAIT(sdioh_request_byte_wait);
538 DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
539 if (rw) { /* CMD52 Write */
541 /* Can only directly write to some F0 registers.
545 if (regaddr == SDIO_CCCR_IOEx) {
546 if (gInstance->func[2]) {
547 sdio_claim_host(gInstance->func[2]);
548 if (*byte & SDIO_FUNC_ENABLE_2) {
549 /* Enable Function 2 */
552 (gInstance->func[2]);
554 sd_err(("bcmsdh_sdmmc: enable F2 failed:%d",
557 /* Disable Function 2 */
560 (gInstance->func[2]);
562 sd_err(("bcmsdh_sdmmc: Disab F2 failed:%d",
565 sdio_release_host(gInstance->func[2]);
568 /* to allow abort command through F1 */
569 else if (regaddr == SDIO_CCCR_ABORT) {
570 sdio_claim_host(gInstance->func[func]);
572 * this sdio_f0_writeb() can be replaced
574 * depending upon MMC driver change.
575 * As of this time, this is temporaray one
577 sdio_writeb(gInstance->func[func], *byte,
579 sdio_release_host(gInstance->func[func]);
581 else if (regaddr < 0xF0) {
582 sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write "
583 "disallowed\n", regaddr));
585 /* Claim host controller, perform F0 write,
587 sdio_claim_host(gInstance->func[func]);
588 sdio_f0_writeb(gInstance->func[func], *byte,
590 sdio_release_host(gInstance->func[func]);
593 /* Claim host controller, perform Fn write,
595 sdio_claim_host(gInstance->func[func]);
596 sdio_writeb(gInstance->func[func], *byte, regaddr,
598 sdio_release_host(gInstance->func[func]);
600 } else { /* CMD52 Read */
601 /* Claim host controller, perform Fn read, and release */
602 sdio_claim_host(gInstance->func[func]);
606 sdio_f0_readb(gInstance->func[func], regaddr,
610 sdio_readb(gInstance->func[func], regaddr,
614 sdio_release_host(gInstance->func[func]);
618 sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, "
619 "Err: %d\n", rw ? "Write" : "Read", func, regaddr,
622 return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
626 brcmf_sdioh_request_word(struct sdioh_info *sd, uint cmd_type, uint rw,
627 uint func, uint addr, u32 *word, uint nbytes)
629 int err_ret = SDIOH_API_RC_FAIL;
632 sd_err(("%s: Only CMD52 allowed to F0.\n", __func__));
633 return SDIOH_API_RC_FAIL;
636 sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
637 __func__, cmd_type, rw, func, addr, nbytes));
639 DHD_PM_RESUME_WAIT(sdioh_request_word_wait);
640 DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
641 /* Claim host controller */
642 sdio_claim_host(gInstance->func[func]);
644 if (rw) { /* CMD52 Write */
646 sdio_writel(gInstance->func[func], *word, addr,
648 } else if (nbytes == 2) {
649 sdio_writew(gInstance->func[func], (*word & 0xFFFF),
652 sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
654 } else { /* CMD52 Read */
657 sdio_readl(gInstance->func[func], addr, &err_ret);
658 } else if (nbytes == 2) {
660 sdio_readw(gInstance->func[func], addr,
663 sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
667 /* Release host controller */
668 sdio_release_host(gInstance->func[func]);
671 sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x",
672 rw ? "Write" : "Read", err_ret));
675 return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
679 brcmf_sdioh_request_packet(struct sdioh_info *sd, uint fix_inc, uint write,
680 uint func, uint addr, struct sk_buff *pkt)
682 bool fifo = (fix_inc == SDIOH_DATA_FIX);
686 struct sk_buff *pnext;
688 sd_trace(("%s: Enter\n", __func__));
691 DHD_PM_RESUME_WAIT(sdioh_request_packet_wait);
692 DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
694 /* Claim host controller */
695 sdio_claim_host(gInstance->func[func]);
696 for (pnext = pkt; pnext; pnext = pnext->next) {
697 uint pkt_len = pnext->len;
699 pkt_len &= 0xFFFFFFFC;
701 /* Make sure the packet is aligned properly.
702 * If it isn't, then this
703 * is the fault of brcmf_sdioh_request_buffer() which
704 * is supposed to give
705 * us something we can work with.
707 ASSERT(((u32) (pkt->data) & DMA_ALIGN_MASK) == 0);
709 if ((write) && (!fifo)) {
710 err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
711 ((u8 *) (pnext->data)),
714 err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
715 ((u8 *) (pnext->data)),
718 err_ret = sdio_readsb(gInstance->func[func],
719 ((u8 *) (pnext->data)),
722 err_ret = sdio_memcpy_fromio(gInstance->func[func],
723 ((u8 *) (pnext->data)),
728 sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d,"
729 "ERR=0x%08x\n", __func__,
730 (write) ? "TX" : "RX",
731 pnext, SGCount, addr, pkt_len, err_ret));
733 sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n",
735 (write) ? "TX" : "RX",
736 pnext, SGCount, addr, pkt_len));
745 /* Release host controller */
746 sdio_release_host(gInstance->func[func]);
748 sd_trace(("%s: Exit\n", __func__));
749 return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
753 * This function takes a buffer or packet, and fixes everything up
754 * so that in the end, a DMA-able packet is created.
756 * A buffer does not have an associated packet pointer,
757 * and may or may not be aligned.
758 * A packet may consist of a single packet, or a packet chain.
759 * If it is a packet chain, then all the packets in the chain
760 * must be properly aligned.
762 * If the packet data is not aligned, then there may only be
763 * one packet, and in this case, it is copied to a new
768 brcmf_sdioh_request_buffer(struct sdioh_info *sd, uint pio_dma, uint fix_inc,
769 uint write, uint func, uint addr, uint reg_width,
770 uint buflen_u, u8 *buffer, struct sk_buff *pkt)
773 struct sk_buff *mypkt = NULL;
775 sd_trace(("%s: Enter\n", __func__));
777 DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait);
778 DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
779 /* Case 1: we don't have a packet. */
781 sd_data(("%s: Creating new %s Packet, len=%d\n",
782 __func__, write ? "TX" : "RX", buflen_u));
783 mypkt = brcmu_pkt_buf_get_skb(buflen_u);
785 sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
786 __func__, buflen_u));
787 return SDIOH_API_RC_FAIL;
790 /* For a write, copy the buffer data into the packet. */
792 memcpy(mypkt->data, buffer, buflen_u);
794 Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
797 /* For a read, copy the packet data back to the buffer. */
799 memcpy(buffer, mypkt->data, buflen_u);
801 brcmu_pkt_buf_free_skb(mypkt);
802 } else if (((u32) (pkt->data) & DMA_ALIGN_MASK) != 0) {
803 /* Case 2: We have a packet, but it is unaligned. */
805 /* In this case, we cannot have a chain. */
806 ASSERT(pkt->next == NULL);
808 sd_data(("%s: Creating aligned %s Packet, len=%d\n",
809 __func__, write ? "TX" : "RX", pkt->len));
810 mypkt = brcmu_pkt_buf_get_skb(pkt->len);
812 sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
813 __func__, pkt->len));
814 return SDIOH_API_RC_FAIL;
817 /* For a write, copy the buffer data into the packet. */
819 memcpy(mypkt->data, pkt->data, pkt->len);
821 Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
824 /* For a read, copy the packet data back to the buffer. */
826 memcpy(pkt->data, mypkt->data, mypkt->len);
828 brcmu_pkt_buf_free_skb(mypkt);
829 } else { /* case 3: We have a packet and
831 sd_data(("%s: Aligned %s Packet, direct DMA\n",
832 __func__, write ? "Tx" : "Rx"));
833 Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
840 /* this function performs "abort" for both of host & device */
841 extern int brcmf_sdioh_abort(struct sdioh_info *sd, uint func)
843 char t_func = (char)func;
844 sd_trace(("%s: Enter\n", __func__));
846 /* issue abort cmd52 command through F0 */
847 brcmf_sdioh_request_byte(sd, SDIOH_WRITE, SDIO_FUNC_0, SDIO_CCCR_ABORT,
850 sd_trace(("%s: Exit\n", __func__));
851 return SDIOH_API_RC_SUCCESS;
854 /* Reset and re-initialize the device */
855 int brcmf_sdioh_reset(struct sdioh_info *si)
857 sd_trace(("%s: Enter\n", __func__));
858 sd_trace(("%s: Exit\n", __func__));
859 return SDIOH_API_RC_SUCCESS;
862 /* Disable device interrupt */
863 void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd)
865 sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
866 sd->intmask &= ~CLIENT_INTR;
869 /* Enable device interrupt */
870 void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd)
872 sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
873 sd->intmask |= CLIENT_INTR;
876 /* Read client card reg */
878 brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
879 int regsize, u32 *data)
882 if ((func == 0) || (regsize == 1)) {
885 brcmf_sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
888 sd_data(("%s: byte read data=0x%02x\n", __func__, *data));
890 brcmf_sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data,
895 sd_data(("%s: word read data=0x%08x\n", __func__, *data));
901 /* bcmsdh_sdmmc interrupt handler */
902 static void brcmf_sdioh_irqhandler(struct sdio_func *func)
904 struct sdioh_info *sd;
906 sd_trace(("bcmsdh_sdmmc: ***IRQHandler\n"));
910 sdio_release_host(gInstance->func[0]);
912 if (sd->use_client_ints) {
914 ASSERT(sd->intr_handler);
915 ASSERT(sd->intr_handler_arg);
916 (sd->intr_handler) (sd->intr_handler_arg);
918 sd_err(("bcmsdh_sdmmc: ***IRQHandler\n"));
920 sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
921 __func__, sd->client_intr_enabled, sd->intr_handler));
924 sdio_claim_host(gInstance->func[0]);
927 /* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */
928 static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func)
930 struct sdioh_info *sd;
932 sd_trace(("bcmsdh_sdmmc: ***IRQHandlerF2\n"));
939 int brcmf_sdioh_start(struct sdioh_info *si, int stage)
944 int brcmf_sdioh_stop(struct sdioh_info *si)