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 /* ****************** SDIO CARD Interface Functions **************************/
18 #include <linux/types.h>
19 #include <linux/netdevice.h>
20 #include <linux/pci_ids.h>
21 #include <linux/sched.h>
24 #include <brcm_hw_ids.h>
25 #include <brcmu_utils.h>
26 #include <brcmu_wifi.h>
28 #include "bcmsdbus.h" /* common SDIO/controller interface */
29 #include "sbsdio.h" /* BRCM sdio device core */
30 #include "dngl_stats.h"
33 #define SDIOH_API_ACCESS_RETRY_LIMIT 2
35 #define BRCMF_SD_ERROR_VAL 0x0001 /* Error */
36 #define BRCMF_SD_INFO_VAL 0x0002 /* Info */
39 #define BRCMF_SD_ERROR(x) \
41 if ((brcmf_sdio_msglevel & BRCMF_SD_ERROR_VAL) && \
45 #define BRCMF_SD_INFO(x) \
47 if ((brcmf_sdio_msglevel & BRCMF_SD_INFO_VAL) && \
52 #define BRCMF_SD_ERROR(x)
53 #define BRCMF_SD_INFO(x)
56 const uint brcmf_sdio_msglevel
= BRCMF_SD_ERROR_VAL
;
58 struct brcmf_sdio_card
{
59 bool init_success
; /* underlying driver successfully attached */
60 void *sdioh
; /* handler for sdioh */
61 u32 vendevid
; /* Target Vendor and Device ID on SD bus */
62 bool regfail
; /* Save status of last
63 reg_read/reg_write call */
64 u32 sbwad
; /* Save backplane window address */
66 /* local copy of bcm sd handler */
67 static struct brcmf_sdio_card
*l_card
;
69 struct brcmf_sdio_card
*
70 brcmf_sdcard_attach(void *cfghdl
, void **regsva
, uint irq
)
72 struct brcmf_sdio_card
*card
;
74 card
= kzalloc(sizeof(struct brcmf_sdio_card
), GFP_ATOMIC
);
76 BRCMF_SD_ERROR(("sdcard_attach: out of memory"));
80 /* save the handler locally */
83 card
->sdioh
= brcmf_sdioh_attach(cfghdl
, irq
);
85 brcmf_sdcard_detach(card
);
89 card
->init_success
= true;
91 *regsva
= (u32
*) SI_ENUM_BASE
;
93 /* Report the BAR, to fix if needed */
94 card
->sbwad
= SI_ENUM_BASE
;
98 int brcmf_sdcard_detach(struct brcmf_sdio_card
*card
)
102 brcmf_sdioh_detach(card
->sdioh
);
113 brcmf_sdcard_iovar_op(struct brcmf_sdio_card
*card
, const char *name
,
114 void *params
, int plen
, void *arg
, int len
, bool set
)
116 return brcmf_sdioh_iovar_op(card
->sdioh
, name
, params
, plen
, arg
,
120 bool brcmf_sdcard_intr_query(struct brcmf_sdio_card
*card
)
126 status
= brcmf_sdioh_interrupt_query(card
->sdioh
, &on
);
133 int brcmf_sdcard_intr_enable(struct brcmf_sdio_card
*card
)
137 return brcmf_sdioh_interrupt_set(card
->sdioh
, true);
140 int brcmf_sdcard_intr_disable(struct brcmf_sdio_card
*card
)
144 return brcmf_sdioh_interrupt_set(card
->sdioh
, false);
147 int brcmf_sdcard_intr_reg(struct brcmf_sdio_card
*card
,
148 void (*fn
)(void *), void *argh
)
152 return brcmf_sdioh_interrupt_register(card
->sdioh
, fn
, argh
);
155 int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card
*card
)
159 return brcmf_sdioh_interrupt_deregister(card
->sdioh
);
162 int brcmf_sdcard_devremove_reg(struct brcmf_sdio_card
*card
,
163 void (*fn
)(void *), void *argh
)
167 /* don't support yet */
171 u8
brcmf_sdcard_cfg_read(struct brcmf_sdio_card
*card
, uint fnc_num
, u32 addr
,
175 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
183 ASSERT(card
->init_success
);
185 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
187 if (retry
) /* wait for 1 ms till bus get settled down */
191 brcmf_sdioh_cfg_read(card
->sdioh
, fnc_num
, addr
,
193 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
195 && (retry
++ < SDIOH_API_ACCESS_RETRY_LIMIT
));
200 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
201 __func__
, fnc_num
, addr
, data
));
207 brcmf_sdcard_cfg_write(struct brcmf_sdio_card
*card
, uint fnc_num
, u32 addr
,
211 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
218 ASSERT(card
->init_success
);
220 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
222 if (retry
) /* wait for 1 ms till bus get settled down */
226 brcmf_sdioh_cfg_write(card
->sdioh
, fnc_num
, addr
,
228 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
230 && (retry
++ < SDIOH_API_ACCESS_RETRY_LIMIT
));
235 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
236 __func__
, fnc_num
, addr
, data
));
239 u32
brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card
*card
, uint fnc_num
,
248 ASSERT(card
->init_success
);
250 status
= brcmf_sdioh_request_word(card
->sdioh
, SDIOH_CMD_TYPE_NORMAL
,
251 SDIOH_READ
, fnc_num
, addr
, &data
, 4);
256 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
257 __func__
, fnc_num
, addr
, data
));
263 brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card
*card
, uint fnc_num
,
264 u32 addr
, u32 data
, int *err
)
271 ASSERT(card
->init_success
);
274 brcmf_sdioh_request_word(card
->sdioh
, SDIOH_CMD_TYPE_NORMAL
,
275 SDIOH_WRITE
, fnc_num
, addr
, &data
, 4);
280 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
281 __func__
, fnc_num
, addr
, data
));
284 int brcmf_sdcard_cis_read(struct brcmf_sdio_card
*card
, uint func
, u8
* cis
,
289 u8
*tmp_buf
, *tmp_ptr
;
291 bool ascii
= func
& ~0xf;
297 ASSERT(card
->init_success
);
299 ASSERT(length
<= SBSDIO_CIS_SIZE_LIMIT
);
301 status
= brcmf_sdioh_cis_read(card
->sdioh
, func
, cis
, length
);
304 /* Move binary bits to tmp and format them
305 into the provided buffer. */
306 tmp_buf
= kmalloc(length
, GFP_ATOMIC
);
307 if (tmp_buf
== NULL
) {
308 BRCMF_SD_ERROR(("%s: out of memory\n", __func__
));
311 memcpy(tmp_buf
, cis
, length
);
312 for (tmp_ptr
= tmp_buf
, ptr
= cis
; ptr
< (cis
+ length
- 4);
314 ptr
+= sprintf((char *)ptr
, "%.2x ", *tmp_ptr
& 0xff);
315 if ((((tmp_ptr
- tmp_buf
) + 1) & 0xf) == 0)
316 ptr
+= sprintf((char *)ptr
, "\n");
325 brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_card
*card
, u32 address
)
328 brcmf_sdcard_cfg_write(card
, SDIO_FUNC_1
, SBSDIO_FUNC1_SBADDRLOW
,
329 (address
>> 8) & SBSDIO_SBADDRLOW_MASK
, &err
);
331 brcmf_sdcard_cfg_write(card
, SDIO_FUNC_1
,
332 SBSDIO_FUNC1_SBADDRMID
,
333 (address
>> 16) & SBSDIO_SBADDRMID_MASK
,
336 brcmf_sdcard_cfg_write(card
, SDIO_FUNC_1
,
337 SBSDIO_FUNC1_SBADDRHIGH
,
338 (address
>> 24) & SBSDIO_SBADDRHIGH_MASK
,
344 u32
brcmf_sdcard_reg_read(struct brcmf_sdio_card
*card
, u32 addr
, uint size
)
348 uint bar0
= addr
& ~SBSDIO_SB_OFT_ADDR_MASK
;
350 BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, ", __func__
, addr
));
355 ASSERT(card
->init_success
);
357 if (bar0
!= card
->sbwad
) {
358 if (brcmf_sdcard_set_sbaddr_window(card
, bar0
))
364 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
366 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
368 status
= brcmf_sdioh_request_word(card
->sdioh
, SDIOH_CMD_TYPE_NORMAL
,
369 SDIOH_READ
, SDIO_FUNC_1
, addr
, &word
, size
);
371 card
->regfail
= (status
!= 0);
373 BRCMF_SD_INFO(("u32data = 0x%x\n", word
));
375 /* if ok, return appropriately masked word */
381 return word
& 0xffff;
385 card
->regfail
= true;
390 /* otherwise, bad sdio access or invalid size */
391 BRCMF_SD_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__
,
396 u32
brcmf_sdcard_reg_write(struct brcmf_sdio_card
*card
, u32 addr
, uint size
,
400 uint bar0
= addr
& ~SBSDIO_SB_OFT_ADDR_MASK
;
403 BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
404 __func__
, addr
, size
* 8, data
));
409 ASSERT(card
->init_success
);
411 if (bar0
!= card
->sbwad
) {
412 err
= brcmf_sdcard_set_sbaddr_window(card
, bar0
);
419 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
421 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
423 brcmf_sdioh_request_word(card
->sdioh
, SDIOH_CMD_TYPE_NORMAL
,
424 SDIOH_WRITE
, SDIO_FUNC_1
, addr
, &data
, size
);
425 card
->regfail
= (status
!= 0);
430 BRCMF_SD_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
431 __func__
, data
, addr
, size
));
435 bool brcmf_sdcard_regfail(struct brcmf_sdio_card
*card
)
437 return card
->regfail
;
441 brcmf_sdcard_recv_buf(struct brcmf_sdio_card
*card
, u32 addr
, uint fn
,
443 u8
*buf
, uint nbytes
, struct sk_buff
*pkt
,
444 void (*complete
)(void *handle
, int status
,
451 uint bar0
= addr
& ~SBSDIO_SB_OFT_ADDR_MASK
;
455 ASSERT(card
->init_success
);
457 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
458 __func__
, fn
, addr
, nbytes
));
460 /* Async not implemented yet */
461 ASSERT(!(flags
& SDIO_REQ_ASYNC
));
462 if (flags
& SDIO_REQ_ASYNC
)
465 if (bar0
!= card
->sbwad
) {
466 err
= brcmf_sdcard_set_sbaddr_window(card
, bar0
);
473 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
475 incr_fix
= (flags
& SDIO_REQ_FIXED
) ? SDIOH_DATA_FIX
: SDIOH_DATA_INC
;
476 width
= (flags
& SDIO_REQ_4BYTE
) ? 4 : 2;
478 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
480 status
= brcmf_sdioh_request_buffer(card
->sdioh
, SDIOH_DATA_PIO
,
481 incr_fix
, SDIOH_READ
, fn
, addr
, width
, nbytes
, buf
, pkt
);
487 brcmf_sdcard_send_buf(struct brcmf_sdio_card
*card
, u32 addr
, uint fn
,
488 uint flags
, u8
*buf
, uint nbytes
, void *pkt
,
489 void (*complete
)(void *handle
, int status
,
495 uint bar0
= addr
& ~SBSDIO_SB_OFT_ADDR_MASK
;
499 ASSERT(card
->init_success
);
501 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
502 __func__
, fn
, addr
, nbytes
));
504 /* Async not implemented yet */
505 ASSERT(!(flags
& SDIO_REQ_ASYNC
));
506 if (flags
& SDIO_REQ_ASYNC
)
509 if (bar0
!= card
->sbwad
) {
510 err
= brcmf_sdcard_set_sbaddr_window(card
, bar0
);
517 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
519 incr_fix
= (flags
& SDIO_REQ_FIXED
) ? SDIOH_DATA_FIX
: SDIOH_DATA_INC
;
520 width
= (flags
& SDIO_REQ_4BYTE
) ? 4 : 2;
522 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
524 return brcmf_sdioh_request_buffer(card
->sdioh
, SDIOH_DATA_PIO
,
525 incr_fix
, SDIOH_WRITE
, fn
, addr
, width
, nbytes
, buf
, pkt
);
528 int brcmf_sdcard_rwdata(struct brcmf_sdio_card
*card
, uint rw
, u32 addr
,
529 u8
*buf
, uint nbytes
)
532 ASSERT(card
->init_success
);
533 ASSERT((addr
& SBSDIO_SBWINDOW_MASK
) == 0);
535 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
536 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
538 return brcmf_sdioh_request_buffer(card
->sdioh
, SDIOH_DATA_PIO
,
539 SDIOH_DATA_INC
, (rw
? SDIOH_WRITE
: SDIOH_READ
), SDIO_FUNC_1
,
540 addr
, 4, nbytes
, buf
, NULL
);
543 int brcmf_sdcard_abort(struct brcmf_sdio_card
*card
, uint fn
)
545 return brcmf_sdioh_abort(card
->sdioh
, fn
);
548 int brcmf_sdcard_query_device(struct brcmf_sdio_card
*card
)
550 card
->vendevid
= (PCI_VENDOR_ID_BROADCOM
<< 16) | 0;
551 return card
->vendevid
;
554 uint
brcmf_sdcard_query_iofnum(struct brcmf_sdio_card
*card
)
559 return brcmf_sdioh_query_iofnum(card
->sdioh
);
562 void *brcmf_sdcard_get_sdioh(struct brcmf_sdio_card
*card
)
568 /* Function to pass device-status bits to DHD. */
569 u32
brcmf_sdcard_get_dstatus(struct brcmf_sdio_card
*card
)
574 u32
brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card
*card
)
582 void brcmf_sdcard_chipinfo(struct brcmf_sdio_card
*card
, u32 chip
, u32 chiprev
)