1 /******************************************************************************
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
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.
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
14 *******************************************************************************/
17 #include <drv_types.h>
18 #include <rtw_debug.h>
19 #include <rtl8723b_hal.h>
21 /* define SDIO_DEBUG_IO 1 */
26 /* The following mapping is for SDIO host local register space. */
28 /* Creadted by Roger, 2011.01.31. */
30 static void HalSdioGetCmdAddr8723BSdio(
31 struct adapter * padapter,
39 case SDIO_LOCAL_DEVICE_ID:
40 *pCmdAddr = ((SDIO_LOCAL_DEVICE_ID << 13) | (Addr & SDIO_LOCAL_MSK));
43 case WLAN_IOREG_DEVICE_ID:
44 *pCmdAddr = ((WLAN_IOREG_DEVICE_ID << 13) | (Addr & WLAN_IOREG_MSK));
47 case WLAN_TX_HIQ_DEVICE_ID:
48 *pCmdAddr = ((WLAN_TX_HIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
51 case WLAN_TX_MIQ_DEVICE_ID:
52 *pCmdAddr = ((WLAN_TX_MIQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
55 case WLAN_TX_LOQ_DEVICE_ID:
56 *pCmdAddr = ((WLAN_TX_LOQ_DEVICE_ID << 13) | (Addr & WLAN_FIFO_MSK));
59 case WLAN_RX0FF_DEVICE_ID:
60 *pCmdAddr = ((WLAN_RX0FF_DEVICE_ID << 13) | (Addr & WLAN_RX0FF_MSK));
68 static u8 get_deviceid(u32 addr)
74 pseudoId = (u16)(addr >> 16);
78 devideId = SDIO_LOCAL_DEVICE_ID;
82 devideId = WLAN_IOREG_DEVICE_ID;
86 /* devideId = SDIO_FIRMWARE_FIFO; */
90 devideId = WLAN_TX_HIQ_DEVICE_ID;
94 devideId = WLAN_TX_MIQ_DEVICE_ID;
98 devideId = WLAN_TX_LOQ_DEVICE_ID;
102 devideId = WLAN_RX0FF_DEVICE_ID;
106 /* devideId = (u8)((addr >> 13) & 0xF); */
107 devideId = WLAN_IOREG_DEVICE_ID;
116 *HalSdioGetCmdAddr8723BSdio()
118 static u32 _cvrt2ftaddr(const u32 addr, u8 *pdeviceId, u16 *poffset)
125 deviceId = get_deviceid(addr);
130 case SDIO_LOCAL_DEVICE_ID:
131 offset = addr & SDIO_LOCAL_MSK;
134 case WLAN_TX_HIQ_DEVICE_ID:
135 case WLAN_TX_MIQ_DEVICE_ID:
136 case WLAN_TX_LOQ_DEVICE_ID:
137 offset = addr & WLAN_FIFO_MSK;
140 case WLAN_RX0FF_DEVICE_ID:
141 offset = addr & WLAN_RX0FF_MSK;
144 case WLAN_IOREG_DEVICE_ID:
146 deviceId = WLAN_IOREG_DEVICE_ID;
147 offset = addr & WLAN_IOREG_MSK;
150 ftaddr = (deviceId << 13) | offset;
152 if (pdeviceId) *pdeviceId = deviceId;
153 if (poffset) *poffset = offset;
158 static u8 sdio_read8(struct intf_hdl *pintfhdl, u32 addr)
163 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
164 val = sd_read8(pintfhdl, ftaddr, NULL);
168 static u16 sdio_read16(struct intf_hdl *pintfhdl, u32 addr)
174 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
175 sd_cmd52_read(pintfhdl, ftaddr, 2, (u8 *)&le_tmp);
176 val = le16_to_cpu(le_tmp);
180 static u32 sdio_read32(struct intf_hdl *pintfhdl, u32 addr)
182 struct adapter *padapter;
192 padapter = pintfhdl->padapter;
193 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
195 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
196 if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
197 || (false == bMacPwrCtrlOn)
198 || (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode))
200 err = sd_cmd52_read(pintfhdl, ftaddr, 4, (u8 *)&le_tmp);
204 val = le32_to_cpu(le_tmp);
209 DBG_8192C(KERN_ERR "%s: Mac Power off, Read FAIL(%d)! addr = 0x%x\n", __func__, err, addr);
210 return SDIO_ERR_VAL32;
214 /* 4 bytes alignment */
215 shift = ftaddr & 0x3;
217 val = sd_read32(pintfhdl, ftaddr, NULL);
221 ptmpbuf = (u8 *)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;
228 sd_read(pintfhdl, ftaddr, 8, ptmpbuf);
229 memcpy(&le_tmp, ptmpbuf+shift, 4);
230 val = le32_to_cpu(le_tmp);
237 static s32 sdio_readN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
239 struct adapter *padapter;
247 padapter = pintfhdl->padapter;
250 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
252 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
253 if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
254 || (false == bMacPwrCtrlOn)
255 || (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode))
257 err = sd_cmd52_read(pintfhdl, ftaddr, cnt, pbuf);
261 /* 4 bytes alignment */
262 shift = ftaddr & 0x3;
264 err = sd_read(pintfhdl, ftaddr, cnt, pbuf);
271 ptmpbuf = rtw_malloc(n);
272 if (NULL == ptmpbuf) return -1;
273 err = sd_read(pintfhdl, ftaddr, n, ptmpbuf);
275 memcpy(pbuf, ptmpbuf+shift, cnt);
281 static s32 sdio_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
286 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
287 sd_write8(pintfhdl, ftaddr, val, &err);
292 static s32 sdio_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
298 ftaddr = _cvrt2ftaddr(addr, NULL, NULL);
299 le_tmp = cpu_to_le16(val);
300 err = sd_cmd52_write(pintfhdl, ftaddr, 2, (u8 *)&le_tmp);
305 static s32 sdio_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
307 struct adapter *padapter;
316 padapter = pintfhdl->padapter;
319 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
321 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
322 if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100)) ||
323 (!bMacPwrCtrlOn) || (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode)) {
324 le_tmp = cpu_to_le32(val);
325 err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&le_tmp);
329 /* 4 bytes alignment */
330 shift = ftaddr & 0x3;
333 sd_write32(pintfhdl, ftaddr, val, &err);
335 le_tmp = cpu_to_le32(val);
336 err = sd_cmd52_write(pintfhdl, ftaddr, 4, (u8 *)&le_tmp);
341 static s32 sdio_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pbuf)
343 struct adapter *padapter;
351 padapter = pintfhdl->padapter;
354 ftaddr = _cvrt2ftaddr(addr, &deviceId, &offset);
356 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
357 if (((deviceId == WLAN_IOREG_DEVICE_ID) && (offset < 0x100))
358 || (false == bMacPwrCtrlOn)
359 || (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode))
361 err = sd_cmd52_write(pintfhdl, ftaddr, cnt, pbuf);
365 shift = ftaddr & 0x3;
367 err = sd_write(pintfhdl, ftaddr, cnt, pbuf);
374 ptmpbuf = rtw_malloc(n);
375 if (NULL == ptmpbuf) return -1;
376 err = sd_read(pintfhdl, ftaddr, 4, ptmpbuf);
381 memcpy(ptmpbuf+shift, pbuf, cnt);
382 err = sd_write(pintfhdl, ftaddr, n, ptmpbuf);
388 static u8 sdio_f0_read8(struct intf_hdl *pintfhdl, u32 addr)
390 return sd_f0_read8(pintfhdl, addr, NULL);
393 static void sdio_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
397 err = sdio_readN(pintfhdl, addr, cnt, rmem);
398 /* TODO: Report error is err not zero */
401 static void sdio_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
403 sdio_writeN(pintfhdl, addr, cnt, wmem);
409 *Round read size to block size,
410 *and make sure data transfer will be done in one command.
413 *pintfhdl a pointer of intf_hdl
416 *rmem address to put data
422 static u32 sdio_read_port(
423 struct intf_hdl *pintfhdl,
428 struct adapter *padapter;
430 struct hal_com_data *phal;
432 #ifdef SDIO_DYNAMIC_ALLOC_MEM
438 padapter = pintfhdl->padapter;
439 psdio = &adapter_to_dvobj(padapter)->intf_data;
440 phal = GET_HAL_DATA(padapter);
442 HalSdioGetCmdAddr8723BSdio(padapter, addr, phal->SdioRxFIFOCnt++, &addr);
445 if (cnt > psdio->block_transfer_len)
446 cnt = _RND(cnt, psdio->block_transfer_len);
447 /* cnt = sdio_align_size(cnt); */
450 #ifdef SDIO_DYNAMIC_ALLOC_MEM
452 mem = rtw_malloc(cnt);
454 DBG_8192C(KERN_WARNING "%s: allocate memory %d bytes fail!\n", __func__, cnt);
459 /* in this case, caller should gurante the buffer is big enough */
460 /* to receive data after alignment */
464 err = _sd_read(pintfhdl, addr, cnt, mem);
466 #ifdef SDIO_DYNAMIC_ALLOC_MEM
467 if ((oldcnt != cnt) && (oldmem)) {
468 memcpy(oldmem, mem, oldcnt);
473 if (err) return _FAIL;
480 *Align write size block size,
481 *and make sure data could be written in one command.
484 *pintfhdl a pointer of intf_hdl
487 *wmem data pointer to write
493 static u32 sdio_write_port(
494 struct intf_hdl *pintfhdl,
499 struct adapter *padapter;
502 struct xmit_buf *xmitbuf = (struct xmit_buf *)mem;
504 padapter = pintfhdl->padapter;
505 psdio = &adapter_to_dvobj(padapter)->intf_data;
507 if (padapter->hw_init_completed == false) {
508 DBG_871X("%s [addr = 0x%x cnt =%d] padapter->hw_init_completed == false\n", __func__, addr, cnt);
513 HalSdioGetCmdAddr8723BSdio(padapter, addr, cnt >> 2, &addr);
515 if (cnt > psdio->block_transfer_len)
516 cnt = _RND(cnt, psdio->block_transfer_len);
517 /* cnt = sdio_align_size(cnt); */
519 err = sd_write(pintfhdl, addr, cnt, xmitbuf->pdata);
521 rtw_sctx_done_err(&xmitbuf->sctx,
522 err ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS);
524 if (err) return _FAIL;
528 void sdio_set_intf_ops(struct adapter *padapter, struct _io_ops *pops)
530 pops->_read8 = &sdio_read8;
531 pops->_read16 = &sdio_read16;
532 pops->_read32 = &sdio_read32;
533 pops->_read_mem = &sdio_read_mem;
534 pops->_read_port = &sdio_read_port;
536 pops->_write8 = &sdio_write8;
537 pops->_write16 = &sdio_write16;
538 pops->_write32 = &sdio_write32;
539 pops->_writeN = &sdio_writeN;
540 pops->_write_mem = &sdio_write_mem;
541 pops->_write_port = &sdio_write_port;
543 pops->_sd_f0_read8 = sdio_f0_read8;
547 * Todo: align address to 4 bytes.
549 static s32 _sdio_local_read(
550 struct adapter *padapter,
555 struct intf_hdl * pintfhdl;
562 pintfhdl =&padapter->iopriv.intf;
564 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
566 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
567 if (false == bMacPwrCtrlOn)
569 err = _sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
574 ptmpbuf = (u8 *)rtw_malloc(n);
578 err = _sd_read(pintfhdl, addr, n, ptmpbuf);
580 memcpy(pbuf, ptmpbuf, cnt);
589 * Todo: align address to 4 bytes.
592 struct adapter *padapter,
597 struct intf_hdl * pintfhdl;
603 pintfhdl =&padapter->iopriv.intf;
605 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
607 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
608 if ((false == bMacPwrCtrlOn)
609 || (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode))
611 err = sd_cmd52_read(pintfhdl, addr, cnt, pbuf);
616 ptmpbuf = (u8 *)rtw_malloc(n);
620 err = sd_read(pintfhdl, addr, n, ptmpbuf);
622 memcpy(pbuf, ptmpbuf, cnt);
631 * Todo: align address to 4 bytes.
633 s32 sdio_local_write(
634 struct adapter *padapter,
639 struct intf_hdl * pintfhdl;
645 DBG_8192C("%s, address must be 4 bytes alignment\n", __func__);
648 DBG_8192C("%s, size must be the multiple of 4\n", __func__);
650 pintfhdl =&padapter->iopriv.intf;
652 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
654 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
655 if ((false == bMacPwrCtrlOn)
656 || (true == adapter_to_pwrctl(padapter)->bFwCurrentInPSMode))
658 err = sd_cmd52_write(pintfhdl, addr, cnt, pbuf);
662 ptmpbuf = (u8 *)rtw_malloc(cnt);
666 memcpy(ptmpbuf, pbuf, cnt);
668 err = sd_write(pintfhdl, addr, cnt, ptmpbuf);
675 u8 SdioLocalCmd52Read1Byte(struct adapter *padapter, u32 addr)
678 struct intf_hdl * pintfhdl =&padapter->iopriv.intf;
680 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
681 sd_cmd52_read(pintfhdl, addr, 1, &val);
686 static u16 SdioLocalCmd52Read2Byte(struct adapter *padapter, u32 addr)
689 struct intf_hdl * pintfhdl =&padapter->iopriv.intf;
691 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
692 sd_cmd52_read(pintfhdl, addr, 2, (u8 *)&val);
694 return le16_to_cpu(val);
697 static u32 SdioLocalCmd53Read4Byte(struct adapter *padapter, u32 addr)
702 struct intf_hdl * pintfhdl =&padapter->iopriv.intf;
705 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
706 rtw_hal_get_hwreg(padapter, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
707 if (!bMacPwrCtrlOn || adapter_to_pwrctl(padapter)->bFwCurrentInPSMode) {
708 sd_cmd52_read(pintfhdl, addr, 4, (u8 *)&le_tmp);
709 val = le32_to_cpu(le_tmp);
711 val = sd_read32(pintfhdl, addr, NULL);
716 void SdioLocalCmd52Write1Byte(struct adapter *padapter, u32 addr, u8 v)
718 struct intf_hdl * pintfhdl =&padapter->iopriv.intf;
720 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
721 sd_cmd52_write(pintfhdl, addr, 1, &v);
724 static void SdioLocalCmd52Write4Byte(struct adapter *padapter, u32 addr, u32 v)
726 struct intf_hdl * pintfhdl =&padapter->iopriv.intf;
729 HalSdioGetCmdAddr8723BSdio(padapter, SDIO_LOCAL_DEVICE_ID, addr, &addr);
730 le_tmp = cpu_to_le32(v);
731 sd_cmd52_write(pintfhdl, addr, 4, (u8 *)&le_tmp);
734 static s32 ReadInterrupt8723BSdio(struct adapter *padapter, u32 *phisr)
743 himr = GET_HAL_DATA(padapter)->sdio_himr;
745 /* decide how many bytes need to be read */
754 while (hisr_len != 0)
757 val8 = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HISR+hisr_len);
758 hisr |= (val8 << (8*hisr_len));
768 /* Initialize SDIO Host Interrupt Mask configuration variables for future use. */
771 /* Using SDIO Local register ONLY for configuration. */
773 /* Created by Roger, 2011.02.11. */
775 void InitInterrupt8723BSdio(struct adapter *padapter)
777 struct hal_com_data *pHalData;
780 pHalData = GET_HAL_DATA(padapter);
781 pHalData->sdio_himr = (u32)( \
782 SDIO_HIMR_RX_REQUEST_MSK |
784 /* SDIO_HIMR_TXERR_MSK | */
785 /* SDIO_HIMR_RXERR_MSK | */
786 /* SDIO_HIMR_TXFOVW_MSK | */
787 /* SDIO_HIMR_RXFOVW_MSK | */
788 /* SDIO_HIMR_TXBCNOK_MSK | */
789 /* SDIO_HIMR_TXBCNERR_MSK | */
790 /* SDIO_HIMR_BCNERLY_INT_MSK | */
791 /* SDIO_HIMR_C2HCMD_MSK | */
792 /* SDIO_HIMR_HSISR_IND_MSK | */
793 /* SDIO_HIMR_GTINT3_IND_MSK | */
794 /* SDIO_HIMR_GTINT4_IND_MSK | */
795 /* SDIO_HIMR_PSTIMEOUT_MSK | */
796 /* SDIO_HIMR_OCPINT_MSK | */
797 /* SDIO_HIMR_ATIMEND_MSK | */
798 /* SDIO_HIMR_ATIMEND_E_MSK | */
799 /* SDIO_HIMR_CTWEND_MSK | */
805 /* Initialize System Host Interrupt Mask configuration variables for future use. */
807 /* Created by Roger, 2011.08.03. */
809 void InitSysInterrupt8723BSdio(struct adapter *padapter)
811 struct hal_com_data *pHalData;
814 pHalData = GET_HAL_DATA(padapter);
816 pHalData->SysIntrMask = ( \
817 /* HSIMR_GPIO12_0_INT_EN | */
818 /* HSIMR_SPS_OCP_INT_EN | */
819 /* HSIMR_RON_INT_EN | */
820 /* HSIMR_PDNINT_EN | */
821 /* HSIMR_GPIO9_INT_EN | */
828 /* Clear corresponding SDIO Host ISR interrupt service. */
831 /* Using SDIO Local register ONLY for configuration. */
833 /* Created by Roger, 2011.02.11. */
835 void ClearInterrupt8723BSdio(struct adapter *padapter)
837 struct hal_com_data *pHalData;
841 if (true == padapter->bSurpriseRemoved)
844 pHalData = GET_HAL_DATA(padapter);
845 clear = rtw_zmalloc(4);
847 /* Clear corresponding HISR Content if needed */
848 *(__le32*)clear = cpu_to_le32(pHalData->sdio_hisr & MASK_SDIO_HISR_CLEAR);
849 if (*(__le32*)clear) {
850 /* Perform write one clear operation */
851 sdio_local_write(padapter, SDIO_REG_HISR, 4, clear);
860 /* Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain. */
863 /* 1. Using SDIO Local register ONLY for configuration. */
864 /* 2. PASSIVE LEVEL */
866 /* Created by Roger, 2011.02.11. */
868 void EnableInterrupt8723BSdio(struct adapter *padapter)
870 struct hal_com_data *pHalData;
874 pHalData = GET_HAL_DATA(padapter);
876 himr = cpu_to_le32(pHalData->sdio_himr);
877 sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
879 RT_TRACE(_module_hci_ops_c_, _drv_notice_,
880 ("%s: enable SDIO HIMR = 0x%08X\n", __func__, pHalData->sdio_himr));
882 /* Update current system IMR settings */
883 tmp = rtw_read32(padapter, REG_HSIMR);
884 rtw_write32(padapter, REG_HSIMR, tmp | pHalData->SysIntrMask);
886 RT_TRACE(_module_hci_ops_c_, _drv_notice_,
887 ("%s: enable HSIMR = 0x%08X\n", __func__, pHalData->SysIntrMask));
890 /* <Roger_Notes> There are some C2H CMDs have been sent before system interrupt is enabled, e.g., C2H, CPWM. */
891 /* So we need to clear all C2H events that FW has notified, otherwise FW won't schedule any commands anymore. */
894 rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
899 /* Disable SDIO Host IMR configuration to mask unnecessary interrupt service. */
902 /* Using SDIO Local register ONLY for configuration. */
904 /* Created by Roger, 2011.02.11. */
906 void DisableInterrupt8723BSdio(struct adapter *padapter)
910 himr = cpu_to_le32(SDIO_HIMR_DISABLED);
911 sdio_local_write(padapter, SDIO_REG_HIMR, 4, (u8 *)&himr);
916 /* Using 0x100 to check the power status of FW. */
919 /* Using SDIO Local register ONLY for configuration. */
921 /* Created by Isaac, 2013.09.10. */
923 u8 CheckIPSStatus(struct adapter *padapter)
925 DBG_871X("%s(): Read 0x100 = 0x%02x 0x86 = 0x%02x\n", __func__,
926 rtw_read8(padapter, 0x100), rtw_read8(padapter, 0x86));
928 if (rtw_read8(padapter, 0x100) == 0xEA)
934 static struct recv_buf* sd_recv_rxfifo(struct adapter *padapter, u32 size)
938 struct recv_priv *precvpriv;
939 struct recv_buf *precvbuf;
942 /* Patch for some SDIO Host 4 bytes issue */
944 readsize = RND4(size);
946 /* 3 1. alloc recvbuf */
947 precvpriv = &padapter->recvpriv;
948 precvbuf = rtw_dequeue_recvbuf(&precvpriv->free_recv_buf_queue);
949 if (precvbuf == NULL) {
950 DBG_871X_LEVEL(_drv_err_, "%s: alloc recvbuf FAIL!\n", __func__);
955 if (precvbuf->pskb == NULL) {
956 SIZE_PTR tmpaddr = 0;
957 SIZE_PTR alignment = 0;
959 precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
963 precvbuf->pskb->dev = padapter->pnetdev;
965 tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
966 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
967 skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
970 if (precvbuf->pskb == NULL) {
971 DBG_871X("%s: alloc_skb fail! read =%d\n", __func__, readsize);
976 /* 3 3. read data from rxfifo */
977 preadbuf = precvbuf->pskb->data;
978 ret = sdio_read_port(&padapter->iopriv.intf, WLAN_RX0FF_DEVICE_ID, readsize, preadbuf);
980 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s: read port FAIL!\n", __func__));
985 /* 3 4. init recvbuf */
986 precvbuf->len = size;
987 precvbuf->phead = precvbuf->pskb->head;
988 precvbuf->pdata = precvbuf->pskb->data;
989 skb_set_tail_pointer(precvbuf->pskb, size);
990 precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
991 precvbuf->pend = skb_end_pointer(precvbuf->pskb);
996 static void sd_rxhandler(struct adapter *padapter, struct recv_buf *precvbuf)
998 struct recv_priv *precvpriv;
999 struct __queue *ppending_queue;
1001 precvpriv = &padapter->recvpriv;
1002 ppending_queue = &precvpriv->recv_buf_pending_queue;
1004 /* 3 1. enqueue recvbuf */
1005 rtw_enqueue_recvbuf(precvbuf, ppending_queue);
1007 /* 3 2. schedule tasklet */
1008 tasklet_schedule(&precvpriv->recv_tasklet);
1011 void sd_int_dpc(struct adapter *padapter)
1013 struct hal_com_data *phal;
1014 struct dvobj_priv *dvobj;
1015 struct intf_hdl * pintfhdl =&padapter->iopriv.intf;
1016 struct pwrctrl_priv *pwrctl;
1019 phal = GET_HAL_DATA(padapter);
1020 dvobj = adapter_to_dvobj(padapter);
1021 pwrctl = dvobj_to_pwrctl(dvobj);
1023 if (phal->sdio_hisr & SDIO_HISR_AVAL)
1027 _sdio_local_read(padapter, SDIO_REG_FREE_TXPG, 4, freepage);
1028 up(&(padapter->xmitpriv.xmit_sema));
1030 if (phal->sdio_hisr & SDIO_HISR_CPWM1)
1032 struct reportpwrstate_parm report;
1035 _cancel_timer(&(pwrctl->pwr_rpwm_timer), &bcancelled);
1037 report.state = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HCPWM1_8723B);
1039 /* cpwm_int_hdl(padapter, &report); */
1040 _set_workitem(&(pwrctl->cpwm_event));
1043 if (phal->sdio_hisr & SDIO_HISR_TXERR)
1048 status = rtw_malloc(4);
1051 addr = REG_TXDMA_STATUS;
1052 HalSdioGetCmdAddr8723BSdio(padapter, WLAN_IOREG_DEVICE_ID, addr, &addr);
1053 _sd_read(pintfhdl, addr, 4, status);
1054 _sd_write(pintfhdl, addr, 4, status);
1055 DBG_8192C("%s: SDIO_HISR_TXERR (0x%08x)\n", __func__, le32_to_cpu(*(u32*)status));
1058 DBG_8192C("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__);
1062 if (phal->sdio_hisr & SDIO_HISR_TXBCNOK)
1064 DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__);
1067 if (phal->sdio_hisr & SDIO_HISR_TXBCNERR)
1069 DBG_8192C("%s: SDIO_HISR_TXBCNERR\n", __func__);
1071 #ifndef CONFIG_C2H_PACKET_EN
1072 if (phal->sdio_hisr & SDIO_HISR_C2HCMD)
1074 struct c2h_evt_hdr_88xx *c2h_evt;
1076 DBG_8192C("%s: C2H Command\n", __func__);
1077 if ((c2h_evt = (struct c2h_evt_hdr_88xx*)rtw_zmalloc(16)) != NULL) {
1078 if (rtw_hal_c2h_evt_read(padapter, (u8 *)c2h_evt) == _SUCCESS) {
1079 if (c2h_id_filter_ccx_8723b((u8 *)c2h_evt)) {
1080 /* Handle CCX report here */
1081 rtw_hal_c2h_handler(padapter, (u8 *)c2h_evt);
1082 kfree((u8 *)c2h_evt);
1084 rtw_c2h_wk_cmd(padapter, (u8 *)c2h_evt);
1088 /* Error handling for malloc fail */
1089 if (rtw_cbuf_push(padapter->evtpriv.c2h_queue, (void*)NULL) != _SUCCESS)
1090 DBG_871X("%s rtw_cbuf_push fail\n", __func__);
1091 _set_workitem(&padapter->evtpriv.c2h_wk);
1096 if (phal->sdio_hisr & SDIO_HISR_RXFOVW)
1098 DBG_8192C("%s: Rx Overflow\n", __func__);
1100 if (phal->sdio_hisr & SDIO_HISR_RXERR)
1102 DBG_8192C("%s: Rx Error\n", __func__);
1105 if (phal->sdio_hisr & SDIO_HISR_RX_REQUEST)
1107 struct recv_buf *precvbuf;
1108 int alloc_fail_time = 0;
1111 /* DBG_8192C("%s: RX Request, size =%d\n", __func__, phal->SdioRxFIFOSize); */
1112 phal->sdio_hisr ^= SDIO_HISR_RX_REQUEST;
1114 phal->SdioRxFIFOSize = SdioLocalCmd52Read2Byte(padapter, SDIO_REG_RX0_REQ_LEN);
1115 if (phal->SdioRxFIFOSize != 0)
1117 precvbuf = sd_recv_rxfifo(padapter, phal->SdioRxFIFOSize);
1119 sd_rxhandler(padapter, precvbuf);
1123 DBG_871X("precvbuf is Null for %d times because alloc memory failed\n", alloc_fail_time);
1124 if (alloc_fail_time >= 10)
1127 phal->SdioRxFIFOSize = 0;
1133 ReadInterrupt8723BSdio(padapter, &hisr);
1134 hisr &= SDIO_HISR_RX_REQUEST;
1139 if (alloc_fail_time == 10)
1140 DBG_871X("exit because alloc memory failed more than 10 times\n");
1145 void sd_int_hdl(struct adapter *padapter)
1147 struct hal_com_data *phal;
1150 if ((padapter->bDriverStopped == true) ||
1151 (padapter->bSurpriseRemoved == true))
1154 phal = GET_HAL_DATA(padapter);
1156 phal->sdio_hisr = 0;
1157 ReadInterrupt8723BSdio(padapter, &phal->sdio_hisr);
1159 if (phal->sdio_hisr & phal->sdio_himr)
1163 phal->sdio_hisr &= phal->sdio_himr;
1166 v32 = phal->sdio_hisr & MASK_SDIO_HISR_CLEAR;
1168 SdioLocalCmd52Write4Byte(padapter, SDIO_REG_HISR, v32);
1171 sd_int_dpc(padapter);
1173 RT_TRACE(_module_hci_ops_c_, _drv_err_,
1174 ("%s: HISR(0x%08x) and HIMR(0x%08x) not match!\n",
1175 __func__, phal->sdio_hisr, phal->sdio_himr));
1181 /* Query SDIO Local register to query current the number of Free TxPacketBuffer page. */
1184 /* 1. Running at PASSIVE_LEVEL */
1185 /* 2. RT_TX_SPINLOCK is NOT acquired. */
1187 /* Created by Roger, 2011.01.28. */
1189 u8 HalQueryTxBufferStatus8723BSdio(struct adapter *padapter)
1191 struct hal_com_data *phal;
1196 phal = GET_HAL_DATA(padapter);
1198 NumOfFreePage = SdioLocalCmd53Read4Byte(padapter, SDIO_REG_FREE_TXPG);
1200 /* spin_lock_bh(&phal->SdioTxFIFOFreePageLock); */
1201 memcpy(phal->SdioTxFIFOFreePage, &NumOfFreePage, 4);
1202 RT_TRACE(_module_hci_ops_c_, _drv_notice_,
1203 ("%s: Free page for HIQ(%#x), MIDQ(%#x), LOWQ(%#x), PUBQ(%#x)\n",
1205 phal->SdioTxFIFOFreePage[HI_QUEUE_IDX],
1206 phal->SdioTxFIFOFreePage[MID_QUEUE_IDX],
1207 phal->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
1208 phal->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]));
1209 /* spin_unlock_bh(&phal->SdioTxFIFOFreePageLock); */
1216 /* Query SDIO Local register to get the current number of TX OQT Free Space. */
1218 u8 HalQueryTxOQTBufferStatus8723BSdio(struct adapter *padapter)
1220 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1221 pHalData->SdioTxOQTFreeSpace = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_OQT_FREE_PG);
1225 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
1226 u8 RecvOnePkt(struct adapter *padapter, u32 size)
1228 struct recv_buf *precvbuf;
1229 struct dvobj_priv *psddev;
1230 PSDIO_DATA psdio_data;
1231 struct sdio_func *func;
1235 DBG_871X("+%s: size: %d+\n", __func__, size);
1237 if (padapter == NULL) {
1238 DBG_871X(KERN_ERR "%s: padapter is NULL!\n", __func__);
1242 psddev = adapter_to_dvobj(padapter);
1243 psdio_data = &psddev->intf_data;
1244 func = psdio_data->func;
1247 sdio_claim_host(func);
1248 precvbuf = sd_recv_rxfifo(padapter, size);
1251 /* printk("Completed Recv One Pkt.\n"); */
1252 sd_rxhandler(padapter, precvbuf);
1257 sdio_release_host(func);
1259 DBG_871X("-%s-\n", __func__);
1262 #endif /* CONFIG_WOWLAN */