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