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/export.h>
21 #include <linux/pci.h>
22 #include <linux/pci_ids.h>
23 #include <linux/sched.h>
24 #include <linux/completion.h>
25 #include <linux/mmc/sdio.h>
26 #include <linux/mmc/sdio_func.h>
27 #include <linux/mmc/card.h>
30 #include <brcm_hw_ids.h>
31 #include <brcmu_utils.h>
32 #include <brcmu_wifi.h>
37 #include "sdio_host.h"
39 #define SDIOH_API_ACCESS_RETRY_LIMIT 2
41 static void brcmf_sdioh_irqhandler(struct sdio_func *func)
43 struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
45 brcmf_dbg(TRACE, "***IRQHandler\n");
47 sdio_release_host(func);
49 brcmf_sdbrcm_isr(sdiodev->bus);
51 sdio_claim_host(func);
54 int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev)
56 brcmf_dbg(TRACE, "Entering\n");
58 sdio_claim_host(sdiodev->func[1]);
59 sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler);
60 sdio_release_host(sdiodev->func[1]);
65 int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
67 brcmf_dbg(TRACE, "Entering\n");
69 sdio_claim_host(sdiodev->func[1]);
70 sdio_release_irq(sdiodev->func[1]);
71 sdio_release_host(sdiodev->func[1]);
76 u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
84 if (retry) /* wait for 1 ms till bus get settled down */
86 status = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num,
89 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
93 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
100 brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
107 if (retry) /* wait for 1 ms till bus get settled down */
109 status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num,
112 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
116 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
117 fnc_num, addr, data);
121 brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
124 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
125 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
127 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
128 SBSDIO_FUNC1_SBADDRMID,
129 (address >> 16) & SBSDIO_SBADDRMID_MASK,
132 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
133 SBSDIO_FUNC1_SBADDRHIGH,
134 (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
140 u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size)
144 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
146 brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr);
148 if (bar0 != sdiodev->sbwad) {
149 if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0))
152 sdiodev->sbwad = bar0;
155 addr &= SBSDIO_SB_OFT_ADDR_MASK;
157 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
159 status = brcmf_sdioh_request_word(sdiodev, SDIOH_READ, SDIO_FUNC_1,
162 sdiodev->regfail = (status != 0);
164 brcmf_dbg(INFO, "u32data = 0x%x\n", word);
166 /* if ok, return appropriately masked word */
172 return word & 0xffff;
176 sdiodev->regfail = true;
181 /* otherwise, bad sdio access or invalid size */
182 brcmf_dbg(ERROR, "error reading addr 0x%04x size %d\n", addr, size);
186 u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
190 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
193 brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
194 addr, size * 8, data);
196 if (bar0 != sdiodev->sbwad) {
197 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
201 sdiodev->sbwad = bar0;
204 addr &= SBSDIO_SB_OFT_ADDR_MASK;
206 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
208 brcmf_sdioh_request_word(sdiodev, SDIOH_WRITE, SDIO_FUNC_1,
210 sdiodev->regfail = (status != 0);
215 brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n",
220 bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev)
222 return sdiodev->regfail;
226 brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
228 u8 *buf, uint nbytes, struct sk_buff *pkt)
233 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
236 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes);
238 /* Async not implemented yet */
239 if (flags & SDIO_REQ_ASYNC)
242 if (bar0 != sdiodev->sbwad) {
243 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
247 sdiodev->sbwad = bar0;
250 addr &= SBSDIO_SB_OFT_ADDR_MASK;
252 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
253 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
255 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
257 status = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ,
258 fn, addr, width, nbytes, buf, pkt);
264 brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
265 uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt)
269 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
272 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes);
274 /* Async not implemented yet */
275 if (flags & SDIO_REQ_ASYNC)
278 if (bar0 != sdiodev->sbwad) {
279 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
283 sdiodev->sbwad = bar0;
286 addr &= SBSDIO_SB_OFT_ADDR_MASK;
288 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
289 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
291 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
293 return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
294 addr, width, nbytes, buf, pkt);
297 int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
298 u8 *buf, uint nbytes)
300 addr &= SBSDIO_SB_OFT_ADDR_MASK;
301 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
303 return brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC,
304 (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
305 addr, 4, nbytes, buf, NULL);
308 int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
310 char t_func = (char)fn;
311 brcmf_dbg(TRACE, "Enter\n");
313 /* issue abort cmd52 command through F0 */
314 brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
315 SDIO_CCCR_ABORT, &t_func);
317 brcmf_dbg(TRACE, "Exit\n");
321 int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
326 ret = brcmf_sdioh_attach(sdiodev);
332 /* Report the BAR, to fix if needed */
333 sdiodev->sbwad = SI_ENUM_BASE;
335 /* try to attach to the target device */
336 sdiodev->bus = brcmf_sdbrcm_probe(0, 0, 0, 0, regs, sdiodev);
338 brcmf_dbg(ERROR, "device attach failed\n");
345 brcmf_sdio_remove(sdiodev);
349 EXPORT_SYMBOL(brcmf_sdio_probe);
351 int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
354 brcmf_sdbrcm_disconnect(sdiodev->bus);
358 brcmf_sdioh_detach(sdiodev);
364 EXPORT_SYMBOL(brcmf_sdio_remove);
366 void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
369 brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
371 brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);