1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2017 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15 #define _SDIO_OPS_C_
16
17 #include <rtl8188f_hal.h>
18
19 /* #define SDIO_DEBUG_IO 1 */
20 #define CONFIG_RTW_SDIO_REG_FORCE_CMD52 0
21
22 #define WLAN_IOREG_CMD_ADDR(addr) ((WLAN_IOREG_DEVICE_ID << 13) | ((addr) & WLAN_IOREG_MSK))
23 #define WLAN_TXHIQ_CMD_ADDR(r4_cnt) ((WLAN_TX_HIQ_DEVICE_ID << 13) | ((r4_cnt) & WLAN_FIFO_MSK))
24 #define WLAN_TXMIQ_CMD_ADDR(r4_cnt) ((WLAN_TX_MIQ_DEVICE_ID << 13) | ((r4_cnt) & WLAN_FIFO_MSK))
25 #define WLAN_TXLOQ_CMD_ADDR(r4_cnt) ((WLAN_TX_LOQ_DEVICE_ID << 13) | ((r4_cnt) & WLAN_FIFO_MSK))
26 #define WLAN_TXEXQ_CMD_ADDR(r4_cnt) ((WLAN_TX_EXQ_DEVICE_ID << 13) | ((r4_cnt) & WLAN_FIFO_MSK))
27 #define WLAN_RX0FF_CMD_ADDR(seq) ((WLAN_RX0FF_DEVICE_ID << 13) | ((seq) & WLAN_RX0FF_MSK))
28
29 /*
30 * Description:
31 * The following mapping is for SDIO host local register space.
32 *
33 * Creadted by Roger, 2011.01.31.
34 * */
HalSdioGetCmdAddr8188FSdio(PADAPTER padapter,u8 DeviceID,u32 Addr,u32 * pCmdAddr)35 static void HalSdioGetCmdAddr8188FSdio(
36 PADAPTER padapter,
37 u8 DeviceID,
38 u32 Addr,
39 u32 *pCmdAddr
40 )
41 {
42 switch (DeviceID) {
43 case SDIO_LOCAL_DEVICE_ID:
44 *pCmdAddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (Addr & SDIO_LOCAL_MSK));
45 break;
46
47 case WLAN_IOREG_DEVICE_ID:
48 *pCmdAddr = ((WLAN_IOREG_DEVICE_ID << 13) | (Addr & WLAN_IOREG_MSK));
49 break;
50
51 case WLAN_TX_HIQ_DEVICE_ID:
52 *pCmdAddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
53 break;
54
55 case WLAN_TX_MIQ_DEVICE_ID:
56 *pCmdAddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
57 break;
58
59 case WLAN_TX_LOQ_DEVICE_ID:
60 *pCmdAddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
61 break;
62
63 case WLAN_RX0FF_DEVICE_ID:
64 *pCmdAddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (Addr & WLAN_RX0FF_MSK));
65 break;
66
67 default:
68 break;
69 }
70 }
71
get_deviceid(u32 addr)72 static u8 get_deviceid(u32 addr)
73 {
74 u8 devideId;
75 u16 pseudoId;
76
77
78 pseudoId = (u16)(addr >> 16);
79 switch (pseudoId) {
80 case 0x1025:
81 devideId = SDIO_LOCAL_DEVICE_ID;
82 break;
83
84 case 0x1026:
85 devideId = WLAN_IOREG_DEVICE_ID;
86 break;
87
88 /* case 0x1027:
89 * devideId = SDIO_FIRMWARE_FIFO;
90 * break; */
91
92 case 0x1031:
93 devideId = WLAN_TX_HIQ_DEVICE_ID;
94 break;
95
96 case 0x1032:
97 devideId = WLAN_TX_MIQ_DEVICE_ID;
98 break;
99
100 case 0x1033:
101 devideId = WLAN_TX_LOQ_DEVICE_ID;
102 break;
103
104 case 0x1034:
105 devideId = WLAN_RX0FF_DEVICE_ID;
106 break;
107
108 default:
109 /* devideId = (u8)((addr >> 13) & 0xF); */
110 devideId = WLAN_IOREG_DEVICE_ID;
111 break;
112 }
113
114 return devideId;
115 }
116
117 /*
118 * Ref:
119 * HalSdioGetCmdAddr8188FSdio()
120 */
_cvrt2ftaddr(const u32 addr,u8 * pdeviceId,u16 * poffset)121 static u32 _cvrt2ftaddr(const u32 addr, u8 *pdeviceId, u16 *poffset)
122 {
123 u8 deviceId;
124 u16 offset;
125 u32 ftaddr;
126
127
128 deviceId = get_deviceid(addr);
129 offset = 0;
130
131 switch (deviceId) {
132 case SDIO_LOCAL_DEVICE_ID:
133 offset = addr & SDIO_LOCAL_MSK;
134 break;
135
136 case WLAN_TX_HIQ_DEVICE_ID:
137 case WLAN_TX_MIQ_DEVICE_ID:
138 case WLAN_TX_LOQ_DEVICE_ID:
139 offset = addr & WLAN_FIFO_MSK;
140 break;
141
142 case WLAN_RX0FF_DEVICE_ID:
143 offset = addr & WLAN_RX0FF_MSK;
144 break;
145
146 case WLAN_IOREG_DEVICE_ID:
147 default:
148 deviceId = WLAN_IOREG_DEVICE_ID;
149 offset = addr & WLAN_IOREG_MSK;
150 break;
151 }
152 ftaddr = (deviceId << 13) | offset;
153
154 if (pdeviceId)
155 *pdeviceId = deviceId;
156 if (poffset)
157 *poffset = offset;
158
159 return ftaddr;
160 }
161
162
sdio_read8(struct intf_hdl * pintfhdl,u32 addr)163 u8 sdio_read8(struct intf_hdl *pintfhdl, u32 addr)
164 {
165 u32 ftaddr;
166 u8 device_id;
167 u16 offset;
168 u8 val;
169 u8 sus_leave = _FALSE;
170
171 ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
172
173 if (device_id == WLAN_IOREG_DEVICE_ID && offset < 0x100)
174 sus_leave = sdio_chk_hci_resume(pintfhdl);
175
176 val = sd_read8(pintfhdl, ftaddr, NULL);
177
178 if (sus_leave == _TRUE)
179 sdio_chk_hci_suspend(pintfhdl);
180
181 return val;
182 }
183
sdio_read16(struct intf_hdl * pintfhdl,u32 addr)184 u16 sdio_read16(struct intf_hdl *pintfhdl, u32 addr)
185 {
186 u32 ftaddr;
187 u8 device_id;
188 u16 offset;
189 u16 val;
190 u8 sus_leave = _FALSE;
191
192 ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
193
194 if (device_id == WLAN_IOREG_DEVICE_ID && offset < 0x100)
195 sus_leave = sdio_chk_hci_resume(pintfhdl);
196
197 val = 0;
198 sd_cmd52_read(pintfhdl, ftaddr, 2, (u8 *)&val);
199 val = le16_to_cpu(val);
200
201 if (sus_leave == _TRUE)
202 sdio_chk_hci_suspend(pintfhdl);
203
204 return val;
205 }
206
sdio_read32(struct intf_hdl * pintfhdl,u32 addr)207 u32 sdio_read32(struct intf_hdl *pintfhdl, u32 addr)
208 {
209 PADAPTER padapter;
210 u8 bMacPwrCtrlOn;
211 u8 deviceId;
212 u16 offset;
213 u32 ftaddr;
214 u8 shift;
215 u32 val;
216 s32 err;
217
218
219 padapter = pintfhdl->padapter;
220 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
221
222 bMacPwrCtrlOn = _FALSE;
223 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
224
225 if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
226 || (bMacPwrCtrlOn == _FALSE)
227 #ifdef CONFIG_LPS_LCLK
228 || (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
229 #endif
230 || CONFIG_RTW_SDIO_REG_FORCE_CMD52
231 ) {
232 u8 sus_leave = _FALSE;
233
234 if (deviceId == WLAN_IOREG_DEVICE_ID && offset < 0x100)
235 sus_leave = sdio_chk_hci_resume(pintfhdl);
236
237 val = 0;
238 err = sd_cmd52_read(pintfhdl, ftaddr, 4, (u8 *)&val);
239
240 if (sus_leave == _TRUE)
241 sdio_chk_hci_suspend(pintfhdl);
242
243 #ifdef SDIO_DEBUG_IO
244 if (!err) {
245 #endif
246 val = le32_to_cpu(val);
247 return val;
248 #ifdef SDIO_DEBUG_IO
249 }
250
251 RTW_ERR("%s: Mac Power off, Read FAIL(%d)! addr=0x%x\n", __func__, err, addr);
252 return SDIO_ERR_VAL32;
253 #endif
254 }
255
256 /* 4 bytes alignment */
257 shift = ftaddr & 0x3;
258 if (shift == 0)
259 val = sd_read32(pintfhdl, ftaddr, NULL);
260 else {
261 u8 *ptmpbuf;
262
263 ptmpbuf = (u8 *)rtw_malloc(8);
264 if (NULL == ptmpbuf) {
265 RTW_ERR("%s: Allocate memory FAIL!(size=8) addr=0x%x\n", __func__, addr);
266 return SDIO_ERR_VAL32;
267 }
268
269 ftaddr &= ~(u16)0x3;
270 err = sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
271 if (err)
272 return SDIO_ERR_VAL32;
273 _rtw_memcpy(&val, ptmpbuf + shift, 4);
274 val = le32_to_cpu(val);
275
276 rtw_mfree(ptmpbuf, 8);
277 }
278
279
280 return val;
281 }
282
sdio_readN(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * pbuf)283 s32 sdio_readN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
284 {
285 PADAPTER padapter;
286 u8 bMacPwrCtrlOn;
287 u8 deviceId;
288 u16 offset;
289 u32 ftaddr;
290 u8 shift;
291 s32 err;
292
293
294 padapter = pintfhdl->padapter;
295 err = 0;
296
297 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
298
299 bMacPwrCtrlOn = _FALSE;
300 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
301 if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
302 || (bMacPwrCtrlOn == _FALSE)
303 #ifdef CONFIG_LPS_LCLK
304 || (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
305 #endif
306 || CONFIG_RTW_SDIO_REG_FORCE_CMD52
307 ) {
308 u8 sus_leave = _FALSE;
309
310 if (deviceId == WLAN_IOREG_DEVICE_ID && offset < 0x100)
311 sus_leave = sdio_chk_hci_resume(pintfhdl);
312
313 err = sd_cmd52_read(pintfhdl, ftaddr, cnt, pbuf);
314
315 if (sus_leave == _TRUE)
316 sdio_chk_hci_suspend(pintfhdl);
317
318 return err;
319 }
320
321 /* 4 bytes alignment */
322 shift = ftaddr & 0x3;
323 if (shift == 0)
324 err = sd_read(pintfhdl, ftaddr, cnt, pbuf);
325 else {
326 u8 *ptmpbuf;
327 u32 n;
328
329 ftaddr &= ~(u16)0x3;
330 n = cnt + shift;
331 ptmpbuf = rtw_malloc(n);
332 if (NULL == ptmpbuf)
333 return -1;
334 err = sd_read(pintfhdl, ftaddr, n, ptmpbuf);
335 if (!err)
336 _rtw_memcpy(pbuf, ptmpbuf + shift, cnt);
337 rtw_mfree(ptmpbuf, n);
338 }
339
340
341 return err;
342 }
343
sdio_write8(struct intf_hdl * pintfhdl,u32 addr,u8 val)344 s32 sdio_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
345 {
346 u32 ftaddr;
347 u8 device_id;
348 u16 offset;
349 s32 err;
350 u8 sus_leave = _FALSE;
351
352 ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
353
354 if (device_id == WLAN_IOREG_DEVICE_ID && offset < 0x100)
355 sus_leave = sdio_chk_hci_resume(pintfhdl);
356
357 err = 0;
358 sd_write8(pintfhdl, ftaddr, val, &err);
359
360 if (sus_leave == _TRUE)
361 sdio_chk_hci_suspend(pintfhdl);
362
363 return err;
364 }
365
sdio_write16(struct intf_hdl * pintfhdl,u32 addr,u16 val)366 s32 sdio_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
367 {
368 u32 ftaddr;
369 u8 device_id;
370 u16 offset;
371 s32 err;
372 u8 sus_leave = _FALSE;
373
374 ftaddr = _cvrt2ftaddr(addr, &device_id, &offset);
375
376 if (device_id == WLAN_IOREG_DEVICE_ID && offset < 0x100)
377 sus_leave = sdio_chk_hci_resume(pintfhdl);
378
379 val = cpu_to_le16(val);
380 err = sd_cmd52_write(pintfhdl, ftaddr, 2, (u8 *)&val);
381
382 if (sus_leave == _TRUE)
383 sdio_chk_hci_suspend(pintfhdl);
384
385 return err;
386 }
387
sdio_write32(struct intf_hdl * pintfhdl,u32 addr,u32 val)388 s32 sdio_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
389 {
390 PADAPTER padapter;
391 u8 bMacPwrCtrlOn;
392 u8 deviceId;
393 u16 offset;
394 u32 ftaddr;
395 u8 shift;
396 s32 err;
397
398
399 padapter = pintfhdl->padapter;
400 err = 0;
401
402 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
403
404 bMacPwrCtrlOn = _FALSE;
405 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
406
407 if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
408 || (bMacPwrCtrlOn == _FALSE)
409 #ifdef CONFIG_LPS_LCLK
410 || (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
411 #endif
412 || CONFIG_RTW_SDIO_REG_FORCE_CMD52
413 ) {
414 u8 sus_leave = _FALSE;
415
416 if (deviceId == WLAN_IOREG_DEVICE_ID && offset < 0x100)
417 sus_leave = sdio_chk_hci_resume(pintfhdl);
418
419 val = cpu_to_le32(val);
420 err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&val);
421
422 if (sus_leave == _TRUE)
423 sdio_chk_hci_suspend(pintfhdl);
424
425 return err;
426 }
427
428 /* 4 bytes alignment */
429 shift = ftaddr & 0x3;
430 #if 1
431 if (shift == 0)
432 sd_write32(pintfhdl, ftaddr, val, &err);
433 else {
434 val = cpu_to_le32(val);
435 err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&val);
436 }
437 #else
438 if (shift == 0)
439 sd_write32(pintfhdl, ftaddr, val, &err);
440 else {
441 u8 *ptmpbuf;
442
443 ptmpbuf = (u8 *)rtw_malloc(8);
444 if (NULL == ptmpbuf)
445 return -1;
446
447 ftaddr &= ~(u16)0x3;
448 err = sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
449 if (err) {
450 rtw_mfree(ptmpbuf, 8);
451 return err;
452 }
453 val = cpu_to_le32(val);
454 _rtw_memcpy(ptmpbuf + shift, &val, 4);
455 err = sd_write(pintfhdl, ftaddr, 8, ptmpbuf);
456
457 rtw_mfree(ptmpbuf, 8);
458 }
459 #endif
460
461
462 return err;
463 }
464
sdio_writeN(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * pbuf)465 s32 sdio_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
466 {
467 PADAPTER padapter;
468 u8 bMacPwrCtrlOn;
469 u8 deviceId;
470 u16 offset;
471 u32 ftaddr;
472 u8 shift;
473 s32 err;
474
475
476 padapter = pintfhdl->padapter;
477 err = 0;
478
479 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
480
481 bMacPwrCtrlOn = _FALSE;
482 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
483 if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
484 || (bMacPwrCtrlOn == _FALSE)
485 #ifdef CONFIG_LPS_LCLK
486 || (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
487 #endif
488 || CONFIG_RTW_SDIO_REG_FORCE_CMD52
489 ) {
490 u8 sus_leave = _FALSE;
491
492 if (deviceId == WLAN_IOREG_DEVICE_ID && offset < 0x100)
493 sus_leave = sdio_chk_hci_resume(pintfhdl);
494
495 err = sd_cmd52_write(pintfhdl, ftaddr, cnt, pbuf);
496
497 if (sus_leave == _TRUE)
498 sdio_chk_hci_suspend(pintfhdl);
499
500 return err;
501 }
502
503 shift = ftaddr & 0x3;
504 if (shift == 0)
505 err = sd_write(pintfhdl, ftaddr, cnt, pbuf);
506 else {
507 u8 *ptmpbuf;
508 u32 n;
509
510 ftaddr &= ~(u16)0x3;
511 n = cnt + shift;
512 ptmpbuf = rtw_malloc(n);
513 if (NULL == ptmpbuf)
514 return -1;
515 err = sd_read(pintfhdl, ftaddr, 4, ptmpbuf);
516 if (err) {
517 rtw_mfree(ptmpbuf, n);
518 return err;
519 }
520 _rtw_memcpy(ptmpbuf + shift, pbuf, cnt);
521 err = sd_write(pintfhdl, ftaddr, n, ptmpbuf);
522 rtw_mfree(ptmpbuf, n);
523 }
524
525
526 return err;
527 }
528
sdio_f0_read8(struct intf_hdl * pintfhdl,u32 addr)529 u8 sdio_f0_read8(struct intf_hdl *pintfhdl, u32 addr)
530 {
531 u32 ftaddr;
532 u8 val;
533
534 val = sd_f0_read8(pintfhdl, addr, NULL);
535
536
537 return val;
538 }
539
sdio_read_mem(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * rmem)540 void sdio_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
541 {
542 s32 err;
543
544
545 err = sdio_readN(pintfhdl, addr, cnt, rmem);
546
547 }
548
sdio_write_mem(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * wmem)549 void sdio_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
550 {
551
552 sdio_writeN(pintfhdl, addr, cnt, wmem);
553
554 }
555
sdio_read_port_no_align(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * mem)556 static u32 sdio_read_port_no_align(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *mem)
557 {
558 PADAPTER padapter;
559 PHAL_DATA_TYPE phal;
560 s32 err;
561
562 padapter = pintfhdl->padapter;
563 phal = GET_HAL_DATA(padapter);
564
565 HalSdioGetCmdAddr8188FSdio(padapter, addr, phal->SdioRxFIFOCnt++, &addr);
566
567 err = _sd_read(pintfhdl, addr, cnt, mem);
568 if (err)
569 return _FAIL;
570 return _SUCCESS;
571 }
572
573 /*
574 * Description:
575 * Read from RX FIFO
576 * Round read size to block size,
577 * and make sure data transfer will be done in one command.
578 *
579 * Parameters:
580 * pintfhdl a pointer of intf_hdl
581 * addr port ID
582 * cnt size to read
583 * rmem address to put data
584 *
585 * Return:
586 * _SUCCESS(1) Success
587 * _FAIL(0) Fail
588 */
sdio_read_port(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * mem)589 static u32 sdio_read_port(
590 struct intf_hdl *pintfhdl,
591 u32 addr,
592 u32 cnt,
593 u8 *mem)
594 {
595 PADAPTER padapter;
596 u32 oldcnt;
597 #ifdef SDIO_DYNAMIC_ALLOC_MEM
598 u8 *oldmem;
599 #endif
600 u32 ret;
601
602 padapter = pintfhdl->padapter;
603
604 oldcnt = cnt;
605 cnt = rtw_sdio_cmd53_align_size(adapter_to_dvobj(padapter), cnt);
606
607 if (oldcnt != cnt) {
608 #ifdef SDIO_DYNAMIC_ALLOC_MEM
609 oldmem = mem;
610 mem = rtw_malloc(cnt);
611 if (mem == NULL) {
612 RTW_WARN("%s: allocate memory %d bytes fail!\n", __func__, cnt);
613 mem = oldmem;
614 oldmem == NULL;
615 }
616 #else
617 /* in this case, caller should gurante the buffer is big enough */
618 /* to receive data after alignment */
619 #endif
620 }
621
622 ret = sdio_read_port_no_align(pintfhdl, addr, cnt, mem);
623
624 #ifdef SDIO_DYNAMIC_ALLOC_MEM
625 if ((oldcnt != cnt) && (oldmem)) {
626 _rtw_memcpy(oldmem, mem, oldcnt);
627 rtw_mfree(mem, cnt);
628 }
629 #endif
630
631 return ret;
632 }
633
634 /*
635 * Description:
636 * Write to TX FIFO
637 * Align write size block size,
638 * and make sure data could be written in one command.
639 *
640 * Parameters:
641 * pintfhdl a pointer of intf_hdl
642 * addr port ID
643 * cnt size to write
644 * wmem data pointer to write
645 *
646 * Return:
647 * _SUCCESS(1) Success
648 * _FAIL(0) Fail
649 */
sdio_write_port(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * mem)650 static u32 sdio_write_port(
651 struct intf_hdl *pintfhdl,
652 u32 addr,
653 u32 cnt,
654 u8 *mem)
655 {
656 PADAPTER padapter;
657 s32 err;
658 struct xmit_buf *xmitbuf = (struct xmit_buf *)mem;
659
660 padapter = pintfhdl->padapter;
661
662 if (!rtw_is_hw_init_completed(padapter)) {
663 RTW_INFO("%s [addr=0x%x cnt=%d] padapter->hw_init_completed == _FALSE\n", __func__, addr, cnt);
664 return _FAIL;
665 }
666
667 cnt = _RND4(cnt);
668 HalSdioGetCmdAddr8188FSdio(padapter, addr, cnt >> 2, &addr);
669
670 cnt = rtw_sdio_cmd53_align_size(adapter_to_dvobj(padapter), cnt);
671
672 err = sd_write(pintfhdl, addr, cnt, xmitbuf->pdata);
673
674 rtw_sctx_done_err(&xmitbuf->sctx,
675 err ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS);
676
677 if (err)
678 return _FAIL;
679 return _SUCCESS;
680 }
681
682 /*
683 * Todo: align address to 4 bytes.
684 */
_sdio_local_read(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)685 s32 _sdio_local_read(
686 PADAPTER padapter,
687 u32 addr,
688 u32 cnt,
689 u8 *pbuf)
690 {
691 struct intf_hdl *pintfhdl;
692 u8 bMacPwrCtrlOn;
693 s32 err;
694 u8 *ptmpbuf;
695 u32 n;
696
697
698 pintfhdl = &padapter->iopriv.intf;
699
700 HalSdioGetCmdAddr8188FSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
701
702 bMacPwrCtrlOn = _FALSE;
703 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
704 if (bMacPwrCtrlOn == _FALSE
705 || CONFIG_RTW_SDIO_REG_FORCE_CMD52
706 ) {
707 err = _sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
708 return err;
709 }
710
711 n = RND4(cnt);
712 ptmpbuf = (u8 *)rtw_malloc(n);
713 if (!ptmpbuf)
714 return -1;
715
716 err = _sd_read(pintfhdl, addr, n, ptmpbuf);
717 if (!err)
718 _rtw_memcpy(pbuf, ptmpbuf, cnt);
719
720 if (ptmpbuf)
721 rtw_mfree(ptmpbuf, n);
722
723 return err;
724 }
725
726 /*
727 * Todo: align address to 4 bytes.
728 */
sdio_local_read(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)729 s32 sdio_local_read(
730 PADAPTER padapter,
731 u32 addr,
732 u32 cnt,
733 u8 *pbuf)
734 {
735 struct intf_hdl *pintfhdl;
736 u8 bMacPwrCtrlOn;
737 s32 err;
738 u8 *ptmpbuf;
739 u32 n;
740
741 pintfhdl = &padapter->iopriv.intf;
742
743 HalSdioGetCmdAddr8188FSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
744
745 bMacPwrCtrlOn = _FALSE;
746 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
747 if ((_FALSE == bMacPwrCtrlOn)
748 #ifdef CONFIG_LPS_LCLK
749 || (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
750 #endif
751 || CONFIG_RTW_SDIO_REG_FORCE_CMD52
752 ) {
753 err = sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
754 return err;
755 }
756
757 n = RND4(cnt);
758 ptmpbuf = (u8 *)rtw_malloc(n);
759 if (!ptmpbuf)
760 return -1;
761
762 err = sd_read(pintfhdl, addr, n, ptmpbuf);
763 if (!err)
764 _rtw_memcpy(pbuf, ptmpbuf, cnt);
765
766 if (ptmpbuf)
767 rtw_mfree(ptmpbuf, n);
768
769 return err;
770 }
771
772 /*
773 * Todo: align address to 4 bytes.
774 */
_sdio_local_write(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)775 s32 _sdio_local_write(
776 PADAPTER padapter,
777 u32 addr,
778 u32 cnt,
779 u8 *pbuf)
780 {
781 struct intf_hdl *pintfhdl;
782 u8 bMacPwrCtrlOn;
783 s32 err;
784 u8 *ptmpbuf;
785
786 if (addr & 0x3)
787 RTW_INFO("%s, address must be 4 bytes alignment\n", __FUNCTION__);
788
789 if (cnt & 0x3)
790 RTW_INFO("%s, size must be the multiple of 4\n", __FUNCTION__);
791
792 pintfhdl = &padapter->iopriv.intf;
793
794 HalSdioGetCmdAddr8188FSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
795
796 bMacPwrCtrlOn = _FALSE;
797 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
798 if ((_FALSE == bMacPwrCtrlOn)
799 #ifdef CONFIG_LPS_LCLK
800 || (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
801 #endif
802 || CONFIG_RTW_SDIO_REG_FORCE_CMD52
803 ) {
804 err = _sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
805 return err;
806 }
807
808 ptmpbuf = (u8 *)rtw_malloc(cnt);
809 if (!ptmpbuf)
810 return -1;
811
812 _rtw_memcpy(ptmpbuf, pbuf, cnt);
813
814 err = _sd_write(pintfhdl, addr, cnt, ptmpbuf);
815
816 if (ptmpbuf)
817 rtw_mfree(ptmpbuf, cnt);
818
819 return err;
820 }
821
822 /*
823 * Todo: align address to 4 bytes.
824 */
sdio_local_write(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)825 s32 sdio_local_write(
826 PADAPTER padapter,
827 u32 addr,
828 u32 cnt,
829 u8 *pbuf)
830 {
831 struct intf_hdl *pintfhdl;
832 u8 bMacPwrCtrlOn;
833 s32 err;
834 u8 *ptmpbuf;
835
836 if (addr & 0x3)
837 RTW_INFO("%s, address must be 4 bytes alignment\n", __FUNCTION__);
838
839 if (cnt & 0x3)
840 RTW_INFO("%s, size must be the multiple of 4\n", __FUNCTION__);
841
842 pintfhdl = &padapter->iopriv.intf;
843
844 HalSdioGetCmdAddr8188FSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
845
846 bMacPwrCtrlOn = _FALSE;
847 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
848 if ((_FALSE == bMacPwrCtrlOn)
849 #ifdef CONFIG_LPS_LCLK
850 || (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
851 #endif
852 || CONFIG_RTW_SDIO_REG_FORCE_CMD52
853 ) {
854 err = sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
855 return err;
856 }
857
858 ptmpbuf = (u8 *)rtw_malloc(cnt);
859 if (!ptmpbuf)
860 return -1;
861
862 _rtw_memcpy(ptmpbuf, pbuf, cnt);
863
864 err = sd_write(pintfhdl, addr, cnt, ptmpbuf);
865
866 if (ptmpbuf)
867 rtw_mfree(ptmpbuf, cnt);
868
869 return err;
870 }
871
SdioLocalCmd52Read1Byte(PADAPTER padapter,u32 addr)872 u8 SdioLocalCmd52Read1Byte(PADAPTER padapter, u32 addr)
873 {
874 u8 val = 0;
875 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
876
877 HalSdioGetCmdAddr8188FSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
878 sd_cmd52_read(pintfhdl, addr, 1, &val);
879
880 return val;
881 }
882
SdioLocalCmd52Read2Byte(PADAPTER padapter,u32 addr)883 u16 SdioLocalCmd52Read2Byte(PADAPTER padapter, u32 addr)
884 {
885 u16 val = 0;
886 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
887
888 HalSdioGetCmdAddr8188FSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
889 sd_cmd52_read(pintfhdl, addr, 2, (u8 *)&val);
890
891 val = le16_to_cpu(val);
892
893 return val;
894 }
895
SdioLocalCmd52Read4Byte(PADAPTER padapter,u32 addr)896 u32 SdioLocalCmd52Read4Byte(PADAPTER padapter, u32 addr)
897 {
898 u32 val = 0;
899 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
900
901 HalSdioGetCmdAddr8188FSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
902 sd_cmd52_read(pintfhdl, addr, 4, (u8 *)&val);
903
904 val = le32_to_cpu(val);
905
906 return val;
907 }
908
SdioLocalCmd53Read4Byte(PADAPTER padapter,u32 addr)909 u32 SdioLocalCmd53Read4Byte(PADAPTER padapter, u32 addr)
910 {
911
912 u8 bMacPwrCtrlOn;
913 u32 val = 0;
914 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
915
916 HalSdioGetCmdAddr8188FSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
917 bMacPwrCtrlOn = _FALSE;
918 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
919 if ((_FALSE == bMacPwrCtrlOn)
920 #ifdef CONFIG_LPS_LCLK
921 || (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
922 #endif
923 || CONFIG_RTW_SDIO_REG_FORCE_CMD52
924 ) {
925 sd_cmd52_read(pintfhdl, addr, 4, (u8 *)&val);
926 val = le32_to_cpu(val);
927 } else
928 val = sd_read32(pintfhdl, addr, NULL);
929
930 return val;
931 }
932
SdioLocalCmd52Write1Byte(PADAPTER padapter,u32 addr,u8 v)933 void SdioLocalCmd52Write1Byte(PADAPTER padapter, u32 addr, u8 v)
934 {
935 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
936
937 HalSdioGetCmdAddr8188FSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
938 sd_cmd52_write(pintfhdl, addr, 1, &v);
939 }
940
SdioLocalCmd52Write2Byte(PADAPTER padapter,u32 addr,u16 v)941 void SdioLocalCmd52Write2Byte(PADAPTER padapter, u32 addr, u16 v)
942 {
943 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
944
945 HalSdioGetCmdAddr8188FSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
946 v = cpu_to_le16(v);
947 sd_cmd52_write(pintfhdl, addr, 2, (u8 *)&v);
948 }
949
SdioLocalCmd52Write4Byte(PADAPTER padapter,u32 addr,u32 v)950 void SdioLocalCmd52Write4Byte(PADAPTER padapter, u32 addr, u32 v)
951 {
952 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
953 HalSdioGetCmdAddr8188FSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
954 v = cpu_to_le32(v);
955 sd_cmd52_write(pintfhdl, addr, 4, (u8 *)&v);
956 }
957
sdio_set_intf_ops(_adapter * padapter,struct _io_ops * pops)958 void sdio_set_intf_ops(_adapter *padapter, struct _io_ops *pops)
959 {
960
961 pops->_read8 = &sdio_read8;
962 pops->_read16 = &sdio_read16;
963 pops->_read32 = &sdio_read32;
964 pops->_read_mem = &sdio_read_mem;
965 pops->_read_port = &sdio_read_port;
966
967 pops->_write8 = &sdio_write8;
968 pops->_write16 = &sdio_write16;
969 pops->_write32 = &sdio_write32;
970 pops->_writeN = &sdio_writeN;
971 pops->_write_mem = &sdio_write_mem;
972 pops->_write_port = &sdio_write_port;
973
974 pops->_sd_f0_read8 = sdio_f0_read8;
975
976 #ifdef CONFIG_SDIO_INDIRECT_ACCESS
977 pops->_sd_iread8 = sdio_iread8;
978 pops->_sd_iread16 = sdio_iread16;
979 pops->_sd_iread32 = sdio_iread32;
980 pops->_sd_iwrite8 = sdio_iwrite8;
981 pops->_sd_iwrite16 = sdio_iwrite16;
982 pops->_sd_iwrite32 = sdio_iwrite32;
983 #endif
984
985 }
986
987 /*
988 * Description:
989 * Initialize SDIO Host Interrupt Mask configuration variables for future use.
990 *
991 * Assumption:
992 * Using SDIO Local register ONLY for configuration.
993 *
994 * Created by Roger, 2011.02.11.
995 * */
InitInterrupt8188FSdio(PADAPTER padapter)996 void InitInterrupt8188FSdio(PADAPTER padapter)
997 {
998 PHAL_DATA_TYPE pHalData;
999
1000 pHalData = GET_HAL_DATA(padapter);
1001 pHalData->sdio_himr = 0
1002 | SDIO_HIMR_RX_REQUEST_MSK
1003 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
1004 | SDIO_HIMR_AVAL_MSK
1005 #endif
1006 #if 0
1007 | SDIO_HIMR_TXERR_MSK
1008 | SDIO_HIMR_RXERR_MSK
1009 | SDIO_HIMR_TXFOVW_MSK
1010 | SDIO_HIMR_RXFOVW_MSK
1011 | SDIO_HIMR_TXBCNOK_MSK
1012 | SDIO_HIMR_TXBCNERR_MSK
1013 | SDIO_HIMR_BCNERLY_INT_MSK
1014 | SDIO_HIMR_C2HCMD_MSK
1015 #endif
1016 #if defined(CONFIG_LPS_LCLK) && !defined(CONFIG_DETECT_CPWM_BY_POLLING)
1017 | SDIO_HIMR_CPWM1_MSK
1018 #endif
1019 #ifdef CONFIG_WOWLAN
1020 | SDIO_HIMR_CPWM2_MSK
1021 #endif
1022 #if 0
1023 | SDIO_HIMR_HSISR_IND_MSK
1024 | SDIO_HIMR_GTINT3_IND_MSK
1025 | SDIO_HIMR_GTINT4_IND_MSK
1026 | SDIO_HIMR_PSTIMEOUT_MSK
1027 | SDIO_HIMR_OCPINT_MSK
1028 | SDIO_HIMR_ATIMEND_MSK
1029 | SDIO_HIMR_ATIMEND_E_MSK
1030 | SDIO_HIMR_CTWEND_MSK
1031 #endif
1032 ;
1033 }
1034
1035 /*
1036 * Description:
1037 * Initialize System Host Interrupt Mask configuration variables for future use.
1038 *
1039 * Created by Roger, 2011.08.03.
1040 * */
InitSysInterrupt8188FSdio(PADAPTER padapter)1041 void InitSysInterrupt8188FSdio(PADAPTER padapter)
1042 {
1043 PHAL_DATA_TYPE pHalData;
1044
1045
1046 pHalData = GET_HAL_DATA(padapter);
1047
1048 pHalData->SysIntrMask = (\
1049 /* HSIMR_GPIO12_0_INT_EN |
1050 * HSIMR_SPS_OCP_INT_EN |
1051 * HSIMR_RON_INT_EN |
1052 * HSIMR_PDNINT_EN |
1053 * HSIMR_GPIO9_INT_EN | */
1054 0);
1055 }
1056
1057 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
1058 /*
1059 * Description:
1060 * Clear corresponding SDIO Host ISR interrupt service.
1061 *
1062 * Assumption:
1063 * Using SDIO Local register ONLY for configuration.
1064 *
1065 * Created by Roger, 2011.02.11.
1066 * */
ClearInterrupt8188FSdio(PADAPTER padapter)1067 void ClearInterrupt8188FSdio(PADAPTER padapter)
1068 {
1069 PHAL_DATA_TYPE pHalData;
1070 u8 *clear;
1071
1072
1073 if (rtw_is_surprise_removed(padapter))
1074 return;
1075
1076 pHalData = GET_HAL_DATA(padapter);
1077 clear = rtw_zmalloc(4);
1078
1079 /* Clear corresponding HISR Content if needed */
1080 *(u32 *)clear = cpu_to_le32(pHalData->sdio_hisr & MASK_SDIO_HISR_CLEAR);
1081 if (*(u32 *)clear) {
1082 /* Perform write one clear operation */
1083 sdio_local_write(padapter, SDIO_REG_HISR, 4, clear);
1084 }
1085
1086 rtw_mfree(clear, 4);
1087 }
1088 #endif
1089
1090 /*
1091 * Description:
1092 * Clear corresponding system Host ISR interrupt service.
1093 *
1094 *
1095 * Created by Roger, 2011.02.11.
1096 * */
ClearSysInterrupt8188FSdio(PADAPTER padapter)1097 void ClearSysInterrupt8188FSdio(PADAPTER padapter)
1098 {
1099 PHAL_DATA_TYPE pHalData;
1100 u32 clear;
1101
1102
1103 if (rtw_is_surprise_removed(padapter))
1104 return;
1105
1106 pHalData = GET_HAL_DATA(padapter);
1107
1108 /* Clear corresponding HISR Content if needed */
1109 clear = pHalData->SysIntrStatus & MASK_HSISR_CLEAR;
1110 if (clear) {
1111 /* Perform write one clear operation */
1112 rtw_write32(padapter, REG_HSISR, clear);
1113 }
1114 }
1115
1116 /*
1117 * Description:
1118 * Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain.
1119 *
1120 * Assumption:
1121 * 1. Using SDIO Local register ONLY for configuration.
1122 * 2. PASSIVE LEVEL
1123 *
1124 * Created by Roger, 2011.02.11.
1125 * */
EnableInterrupt8188FSdio(PADAPTER padapter)1126 void EnableInterrupt8188FSdio(PADAPTER padapter)
1127 {
1128 PHAL_DATA_TYPE pHalData;
1129 u32 himr;
1130
1131 pHalData = GET_HAL_DATA(padapter);
1132
1133 himr = cpu_to_le32(pHalData->sdio_himr);
1134 sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1135
1136
1137 /* Update current system IMR settings */
1138 himr = rtw_read32(padapter, REG_HSIMR);
1139 rtw_write32(padapter, REG_HSIMR, himr | pHalData->SysIntrMask);
1140
1141
1142 /* */
1143 /* <Roger_Notes> There are some C2H CMDs have been sent before system interrupt is enabled, e.g., C2H, CPWM. */
1144 /* So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore. */
1145 /* 2011.10.19. */
1146 /* */
1147 rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
1148 }
1149
1150 /*
1151 * Description:
1152 * Disable SDIO Host IMR configuration to mask unnecessary interrupt service.
1153 *
1154 * Assumption:
1155 * Using SDIO Local register ONLY for configuration.
1156 *
1157 * Created by Roger, 2011.02.11.
1158 * */
DisableInterrupt8188FSdio(PADAPTER padapter)1159 void DisableInterrupt8188FSdio(PADAPTER padapter)
1160 {
1161 u32 himr;
1162
1163 himr = cpu_to_le32(SDIO_HIMR_DISABLED);
1164 sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1165
1166 }
1167
1168 /*
1169 * Description:
1170 * Using 0x100 to check the power status of FW.
1171 *
1172 * Assumption:
1173 * Using SDIO Local register ONLY for configuration.
1174 *
1175 * Created by Isaac, 2013.09.10.
1176 * */
CheckIPSStatus(PADAPTER padapter)1177 u8 CheckIPSStatus(PADAPTER padapter)
1178 {
1179 RTW_INFO("%s(): Read 0x100=0x%02x 0x86=0x%02x\n", __func__,
1180 rtw_read8(padapter, 0x100), rtw_read8(padapter, 0x86));
1181
1182 if (rtw_read8(padapter, 0x100) == 0xEA)
1183 return _TRUE;
1184 else
1185 return _FALSE;
1186 }
1187
1188 #ifdef CONFIG_WOWLAN
DisableInterruptButCpwm28188FSdio(PADAPTER padapter)1189 void DisableInterruptButCpwm28188FSdio(PADAPTER padapter)
1190 {
1191 u32 himr, tmp;
1192
1193 sdio_local_read(padapter, SDIO_REG_HIMR, 4, (u8 *)&tmp);
1194 RTW_INFO("DisableInterruptButCpwm28188FSdio(): Read SDIO_REG_HIMR: 0x%08x\n", tmp);
1195
1196 himr = cpu_to_le32(SDIO_HIMR_DISABLED) | SDIO_HIMR_CPWM2_MSK;
1197 sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1198
1199 sdio_local_read(padapter, SDIO_REG_HIMR, 4, (u8 *)&tmp);
1200 RTW_INFO("DisableInterruptButCpwm28188FSdio(): Read again SDIO_REG_HIMR: 0x%08x\n", tmp);
1201 }
1202 #endif /* CONFIG_WOWLAN
1203 *
1204 * Description:
1205 * Update SDIO Host Interrupt Mask configuration on SDIO local domain.
1206 *
1207 * Assumption:
1208 * 1. Using SDIO Local register ONLY for configuration.
1209 * 2. PASSIVE LEVEL
1210 *
1211 * Created by Roger, 2011.02.11.
1212 * */
UpdateInterruptMask8188FSdio(PADAPTER padapter,u32 AddMSR,u32 RemoveMSR)1213 void UpdateInterruptMask8188FSdio(PADAPTER padapter, u32 AddMSR, u32 RemoveMSR)
1214 {
1215 HAL_DATA_TYPE *pHalData;
1216
1217 pHalData = GET_HAL_DATA(padapter);
1218
1219 if (AddMSR)
1220 pHalData->sdio_himr |= AddMSR;
1221
1222 if (RemoveMSR)
1223 pHalData->sdio_himr &= (~RemoveMSR);
1224
1225 DisableInterrupt8188FSdio(padapter);
1226 EnableInterrupt8188FSdio(padapter);
1227 }
1228
1229 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
sd_recv_loopback(PADAPTER padapter,u32 size)1230 static void sd_recv_loopback(PADAPTER padapter, u32 size)
1231 {
1232 PLOOPBACKDATA ploopback;
1233 u32 readsize, allocsize;
1234 u8 *preadbuf;
1235
1236
1237 readsize = size;
1238 RTW_INFO("%s: read size=%d\n", __func__, readsize);
1239 allocsize = _RND(readsize, rtw_sdio_get_block_size(adapter_to_dvobj(padapter)));
1240
1241 ploopback = padapter->ploopback;
1242 if (ploopback) {
1243 ploopback->rxsize = readsize;
1244 preadbuf = ploopback->rxbuf;
1245 } else {
1246 preadbuf = rtw_malloc(allocsize);
1247 if (preadbuf == NULL) {
1248 RTW_INFO("%s: malloc fail size=%d\n", __func__, allocsize);
1249 return;
1250 }
1251 }
1252
1253 /* rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); */
1254 sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1255
1256 if (ploopback)
1257 _rtw_up_sema(&ploopback->sema);
1258 else {
1259 u32 i;
1260
1261 RTW_INFO("%s: drop pkt\n", __func__);
1262 for (i = 0; i < readsize; i += 4) {
1263 RTW_INFO("%08X", *(u32 *)(preadbuf + i));
1264 if ((i + 4) & 0x1F)
1265 printk(" ");
1266 else
1267 printk("\n");
1268 }
1269 printk("\n");
1270 rtw_mfree(preadbuf, allocsize);
1271 }
1272 }
1273 #endif /* CONFIG_MAC_LOOPBACK_DRIVER */
1274
1275 #ifdef CONFIG_SDIO_RX_COPY
sd_recv_alloc_buf(_adapter * adapter,u32 size,struct recv_buf ** recvbuf_ret)1276 static u32 sd_recv_alloc_buf(_adapter *adapter, u32 size, struct recv_buf **recvbuf_ret)
1277 {
1278 #ifndef CONFIG_TEST_RBUF_UNAVAIL
1279 #define CONFIG_TEST_RBUF_UNAVAIL 0
1280 #endif
1281
1282 #if CONFIG_TEST_RBUF_UNAVAIL
1283 #define TEST_RBUF_UNAVAIL_CYCLE_MS (10 * 1000)
1284 #define TEST_RBUF_UNAVAIL_TIME_MS (50)
1285 static systime test_start = 0;
1286 #endif
1287 struct recv_priv *precvpriv;
1288 struct recv_buf *precvbuf;
1289 u32 ret;
1290
1291 *recvbuf_ret = NULL;
1292
1293 #if CONFIG_TEST_RBUF_UNAVAIL
1294 if (test_start == 0)
1295 test_start = rtw_get_current_time();
1296
1297 if (rtw_get_passing_time_ms(test_start) >= TEST_RBUF_UNAVAIL_CYCLE_MS) {
1298 if (rtw_get_passing_time_ms(test_start) >= TEST_RBUF_UNAVAIL_CYCLE_MS + TEST_RBUF_UNAVAIL_TIME_MS)
1299 test_start = rtw_get_current_time();
1300 ret = RTW_RBUF_UNAVAIL;
1301 goto exit;
1302 }
1303 #endif
1304
1305 precvpriv = &adapter->recvpriv;
1306 #ifdef CONFIG_SDIO_RECVBUF_PWAIT_RUNTIME_ADJUST
1307 alloc_recvbuf:
1308 #endif
1309 /* alloc recvbuf */
1310 precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
1311 if (precvbuf == NULL) {
1312 if (0)
1313 RTW_INFO("%s: recvbuf unavailable\n", __func__);
1314 ret = RTW_RBUF_UNAVAIL;
1315 goto exit;
1316 }
1317
1318 #ifdef CONFIG_SDIO_RECVBUF_PWAIT_RUNTIME_ADJUST
1319 if (precvbuf->type == RBUF_TYPE_PWAIT_ADJ) {
1320 recvbuf_pwait_config_hdl(precvpriv, precvbuf);
1321 goto alloc_recvbuf;
1322 }
1323 #endif
1324
1325 if (precvbuf->pskb == NULL) {
1326 /* alloc skb */
1327 SIZE_PTR tmpaddr = 0;
1328 SIZE_PTR alignment = 0;
1329
1330 precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
1331 if (precvbuf->pskb == NULL) {
1332 RTW_INFO("%s: alloc_skb fail! size=%d\n", __func__, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
1333 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
1334 ret = RTW_RBUF_PKT_UNAVAIL;
1335 goto exit;
1336 }
1337
1338 precvbuf->pskb->dev = adapter->pnetdev;
1339
1340 tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
1341 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
1342 skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
1343
1344 /* init recvbuf */
1345 precvbuf->phead = precvbuf->pskb->head;
1346 precvbuf->pdata = precvbuf->pskb->data;
1347 precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1348 precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1349 precvbuf->len = 0;
1350
1351 } else {
1352 /* reset recvbuf to len 0*/
1353 precvbuf->len = 0;
1354 precvbuf->pdata = precvbuf->pskb->data;
1355 skb_set_tail_pointer(precvbuf->pskb, 0);
1356 precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1357 }
1358
1359 *recvbuf_ret = precvbuf;
1360 ret = _SUCCESS;
1361
1362 exit:
1363 return ret;
1364 }
1365
sd_recv_rxfifo(_adapter * adapter,struct recv_buf * rbuf,u32 read_sz,u32 ocp_sz)1366 static u32 sd_recv_rxfifo(_adapter *adapter, struct recv_buf *rbuf, u32 read_sz, u32 ocp_sz)
1367 {
1368 struct recv_priv *precvpriv = &adapter->recvpriv;
1369 u32 ret;
1370
1371 /* read data from rxfifo */
1372 /* rtw_read_port(adapter, WLAN_RX0FF_DEVICE_ID, read_sz, rbuf->data); */
1373 ret = sdio_read_port_no_align(&adapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, read_sz, rbuf->ptail);
1374 if (ret == _FAIL) {
1375 rtw_enqueue_recvbuf(rbuf, &precvpriv->free_recv_buf_queue);
1376 goto exit;
1377 }
1378
1379 /* increase recvbuf len */
1380 skb_put(rbuf->pskb, ocp_sz);
1381 rbuf->ptail = skb_tail_pointer(rbuf->pskb);
1382 rbuf->len += ocp_sz;
1383
1384 exit:
1385 return ret;
1386 }
1387 #else /* !CONFIG_SDIO_RX_COPY */
sd_recv_rxfifo(PADAPTER padapter,u32 size)1388 static struct recv_buf *sd_recv_rxfifo(PADAPTER padapter, u32 size)
1389 {
1390 u32 readsize, allocsize, ret;
1391 u8 *preadbuf;
1392 _pkt *ppkt;
1393 struct recv_priv *precvpriv;
1394 struct recv_buf *precvbuf;
1395
1396 /* 3 1. alloc skb */
1397 /* align to block size */
1398 allocsize = rtw_sdio_cmd53_align_size(adapter_to_dvobj(padapter), readsize);
1399
1400 ppkt = rtw_skb_alloc(allocsize);
1401
1402 if (ppkt == NULL) {
1403 return NULL;
1404 }
1405
1406 /* 3 2. read data from rxfifo */
1407 preadbuf = skb_put(ppkt, size);
1408 /* rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); */
1409 ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1410 if (ret == _FAIL) {
1411 rtw_skb_free(ppkt);
1412 return NULL;
1413 }
1414
1415 /* 3 3. alloc recvbuf */
1416 precvpriv = &padapter->recvpriv;
1417 precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
1418 if (precvbuf == NULL) {
1419 rtw_skb_free(ppkt);
1420 RTW_ERR("%s: alloc recvbuf FAIL!\n", __FUNCTION__);
1421 return NULL;
1422 }
1423
1424 /* 3 4. init recvbuf */
1425 precvbuf->pskb = ppkt;
1426
1427 precvbuf->len = ppkt->len;
1428
1429 precvbuf->phead = ppkt->head;
1430 precvbuf->pdata = ppkt->data;
1431 precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1432 precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1433
1434 return precvbuf;
1435 }
1436 #endif /* !CONFIG_SDIO_RX_COPY */
1437
sd_rxhandler(PADAPTER padapter,struct recv_buf * precvbuf)1438 static void sd_rxhandler(PADAPTER padapter, struct recv_buf *precvbuf)
1439 {
1440 struct recv_priv *precvpriv;
1441 _queue *ppending_queue;
1442
1443
1444 precvpriv = &padapter->recvpriv;
1445 ppending_queue = &precvpriv->recv_buf_pending_queue;
1446
1447 /* 3 1. enqueue recvbuf */
1448 rtw_enqueue_recvbuf(precvbuf, ppending_queue);
1449
1450 /* 3 2. trigger recv hdl */
1451 #ifdef CONFIG_RECV_THREAD_MODE
1452 _rtw_up_sema(&precvpriv->recv_sema);
1453 #else
1454 #ifdef PLATFORM_LINUX
1455 tasklet_schedule(&precvpriv->recv_tasklet);
1456 #endif
1457 #endif
1458 }
1459
1460 #ifndef SD_INT_HDL_DIS_HIMR_RX_REQ
1461 #define SD_INT_HDL_DIS_HIMR_RX_REQ 0
1462 #endif
1463
1464 #ifndef CMD52_ACCESS_HISR_RX_REQ_LEN
1465 #define CMD52_ACCESS_HISR_RX_REQ_LEN 0
1466 #endif
1467
1468 #if SD_INT_HDL_DIS_HIMR_RX_REQ
1469 #define DIS_HIMR_RX_REQ_WITH_CMD52 1
disable_himr_rx_req_8188f_sdio(_adapter * adapter)1470 static void disable_himr_rx_req_8188f_sdio(_adapter *adapter)
1471 {
1472 HAL_DATA_TYPE *hal = GET_HAL_DATA(adapter);
1473 u32 himr = cpu_to_le32(hal->sdio_himr & ~SDIO_HISR_RX_REQUEST);
1474
1475 #if DIS_HIMR_RX_REQ_WITH_CMD52
1476 SdioLocalCmd52Write1Byte(adapter, SDIO_REG_HIMR, *((u8 *)&himr));
1477 #else
1478 sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1479 #endif
1480 }
1481
restore_himr_8188f_sdio(_adapter * adapter)1482 static void restore_himr_8188f_sdio(_adapter *adapter)
1483 {
1484 HAL_DATA_TYPE *hal = GET_HAL_DATA(adapter);
1485 u32 himr = cpu_to_le32(hal->sdio_himr);
1486
1487 #if DIS_HIMR_RX_REQ_WITH_CMD52
1488 SdioLocalCmd52Write1Byte(adapter, SDIO_REG_HIMR, *((u8 *)&himr));
1489 #else
1490 sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1491 #endif
1492 }
1493 #endif /* SD_INT_HDL_DIS_HIMR_RX_REQ */
1494
1495 #if CMD52_ACCESS_HISR_RX_REQ_LEN
ReadInterrupt8188FSdio(PADAPTER padapter,u32 * phisr)1496 static s32 ReadInterrupt8188FSdio(PADAPTER padapter, u32 *phisr)
1497 {
1498 u32 hisr, himr;
1499 u8 val8, hisr_len;
1500 int i;
1501
1502 if (phisr == NULL)
1503 return _FALSE;
1504
1505 himr = GET_HAL_DATA(padapter)->sdio_himr;
1506
1507 /* decide how many bytes need to be read */
1508 hisr_len = 0;
1509 while (himr) {
1510 hisr_len++;
1511 himr >>= 8;
1512 }
1513
1514 hisr = 0;
1515 for (i = 0; i < hisr_len; i++) {
1516 val8 = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HISR + i);
1517 hisr |= (val8 << (8 * i));
1518 }
1519
1520 *phisr = hisr;
1521
1522 return _TRUE;
1523 }
1524 #endif /* CMD52_ACCESS_HISR_RX_REQ_LEN */
1525
sd_recv(_adapter * adapter)1526 void sd_recv(_adapter *adapter)
1527 {
1528 PHAL_DATA_TYPE phal = GET_HAL_DATA(adapter);
1529 struct recv_priv *recvpriv = &adapter->recvpriv;
1530 struct recv_buf *rbuf = NULL;
1531 u32 read_sz, ocp_sz, buf_sz;
1532 u32 recv_fail_cnt = 0;
1533 u32 rx_cnt = 0;
1534 u32 ret;
1535
1536 do {
1537 if (phal->SdioRxFIFOSize == 0) {
1538 #if CMD52_ACCESS_HISR_RX_REQ_LEN
1539 u16 rx_req_len;
1540
1541 rx_req_len = SdioLocalCmd52Read2Byte(adapter, SDIO_REG_RX0_REQ_LEN);
1542 if (rx_req_len) {
1543 if (rx_req_len % 256 == 0)
1544 rx_req_len += SdioLocalCmd52Read1Byte(adapter, SDIO_REG_RX0_REQ_LEN);
1545 phal->SdioRxFIFOSize = rx_req_len;
1546 }
1547 #else
1548 u8 data[4];
1549
1550 _sdio_local_read(adapter, SDIO_REG_RX0_REQ_LEN, 4, data);
1551 phal->SdioRxFIFOSize = le16_to_cpu(*(u16 *)data);
1552 #endif
1553
1554 if (phal->SdioRxFIFOSize == 0)
1555 break;
1556 }
1557
1558 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
1559 sd_recv_loopback(adapter, phal->SdioRxFIFOSize);
1560 #else
1561 read_sz = rtw_sdio_cmd53_align_size(adapter_to_dvobj(adapter), phal->SdioRxFIFOSize);
1562 read_sz = RND4(read_sz); /* Patch for some SDIO Host 4 bytes issue, ex. RK3188 */
1563 ocp_sz = _RND8(phal->SdioRxFIFOSize);
1564 buf_sz = rtw_max(read_sz, ocp_sz);
1565 if (buf_sz > MAX_RECVBUF_SZ) {
1566 RTW_INFO(FUNC_ADPT_FMT" %u > MAX_RECVBUF_SZ(%u)\n", FUNC_ADPT_ARG(adapter), buf_sz, MAX_RECVBUF_SZ);
1567 rtw_warn_on(1);
1568 }
1569
1570 if (rbuf
1571 && (!recv_buf_agg(recvpriv)
1572 || _rtw_queue_empty(&recvpriv->recv_buf_pending_queue)
1573 || rbuf->ptail + buf_sz > rbuf->pend
1574 )
1575 ) {
1576 sd_rxhandler(adapter, rbuf);
1577 rbuf = NULL;
1578 }
1579
1580 if (!rbuf) {
1581 struct rtw_pwait_ctx *pwctx = &recvpriv->recvbuf_pwait;
1582
1583 rtw_pwctx_reset(pwctx);
1584 while (sd_recv_alloc_buf(adapter, buf_sz, &rbuf) != _SUCCESS) {
1585 if (rtw_pwctx_exceed(&recvpriv->recvbuf_pwait)) {
1586 if (rx_cnt)
1587 break;
1588 }
1589 rtw_pwctx_wait(&recvpriv->recvbuf_pwait);
1590 }
1591 if (!rbuf)
1592 break;
1593 }
1594
1595 ret = sd_recv_rxfifo(adapter, rbuf, read_sz, ocp_sz);
1596 if (ret == _SUCCESS) {
1597 if (!recv_buf_agg(recvpriv)
1598 || _rtw_queue_empty(&recvpriv->recv_buf_pending_queue)
1599 || rbuf->ptail >= rbuf->pend
1600 ) {
1601 sd_rxhandler(adapter, rbuf);
1602 rbuf = NULL;
1603 }
1604 rx_cnt++;
1605 phal->SdioRxFIFOSize = 0;
1606 } else {
1607 recv_fail_cnt++;
1608 RTW_WARN("%s: recv fail! cnt:%u\n", __func__, recv_fail_cnt);
1609 phal->SdioRxFIFOSize = 0;
1610 if (recv_fail_cnt >= 10) {
1611 RTW_WARN("%s: exit because recv_fail_cnt=%u! (rx_cnt=%u)\n"
1612 , __func__, recv_fail_cnt, rx_cnt);
1613 break;
1614 }
1615 }
1616 #endif
1617 } while (1);
1618
1619 if (rbuf)
1620 sd_rxhandler(adapter, rbuf);
1621 }
1622
sd_int_dpc(PADAPTER padapter)1623 void sd_int_dpc(PADAPTER padapter)
1624 {
1625 PHAL_DATA_TYPE phal;
1626 struct dvobj_priv *dvobj;
1627 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
1628 struct pwrctrl_priv *pwrctl;
1629
1630
1631 phal = GET_HAL_DATA(padapter);
1632 dvobj = adapter_to_dvobj(padapter);
1633 pwrctl = dvobj_to_pwrctl(dvobj);
1634
1635 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
1636 if (phal->sdio_hisr & SDIO_HISR_AVAL) {
1637 u8 freepage[8];
1638
1639 _sdio_local_read(padapter, SDIO_REG_FREE_TXPG, 8, freepage);
1640 #ifdef DBG_TX_FREE_PAGE
1641 RTW_INFO("SDIO_HISR_AVAL, Tx Free Page = H:%u, M:%u, L:%u, P:%u\n",
1642 freepage[0], freepage[2], freepage[4], freepage[6]);
1643 #endif
1644
1645 _rtw_up_sema(&(padapter->xmitpriv.xmit_sema));
1646 }
1647 #endif
1648
1649 if (phal->sdio_hisr & SDIO_HISR_CPWM1) {
1650 struct reportpwrstate_parm report;
1651
1652 #ifdef CONFIG_LPS_RPWM_TIMER
1653 _cancel_timer_ex(&(pwrctl->pwr_rpwm_timer));
1654 #endif /* CONFIG_LPS_RPWM_TIMER */
1655
1656 report.state = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HCPWM1_8188F);
1657
1658 #ifdef CONFIG_LPS_LCLK
1659 /* cpwm_int_hdl(padapter, &report); */
1660 _set_workitem(&(pwrctl->cpwm_event));
1661 #endif
1662 }
1663
1664 if (phal->sdio_hisr & SDIO_HISR_TXERR) {
1665 u8 *status;
1666 u32 addr;
1667
1668 status = rtw_malloc(4);
1669 if (status) {
1670 addr = REG_TXDMA_STATUS;
1671 HalSdioGetCmdAddr8188FSdio(padapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
1672 _sd_read(pintfhdl, addr, 4, status);
1673 _sd_write(pintfhdl, addr, 4, status);
1674 RTW_INFO("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32 *)status));
1675 rtw_mfree(status, 4);
1676 } else
1677 RTW_INFO("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__);
1678 }
1679
1680 if (phal->sdio_hisr & SDIO_HISR_TXBCNOK)
1681 RTW_INFO("%s: SDIO_HISR_TXBCNOK\n", __func__);
1682
1683 if (phal->sdio_hisr & SDIO_HISR_TXBCNERR)
1684 RTW_INFO("%s: SDIO_HISR_TXBCNERR\n", __func__);
1685
1686 #ifdef CONFIG_FW_C2H_REG
1687 if (phal->sdio_hisr & SDIO_HISR_C2HCMD) {
1688 RTW_INFO("%s: C2H Command\n", __func__);
1689 sd_c2h_hisr_hdl(padapter);
1690 }
1691 #endif
1692
1693 if (phal->sdio_hisr & SDIO_HISR_RXFOVW)
1694 RTW_INFO("%s: Rx Overflow\n", __func__);
1695 if (phal->sdio_hisr & SDIO_HISR_RXERR)
1696 RTW_INFO("%s: Rx Error\n", __func__);
1697
1698 if (phal->sdio_hisr & SDIO_HISR_RX_REQUEST) {
1699 phal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
1700 sd_recv(padapter);
1701 }
1702 }
1703
1704 #ifndef DBG_SD_INT_HISR_HIMR
1705 #define DBG_SD_INT_HISR_HIMR 0
1706 #endif
1707
sd_int_hdl(PADAPTER padapter)1708 void sd_int_hdl(PADAPTER padapter)
1709 {
1710 PHAL_DATA_TYPE phal;
1711 #if !CMD52_ACCESS_HISR_RX_REQ_LEN
1712 u8 data[6];
1713 #endif
1714
1715 if (RTW_CANNOT_RUN(padapter))
1716 return;
1717
1718 phal = GET_HAL_DATA(padapter);
1719
1720 #if SD_INT_HDL_DIS_HIMR_RX_REQ
1721 disable_himr_rx_req_8188f_sdio(padapter);
1722 #endif
1723
1724 #if CMD52_ACCESS_HISR_RX_REQ_LEN
1725 phal->sdio_hisr = 0;
1726 ReadInterrupt8188FSdio(padapter, &phal->sdio_hisr);
1727 #else
1728 _sdio_local_read(padapter, SDIO_REG_HISR, 6, data);
1729 phal->sdio_hisr = le32_to_cpu(*(u32 *)data);
1730 phal->SdioRxFIFOSize = le16_to_cpu(*(u16 *)&data[4]);
1731 #endif
1732
1733 if (phal->sdio_hisr & phal->sdio_himr) {
1734 u32 v32;
1735 #if DBG_SD_INT_HISR_HIMR
1736 static u32 match_cnt = 0;
1737
1738 if ((match_cnt++) % 1000 == 0)
1739 RTW_INFO("%s: HISR(0x%08x) and HIMR(0x%08x) match!\n"
1740 , __func__, phal->sdio_hisr, phal->sdio_himr);
1741 #endif
1742
1743 phal->sdio_hisr &= phal->sdio_himr;
1744
1745 /* clear HISR */
1746 v32 = phal->sdio_hisr & MASK_SDIO_HISR_CLEAR;
1747 if (v32) {
1748 #if CMD52_ACCESS_HISR_RX_REQ_LEN
1749 SdioLocalCmd52Write4Byte(padapter, SDIO_REG_HISR, v32);
1750 #else
1751 v32 = cpu_to_le32(v32);
1752 _sdio_local_write(padapter, SDIO_REG_HISR, 4, (u8 *)&v32);
1753 #endif
1754 }
1755
1756 sd_int_dpc(padapter);
1757 }
1758 #if DBG_SD_INT_HISR_HIMR
1759 else
1760 RTW_INFO("%s: HISR(0x%08x) and HIMR(0x%08x) not match!\n"
1761 , __func__, phal->sdio_hisr, phal->sdio_himr);
1762 #endif
1763
1764 #if SD_INT_HDL_DIS_HIMR_RX_REQ
1765 restore_himr_8188f_sdio(padapter);
1766 #endif
1767 }
1768
1769 /*
1770 * Description:
1771 * Query SDIO Local register to query current the number of Free TxPacketBuffer page.
1772 *
1773 * Assumption:
1774 * 1. Running at PASSIVE_LEVEL
1775 * 2. RT_TX_SPINLOCK is NOT acquired.
1776 *
1777 * Created by Roger, 2011.01.28.
1778 * */
HalQueryTxBufferStatus8188FSdio(PADAPTER padapter)1779 u8 HalQueryTxBufferStatus8188FSdio(PADAPTER padapter)
1780 {
1781 /* TODO: EXQ */
1782 PHAL_DATA_TYPE phal;
1783 u8 NumOfFreePage[8];
1784 /* _irqL irql; */
1785
1786 phal = GET_HAL_DATA(padapter);
1787
1788 sdio_local_read(padapter, SDIO_REG_FREE_TXPG, 8, NumOfFreePage);
1789
1790 /* _enter_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); */
1791 phal->SdioTxFIFOFreePage[HI_QUEUE_IDX] = NumOfFreePage[0];
1792 phal->SdioTxFIFOFreePage[MID_QUEUE_IDX] = NumOfFreePage[2];
1793 phal->SdioTxFIFOFreePage[LOW_QUEUE_IDX] = NumOfFreePage[4];
1794 phal->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] = NumOfFreePage[6];
1795 /* _exit_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); */
1796
1797 return _TRUE;
1798 }
1799
1800 /*
1801 * Description:
1802 * Query SDIO Local register to get the current number of TX OQT Free Space.
1803 * */
HalQueryTxOQTBufferStatus8188FSdio(PADAPTER padapter)1804 u8 HalQueryTxOQTBufferStatus8188FSdio(PADAPTER padapter)
1805 {
1806 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
1807 pHalData->SdioTxOQTFreeSpace = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_AC_OQT_FREEPG_8188F);
1808 return _TRUE;
1809 }
1810
1811 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
RecvOnePkt(PADAPTER padapter)1812 u8 RecvOnePkt(PADAPTER padapter)
1813 {
1814 struct recv_buf *precvbuf;
1815 struct dvobj_priv *psddev;
1816 PSDIO_DATA psdio_data;
1817 struct sdio_func *func;
1818 u32 tmp = 0;
1819 u16 len = 0;
1820 u32 read_sz, ocp_sz, buf_sz;
1821 u8 res = _FALSE;
1822
1823 if (padapter == NULL) {
1824 RTW_ERR("%s: padapter is NULL!\n", __func__);
1825 return _FALSE;
1826 }
1827
1828 psddev = adapter_to_dvobj(padapter);
1829 psdio_data = &psddev->intf_data;
1830 func = psdio_data->func;
1831
1832 /* If RX_DMA is not idle, receive one pkt from DMA */
1833 res = sdio_local_read(padapter,
1834 SDIO_REG_RX0_REQ_LEN, 4, (u8 *)&tmp);
1835 len = le16_to_cpu(tmp);
1836 RTW_INFO("+%s: size: %d+\n", __func__, len);
1837
1838 if (len) {
1839 read_sz = rtw_sdio_cmd53_align_size(adapter_to_dvobj(padapter), len);
1840 read_sz = RND4(read_sz); /* Patch for some SDIO Host 4 bytes issue, ex. RK3188 */
1841 ocp_sz = _RND8(len);
1842 buf_sz = rtw_max(read_sz, ocp_sz);
1843 if (buf_sz > MAX_RECVBUF_SZ) {
1844 RTW_INFO(FUNC_ADPT_FMT" %u > MAX_RECVBUF_SZ(%u)\n", FUNC_ADPT_ARG(padapter), buf_sz, MAX_RECVBUF_SZ);
1845 rtw_warn_on(1);
1846 }
1847 if (sd_recv_alloc_buf(padapter, buf_sz, &precvbuf) != _SUCCESS) {
1848 res = _FALSE;
1849 goto exit;
1850 }
1851 sdio_claim_host(func);
1852 if (sd_recv_rxfifo(padapter, precvbuf, read_sz, ocp_sz) == _SUCCESS) {
1853 /* printk("Completed Recv One Pkt.\n"); */
1854 sd_rxhandler(padapter, precvbuf);
1855 res = _TRUE;
1856 } else
1857 res = _FALSE;
1858 sdio_release_host(func);
1859 }
1860
1861 exit:
1862 RTW_INFO("-%s-\n", __func__);
1863 return res;
1864 }
1865 #endif /* CONFIG_WOWLAN */
1866