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.h>
21 #include <linux/pci_ids.h>
22 #include <linux/sched.h>
23 #include <linux/completion.h>
26 #include <brcm_hw_ids.h>
27 #include <brcmu_utils.h>
28 #include <brcmu_wifi.h>
32 #include "sdio_host.h"
34 #define SDIOH_API_ACCESS_RETRY_LIMIT 2
36 #define BRCMF_SD_ERROR_VAL 0x0001 /* Error */
37 #define BRCMF_SD_INFO_VAL 0x0002 /* Info */
41 #define BRCMF_SD_ERROR(x) \
43 if ((brcmf_sdio_msglevel & BRCMF_SD_ERROR_VAL) && \
47 #define BRCMF_SD_INFO(x) \
49 if ((brcmf_sdio_msglevel & BRCMF_SD_INFO_VAL) && \
54 #define BRCMF_SD_ERROR(x)
55 #define BRCMF_SD_INFO(x)
58 /* debugging macros */
61 #define SDIOH_CMD_TYPE_NORMAL 0 /* Normal command */
62 #define SDIOH_CMD_TYPE_APPEND 1 /* Append command */
63 #define SDIOH_CMD_TYPE_CUTTHRU 2 /* Cut-through command */
65 #define SDIOH_DATA_PIO 0 /* PIO mode */
66 #define SDIOH_DATA_DMA 1 /* DMA mode */
68 struct brcmf_sdio_card
{
69 bool init_success
; /* underlying driver successfully attached */
70 void *sdioh
; /* handler for sdioh */
71 u32 vendevid
; /* Target Vendor and Device ID on SD bus */
72 bool regfail
; /* Save status of last
73 reg_read/reg_write call */
74 u32 sbwad
; /* Save backplane window address */
78 * SDIO Host Controller info
82 struct device
*dev
; /* platform device handle */
83 void *regs
; /* SDIO Host Controller address */
84 struct brcmf_sdio_card
*card
;
87 unsigned long oob_flags
; /* OOB Host specifiction
89 bool oob_irq_registered
;
92 /* local copy of bcm sd handler */
93 static struct brcmf_sdio_card
*l_card
;
95 const uint brcmf_sdio_msglevel
= BRCMF_SD_ERROR_VAL
;
97 static struct sdio_hc
*sdhcinfo
;
99 /* driver info, initialized when brcmf_sdio_register is called */
100 static struct brcmf_sdioh_driver drvinfo
= { NULL
, NULL
};
102 /* Module parameters specific to each host-controller driver */
104 module_param(sd_msglevel
, uint
, 0);
106 extern uint sd_f2_blocksize
;
107 module_param(sd_f2_blocksize
, int, 0);
109 /* forward declarations */
110 int brcmf_sdio_probe(struct device
*dev
);
111 EXPORT_SYMBOL(brcmf_sdio_probe
);
113 int brcmf_sdio_remove(struct device
*dev
);
114 EXPORT_SYMBOL(brcmf_sdio_remove
);
116 struct brcmf_sdio_card
*
117 brcmf_sdcard_attach(void *cfghdl
, u32
*regsva
, uint irq
)
119 struct brcmf_sdio_card
*card
;
121 card
= kzalloc(sizeof(struct brcmf_sdio_card
), GFP_ATOMIC
);
123 BRCMF_SD_ERROR(("sdcard_attach: out of memory"));
127 /* save the handler locally */
130 card
->sdioh
= brcmf_sdioh_attach(cfghdl
, irq
);
132 brcmf_sdcard_detach(card
);
136 card
->init_success
= true;
138 *regsva
= SI_ENUM_BASE
;
140 /* Report the BAR, to fix if needed */
141 card
->sbwad
= SI_ENUM_BASE
;
145 int brcmf_sdcard_detach(struct brcmf_sdio_card
*card
)
149 brcmf_sdioh_detach(card
->sdioh
);
160 brcmf_sdcard_iovar_op(struct brcmf_sdio_card
*card
, const char *name
,
161 void *params
, int plen
, void *arg
, int len
, bool set
)
163 return brcmf_sdioh_iovar_op(card
->sdioh
, name
, params
, plen
, arg
,
167 int brcmf_sdcard_intr_enable(struct brcmf_sdio_card
*card
)
169 return brcmf_sdioh_interrupt_set(card
->sdioh
, true);
172 int brcmf_sdcard_intr_disable(struct brcmf_sdio_card
*card
)
174 return brcmf_sdioh_interrupt_set(card
->sdioh
, false);
177 int brcmf_sdcard_intr_reg(struct brcmf_sdio_card
*card
,
178 void (*fn
)(void *), void *argh
)
180 return brcmf_sdioh_interrupt_register(card
->sdioh
, fn
, argh
);
183 int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card
*card
)
185 return brcmf_sdioh_interrupt_deregister(card
->sdioh
);
188 u8
brcmf_sdcard_cfg_read(struct brcmf_sdio_card
*card
, uint fnc_num
, u32 addr
,
199 if (retry
) /* wait for 1 ms till bus get settled down */
202 brcmf_sdioh_cfg_read(card
->sdioh
, fnc_num
, addr
,
205 && (retry
++ < SDIOH_API_ACCESS_RETRY_LIMIT
));
209 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
210 __func__
, fnc_num
, addr
, data
));
216 brcmf_sdcard_cfg_write(struct brcmf_sdio_card
*card
, uint fnc_num
, u32 addr
,
226 if (retry
) /* wait for 1 ms till bus get settled down */
229 brcmf_sdioh_cfg_write(card
->sdioh
, fnc_num
, addr
,
232 && (retry
++ < SDIOH_API_ACCESS_RETRY_LIMIT
));
236 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
237 __func__
, fnc_num
, addr
, data
));
240 u32
brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card
*card
, uint fnc_num
,
249 status
= brcmf_sdioh_request_word(card
->sdioh
, SDIOH_CMD_TYPE_NORMAL
,
250 SDIOH_READ
, fnc_num
, addr
, &data
, 4);
255 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
256 __func__
, fnc_num
, addr
, data
));
262 brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card
*card
, uint fnc_num
,
263 u32 addr
, u32 data
, int *err
)
271 brcmf_sdioh_request_word(card
->sdioh
, SDIOH_CMD_TYPE_NORMAL
,
272 SDIOH_WRITE
, fnc_num
, addr
, &data
, 4);
277 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
278 __func__
, fnc_num
, addr
, data
));
281 int brcmf_sdcard_cis_read(struct brcmf_sdio_card
*card
, uint func
, u8
* cis
,
286 u8
*tmp_buf
, *tmp_ptr
;
288 bool ascii
= func
& ~0xf;
294 status
= brcmf_sdioh_cis_read(card
->sdioh
, func
, cis
, length
);
297 /* Move binary bits to tmp and format them
298 into the provided buffer. */
299 tmp_buf
= kmalloc(length
, GFP_ATOMIC
);
300 if (tmp_buf
== NULL
) {
301 BRCMF_SD_ERROR(("%s: out of memory\n", __func__
));
304 memcpy(tmp_buf
, cis
, length
);
305 for (tmp_ptr
= tmp_buf
, ptr
= cis
; ptr
< (cis
+ length
- 4);
307 ptr
+= sprintf((char *)ptr
, "%.2x ", *tmp_ptr
& 0xff);
308 if ((((tmp_ptr
- tmp_buf
) + 1) & 0xf) == 0)
309 ptr
+= sprintf((char *)ptr
, "\n");
318 brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_card
*card
, u32 address
)
321 brcmf_sdcard_cfg_write(card
, SDIO_FUNC_1
, SBSDIO_FUNC1_SBADDRLOW
,
322 (address
>> 8) & SBSDIO_SBADDRLOW_MASK
, &err
);
324 brcmf_sdcard_cfg_write(card
, SDIO_FUNC_1
,
325 SBSDIO_FUNC1_SBADDRMID
,
326 (address
>> 16) & SBSDIO_SBADDRMID_MASK
,
329 brcmf_sdcard_cfg_write(card
, SDIO_FUNC_1
,
330 SBSDIO_FUNC1_SBADDRHIGH
,
331 (address
>> 24) & SBSDIO_SBADDRHIGH_MASK
,
337 u32
brcmf_sdcard_reg_read(struct brcmf_sdio_card
*card
, u32 addr
, uint size
)
341 uint bar0
= addr
& ~SBSDIO_SB_OFT_ADDR_MASK
;
343 BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, ", __func__
, addr
));
348 if (bar0
!= card
->sbwad
) {
349 if (brcmf_sdcard_set_sbaddr_window(card
, bar0
))
355 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
357 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
359 status
= brcmf_sdioh_request_word(card
->sdioh
, SDIOH_CMD_TYPE_NORMAL
,
360 SDIOH_READ
, SDIO_FUNC_1
, addr
, &word
, size
);
362 card
->regfail
= (status
!= 0);
364 BRCMF_SD_INFO(("u32data = 0x%x\n", word
));
366 /* if ok, return appropriately masked word */
372 return word
& 0xffff;
376 card
->regfail
= true;
381 /* otherwise, bad sdio access or invalid size */
382 BRCMF_SD_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__
,
387 u32
brcmf_sdcard_reg_write(struct brcmf_sdio_card
*card
, u32 addr
, uint size
,
391 uint bar0
= addr
& ~SBSDIO_SB_OFT_ADDR_MASK
;
394 BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
395 __func__
, addr
, size
* 8, data
));
400 if (bar0
!= card
->sbwad
) {
401 err
= brcmf_sdcard_set_sbaddr_window(card
, bar0
);
408 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
410 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
412 brcmf_sdioh_request_word(card
->sdioh
, SDIOH_CMD_TYPE_NORMAL
,
413 SDIOH_WRITE
, SDIO_FUNC_1
, addr
, &data
, size
);
414 card
->regfail
= (status
!= 0);
419 BRCMF_SD_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
420 __func__
, data
, addr
, size
));
424 bool brcmf_sdcard_regfail(struct brcmf_sdio_card
*card
)
426 return card
->regfail
;
430 brcmf_sdcard_recv_buf(struct brcmf_sdio_card
*card
, u32 addr
, uint fn
,
432 u8
*buf
, uint nbytes
, struct sk_buff
*pkt
,
433 void (*complete
)(void *handle
, int status
,
440 uint bar0
= addr
& ~SBSDIO_SB_OFT_ADDR_MASK
;
443 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
444 __func__
, fn
, addr
, nbytes
));
446 /* Async not implemented yet */
447 if (flags
& SDIO_REQ_ASYNC
)
450 if (bar0
!= card
->sbwad
) {
451 err
= brcmf_sdcard_set_sbaddr_window(card
, bar0
);
458 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
460 incr_fix
= (flags
& SDIO_REQ_FIXED
) ? SDIOH_DATA_FIX
: SDIOH_DATA_INC
;
461 width
= (flags
& SDIO_REQ_4BYTE
) ? 4 : 2;
463 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
465 status
= brcmf_sdioh_request_buffer(card
->sdioh
, SDIOH_DATA_PIO
,
466 incr_fix
, SDIOH_READ
, fn
, addr
, width
, nbytes
, buf
, pkt
);
472 brcmf_sdcard_send_buf(struct brcmf_sdio_card
*card
, u32 addr
, uint fn
,
473 uint flags
, u8
*buf
, uint nbytes
, void *pkt
,
474 void (*complete
)(void *handle
, int status
,
480 uint bar0
= addr
& ~SBSDIO_SB_OFT_ADDR_MASK
;
483 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
484 __func__
, fn
, addr
, nbytes
));
486 /* Async not implemented yet */
487 if (flags
& SDIO_REQ_ASYNC
)
490 if (bar0
!= card
->sbwad
) {
491 err
= brcmf_sdcard_set_sbaddr_window(card
, bar0
);
498 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
500 incr_fix
= (flags
& SDIO_REQ_FIXED
) ? SDIOH_DATA_FIX
: SDIOH_DATA_INC
;
501 width
= (flags
& SDIO_REQ_4BYTE
) ? 4 : 2;
503 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
505 return brcmf_sdioh_request_buffer(card
->sdioh
, SDIOH_DATA_PIO
,
506 incr_fix
, SDIOH_WRITE
, fn
, addr
, width
, nbytes
, buf
, pkt
);
509 int brcmf_sdcard_rwdata(struct brcmf_sdio_card
*card
, uint rw
, u32 addr
,
510 u8
*buf
, uint nbytes
)
512 addr
&= SBSDIO_SB_OFT_ADDR_MASK
;
513 addr
|= SBSDIO_SB_ACCESS_2_4B_FLAG
;
515 return brcmf_sdioh_request_buffer(card
->sdioh
, SDIOH_DATA_PIO
,
516 SDIOH_DATA_INC
, (rw
? SDIOH_WRITE
: SDIOH_READ
), SDIO_FUNC_1
,
517 addr
, 4, nbytes
, buf
, NULL
);
520 int brcmf_sdcard_abort(struct brcmf_sdio_card
*card
, uint fn
)
522 return brcmf_sdioh_abort(card
->sdioh
, fn
);
525 int brcmf_sdcard_query_device(struct brcmf_sdio_card
*card
)
527 card
->vendevid
= (PCI_VENDOR_ID_BROADCOM
<< 16) | 0;
528 return card
->vendevid
;
531 u32
brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card
*card
)
539 int brcmf_sdio_probe(struct device
*dev
)
541 struct sdio_hc
*sdhc
= NULL
;
543 struct brcmf_sdio_card
*card
= NULL
;
546 unsigned long irq_flags
= 0;
548 /* allocate SDIO Host Controller state info */
549 sdhc
= kzalloc(sizeof(struct sdio_hc
), GFP_ATOMIC
);
551 SDLX_MSG(("%s: out of memory\n", __func__
));
554 sdhc
->dev
= (void *)dev
;
556 card
= brcmf_sdcard_attach((void *)0, ®s
, irq
);
558 SDLX_MSG(("%s: attach failed\n", __func__
));
564 sdhc
->oob_flags
= irq_flags
;
565 sdhc
->oob_irq_registered
= false; /* to make sure.. */
567 /* chain SDIO Host Controller info together */
568 sdhc
->next
= sdhcinfo
;
570 /* Read the vendor/device ID from the CIS */
571 vendevid
= brcmf_sdcard_query_device(card
);
573 /* try to attach to the target device */
574 sdhc
->ch
= drvinfo
.attach((vendevid
>> 16), (vendevid
& 0xFFFF),
575 0, 0, 0, 0, regs
, card
);
577 SDLX_MSG(("%s: device attach failed\n", __func__
));
587 brcmf_sdcard_detach(sdhc
->card
);
594 int brcmf_sdio_remove(struct device
*dev
)
596 struct sdio_hc
*sdhc
, *prev
;
599 drvinfo
.detach(sdhc
->ch
);
600 brcmf_sdcard_detach(sdhc
->card
);
601 /* find the SDIO Host Controller state for this pdev
602 and take it out from the list */
603 for (sdhc
= sdhcinfo
, prev
= NULL
; sdhc
; sdhc
= sdhc
->next
) {
604 if (sdhc
->dev
== (void *)dev
) {
606 prev
->next
= sdhc
->next
;
614 SDLX_MSG(("%s: failed\n", __func__
));
618 /* release SDIO Host Controller info */
623 int brcmf_sdio_register(struct brcmf_sdioh_driver
*driver
)
627 SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
628 return brcmf_sdio_function_init();
631 void brcmf_sdio_unregister(void)
633 brcmf_sdio_function_cleanup();
636 void brcmf_sdio_wdtmr_enable(bool enable
)
639 brcmf_sdbrcm_wd_timer(sdhcinfo
->ch
, brcmf_watchdog_ms
);
641 brcmf_sdbrcm_wd_timer(sdhcinfo
->ch
, 0);