brcm80211: Use brcmu_dbg_hex_dump
[deliverable/linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / bcmsdh.c
CommitLineData
5b435de0
AS
1/*
2 * Copyright (c) 2010 Broadcom Corporation
3 *
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.
7 *
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.
15 */
16/* ****************** SDIO CARD Interface Functions **************************/
17
18#include <linux/types.h>
19#include <linux/netdevice.h>
ee40fa06 20#include <linux/export.h>
5b435de0
AS
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>
28
29#include <defs.h>
30#include <brcm_hw_ids.h>
31#include <brcmu_utils.h>
32#include <brcmu_wifi.h>
33#include <soc.h>
5b435de0
AS
34#include "dhd_bus.h"
35#include "dhd_dbg.h"
36#include "sdio_host.h"
37
38#define SDIOH_API_ACCESS_RETRY_LIMIT 2
39
40static void brcmf_sdioh_irqhandler(struct sdio_func *func)
41{
d76d1c8c 42 struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
5b435de0
AS
43
44 brcmf_dbg(TRACE, "***IRQHandler\n");
45
46 sdio_release_host(func);
47
48 brcmf_sdbrcm_isr(sdiodev->bus);
49
50 sdio_claim_host(func);
51}
52
fbf59108
FL
53/* dummy handler for SDIO function 2 interrupt */
54static void brcmf_sdioh_dummy_irq_handler(struct sdio_func *func)
55{
56}
57
5b435de0
AS
58int brcmf_sdcard_intr_reg(struct brcmf_sdio_dev *sdiodev)
59{
60 brcmf_dbg(TRACE, "Entering\n");
61
62 sdio_claim_host(sdiodev->func[1]);
63 sdio_claim_irq(sdiodev->func[1], brcmf_sdioh_irqhandler);
fbf59108 64 sdio_claim_irq(sdiodev->func[2], brcmf_sdioh_dummy_irq_handler);
5b435de0
AS
65 sdio_release_host(sdiodev->func[1]);
66
67 return 0;
68}
69
70int brcmf_sdcard_intr_dereg(struct brcmf_sdio_dev *sdiodev)
71{
72 brcmf_dbg(TRACE, "Entering\n");
73
74 sdio_claim_host(sdiodev->func[1]);
fbf59108 75 sdio_release_irq(sdiodev->func[2]);
5b435de0
AS
76 sdio_release_irq(sdiodev->func[1]);
77 sdio_release_host(sdiodev->func[1]);
78
79 return 0;
80}
81
82u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
83 int *err)
84{
85 int status;
86 s32 retry = 0;
87 u8 data = 0;
88
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;
98
99 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
100 fnc_num, addr, data);
101
102 return data;
103}
104
105void
106brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr,
107 u8 data, int *err)
108{
109 int status;
110 s32 retry = 0;
111
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;
121
122 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n",
123 fnc_num, addr, data);
124}
125
126int
127brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
128{
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);
142
143 return err;
144}
145
146u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size)
147{
148 int status;
149 u32 word = 0;
150 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
151
152 brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr);
153
154 if (bar0 != sdiodev->sbwad) {
155 if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0))
156 return 0xFFFFFFFF;
157
158 sdiodev->sbwad = bar0;
159 }
160
161 addr &= SBSDIO_SB_OFT_ADDR_MASK;
162 if (size == 4)
163 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
164
165 status = brcmf_sdioh_request_word(sdiodev, SDIOH_READ, SDIO_FUNC_1,
166 addr, &word, size);
167
168 sdiodev->regfail = (status != 0);
169
170 brcmf_dbg(INFO, "u32data = 0x%x\n", word);
171
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;
183
184 }
185 }
186
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;
190}
191
192u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size,
193 u32 data)
194{
195 int status;
196 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
197 int err = 0;
198
199 brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
200 addr, size * 8, data);
201
202 if (bar0 != sdiodev->sbwad) {
203 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
204 if (err)
205 return err;
206
207 sdiodev->sbwad = bar0;
208 }
209
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);
217
218 if (status == 0)
219 return 0;
220
221 brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n",
222 data, addr, size);
223 return 0xFFFFFFFF;
224}
225
226bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev)
227{
228 return sdiodev->regfail;
229}
230
5adfeb63
AS
231static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn,
232 uint flags, uint width, u32 *addr)
5b435de0 233{
5adfeb63 234 uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
5b435de0
AS
235 int err = 0;
236
5b435de0
AS
237 /* Async not implemented yet */
238 if (flags & SDIO_REQ_ASYNC)
239 return -ENOTSUPP;
240
241 if (bar0 != sdiodev->sbwad) {
242 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
243 if (err)
244 return err;
245
246 sdiodev->sbwad = bar0;
247 }
248
5adfeb63
AS
249 *addr &= SBSDIO_SB_OFT_ADDR_MASK;
250
251 if (width == 4)
252 *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
253
254 return 0;
255}
256
257int
258brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
259 uint flags, u8 *buf, uint nbytes)
260{
261 struct sk_buff *mypkt;
262 int err;
263
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;
269 }
270
271 err = brcmf_sdcard_recv_pkt(sdiodev, addr, fn, flags, mypkt);
272 if (!err)
273 memcpy(buf, mypkt->data, nbytes);
274
275 brcmu_pkt_buf_free_skb(mypkt);
276 return err;
277}
278
279int
280brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
281 uint flags, struct sk_buff *pkt)
282{
283 uint incr_fix;
284 uint width;
285 int err = 0;
286
287 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
288 fn, addr, pkt->len);
289
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;
5b435de0
AS
294
295 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
5adfeb63 296 err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ,
4c6e869d 297 fn, addr, pkt);
5adfeb63
AS
298
299 return err;
300}
301
302int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
303 uint flags, struct sk_buff_head *pktq)
304{
305 uint incr_fix;
306 uint width;
307 int err = 0;
308
309 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
310 fn, addr, pktq->qlen);
311
5b435de0 312 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
5adfeb63
AS
313 err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
314 if (err)
315 return err;
5b435de0 316
5adfeb63
AS
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);
5b435de0 320
5adfeb63 321 return err;
5b435de0
AS
322}
323
324int
325brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
5adfeb63
AS
326 uint flags, u8 *buf, uint nbytes)
327{
328 struct sk_buff *mypkt;
329 int err;
330
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;
336 }
337
338 memcpy(mypkt->data, buf, nbytes);
339 err = brcmf_sdcard_send_pkt(sdiodev, addr, fn, flags, mypkt);
340
341 brcmu_pkt_buf_free_skb(mypkt);
342 return err;
343
344}
345
346int
347brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
348 uint flags, struct sk_buff *pkt)
5b435de0
AS
349{
350 uint incr_fix;
351 uint width;
352 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
353 int err = 0;
354
5adfeb63
AS
355 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
356 fn, addr, pkt->len);
5b435de0
AS
357
358 /* Async not implemented yet */
359 if (flags & SDIO_REQ_ASYNC)
360 return -ENOTSUPP;
361
362 if (bar0 != sdiodev->sbwad) {
363 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
364 if (err)
365 return err;
366
367 sdiodev->sbwad = bar0;
368 }
369
370 addr &= SBSDIO_SB_OFT_ADDR_MASK;
371
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;
376
377 return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
4c6e869d 378 addr, pkt);
5b435de0
AS
379}
380
381int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
382 u8 *buf, uint nbytes)
383{
4c6e869d
AS
384 struct sk_buff *mypkt;
385 bool write = rw ? SDIOH_WRITE : SDIOH_READ;
386 int err;
387
5b435de0
AS
388 addr &= SBSDIO_SB_OFT_ADDR_MASK;
389 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
390
4c6e869d
AS
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;
396 }
397
398 /* For a write, copy the buffer data into the packet. */
399 if (write)
400 memcpy(mypkt->data, buf, nbytes);
401
402 err = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC, write,
403 SDIO_FUNC_1, addr, mypkt);
404
405 /* For a read, copy the packet data back to the buffer. */
406 if (!err && !write)
407 memcpy(buf, mypkt->data, nbytes);
408
409 brcmu_pkt_buf_free_skb(mypkt);
410 return err;
5b435de0
AS
411}
412
413int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
414{
415 char t_func = (char)fn;
416 brcmf_dbg(TRACE, "Enter\n");
417
418 /* issue abort cmd52 command through F0 */
419 brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
420 SDIO_CCCR_ABORT, &t_func);
421
422 brcmf_dbg(TRACE, "Exit\n");
423 return 0;
424}
425
426int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
427{
428 u32 regs = 0;
429 int ret = 0;
430
431 ret = brcmf_sdioh_attach(sdiodev);
432 if (ret)
433 goto out;
434
435 regs = SI_ENUM_BASE;
436
437 /* Report the BAR, to fix if needed */
438 sdiodev->sbwad = SI_ENUM_BASE;
439
440 /* try to attach to the target device */
4175b88b 441 sdiodev->bus = brcmf_sdbrcm_probe(regs, sdiodev);
5b435de0
AS
442 if (!sdiodev->bus) {
443 brcmf_dbg(ERROR, "device attach failed\n");
444 ret = -ENODEV;
445 goto out;
446 }
447
448out:
449 if (ret)
450 brcmf_sdio_remove(sdiodev);
451
452 return ret;
453}
454EXPORT_SYMBOL(brcmf_sdio_probe);
455
456int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
457{
458 if (sdiodev->bus) {
459 brcmf_sdbrcm_disconnect(sdiodev->bus);
460 sdiodev->bus = NULL;
461 }
462
463 brcmf_sdioh_detach(sdiodev);
464
465 sdiodev->sbwad = 0;
466
467 return 0;
468}
469EXPORT_SYMBOL(brcmf_sdio_remove);
470
471void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
472{
473 if (enable)
474 brcmf_sdbrcm_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
475 else
476 brcmf_sdbrcm_wd_timer(sdiodev->bus, 0);
477}
This page took 0.074428 seconds and 5 git commands to generate.