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
16typedef 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
29static wilc_sdio_t g_sdio;
30
31#ifdef WILC_SDIO_IRQ_GPIO
32static int sdio_write_reg(u32 addr, u32 data);
33static int sdio_read_reg(u32 addr, u32 *data);
34#endif
35
36/********************************************
37 *
38 *      Function 0
39 *
40 ********************************************/
41
42static 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
78static 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
110static 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
135static 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, &reg)) {
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
163u32 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 ********************************************/
200int 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
224static 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
273static 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
357static 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
404static 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
494static int sdio_deinit(void *pv)
495{
496	return 1;
497}
498
499static int sdio_sync(void)
500{
501	u32 reg;
502
503	/**
504	 *      Disable power sequencer
505	 **/
506	if (!sdio_read_reg(WILC_MISC, &reg)) {
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, &reg);
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, &reg);
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
557static 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
682static void sdio_set_max_speed(void)
683{
684	g_sdio.sdio_set_max_speed();
685}
686
687static void sdio_set_default_speed(void)
688{
689	g_sdio.sdio_set_default_speed();
690}
691
692static 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
721static 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
781static 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
903static 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, &reg)) {
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, &reg);
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, &reg);
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, &reg);
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, &reg);
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
995wilc_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