2010-12-08 11:12:31 -06:00
/******************************************************************************
*
2012-01-07 20:46:43 -06:00
* Copyright ( c ) 2009 - 2012 Realtek Corporation .
2010-12-08 11:12:31 -06:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE .
*
* Contact Information :
* wlanfae < wlanfae @ realtek . com >
* Realtek Corporation , No . 2 , Innovation Road II , Hsinchu Science Park ,
* Hsinchu 300 , Taiwan .
*
* Larry Finger < Larry . Finger @ lwfinger . net >
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "../wifi.h"
# include "../pci.h"
# include "../base.h"
2014-09-26 16:40:27 -05:00
# include "../core.h"
2011-02-23 10:24:58 -06:00
# include "../rtl8192ce/reg.h"
# include "../rtl8192ce/def.h"
# include "fw_common.h"
2012-01-27 13:59:25 -06:00
# include <linux/export.h>
2012-04-13 13:57:43 -05:00
# include <linux/kmemleak.h>
2010-12-08 11:12:31 -06:00
static void _rtl92c_enable_fw_download ( struct ieee80211_hw * hw , bool enable )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
if ( rtlhal - > hw_type = = HARDWARE_TYPE_RTL8192CU ) {
u32 value32 = rtl_read_dword ( rtlpriv , REG_MCUFWDL ) ;
if ( enable )
value32 | = MCUFWDL_EN ;
else
value32 & = ~ MCUFWDL_EN ;
rtl_write_dword ( rtlpriv , REG_MCUFWDL , value32 ) ;
} else if ( rtlhal - > hw_type = = HARDWARE_TYPE_RTL8192CE ) {
u8 tmp ;
if ( enable ) {
tmp = rtl_read_byte ( rtlpriv , REG_SYS_FUNC_EN + 1 ) ;
rtl_write_byte ( rtlpriv , REG_SYS_FUNC_EN + 1 ,
tmp | 0x04 ) ;
tmp = rtl_read_byte ( rtlpriv , REG_MCUFWDL ) ;
rtl_write_byte ( rtlpriv , REG_MCUFWDL , tmp | 0x01 ) ;
tmp = rtl_read_byte ( rtlpriv , REG_MCUFWDL + 2 ) ;
rtl_write_byte ( rtlpriv , REG_MCUFWDL + 2 , tmp & 0xf7 ) ;
} else {
tmp = rtl_read_byte ( rtlpriv , REG_MCUFWDL ) ;
rtl_write_byte ( rtlpriv , REG_MCUFWDL , tmp & 0xfe ) ;
rtl_write_byte ( rtlpriv , REG_MCUFWDL + 1 , 0x00 ) ;
}
}
}
static void _rtl92c_fw_block_write ( struct ieee80211_hw * hw ,
const u8 * buffer , u32 size )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
2014-09-26 16:40:26 -05:00
u32 blocksize = sizeof ( u32 ) ;
u8 * bufferptr = ( u8 * ) buffer ;
u32 * pu4byteptr = ( u32 * ) buffer ;
u32 i , offset , blockcount , remainsize ;
2010-12-08 11:12:31 -06:00
2014-09-26 16:40:26 -05:00
blockcount = size / blocksize ;
remainsize = size % blocksize ;
for ( i = 0 ; i < blockcount ; i + + ) {
offset = i * blocksize ;
2010-12-08 11:12:31 -06:00
rtl_write_dword ( rtlpriv , ( FW_8192C_START_ADDRESS + offset ) ,
2014-09-26 16:40:26 -05:00
* ( pu4byteptr + i ) ) ;
}
if ( remainsize ) {
offset = blockcount * blocksize ;
bufferptr + = offset ;
for ( i = 0 ; i < remainsize ; i + + ) {
rtl_write_byte ( rtlpriv , ( FW_8192C_START_ADDRESS +
offset + i ) , * ( bufferptr + i ) ) ;
}
2010-12-08 11:12:31 -06:00
}
}
static void _rtl92c_fw_page_write ( struct ieee80211_hw * hw ,
u32 page , const u8 * buffer , u32 size )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
u8 value8 ;
u8 u8page = ( u8 ) ( page & 0x07 ) ;
value8 = ( rtl_read_byte ( rtlpriv , REG_MCUFWDL + 2 ) & 0xF8 ) | u8page ;
rtl_write_byte ( rtlpriv , ( REG_MCUFWDL + 2 ) , value8 ) ;
_rtl92c_fw_block_write ( hw , buffer , size ) ;
}
static void _rtl92c_fill_dummy ( u8 * pfwbuf , u32 * pfwlen )
{
u32 fwlen = * pfwlen ;
u8 remain = ( u8 ) ( fwlen % 4 ) ;
remain = ( remain = = 0 ) ? 0 : ( 4 - remain ) ;
while ( remain > 0 ) {
pfwbuf [ fwlen ] = 0 ;
fwlen + + ;
remain - - ;
}
* pfwlen = fwlen ;
}
static void _rtl92c_write_fw ( struct ieee80211_hw * hw ,
enum version_8192c version , u8 * buffer , u32 size )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
2014-09-26 16:40:26 -05:00
bool is_version_b ;
u8 * bufferptr = ( u8 * ) buffer ;
2010-12-08 11:12:31 -06:00
2014-09-26 16:40:26 -05:00
RT_TRACE ( rtlpriv , COMP_FW , DBG_TRACE , " FW size is %d bytes, \n " , size ) ;
is_version_b = IS_NORMAL_CHIP ( version ) ;
if ( is_version_b ) {
u32 pageNums , remainsize ;
2010-12-08 11:12:31 -06:00
u32 page , offset ;
2014-09-26 16:40:26 -05:00
if ( rtlhal - > hw_type = = HARDWARE_TYPE_RTL8192CE )
_rtl92c_fill_dummy ( bufferptr , & size ) ;
2010-12-08 11:12:31 -06:00
pageNums = size / FW_8192C_PAGE_SIZE ;
2014-09-26 16:40:26 -05:00
remainsize = size % FW_8192C_PAGE_SIZE ;
2010-12-08 11:12:31 -06:00
if ( pageNums > 4 ) {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_EMERG ,
2012-01-04 19:40:41 -08:00
" Page numbers should not greater then 4 \n " ) ;
2010-12-08 11:12:31 -06:00
}
for ( page = 0 ; page < pageNums ; page + + ) {
offset = page * FW_8192C_PAGE_SIZE ;
2014-09-26 16:40:26 -05:00
_rtl92c_fw_page_write ( hw , page , ( bufferptr + offset ) ,
2010-12-08 11:12:31 -06:00
FW_8192C_PAGE_SIZE ) ;
}
2014-09-26 16:40:26 -05:00
if ( remainsize ) {
2010-12-08 11:12:31 -06:00
offset = pageNums * FW_8192C_PAGE_SIZE ;
page = pageNums ;
2014-09-26 16:40:26 -05:00
_rtl92c_fw_page_write ( hw , page , ( bufferptr + offset ) ,
remainsize ) ;
2010-12-08 11:12:31 -06:00
}
} else {
_rtl92c_fw_block_write ( hw , buffer , size ) ;
}
}
static int _rtl92c_fw_free_to_go ( struct ieee80211_hw * hw )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
2014-09-26 16:40:26 -05:00
int err = - EIO ;
2010-12-08 11:12:31 -06:00
u32 counter = 0 ;
u32 value32 ;
do {
value32 = rtl_read_dword ( rtlpriv , REG_MCUFWDL ) ;
} while ( ( counter + + < FW_8192C_POLLING_TIMEOUT_COUNT ) & &
( ! ( value32 & FWDL_ChkSum_rpt ) ) ) ;
if ( counter > = FW_8192C_POLLING_TIMEOUT_COUNT ) {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_EMERG ,
2014-09-26 16:40:26 -05:00
" chksum report faill ! REG_MCUFWDL:0x%08x . \n " ,
value32 ) ;
goto exit ;
2010-12-08 11:12:31 -06:00
}
RT_TRACE ( rtlpriv , COMP_FW , DBG_TRACE ,
2014-09-26 16:40:26 -05:00
" Checksum report OK ! REG_MCUFWDL:0x%08x . \n " , value32 ) ;
2010-12-08 11:12:31 -06:00
value32 = rtl_read_dword ( rtlpriv , REG_MCUFWDL ) ;
value32 | = MCUFWDL_RDY ;
value32 & = ~ WINTINI_RDY ;
rtl_write_dword ( rtlpriv , REG_MCUFWDL , value32 ) ;
counter = 0 ;
do {
value32 = rtl_read_dword ( rtlpriv , REG_MCUFWDL ) ;
if ( value32 & WINTINI_RDY ) {
RT_TRACE ( rtlpriv , COMP_FW , DBG_TRACE ,
2014-09-26 16:40:26 -05:00
" Polling FW ready success!! REG_MCUFWDL:0x%08x . \n " ,
value32 ) ;
err = 0 ;
goto exit ;
2010-12-08 11:12:31 -06:00
}
mdelay ( FW_8192C_POLLING_DELAY ) ;
} while ( counter + + < FW_8192C_POLLING_TIMEOUT_COUNT ) ;
RT_TRACE ( rtlpriv , COMP_ERR , DBG_EMERG ,
2014-09-26 16:40:26 -05:00
" Polling FW ready fail!! REG_MCUFWDL:0x%08x . \n " , value32 ) ;
exit :
return err ;
2010-12-08 11:12:31 -06:00
}
int rtl92c_download_fw ( struct ieee80211_hw * hw )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
struct rtl92c_firmware_header * pfwheader ;
u8 * pfwdata ;
u32 fwsize ;
2014-09-26 16:40:26 -05:00
int err ;
2010-12-08 11:12:31 -06:00
enum version_8192c version = rtlhal - > version ;
2014-09-26 16:40:26 -05:00
if ( ! rtlhal - > pfirmware )
2010-12-08 11:12:31 -06:00
return 1 ;
pfwheader = ( struct rtl92c_firmware_header * ) rtlhal - > pfirmware ;
2014-09-26 16:40:26 -05:00
pfwdata = ( u8 * ) rtlhal - > pfirmware ;
2011-04-25 12:53:40 -05:00
fwsize = rtlhal - > fwsize ;
2010-12-08 11:12:31 -06:00
if ( IS_FW_HEADER_EXIST ( pfwheader ) ) {
RT_TRACE ( rtlpriv , COMP_FW , DBG_DMESG ,
2012-01-04 19:40:41 -08:00
" Firmware Version(%d), Signature(%#x),Size(%d) \n " ,
2014-09-26 16:40:26 -05:00
pfwheader - > version , pfwheader - > signature ,
( int ) sizeof ( struct rtl92c_firmware_header ) ) ;
2010-12-08 11:12:31 -06:00
pfwdata = pfwdata + sizeof ( struct rtl92c_firmware_header ) ;
fwsize = fwsize - sizeof ( struct rtl92c_firmware_header ) ;
}
_rtl92c_enable_fw_download ( hw , true ) ;
_rtl92c_write_fw ( hw , version , pfwdata , fwsize ) ;
_rtl92c_enable_fw_download ( hw , false ) ;
2014-09-26 16:40:26 -05:00
err = _rtl92c_fw_free_to_go ( hw ) ;
if ( err ) {
2010-12-08 11:12:31 -06:00
RT_TRACE ( rtlpriv , COMP_ERR , DBG_EMERG ,
2012-01-04 19:40:41 -08:00
" Firmware is not ready to run! \n " ) ;
2010-12-08 11:12:31 -06:00
} else {
RT_TRACE ( rtlpriv , COMP_FW , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" Firmware is ready to run! \n " ) ;
2010-12-08 11:12:31 -06:00
}
return 0 ;
}
2011-02-23 10:24:58 -06:00
EXPORT_SYMBOL ( rtl92c_download_fw ) ;
2010-12-08 11:12:31 -06:00
static bool _rtl92c_check_fw_read_last_h2c ( struct ieee80211_hw * hw , u8 boxnum )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
u8 val_hmetfr , val_mcutst_1 ;
bool result = false ;
val_hmetfr = rtl_read_byte ( rtlpriv , REG_HMETFR ) ;
val_mcutst_1 = rtl_read_byte ( rtlpriv , ( REG_MCUTST_1 + boxnum ) ) ;
if ( ( ( val_hmetfr > > boxnum ) & BIT ( 0 ) ) = = 0 & & val_mcutst_1 = = 0 )
result = true ;
return result ;
}
static void _rtl92c_fill_h2c_command ( struct ieee80211_hw * hw ,
2014-09-26 16:40:26 -05:00
u8 element_id , u32 cmd_len , u8 * cmdbuffer )
2010-12-08 11:12:31 -06:00
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
u8 boxnum ;
2011-04-13 21:00:02 -05:00
u16 box_reg = 0 , box_extreg = 0 ;
2010-12-08 11:12:31 -06:00
u8 u1b_tmp ;
bool isfw_read = false ;
2014-09-26 16:40:26 -05:00
u8 buf_index = 0 ;
bool bwrite_sucess = false ;
2010-12-08 11:12:31 -06:00
u8 wait_h2c_limmit = 100 ;
u8 wait_writeh2c_limmit = 100 ;
u8 boxcontent [ 4 ] , boxextcontent [ 2 ] ;
u32 h2c_waitcounter = 0 ;
unsigned long flag ;
u8 idx ;
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , COMP_CMD , DBG_LOUD , " come in \n " ) ;
2010-12-08 11:12:31 -06:00
while ( true ) {
spin_lock_irqsave ( & rtlpriv - > locks . h2c_lock , flag ) ;
2011-02-19 16:28:57 -06:00
if ( rtlhal - > h2c_setinprogress ) {
2010-12-08 11:12:31 -06:00
RT_TRACE ( rtlpriv , COMP_CMD , DBG_LOUD ,
2014-09-26 16:40:26 -05:00
" H2C set in progress! Wait to set..element_id(%d). \n " ,
2012-01-04 19:40:41 -08:00
element_id ) ;
2011-02-19 16:28:57 -06:00
while ( rtlhal - > h2c_setinprogress ) {
2010-12-08 11:12:31 -06:00
spin_unlock_irqrestore ( & rtlpriv - > locks . h2c_lock ,
flag ) ;
h2c_waitcounter + + ;
RT_TRACE ( rtlpriv , COMP_CMD , DBG_LOUD ,
2012-01-04 19:40:41 -08:00
" Wait 100 us (%d times)... \n " ,
2014-09-26 16:40:26 -05:00
h2c_waitcounter ) ;
2010-12-08 11:12:31 -06:00
udelay ( 100 ) ;
if ( h2c_waitcounter > 1000 )
return ;
spin_lock_irqsave ( & rtlpriv - > locks . h2c_lock ,
flag ) ;
}
spin_unlock_irqrestore ( & rtlpriv - > locks . h2c_lock , flag ) ;
} else {
2011-02-19 16:28:57 -06:00
rtlhal - > h2c_setinprogress = true ;
2010-12-08 11:12:31 -06:00
spin_unlock_irqrestore ( & rtlpriv - > locks . h2c_lock , flag ) ;
break ;
}
}
2014-09-26 16:40:26 -05:00
while ( ! bwrite_sucess ) {
2010-12-08 11:12:31 -06:00
wait_writeh2c_limmit - - ;
if ( wait_writeh2c_limmit = = 0 ) {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_EMERG ,
2012-01-04 19:40:41 -08:00
" Write H2C fail because no trigger for FW INT! \n " ) ;
2010-12-08 11:12:31 -06:00
break ;
}
boxnum = rtlhal - > last_hmeboxnum ;
switch ( boxnum ) {
case 0 :
box_reg = REG_HMEBOX_0 ;
box_extreg = REG_HMEBOX_EXT_0 ;
break ;
case 1 :
box_reg = REG_HMEBOX_1 ;
box_extreg = REG_HMEBOX_EXT_1 ;
break ;
case 2 :
box_reg = REG_HMEBOX_2 ;
box_extreg = REG_HMEBOX_EXT_2 ;
break ;
case 3 :
box_reg = REG_HMEBOX_3 ;
box_extreg = REG_HMEBOX_EXT_3 ;
break ;
default :
2014-09-26 16:40:26 -05:00
RT_TRACE ( rtlpriv , COMP_ERR , DBG_LOUD ,
" switch case not process \n " ) ;
2010-12-08 11:12:31 -06:00
break ;
}
isfw_read = _rtl92c_check_fw_read_last_h2c ( hw , boxnum ) ;
while ( ! isfw_read ) {
wait_h2c_limmit - - ;
if ( wait_h2c_limmit = = 0 ) {
RT_TRACE ( rtlpriv , COMP_CMD , DBG_LOUD ,
2012-01-04 19:40:41 -08:00
" Waiting too long for FW read clear HMEBox(%d)! \n " ,
boxnum ) ;
2010-12-08 11:12:31 -06:00
break ;
}
udelay ( 10 ) ;
isfw_read = _rtl92c_check_fw_read_last_h2c ( hw , boxnum ) ;
u1b_tmp = rtl_read_byte ( rtlpriv , 0x1BF ) ;
RT_TRACE ( rtlpriv , COMP_CMD , DBG_LOUD ,
2012-01-04 19:40:41 -08:00
" Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x \n " ,
boxnum , u1b_tmp ) ;
2010-12-08 11:12:31 -06:00
}
if ( ! isfw_read ) {
RT_TRACE ( rtlpriv , COMP_CMD , DBG_LOUD ,
2014-09-26 16:40:26 -05:00
" Write H2C register BOX[%d] fail!!!!! Fw do not read. \n " ,
2012-01-04 19:40:41 -08:00
boxnum ) ;
2010-12-08 11:12:31 -06:00
break ;
}
memset ( boxcontent , 0 , sizeof ( boxcontent ) ) ;
memset ( boxextcontent , 0 , sizeof ( boxextcontent ) ) ;
boxcontent [ 0 ] = element_id ;
RT_TRACE ( rtlpriv , COMP_CMD , DBG_LOUD ,
2012-01-04 19:40:41 -08:00
" Write element_id box_reg(%4x) = %2x \n " ,
2014-09-26 16:40:26 -05:00
box_reg , element_id ) ;
2010-12-08 11:12:31 -06:00
switch ( cmd_len ) {
case 1 :
boxcontent [ 0 ] & = ~ ( BIT ( 7 ) ) ;
2014-09-26 16:40:26 -05:00
memcpy ( ( u8 * ) ( boxcontent ) + 1 ,
cmdbuffer + buf_index , 1 ) ;
2010-12-08 11:12:31 -06:00
for ( idx = 0 ; idx < 4 ; idx + + ) {
rtl_write_byte ( rtlpriv , box_reg + idx ,
boxcontent [ idx ] ) ;
}
break ;
case 2 :
boxcontent [ 0 ] & = ~ ( BIT ( 7 ) ) ;
2014-09-26 16:40:26 -05:00
memcpy ( ( u8 * ) ( boxcontent ) + 1 ,
cmdbuffer + buf_index , 2 ) ;
2010-12-08 11:12:31 -06:00
for ( idx = 0 ; idx < 4 ; idx + + ) {
rtl_write_byte ( rtlpriv , box_reg + idx ,
boxcontent [ idx ] ) ;
}
break ;
case 3 :
boxcontent [ 0 ] & = ~ ( BIT ( 7 ) ) ;
2014-09-26 16:40:26 -05:00
memcpy ( ( u8 * ) ( boxcontent ) + 1 ,
cmdbuffer + buf_index , 3 ) ;
2010-12-08 11:12:31 -06:00
for ( idx = 0 ; idx < 4 ; idx + + ) {
rtl_write_byte ( rtlpriv , box_reg + idx ,
boxcontent [ idx ] ) ;
}
break ;
case 4 :
boxcontent [ 0 ] | = ( BIT ( 7 ) ) ;
2014-09-26 16:40:26 -05:00
memcpy ( ( u8 * ) ( boxextcontent ) ,
cmdbuffer + buf_index , 2 ) ;
memcpy ( ( u8 * ) ( boxcontent ) + 1 ,
cmdbuffer + buf_index + 2 , 2 ) ;
2010-12-08 11:12:31 -06:00
for ( idx = 0 ; idx < 2 ; idx + + ) {
rtl_write_byte ( rtlpriv , box_extreg + idx ,
boxextcontent [ idx ] ) ;
}
for ( idx = 0 ; idx < 4 ; idx + + ) {
rtl_write_byte ( rtlpriv , box_reg + idx ,
boxcontent [ idx ] ) ;
}
break ;
case 5 :
boxcontent [ 0 ] | = ( BIT ( 7 ) ) ;
2014-09-26 16:40:26 -05:00
memcpy ( ( u8 * ) ( boxextcontent ) ,
cmdbuffer + buf_index , 2 ) ;
memcpy ( ( u8 * ) ( boxcontent ) + 1 ,
cmdbuffer + buf_index + 2 , 3 ) ;
2010-12-08 11:12:31 -06:00
for ( idx = 0 ; idx < 2 ; idx + + ) {
rtl_write_byte ( rtlpriv , box_extreg + idx ,
boxextcontent [ idx ] ) ;
}
for ( idx = 0 ; idx < 4 ; idx + + ) {
rtl_write_byte ( rtlpriv , box_reg + idx ,
boxcontent [ idx ] ) ;
}
break ;
default :
2014-09-26 16:40:26 -05:00
RT_TRACE ( rtlpriv , COMP_ERR , DBG_LOUD ,
" switch case not process \n " ) ;
2010-12-08 11:12:31 -06:00
break ;
}
2014-09-26 16:40:26 -05:00
bwrite_sucess = true ;
2010-12-08 11:12:31 -06:00
rtlhal - > last_hmeboxnum = boxnum + 1 ;
if ( rtlhal - > last_hmeboxnum = = 4 )
rtlhal - > last_hmeboxnum = 0 ;
RT_TRACE ( rtlpriv , COMP_CMD , DBG_LOUD ,
2012-01-04 19:40:41 -08:00
" pHalData->last_hmeboxnum = %d \n " ,
2014-09-26 16:40:26 -05:00
rtlhal - > last_hmeboxnum ) ;
2010-12-08 11:12:31 -06:00
}
spin_lock_irqsave ( & rtlpriv - > locks . h2c_lock , flag ) ;
2011-02-19 16:28:57 -06:00
rtlhal - > h2c_setinprogress = false ;
2010-12-08 11:12:31 -06:00
spin_unlock_irqrestore ( & rtlpriv - > locks . h2c_lock , flag ) ;
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , COMP_CMD , DBG_LOUD , " go out \n " ) ;
2010-12-08 11:12:31 -06:00
}
void rtl92c_fill_h2c_cmd ( struct ieee80211_hw * hw ,
2014-09-26 16:40:26 -05:00
u8 element_id , u32 cmd_len , u8 * cmdbuffer )
2010-12-08 11:12:31 -06:00
{
2014-09-26 16:40:26 -05:00
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
2010-12-08 11:12:31 -06:00
u32 tmp_cmdbuf [ 2 ] ;
2014-09-26 16:40:26 -05:00
if ( ! rtlhal - > fw_ready ) {
RT_ASSERT ( false ,
" return H2C cmd because of Fw download fail!!! \n " ) ;
return ;
}
2010-12-08 11:12:31 -06:00
memset ( tmp_cmdbuf , 0 , 8 ) ;
2014-09-26 16:40:26 -05:00
memcpy ( tmp_cmdbuf , cmdbuffer , cmd_len ) ;
2010-12-08 11:12:31 -06:00
_rtl92c_fill_h2c_command ( hw , element_id , cmd_len , ( u8 * ) & tmp_cmdbuf ) ;
return ;
}
2011-02-23 10:24:58 -06:00
EXPORT_SYMBOL ( rtl92c_fill_h2c_cmd ) ;
2010-12-08 11:12:31 -06:00
void rtl92c_firmware_selfreset ( struct ieee80211_hw * hw )
{
u8 u1b_tmp ;
u8 delay = 100 ;
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
rtl_write_byte ( rtlpriv , REG_HMETFR + 3 , 0x20 ) ;
u1b_tmp = rtl_read_byte ( rtlpriv , REG_SYS_FUNC_EN + 1 ) ;
while ( u1b_tmp & BIT ( 2 ) ) {
delay - - ;
if ( delay = = 0 ) {
2014-09-26 16:40:26 -05:00
RT_ASSERT ( false , " 8051 reset fail. \n " ) ;
2010-12-08 11:12:31 -06:00
break ;
}
udelay ( 50 ) ;
u1b_tmp = rtl_read_byte ( rtlpriv , REG_SYS_FUNC_EN + 1 ) ;
}
}
2011-02-23 10:24:58 -06:00
EXPORT_SYMBOL ( rtl92c_firmware_selfreset ) ;
2010-12-08 11:12:31 -06:00
void rtl92c_set_fw_pwrmode_cmd ( struct ieee80211_hw * hw , u8 mode )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
2014-09-26 16:40:26 -05:00
u8 u1_h2c_set_pwrmode [ 3 ] = { 0 } ;
2010-12-08 11:12:31 -06:00
struct rtl_ps_ctl * ppsc = rtl_psc ( rtl_priv ( hw ) ) ;
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , COMP_POWER , DBG_LOUD , " FW LPS mode = %d \n " , mode ) ;
2010-12-08 11:12:31 -06:00
SET_H2CCMD_PWRMODE_PARM_MODE ( u1_h2c_set_pwrmode , mode ) ;
2013-03-24 22:06:40 -05:00
SET_H2CCMD_PWRMODE_PARM_SMART_PS ( u1_h2c_set_pwrmode ,
2014-09-26 16:40:26 -05:00
( rtlpriv - > mac80211 . p2p ) ? ppsc - > smart_ps : 1 ) ;
2010-12-08 11:12:31 -06:00
SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME ( u1_h2c_set_pwrmode ,
ppsc - > reg_max_lps_awakeintvl ) ;
RT_PRINT_DATA ( rtlpriv , COMP_CMD , DBG_DMESG ,
2014-09-26 16:40:26 -05:00
" rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode \n " ,
2010-12-08 11:12:31 -06:00
u1_h2c_set_pwrmode , 3 ) ;
rtl92c_fill_h2c_cmd ( hw , H2C_SETPWRMODE , 3 , u1_h2c_set_pwrmode ) ;
}
2011-02-23 10:24:58 -06:00
EXPORT_SYMBOL ( rtl92c_set_fw_pwrmode_cmd ) ;
2010-12-08 11:12:31 -06:00
# define BEACON_PG 0 /*->1*/
# define PSPOLL_PG 2
# define NULL_PG 3
# define PROBERSP_PG 4 /*->5*/
# define TOTAL_RESERVED_PKT_LEN 768
static u8 reserved_page_packet [ TOTAL_RESERVED_PKT_LEN ] = {
/* page 0 beacon */
0x80 , 0x00 , 0x00 , 0x00 , 0xFF , 0xFF , 0xFF , 0xFF ,
0xFF , 0xFF , 0x00 , 0xE0 , 0x4C , 0x76 , 0x00 , 0x42 ,
0x00 , 0x40 , 0x10 , 0x10 , 0x00 , 0x03 , 0x50 , 0x08 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x64 , 0x00 , 0x00 , 0x04 , 0x00 , 0x0C , 0x6C , 0x69 ,
0x6E , 0x6B , 0x73 , 0x79 , 0x73 , 0x5F , 0x77 , 0x6C ,
0x61 , 0x6E , 0x01 , 0x04 , 0x82 , 0x84 , 0x8B , 0x96 ,
0x03 , 0x01 , 0x01 , 0x06 , 0x02 , 0x00 , 0x00 , 0x2A ,
0x01 , 0x00 , 0x32 , 0x08 , 0x24 , 0x30 , 0x48 , 0x6C ,
0x0C , 0x12 , 0x18 , 0x60 , 0x2D , 0x1A , 0x6C , 0x18 ,
0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x3D , 0x00 , 0xDD , 0x06 , 0x00 , 0xE0 , 0x4C , 0x02 ,
0x01 , 0x70 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
/* page 1 beacon */
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x10 , 0x00 , 0x20 , 0x8C , 0x00 , 0x12 , 0x10 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
/* page 2 ps-poll */
0xA4 , 0x10 , 0x01 , 0xC0 , 0x00 , 0x40 , 0x10 , 0x10 ,
0x00 , 0x03 , 0x00 , 0xE0 , 0x4C , 0x76 , 0x00 , 0x42 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x18 , 0x00 , 0x20 , 0x8C , 0x00 , 0x12 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x80 ,
0x80 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
/* page 3 null */
0x48 , 0x01 , 0x00 , 0x00 , 0x00 , 0x40 , 0x10 , 0x10 ,
0x00 , 0x03 , 0x00 , 0xE0 , 0x4C , 0x76 , 0x00 , 0x42 ,
0x00 , 0x40 , 0x10 , 0x10 , 0x00 , 0x03 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x72 , 0x00 , 0x20 , 0x8C , 0x00 , 0x12 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x80 ,
0x80 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
/* page 4 probe_resp */
0x50 , 0x00 , 0x00 , 0x00 , 0x00 , 0x40 , 0x10 , 0x10 ,
0x00 , 0x03 , 0x00 , 0xE0 , 0x4C , 0x76 , 0x00 , 0x42 ,
0x00 , 0x40 , 0x10 , 0x10 , 0x00 , 0x03 , 0x00 , 0x00 ,
0x9E , 0x46 , 0x15 , 0x32 , 0x27 , 0xF2 , 0x2D , 0x00 ,
0x64 , 0x00 , 0x00 , 0x04 , 0x00 , 0x0C , 0x6C , 0x69 ,
0x6E , 0x6B , 0x73 , 0x79 , 0x73 , 0x5F , 0x77 , 0x6C ,
0x61 , 0x6E , 0x01 , 0x04 , 0x82 , 0x84 , 0x8B , 0x96 ,
0x03 , 0x01 , 0x01 , 0x06 , 0x02 , 0x00 , 0x00 , 0x2A ,
0x01 , 0x00 , 0x32 , 0x08 , 0x24 , 0x30 , 0x48 , 0x6C ,
0x0C , 0x12 , 0x18 , 0x60 , 0x2D , 0x1A , 0x6C , 0x18 ,
0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x3D , 0x00 , 0xDD , 0x06 , 0x00 , 0xE0 , 0x4C , 0x02 ,
0x01 , 0x70 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
/* page 5 probe_resp */
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
} ;
2014-10-22 15:47:34 +02:00
void rtl92c_set_fw_rsvdpagepkt ( struct ieee80211_hw * hw ,
bool ( * cmd_send_packet ) ( struct ieee80211_hw * , struct sk_buff * ) )
2010-12-08 11:12:31 -06:00
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_mac * mac = rtl_mac ( rtl_priv ( hw ) ) ;
struct sk_buff * skb = NULL ;
u32 totalpacketlen ;
bool rtstatus ;
2014-09-26 16:40:26 -05:00
u8 u1rsvdpageloc [ 3 ] = { 0 } ;
bool b_dlok = false ;
2010-12-08 11:12:31 -06:00
u8 * beacon ;
2014-09-26 16:40:26 -05:00
u8 * p_pspoll ;
2010-12-08 11:12:31 -06:00
u8 * nullfunc ;
2014-09-26 16:40:26 -05:00
u8 * p_probersp ;
2010-12-08 11:12:31 -06:00
/*---------------------------------------------------------
( 1 ) beacon
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
beacon = & reserved_page_packet [ BEACON_PG * 128 ] ;
SET_80211_HDR_ADDRESS2 ( beacon , mac - > mac_addr ) ;
SET_80211_HDR_ADDRESS3 ( beacon , mac - > bssid ) ;
/*-------------------------------------------------------
( 2 ) ps - poll
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-09-26 16:40:26 -05:00
p_pspoll = & reserved_page_packet [ PSPOLL_PG * 128 ] ;
SET_80211_PS_POLL_AID ( p_pspoll , ( mac - > assoc_id | 0xc000 ) ) ;
SET_80211_PS_POLL_BSSID ( p_pspoll , mac - > bssid ) ;
SET_80211_PS_POLL_TA ( p_pspoll , mac - > mac_addr ) ;
2010-12-08 11:12:31 -06:00
2014-09-26 16:40:26 -05:00
SET_H2CCMD_RSVDPAGE_LOC_PSPOLL ( u1rsvdpageloc , PSPOLL_PG ) ;
2010-12-08 11:12:31 -06:00
/*--------------------------------------------------------
( 3 ) null data
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
nullfunc = & reserved_page_packet [ NULL_PG * 128 ] ;
SET_80211_HDR_ADDRESS1 ( nullfunc , mac - > bssid ) ;
SET_80211_HDR_ADDRESS2 ( nullfunc , mac - > mac_addr ) ;
SET_80211_HDR_ADDRESS3 ( nullfunc , mac - > bssid ) ;
2014-09-26 16:40:26 -05:00
SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA ( u1rsvdpageloc , NULL_PG ) ;
2010-12-08 11:12:31 -06:00
/*---------------------------------------------------------
( 4 ) probe response
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-09-26 16:40:26 -05:00
p_probersp = & reserved_page_packet [ PROBERSP_PG * 128 ] ;
SET_80211_HDR_ADDRESS1 ( p_probersp , mac - > bssid ) ;
SET_80211_HDR_ADDRESS2 ( p_probersp , mac - > mac_addr ) ;
SET_80211_HDR_ADDRESS3 ( p_probersp , mac - > bssid ) ;
2010-12-08 11:12:31 -06:00
2014-09-26 16:40:26 -05:00
SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP ( u1rsvdpageloc , PROBERSP_PG ) ;
2010-12-08 11:12:31 -06:00
totalpacketlen = TOTAL_RESERVED_PKT_LEN ;
RT_PRINT_DATA ( rtlpriv , COMP_CMD , DBG_LOUD ,
2014-09-26 16:40:26 -05:00
" rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL \n " ,
2010-12-08 11:12:31 -06:00
& reserved_page_packet [ 0 ] , totalpacketlen ) ;
RT_PRINT_DATA ( rtlpriv , COMP_CMD , DBG_DMESG ,
2014-09-26 16:40:26 -05:00
" rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL \n " ,
u1rsvdpageloc , 3 ) ;
2010-12-08 11:12:31 -06:00
skb = dev_alloc_skb ( totalpacketlen ) ;
2014-09-26 16:40:26 -05:00
memcpy ( ( u8 * ) skb_put ( skb , totalpacketlen ) ,
2010-12-08 11:12:31 -06:00
& reserved_page_packet , totalpacketlen ) ;
2014-10-22 15:47:34 +02:00
if ( cmd_send_packet )
rtstatus = cmd_send_packet ( hw , skb ) ;
else
rtstatus = rtl_cmd_send_packet ( hw , skb ) ;
2010-12-08 11:12:31 -06:00
if ( rtstatus )
2014-09-26 16:40:26 -05:00
b_dlok = true ;
2010-12-08 11:12:31 -06:00
2014-09-26 16:40:26 -05:00
if ( b_dlok ) {
2010-12-08 11:12:31 -06:00
RT_TRACE ( rtlpriv , COMP_POWER , DBG_LOUD ,
2014-09-26 16:40:26 -05:00
" Set RSVD page location to Fw. \n " ) ;
2010-12-08 11:12:31 -06:00
RT_PRINT_DATA ( rtlpriv , COMP_CMD , DBG_DMESG ,
2014-09-26 16:40:26 -05:00
" H2C_RSVDPAGE: \n " ,
u1rsvdpageloc , 3 ) ;
2010-12-08 11:12:31 -06:00
rtl92c_fill_h2c_cmd ( hw , H2C_RSVDPAGE ,
2014-09-26 16:40:26 -05:00
sizeof ( u1rsvdpageloc ) , u1rsvdpageloc ) ;
2010-12-08 11:12:31 -06:00
} else
RT_TRACE ( rtlpriv , COMP_ERR , DBG_WARNING ,
2014-09-26 16:40:26 -05:00
" Set RSVD page location to Fw FAIL!!!!!!. \n " ) ;
2010-12-08 11:12:31 -06:00
}
2011-02-23 10:24:58 -06:00
EXPORT_SYMBOL ( rtl92c_set_fw_rsvdpagepkt ) ;
2010-12-08 11:12:31 -06:00
void rtl92c_set_fw_joinbss_report_cmd ( struct ieee80211_hw * hw , u8 mstatus )
{
2014-09-26 16:40:26 -05:00
u8 u1_joinbssrpt_parm [ 1 ] = { 0 } ;
2010-12-08 11:12:31 -06:00
SET_H2CCMD_JOINBSSRPT_PARM_OPMODE ( u1_joinbssrpt_parm , mstatus ) ;
rtl92c_fill_h2c_cmd ( hw , H2C_JOINBSSRPT , 1 , u1_joinbssrpt_parm ) ;
}
2011-02-23 10:24:58 -06:00
EXPORT_SYMBOL ( rtl92c_set_fw_joinbss_report_cmd ) ;
2013-03-24 22:06:40 -05:00
static void rtl92c_set_p2p_ctw_period_cmd ( struct ieee80211_hw * hw , u8 ctwindow )
{
2014-09-26 16:40:26 -05:00
u8 u1_ctwindow_period [ 1 ] = { ctwindow } ;
2013-03-24 22:06:40 -05:00
rtl92c_fill_h2c_cmd ( hw , H2C_P2P_PS_CTW_CMD , 1 , u1_ctwindow_period ) ;
}
2014-09-26 16:40:26 -05:00
/* refactored routine */
static void set_noa_data ( struct rtl_priv * rtlpriv ,
struct rtl_p2p_ps_info * p2pinfo ,
struct p2p_ps_offload_t * p2p_ps_offload )
{
int i ;
u32 start_time , tsf_low ;
/* hw only support 2 set of NoA */
for ( i = 0 ; i < p2pinfo - > noa_num ; i + + ) {
/* To control the reg setting for which NOA*/
rtl_write_byte ( rtlpriv , 0x5cf , ( i < < 4 ) ) ;
if ( i = = 0 )
p2p_ps_offload - > noa0_en = 1 ;
else
p2p_ps_offload - > noa1_en = 1 ;
/* config P2P NoA Descriptor Register */
rtl_write_dword ( rtlpriv , 0x5E0 ,
p2pinfo - > noa_duration [ i ] ) ;
rtl_write_dword ( rtlpriv , 0x5E4 ,
p2pinfo - > noa_interval [ i ] ) ;
/*Get Current TSF value */
tsf_low = rtl_read_dword ( rtlpriv , REG_TSFTR ) ;
start_time = p2pinfo - > noa_start_time [ i ] ;
if ( p2pinfo - > noa_count_type [ i ] ! = 1 ) {
while ( start_time < = ( tsf_low + ( 50 * 1024 ) ) ) {
start_time + = p2pinfo - > noa_interval [ i ] ;
if ( p2pinfo - > noa_count_type [ i ] ! = 255 )
p2pinfo - > noa_count_type [ i ] - - ;
}
}
rtl_write_dword ( rtlpriv , 0x5E8 , start_time ) ;
rtl_write_dword ( rtlpriv , 0x5EC ,
p2pinfo - > noa_count_type [ i ] ) ;
}
}
2013-03-24 22:06:40 -05:00
void rtl92c_set_p2p_ps_offload_cmd ( struct ieee80211_hw * hw , u8 p2p_ps_state )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_ps_ctl * rtlps = rtl_psc ( rtl_priv ( hw ) ) ;
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
struct rtl_p2p_ps_info * p2pinfo = & ( rtlps - > p2p_ps_info ) ;
struct p2p_ps_offload_t * p2p_ps_offload = & rtlhal - > p2p_ps_offload ;
u16 ctwindow ;
switch ( p2p_ps_state ) {
case P2P_PS_DISABLE :
2014-09-26 16:40:26 -05:00
RT_TRACE ( rtlpriv , COMP_FW , DBG_LOUD ,
" P2P_PS_DISABLE \n " ) ;
memset ( p2p_ps_offload , 0 , sizeof ( * p2p_ps_offload ) ) ;
break ;
2013-03-24 22:06:40 -05:00
case P2P_PS_ENABLE :
2014-09-26 16:40:26 -05:00
RT_TRACE ( rtlpriv , COMP_FW , DBG_LOUD ,
" P2P_PS_ENABLE \n " ) ;
/* update CTWindow value. */
if ( p2pinfo - > ctwindow > 0 ) {
p2p_ps_offload - > ctwindow_en = 1 ;
ctwindow = p2pinfo - > ctwindow ;
rtl92c_set_p2p_ctw_period_cmd ( hw , ctwindow ) ;
2013-03-24 22:06:40 -05:00
}
2014-09-26 16:40:26 -05:00
/* call refactored routine */
set_noa_data ( rtlpriv , p2pinfo , p2p_ps_offload ) ;
2013-03-24 22:06:40 -05:00
2014-09-26 16:40:26 -05:00
if ( ( p2pinfo - > opp_ps = = 1 ) | | ( p2pinfo - > noa_num > 0 ) ) {
/* rst p2p circuit */
rtl_write_byte ( rtlpriv , REG_DUAL_TSF_RST ,
BIT ( 4 ) ) ;
2013-03-24 22:06:40 -05:00
2014-09-26 16:40:26 -05:00
p2p_ps_offload - > offload_en = 1 ;
2013-03-24 22:06:40 -05:00
2014-09-26 16:40:26 -05:00
if ( P2P_ROLE_GO = = rtlpriv - > mac80211 . p2p ) {
p2p_ps_offload - > role = 1 ;
p2p_ps_offload - > allstasleep = 0 ;
} else {
p2p_ps_offload - > role = 0 ;
}
2013-03-24 22:06:40 -05:00
2014-09-26 16:40:26 -05:00
p2p_ps_offload - > discovery = 0 ;
}
break ;
2013-03-24 22:06:40 -05:00
case P2P_PS_SCAN :
2014-09-26 16:40:26 -05:00
RT_TRACE ( rtlpriv , COMP_FW , DBG_LOUD , " P2P_PS_SCAN \n " ) ;
p2p_ps_offload - > discovery = 1 ;
break ;
2013-03-24 22:06:40 -05:00
case P2P_PS_SCAN_DONE :
2014-09-26 16:40:26 -05:00
RT_TRACE ( rtlpriv , COMP_FW , DBG_LOUD ,
" P2P_PS_SCAN_DONE \n " ) ;
p2p_ps_offload - > discovery = 0 ;
p2pinfo - > p2p_ps_state = P2P_PS_ENABLE ;
break ;
2013-03-24 22:06:40 -05:00
default :
2014-09-26 16:40:26 -05:00
break ;
2013-03-24 22:06:40 -05:00
}
rtl92c_fill_h2c_cmd ( hw , H2C_P2P_PS_OFFLOAD , 1 , ( u8 * ) p2p_ps_offload ) ;
2014-09-26 16:40:26 -05:00
2013-03-24 22:06:40 -05:00
}
EXPORT_SYMBOL_GPL ( rtl92c_set_p2p_ps_offload_cmd ) ;