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