spi-topcliff-pch: add recovery processing in case wait-event timeout
[zen-stable.git] / drivers / net / wireless / brcm80211 / brcmfmac / bcmsdh.c
blob4bc8d251acf8ed79d446b0dce22c938ca9bcb709
1 /*
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>
29 #include <defs.h>
30 #include <brcm_hw_ids.h>
31 #include <brcmu_utils.h>
32 #include <brcmu_wifi.h>
33 #include <soc.h>
34 #include "dhd_bus.h"
35 #include "dhd_dbg.h"
36 #include "sdio_host.h"
38 #define SDIOH_API_ACCESS_RETRY_LIMIT 2
40 static void brcmf_sdioh_irqhandler(struct sdio_func *func)
42 struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
44 brcmf_dbg(TRACE, "***IRQHandler\n");
46 sdio_release_host(func);
48 brcmf_sdbrcm_isr(sdiodev->bus);
50 sdio_claim_host(func);
53 /* dummy handler for SDIO function 2 interrupt */
54 static void brcmf_sdioh_dummy_irq_handler(struct sdio_func *func)
58 int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev)
60 brcmf_dbg(TRACE, "Entering\n");
62 sdio_claim_host(sdiodev->func[1]);
63 sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler);
64 sdio_claim_irq(sdiodev->func[2], brcmf_sdioh_dummy_irq_handler);
65 sdio_release_host(sdiodev->func[1]);
67 return 0;
70 int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
72 brcmf_dbg(TRACE, "Entering\n");
74 sdio_claim_host(sdiodev->func[1]);
75 sdio_release_irq(sdiodev->func[2]);
76 sdio_release_irq(sdiodev->func[1]);
77 sdio_release_host(sdiodev->func[1]);
79 return 0;
82 u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
83 int *err)
85 int status;
86 s32 retry = 0;
87 u8 data = 0;
89 do {
90 if (retry) /* wait for 1 ms till bus get settled down */
91 udelay(1000);
92 status = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num,
93 addr, (u8 *) &data);
94 } while (status != 0
95 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
96 if (err)
97 *err = status;
99 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
100 fnc_num, addr, data);
102 return data;
105 void
106 brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
107 u8 data, int *err)
109 int status;
110 s32 retry = 0;
112 do {
113 if (retry) /* wait for 1 ms till bus get settled down */
114 udelay(1000);
115 status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num,
116 addr, (u8 *) &data);
117 } while (status != 0
118 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
119 if (err)
120 *err = status;
122 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
123 fnc_num, addr, data);
127 brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
129 int err = 0;
130 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
131 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
132 if (!err)
133 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
134 SBSDIO_FUNC1_SBADDRMID,
135 (address >> 16) & SBSDIO_SBADDRMID_MASK,
136 &err);
137 if (!err)
138 brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
139 SBSDIO_FUNC1_SBADDRHIGH,
140 (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
141 &err);
143 return err;
146 u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size)
148 int status;
149 u32 word = 0;
150 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
152 brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr);
154 if (bar0 != sdiodev->sbwad) {
155 if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0))
156 return 0xFFFFFFFF;
158 sdiodev->sbwad = bar0;
161 addr &= SBSDIO_SB_OFT_ADDR_MASK;
162 if (size == 4)
163 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
165 status = brcmf_sdioh_request_word(sdiodev, SDIOH_READ, SDIO_FUNC_1,
166 addr, &word, size);
168 sdiodev->regfail = (status != 0);
170 brcmf_dbg(INFO, "u32data = 0x%x\n", word);
172 /* if ok, return appropriately masked word */
173 if (status == 0) {
174 switch (size) {
175 case sizeof(u8):
176 return word & 0xff;
177 case sizeof(u16):
178 return word & 0xffff;
179 case sizeof(u32):
180 return word;
181 default:
182 sdiodev->regfail = true;
187 /* otherwise, bad sdio access or invalid size */
188 brcmf_dbg(ERROR, "error reading addr 0x%04x size %d\n", addr, size);
189 return 0xFFFFFFFF;
192 u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
193 u32 data)
195 int status;
196 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
197 int err = 0;
199 brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
200 addr, size * 8, data);
202 if (bar0 != sdiodev->sbwad) {
203 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
204 if (err)
205 return err;
207 sdiodev->sbwad = bar0;
210 addr &= SBSDIO_SB_OFT_ADDR_MASK;
211 if (size == 4)
212 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
213 status =
214 brcmf_sdioh_request_word(sdiodev, SDIOH_WRITE, SDIO_FUNC_1,
215 addr, &data, size);
216 sdiodev->regfail = (status != 0);
218 if (status == 0)
219 return 0;
221 brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n",
222 data, addr, size);
223 return 0xFFFFFFFF;
226 bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev)
228 return sdiodev->regfail;
231 static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn,
232 uint flags, uint width, u32 *addr)
234 uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
235 int err = 0;
237 /* Async not implemented yet */
238 if (flags & SDIO_REQ_ASYNC)
239 return -ENOTSUPP;
241 if (bar0 != sdiodev->sbwad) {
242 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
243 if (err)
244 return err;
246 sdiodev->sbwad = bar0;
249 *addr &= SBSDIO_SB_OFT_ADDR_MASK;
251 if (width == 4)
252 *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
254 return 0;
258 brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
259 uint flags, u8 *buf, uint nbytes)
261 struct sk_buff *mypkt;
262 int err;
264 mypkt = brcmu_pkt_buf_get_skb(nbytes);
265 if (!mypkt) {
266 brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
267 nbytes);
268 return -EIO;
271 err = brcmf_sdcard_recv_pkt(sdiodev, addr, fn, flags, mypkt);
272 if (!err)
273 memcpy(buf, mypkt->data, nbytes);
275 brcmu_pkt_buf_free_skb(mypkt);
276 return err;
280 brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
281 uint flags, struct sk_buff *pkt)
283 uint incr_fix;
284 uint width;
285 int err = 0;
287 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
288 fn, addr, pkt->len);
290 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
291 err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
292 if (err)
293 return err;
295 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
296 err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ,
297 fn, addr, pkt);
299 return err;
302 int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
303 uint flags, struct sk_buff_head *pktq)
305 uint incr_fix;
306 uint width;
307 int err = 0;
309 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
310 fn, addr, pktq->qlen);
312 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
313 err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
314 if (err)
315 return err;
317 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
318 err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr,
319 pktq);
321 return err;
325 brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
326 uint flags, u8 *buf, uint nbytes)
328 struct sk_buff *mypkt;
329 int err;
331 mypkt = brcmu_pkt_buf_get_skb(nbytes);
332 if (!mypkt) {
333 brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
334 nbytes);
335 return -EIO;
338 memcpy(mypkt->data, buf, nbytes);
339 err = brcmf_sdcard_send_pkt(sdiodev, addr, fn, flags, mypkt);
341 brcmu_pkt_buf_free_skb(mypkt);
342 return err;
347 brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
348 uint flags, struct sk_buff *pkt)
350 uint incr_fix;
351 uint width;
352 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
353 int err = 0;
355 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
356 fn, addr, pkt->len);
358 /* Async not implemented yet */
359 if (flags & SDIO_REQ_ASYNC)
360 return -ENOTSUPP;
362 if (bar0 != sdiodev->sbwad) {
363 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
364 if (err)
365 return err;
367 sdiodev->sbwad = bar0;
370 addr &= SBSDIO_SB_OFT_ADDR_MASK;
372 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
373 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
374 if (width == 4)
375 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
377 return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
378 addr, pkt);
381 int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
382 u8 *buf, uint nbytes)
384 struct sk_buff *mypkt;
385 bool write = rw ? SDIOH_WRITE : SDIOH_READ;
386 int err;
388 addr &= SBSDIO_SB_OFT_ADDR_MASK;
389 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
391 mypkt = brcmu_pkt_buf_get_skb(nbytes);
392 if (!mypkt) {
393 brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
394 nbytes);
395 return -EIO;
398 /* For a write, copy the buffer data into the packet. */
399 if (write)
400 memcpy(mypkt->data, buf, nbytes);
402 err = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC, write,
403 SDIO_FUNC_1, addr, mypkt);
405 /* For a read, copy the packet data back to the buffer. */
406 if (!err && !write)
407 memcpy(buf, mypkt->data, nbytes);
409 brcmu_pkt_buf_free_skb(mypkt);
410 return err;
413 int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
415 char t_func = (char)fn;
416 brcmf_dbg(TRACE, "Enter\n");
418 /* issue abort cmd52 command through F0 */
419 brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
420 SDIO_CCCR_ABORT, &t_func);
422 brcmf_dbg(TRACE, "Exit\n");
423 return 0;
426 int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
428 u32 regs = 0;
429 int ret = 0;
431 ret = brcmf_sdioh_attach(sdiodev);
432 if (ret)
433 goto out;
435 regs = SI_ENUM_BASE;
437 /* Report the BAR, to fix if needed */
438 sdiodev->sbwad = SI_ENUM_BASE;
440 /* try to attach to the target device */
441 sdiodev->bus = brcmf_sdbrcm_probe(regs, sdiodev);
442 if (!sdiodev->bus) {
443 brcmf_dbg(ERROR, "device attach failed\n");
444 ret = -ENODEV;
445 goto out;
448 out:
449 if (ret)
450 brcmf_sdio_remove(sdiodev);
452 return ret;
454 EXPORT_SYMBOL(brcmf_sdio_probe);
456 int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
458 if (sdiodev->bus) {
459 brcmf_sdbrcm_disconnect(sdiodev->bus);
460 sdiodev->bus = NULL;
463 brcmf_sdioh_detach(sdiodev);
465 sdiodev->sbwad = 0;
467 return 0;
469 EXPORT_SYMBOL(brcmf_sdio_remove);
471 void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
473 if (enable)
474 brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
475 else
476 brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);