• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &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 
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, &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 
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, &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 
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