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
,
38 case SDIO_LOCAL_DEVICE_ID
:
39 *pCmdAddr
= ((SDIO_LOCAL_DEVICE_ID
<< 13) | (Addr
& SDIO_LOCAL_MSK
));
42 case WLAN_IOREG_DEVICE_ID
:
43 *pCmdAddr
= ((WLAN_IOREG_DEVICE_ID
<< 13) | (Addr
& WLAN_IOREG_MSK
));
46 case WLAN_TX_HIQ_DEVICE_ID
:
47 *pCmdAddr
= ((WLAN_TX_HIQ_DEVICE_ID
<< 13) | (Addr
& WLAN_FIFO_MSK
));
50 case WLAN_TX_MIQ_DEVICE_ID
:
51 *pCmdAddr
= ((WLAN_TX_MIQ_DEVICE_ID
<< 13) | (Addr
& WLAN_FIFO_MSK
));
54 case WLAN_TX_LOQ_DEVICE_ID
:
55 *pCmdAddr
= ((WLAN_TX_LOQ_DEVICE_ID
<< 13) | (Addr
& WLAN_FIFO_MSK
));
58 case WLAN_RX0FF_DEVICE_ID
:
59 *pCmdAddr
= ((WLAN_RX0FF_DEVICE_ID
<< 13) | (Addr
& WLAN_RX0FF_MSK
));
67 static u8
get_deviceid(u32 addr
)
73 pseudoId
= (u16
)(addr
>> 16);
76 devideId
= SDIO_LOCAL_DEVICE_ID
;
80 devideId
= WLAN_IOREG_DEVICE_ID
;
84 /* devideId = SDIO_FIRMWARE_FIFO; */
88 devideId
= WLAN_TX_HIQ_DEVICE_ID
;
92 devideId
= WLAN_TX_MIQ_DEVICE_ID
;
96 devideId
= WLAN_TX_LOQ_DEVICE_ID
;
100 devideId
= WLAN_RX0FF_DEVICE_ID
;
104 /* devideId = (u8)((addr >> 13) & 0xF); */
105 devideId
= WLAN_IOREG_DEVICE_ID
;
114 *HalSdioGetCmdAddr8723BSdio()
116 static u32
_cvrt2ftaddr(const u32 addr
, u8
*pdeviceId
, u16
*poffset
)
123 deviceId
= get_deviceid(addr
);
127 case SDIO_LOCAL_DEVICE_ID
:
128 offset
= addr
& SDIO_LOCAL_MSK
;
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
;
137 case WLAN_RX0FF_DEVICE_ID
:
138 offset
= addr
& WLAN_RX0FF_MSK
;
141 case WLAN_IOREG_DEVICE_ID
:
143 deviceId
= WLAN_IOREG_DEVICE_ID
;
144 offset
= addr
& WLAN_IOREG_MSK
;
147 ftaddr
= (deviceId
<< 13) | offset
;
150 *pdeviceId
= deviceId
;
157 static u8
sdio_read8(struct intf_hdl
*pintfhdl
, u32 addr
)
162 ftaddr
= _cvrt2ftaddr(addr
, NULL
, NULL
);
163 val
= sd_read8(pintfhdl
, ftaddr
, NULL
);
167 static u16
sdio_read16(struct intf_hdl
*pintfhdl
, u32 addr
)
173 ftaddr
= _cvrt2ftaddr(addr
, NULL
, NULL
);
174 sd_cmd52_read(pintfhdl
, ftaddr
, 2, (u8
*)&le_tmp
);
175 val
= le16_to_cpu(le_tmp
);
179 static u32
sdio_read32(struct intf_hdl
*pintfhdl
, u32 addr
)
181 struct adapter
*padapter
;
191 padapter
= pintfhdl
->padapter
;
192 ftaddr
= _cvrt2ftaddr(addr
, &deviceId
, &offset
);
194 rtw_hal_get_hwreg(padapter
, HW_VAR_APFM_ON_MAC
, &bMacPwrCtrlOn
);
196 ((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
= 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
);
254 ((deviceId
== WLAN_IOREG_DEVICE_ID
) && (offset
< 0x100)) ||
255 (false == bMacPwrCtrlOn
) ||
256 (true == adapter_to_pwrctl(padapter
)->bFwCurrentInPSMode
)
258 err
= sd_cmd52_read(pintfhdl
, ftaddr
, cnt
, pbuf
);
262 /* 4 bytes alignment */
263 shift
= ftaddr
& 0x3;
265 err
= sd_read(pintfhdl
, ftaddr
, cnt
, pbuf
);
272 ptmpbuf
= rtw_malloc(n
);
276 err
= sd_read(pintfhdl
, ftaddr
, n
, ptmpbuf
);
278 memcpy(pbuf
, ptmpbuf
+shift
, cnt
);
284 static s32
sdio_write8(struct intf_hdl
*pintfhdl
, u32 addr
, u8 val
)
289 ftaddr
= _cvrt2ftaddr(addr
, NULL
, NULL
);
290 sd_write8(pintfhdl
, ftaddr
, val
, &err
);
295 static s32
sdio_write16(struct intf_hdl
*pintfhdl
, u32 addr
, u16 val
)
301 ftaddr
= _cvrt2ftaddr(addr
, NULL
, NULL
);
302 le_tmp
= cpu_to_le16(val
);
303 err
= sd_cmd52_write(pintfhdl
, ftaddr
, 2, (u8
*)&le_tmp
);
308 static s32
sdio_write32(struct intf_hdl
*pintfhdl
, u32 addr
, u32 val
)
310 struct adapter
*padapter
;
319 padapter
= pintfhdl
->padapter
;
322 ftaddr
= _cvrt2ftaddr(addr
, &deviceId
, &offset
);
324 rtw_hal_get_hwreg(padapter
, HW_VAR_APFM_ON_MAC
, &bMacPwrCtrlOn
);
326 ((deviceId
== WLAN_IOREG_DEVICE_ID
) && (offset
< 0x100)) ||
328 (adapter_to_pwrctl(padapter
)->bFwCurrentInPSMode
)
330 le_tmp
= cpu_to_le32(val
);
331 err
= sd_cmd52_write(pintfhdl
, ftaddr
, 4, (u8
*)&le_tmp
);
335 /* 4 bytes alignment */
336 shift
= ftaddr
& 0x3;
338 sd_write32(pintfhdl
, ftaddr
, val
, &err
);
340 le_tmp
= cpu_to_le32(val
);
341 err
= sd_cmd52_write(pintfhdl
, ftaddr
, 4, (u8
*)&le_tmp
);
346 static s32
sdio_writeN(struct intf_hdl
*pintfhdl
, u32 addr
, u32 cnt
, u8
*pbuf
)
348 struct adapter
*padapter
;
356 padapter
= pintfhdl
->padapter
;
359 ftaddr
= _cvrt2ftaddr(addr
, &deviceId
, &offset
);
361 rtw_hal_get_hwreg(padapter
, HW_VAR_APFM_ON_MAC
, &bMacPwrCtrlOn
);
363 ((deviceId
== WLAN_IOREG_DEVICE_ID
) && (offset
< 0x100)) ||
364 (false == bMacPwrCtrlOn
) ||
365 (true == adapter_to_pwrctl(padapter
)->bFwCurrentInPSMode
)
367 err
= sd_cmd52_write(pintfhdl
, ftaddr
, cnt
, pbuf
);
371 shift
= ftaddr
& 0x3;
373 err
= sd_write(pintfhdl
, ftaddr
, cnt
, pbuf
);
380 ptmpbuf
= rtw_malloc(n
);
383 err
= sd_read(pintfhdl
, ftaddr
, 4, ptmpbuf
);
388 memcpy(ptmpbuf
+shift
, pbuf
, cnt
);
389 err
= sd_write(pintfhdl
, ftaddr
, n
, ptmpbuf
);
395 static u8
sdio_f0_read8(struct intf_hdl
*pintfhdl
, u32 addr
)
397 return sd_f0_read8(pintfhdl
, addr
, NULL
);
400 static void sdio_read_mem(
401 struct intf_hdl
*pintfhdl
,
409 err
= sdio_readN(pintfhdl
, addr
, cnt
, rmem
);
410 /* TODO: Report error is err not zero */
413 static void sdio_write_mem(
414 struct intf_hdl
*pintfhdl
,
420 sdio_writeN(pintfhdl
, addr
, cnt
, wmem
);
426 *Round read size to block size,
427 *and make sure data transfer will be done in one command.
430 *pintfhdl a pointer of intf_hdl
433 *rmem address to put data
439 static u32
sdio_read_port(
440 struct intf_hdl
*pintfhdl
,
446 struct adapter
*padapter
;
448 struct hal_com_data
*phal
;
450 #ifdef SDIO_DYNAMIC_ALLOC_MEM
456 padapter
= pintfhdl
->padapter
;
457 psdio
= &adapter_to_dvobj(padapter
)->intf_data
;
458 phal
= GET_HAL_DATA(padapter
);
460 HalSdioGetCmdAddr8723BSdio(padapter
, addr
, phal
->SdioRxFIFOCnt
++, &addr
);
463 if (cnt
> psdio
->block_transfer_len
)
464 cnt
= _RND(cnt
, psdio
->block_transfer_len
);
465 /* cnt = sdio_align_size(cnt); */
468 #ifdef SDIO_DYNAMIC_ALLOC_MEM
470 mem
= rtw_malloc(cnt
);
472 DBG_8192C(KERN_WARNING
"%s: allocate memory %d bytes fail!\n", __func__
, cnt
);
477 /* in this case, caller should gurante the buffer is big enough */
478 /* to receive data after alignment */
482 err
= _sd_read(pintfhdl
, addr
, cnt
, mem
);
484 #ifdef SDIO_DYNAMIC_ALLOC_MEM
485 if ((oldcnt
!= cnt
) && (oldmem
)) {
486 memcpy(oldmem
, mem
, oldcnt
);
499 *Align write size block size,
500 *and make sure data could be written in one command.
503 *pintfhdl a pointer of intf_hdl
506 *wmem data pointer to write
512 static u32
sdio_write_port(
513 struct intf_hdl
*pintfhdl
,
519 struct adapter
*padapter
;
522 struct xmit_buf
*xmitbuf
= (struct xmit_buf
*)mem
;
524 padapter
= pintfhdl
->padapter
;
525 psdio
= &adapter_to_dvobj(padapter
)->intf_data
;
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
);
533 HalSdioGetCmdAddr8723BSdio(padapter
, addr
, cnt
>> 2, &addr
);
535 if (cnt
> psdio
->block_transfer_len
)
536 cnt
= _RND(cnt
, psdio
->block_transfer_len
);
537 /* cnt = sdio_align_size(cnt); */
539 err
= sd_write(pintfhdl
, addr
, cnt
, xmitbuf
->pdata
);
543 err
? RTW_SCTX_DONE_WRITE_PORT_ERR
: RTW_SCTX_DONE_SUCCESS
551 void sdio_set_intf_ops(struct adapter
*padapter
, struct _io_ops
*pops
)
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
;
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
;
566 pops
->_sd_f0_read8
= sdio_f0_read8
;
570 * Todo: align address to 4 bytes.
572 static s32
_sdio_local_read(
573 struct adapter
*padapter
,
579 struct intf_hdl
*pintfhdl
;
586 pintfhdl
= &padapter
->iopriv
.intf
;
588 HalSdioGetCmdAddr8723BSdio(padapter
, SDIO_LOCAL_DEVICE_ID
, addr
, &addr
);
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
);
597 ptmpbuf
= rtw_malloc(n
);
601 err
= _sd_read(pintfhdl
, addr
, n
, ptmpbuf
);
603 memcpy(pbuf
, ptmpbuf
, cnt
);
611 * Todo: align address to 4 bytes.
614 struct adapter
*padapter
,
620 struct intf_hdl
*pintfhdl
;
626 pintfhdl
= &padapter
->iopriv
.intf
;
628 HalSdioGetCmdAddr8723BSdio(padapter
, SDIO_LOCAL_DEVICE_ID
, addr
, &addr
);
630 rtw_hal_get_hwreg(padapter
, HW_VAR_APFM_ON_MAC
, &bMacPwrCtrlOn
);
632 (false == bMacPwrCtrlOn
) ||
633 (true == adapter_to_pwrctl(padapter
)->bFwCurrentInPSMode
)
635 err
= sd_cmd52_read(pintfhdl
, addr
, cnt
, pbuf
);
640 ptmpbuf
= rtw_malloc(n
);
644 err
= sd_read(pintfhdl
, addr
, n
, ptmpbuf
);
646 memcpy(pbuf
, ptmpbuf
, cnt
);
654 * Todo: align address to 4 bytes.
656 s32
sdio_local_write(
657 struct adapter
*padapter
,
663 struct intf_hdl
*pintfhdl
;
669 DBG_8192C("%s, address must be 4 bytes alignment\n", __func__
);
672 DBG_8192C("%s, size must be the multiple of 4\n", __func__
);
674 pintfhdl
= &padapter
->iopriv
.intf
;
676 HalSdioGetCmdAddr8723BSdio(padapter
, SDIO_LOCAL_DEVICE_ID
, addr
, &addr
);
678 rtw_hal_get_hwreg(padapter
, HW_VAR_APFM_ON_MAC
, &bMacPwrCtrlOn
);
680 (false == bMacPwrCtrlOn
) ||
681 (true == adapter_to_pwrctl(padapter
)->bFwCurrentInPSMode
)
683 err
= sd_cmd52_write(pintfhdl
, addr
, cnt
, pbuf
);
687 ptmpbuf
= rtw_malloc(cnt
);
691 memcpy(ptmpbuf
, pbuf
, cnt
);
693 err
= sd_write(pintfhdl
, addr
, cnt
, ptmpbuf
);
700 u8
SdioLocalCmd52Read1Byte(struct adapter
*padapter
, u32 addr
)
703 struct intf_hdl
*pintfhdl
= &padapter
->iopriv
.intf
;
705 HalSdioGetCmdAddr8723BSdio(padapter
, SDIO_LOCAL_DEVICE_ID
, addr
, &addr
);
706 sd_cmd52_read(pintfhdl
, addr
, 1, &val
);
711 static u16
SdioLocalCmd52Read2Byte(struct adapter
*padapter
, u32 addr
)
714 struct intf_hdl
*pintfhdl
= &padapter
->iopriv
.intf
;
716 HalSdioGetCmdAddr8723BSdio(padapter
, SDIO_LOCAL_DEVICE_ID
, addr
, &addr
);
717 sd_cmd52_read(pintfhdl
, addr
, 2, (u8
*)&val
);
719 return le16_to_cpu(val
);
722 static u32
SdioLocalCmd53Read4Byte(struct adapter
*padapter
, u32 addr
)
727 struct intf_hdl
*pintfhdl
= &padapter
->iopriv
.intf
;
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
);
736 val
= sd_read32(pintfhdl
, addr
, NULL
);
741 void SdioLocalCmd52Write1Byte(struct adapter
*padapter
, u32 addr
, u8 v
)
743 struct intf_hdl
*pintfhdl
= &padapter
->iopriv
.intf
;
745 HalSdioGetCmdAddr8723BSdio(padapter
, SDIO_LOCAL_DEVICE_ID
, addr
, &addr
);
746 sd_cmd52_write(pintfhdl
, addr
, 1, &v
);
749 static void SdioLocalCmd52Write4Byte(struct adapter
*padapter
, u32 addr
, u32 v
)
751 struct intf_hdl
*pintfhdl
= &padapter
->iopriv
.intf
;
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
);
759 static s32
ReadInterrupt8723BSdio(struct adapter
*padapter
, u32
*phisr
)
768 himr
= GET_HAL_DATA(padapter
)->sdio_himr
;
770 /* decide how many bytes need to be read */
778 while (hisr_len
!= 0) {
780 val8
= SdioLocalCmd52Read1Byte(padapter
, SDIO_REG_HISR
+hisr_len
);
781 hisr
|= (val8
<< (8*hisr_len
));
791 /* Initialize SDIO Host Interrupt Mask configuration variables for future use. */
794 /* Using SDIO Local register ONLY for configuration. */
796 /* Created by Roger, 2011.02.11. */
798 void InitInterrupt8723BSdio(struct adapter
*padapter
)
800 struct hal_com_data
*pHalData
;
803 pHalData
= GET_HAL_DATA(padapter
);
804 pHalData
->sdio_himr
= (u32
)( \
805 SDIO_HIMR_RX_REQUEST_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 | */
828 /* Initialize System Host Interrupt Mask configuration variables for future use. */
830 /* Created by Roger, 2011.08.03. */
832 void InitSysInterrupt8723BSdio(struct adapter
*padapter
)
834 struct hal_com_data
*pHalData
;
837 pHalData
= GET_HAL_DATA(padapter
);
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 | */
851 /* Clear corresponding SDIO Host ISR interrupt service. */
854 /* Using SDIO Local register ONLY for configuration. */
856 /* Created by Roger, 2011.02.11. */
858 void ClearInterrupt8723BSdio(struct adapter
*padapter
)
860 struct hal_com_data
*pHalData
;
864 if (true == padapter
->bSurpriseRemoved
)
867 pHalData
= GET_HAL_DATA(padapter
);
868 clear
= rtw_zmalloc(4);
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
);
883 /* Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain. */
886 /* 1. Using SDIO Local register ONLY for configuration. */
887 /* 2. PASSIVE LEVEL */
889 /* Created by Roger, 2011.02.11. */
891 void EnableInterrupt8723BSdio(struct adapter
*padapter
)
893 struct hal_com_data
*pHalData
;
897 pHalData
= GET_HAL_DATA(padapter
);
899 himr
= cpu_to_le32(pHalData
->sdio_himr
);
900 sdio_local_write(padapter
, SDIO_REG_HIMR
, 4, (u8
*)&himr
);
906 "%s: enable SDIO HIMR = 0x%08X\n",
912 /* Update current system IMR settings */
913 tmp
= rtw_read32(padapter
, REG_HSIMR
);
914 rtw_write32(padapter
, REG_HSIMR
, tmp
| pHalData
->SysIntrMask
);
920 "%s: enable HSIMR = 0x%08X\n",
922 pHalData
->SysIntrMask
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. */
931 rtw_write8(padapter
, REG_C2HEVT_CLEAR
, C2H_EVT_HOST_CLOSE
);
936 /* Disable SDIO Host IMR configuration to mask unnecessary interrupt service. */
939 /* Using SDIO Local register ONLY for configuration. */
941 /* Created by Roger, 2011.02.11. */
943 void DisableInterrupt8723BSdio(struct adapter
*padapter
)
947 himr
= cpu_to_le32(SDIO_HIMR_DISABLED
);
948 sdio_local_write(padapter
, SDIO_REG_HIMR
, 4, (u8
*)&himr
);
953 /* Using 0x100 to check the power status of FW. */
956 /* Using SDIO Local register ONLY for configuration. */
958 /* Created by Isaac, 2013.09.10. */
960 u8
CheckIPSStatus(struct adapter
*padapter
)
963 "%s(): Read 0x100 = 0x%02x 0x86 = 0x%02x\n",
965 rtw_read8(padapter
, 0x100),
966 rtw_read8(padapter
, 0x86)
969 if (rtw_read8(padapter
, 0x100) == 0xEA)
975 static struct recv_buf
*sd_recv_rxfifo(struct adapter
*padapter
, u32 size
)
979 struct recv_priv
*precvpriv
;
980 struct recv_buf
*precvbuf
;
983 /* Patch for some SDIO Host 4 bytes issue */
985 readsize
= RND4(size
);
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__
);
996 if (precvbuf
->pskb
== NULL
) {
997 SIZE_PTR tmpaddr
= 0;
998 SIZE_PTR alignment
= 0;
1000 precvbuf
->pskb
= rtw_skb_alloc(MAX_RECVBUF_SZ
+ RECVBUFF_ALIGN_SZ
);
1002 if (precvbuf
->pskb
) {
1003 precvbuf
->pskb
->dev
= padapter
->pnetdev
;
1005 tmpaddr
= (SIZE_PTR
)precvbuf
->pskb
->data
;
1006 alignment
= tmpaddr
& (RECVBUFF_ALIGN_SZ
-1);
1007 skb_reserve(precvbuf
->pskb
, (RECVBUFF_ALIGN_SZ
- alignment
));
1010 if (precvbuf
->pskb
== NULL
) {
1011 DBG_871X("%s: alloc_skb fail! read =%d\n", __func__
, readsize
);
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
);
1020 RT_TRACE(_module_hci_ops_os_c_
, _drv_err_
, ("%s: read port FAIL!\n", __func__
));
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
);
1036 static void sd_rxhandler(struct adapter
*padapter
, struct recv_buf
*precvbuf
)
1038 struct recv_priv
*precvpriv
;
1039 struct __queue
*ppending_queue
;
1041 precvpriv
= &padapter
->recvpriv
;
1042 ppending_queue
= &precvpriv
->recv_buf_pending_queue
;
1044 /* 3 1. enqueue recvbuf */
1045 rtw_enqueue_recvbuf(precvbuf
, ppending_queue
);
1047 /* 3 2. schedule tasklet */
1048 tasklet_schedule(&precvpriv
->recv_tasklet
);
1051 void sd_int_dpc(struct adapter
*padapter
)
1053 struct hal_com_data
*phal
;
1054 struct dvobj_priv
*dvobj
;
1055 struct intf_hdl
*pintfhdl
= &padapter
->iopriv
.intf
;
1056 struct pwrctrl_priv
*pwrctl
;
1059 phal
= GET_HAL_DATA(padapter
);
1060 dvobj
= adapter_to_dvobj(padapter
);
1061 pwrctl
= dvobj_to_pwrctl(dvobj
);
1063 if (phal
->sdio_hisr
& SDIO_HISR_AVAL
) {
1066 _sdio_local_read(padapter
, SDIO_REG_FREE_TXPG
, 4, freepage
);
1067 up(&(padapter
->xmitpriv
.xmit_sema
));
1070 if (phal
->sdio_hisr
& SDIO_HISR_CPWM1
) {
1071 struct reportpwrstate_parm report
;
1074 _cancel_timer(&(pwrctl
->pwr_rpwm_timer
), &bcancelled
);
1076 report
.state
= SdioLocalCmd52Read1Byte(padapter
, SDIO_REG_HCPWM1_8723B
);
1078 /* cpwm_int_hdl(padapter, &report); */
1079 _set_workitem(&(pwrctl
->cpwm_event
));
1082 if (phal
->sdio_hisr
& SDIO_HISR_TXERR
) {
1086 status
= rtw_malloc(4);
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
));
1095 DBG_8192C("%s: SDIO_HISR_TXERR, but can't allocate memory to read status!\n", __func__
);
1099 if (phal
->sdio_hisr
& SDIO_HISR_TXBCNOK
) {
1100 DBG_8192C("%s: SDIO_HISR_TXBCNOK\n", __func__
);
1103 if (phal
->sdio_hisr
& SDIO_HISR_TXBCNERR
) {
1104 DBG_8192C("%s: SDIO_HISR_TXBCNERR\n", __func__
);
1106 #ifndef CONFIG_C2H_PACKET_EN
1107 if (phal
->sdio_hisr
& SDIO_HISR_C2HCMD
) {
1108 struct c2h_evt_hdr_88xx
*c2h_evt
;
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
);
1119 rtw_c2h_wk_cmd(padapter
, (u8
*)c2h_evt
);
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
);
1131 if (phal
->sdio_hisr
& SDIO_HISR_RXFOVW
) {
1132 DBG_8192C("%s: Rx Overflow\n", __func__
);
1135 if (phal
->sdio_hisr
& SDIO_HISR_RXERR
) {
1136 DBG_8192C("%s: Rx Error\n", __func__
);
1139 if (phal
->sdio_hisr
& SDIO_HISR_RX_REQUEST
) {
1140 struct recv_buf
*precvbuf
;
1141 int alloc_fail_time
= 0;
1144 /* DBG_8192C("%s: RX Request, size =%d\n", __func__, phal->SdioRxFIFOSize); */
1145 phal
->sdio_hisr
^= SDIO_HISR_RX_REQUEST
;
1147 phal
->SdioRxFIFOSize
= SdioLocalCmd52Read2Byte(padapter
, SDIO_REG_RX0_REQ_LEN
);
1148 if (phal
->SdioRxFIFOSize
!= 0) {
1149 precvbuf
= sd_recv_rxfifo(padapter
, phal
->SdioRxFIFOSize
);
1151 sd_rxhandler(padapter
, precvbuf
);
1154 DBG_871X("precvbuf is Null for %d times because alloc memory failed\n", alloc_fail_time
);
1155 if (alloc_fail_time
>= 10)
1158 phal
->SdioRxFIFOSize
= 0;
1163 ReadInterrupt8723BSdio(padapter
, &hisr
);
1164 hisr
&= SDIO_HISR_RX_REQUEST
;
1169 if (alloc_fail_time
== 10)
1170 DBG_871X("exit because alloc memory failed more than 10 times\n");
1175 void sd_int_hdl(struct adapter
*padapter
)
1177 struct hal_com_data
*phal
;
1181 (padapter
->bDriverStopped
== true) ||
1182 (padapter
->bSurpriseRemoved
== true)
1186 phal
= GET_HAL_DATA(padapter
);
1188 phal
->sdio_hisr
= 0;
1189 ReadInterrupt8723BSdio(padapter
, &phal
->sdio_hisr
);
1191 if (phal
->sdio_hisr
& phal
->sdio_himr
) {
1194 phal
->sdio_hisr
&= phal
->sdio_himr
;
1197 v32
= phal
->sdio_hisr
& MASK_SDIO_HISR_CLEAR
;
1199 SdioLocalCmd52Write4Byte(padapter
, SDIO_REG_HISR
, v32
);
1202 sd_int_dpc(padapter
);
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
));
1212 /* Query SDIO Local register to query current the number of Free TxPacketBuffer page. */
1215 /* 1. Running at PASSIVE_LEVEL */
1216 /* 2. RT_TX_SPINLOCK is NOT acquired. */
1218 /* Created by Roger, 2011.01.28. */
1220 u8
HalQueryTxBufferStatus8723BSdio(struct adapter
*padapter
)
1222 struct hal_com_data
*phal
;
1227 phal
= GET_HAL_DATA(padapter
);
1229 NumOfFreePage
= SdioLocalCmd53Read4Byte(padapter
, SDIO_REG_FREE_TXPG
);
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",
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); */
1247 /* Query SDIO Local register to get the current number of TX OQT Free Space. */
1249 u8
HalQueryTxOQTBufferStatus8723BSdio(struct adapter
*padapter
)
1251 struct hal_com_data
*pHalData
= GET_HAL_DATA(padapter
);
1253 pHalData
->SdioTxOQTFreeSpace
= SdioLocalCmd52Read1Byte(padapter
, SDIO_REG_OQT_FREE_PG
);
1257 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
1258 u8
RecvOnePkt(struct adapter
*padapter
, u32 size
)
1260 struct recv_buf
*precvbuf
;
1261 struct dvobj_priv
*psddev
;
1262 PSDIO_DATA psdio_data
;
1263 struct sdio_func
*func
;
1267 DBG_871X("+%s: size: %d+\n", __func__
, size
);
1269 if (padapter
== NULL
) {
1270 DBG_871X(KERN_ERR
"%s: padapter is NULL!\n", __func__
);
1274 psddev
= adapter_to_dvobj(padapter
);
1275 psdio_data
= &psddev
->intf_data
;
1276 func
= psdio_data
->func
;
1279 sdio_claim_host(func
);
1280 precvbuf
= sd_recv_rxfifo(padapter
, size
);
1283 /* printk("Completed Recv One Pkt.\n"); */
1284 sd_rxhandler(padapter
, precvbuf
);
1289 sdio_release_host(func
);
1291 DBG_871X("-%s-\n", __func__
);
1294 #endif /* CONFIG_WOWLAN */