]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/staging/rtl8723bs/hal/sdio_ops.c
staging: rtl8723bs: Remove unnecessary rtw_z?malloc casts
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / rtl8723bs / hal / sdio_ops.c
1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
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 <drv_types.h>
18 #include <rtw_debug.h>
19 #include <rtl8723b_hal.h>
20
21 /* define SDIO_DEBUG_IO 1 */
22
23
24 /* */
25 /* Description: */
26 /* The following mapping is for SDIO host local register space. */
27 /* */
28 /* Creadted by Roger, 2011.01.31. */
29 /* */
30 static void HalSdioGetCmdAddr8723BSdio(
31 struct adapter *padapter,
32 u8 DeviceID,
33 u32 Addr,
34 u32 *pCmdAddr
35 )
36 {
37 switch (DeviceID) {
38 case SDIO_LOCAL_DEVICE_ID:
39 *pCmdAddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (Addr & SDIO_LOCAL_MSK));
40 break;
41
42 case WLAN_IOREG_DEVICE_ID:
43 *pCmdAddr = ((WLAN_IOREG_DEVICE_ID << 13) | (Addr & WLAN_IOREG_MSK));
44 break;
45
46 case WLAN_TX_HIQ_DEVICE_ID:
47 *pCmdAddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
48 break;
49
50 case WLAN_TX_MIQ_DEVICE_ID:
51 *pCmdAddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
52 break;
53
54 case WLAN_TX_LOQ_DEVICE_ID:
55 *pCmdAddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
56 break;
57
58 case WLAN_RX0FF_DEVICE_ID:
59 *pCmdAddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (Addr & WLAN_RX0FF_MSK));
60 break;
61
62 default:
63 break;
64 }
65 }
66
67 static u8 get_deviceid(u32 addr)
68 {
69 u8 devideId;
70 u16 pseudoId;
71
72
73 pseudoId = (u16)(addr >> 16);
74 switch (pseudoId) {
75 case 0x1025:
76 devideId = SDIO_LOCAL_DEVICE_ID;
77 break;
78
79 case 0x1026:
80 devideId = WLAN_IOREG_DEVICE_ID;
81 break;
82
83 /* case 0x1027: */
84 /* devideId = SDIO_FIRMWARE_FIFO; */
85 /* break; */
86
87 case 0x1031:
88 devideId = WLAN_TX_HIQ_DEVICE_ID;
89 break;
90
91 case 0x1032:
92 devideId = WLAN_TX_MIQ_DEVICE_ID;
93 break;
94
95 case 0x1033:
96 devideId = WLAN_TX_LOQ_DEVICE_ID;
97 break;
98
99 case 0x1034:
100 devideId = WLAN_RX0FF_DEVICE_ID;
101 break;
102
103 default:
104 /* devideId = (u8)((addr >> 13) & 0xF); */
105 devideId = WLAN_IOREG_DEVICE_ID;
106 break;
107 }
108
109 return devideId;
110 }
111
112 /*
113 * Ref:
114 *HalSdioGetCmdAddr8723BSdio()
115 */
116 static u32 _cvrt2ftaddr(const u32 addr, u8 *pdeviceId, u16 *poffset)
117 {
118 u8 deviceId;
119 u16 offset;
120 u32 ftaddr;
121
122
123 deviceId = get_deviceid(addr);
124 offset = 0;
125
126 switch (deviceId) {
127 case SDIO_LOCAL_DEVICE_ID:
128 offset = addr & SDIO_LOCAL_MSK;
129 break;
130
131 case WLAN_TX_HIQ_DEVICE_ID:
132 case WLAN_TX_MIQ_DEVICE_ID:
133 case WLAN_TX_LOQ_DEVICE_ID:
134 offset = addr & WLAN_FIFO_MSK;
135 break;
136
137 case WLAN_RX0FF_DEVICE_ID:
138 offset = addr & WLAN_RX0FF_MSK;
139 break;
140
141 case WLAN_IOREG_DEVICE_ID:
142 default:
143 deviceId = WLAN_IOREG_DEVICE_ID;
144 offset = addr & WLAN_IOREG_MSK;
145 break;
146 }
147 ftaddr = (deviceId << 13) | offset;
148
149 if (pdeviceId)
150 *pdeviceId = deviceId;
151 if (poffset)
152 *poffset = offset;
153
154 return ftaddr;
155 }
156
157 static u8 sdio_read8(struct intf_hdl *pintfhdl, u32 addr)
158 {
159 u32 ftaddr;
160 u8 val;
161
162 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
163 val = sd_read8(pintfhdl, ftaddr, NULL);
164 return val;
165 }
166
167 static u16 sdio_read16(struct intf_hdl *pintfhdl, u32 addr)
168 {
169 u32 ftaddr;
170 u16 val;
171 __le16 le_tmp;
172
173 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
174 sd_cmd52_read(pintfhdl, ftaddr, 2, (u8 *)&le_tmp);
175 val = le16_to_cpu(le_tmp);
176 return val;
177 }
178
179 static u32 sdio_read32(struct intf_hdl *pintfhdl, u32 addr)
180 {
181 struct adapter *padapter;
182 u8 bMacPwrCtrlOn;
183 u8 deviceId;
184 u16 offset;
185 u32 ftaddr;
186 u8 shift;
187 u32 val;
188 s32 err;
189 __le32 le_tmp;
190
191 padapter = pintfhdl->padapter;
192 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
193
194 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
195 if (
196 ((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
197 (false == bMacPwrCtrlOn) ||
198 (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
199 ) {
200 err = sd_cmd52_read(pintfhdl, ftaddr, 4, (u8 *)&le_tmp);
201 #ifdef SDIO_DEBUG_IO
202 if (!err) {
203 #endif
204 val = le32_to_cpu(le_tmp);
205 return val;
206 #ifdef SDIO_DEBUG_IO
207 }
208
209 DBG_8192C(KERN_ERR "%s: Mac Power off, Read FAIL(%d)! addr = 0x%x\n", __func__, err, addr);
210 return SDIO_ERR_VAL32;
211 #endif
212 }
213
214 /* 4 bytes alignment */
215 shift = ftaddr & 0x3;
216 if (shift == 0) {
217 val = sd_read32(pintfhdl, ftaddr, NULL);
218 } else {
219 u8 *ptmpbuf;
220
221 ptmpbuf = rtw_malloc(8);
222 if (NULL == ptmpbuf) {
223 DBG_8192C(KERN_ERR "%s: Allocate memory FAIL!(size =8) addr = 0x%x\n", __func__, addr);
224 return SDIO_ERR_VAL32;
225 }
226
227 ftaddr &= ~(u16)0x3;
228 sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
229 memcpy(&le_tmp, ptmpbuf+shift, 4);
230 val = le32_to_cpu(le_tmp);
231
232 kfree(ptmpbuf);
233 }
234 return val;
235 }
236
237 static s32 sdio_readN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
238 {
239 struct adapter *padapter;
240 u8 bMacPwrCtrlOn;
241 u8 deviceId;
242 u16 offset;
243 u32 ftaddr;
244 u8 shift;
245 s32 err;
246
247 padapter = pintfhdl->padapter;
248 err = 0;
249
250 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
251
252 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
253 if (
254 ((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
255 (false == bMacPwrCtrlOn) ||
256 (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
257 ) {
258 err = sd_cmd52_read(pintfhdl, ftaddr, cnt, pbuf);
259 return err;
260 }
261
262 /* 4 bytes alignment */
263 shift = ftaddr & 0x3;
264 if (shift == 0) {
265 err = sd_read(pintfhdl, ftaddr, cnt, pbuf);
266 } else {
267 u8 *ptmpbuf;
268 u32 n;
269
270 ftaddr &= ~(u16)0x3;
271 n = cnt + shift;
272 ptmpbuf = rtw_malloc(n);
273 if (NULL == ptmpbuf)
274 return -1;
275
276 err = sd_read(pintfhdl, ftaddr, n, ptmpbuf);
277 if (!err)
278 memcpy(pbuf, ptmpbuf+shift, cnt);
279 kfree(ptmpbuf);
280 }
281 return err;
282 }
283
284 static s32 sdio_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
285 {
286 u32 ftaddr;
287 s32 err;
288
289 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
290 sd_write8(pintfhdl, ftaddr, val, &err);
291
292 return err;
293 }
294
295 static s32 sdio_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
296 {
297 u32 ftaddr;
298 s32 err;
299 __le16 le_tmp;
300
301 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
302 le_tmp = cpu_to_le16(val);
303 err = sd_cmd52_write(pintfhdl, ftaddr, 2, (u8 *)&le_tmp);
304
305 return err;
306 }
307
308 static s32 sdio_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
309 {
310 struct adapter *padapter;
311 u8 bMacPwrCtrlOn;
312 u8 deviceId;
313 u16 offset;
314 u32 ftaddr;
315 u8 shift;
316 s32 err;
317 __le32 le_tmp;
318
319 padapter = pintfhdl->padapter;
320 err = 0;
321
322 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
323
324 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
325 if (
326 ((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
327 (!bMacPwrCtrlOn) ||
328 (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
329 ) {
330 le_tmp = cpu_to_le32(val);
331 err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&le_tmp);
332 return err;
333 }
334
335 /* 4 bytes alignment */
336 shift = ftaddr & 0x3;
337 if (shift == 0) {
338 sd_write32(pintfhdl, ftaddr, val, &err);
339 } else {
340 le_tmp = cpu_to_le32(val);
341 err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&le_tmp);
342 }
343 return err;
344 }
345
346 static s32 sdio_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
347 {
348 struct adapter *padapter;
349 u8 bMacPwrCtrlOn;
350 u8 deviceId;
351 u16 offset;
352 u32 ftaddr;
353 u8 shift;
354 s32 err;
355
356 padapter = pintfhdl->padapter;
357 err = 0;
358
359 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
360
361 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
362 if (
363 ((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
364 (false == bMacPwrCtrlOn) ||
365 (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
366 ) {
367 err = sd_cmd52_write(pintfhdl, ftaddr, cnt, pbuf);
368 return err;
369 }
370
371 shift = ftaddr & 0x3;
372 if (shift == 0) {
373 err = sd_write(pintfhdl, ftaddr, cnt, pbuf);
374 } else {
375 u8 *ptmpbuf;
376 u32 n;
377
378 ftaddr &= ~(u16)0x3;
379 n = cnt + shift;
380 ptmpbuf = rtw_malloc(n);
381 if (NULL == ptmpbuf)
382 return -1;
383 err = sd_read(pintfhdl, ftaddr, 4, ptmpbuf);
384 if (err) {
385 kfree(ptmpbuf);
386 return err;
387 }
388 memcpy(ptmpbuf+shift, pbuf, cnt);
389 err = sd_write(pintfhdl, ftaddr, n, ptmpbuf);
390 kfree(ptmpbuf);
391 }
392 return err;
393 }
394
395 static u8 sdio_f0_read8(struct intf_hdl *pintfhdl, u32 addr)
396 {
397 return sd_f0_read8(pintfhdl, addr, NULL);
398 }
399
400 static void sdio_read_mem(
401 struct intf_hdl *pintfhdl,
402 u32 addr,
403 u32 cnt,
404 u8 *rmem
405 )
406 {
407 s32 err;
408
409 err = sdio_readN(pintfhdl, addr, cnt, rmem);
410 /* TODO: Report error is err not zero */
411 }
412
413 static void sdio_write_mem(
414 struct intf_hdl *pintfhdl,
415 u32 addr,
416 u32 cnt,
417 u8 *wmem
418 )
419 {
420 sdio_writeN(pintfhdl, addr, cnt, wmem);
421 }
422
423 /*
424 * Description:
425 *Read from RX FIFO
426 *Round read size to block size,
427 *and make sure data transfer will be done in one command.
428 *
429 * Parameters:
430 *pintfhdl a pointer of intf_hdl
431 *addr port ID
432 *cnt size to read
433 *rmem address to put data
434 *
435 * Return:
436 *_SUCCESS(1) Success
437 *_FAIL(0) Fail
438 */
439 static u32 sdio_read_port(
440 struct intf_hdl *pintfhdl,
441 u32 addr,
442 u32 cnt,
443 u8 *mem
444 )
445 {
446 struct adapter *padapter;
447 PSDIO_DATA psdio;
448 struct hal_com_data *phal;
449 u32 oldcnt;
450 #ifdef SDIO_DYNAMIC_ALLOC_MEM
451 u8 *oldmem;
452 #endif
453 s32 err;
454
455
456 padapter = pintfhdl->padapter;
457 psdio = &adapter_to_dvobj(padapter)->intf_data;
458 phal = GET_HAL_DATA(padapter);
459
460 HalSdioGetCmdAddr8723BSdio(padapter, addr, phal->SdioRxFIFOCnt++, &addr);
461
462 oldcnt = cnt;
463 if (cnt > psdio->block_transfer_len)
464 cnt = _RND(cnt, psdio->block_transfer_len);
465 /* cnt = sdio_align_size(cnt); */
466
467 if (oldcnt != cnt) {
468 #ifdef SDIO_DYNAMIC_ALLOC_MEM
469 oldmem = mem;
470 mem = rtw_malloc(cnt);
471 if (mem == NULL) {
472 DBG_8192C(KERN_WARNING "%s: allocate memory %d bytes fail!\n", __func__, cnt);
473 mem = oldmem;
474 oldmem == NULL;
475 }
476 #else
477 /* in this case, caller should gurante the buffer is big enough */
478 /* to receive data after alignment */
479 #endif
480 }
481
482 err = _sd_read(pintfhdl, addr, cnt, mem);
483
484 #ifdef SDIO_DYNAMIC_ALLOC_MEM
485 if ((oldcnt != cnt) && (oldmem)) {
486 memcpy(oldmem, mem, oldcnt);
487 kfree(mem);
488 }
489 #endif
490
491 if (err)
492 return _FAIL;
493 return _SUCCESS;
494 }
495
496 /*
497 * Description:
498 *Write to TX FIFO
499 *Align write size block size,
500 *and make sure data could be written in one command.
501 *
502 * Parameters:
503 *pintfhdl a pointer of intf_hdl
504 *addr port ID
505 *cnt size to write
506 *wmem data pointer to write
507 *
508 * Return:
509 *_SUCCESS(1) Success
510 *_FAIL(0) Fail
511 */
512 static u32 sdio_write_port(
513 struct intf_hdl *pintfhdl,
514 u32 addr,
515 u32 cnt,
516 u8 *mem
517 )
518 {
519 struct adapter *padapter;
520 PSDIO_DATA psdio;
521 s32 err;
522 struct xmit_buf *xmitbuf = (struct xmit_buf *)mem;
523
524 padapter = pintfhdl->padapter;
525 psdio = &adapter_to_dvobj(padapter)->intf_data;
526
527 if (padapter->hw_init_completed == false) {
528 DBG_871X("%s [addr = 0x%x cnt =%d] padapter->hw_init_completed == false\n", __func__, addr, cnt);
529 return _FAIL;
530 }
531
532 cnt = _RND4(cnt);
533 HalSdioGetCmdAddr8723BSdio(padapter, addr, cnt >> 2, &addr);
534
535 if (cnt > psdio->block_transfer_len)
536 cnt = _RND(cnt, psdio->block_transfer_len);
537 /* cnt = sdio_align_size(cnt); */
538
539 err = sd_write(pintfhdl, addr, cnt, xmitbuf->pdata);
540
541 rtw_sctx_done_err(
542 &xmitbuf->sctx,
543 err ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS
544 );
545
546 if (err)
547 return _FAIL;
548 return _SUCCESS;
549 }
550
551 void sdio_set_intf_ops(struct adapter *padapter, struct _io_ops *pops)
552 {
553 pops->_read8 = &sdio_read8;
554 pops->_read16 = &sdio_read16;
555 pops->_read32 = &sdio_read32;
556 pops->_read_mem = &sdio_read_mem;
557 pops->_read_port = &sdio_read_port;
558
559 pops->_write8 = &sdio_write8;
560 pops->_write16 = &sdio_write16;
561 pops->_write32 = &sdio_write32;
562 pops->_writeN = &sdio_writeN;
563 pops->_write_mem = &sdio_write_mem;
564 pops->_write_port = &sdio_write_port;
565
566 pops->_sd_f0_read8 = sdio_f0_read8;
567 }
568
569 /*
570 * Todo: align address to 4 bytes.
571 */
572 static s32 _sdio_local_read(
573 struct adapter *padapter,
574 u32 addr,
575 u32 cnt,
576 u8 *pbuf
577 )
578 {
579 struct intf_hdl *pintfhdl;
580 u8 bMacPwrCtrlOn;
581 s32 err;
582 u8 *ptmpbuf;
583 u32 n;
584
585
586 pintfhdl = &padapter->iopriv.intf;
587
588 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
589
590 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
591 if (false == bMacPwrCtrlOn) {
592 err = _sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
593 return err;
594 }
595
596 n = RND4(cnt);
597 ptmpbuf = rtw_malloc(n);
598 if (!ptmpbuf)
599 return (-1);
600
601 err = _sd_read(pintfhdl, addr, n, ptmpbuf);
602 if (!err)
603 memcpy(pbuf, ptmpbuf, cnt);
604
605 kfree(ptmpbuf);
606
607 return err;
608 }
609
610 /*
611 * Todo: align address to 4 bytes.
612 */
613 s32 sdio_local_read(
614 struct adapter *padapter,
615 u32 addr,
616 u32 cnt,
617 u8 *pbuf
618 )
619 {
620 struct intf_hdl *pintfhdl;
621 u8 bMacPwrCtrlOn;
622 s32 err;
623 u8 *ptmpbuf;
624 u32 n;
625
626 pintfhdl = &padapter->iopriv.intf;
627
628 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
629
630 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
631 if (
632 (false == bMacPwrCtrlOn) ||
633 (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
634 ) {
635 err = sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
636 return err;
637 }
638
639 n = RND4(cnt);
640 ptmpbuf = rtw_malloc(n);
641 if (!ptmpbuf)
642 return (-1);
643
644 err = sd_read(pintfhdl, addr, n, ptmpbuf);
645 if (!err)
646 memcpy(pbuf, ptmpbuf, cnt);
647
648 kfree(ptmpbuf);
649
650 return err;
651 }
652
653 /*
654 * Todo: align address to 4 bytes.
655 */
656 s32 sdio_local_write(
657 struct adapter *padapter,
658 u32 addr,
659 u32 cnt,
660 u8 *pbuf
661 )
662 {
663 struct intf_hdl *pintfhdl;
664 u8 bMacPwrCtrlOn;
665 s32 err;
666 u8 *ptmpbuf;
667
668 if (addr & 0x3)
669 DBG_8192C("%s, address must be 4 bytes alignment\n", __func__);
670
671 if (cnt & 0x3)
672 DBG_8192C("%s, size must be the multiple of 4\n", __func__);
673
674 pintfhdl = &padapter->iopriv.intf;
675
676 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
677
678 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
679 if (
680 (false == bMacPwrCtrlOn) ||
681 (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)
682 ) {
683 err = sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
684 return err;
685 }
686
687 ptmpbuf = rtw_malloc(cnt);
688 if (!ptmpbuf)
689 return (-1);
690
691 memcpy(ptmpbuf, pbuf, cnt);
692
693 err = sd_write(pintfhdl, addr, cnt, ptmpbuf);
694
695 kfree(ptmpbuf);
696
697 return err;
698 }
699
700 u8 SdioLocalCmd52Read1Byte(struct adapter *padapter, u32 addr)
701 {
702 u8 val = 0;
703 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
704
705 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
706 sd_cmd52_read(pintfhdl, addr, 1, &val);
707
708 return val;
709 }
710
711 static u16 SdioLocalCmd52Read2Byte(struct adapter *padapter, u32 addr)
712 {
713 __le16 val = 0;
714 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
715
716 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
717 sd_cmd52_read(pintfhdl, addr, 2, (u8 *)&val);
718
719 return le16_to_cpu(val);
720 }
721
722 static u32 SdioLocalCmd53Read4Byte(struct adapter *padapter, u32 addr)
723 {
724
725 u8 bMacPwrCtrlOn;
726 u32 val = 0;
727 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
728 __le32 le_tmp;
729
730 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
731 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
732 if (!bMacPwrCtrlOn || adapter_to_pwrctl(padapter)->bFwCurrentInPSMode) {
733 sd_cmd52_read(pintfhdl, addr, 4, (u8 *)&le_tmp);
734 val = le32_to_cpu(le_tmp);
735 } else {
736 val = sd_read32(pintfhdl, addr, NULL);
737 }
738 return val;
739 }
740
741 void SdioLocalCmd52Write1Byte(struct adapter *padapter, u32 addr, u8 v)
742 {
743 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
744
745 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
746 sd_cmd52_write(pintfhdl, addr, 1, &v);
747 }
748
749 static void SdioLocalCmd52Write4Byte(struct adapter *padapter, u32 addr, u32 v)
750 {
751 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
752 __le32 le_tmp;
753
754 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
755 le_tmp = cpu_to_le32(v);
756 sd_cmd52_write(pintfhdl, addr, 4, (u8 *)&le_tmp);
757 }
758
759 static s32 ReadInterrupt8723BSdio(struct adapter *padapter, u32 *phisr)
760 {
761 u32 hisr, himr;
762 u8 val8, hisr_len;
763
764
765 if (phisr == NULL)
766 return false;
767
768 himr = GET_HAL_DATA(padapter)->sdio_himr;
769
770 /* decide how many bytes need to be read */
771 hisr_len = 0;
772 while (himr) {
773 hisr_len++;
774 himr >>= 8;
775 }
776
777 hisr = 0;
778 while (hisr_len != 0) {
779 hisr_len--;
780 val8 = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HISR+hisr_len);
781 hisr |= (val8 << (8*hisr_len));
782 }
783
784 *phisr = hisr;
785
786 return true;
787 }
788
789 /* */
790 /* Description: */
791 /* Initialize SDIO Host Interrupt Mask configuration variables for future use. */
792 /* */
793 /* Assumption: */
794 /* Using SDIO Local register ONLY for configuration. */
795 /* */
796 /* Created by Roger, 2011.02.11. */
797 /* */
798 void InitInterrupt8723BSdio(struct adapter *padapter)
799 {
800 struct hal_com_data *pHalData;
801
802
803 pHalData = GET_HAL_DATA(padapter);
804 pHalData->sdio_himr = (u32)( \
805 SDIO_HIMR_RX_REQUEST_MSK |
806 SDIO_HIMR_AVAL_MSK |
807 /* SDIO_HIMR_TXERR_MSK | */
808 /* SDIO_HIMR_RXERR_MSK | */
809 /* SDIO_HIMR_TXFOVW_MSK | */
810 /* SDIO_HIMR_RXFOVW_MSK | */
811 /* SDIO_HIMR_TXBCNOK_MSK | */
812 /* SDIO_HIMR_TXBCNERR_MSK | */
813 /* SDIO_HIMR_BCNERLY_INT_MSK | */
814 /* SDIO_HIMR_C2HCMD_MSK | */
815 /* SDIO_HIMR_HSISR_IND_MSK | */
816 /* SDIO_HIMR_GTINT3_IND_MSK | */
817 /* SDIO_HIMR_GTINT4_IND_MSK | */
818 /* SDIO_HIMR_PSTIMEOUT_MSK | */
819 /* SDIO_HIMR_OCPINT_MSK | */
820 /* SDIO_HIMR_ATIMEND_MSK | */
821 /* SDIO_HIMR_ATIMEND_E_MSK | */
822 /* SDIO_HIMR_CTWEND_MSK | */
823 0);
824 }
825
826 /* */
827 /* Description: */
828 /* Initialize System Host Interrupt Mask configuration variables for future use. */
829 /* */
830 /* Created by Roger, 2011.08.03. */
831 /* */
832 void InitSysInterrupt8723BSdio(struct adapter *padapter)
833 {
834 struct hal_com_data *pHalData;
835
836
837 pHalData = GET_HAL_DATA(padapter);
838
839 pHalData->SysIntrMask = ( \
840 /* HSIMR_GPIO12_0_INT_EN | */
841 /* HSIMR_SPS_OCP_INT_EN | */
842 /* HSIMR_RON_INT_EN | */
843 /* HSIMR_PDNINT_EN | */
844 /* HSIMR_GPIO9_INT_EN | */
845 0);
846 }
847
848 #ifdef CONFIG_WOWLAN
849 /* */
850 /* Description: */
851 /* Clear corresponding SDIO Host ISR interrupt service. */
852 /* */
853 /* Assumption: */
854 /* Using SDIO Local register ONLY for configuration. */
855 /* */
856 /* Created by Roger, 2011.02.11. */
857 /* */
858 void ClearInterrupt8723BSdio(struct adapter *padapter)
859 {
860 struct hal_com_data *pHalData;
861 u8 *clear;
862
863
864 if (true == padapter->bSurpriseRemoved)
865 return;
866
867 pHalData = GET_HAL_DATA(padapter);
868 clear = rtw_zmalloc(4);
869
870 /* Clear corresponding HISR Content if needed */
871 *(__le32 *)clear = cpu_to_le32(pHalData->sdio_hisr & MASK_SDIO_HISR_CLEAR);
872 if (*(__le32 *)clear) {
873 /* Perform write one clear operation */
874 sdio_local_write(padapter, SDIO_REG_HISR, 4, clear);
875 }
876
877 kfree(clear);
878 }
879 #endif
880
881 /* */
882 /* Description: */
883 /* Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain. */
884 /* */
885 /* Assumption: */
886 /* 1. Using SDIO Local register ONLY for configuration. */
887 /* 2. PASSIVE LEVEL */
888 /* */
889 /* Created by Roger, 2011.02.11. */
890 /* */
891 void EnableInterrupt8723BSdio(struct adapter *padapter)
892 {
893 struct hal_com_data *pHalData;
894 __le32 himr;
895 u32 tmp;
896
897 pHalData = GET_HAL_DATA(padapter);
898
899 himr = cpu_to_le32(pHalData->sdio_himr);
900 sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
901
902 RT_TRACE(
903 _module_hci_ops_c_,
904 _drv_notice_,
905 (
906 "%s: enable SDIO HIMR = 0x%08X\n",
907 __func__,
908 pHalData->sdio_himr
909 )
910 );
911
912 /* Update current system IMR settings */
913 tmp = rtw_read32(padapter, REG_HSIMR);
914 rtw_write32(padapter, REG_HSIMR, tmp | pHalData->SysIntrMask);
915
916 RT_TRACE(
917 _module_hci_ops_c_,
918 _drv_notice_,
919 (
920 "%s: enable HSIMR = 0x%08X\n",
921 __func__,
922 pHalData->SysIntrMask
923 )
924 );
925
926 /* */
927 /* <Roger_Notes> There are some C2H CMDs have been sent before system interrupt is enabled, e.g., C2H, CPWM. */
928 /* So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore. */
929 /* 2011.10.19. */
930 /* */
931 rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
932 }
933
934 /* */
935 /* Description: */
936 /* Disable SDIO Host IMR configuration to mask unnecessary interrupt service. */
937 /* */
938 /* Assumption: */
939 /* Using SDIO Local register ONLY for configuration. */
940 /* */
941 /* Created by Roger, 2011.02.11. */
942 /* */
943 void DisableInterrupt8723BSdio(struct adapter *padapter)
944 {
945 __le32 himr;
946
947 himr = cpu_to_le32(SDIO_HIMR_DISABLED);
948 sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
949 }
950
951 /* */
952 /* Description: */
953 /* Using 0x100 to check the power status of FW. */
954 /* */
955 /* Assumption: */
956 /* Using SDIO Local register ONLY for configuration. */
957 /* */
958 /* Created by Isaac, 2013.09.10. */
959 /* */
960 u8 CheckIPSStatus(struct adapter *padapter)
961 {
962 DBG_871X(
963 "%s(): Read 0x100 = 0x%02x 0x86 = 0x%02x\n",
964 __func__,
965 rtw_read8(padapter, 0x100),
966 rtw_read8(padapter, 0x86)
967 );
968
969 if (rtw_read8(padapter, 0x100) == 0xEA)
970 return true;
971 else
972 return false;
973 }
974
975 static struct recv_buf *sd_recv_rxfifo(struct adapter *padapter, u32 size)
976 {
977 u32 readsize, ret;
978 u8 *preadbuf;
979 struct recv_priv *precvpriv;
980 struct recv_buf *precvbuf;
981
982
983 /* Patch for some SDIO Host 4 bytes issue */
984 /* ex. RK3188 */
985 readsize = RND4(size);
986
987 /* 3 1. alloc recvbuf */
988 precvpriv = &padapter->recvpriv;
989 precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
990 if (precvbuf == NULL) {
991 DBG_871X_LEVEL(_drv_err_, "%s: alloc recvbuf FAIL!\n", __func__);
992 return NULL;
993 }
994
995 /* 3 2. alloc skb */
996 if (precvbuf->pskb == NULL) {
997 SIZE_PTR tmpaddr = 0;
998 SIZE_PTR alignment = 0;
999
1000 precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
1001
1002 if (precvbuf->pskb) {
1003 precvbuf->pskb->dev = padapter->pnetdev;
1004
1005 tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
1006 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
1007 skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
1008 }
1009
1010 if (precvbuf->pskb == NULL) {
1011 DBG_871X("%s: alloc_skb fail! read =%d\n", __func__, readsize);
1012 return NULL;
1013 }
1014 }
1015
1016 /* 3 3. read data from rxfifo */
1017 preadbuf = precvbuf->pskb->data;
1018 ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
1019 if (ret == _FAIL) {
1020 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __func__));
1021 return NULL;
1022 }
1023
1024
1025 /* 3 4. init recvbuf */
1026 precvbuf->len = size;
1027 precvbuf->phead = precvbuf->pskb->head;
1028 precvbuf->pdata = precvbuf->pskb->data;
1029 skb_set_tail_pointer(precvbuf->pskb, size);
1030 precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
1031 precvbuf->pend = skb_end_pointer(precvbuf->pskb);
1032
1033 return precvbuf;
1034 }
1035
1036 static void sd_rxhandler(struct adapter *padapter, struct recv_buf *precvbuf)
1037 {
1038 struct recv_priv *precvpriv;
1039 struct __queue *ppending_queue;
1040
1041 precvpriv = &padapter->recvpriv;
1042 ppending_queue = &precvpriv->recv_buf_pending_queue;
1043
1044 /* 3 1. enqueue recvbuf */
1045 rtw_enqueue_recvbuf(precvbuf, ppending_queue);
1046
1047 /* 3 2. schedule tasklet */
1048 tasklet_schedule(&precvpriv->recv_tasklet);
1049 }
1050
1051 void sd_int_dpc(struct adapter *padapter)
1052 {
1053 struct hal_com_data *phal;
1054 struct dvobj_priv *dvobj;
1055 struct intf_hdl *pintfhdl = &padapter->iopriv.intf;
1056 struct pwrctrl_priv *pwrctl;
1057
1058
1059 phal = GET_HAL_DATA(padapter);
1060 dvobj = adapter_to_dvobj(padapter);
1061 pwrctl = dvobj_to_pwrctl(dvobj);
1062
1063 if (phal->sdio_hisr & SDIO_HISR_AVAL) {
1064 u8 freepage[4];
1065
1066 _sdio_local_read(padapter, SDIO_REG_FREE_TXPG, 4, freepage);
1067 up(&(padapter->xmitpriv.xmit_sema));
1068 }
1069
1070 if (phal->sdio_hisr & SDIO_HISR_CPWM1) {
1071 struct reportpwrstate_parm report;
1072
1073 u8 bcancelled;
1074 _cancel_timer(&(pwrctl->pwr_rpwm_timer), &bcancelled);
1075
1076 report.state = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HCPWM1_8723B);
1077
1078 /* cpwm_int_hdl(padapter, &report); */
1079 _set_workitem(&(pwrctl->cpwm_event));
1080 }
1081
1082 if (phal->sdio_hisr & SDIO_HISR_TXERR) {
1083 u8 *status;
1084 u32 addr;
1085
1086 status = rtw_malloc(4);
1087 if (status) {
1088 addr = REG_TXDMA_STATUS;
1089 HalSdioGetCmdAddr8723BSdio(padapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
1090 _sd_read(pintfhdl, addr, 4, status);
1091 _sd_write(pintfhdl, addr, 4, status);
1092 DBG_8192C("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32 *)status));
1093 kfree(status);
1094 } else {
1095 DBG_8192C("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__);
1096 }
1097 }
1098
1099 if (phal->sdio_hisr & SDIO_HISR_TXBCNOK) {
1100 DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__);
1101 }
1102
1103 if (phal->sdio_hisr & SDIO_HISR_TXBCNERR) {
1104 DBG_8192C("%s: SDIO_HISR_TXBCNERR\n", __func__);
1105 }
1106 #ifndef CONFIG_C2H_PACKET_EN
1107 if (phal->sdio_hisr & SDIO_HISR_C2HCMD) {
1108 struct c2h_evt_hdr_88xx *c2h_evt;
1109
1110 DBG_8192C("%s: C2H Command\n", __func__);
1111 c2h_evt = rtw_zmalloc(16);
1112 if (c2h_evt != NULL) {
1113 if (rtw_hal_c2h_evt_read(padapter, (u8 *)c2h_evt) == _SUCCESS) {
1114 if (c2h_id_filter_ccx_8723b((u8 *)c2h_evt)) {
1115 /* Handle CCX report here */
1116 rtw_hal_c2h_handler(padapter, (u8 *)c2h_evt);
1117 kfree((u8 *)c2h_evt);
1118 } else {
1119 rtw_c2h_wk_cmd(padapter, (u8 *)c2h_evt);
1120 }
1121 }
1122 } else {
1123 /* Error handling for malloc fail */
1124 if (rtw_cbuf_push(padapter->evtpriv.c2h_queue, NULL) != _SUCCESS)
1125 DBG_871X("%s rtw_cbuf_push fail\n", __func__);
1126 _set_workitem(&padapter->evtpriv.c2h_wk);
1127 }
1128 }
1129 #endif
1130
1131 if (phal->sdio_hisr & SDIO_HISR_RXFOVW) {
1132 DBG_8192C("%s: Rx Overflow\n", __func__);
1133 }
1134
1135 if (phal->sdio_hisr & SDIO_HISR_RXERR) {
1136 DBG_8192C("%s: Rx Error\n", __func__);
1137 }
1138
1139 if (phal->sdio_hisr & SDIO_HISR_RX_REQUEST) {
1140 struct recv_buf *precvbuf;
1141 int alloc_fail_time = 0;
1142 u32 hisr;
1143
1144 /* DBG_8192C("%s: RX Request, size =%d\n", __func__, phal->SdioRxFIFOSize); */
1145 phal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
1146 do {
1147 phal->SdioRxFIFOSize = SdioLocalCmd52Read2Byte(padapter, SDIO_REG_RX0_REQ_LEN);
1148 if (phal->SdioRxFIFOSize != 0) {
1149 precvbuf = sd_recv_rxfifo(padapter, phal->SdioRxFIFOSize);
1150 if (precvbuf)
1151 sd_rxhandler(padapter, precvbuf);
1152 else {
1153 alloc_fail_time++;
1154 DBG_871X("precvbuf is Null for %d times because alloc memory failed\n", alloc_fail_time);
1155 if (alloc_fail_time >= 10)
1156 break;
1157 }
1158 phal->SdioRxFIFOSize = 0;
1159 } else
1160 break;
1161
1162 hisr = 0;
1163 ReadInterrupt8723BSdio(padapter, &hisr);
1164 hisr &= SDIO_HISR_RX_REQUEST;
1165 if (!hisr)
1166 break;
1167 } while (1);
1168
1169 if (alloc_fail_time == 10)
1170 DBG_871X("exit because alloc memory failed more than 10 times\n");
1171
1172 }
1173 }
1174
1175 void sd_int_hdl(struct adapter *padapter)
1176 {
1177 struct hal_com_data *phal;
1178
1179
1180 if (
1181 (padapter->bDriverStopped == true) ||
1182 (padapter->bSurpriseRemoved == true)
1183 )
1184 return;
1185
1186 phal = GET_HAL_DATA(padapter);
1187
1188 phal->sdio_hisr = 0;
1189 ReadInterrupt8723BSdio(padapter, &phal->sdio_hisr);
1190
1191 if (phal->sdio_hisr & phal->sdio_himr) {
1192 u32 v32;
1193
1194 phal->sdio_hisr &= phal->sdio_himr;
1195
1196 /* clear HISR */
1197 v32 = phal->sdio_hisr & MASK_SDIO_HISR_CLEAR;
1198 if (v32) {
1199 SdioLocalCmd52Write4Byte(padapter, SDIO_REG_HISR, v32);
1200 }
1201
1202 sd_int_dpc(padapter);
1203 } else {
1204 RT_TRACE(_module_hci_ops_c_, _drv_err_,
1205 ("%s: HISR(0x%08x) and HIMR(0x%08x) not match!\n",
1206 __func__, phal->sdio_hisr, phal->sdio_himr));
1207 }
1208 }
1209
1210 /* */
1211 /* Description: */
1212 /* Query SDIO Local register to query current the number of Free TxPacketBuffer page. */
1213 /* */
1214 /* Assumption: */
1215 /* 1. Running at PASSIVE_LEVEL */
1216 /* 2. RT_TX_SPINLOCK is NOT acquired. */
1217 /* */
1218 /* Created by Roger, 2011.01.28. */
1219 /* */
1220 u8 HalQueryTxBufferStatus8723BSdio(struct adapter *padapter)
1221 {
1222 struct hal_com_data *phal;
1223 u32 NumOfFreePage;
1224 /* _irqL irql; */
1225
1226
1227 phal = GET_HAL_DATA(padapter);
1228
1229 NumOfFreePage = SdioLocalCmd53Read4Byte(padapter, SDIO_REG_FREE_TXPG);
1230
1231 /* spin_lock_bh(&phal->SdioTxFIFOFreePageLock); */
1232 memcpy(phal->SdioTxFIFOFreePage, &NumOfFreePage, 4);
1233 RT_TRACE(_module_hci_ops_c_, _drv_notice_,
1234 ("%s: Free page for HIQ(%#x), MIDQ(%#x), LOWQ(%#x), PUBQ(%#x)\n",
1235 __func__,
1236 phal->SdioTxFIFOFreePage[HI_QUEUE_IDX],
1237 phal->SdioTxFIFOFreePage[MID_QUEUE_IDX],
1238 phal->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
1239 phal->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
1240 /* spin_unlock_bh(&phal->SdioTxFIFOFreePageLock); */
1241
1242 return true;
1243 }
1244
1245 /* */
1246 /* Description: */
1247 /* Query SDIO Local register to get the current number of TX OQT Free Space. */
1248 /* */
1249 u8 HalQueryTxOQTBufferStatus8723BSdio(struct adapter *padapter)
1250 {
1251 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1252
1253 pHalData->SdioTxOQTFreeSpace = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_OQT_FREE_PG);
1254 return true;
1255 }
1256
1257 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
1258 u8 RecvOnePkt(struct adapter *padapter, u32 size)
1259 {
1260 struct recv_buf *precvbuf;
1261 struct dvobj_priv *psddev;
1262 PSDIO_DATA psdio_data;
1263 struct sdio_func *func;
1264
1265 u8 res = false;
1266
1267 DBG_871X("+%s: size: %d+\n", __func__, size);
1268
1269 if (padapter == NULL) {
1270 DBG_871X(KERN_ERR "%s: padapter is NULL!\n", __func__);
1271 return false;
1272 }
1273
1274 psddev = adapter_to_dvobj(padapter);
1275 psdio_data = &psddev->intf_data;
1276 func = psdio_data->func;
1277
1278 if (size) {
1279 sdio_claim_host(func);
1280 precvbuf = sd_recv_rxfifo(padapter, size);
1281
1282 if (precvbuf) {
1283 /* printk("Completed Recv One Pkt.\n"); */
1284 sd_rxhandler(padapter, precvbuf);
1285 res = true;
1286 } else {
1287 res = false;
1288 }
1289 sdio_release_host(func);
1290 }
1291 DBG_871X("-%s-\n", __func__);
1292 return res;
1293 }
1294 #endif /* CONFIG_WOWLAN */