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 <rtl8723b_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 * */
HalSdioGetCmdAddr8723BSdio(IN PADAPTER padapter,IN u8 DeviceID,IN u32 Addr,OUT u32 * pCmdAddr)28 static void HalSdioGetCmdAddr8723BSdio(
29 IN PADAPTER padapter,
30 IN u8 DeviceID,
31 IN u32 Addr,
32 OUT 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 * HalSdioGetCmdAddr8723BSdio()
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 err = sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
234 if (err)
235 return SDIO_ERR_VAL32;
236 _rtw_memcpy(&val, ptmpbuf + shift, 4);
237 val = le32_to_cpu(val);
238
239 rtw_mfree(ptmpbuf, 8);
240 }
241
242
243 return val;
244 }
245
sdio_readN(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * pbuf)246 s32 sdio_readN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
247 {
248 PADAPTER padapter;
249 u8 bMacPwrCtrlOn;
250 u8 deviceId;
251 u16 offset;
252 u32 ftaddr;
253 u8 shift;
254 s32 err;
255
256
257 padapter = pintfhdl->padapter;
258 err = 0;
259
260 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
261
262 bMacPwrCtrlOn = _FALSE;
263 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
264 if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
265 || (_FALSE == bMacPwrCtrlOn)
266 #ifdef CONFIG_LPS_LCLK
267 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
268 #endif
269 ) {
270 err = sd_cmd52_read(pintfhdl, ftaddr, cnt, pbuf);
271 return err;
272 }
273
274 /* 4 bytes alignment */
275 shift = ftaddr & 0x3;
276 if (shift == 0)
277 err = sd_read(pintfhdl, ftaddr, cnt, pbuf);
278 else {
279 u8 *ptmpbuf;
280 u32 n;
281
282 ftaddr &= ~(u16)0x3;
283 n = cnt + shift;
284 ptmpbuf = rtw_malloc(n);
285 if (NULL == ptmpbuf)
286 return -1;
287 err = sd_read(pintfhdl, ftaddr, n, ptmpbuf);
288 if (!err)
289 _rtw_memcpy(pbuf, ptmpbuf + shift, cnt);
290 rtw_mfree(ptmpbuf, n);
291 }
292
293
294 return err;
295 }
296
sdio_write8(struct intf_hdl * pintfhdl,u32 addr,u8 val)297 s32 sdio_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
298 {
299 u32 ftaddr;
300 s32 err;
301
302 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
303 err = 0;
304 sd_write8(pintfhdl, ftaddr, val, &err);
305
306
307 return err;
308 }
309
sdio_write16(struct intf_hdl * pintfhdl,u32 addr,u16 val)310 s32 sdio_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
311 {
312 u32 ftaddr;
313 u8 shift;
314 s32 err;
315
316 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
317 val = cpu_to_le16(val);
318 err = sd_cmd52_write(pintfhdl, ftaddr, 2, (u8 *)&val);
319
320
321 return err;
322 }
323
sdio_write32(struct intf_hdl * pintfhdl,u32 addr,u32 val)324 s32 sdio_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
325 {
326 PADAPTER padapter;
327 u8 bMacPwrCtrlOn;
328 u8 deviceId;
329 u16 offset;
330 u32 ftaddr;
331 u8 shift;
332 s32 err;
333
334
335 padapter = pintfhdl->padapter;
336 err = 0;
337
338 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
339
340 bMacPwrCtrlOn = _FALSE;
341 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
342 if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
343 || (_FALSE == bMacPwrCtrlOn)
344 #ifdef CONFIG_LPS_LCLK
345 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
346 #endif
347 ) {
348 val = cpu_to_le32(val);
349 err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&val);
350 return err;
351 }
352
353 /* 4 bytes alignment */
354 shift = ftaddr & 0x3;
355 #if 1
356 if (shift == 0)
357 sd_write32(pintfhdl, ftaddr, val, &err);
358 else {
359 val = cpu_to_le32(val);
360 err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&val);
361 }
362 #else
363 if (shift == 0)
364 sd_write32(pintfhdl, ftaddr, val, &err);
365 else {
366 u8 *ptmpbuf;
367
368 ptmpbuf = (u8 *)rtw_malloc(8);
369 if (NULL == ptmpbuf)
370 return -1;
371
372 ftaddr &= ~(u16)0x3;
373 err = sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
374 if (err) {
375 rtw_mfree(ptmpbuf, 8);
376 return err;
377 }
378 val = cpu_to_le32(val);
379 _rtw_memcpy(ptmpbuf + shift, &val, 4);
380 err = sd_write(pintfhdl, ftaddr, 8, ptmpbuf);
381
382 rtw_mfree(ptmpbuf, 8);
383 }
384 #endif
385
386
387 return err;
388 }
389
sdio_writeN(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * pbuf)390 s32 sdio_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
391 {
392 PADAPTER padapter;
393 u8 bMacPwrCtrlOn;
394 u8 deviceId;
395 u16 offset;
396 u32 ftaddr;
397 u8 shift;
398 s32 err;
399
400
401 padapter = pintfhdl->padapter;
402 err = 0;
403
404 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
405
406 bMacPwrCtrlOn = _FALSE;
407 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
408 if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
409 || (_FALSE == bMacPwrCtrlOn)
410 #ifdef CONFIG_LPS_LCLK
411 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
412 #endif
413 ) {
414 err = sd_cmd52_write(pintfhdl, ftaddr, cnt, pbuf);
415 return err;
416 }
417
418 shift = ftaddr & 0x3;
419 if (shift == 0)
420 err = sd_write(pintfhdl, ftaddr, cnt, pbuf);
421 else {
422 u8 *ptmpbuf;
423 u32 n;
424
425 ftaddr &= ~(u16)0x3;
426 n = cnt + shift;
427 ptmpbuf = rtw_malloc(n);
428 if (NULL == ptmpbuf)
429 return -1;
430 err = sd_read(pintfhdl, ftaddr, 4, ptmpbuf);
431 if (err) {
432 rtw_mfree(ptmpbuf, n);
433 return err;
434 }
435 _rtw_memcpy(ptmpbuf + shift, pbuf, cnt);
436 err = sd_write(pintfhdl, ftaddr, n, ptmpbuf);
437 rtw_mfree(ptmpbuf, n);
438 }
439
440
441 return err;
442 }
443
sdio_f0_read8(struct intf_hdl * pintfhdl,u32 addr)444 u8 sdio_f0_read8(struct intf_hdl *pintfhdl, u32 addr)
445 {
446 u32 ftaddr;
447 u8 val;
448
449 val = sd_f0_read8(pintfhdl, addr, NULL);
450
451
452 return val;
453 }
454
sdio_read_mem(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * rmem)455 void sdio_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
456 {
457 s32 err;
458
459
460 err = sdio_readN(pintfhdl, addr, cnt, rmem);
461
462 }
463
sdio_write_mem(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * wmem)464 void sdio_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
465 {
466
467 sdio_writeN(pintfhdl, addr, cnt, wmem);
468
469 }
470
471 /*
472 * Description:
473 * Read from RX FIFO
474 * Round read size to block size,
475 * and make sure data transfer will be done in one command.
476 *
477 * Parameters:
478 * pintfhdl a pointer of intf_hdl
479 * addr port ID
480 * cnt size to read
481 * rmem address to put data
482 *
483 * Return:
484 * _SUCCESS(1) Success
485 * _FAIL(0) Fail
486 */
sdio_read_port(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * mem)487 static u32 sdio_read_port(
488 struct intf_hdl *pintfhdl,
489 u32 addr,
490 u32 cnt,
491 u8 *mem)
492 {
493 PADAPTER padapter;
494 PSDIO_DATA psdio;
495 PHAL_DATA_TYPE phal;
496 u32 oldcnt;
497 #ifdef SDIO_DYNAMIC_ALLOC_MEM
498 u8 *oldmem;
499 #endif
500 s32 err;
501
502
503 padapter = pintfhdl->padapter;
504 psdio = &adapter_to_dvobj(padapter)->intf_data;
505 phal = GET_HAL_DATA(padapter);
506
507 HalSdioGetCmdAddr8723BSdio(padapter, addr, phal->SdioRxFIFOCnt++, &addr);
508
509 oldcnt = cnt;
510 if (cnt > psdio->block_transfer_len)
511 cnt = _RND(cnt, psdio->block_transfer_len);
512 /* cnt = sdio_align_size(cnt); */
513
514 if (oldcnt != cnt) {
515 #ifdef SDIO_DYNAMIC_ALLOC_MEM
516 oldmem = mem;
517 mem = rtw_malloc(cnt);
518 if (mem == NULL) {
519 RTW_WARN("%s: allocate memory %d bytes fail!\n", __func__, cnt);
520 mem = oldmem;
521 oldmem == NULL;
522 }
523 #else
524 /* in this case, caller should gurante the buffer is big enough */
525 /* to receive data after alignment */
526 #endif
527 }
528
529 err = _sd_read(pintfhdl, addr, cnt, mem);
530
531 #ifdef SDIO_DYNAMIC_ALLOC_MEM
532 if ((oldcnt != cnt) && (oldmem)) {
533 _rtw_memcpy(oldmem, mem, oldcnt);
534 rtw_mfree(mem, cnt);
535 }
536 #endif
537
538 if (err)
539 return _FAIL;
540 return _SUCCESS;
541 }
542
543 /*
544 * Description:
545 * Write to TX FIFO
546 * Align write size block size,
547 * and make sure data could be written in one command.
548 *
549 * Parameters:
550 * pintfhdl a pointer of intf_hdl
551 * addr port ID
552 * cnt size to write
553 * wmem data pointer to write
554 *
555 * Return:
556 * _SUCCESS(1) Success
557 * _FAIL(0) Fail
558 */
sdio_write_port(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * mem)559 static u32 sdio_write_port(
560 struct intf_hdl *pintfhdl,
561 u32 addr,
562 u32 cnt,
563 u8 *mem)
564 {
565 PADAPTER padapter;
566 PSDIO_DATA psdio;
567 s32 err;
568 struct xmit_buf *xmitbuf = (struct xmit_buf *)mem;
569
570 padapter = pintfhdl->padapter;
571 psdio = &adapter_to_dvobj(padapter)->intf_data;
572
573 if (!rtw_is_hw_init_completed(padapter)) {
574 RTW_INFO("%s [addr=0x%x cnt=%d] padapter->hw_init_completed == _FALSE\n", __func__, addr, cnt);
575 return _FAIL;
576 }
577
578 cnt = _RND4(cnt);
579 HalSdioGetCmdAddr8723BSdio(padapter, addr, cnt >> 2, &addr);
580
581 if (cnt > psdio->block_transfer_len)
582 cnt = _RND(cnt, psdio->block_transfer_len);
583 /* cnt = sdio_align_size(cnt); */
584
585 err = sd_write(pintfhdl, addr, cnt, xmitbuf->pdata);
586
587 rtw_sctx_done_err(&xmitbuf->sctx,
588 err ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS);
589
590 if (err)
591 return _FAIL;
592 return _SUCCESS;
593 }
594
sdio_set_intf_ops(_adapter * padapter,struct _io_ops * pops)595 void sdio_set_intf_ops(_adapter *padapter, struct _io_ops *pops)
596 {
597
598 pops->_read8 = &sdio_read8;
599 pops->_read16 = &sdio_read16;
600 pops->_read32 = &sdio_read32;
601 pops->_read_mem = &sdio_read_mem;
602 pops->_read_port = &sdio_read_port;
603
604 pops->_write8 = &sdio_write8;
605 pops->_write16 = &sdio_write16;
606 pops->_write32 = &sdio_write32;
607 pops->_writeN = &sdio_writeN;
608 pops->_write_mem = &sdio_write_mem;
609 pops->_write_port = &sdio_write_port;
610
611 pops->_sd_f0_read8 = sdio_f0_read8;
612
613 }
614
615 /*
616 * Todo: align address to 4 bytes.
617 */
_sdio_local_read(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)618 s32 _sdio_local_read(
619 PADAPTER padapter,
620 u32 addr,
621 u32 cnt,
622 u8 *pbuf)
623 {
624 struct intf_hdl *pintfhdl;
625 u8 bMacPwrCtrlOn;
626 s32 err;
627 u8 *ptmpbuf;
628 u32 n;
629
630
631 pintfhdl = &padapter->iopriv.intf;
632
633 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
634
635 bMacPwrCtrlOn = _FALSE;
636 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
637 if (_FALSE == bMacPwrCtrlOn) {
638 err = _sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
639 return err;
640 }
641
642 n = RND4(cnt);
643 ptmpbuf = (u8 *)rtw_malloc(n);
644 if (!ptmpbuf)
645 return -1;
646
647 err = _sd_read(pintfhdl, addr, n, ptmpbuf);
648 if (!err)
649 _rtw_memcpy(pbuf, ptmpbuf, cnt);
650
651 if (ptmpbuf)
652 rtw_mfree(ptmpbuf, n);
653
654 return err;
655 }
656
657 /*
658 * Todo: align address to 4 bytes.
659 */
sdio_local_read(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)660 s32 sdio_local_read(
661 PADAPTER padapter,
662 u32 addr,
663 u32 cnt,
664 u8 *pbuf)
665 {
666 struct intf_hdl *pintfhdl;
667 u8 bMacPwrCtrlOn;
668 s32 err;
669 u8 *ptmpbuf;
670 u32 n;
671
672 pintfhdl = &padapter->iopriv.intf;
673
674 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
675
676 bMacPwrCtrlOn = _FALSE;
677 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
678 if ((_FALSE == bMacPwrCtrlOn)
679 #ifdef CONFIG_LPS_LCLK
680 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
681 #endif
682 ) {
683 err = sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
684 return err;
685 }
686
687 n = RND4(cnt);
688 ptmpbuf = (u8 *)rtw_malloc(n);
689 if (!ptmpbuf)
690 return -1;
691
692 err = sd_read(pintfhdl, addr, n, ptmpbuf);
693 if (!err)
694 _rtw_memcpy(pbuf, ptmpbuf, cnt);
695
696 if (ptmpbuf)
697 rtw_mfree(ptmpbuf, n);
698
699 return err;
700 }
701
702 /*
703 * Todo: align address to 4 bytes.
704 */
_sdio_local_write(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)705 s32 _sdio_local_write(
706 PADAPTER padapter,
707 u32 addr,
708 u32 cnt,
709 u8 *pbuf)
710 {
711 struct intf_hdl *pintfhdl;
712 u8 bMacPwrCtrlOn;
713 s32 err;
714 u8 *ptmpbuf;
715
716 if (addr & 0x3)
717 RTW_INFO("%s, address must be 4 bytes alignment\n", __FUNCTION__);
718
719 if (cnt & 0x3)
720 RTW_INFO("%s, size must be the multiple of 4\n", __FUNCTION__);
721
722 pintfhdl = &padapter->iopriv.intf;
723
724 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
725
726 bMacPwrCtrlOn = _FALSE;
727 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
728 if ((_FALSE == bMacPwrCtrlOn)
729 #ifdef CONFIG_LPS_LCLK
730 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
731 #endif
732 ) {
733 err = _sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
734 return err;
735 }
736
737 ptmpbuf = (u8 *)rtw_malloc(cnt);
738 if (!ptmpbuf)
739 return -1;
740
741 _rtw_memcpy(ptmpbuf, pbuf, cnt);
742
743 err = _sd_write(pintfhdl, addr, cnt, ptmpbuf);
744
745 if (ptmpbuf)
746 rtw_mfree(ptmpbuf, cnt);
747
748 return err;
749 }
750
751 /*
752 * Todo: align address to 4 bytes.
753 */
sdio_local_write(PADAPTER padapter,u32 addr,u32 cnt,u8 * pbuf)754 s32 sdio_local_write(
755 PADAPTER padapter,
756 u32 addr,
757 u32 cnt,
758 u8 *pbuf)
759 {
760 struct intf_hdl *pintfhdl;
761 u8 bMacPwrCtrlOn;
762 s32 err;
763 u8 *ptmpbuf;
764
765 if (addr & 0x3)
766 RTW_INFO("%s, address must be 4 bytes alignment\n", __FUNCTION__);
767
768 if (cnt & 0x3)
769 RTW_INFO("%s, size must be the multiple of 4\n", __FUNCTION__);
770
771 pintfhdl = &padapter->iopriv.intf;
772
773 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
774
775 bMacPwrCtrlOn = _FALSE;
776 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
777 if ((_FALSE == bMacPwrCtrlOn)
778 #ifdef CONFIG_LPS_LCLK
779 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
780 #endif
781 ) {
782 err = sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
783 return err;
784 }
785
786 ptmpbuf = (u8 *)rtw_malloc(cnt);
787 if (!ptmpbuf)
788 return -1;
789
790 _rtw_memcpy(ptmpbuf, pbuf, cnt);
791
792 err = sd_write(pintfhdl, addr, cnt, ptmpbuf);
793
794 if (ptmpbuf)
795 rtw_mfree(ptmpbuf, cnt);
796
797 return err;
798 }
799
SdioLocalCmd52Read1Byte(PADAPTER padapter,u32 addr)800 u8 SdioLocalCmd52Read1Byte(PADAPTER padapter, u32 addr)
801 {
802 u8 val = 0;
803 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
804
805 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
806 sd_cmd52_read(pintfhdl, addr, 1, &val);
807
808 return val;
809 }
810
SdioLocalCmd52Read2Byte(PADAPTER padapter,u32 addr)811 u16 SdioLocalCmd52Read2Byte(PADAPTER padapter, u32 addr)
812 {
813 u16 val = 0;
814 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
815
816 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
817 sd_cmd52_read(pintfhdl, addr, 2, (u8 *)&val);
818
819 val = le16_to_cpu(val);
820
821 return val;
822 }
823
SdioLocalCmd52Read4Byte(PADAPTER padapter,u32 addr)824 u32 SdioLocalCmd52Read4Byte(PADAPTER padapter, u32 addr)
825 {
826 u32 val = 0;
827 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
828
829 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
830 sd_cmd52_read(pintfhdl, addr, 4, (u8 *)&val);
831
832 val = le32_to_cpu(val);
833
834 return val;
835 }
836
SdioLocalCmd53Read4Byte(PADAPTER padapter,u32 addr)837 u32 SdioLocalCmd53Read4Byte(PADAPTER padapter, u32 addr)
838 {
839
840 u8 bMacPwrCtrlOn;
841 u32 val = 0;
842 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
843
844 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
845 bMacPwrCtrlOn = _FALSE;
846 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
847 if ((_FALSE == bMacPwrCtrlOn)
848 #ifdef CONFIG_LPS_LCLK
849 || (_TRUE == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
850 #endif
851 ) {
852 sd_cmd52_read(pintfhdl, addr, 4, (u8 *)&val);
853 val = le32_to_cpu(val);
854 } else
855 val = sd_read32(pintfhdl, addr, NULL);
856
857 return val;
858 }
859
SdioLocalCmd52Write1Byte(PADAPTER padapter,u32 addr,u8 v)860 void SdioLocalCmd52Write1Byte(PADAPTER padapter, u32 addr, u8 v)
861 {
862 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
863
864 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
865 sd_cmd52_write(pintfhdl, addr, 1, &v);
866 }
867
SdioLocalCmd52Write2Byte(PADAPTER padapter,u32 addr,u16 v)868 void SdioLocalCmd52Write2Byte(PADAPTER padapter, u32 addr, u16 v)
869 {
870 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
871
872 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
873 v = cpu_to_le16(v);
874 sd_cmd52_write(pintfhdl, addr, 2, (u8 *)&v);
875 }
876
SdioLocalCmd52Write4Byte(PADAPTER padapter,u32 addr,u32 v)877 void SdioLocalCmd52Write4Byte(PADAPTER padapter, u32 addr, u32 v)
878 {
879 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
880 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
881 v = cpu_to_le32(v);
882 sd_cmd52_write(pintfhdl, addr, 4, (u8 *)&v);
883 }
884
885 #if 0
886 void
887 DumpLoggedInterruptHistory8723Sdio(
888 PADAPTER padapter
889 )
890 {
891 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
892 u4Byte DebugLevel = DBG_LOUD;
893
894 if (DBG_Var.DbgPrintIsr == 0)
895 return;
896
897 DBG_ChkDrvResource(padapter);
898
899
900
901 }
902
903 void
904 LogInterruptHistory8723Sdio(
905 PADAPTER padapter,
906 PRT_ISR_CONTENT pIsrContent
907 )
908 {
909 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
910
911 if ((pHalData->IntrMask[0] & SDIO_HIMR_RX_REQUEST_MSK) &&
912 (pIsrContent->IntArray[0] & SDIO_HISR_RX_REQUEST))
913 pHalData->InterruptLog.nISR_RX_REQUEST++;
914 if ((pHalData->IntrMask[0] & SDIO_HIMR_AVAL_MSK) &&
915 (pIsrContent->IntArray[0] & SDIO_HISR_AVAL))
916 pHalData->InterruptLog.nISR_AVAL++;
917 if ((pHalData->IntrMask[0] & SDIO_HIMR_TXERR_MSK) &&
918 (pIsrContent->IntArray[0] & SDIO_HISR_TXERR))
919 pHalData->InterruptLog.nISR_TXERR++;
920 if ((pHalData->IntrMask[0] & SDIO_HIMR_RXERR_MSK) &&
921 (pIsrContent->IntArray[0] & SDIO_HISR_RXERR))
922 pHalData->InterruptLog.nISR_RXERR++;
923 if ((pHalData->IntrMask[0] & SDIO_HIMR_TXFOVW_MSK) &&
924 (pIsrContent->IntArray[0] & SDIO_HISR_TXFOVW))
925 pHalData->InterruptLog.nISR_TXFOVW++;
926 if ((pHalData->IntrMask[0] & SDIO_HIMR_RXFOVW_MSK) &&
927 (pIsrContent->IntArray[0] & SDIO_HISR_RXFOVW))
928 pHalData->InterruptLog.nISR_RXFOVW++;
929 if ((pHalData->IntrMask[0] & SDIO_HIMR_TXBCNOK_MSK) &&
930 (pIsrContent->IntArray[0] & SDIO_HISR_TXBCNOK))
931 pHalData->InterruptLog.nISR_TXBCNOK++;
932 if ((pHalData->IntrMask[0] & SDIO_HIMR_TXBCNERR_MSK) &&
933 (pIsrContent->IntArray[0] & SDIO_HISR_TXBCNERR))
934 pHalData->InterruptLog.nISR_TXBCNERR++;
935 if ((pHalData->IntrMask[0] & SDIO_HIMR_BCNERLY_INT_MSK) &&
936 (pIsrContent->IntArray[0] & SDIO_HISR_BCNERLY_INT))
937 pHalData->InterruptLog.nISR_BCNERLY_INT++;
938 if ((pHalData->IntrMask[0] & SDIO_HIMR_C2HCMD_MSK) &&
939 (pIsrContent->IntArray[0] & SDIO_HISR_C2HCMD))
940 pHalData->InterruptLog.nISR_C2HCMD++;
941 if ((pHalData->IntrMask[0] & SDIO_HIMR_CPWM1_MSK) &&
942 (pIsrContent->IntArray[0] & SDIO_HISR_CPWM1))
943 pHalData->InterruptLog.nISR_CPWM1++;
944 if ((pHalData->IntrMask[0] & SDIO_HIMR_CPWM2_MSK) &&
945 (pIsrContent->IntArray[0] & SDIO_HISR_CPWM2))
946 pHalData->InterruptLog.nISR_CPWM2++;
947 if ((pHalData->IntrMask[0] & SDIO_HIMR_HSISR_IND_MSK) &&
948 (pIsrContent->IntArray[0] & SDIO_HISR_HSISR_IND))
949 pHalData->InterruptLog.nISR_HSISR_IND++;
950 if ((pHalData->IntrMask[0] & SDIO_HIMR_GTINT3_IND_MSK) &&
951 (pIsrContent->IntArray[0] & SDIO_HISR_GTINT3_IND))
952 pHalData->InterruptLog.nISR_GTINT3_IND++;
953 if ((pHalData->IntrMask[0] & SDIO_HIMR_GTINT4_IND_MSK) &&
954 (pIsrContent->IntArray[0] & SDIO_HISR_GTINT4_IND))
955 pHalData->InterruptLog.nISR_GTINT4_IND++;
956 if ((pHalData->IntrMask[0] & SDIO_HIMR_PSTIMEOUT_MSK) &&
957 (pIsrContent->IntArray[0] & SDIO_HISR_PSTIMEOUT))
958 pHalData->InterruptLog.nISR_PSTIMEOUT++;
959 if ((pHalData->IntrMask[0] & SDIO_HIMR_OCPINT_MSK) &&
960 (pIsrContent->IntArray[0] & SDIO_HISR_OCPINT))
961 pHalData->InterruptLog.nISR_OCPINT++;
962 if ((pHalData->IntrMask[0] & SDIO_HIMR_ATIMEND_MSK) &&
963 (pIsrContent->IntArray[0] & SDIO_HISR_ATIMEND))
964 pHalData->InterruptLog.nISR_ATIMEND++;
965 if ((pHalData->IntrMask[0] & SDIO_HIMR_ATIMEND_E_MSK) &&
966 (pIsrContent->IntArray[0] & SDIO_HISR_ATIMEND_E))
967 pHalData->InterruptLog.nISR_ATIMEND_E++;
968 if ((pHalData->IntrMask[0] & SDIO_HIMR_CTWEND_MSK) &&
969 (pIsrContent->IntArray[0] & SDIO_HISR_CTWEND))
970 pHalData->InterruptLog.nISR_CTWEND++;
971
972 }
973
974 void
975 DumpHardwareProfile8723Sdio(
976 IN PADAPTER padapter
977 )
978 {
979 DumpLoggedInterruptHistory8723Sdio(padapter);
980 }
981 #endif
982
ReadInterrupt8723BSdio(PADAPTER padapter,u32 * phisr)983 static s32 ReadInterrupt8723BSdio(PADAPTER padapter, u32 *phisr)
984 {
985 u32 hisr, himr;
986 u8 val8, hisr_len;
987
988
989 if (phisr == NULL)
990 return _FALSE;
991
992 himr = GET_HAL_DATA(padapter)->sdio_himr;
993
994 /* decide how many bytes need to be read */
995 hisr_len = 0;
996 while (himr) {
997 hisr_len++;
998 himr >>= 8;
999 }
1000
1001 hisr = 0;
1002 while (hisr_len != 0) {
1003 hisr_len--;
1004 val8 = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HISR + hisr_len);
1005 hisr |= (val8 << (8 * hisr_len));
1006 }
1007
1008 *phisr = hisr;
1009
1010 return _TRUE;
1011 }
1012
1013 /*
1014 * Description:
1015 * Initialize SDIO Host Interrupt Mask configuration variables for future use.
1016 *
1017 * Assumption:
1018 * Using SDIO Local register ONLY for configuration.
1019 *
1020 * Created by Roger, 2011.02.11.
1021 * */
InitInterrupt8723BSdio(PADAPTER padapter)1022 void InitInterrupt8723BSdio(PADAPTER padapter)
1023 {
1024 PHAL_DATA_TYPE pHalData;
1025
1026
1027 pHalData = GET_HAL_DATA(padapter);
1028 pHalData->sdio_himr = (u32)(\
1029 SDIO_HIMR_RX_REQUEST_MSK |
1030 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
1031 SDIO_HIMR_AVAL_MSK |
1032 #endif
1033 /* SDIO_HIMR_TXERR_MSK |
1034 * SDIO_HIMR_RXERR_MSK |
1035 * SDIO_HIMR_TXFOVW_MSK |
1036 * SDIO_HIMR_RXFOVW_MSK |
1037 * SDIO_HIMR_TXBCNOK_MSK |
1038 * SDIO_HIMR_TXBCNERR_MSK |
1039 * SDIO_HIMR_BCNERLY_INT_MSK |
1040 * SDIO_HIMR_C2HCMD_MSK | */
1041 #if defined(CONFIG_LPS_LCLK) && !defined(CONFIG_DETECT_CPWM_BY_POLLING)
1042 SDIO_HIMR_CPWM1_MSK |
1043 #endif /* CONFIG_LPS_LCLK && !CONFIG_DETECT_CPWM_BY_POLLING */
1044 #ifdef CONFIG_WOWLAN
1045 SDIO_HIMR_CPWM2_MSK |
1046 #endif
1047
1048 /* SDIO_HIMR_HSISR_IND_MSK |
1049 * SDIO_HIMR_GTINT3_IND_MSK |
1050 * SDIO_HIMR_GTINT4_IND_MSK |
1051 * SDIO_HIMR_PSTIMEOUT_MSK |
1052 * SDIO_HIMR_OCPINT_MSK |
1053 * SDIO_HIMR_ATIMEND_MSK |
1054 * SDIO_HIMR_ATIMEND_E_MSK |
1055 * SDIO_HIMR_CTWEND_MSK | */
1056 0);
1057 }
1058
1059 /*
1060 * Description:
1061 * Initialize System Host Interrupt Mask configuration variables for future use.
1062 *
1063 * Created by Roger, 2011.08.03.
1064 * */
InitSysInterrupt8723BSdio(PADAPTER padapter)1065 void InitSysInterrupt8723BSdio(PADAPTER padapter)
1066 {
1067 PHAL_DATA_TYPE pHalData;
1068
1069
1070 pHalData = GET_HAL_DATA(padapter);
1071
1072 pHalData->SysIntrMask = (\
1073 /* HSIMR_GPIO12_0_INT_EN |
1074 * HSIMR_SPS_OCP_INT_EN |
1075 * HSIMR_RON_INT_EN |
1076 * HSIMR_PDNINT_EN |
1077 * HSIMR_GPIO9_INT_EN | */
1078 0);
1079 }
1080
1081 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
1082 /*
1083 * Description:
1084 * Clear corresponding SDIO Host ISR interrupt service.
1085 *
1086 * Assumption:
1087 * Using SDIO Local register ONLY for configuration.
1088 *
1089 * Created by Roger, 2011.02.11.
1090 * */
ClearInterrupt8723BSdio(PADAPTER padapter)1091 void ClearInterrupt8723BSdio(PADAPTER padapter)
1092 {
1093 PHAL_DATA_TYPE pHalData;
1094 u8 *clear;
1095
1096
1097 if (rtw_is_surprise_removed(padapter))
1098 return;
1099
1100 pHalData = GET_HAL_DATA(padapter);
1101 clear = rtw_zmalloc(4);
1102
1103 /* Clear corresponding HISR Content if needed */
1104 *(u32 *)clear = cpu_to_le32(pHalData->sdio_hisr & MASK_SDIO_HISR_CLEAR);
1105 if (*(u32 *)clear) {
1106 /* Perform write one clear operation */
1107 sdio_local_write(padapter, SDIO_REG_HISR, 4, clear);
1108 }
1109
1110 rtw_mfree(clear, 4);
1111 }
1112 #endif
1113
1114 /*
1115 * Description:
1116 * Clear corresponding system Host ISR interrupt service.
1117 *
1118 *
1119 * Created by Roger, 2011.02.11.
1120 * */
ClearSysInterrupt8723BSdio(PADAPTER padapter)1121 void ClearSysInterrupt8723BSdio(PADAPTER padapter)
1122 {
1123 PHAL_DATA_TYPE pHalData;
1124 u32 clear;
1125
1126
1127 if (rtw_is_surprise_removed(padapter))
1128 return;
1129
1130 pHalData = GET_HAL_DATA(padapter);
1131
1132 /* Clear corresponding HISR Content if needed */
1133 clear = pHalData->SysIntrStatus & MASK_HSISR_CLEAR;
1134 if (clear) {
1135 /* Perform write one clear operation */
1136 rtw_write32(padapter, REG_HSISR, clear);
1137 }
1138 }
1139
1140 /*
1141 * Description:
1142 * Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain.
1143 *
1144 * Assumption:
1145 * 1. Using SDIO Local register ONLY for configuration.
1146 * 2. PASSIVE LEVEL
1147 *
1148 * Created by Roger, 2011.02.11.
1149 * */
EnableInterrupt8723BSdio(PADAPTER padapter)1150 void EnableInterrupt8723BSdio(PADAPTER padapter)
1151 {
1152 PHAL_DATA_TYPE pHalData;
1153 u32 himr;
1154
1155 pHalData = GET_HAL_DATA(padapter);
1156
1157 himr = cpu_to_le32(pHalData->sdio_himr);
1158 sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1159
1160
1161 /* Update current system IMR settings */
1162 himr = rtw_read32(padapter, REG_HSIMR);
1163 rtw_write32(padapter, REG_HSIMR, himr | pHalData->SysIntrMask);
1164
1165
1166 /* */
1167 /* <Roger_Notes> There are some C2H CMDs have been sent before system interrupt is enabled, e.g., C2H, CPWM. */
1168 /* So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore. */
1169 /* 2011.10.19. */
1170 /* */
1171 rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
1172 }
1173
1174 /*
1175 * Description:
1176 * Disable SDIO Host IMR configuration to mask unnecessary interrupt service.
1177 *
1178 * Assumption:
1179 * Using SDIO Local register ONLY for configuration.
1180 *
1181 * Created by Roger, 2011.02.11.
1182 * */
DisableInterrupt8723BSdio(PADAPTER padapter)1183 void DisableInterrupt8723BSdio(PADAPTER padapter)
1184 {
1185 u32 himr;
1186
1187 himr = cpu_to_le32(SDIO_HIMR_DISABLED);
1188 sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1189
1190 }
1191
1192 /*
1193 * Description:
1194 * Using 0x100 to check the power status of FW.
1195 *
1196 * Assumption:
1197 * Using SDIO Local register ONLY for configuration.
1198 *
1199 * Created by Isaac, 2013.09.10.
1200 * */
CheckIPSStatus(PADAPTER padapter)1201 u8 CheckIPSStatus(PADAPTER padapter)
1202 {
1203 RTW_INFO("%s(): Read 0x100=0x%02x 0x86=0x%02x\n", __func__,
1204 rtw_read8(padapter, 0x100), rtw_read8(padapter, 0x86));
1205
1206 if (rtw_read8(padapter, 0x100) == 0xEA)
1207 return _TRUE;
1208 else
1209 return _FALSE;
1210 }
1211
1212 #ifdef CONFIG_WOWLAN
DisableInterruptButCpwm28723BSdio(PADAPTER padapter)1213 void DisableInterruptButCpwm28723BSdio(PADAPTER padapter)
1214 {
1215 u32 himr, tmp;
1216
1217 sdio_local_read(padapter, SDIO_REG_HIMR, 4, (u8 *)&tmp);
1218 RTW_INFO("DisableInterruptButCpwm28723BSdio(): Read SDIO_REG_HIMR: 0x%08x\n", tmp);
1219
1220 himr = cpu_to_le32(SDIO_HIMR_DISABLED) | SDIO_HIMR_CPWM2_MSK;
1221 sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
1222
1223 sdio_local_read(padapter, SDIO_REG_HIMR, 4, (u8 *)&tmp);
1224 RTW_INFO("DisableInterruptButCpwm28723BSdio(): Read again SDIO_REG_HIMR: 0x%08x\n", tmp);
1225 }
1226 #endif /* CONFIG_WOWLAN
1227 *
1228 * Description:
1229 * Update SDIO Host Interrupt Mask configuration on SDIO local domain.
1230 *
1231 * Assumption:
1232 * 1. Using SDIO Local register ONLY for configuration.
1233 * 2. PASSIVE LEVEL
1234 *
1235 * Created by Roger, 2011.02.11.
1236 * */
UpdateInterruptMask8723BSdio(PADAPTER padapter,u32 AddMSR,u32 RemoveMSR)1237 void UpdateInterruptMask8723BSdio(PADAPTER padapter, u32 AddMSR, u32 RemoveMSR)
1238 {
1239 HAL_DATA_TYPE *pHalData;
1240
1241 pHalData = GET_HAL_DATA(padapter);
1242
1243 if (AddMSR)
1244 pHalData->sdio_himr |= AddMSR;
1245
1246 if (RemoveMSR)
1247 pHalData->sdio_himr &= (~RemoveMSR);
1248
1249 DisableInterrupt8723BSdio(padapter);
1250 EnableInterrupt8723BSdio(padapter);
1251 }
1252
1253 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
sd_recv_loopback(PADAPTER padapter,u32 size)1254 static void sd_recv_loopback(PADAPTER padapter, u32 size)
1255 {
1256 PLOOPBACKDATA ploopback;
1257 u32 readsize, allocsize;
1258 u8 *preadbuf;
1259
1260
1261 readsize = size;
1262 RTW_INFO("%s: read size=%d\n", __func__, readsize);
1263 allocsize = _RND(readsize, adapter_to_dvobj(padapter)->intf_data.block_transfer_len);
1264
1265 ploopback = padapter->ploopback;
1266 if (ploopback) {
1267 ploopback->rxsize = readsize;
1268 preadbuf = ploopback->rxbuf;
1269 } else {
1270 preadbuf = rtw_malloc(allocsize);
1271 if (preadbuf == NULL) {
1272 RTW_INFO("%s: malloc fail size=%d\n", __func__, allocsize);
1273 return;
1274 }
1275 }
1276
1277 /* rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); */
1278 sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1279
1280 if (ploopback)
1281 _rtw_up_sema(&ploopback->sema);
1282 else {
1283 u32 i;
1284
1285 RTW_INFO("%s: drop pkt\n", __func__);
1286 for (i = 0; i < readsize; i += 4) {
1287 RTW_INFO("%08X", *(u32 *)(preadbuf + i));
1288 if ((i + 4) & 0x1F)
1289 printk(" ");
1290 else
1291 printk("\n");
1292 }
1293 printk("\n");
1294 rtw_mfree(preadbuf, allocsize);
1295 }
1296 }
1297 #endif /* CONFIG_MAC_LOOPBACK_DRIVER */
1298
1299 #ifdef CONFIG_SDIO_RX_COPY
sd_recv_rxfifo(PADAPTER padapter,u32 size)1300 static struct recv_buf *sd_recv_rxfifo(PADAPTER padapter, u32 size)
1301 {
1302 u32 readsize, ret;
1303 u8 *preadbuf;
1304 struct recv_priv *precvpriv;
1305 struct recv_buf *precvbuf;
1306
1307
1308 #if 0
1309 readsize = size;
1310 #else
1311 /* Patch for some SDIO Host 4 bytes issue */
1312 /* ex. RK3188 */
1313 readsize = RND4(size);
1314 #endif
1315
1316 /* 3 1. alloc recvbuf */
1317 precvpriv = &padapter->recvpriv;
1318 precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
1319 if (precvbuf == NULL) {
1320 RTW_ERR("%s: alloc recvbuf FAIL!\n", __FUNCTION__);
1321 return NULL;
1322 }
1323
1324 /* 3 2. alloc skb */
1325 if (precvbuf->pskb == NULL) {
1326 SIZE_PTR tmpaddr = 0;
1327 SIZE_PTR alignment = 0;
1328
1329 precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
1330 if (precvbuf->pskb == NULL) {
1331 RTW_INFO("%s: alloc_skb fail! read=%d\n", __FUNCTION__, readsize);
1332 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
1333 return NULL;
1334 }
1335
1336 precvbuf->pskb->dev = padapter->pnetdev;
1337
1338 tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
1339 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
1340 skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
1341 }
1342
1343 /* 3 3. read data from rxfifo */
1344 preadbuf = precvbuf->pskb->data;
1345 /* rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); */
1346 ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1347 if (ret == _FAIL) {
1348 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
1349 return NULL;
1350 }
1351
1352 /* 3 4. init recvbuf */
1353 precvbuf->len = size;
1354 precvbuf->phead = precvbuf->pskb->head;
1355 precvbuf->pdata = precvbuf->pskb->data;
1356 skb_set_tail_pointer(precvbuf->pskb, size);
1357 precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1358 precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1359
1360 return precvbuf;
1361 }
1362 #else /* !CONFIG_SDIO_RX_COPY */
sd_recv_rxfifo(PADAPTER padapter,u32 size)1363 static struct recv_buf *sd_recv_rxfifo(PADAPTER padapter, u32 size)
1364 {
1365 u32 sdioblksize, readsize, allocsize, ret;
1366 u8 *preadbuf;
1367 _pkt *ppkt;
1368 struct recv_priv *precvpriv;
1369 struct recv_buf *precvbuf;
1370
1371
1372 sdioblksize = adapter_to_dvobj(padapter)->intf_data.block_transfer_len;
1373 #if 0
1374 readsize = size;
1375 #else
1376 /* Patch for some SDIO Host 4 bytes issue */
1377 /* ex. RK3188 */
1378 readsize = RND4(size);
1379 #endif
1380
1381 /* 3 1. alloc skb */
1382 /* align to block size */
1383 if (readsize > sdioblksize)
1384 allocsize = _RND(readsize, sdioblksize);
1385 else
1386 allocsize = readsize;
1387
1388 ppkt = rtw_skb_alloc(allocsize);
1389
1390 if (ppkt == NULL) {
1391 return NULL;
1392 }
1393
1394 /* 3 2. read data from rxfifo */
1395 preadbuf = skb_put(ppkt, size);
1396 /* rtw_read_port(padapter, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf); */
1397 ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1398 if (ret == _FAIL) {
1399 rtw_skb_free(ppkt);
1400 return NULL;
1401 }
1402
1403 /* 3 3. alloc recvbuf */
1404 precvpriv = &padapter->recvpriv;
1405 precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
1406 if (precvbuf == NULL) {
1407 rtw_skb_free(ppkt);
1408 RTW_ERR("%s: alloc recvbuf FAIL!\n", __FUNCTION__);
1409 return NULL;
1410 }
1411
1412 /* 3 4. init recvbuf */
1413 precvbuf->pskb = ppkt;
1414
1415 precvbuf->len = ppkt->len;
1416
1417 precvbuf->phead = ppkt->head;
1418 precvbuf->pdata = ppkt->data;
1419 precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1420 precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1421
1422 return precvbuf;
1423 }
1424 #endif /* !CONFIG_SDIO_RX_COPY */
1425
sd_rxhandler(PADAPTER padapter,struct recv_buf * precvbuf)1426 static void sd_rxhandler(PADAPTER padapter, struct recv_buf *precvbuf)
1427 {
1428 struct recv_priv *precvpriv;
1429 _queue *ppending_queue;
1430
1431
1432 precvpriv = &padapter->recvpriv;
1433 ppending_queue = &precvpriv->recv_buf_pending_queue;
1434
1435 /* 3 1. enqueue recvbuf */
1436 rtw_enqueue_recvbuf(precvbuf, ppending_queue);
1437
1438 /* 3 2. schedule tasklet */
1439 #ifdef PLATFORM_LINUX
1440 tasklet_schedule(&precvpriv->recv_tasklet);
1441 #endif
1442 }
1443
sd_int_dpc(PADAPTER padapter)1444 void sd_int_dpc(PADAPTER padapter)
1445 {
1446 PHAL_DATA_TYPE phal;
1447 struct dvobj_priv *dvobj;
1448 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
1449 struct pwrctrl_priv *pwrctl;
1450
1451
1452 phal = GET_HAL_DATA(padapter);
1453 dvobj = adapter_to_dvobj(padapter);
1454 pwrctl = dvobj_to_pwrctl(dvobj);
1455
1456 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
1457 if (phal->sdio_hisr & SDIO_HISR_AVAL) {
1458 /* _irqL irql; */
1459 u8 freepage[4];
1460
1461 _sdio_local_read(padapter, SDIO_REG_FREE_TXPG, 4, freepage);
1462 /* _enter_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); */
1463 /* _rtw_memcpy(phal->SdioTxFIFOFreePage, freepage, 4); */
1464 /* _exit_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql); */
1465 /* RTW_INFO("SDIO_HISR_AVAL, Tx Free Page = 0x%x%x%x%x\n", */
1466 /* freepage[0], */
1467 /* freepage[1], */
1468 /* freepage[2], */
1469 /* freepage[3]); */
1470 _rtw_up_sema(&(padapter->xmitpriv.xmit_sema));
1471 }
1472 #endif
1473 if (phal->sdio_hisr & SDIO_HISR_CPWM1) {
1474 struct reportpwrstate_parm report;
1475
1476 #ifdef CONFIG_LPS_RPWM_TIMER
1477 _cancel_timer_ex(&(pwrctl->pwr_rpwm_timer));
1478 #endif /* CONFIG_LPS_RPWM_TIMER */
1479
1480 report.state = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HCPWM1_8723B);
1481
1482 #ifdef CONFIG_LPS_LCLK
1483 /* cpwm_int_hdl(padapter, &report); */
1484 _set_workitem(&(pwrctl->cpwm_event));
1485 #endif
1486 }
1487
1488 if (phal->sdio_hisr & SDIO_HISR_TXERR) {
1489 u8 *status;
1490 u32 addr;
1491
1492 status = rtw_malloc(4);
1493 if (status) {
1494 addr = REG_TXDMA_STATUS;
1495 HalSdioGetCmdAddr8723BSdio(padapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
1496 _sd_read(pintfhdl, addr, 4, status);
1497 _sd_write(pintfhdl, addr, 4, status);
1498 RTW_INFO("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32 *)status));
1499 rtw_mfree(status, 4);
1500 } else
1501 RTW_INFO("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__);
1502 }
1503
1504 if (phal->sdio_hisr & SDIO_HISR_TXBCNOK)
1505 RTW_INFO("%s: SDIO_HISR_TXBCNOK\n", __func__);
1506
1507 if (phal->sdio_hisr & SDIO_HISR_TXBCNERR)
1508 RTW_INFO("%s: SDIO_HISR_TXBCNERR\n", __func__);
1509
1510 #ifdef CONFIG_FW_C2H_REG
1511 if (phal->sdio_hisr & SDIO_HISR_C2HCMD) {
1512 RTW_INFO("%s: C2H Command\n", __func__);
1513 sd_c2h_hisr_hdl(padapter);
1514 }
1515 #endif
1516
1517 if (phal->sdio_hisr & SDIO_HISR_RXFOVW)
1518 RTW_INFO("%s: Rx Overflow\n", __func__);
1519 if (phal->sdio_hisr & SDIO_HISR_RXERR)
1520 RTW_INFO("%s: Rx Error\n", __func__);
1521
1522 if (phal->sdio_hisr & SDIO_HISR_RX_REQUEST) {
1523 struct recv_buf *precvbuf;
1524 int alloc_fail_time = 0;
1525 u32 hisr;
1526
1527 /* RTW_INFO("%s: RX Request, size=%d\n", __func__, phal->SdioRxFIFOSize); */
1528 phal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
1529 do {
1530 phal->SdioRxFIFOSize = SdioLocalCmd52Read2Byte(padapter, SDIO_REG_RX0_REQ_LEN);
1531 if (phal->SdioRxFIFOSize != 0) {
1532 #ifdef CONFIG_MAC_LOOPBACK_DRIVER
1533 sd_recv_loopback(padapter, phal->SdioRxFIFOSize);
1534 #else
1535 precvbuf = sd_recv_rxfifo(padapter, phal->SdioRxFIFOSize);
1536 if (precvbuf)
1537 sd_rxhandler(padapter, precvbuf);
1538 else {
1539 alloc_fail_time++;
1540 RTW_INFO("%s: recv fail!(time=%d)\n", __func__, alloc_fail_time);
1541 if (alloc_fail_time >= 10)
1542 break;
1543 }
1544 phal->SdioRxFIFOSize = 0;
1545 #endif
1546 } else
1547 break;
1548
1549 hisr = 0;
1550 ReadInterrupt8723BSdio(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 ReadInterrupt8723BSdio(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 * */
HalQueryTxBufferStatus8723BSdio(PADAPTER padapter)1598 u8 HalQueryTxBufferStatus8723BSdio(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 * */
HalQueryTxOQTBufferStatus8723BSdio(PADAPTER padapter)1620 u8 HalQueryTxOQTBufferStatus8723BSdio(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 precvbuf = sd_recv_rxfifo(padapter, len);
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