1 /* ////////////////////////////////////////////////////////////////////////// */
2 /* */
3 /* Copyright (c) Atmel Corporation. All rights reserved. */
4 /* */
5 /* Module Name: wilc_sdio.c */
6 /* */
7 /* */
8 /* //////////////////////////////////////////////////////////////////////////// */
9
10 #include <linux/string.h>
11 #include "wilc_wlan_if.h"
12 #include "wilc_wlan.h"
13
14 #define WILC_SDIO_BLOCK_SIZE 512
15
16 typedef struct {
17 void *os_context;
18 u32 block_size;
19 int (*sdio_cmd52)(sdio_cmd52_t *);
20 int (*sdio_cmd53)(sdio_cmd53_t *);
21 int (*sdio_set_max_speed)(void);
22 int (*sdio_set_default_speed)(void);
23 wilc_debug_func dPrint;
24 int nint;
25 #define MAX_NUN_INT_THRPT_ENH2 (5) /* Max num interrupts allowed in registers 0xf7, 0xf8 */
26 int has_thrpt_enh3;
27 } wilc_sdio_t;
28
29 static wilc_sdio_t g_sdio;
30
31 #ifdef WILC_SDIO_IRQ_GPIO
32 static int sdio_write_reg(u32 addr, u32 data);
33 static int sdio_read_reg(u32 addr, u32 *data);
34 #endif
35
36 /********************************************
37 *
38 * Function 0
39 *
40 ********************************************/
41
sdio_set_func0_csa_address(u32 adr)42 static int sdio_set_func0_csa_address(u32 adr)
43 {
44 sdio_cmd52_t cmd;
45
46 /**
47 * Review: BIG ENDIAN
48 **/
49 cmd.read_write = 1;
50 cmd.function = 0;
51 cmd.raw = 0;
52 cmd.address = 0x10c;
53 cmd.data = (u8)adr;
54 if (!g_sdio.sdio_cmd52(&cmd)) {
55 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10c data...\n");
56 goto _fail_;
57 }
58
59 cmd.address = 0x10d;
60 cmd.data = (u8)(adr >> 8);
61 if (!g_sdio.sdio_cmd52(&cmd)) {
62 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10d data...\n");
63 goto _fail_;
64 }
65
66 cmd.address = 0x10e;
67 cmd.data = (u8)(adr >> 16);
68 if (!g_sdio.sdio_cmd52(&cmd)) {
69 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10e data...\n");
70 goto _fail_;
71 }
72
73 return 1;
74 _fail_:
75 return 0;
76 }
77
sdio_set_func0_block_size(u32 block_size)78 static int sdio_set_func0_block_size(u32 block_size)
79 {
80 sdio_cmd52_t cmd;
81
82 cmd.read_write = 1;
83 cmd.function = 0;
84 cmd.raw = 0;
85 cmd.address = 0x10;
86 cmd.data = (u8)block_size;
87 if (!g_sdio.sdio_cmd52(&cmd)) {
88 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10 data...\n");
89 goto _fail_;
90 }
91
92 cmd.address = 0x11;
93 cmd.data = (u8)(block_size >> 8);
94 if (!g_sdio.sdio_cmd52(&cmd)) {
95 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x11 data...\n");
96 goto _fail_;
97 }
98
99 return 1;
100 _fail_:
101 return 0;
102 }
103
104 /********************************************
105 *
106 * Function 1
107 *
108 ********************************************/
109
sdio_set_func1_block_size(u32 block_size)110 static int sdio_set_func1_block_size(u32 block_size)
111 {
112 sdio_cmd52_t cmd;
113
114 cmd.read_write = 1;
115 cmd.function = 0;
116 cmd.raw = 0;
117 cmd.address = 0x110;
118 cmd.data = (u8)block_size;
119 if (!g_sdio.sdio_cmd52(&cmd)) {
120 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x110 data...\n");
121 goto _fail_;
122 }
123 cmd.address = 0x111;
124 cmd.data = (u8)(block_size >> 8);
125 if (!g_sdio.sdio_cmd52(&cmd)) {
126 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x111 data...\n");
127 goto _fail_;
128 }
129
130 return 1;
131 _fail_:
132 return 0;
133 }
134
sdio_clear_int(void)135 static int sdio_clear_int(void)
136 {
137 #ifndef WILC_SDIO_IRQ_GPIO
138 /* u32 sts; */
139 sdio_cmd52_t cmd;
140
141 cmd.read_write = 0;
142 cmd.function = 1;
143 cmd.raw = 0;
144 cmd.address = 0x4;
145 cmd.data = 0;
146 g_sdio.sdio_cmd52(&cmd);
147
148 return cmd.data;
149 #else
150 u32 reg;
151
152 if (!sdio_read_reg(WILC_HOST_RX_CTRL_0, ®)) {
153 g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_HOST_RX_CTRL_0);
154 return 0;
155 }
156 reg &= ~0x1;
157 sdio_write_reg(WILC_HOST_RX_CTRL_0, reg);
158 return 1;
159 #endif
160
161 }
162
sdio_xfer_cnt(void)163 u32 sdio_xfer_cnt(void)
164 {
165 u32 cnt = 0;
166 sdio_cmd52_t cmd;
167
168 cmd.read_write = 0;
169 cmd.function = 1;
170 cmd.raw = 0;
171 cmd.address = 0x1C;
172 cmd.data = 0;
173 g_sdio.sdio_cmd52(&cmd);
174 cnt = cmd.data;
175
176 cmd.read_write = 0;
177 cmd.function = 1;
178 cmd.raw = 0;
179 cmd.address = 0x1D;
180 cmd.data = 0;
181 g_sdio.sdio_cmd52(&cmd);
182 cnt |= (cmd.data << 8);
183
184 cmd.read_write = 0;
185 cmd.function = 1;
186 cmd.raw = 0;
187 cmd.address = 0x1E;
188 cmd.data = 0;
189 g_sdio.sdio_cmd52(&cmd);
190 cnt |= (cmd.data << 16);
191
192 return cnt;
193 }
194
195 /********************************************
196 *
197 * Sdio interfaces
198 *
199 ********************************************/
sdio_check_bs(void)200 int sdio_check_bs(void)
201 {
202 sdio_cmd52_t cmd;
203
204 /**
205 * poll until BS is 0
206 **/
207 cmd.read_write = 0;
208 cmd.function = 0;
209 cmd.raw = 0;
210 cmd.address = 0xc;
211 cmd.data = 0;
212 if (!g_sdio.sdio_cmd52(&cmd)) {
213 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, get BS register...\n");
214 goto _fail_;
215 }
216
217 return 1;
218
219 _fail_:
220
221 return 0;
222 }
223
sdio_write_reg(u32 addr,u32 data)224 static int sdio_write_reg(u32 addr, u32 data)
225 {
226 #ifdef BIG_ENDIAN
227 data = BYTE_SWAP(data);
228 #endif
229
230 if ((addr >= 0xf0) && (addr <= 0xff)) {
231 sdio_cmd52_t cmd;
232
233 cmd.read_write = 1;
234 cmd.function = 0;
235 cmd.raw = 0;
236 cmd.address = addr;
237 cmd.data = data;
238 if (!g_sdio.sdio_cmd52(&cmd)) {
239 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd 52, read reg (%08x) ...\n", addr);
240 goto _fail_;
241 }
242 } else {
243 sdio_cmd53_t cmd;
244
245 /**
246 * set the AHB address
247 **/
248 if (!sdio_set_func0_csa_address(addr))
249 goto _fail_;
250
251 cmd.read_write = 1;
252 cmd.function = 0;
253 cmd.address = 0x10f;
254 cmd.block_mode = 0;
255 cmd.increment = 1;
256 cmd.count = 4;
257 cmd.buffer = (u8 *)&data;
258 cmd.block_size = g_sdio.block_size; /* johnny : prevent it from setting unexpected value */
259
260 if (!g_sdio.sdio_cmd53(&cmd)) {
261 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53, write reg (%08x)...\n", addr);
262 goto _fail_;
263 }
264 }
265
266 return 1;
267
268 _fail_:
269
270 return 0;
271 }
272
sdio_write(u32 addr,u8 * buf,u32 size)273 static int sdio_write(u32 addr, u8 *buf, u32 size)
274 {
275 u32 block_size = g_sdio.block_size;
276 sdio_cmd53_t cmd;
277 int nblk, nleft;
278
279 cmd.read_write = 1;
280 if (addr > 0) {
281 /**
282 * has to be word aligned...
283 **/
284 if (size & 0x3) {
285 size += 4;
286 size &= ~0x3;
287 }
288
289 /**
290 * func 0 access
291 **/
292 cmd.function = 0;
293 cmd.address = 0x10f;
294 } else {
295 /**
296 * has to be word aligned...
297 **/
298 if (size & 0x3) {
299 size += 4;
300 size &= ~0x3;
301 }
302
303 /**
304 * func 1 access
305 **/
306 cmd.function = 1;
307 cmd.address = 0;
308 }
309
310 nblk = size / block_size;
311 nleft = size % block_size;
312
313 if (nblk > 0) {
314 cmd.block_mode = 1;
315 cmd.increment = 1;
316 cmd.count = nblk;
317 cmd.buffer = buf;
318 cmd.block_size = block_size;
319 if (addr > 0) {
320 if (!sdio_set_func0_csa_address(addr))
321 goto _fail_;
322 }
323 if (!g_sdio.sdio_cmd53(&cmd)) {
324 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block send...\n", addr);
325 goto _fail_;
326 }
327 if (addr > 0)
328 addr += nblk * block_size;
329 buf += nblk * block_size;
330 }
331
332 if (nleft > 0) {
333 cmd.block_mode = 0;
334 cmd.increment = 1;
335 cmd.count = nleft;
336 cmd.buffer = buf;
337
338 cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */
339
340 if (addr > 0) {
341 if (!sdio_set_func0_csa_address(addr))
342 goto _fail_;
343 }
344 if (!g_sdio.sdio_cmd53(&cmd)) {
345 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], bytes send...\n", addr);
346 goto _fail_;
347 }
348 }
349
350 return 1;
351
352 _fail_:
353
354 return 0;
355 }
356
sdio_read_reg(u32 addr,u32 * data)357 static int sdio_read_reg(u32 addr, u32 *data)
358 {
359 if ((addr >= 0xf0) && (addr <= 0xff)) {
360 sdio_cmd52_t cmd;
361
362 cmd.read_write = 0;
363 cmd.function = 0;
364 cmd.raw = 0;
365 cmd.address = addr;
366 if (!g_sdio.sdio_cmd52(&cmd)) {
367 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd 52, read reg (%08x) ...\n", addr);
368 goto _fail_;
369 }
370 *data = cmd.data;
371 } else {
372 sdio_cmd53_t cmd;
373
374 if (!sdio_set_func0_csa_address(addr))
375 goto _fail_;
376
377 cmd.read_write = 0;
378 cmd.function = 0;
379 cmd.address = 0x10f;
380 cmd.block_mode = 0;
381 cmd.increment = 1;
382 cmd.count = 4;
383 cmd.buffer = (u8 *)data;
384
385 cmd.block_size = g_sdio.block_size; /* johnny : prevent it from setting unexpected value */
386
387 if (!g_sdio.sdio_cmd53(&cmd)) {
388 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53, read reg (%08x)...\n", addr);
389 goto _fail_;
390 }
391 }
392
393 #ifdef BIG_ENDIAN
394 *data = BYTE_SWAP(*data);
395 #endif
396
397 return 1;
398
399 _fail_:
400
401 return 0;
402 }
403
sdio_read(u32 addr,u8 * buf,u32 size)404 static int sdio_read(u32 addr, u8 *buf, u32 size)
405 {
406 u32 block_size = g_sdio.block_size;
407 sdio_cmd53_t cmd;
408 int nblk, nleft;
409
410 cmd.read_write = 0;
411 if (addr > 0) {
412 /**
413 * has to be word aligned...
414 **/
415 if (size & 0x3) {
416 size += 4;
417 size &= ~0x3;
418 }
419
420 /**
421 * func 0 access
422 **/
423 cmd.function = 0;
424 cmd.address = 0x10f;
425 } else {
426 /**
427 * has to be word aligned...
428 **/
429 if (size & 0x3) {
430 size += 4;
431 size &= ~0x3;
432 }
433
434 /**
435 * func 1 access
436 **/
437 cmd.function = 1;
438 cmd.address = 0;
439 }
440
441 nblk = size / block_size;
442 nleft = size % block_size;
443
444 if (nblk > 0) {
445 cmd.block_mode = 1;
446 cmd.increment = 1;
447 cmd.count = nblk;
448 cmd.buffer = buf;
449 cmd.block_size = block_size;
450 if (addr > 0) {
451 if (!sdio_set_func0_csa_address(addr))
452 goto _fail_;
453 }
454 if (!g_sdio.sdio_cmd53(&cmd)) {
455 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr);
456 goto _fail_;
457 }
458 if (addr > 0)
459 addr += nblk * block_size;
460 buf += nblk * block_size;
461 } /* if (nblk > 0) */
462
463 if (nleft > 0) {
464 cmd.block_mode = 0;
465 cmd.increment = 1;
466 cmd.count = nleft;
467 cmd.buffer = buf;
468
469 cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */
470
471 if (addr > 0) {
472 if (!sdio_set_func0_csa_address(addr))
473 goto _fail_;
474 }
475 if (!g_sdio.sdio_cmd53(&cmd)) {
476 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], bytes read...\n", addr);
477 goto _fail_;
478 }
479 }
480
481 return 1;
482
483 _fail_:
484
485 return 0;
486 }
487
488 /********************************************
489 *
490 * Bus interfaces
491 *
492 ********************************************/
493
sdio_deinit(void * pv)494 static int sdio_deinit(void *pv)
495 {
496 return 1;
497 }
498
sdio_sync(void)499 static int sdio_sync(void)
500 {
501 u32 reg;
502
503 /**
504 * Disable power sequencer
505 **/
506 if (!sdio_read_reg(WILC_MISC, ®)) {
507 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read misc reg...\n");
508 return 0;
509 }
510
511 reg &= ~BIT(8);
512 if (!sdio_write_reg(WILC_MISC, reg)) {
513 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write misc reg...\n");
514 return 0;
515 }
516
517 #ifdef WILC_SDIO_IRQ_GPIO
518 {
519 u32 reg;
520 int ret;
521
522 /**
523 * interrupt pin mux select
524 **/
525 ret = sdio_read_reg(WILC_PIN_MUX_0, ®);
526 if (!ret) {
527 g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0);
528 return 0;
529 }
530 reg |= BIT(8);
531 ret = sdio_write_reg(WILC_PIN_MUX_0, reg);
532 if (!ret) {
533 g_sdio.dPrint(N_ERR, "[wilc spi]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0);
534 return 0;
535 }
536
537 /**
538 * interrupt enable
539 **/
540 ret = sdio_read_reg(WILC_INTR_ENABLE, ®);
541 if (!ret) {
542 g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE);
543 return 0;
544 }
545 reg |= BIT(16);
546 ret = sdio_write_reg(WILC_INTR_ENABLE, reg);
547 if (!ret) {
548 g_sdio.dPrint(N_ERR, "[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE);
549 return 0;
550 }
551 }
552 #endif
553
554 return 1;
555 }
556
sdio_init(wilc_wlan_inp_t * inp,wilc_debug_func func)557 static int sdio_init(wilc_wlan_inp_t *inp, wilc_debug_func func)
558 {
559 sdio_cmd52_t cmd;
560 int loop;
561 u32 chipid;
562
563 memset(&g_sdio, 0, sizeof(wilc_sdio_t));
564
565 g_sdio.dPrint = func;
566 g_sdio.os_context = inp->os_context.os_private;
567
568 if (inp->io_func.io_init) {
569 if (!inp->io_func.io_init(g_sdio.os_context)) {
570 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed io init bus...\n");
571 return 0;
572 }
573 } else {
574 return 0;
575 }
576
577 g_sdio.sdio_cmd52 = inp->io_func.u.sdio.sdio_cmd52;
578 g_sdio.sdio_cmd53 = inp->io_func.u.sdio.sdio_cmd53;
579 g_sdio.sdio_set_max_speed = inp->io_func.u.sdio.sdio_set_max_speed;
580 g_sdio.sdio_set_default_speed = inp->io_func.u.sdio.sdio_set_default_speed;
581
582 /**
583 * function 0 csa enable
584 **/
585 cmd.read_write = 1;
586 cmd.function = 0;
587 cmd.raw = 1;
588 cmd.address = 0x100;
589 cmd.data = 0x80;
590 if (!g_sdio.sdio_cmd52(&cmd)) {
591 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, enable csa...\n");
592 goto _fail_;
593 }
594
595 /**
596 * function 0 block size
597 **/
598 if (!sdio_set_func0_block_size(WILC_SDIO_BLOCK_SIZE)) {
599 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, set func 0 block size...\n");
600 goto _fail_;
601 }
602 g_sdio.block_size = WILC_SDIO_BLOCK_SIZE;
603
604 /**
605 * enable func1 IO
606 **/
607 cmd.read_write = 1;
608 cmd.function = 0;
609 cmd.raw = 1;
610 cmd.address = 0x2;
611 cmd.data = 0x2;
612 if (!g_sdio.sdio_cmd52(&cmd)) {
613 g_sdio.dPrint(N_ERR, "[wilc sdio] Fail cmd 52, set IOE register...\n");
614 goto _fail_;
615 }
616
617 /**
618 * make sure func 1 is up
619 **/
620 cmd.read_write = 0;
621 cmd.function = 0;
622 cmd.raw = 0;
623 cmd.address = 0x3;
624 loop = 3;
625 do {
626 cmd.data = 0;
627 if (!g_sdio.sdio_cmd52(&cmd)) {
628 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, get IOR register...\n");
629 goto _fail_;
630 }
631 if (cmd.data == 0x2)
632 break;
633 } while (loop--);
634
635 if (loop <= 0) {
636 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail func 1 is not ready...\n");
637 goto _fail_;
638 }
639
640 /**
641 * func 1 is ready, set func 1 block size
642 **/
643 if (!sdio_set_func1_block_size(WILC_SDIO_BLOCK_SIZE)) {
644 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail set func 1 block size...\n");
645 goto _fail_;
646 }
647
648 /**
649 * func 1 interrupt enable
650 **/
651 cmd.read_write = 1;
652 cmd.function = 0;
653 cmd.raw = 1;
654 cmd.address = 0x4;
655 cmd.data = 0x3;
656 if (!g_sdio.sdio_cmd52(&cmd)) {
657 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, set IEN register...\n");
658 goto _fail_;
659 }
660
661 /**
662 * make sure can read back chip id correctly
663 **/
664 if (!sdio_read_reg(0x1000, &chipid)) {
665 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd read chip id...\n");
666 goto _fail_;
667 }
668 g_sdio.dPrint(N_ERR, "[wilc sdio]: chipid (%08x)\n", chipid);
669 if ((chipid & 0xfff) > 0x2a0)
670 g_sdio.has_thrpt_enh3 = 1;
671 else
672 g_sdio.has_thrpt_enh3 = 0;
673 g_sdio.dPrint(N_ERR, "[wilc sdio]: has_thrpt_enh3 = %d...\n", g_sdio.has_thrpt_enh3);
674
675 return 1;
676
677 _fail_:
678
679 return 0;
680 }
681
sdio_set_max_speed(void)682 static void sdio_set_max_speed(void)
683 {
684 g_sdio.sdio_set_max_speed();
685 }
686
sdio_set_default_speed(void)687 static void sdio_set_default_speed(void)
688 {
689 g_sdio.sdio_set_default_speed();
690 }
691
sdio_read_size(u32 * size)692 static int sdio_read_size(u32 *size)
693 {
694
695 u32 tmp;
696 sdio_cmd52_t cmd;
697
698 /**
699 * Read DMA count in words
700 **/
701 cmd.read_write = 0;
702 cmd.function = 0;
703 cmd.raw = 0;
704 cmd.address = 0xf2;
705 cmd.data = 0;
706 g_sdio.sdio_cmd52(&cmd);
707 tmp = cmd.data;
708
709 /* cmd.read_write = 0; */
710 /* cmd.function = 0; */
711 /* cmd.raw = 0; */
712 cmd.address = 0xf3;
713 cmd.data = 0;
714 g_sdio.sdio_cmd52(&cmd);
715 tmp |= (cmd.data << 8);
716
717 *size = tmp;
718 return 1;
719 }
720
sdio_read_int(u32 * int_status)721 static int sdio_read_int(u32 *int_status)
722 {
723
724 u32 tmp;
725 sdio_cmd52_t cmd;
726
727 sdio_read_size(&tmp);
728
729 /**
730 * Read IRQ flags
731 **/
732 #ifndef WILC_SDIO_IRQ_GPIO
733 cmd.function = 1;
734 cmd.address = 0x04;
735 cmd.data = 0;
736 g_sdio.sdio_cmd52(&cmd);
737
738 if (cmd.data & BIT(0))
739 tmp |= INT_0;
740 if (cmd.data & BIT(2))
741 tmp |= INT_1;
742 if (cmd.data & BIT(3))
743 tmp |= INT_2;
744 if (cmd.data & BIT(4))
745 tmp |= INT_3;
746 if (cmd.data & BIT(5))
747 tmp |= INT_4;
748 if (cmd.data & BIT(6))
749 tmp |= INT_5;
750 {
751 int i;
752
753 for (i = g_sdio.nint; i < MAX_NUM_INT; i++) {
754 if ((tmp >> (IRG_FLAGS_OFFSET + i)) & 0x1) {
755 g_sdio.dPrint(N_ERR, "[wilc sdio]: Unexpected interrupt (1) : tmp=%x, data=%x\n", tmp, cmd.data);
756 break;
757 }
758 }
759 }
760 #else
761 {
762 u32 irq_flags;
763
764 cmd.read_write = 0;
765 cmd.function = 0;
766 cmd.raw = 0;
767 cmd.address = 0xf7;
768 cmd.data = 0;
769 g_sdio.sdio_cmd52(&cmd);
770 irq_flags = cmd.data & 0x1f;
771 tmp |= ((irq_flags >> 0) << IRG_FLAGS_OFFSET);
772 }
773
774 #endif
775
776 *int_status = tmp;
777
778 return 1;
779 }
780
sdio_clear_int_ext(u32 val)781 static int sdio_clear_int_ext(u32 val)
782 {
783 int ret;
784
785 if (g_sdio.has_thrpt_enh3) {
786 u32 reg;
787
788 #ifdef WILC_SDIO_IRQ_GPIO
789 {
790 u32 flags;
791
792 flags = val & (BIT(MAX_NUN_INT_THRPT_ENH2) - 1);
793 reg = flags;
794 }
795 #else
796 reg = 0;
797 #endif
798 /* select VMM table 0 */
799 if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0)
800 reg |= BIT(5);
801 /* select VMM table 1 */
802 if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1)
803 reg |= BIT(6);
804 /* enable VMM */
805 if ((val & EN_VMM) == EN_VMM)
806 reg |= BIT(7);
807 if (reg) {
808 sdio_cmd52_t cmd;
809
810 cmd.read_write = 1;
811 cmd.function = 0;
812 cmd.raw = 0;
813 cmd.address = 0xf8;
814 cmd.data = reg;
815
816 ret = g_sdio.sdio_cmd52(&cmd);
817 if (!ret) {
818 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0xf8 data (%d) ...\n", __LINE__);
819 goto _fail_;
820 }
821
822 }
823 } else {
824 #ifdef WILC_SDIO_IRQ_GPIO
825 {
826 /* see below. has_thrpt_enh2 uses register 0xf8 to clear interrupts. */
827 /* Cannot clear multiple interrupts. Must clear each interrupt individually */
828 u32 flags;
829
830 flags = val & (BIT(MAX_NUM_INT) - 1);
831 if (flags) {
832 int i;
833
834 ret = 1;
835 for (i = 0; i < g_sdio.nint; i++) {
836 if (flags & 1) {
837 sdio_cmd52_t cmd;
838
839 cmd.read_write = 1;
840 cmd.function = 0;
841 cmd.raw = 0;
842 cmd.address = 0xf8;
843 cmd.data = BIT(i);
844
845 ret = g_sdio.sdio_cmd52(&cmd);
846 if (!ret) {
847 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0xf8 data (%d) ...\n", __LINE__);
848 goto _fail_;
849 }
850
851 }
852 if (!ret)
853 break;
854 flags >>= 1;
855 }
856 if (!ret)
857 goto _fail_;
858 for (i = g_sdio.nint; i < MAX_NUM_INT; i++) {
859 if (flags & 1)
860 g_sdio.dPrint(N_ERR, "[wilc sdio]: Unexpected interrupt cleared %d...\n", i);
861 flags >>= 1;
862 }
863 }
864 }
865 #endif /* WILC_SDIO_IRQ_GPIO */
866
867 {
868 u32 vmm_ctl;
869
870 vmm_ctl = 0;
871 /* select VMM table 0 */
872 if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0)
873 vmm_ctl |= BIT(0);
874 /* select VMM table 1 */
875 if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1)
876 vmm_ctl |= BIT(1);
877 /* enable VMM */
878 if ((val & EN_VMM) == EN_VMM)
879 vmm_ctl |= BIT(2);
880
881 if (vmm_ctl) {
882 sdio_cmd52_t cmd;
883
884 cmd.read_write = 1;
885 cmd.function = 0;
886 cmd.raw = 0;
887 cmd.address = 0xf6;
888 cmd.data = vmm_ctl;
889 ret = g_sdio.sdio_cmd52(&cmd);
890 if (!ret) {
891 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0xf6 data (%d) ...\n", __LINE__);
892 goto _fail_;
893 }
894 }
895 }
896 }
897
898 return 1;
899 _fail_:
900 return 0;
901 }
902
sdio_sync_ext(int nint)903 static int sdio_sync_ext(int nint /* how mant interrupts to enable. */)
904 {
905 u32 reg;
906
907 if (nint > MAX_NUM_INT) {
908 g_sdio.dPrint(N_ERR, "[wilc sdio]: Too many interupts (%d)...\n", nint);
909 return 0;
910 }
911 if (nint > MAX_NUN_INT_THRPT_ENH2) {
912 g_sdio.dPrint(N_ERR, "[wilc sdio]: Error: Cannot support more than 5 interrupts when has_thrpt_enh2=1.\n");
913 return 0;
914 }
915
916 g_sdio.nint = nint;
917
918 /**
919 * Disable power sequencer
920 **/
921 if (!sdio_read_reg(WILC_MISC, ®)) {
922 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read misc reg...\n");
923 return 0;
924 }
925
926 reg &= ~BIT(8);
927 if (!sdio_write_reg(WILC_MISC, reg)) {
928 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write misc reg...\n");
929 return 0;
930 }
931
932 #ifdef WILC_SDIO_IRQ_GPIO
933 {
934 u32 reg;
935 int ret, i;
936
937 /**
938 * interrupt pin mux select
939 **/
940 ret = sdio_read_reg(WILC_PIN_MUX_0, ®);
941 if (!ret) {
942 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0);
943 return 0;
944 }
945 reg |= BIT(8);
946 ret = sdio_write_reg(WILC_PIN_MUX_0, reg);
947 if (!ret) {
948 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0);
949 return 0;
950 }
951
952 /**
953 * interrupt enable
954 **/
955 ret = sdio_read_reg(WILC_INTR_ENABLE, ®);
956 if (!ret) {
957 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE);
958 return 0;
959 }
960
961 for (i = 0; (i < 5) && (nint > 0); i++, nint--)
962 reg |= BIT((27 + i));
963 ret = sdio_write_reg(WILC_INTR_ENABLE, reg);
964 if (!ret) {
965 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE);
966 return 0;
967 }
968 if (nint) {
969 ret = sdio_read_reg(WILC_INTR2_ENABLE, ®);
970 if (!ret) {
971 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read reg (%08x)...\n", WILC_INTR2_ENABLE);
972 return 0;
973 }
974
975 for (i = 0; (i < 3) && (nint > 0); i++, nint--)
976 reg |= BIT(i);
977
978 ret = sdio_read_reg(WILC_INTR2_ENABLE, ®);
979 if (!ret) {
980 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_INTR2_ENABLE);
981 return 0;
982 }
983 }
984 }
985 #endif /* WILC_SDIO_IRQ_GPIO */
986 return 1;
987 }
988
989 /********************************************
990 *
991 * Global sdio HIF function table
992 *
993 ********************************************/
994
995 wilc_hif_func_t hif_sdio = {
996 sdio_init,
997 sdio_deinit,
998 sdio_read_reg,
999 sdio_write_reg,
1000 sdio_read,
1001 sdio_write,
1002 sdio_sync,
1003 sdio_clear_int,
1004 sdio_read_int,
1005 sdio_clear_int_ext,
1006 sdio_read_size,
1007 sdio_write,
1008 sdio_read,
1009 sdio_sync_ext,
1010
1011 sdio_set_max_speed,
1012 sdio_set_default_speed,
1013 };
1014
1015