staging: brcm80211: removed asserts from dhd_linux.c
[deliverable/linux.git] / drivers / staging / brcm80211 / brcmfmac / bcmsdh_sdmmc.c
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 #include <linux/types.h>
17 #include <linux/netdevice.h>
18 #include <linux/mmc/sdio.h>
19 #include <linux/mmc/core.h>
20 #include <linux/mmc/sdio_func.h>
21 #include <linux/mmc/sdio_ids.h>
22 #include <linux/suspend.h>
23 #include <linux/errno.h>
24
25 #include <defs.h>
26 #include <brcm_hw_ids.h>
27 #include <brcmu_utils.h>
28 #include <brcmu_wifi.h>
29 #include "sdio_host.h"
30 #include "bcmsdbus.h"
31 #include "dngl_stats.h"
32 #include "dhd.h"
33
34 #define BLOCK_SIZE_64 64
35 #define BLOCK_SIZE_512 512
36 #define BLOCK_SIZE_4318 64
37 #define BLOCK_SIZE_4328 512
38
39 /* private bus modes */
40 #define SDIOH_MODE_SD4 2
41
42 #define CLIENT_INTR 0x100 /* Get rid of this! */
43
44 static void brcmf_sdioh_irqhandler(struct sdio_func *func);
45 static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func);
46 static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr);
47
48 uint sd_f2_blocksize = 512; /* Default blocksize */
49
50 uint sd_msglevel = 0x01;
51 BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
52 BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
53 BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
54 BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
55
56 #define DMA_ALIGN_MASK 0x03
57
58 static int
59 brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
60 int regsize, u32 *data);
61
62 static int brcmf_sdioh_enablefuncs(struct sdioh_info *sd)
63 {
64 int err_ret;
65 u32 fbraddr;
66 u8 func;
67
68 sd_trace(("%s\n", __func__));
69
70 /* Get the Card's common CIS address */
71 sd->com_cis_ptr = brcmf_sdioh_get_cisaddr(sd, SDIO_CCCR_CIS);
72 sd->func_cis_ptr[0] = sd->com_cis_ptr;
73 sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
74 sd->com_cis_ptr));
75
76 /* Get the Card's function CIS (for each function) */
77 for (fbraddr = SDIO_FBR_BASE(1), func = 1;
78 func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
79 sd->func_cis_ptr[func] =
80 brcmf_sdioh_get_cisaddr(sd, SDIO_FBR_CIS + fbraddr);
81 sd_info(("%s: Function %d CIS Ptr = 0x%x\n", __func__, func,
82 sd->func_cis_ptr[func]));
83 }
84
85 sd->func_cis_ptr[0] = sd->com_cis_ptr;
86 sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
87 sd->com_cis_ptr));
88
89 /* Enable Function 1 */
90 sdio_claim_host(gInstance->func[1]);
91 err_ret = sdio_enable_func(gInstance->func[1]);
92 sdio_release_host(gInstance->func[1]);
93 if (err_ret) {
94 sd_err(("brcmf_sdioh_enablefuncs: Failed to enable F1 "
95 "Err: 0x%08x", err_ret));
96 }
97
98 return false;
99 }
100
101 /*
102 * Public entry points & extern's
103 */
104 struct sdioh_info *brcmf_sdioh_attach(void *bar0, uint irq)
105 {
106 struct sdioh_info *sd;
107 int err_ret;
108
109 sd_trace(("%s\n", __func__));
110
111 if (gInstance == NULL) {
112 sd_err(("%s: SDIO Device not present\n", __func__));
113 return NULL;
114 }
115
116 sd = kzalloc(sizeof(struct sdioh_info), GFP_ATOMIC);
117 if (sd == NULL) {
118 sd_err(("sdioh_attach: out of memory\n"));
119 return NULL;
120 }
121 if (brcmf_sdioh_osinit(sd) != 0) {
122 sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__));
123 kfree(sd);
124 return NULL;
125 }
126
127 sd->num_funcs = 2;
128 sd->use_client_ints = true;
129 sd->client_block_size[0] = 64;
130
131 gInstance->sd = sd;
132
133 /* Claim host controller */
134 sdio_claim_host(gInstance->func[1]);
135
136 sd->client_block_size[1] = 64;
137 err_ret = sdio_set_block_size(gInstance->func[1], 64);
138 if (err_ret)
139 sd_err(("brcmf_sdioh_attach: Failed to set F1 blocksize\n"));
140
141 /* Release host controller F1 */
142 sdio_release_host(gInstance->func[1]);
143
144 if (gInstance->func[2]) {
145 /* Claim host controller F2 */
146 sdio_claim_host(gInstance->func[2]);
147
148 sd->client_block_size[2] = sd_f2_blocksize;
149 err_ret =
150 sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
151 if (err_ret)
152 sd_err(("brcmf_sdioh_attach: Failed to set F2 blocksize"
153 " to %d\n", sd_f2_blocksize));
154
155 /* Release host controller F2 */
156 sdio_release_host(gInstance->func[2]);
157 }
158
159 brcmf_sdioh_enablefuncs(sd);
160
161 sd_trace(("%s: Done\n", __func__));
162 return sd;
163 }
164
165 extern int brcmf_sdioh_detach(struct sdioh_info *sd)
166 {
167 sd_trace(("%s\n", __func__));
168
169 if (sd) {
170
171 /* Disable Function 2 */
172 sdio_claim_host(gInstance->func[2]);
173 sdio_disable_func(gInstance->func[2]);
174 sdio_release_host(gInstance->func[2]);
175
176 /* Disable Function 1 */
177 sdio_claim_host(gInstance->func[1]);
178 sdio_disable_func(gInstance->func[1]);
179 sdio_release_host(gInstance->func[1]);
180
181 /* deregister irq */
182 brcmf_sdioh_osfree(sd);
183
184 kfree(sd);
185 }
186 return 0;
187 }
188
189 /* Configure callback to client when we receive client interrupt */
190 extern int
191 brcmf_sdioh_interrupt_register(struct sdioh_info *sd, void (*fn)(void *),
192 void *argh)
193 {
194 sd_trace(("%s: Entering\n", __func__));
195 if (fn == NULL) {
196 sd_err(("%s: interrupt handler is NULL, not registering\n",
197 __func__));
198 return -EINVAL;
199 }
200
201 sd->intr_handler = fn;
202 sd->intr_handler_arg = argh;
203 sd->intr_handler_valid = true;
204
205 /* register and unmask irq */
206 if (gInstance->func[2]) {
207 sdio_claim_host(gInstance->func[2]);
208 sdio_claim_irq(gInstance->func[2], brcmf_sdioh_irqhandler_f2);
209 sdio_release_host(gInstance->func[2]);
210 }
211
212 if (gInstance->func[1]) {
213 sdio_claim_host(gInstance->func[1]);
214 sdio_claim_irq(gInstance->func[1], brcmf_sdioh_irqhandler);
215 sdio_release_host(gInstance->func[1]);
216 }
217
218 return 0;
219 }
220
221 extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *sd)
222 {
223 sd_trace(("%s: Entering\n", __func__));
224
225 if (gInstance->func[1]) {
226 /* register and unmask irq */
227 sdio_claim_host(gInstance->func[1]);
228 sdio_release_irq(gInstance->func[1]);
229 sdio_release_host(gInstance->func[1]);
230 }
231
232 if (gInstance->func[2]) {
233 /* Claim host controller F2 */
234 sdio_claim_host(gInstance->func[2]);
235 sdio_release_irq(gInstance->func[2]);
236 /* Release host controller F2 */
237 sdio_release_host(gInstance->func[2]);
238 }
239
240 sd->intr_handler_valid = false;
241 sd->intr_handler = NULL;
242 sd->intr_handler_arg = NULL;
243
244 return 0;
245 }
246
247 /* IOVar table */
248 enum {
249 IOV_MSGLEVEL = 1,
250 IOV_BLOCKSIZE,
251 IOV_USEINTS,
252 IOV_NUMINTS,
253 IOV_DEVREG,
254 IOV_HCIREGS,
255 IOV_RXCHAIN
256 };
257
258 const struct brcmu_iovar sdioh_iovars[] = {
259 {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0},
260 {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0},/* ((fn << 16) |
261 size) */
262 {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0},
263 {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0},
264 {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)}
265 ,
266 {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0}
267 ,
268 {NULL, 0, 0, 0, 0}
269 };
270
271 int
272 brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name,
273 void *params, int plen, void *arg, int len, bool set)
274 {
275 const struct brcmu_iovar *vi = NULL;
276 int bcmerror = 0;
277 int val_size;
278 s32 int_val = 0;
279 bool bool_val;
280 u32 actionid;
281
282 if (name == NULL || len <= 0)
283 return -EINVAL;
284
285 /* Set does not take qualifiers */
286 if (set && (params || plen))
287 return -EINVAL;
288
289 /* Get must have return space;*/
290 if (!set && !(arg && len))
291 return -EINVAL;
292
293 sd_trace(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"),
294 name));
295
296 vi = brcmu_iovar_lookup(sdioh_iovars, name);
297 if (vi == NULL) {
298 bcmerror = -ENOTSUPP;
299 goto exit;
300 }
301
302 bcmerror = brcmu_iovar_lencheck(vi, arg, len, set);
303 if (bcmerror != 0)
304 goto exit;
305
306 /* Set up params so get and set can share the convenience variables */
307 if (params == NULL) {
308 params = arg;
309 plen = len;
310 }
311
312 if (vi->type == IOVT_VOID)
313 val_size = 0;
314 else if (vi->type == IOVT_BUFFER)
315 val_size = len;
316 else
317 val_size = sizeof(int);
318
319 if (plen >= (int)sizeof(int_val))
320 memcpy(&int_val, params, sizeof(int_val));
321
322 bool_val = (int_val != 0) ? true : false;
323
324 actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
325 switch (actionid) {
326 case IOV_GVAL(IOV_MSGLEVEL):
327 int_val = (s32) sd_msglevel;
328 memcpy(arg, &int_val, val_size);
329 break;
330
331 case IOV_SVAL(IOV_MSGLEVEL):
332 sd_msglevel = int_val;
333 break;
334
335 case IOV_GVAL(IOV_BLOCKSIZE):
336 if ((u32) int_val > si->num_funcs) {
337 bcmerror = -EINVAL;
338 break;
339 }
340 int_val = (s32) si->client_block_size[int_val];
341 memcpy(arg, &int_val, val_size);
342 break;
343
344 case IOV_SVAL(IOV_BLOCKSIZE):
345 {
346 uint func = ((u32) int_val >> 16);
347 uint blksize = (u16) int_val;
348 uint maxsize;
349
350 if (func > si->num_funcs) {
351 bcmerror = -EINVAL;
352 break;
353 }
354
355 switch (func) {
356 case 0:
357 maxsize = 32;
358 break;
359 case 1:
360 maxsize = BLOCK_SIZE_4318;
361 break;
362 case 2:
363 maxsize = BLOCK_SIZE_4328;
364 break;
365 default:
366 maxsize = 0;
367 }
368 if (blksize > maxsize) {
369 bcmerror = -EINVAL;
370 break;
371 }
372 if (!blksize)
373 blksize = maxsize;
374
375 /* Now set it */
376 si->client_block_size[func] = blksize;
377
378 break;
379 }
380
381 case IOV_GVAL(IOV_RXCHAIN):
382 int_val = false;
383 memcpy(arg, &int_val, val_size);
384 break;
385
386 case IOV_GVAL(IOV_USEINTS):
387 int_val = (s32) si->use_client_ints;
388 memcpy(arg, &int_val, val_size);
389 break;
390
391 case IOV_SVAL(IOV_USEINTS):
392 si->use_client_ints = (bool) int_val;
393 if (si->use_client_ints)
394 si->intmask |= CLIENT_INTR;
395 else
396 si->intmask &= ~CLIENT_INTR;
397
398 break;
399
400 case IOV_GVAL(IOV_NUMINTS):
401 int_val = (s32) si->intrcount;
402 memcpy(arg, &int_val, val_size);
403 break;
404
405 case IOV_GVAL(IOV_DEVREG):
406 {
407 struct brcmf_sdreg *sd_ptr =
408 (struct brcmf_sdreg *) params;
409 u8 data = 0;
410
411 if (brcmf_sdioh_cfg_read
412 (si, sd_ptr->func, sd_ptr->offset, &data)) {
413 bcmerror = -EIO;
414 break;
415 }
416
417 int_val = (int)data;
418 memcpy(arg, &int_val, sizeof(int_val));
419 break;
420 }
421
422 case IOV_SVAL(IOV_DEVREG):
423 {
424 struct brcmf_sdreg *sd_ptr =
425 (struct brcmf_sdreg *) params;
426 u8 data = (u8) sd_ptr->value;
427
428 if (brcmf_sdioh_cfg_write
429 (si, sd_ptr->func, sd_ptr->offset, &data)) {
430 bcmerror = -EIO;
431 break;
432 }
433 break;
434 }
435
436 default:
437 bcmerror = -ENOTSUPP;
438 break;
439 }
440 exit:
441
442 return bcmerror;
443 }
444
445 extern int
446 brcmf_sdioh_cfg_read(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
447 {
448 int status;
449 /* No lock needed since brcmf_sdioh_request_byte does locking */
450 status = brcmf_sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
451 return status;
452 }
453
454 extern int
455 brcmf_sdioh_cfg_write(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data)
456 {
457 /* No lock needed since brcmf_sdioh_request_byte does locking */
458 int status;
459 status = brcmf_sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
460 return status;
461 }
462
463 static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr)
464 {
465 /* read 24 bits and return valid 17 bit addr */
466 int i;
467 u32 scratch, regdata;
468 u8 *ptr = (u8 *)&scratch;
469 for (i = 0; i < 3; i++) {
470 if ((brcmf_sdioh_card_regread(sd, 0, regaddr, 1, &regdata)) !=
471 SUCCESS)
472 sd_err(("%s: Can't read!\n", __func__));
473
474 *ptr++ = (u8) regdata;
475 regaddr++;
476 }
477
478 /* Only the lower 17-bits are valid */
479 scratch = le32_to_cpu(scratch);
480 scratch &= 0x0001FFFF;
481 return scratch;
482 }
483
484 extern int
485 brcmf_sdioh_cis_read(struct sdioh_info *sd, uint func, u8 *cisd, u32 length)
486 {
487 u32 count;
488 int offset;
489 u32 foo;
490 u8 *cis = cisd;
491
492 sd_trace(("%s: Func = %d\n", __func__, func));
493
494 if (!sd->func_cis_ptr[func]) {
495 memset(cis, 0, length);
496 sd_err(("%s: no func_cis_ptr[%d]\n", __func__, func));
497 return -ENOTSUPP;
498 }
499
500 sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __func__, func,
501 sd->func_cis_ptr[func]));
502
503 for (count = 0; count < length; count++) {
504 offset = sd->func_cis_ptr[func] + count;
505 if (brcmf_sdioh_card_regread(sd, 0, offset, 1, &foo) < 0) {
506 sd_err(("%s: regread failed: Can't read CIS\n",
507 __func__));
508 return -EIO;
509 }
510
511 *cis = (u8) (foo & 0xff);
512 cis++;
513 }
514
515 return 0;
516 }
517
518 extern int
519 brcmf_sdioh_request_byte(struct sdioh_info *sd, uint rw, uint func,
520 uint regaddr, u8 *byte)
521 {
522 int err_ret;
523
524 sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __func__, rw, func,
525 regaddr));
526
527 BRCMF_PM_RESUME_WAIT(sdioh_request_byte_wait);
528 BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
529 if (rw) { /* CMD52 Write */
530 if (func == 0) {
531 /* Can only directly write to some F0 registers.
532 * Handle F2 enable
533 * as a special case.
534 */
535 if (regaddr == SDIO_CCCR_IOEx) {
536 if (gInstance->func[2]) {
537 sdio_claim_host(gInstance->func[2]);
538 if (*byte & SDIO_FUNC_ENABLE_2) {
539 /* Enable Function 2 */
540 err_ret =
541 sdio_enable_func
542 (gInstance->func[2]);
543 if (err_ret)
544 sd_err(("request_byte: "
545 "enable F2 "
546 "failed:%d",
547 err_ret));
548 } else {
549 /* Disable Function 2 */
550 err_ret =
551 sdio_disable_func
552 (gInstance->func[2]);
553 if (err_ret)
554 sd_err(("request_byte: "
555 "Disab F2 "
556 "failed:%d",
557 err_ret));
558 }
559 sdio_release_host(gInstance->func[2]);
560 }
561 }
562 /* to allow abort command through F1 */
563 else if (regaddr == SDIO_CCCR_ABORT) {
564 sdio_claim_host(gInstance->func[func]);
565 /*
566 * this sdio_f0_writeb() can be replaced
567 * with another api
568 * depending upon MMC driver change.
569 * As of this time, this is temporaray one
570 */
571 sdio_writeb(gInstance->func[func], *byte,
572 regaddr, &err_ret);
573 sdio_release_host(gInstance->func[func]);
574 } else if (regaddr < 0xF0) {
575 sd_err(("brcmf: F0 Wr:0x%02x: write "
576 "disallowed\n", regaddr));
577 } else {
578 /* Claim host controller, perform F0 write,
579 and release */
580 sdio_claim_host(gInstance->func[func]);
581 sdio_f0_writeb(gInstance->func[func], *byte,
582 regaddr, &err_ret);
583 sdio_release_host(gInstance->func[func]);
584 }
585 } else {
586 /* Claim host controller, perform Fn write,
587 and release */
588 sdio_claim_host(gInstance->func[func]);
589 sdio_writeb(gInstance->func[func], *byte, regaddr,
590 &err_ret);
591 sdio_release_host(gInstance->func[func]);
592 }
593 } else { /* CMD52 Read */
594 /* Claim host controller, perform Fn read, and release */
595 sdio_claim_host(gInstance->func[func]);
596
597 if (func == 0) {
598 *byte =
599 sdio_f0_readb(gInstance->func[func], regaddr,
600 &err_ret);
601 } else {
602 *byte =
603 sdio_readb(gInstance->func[func], regaddr,
604 &err_ret);
605 }
606
607 sdio_release_host(gInstance->func[func]);
608 }
609
610 if (err_ret)
611 sd_err(("brcmf: Failed to %s byte F%d:@0x%05x=%02x, "
612 "Err: %d\n", rw ? "Write" : "Read", func, regaddr,
613 *byte, err_ret));
614
615 return err_ret;
616 }
617
618 extern int
619 brcmf_sdioh_request_word(struct sdioh_info *sd, uint cmd_type, uint rw,
620 uint func, uint addr, u32 *word, uint nbytes)
621 {
622 int err_ret = -EIO;
623
624 if (func == 0) {
625 sd_err(("%s: Only CMD52 allowed to F0.\n", __func__));
626 return -EINVAL;
627 }
628
629 sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
630 __func__, cmd_type, rw, func, addr, nbytes));
631
632 BRCMF_PM_RESUME_WAIT(sdioh_request_word_wait);
633 BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
634 /* Claim host controller */
635 sdio_claim_host(gInstance->func[func]);
636
637 if (rw) { /* CMD52 Write */
638 if (nbytes == 4) {
639 sdio_writel(gInstance->func[func], *word, addr,
640 &err_ret);
641 } else if (nbytes == 2) {
642 sdio_writew(gInstance->func[func], (*word & 0xFFFF),
643 addr, &err_ret);
644 } else {
645 sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
646 }
647 } else { /* CMD52 Read */
648 if (nbytes == 4) {
649 *word =
650 sdio_readl(gInstance->func[func], addr, &err_ret);
651 } else if (nbytes == 2) {
652 *word =
653 sdio_readw(gInstance->func[func], addr,
654 &err_ret) & 0xFFFF;
655 } else {
656 sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
657 }
658 }
659
660 /* Release host controller */
661 sdio_release_host(gInstance->func[func]);
662
663 if (err_ret) {
664 sd_err(("brcmf: Failed to %s word, Err: 0x%08x",
665 rw ? "Write" : "Read", err_ret));
666 }
667
668 return err_ret;
669 }
670
671 static int
672 brcmf_sdioh_request_packet(struct sdioh_info *sd, uint fix_inc, uint write,
673 uint func, uint addr, struct sk_buff *pkt)
674 {
675 bool fifo = (fix_inc == SDIOH_DATA_FIX);
676 u32 SGCount = 0;
677 int err_ret = 0;
678
679 struct sk_buff *pnext;
680
681 sd_trace(("%s: Enter\n", __func__));
682
683 BRCMF_PM_RESUME_WAIT(sdioh_request_packet_wait);
684 BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
685
686 /* Claim host controller */
687 sdio_claim_host(gInstance->func[func]);
688 for (pnext = pkt; pnext; pnext = pnext->next) {
689 uint pkt_len = pnext->len;
690 pkt_len += 3;
691 pkt_len &= 0xFFFFFFFC;
692
693 if ((write) && (!fifo)) {
694 err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
695 ((u8 *) (pnext->data)),
696 pkt_len);
697 } else if (write) {
698 err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
699 ((u8 *) (pnext->data)),
700 pkt_len);
701 } else if (fifo) {
702 err_ret = sdio_readsb(gInstance->func[func],
703 ((u8 *) (pnext->data)),
704 addr, pkt_len);
705 } else {
706 err_ret = sdio_memcpy_fromio(gInstance->func[func],
707 ((u8 *) (pnext->data)),
708 addr, pkt_len);
709 }
710
711 if (err_ret) {
712 sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d,"
713 "ERR=0x%08x\n", __func__,
714 (write) ? "TX" : "RX",
715 pnext, SGCount, addr, pkt_len, err_ret));
716 } else {
717 sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n",
718 __func__,
719 (write) ? "TX" : "RX",
720 pnext, SGCount, addr, pkt_len));
721 }
722
723 if (!fifo)
724 addr += pkt_len;
725 SGCount++;
726
727 }
728
729 /* Release host controller */
730 sdio_release_host(gInstance->func[func]);
731
732 sd_trace(("%s: Exit\n", __func__));
733 return err_ret;
734 }
735
736 /*
737 * This function takes a buffer or packet, and fixes everything up
738 * so that in the end, a DMA-able packet is created.
739 *
740 * A buffer does not have an associated packet pointer,
741 * and may or may not be aligned.
742 * A packet may consist of a single packet, or a packet chain.
743 * If it is a packet chain, then all the packets in the chain
744 * must be properly aligned.
745 *
746 * If the packet data is not aligned, then there may only be
747 * one packet, and in this case, it is copied to a new
748 * aligned packet.
749 *
750 */
751 extern int
752 brcmf_sdioh_request_buffer(struct sdioh_info *sd, uint pio_dma, uint fix_inc,
753 uint write, uint func, uint addr, uint reg_width,
754 uint buflen_u, u8 *buffer, struct sk_buff *pkt)
755 {
756 int Status;
757 struct sk_buff *mypkt = NULL;
758
759 sd_trace(("%s: Enter\n", __func__));
760
761 BRCMF_PM_RESUME_WAIT(sdioh_request_buffer_wait);
762 BRCMF_PM_RESUME_RETURN_ERROR(-EIO);
763 /* Case 1: we don't have a packet. */
764 if (pkt == NULL) {
765 sd_data(("%s: Creating new %s Packet, len=%d\n",
766 __func__, write ? "TX" : "RX", buflen_u));
767 mypkt = brcmu_pkt_buf_get_skb(buflen_u);
768 if (!mypkt) {
769 sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
770 __func__, buflen_u));
771 return -EIO;
772 }
773
774 /* For a write, copy the buffer data into the packet. */
775 if (write)
776 memcpy(mypkt->data, buffer, buflen_u);
777
778 Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
779 addr, mypkt);
780
781 /* For a read, copy the packet data back to the buffer. */
782 if (!write)
783 memcpy(buffer, mypkt->data, buflen_u);
784
785 brcmu_pkt_buf_free_skb(mypkt);
786 } else if (((ulong) (pkt->data) & DMA_ALIGN_MASK) != 0) {
787 /*
788 * Case 2: We have a packet, but it is unaligned.
789 * In this case, we cannot have a chain (pkt->next == NULL)
790 */
791 sd_data(("%s: Creating aligned %s Packet, len=%d\n",
792 __func__, write ? "TX" : "RX", pkt->len));
793 mypkt = brcmu_pkt_buf_get_skb(pkt->len);
794 if (!mypkt) {
795 sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n",
796 __func__, pkt->len));
797 return -EIO;
798 }
799
800 /* For a write, copy the buffer data into the packet. */
801 if (write)
802 memcpy(mypkt->data, pkt->data, pkt->len);
803
804 Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
805 addr, mypkt);
806
807 /* For a read, copy the packet data back to the buffer. */
808 if (!write)
809 memcpy(pkt->data, mypkt->data, mypkt->len);
810
811 brcmu_pkt_buf_free_skb(mypkt);
812 } else { /* case 3: We have a packet and
813 it is aligned. */
814 sd_data(("%s: Aligned %s Packet, direct DMA\n",
815 __func__, write ? "Tx" : "Rx"));
816 Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func,
817 addr, pkt);
818 }
819
820 return Status;
821 }
822
823 /* this function performs "abort" for both of host & device */
824 extern int brcmf_sdioh_abort(struct sdioh_info *sd, uint func)
825 {
826 char t_func = (char)func;
827 sd_trace(("%s: Enter\n", __func__));
828
829 /* issue abort cmd52 command through F0 */
830 brcmf_sdioh_request_byte(sd, SDIOH_WRITE, SDIO_FUNC_0, SDIO_CCCR_ABORT,
831 &t_func);
832
833 sd_trace(("%s: Exit\n", __func__));
834 return 0;
835 }
836
837 /* Disable device interrupt */
838 void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd)
839 {
840 sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
841 sd->intmask &= ~CLIENT_INTR;
842 }
843
844 /* Enable device interrupt */
845 void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd)
846 {
847 sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
848 sd->intmask |= CLIENT_INTR;
849 }
850
851 /* Read client card reg */
852 int
853 brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr,
854 int regsize, u32 *data)
855 {
856
857 if ((func == 0) || (regsize == 1)) {
858 u8 temp = 0;
859
860 brcmf_sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
861 *data = temp;
862 *data &= 0xff;
863 sd_data(("%s: byte read data=0x%02x\n", __func__, *data));
864 } else {
865 brcmf_sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data,
866 regsize);
867 if (regsize == 2)
868 *data &= 0xffff;
869
870 sd_data(("%s: word read data=0x%08x\n", __func__, *data));
871 }
872
873 return SUCCESS;
874 }
875
876 static void brcmf_sdioh_irqhandler(struct sdio_func *func)
877 {
878 struct sdioh_info *sd;
879
880 sd_trace(("brcmf: ***IRQHandler\n"));
881 sd = gInstance->sd;
882
883 sdio_release_host(gInstance->func[0]);
884
885 if (sd->use_client_ints) {
886 sd->intrcount++;
887 (sd->intr_handler) (sd->intr_handler_arg);
888 } else {
889 sd_err(("brcmf: ***IRQHandler\n"));
890
891 sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
892 __func__, sd->client_intr_enabled, sd->intr_handler));
893 }
894
895 sdio_claim_host(gInstance->func[0]);
896 }
897
898 /* interrupt handler for F2 (dummy handler) */
899 static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func)
900 {
901 struct sdioh_info *sd;
902
903 sd_trace(("brcmf: ***IRQHandlerF2\n"));
904
905 sd = gInstance->sd;
906 }
This page took 0.052981 seconds and 5 git commands to generate.