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
, u32
*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
= 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 int brcmf_sdcard_intr_enable(struct brcmf_sdio_card
*card
)
124 return brcmf_sdioh_interrupt_set(card
->sdioh
, true);
127 int brcmf_sdcard_intr_disable(struct brcmf_sdio_card
*card
)
131 return brcmf_sdioh_interrupt_set(card
->sdioh
, false);
134 int brcmf_sdcard_intr_reg(struct brcmf_sdio_card
*card
,
135 void (*fn
)(void *), void *argh
)
139 return brcmf_sdioh_interrupt_register(card
->sdioh
, fn
, argh
);
142 int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card
*card
)
146 return brcmf_sdioh_interrupt_deregister(card
->sdioh
);
149 u8
brcmf_sdcard_cfg_read(struct brcmf_sdio_card
*card
, uint fnc_num
, u32 addr
,
153 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
161 ASSERT(card
->init_success
);
163 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
165 if (retry
) /* wait for 1 ms till bus get settled down */
169 brcmf_sdioh_cfg_read(card
->sdioh
, fnc_num
, addr
,
171 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
173 && (retry
++ < SDIOH_API_ACCESS_RETRY_LIMIT
));
178 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
179 __func__
, fnc_num
, addr
, data
));
185 brcmf_sdcard_cfg_write(struct brcmf_sdio_card
*card
, uint fnc_num
, u32 addr
,
189 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
196 ASSERT(card
->init_success
);
198 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
200 if (retry
) /* wait for 1 ms till bus get settled down */
204 brcmf_sdioh_cfg_write(card
->sdioh
, fnc_num
, addr
,
206 #ifdef SDIOH_API_ACCESS_RETRY_LIMIT
208 && (retry
++ < SDIOH_API_ACCESS_RETRY_LIMIT
));
213 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
214 __func__
, fnc_num
, addr
, data
));
217 u32
brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card
*card
, uint fnc_num
,
226 ASSERT(card
->init_success
);
228 status
= brcmf_sdioh_request_word(card
->sdioh
, SDIOH_CMD_TYPE_NORMAL
,
229 SDIOH_READ
, fnc_num
, addr
, &data
, 4);
234 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
235 __func__
, fnc_num
, addr
, data
));
241 brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card
*card
, uint fnc_num
,
242 u32 addr
, u32 data
, int *err
)
249 ASSERT(card
->init_success
);
252 brcmf_sdioh_request_word(card
->sdioh
, SDIOH_CMD_TYPE_NORMAL
,
253 SDIOH_WRITE
, fnc_num
, addr
, &data
, 4);
258 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
259 __func__
, fnc_num
, addr
, data
));
262 int brcmf_sdcard_cis_read(struct brcmf_sdio_card
*card
, uint func
, u8
* cis
,
267 u8
*tmp_buf
, *tmp_ptr
;
269 bool ascii
= func
& ~0xf;
275 ASSERT(card
->init_success
);
277 ASSERT(length
<= SBSDIO_CIS_SIZE_LIMIT
);
279 status
= brcmf_sdioh_cis_read(card
->sdioh
, func
, cis
, length
);
282 /* Move binary bits to tmp and format them
283 into the provided buffer. */
284 tmp_buf
= kmalloc(length
, GFP_ATOMIC
);
285 if (tmp_buf
== NULL
) {
286 BRCMF_SD_ERROR(("%s: out of memory\n", __func__
));
289 memcpy(tmp_buf
, cis
, length
);
290 for (tmp_ptr
= tmp_buf
, ptr
= cis
; ptr
< (cis
+ length
- 4);
292 ptr
+= sprintf((char *)ptr
, "%.2x ", *tmp_ptr
& 0xff);
293 if ((((tmp_ptr
- tmp_buf
) + 1) & 0xf) == 0)
294 ptr
+= sprintf((char *)ptr
, "\n");
303 brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_card
*card
, u32 address
)
306 brcmf_sdcard_cfg_write(card
, SDIO_FUNC_1
, SBSDIO_FUNC1_SBADDRLOW
,
307 (address
>> 8) & SBSDIO_SBADDRLOW_MASK
, &err
);
309 brcmf_sdcard_cfg_write(card
, SDIO_FUNC_1
,
310 SBSDIO_FUNC1_SBADDRMID
,
311 (address
>> 16) & SBSDIO_SBADDRMID_MASK
,
314 brcmf_sdcard_cfg_write(card
, SDIO_FUNC_1
,
315 SBSDIO_FUNC1_SBADDRHIGH
,
316 (address
>> 24) & SBSDIO_SBADDRHIGH_MASK
,
322 u32
brcmf_sdcard_reg_read(struct brcmf_sdio_card
*card
, u32 addr
, uint size
)
326 uint bar0
= addr
& ~SBSDIO_SB_OFT_ADDR_MASK
;
328 BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, ", __func__
, addr
));
333 ASSERT(card
->init_success
);
335 if (bar0
!= card
->sbwad
) {
336 if (brcmf_sdcard_set_sbaddr_window(card
, bar0
))
342 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
344 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
346 status
= brcmf_sdioh_request_word(card
->sdioh
, SDIOH_CMD_TYPE_NORMAL
,
347 SDIOH_READ
, SDIO_FUNC_1
, addr
, &word
, size
);
349 card
->regfail
= (status
!= 0);
351 BRCMF_SD_INFO(("u32data = 0x%x\n", word
));
353 /* if ok, return appropriately masked word */
359 return word
& 0xffff;
363 card
->regfail
= true;
368 /* otherwise, bad sdio access or invalid size */
369 BRCMF_SD_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__
,
374 u32
brcmf_sdcard_reg_write(struct brcmf_sdio_card
*card
, u32 addr
, uint size
,
378 uint bar0
= addr
& ~SBSDIO_SB_OFT_ADDR_MASK
;
381 BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
382 __func__
, addr
, size
* 8, data
));
387 ASSERT(card
->init_success
);
389 if (bar0
!= card
->sbwad
) {
390 err
= brcmf_sdcard_set_sbaddr_window(card
, bar0
);
397 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
399 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
401 brcmf_sdioh_request_word(card
->sdioh
, SDIOH_CMD_TYPE_NORMAL
,
402 SDIOH_WRITE
, SDIO_FUNC_1
, addr
, &data
, size
);
403 card
->regfail
= (status
!= 0);
408 BRCMF_SD_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
409 __func__
, data
, addr
, size
));
413 bool brcmf_sdcard_regfail(struct brcmf_sdio_card
*card
)
415 return card
->regfail
;
419 brcmf_sdcard_recv_buf(struct brcmf_sdio_card
*card
, u32 addr
, uint fn
,
421 u8
*buf
, uint nbytes
, struct sk_buff
*pkt
,
422 void (*complete
)(void *handle
, int status
,
429 uint bar0
= addr
& ~SBSDIO_SB_OFT_ADDR_MASK
;
433 ASSERT(card
->init_success
);
435 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
436 __func__
, fn
, addr
, nbytes
));
438 /* Async not implemented yet */
439 ASSERT(!(flags
& SDIO_REQ_ASYNC
));
440 if (flags
& SDIO_REQ_ASYNC
)
443 if (bar0
!= card
->sbwad
) {
444 err
= brcmf_sdcard_set_sbaddr_window(card
, bar0
);
451 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
453 incr_fix
= (flags
& SDIO_REQ_FIXED
) ? SDIOH_DATA_FIX
: SDIOH_DATA_INC
;
454 width
= (flags
& SDIO_REQ_4BYTE
) ? 4 : 2;
456 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
458 status
= brcmf_sdioh_request_buffer(card
->sdioh
, SDIOH_DATA_PIO
,
459 incr_fix
, SDIOH_READ
, fn
, addr
, width
, nbytes
, buf
, pkt
);
465 brcmf_sdcard_send_buf(struct brcmf_sdio_card
*card
, u32 addr
, uint fn
,
466 uint flags
, u8
*buf
, uint nbytes
, void *pkt
,
467 void (*complete
)(void *handle
, int status
,
473 uint bar0
= addr
& ~SBSDIO_SB_OFT_ADDR_MASK
;
477 ASSERT(card
->init_success
);
479 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
480 __func__
, fn
, addr
, nbytes
));
482 /* Async not implemented yet */
483 ASSERT(!(flags
& SDIO_REQ_ASYNC
));
484 if (flags
& SDIO_REQ_ASYNC
)
487 if (bar0
!= card
->sbwad
) {
488 err
= brcmf_sdcard_set_sbaddr_window(card
, bar0
);
495 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
497 incr_fix
= (flags
& SDIO_REQ_FIXED
) ? SDIOH_DATA_FIX
: SDIOH_DATA_INC
;
498 width
= (flags
& SDIO_REQ_4BYTE
) ? 4 : 2;
500 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
502 return brcmf_sdioh_request_buffer(card
->sdioh
, SDIOH_DATA_PIO
,
503 incr_fix
, SDIOH_WRITE
, fn
, addr
, width
, nbytes
, buf
, pkt
);
506 int brcmf_sdcard_rwdata(struct brcmf_sdio_card
*card
, uint rw
, u32 addr
,
507 u8
*buf
, uint nbytes
)
510 ASSERT(card
->init_success
);
511 ASSERT((addr
& SBSDIO_SBWINDOW_MASK
) == 0);
513 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
514 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
516 return brcmf_sdioh_request_buffer(card
->sdioh
, SDIOH_DATA_PIO
,
517 SDIOH_DATA_INC
, (rw
? SDIOH_WRITE
: SDIOH_READ
), SDIO_FUNC_1
,
518 addr
, 4, nbytes
, buf
, NULL
);
521 int brcmf_sdcard_abort(struct brcmf_sdio_card
*card
, uint fn
)
523 return brcmf_sdioh_abort(card
->sdioh
, fn
);
526 int brcmf_sdcard_query_device(struct brcmf_sdio_card
*card
)
528 card
->vendevid
= (PCI_VENDOR_ID_BROADCOM
<< 16) | 0;
529 return card
->vendevid
;
532 u32
brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card
*card
)