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 static void brcmf_sdioh_irqhandler(struct sdio_func *func);
36 static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func);
37 static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr);
39 uint sd_f2_blocksize = 512; /* Default blocksize */
41 uint sd_msglevel = 0x01;
42 BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
43 BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
44 BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
45 BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
47 #define DMA_ALIGN_MASK 0x03
50 brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
51 int regsize, u32 *data);
53 static int brcmf_sdioh_enablefuncs(struct sdioh_info *sd)
59 sd_trace(("%s\n", __func__));
61 /* Get the Card's common CIS address */
62 sd->com_cis_ptr = brcmf_sdioh_get_cisaddr(sd, SDIO_CCCR_CIS);
63 sd->func_cis_ptr[0] = sd->com_cis_ptr;
64 sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
67 /* Get the Card's function CIS (for each function) */
68 for (fbraddr = SDIO_FBR_BASE(1), func = 1;
69 func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
70 sd->func_cis_ptr[func] =
71 brcmf_sdioh_get_cisaddr(sd, SDIO_FBR_CIS + fbraddr);
72 sd_info(("%s: Function %d CIS Ptr = 0x%x\n", __func__, func,
73 sd->func_cis_ptr[func]));
76 sd->func_cis_ptr[0] = sd->com_cis_ptr;
77 sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
80 /* Enable Function 1 */
81 sdio_claim_host(gInstance->func[1]);
82 err_ret = sdio_enable_func(gInstance->func[1]);
83 sdio_release_host(gInstance->func[1]);
85 sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x",
93 * Public entry points & extern's
95 struct sdioh_info *brcmf_sdioh_attach(void *bar0, uint irq)
97 struct sdioh_info *sd;
100 sd_trace(("%s\n", __func__));
102 if (gInstance == NULL) {
103 sd_err(("%s: SDIO Device not present\n", __func__));
107 sd = kzalloc(sizeof(struct sdioh_info), GFP_ATOMIC);
109 sd_err(("sdioh_attach: out of memory\n"));
112 if (brcmf_sdioh_osinit(sd) != 0) {
113 sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__));
119 sd->use_client_ints = true;
120 sd->client_block_size[0] = 64;
124 /* Claim host controller */
125 sdio_claim_host(gInstance->func[1]);
127 sd->client_block_size[1] = 64;
128 err_ret = sdio_set_block_size(gInstance->func[1], 64);
130 sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n"));
132 /* Release host controller F1 */
133 sdio_release_host(gInstance->func[1]);
135 if (gInstance->func[2]) {
136 /* Claim host controller F2 */
137 sdio_claim_host(gInstance->func[2]);
139 sd->client_block_size[2] = sd_f2_blocksize;
141 sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
143 sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize "
144 "to %d\n", sd_f2_blocksize));
146 /* Release host controller F2 */
147 sdio_release_host(gInstance->func[2]);
150 brcmf_sdioh_enablefuncs(sd);
152 sd_trace(("%s: Done\n", __func__));
156 extern int brcmf_sdioh_detach(struct sdioh_info *sd)
158 sd_trace(("%s\n", __func__));
162 /* Disable Function 2 */
163 sdio_claim_host(gInstance->func[2]);
164 sdio_disable_func(gInstance->func[2]);
165 sdio_release_host(gInstance->func[2]);
167 /* Disable Function 1 */
168 sdio_claim_host(gInstance->func[1]);
169 sdio_disable_func(gInstance->func[1]);
170 sdio_release_host(gInstance->func[1]);
173 brcmf_sdioh_osfree(sd);
177 return SDIOH_API_RC_SUCCESS;
180 /* Configure callback to client when we receive client interrupt */
182 brcmf_sdioh_interrupt_register(struct sdioh_info *sd, sdioh_cb_fn_t fn,
185 sd_trace(("%s: Entering\n", __func__));
187 sd_err(("%s: interrupt handler is NULL, not registering\n",
189 return SDIOH_API_RC_FAIL;
192 sd->intr_handler = fn;
193 sd->intr_handler_arg = argh;
194 sd->intr_handler_valid = true;
196 /* register and unmask irq */
197 if (gInstance->func[2]) {
198 sdio_claim_host(gInstance->func[2]);
199 sdio_claim_irq(gInstance->func[2], brcmf_sdioh_irqhandler_f2);
200 sdio_release_host(gInstance->func[2]);
203 if (gInstance->func[1]) {
204 sdio_claim_host(gInstance->func[1]);
205 sdio_claim_irq(gInstance->func[1], brcmf_sdioh_irqhandler);
206 sdio_release_host(gInstance->func[1]);
209 return SDIOH_API_RC_SUCCESS;
212 extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *sd)
214 sd_trace(("%s: Entering\n", __func__));
216 if (gInstance->func[1]) {
217 /* register and unmask irq */
218 sdio_claim_host(gInstance->func[1]);
219 sdio_release_irq(gInstance->func[1]);
220 sdio_release_host(gInstance->func[1]);
223 if (gInstance->func[2]) {
224 /* Claim host controller F2 */
225 sdio_claim_host(gInstance->func[2]);
226 sdio_release_irq(gInstance->func[2]);
227 /* Release host controller F2 */
228 sdio_release_host(gInstance->func[2]);
231 sd->intr_handler_valid = false;
232 sd->intr_handler = NULL;
233 sd->intr_handler_arg = NULL;
235 return SDIOH_API_RC_SUCCESS;
239 brcmf_sdioh_interrupt_query(struct sdioh_info *sd, bool *onoff)
241 sd_trace(("%s: Entering\n", __func__));
242 *onoff = sd->client_intr_enabled;
243 return SDIOH_API_RC_SUCCESS;
247 extern bool brcmf_sdioh_interrupt_pending(struct sdioh_info *sd)
253 uint brcmf_sdioh_query_iofnum(struct sdioh_info *sd)
255 return sd->num_funcs;
269 const struct brcmu_iovar sdioh_iovars[] = {
270 {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0},
271 {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0},/* ((fn << 16) |
273 {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0},
274 {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0},
275 {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
277 {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0}
283 brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name,
284 void *params, int plen, void *arg, int len, bool set)
286 const struct brcmu_iovar *vi = NULL;
296 /* Get must have return space; Set does not take qualifiers */
297 ASSERT(set || (arg && len));
298 ASSERT(!set || (!params && !plen));
300 sd_trace(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"),
303 vi = brcmu_iovar_lookup(sdioh_iovars, name);
305 bcmerror = -ENOTSUPP;
309 bcmerror = brcmu_iovar_lencheck(vi, arg, len, set);
313 /* Set up params so get and set can share the convenience variables */
314 if (params == NULL) {
319 if (vi->type == IOVT_VOID)
321 else if (vi->type == IOVT_BUFFER)
324 val_size = sizeof(int);
326 if (plen >= (int)sizeof(int_val))
327 memcpy(&int_val, params, sizeof(int_val));
329 bool_val = (int_val != 0) ? true : false;
331 actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
333 case IOV_GVAL(IOV_MSGLEVEL):
334 int_val = (s32) sd_msglevel;
335 memcpy(arg, &int_val, val_size);
338 case IOV_SVAL(IOV_MSGLEVEL):
339 sd_msglevel = int_val;
342 case IOV_GVAL(IOV_BLOCKSIZE):
343 if ((u32) int_val > si->num_funcs) {
347 int_val = (s32) si->client_block_size[int_val];
348 memcpy(arg, &int_val, val_size);
351 case IOV_SVAL(IOV_BLOCKSIZE):
353 uint func = ((u32) int_val >> 16);
354 uint blksize = (u16) int_val;
357 if (func > si->num_funcs) {
367 maxsize = BLOCK_SIZE_4318;
370 maxsize = BLOCK_SIZE_4328;
375 if (blksize > maxsize) {
383 si->client_block_size[func] = blksize;
388 case IOV_GVAL(IOV_RXCHAIN):
390 memcpy(arg, &int_val, val_size);
393 case IOV_GVAL(IOV_USEINTS):
394 int_val = (s32) si->use_client_ints;
395 memcpy(arg, &int_val, val_size);
398 case IOV_SVAL(IOV_USEINTS):
399 si->use_client_ints = (bool) int_val;
400 if (si->use_client_ints)
401 si->intmask |= CLIENT_INTR;
403 si->intmask &= ~CLIENT_INTR;
407 case IOV_GVAL(IOV_NUMINTS):
408 int_val = (s32) si->intrcount;
409 memcpy(arg, &int_val, val_size);
412 case IOV_GVAL(IOV_DEVREG):
414 struct brcmf_sdreg *sd_ptr =
415 (struct brcmf_sdreg *) params;
418 if (brcmf_sdioh_cfg_read
419 (si, sd_ptr->func, sd_ptr->offset, &data)) {
425 memcpy(arg, &int_val, sizeof(int_val));
429 case IOV_SVAL(IOV_DEVREG):
431 struct brcmf_sdreg *sd_ptr =
432 (struct brcmf_sdreg *) params;
433 u8 data = (u8) sd_ptr->value;
435 if (brcmf_sdioh_cfg_write
436 (si, sd_ptr->func, sd_ptr->offset, &data)) {
444 bcmerror = -ENOTSUPP;
453 brcmf_sdioh_cfg_read(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
456 /* No lock needed since brcmf_sdioh_request_byte does locking */
457 status = brcmf_sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
462 brcmf_sdioh_cfg_write(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
464 /* No lock needed since brcmf_sdioh_request_byte does locking */
466 status = brcmf_sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
470 static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr)
472 /* read 24 bits and return valid 17 bit addr */
474 u32 scratch, regdata;
475 u8 *ptr = (u8 *)&scratch;
476 for (i = 0; i < 3; i++) {
477 if ((brcmf_sdioh_card_regread(sd, 0, regaddr, 1, ®data)) !=
479 sd_err(("%s: Can't read!\n", __func__));
481 *ptr++ = (u8) regdata;
485 /* Only the lower 17-bits are valid */
486 scratch = le32_to_cpu(scratch);
487 scratch &= 0x0001FFFF;
492 brcmf_sdioh_cis_read(struct sdioh_info *sd, uint func, u8 *cisd, u32 length)
499 sd_trace(("%s: Func = %d\n", __func__, func));
501 if (!sd->func_cis_ptr[func]) {
502 memset(cis, 0, length);
503 sd_err(("%s: no func_cis_ptr[%d]\n", __func__, func));
504 return SDIOH_API_RC_FAIL;
507 sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __func__, func,
508 sd->func_cis_ptr[func]));
510 for (count = 0; count < length; count++) {
511 offset = sd->func_cis_ptr[func] + count;
512 if (brcmf_sdioh_card_regread(sd, 0, offset, 1, &foo) < 0) {
513 sd_err(("%s: regread failed: Can't read CIS\n",
515 return SDIOH_API_RC_FAIL;
518 *cis = (u8) (foo & 0xff);
522 return SDIOH_API_RC_SUCCESS;
526 brcmf_sdioh_request_byte(struct sdioh_info *sd, uint rw, uint func,
527 uint regaddr, u8 *byte)
531 sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __func__, rw, func,
534 BRCMF_PM_RESUME_WAIT(sdioh_request_byte_wait);
535 BRCMF_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
536 if (rw) { /* CMD52 Write */
538 /* Can only directly write to some F0 registers.
542 if (regaddr == SDIO_CCCR_IOEx) {
543 if (gInstance->func[2]) {
544 sdio_claim_host(gInstance->func[2]);
545 if (*byte & SDIO_FUNC_ENABLE_2) {
546 /* Enable Function 2 */
549 (gInstance->func[2]);
551 sd_err(("bcmsdh_sdmmc: enable F2 failed:%d",
554 /* Disable Function 2 */
557 (gInstance->func[2]);
559 sd_err(("bcmsdh_sdmmc: Disab F2 failed:%d",
562 sdio_release_host(gInstance->func[2]);
565 /* to allow abort command through F1 */
566 else if (regaddr == SDIO_CCCR_ABORT) {
567 sdio_claim_host(gInstance->func[func]);
569 * this sdio_f0_writeb() can be replaced
571 * depending upon MMC driver change.
572 * As of this time, this is temporaray one
574 sdio_writeb(gInstance->func[func], *byte,
576 sdio_release_host(gInstance->func[func]);
578 else if (regaddr < 0xF0) {
579 sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write "
580 "disallowed\n", regaddr));
582 /* Claim host controller, perform F0 write,
584 sdio_claim_host(gInstance->func[func]);
585 sdio_f0_writeb(gInstance->func[func], *byte,
587 sdio_release_host(gInstance->func[func]);
590 /* Claim host controller, perform Fn write,
592 sdio_claim_host(gInstance->func[func]);
593 sdio_writeb(gInstance->func[func], *byte, regaddr,
595 sdio_release_host(gInstance->func[func]);
597 } else { /* CMD52 Read */
598 /* Claim host controller, perform Fn read, and release */
599 sdio_claim_host(gInstance->func[func]);
603 sdio_f0_readb(gInstance->func[func], regaddr,
607 sdio_readb(gInstance->func[func], regaddr,
611 sdio_release_host(gInstance->func[func]);
615 sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, "
616 "Err: %d\n", rw ? "Write" : "Read", func, regaddr,
619 return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
623 brcmf_sdioh_request_word(struct sdioh_info *sd, uint cmd_type, uint rw,
624 uint func, uint addr, u32 *word, uint nbytes)
626 int err_ret = SDIOH_API_RC_FAIL;
629 sd_err(("%s: Only CMD52 allowed to F0.\n", __func__));
630 return SDIOH_API_RC_FAIL;
633 sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
634 __func__, cmd_type, rw, func, addr, nbytes));
636 BRCMF_PM_RESUME_WAIT(sdioh_request_word_wait);
637 BRCMF_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
638 /* Claim host controller */
639 sdio_claim_host(gInstance->func[func]);
641 if (rw) { /* CMD52 Write */
643 sdio_writel(gInstance->func[func], *word, addr,
645 } else if (nbytes == 2) {
646 sdio_writew(gInstance->func[func], (*word & 0xFFFF),
649 sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
651 } else { /* CMD52 Read */
654 sdio_readl(gInstance->func[func], addr, &err_ret);
655 } else if (nbytes == 2) {
657 sdio_readw(gInstance->func[func], addr,
660 sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
664 /* Release host controller */
665 sdio_release_host(gInstance->func[func]);
668 sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x",
669 rw ? "Write" : "Read", err_ret));
672 return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
676 brcmf_sdioh_request_packet(struct sdioh_info *sd, uint fix_inc, uint write,
677 uint func, uint addr, struct sk_buff *pkt)
679 bool fifo = (fix_inc == SDIOH_DATA_FIX);
683 struct sk_buff *pnext;
685 sd_trace(("%s: Enter\n", __func__));
688 BRCMF_PM_RESUME_WAIT(sdioh_request_packet_wait);
689 BRCMF_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
691 /* Claim host controller */
692 sdio_claim_host(gInstance->func[func]);
693 for (pnext = pkt; pnext; pnext = pnext->next) {
694 uint pkt_len = pnext->len;
696 pkt_len &= 0xFFFFFFFC;
698 /* Make sure the packet is aligned properly.
699 * If it isn't, then this
700 * is the fault of brcmf_sdioh_request_buffer() which
701 * is supposed to give
702 * us something we can work with.
704 ASSERT(((u32) (pkt->data) & DMA_ALIGN_MASK) == 0);
706 if ((write) && (!fifo)) {
707 err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
708 ((u8 *) (pnext->data)),
711 err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
712 ((u8 *) (pnext->data)),
715 err_ret = sdio_readsb(gInstance->func[func],
716 ((u8 *) (pnext->data)),
719 err_ret = sdio_memcpy_fromio(gInstance->func[func],
720 ((u8 *) (pnext->data)),
725 sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d,"
726 "ERR=0x%08x\n", __func__,
727 (write) ? "TX" : "RX",
728 pnext, SGCount, addr, pkt_len, err_ret));
730 sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n",
732 (write) ? "TX" : "RX",
733 pnext, SGCount, addr, pkt_len));
742 /* Release host controller */
743 sdio_release_host(gInstance->func[func]);
745 sd_trace(("%s: Exit\n", __func__));
746 return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
750 * This function takes a buffer or packet, and fixes everything up
751 * so that in the end, a DMA-able packet is created.
753 * A buffer does not have an associated packet pointer,
754 * and may or may not be aligned.
755 * A packet may consist of a single packet, or a packet chain.
756 * If it is a packet chain, then all the packets in the chain
757 * must be properly aligned.
759 * If the packet data is not aligned, then there may only be
760 * one packet, and in this case, it is copied to a new
765 brcmf_sdioh_request_buffer(struct sdioh_info *sd, uint pio_dma, uint fix_inc,
766 uint write, uint func, uint addr, uint reg_width,
767 uint buflen_u, u8 *buffer, struct sk_buff *pkt)
770 struct sk_buff *mypkt = NULL;
772 sd_trace(("%s: Enter\n", __func__));
774 BRCMF_PM_RESUME_WAIT(sdioh_request_buffer_wait);
775 BRCMF_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
776 /* Case 1: we don't have a packet. */
778 sd_data(("%s: Creating new %s Packet, len=%d\n",
779 __func__, write ? "TX" : "RX", buflen_u));
780 mypkt = brcmu_pkt_buf_get_skb(buflen_u);
782 sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
783 __func__, buflen_u));
784 return SDIOH_API_RC_FAIL;
787 /* For a write, copy the buffer data into the packet. */
789 memcpy(mypkt->data, buffer, buflen_u);
791 Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
794 /* For a read, copy the packet data back to the buffer. */
796 memcpy(buffer, mypkt->data, buflen_u);
798 brcmu_pkt_buf_free_skb(mypkt);
799 } else if (((u32) (pkt->data) & DMA_ALIGN_MASK) != 0) {
800 /* Case 2: We have a packet, but it is unaligned. */
802 /* In this case, we cannot have a chain. */
803 ASSERT(pkt->next == NULL);
805 sd_data(("%s: Creating aligned %s Packet, len=%d\n",
806 __func__, write ? "TX" : "RX", pkt->len));
807 mypkt = brcmu_pkt_buf_get_skb(pkt->len);
809 sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
810 __func__, pkt->len));
811 return SDIOH_API_RC_FAIL;
814 /* For a write, copy the buffer data into the packet. */
816 memcpy(mypkt->data, pkt->data, pkt->len);
818 Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
821 /* For a read, copy the packet data back to the buffer. */
823 memcpy(pkt->data, mypkt->data, mypkt->len);
825 brcmu_pkt_buf_free_skb(mypkt);
826 } else { /* case 3: We have a packet and
828 sd_data(("%s: Aligned %s Packet, direct DMA\n",
829 __func__, write ? "Tx" : "Rx"));
830 Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
837 /* this function performs "abort" for both of host & device */
838 extern int brcmf_sdioh_abort(struct sdioh_info *sd, uint func)
840 char t_func = (char)func;
841 sd_trace(("%s: Enter\n", __func__));
843 /* issue abort cmd52 command through F0 */
844 brcmf_sdioh_request_byte(sd, SDIOH_WRITE, SDIO_FUNC_0, SDIO_CCCR_ABORT,
847 sd_trace(("%s: Exit\n", __func__));
848 return SDIOH_API_RC_SUCCESS;
851 /* Reset and re-initialize the device */
852 int brcmf_sdioh_reset(struct sdioh_info *si)
854 sd_trace(("%s: Enter\n", __func__));
855 sd_trace(("%s: Exit\n", __func__));
856 return SDIOH_API_RC_SUCCESS;
859 /* Disable device interrupt */
860 void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd)
862 sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
863 sd->intmask &= ~CLIENT_INTR;
866 /* Enable device interrupt */
867 void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd)
869 sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
870 sd->intmask |= CLIENT_INTR;
873 /* Read client card reg */
875 brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
876 int regsize, u32 *data)
879 if ((func == 0) || (regsize == 1)) {
882 brcmf_sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
885 sd_data(("%s: byte read data=0x%02x\n", __func__, *data));
887 brcmf_sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data,
892 sd_data(("%s: word read data=0x%08x\n", __func__, *data));
898 /* bcmsdh_sdmmc interrupt handler */
899 static void brcmf_sdioh_irqhandler(struct sdio_func *func)
901 struct sdioh_info *sd;
903 sd_trace(("bcmsdh_sdmmc: ***IRQHandler\n"));
907 sdio_release_host(gInstance->func[0]);
909 if (sd->use_client_ints) {
911 ASSERT(sd->intr_handler);
912 ASSERT(sd->intr_handler_arg);
913 (sd->intr_handler) (sd->intr_handler_arg);
915 sd_err(("bcmsdh_sdmmc: ***IRQHandler\n"));
917 sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
918 __func__, sd->client_intr_enabled, sd->intr_handler));
921 sdio_claim_host(gInstance->func[0]);
924 /* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */
925 static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func)
927 struct sdioh_info *sd;
929 sd_trace(("bcmsdh_sdmmc: ***IRQHandlerF2\n"));
936 int brcmf_sdioh_start(struct sdioh_info *si, int stage)
941 int brcmf_sdioh_stop(struct sdioh_info *si)