summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rda
diff options
context:
space:
mode:
authorSrikant Patnaik2015-01-11 12:28:04 +0530
committerSrikant Patnaik2015-01-11 12:28:04 +0530
commit871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch)
tree8718f573808810c2a1e8cb8fb6ac469093ca2784 /drivers/net/wireless/rda
parent9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff)
downloadFOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure.
Diffstat (limited to 'drivers/net/wireless/rda')
-rwxr-xr-xdrivers/net/wireless/rda/Makefile3
-rwxr-xr-xdrivers/net/wireless/rda/rda_combo_power_ctrl/Makefile8
-rwxr-xr-xdrivers/net/wireless/rda/rda_combo_power_ctrl/rda_5990_power_ctrl.c1310
-rwxr-xr-xdrivers/net/wireless/rda/rda_combo_power_ctrl/rda_5991_power_ctrl.c725
-rwxr-xr-xdrivers/net/wireless/rda/rda_combo_power_ctrl/rda_5991e_power_ctrl.c796
-rwxr-xr-xdrivers/net/wireless/rda/rda_combo_power_ctrl/rda_5991f_power_ctrl.c803
-rwxr-xr-xdrivers/net/wireless/rda/rda_combo_power_ctrl/rda_combo.h132
-rwxr-xr-xdrivers/net/wireless/rda/rda_combo_power_ctrl/rda_combo_power_main.c1282
-rwxr-xr-xdrivers/net/wireless/rda/rda_fm/Makefile1
-rwxr-xr-xdrivers/net/wireless/rda/rda_fm/fm.h517
-rwxr-xr-xdrivers/net/wireless/rda/rda_fm/fm_drv.c2257
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/Makefile17
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_assoc.c228
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_aver_rssi.c152
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_aver_rssi.h25
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_debugfs.c225
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_defs.h168
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_dev.h418
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_event.c227
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_event.h33
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_includes.h115
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_init.c736
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_module.c992
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_nvram.c209
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_os.h145
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_rxtx.c289
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_scan.c429
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_sdio.c584
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_sdio.h42
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_sdio_patch.c429
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_sdio_patch.h12
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_90.h1793
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_91.h754
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_91e.h675
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_91f.h583
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_wext.c1870
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_wid.c1771
-rwxr-xr-xdrivers/net/wireless/rda/rda_wlan/wlan_wid.h344
38 files changed, 21099 insertions, 0 deletions
diff --git a/drivers/net/wireless/rda/Makefile b/drivers/net/wireless/rda/Makefile
new file mode 100755
index 00000000..504f73f6
--- /dev/null
+++ b/drivers/net/wireless/rda/Makefile
@@ -0,0 +1,3 @@
+obj-m += rda_combo_power_ctrl/
+obj-m += rda_wlan/
+obj-m += rda_fm/
diff --git a/drivers/net/wireless/rda/rda_combo_power_ctrl/Makefile b/drivers/net/wireless/rda/rda_combo_power_ctrl/Makefile
new file mode 100755
index 00000000..8ab7c892
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_combo_power_ctrl/Makefile
@@ -0,0 +1,8 @@
+subdir-ccflags-y := -Werror
+obj-m := rda_combo_power_ctrl.o
+rda_combo_power_ctrl-objs := \
+ rda_combo_power_main.o \
+ rda_5990_power_ctrl.o \
+ rda_5991_power_ctrl.o \
+ rda_5991e_power_ctrl.o \
+ rda_5991f_power_ctrl.o
diff --git a/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_5990_power_ctrl.c b/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_5990_power_ctrl.c
new file mode 100755
index 00000000..988579f8
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_5990_power_ctrl.c
@@ -0,0 +1,1310 @@
+#include "rda_combo.h"
+
+static u8 wifi_is_on = 0;
+
+static const u16 wifi_off_data[][2] =
+{
+ { 0x3F, 0x0001 }, //page up
+ { 0x31, 0x0B40 }, //power off wifi
+ { 0x3F, 0x0000 }, //page down
+};
+
+static const u16 wifi_en_data_90[][2] =
+{
+ //item:VerD_wf_on_2012_02_08
+ {0x3f, 0x0001},
+#ifdef WLAN_USE_DCDC /*houzhen update Mar 15 2012 */
+ {0x23, 0x8F21},//20111001 higher AVDD voltage to improve EVM to 0x8f21 download current -1db 0x8fA1>>0x8bA1
+#else
+ {0x23, 0x0FA1},
+#endif
+ {0x31, 0x0B40 }, //power off wifi
+// {0x22, 0xD3C7},//for ver.c 20111109, txswitch
+ {0x24, 0x80C8},//freq_osc_in[1:0]00 0x80C8 >> 0x80CB
+ {0x27, 0x4925},//for ver.c20111109, txswitch
+ // {0x28, 0x80A1}, //BT_enable
+ {0x31, 0x8140},//enable wifi
+ {0x32, 0x0113},//set_ rdenout_ldooff_wf=0; rden4in_ldoon_wf=1
+ {0x33, 0x0507},//stable time chenggangdeng
+ // {0x39, 0x0004}, //uart switch to wf
+ {0x3F, 0x0000}, //page down
+};
+
+static const u16 wifi_dc_cal_data[][2]=
+{
+ {0x3f, 0x0000},
+ {0x30, 0x0248},
+ {0x30, 0x0249},
+ //{wait 200ms; } here
+};
+
+static const u16 wifi_dig_reset_data_90[][2]=
+{
+ {0x3F, 0x0001},
+ {0x31, 0x8D40},
+ {0x31, 0x8F40},
+ {0x31, 0x8b40},
+ {0x3F, 0x0000},
+};
+
+static const u16 wifi_rf_init_data_90_verE[][2] =
+{
+ {0x3f, 0x0000},
+ //{;;set_rf_swi},ch
+ {0x05, 0x8000},
+ {0x06, 0x0101},
+ {0x07, 0x0101},
+ {0x08, 0x0101},
+ {0x09, 0x3040},
+ {0x0A, 0x002C},//aain_0
+ {0x0D, 0x0507},
+ {0x0E, 0x2300},
+ {0x0F, 0x5689},//
+ //{;;//set_RF },
+ {0x10, 0x0f78},//20110824
+ {0x11, 0x0602},
+ {0x13, 0x0652},//adc_tuning_bit[011]
+ {0x14, 0x8886},
+ {0x15, 0x0910},
+ {0x16, 0x049f},
+#ifdef WLAN_USE_CRYSTAL
+ {0x17, 0x0990},
+ {0x18, 0x049F},
+#else
+ {0x17, 0x0910},
+ {0x18, 0x249F},
+#endif
+ {0x19, 0x3C01},
+ {0x1C, 0x0934},
+ {0x1D, 0xFF00},//for ver.D20120119for temperature 70 degree
+ //{0x1F, 0x01F8},//for ver.c20111109
+ //{0x1F, 0x0300},//for burst tx 不锁
+ {0x20, 0x06E4},
+ {0x21, 0x0ACF},//for ver.c20111109,dr dac reset,dr txflt reset
+ {0x22, 0x24DC},
+#ifdef WLAN_FOR_CTA
+ {0x23, 0x0BFF},
+#else
+ {0x23, 0x23FF},
+#endif
+ {0x24, 0x00FC},
+ {0x26, 0x004F},//004F >> 005f premote pa
+ {0x27, 0x171D},///mdll*7
+ {0x28, 0x031D},///mdll*7
+#ifdef WLAN_USE_CRYSTAL
+ {0x2A, 0x2860},//et0x2849-8.5p :yd 0x2861-7pf C1,C2=6.8p
+#else
+ {0x2A, 0x7860},
+#endif
+ {0x2B, 0x0804},//bbpll,or ver.c20111116
+ {0x32, 0x8a08},
+ {0x33, 0x1D02},//liuyanan
+ //{;;//agc_gain},
+#if 1
+ {0x36, 0x02f4}, //00F8;//gain_7
+ {0x37, 0x01f4}, //0074;//aain_6
+ {0x38, 0x21d4}, //0014;//gain_5
+ {0x39, 0x25d4}, //0414;//aain_4
+ {0x3A, 0x2584}, //1804;//gain_3
+ {0x3B, 0x2dc4}, //1C04;//aain_2
+ {0x3C, 0x2d04}, //1C02;//gain_1
+ {0x3D, 0x2c02}, //3C01;//gain_0
+#else
+ {0x36, 0x01f8}, //00F8;//gain_7
+ {0x37, 0x01f4}, //0074;//aain_6
+ {0x38, 0x21d4}, //0014;//gain_5
+ {0x39, 0x2073}, //0414;//aain_4
+ {0x3A, 0x2473}, //1804;//gain_3
+ {0x3B, 0x2dc7}, //1C04;//aain_2
+ {0x3C, 0x2d07}, //1C02;//gain_1
+ {0x3D, 0x2c04}, //3C01;//gain_0
+#endif
+ {0x33, 0x1502},//liuyanan
+ //{;;SET_channe},_to_11
+ {0x1B, 0x0001},//set_channel
+ {0x30, 0x024D},
+ {0x29, 0xD468},
+ {0x29, 0x1468},
+ {0x30, 0x0249},
+ {0x3f, 0x0000},
+};
+
+static const u16 wifi_rf_init_data_90_verD[][2] =
+{
+ {0x3f, 0x0000},
+ //{;;set_rf_swi},ch
+ {0x05, 0x8000},
+ {0x06, 0x0101},
+ {0x07, 0x0101},
+ {0x08, 0x0101},
+ {0x09, 0x3040},
+ {0x0A, 0x002C},//aain_0
+ {0x0D, 0x0507},
+ {0x0E, 0x2300},//2012_02_20
+ {0x0F, 0x5689},//
+ //{;;//set_RF },
+ {0x10, 0x0f78},//20110824
+ {0x11, 0x0602},
+ {0x13, 0x0652},//adc_tuning_bit[011]
+ {0x14, 0x8886},
+ {0x15, 0x0910},
+ {0x16, 0x049f},
+#ifdef WLAN_USE_CRYSTAL
+ {0x17, 0x0990},
+ {0x18, 0x049F},
+#else
+ {0x17, 0x0910},
+ {0x18, 0x249F},
+#endif
+ {0x19, 0x3C01},//sdm_vbit[3:0]=1111
+ {0x1C, 0x0934},
+ {0x1D, 0xFF00},//for ver.D20120119for temperature 70 degree 0xCE00 >> 0xFF00
+ {0x1F, 0x0300},//div2_band_48g_dr=1;div2_band_48g_reg[8:0]
+ {0x20, 0x06E4},
+ {0x21, 0x0ACF},//for ver.c20111109,dr dac reset,dr txflt reset
+ {0x22, 0x24DC},
+#ifdef WLAN_FOR_CTA
+ {0x23, 0x0BFF},
+#else
+ {0x23, 0x23FF},
+#endif
+ {0x24, 0x00FC},
+ {0x26, 0x004F},//004F >> 005f premote pa
+ {0x27, 0x171D},///mdll*7
+ {0x28, 0x031D},///mdll*7
+#ifdef WLAN_USE_CRYSTAL
+ {0x2A, 0x2860},//et0x2849-8.5p :yd 0x2861-7pf
+#else
+ {0x2A, 0x7860},
+#endif
+ {0x2B, 0x0804},//bbpll,or ver.c20111116
+ {0x32, 0x8a08},
+ {0x33, 0x1D02},//liuyanan
+ //{;;//agc_gain},
+#if 1
+ {0x36, 0x02f4}, //00F8;//gain_7
+ {0x37, 0x01f4}, //0074;//aain_6
+ {0x38, 0x21d4}, //0014;//gain_5
+ {0x39, 0x25d4}, //0414;//aain_4
+ {0x3A, 0x2584}, //1804;//gain_3
+ {0x3B, 0x2dc4}, //1C04;//aain_2
+ {0x3C, 0x2d04}, //1C02;//gain_1
+ {0x3D, 0x2c02}, //3C01;//gain_0
+#else
+ {0x36, 0x01f8}, //00F8;//gain_7
+ {0x37, 0x01f4}, //0074;//aain_6
+ {0x38, 0x21d4}, //0014;//gain_5
+ {0x39, 0x2073}, //0414;//aain_4
+ {0x3A, 0x2473}, //1804;//gain_3
+ {0x3B, 0x2dc7}, //1C04;//aain_2
+ {0x3C, 0x2d07}, //1C02;//gain_1
+ {0x3D, 0x2c04}, //3C01;//gain_0
+#endif
+ {0x33, 0x1502},//liuyanan
+ //{;;SET_channe},_to_11
+ {0x1B, 0x0001},//set_channel
+ {0x30, 0x024D},
+ {0x29, 0xD468},
+ {0x29, 0x1468},
+ {0x30, 0x0249},
+ {0x3f, 0x0000},
+};
+
+static const u16 wifi_tm_en_data_90[][2] =
+{
+ {0x3F,0x0001},
+#ifdef WLAN_USE_DCDC /*houzhen update Mar 15 2012 */
+ {0x23, 0x8F21},//20111001 higher AVDD voltage to improve EVM to 0x8f21 download current -1db 0x8fA1>>0x8bA1
+#else
+ {0x23, 0x0FA1},
+#endif
+ {0x22,0xD3C7},//for ver.c 20111109, tx
+ {0x24, 0x80C8},//freq_osc_in[1:0]00 0x80C8 >> 0x80CB
+ {0x27,0x4925},//for ver.c20111109, txs
+ {0x28,0x80A1}, //BT_enable
+ {0x29,0x111F},
+ {0x31,0x8140},
+ {0x32,0x0113},//set_ rdenout_ldooff_wf
+ {0x39,0x0004},//uart switch to wf
+ {0x3f,0x0000},
+};
+
+static const u16 wifi_tm_rf_init_data_90[][2] =
+{
+ {0x3f,0x0000},
+ //set_rf_switch
+ {0x06,0x0101},
+ {0x07,0x0101},
+ {0x08,0x0101},
+ {0x09,0x3040},
+ {0x0A,0x002C},//aain_0
+ {0x0D,0x0507},
+ {0x0E,0x2300},//2012_02_20
+ {0x0F,0x5689},//
+ //set_RF
+ {0x10,0x0f78},//20110824
+ {0x11,0x0602},
+ {0x13,0x0652},//adc_tuning_bit[011]
+ {0x14,0x8886},
+ {0x15,0x0910},
+ {0x16,0x049f},
+#ifdef WLAN_USE_CRYSTAL
+ {0x17,0x0990},
+ {0x18,0x049F},
+#else
+ {0x17,0x0910},
+ {0x18,0x249F},
+#endif
+ {0x19,0x3C01},//sdm_vbit[3:0]=1111
+ {0x1C,0x0934},
+ {0x1D,0xFF00},//for ver.D20120119for temperature 70 degree
+ {0x1F,0x0300},//div2_band_48g_dr=1;div2_band_48g_reg[8:0]1000000000
+ {0x20,0x06E4},
+ {0x21,0x0ACF},//for ver.c20111109,dr dac reset,dr txflt reset
+ {0x22,0x24DC},
+#ifdef WLAN_FOR_CTA
+ {0x23, 0x03FF},
+#else
+ {0x23, 0x0BFF},
+#endif
+ {0x24,0x00FC},
+ {0x26,0x004F},
+ {0x27,0x171D},///mdll*7
+ {0x28,0x031D},///mdll*7
+#ifdef WLAN_USE_CRYSTAL
+ {0x2A,0x2860},
+#else
+ {0x2A,0x7860},
+#endif
+ {0x2B,0x0804},//bbpll,or ver.c20111116
+ {0x32,0x8a08},
+ {0x33,0x1D02},//liuyanan
+ //agc_gain
+#if 1
+ {0x36, 0x02f4}, //00F8;//gain_7
+ {0x37, 0x01f4}, //0074;//aain_6
+ {0x38, 0x21d4}, //0014;//gain_5
+ {0x39, 0x25d4}, //0414;//aain_4
+ {0x3A, 0x2584}, //1804;//gain_3
+ {0x3B, 0x2dc4}, //1C04;//aain_2
+ {0x3C, 0x2d04}, //1C02;//gain_1
+ {0x3D, 0x2c02}, //3C01;//gain_0
+#else
+ {0x36, 0x01f8}, //00F8;//gain_7
+ {0x37, 0x01f4}, //0074;//aain_6
+ {0x38, 0x21d4}, //0014;//gain_5
+ {0x39, 0x2073}, //0414;//aain_4
+ {0x3A, 0x2473}, //1804;//gain_3
+ {0x3B, 0x2dc7}, //1C04;//aain_2
+ {0x3C, 0x2d07}, //1C02;//gain_1
+ {0x3D, 0x2c04}, //3C01;//gain_0
+#endif
+ {0x30,0x0248},
+ {0x30,0x0249},
+ //wait 200ms;
+ {0x33,0x1502},//liuyanan
+ //SET_channel_to_11
+ {0x1B,0x0001},//set_channel
+ {0x3f,0x0000},
+};
+
+
+/*houzhen update Mar 15 2012
+ should be called when power up/down bt
+ */
+static int rda5990_wf_setup_A2_power(int enable)
+{
+ int ret;
+ u16 temp_data=0;
+ printk(KERN_INFO "***rda5990_wf_setup_A2_power start! \n");
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001);
+ if(ret)
+ goto err;
+
+ if(enable){
+ ret=i2c_read_1_addr_2_data(rda_wifi_rf_client,0x22,&temp_data);
+ if(ret)
+ goto err;
+ printk(KERN_INFO "***0xA2 readback value:0x%X \n", temp_data);
+
+ temp_data |=0x0200; /*en reg4_pa bit*/
+#ifdef WLAN_USE_CRYSTAL
+ temp_data &= ~(1 << 14); //disable xen_out
+#endif
+ ret=i2c_write_1_addr_2_data(rda_wifi_rf_client,0x22,temp_data);
+ if(ret)
+ goto err;
+ }
+ else{
+ ret=i2c_read_1_addr_2_data(rda_wifi_rf_client,0x28,&temp_data);
+ if(ret)
+ goto err;
+ if(temp_data&0x8000){ // bt is on
+ goto out;
+ }
+ else{
+ ret=i2c_read_1_addr_2_data(rda_wifi_rf_client,0x22,&temp_data);
+ if(ret)
+ goto err;
+ temp_data&=0xfdff;
+
+ ret=i2c_write_1_addr_2_data(rda_wifi_rf_client,0x22,temp_data);
+ if(ret)
+ goto err;
+ }
+ }
+
+out:
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000);
+ if(ret)
+ goto err;
+ printk(KERN_INFO "***rda5990_wf_setup_A2_power succeed! \n");
+ return 0;
+
+err:
+ printk(KERN_INFO "***rda5990_wf_setup_A2_power failed! \n");
+ return -1;
+}
+
+
+int rda_5990_wifi_rf_init(void)
+{
+ int ret = 0;
+
+ rda_combo_i2c_lock();
+
+ if( rda_wlan_version() == WLAN_VERSION_90_D){
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_rf_init_data_90_verD);
+ if(ret)
+ goto err;
+ }
+ else if(rda_wlan_version() == WLAN_VERSION_90_E){
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_rf_init_data_90_verE);
+ if(ret)
+ goto err;
+ }
+ else{
+ printk("unknown version of this chip\n");
+ goto err;
+ }
+
+ rda_combo_i2c_unlock();
+
+ printk(KERN_INFO "***rda_5990_wifi_rf_init_succceed \n");
+ msleep(5); //5ms delay
+ return 0;
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***rda_5990_wifi_rf_init failed! \n");
+ return -1;
+}
+
+int rda_5990_wifi_dc_cal(void)
+{
+ int ret = 0;
+
+ rda_combo_i2c_lock();
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client ,wifi_dc_cal_data);
+ if(ret)
+ goto err;
+
+ rda_combo_i2c_unlock();
+
+ printk(KERN_INFO "***rda_wifi_rf_dc_calsuccceed \n");
+ msleep(50); //50ms delay
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+
+ printk(KERN_INFO "***rda_wifi_rf_dc_calf_failed! \n");
+ return -1;
+}
+
+int rda_5990_wifi_en(void)
+{
+ int ret = 0;
+ enable_26m_regulator(CLOCK_WLAN);
+ enable_32k_rtc(CLOCK_WLAN);
+ enable_26m_rtc(CLOCK_WLAN);
+
+ msleep(8);
+
+ rda_combo_i2c_lock();
+
+ if(rda_wlan_version() == WLAN_VERSION_90_D || rda_wlan_version() == WLAN_VERSION_90_E){
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_en_data_90);
+ if(ret)
+ goto err;
+ }
+
+ ret=rda5990_wf_setup_A2_power(1); //en pa_reg for wf
+ if(ret)
+ goto err;
+
+ rda_combo_i2c_unlock();
+
+ msleep(8); //8ms delay
+
+ printk(KERN_INFO "***rda_5990_wifi_en_succceed \n");
+ //in rda platform should close 26M after wifi power on success
+ disable_26m_rtc(CLOCK_WLAN);
+ return 0;
+err:
+ rda_combo_i2c_unlock();
+ disable_32k_rtc(CLOCK_WLAN);
+ disable_26m_rtc(CLOCK_WLAN);
+ disable_26m_regulator(CLOCK_WLAN);
+ printk(KERN_INFO "***rda_5990_wifi_en failed! \n");
+ return -1;
+}
+
+static int rda_5990_wifi_debug_en(int enable)
+{
+ int ret = 0;
+ u16 temp_data = 0;
+
+ rda_combo_i2c_lock();
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001);
+ if (ret < 0)
+ goto err;
+ if (enable == 1){
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x28, 0x80A1);
+ if (ret < 0)
+ goto err;
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x39, &temp_data);
+ if (ret < 0)
+ goto err;
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x39, temp_data | (1 << 2));
+ if (ret < 0)
+ goto err;
+ }else{
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x28, 0x00A1);
+ if (ret < 0)
+ goto err;
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x39, &temp_data);
+ if (ret < 0)
+ goto err;
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x39, temp_data & (~(1 << 2)));
+ if (ret < 0)
+ goto err;
+ }
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000);
+ if (ret < 0)
+ goto err;
+err:
+ rda_combo_i2c_unlock();
+ return ret;
+}
+
+int rda_5990_tm_wifi_en(void)
+{
+ int ret = 0;
+ enable_26m_regulator(CLOCK_WLAN);
+ enable_32k_rtc(CLOCK_WLAN);
+ enable_26m_rtc(CLOCK_WLAN);
+ msleep(5);
+
+ if(rda_wlan_version() == WLAN_VERSION_90_D || rda_wlan_version() == WLAN_VERSION_90_E){
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_tm_en_data_90);
+ if(ret)
+ goto err;
+ }
+
+ msleep(8); //8ms delay
+ printk(KERN_INFO "***rda_5990_tm_wifi_en succceed \n");
+ disable_26m_rtc(CLOCK_WLAN);
+ return 0;
+err:
+ disable_32k_rtc(CLOCK_WLAN);
+ disable_26m_rtc(CLOCK_WLAN);
+ printk(KERN_INFO "***rda_5990_tm_wifi_en failed! \n");
+ return -1;
+}
+
+int rda_5990_tm_wifi_rf_init(void)
+{
+ int ret = 0;
+
+ if(rda_wlan_version() == WLAN_VERSION_90_D || rda_wlan_version() == WLAN_VERSION_90_E){
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_tm_rf_init_data_90);
+ if(ret)
+ goto err;
+ }else
+ return -1;
+
+ printk(KERN_INFO "***rda_5990_tm_wifi_rf_init \n");
+ msleep(5); //5ms delay
+ return 0;
+
+err:
+ printk(KERN_INFO "***rda_5990_tm_wifi_rf_init failed! \n");
+ return -1;
+}
+/*houzhen add 2012 04 09
+ add to ensure wf dig powerup
+ */
+
+int rda_5990_wifi_dig_reset(void)
+{
+ int ret = 0;
+
+ msleep(8); //8ms delay
+
+ rda_combo_i2c_lock();
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_dig_reset_data_90);
+ if(ret)
+ goto err;
+
+ rda_combo_i2c_unlock();
+
+ msleep(8); //8ms delay
+
+ printk(KERN_INFO "***rda_5990_wifi_dig_reset \n");
+ return 0;
+err:
+ rda_combo_i2c_unlock();
+
+ printk(KERN_INFO "***rda_5990_wifi_dig_reset failed! \n");
+ return -1;
+}
+
+int rda_5990_wifi_power_off(void)
+{
+ int ret = 0;
+ u16 temp=0x0000;
+ printk(KERN_INFO "rda_5990_wifi_power_off \n");
+
+ if(!rda_wifi_rf_client){
+ printk(KERN_INFO "rda_5990_wifi_power_off failed on:i2c client \n");
+ return -1;
+ }
+
+ rda_combo_i2c_lock();
+
+ ret=rda5990_wf_setup_A2_power(0); //disable pa_reg for wf
+ if(ret)
+ goto err;
+
+ if(rda_wlan_version() == WLAN_VERSION_90_D || rda_wlan_version() == WLAN_VERSION_90_E){
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001); //page up
+ if(ret)
+ goto err;
+
+ ret=i2c_read_1_addr_2_data(rda_wifi_rf_client,0x28,&temp); //poll bt status
+ if(ret)
+ goto err;
+
+ if(temp&0x8000){
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000); //page down
+ if(ret)
+ goto err;
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x0f, 0x2223); // set antenna for bt
+ if(ret)
+ goto err;
+
+ }
+ }
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_off_data);
+ if(ret)
+ goto err;
+
+ rda_combo_i2c_unlock();
+
+ wifi_is_on = 0;
+ disable_32k_rtc(CLOCK_WLAN);
+ disable_26m_rtc(CLOCK_WLAN);
+ disable_26m_regulator(CLOCK_WLAN);
+ printk(KERN_INFO "***rda_5990_wifi_power_off success!!! \n");
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***rda_5990_wifi_power_off failed! \n");
+ return -1;
+
+}
+
+int rda_5990_wifi_power_on(void)
+{
+ int ret;
+ char retry = 3;
+
+ if(!rda_wifi_rf_client){
+ printk(KERN_INFO "rda_5990_wifi_power_on failed on:i2c client \n");
+ return -1;
+ }
+
+_retry:
+ if(!rda_combo_wifi_in_test_mode()){
+ ret = rda_5990_wifi_en();
+ if(ret < 0)
+ goto err;
+
+ ret = rda_5990_wifi_rf_init();
+ if(ret < 0)
+ goto err;
+
+ ret = rda_5990_wifi_dc_cal();
+ if(ret < 0)
+ goto err;
+
+ msleep(20); //20ms delay
+ ret=rda_5990_wifi_dig_reset(); //houzhen add to ensure wf power up safely
+
+ if(ret < 0)
+ goto err;
+ msleep(20); //20ms delay
+ }
+ else{
+ ret = rda_5990_tm_wifi_en();
+ if(ret < 0)
+ goto err;
+
+ ret = rda_5990_tm_wifi_rf_init();
+ if(ret < 0)
+ goto err;
+ }
+ printk(KERN_INFO "rda_5990_wifi_power_on_succeed!! \n");
+ wifi_is_on = 1;
+ return 0;
+
+err:
+ printk(KERN_INFO "rda_5990_wifi_power_on_failed retry:%d \n", retry);
+ if(retry -- > 0) {
+ rda_5990_wifi_power_off();
+ goto _retry;
+ }
+ wifi_is_on = 0;
+ return -1;
+}
+
+int rda_5990_fm_power_on(void)
+{
+ int ret = 0;
+ u16 temp = 0;
+
+ if(!rda_wifi_rf_client){
+ printk(KERN_INFO "rda_wifi_rf_client is NULL, rda_fm_power_on failed!\n");
+ return -1;
+ }
+
+ enable_32k_rtc(CLOCK_FM);
+ msleep(8);
+ rda_combo_i2c_lock();
+
+ if(rda_wlan_version() == WLAN_VERSION_90_D || rda_wlan_version() == WLAN_VERSION_90_E){
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001); // page down
+ if(ret < 0){
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n", __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x22, &temp); //read 0xA2
+ if(ret < 0){
+ printk(KERN_INFO "%s() read from address(0x%02x) failed! \n", __func__, 0x22);
+ goto err;
+ }
+ temp = temp & (~(1 << 15)); //clear bit[15]
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x22, temp); //write back
+ if(ret < 0){
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n", __func__, 0x3f, 0x0001);
+ goto err;
+ }
+ }
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000); // page up
+ if(ret < 0){
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n", __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ rda_combo_i2c_unlock();
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+ disable_32k_rtc(CLOCK_FM);
+ printk(KERN_INFO "***rda_fm_power_on failed! \n");
+ return -1;
+}
+
+int rda_5990_fm_power_off(void)
+{
+ int ret = 0;
+ u16 temp = 0;
+
+ if(!rda_wifi_rf_client){
+ printk(KERN_INFO "rda_wifi_rf_client is NULL, rda_fm_power_off failed!\n");
+ return -1;
+ }
+
+ rda_combo_i2c_lock();
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001); // page down
+ if(ret < 0){
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n", __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ if(rda_wlan_version() == WLAN_VERSION_90_D || rda_wlan_version() == WLAN_VERSION_90_E){
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x22, &temp); //read 0xA2
+ if(ret < 0){
+ printk(KERN_INFO "%s() read from address(0x%02x) failed! \n", __func__, 0x22);
+ goto err;
+ }
+ temp = temp | (1 << 15); //set bit[15]
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x22, temp); //write back
+ if(ret < 0){
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n", __func__, 0x3f, 0x0001);
+ goto err;
+ }
+ }
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000); // page up
+ if(ret < 0){
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n", __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ rda_combo_i2c_unlock();
+ disable_32k_rtc(CLOCK_FM);
+ return 0;
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***rda_fm_power_off failed! \n");
+ return -1;
+}
+
+
+static const u16 rda_5990_bt_off_data[][2] =
+{
+ {0x3f, 0x0001 }, //pageup
+ {0x28, 0x00A1 }, //power off bt
+ {0x3f, 0x0000 }, //pagedown
+};
+
+/*houzhen update 2012 03 06*/
+static const u16 rda_5990_bt_en_data[][2] =
+{
+ {0x3f, 0x0001 }, //pageup
+#ifdef WLAN_USE_DCDC
+ {0x23, 0x8FA1}, // //20111001 higher AVDD voltage to improve EVM
+#else
+ {0x23, 0x0FA1},
+#endif
+ {0x24, 0x80C8}, // ;//freq_osc_in[1:0]00
+ {0x26, 0x47A5}, // reg_vbit_normal_bt[2:0] =111
+ {0x27, 0x4925}, // //for ver.c20111109, txswitch
+ {0x29, 0x111F}, // // rden4in_ldoon_bt=1
+ {0x32, 0x0111}, // set_ rdenout_ldooff_wf=0;
+ {0x39, 0x0000}, // //uart switch to bt
+
+ {0x28, 0x80A1}, // bt en
+ {0x3f, 0x0000}, //pagedown
+};
+
+static const u16 rda_5990_bt_dc_cal[][2] =
+{
+ {0x3f, 0x0000 },
+ {0x30, 0x0129 },
+ {0x30, 0x012B },
+ {0x3f, 0x0000 },
+};
+
+static const u16 rda_5990_bt_set_rf_switch_data[][2] =
+{
+ {0x3f, 0x0000 },
+ {0x0F, 0x2223 },
+ {0x3f, 0x0000 },
+};
+
+static const u16 RDA5990_bt_enable_clk_data[][2] =
+{
+ {0x3f, 0x0000 },
+ {0x30, 0x0040 },
+ {0x2a, 0x285d },
+ {0x3f, 0x0000 },
+};
+
+static const u16 RDA5990_bt_dig_reset_data[][2] =
+{
+ {0x3f, 0x0001 }, //pageup
+ {0x28, 0x86A1 },
+ {0x28, 0x87A1 },
+ {0x28, 0x85A1 },
+ {0x3f, 0x0000 }, //pagedown
+};
+
+/*houzhen update 2012 03 06*/
+static const u16 rda_5990_bt_rf_data[][2] =
+{
+ {0x3f, 0x0000}, //pagedown
+ {0x01, 0x1FFF},
+ {0x06, 0x07F7},
+ {0x08, 0x29E7},
+ {0x09, 0x0520},
+ {0x0B, 0x03DF},
+ {0x0C, 0x85E8},
+ {0x0F, 0x0DBC},
+ {0x12, 0x07F7},
+ {0x13, 0x0327},
+ {0x14, 0x0CCC},
+ {0x15, 0x0526},
+ {0x16, 0x8918},
+ {0x18, 0x8800},
+ {0x19, 0x10C8},
+ {0x1A, 0x9078},
+ {0x1B, 0x80E2},
+ {0x1C, 0x361F},
+ {0x1D, 0x4363},
+ {0x1E, 0x303F},
+ {0x23, 0x2222},
+ {0x24, 0x359D},
+ {0x27, 0x0011},
+ {0x28, 0x124F},
+ {0x39, 0xA5FC},
+ {0x3f, 0x0001}, //page 1
+ {0x00, 0x043F},
+ {0x01, 0x467F},
+ {0x02, 0x28FF},
+ {0x03, 0x67FF},
+ {0x04, 0x57FF},
+ {0x05, 0x7BFF},
+ {0x06, 0x3FFF},
+ {0x07, 0x7FFF},
+ {0x18, 0xF3F5},
+ {0x19, 0xF3F5},
+ {0x1A, 0xE7F3},
+ {0x1B, 0xF1FF},
+ {0x1C, 0xFFFF},
+ {0x1D, 0xFFFF},
+ {0x1E, 0xFFFF},
+ {0x1F, 0xFFFF},
+ // {0x22, 0xD3C7},
+ // {0x23, 0x8fa1},
+ // {0x24, 0x80c8},
+ // {0x26, 0x47A5},
+ // {0x27, 0x4925},
+ // {0x28, 0x85a1},
+ // {0x29, 0x111f},
+ // {0x32, 0x0111},
+ // {0x39, 0x0000},
+ {0x3f, 0x0000}, //pagedown
+};
+
+/*houzhen update Mar 15 2012
+ should be called when power up/down bt
+ */
+static int rda5990_bt_setup_A2_power(int enable)
+{
+ int ret;
+ u16 temp_data=0;
+
+ ret = i2c_write_1_addr_2_data(rda_bt_rf_client, 0x3f, 0x0001);
+ if(ret)
+ goto err;
+
+ if(enable){
+ ret=i2c_read_1_addr_2_data(rda_bt_rf_client,0x22,&temp_data);
+ if(ret)
+ goto err;
+ printk(KERN_INFO "***0xA2 readback value:0x%X \n", temp_data);
+
+ temp_data |=0x0200; /*en reg4_pa bit*/
+
+ ret=i2c_write_1_addr_2_data(rda_bt_rf_client,0x22,temp_data);
+ if(ret)
+ goto err;
+ }
+ else
+ {
+ ret=i2c_read_1_addr_2_data(rda_bt_rf_client,0x31,&temp_data);
+ if(ret)
+ goto err;
+
+ if(temp_data&0x8000){ // wf is on
+ goto out;
+ }
+ else{
+ ret=i2c_read_1_addr_2_data(rda_bt_rf_client,0x22,&temp_data);
+ if(ret)
+ goto err;
+ temp_data&=0xfdff;
+
+ ret=i2c_write_1_addr_2_data(rda_bt_rf_client,0x22,temp_data);
+ if(ret)
+ goto err;
+ }
+
+ }
+
+out:
+ ret = i2c_write_1_addr_2_data(rda_bt_rf_client, 0x3f, 0x0000);
+ if(ret)
+ goto err;
+ return 0;
+
+err:
+ printk(KERN_INFO "***rda5990_bt_setup_A2_power failed! \n");
+ return -1;
+}
+
+int rda_5990_bt_power_on(void)
+{
+ int ret = 0;
+
+ printk(KERN_INFO "rda_bt_power_on \n");
+
+ if(!rda_bt_rf_client || !rda_bt_rf_client){
+ printk(KERN_INFO "rda_bt_power_on failed on:i2c client \n");
+ return -1;
+ }
+ enable_26m_regulator(CLOCK_BT);
+ enable_26m_rtc(CLOCK_BT);
+ enable_32k_rtc(CLOCK_BT);
+ msleep(8);
+
+ rda_combo_i2c_lock();
+
+ if(rda_wlan_version() == WLAN_VERSION_90_D || rda_wlan_version() == WLAN_VERSION_90_E){
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5990_bt_en_data);
+ if(ret)
+ goto err;
+ }
+
+ ret=rda5990_bt_setup_A2_power(1);
+ if(ret){
+ printk(KERN_INFO "***rda5990_bt_setup_A2_power fail!!! \n");
+ goto err;
+ }
+
+ printk(KERN_INFO "***rda_bt_power_on success!!! \n");
+
+ rda_combo_i2c_unlock();
+ /*houzhen update 2012 03 06*/
+ msleep(10); //delay 10 ms after power on
+ disable_26m_rtc(CLOCK_BT);
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+ disable_26m_rtc(CLOCK_BT);
+ disable_32k_rtc(CLOCK_BT);
+ disable_26m_regulator(CLOCK_BT);
+ printk(KERN_INFO "***rda_bt_power_on failed! \n");
+ return -1;
+
+}
+
+int rda_5990_bt_power_off(void)
+{
+ int ret = 0;
+ printk(KERN_INFO "rda_5990_bt_power_off \n");
+
+ if(!rda_bt_rf_client){
+ printk(KERN_INFO "rda_5990_bt_power_off failed on:i2c client \n");
+ return -1;
+ }
+
+ rda_combo_i2c_lock();
+
+ if(rda_wlan_version() == WLAN_VERSION_90_D || rda_wlan_version() == WLAN_VERSION_90_E){
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client ,rda_5990_bt_off_data);
+ if(ret)
+ goto err;
+ }
+
+ msleep(10); //10ms
+ printk(KERN_INFO "***rda_5990_bt_power_off success!!! \n");
+
+ ret=rda5990_bt_setup_A2_power(0);//disable ldo_pa reg
+ if(ret)
+ goto err;
+
+ rda_combo_i2c_unlock();
+ disable_26m_rtc(CLOCK_BT);
+ disable_32k_rtc(CLOCK_BT);
+ disable_26m_regulator(CLOCK_BT);
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***rda_5990_bt_power_off failed! \n");
+ return -1;
+
+}
+
+
+static int RDA5990_bt_rf_init(void)
+{
+ int ret = 0;
+
+ if(!rda_bt_rf_client){
+ printk(KERN_INFO "RDA5990_bt_rf_init on:i2c client \n");
+ return -1;
+ }
+
+ rda_combo_i2c_lock();
+
+ if(rda_wlan_version() == WLAN_VERSION_90_D || rda_wlan_version() == WLAN_VERSION_90_E){
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5990_bt_rf_data);
+ if(ret)
+ goto err;
+ }
+
+ rda_combo_i2c_unlock();
+
+ printk(KERN_INFO "***RDA5990_bt_rf_init success!!! \n");
+ msleep(5); //5ms
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***RDA5990_bt_rf_init failed! \n");
+ return -1;
+}
+
+/*houzhen add 2012 04 09
+ add to ensure bt dig powerup
+ */
+static int RDA5990_bt_dig_reset(void)
+{
+ int ret = 0;
+
+ if(!rda_bt_rf_client){
+ printk(KERN_INFO "RDA5990_bt_dig_reset on:i2c client \n");
+ return -1;
+ }
+
+ rda_combo_i2c_lock();
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, RDA5990_bt_dig_reset_data);
+ if(ret)
+ goto err;
+
+ rda_combo_i2c_unlock();
+
+ printk(KERN_INFO "***RDA5990_bt_dig_reset success!!! \n");
+ msleep(5); //5ms
+
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***RDA5990_bt_dig_reset failed! \n");
+ return -1;
+}
+
+
+static int RDA5990_bt_dc_cal(void)
+{
+ int ret = 0;
+
+ if(!rda_bt_rf_client){
+ printk(KERN_INFO "rda_bt_rf_client \n");
+ return -1;
+ }
+
+ rda_combo_i2c_lock();
+
+ if(rda_wlan_version() == WLAN_VERSION_90_D || rda_wlan_version() == WLAN_VERSION_90_E){
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5990_bt_dc_cal);
+ if(ret)
+ goto err;
+ }
+
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***rda_bt_dc_cal success!!! \n");
+ msleep(200); //200ms
+
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***rda_bt_dc_cal failed! \n");
+ return -1;
+
+}
+
+
+/*houzhen update Mar 15 2012
+ bypass RDA5990_bt_set_rf_switch when wf is already on
+*/
+
+static int RDA5990_bt_set_rf_switch(void)
+{
+ int ret = 0;
+ u16 temp_data=0;
+
+ if(!rda_bt_rf_client || !rda_wifi_rf_client){
+ printk(KERN_INFO "RDA5990_bt_set_rf_switch failed on:i2c client \n");
+ return -1;
+ }
+
+ rda_combo_i2c_lock();
+
+ if(rda_wlan_version() == WLAN_VERSION_90_D || rda_wlan_version() == WLAN_VERSION_90_E){
+ ret = i2c_write_1_addr_2_data(rda_bt_rf_client, 0x3f, 0x0001);
+ if(ret)
+ goto err;
+
+ ret=i2c_read_1_addr_2_data(rda_bt_rf_client,0x31,&temp_data);
+ if(ret)
+ goto err;
+
+ if(temp_data&0x8000) { // if wf is already on
+ printk(KERN_INFO "wf already en, bypass RDA5990_bt_set_rf_switch function \n");
+ ret = i2c_write_1_addr_2_data(rda_bt_rf_client, 0x3f, 0x0000);
+ if(ret)
+ goto err;
+
+ rda_combo_i2c_unlock();
+ return 0;
+ }
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, rda_5990_bt_set_rf_switch_data);
+ if(ret)
+ goto err;
+ }
+
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***RDA5990_bt_set_rf_switch success!!! \n");
+ msleep(50); //50ms
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***RDA5990_bt_set_rf_switch failed! \n");
+ return -1;
+
+}
+
+
+/*houzhen update Mar 15 2012
+ bypass RDA5990_bt_enable_clk when wf is already on
+ */
+static int RDA5990_bt_enable_clk(void)
+{
+ int ret = 0;
+ u16 temp_data=0;
+
+ if(!rda_bt_rf_client){
+ printk(KERN_INFO "RDA5990_bt_enable_clk failed on:i2c client \n");
+ return -1;
+ }
+
+ rda_combo_i2c_lock();
+ ret = i2c_write_1_addr_2_data(rda_bt_rf_client, 0x3f, 0x0001);
+ if(ret)
+ goto err;
+
+ ret=i2c_read_1_addr_2_data(rda_bt_rf_client,0x31,&temp_data);
+
+ if(ret)
+ goto err;
+
+ if(temp_data&0x8000){ // if wf is already on
+ printk(KERN_INFO "wf already en, bypass RDA5990_bt_enable_clk function \n");
+ ret = i2c_write_1_addr_2_data(rda_bt_rf_client, 0x3f, 0x0000);
+ if(ret)
+ goto err;
+ rda_combo_i2c_unlock();
+ return 0;
+ }
+
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, RDA5990_bt_enable_clk_data);
+ if(ret)
+ goto err;
+
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***RDA5990_bt_enable_clk success!!! \n");
+ msleep(50); //50ms
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***RDA5990_bt_enable_clk failed! \n");
+ return -1;
+}
+
+long rda_5990_pw_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+
+ switch(cmd)
+ {
+ case RDA_WIFI_POWER_ON_IOCTL:
+ ret = rda_5990_wifi_power_on();
+ break;
+
+ case RDA_WIFI_POWER_OFF_IOCTL:
+ ret = rda_5990_wifi_power_off();
+ break;
+
+ case RDA_WIFI_DEBUG_MODE_IOCTL:
+ {
+ int enable = 0;
+ if(copy_from_user(&enable, (void*)arg, sizeof(int))) {
+ printk(KERN_ERR "copy_from_user enable failed!\n");
+ return -EFAULT;
+ }
+ ret = rda_5990_wifi_debug_en(enable);
+ break;
+ }
+
+ case RDA_BT_POWER_ON_IOCTL:
+ ret = rda_5990_bt_power_on();
+ break;
+
+ /* should call this function after bt_power_on*/
+ case RDA_BT_EN_CLK:
+ ret = RDA5990_bt_enable_clk();
+ break;
+
+ case RDA_BT_RF_INIT_IOCTL:
+ ret = RDA5990_bt_rf_init();
+ break;
+
+ case RDA_BT_DC_CAL_IOCTL:
+ ret = RDA5990_bt_dc_cal();
+ break;
+
+ case RDA_BT_DC_DIG_RESET_IOCTL:
+ ret = RDA5990_bt_dig_reset();
+ break;
+
+ case RDA_BT_RF_SWITCH_IOCTL:
+ ret = RDA5990_bt_set_rf_switch();
+ break;
+
+ case RDA_BT_POWER_OFF_IOCTL:
+ ret = rda_5990_bt_power_off();
+ break;
+
+ default:
+ {
+ ret = -EFAULT;
+ printk(KERN_ERR "******rda_5990_pw_ioctl cmd[0x%02x]******.\n", cmd);
+ break;
+ }
+ }
+
+ printk(KERN_INFO "rda_bt_pw_ioctl cmd=0x%02x \n", cmd);
+ return ret;
+}
+
diff --git a/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_5991_power_ctrl.c b/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_5991_power_ctrl.c
new file mode 100755
index 00000000..58d1fca4
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_5991_power_ctrl.c
@@ -0,0 +1,725 @@
+#include "rda_combo.h"
+
+#ifdef WLAN_USE_DCDC
+static const u16 pmu_setting[][2] = {
+ {0x3F, 0x0001},
+ {0x22, 0xA1F3}, //Pu_rf_dr=0;Nonov_delay_dig=11,Nonov_delay_ana=11
+ {0x24, 0x8808}, //pu_dcdc_dr_ana=0;pu_ldo_dr_ana=0;AVDD=2.07V;sleep vol=0000;clk_mode_sel_dr_ana =0
+ {0x26, 0x8255}, //sleep voltage=800mV;clk_mode_sel_dr_dig=0
+ {0x23, 0xC200}, //Dcdc_en_ana=1
+ {0x25, 0xC27F}, //Dcdc_en_dig=1;sleep_ldo_vout=111=1.1v
+ {0x37, 0x0B8A},
+ {0x39, 0x1200}, //for dcdc;uart_bypass_en
+ {0x3F, 0x0000},
+};
+#else
+static const u16 pmu_setting[][2] = {
+ {0x3F, 0x0001},
+ {0x22, 0xA1F3}, //Pu_rf_dr=0;Nonov_delay_dig=11,Nonov_delay_ana=11
+ {0x24, 0x8808}, //pu_dcdc_dr_ana=0;pu_ldo_dr_ana=0;AVDD=2.07V;sleep vol=0000;clk_mode_sel_dr_ana =0
+ {0x26, 0x8255}, //sleep voltage=800mV;clk_mode_sel_dr_dig=0;pu_ldo_dr_dig=1;pu_ldo_reg_dig =1
+ {0x23, 0x4200}, //Dcdc_en_ana=0
+ {0x25, 0x427F}, //Dcdc_en_dig=0;sleep_ldo_vout=111=1.1v
+ {0x37, 0x0B8A},
+ {0x39, 0x1200}, //for dcdc;uart_bypass_en
+ {0x3F, 0x0000},
+};
+#endif
+
+/*add according to hongjun's new config*/
+static const u16 soft_reset[][2] = {
+ {0x3F, 0x0000},
+ {0x30, 0x8000},
+ {0x30, 0x0000},
+};
+
+static const u16 wf_en[][2] = {
+ {0x3F, 0x0001},
+ {0x31, 0x8B40}, //;WIFI_en=1
+ {0x3F, 0x0000},
+};
+
+static const u16 wifi_disable[][2] = {
+ {0x3F, 0x0001},
+ {0x31, 0x0B40}, //;WIFI_en=0
+ {0x3F, 0x0000},
+};
+
+static const u16 wf_rf_setting[][2] = {
+ {0x3F, 0x0000},
+ {0x10, 0x9f33}, //wf_lna_bpf_en =1
+ {0x11, 0xFF8A},
+ {0x13, 0x5054},
+ {0x14, 0x988C}, //wf_pll_regbit_presc[3:0]=1100,for temperatrue
+ {0x15, 0x596F},
+ {0x16, 0x200B}, //wf_pll_r_bit[1:0] =01;wf_pll_r_bit[1:0]=00
+ {0x19, 0x9C01}, //wf_pll_sinc_mode[2:0]=001 ,ver D
+ {0x1C, 0x06E4}, //wf_dac_cm_bit[1:0]=00,1.1V
+ {0x1D, 0x3A8C},
+ {0x22, 0xFF4B}, //ver D
+ {0x23, 0xAA3C},
+ {0x24, 0x88C4}, //wf_dac_cal_dr=1;ver D
+ {0x28, 0x1320},
+ {0x2A, 0x0036},
+ {0x2B, 0x41BB}, //wf_ovd_resbit_for_wf_tx[7:0]=FF;wf_pa_cap2_open_for_wf_tx=1
+ {0x2D, 0xFF03}, //wf_pa_capbit_for_wf_tx[7:0]=3
+ {0x2F, 0x00DE}, //wf_dsp_resetn_tx_dr=1;wf_dsp_resetn_tx_reg=1; ;;wf_dsp_resetn_rx_dr=1;wf_dsp_resetn_rx_reg=1;
+ {0x34, 0x3000}, //wf_dac_clk_inv[1:0]=11
+ {0x39, 0x8000},
+ {0x40, 0x7FFF}, //wf_tmx_gain,wf_pabias
+ {0x41, 0xFFFF}, //wf_pabias
+};
+
+static const u16 wf_agc_setting_for_dccal[][2] = {
+ {0x3F, 0x0000},
+ {0x0F, 0x61F7}, //;//0F
+ {0x0E, 0x61F0}, //
+ {0x0D, 0x60F0}, //
+ {0x0C, 0x6070}, //
+ {0x0B, 0x6030}, //
+ {0x0A, 0x6010}, //
+ {0x09, 0x7033}, //
+ {0x08, 0x6830}, //;;//08
+ {0x3F, 0x0001},
+ {0x07, 0x7031}, //;;//07
+ {0x06, 0x7011}, //;;//06
+ {0x05, 0x7871}, //
+ {0x04, 0x7831}, //;;//04
+ {0x03, 0x7811}, //;;//03
+ {0x02, 0x7801}, //;;//02
+ {0x01, 0x7800}, //;;//01
+ {0x00, 0x7800}, //;;//00
+ {0x3F, 0x0000},
+};
+
+static const u16 wf_agc_setting[][2] = {
+ {0x3F, 0x0000},
+ {0x0F, 0x01F7}, //;//0F
+ {0x0E, 0x01F0}, //
+ {0x0D, 0x00F0}, //
+ {0x0C, 0x0070}, //
+ {0x0B, 0x0030}, //
+ {0x0A, 0x0010}, //
+ {0x09, 0x3033}, //
+ {0x08, 0x0830}, //;;//08
+ {0x3F, 0x0001},
+ {0x07, 0x7031}, //;;//07
+ {0x06, 0x7011}, //;;//06
+ {0x05, 0x7871}, //
+ {0x04, 0x7831}, //;;//04
+ {0x03, 0x7811}, //;;//03
+ {0x02, 0x7801}, //;;//02
+ {0x01, 0x7800}, //;;//01
+ {0x00, 0x7800}, //;;//00
+ {0x3F, 0x0000},
+};
+
+static const u16 wf_calibration[][2] = {
+#if 1 //hongjun's new config
+ {0x3F,0x0000},
+ {0x1a,0x0026},//趨Ƶ2487MHZ
+ {0x1B,0xDC00},//趨Ƶ2487MHZ
+ {0x28,0x1F20},
+ {0x28,0x1320},
+ {0x30,0x0159},//趨frequency mode
+ {0x30,0x0158},
+ {0x30,0x0159},//dc_cal
+ DELAY_MS(200)
+#else
+ {0x3F, 0x0000},
+ {0x30, 0x0148},
+ DELAY_MS(100)
+ {0x28, 0x1F20}, //mdll_startup
+ {0x28, 0x1320}, //mdll_startup_done
+ {0x30, 0x0149},
+ DELAY_MS(100)
+ {0x30, 0x0349}, //wf_chip_self_cal_en=1
+#endif
+};
+
+static const u16 bt_rf_setting[][2] = {
+ {0x3F, 0x0000},
+ {0x02, 0x0E00}, //BT_Agc<2:0>;
+ {0x08, 0xEFFF}, //bt_lna_gain2_7[2:0=11111
+ {0x0A, 0x09FF}, //bt_rxflt_gain_5=11
+ {0x11, 0x0035}, //
+ {0x13, 0x2C68}, //
+ {0x14, 0x91C4}, //bt_adc_digi_pwr_bit_reg[2:0]=011
+ {0x18, 0x2010}, //bt_pll_phase_ctrl_dly[1:0]=00
+ {0x30, 0x0141},
+ {0x3F, 0x0001},
+ {0x01, 0x66F3}, //bt_tmx_therm_gain_f[3:0]=0011
+ {0x3F, 0x0000},
+ {0x2E, 0xCAA3}, //bt_swtrx_dr=1;bt_swtrx_reg=1
+ {0x37, 0x4411}, //PSK
+ {0x38, 0x1348}, //PSK
+ {0x3B, 0x2200}, //GFSK
+ {0x3C, 0x0124}, //GFSK
+ {0x3F, 0x0001},
+ {0x00, 0xBBBB}, //
+ {0x01, 0x66F3}, //
+ {0x02, 0xBBBB}, //
+ {0x03, 0x66F3}, //
+ {0x04, 0xBBBB}, //
+ {0x05, 0x66F3}, //
+ {0x06, 0xBBBB}, //
+ {0x07, 0x66FF}, //
+ {0x08, 0xBBBB}, //
+ {0x09, 0x66F7}, //
+ {0x0A, 0xBBBB}, //
+ {0x0B, 0x66F0}, //
+ {0x39, 0x1200}, //uart_bypass_en=0
+ {0x3F, 0x0000},
+};
+
+static const u16 control_mode_disable[][2] = {
+#if 1 //hongjun's new config
+ {0x3F,0x0000},
+ {0x30,0x0149},//趨channel mode
+ {0x30,0x014D},
+ {0x30,0x0141},
+#else
+ {0x3F, 0x0000},
+ {0x30, 0x0141},
+#endif
+};
+
+static const u16 bt_en[][2] = {
+ {0x3F, 0x0001},
+ {0x28, 0x85A1}, //;bt_en=1
+ {0x3F, 0x0000},
+};
+
+static const u16 bt_disable[][2] = {
+ {0x3F, 0x0001},
+ {0x28, 0x05A1}, //;bt_en=1
+ {0x3F, 0x0000},
+};
+static const u16 rda_5991_bt_dc_ca_fix_gain[][2] =
+{
+ {0x3f, 0x0000 },
+ {0x30, 0x0141 },
+ {0x30, 0x0140 },
+ {0x30, 0x0141 },
+ {0x30, 0x0341 }, //force gain level to 7 before lna issue fixed
+ {0x2e, 0x8aa3 }, //force gain level to 7 before lna issue fixed
+ {0x3f, 0x0000 },
+};
+static const u16 rda_5991_bt_dc_ca_fix_gain_no_wf[][2] =
+{
+ {0x3f, 0x0000 },
+ {0x30, 0x0140 },
+ {0x30, 0x0141 },
+ {0x3f, 0x0000 },
+};
+// add for pta
+
+// add for pta
+static const u16 rda_5991_bt_force_swtrx[][2] =
+{
+ {0x3f, 0x0000 },
+ {0x2e, 0xcaa3 }, //force gain level to 7 before lna issue fixed
+ {0x3f, 0x0000 },
+};
+static const u16 rda_5991_bt_no_force_swtrx[][2] =
+{
+ {0x3f, 0x0000 },
+ {0x2e, 0x8aa3 }, //force gain level to 7 before lna issue fixed
+ {0x3f, 0x0000 },
+};
+
+static int check_wifi_power_on(void)
+{
+ int ret = 0;
+ u16 temp_data;
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001);
+ if (ret)
+ goto err;
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x31, &temp_data);
+ if (ret)
+ goto err;
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000);
+
+ if (temp_data & 0x8000)
+ return 1;
+err:
+ return 0;
+}
+
+static int check_bt_power_on(void)
+{
+ int ret = 0;
+ u16 temp_data;
+
+ ret = i2c_write_1_addr_2_data(rda_bt_rf_client, 0x3f, 0x0001);
+ if (ret)
+ goto err;
+
+ ret = i2c_read_1_addr_2_data(rda_bt_rf_client, 0x28, &temp_data);
+ if (ret)
+ goto err;
+
+ ret = i2c_write_1_addr_2_data(rda_bt_rf_client, 0x3f, 0x0000);
+ if (temp_data & 0x8000)
+ return 1;
+err:
+ return 0;
+}
+
+static int power_on(int isWifi)
+{
+ int ret = 0;
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, pmu_setting);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write pmu_setting succeed!! \n", __func__);
+
+ if (isWifi) { // for wifi
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_en);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write wf_en succeed!! \n", __func__);
+ } else { // for bt
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_en);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write bt_en succeed!! \n", __func__);
+ }
+
+ rda_combo_i2c_unlock();
+ msleep(5);
+ rda_combo_i2c_lock();
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, soft_reset);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write soft_reset succeed!! \n", __func__);
+
+ rda_combo_i2c_unlock();
+ msleep(10);
+ rda_combo_i2c_lock();
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_rf_setting);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write wf_rf_setting succeed!! \n", __func__);
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_rf_setting);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write bt_rf_setting succeed!! \n", __func__);
+
+ ret =
+ RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_agc_setting_for_dccal);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write wf_agc_setting_for_dccal succeed!! \n",
+ __func__);
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_calibration);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write wf_calibration succeed!! \n", __func__);
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_agc_setting);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write wf_agc_setting succeed!! \n", __func__);
+
+ return 0;
+power_off:
+ if (isWifi) { // for wifi
+ RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_disable);
+ } else {
+ RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_disable);
+ }
+err:
+ return -1;
+}
+
+static int rda_5991_wifi_debug_en(void)
+{
+ u16 temp_data = 0;
+ int ret = 0;
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001);
+ if (ret < 0)
+ return -1;
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x28, 0x80a1);
+ if (ret < 0)
+ return -1;
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x39, &temp_data);
+ if (ret < 0)
+ return -1;
+
+ ret =
+ i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x39, temp_data | 0x04);
+ if (ret < 0)
+ return -1;
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000);
+ if (ret < 0)
+ return -1;
+ return ret;
+}
+
+int rda_5991_wifi_power_on(void)
+{
+ int ret = 0, bt_power_on = 0;
+
+ //if bt is power on wait until it's complete
+ wait_for_completion(&rda_wifi_bt_comp);
+
+ rda_combo_i2c_lock();
+ #ifdef RDA_KERNEL_PLATFORM
+ enable_26m_regulator(CLOCK_WLAN);
+ enable_32k_rtc(CLOCK_WLAN);
+ enable_26m_rtc(CLOCK_WLAN);
+ #endif
+ bt_power_on = check_bt_power_on();
+ printk(KERN_INFO "%s bt_power_on=%d \n", __func__, bt_power_on);
+
+ if (bt_power_on) {
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_en);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write wf_en succeed!! \n", __func__);
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5991_bt_no_force_swtrx);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write rda_5991_bt_no_force_swtrx succeed!! \n", __func__);
+ rda_combo_i2c_unlock();
+ msleep(5);
+ rda_combo_i2c_lock();
+ } else {
+ ret = power_on(1);
+ if (ret)
+ goto err;
+ }
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, control_mode_disable);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write control_mode_disable succeed!! \n",
+ __func__);
+ if (rda_combo_wifi_in_test_mode()) {
+ rda_5991_wifi_debug_en();
+ printk(KERN_INFO
+ "%s: IN test mode, switch uart to WIFI succeed!! \n",
+ __func__);
+ }
+
+ rda_combo_i2c_unlock();
+ msleep(100);
+ complete(&rda_wifi_bt_comp);
+ return ret;
+
+power_off:
+ RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_disable);
+err:
+ #ifdef RDA_KERNEL_PLATFORM
+ disable_26m_rtc(CLOCK_WLAN);
+ disable_32k_rtc(CLOCK_WLAN);
+ disable_26m_regulator(CLOCK_WLAN);
+ #endif
+ rda_combo_i2c_unlock();
+ return -1;
+}
+
+int rda_5991_wifi_power_off(void)
+{
+ int ret = 0;
+ int bt_power_on = 0; // add for pta
+ rda_combo_i2c_lock();
+ bt_power_on = check_bt_power_on();
+ if(bt_power_on){
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5991_bt_force_swtrx);
+ if (ret) {
+ printk(KERN_INFO "%s rda_5991_bt_force_swtrx failed!! \n", __func__);
+ } else {
+ printk(KERN_INFO "%s rda_5991_bt_force_swtrx succeed!! \n", __func__);
+ }
+ }
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_disable);
+ if (ret) {
+ printk(KERN_INFO "%s failed!! \n", __func__);
+ } else {
+ printk(KERN_INFO "%s succeed!! \n", __func__);
+ }
+ #ifdef RDA_KERNEL_PLATFORM
+ disable_26m_rtc(CLOCK_WLAN);
+ disable_32k_rtc(CLOCK_WLAN);
+ disable_26m_regulator(CLOCK_WLAN);
+ #endif
+ rda_combo_i2c_unlock();
+ return ret;
+}
+
+int rda_5991_bt_power_on(void)
+{
+ int ret = 0, wifi_power_on = 0;
+
+ //if wifi is power on wait until it's complete
+ wait_for_completion(&rda_wifi_bt_comp);
+
+ rda_combo_i2c_lock();
+ #ifdef RDA_KERNEL_PLATFORM
+ enable_26m_regulator(CLOCK_BT);
+ enable_26m_rtc(CLOCK_BT);
+ enable_32k_rtc(CLOCK_BT);
+ #endif
+ wifi_power_on = check_wifi_power_on();
+ printk(KERN_INFO "%s wifi_power_on=%d \n", __func__, wifi_power_on);
+
+ if (wifi_power_on) {
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_en);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write bt_en succeed!! \n", __func__);
+ rda_combo_i2c_unlock();
+ msleep(5);
+ rda_combo_i2c_lock();
+ } else {
+ ret = power_on(0);
+ if (ret)
+ goto err;
+ }
+
+ printk(KERN_INFO "%s succeed!! \n", __func__);
+
+ rda_combo_i2c_unlock();
+ msleep(10);
+ complete(&rda_wifi_bt_comp);
+ return ret;
+
+err:
+ #ifdef RDA_KERNEL_PLATFORM
+ disable_26m_rtc(CLOCK_BT);
+ disable_32k_rtc(CLOCK_BT);
+ disable_26m_regulator(CLOCK_BT);
+ #endif
+ rda_combo_i2c_unlock();
+ return -1;
+}
+
+int rda_5991_bt_power_off(void)
+{
+ int ret = 0;
+ rda_combo_i2c_lock();
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_disable);
+ if (ret) {
+ printk(KERN_INFO "%s failed!! \n", __func__);
+ } else {
+ printk(KERN_INFO "%s succeed!! \n", __func__);
+ }
+ #ifdef RDA_KERNEL_PLATFORM
+ disable_26m_rtc(CLOCK_BT);
+ disable_32k_rtc(CLOCK_BT);
+ disable_26m_regulator(CLOCK_BT);
+ #endif
+ rda_combo_i2c_unlock();
+ return ret;
+}
+// add for pta
+static int RDA5991_bt_dc_cal_fix_gain(void)
+{
+ int ret = 0;
+ int is_wfen;
+ if(!rda_bt_rf_client){
+ printk(KERN_INFO "rda_bt_rf_client is NULL!\n");
+ return -1;
+ }
+ rda_combo_i2c_lock();
+ is_wfen= check_wifi_power_on();
+ if(rda_wlan_version() == WLAN_VERSION_91)
+ {
+ if(is_wfen)
+ {
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5991_bt_dc_ca_fix_gain);
+ }
+ else
+ {
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5991_bt_dc_ca_fix_gain_no_wf);
+ }
+ if(ret)
+ goto err;
+ }
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***RDA5991_bt_dc_cal_fix_gain_update success!!! \n");
+ msleep(200); //200ms
+ return 0;
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***RDA5991_bt_dc_cal_fix_gain failed! \n");
+ return -1;
+}
+
+long rda_5991_pw_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+
+ switch (cmd) {
+ case RDA_WIFI_POWER_ON_IOCTL:
+ ret = rda_5991_wifi_power_on();
+ break;
+
+ case RDA_WIFI_POWER_OFF_IOCTL:
+ ret = rda_5991_wifi_power_off();
+ break;
+
+ case RDA_BT_POWER_ON_IOCTL:
+ ret = rda_5991_bt_power_on();
+ break;
+
+ case RDA_BT_POWER_OFF_IOCTL:
+ ret = rda_5991_bt_power_off();
+ break;
+
+ case RDA_WIFI_DEBUG_MODE_IOCTL:
+ ret = rda_5991_wifi_debug_en();
+ break;
+ case RDA_BT_DC_CAL_IOCTL_FIX_5991_LNA_GAIN:
+ ret = RDA5991_bt_dc_cal_fix_gain();
+ break;
+ default:
+ break;
+ }
+
+ printk(KERN_INFO "rda_bt_pw_ioctl cmd=0x%02x \n", cmd);
+ return ret;
+}
+
+int rda_5991_fm_power_on(void)
+{
+ int ret = 0;
+ u16 temp = 0;
+
+ if (!rda_wifi_rf_client) {
+ printk(KERN_INFO
+ "rda_wifi_rf_client is NULL, rda_fm_power_on failed!\n");
+ return -1;
+ }
+
+ enable_32k_rtc(CLOCK_FM);
+ msleep(8);
+ rda_combo_i2c_lock();
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001); // page down
+ if (ret < 0) {
+ printk(KERN_INFO
+ "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ if (rda_wlan_version() == WLAN_VERSION_91) {
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x27, &temp); //read 0xA7
+ if (ret < 0) {
+ printk(KERN_INFO
+ "%s() read from address(0x%02x) failed! \n",
+ __func__, 0xA7);
+ goto err;
+ }
+ temp = temp | 0x1; //set bit[0]
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x27, temp); //write back
+ if (ret < 0) {
+ printk(KERN_INFO
+ "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0xA7, temp);
+ goto err;
+ }
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x39, &temp); //read 0xB9
+ if (ret < 0) {
+ printk(KERN_INFO
+ "%s() read from address(0x%02x) failed! \n",
+ __func__, 0xB9);
+ goto err;
+ }
+ temp = temp | (0x1 << 15); //set bit[15]
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x39, temp); //write back
+ if (ret < 0) {
+ printk(KERN_INFO
+ "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0xB9, temp);
+ goto err;
+ }
+ }
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000); // page up
+ if (ret < 0) {
+ printk(KERN_INFO
+ "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ rda_combo_i2c_unlock();
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+ disable_32k_rtc(CLOCK_FM);
+ printk(KERN_INFO "***rda_fm_power_on failed! \n");
+ return -1;
+}
+
+int rda_5991_fm_power_off(void)
+{
+ int ret = 0;
+ u16 temp = 0;
+
+ if (!rda_wifi_rf_client) {
+ printk(KERN_INFO
+ "rda_wifi_rf_client is NULL, rda_fm_power_off failed!\n");
+ return -1;
+ }
+
+ rda_combo_i2c_lock();
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001); // page down
+ if (ret < 0) {
+ printk(KERN_INFO
+ "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ if (rda_wlan_version() == WLAN_VERSION_91) {
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x27, &temp); //read 0xA7
+ if (ret < 0) {
+ printk(KERN_INFO
+ "%s() read from address(0x%02x) failed! \n",
+ __func__, 0xA7);
+ goto err;
+ }
+ temp = temp & ~(0x1 << 15); //clear bit[0]
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x27, temp); //write back
+ if (ret < 0) {
+ printk(KERN_INFO
+ "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0xA7, temp);
+ goto err;
+ }
+ }
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000); // page up
+ if (ret < 0) {
+ printk(KERN_INFO
+ "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ rda_combo_i2c_unlock();
+ disable_32k_rtc(CLOCK_FM);
+ return 0;
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***rda_fm_power_off failed! \n");
+ return -1;
+}
diff --git a/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_5991e_power_ctrl.c b/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_5991e_power_ctrl.c
new file mode 100755
index 00000000..2c330e4c
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_5991e_power_ctrl.c
@@ -0,0 +1,796 @@
+#include "rda_combo.h"
+
+#define COMBO_WITH_26MHZ
+
+#ifdef WLAN_USE_DCDC
+static const u16 pmu_setting[][2] = {
+ {0x3F, 0x0001},
+ {0x22, 0xA1F3},
+ {0x24, 0x8906}, //{0x24, 0x8908} sleep mode with analog power on
+ {0x26, 0x8055},
+ {0x33, 0x0510},
+ {0x39, 0xC208},
+ {0x23, 0xA200}, //{0x23, 0x8200}
+ {0x25, 0xA247}, //{0x25, 0x8247} heavy_load_dig
+ {0x37, 0x0B8A},
+ {0x3F, 0x0000},
+};
+#else
+static const u16 pmu_setting[][2] = {
+ {0x3F, 0x0001},
+ {0x22, 0xA1F3},
+ {0x24, 0x8906},
+ {0x26, 0x8555},
+ {0x33, 0x0510},
+ {0x39, 0xC208},
+ {0x23, 0x0200},
+ {0x25, 0x027F},
+ {0x3F, 0x0000},
+};
+#endif
+
+/*add according to hongjun's new config*/
+static const u16 soft_reset[][2] = {
+ {0x3F, 0x0000},
+ {0x30, 0x8000},
+ {0x30, 0x0000},
+};
+
+static const u16 wf_en[][2] = {
+ {0x3F, 0x0001},
+ {0x31, 0x8B40}, //;WIFI_en=1
+ {0x3F, 0x0000},
+};
+
+static const u16 wifi_disable[][2] = {
+ {0x3F, 0x0001},
+ {0x31, 0x0B40}, //;WIFI_en=0
+ {0x3F, 0x0000},
+};
+
+#ifdef COMBO_WITH_26MHZ
+static const u16 wf_rf_setting[][2] = {
+ {0x3F, 0x0000},
+ {0x05, 0x0000},
+ {0x06, 0x1124}, //wf_bbpll_cpaux_bit[2:0]=100
+ {0x07, 0x0820},
+ {0x10, 0x9ff7},
+ {0x11, 0xFF8A},
+ {0x13, 0x5054},
+ {0x14, 0x988C},
+ {0x15, 0x58e8},
+ {0x16, 0x200B},
+ {0x19, 0x9C01},
+ {0x1C, 0x06E4},
+ {0x1D, 0x3A8C},
+ {0x22, 0xFF7B},
+ {0x23, 0x283C},
+ {0x24, 0xA0C4},
+ {0x28, 0x4320},
+ //add by LA, set different value according to different type 26M crystal
+ //{0x2A, 0x0036},
+ {0x2A, 0x103A},//for pingwang a23 5991e
+ {0x2B, 0x41BB},
+ {0x2D, 0xFF03},
+ {0x2F, 0x15DE},
+ {0x34, 0x3000},
+ {0x35, 0x8011},
+ {0x39, 0x6018},
+ {0x3B, 0x3218},
+ {0x40, 0x7FFF},//wf_tmx_gain,wf_pabias
+ {0x41, 0xFFFF},
+ {0x7D, 0x4020},//paon delay
+ {0x3F, 0x0001},
+ {0x37, 0x0B8A},
+ {0x3F, 0x0000},
+ {0x30, 0x0100},
+ {0x28, 0x4F20},
+ DELAY_MS(1)
+ {0x28, 0x4320},
+ {0x30, 0x0149},
+};
+#else
+static const u16 wf_rf_setting[][2] = {
+ {0x3F, 0x0000},
+ {0x03, 0x16AA},
+ {0x04, 0xAAAB},
+ {0x05, 0x0000},
+ {0x06, 0x1124}, //wf_bbpll_cpaux_bit[2:0]=100
+ {0x07, 0x0820},
+ {0x10, 0x9ff7},
+ {0x11, 0xFF8A},
+ {0x13, 0x5054},
+ {0x14, 0x988C},
+ {0x15, 0x58e8},
+ {0x16, 0x200B},
+ {0x19, 0x9C01},
+ {0x1C, 0x06E4},
+ {0x1D, 0x3A8C},
+ {0x22, 0xFF7B},
+ {0x23, 0x3D3C},
+ {0x24, 0xA0C4},
+ {0x27, 0x5318},
+ {0x28, 0x3318},
+ {0x2A, 0x0036},
+ {0x2B, 0x41BB},
+ {0x2D, 0xFF03},
+ {0x2F, 0x15DE},
+ {0x34, 0x3000},
+ {0x35, 0x8011},
+ {0x39, 0x6018},
+ {0x3B, 0x3218},
+ {0x40, 0x7FFF},//wf_tmx_gain,wf_pabias
+ {0x41, 0xFFFF},
+ {0x7D, 0x4020},//paon delay
+ {0x3F, 0x0001},
+ {0x37, 0x0B8A},
+ {0x3F, 0x0000},
+ {0x28, 0x1F20},
+ {0x28, 0x1320},
+ {0x30, 0x0100},
+ {0x28, 0x3F18},
+ DELAY_MS(1)
+ {0x28, 0x3318},
+ {0x30, 0x0149},
+};
+#endif
+
+static const u16 wf_agc_setting_for_dccal[][2] = {
+
+};
+
+static const u16 wf_agc_setting[][2] = {
+ {0x3F, 0x0000},
+ {0x0F, 0x01F7},
+ {0x0E, 0x01F0},
+ {0x0D, 0x00F0},
+ {0x0C, 0x0070},
+ {0x0B, 0x0030},
+ {0x0A, 0x0010},
+ {0x09, 0x3033},
+ {0x08, 0x0830},
+ {0x3F, 0x0001},
+ {0x07, 0x7030},
+ {0x06, 0x7010},
+ {0x05, 0x7870},
+ {0x04, 0x7830},
+ {0x03, 0x7811},
+ {0x02, 0x7800},
+ {0x01, 0x7800},
+ {0x00, 0x7800},
+ {0x3F, 0x0000},
+};
+
+static const u16 wf_calibration[][2] = {
+ {0x3F, 0x0000},
+ {0x30, 0x0148},
+ {0x30, 0x0149},
+ DELAY_MS(50)
+};
+
+static const u16 fix_agc_gain[][2] = {
+ {0x3F, 0x0000},
+ {0x30, 0x0349},
+};
+
+static const u16 bt_rf_setting[][2] = {
+ {0x3F, 0x0000},
+ {0x02, 0x0E00},
+ {0x08, 0xEFFF},
+ {0x0A, 0x09FF},
+ {0x11, 0x00B5},
+ {0x13, 0x07C0},
+ {0x14, 0xFDC4},
+ {0x18, 0x2010},
+ {0x19, 0x7956},
+ {0x1B, 0xDFE0},
+ {0x26, 0x7800},
+ {0x2B, 0x007F},
+ {0x2C, 0x600F},
+ {0x2D, 0x007F},
+#ifdef COMBO_WITH_26MHZ
+ {0x2E, 0xCAB3},
+#else
+ {0x2E, 0xCAA3},
+#endif
+ {0x2F, 0x1000},
+ {0x30, 0x0141},
+ {0x37, 0x4244}, //PSK
+ {0x38, 0x4688}, //PSK
+ {0x3B, 0x2122}, //GFSK
+ {0x3C, 0x2355}, //GFSK
+ {0x3F, 0x0001},
+ {0x00, 0xFFFF},
+ {0x01, 0xFFFF}, // bt power
+ {0x02, 0xFFFF},
+ {0x03, 0xFFF7},
+ {0x04, 0xFFFF},
+ {0x05, 0xFFF7},
+ {0x06, 0xFFFF},
+ {0x07, 0xFFF1},
+ {0x08, 0xFFFF},
+ {0x09, 0xFFE1},
+ {0x0A, 0xFFFF},
+ {0x0B, 0xFFE1},
+ //{0x39, 0x1208},
+ {0x3F, 0x0000},
+};
+
+static const u16 control_mode_disable[][2] = {
+ {0x3F, 0x0000},
+ {0x30, 0x0141},
+};
+
+static const u16 bt_en[][2] = {
+ {0x3F, 0x0001},
+ {0x28, 0x85A1}, //;bt_en=1
+ {0x3F, 0x0000},
+};
+
+static const u16 bt_disable[][2] = {
+ {0x3F, 0x0001},
+ {0x28, 0x05A1}, //;bt_en=1
+ {0x3F, 0x0000},
+};
+static const u16 rda_5991e_bt_dc_ca_fix_gain[][2] =
+{
+ {0x3f, 0x0000 },
+ {0x30, 0x0141 },
+ {0x30, 0x0140 },
+ {0x30, 0x0141 },
+#ifdef COMBO_WITH_26MHZ
+ {0x2e, 0x8ab3 }, //force gain level to 7 before lna issue fixed
+#else
+ {0x2e, 0x8aa3 }, //force gain level to 7 before lna issue fixed
+#endif
+ {0x3f, 0x0000 },
+};
+static const u16 rda_5991e_bt_dc_ca_fix_gain_no_wf[][2] =
+{
+ {0x3f, 0x0000 },
+ {0x30, 0x0140 },
+ {0x30, 0x0141 },
+ {0x3f, 0x0000 },
+};
+static const u16 rda_5991e_bt_force_swtrx[][2] =
+{
+ {0x3f, 0x0000 },
+#ifdef COMBO_WITH_26MHZ
+ {0x2e, 0xcab3 }, //force gain level to 7 before lna issue fixed
+#else
+ {0x2e, 0xcaa3 }, //force gain level to 7 before lna issue fixed
+#endif
+ {0x3f, 0x0000 },
+};
+static const u16 rda_5991e_bt_no_force_swtrx[][2] =
+{
+ {0x3f, 0x0000 },
+#ifdef COMBO_WITH_26MHZ
+ {0x2e, 0x8ab3 }, //force gain level to 7 before lna issue fixed
+#else
+ {0x2e, 0x8aa3 }, //force gain level to 7 before lna issue fixed
+#endif
+ {0x3f, 0x0000 },
+};
+
+static const u16 bt_dc_cal[][2] = {
+ {0x3F, 0x0000},
+ {0x30, 0x0140},
+ {0x30, 0x0141},
+ DELAY_MS(50)
+};
+static int check_wifi_power_on(void)
+{
+ int ret = 0;
+ u16 temp_data;
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001);
+ if (ret)
+ goto err;
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x31, &temp_data);
+ if (ret)
+ goto err;
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000);
+
+ if (temp_data & 0x8000)
+ return 1;
+err:
+ return 0;
+}
+
+static int check_bt_power_on(void)
+{
+ int ret = 0;
+ u16 temp_data;
+
+ ret = i2c_write_1_addr_2_data(rda_bt_rf_client, 0x3f, 0x0001);
+ if (ret)
+ goto err;
+
+ ret = i2c_read_1_addr_2_data(rda_bt_rf_client, 0x28, &temp_data);
+ if (ret)
+ goto err;
+
+ ret = i2c_write_1_addr_2_data(rda_bt_rf_client, 0x3f, 0x0000);
+ if (temp_data & 0x8000)
+ return 1;
+err:
+ return 0;
+}
+
+static int power_on(int isWifi)
+{
+ int ret = 0;
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, pmu_setting);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write pmu_setting succeed!! \n", __func__);
+
+ if (isWifi) { // for wifi
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_en);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write wf_en succeed!! \n", __func__);
+ } else { // for bt
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_en);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write bt_en succeed!! \n", __func__);
+ }
+
+ rda_combo_i2c_unlock();
+ msleep(5);
+ rda_combo_i2c_lock();
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, soft_reset);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write soft_reset succeed!! \n", __func__);
+
+ rda_combo_i2c_unlock();
+ msleep(10);
+ rda_combo_i2c_lock();
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_rf_setting);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write wf_rf_setting succeed!! \n", __func__);
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_rf_setting);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write bt_rf_setting succeed!! \n", __func__);
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_agc_setting);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write wf_agc_setting succeed!! \n",
+ __func__);
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_calibration);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write wf_calibration succeed!! \n", __func__);
+
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, fix_agc_gain);
+ if(ret)
+ goto power_off;
+ printk(KERN_INFO "%s write fix_agc_gain succeed!! \n", __func__);
+ return 0;
+power_off:
+ if (isWifi) { // for wifi
+ RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_disable);
+ } else {
+ RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_disable);
+ }
+err:
+ return -1;
+}
+
+static int rda_5991e_wifi_debug_en(int enable)
+{
+ u16 temp_data = 0;
+ int ret = 0;
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001);
+ if (ret < 0)
+ return -1;
+ if (enable == 1){
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x28, 0x80a1);
+ if (ret < 0)
+ return -1;
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x39, &temp_data);
+ if (ret < 0)
+ return -1;
+
+ ret =
+ i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x39, temp_data | (1 << 2));
+ if (ret < 0)
+ return -1;
+ }else{
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x28, 0x00a1);
+ if (ret < 0)
+ return -1;
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x39, &temp_data);
+ if (ret < 0)
+ return -1;
+ ret =
+ i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x39, temp_data & (~(1 << 2)));
+ if (ret < 0)
+ return -1;
+ }
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000);
+ if (ret < 0)
+ return -1;
+ return ret;
+}
+
+int rda_5991e_wifi_power_on(void)
+{
+ int ret = 0, bt_power_on = 0;
+
+ //if bt is power on wait until it's complete
+ wait_for_completion(&rda_wifi_bt_comp);
+
+ rda_combo_i2c_lock();
+ #ifdef RDA_KERNEL_PLATFORM
+ enable_26m_regulator(CLOCK_WLAN);
+ enable_32k_rtc(CLOCK_WLAN);
+ enable_26m_rtc(CLOCK_WLAN);
+ #endif
+ bt_power_on = check_bt_power_on();
+ printk(KERN_INFO "%s bt_power_on=%d \n", __func__, bt_power_on);
+
+ if (bt_power_on) {
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_en);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write wf_en succeed!! \n", __func__);
+ //add for pta
+ //handle btswtrx dr
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5991e_bt_no_force_swtrx);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write rda_5991_bt_no_force_swtrx succeed!! \n", __func__);
+ rda_combo_i2c_unlock();
+ msleep(5);
+ rda_combo_i2c_lock();
+ } else {
+ ret = power_on(1);
+ if (ret)
+ goto err;
+ }
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, control_mode_disable);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write control_mode_disable succeed!! \n", __func__);
+ if (rda_combo_wifi_in_test_mode()) {
+ rda_5991e_wifi_debug_en(1);
+ printk(KERN_INFO "%s: IN test mode, switch uart to WIFI succeed!! \n", __func__);
+ }
+
+ rda_combo_i2c_unlock();
+ msleep(100);
+ complete(&rda_wifi_bt_comp);
+ return ret;
+
+power_off:
+ RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_disable);
+err:
+#ifdef RDA_KERNEL_PLATFORM
+ disable_26m_rtc(CLOCK_WLAN);
+ disable_32k_rtc(CLOCK_WLAN);
+ disable_26m_regulator(CLOCK_WLAN);
+#endif
+ rda_combo_i2c_unlock();
+ return -1;
+}
+
+int rda_5991e_wifi_power_off(void)
+{
+ int ret = 0, bt_power_on = 0;
+ rda_combo_i2c_lock();
+ bt_power_on = check_bt_power_on();
+ if(bt_power_on){
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5991e_bt_force_swtrx);
+ if (ret) {
+ printk(KERN_INFO "%s rda_5991_bt_force_swtrx failed!! \n", __func__);
+ } else {
+ printk(KERN_INFO "%s rda_5991_bt_force_swtrx succeed!! \n", __func__);
+ }
+ }
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_disable);
+ if (ret) {
+ printk(KERN_INFO "%s failed!! \n", __func__);
+ } else {
+ printk(KERN_INFO "%s succeed!! \n", __func__);
+ }
+ bt_power_on = check_bt_power_on();
+ if (bt_power_on) {
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, fix_agc_gain);
+ printk(KERN_INFO "%s write fix_agc_gain succeed!! \n", __func__);
+ }
+ #ifdef RDA_KERNEL_PLATFORM
+ disable_26m_rtc(CLOCK_WLAN);
+ disable_32k_rtc(CLOCK_WLAN);
+ disable_26m_regulator(CLOCK_WLAN);
+ #endif
+ rda_combo_i2c_unlock();
+ return ret;
+}
+
+int rda_5991e_bt_power_on(void)
+{
+ int ret = 0, wifi_power_on = 0;
+
+ //if wifi is power on wait until it's complete
+ wait_for_completion(&rda_wifi_bt_comp);
+
+ rda_combo_i2c_lock();
+ #ifdef RDA_KERNEL_PLATFORM
+ enable_26m_regulator(CLOCK_BT);
+ enable_26m_rtc(CLOCK_BT);
+ enable_32k_rtc(CLOCK_BT);
+#endif
+
+ wifi_power_on = check_wifi_power_on();
+ printk(KERN_INFO "%s wifi_power_on=%d \n", __func__, wifi_power_on);
+
+ if (wifi_power_on) {
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_en);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write bt_en succeed!! \n", __func__);
+ rda_combo_i2c_unlock();
+ msleep(5);
+ rda_combo_i2c_lock();
+ } else {
+ ret = power_on(0);
+ if (ret)
+ goto err;
+ }
+
+ printk(KERN_INFO "%s succeed!! \n", __func__);
+
+ rda_combo_i2c_unlock();
+ msleep(10);
+ complete(&rda_wifi_bt_comp);
+ return ret;
+
+err:
+#ifdef RDA_KERNEL_PLATFORM
+ disable_26m_rtc(CLOCK_BT);
+ disable_32k_rtc(CLOCK_BT);
+ disable_26m_regulator(CLOCK_BT);
+#endif
+ rda_combo_i2c_unlock();
+ return -1;
+}
+
+int rda_5991e_bt_power_off(void)
+{
+ int ret = 0;
+ rda_combo_i2c_lock();
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_disable);
+ if (ret) {
+ printk(KERN_INFO "%s failed!! \n", __func__);
+ } else {
+ printk(KERN_INFO "%s succeed!! \n", __func__);
+ }
+ #ifdef RDA_KERNEL_PLATFORM
+ disable_26m_rtc(CLOCK_BT);
+ disable_32k_rtc(CLOCK_BT);
+ disable_26m_regulator(CLOCK_BT);
+ #endif
+ rda_combo_i2c_unlock();
+ return ret;
+}
+static int RDA5991e_bt_dc_cal_fix_gain(void)
+{
+ int ret = 0;
+ int is_wfen;
+
+ if(!rda_bt_rf_client){
+ printk(KERN_INFO "rda_bt_rf_client is NULL!\n");
+ return -1;
+ }
+ rda_combo_i2c_lock();
+ is_wfen= check_wifi_power_on();
+ if(rda_wlan_version() == WLAN_VERSION_91_E)
+ {
+ if(is_wfen)
+ {
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5991e_bt_dc_ca_fix_gain);
+ }
+ else
+ {
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5991e_bt_dc_ca_fix_gain_no_wf);
+ }
+ if(ret)
+ goto err;
+ }
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***RDA5991e_bt_dc_cal_fix_gain success!!!\n");
+ msleep(200); //200ms
+ return 0;
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***RDA5991e_bt_dc_cal_fix_gain failed! \n");
+ return -1;
+}
+long rda_5991e_pw_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+
+ switch (cmd) {
+ case RDA_WIFI_POWER_ON_IOCTL:
+ ret = rda_5991e_wifi_power_on();
+ break;
+
+ case RDA_WIFI_POWER_OFF_IOCTL:
+ ret = rda_5991e_wifi_power_off();
+ break;
+
+ case RDA_BT_POWER_ON_IOCTL:
+ ret = rda_5991e_bt_power_on();
+ break;
+
+ case RDA_BT_POWER_OFF_IOCTL:
+ ret = rda_5991e_bt_power_off();
+ break;
+
+ case RDA_WIFI_DEBUG_MODE_IOCTL:
+ {
+ int enable = 0;
+ if(copy_from_user(&enable, (void*)arg, sizeof(int))) {
+ printk(KERN_ERR "copy_from_user enable failed!\n");
+ return -EFAULT;
+ }
+ ret = rda_5991e_wifi_debug_en(enable);
+ break;
+ }
+ case RDA_BT_DC_CAL_IOCTL_FIX_5991_LNA_GAIN:
+ ret = RDA5991e_bt_dc_cal_fix_gain();
+ break;
+ default:
+ break;
+ }
+
+ printk(KERN_INFO "rda_bt_pw_ioctl cmd=0x%02x \n", cmd);
+ return ret;
+}
+
+int rda_5991e_fm_power_on(void)
+{
+ int ret = 0;
+ u16 temp = 0;
+
+ if (!rda_wifi_rf_client) {
+ printk(KERN_INFO
+ "rda_wifi_rf_client is NULL, rda_fm_power_on failed!\n");
+ return -1;
+ }
+
+ enable_32k_rtc(CLOCK_FM);
+ msleep(8);
+ rda_combo_i2c_lock();
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001); // page down
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ if (rda_wlan_version() == WLAN_VERSION_91_E) {
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x27, &temp); //read 0xA7
+ if (ret < 0) {
+ printk(KERN_INFO "%s() read from address(0x%02x) failed! \n",
+ __func__, 0xA7);
+ goto err;
+ }
+ temp = temp | 0x1; //set bit[0]
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x27, temp); //write back
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0xA7, temp);
+ goto err;
+ }
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x39, &temp); //read 0xB9
+ if (ret < 0) {
+ printk(KERN_INFO "%s() read from address(0x%02x) failed! \n",
+ __func__, 0xB9);
+ goto err;
+ }
+ temp = temp & 0x7fff; //set bit[15]=0
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x39, temp); //write back
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0xB9, temp);
+ goto err;
+ }
+
+ temp = temp | (0x1 << 15); //set bit[15]
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x39, temp); //write back
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0xB9, temp);
+ goto err;
+ }
+ }
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000); // page up
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ rda_combo_i2c_unlock();
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+ disable_32k_rtc(CLOCK_FM);
+ printk(KERN_INFO "***rda_fm_power_on failed! \n");
+ return -1;
+}
+
+int rda_5991e_fm_power_off(void)
+{
+ int ret = 0;
+ u16 temp = 0;
+
+ if (!rda_wifi_rf_client) {
+ printk(KERN_INFO
+ "rda_wifi_rf_client is NULL, rda_fm_power_off failed!\n");
+ return -1;
+ }
+
+ rda_combo_i2c_lock();
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001); // page down
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ if (rda_wlan_version() == WLAN_VERSION_91_E) {
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x27, &temp); //read 0xA7
+ if (ret < 0) {
+ printk(KERN_INFO "%s() read from address(0x%02x) failed! \n",
+ __func__, 0xA7);
+ goto err;
+ }
+ temp = temp & ~(0x1 << 15); //clear bit[0]
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x27, temp); //write back
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0xA7, temp);
+ goto err;
+ }
+ }
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000); // page up
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ rda_combo_i2c_unlock();
+ disable_32k_rtc(CLOCK_FM);
+ return 0;
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***rda_fm_power_off failed! \n");
+ return -1;
+}
+
diff --git a/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_5991f_power_ctrl.c b/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_5991f_power_ctrl.c
new file mode 100755
index 00000000..dfc64ffb
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_5991f_power_ctrl.c
@@ -0,0 +1,803 @@
+#include "rda_combo.h"
+
+#define COMBO_WITH_26MHZ
+
+#ifdef WLAN_USE_DCDC
+static const u16 pmu_setting[][2] = {
+ {0x3F, 0x0001},
+ {0x22, 0xA1F3},
+ {0x24, 0x8906}, //{0x24, 0x8908} sleep mode with analog power on
+ {0x26, 0x8057},
+ {0x33, 0x0510},
+ {0x39, 0x420C},
+ {0x23, 0xA200}, //{0x23, 0x8200}
+ {0x25, 0xA247}, //{0x25, 0x8247} heavy_load_dig
+ {0x37, 0x0B8A},
+ {0x3F, 0x0000},
+};
+#else
+static const u16 pmu_setting[][2] = {
+ {0x3F, 0x0001},
+ {0x22, 0xA1F3},
+ {0x24, 0x8908},
+ {0x26, 0x8555},
+ {0x33, 0x0510},
+ {0x39, 0x120C},
+ {0x23, 0x0200},
+ {0x25, 0x027F},
+ {0x3F, 0x0000},
+};
+#endif
+
+/*add according to hongjun's new config*/
+static const u16 soft_reset[][2] = {
+ {0x3F, 0x0000},
+ {0x30, 0x8000},
+ {0x30, 0x0000},
+};
+
+static const u16 wf_en[][2] = {
+ {0x3F, 0x0001},
+ {0x31, 0x8B40}, //;WIFI_en=1
+ {0x3F, 0x0000},
+};
+
+static const u16 wifi_disable[][2] = {
+ {0x3F, 0x0001},
+ {0x31, 0x0B40}, //;WIFI_en=0
+ {0x3F, 0x0000},
+};
+
+#ifdef COMBO_WITH_26MHZ
+static const u16 wf_rf_setting[][2] = {
+ {0x3F, 0x0000},
+ {0x05, 0x0000},
+ {0x06, 0x193F}, //wf_bbpll_cpaux_bit[2:0]=100
+ {0x07, 0x0820},
+ {0x10, 0x9ff7},
+ {0x11, 0xFF8A},
+ {0x13, 0x5054},
+ {0x14, 0x988C},
+ {0x15, 0x58eF},
+ {0x16, 0x200B},
+ {0x19, 0x9C01},
+ {0x1C, 0x06E4},
+ {0x1D, 0x3A8C},
+ {0x22, 0xFF7B},
+ {0x23, 0x283C},
+ {0x24, 0xA0C4},
+ {0x28, 0x4320},
+ {0x2A, 0x1036},//{0x2A, 0x0077}
+ {0x2B, 0x41BB},
+ {0x2D, 0xFF03},
+ {0x2F, 0x00DE},
+ {0x34, 0x3000},
+ {0x35, 0x8011},
+ {0x39, 0x8C00},
+ {0x40, 0x7FFF},//wf_tmx_gain,wf_pabias
+ {0x41, 0xFFFF},
+ {0x3F, 0x0001},
+ {0x37, 0x0B8A},
+ {0x3F, 0x0000},
+ {0x30, 0x0100},
+ {0x28, 0x4F20},
+ DELAY_MS(1)
+ {0x28, 0x4320},
+ {0x30, 0x0149},
+};
+#else
+static const u16 wf_rf_setting[][2] = {
+ {0x3F, 0x0000},
+ {0x03, 0x16AA},
+ {0x04, 0xAAAB},
+ {0x05, 0x0000},
+ {0x06, 0x112C}, //wf_bbpll_cpaux_bit[2:0]=100
+ {0x07, 0x0820},
+ {0x10, 0x9ff7},
+ {0x11, 0xFF8A},
+ {0x13, 0x5054},
+ {0x14, 0x988C},
+ {0x15, 0x58eF},
+ {0x16, 0x200B},
+ {0x19, 0x9C01},
+ {0x1C, 0x06E4},
+ {0x1D, 0x3A8C},
+ {0x22, 0xFF7B},
+ {0x23, 0x3D3C},
+ {0x24, 0xA0C4},
+ {0x27, 0x5318},
+ {0x28, 0x3318},
+ {0x2A, 0x0036},
+ {0x2B, 0x41BB},
+ {0x2D, 0xFF03},
+ {0x2F, 0x00DE},
+ {0x34, 0x3000},
+ {0x35, 0x8011},
+ {0x39, 0x8C00},
+ {0x40, 0x7FFF},//wf_tmx_gain,wf_pabias
+ {0x41, 0xFFFF},
+ {0x3F, 0x0001},
+ {0x37, 0x0B8A},
+ {0x3F, 0x0000},
+ {0x28, 0x1F20},
+ {0x28, 0x1320},
+ {0x30, 0x0100},
+ {0x28, 0x3F18},
+ DELAY_MS(1)
+ {0x28, 0x3318},
+ {0x30, 0x0149},
+};
+#endif
+
+static const u16 wf_agc_setting_for_dccal[][2] = {
+
+};
+
+static const u16 wf_agc_setting[][2] = {
+ {0x3F, 0x0000},
+ {0x0F, 0x01F7},
+ {0x0E, 0x01F0},
+ {0x0D, 0x00F0},
+ {0x0C, 0x0070},
+ {0x0B, 0x0030},
+ {0x0A, 0x0010},
+ {0x09, 0x3033},
+ {0x08, 0x0830},
+ {0x3F, 0x0001},
+ {0x07, 0x7031},
+ {0x06, 0x7011},
+ {0x05, 0x7001},
+ {0x04, 0x7831},
+ {0x03, 0x7811},
+ {0x02, 0x7801},
+ {0x01, 0x7800},
+ {0x00, 0x7800},
+ {0x3F, 0x0000},
+};
+
+static const u16 wf_calibration[][2] = {
+ {0x3F, 0x0000},
+ {0x30, 0x0148},
+ {0x30, 0x0149},
+ DELAY_MS(50)
+};
+
+static const u16 fix_agc_gain[][2] = {
+ {0x3F, 0x0000},
+ {0x30, 0x0349},
+};
+
+static const u16 bt_rf_setting[][2] = {
+ {0x3F, 0x0000},
+ {0x02, 0x0E00},
+ {0x08, 0xEFFF},
+ {0x0A, 0x09FF},
+ {0x11, 0x00B5},
+ {0x13, 0x07C0},
+ {0x14, 0xFDC4},
+ {0x18, 0x2010},
+ {0x19, 0x7956},
+ {0x1B, 0xDFE0},
+ {0x26, 0x7800},
+ {0x2B, 0x007F},
+ {0x2C, 0x600F},
+ {0x2D, 0x007F},
+#ifdef COMBO_WITH_26MHZ
+ {0x2E, 0xCAB3},
+#else
+ {0x2E, 0xCAA3},
+#endif
+ {0x2F, 0x1000},
+ {0x30, 0x0141},
+ {0x37, 0x4244}, //PSK
+ {0x38, 0x4688}, //PSK
+ {0x3B, 0x2122}, //GFSK
+ {0x3C, 0x2355}, //GFSK
+ {0x3F, 0x0001},
+ {0x00, 0xFFFF},
+ {0x01, 0xFFFF}, // bt power
+ {0x02, 0xFFFF},
+ {0x03, 0xFFF7},
+ {0x04, 0xFFFF},
+ {0x05, 0xFFF7},
+ {0x06, 0xFFFF},
+ {0x07, 0xFFF1},
+ {0x08, 0xFFFF},
+ {0x09, 0xFFE1},
+ {0x0A, 0xFFFF},
+ {0x0B, 0xFFE1},
+ {0x39, 0x1208},
+ {0x3F, 0x0000},
+};
+
+static const u16 control_mode_disable[][2] = {
+ {0x3F, 0x0000},
+ {0x30, 0x0141},
+};
+
+static const u16 bt_en[][2] = {
+ {0x3F, 0x0001},
+ {0x28, 0x85A1}, //;bt_en=1
+ {0x3F, 0x0000},
+};
+
+static const u16 bt_disable[][2] = {
+ {0x3F, 0x0001},
+ {0x28, 0x05A1}, //;bt_en=1
+ {0x3F, 0x0000},
+};
+
+// add for pta
+static const u16 rda_5991f_bt_dc_ca_fix_gain[][2] =
+{
+ {0x3f, 0x0000 },
+ {0x30, 0x0141 },
+ {0x30, 0x0140 },
+ {0x30, 0x0141 },
+// {0x30, 0x0341 }, //force gain level to 7 before lna issue fixed
+#ifdef COMBO_WITH_26MHZ
+ {0x2e, 0x8ab3 }, //force gain level to 7 before lna issue fixed
+#else
+ {0x2e, 0x8aa3 }, //force gain level to 7 before lna issue fixed
+#endif
+ {0x3f, 0x0000 },
+};
+// add for pta
+
+// add for pta
+static const u16 rda_5991f_bt_dc_ca_fix_gain_no_wf[][2] =
+{
+ {0x3f, 0x0000 },
+ {0x30, 0x0140 },
+ {0x30, 0x0141 },
+ {0x3f, 0x0000 },
+};
+// add for pta
+
+// add for pta
+static const u16 rda_5991f_bt_force_swtrx[][2] =
+{
+ {0x3f, 0x0000 },
+#ifdef COMBO_WITH_26MHZ
+ {0x2e, 0xcab3 }, //force gain level to 7 before lna issue fixed
+#else
+ {0x2e, 0xcaa3 }, //force gain level to 7 before lna issue fixed
+#endif
+ {0x3f, 0x0000 },
+};
+// add for pta
+
+// add for pta
+static const u16 rda_5991f_bt_no_force_swtrx[][2] =
+{
+ {0x3f, 0x0000 },
+#ifdef COMBO_WITH_26MHZ
+ {0x2e, 0x8ab3 }, //force gain level to 7 before lna issue fixed
+#else
+ {0x2e, 0x8aa3 }, //force gain level to 7 before lna issue fixed
+#endif
+ {0x3f, 0x0000 },
+};
+// add for pta
+
+
+
+static const u16 bt_dc_cal[][2] = {
+ {0x3F, 0x0000},
+ {0x30, 0x0140},
+ {0x30, 0x0141},
+ DELAY_MS(50)
+};
+static int check_wifi_power_on(void)
+{
+ int ret = 0;
+ u16 temp_data;
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001);
+ if (ret)
+ goto err;
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x31, &temp_data);
+ if (ret)
+ goto err;
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000);
+
+ if (temp_data & 0x8000)
+ return 1;
+err:
+ return 0;
+}
+
+static int check_bt_power_on(void)
+{
+ int ret = 0;
+ u16 temp_data;
+
+ ret = i2c_write_1_addr_2_data(rda_bt_rf_client, 0x3f, 0x0001);
+ if (ret)
+ goto err;
+
+ ret = i2c_read_1_addr_2_data(rda_bt_rf_client, 0x28, &temp_data);
+ if (ret)
+ goto err;
+
+ ret = i2c_write_1_addr_2_data(rda_bt_rf_client, 0x3f, 0x0000);
+ if (temp_data & 0x8000)
+ return 1;
+err:
+ return 0;
+}
+
+static int power_on(int isWifi)
+{
+ int ret = 0;
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, pmu_setting);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write pmu_setting succeed!! \n", __func__);
+
+ if (isWifi) { // for wifi
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_en);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write wf_en succeed!! \n", __func__);
+ } else { // for bt
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_en);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write bt_en succeed!! \n", __func__);
+ }
+
+ rda_combo_i2c_unlock();
+ msleep(5);
+ rda_combo_i2c_lock();
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, soft_reset);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write soft_reset succeed!! \n", __func__);
+
+ rda_combo_i2c_unlock();
+ msleep(10);
+ rda_combo_i2c_lock();
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_rf_setting);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write wf_rf_setting succeed!! \n", __func__);
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_rf_setting);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write bt_rf_setting succeed!! \n", __func__);
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_agc_setting);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write wf_agc_setting succeed!! \n",
+ __func__);
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_calibration);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write wf_calibration succeed!! \n", __func__);
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, fix_agc_gain);
+ if(ret)
+ goto power_off;
+ printk(KERN_INFO "%s write fix_agc_gain succeed!! \n", __func__);
+ return 0;
+power_off:
+ if (isWifi) { // for wifi
+ RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_disable);
+ } else {
+ RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_disable);
+ }
+err:
+ return -1;
+}
+
+static int rda_5991f_wifi_debug_en(int enable)
+{
+ u16 temp_data = 0;
+ int ret = 0;
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001);
+ if (ret < 0)
+ return -1;
+ if (enable == 1){
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x28, 0x80a1);
+ if (ret < 0)
+ return -1;
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x39, &temp_data);
+ if (ret < 0)
+ return -1;
+
+ ret =
+ i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x39, temp_data | (1 << 2));
+ if (ret < 0)
+ return -1;
+ }else{
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x28, 0x00a1);
+ if (ret < 0)
+ return -1;
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x39, &temp_data);
+ if (ret < 0)
+ return -1;
+
+ ret =
+ i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x39, temp_data & (~(1 << 2)));
+ if (ret < 0)
+ return -1;
+ }
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000);
+ if (ret < 0)
+ return -1;
+ return ret;
+}
+
+int rda_5991f_wifi_power_on(void)
+{
+ int ret = 0, bt_power_on = 0;
+
+ //if bt is power on wait until it's complete
+ wait_for_completion(&rda_wifi_bt_comp);
+
+ rda_combo_i2c_lock();
+ enable_26m_regulator(CLOCK_WLAN);
+ enable_32k_rtc(CLOCK_WLAN);
+ enable_26m_rtc(CLOCK_WLAN);
+ bt_power_on = check_bt_power_on();
+ printk(KERN_INFO "%s bt_power_on=%d \n", __func__, bt_power_on);
+
+ if (bt_power_on) {
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wf_en);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write wf_en succeed!! \n", __func__);
+
+ //add for pta
+ //handle btswtrx dr
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5991f_bt_no_force_swtrx);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write rda_5991_bt_no_force_swtrx succeed!! \n", __func__);
+ // add for pta
+ rda_combo_i2c_unlock();
+ msleep(5);
+ rda_combo_i2c_lock();
+ } else {
+ ret = power_on(1);
+ if (ret)
+ goto err;
+ }
+
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, control_mode_disable);
+ if (ret)
+ goto power_off;
+ printk(KERN_INFO "%s write control_mode_disable succeed!! \n", __func__);
+ if (rda_combo_wifi_in_test_mode()) {
+ rda_5991f_wifi_debug_en(1);
+ printk(KERN_INFO "%s: IN test mode, switch uart to WIFI succeed!! \n", __func__);
+ }
+
+ rda_combo_i2c_unlock();
+ msleep(100);
+ disable_26m_rtc(CLOCK_WLAN);
+ complete(&rda_wifi_bt_comp);
+ return ret;
+
+power_off:
+ RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_disable);
+err:
+ disable_26m_rtc(CLOCK_WLAN);
+ disable_32k_rtc(CLOCK_WLAN);
+ disable_26m_regulator(CLOCK_WLAN);
+ rda_combo_i2c_unlock();
+ return -1;
+}
+
+int rda_5991f_wifi_power_off(void)
+{
+ int ret = 0, bt_power_on = 0;
+ rda_combo_i2c_lock();
+ bt_power_on = check_bt_power_on();
+ //add for pta
+ if(bt_power_on){
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5991f_bt_force_swtrx);
+ if (ret) {
+ printk(KERN_INFO "%s rda_5991_bt_force_swtrx failed!! \n", __func__);
+ } else {
+ printk(KERN_INFO "%s rda_5991_bt_force_swtrx succeed!! \n", __func__);
+ }
+ }
+ // add for pta
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, wifi_disable);
+ if (ret) {
+ printk(KERN_INFO "%s failed!! \n", __func__);
+ } else {
+ printk(KERN_INFO "%s succeed!! \n", __func__);
+ }
+
+ bt_power_on = check_bt_power_on();
+ if (bt_power_on) {
+ ret = RDA_WRITE_DATA_TO_RF(rda_wifi_rf_client, fix_agc_gain);
+ printk(KERN_INFO "%s write fix_agc_gain succeed!! \n", __func__);
+ }
+ disable_26m_rtc(CLOCK_WLAN);
+ disable_32k_rtc(CLOCK_WLAN);
+ disable_26m_regulator(CLOCK_WLAN);
+ rda_combo_i2c_unlock();
+ return ret;
+}
+
+int rda_5991f_bt_power_on(void)
+{
+ int ret = 0, wifi_power_on = 0;
+
+ //if wifi is power on wait until it's complete
+ wait_for_completion(&rda_wifi_bt_comp);
+
+ rda_combo_i2c_lock();
+ enable_26m_regulator(CLOCK_BT);
+ enable_26m_rtc(CLOCK_BT);
+ enable_32k_rtc(CLOCK_BT);
+
+ wifi_power_on = check_wifi_power_on();
+ printk(KERN_INFO "%s wifi_power_on=%d \n", __func__, wifi_power_on);
+
+ if (wifi_power_on) {
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_en);
+ if (ret)
+ goto err;
+ printk(KERN_INFO "%s write bt_en succeed!! \n", __func__);
+ rda_combo_i2c_unlock();
+ msleep(5);
+ rda_combo_i2c_lock();
+ } else {
+ ret = power_on(0);
+ if (ret)
+ goto err;
+ }
+
+ printk(KERN_INFO "%s succeed!! \n", __func__);
+
+ rda_combo_i2c_unlock();
+ msleep(10);
+ disable_26m_rtc(CLOCK_BT);
+ complete(&rda_wifi_bt_comp);
+ return ret;
+
+err:
+ disable_26m_rtc(CLOCK_BT);
+ disable_32k_rtc(CLOCK_BT);
+ disable_26m_regulator(CLOCK_BT);
+ rda_combo_i2c_unlock();
+ return -1;
+}
+
+int rda_5991f_bt_power_off(void)
+{
+ int ret = 0;
+ rda_combo_i2c_lock();
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, bt_disable);
+ if (ret) {
+ printk(KERN_INFO "%s failed!! \n", __func__);
+ } else {
+ printk(KERN_INFO "%s succeed!! \n", __func__);
+ }
+ disable_26m_rtc(CLOCK_BT);
+ disable_32k_rtc(CLOCK_BT);
+ disable_26m_regulator(CLOCK_BT);
+ rda_combo_i2c_unlock();
+ return ret;
+}
+// add for pta
+static int RDA5991f_bt_dc_cal_fix_gain(void)
+{
+ int ret = 0;
+ int is_wfen;
+
+ if(!rda_bt_rf_client){
+ printk(KERN_INFO "rda_bt_rf_client is NULL!\n");
+ return -1;
+ }
+
+ rda_combo_i2c_lock();
+ is_wfen= check_wifi_power_on();
+ //check the version and make sure this applies to 5991
+ if(rda_wlan_version() == WLAN_VERSION_91_F)
+ {
+ if(is_wfen)
+ {
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5991f_bt_dc_ca_fix_gain);
+ }
+ else
+ {
+ ret = RDA_WRITE_DATA_TO_RF(rda_bt_rf_client, rda_5991f_bt_dc_ca_fix_gain_no_wf);
+ }
+
+ if(ret)
+ goto err;
+ }
+
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***RDA5991f_bt_dc_cal_fix_gain success!!!\n");
+ msleep(200); //200ms
+
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***RDA5991f_bt_dc_cal_fix_gain failed! \n");
+ return -1;
+
+}
+// add for pta
+long rda_5991f_pw_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+
+ switch (cmd) {
+ case RDA_WIFI_POWER_ON_IOCTL:
+ ret = rda_5991f_wifi_power_on();
+ break;
+
+ case RDA_WIFI_POWER_OFF_IOCTL:
+ ret = rda_5991f_wifi_power_off();
+ break;
+
+ case RDA_BT_POWER_ON_IOCTL:
+ ret = rda_5991f_bt_power_on();
+ break;
+
+ case RDA_BT_POWER_OFF_IOCTL:
+ ret = rda_5991f_bt_power_off();
+ break;
+
+ case RDA_WIFI_DEBUG_MODE_IOCTL:
+ {
+ int enable = 0;
+ if(copy_from_user(&enable, (void*)arg, sizeof(int))) {
+ printk(KERN_ERR "copy_from_user enable failed!\n");
+ return -EFAULT;
+ }
+ ret = rda_5991f_wifi_debug_en(enable);
+ break;
+ }
+ // add for pta
+ case RDA_BT_DC_CAL_IOCTL_FIX_5991_LNA_GAIN:
+ ret = RDA5991f_bt_dc_cal_fix_gain();
+ break;
+ // add for pta
+ default:
+ break;
+ }
+
+ printk(KERN_INFO "rda_bt_pw_ioctl cmd=0x%02x \n", cmd);
+ return ret;
+}
+
+int rda_5991f_fm_power_on(void)
+{
+ int ret = 0;
+ u16 temp = 0;
+
+ if (!rda_wifi_rf_client) {
+ printk(KERN_INFO
+ "rda_wifi_rf_client is NULL, rda_fm_power_on failed!\n");
+ return -1;
+ }
+
+ enable_32k_rtc(CLOCK_FM);
+ msleep(8);
+ rda_combo_i2c_lock();
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001); // page down
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ if (rda_wlan_version() == WLAN_VERSION_91_F) {
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x27, &temp); //read 0xA7
+ if (ret < 0) {
+ printk(KERN_INFO "%s() read from address(0x%02x) failed! \n",
+ __func__, 0xA7);
+ goto err;
+ }
+ temp = temp | 0x1; //set bit[0]
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x27, temp); //write back
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0xA7, temp);
+ goto err;
+ }
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x39, &temp); //read 0xB9
+ if (ret < 0) {
+ printk(KERN_INFO "%s() read from address(0x%02x) failed! \n",
+ __func__, 0xB9);
+ goto err;
+ }
+ temp = temp | (0x1 << 15); //set bit[15]
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x39, temp); //write back
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0xB9, temp);
+ goto err;
+ }
+ }
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000); // page up
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ rda_combo_i2c_unlock();
+ return 0;
+
+err:
+ rda_combo_i2c_unlock();
+ disable_32k_rtc(CLOCK_FM);
+ printk(KERN_INFO "***rda_fm_power_on failed! \n");
+ return -1;
+}
+
+int rda_5991f_fm_power_off(void)
+{
+ int ret = 0;
+ u16 temp = 0;
+
+ if (!rda_wifi_rf_client) {
+ printk(KERN_INFO
+ "rda_wifi_rf_client is NULL, rda_fm_power_off failed!\n");
+ return -1;
+ }
+
+ rda_combo_i2c_lock();
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001); // page down
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ if (rda_wlan_version() == WLAN_VERSION_91_F) {
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x27, &temp); //read 0xA7
+ if (ret < 0) {
+ printk(KERN_INFO "%s() read from address(0x%02x) failed! \n",
+ __func__, 0xA7);
+ goto err;
+ }
+ temp = temp & ~(0x1 << 15); //clear bit[0]
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x27, temp); //write back
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0xA7, temp);
+ goto err;
+ }
+ }
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000); // page up
+ if (ret < 0) {
+ printk(KERN_INFO "%s() write address(0x%02x) with value(0x%04x) failed! \n",
+ __func__, 0x3f, 0x0001);
+ goto err;
+ }
+
+ rda_combo_i2c_unlock();
+ disable_32k_rtc(CLOCK_FM);
+ return 0;
+err:
+ rda_combo_i2c_unlock();
+ printk(KERN_INFO "***rda_fm_power_off failed! \n");
+ return -1;
+}
+
diff --git a/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_combo.h b/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_combo.h
new file mode 100755
index 00000000..935e2722
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_combo.h
@@ -0,0 +1,132 @@
+#ifndef __RDA_COMBO_H__
+#define __RDA_COMBO_H__
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/i2c.h>
+#include <linux/wakelock.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <asm-generic/ioctl.h>
+#include <asm/uaccess.h>
+
+//if not RDA Platform,for example, you use Allwinner platform ,don't define RDA_KERNEL_PLATFORM
+//#define RDA_KERNEL_PLATFORM
+#define RDA_BT_IOCTL_MAGIC 'u'
+
+/* bt module */
+#define RDA_BT_POWER_ON_IOCTL _IO(RDA_BT_IOCTL_MAGIC ,0x01)
+#define RDA_BT_RF_INIT_IOCTL _IO(RDA_BT_IOCTL_MAGIC ,0x02)
+#define RDA_BT_DC_CAL_IOCTL _IO(RDA_BT_IOCTL_MAGIC ,0x03)
+#define RDA_BT_RF_SWITCH_IOCTL _IO(RDA_BT_IOCTL_MAGIC ,0x04)
+#define RDA_BT_POWER_OFF_IOCTL _IO(RDA_BT_IOCTL_MAGIC ,0x05)
+#define RDA_BT_EN_CLK _IO(RDA_BT_IOCTL_MAGIC ,0x06)
+#define RDA_BT_DC_DIG_RESET_IOCTL _IO(RDA_BT_IOCTL_MAGIC ,0x07)
+#define RDA_BT_GET_ADDRESS_IOCTL _IO(RDA_BT_IOCTL_MAGIC ,0x08)
+// add for pta
+#define RDA_BT_DC_CAL_IOCTL_FIX_5991_LNA_GAIN _IO(RDA_BT_IOCTL_MAGIC ,0x26)
+// add for pta
+/* wifi module */
+#define RDA_WIFI_POWER_ON_IOCTL _IO(RDA_BT_IOCTL_MAGIC ,0x10)
+#define RDA_WIFI_POWER_OFF_IOCTL _IO(RDA_BT_IOCTL_MAGIC ,0x11)
+#define RDA_WIFI_POWER_SET_TEST_MODE_IOCTL _IO(RDA_BT_IOCTL_MAGIC ,0x12)
+#define RDA_WIFI_POWER_CANCEL_TEST_MODE_IOCTL _IO(RDA_BT_IOCTL_MAGIC ,0x13)
+#define RDA_WIFI_DEBUG_MODE_IOCTL _IO(RDA_BT_IOCTL_MAGIC ,0x14)
+#define RDA_WLAN_COMBO_VERSION _IO(RDA_BT_IOCTL_MAGIC ,0x15)
+#define RDA_COMBO_I2C_OPS _IO(RDA_BT_IOCTL_MAGIC ,0x16)
+
+
+//#define WLAN_USE_CRYSTAL // if use share crystal should close this
+#define WLAN_USE_DCDC // if use LDO mode, should close this
+//#define WLAN_FOR_CTA // if need pass CTA authenticate, should open this define
+
+#define WLAN_USE_CRYSTAL
+//config the correct channel according to schematic diagram
+#define RDA_I2C_CHANNEL (4)
+#define RDA_WIFI_CORE_ADDR (0x13)
+#define RDA_WIFI_RF_ADDR (0x14) //correct add is 0x14
+#define RDA_BT_CORE_ADDR (0x15)
+#define RDA_BT_RF_ADDR (0x16)
+
+#define I2C_MASTER_ACK (1<<0)
+#define I2C_MASTER_RD (1<<4)
+#define I2C_MASTER_STO (1<<8)
+#define I2C_MASTER_WR (1<<12)
+#define I2C_MASTER_STA (1<<16)
+#define RDA_I2C_SPEED 100*1000
+#define WLAN_VERSION_90_D (1)
+#define WLAN_VERSION_90_E (2)
+#define WLAN_VERSION_91 (3)
+#define WLAN_VERSION_91_E (4)
+#define WLAN_VERSION_91_F (5)
+
+#define CLOCK_WLAN (1 << 0)
+#define CLOCK_BT (1 << 1)
+#define CLOCK_FM (1 << 2)
+#define CLOCK_GPS (1 << 3)
+#define CLOCK_MASK_ALL (0x0f)
+
+#define I2C_DELAY_FLAG (0xFFFF)
+#define DELAY_MS(x) {I2C_DELAY_FLAG, x},
+#define RDA_WIFI_RF_I2C_DEVNAME "rda_wifi_rf_i2c"
+#define RDA_WIFI_CORE_I2C_DEVNAME "rda_wifi_core_i2c"
+#define RDA_BT_RF_I2C_DEVNAME "rda_bt_rf_i2c"
+#define RDA_BT_CORE_I2C_DEVNAME "rda_bt_core_i2c"
+
+extern struct i2c_client * rda_wifi_core_client;
+extern struct i2c_client * rda_wifi_rf_client;
+extern struct i2c_client * rda_bt_core_client;
+extern struct i2c_client * rda_bt_rf_client;
+extern struct completion rda_wifi_bt_comp;
+
+
+int i2c_write_1_addr_2_data(struct i2c_client* client, const u8 addr, const u16 data);
+int i2c_read_1_addr_2_data(struct i2c_client* client, const u8 addr, u16* data);
+int rda_write_data_to_rf(struct i2c_client* client, const u16 (*data)[2], u32 count);
+#define RDA_WRITE_DATA_TO_RF(CLIENT, ARRAY_DATA) rda_write_data_to_rf(CLIENT, ARRAY_DATA, sizeof(ARRAY_DATA)/sizeof(ARRAY_DATA[0]))
+
+void enable_26m_regulator(u8 mask);
+void disable_26m_regulator(u8 mask);
+void enable_32k_rtc(u8 mask);
+void disable_32k_rtc(u8 mask);
+void enable_26m_rtc(u8 mask);
+void disable_26m_rtc(u8 mask);
+
+void rda_combo_i2c_lock(void);
+void rda_combo_i2c_unlock(void);
+
+u32 rda_wlan_version(void);
+unsigned char rda_combo_wifi_in_test_mode(void);
+
+int rda_5990_wifi_power_off(void);
+int rda_5990_wifi_power_on(void);
+int rda_5990_bt_power_on(void);
+int rda_5990_bt_power_off(void);
+int rda_5990_fm_power_on(void);
+int rda_5990_fm_power_off(void);
+long rda_5990_pw_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+
+int rda_5991_wifi_power_on(void);
+int rda_5991_wifi_power_off(void);
+int rda_5991_bt_power_on(void);
+int rda_5991_bt_power_off(void);
+int rda_5991_fm_power_on(void);
+int rda_5991_fm_power_off(void);
+long rda_5991_pw_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+int rda_5991e_wifi_power_on(void);
+int rda_5991f_wifi_power_on(void);
+int rda_5991e_wifi_power_off(void);
+int rda_5991f_wifi_power_off(void);
+int rda_5991e_bt_power_on(void);
+int rda_5991f_bt_power_on(void);
+int rda_5991e_bt_power_off(void);
+int rda_5991f_bt_power_off(void);
+int rda_5991e_fm_power_on(void);
+int rda_5991f_fm_power_on(void);
+int rda_5991e_fm_power_off(void);
+int rda_5991f_fm_power_off(void);
+long rda_5991e_pw_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+long rda_5991f_pw_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+
+#endif
+
diff --git a/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_combo_power_main.c b/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_combo_power_main.c
new file mode 100755
index 00000000..a54ffead
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_combo_power_ctrl/rda_combo_power_main.c
@@ -0,0 +1,1282 @@
+/* ----------------------------------------------------------------------- *
+ *
+ This file created by albert RDA Inc
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/rtc.h> /* get the user-level API */
+#include <linux/bcd.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_fs_sb.h>
+#include <linux/nfs_mount.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/tty.h>
+#include <linux/syscalls.h>
+#include <asm/termbits.h>
+#include <linux/serial.h>
+#include <linux/platform_device.h>
+#include <linux/rfkill.h>
+//#include <mach/iomap.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+//#include <linux/clk.h>
+//#include <mach/rda_clk_name.h>
+//#include <mach/board.h>
+#include "rda_combo.h"
+#include <mach/gpio.h>
+//#include <mach/sys_config.h>
+#include <mach/hardware.h>//WMT_MMAP_OFFSET
+#include <linux/pwm.h> //for pwm
+#include <mach/io.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+void set_wifi_name(char * name);
+static void enable_pwm1_32KHz(int enable);
+static struct mutex i2c_rw_lock;
+static struct rfkill *wlan_rfkill = NULL;
+static struct rfkill *bt_rfkill = NULL;
+static struct platform_device *platform_device;
+static unsigned short wlan_version = 0;
+static struct wake_lock rda_combo_wake_lock;
+static struct delayed_work rda_combo_sleep_worker;
+static struct work_struct rda_bt_interrupt;
+struct i2c_client *rda_wifi_core_client = NULL;
+struct i2c_client *rda_wifi_rf_client = NULL;
+struct i2c_client *rda_bt_core_client = NULL;
+struct i2c_client *rda_bt_rf_client = NULL;
+struct completion rda_wifi_bt_comp;
+struct regulator *combo_reg;
+
+static unsigned int bt_host_wake=9;
+static unsigned int bt_host_wake_irq;
+
+static u8 isBigEnded = 0;
+static u8 wifi_in_test_mode = 0;
+#ifdef RDA_KERNEL_PLATFORM
+static u8 clock_mask_32k = 0;
+static u8 clock_mask_26m = 0;
+static u8 regulator_mask = 0;
+static struct clk * clk32k = NULL;
+static struct clk * clk26m = NULL;
+#endif
+void enable_26m_regulator(u8 mask)
+{
+ #ifdef RDA_KERNEL_PLATFORM
+ if (regulator_mask & CLOCK_MASK_ALL) {
+ } else {
+ regulator_enable(combo_reg);
+ }
+ regulator_mask |= mask;
+ #endif
+
+}
+void disable_26m_regulator(u8 mask)
+{
+ #ifdef RDA_KERNEL_PLATFORM
+ if (regulator_mask & mask) {
+ regulator_mask &= ~mask;
+ if (regulator_mask & CLOCK_MASK_ALL) {
+ } else {
+ regulator_disable(combo_reg);
+ }
+ }
+ #endif
+}
+void enable_32k_rtc(u8 mask)
+{
+ #ifdef RDA_KERNEL_PLATFORM
+ if (clock_mask_32k & CLOCK_MASK_ALL) {
+
+ } else {
+ clk_prepare_enable(clk32k);
+ }
+ clock_mask_32k |= mask;
+ #endif
+}
+
+void disable_32k_rtc(u8 mask)
+{
+ #ifdef RDA_KERNEL_PLATFORM
+ if (clock_mask_32k & mask) {
+ clock_mask_32k &= ~mask;
+ if (clock_mask_32k & CLOCK_MASK_ALL) {
+
+ } else {
+ clk_disable_unprepare(clk32k);
+ }
+ }
+ #endif
+}
+
+void enable_26m_rtc(u8 mask)
+{
+ #ifdef RDA_KERNEL_PLATFORM
+ if (clock_mask_26m & CLOCK_MASK_ALL) {
+
+ } else {
+ clk_prepare_enable(clk26m);
+ }
+ clock_mask_26m |= mask;
+ #endif
+}
+
+void disable_26m_rtc(u8 mask)
+{
+ #ifdef RDA_KERNEL_PLATFORM
+ if (clock_mask_26m & mask) {
+ clock_mask_26m &= ~mask;
+ if (clock_mask_26m & CLOCK_MASK_ALL) {
+
+ } else {
+ clk_disable_unprepare(clk26m);
+ }
+ }
+ #endif
+}
+
+int i2c_write_1_addr_2_data(struct i2c_client *client, const u8 addr,
+ const u16 data)
+{
+ unsigned char tmp_data[3];
+ int ret = 0;
+ int retry = 3;
+
+ if (!isBigEnded) {
+ tmp_data[0] = addr;
+ tmp_data[1] = data >> 8;
+ tmp_data[2] = data >> 0;
+ } else {
+ tmp_data[0] = addr;
+ tmp_data[1] = data >> 0;
+ tmp_data[2] = data >> 8;
+ }
+
+ while (retry--) {
+ ret = i2c_master_send(client, (char *)tmp_data, 3);
+ if (ret >= 0) {
+ break;
+ }
+ }
+
+ if (ret < 0) {
+ printk(KERN_INFO
+ "***i2c_write_1_addr_2_data send:0x%X err:%d bigendia: %d \n",
+ addr, ret, isBigEnded);
+ return -1;
+ } else {
+ return 0;
+ }
+
+}
+
+int i2c_read_1_addr_2_data(struct i2c_client *client, const u8 addr, u16 * data)
+{
+ unsigned char tmp_data[2];
+ int ret = 0;
+ int retry = 3;
+
+ while (retry--) {
+ ret = i2c_master_send(client, (char *)&addr, 1);
+ if (ret >= 0) {
+ break;
+ }
+ }
+
+ if (ret < 0) {
+ printk(KERN_INFO "***i2c_read_1_addr_2_data send:0x%X err:%d\n",
+ addr, ret);
+ return -1;
+ }
+
+ retry = 3;
+ while (retry--) {
+ ret = i2c_master_recv(client, tmp_data, 2);
+ if (ret >= 0) {
+ break;
+ }
+ }
+
+ if (ret < 0) {
+ printk(KERN_INFO "***i2c_read_1_addr_2_data send:0x%X err:%d\n",
+ addr, ret);
+ return -1;
+ }
+
+ if (!isBigEnded) {
+ *data = (tmp_data[0] << 8) | tmp_data[1];
+ } else {
+ *data = (tmp_data[1] << 8) | tmp_data[0];
+ }
+ return 0;
+}
+
+static void wlan_read_version_from_chip(void)
+{
+ int ret;
+ u16 project_id = 0, chip_version = 0;
+
+ if (wlan_version != 0 || !rda_wifi_rf_client)
+ return;
+
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0001);
+ if (ret)
+ goto err;
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x21, &chip_version);
+ if (ret)
+ goto err;
+
+ ret = i2c_read_1_addr_2_data(rda_wifi_rf_client, 0x20, &project_id);
+ if (ret)
+ goto err;
+
+ if (project_id == 0x5990) {
+ if (chip_version == 0x47)
+ wlan_version = WLAN_VERSION_90_D;
+ else if (chip_version == 0x44 || chip_version == 0x45)
+ wlan_version = WLAN_VERSION_90_E;
+ } else if (project_id == 0x5991) {
+ set_wifi_name("rda5991.ko");
+ if (chip_version == 0x44)
+ wlan_version = WLAN_VERSION_91;
+ else if(chip_version == 0x45)
+ wlan_version = WLAN_VERSION_91_E;
+ else if(chip_version == 0x46)
+ wlan_version = WLAN_VERSION_91_F;
+ }
+
+ printk("read project_id:%x version:%x wlan_version:%x \n", project_id,
+ chip_version, wlan_version);
+err:
+ ret = i2c_write_1_addr_2_data(rda_wifi_rf_client, 0x3f, 0x0000);
+ return;
+
+}
+
+int rda_write_data_to_rf(struct i2c_client *client, const u16(*data)[2],
+ u32 count)
+{
+ int ret = 0;
+ u32 i = 0;
+
+ for (i = 0; i < count; i++) {
+ if (data[i][0] == I2C_DELAY_FLAG) {
+ msleep(data[i][2]);
+ continue;
+ }
+ ret = i2c_write_1_addr_2_data(client, data[i][0], data[i][1]);
+ if (ret < 0)
+ break;
+ }
+ return ret;
+}
+
+u32 rda_wlan_version(void)
+{
+ if(wlan_version == 0)
+ wlan_read_version_from_chip();
+ return wlan_version;
+}
+
+static int rda_wifi_rf_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int result = 0;
+
+ rda_wifi_rf_client = client;
+ printk("rda_wifi_rf_probe \n");
+ return result;
+}
+
+static int rda_wifi_rf_remove(struct i2c_client *client)
+{
+ return 0;
+}
+
+static int rda_wifi_rf_detect(struct i2c_client *client,
+ struct i2c_board_info *info)
+{
+ strcpy(info->type, RDA_WIFI_RF_I2C_DEVNAME);
+ return 0;
+}
+
+static const struct i2c_device_id wifi_rf_i2c_id[] =
+ { {RDA_WIFI_RF_I2C_DEVNAME, RDA_I2C_CHANNEL}, {} };
+static struct i2c_driver rda_wifi_rf_driver = {
+ //.class = I2C_CLASS_HWMON,
+ .probe = rda_wifi_rf_probe,
+ .remove = rda_wifi_rf_remove,
+ .detect = rda_wifi_rf_detect,
+ .driver.name = RDA_WIFI_RF_I2C_DEVNAME,
+ .id_table = wifi_rf_i2c_id,
+};
+
+static int rda_wifi_core_detect(struct i2c_client *client,
+ struct i2c_board_info *info)
+{
+ strcpy(info->type, RDA_WIFI_CORE_I2C_DEVNAME);
+ return 0;
+}
+
+static int rda_wifi_core_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int result = 0;
+
+ rda_wifi_core_client = client;
+ printk("rda_wifi_core_probe \n");
+ return result;
+}
+
+
+static int rda_suspend(struct i2c_client *client, pm_message_t state)
+{
+
+ return 0;
+}
+
+static int rda_resume(struct i2c_client *client)
+{
+ enable_pwm1_32KHz(1);
+ return 0;
+}
+
+
+static int rda_wifi_core_remove(struct i2c_client *client)
+{
+ return 0;
+}
+
+int rda_wifi_power_off(void)
+{
+ if (wlan_version == WLAN_VERSION_90_D
+ || wlan_version == WLAN_VERSION_90_E)
+ return rda_5990_wifi_power_off();
+ else if (wlan_version == WLAN_VERSION_91)
+ return rda_5991_wifi_power_off();
+ else if (wlan_version == WLAN_VERSION_91_E)
+ return rda_5991e_wifi_power_off();
+ else if (wlan_version == WLAN_VERSION_91_F)
+ return rda_5991f_wifi_power_off();
+ return 0;
+}
+
+int rda_wifi_power_on(void)
+{
+ wlan_read_version_from_chip();
+ if (wlan_version == WLAN_VERSION_90_D
+ || wlan_version == WLAN_VERSION_90_E) {
+ return rda_5990_wifi_power_on();
+ } else if (wlan_version == WLAN_VERSION_91)
+ return rda_5991_wifi_power_on();
+ else if (wlan_version == WLAN_VERSION_91_E)
+ return rda_5991e_wifi_power_on();
+ else if (wlan_version == WLAN_VERSION_91_F)
+ return rda_5991f_wifi_power_on();
+ return 0;
+}
+
+static void rda_wifi_shutdown(struct i2c_client *client)
+{
+ printk("rda_wifi_shutdown \n");
+ rda_wifi_power_off();
+}
+
+static const struct i2c_device_id wifi_core_i2c_id[] =
+ { {RDA_WIFI_CORE_I2C_DEVNAME, RDA_I2C_CHANNEL}, {} };
+static struct i2c_driver rda_wifi_core_driver = {
+ //.class = I2C_CLASS_HWMON,
+ .probe = rda_wifi_core_probe,
+ .remove = rda_wifi_core_remove,
+ .detect = rda_wifi_core_detect,
+ .shutdown = rda_wifi_shutdown,
+ .suspend = rda_suspend,
+ .resume = rda_resume,
+ .driver.name = RDA_WIFI_CORE_I2C_DEVNAME,
+ .id_table = wifi_core_i2c_id,
+};
+
+static int rda_bt_rf_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int result = 0;
+
+ rda_bt_rf_client = client;
+ printk("rda_bt_rf_probe \n");
+ return result;
+}
+
+static int rda_bt_rf_remove(struct i2c_client *client)
+{
+ rda_bt_rf_client = NULL;
+ return 0;
+}
+
+static int rda_bt_rf_detect(struct i2c_client *client,
+ struct i2c_board_info *info)
+{
+ strcpy(info->type, RDA_BT_RF_I2C_DEVNAME);
+ return 0;
+}
+
+static const struct i2c_device_id bt_rf_i2c_id[] =
+ { {RDA_BT_RF_I2C_DEVNAME, RDA_I2C_CHANNEL}, {} };
+static struct i2c_driver rda_bt_rf_driver = {
+ //.class = I2C_CLASS_HWMON,
+ .probe = rda_bt_rf_probe,
+ .remove = rda_bt_rf_remove,
+ .detect = rda_bt_rf_detect,
+ .driver.name = RDA_BT_RF_I2C_DEVNAME,
+ .id_table = bt_rf_i2c_id,
+};
+
+static int rda_bt_core_detect(struct i2c_client *client,
+ struct i2c_board_info *info)
+{
+ strcpy(info->type, RDA_BT_CORE_I2C_DEVNAME);
+ return 0;
+}
+
+void rda_combo_set_wake_lock(void);
+
+#ifdef CONFIG_BLUEZ_SUPPORT
+extern void hci_bt_wakeup_host(void);
+#endif
+
+
+static irqreturn_t rda_bt_host_wake_eirq_handler(int irq, void *dev_id)
+{
+
+ int pin_state;
+
+ if(!is_gpio_irqenable(bt_host_wake) || !gpio_irqstatus(bt_host_wake))
+ return IRQ_NONE;
+
+ pin_state = gpio_direction_input(bt_host_wake);
+
+
+ if(pin_state == 0)
+ {
+ printk("irq_handler\n");
+
+
+#ifdef CONFIG_BLUEZ_SUPPORT
+ hci_bt_wakeup_host();
+
+#endif
+ //int *p=NULL,aaa;
+ //aaa=*p+3;
+ printk("rda_bt_host_wake_eirq_handler\n");
+ //rda_combo_set_wake_lock();
+ schedule_work(&rda_bt_interrupt);
+
+
+
+ }
+ else
+ {
+ printk("fake interruption:%d\n",pin_state);
+ }
+
+
+
+ return IRQ_HANDLED;
+}
+
+int aaaa;
+//tip,for different platform, you must check how to realize a interrupt.
+int bt_register_host_wake_irq(void *dev)
+{
+ int ret = 0;
+#ifdef ALLWINNER
+ script_item_u val;
+ script_item_value_type_e type;
+
+ type = script_get_item("wifi_para", "rda5990_bt_host_wake", &val);
+ if (SCIRPT_ITEM_VALUE_TYPE_PIO!=type)
+ {
+ printk("get RDA rda5990_bt_host_wake gpio failed\n");
+ goto err;
+
+ }
+ else
+ bt_host_wake = val.gpio.gpio;
+
+ bt_host_wake_irq = gpio_to_irq(bt_host_wake);
+ if (IS_ERR_VALUE(bt_host_wake_irq)) {
+ pr_warn("map gpio [%d] to virq failed, errno = %d\n",
+ bt_host_wake, bt_host_wake_irq);
+ ret = -1;
+ goto err;
+ }
+ ret = devm_request_irq(dev, bt_host_wake_irq, rda_bt_host_wake_eirq_handler,
+ IRQF_TRIGGER_RISING, "rda_combo_bt", NULL);
+ if (IS_ERR_VALUE(ret)) {
+ pr_warn("request virq %d failed, errno = %d\n",
+ bt_host_wake_irq, ret);
+ goto err;
+ }
+
+ enable_irq(bt_host_wake_irq);
+
+
+#endif
+ bt_host_wake_irq = IRQ_GPIO;
+ wmt_gpio_mask_irq(bt_host_wake);
+ wmt_gpio_set_irq_type(bt_host_wake,IRQ_TYPE_LEVEL_LOW);
+
+ /*enable pull down*/
+ wmt_gpio_setpull(bt_host_wake,WMT_GPIO_PULL_UP);
+
+ ret = request_irq(bt_host_wake_irq, rda_bt_host_wake_eirq_handler, IRQF_SHARED, "rda_5991", (void*)&aaaa);
+ if (ret){
+ printk("Request IRQ failed!ERRNO:%d.", ret);
+ goto err;
+ }
+
+
+
+ return 0;
+ err:
+ return -1;
+}
+
+int bt_unregister_host_wake_irq(void *dev)
+{
+ if(bt_host_wake_irq > 0)
+ {
+ //disable_irq_nosync(bt_host_wake_irq);
+ //devm_free_irq(dev, bt_host_wake_irq, NULL);
+ free_irq(IRQ_GPIO, (void*)&aaaa);
+ bt_host_wake_irq = -1;
+ }
+ return 0;
+
+}
+
+//tip end
+
+
+static int rda_bt_core_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int result = 0;
+ rda_bt_core_client = client;
+ printk("rda_bt_core_probe\n");
+ return result;
+}
+
+static int rda_bt_core_remove(struct i2c_client *client)
+{
+ return 0;
+}
+
+static const struct i2c_device_id bt_core_i2c_id[] =
+ { {RDA_BT_CORE_I2C_DEVNAME, RDA_I2C_CHANNEL}, {} };
+static struct i2c_driver rda_bt_core_driver = {
+ //.class = I2C_CLASS_HWMON,
+ .probe = rda_bt_core_probe,
+ .remove = rda_bt_core_remove,
+ .detect = rda_bt_core_detect,
+ .driver.name = RDA_BT_CORE_I2C_DEVNAME,
+ .id_table = bt_core_i2c_id,
+};
+
+#ifdef CONFIG_BT_RANDADDR
+extern void bt_get_random_address(char *buf);
+#endif
+
+
+static int rda_combo_i2c_ops(unsigned long arg)
+{
+ int ret = 0, argc = 0;
+ u8 cmd[256], *argv[5], *pos, rw = 0, addr = 0, pageup = 0;
+ struct i2c_client * i2Client = NULL;
+ u16 data = 0;
+ void __user *argp = (void __user *)arg;
+
+ if(copy_from_user(cmd, argp, 256))
+ return -EFAULT;
+ else{
+ pos = cmd;
+ while (*pos != '\0') {
+ if (*pos == '\n') {
+ *pos = '\0';
+ break;
+ }
+ pos++;
+ }
+ argc = 0;
+ pos = cmd;
+ for (;;) {
+ while (*pos == ' ')
+ pos++;
+ if (*pos == '\0')
+ break;
+ argv[argc] = pos;
+ argc++;
+ if (argc == 5)
+ break;
+ if (*pos == '"') {
+ char *pos2 = strrchr(pos, '"');
+ if (pos2)
+ pos = pos2 + 1;
+ }
+ while (*pos != '\0' && *pos != ' ')
+ pos++;
+ if (*pos == ' ')
+ *pos++ = '\0';
+ }
+ }
+
+ if(!memcmp(argv[1], "bt", 2)){
+ i2Client = rda_bt_rf_client;
+ }
+ else
+ i2Client = rda_wifi_rf_client;
+
+ if (kstrtou8(argv[3], 0, &addr))
+ return -EINVAL;
+
+ if(*(argv[2]) == 'r'){
+ rw = 0;
+ }
+ else{
+ rw = 1;
+ if (kstrtou16(argv[4], 0, &data))
+ return -EINVAL;
+ }
+
+ if(addr >= 0x80){
+ i2c_write_1_addr_2_data(i2Client, 0x3F, 0x0001);
+ addr -= 0x80;
+ pageup = 1;
+ }
+
+ if(*(argv[2]) == 'r'){
+ int read_data = 0;
+ i2c_read_1_addr_2_data(i2Client, addr, &data);
+ read_data = (int)data;
+
+ if(copy_to_user(argp, &read_data, sizeof(int)))
+ ret = -EFAULT;
+ }
+ else
+ i2c_write_1_addr_2_data(i2Client, addr, data);
+
+ if(pageup == 1)
+ i2c_write_1_addr_2_data(i2Client, 0x3F, 0x0000);
+
+ printk("wlan: %s %s %s %s :0x%x \n", argv[0], argv[1], argv[2], argv[3], data);
+ return ret;
+}
+
+
+static long rda_combo_pw_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = 0;
+ void __user *argp = (void __user *)arg;
+
+ switch (cmd) {
+
+ case RDA_WLAN_COMBO_VERSION:
+ {
+ u32 version = rda_wlan_version();
+ if (copy_to_user(argp, &version, sizeof(version)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case RDA_WIFI_POWER_SET_TEST_MODE_IOCTL:
+ wifi_in_test_mode = 1;
+ printk("****set rda wifi in test mode \n");
+ break;
+
+ case RDA_WIFI_POWER_CANCEL_TEST_MODE_IOCTL:
+ wifi_in_test_mode = 0;
+ printk("****set rda wifi in normal mode \n");
+ break;
+
+ case RDA_BT_GET_ADDRESS_IOCTL:
+ {
+ u8 bt_addr[6] = { 0 };
+
+#ifdef CONFIG_BT_RANDADDR
+ bt_get_random_address(bt_addr);
+#endif
+ printk(KERN_INFO
+ "rdabt address[0x%x]:[0x%x]:[0x%x]:[0x%x]:[0x%x]:[0x%x].\n",
+ bt_addr[0], bt_addr[1], bt_addr[2], bt_addr[3],
+ bt_addr[4], bt_addr[5]);
+ //tmp for bt adr
+ if (copy_to_user(argp, &bt_addr[0], sizeof(bt_addr))) {
+ ret = -EFAULT;
+ }
+ }
+ break;
+
+ case RDA_COMBO_I2C_OPS:
+ {
+ ret = rda_combo_i2c_ops(arg);
+ }
+ break;
+
+ case RDA_WIFI_POWER_ON_IOCTL:
+ case RDA_BT_POWER_ON_IOCTL:
+ wlan_read_version_from_chip();
+ default:
+ if (wlan_version == WLAN_VERSION_90_D
+ || wlan_version == WLAN_VERSION_90_E) {
+ ret = rda_5990_pw_ioctl(file, cmd, arg);
+ } else if (wlan_version == WLAN_VERSION_91)
+ ret = rda_5991_pw_ioctl(file, cmd, arg);
+ else if (wlan_version == WLAN_VERSION_91_E)
+ ret = rda_5991e_pw_ioctl(file, cmd, arg);
+ else if (wlan_version == WLAN_VERSION_91_F)
+ ret = rda_5991f_pw_ioctl(file, cmd, arg);
+ break;
+ }
+ return ret;
+}
+
+static int rda_combo_major;
+static struct class *rda_combo_class = NULL;
+static const struct file_operations rda_combo_operations = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = rda_combo_pw_ioctl,
+ .release = NULL
+};
+
+void rda_combo_sleep_worker_task(struct work_struct *work)
+{
+ printk("---rda_combo_sleep_worker_task end \n");
+ wake_unlock(&rda_combo_wake_lock);
+}
+//add by LA
+void rda_bt_interrupt_task(struct work_struct *work)
+{
+ printk("---rda_bt_interrupt_task \n");
+ rda_combo_set_wake_lock();
+ printk("---rda_bt_interrupt_task end \n");
+
+
+}
+void rda_combo_set_wake_lock(void)
+{
+ printk("rda_combo_set_wake_lock\n");
+ wake_lock(&rda_combo_wake_lock);
+ cancel_delayed_work(&rda_combo_sleep_worker);
+ schedule_delayed_work(&rda_combo_sleep_worker, 6 * HZ);
+ printk("rda_combo_set_wake_lock end \n");
+}
+
+static struct platform_driver platform_driver = {
+ .driver = {
+ .name = "rda_combo_rfkill_device",
+ .owner = THIS_MODULE,
+ }
+};
+
+static int wlan_rfkill_set(void *data, bool blocked)
+{
+ printk("wlan_rfkill_set %d \n", blocked);
+ if (blocked) {
+ rda_wifi_power_off();
+ } else {
+ rda_wifi_power_on();
+ }
+ return 0;
+}
+
+static int rda_bt_power_off(void)
+{
+ if (wlan_version == WLAN_VERSION_90_D
+ || wlan_version == WLAN_VERSION_90_E) {
+ return rda_5990_bt_power_off();
+ } else if (wlan_version == WLAN_VERSION_91)
+ return rda_5991_bt_power_off();
+ else if (wlan_version == WLAN_VERSION_91_E)
+ return rda_5991e_bt_power_off();
+ else if (wlan_version == WLAN_VERSION_91_F)
+ return rda_5991f_bt_power_off();
+ return 0;
+}
+
+static int rda_bt_power_on(void)
+{
+ wlan_read_version_from_chip();
+ if (wlan_version == WLAN_VERSION_90_D
+ || wlan_version == WLAN_VERSION_90_E) {
+ return rda_5990_bt_power_on();
+ } else if (wlan_version == WLAN_VERSION_91)
+ return rda_5991_bt_power_on();
+ else if (wlan_version == WLAN_VERSION_91_E)
+ return rda_5991e_bt_power_on();
+ else if (wlan_version == WLAN_VERSION_91_F)
+ return rda_5991f_bt_power_on();
+ return 0;
+}
+
+static const struct rfkill_ops wlan_rfkill_ops = {
+ .set_block = wlan_rfkill_set,
+};
+
+static int bt_rfkill_set(void *data, bool blocked)
+{
+ printk("bt_rfkill_set %d \n", blocked);
+ if (blocked) {
+ rda_bt_power_off();
+ } else {
+ rda_bt_power_on();
+ }
+ return 0;
+}
+
+static const struct rfkill_ops bt_rfkill_ops = {
+ .set_block = bt_rfkill_set,
+};
+
+
+
+
+//configure pwm1 pin
+static void config_pwm1_pin(int enable)
+{
+ int val;
+ if(enable) {
+ val = readb(0xd8110200+WMT_MMAP_OFFSET);
+ val &= ~(1 << 7);
+ writeb(val, 0xd8110200+WMT_MMAP_OFFSET);
+ }else{
+ val = readb(0xd8110200+WMT_MMAP_OFFSET);
+ val |= (1 << 7);
+ writeb(val, 0xd8110200+WMT_MMAP_OFFSET);
+ }
+}
+
+struct pwm_device * g_pwm =NULL;
+
+static void enable_pwm1_32KHz(int enable)
+{
+ if(enable) {
+ //pwm_config(g_pwm, 15625, 31250);// configuration output 32KHZ
+ pwm_config(g_pwm, 15258, 30517);// configuration output 32768HZ
+ pwm_enable(g_pwm);
+ config_pwm1_pin(0x01);
+ printk("enable 32khz output\n");
+ }else{
+ pwm_disable(g_pwm);
+ config_pwm1_pin(0x00);
+ printk("disable 32khz output\n");
+ }
+}
+
+static struct i2c_client *rda_wifi_core=NULL;
+static struct i2c_client *rda_wifi_rf=NULL;
+static struct i2c_client *rda_bt_core=NULL;
+static struct i2c_client *rda_bt_rf=NULL;
+
+
+#define RDA_WIFI_CORE_ADDR (0x13)
+#define RDA_WIFI_RF_ADDR (0x14)
+#define RDA_BT_CORE_ADDR (0x15)
+#define RDA_BT_RF_ADDR (0x16)
+#define RDA_WIFI_RF_I2C_DEVNAME "rda_wifi_rf_i2c"
+#define RDA_WIFI_CORE_I2C_DEVNAME "rda_wifi_core_i2c"
+#define RDA_BT_RF_I2C_DEVNAME "rda_bt_rf_i2c"
+#define RDA_BT_CORE_I2C_DEVNAME "rda_bt_core_i2c"
+
+
+
+struct i2c_board_info rda_wifi_core_i2c_board_info = {
+ .type = RDA_WIFI_CORE_I2C_DEVNAME,
+ .flags = 0x00,
+ .addr = RDA_WIFI_CORE_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+struct i2c_board_info rda_wifi_rf_i2c_board_info = {
+ .type = RDA_WIFI_RF_I2C_DEVNAME,
+ .flags = 0x00,
+ .addr = RDA_WIFI_RF_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+struct i2c_board_info rda_bt_core_i2c_board_info = {
+ .type = RDA_BT_CORE_I2C_DEVNAME,
+ .flags = 0x00,
+ .addr = RDA_BT_CORE_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+struct i2c_board_info rda_bt_rf_i2c_board_info = {
+ .type = RDA_BT_RF_I2C_DEVNAME,
+ .flags = 0x00,
+ .addr = RDA_BT_RF_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+
+static int rda_i2c_register_device (struct i2c_board_info *ts_i2c_bi,struct i2c_client **l_client)
+{
+ struct i2c_adapter *adapter = NULL;
+ adapter = i2c_get_adapter(4);
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+
+ *l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (*l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+
+ i2c_put_adapter(adapter);
+
+ return 0;
+}
+
+static void rda_i2c_unregister_device(struct i2c_client *l_client)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+
+
+int rda_combo_power_ctrl_init(void)
+{
+ int ret = 0;
+ int n;
+
+ ret = rda_i2c_register_device(&rda_wifi_core_i2c_board_info,&rda_wifi_core);
+ if(ret!=0)
+ return -1;
+ rda_i2c_register_device(&rda_wifi_rf_i2c_board_info,&rda_wifi_rf);
+ rda_i2c_register_device(&rda_bt_core_i2c_board_info,&rda_bt_core);
+ rda_i2c_register_device(&rda_bt_rf_i2c_board_info,&rda_bt_rf);
+
+
+
+
+
+
+
+
+
+ printk("begint to pwm request\n");
+ g_pwm = pwm_request(0x01,"rda5991 bluetooth 32KHz");
+ if(!g_pwm){
+ printk("can not request pwm1 for bluetooth mtk6622\n");
+ return -1;
+ }
+
+
+ if (gpio_request(bt_host_wake, "rda5991_intr") < 0) {
+ printk("gpio(%d) rda5991_intr gpio request fail\n", bt_host_wake);
+ return -1;
+ }
+ enable_pwm1_32KHz(1);
+
+
+
+
+
+
+
+
+ printk("rda_combo_power_ctrl_init begin\n");
+ if (i2c_add_driver(&rda_wifi_core_driver)) {
+ printk("rda_wifi_core_driver failed!\n");
+ ret = -ENODEV;
+ return ret;
+ }
+
+ if (i2c_add_driver(&rda_wifi_rf_driver)) {
+ printk("rda_wifi_rf_driver failed!\n");
+ ret = -ENODEV;
+ return ret;
+ }
+
+ if (i2c_add_driver(&rda_bt_core_driver)) {
+ printk("rda_bt_core_driver failed!\n");
+ ret = -ENODEV;
+ return ret;
+ }
+
+ if (i2c_add_driver(&rda_bt_rf_driver)) {
+ printk("rda_bt_rf_driver failed!\n");
+ ret = -ENODEV;
+ return ret;
+ }
+
+ rda_combo_major = XENVBD_MAJOR;
+
+
+ n= register_chrdev(rda_combo_major, "rdacombo_power_ctrl", &rda_combo_operations);
+ if (n < 0) {
+ printk(KERN_INFO "register rdabt_power_ctrl failed!!! \n");
+ return rda_combo_major;
+ }else
+ printk("rda_combo_major %d\n",rda_combo_major);
+
+ rda_combo_class = class_create(THIS_MODULE, "rda_combo");
+ if (IS_ERR(rda_combo_class)) {
+ unregister_chrdev(rda_combo_major, "rdacombo_power_ctrl");
+ return PTR_ERR(rda_combo_class);
+ }
+
+ device_create(rda_combo_class, NULL, MKDEV(rda_combo_major, 0), NULL,
+ "rdacombo");
+ #ifdef RDA_KERNEL_PLATFORM
+ combo_reg = regulator_get(NULL, LDO_BT);
+ if (IS_ERR(combo_reg)) {
+ printk(KERN_INFO "could not find regulator devices\n");
+ ret = PTR_ERR(combo_reg);
+ goto fail_platform_driver;
+ }
+ #endif
+ {
+ unsigned char *temp = NULL;
+ unsigned short testData = 0xffee;
+ temp = (unsigned char *)&testData;
+ if (*temp == 0xee)
+ isBigEnded = 0;
+ else
+ isBigEnded = 1;
+ }
+
+ INIT_DELAYED_WORK(&rda_combo_sleep_worker, rda_combo_sleep_worker_task);
+ wake_lock_init(&rda_combo_wake_lock, WAKE_LOCK_SUSPEND,
+ "RDA_sleep_worker_wake_lock");
+ //add by RDA
+ INIT_WORK(&rda_bt_interrupt,rda_bt_interrupt_task);
+
+ mutex_init(&i2c_rw_lock);
+
+ ret = platform_driver_register(&platform_driver);
+ if (ret)
+ goto fail_platform_driver;
+
+ platform_device = platform_device_alloc("rda_combo_rfkill_device", -1);
+ if (!platform_device) {
+ ret = -ENOMEM;
+ } else
+ ret = platform_device_add(platform_device);
+
+ if (ret)
+ goto fail_platform_device;
+
+ wlan_rfkill =
+ rfkill_alloc("rda_wlan_rk", &platform_device->dev, RFKILL_TYPE_WLAN,
+ &wlan_rfkill_ops, NULL);
+ if (wlan_rfkill) {
+ rfkill_init_sw_state(wlan_rfkill, true);
+ ret = rfkill_register(wlan_rfkill);
+ }
+
+ bt_rfkill =
+ rfkill_alloc("rda_bt_rk", &platform_device->dev,
+ RFKILL_TYPE_BLUETOOTH, &bt_rfkill_ops, NULL);
+ if (bt_rfkill) {
+ rfkill_init_sw_state(bt_rfkill, true);
+ ret = rfkill_register(bt_rfkill);
+ } else
+ printk("rda_bt_rk failed\n");
+#if 0
+//tip,for different platform, you must check how to realize a interrupt.
+ type = script_get_item("wifi_para", "rda5990_bt_host_wake", &val);
+ if (SCIRPT_ITEM_VALUE_TYPE_PIO!=type)
+ printk("get RDA rda5990_bt_host_wake gpio failed\n");
+ else
+ bt_host_wake = val.gpio.gpio;
+
+ bt_host_wake_irq = gpio_to_irq(bt_host_wake);
+ if (IS_ERR_VALUE(bt_host_wake_irq)) {
+ pr_warn("map gpio [%d] to virq failed, errno = %d\n",
+ bt_host_wake, bt_host_wake_irq);
+ ret = -1;
+ goto fail_platform_driver;
+ }
+ ret = devm_request_irq(&platform_device->dev, bt_host_wake_irq, rda_bt_host_wake_eirq_handler,
+ IRQF_TRIGGER_RISING, "rda_combo_bt", NULL);
+ if (IS_ERR_VALUE(ret)) {
+ pr_warn("request virq %d failed, errno = %d\n",
+ bt_host_wake_irq, ret);
+ goto fail_platform_driver;
+ }
+//tip end
+#else
+ //tip,for different platform, you must check how to realize a interrupt.
+ if(bt_register_host_wake_irq(&platform_device->dev) == -1)
+ goto fail_platform_driver;
+ //tip end
+
+#endif
+ #ifdef RDA_KERNEL_PLATFORM
+ clk32k = clk_get(NULL, RDA_CLK_OUT);
+ clk26m = clk_get(NULL, RDA_CLK_AUX);
+ #endif
+ init_completion(&rda_wifi_bt_comp);
+ complete(&rda_wifi_bt_comp);
+
+ printk("rda_combo_power_ctrl_init end\n");
+ return 0;
+
+fail_platform_driver:
+fail_platform_device:
+ unregister_chrdev(rda_combo_major, "rdacombo_power_ctrl");
+ printk("rda_combo_power_ctrl_init failed\n");
+
+ #ifdef RDA_KERNEL_PLATFORM
+ if (!IS_ERR(combo_reg)) {
+ regulator_put(combo_reg);
+ }
+ #endif
+ return ret;
+}
+
+void rda_combo_power_ctrl_exit(void)
+{
+ i2c_del_driver(&rda_wifi_core_driver);
+ i2c_del_driver(&rda_wifi_rf_driver);
+ i2c_del_driver(&rda_bt_core_driver);
+ i2c_del_driver(&rda_bt_rf_driver);
+
+ unregister_chrdev(rda_combo_major, "rdacombo_power_ctrl");
+ device_destroy(rda_combo_class, MKDEV(rda_combo_major, 0));
+ if (rda_combo_class)
+ class_destroy(rda_combo_class);
+
+ cancel_delayed_work_sync(&rda_combo_sleep_worker);
+ cancel_work_sync(&rda_bt_interrupt);
+ wake_lock_destroy(&rda_combo_wake_lock);
+ disable_32k_rtc(CLOCK_MASK_ALL);
+ disable_26m_rtc(CLOCK_MASK_ALL);
+ #ifdef RDA_KERNEL_PLATFORM
+ clk_put(clk32k);
+ clk_put(clk26m);
+ #endif
+ if (wlan_rfkill) {
+ rfkill_unregister(wlan_rfkill);
+ rfkill_destroy(wlan_rfkill);
+ }
+
+ if (bt_rfkill) {
+ rfkill_unregister(bt_rfkill);
+ rfkill_destroy(bt_rfkill);
+ }
+
+ #if 0
+ devm_free_irq(&platform_device->dev, bt_host_wake_irq, NULL);
+ bt_host_wake_irq = -1;
+ #else
+ bt_unregister_host_wake_irq(&platform_device->dev);
+ #endif
+
+ if (platform_device) {
+ platform_device_unregister(platform_device);
+ platform_driver_unregister(&platform_driver);
+ }
+ #ifdef RDA_KERNEL_PLATFORM
+ if (!IS_ERR(combo_reg)) {
+ regulator_disable(combo_reg);
+ regulator_put(combo_reg);
+ }
+ #endif
+
+ rda_i2c_unregister_device(rda_wifi_core);
+ rda_i2c_unregister_device(rda_wifi_rf);
+ rda_i2c_unregister_device(rda_bt_core);
+ rda_i2c_unregister_device(rda_bt_rf);
+
+ enable_pwm1_32KHz(0);
+ if(g_pwm)
+ pwm_free(g_pwm);
+ gpio_free(bt_host_wake);
+
+
+}
+
+unsigned char rda_combo_wifi_in_test_mode(void)
+{
+ return wifi_in_test_mode;
+}
+
+void rda_combo_i2c_lock(void)
+{
+ mutex_lock(&i2c_rw_lock);
+}
+
+void rda_combo_i2c_unlock(void)
+{
+ mutex_unlock(&i2c_rw_lock);
+}
+
+int rda_fm_power_on(void)
+{
+ int ret = 0;
+ wlan_read_version_from_chip();
+ if (wlan_version == WLAN_VERSION_90_D
+ || wlan_version == WLAN_VERSION_90_E) {
+ ret = rda_5990_fm_power_on();
+ } else if (wlan_version == WLAN_VERSION_91)
+ ret = rda_5991_fm_power_on();
+ else if (wlan_version == WLAN_VERSION_91_E)
+ ret = rda_5991e_fm_power_on();
+ else if (wlan_version == WLAN_VERSION_91_F)
+ ret = rda_5991f_fm_power_on();
+ return ret;
+}
+
+int rda_fm_power_off(void)
+{
+ int ret = 0;
+ wlan_read_version_from_chip();
+ if (wlan_version == WLAN_VERSION_90_D
+ || wlan_version == WLAN_VERSION_90_E) {
+ ret = rda_5990_fm_power_off();
+ } else if (wlan_version == WLAN_VERSION_91)
+ ret = rda_5991_fm_power_off();
+ else if (wlan_version == WLAN_VERSION_91_E)
+ ret = rda_5991e_fm_power_off();
+ else if (wlan_version == WLAN_VERSION_91_F)
+ ret = rda_5991f_fm_power_off();
+ return ret;
+
+}
+
+EXPORT_SYMBOL(rda_wlan_version);
+
+EXPORT_SYMBOL(rda_combo_wifi_in_test_mode);
+
+EXPORT_SYMBOL(rda_combo_set_wake_lock);
+EXPORT_SYMBOL(rda_wifi_power_off);
+EXPORT_SYMBOL(rda_wifi_power_on);
+EXPORT_SYMBOL(rda_fm_power_on);
+EXPORT_SYMBOL(rda_fm_power_off);
+
+module_init(rda_combo_power_ctrl_init);
+module_exit(rda_combo_power_ctrl_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rda/rda_fm/Makefile b/drivers/net/wireless/rda/rda_fm/Makefile
new file mode 100755
index 00000000..fe6851a5
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_fm/Makefile
@@ -0,0 +1 @@
+obj-m := fm_drv.o
diff --git a/drivers/net/wireless/rda/rda_fm/fm.h b/drivers/net/wireless/rda/rda_fm/fm.h
new file mode 100755
index 00000000..c97c85e8
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_fm/fm.h
@@ -0,0 +1,517 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ */
+/* MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+/* alps/ALPS_SW/TRUNK/MAIN/alps/kernel/arch/arm/mach-mt6516/include/mach/fm.h
+ *
+ * (C) Copyright 2009
+ * MediaTek <www.MediaTek.com>
+ * William Chung <William.Chung@MediaTek.com>
+ *
+ * MT6516 AR10x0 FM Radio Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __FM_H__
+#define __FM_H__
+
+//#define FMDEBUG
+
+#include <linux/ioctl.h>
+#include <linux/time.h>
+
+//scan sort algorithm
+enum{
+ FM_SCAN_SORT_NON = 0,
+ FM_SCAN_SORT_UP,
+ FM_SCAN_SORT_DOWN,
+ FM_SCAN_SORT_MAX
+};
+
+//*****************************************************************************************
+//***********************************FM config for customer ***********************************
+//*****************************************************************************************
+//RX
+#define FMR_RSSI_TH_LONG 0x0301 //FM radio long antenna RSSI threshold(11.375dBuV)
+#define FMR_RSSI_TH_SHORT 0x02E0 //FM radio short antenna RSSI threshold(-1dBuV)
+#define FMR_CQI_TH 0x00E9 //FM radio Channel quality indicator threshold(0x0000~0x00FF)
+#define FMR_SEEK_SPACE 1 //FM radio seek space,1:100KHZ; 2:200KHZ
+#define FMR_SCAN_CH_SIZE 40 //FM radio scan max channel size
+#define FMR_BAND 1 //FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; 3:76.0MHz~108.0MHz; 4:special
+#define FMR_BAND_FREQ_L 875 //FM radio special band low freq(Default 87.5MHz)
+#define FMR_BAND_FREQ_H 1080 //FM radio special band high freq(Default 108.0MHz)
+#define FM_SCAN_SORT_SELECT FM_SCAN_SORT_NON
+
+//TX
+
+//*****************************************************************************************
+//***********************************FM config for engineer ***********************************
+//*****************************************************************************************
+//RX
+#define FMR_MR_TH 0x01BD //FM radio MR threshold
+#define ADDR_SCAN_TH 0xE0 //scan thrshold register
+#define ADDR_CQI_TH 0xE1 //scan CQI register
+
+//TX
+#define FMTX_SCAN_HOLE_LOW 923 //92.3MHz~95.4MHz should not show to user
+#define FMTX_SCAN_HOLE_HIGH 954 //92.3MHz~95.4MHz should not show to user
+//*****************************************************************************************
+
+#define FM_NAME "fm"
+#define FM_DEVICE_NAME "/dev/fm"
+
+// errno
+#define FM_SUCCESS 0
+#define FM_FAILED 1
+#define FM_EPARM 2
+#define FM_BADSTATUS 3
+#define FM_TUNE_FAILED 4
+#define FM_SEEK_FAILED 5
+#define FM_BUSY 6
+#define FM_SCAN_FAILED 7
+
+// band
+
+#define FM_BAND_UNKNOWN 0
+#define FM_BAND_UE 1 // US/Europe band 87.5MHz ~ 108MHz (DEFAULT)
+#define FM_BAND_JAPAN 2 // Japan band 76MHz ~ 90MHz
+#define FM_BAND_JAPANW 3 // Japan wideband 76MHZ ~ 108MHz
+#define FM_BAND_SPECIAL 4 // special band between 76MHZ and 108MHz
+#define FM_BAND_DEFAULT FM_BAND_UE
+#define FM_FREQ_MIN FMR_BAND_FREQ_L
+#define FM_FREQ_MAX FMR_BAND_FREQ_H
+#define FM_RAIDO_BAND FM_BAND_UE
+// space
+#define FM_SPACE_UNKNOWN 0
+#define FM_SPACE_100K 1
+#define FM_SPACE_200K 2
+#define FM_SPACE_DEFAULT FMR_SEEK_SPACE
+#define FM_SEEK_SPACE FMR_SEEK_SPACE
+
+//max scan chl num
+#define FM_MAX_CHL_SIZE FMR_SCAN_CH_SIZE
+// auto HiLo
+#define FM_AUTO_HILO_OFF 0
+#define FM_AUTO_HILO_ON 1
+
+// seek direction
+#define FM_SEEK_UP 0
+#define FM_SEEK_DOWN 1
+
+#define FM_CHIP_AR1000 0x1000
+#define FM_CHIP_MT5192 0x91
+#define FM_CHIP_MT5193 0x92
+#define FM_CHIP_MT6616 0x6616
+#define FM_CHIP_MT6626 0x6626
+#define FM_CHIP_MT6628 0x6628
+#define FM_CHIP_MT6620 0x6620
+#define FM_CHIP_UNSUPPORTED 0xffff
+
+// seek threshold
+#define FM_SEEKTH_LEVEL_DEFAULT 4
+
+#define FM_IOC_MAGIC 0xf5 // FIXME: any conflict?
+
+struct fm_tune_parm {
+ uint8_t err;
+ uint8_t band;
+ uint8_t space;
+ uint8_t hilo;
+ uint16_t freq; // IN/OUT parameter
+};
+
+struct fm_seek_parm {
+ uint8_t err;
+ uint8_t band;
+ uint8_t space;
+ uint8_t hilo;
+ uint8_t seekdir;
+ uint8_t seekth;
+ uint16_t freq; // IN/OUT parameter
+};
+
+struct fm_scan_parm {
+ uint8_t err;
+ uint8_t band;
+ uint8_t space;
+ uint8_t hilo;
+ uint16_t freq; // OUT parameter
+ uint16_t ScanTBL[16]; //need no less than the chip
+ uint16_t ScanTBLSize; //IN/OUT parameter
+};
+
+struct fm_ch_rssi{
+ uint16_t freq;
+ uint16_t rssi;
+};
+
+struct fm_rssi_req{
+ uint16_t num;
+ uint16_t read_cnt;
+ struct fm_ch_rssi cr[16*16];
+};
+
+#if 1
+#define NEED_DEF_RDS 1
+#else
+#define NEED_DEF_RDS 0
+#endif
+
+#if NEED_DEF_RDS
+//For RDS feature
+typedef struct
+{
+ uint8_t TP;
+ uint8_t TA;
+ uint8_t Music;
+ uint8_t Stereo;
+ uint8_t Artificial_Head;
+ uint8_t Compressed;
+ uint8_t Dynamic_PTY;
+ uint8_t Text_AB;
+ uint32_t flag_status;
+}RDSFlag_Struct;
+
+typedef struct
+{
+ uint16_t Month;
+ uint16_t Day;
+ uint16_t Year;
+ uint16_t Hour;
+ uint16_t Minute;
+ uint8_t Local_Time_offset_signbit;
+ uint8_t Local_Time_offset_half_hour;
+}CT_Struct;
+
+typedef struct
+{
+ int16_t AF_Num;
+ int16_t AF[2][25]; //100KHz
+ uint8_t Addr_Cnt;
+ uint8_t isMethod_A;
+ uint8_t isAFNum_Get;
+}AF_Info;
+
+typedef struct
+{
+ uint8_t PS[4][8];
+ uint8_t Addr_Cnt;
+}PS_Info;
+
+typedef struct
+{
+ uint8_t TextData[4][64];
+ uint8_t GetLength;
+ uint8_t isRTDisplay;
+ uint8_t TextLength;
+ uint8_t isTypeA;
+ uint8_t BufCnt;
+ uint16_t Addr_Cnt;
+}RT_Info;
+
+struct rds_raw_data
+{
+ int dirty; //indicate if the data changed or not
+ int len; //the data len form chip
+ uint8_t data[146];
+};
+
+struct rds_group_cnt
+{
+ unsigned long total;
+ unsigned long groupA[16]; //RDS groupA counter
+ unsigned long groupB[16]; //RDS groupB counter
+};
+
+enum rds_group_cnt_opcode
+{
+ RDS_GROUP_CNT_READ = 0,
+ RDS_GROUP_CNT_WRITE,
+ RDS_GROUP_CNT_RESET,
+ RDS_GROUP_CNT_MAX
+};
+
+struct rds_group_cnt_req
+{
+ int err;
+ enum rds_group_cnt_opcode op;
+ struct rds_group_cnt gc;
+};
+
+typedef struct
+{
+ CT_Struct CT;
+ RDSFlag_Struct RDSFlag;
+ uint16_t PI;
+ uint8_t Switch_TP;
+ uint8_t PTY;
+ AF_Info AF_Data;
+ AF_Info AFON_Data;
+ uint8_t Radio_Page_Code;
+ uint16_t Program_Item_Number_Code;
+ uint8_t Extend_Country_Code;
+ uint16_t Language_Code;
+ PS_Info PS_Data;
+ uint8_t PS_ON[8];
+ RT_Info RT_Data;
+ uint16_t event_status; //will use RDSFlag_Struct RDSFlag->flag_status to check which event, is that ok?
+ struct rds_group_cnt gc;
+} RDSData_Struct;
+
+
+//Need care the following definition.
+//valid Rds Flag for notify
+typedef enum {
+ RDS_FLAG_IS_TP = 0x0001, // Program is a traffic program
+ RDS_FLAG_IS_TA = 0x0002, // Program currently broadcasts a traffic ann.
+ RDS_FLAG_IS_MUSIC = 0x0004, // Program currently broadcasts music
+ RDS_FLAG_IS_STEREO = 0x0008, // Program is transmitted in stereo
+ RDS_FLAG_IS_ARTIFICIAL_HEAD = 0x0010, // Program is an artificial head recording
+ RDS_FLAG_IS_COMPRESSED = 0x0020, // Program content is compressed
+ RDS_FLAG_IS_DYNAMIC_PTY = 0x0040, // Program type can change
+ RDS_FLAG_TEXT_AB = 0x0080 // If this flag changes state, a new radio text string begins
+} RdsFlag;
+
+typedef enum {
+ RDS_EVENT_FLAGS = 0x0001, // One of the RDS flags has changed state
+ RDS_EVENT_PI_CODE = 0x0002, // The program identification code has changed
+ RDS_EVENT_PTY_CODE = 0x0004, // The program type code has changed
+ RDS_EVENT_PROGRAMNAME = 0x0008, // The program name has changed
+ RDS_EVENT_UTCDATETIME = 0x0010, // A new UTC date/time is available
+ RDS_EVENT_LOCDATETIME = 0x0020, // A new local date/time is available
+ RDS_EVENT_LAST_RADIOTEXT = 0x0040, // A radio text string was completed
+ RDS_EVENT_AF = 0x0080, // Current Channel RF signal strength too weak, need do AF switch
+ RDS_EVENT_AF_LIST = 0x0100, // An alternative frequency list is ready
+ RDS_EVENT_AFON_LIST = 0x0200, // An alternative frequency list is ready
+ RDS_EVENT_TAON = 0x0400, // Other Network traffic announcement start
+ RDS_EVENT_TAON_OFF = 0x0800, // Other Network traffic announcement finished.
+ RDS_EVENT_RDS = 0x2000, // RDS Interrupt had arrived durint timer period
+ RDS_EVENT_NO_RDS = 0x4000, // RDS Interrupt not arrived durint timer period
+ RDS_EVENT_RDS_TIMER = 0x8000 // Timer for RDS Bler Check. ---- BLER block error rate
+} RdsEvent;
+#endif
+
+struct fm_rds_tx_parm {
+ uint8_t err;
+ uint16_t pi;
+ uint16_t ps[12]; // 4 ps
+ uint16_t other_rds[87]; // 0~29 other groups
+ uint8_t other_rds_cnt; // # of other group
+};
+
+typedef struct fm_rds_tx_req{
+ unsigned char pty; // 0~31 integer
+ unsigned char rds_rbds; // 0:RDS, 1:RBDS
+ unsigned char dyn_pty; // 0:static, 1:dynamic
+ unsigned short pi_code; // 2-byte hex
+ unsigned char ps_buf[8]; // hex buf of PS
+ unsigned char ps_len; // length of PS, must be 0 / 8"
+ unsigned char af; // 0~204, 0:not used, 1~204:(87.5+0.1*af)MHz
+ unsigned char ah; // Artificial head, 0:no, 1:yes
+ unsigned char stereo; // 0:mono, 1:stereo
+ unsigned char compress; // Audio compress, 0:no, 1:yes
+ unsigned char tp; // traffic program, 0:no, 1:yes
+ unsigned char ta; // traffic announcement, 0:no, 1:yes
+ unsigned char speech; // 0:music, 1:speech
+}fm_rds_tx_req;
+
+#define TX_SCAN_MAX 10
+#define TX_SCAN_MIN 1
+struct fm_tx_scan_parm {
+ uint8_t err;
+ uint8_t band; //87.6~108MHz
+ uint8_t space;
+ uint8_t hilo;
+ uint16_t freq; // start freq, if less than band min freq, then will use band min freq
+ uint8_t scandir;
+ uint16_t ScanTBL[TX_SCAN_MAX]; //need no less than the chip
+ uint16_t ScanTBLSize; //IN: desired size, OUT: scan result size
+};
+
+struct fm_gps_rtc_info{
+ int err; //error number, 0: success, other: err code
+ int retryCnt; //GPS mnl can decide retry times
+ int ageThd; //GPS 3D fix time diff threshold
+ int driftThd; //GPS RTC drift threshold
+ struct timeval tvThd; //time value diff threshold
+ int age; //GPS 3D fix time diff
+ int drift; //GPS RTC drift
+ union{
+ unsigned long stamp; //time stamp in jiffies
+ struct timeval tv; //time stamp value in RTC
+ };
+ int flag; //rw flag
+};
+
+typedef enum
+{
+ FM_I2S_ON = 0,
+ FM_I2S_OFF
+}fm_i2s_state;
+
+typedef enum
+{
+ FM_I2S_MASTER = 0,
+ FM_I2S_SLAVE
+}fm_i2s_mode;
+
+typedef enum
+{
+ FM_I2S_32K = 0,
+ FM_I2S_44K,
+ FM_I2S_48K
+}fm_i2s_sample;
+
+struct fm_i2s_setting{
+ int onoff;
+ int mode;
+ int sample;
+};
+
+typedef enum{
+ FM_RX = 0,
+ FM_TX = 1
+}FM_PWR_T;
+
+#define FM_IOCTL_POWERUP _IOWR(FM_IOC_MAGIC, 0, struct fm_tune_parm*)
+#define FM_IOCTL_POWERDOWN _IOWR(FM_IOC_MAGIC, 1, int32_t*)
+#define FM_IOCTL_TUNE _IOWR(FM_IOC_MAGIC, 2, struct fm_tune_parm*)
+#define FM_IOCTL_SEEK _IOWR(FM_IOC_MAGIC, 3, struct fm_seek_parm*)
+#define FM_IOCTL_SETVOL _IOWR(FM_IOC_MAGIC, 4, uint32_t*)
+#define FM_IOCTL_GETVOL _IOWR(FM_IOC_MAGIC, 5, uint32_t*)
+#define FM_IOCTL_MUTE _IOWR(FM_IOC_MAGIC, 6, uint32_t*)
+#define FM_IOCTL_GETRSSI _IOWR(FM_IOC_MAGIC, 7, int32_t*)
+#define FM_IOCTL_SCAN _IOWR(FM_IOC_MAGIC, 8, struct fm_scan_parm*)
+#define FM_IOCTL_STOP_SCAN _IO(FM_IOC_MAGIC, 9)
+#define FM_IOCTL_POWERUP_TX _IOWR(FM_IOC_MAGIC, 20, struct fm_tune_parm*)
+#define FM_IOCTL_TUNE_TX _IOWR(FM_IOC_MAGIC, 21, struct fm_tune_parm*)
+#define FM_IOCTL_RDS_TX _IOWR(FM_IOC_MAGIC, 22, struct fm_rds_tx_parm*)
+
+//IOCTL and struct for test
+#define FM_IOCTL_GETCHIPID _IOWR(FM_IOC_MAGIC, 10, uint16_t*)
+#define FM_IOCTL_EM_TEST _IOWR(FM_IOC_MAGIC, 11, struct fm_em_parm*)
+#define FM_IOCTL_RW_REG _IOWR(FM_IOC_MAGIC, 12, struct fm_ctl_parm*)
+#define FM_IOCTL_GETMONOSTERO _IOWR(FM_IOC_MAGIC, 13, uint16_t*)
+#define FM_IOCTL_GETCURPAMD _IOWR(FM_IOC_MAGIC, 14, uint16_t*)
+#define FM_IOCTL_GETGOODBCNT _IOWR(FM_IOC_MAGIC, 15, uint16_t*)
+#define FM_IOCTL_GETBADBNT _IOWR(FM_IOC_MAGIC, 16, uint16_t*)
+#define FM_IOCTL_GETBLERRATIO _IOWR(FM_IOC_MAGIC, 17, uint16_t*)
+
+
+//IOCTL for RDS
+#define FM_IOCTL_RDS_ONOFF _IOWR(FM_IOC_MAGIC, 18, uint16_t*)
+#define FM_IOCTL_RDS_SUPPORT _IOWR(FM_IOC_MAGIC, 19, int32_t*)
+
+#define FM_IOCTL_RDS_SIM_DATA _IOWR(FM_IOC_MAGIC, 23, uint32_t*)
+#define FM_IOCTL_IS_FM_POWERED_UP _IOWR(FM_IOC_MAGIC, 24, uint32_t*)
+
+//IOCTL for FM Tx
+#define FM_IOCTL_TX_SUPPORT _IOWR(FM_IOC_MAGIC, 25, int32_t*)
+#define FM_IOCTL_RDSTX_SUPPORT _IOWR(FM_IOC_MAGIC, 26, int32_t*)
+#define FM_IOCTL_RDSTX_ENABLE _IOWR(FM_IOC_MAGIC, 27, int32_t*)
+#define FM_IOCTL_TX_SCAN _IOWR(FM_IOC_MAGIC, 28, struct fm_tx_scan_parm*)
+
+//IOCTL for FM over BT
+#define FM_IOCTL_OVER_BT_ENABLE _IOWR(FM_IOC_MAGIC, 29, int32_t*)
+
+//IOCTL for FM ANTENNA SWITCH
+#define FM_IOCTL_ANA_SWITCH _IOWR(FM_IOC_MAGIC, 30, int32_t*)
+#define FM_IOCTL_GETCAPARRAY _IOWR(FM_IOC_MAGIC, 31, int32_t*)
+
+//IOCTL for FM compensation by GPS RTC
+#define FM_IOCTL_GPS_RTC_DRIFT _IOWR(FM_IOC_MAGIC, 32, struct fm_gps_rtc_info*)
+
+//IOCTL for FM I2S Setting
+#define FM_IOCTL_I2S_SETTING _IOWR(FM_IOC_MAGIC, 33, struct fm_i2s_setting*)
+
+#define FM_IOCTL_RDS_GROUPCNT _IOWR(FM_IOC_MAGIC, 34, struct rds_group_cnt_req*)
+#define FM_IOCTL_RDS_GET_LOG _IOWR(FM_IOC_MAGIC, 35, struct rds_raw_data*)
+
+#define FM_IOCTL_SCAN_GETRSSI _IOWR(FM_IOC_MAGIC, 36, struct fm_rssi_req*)
+#define FM_IOCTL_SETMONOSTERO _IOWR(FM_IOC_MAGIC, 37, int32_t)
+
+#define FM_IOCTL_RDS_BC_RST _IOWR(FM_IOC_MAGIC, 38, int32_t*)
+
+#define FM_IOCTL_DUMP_REG _IO(FM_IOC_MAGIC, 0xFF)
+
+enum group_idx {
+ mono=0,
+ stereo,
+ RSSI_threshold,
+ HCC_Enable,
+ PAMD_threshold,
+ Softmute_Enable,
+ De_emphasis,
+ HL_Side,
+ Demod_BW,
+ Dynamic_Limiter,
+ Softmute_Rate,
+ AFC_Enable,
+ Softmute_Level,
+ Analog_Volume,
+ GROUP_TOTAL_NUMS
+};
+
+enum item_idx {
+ Sblend_OFF=0,
+ Sblend_ON,
+ ITEM_TOTAL_NUMS
+};
+
+struct fm_ctl_parm {
+ uint8_t err;
+ uint8_t addr;
+ uint16_t val;
+ uint16_t rw_flag;//0:write, 1:read
+};
+
+struct fm_em_parm {
+ uint16_t group_idx;
+ uint16_t item_idx;
+ uint32_t item_value;
+};
+#endif // __FM_H__
diff --git a/drivers/net/wireless/rda/rda_fm/fm_drv.c b/drivers/net/wireless/rda/rda_fm/fm_drv.c
new file mode 100755
index 00000000..cc44d8f3
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_fm/fm_drv.c
@@ -0,0 +1,2257 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h> // udelay()
+#include <linux/device.h> // device_create()
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/version.h> /* constant of kernel version */
+#include <asm/uaccess.h> // get_user()
+#include <linux/semaphore.h>
+
+//#include <linux/fm.h>
+#include "fm.h"
+//#include <mach/mt6573_gpio.h>
+//#include <mach/mtk_rtc.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#define FMDEBUG 1
+#define MTK_MT6515 1
+#define RDA599X_FM_SUPPORT 1
+#define FM_ALERT(f, s...) \
+ do { \
+ printk(KERN_ALERT "RDAFM " f, ## s); \
+ } while(0)
+
+#ifdef FMDEBUG
+#define FM_DEBUG(f, s...) \
+ do { \
+ printk("RDAFM " f, ## s); \
+ } while(0)
+#else
+#define FM_DEBUG(f, s...)
+#endif
+#define RDA599X_SCANTBL_SIZE 16 //16*uinit16_t
+#define RDA599X_FM_SCAN_UP 0x0
+#define RDA599X_FM_SCAN_DOWN 0x01
+
+
+typedef signed char int8;
+typedef unsigned char uint8;
+typedef signed short int16;
+typedef unsigned short uint16;
+typedef signed int int32;
+typedef unsigned int uint32;
+
+extern int rda_fm_power_off();
+extern int rda_fm_power_on();
+
+/******************************************************************************
+ * CONSTANT DEFINITIONS
+ *****************************************************************************/
+#define RDAFM_SLAVE_ADDR (0x11) //RDA FM Chip address
+
+#define RDAFM_MASK_RSSI 0X7F // RSSI
+#define RDAFM_DEV "RDA_FM"
+
+//customer need customize the I2C port
+#define RDAFM_I2C_PORT 0
+
+
+#define ID_RDA5802E 0x5804
+#define ID_RDA5802H 0x5801
+#define ID_RDA5802N 0x5808
+#define ID_RDA5820 0x5805
+#define ID_RDA5820NS 0x5820
+
+
+static struct proc_dir_entry *g_fm_proc = NULL;
+static struct fm *g_fm_struct = NULL;
+static atomic_t scan_complete_flag;
+
+#define FM_PROC_FILE "fm"
+
+/******************************************************************************
+ * STRUCTURE DEFINITIONS
+ *****************************************************************************/
+
+enum RDAFM_CHIP_TYPE {
+ CHIP_TYPE_RDA5802E = 0,
+ CHIP_TYPE_RDA5802H,
+ CHIP_TYPE_RDA5802N,
+ CHIP_TYPE_RDA5820,
+ CHIP_TYPE_RDA5820NS,
+};
+
+
+
+typedef struct
+{
+ uint8_t address;
+ uint16_t value;
+}RDA_FM_REG_T;
+
+typedef struct
+{
+ bool byPowerUp;
+ struct fm_tune_parm parm
+}FM_TUNE_T;
+static FM_TUNE_T fm_tune_data = {false, {}};
+
+typedef enum
+{
+ FM_RECEIVER, //5800,5802,5804
+ FM_TRANSMITTER, //5820
+}RDA_RADIO_WORK_E;
+
+typedef enum
+{
+ OFF,
+ ON,
+}RDA_FM_POWER_STATE_T;
+
+struct fm {
+ uint32_t ref;
+ bool powerup;
+ uint16_t chip_id;
+ uint16_t device_id;
+ dev_t dev_t;
+ uint16_t min_freq; // KHz
+ uint16_t max_freq; // KHz
+ uint8_t band; // TODO
+ struct class *cls;
+ struct device *dev;
+ struct cdev cdev;
+ struct i2c_client *i2c_client;
+};
+
+
+/******************************************************************************
+ * FUNCTION PROTOTYPES
+ *****************************************************************************/
+//extern void fm_low_power_wa(int fmon);
+
+static int RDAFM_clear_hmute(struct i2c_client *client);
+static int RDAFM_enable_hmute(struct i2c_client *client);
+static int RDAFM_clear_tune(struct i2c_client *client);
+static int RDAFM_enable_tune(struct i2c_client *client);
+static int RDAFM_clear_seek(struct i2c_client *client);
+static int RDAFM_enable_seek(struct i2c_client *client);
+static int RDAFM_SetStereo(struct i2c_client *client,uint8_t b);
+static int RDAFM_SetRSSI_Threshold(struct i2c_client *client,uint8_t RssiThreshold);
+static int RDAFM_SetDe_Emphasis(struct i2c_client *client,uint8_t index);
+static bool RDAFM_Scan(struct i2c_client *client,
+ uint16_t min_freq, uint16_t max_freq,
+ uint16_t *pFreq, //get the valid freq after scan
+ uint16_t *pScanTBL,
+ uint16_t *ScanTBLsize,
+ uint16_t scandir,
+ uint16_t space);
+
+
+static int RDAFM_read(struct i2c_client *client, uint8_t addr, uint16_t *val);
+static int RDAFM_write(struct i2c_client *client, uint8_t addr, uint16_t val);
+static void RDAFM_em_test(struct i2c_client *client, uint16_t group_idx, uint16_t item_idx, uint32_t item_value);
+static int fm_setup_cdev(struct fm *fm);
+static int fm_ops_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+static loff_t fm_ops_lseek(struct file *filp, loff_t off, int whence);
+static int fm_ops_open(struct inode *inode, struct file *filp);
+static int fm_ops_release(struct inode *inode, struct file *filp);
+
+static int fm_init(struct i2c_client *client);
+static int fm_destroy(struct fm *fm);
+static int fm_powerup(struct fm *fm, struct fm_tune_parm *parm);
+static int fm_powerdown(struct fm *fm);
+
+static int fm_tune(struct fm *fm, struct fm_tune_parm *parm);
+static int fm_seek(struct fm *fm, struct fm_seek_parm *parm);
+static int fm_scan(struct fm *fm, struct fm_scan_parm *parm);
+static int fm_setvol(struct fm *fm, uint32_t vol);
+static int fm_getvol(struct fm *fm, uint32_t *vol);
+static int fm_getrssi(struct fm *fm, uint32_t *rssi);
+static int fm_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31))
+static int fm_i2c_attach_adapter(struct i2c_adapter *adapter);
+static int fm_i2c_detect(struct i2c_adapter *adapter, int addr, int kind);
+static int fm_i2c_detach_client(struct i2c_client *client);
+#else
+static int fm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
+static int fm_i2c_detect(struct i2c_client *client, struct i2c_board_info *info);
+static int fm_i2c_remove(struct i2c_client *client);
+#endif
+
+/******************************************************************************
+ * GLOBAL DATA
+ *****************************************************************************/
+/* Addresses to scan */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31))
+static unsigned short normal_i2c[] = {RDAFM_SLAVE_ADDR, I2C_CLIENT_END};
+static unsigned short ignore = I2C_CLIENT_END;
+
+static struct i2c_client_address_data RDAFM_addr_data = {
+ .normal_i2c = normal_i2c,
+ .probe = &ignore,
+ .ignore = &ignore,
+};
+#else
+static const struct i2c_device_id fm_i2c_id = {RDAFM_DEV, 0};
+static unsigned short force[] = {RDAFM_I2C_PORT, RDAFM_SLAVE_ADDR, I2C_CLIENT_END, I2C_CLIENT_END};
+static const unsigned short * const forces[] = {force, NULL};
+//static struct i2c_client_address_data addr_data = {.forces = forces};
+static unsigned short addr_data[] = {/*RDAFM_I2C_PORT,*/ RDAFM_SLAVE_ADDR, I2C_CLIENT_END, I2C_CLIENT_END};
+
+#endif
+
+static struct i2c_driver RDAFM_driver = {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31))
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = RDAFM_DEV,
+ },
+ .attach_adapter = fm_i2c_attach_adapter,
+ .detach_client = fm_i2c_detach_client,
+#else
+ .class = I2C_CLASS_HWMON,
+ .probe = fm_i2c_probe,
+ .remove = fm_i2c_remove,
+ .detect = fm_i2c_detect,
+ .driver.name = RDAFM_DEV,
+ .driver.owner = THIS_MODULE,
+ .id_table = &fm_i2c_id,
+ //.address_data = &addr_data,
+ .address_list = (const unsigned short*) addr_data,
+#endif
+};
+
+static uint16_t RDAFM_CHIP_ID = 0x5808;
+static RDA_RADIO_WORK_E RDA_RADIO_WorkType = FM_RECEIVER;
+
+
+
+#if 1
+static uint16_t RDA5802N_initialization_reg[]={
+ 0xC005, //02h
+ 0x0000,
+ 0x0400,
+ 0xC6ED, //0x86AD, //05h
+ 0x6000,
+ 0x721A,
+ 0x0000,
+ 0x0000,
+ 0x0000, //0x0ah
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000, //0x10h
+ 0x0019,
+ 0x2A11,
+ 0xB042,
+ 0x2A11,
+ 0xB831, //0x15h
+ 0xC000,
+ 0x2A91,
+ 0x9400,
+ 0x00A8,
+ 0xc400, //0x1ah
+ 0xF7CF, //Զ
+ 0x2414, //0x2ADC, //0x1ch VIO VDD֮ѹIJ
+ 0x806F,
+ 0x4608,
+ 0x0086,
+ 0x0661, //0x20H
+ 0x0000,
+ 0x109E,
+ 0x23C8,
+ 0x0406,
+ 0x0E1C, //0x25H
+};
+#else
+static uint16_t RDA5802N_initialization_reg[]={
+ 0xc401, //02h
+ 0x0000,
+ 0x0400,
+ 0x86ad, //05h//
+ 0x0000,
+ 0x42c6,
+ 0x0000,
+ 0x0000,
+ 0x0000, //0x0ah
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000, //0x10h
+ 0x0019,
+ 0x2a11,
+ 0xa053,//0x80,0x53,
+ 0x3e11,//0x22,0x11,
+ 0xfc7d, //0x15h
+ 0xc000,
+ 0x2a91,
+ 0x9400,
+ 0x00a8,
+ 0xc400, //0x1ah
+ 0xe000,
+ 0x2b1d, //0x23,0x14
+ 0x816a,
+ 0x4608,
+ 0x0086,
+ 0x0661, //0x20h
+ 0x0000,
+ 0x109e,
+ 0x2244,
+ 0x0408, //0x24
+ 0x0408, //0x25
+};
+#endif
+
+static RDA_FM_REG_T RDA5820NS_TX_initialization_reg[]={
+ {0x02, 0xE003},
+ {0xFF, 100}, // if address is 0xFF, sleep value ms
+ {0x02, 0xE001},
+ {0x19, 0x88A8},
+ {0x1A, 0x4290},
+ {0x68, 0x0AF0},
+ {0x40, 0x0001},
+ {0x41, 0x41FF},
+ {0xFF, 500},
+ {0x03, 0x1B90},
+};
+
+static RDA_FM_REG_T RDA5820NS_RX_initialization_reg[]={
+ {0x02, 0x0002}, //Soft reset
+ {0xFF, 100}, // wait
+ {0x02, 0xC001}, //Power Up
+ {0x05, 0x888F}, //LNAP 0x884F --LNAN
+ {0x06, 0x6000},
+ {0x13, 0x80E1},
+ {0x14, 0x2A11},
+ {0x1C, 0x22DE},
+ {0x21, 0x0020},
+ {0x03, 0x1B90},
+};
+
+
+
+static struct file_operations fm_ops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = fm_ops_ioctl,
+ .llseek = fm_ops_lseek,
+ .open = fm_ops_open,
+ .release = fm_ops_release,
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
+static DECLARE_MUTEX(fm_ops_mutex);
+#else
+DEFINE_SEMAPHORE(fm_ops_mutex);
+#endif
+
+/******************************************************************************
+ *****************************************************************************/
+
+/******************************************************************************
+ *****************************************************************************/
+
+
+
+static int RDAFM_GetChipID(struct i2c_client *client, uint16_t *pChipID)
+{
+ int err;
+ int ret = -1;
+ uint16_t val = 0x0002;
+
+ //Reset RDA FM
+ err = RDAFM_write(client, 0x02, val);
+ if(err < 0){
+#ifdef FMDEBUG
+ FM_DEBUG("RDAFM_GetChipID: reset FM chip failed!\n");
+#endif
+ ret = -1;
+ return ret;
+ }
+ msleep(80);
+
+ val = 0;
+ err = RDAFM_read(client, 0x0C, &val);
+ if (err == 0)
+ {
+ if ((0x5802 == val) || (0x5803 == val))
+ {
+ err = RDAFM_read(client, 0x0E, &val);
+
+ if (err == 0)
+ *pChipID = val;
+ else
+ *pChipID = 0x5802;
+
+#ifdef FMDEBUG
+ FM_DEBUG("RDAFM_GetChipID: Chip ID = %04X\n", val);
+#endif
+
+ ret = 0;
+
+ }
+ else if ((0x5805 == val) || (0x5820 == val))
+ {
+ *pChipID = val;
+ ret = 0;
+ }
+ else
+ {
+#ifdef FMDEBUG
+ FM_DEBUG("RDAFM_GetChipID: get chip ID failed! get value = %04X\n", val);
+#endif
+ ret = -1;
+ }
+
+ }
+ else
+ {
+#ifdef FMDEBUG
+ FM_DEBUG("RDAFM_GetChipID: get chip ID failed!\n");
+#endif
+ ret = -1;
+ }
+
+ return ret;
+}
+
+
+/*
+ * RDAFM_read
+ */
+static int RDAFM_read(struct i2c_client *client, uint8_t addr, uint16_t *val)
+{
+ int n;
+ char b[2] = {0};
+
+ // first, send addr to RDAFM
+ n = i2c_master_send(client, (char*)&addr, 1);
+ if (n < 0)
+ {
+ FM_ALERT("RDAFM_read send:0x%X err:%d\n", addr, n);
+ return -1;
+ }
+
+ // second, receive two byte from RDAFM
+ n = i2c_master_recv(client, b, 2);
+ if (n < 0)
+ {
+ FM_ALERT("RDAFM_read recv:0x%X err:%d\n", addr, n);
+ return -1;
+ }
+
+ *val = (uint16_t)(b[0] << 8 | b[1]);
+
+ return 0;
+}
+
+/*
+ * RDAFM_write
+ */
+static int RDAFM_write(struct i2c_client *client, uint8_t addr, uint16_t val)
+{
+ int n;
+ char b[3];
+
+ b[0] = addr;
+ b[1] = (char)(val >> 8);
+ b[2] = (char)(val & 0xFF);
+
+ n = i2c_master_send(client, b, 3);
+ if (n < 0)
+ {
+ FM_ALERT("RDAFM_write send:0x%X err:%d\n", addr, n);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int RDAFM_clear_hmute(struct i2c_client *client)
+{
+ int ret = 0;
+ uint16_t tRegValue = 0;
+
+ FM_DEBUG("RDAFM_clear_hmute\n");
+
+ ret = RDAFM_read(client, 0x02, &tRegValue);
+ if (ret < 0)
+ {
+ FM_ALERT("RDAFM_clear_hmute read register failed!\n");
+ return -1;
+ }
+
+ tRegValue |= (1 << 14);
+
+ ret = RDAFM_write(client, 0x02, tRegValue);
+
+ if (ret < 0)
+ {
+ FM_ALERT("RDAFM_clear_hmute write register failed!\n");
+ return -1;
+ }
+
+ if(fm_tune_data.byPowerUp){
+ if (fm_tune(g_fm_struct, &(fm_tune_data.parm)) < 0)
+ {
+ fm_tune_data.byPowerUp = false;
+ memset(&fm_tune_data.parm, 0, sizeof(fm_tune_data.parm));
+ return -EPERM;
+ }
+ fm_tune_data.byPowerUp = false;
+ memset(&fm_tune_data.parm, 0, sizeof(fm_tune_data.parm));
+ }
+
+ return 0;
+}
+
+
+
+static int RDAFM_enable_hmute(struct i2c_client *client)
+{
+ int ret = 0;
+ uint16_t tRegValue = 0;
+
+ FM_DEBUG("RDAFM_enable_hmute\n");
+
+ ret = RDAFM_read(client, 0x02, &tRegValue);
+ if (ret < 0)
+ {
+ FM_ALERT("RDAFM_enable_hmute read register failed!\n");
+ return -1;
+ }
+
+ tRegValue &= (~(1 << 14));
+
+ ret = RDAFM_write(client, 0x02, tRegValue);
+
+ if (ret < 0)
+ {
+ FM_ALERT("RDAFM_enable_hmute write register failed!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+static int RDAFM_clear_tune(struct i2c_client *client)
+{
+ //Don't need it
+ return 0;
+}
+
+
+
+static int RDAFM_enable_tune(struct i2c_client *client)
+{
+ //Don't need it
+ return 0;
+}
+
+
+
+static int RDAFM_clear_seek(struct i2c_client *client)
+{
+ //Don't need it
+ return 0;
+}
+
+
+
+static int RDAFM_enable_seek(struct i2c_client *client)
+{
+ //Don't need it
+ return 0;
+}
+
+
+//b=true set stereo else set mono
+static int RDAFM_SetStereo(struct i2c_client *client, uint8_t b)
+{
+ int ret = 0;
+ uint16_t tRegValue = 0;
+
+ FM_DEBUG("RDAFM_SetStereo\n");
+
+ ret = RDAFM_read(client, 0x02, &tRegValue);
+ if (ret < 0)
+ {
+ FM_ALERT("RDAFM_SetStereo read register failed!\n");
+ return -1;
+ }
+ if (b)
+ tRegValue &= (~(1 << 13));//set stereo
+ else
+ tRegValue |= (1 << 13); //set mono
+
+ ret = RDAFM_write(client, 0x02, tRegValue);
+
+ if (ret < 0)
+ {
+ FM_ALERT("RDAFM_SetStereo write register failed!\n");
+ return -1;
+ }
+
+
+ return 0;
+
+}
+
+
+
+static int RDAFM_SetRSSI_Threshold(struct i2c_client *client, uint8_t RssiThreshold)
+{
+ int ret = 0;
+ uint16_t tRegValue = 0;
+
+ FM_DEBUG("RDAFM_SetRSSI_Threshold\n");
+
+ ret = RDAFM_read(client, 0x05, &tRegValue);
+ if (ret < 0)
+ {
+ FM_ALERT("RDAFM_SetRSSI_Threshold read register failed!\n");
+ return -1;
+ }
+
+ tRegValue &= 0x80FF;//clear valume
+ tRegValue |= ((RssiThreshold & 0x7f) << 8); //set valume
+
+ ret = RDAFM_write(client, 0x05, tRegValue);
+
+ if (ret < 0)
+ {
+ FM_ALERT("RDAFM_SetRSSI_Threshold write register failed!\n");
+ return -1;
+ }
+
+
+ return 0;
+
+}
+
+
+
+static int RDAFM_SetDe_Emphasis(struct i2c_client *client, uint8_t index)
+{
+ int ret = 0;
+ uint16_t tRegValue = 0;
+
+ FM_DEBUG("RDAFM_SetRSSI_Threshold\n");
+
+ ret = RDAFM_read(client, 0x04, &tRegValue);
+ if (ret < 0)
+ {
+ FM_ALERT("RDAFM_SetRSSI_Threshold read register failed!\n");
+ return -1;
+ }
+
+ if (0 == index)
+ {
+ tRegValue &= (~(1 << 11));//De_Emphasis=75us
+ }
+ else if (1 == index)
+ {
+ tRegValue |= (1 << 11);//De_Emphasis=50us
+ }
+
+
+ ret = RDAFM_write(client, 0x04, tRegValue);
+
+ if (ret < 0)
+ {
+ FM_ALERT("RDAFM_SetRSSI_Threshold write register failed!\n");
+ return -1;
+ }
+
+
+ return 0;
+
+
+}
+
+static void RDAFM_em_test(struct i2c_client *client, uint16_t group_idx, uint16_t item_idx, uint32_t item_value)
+{
+ FM_ALERT("RDAFM_em_test %d:%d:%d\n", group_idx, item_idx, item_value);
+ switch (group_idx)
+ {
+ case mono:
+ if(item_value == 1)
+ {
+ RDAFM_SetStereo(client, 0); //force mono
+ }
+ else
+ {
+ RDAFM_SetStereo(client, 1); //stereo
+
+ }
+
+ break;
+ case stereo:
+ if(item_value == 0)
+ {
+ RDAFM_SetStereo(client, 1); //stereo
+ }
+ else
+ {
+ RDAFM_SetStereo(client, 0); //force mono
+ }
+ break;
+ case RSSI_threshold:
+ item_value &= 0x7F;
+ RDAFM_SetRSSI_Threshold(client, item_value);
+ break;
+ case Softmute_Enable:
+ if (item_idx)
+ {
+ RDAFM_enable_hmute(client);
+ }
+ else
+ {
+ RDAFM_clear_hmute(client);
+ }
+ break;
+ case De_emphasis:
+ if(item_idx >= 2) //0us
+ {
+ FM_ALERT("RDAFM not support De_emphasis 0\n");
+ }
+ else
+ {
+ RDAFM_SetDe_Emphasis(client,item_idx);//0=75us,1=50us
+ }
+ break;
+
+ case HL_Side:
+
+ break;
+ default:
+ FM_ALERT("RDAFM not support this setting\n");
+ break;
+ }
+}
+
+static bool RDAFM_Scan(struct i2c_client *client,
+ uint16_t min_freq, uint16_t max_freq,
+ uint16_t *pFreq,
+ uint16_t *pScanTBL,
+ uint16_t *ScanTBLsize,
+ uint16_t scandir,
+ uint16_t space)
+{
+ uint16_t tFreq, tRegValue = 0;
+ uint16_t tmp_scanTBLsize = *ScanTBLsize;
+ int ret = -1;
+ bool isTrueStation = false;
+ uint16_t oldValue = 0;
+ int channel = 0;
+ if((!pScanTBL) || (tmp_scanTBLsize == 0)) {
+ return false;
+ }
+
+ //clear the old value of pScanTBL
+ memset(pScanTBL, 0, sizeof(uint16_t)*RDA599X_SCANTBL_SIZE);
+
+ if(tmp_scanTBLsize > RDA599X_SCANTBL_SIZE)
+ {
+ tmp_scanTBLsize = RDA599X_SCANTBL_SIZE;
+ }
+
+ //scan up
+ if(scandir == RDA599X_FM_SCAN_UP){ // now, only support scan up
+ tFreq = min_freq;
+ }else{ //scan down
+ tFreq = max_freq;//max_freq compare need or not
+ }
+
+ //mute FM
+ RDAFM_enable_hmute(client);
+#if 0
+ //set seekth
+ tRegValue = 0;
+ RDAFM_read(client, 0x05, &tRegValue);
+ tRegValue &= (~(0x7f<<8));
+ tRegValue |= ((0x8 & 0x7f) << 8);
+ RDAFM_write(client, 0x05, tRegValue);
+ msleep(50);
+#endif
+ atomic_set(&scan_complete_flag, 1);
+ do {
+ if(atomic_read(&scan_complete_flag) == 0)
+ break;
+ isTrueStation = false;
+
+ //set channel and enable TUNE
+ tRegValue = 0;
+ RDAFM_read(client, 0x03, &tRegValue);
+ tRegValue &= (~(0x03ff<<6)); //clear bit[15:6]
+ channel = tFreq - min_freq;
+ tRegValue |= ((channel << 6) | (1 << 4)); //set bit[15:6] and bit[4]
+ ret = RDAFM_write(client, 0x03, tRegValue);
+ msleep(40);
+
+ //read 0x0B and check FM_TRUE(bit[8])
+ tRegValue = 0;
+ ret = RDAFM_read(client, 0x0B, &tRegValue);
+ if(!ret){
+ if((tRegValue & 0x0100) == 0x0100){
+ isTrueStation = true;
+ }
+ }
+
+ //if this freq is a true station, read the channel
+ if(isTrueStation){
+ //tRegValue = 0;
+ //RDAFM_read(client, 0x03, &tRegValue);
+ //channel = ((tRegValue>>6) & 0x03ff) - 5;
+ channel = channel - 5;
+ if((channel >= 0) && (channel != 85)){
+ oldValue = *(pScanTBL+(channel/16));
+ oldValue |= (1<<(channel%16));
+ *(pScanTBL+(channel/16)) = oldValue;
+ }
+ }
+
+ //increase freq
+ tFreq += space;
+ }while( tFreq <= max_freq );
+
+#if defined(MTK_MT6515) && defined(MT6626)
+ *(pScanTBL+13) = 0xb2d4;
+ *(pScanTBL+14) = 0xb2d4;
+ *(pScanTBL+15) = 0xb2d4;
+#endif
+
+ *ScanTBLsize = tmp_scanTBLsize;
+ *pFreq = 0;
+
+ //clear FM mute
+ RDAFM_clear_hmute(client);
+
+ return true;
+}
+
+
+static int fm_setup_cdev(struct fm *fm)
+{
+ int err;
+
+ err = alloc_chrdev_region(&fm->dev_t, 0, 1, FM_NAME);
+ if (err) {
+ FM_ALERT("alloc dev_t failed\n");
+ return -1;
+ }
+
+ FM_ALERT("alloc %s:%d:%d\n", FM_NAME,
+ MAJOR(fm->dev_t), MINOR(fm->dev_t));
+
+ cdev_init(&fm->cdev, &fm_ops);
+
+ fm->cdev.owner = THIS_MODULE;
+ fm->cdev.ops = &fm_ops;
+
+ err = cdev_add(&fm->cdev, fm->dev_t, 1);
+ if (err) {
+ FM_ALERT("alloc dev_t failed\n");
+ return -1;
+ }
+
+ fm->cls = class_create(THIS_MODULE, FM_NAME);
+ if (IS_ERR(fm->cls)) {
+ err = PTR_ERR(fm->cls);
+ FM_ALERT("class_create err:%d\n", err);
+ return err;
+ }
+ fm->dev = device_create(fm->cls, NULL, fm->dev_t, NULL, FM_NAME);
+
+ return 0;
+}
+
+
+
+static int fm_ops_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+ struct fm *fm = container_of(filp->f_dentry->d_inode->i_cdev, struct fm, cdev);
+
+ FM_DEBUG("%s cmd(%x)\n", __func__, cmd);
+
+ switch(cmd)
+ {
+ case FM_IOCTL_POWERUP:
+ {
+ struct fm_tune_parm parm;
+ FM_DEBUG("FM_IOCTL_POWERUP\n");
+
+ // FIXME!!
+ // if (!capable(CAP_SYS_ADMIN))
+ // return -EPERM;
+
+ if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm)))
+ return -EFAULT;
+
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+ ret = fm_powerup(fm, &parm);
+ up(&fm_ops_mutex);
+ if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm)))
+ return -EFAULT;
+ // fm_low_power_wa(1);
+ break;
+ }
+
+ case FM_IOCTL_POWERDOWN:
+ {
+ FM_DEBUG("FM_IOCTL_POWERDOWN\n");
+ // FIXME!!
+ // if (!capable(CAP_SYS_ADMIN))
+ // return -EPERM;
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+ ret = fm_powerdown(fm);
+ up(&fm_ops_mutex);
+// fm_low_power_wa(0);
+ break;
+ }
+
+ // tune (frequency, auto Hi/Lo ON/OFF )
+ case FM_IOCTL_TUNE:
+ {
+ struct fm_tune_parm parm;
+ FM_DEBUG("FM_IOCTL_TUNE\n");
+// FIXME!
+// if (!capable(CAP_SYS_ADMIN))
+// return -EPERM;
+
+ if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_tune_parm)))
+ return -EFAULT;
+
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+ ret = fm_tune(fm, &parm);
+ up(&fm_ops_mutex);
+
+ if (copy_to_user((void*)arg, &parm, sizeof(struct fm_tune_parm)))
+ return -EFAULT;
+
+ break;
+ }
+
+ case FM_IOCTL_SEEK:
+ {
+ struct fm_seek_parm parm;
+ FM_DEBUG("FM_IOCTL_SEEK\n");
+
+// FIXME!!
+// if (!capable(CAP_SYS_ADMIN))
+// return -EPERM;
+
+ if (copy_from_user(&parm, (void*)arg, sizeof(struct fm_seek_parm)))
+ return -EFAULT;
+
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+ ret = fm_seek(fm, &parm);
+ up(&fm_ops_mutex);
+
+ if (copy_to_user((void*)arg, &parm, sizeof(struct fm_seek_parm)))
+ return -EFAULT;
+
+ break;
+ }
+
+ case FM_IOCTL_SETVOL:
+ {
+ uint32_t vol;
+ FM_DEBUG("FM_IOCTL_SETVOL\n");
+
+// FIXME!!
+// if (!capable(CAP_SYS_ADMIN))
+// return -EPERM;
+
+ if(copy_from_user(&vol, (void*)arg, sizeof(uint32_t))) {
+ FM_ALERT("copy_from_user failed\n");
+ return -EFAULT;
+ }
+
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+ ret = fm_setvol(fm, vol);
+ up(&fm_ops_mutex);
+
+ break;
+ }
+
+ case FM_IOCTL_GETVOL:
+ {
+ uint32_t vol;
+ FM_DEBUG("FM_IOCTL_GETVOL\n");
+
+// FIXME!!
+// if (!capable(CAP_SYS_ADMIN))
+// return -EPERM;
+
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+ ret = fm_getvol(fm, &vol);
+ up(&fm_ops_mutex);
+
+ if (copy_to_user((void*)arg, &vol, sizeof(uint32_t)))
+ return -EFAULT;
+
+ break;
+ }
+
+ case FM_IOCTL_MUTE:
+ {
+ uint32_t bmute;
+ FM_DEBUG("FM_IOCTL_MUTE\n");
+
+ // FIXME!!
+ // if (!capable(CAP_SYS_ADMIN))
+ // return -EPERM;
+ if (copy_from_user(&bmute, (void*)arg, sizeof(uint32_t)))
+ {
+ FM_DEBUG("copy_from_user mute failed!\n");
+ return -EFAULT;
+ }
+
+ FM_DEBUG("FM_IOCTL_MUTE:%d\n", bmute);
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+
+ if (bmute){
+ ret = RDAFM_enable_hmute(fm->i2c_client);
+ }else{
+ ret = RDAFM_clear_hmute(fm->i2c_client);
+ }
+
+ up(&fm_ops_mutex);
+
+ break;
+ }
+
+ case FM_IOCTL_GETRSSI:
+ {
+ uint32_t rssi;
+ FM_DEBUG("FM_IOCTL_GETRSSI\n");
+
+// FIXME!!
+// if (!capable(CAP_SYS_ADMIN))
+// return -EPERM;
+
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+
+ ret = fm_getrssi(fm, &rssi);
+ up(&fm_ops_mutex);
+
+ if (copy_to_user((void*)arg, &rssi, sizeof(uint32_t)))
+ return -EFAULT;
+
+ break;
+ }
+
+ case FM_IOCTL_RW_REG:
+ {
+ struct fm_ctl_parm parm_ctl;
+ FM_DEBUG("FM_IOCTL_RW_REG\n");
+
+// FIXME!!
+// if (!capable(CAP_SYS_ADMIN))
+// return -EPERM;
+
+ if (copy_from_user(&parm_ctl, (void*)arg, sizeof(struct fm_ctl_parm)))
+ return -EFAULT;
+
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+
+ if(parm_ctl.rw_flag == 0) //write
+ {
+ ret = RDAFM_write(fm->i2c_client, parm_ctl.addr, parm_ctl.val);
+ }
+ else
+ {
+ ret = RDAFM_read(fm->i2c_client, parm_ctl.addr, &parm_ctl.val);
+ }
+
+ up(&fm_ops_mutex);
+ if ((parm_ctl.rw_flag == 0x01) && (!ret)) // Read success.
+ {
+ if (copy_to_user((void*)arg, &parm_ctl, sizeof(struct fm_ctl_parm)))
+ return -EFAULT;
+ }
+ break;
+ }
+
+ case FM_IOCTL_GETCHIPID:
+ {
+ uint16_t chipid;
+
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+
+ RDAFM_GetChipID(fm->i2c_client, &chipid);
+ //chipid = fm->chip_id;
+ chipid = 0x6620;
+ FM_DEBUG("FM_IOCTL_GETCHIPID:%04x\n", chipid);
+ up(&fm_ops_mutex);
+
+ if (copy_to_user((void*)arg, &chipid, sizeof(uint16_t)))
+ return -EFAULT;
+
+ break;
+ }
+
+ case FM_IOCTL_EM_TEST:
+ {
+ struct fm_em_parm parm_em;
+ FM_DEBUG("FM_IOCTL_EM_TEST\n");
+
+// FIXME!!
+// if (!capable(CAP_SYS_ADMIN))
+// return -EPERM;
+
+ if (copy_from_user(&parm_em, (void*)arg, sizeof(struct fm_em_parm)))
+ return -EFAULT;
+
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+
+ RDAFM_em_test(fm->i2c_client, parm_em.group_idx, parm_em.item_idx, parm_em.item_value);
+
+ up(&fm_ops_mutex);
+
+ break;
+ }
+ case FM_IOCTL_IS_FM_POWERED_UP:
+ {
+ uint32_t powerup;
+ FM_DEBUG("FM_IOCTL_IS_FM_POWERED_UP");
+ if (fm->powerup) {
+ powerup = 1;
+ } else {
+ powerup = 0;
+ }
+ if (copy_to_user((void*)arg, &powerup, sizeof(uint32_t)))
+ return -EFAULT;
+ break;
+ }
+
+#ifdef FMDEBUG
+ case FM_IOCTL_DUMP_REG:
+ {
+ uint16_t chipid = 0;
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+ RDAFM_GetChipID(fm->i2c_client, &chipid);
+ up(&fm_ops_mutex);
+
+ break;
+ }
+#endif
+
+ case FM_IOCTL_SCAN:
+ {
+ struct fm_scan_parm parm;
+ FM_DEBUG("FM_IOCTL_SCAN\n");
+ if (false == fm->powerup){
+ return -EFAULT;
+ }
+ if(copy_from_user(&parm, (void*)arg, sizeof(struct fm_scan_parm))){
+ return -EFAULT;
+ }
+ if (down_interruptible(&fm_ops_mutex)){
+ return -EFAULT;
+ }
+ fm_scan(fm, &parm);
+ up(&fm_ops_mutex);
+
+ if(copy_to_user((void*)arg, &parm, sizeof(struct fm_scan_parm))){
+ return -EFAULT;
+ }
+
+ break;
+ }
+
+ case FM_IOCTL_STOP_SCAN:
+ {
+ FM_DEBUG("FM_IOCTL_STOP_SCAN\n");
+ break;
+ }
+
+ default:
+ {
+ FM_DEBUG("default\n");
+ break;
+ }
+ }
+
+ return ret;
+}
+static loff_t fm_ops_lseek(struct file *filp, loff_t off, int whence)
+{
+// struct fm *fm = filp->private_data;
+
+ if(whence == SEEK_END){
+ //fm_hwscan_stop(fm);
+ atomic_set(&scan_complete_flag, 0);
+ }else if(whence == SEEK_SET){
+ //FM_EVENT_SEND(fm->rds_event, FM_RDS_DATA_READY);
+ }
+ return off;
+}
+
+static int fm_ops_open(struct inode *inode, struct file *filp)
+{
+ struct fm *fm = container_of(inode->i_cdev, struct fm, cdev);
+
+ FM_DEBUG("%s\n", __func__);
+
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+
+ // TODO: only have to set in the first time?
+ // YES!!!!
+
+ fm->ref++;
+
+ up(&fm_ops_mutex);
+
+ filp->private_data = fm;
+
+ // TODO: check open flags
+
+ return 0;
+}
+
+static int fm_ops_release(struct inode *inode, struct file *filp)
+{
+ int err = 0;
+ struct fm *fm = container_of(inode->i_cdev, struct fm, cdev);
+
+ FM_DEBUG("%s\n", __func__);
+
+ if (down_interruptible(&fm_ops_mutex))
+ return -EFAULT;
+ fm->ref--;
+ if(fm->ref < 1) {
+ if(fm->powerup == true) {
+ fm_powerdown(fm);
+ }
+ }
+
+ up(&fm_ops_mutex);
+
+ return err;
+}
+
+//#define WMT_TEST_ORI 1
+
+static int fm_init(struct i2c_client *client)
+{
+ int err;
+ struct fm *fm = NULL;
+ int ret = -1;
+
+
+ FM_DEBUG("%s()\n", __func__);
+ if (!(fm = kzalloc(sizeof(struct fm), GFP_KERNEL)))
+ {
+ FM_ALERT("-ENOMEM\n");
+ err = -ENOMEM;
+ goto ERR_EXIT;
+ }
+
+ fm->ref = 0;
+ fm->powerup = false;
+ atomic_set(&scan_complete_flag, 0);
+
+#ifdef RDA599X_FM_SUPPORT
+
+ ret = rda_fm_power_on();
+ if(ret < 0){
+ err = -ENOMEM;
+ goto ERR_EXIT;
+ }
+ msleep(100);
+#endif
+
+ // First, read 5802NM chip ID
+ FM_DEBUG("%s()First, read 5802NM chip ID\n", __func__);
+ ret = RDAFM_GetChipID(client, &RDAFM_CHIP_ID);
+ if(ret < 0){
+ FM_DEBUG("%s() read RDA chip ID failed\n", __func__);
+ err = -ENOMEM;
+ goto ERR_EXIT;
+ }
+ else{
+ fm->chip_id = RDAFM_CHIP_ID;
+ }
+
+ FM_DEBUG("%s() 5802NM chip ID = 0x%04x\n", __func__, RDAFM_CHIP_ID);
+
+#ifdef RDA599X_FM_SUPPORT
+ ret = rda_fm_power_off();
+ if(ret < 0){
+ err = -ENOMEM;
+ goto ERR_EXIT;
+ }
+#endif
+
+
+#if WMT_TEST_ORI
+ printk("ori code\n");
+ // if failed, means use FM in 5990P_E
+ if(ret < 0){
+ // enable the FM chip in combo
+ FM_DEBUG("%s() enable the FM chip in combo\n", __func__);
+ ret = rda_fm_power_on();
+ if(ret < 0){
+ err = -ENOMEM;
+ goto ERR_EXIT;
+ }
+ msleep(100);
+ ret = RDAFM_GetChipID(client, &RDAFM_CHIP_ID);
+ FM_DEBUG("%s() the FM in combo chip ID = 0x%04x\n", __func__, RDAFM_CHIP_ID);
+ if(ret < 0){
+ err = -ENOMEM;
+ goto ERR_EXIT;
+ }else{
+ fm->chip_id = RDAFM_CHIP_ID;
+ }
+
+ // disable the FM chip for power saving
+ ret = rda_fm_power_off();
+ if(ret < 0){
+ err = -ENOMEM;
+ goto ERR_EXIT;
+ }
+ }else{
+ fm->chip_id = RDAFM_CHIP_ID;
+ }
+
+
+#endif
+
+
+ if ((err = fm_setup_cdev(fm)))
+ {
+ goto ERR_EXIT;
+ }
+
+ g_fm_struct = fm;
+ fm->i2c_client = client;
+ i2c_set_clientdata(client, fm);
+
+
+ /***********Add porc file system*************/
+
+ g_fm_proc = create_proc_entry(FM_PROC_FILE, 0444, NULL);
+ if (g_fm_proc == NULL) {
+ FM_ALERT("create_proc_entry failed\n");
+ err = -ENOMEM;
+ goto ERR_EXIT;
+ } else {
+ g_fm_proc->read_proc = fm_proc_read;
+ g_fm_proc->write_proc = NULL;
+ //g_fm_proc->owner = THIS_MODULE;
+ FM_ALERT("create_proc_entry success\n");
+ }
+
+ /********************************************/
+
+ FM_DEBUG("fm_init is ok!\n");
+
+ return 0;
+
+ERR_EXIT:
+ kfree(fm);
+#ifdef RDA599X_FM_SUPPORT
+ rda_fm_power_off();
+#endif
+
+ return err;
+}
+
+static int fm_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int cnt= 0;
+ struct fm *fm = g_fm_struct;
+ FM_ALERT("Enter fm_proc_read.\n");
+ if(off != 0)
+ return 0;
+ if (fm != NULL && fm->powerup) {
+ cnt = sprintf(page, "1\n");
+ } else {
+ cnt = sprintf(page, "0\n");
+ }
+ *eof = 1;
+ FM_ALERT("Leave fm_proc_read. cnt = %d\n", cnt);
+ return cnt;
+}
+
+
+static int fm_destroy(struct fm *fm)
+{
+ int err = 0;
+
+ FM_DEBUG("%s\n", __func__);
+
+ device_destroy(fm->cls, fm->dev_t);
+ class_destroy(fm->cls);
+
+ cdev_del(&fm->cdev);
+ unregister_chrdev_region(fm->dev_t, 1);
+
+ fm_powerdown(fm);
+
+ /***********************************/
+ remove_proc_entry(FM_PROC_FILE, NULL);
+
+ /**********************************/
+
+ // FIXME: any other hardware configuration ?
+
+ // free all memory
+ kfree(fm);
+
+ return err;
+}
+
+/*
+ * fm_powerup
+ */
+static int fm_powerup(struct fm *fm, struct fm_tune_parm *parm)
+{
+ int i;
+ uint16_t tRegValue = 0x0002;
+ int ret = -1;
+
+ struct i2c_client *client = fm->i2c_client;
+
+ if (fm->powerup)
+ {
+ parm->err = FM_BADSTATUS;
+ return -EPERM;
+ }
+
+ // if chip_id is ID_RDA5820NS, enable the FM chip in combo
+#ifdef RDA599X_FM_SUPPORT
+ ret = rda_fm_power_on();
+ if(ret < 0){
+ return -EPERM;
+ }
+ msleep(100);
+#endif
+
+
+ //Reset RDA FM
+ tRegValue = 0x0002;
+ RDAFM_write(client, 0x02, tRegValue);
+ msleep(100);
+
+ if ((ID_RDA5802N == RDAFM_CHIP_ID) || (ID_RDA5802H == RDAFM_CHIP_ID)){
+ //if (ID_RDA5802N == RDAFM_CHIP_ID){
+
+ for (i=0; i<((sizeof(RDA5802N_initialization_reg)) / (sizeof(uint16_t))); i++)
+ {
+ ret = RDAFM_write(client, i+2, RDA5802N_initialization_reg[i]);
+
+ if (ret < 0)
+ {
+ FM_DEBUG("fm_powerup init failed!\n");
+ FM_ALERT("fm_powerup init failed!\n");
+ parm->err = FM_FAILED;
+
+ return -EPERM;
+ }
+ }
+
+ }else if (ID_RDA5820NS == RDAFM_CHIP_ID){
+ if(RDA_RADIO_WorkType == FM_RECEIVER){
+ for (i = 0; i < ((sizeof(RDA5820NS_RX_initialization_reg)) / (sizeof(RDA_FM_REG_T))); i++)
+ {
+ if(RDA5820NS_RX_initialization_reg[i].address == 0xFF){
+ msleep(RDA5820NS_RX_initialization_reg[i].value);
+ }else{
+ ret = RDAFM_write(client, RDA5820NS_RX_initialization_reg[i].address, RDA5820NS_RX_initialization_reg[i].value);
+ if (ret < 0)
+ {
+ FM_DEBUG("fm_powerup init failed!\n");
+ parm->err = FM_FAILED;
+ return -EPERM;
+ }
+ }
+ }
+ }else{
+ for (i = 0; i < ((sizeof(RDA5820NS_TX_initialization_reg)) / (sizeof(RDA_FM_REG_T))); i++)
+ {
+ if(RDA5820NS_TX_initialization_reg[i].address == 0xFF){
+ msleep(RDA5820NS_TX_initialization_reg[i].value);
+ }else{
+ ret = RDAFM_write(client, RDA5820NS_TX_initialization_reg[i].address, RDA5820NS_TX_initialization_reg[i].value);
+ if (ret < 0)
+ {
+ FM_DEBUG("fm_powerup init failed!\n");
+ parm->err = FM_FAILED;
+ return -EPERM;
+ }
+ }
+ }
+ }
+
+ }
+
+
+ FM_DEBUG("pwron ok\n");
+ fm->powerup = true;
+
+ if (fm_tune(fm, parm) < 0)
+ {
+ return -EPERM;
+ }
+ fm_tune_data.byPowerUp = true;
+ memcpy(&fm_tune_data.parm, parm, sizeof(fm_tune_data.parm));
+
+ parm->err = FM_SUCCESS;
+
+ return 0;
+
+}
+
+/*
+ * fm_powerdown
+ */
+static int fm_powerdown(struct fm *fm)
+{
+ uint16_t tRegValue = 0;
+ int ret = -1;
+ struct i2c_client *client = fm->i2c_client;
+
+ RDAFM_read(client, 0x02, &tRegValue);
+ tRegValue &= (~(1 << 0));
+ RDAFM_write(client, 0x02, tRegValue);
+/*
+ if((fm->chip_id == ID_RDA5820NS) || (fm->chip_id == ID_RDA5991_FM){
+ ret = rda_fm_power_off();
+ if(ret < 0){
+ return -EPERM;
+ }
+ }
+*/
+
+#ifdef RDA599X_FM_SUPPORT
+ ret = rda_fm_power_off();
+ if(ret < 0){
+ return -EPERM;
+ }
+#endif
+
+
+ fm->powerup = false;
+ FM_ALERT("pwrdown ok\n");
+
+ return 0;
+}
+
+/*
+ * fm_seek
+ */
+static int fm_seek(struct fm *fm, struct fm_seek_parm *parm)
+{
+ int ret = 0;
+ uint16_t val = 0;
+ uint8_t spaec = 1;
+ uint16_t tFreq = 875;
+ uint16_t tRegValue = 0;
+ uint16_t bottomOfBand = 875;
+ int falseStation = -1;
+
+
+ struct i2c_client *client = fm->i2c_client;
+
+ if (!fm->powerup)
+ {
+ parm->err = FM_BADSTATUS;
+ return -EPERM;
+ }
+
+ if (parm->space == FM_SPACE_100K)
+ {
+ spaec = 1;
+ val &= (~((1<<0) | (1<<1)));
+ }
+ else if (parm->space == FM_SPACE_200K)
+ {
+ spaec = 2;
+ val &= (~(1<<1));
+ val |= (1<<0);
+ }
+ else
+ {
+ parm->err = FM_EPARM;
+ return -EPERM;
+ }
+
+ if (parm->band == FM_BAND_UE)
+ {
+ val &= (~((1<<2) | (1<<3)));
+ bottomOfBand = 875;
+ fm->min_freq = 875;
+ fm->max_freq = 1080;
+ }
+ else if (parm->band == FM_BAND_JAPAN)
+ {
+ val &= (~(1<<3));
+ val |= (1 << 2);
+ bottomOfBand = 760;
+ fm->min_freq = 760;
+ fm->max_freq = 910;
+ }
+ else if (parm->band == FM_BAND_JAPANW) {
+ val &= (~(1<<2));
+ val |= (1 << 3);
+ bottomOfBand = 760;
+ fm->min_freq = 760;
+ fm->max_freq = 1080;
+ }
+ else
+ {
+ FM_ALERT("band:%d out of range\n", parm->band);
+ parm->err = FM_EPARM;
+ return -EPERM;
+ }
+
+ if (parm->freq < fm->min_freq || parm->freq > fm->max_freq) {
+ FM_ALERT("freq:%d out of range\n", parm->freq);
+ parm->err = FM_EPARM;
+ return -EPERM;
+ }
+
+ if (parm->seekth > 0x0B) {
+ FM_ALERT("seekth:%d out of range\n", parm->seekth);
+ parm->err = FM_EPARM;
+ return -EPERM;
+ }
+#if 0
+ RDAFM_read(client, 0x05, &tRegValue);
+ tRegValue &= (~(0x7f<<8));
+ //tRegValue |= ((parm->seekth & 0x7f) << 8);
+ tRegValue |= ((0x8 & 0x7f) << 8);
+ RDAFM_write(client, 0x05, tRegValue);
+#endif
+
+#ifdef FMDEBUG
+ if (parm->seekdir == FM_SEEK_UP)
+ FM_DEBUG("seek %d up\n", parm->freq);
+ else
+ FM_DEBUG("seek %d down\n", parm->freq);
+#endif
+
+ // (1) set hmute bit
+ RDAFM_enable_hmute(client);
+
+ tFreq = parm->freq;
+
+ do {
+ if (parm->seekdir == FM_SEEK_UP)
+ tFreq += spaec;
+ else
+ tFreq -= spaec;
+
+ if (tFreq > fm->max_freq)
+ tFreq = fm->min_freq;
+ if (tFreq < fm->min_freq)
+ tFreq = fm->max_freq;
+
+ val = (((tFreq - bottomOfBand+5) << 6) | (1 << 4) | (val & 0x0f));
+ RDAFM_write(client, 0x03, val);
+ msleep(40);
+ ret = RDAFM_read(client, 0x0B, &tRegValue);
+ if (ret < 0)
+ {
+ FM_DEBUG("fm_seek: read register failed tunning freq = %4X\n", tFreq);
+ falseStation = -1;
+ }
+ else
+ {
+ if ((tRegValue & 0x0100) == 0x0100)
+ falseStation = 0;
+ else
+ falseStation = -1;
+ }
+
+ if(falseStation == 0)
+ break;
+ }while(tFreq != parm->freq);
+
+
+ //clear hmute
+ RDAFM_clear_hmute(client);
+
+ if (falseStation == 0) // seek successfully
+ {
+ parm->freq = tFreq;
+ FM_ALERT("fm_seek success, freq:%d\n", parm->freq);
+ parm->err = FM_SUCCESS;
+ }
+ else
+ {
+ FM_ALERT("fm_seek failed, invalid freq\n");
+ parm->err = FM_SEEK_FAILED;
+ ret = -1;
+ }
+
+ return ret;
+}
+static int fm_scan(struct fm *fm, struct fm_scan_parm *parm)
+{
+ int ret = 0;
+ uint16_t tRegValue = 0;
+ uint16_t scandir = RDA599X_FM_SCAN_UP; //scandir
+ uint8_t space = 1;
+ struct i2c_client *client = fm->i2c_client;
+
+ if (!fm->powerup){
+ parm->err = FM_BADSTATUS;
+ return -EPERM;
+ }
+
+ RDAFM_read(client, 0x03, &tRegValue);
+
+ if (parm->space == FM_SPACE_100K){
+ space = 1;
+ tRegValue &= (~((1<<0) | (1<<1))); //set 03H's bit[1:0] to 00
+ }else if (parm->space == FM_SPACE_200K) {
+ space = 2;
+ tRegValue &= (~(1<<1)); //clear bit[1]
+ tRegValue |= (1<<0); //set bit[0]
+ }else{
+ //default
+ space = 1;
+ tRegValue &= (~((1<<0) | (1<<1))); //set 03H's bit[1:0] to 00
+ }
+
+ if(parm->band == FM_BAND_UE){
+ tRegValue &= (~((1<<2) | (1<<3)));
+ fm->min_freq = 875;
+ fm->max_freq = 1080;
+ }else if(parm->band == FM_BAND_JAPAN){
+ tRegValue &= (~(1<<3));
+ tRegValue |= (1 << 2);
+ fm->min_freq = 760;
+ fm->max_freq = 900;
+ }else if(parm->band == FM_BAND_JAPANW){
+ tRegValue &= (~(1<<2));
+ tRegValue |= (1 << 3);
+ fm->min_freq = 760;
+ fm->max_freq = 1080;
+ }else{
+ parm->err = FM_EPARM;
+ return -EPERM;
+ }
+
+ //set space and band
+ RDAFM_write(client, 0x03, tRegValue);
+ msleep(40);
+
+
+ if(RDAFM_Scan(client, fm->min_freq, fm->max_freq, &(parm->freq), parm->ScanTBL, &(parm->ScanTBLSize), scandir, space)){
+ parm->err = FM_SUCCESS;
+ }else{
+ parm->err = FM_SEEK_FAILED;
+ }
+
+ return ret;
+}
+
+
+static int fm_setvol(struct fm *fm, uint32_t vol)
+{
+ int ret = 0;
+ uint16_t tRegValue = 0;
+ struct i2c_client *client = fm->i2c_client;
+
+ if (vol > 15)
+ vol = 15;
+
+ FM_DEBUG("fm_setvol:%d\n", vol);
+
+ ret = RDAFM_read(client, 0x05, &tRegValue);
+ if (ret)
+ return -EPERM;
+ tRegValue &= ~(0x000f);
+ tRegValue |= vol;
+
+ ret = RDAFM_write(client, 0x05, tRegValue);
+ if (ret)
+ return -EPERM;
+
+ return 0;
+}
+
+static int fm_getvol(struct fm *fm, uint32_t *vol)
+{
+ int ret = 0;
+ uint16_t tRegValue;
+ struct i2c_client *client = fm->i2c_client;
+
+ ret = RDAFM_read(client, 0x05, &tRegValue);
+ if (ret)
+ return -EPERM;
+
+
+ *vol = (tRegValue & 0x000F);
+
+ return 0;
+}
+
+static int fm_getrssi(struct fm *fm, uint32_t *rssi)
+{
+ int ret = 0;
+ uint16_t tRegValue;
+ struct i2c_client *client = fm->i2c_client;
+
+ ret = RDAFM_read(client, 0x0B, &tRegValue);
+ if (ret)
+ return -EPERM;
+
+
+ *rssi = (uint32_t)((tRegValue >> 9) & RDAFM_MASK_RSSI);
+
+ FM_DEBUG("rssi value:%d\n", *rssi);
+
+ return 0;
+}
+
+/*
+ * fm_tune
+ */
+static int fm_tune(struct fm *fm, struct fm_tune_parm *parm)
+{
+ int ret;
+ uint16_t val = 0;
+ uint8_t space = 1;
+ uint16_t bottomOfBand = 875;
+
+ struct i2c_client *client = fm->i2c_client;
+
+ FM_DEBUG("%s\n", __func__);
+
+ if (!fm->powerup)
+ {
+ parm->err = FM_BADSTATUS;
+ return -EPERM;
+ }
+
+ if (parm->space == FM_SPACE_100K)
+ {
+ space = 1;
+ val &= (~((1<<0) | (1<<1)));
+ }
+ else if (parm->space == FM_SPACE_200K)
+ {
+ space = 2;
+ val |= (1<<0);
+ val &= (~(1<<1));
+ }
+ else
+ {
+ parm->err = FM_EPARM;
+ return -EPERM;
+ }
+
+ if (parm->band == FM_BAND_UE)
+ {
+ val &= (~((1<<2) | (1<<3)));
+ bottomOfBand = 875;
+ fm->min_freq = 875;
+ fm->max_freq = 1080;
+ }
+ else if (parm->band == FM_BAND_JAPAN)
+ {
+ val &= (~(1<<3));
+ val |= (1 << 2);
+ bottomOfBand = 760;
+ fm->min_freq = 760;
+ fm->max_freq = 910;
+ }
+ else if (parm->band == FM_BAND_JAPANW) {
+ val &= (~(1<<2));
+ val |= (1 << 3);
+ bottomOfBand = 760;
+ fm->min_freq = 760;
+ fm->max_freq = 1080;
+ }
+ else
+ {
+ FM_ALERT("band:%d out of range\n", parm->band);
+ parm->err = FM_EPARM;
+ return -EPERM;
+ }
+
+ if (parm->freq < fm->min_freq || parm->freq > fm->max_freq) {
+ FM_ALERT("freq:%d out of range\n", parm->freq);
+ parm->err = FM_EPARM;
+ return -EPERM;
+ }
+
+ FM_DEBUG("fm_tune, freq:%d\n", parm->freq);
+
+ //RDAFM_enable_hmute(client);
+
+ val = (((parm->freq - bottomOfBand + 5) << 6) | (1 << 4) | (val & 0x0f));
+
+ ret = RDAFM_write(client, 0x03, val);
+ if (ret < 0)
+ {
+ FM_ALERT("fm_tune write freq failed\n");
+ parm->err = FM_SEEK_FAILED;
+ return ret;
+ }
+ msleep(40);
+
+#ifdef FM_DEBUG
+ RDAFM_read(client, 0x0A, &val);
+ FM_DEBUG("%s() read freq reg value = 0x%04x\n", __func__, val);
+#endif
+
+ return ret;
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31))
+/*
+ * fm_i2c_attach_adapter
+ */
+static int fm_i2c_attach_adapter(struct i2c_adapter *adapter)
+{
+ int err = 0;
+
+ if (adapter->id == RDAFM_I2C_PORT)
+ {
+ return i2c_probe(adapter, &RDAFM_addr_data, fm_i2c_detect);
+ }
+
+ return err;
+}
+
+/*
+ * fm_i2c_detect
+ * This function is called by i2c_detect
+ */
+static int fm_i2c_detect(struct i2c_adapter *adapter, int addr, int kind)
+{
+ int err;
+ struct i2c_client *client = NULL;
+
+ /* skip this since MT6516 shall support all the needed functionalities
+ if (!i2c_check_functionality(adapter, xxx))
+ {
+ FM_DEBUG("i2c_check_functionality failed\n");
+ return -ENOTSUPP;
+ }
+ */
+
+ /* initial i2c client */
+ if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL)))
+ {
+ FM_ALERT("kzalloc failed\n");
+ err = -ENOMEM;
+ goto ERR_EXIT;
+ }
+
+ client->addr = addr;
+ client->adapter = adapter;
+ client->driver = &RDAFM_driver;
+ client->flags = 0;
+ strncpy(client->name, "RDA FM RADIO", I2C_NAME_SIZE);
+
+ if ((err = fm_init(client)))
+ {
+ FM_ALERT("fm_init ERR:%d\n", err);
+ goto ERR_EXIT;
+ }
+
+ if (err = i2c_attach_client(client))
+ {
+ FM_ALERT("i2c_attach_client ERR:%d\n", err);
+ goto ERR_EXIT;
+ }
+
+ return 0;
+
+ERR_EXIT:
+ kfree(client);
+
+ return err;
+}
+static int fm_i2c_detach_client(struct i2c_client *client)
+{
+ int err = 0;
+ struct fm *fm = i2c_get_clientdata(client);
+
+ FM_DEBUG("fm_i2c_detach_client\n");
+
+ err = i2c_detach_client(client);
+ if (err)
+ {
+ dev_err(&client->dev, "fm_i2c_detach_client failed\n");
+ return err;
+ }
+
+ fm_destroy(fm);
+ kfree(client);
+
+ return err;
+}
+#else
+static int fm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int err = -1;
+ FM_DEBUG("fm_i2c_probe\n");
+ //client->timing = 50;
+ //client->timing = 200;
+ if ((err = fm_init(client)))
+ {
+ FM_ALERT("fm_init ERR:%d\n", err);
+ goto ERR_EXIT;
+ }
+
+ return 0;
+
+ERR_EXIT:
+ return err;
+}
+/*
+static int fm_for_read_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ client_for_read = client;
+ return 0;
+}
+*/
+
+static int fm_i2c_detect(struct i2c_client *client, struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ if(adapter->nr == 1)
+ {
+ FM_DEBUG("fm_i2c_detect\n");
+ strcpy(info->type, RDAFM_DEV);
+ return 0;
+ }
+ else
+ {
+ return -ENODEV;
+ }
+}
+/*
+static int fm_for_read_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info)
+{
+ FM_DEBUG("fm_wifi_i2c_detect\n");
+ printk(KERN_DEBUG "####[%s(): %d]\n", __func__, __LINE__);
+ strcpy(info->type, RDAFM_READ_DEV);
+ return 0;
+}
+*/
+
+static int fm_i2c_remove(struct i2c_client *client)
+{
+ int err = 0;
+ struct fm *fm = i2c_get_clientdata(client);
+
+ FM_DEBUG("fm_i2c_remove\n");
+ if(fm)
+ {
+ fm_destroy(fm);
+ fm = NULL;
+ }
+
+ return err;
+}
+/*
+static int fm_for_read_i2c_remove(struct i2c_client *client)
+{
+ return 0;
+}
+*/
+#endif
+
+static int mt_fm_probe(struct platform_device *pdev)
+{
+ int err = -1;
+ FM_ALERT("mt_fm_probe\n");
+
+ /*
+ printk(KERN_DEBUG "####[%s(): %d]\n", __func__, __LINE__);
+ err = i2c_add_driver(&RDAFM_for_read_driver);
+ if (err)
+ {
+ FM_ALERT("i2c err\n");
+ }
+ */
+
+ // Open I2C driver
+ err = i2c_add_driver(&RDAFM_driver);
+ if (err)
+ {
+ FM_ALERT("i2c err\n");
+ }
+
+ return err;
+}
+
+static int mt_fm_remove(struct platform_device *pdev)
+{
+ FM_ALERT("mt_fm_remove\n");
+ i2c_del_driver(&RDAFM_driver);
+
+ return 0;
+}
+
+
+static struct platform_driver mt_fm_dev_drv =
+{
+ .probe = mt_fm_probe,
+ .remove = mt_fm_remove,
+#if 0//def CONFIG_PM //Not need now
+ .suspend = mt_fm_suspend,
+ .resume = mt_fm_resume,
+#endif
+ .driver = {
+ .name = FM_NAME,
+ .owner = THIS_MODULE,
+ }
+};
+
+
+
+#if defined(MTK_MT6515)
+static void fm_release(struct device * dev) {}
+
+static struct platform_device mt_fm_device = {
+ .name = FM_NAME,
+ .id = 0,
+ .dev = {
+ .release = fm_release,
+ },
+
+};
+#endif
+
+static void fm_test_tune()
+{
+ struct fm *fm;
+ struct fm_tune_parm parm;
+
+ fm_powerup(fm, &parm);
+}
+
+static struct i2c_client *rda_fm=NULL;
+
+#define RDA_FM_ADDR (0x11)
+#define RDA_FM_I2C_DEVNAME "RDA_FM"
+struct i2c_board_info rda_fm_i2c_board_info = {
+ .type = RDA_FM_I2C_DEVNAME,
+ .flags = 0x00,
+ .addr = RDA_FM_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int rda_i2c_register_device (struct i2c_board_info *ts_i2c_bi,struct i2c_client **l_client)
+{
+ struct i2c_adapter *adapter = NULL;
+
+ adapter = i2c_get_adapter(4);
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ *l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (*l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void rda_i2c_unregister_device(struct i2c_client *l_client)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+
+
+/*
+ * mt_fm_init
+ */
+static int __init mt_fm_init(void)
+{
+ int err = 0;
+ rda_i2c_register_device(&rda_fm_i2c_board_info,&rda_fm);
+
+ FM_ALERT("mt_fm_init\n");
+#if defined(MTK_MT6515)
+ err = platform_device_register(&mt_fm_device);
+ if(err){
+ FM_ALERT("platform_device_register fail\n");
+ return err;
+ }else{
+ FM_ALERT("platform_device_register success\n");
+ }
+#endif
+ err = platform_driver_register(&mt_fm_dev_drv);
+ if (err)
+ {
+ FM_ALERT("platform_driver_register failed\n");
+ }else{
+ FM_ALERT("platform_driver_register success\n");
+ }
+
+ return err;
+}
+
+/*
+ * mt_fm_exit
+ */
+static void __exit mt_fm_exit(void)
+{
+ FM_ALERT("mt_fm_exit\n");
+ platform_driver_unregister(&mt_fm_dev_drv);
+#if defined(MTK_MT6515)
+ platform_device_unregister(&mt_fm_device);
+#endif
+
+ rda_i2c_unregister_device(rda_fm);
+
+}
+
+module_init(mt_fm_init);
+module_exit(mt_fm_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MediaTek FM Driver");
+MODULE_AUTHOR("William Chung <William.Chung@MediaTek.com>");
+
+
diff --git a/drivers/net/wireless/rda/rda_wlan/Makefile b/drivers/net/wireless/rda/rda_wlan/Makefile
new file mode 100755
index 00000000..1be8914f
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/Makefile
@@ -0,0 +1,17 @@
+obj-m := rda_wlan.o
+rda_wlan-objs := \
+ wlan_module.o \
+ wlan_init.o \
+ wlan_rxtx.o \
+ wlan_wid.o \
+ wlan_wext.o \
+ wlan_sdio_patch.o \
+ wlan_nvram.o \
+ wlan_scan.o \
+ wlan_assoc.o \
+ wlan_sdio.o \
+ wlan_event.o\
+ wlan_debugfs.o\
+ wlan_aver_rssi.o
+
+subdir-ccflags-y := -Werror
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_assoc.c b/drivers/net/wireless/rda/rda_wlan/wlan_assoc.c
new file mode 100755
index 00000000..714c6c31
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_assoc.c
@@ -0,0 +1,228 @@
+#include "wlan_includes.h"
+
+
+//imode
+/* BIT0: 1 -> Security ON 0 -> OFF */
+/* BIT1: 1 -> WEP40 cypher supported 0 -> Not supported */
+/* BIT2: 1 -> WEP104 cypher supported 0 -> Not supported */
+/* BIT3: 1 -> WPA mode supported 0 -> Not supported */
+/* BIT4: 1 -> WPA2 (RSN) supported 0 -> Not supported */
+/* BIT5: 1 -> AES-CCMP cphr supported 0 -> Not supported */
+/* BIT6: 1 -> TKIP cypher supported 0 -> Not supported */
+/* BIT7: 1 -> TSN supported 0 -> Not supported */
+
+//authtype
+/* BIT0: 1 -> OPEN SYSTEM */
+/* BIT1: 1 -> SHARED KEY */
+/* BIT3: 1 -> WAPI */
+static int assoc_helper_secinfo(wlan_private *priv,
+ struct bss_descriptor *assoc_bss)
+{
+ int ret = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+
+ /* set imode and key */
+ if ( !priv->secinfo.wep_enabled
+ && !priv->secinfo.WPAenabled && !priv->secinfo.WPA2enabled) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "%s, NO SEC\n", __func__);
+ priv->imode = 0;
+ } else {
+ u16 key_len = 0;
+
+ if ( priv->secinfo.wep_enabled
+ && !priv->secinfo.WPAenabled
+ && !priv->secinfo.WPA2enabled) {
+ /* WEP */
+ key_len = priv->wep_keys[0].len;
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "%s, WEP, len = %d\n", __func__, key_len * 8);
+ if (key_len == KEY_LEN_WEP_40) {
+ priv->imode = BIT0 | BIT1;
+ } else if (key_len == KEY_LEN_WEP_104) {
+ priv->imode = BIT0 | BIT2;
+ } else {
+ WLAN_ERRP("Invalide WEP Key length %d\n", key_len);
+ ret = -EINVAL;
+ goto out;
+ }
+ } else if ( !priv->secinfo.wep_enabled
+ && (priv->secinfo.WPAenabled ||
+ priv->secinfo.WPA2enabled)) {
+ /* WPA */
+ struct enc_key * pkey = NULL;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "%s, WPA cp:%x wpa:%d wpa2:%d \n", __func__, priv->secinfo.cipther_type, priv->secinfo.WPAenabled, priv->secinfo.WPA2enabled);
+
+ if ( priv->wpa_mcast_key.len
+ && (priv->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED))
+ pkey = &priv->wpa_mcast_key;
+ else if ( priv->wpa_unicast_key.len
+ && (priv->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED))
+ pkey = &priv->wpa_unicast_key;
+
+ priv->imode = 0;
+ /* turn on security */
+ priv->imode |= (BIT0);
+ priv->imode &= ~(BIT3 | BIT4);
+ if (priv->secinfo.WPA2enabled)
+ priv->imode |= (BIT4);
+ else if (priv->secinfo.WPAenabled)
+ priv->imode |= (BIT3);
+ /*
+ * we don't know the cipher type by now
+ * use dot11i_info to decide
+ * and use CCMP if possible
+ */
+ priv->imode &= ~(BIT5 | BIT6);
+ if (priv->secinfo.cipther_type & IW_AUTH_CIPHER_CCMP)
+ priv->imode |= BIT5;
+ else if (priv->secinfo.cipther_type & IW_AUTH_CIPHER_TKIP)
+ priv->imode |= BIT6;
+ } else {
+ WLAN_ERRP("WEP and WPA/WPA2 enabled simutanously\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ /* set authtype */
+ if (priv->secinfo.auth_mode & IW_AUTH_ALG_OPEN_SYSTEM
+ || priv->secinfo.auth_mode & IW_AUTH_ALG_SHARED_KEY){
+
+ if (priv->secinfo.auth_mode & IW_AUTH_ALG_OPEN_SYSTEM){
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "%s, Open Auth, KEY_MGMT = %d, AUTH_ALG mode:%x\n", __func__, priv->secinfo.key_mgmt, priv->secinfo.auth_mode);
+ if (priv->secinfo.key_mgmt == 0x01)
+ priv->authtype = BIT2;
+ else
+ priv->authtype = BIT0;
+ }else if(priv->secinfo.auth_mode & IW_AUTH_ALG_SHARED_KEY){
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "%s, Shared-Key Auth AUTH_ALG mode:%x \n", __func__, priv->secinfo.auth_mode);
+ priv->authtype = BIT1;
+ }
+
+ if (priv->secinfo.key_mgmt == WAPI_KEY_MGMT_PSK
+ || priv->secinfo.key_mgmt == WAPI_KEY_MGMT_CERT)
+ priv->authtype = BIT3;
+
+ }else if (priv->secinfo.auth_mode == IW_AUTH_ALG_WAPI) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "%s, Shared-Key Auth\n", __func__);
+ priv->authtype = IW_AUTH_ALG_WAPI;
+ }else if (priv->secinfo.auth_mode == IW_AUTH_ALG_LEAP) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "%s, LEAP Auth, not supported\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }else {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "%s, Unknown Auth\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+out:
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>> \n", __func__);
+ return ret;
+}
+
+
+void wlan_assocication(wlan_private* priv)
+{
+ int ret = 0;
+ struct bss_descriptor *assoc_bss;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ assoc_bss = get_bss_desc_from_scanlist(priv, priv->assoc_bssid);
+ if (assoc_bss == NULL) {
+ WLAN_ERRP("****fail to find bss in the scan list\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ priv->curbssparams.channel = assoc_bss->channel;
+ memcpy(priv->curbssparams.bssid, assoc_bss->bssid, ETH_ALEN);
+ memcpy(priv->curbssparams.ssid, assoc_bss->ssid,IW_ESSID_MAX_SIZE + 1);
+
+ ret = assoc_helper_secinfo(priv, assoc_bss);
+ if (ret) {
+ WLAN_ERRP("assoc_helper_secinfo fail, ret = %d\n", ret);
+ goto out;
+ }
+
+ //wep so we need retry association
+ if (priv->imode & 0x06) {
+ priv->ToggalAssociation = TRUE;
+ }
+
+ ret = wlan_start_join(priv);
+ if (ret) {
+ WLAN_ERRP("wlan_set_ssid fail, ret = %d\n", ret);
+ wlan_cancel_timer(&priv->AssociationTimeOut);
+ priv->assoc_ongoing = FALSE;
+ goto out;
+ }
+
+ //25S for association
+ wlan_mod_timer(&priv->AssociationTimeOut, 25000);
+
+ //reassociation
+ wlan_mod_timer(&priv->ReAssociationTimeOut, 3000);
+out:
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<< \n", __func__);
+}
+
+void wlan_re_assocication(wlan_private* priv)
+{
+ int ret = 0;
+
+ ENTER();
+#ifdef WLAN_FORCE_SUSPEND_SUPPORT
+ if (priv->CardInSuspend == TRUE) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s ingnored in ap deep sleep mode.\n", __func__);
+ return;
+ }
+#endif
+ if(priv->connect_status == MAC_CONNECTED)
+ return;
+ if(priv->reassoc_count++ > 4)
+ return;
+ //wep shared key & open turn arount
+ if (priv->imode & 0x06) {
+ if (priv->authtype == 0x01)
+ priv->authtype = 0x02;
+ else
+ priv->authtype = 0x01;
+ }
+
+ ret = wlan_start_join(priv);
+ if (ret) {
+ WLAN_ERRP("wlan_set_ssid fail, ret = %d\n", ret);
+ return;
+ }
+
+ wlan_mod_timer(&priv->ReAssociationTimeOut, 3000);
+ LEAVE();
+}
+
+void wlan_assocication_timeout(wlan_private* priv)
+{
+
+ ENTER();
+
+
+ wlan_cancel_timer(&priv->ReAssociationTimeOut);
+
+ priv->assoc_ongoing = FALSE;
+ wlan_assoc_power_save(priv);
+ //restore tx rate
+ wlan_set_txrate(priv, 0);
+
+ LEAVE();
+}
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_aver_rssi.c b/drivers/net/wireless/rda/rda_wlan/wlan_aver_rssi.c
new file mode 100755
index 00000000..c4518238
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_aver_rssi.c
@@ -0,0 +1,152 @@
+#include "wlan_includes.h"
+
+DEFINE_SPINLOCK(rssi_buf_lock);
+
+void wlan_add_new_aver_rssi(wlan_private * priv, u8 * bssid, u8 rssi)
+{
+ t_aver_bssid_rssi * list = (t_aver_bssid_rssi *)kmalloc(sizeof(t_aver_bssid_rssi), GFP_KERNEL);
+
+ if(!list)
+ return;
+
+ list->dirty = 0;
+ memset(list->rssi, 0, sizeof(list->rssi));
+
+ if(((s8)rssi) > 0)
+ rssi -= 0x100;
+ else if(((s8)rssi) > -20)
+ rssi = ((s8)rssi) - 20;
+
+ list->rssi[0] = rssi;
+ list->index = 1;
+ list->count = 1;
+ memcpy(list->bssid, bssid, 6);
+
+ spin_lock(&rssi_buf_lock);
+ list_add_tail(&list->list, &priv->AverRssiQ);
+ spin_unlock(&rssi_buf_lock);
+}
+
+t_aver_bssid_rssi* wlan_find_bssid_in_aver_rssi(wlan_private * priv, u8 * bssid)
+{
+ t_aver_bssid_rssi * rssi_list = NULL;
+
+ spin_lock(&rssi_buf_lock);
+
+ if(list_empty(&priv->AverRssiQ)){
+ spin_unlock(&rssi_buf_lock);
+ return NULL;
+ }
+
+ list_for_each_entry(rssi_list, &priv->AverRssiQ, list){
+ if(memcmp(bssid, rssi_list->bssid, 6) == 0){
+ spin_unlock(&rssi_buf_lock);
+ return rssi_list;
+ }
+ }
+
+ spin_unlock(&rssi_buf_lock);
+ return NULL;
+}
+
+void wlan_set_aver_rssi(t_aver_bssid_rssi* aver_rssi, u8 rssi)
+{
+ u8 index = 0;
+
+ u8 *ch = 0;
+ ch = aver_rssi->bssid;
+
+ if(((s8)rssi) > 0)
+ rssi -= 0x100;
+ else if(((s8)rssi) > -20)
+ rssi = ((s8)rssi) - 20;
+
+ index = aver_rssi->index;
+ aver_rssi->rssi[index] = rssi;
+ index = (index + 1)%MAX_RSSI_RECORD;
+ aver_rssi->index = index;
+
+ if(aver_rssi->count < MAX_RSSI_RECORD)
+ aver_rssi->count ++;
+
+ if(aver_rssi->dirty > 0)
+ aver_rssi->dirty --;
+}
+
+void wlan_update_aver_rssi(wlan_private * priv, u8 * bssid, u8 rssi)
+{
+ t_aver_bssid_rssi* aver_rssi = NULL;
+
+ aver_rssi = wlan_find_bssid_in_aver_rssi(priv, bssid);
+ if(aver_rssi)
+ wlan_set_aver_rssi(aver_rssi, rssi);
+ else
+ wlan_add_new_aver_rssi(priv, bssid, rssi);
+}
+
+s8 wlan_cal_aver_rssi(t_aver_bssid_rssi* aver_rssi)
+{
+ s32 rssi = 0;
+ u8 i = 0, count = 0;
+
+ count = aver_rssi->count;
+
+ for(i = 0; i < count; i ++){
+ rssi += (s8)aver_rssi->rssi[i];
+ }
+ //-15 was hardware diff
+ return ((s8)(rssi/count)) - 15;
+}
+
+s8 wlan_get_aver_rssi(wlan_private * priv, u8 * bssid)
+{
+ t_aver_bssid_rssi * rssi_list = NULL;
+
+ rssi_list = wlan_find_bssid_in_aver_rssi(priv, bssid);
+ if(rssi_list)
+ return wlan_cal_aver_rssi(rssi_list);
+ else{
+ return INVALID_RSSI;
+ }
+}
+
+void wlan_set_rssi_dirty(wlan_private * priv)
+{
+ t_aver_bssid_rssi * rssi_list = NULL, *next = NULL;
+
+ spin_lock(&rssi_buf_lock);
+ if(list_empty(&priv->AverRssiQ)){
+ spin_unlock(&rssi_buf_lock);
+ return;
+ }
+
+ list_for_each_entry_safe(rssi_list, next, &priv->AverRssiQ, list){
+ rssi_list->dirty ++;
+
+ if(rssi_list->dirty >= MAX_RSSI_RECORD){
+ if(memcmp(rssi_list->bssid, priv->curbssparams.bssid, 6) != 0){
+ list_del(&rssi_list->list);
+ kfree(rssi_list);
+ }
+ }
+ }
+ spin_unlock(&rssi_buf_lock);
+}
+
+void wlan_free_aver_rssi(wlan_private * priv)
+{
+ t_aver_bssid_rssi * rssi_list = NULL, *next = NULL;
+
+ spin_lock(&rssi_buf_lock);
+ if(list_empty(&priv->AverRssiQ)){
+ spin_unlock(&rssi_buf_lock);
+ return;
+ }
+
+ list_for_each_entry_safe(rssi_list, next, &priv->AverRssiQ, list){
+ list_del(&rssi_list->list);
+ kfree(rssi_list);
+ }
+ spin_unlock(&rssi_buf_lock);
+}
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_aver_rssi.h b/drivers/net/wireless/rda/rda_wlan/wlan_aver_rssi.h
new file mode 100755
index 00000000..4fa5d260
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_aver_rssi.h
@@ -0,0 +1,25 @@
+#ifndef __WLAN_AVER_RSSI_H__
+#define __WLAN_AVER_RSSI_H__
+
+#define MAX_RSSI_RECORD (8)
+#define INVALID_RSSI (-110)
+typedef struct _t_aver_bssid_rssi{
+ struct list_head list;
+ u8 bssid[6];
+ s8 dirty;
+ u8 count;
+ u8 index;
+ u8 rssi[8];
+}t_aver_bssid_rssi;
+
+
+void wlan_add_new_aver_rssi(wlan_private * priv, u8 * bssid, u8 rssi);
+t_aver_bssid_rssi* wlan_find_bssid_in_aver_rssi(wlan_private * priv, u8 * bssid);
+void wlan_update_aver_rssi(wlan_private * priv, u8 * bssid, u8 rssi);
+void wlan_set_rssi_dirty(wlan_private * priv);
+s8 wlan_cal_aver_rssi(t_aver_bssid_rssi* aver_rssi);
+s8 wlan_get_aver_rssi(wlan_private * priv, u8 * bssid);
+void wlan_free_aver_rssi(wlan_private * priv);
+
+#endif
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_debugfs.c b/drivers/net/wireless/rda/rda_wlan/wlan_debugfs.c
new file mode 100755
index 00000000..c40edc36
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_debugfs.c
@@ -0,0 +1,225 @@
+#include "wlan_includes.h"
+
+static int open_file_generic(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+#define FOPS(fread, fwrite) { \
+ .owner = THIS_MODULE, \
+ .open = open_file_generic, \
+ .read = (fread), \
+ .write = (fwrite), \
+}
+
+struct wlan_debugfs_files {
+ char *name;
+ int perm;
+ struct file_operations fops;
+};
+
+extern int wlan_dbg_level;
+extern int wlan_dbg_area;
+static struct dentry *wlan_dbg_dir = NULL;
+
+static ssize_t wlan_debugarea_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ size_t pos = 0;
+ unsigned long addr = get_zeroed_page(GFP_KERNEL);
+ char *buf = (char *)addr;
+ ssize_t res;
+
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_TRACE,
+ "%s\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_TRACE,
+ "get debug_area = 0x%x\n",wlan_dbg_area);
+
+ pos += snprintf(buf+pos, PAGE_SIZE - pos, "%x\n",
+ wlan_dbg_area);
+
+ res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+
+ free_page(addr);
+ return res;
+}
+
+static ssize_t wlan_debugarea_write(struct file *file,
+ const char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ ssize_t ret;
+ int debug_area;
+ unsigned long addr = get_zeroed_page(GFP_KERNEL);
+ char *buf = (char *)addr;
+
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_TRACE,
+ "%s count:%d \n", __func__, count);
+
+ if (copy_from_user(buf, user_buf, count)) {
+ ret = -EFAULT;
+ goto out_unlock;
+ }
+ ret = sscanf(buf, "%x", &debug_area);
+ if (ret != 1) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ wlan_dbg_area = debug_area;
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_TRACE,
+ "set debug_area = 0x%x\n",wlan_dbg_area);
+
+ ret = count;
+out_unlock:
+ free_page(addr);
+ return ret;
+}
+
+static ssize_t wlan_debuglevel_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ size_t pos = 0;
+ unsigned long addr = get_zeroed_page(GFP_KERNEL);
+ char *buf = (char *)addr;
+ ssize_t res;
+
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_TRACE,
+ "%s\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_TRACE,
+ "get debug_level = 0x%x\n",wlan_dbg_level);
+
+ pos += snprintf(buf+pos, PAGE_SIZE - pos, "%x\n",
+ wlan_dbg_level);
+
+ res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+
+ free_page(addr);
+ return res;
+}
+
+static ssize_t wlan_debuglevel_write(struct file *file,
+ const char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ ssize_t ret;
+ int debug_level;
+ unsigned long addr = get_zeroed_page(GFP_KERNEL);
+ char *buf = (char *)addr;
+
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_TRACE,
+ "%s\n", __func__);
+
+ if (copy_from_user(buf, user_buf, count)) {
+ ret = -EFAULT;
+ goto out_unlock;
+ }
+ ret = sscanf(buf, "%x", &debug_level);
+ if (ret != 1) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ wlan_dbg_level = debug_level;
+
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_TRACE,
+ "set debug_level = 0x%x\n",wlan_dbg_level);
+
+ ret = count;
+out_unlock:
+ free_page(addr);
+ return ret;
+}
+
+#if 0
+static ssize_t wlan_loopback_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ ssize_t ret;
+ ret = 0;
+ return ret;
+}
+
+static ssize_t wlan_loopback_write(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ ssize_t ret;
+ ret = 0;
+ return ret;
+}
+#endif
+
+static struct wlan_debugfs_files debugfs_files[] = {
+ { "debugarea", 0444, FOPS(wlan_debugarea_read, wlan_debugarea_write), },
+ { "debuglevel", 0444, FOPS(wlan_debuglevel_read, wlan_debuglevel_write), },
+ //{ "loopback", 0444, FOPS(wlan_loopback_read, wlan_loopback_write), },
+};
+
+
+void wlan_debugfs_init(void)
+{
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_DEBUG,
+ "%s\n", __func__);
+
+ if (!wlan_dbg_dir)
+ wlan_dbg_dir = debugfs_create_dir("rdawlan", NULL);
+
+ return;
+}
+
+void wlan_debugfs_remove(void)
+{
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_DEBUG,
+ "%s\n", __func__);
+
+ if (wlan_dbg_dir)
+ debugfs_remove(wlan_dbg_dir);
+
+ wlan_dbg_dir = NULL;
+
+ return;
+}
+
+void wlan_debugfs_init_all(wlan_private *priv)
+{
+ int i;
+ struct wlan_debugfs_files *files;
+ if (!wlan_dbg_dir)
+ goto exit;
+
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_DEBUG,
+ "%s\n", __func__);
+
+ priv->debugfs_dir = debugfs_create_dir("rdawlan_dev", wlan_dbg_dir);
+ if (!priv->debugfs_dir)
+ goto exit;
+
+ for (i=0; i<ARRAY_SIZE(debugfs_files); i++) {
+ files = &debugfs_files[i];
+ priv->debugfs_files[i] = debugfs_create_file(files->name,
+ files->perm,
+ priv->debugfs_dir,
+ priv,
+ &files->fops);
+ }
+
+exit:
+ return;
+}
+
+void wlan_debugfs_remove_all(wlan_private *priv)
+{
+ int i;
+
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_DEBUG,
+ "%s\n", __func__);
+
+ for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
+ debugfs_remove(priv->debugfs_files[i]);
+ debugfs_remove(priv->debugfs_dir);
+}
+
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_defs.h b/drivers/net/wireless/rda/rda_wlan/wlan_defs.h
new file mode 100755
index 00000000..00059422
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_defs.h
@@ -0,0 +1,168 @@
+#ifndef _WLAN_DEFS_H_
+#define _WLAN_DEFS_H_
+
+#ifndef __KERNEL__
+/** Character, 1 byte */
+typedef char s8;
+/** Unsigned character, 1 byte */
+typedef unsigned char u8;
+
+/** Short integer */
+typedef signed short s16;
+/** Unsigned short integer */
+typedef unsigned short u16;
+
+/** Long integer */
+typedef signed long s32;
+/** Unsigned long integer */
+typedef unsigned long u32;
+
+/** Long long integer */
+typedef signed long long s64;
+/** Unsigned long long integer */
+typedef unsigned long long u64;
+#endif
+
+//#define NORMAL_FIXED
+//#define WLAN_FLOW_CTRL_90E
+#define WLAN_BIG_CURRENT_90E
+//driver version
+#define WLAN_SDIOWIFI_VER_MAJ 0
+#define WLAN_SDIOWIFI_VER_MIN 3
+#define WLAN_SDIOWIFI_VER_BLD 1
+//for not RDA PLATFORM,for example,Allwinner platform, don't define this
+//#define RDA_ANDROID_PLATFORM 1
+
+#define WLAN_VERSION_90_D (1)
+#define WLAN_VERSION_90_E (2)
+#define WLAN_VERSION_91 (3)
+#define WLAN_VERSION_91_E (4)
+#define WLAN_VERSION_91_F (5)
+
+//power manager
+#define WLAN_SYS_SUSPEND
+#define WLAN_POWER_MANAGER (1)
+#define WLAN_UNLOCK_SYSTEM (1)
+#define CARD_ENTER_SLEEP_TIMER (1000)
+#define FLOW_CTRL_INT_SLEEP_RETRY_COUNT_91 25
+#define FLOW_CTRL_INT_SLEEP_RETRY_COUNT_90 30
+#define FLOW_CTRL_RXCMPL_RETRY_COUNT_91 30
+#define FLOW_CTRL_RXCMPL_RETRY_COUNT_90 2000
+#define SCAN_TIME_AT_EACH_CHANNEL 102
+
+//#define WLAN_FORCE_SUSPEND_SUPPORT (1)
+#define WIFI_SLEEP_LISTEN_INTERVAL 0xF0
+#define WIFI_SLEEP_LINK_LOSS_THRESHOLD_90 0x0A
+#define WIFI_SLEEP_LINK_LOSS_THRESHOLD_91 0x0A
+#define DEFAULT_MAX_SCAN_AGE (25*HZ)
+#define GET_SCAN_FROM_NETWORK_INFO (1)
+#define USE_MAC_DYNAMIC_ONCE (1)
+//#define USE_MAC_FROM_RDA_NVRAM
+#define WIFI_MAC_ACTIVATED_FLAG 0x5990
+
+#define DEFAULT_WATCHDOG_TIMEOUT (5 * HZ)
+#define WID_HEADER_LEN (2)
+#define CHECK_SDIO_STAUTS (1)
+#define WLAN_SDIO_MAX_ERR (3)
+#define WLAN_EVENT_MAX_ERR (3)
+
+//queue number form wid cmd & sdio received queue
+#define WLAN_CMD_QUEUE_NUM (10)
+#define WLAN_RX_QUEUE_NUM (10)
+#define WLAN_TX_QUEUE_NUM_90 (10)
+#define WLAN_TX_QUEUE_NUM_91 (100)
+#define SDIO_MAX_BUFSZ 2048 /* Maximum size of a sdio dma buffer */
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+#define BIT7 (1 << 7)
+#define BIT6 (1 << 6)
+#define BIT5 (1 << 5)
+#define BIT4 (1 << 4)
+#define BIT3 (1 << 3)
+#define BIT2 (1 << 2)
+#define BIT1 (1 << 1)
+#define BIT0 (1 << 0)
+
+#define CLEAR_BIT(X , Y) (X) &= (~(Y))
+#define SET_BIT(X , Y) (X) |= (Y)
+
+#define RDA_SLEEP_ENABLE BIT0
+#define RDA_SLEEP_PREASSO BIT1
+#define WIFI_LISTEN_INTERVAL 0x06
+/* link_loss_threshold */
+#define WIFI_LINK_LOSS_THRESHOLD_90 0x20
+#define WIFI_LINK_LOSS_THRESHOLD_91 0x20
+/* Link Sleep Threashold,old Value: 0x00A00080 */
+#define WIFI_PREASSO_SLEEP 0x000500FF
+
+extern int wlan_dbg_level;
+extern int wlan_dbg_area;
+
+typedef enum {
+ WLAN_DL_ALL = 0,
+ WLAN_DL_CRIT = 1,
+ WLAN_DL_TRACE = 2,
+ WLAN_DL_NORM = 3,
+ WLAN_DL_DEBUG = 4,
+ WLAN_DL_VERB = 5,
+} WLAN_DBG_LEVEL;
+
+#define WLAN_DA_MAIN (1 << 0)
+#define WLAN_DA_SDIO (1 << 1)
+#define WLAN_DA_ETHER (1 << 2)
+#define WLAN_DA_WID (1 << 3)
+#define WLAN_DA_WEXT (1 << 4)
+#define WLAN_DA_TXRX (1 << 5)
+#define WLAN_DA_PM (1 << 6)
+#define WLAN_DA_ALL 0x0000007f
+
+#define WLAN_LOG "WLAN: "
+
+//#define DEBUG
+//#define WLAN_RAW_DATA_DEBUG
+#ifdef DEBUG
+#define WLAN_DBGLA(area, lvl) \
+ (((lvl) <= wlan_dbg_level) && ((area) & wlan_dbg_area))
+#define WLAN_DBGLAP(area,lvl, x...) \
+ do{ \
+ if (((lvl) <= wlan_dbg_level) && ((area) & wlan_dbg_area)) \
+ printk(KERN_ERR WLAN_LOG x ); \
+ }while(0)
+#define WLAN_DBGP(x...) \
+ do{ \
+ printk(KERN_ERR WLAN_LOG x ); \
+ }while(0)
+#else
+#define WLAN_DBGLA(area, lvl) 0
+#define WLAN_DBGLAP(area,lvl, x...) do {} while (0)
+#define WLAN_DBGP(x...) do {} while (0)
+#endif
+
+#define WLAN_ERRP(fmt, args...) \
+ do{ \
+ printk(KERN_ERR WLAN_LOG "%s: "fmt, __func__, ## args ); \
+ }while(0)
+
+/** Log entry point for debugging */
+#define ENTER() WLAN_DBGLAP(WLAN_DA_MAIN, WLAN_DL_DEBUG, "Enter: %s :%i\n", __FUNCTION__, \
+ __LINE__)
+/** Log exit point for debugging */
+#define LEAVE() WLAN_DBGLAP(WLAN_DA_MAIN, WLAN_DL_DEBUG, "Leave: %s :%i\n", __FUNCTION__, \
+ __LINE__)
+
+#define WLAN_STATUS_FAILED (-1)
+#define WLAN_STATUS_SUCCESS (0)
+#endif
+
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_dev.h b/drivers/net/wireless/rda/rda_wlan/wlan_dev.h
new file mode 100755
index 00000000..5af1985c
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_dev.h
@@ -0,0 +1,418 @@
+#ifndef __WLAN_DEV_H__
+#define __WLAN_DEV_H__
+
+#ifndef MAX_WPA_IE_LEN
+#define MAX_WPA_IE_LEN 100
+#endif
+
+#ifndef MAX_WPS_IE_LEN
+#define MAX_WPS_IE_LEN (512)
+#endif
+#ifndef MAX_RATES
+#define MAX_RATES 14
+#endif
+
+#define WLAN_MAX_NETWORK_NUM 64
+
+#define KEY_LEN_WPA_AES 16
+#define KEY_LEN_WPA_TKIP 32
+#define KEY_LEN_WEP_104 13
+#define KEY_LEN_WEP_40 5
+
+#define ASSOC_FLAG_SSID 1
+#define ASSOC_FLAG_CHANNEL 2
+#define ASSOC_FLAG_BAND 3
+#define ASSOC_FLAG_MODE 4
+#define ASSOC_FLAG_BSSID 5
+#define ASSOC_FLAG_WEP_KEYS 6
+#define ASSOC_FLAG_WEP_TX_KEYIDX 7
+#define ASSOC_FLAG_WPA_MCAST_KEY 8
+#define ASSOC_FLAG_WPA_UCAST_KEY 9
+#define ASSOC_FLAG_SECINFO 10
+#define ASSOC_FLAG_WPA_IE 11
+#define ASSOC_FLAG_ASSOC_RETRY 12
+#define ASSOC_FLAG_ASSOC_START 13
+#define ASSOC_FLAG_WLAN_CONNECTING 14
+
+#define WLAN_NF_DEFAULT_SCAN_VALUE (-96)
+#define PERFECT_RSSI ((u8)50)
+#define WORST_RSSI ((u8)0)
+#define RSSI_DIFF ((u8)(PERFECT_RSSI - WORST_RSSI))
+
+#define WLAN_RTS_MIN_VALUE 0
+#define WLAN_RTS_MAX_VALUE 2347
+#define WLAN_FRAG_MIN_VALUE 256
+#define WLAN_FRAG_MAX_VALUE 2346
+
+
+#define WLAN_AUTH_OPEN 0
+#define WLAN_AUTH_SHARED_KEY 1
+#define WLAN_AUTH_FT 2
+#define WLAN_AUTH_LEAP 128
+
+#define WLAN_AUTH_CHALLENGE_LEN 128
+
+#define WLAN_CAPABILITY_ESS (1<<0)
+#define WLAN_CAPABILITY_IBSS (1<<1)
+#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
+#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
+#define WLAN_CAPABILITY_PRIVACY (1<<4)
+#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
+#define WLAN_CAPABILITY_PBCC (1<<6)
+#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
+#define IW_AUTH_ALG_WAPI 0x08
+#define IW_ENCODE_ALG_WAPI 0x80
+#define IW_AUTH_WAPI_ENABLED 0x20
+
+#define WAPI_KEY_MGMT_NONE 0
+#define WAPI_KEY_MGMT_CERT BIT2
+#define WAPI_KEY_MGMT_PSK BIT3
+
+#define IW_ENCODE_ALG_SM4 0x20
+
+enum WLAN_SCAN_STATUS{
+ WLAN_SCAN_IDLE = 0,
+ WLAN_SCAN_RUNNING = 1,
+ WLAN_SCAN_COMPLET = 2
+};
+
+enum WLAN_PACKET_TYPE{
+ WLAN_CMD = 1,
+ WLAN_DATA = 2
+};
+
+/** KEY_TYPE_ID */
+enum KEY_TYPE_ID {
+ KEY_TYPE_ID_WEP = 0,
+ KEY_TYPE_ID_TKIP,
+ KEY_TYPE_ID_AES
+};
+
+enum PACKET_TYPE{
+ WID_REQUEST_PACKET,
+ WID_REQUEST_POLLING_PACKET,
+ DATA_REQUEST_PACKET
+};
+
+/** KEY_INFO_WPA (applies to both TKIP and AES/CCMP) */
+enum KEY_INFO_WPA {
+ KEY_INFO_WPA_MCAST = 0x01,
+ KEY_INFO_WPA_UNICAST = 0x02,
+ KEY_INFO_WPA_ENABLED = 0x04
+};
+
+typedef struct _wlan_bss_descriptor {
+ u8 ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 bss_type;
+ u8 channel;
+ u8 dot11i_info;
+ u8 bssid[ETH_ALEN];
+ u8 rssi;
+ u8 auth_info;
+ u8 rsn_cap[2];
+}wlan_bss_descriptor;
+
+/**
+ * @brief Structure used to store information for each beacon/probe response
+ */
+struct bss_descriptor {
+ u8 bssid[ETH_ALEN];
+ u8 ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 ssid_len;
+
+ u16 capability;
+ u32 rssi;
+ u32 channel;
+ u16 beaconperiod;
+
+ /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
+ u8 mode;
+
+ /* zero-terminated array of supported data rates */
+ u8 rates[MAX_RATES + 1];
+ u8* wpa_ie;
+ size_t wpa_ie_len;
+ u8* rsn_ie;
+ size_t rsn_ie_len;
+
+ u8* wapi_ie;
+ size_t wapi_ie_len; //wapi valid payload length
+
+ //huanglei add wps
+ u8 *wps_ie;//added in probe req
+ int wps_ie_len;
+
+ unsigned long last_scanned;
+ struct list_head list;
+};
+
+struct wlan_802_11_security {
+ u8 WPAenabled;
+ u8 WPA2enabled;
+ u8 wep_enabled;
+ u8 auth_mode;
+ u32 key_mgmt;
+ u32 cipther_type;
+};
+
+typedef struct _wlan_rx_packet_node{
+ struct list_head List;
+ struct sk_buff *Skb;
+}wlan_rx_packet_node;
+
+typedef struct _wlan_wid_packet_node{
+ struct list_head List;
+ wait_queue_head_t WidDone;
+ u8 WidWaitOption;
+ u16 WidCmd;
+ u8 WidMsgId;
+ u8 BufType;//use this to record the rsp type. in case we need use it to determine system big or little end
+ u32 BufLen;
+ u8 *Buf;
+ u32 RspLen;
+ u8 *RspBuf;
+}wlan_wid_packet_node;
+
+typedef struct _wlan_tx_packet_node{
+ struct list_head List;
+ struct sk_buff *Skb;
+ u8 type;
+ wlan_wid_packet_node * wid_node;
+}wlan_tx_packet_node;
+
+/* Generic structure to hold all key types. */
+struct enc_key {
+ u16 len;
+ u16 flags; /* KEY_INFO_* from defs.h */
+ u16 type; /* KEY_TYPE_* from defs.h */
+ u8 key[32];
+};
+
+typedef struct _wlan_private{
+ struct mmc_card* MmcCard;
+ u8 CardRemoved;
+ int Open;
+ int version;
+#ifdef WLAN_SDIO_RESET_DEBUG
+ int debug_count;
+#endif
+
+ u32 gpio_2_irq;
+ u32 external_irq;
+
+ struct dentry *debugfs_dir;
+ struct dentry *debugfs_files[6];
+ u8 wlan_pm_enable;
+
+ struct net_device *netDev;
+ u8 netDevRegistered;
+ atomic_t netifQuStop;
+ struct mmc_card * mmcCard;
+ void *card;
+ u32 SdioErrorCount;
+ u8 sdio_need_reset;
+ u8 sdio_irq_enable;
+ u8 IgnoreFisrtDisconnect;
+ u8 Suspend;
+ atomic_t CardNeedSleep;
+ u8 CardInSleep;
+ WLAN_DRV_TIMER CardToSleepTimer;
+
+ struct notifier_block pm_nb;
+ u8 CardInSuspend;
+ u8 earlysuspend_enabled;
+
+ struct net_device_stats stats;
+ spinlock_t TxLock;
+ spinlock_t RxLock;
+ spinlock_t WidLock;
+ spinlock_t EventLock;
+ u8 CardSleepWakeLockOn;
+ struct wake_lock CardSleepTimerLock;
+ struct wake_lock MacStatusLock;
+ struct wake_lock ExtIrqTimerLock;
+
+ struct list_head AverRssiQ;
+ u8 wid_msg_id;
+
+ struct completion widComp;
+ /** Free command buffers */
+ struct list_head WidFreeQ;
+ /** Pending command buffers */
+ struct list_head WidPendingQ;
+
+ /**rx packet queue*/
+ u32 RxQuNum;
+ struct list_head RxQueue;
+
+ /**tx packet queue*/
+ atomic_t TxQuNum;
+ struct list_head TxQueue;
+
+ /**tx packet queue*/
+ u32 EventQuNum;
+ struct list_head EventQueue;
+ u32 EventErrorCount;
+
+ /** thread to rx thread */
+ wlan_thread RxThread;
+
+ /** thread to event thread */
+ wlan_thread EventThread;
+
+ /** thread to tx thread */
+ wlan_thread TxThread;
+
+ struct iw_statistics wstats;
+ wlan_bss_descriptor curbssparams;
+ int connect_status;
+ int ToggalAssociation;
+ u8 reassoc_count;
+ u8 assoc_ongoing;
+ u8 assoc_bssid[6];
+ u8 assoc_ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 assoc_ssid_len;
+ WLAN_DRV_TIMER StartAssociationTimeOut;
+ WLAN_DRV_TIMER AssociationTimeOut;
+ WLAN_DRV_TIMER ReAssociationTimeOut;
+ /** Encryption parameter */
+ u8 imode;
+ u8 authtype;
+ struct wlan_802_11_security secinfo;
+
+ /** WEP keys */
+ struct enc_key wep_keys[4];
+ u16 wep_tx_keyidx;
+
+ /** WPA keys */
+ struct enc_key wpa_mcast_key;
+ struct enc_key wpa_unicast_key;
+
+ /** WPA Information Elements*/
+ u8 wpa_ie[MAX_WPA_IE_LEN];
+ u8 wpa_ie_len;
+
+ u8 is_wapi;
+ u8 wps_ie[MAX_WPS_IE_LEN];//added in probe req
+ int wps_ie_len;
+
+ /** Scan results list */
+ int scan_running;
+ WLAN_DRV_TIMER ScanResultsTimeout;
+ spinlock_t ScanListLock;
+ struct list_head network_list;
+ struct list_head network_free_list;
+ struct bss_descriptor *networks;
+ int scan_ssid_len;
+ u8 scan_ssid[IW_ESSID_MAX_SIZE + 1];
+}wlan_private;
+
+typedef struct _wlan_sdio_card
+{
+ spinlock_t cardLock;
+ struct sdio_func * func;
+ wlan_private * priv;
+}wlan_sdio_card;
+
+/*get mac from rda nvram*/
+struct wlan_mac_info {
+ u16 activated;
+ u8 mac_addr[ETH_ALEN];
+};
+static inline int is_same_network(struct bss_descriptor *src,
+ struct bss_descriptor *dst)
+{
+ /* A network is only a duplicate if the channel, BSSID, and ESSID
+ * all match. We treat all <hidden> with the same BSSID and channel
+ * as one network */
+ return ((src->channel == dst->channel) &&
+ !compare_ether_addr(src->bssid, dst->bssid) &&
+ !memcmp(src->ssid, dst->ssid, IW_ESSID_MAX_SIZE));
+}
+
+static inline unsigned char is_zero_eth_addr(unsigned char *addr)
+{
+ return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
+}
+
+static inline void clear_bss_descriptor(struct bss_descriptor *bss)
+{
+ /* Don't blow away ->list, just BSS data */
+ if(bss->wpa_ie)
+ kfree(bss->wpa_ie);
+
+ if(bss->rsn_ie)
+ kfree(bss->wapi_ie);
+
+ if(bss->wapi_ie)
+ kfree(bss->wapi_ie);
+
+ if(bss->wps_ie)
+ kfree(bss->wapi_ie);
+
+ memset(bss, 0, offsetof(struct bss_descriptor, list));
+}
+
+static inline int is_ap_support_11b(u8* rates)
+{
+ int i = 0;
+ for(i = 0; i <= MAX_RATES; i ++){
+ if(rates[i] == 0x96)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static inline void skb_align(struct sk_buff *skb, int align)
+{
+ int off = ((unsigned long)skb->data) & (align - 1);
+
+ if (off)
+ skb_reserve(skb, align - off);
+}
+
+void if_sdio_interrupt(struct sdio_func *func);
+struct bss_descriptor *get_bss_desc_from_scanlist(
+ wlan_private *priv, unsigned char *bssid);
+void wlan_network_information(wlan_private *priv,
+ unsigned char *info, unsigned short info_len);
+void wlan_assocication(wlan_private* priv);
+void wlan_re_assocication(wlan_private* priv);
+void wlan_assocication_timeout(wlan_private* priv);
+int wlan_card_control_init(wlan_private *priv);
+void wlan_report_scan_result(wlan_private * priv);
+int wlan_read_mac_from_file(char* buf);
+int wlan_write_mac_to_file(char * buf);
+int wlan_read_mac_from_nvram(char *buf);
+int wlan_write_mac_to_nvram(const char *buf);
+void wlan_indicate_disconnected(wlan_private *priv);
+void wlan_set_scan_by_driver(wlan_private *priv);
+//wlan_init
+unsigned int wlan_extern_irq_handle(int irq, void *para);
+int wlan_register_host_wake_irq(wlan_private* priv);
+void wlan_unregister_host_wake_irq(wlan_private* priv);
+
+int wlan_init(wlan_private* priv);
+int wlan_add_card(wlan_sdio_card * card);
+int wlan_start_card(wlan_sdio_card * card);
+int wlan_reset_card(wlan_private *priv);
+void wlan_release_dev(wlan_sdio_card * card);
+void wlan_remove_tx_data_queue(wlan_private * priv);
+void wlan_remove_rx_queue(wlan_private * priv);
+void wlan_remove_event_queue(wlan_private * priv);
+void wlan_unit(wlan_private * priv);
+//wlan_rxtx
+void wlan_process_event(wlan_private * priv);
+void wlan_process_rx(wlan_private *priv);
+int wlan_tx_thread(void *data);
+int wlan_rx_thread(void *data);
+
+//extern void rda_mmc_set_sdio_irq(u32 host_id, u8 enable);
+extern struct iw_handler_def wlan_wext_handler_def;
+extern unsigned char rda_combo_wifi_in_test_mode(void);
+void wlan_debugfs_init(void);
+void wlan_debugfs_remove(void);
+void wlan_debugfs_init_all(wlan_private *priv);
+void wlan_debugfs_remove_all(wlan_private *priv);
+#endif
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_event.c b/drivers/net/wireless/rda/rda_wlan/wlan_event.c
new file mode 100755
index 00000000..2bda586b
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_event.c
@@ -0,0 +1,227 @@
+#include "wlan_includes.h"
+
+void wlan_push_event(wlan_private * priv, wlan_event_type type, void* para, u8 front)
+{
+ wlan_event *event = NULL;
+ ENTER();
+
+ event = kzalloc(sizeof(wlan_event), GFP_KERNEL);
+ if (event)
+ event->EventType = type;
+ else {
+ WLAN_ERRP("kzalloc wlan_event memory failed\n");
+ return;
+ }
+
+ event->Para = para;
+
+ spin_lock(&priv->EventLock);
+ if(front)
+ list_add(&event->list, &priv->EventQueue);
+ else
+ list_add_tail(&event->list, &priv->EventQueue);
+ priv->EventQuNum ++;
+ spin_unlock(&priv->EventLock);
+
+ complete(&priv->EventThread.comp);
+
+ LEAVE();
+}
+
+wlan_event* wlan_pull_event(wlan_private * priv)
+{
+ wlan_event* event;
+
+ ENTER();
+ spin_lock(&priv->EventLock);
+ if (list_empty(&priv->EventQueue)) {
+ spin_unlock(&priv->EventLock);
+ return NULL;
+ }
+ event = (wlan_event*)priv->EventQueue.next;
+ list_del(&event->list);
+ priv->EventQuNum --;
+ spin_unlock(&priv->EventLock);
+ LEAVE();
+ return event;
+}
+
+void wlan_timer_handler(unsigned long fcontext)
+{
+ PWLAN_DRV_TIMER timer = (PWLAN_DRV_TIMER) fcontext;
+
+ if(timer->timer_function)
+ timer->timer_function(timer->function_context);
+ else {
+ wlan_push_event((wlan_private *) timer->function_context, timer->EventType, timer->function_context, TRUE);
+ }
+
+ if (timer->timer_is_periodic == TRUE) {
+ mod_timer(&timer->tl, jiffies + ((timer->time_period * HZ) / 1000));
+ } else
+ timer->timer_is_canceled = TRUE;
+}
+
+
+void wlan_mac_status(wlan_private *priv,
+ char *wid_status, unsigned short wid_status_len)
+{
+ char mac_status;
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_DEBUG, "%s >>>\n", __func__);
+
+#ifdef WLAN_FORCE_SUSPEND_SUPPORT
+ if (priv->CardInSuspend == TRUE) {
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "%s ingnored in ap deep sleep mode.\n", __func__);
+ return;
+ }
+#endif
+ mac_status = wid_status[7];
+
+ if (mac_status == MAC_CONNECTED) {
+
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_CRIT, "MAC CONNECTED\n");
+
+ priv->connect_status = MAC_CONNECTED;
+ netif_carrier_on(priv->netDev);
+ netif_wake_queue(priv->netDev);
+
+ wlan_cancel_timer(&priv->ReAssociationTimeOut);
+ //report connect to supper layer
+ wlan_indicate_connected(priv);
+ {
+ wlan_push_event(priv, WLAN_EVENT_SET_PHY_ERR_INT, priv, FALSE);
+ }
+ wake_lock_timeout(&priv->MacStatusLock, 6 * HZ);
+ } else if (mac_status == MAC_DISCONNECTED) {
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_CRIT, "MAC_DISCONNECTED\n");
+
+ wlan_cancel_timer(&priv->ReAssociationTimeOut);
+ //for wep we should toggler from open to shared if auth failed
+ if(priv->ToggalAssociation){
+ wlan_re_assocication(priv);
+ }else{
+ wlan_cancel_timer(&priv->AssociationTimeOut);
+
+ priv->connect_status = MAC_DISCONNECTED;
+ priv->assoc_ongoing = FALSE;
+ netif_stop_queue(priv->netDev);
+ netif_carrier_off(priv->netDev);
+
+ //report disconnect to supper layer
+ if(!priv->IgnoreFisrtDisconnect){
+ wlan_indicate_disconnected(priv);
+
+ wake_lock_timeout(&priv->MacStatusLock, 6*HZ);
+ }else{
+ priv->IgnoreFisrtDisconnect = FALSE;
+ }
+ }
+ } else {
+ WLAN_ERRP("Invalid MAC Status 0x%02x\n", mac_status);
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_DEBUG, "%s <<<\n", __func__);
+}
+
+void wlan_start_netif(wlan_private* priv)
+{
+ netif_wake_queue(priv->netDev);
+}
+void wlan_process_event(wlan_private * priv)
+{
+ int ret=0;
+ wlan_event *event = NULL;
+
+ event = wlan_pull_event(priv);
+ if (!event)
+ return;
+
+ WLAN_DBGLAP(WLAN_DA_MAIN, WLAN_DL_TRACE, "type :%d \n", event->EventType);
+
+ switch(event->EventType){
+ case WLAN_EVENT_SCAN_RESULT_TIMEOUT:
+ wlan_report_scan_result(priv);
+ break;
+
+ case WLAN_EVENT_START_ASSOC:
+ wlan_assocication(priv);
+ break;
+
+ case WLAN_EVENT_ASSOC_TIMEOUT:
+ wlan_assocication_timeout(priv);
+ break;
+
+ case WLAN_EVENT_REASSOC_TIMEOUT:
+ wlan_re_assocication(priv);
+ break;
+
+ case WLAN_EVENT_CARD_TO_SLEEP:
+ handle_card_to_sleep_cmd(priv);
+ break;
+
+ case WLAN_EVENT_CARD_CONTROL_INIT:
+ ret=wlan_card_control_init(priv);
+ if (ret) {
+ WLAN_ERRP("Wlan Card Control Init Failed! \n");
+ } else {
+ WLAN_DBGLAP(WLAN_DA_MAIN, WLAN_DL_CRIT, "Wlan Card Control Init Success, Chip Version:%d \n", priv->version);
+ }
+
+ break;
+ case WLAN_EVENT_CHECK_SDIO:
+ wlan_card_check_sdio(priv);
+ break;
+
+ case WLAN_EVENT_START_NETIF:
+ wlan_start_netif(priv);
+ break;
+
+ case WLAN_EVENT_SET_PHY_ERR_INT:
+ wlan_set_phy_timeout(priv);
+ break;
+
+ case WLAN_EVENT_START_SCAN:
+ wlan_set_scan_by_driver(priv);
+ break;
+ default:
+ break;
+ }
+
+ kfree(event);
+}
+
+
+int wlan_event_thread(void *data)
+{
+ wlan_thread *thread = (wlan_thread *)data;
+ wlan_private *priv = thread->priv;
+
+ ENTER();
+
+ wlan_activate_thread(thread);
+
+ current->flags |= PF_NOFREEZE;
+
+ while(1){
+
+ wait_for_completion_interruptible(&thread->comp);
+
+ if (kthread_should_stop()){
+ WLAN_DBGLAP(WLAN_DA_MAIN, WLAN_DL_CRIT,"wlan_event_thread: break from main thread \n");
+ break;
+ }
+
+ if(priv->CardRemoved){
+ break;
+ }
+
+ wlan_process_event(priv);
+ }
+ wlan_deactivate_thread(thread);
+
+ LEAVE();
+ return 0;
+}
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_event.h b/drivers/net/wireless/rda/rda_wlan/wlan_event.h
new file mode 100755
index 00000000..65af5908
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_event.h
@@ -0,0 +1,33 @@
+#ifndef __WLAN_EVENT_H__
+#define __WLAN_EVENT_H__
+
+typedef enum _wlan_event_type
+{
+ WLAN_EVENT_SCAN_RESULT_TIMEOUT = 0,
+ WLAN_EVENT_START_ASSOC = 1,
+ WLAN_EVENT_ASSOC_TIMEOUT = 2,
+ WLAN_EVENT_REASSOC_TIMEOUT = 3,
+ WLAN_EVENT_CARD_TO_SLEEP = 4,
+ WLAN_EVENT_CARD_CONTROL_INIT = 5,
+ WLAN_EVENT_CHECK_SDIO = 6,
+ WLAN_EVENT_START_NETIF = 7,
+ WLAN_EVENT_SET_PHY_ERR_INT = 8,
+ WLAN_EVENT_START_SCAN = 9,
+}wlan_event_type;
+
+typedef struct _wlan_event
+{
+ struct list_head list;
+ wlan_event_type EventType;
+ void * Para;
+}wlan_event;
+
+void wlan_push_event(wlan_private * priv, wlan_event_type type, void* para, u8 front);
+wlan_event* wlan_pull_event(wlan_private *priv);
+void wlan_mac_status(wlan_private *priv,
+ char *wid_status, unsigned short wid_status_len);
+int wlan_event_thread(void *data);
+void wlan_timer_handler(unsigned long fcontext);
+void wlan_indicate_connected(wlan_private *priv);
+void wlan_indicate_disconnected(wlan_private *priv);
+#endif
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_includes.h b/drivers/net/wireless/rda/rda_wlan/wlan_includes.h
new file mode 100755
index 00000000..54c246c8
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_includes.h
@@ -0,0 +1,115 @@
+/** @file wlan_headers.h
+ *
+ * @brief This file contains all the necessary include file.
+ *
+ * Copyright (C) 2003-2008, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available along with the File in the gpl.txt file or by writing to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
+ *
+ */
+/********************************************************
+Change log:
+ 05/30/07: Initial creation
+********************************************************/
+
+#ifndef _WLAN_HEADERS_H
+#define _WLAN_HEADERS_H
+
+#ifndef __ATTRIB_ALIGN__
+#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
+#endif
+
+#ifndef __ATTRIB_PACK__
+#define __ATTRIB_PACK__ __attribute__ ((packed))
+#endif
+
+/* Linux header files */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/param.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/ctype.h>
+#include <linux/proc_fs.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/notifier.h>
+#include <linux/suspend.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+#include <linux/config.h>
+#endif
+
+#include <linux/ioport.h>
+
+/* ASM files */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#include <linux/semaphore.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+/* Net header files */
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+#include <linux/net.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/etherdevice.h>
+#include <net/arp.h>
+#include <linux/rtnetlink.h>
+#include <linux/ieee80211.h>
+#include <net/iw_handler.h>
+
+/* Wireless header */
+#include <net/iw_handler.h>
+
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/card.h>
+
+#include <linux/wakelock.h>
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include <linux/platform_device.h>
+/*drv header*/
+#include "wlan_defs.h"
+#include "wlan_os.h"
+#include "wlan_dev.h"
+#include "wlan_event.h"
+#include "wlan_wid.h"
+#include "wlan_sdio.h"
+#include "wlan_sdio_patch.h"
+#include "wlan_aver_rssi.h"
+#endif /* _WLAN_HEADERS_H */
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_init.c b/drivers/net/wireless/rda/rda_wlan/wlan_init.c
new file mode 100755
index 00000000..5e978502
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_init.c
@@ -0,0 +1,736 @@
+#include "wlan_includes.h"
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irqnr.h>
+//#include <mach/sys_config.h>
+extern void rda_mci_enable_sdio_irq(struct mmc_host *mmc, int enable);
+
+int wlan_register_host_wake_irq(wlan_private* priv)
+{
+ int ret = 0;
+#ifdef ALL_WINNER
+ script_item_u val;
+ script_item_value_type_e type;
+
+ type = script_get_item("wifi_para", "rda5990_wl_host_wake", &val);
+ if (SCIRPT_ITEM_VALUE_TYPE_PIO != type){
+ printk("get RDA rda5990_wl_host_wake gpio failed\n");
+ priv->gpio_2_irq = 0;
+ }
+ else
+ priv->gpio_2_irq = val.gpio.gpio;
+#endif
+ printk("\n\n\n\n\n\n\n%s %d return\n\n\n\n\n\n\n\n\n",__func__,__LINE__);
+ return 0;
+
+
+ if(priv->external_irq)
+ wlan_unregister_host_wake_irq(priv);
+
+ priv->external_irq = gpio_to_irq(priv->gpio_2_irq);
+ if (IS_ERR_VALUE(priv->external_irq)) {
+ printk("map gpio [%d] to virq failed, errno = %d\n",
+ priv->gpio_2_irq, priv->external_irq);
+ return -1;
+ }
+ ret= devm_request_irq(&priv->MmcCard->dev, priv->external_irq, wlan_extern_irq_handle,
+ IRQF_TRIGGER_LOW, "rda_combo_wifi", priv);
+ if (IS_ERR_VALUE(ret)) {
+ printk("request virq %d failed, errno = %d\n",
+ priv->external_irq, ret);
+ return -1;
+ }
+ return 0;
+}
+
+void wlan_unregister_host_wake_irq(wlan_private* priv)
+{
+ if(!priv || !priv->MmcCard)
+ return;
+
+ if(priv->external_irq)
+ devm_free_irq(&priv->MmcCard->dev, priv->external_irq, priv);
+
+ priv->external_irq = 0;
+
+}
+
+int wlan_init(wlan_private* priv)
+{
+ int ret, i, bufsize;
+ wlan_sdio_card* card = (wlan_sdio_card*)priv->card;
+
+ spin_lock_init(&priv->WidLock);
+ spin_lock_init(&priv->RxLock);
+ spin_lock_init(&priv->TxLock);
+ spin_lock_init(&priv->EventLock);
+ spin_lock_init(&priv->ScanListLock);
+ spin_lock_init(&card->cardLock);
+
+ INIT_LIST_HEAD(&priv->AverRssiQ);
+ INIT_LIST_HEAD(&priv->WidFreeQ);
+ INIT_LIST_HEAD(&priv->WidPendingQ);
+ INIT_LIST_HEAD(&priv->RxQueue);
+ INIT_LIST_HEAD(&priv->TxQueue);
+ INIT_LIST_HEAD(&priv->EventQueue);
+
+ /* Initialize scan result lists */
+ INIT_LIST_HEAD(&priv->network_free_list);
+ INIT_LIST_HEAD(&priv->network_list);
+ /* Allocate buffer to store the BSSID list */
+ bufsize = WLAN_MAX_NETWORK_NUM * (sizeof(struct bss_descriptor) + 4);
+ priv->networks = kzalloc(bufsize, GFP_KERNEL);
+ if (priv->networks == NULL) {
+ WLAN_ERRP("kzalloc bss_descriptor memory failed!\n");
+ return WLAN_STATUS_FAILED;
+ }
+ for (i = 0; i < WLAN_MAX_NETWORK_NUM; i++){
+ list_add_tail(&priv->networks[i].list, &priv->network_list);
+ }
+
+ priv->netDevRegistered = FALSE;
+ atomic_set(&(priv->TxQuNum), 0);
+ priv->RxQuNum = 0;
+ atomic_set(&(priv->netifQuStop), 0);
+ priv->reassoc_count = 0;
+ priv->CardRemoved = FALSE;
+ priv->IgnoreFisrtDisconnect = FALSE;
+ priv->assoc_ongoing = FALSE;
+ priv->scan_running = WLAN_SCAN_IDLE;
+ priv->SdioErrorCount =0;
+ priv->sdio_irq_enable = FALSE;
+ priv->CardInSleep = FALSE;
+ priv->CardSleepWakeLockOn = FALSE;
+ priv->CardInSuspend = FALSE;
+ priv->earlysuspend_enabled=0;
+ priv->sdio_need_reset = 0;
+#ifdef WLAN_SDIO_RESET_DEBUG
+ priv->debug_count = 0;
+#endif
+ priv->EventErrorCount=0;
+
+ ret = wlan_alloc_wid_queue(priv);
+ if(ret)
+ return WLAN_STATUS_FAILED;
+
+ wlan_initialize_timer(&priv->StartAssociationTimeOut, NULL, priv, WLAN_EVENT_START_ASSOC);
+ wlan_initialize_timer(&priv->ScanResultsTimeout, NULL, priv, WLAN_EVENT_SCAN_RESULT_TIMEOUT);
+ wlan_initialize_timer(&priv->AssociationTimeOut, NULL, priv, WLAN_EVENT_ASSOC_TIMEOUT);
+ wlan_initialize_timer(&priv->ReAssociationTimeOut, NULL, priv, WLAN_EVENT_REASSOC_TIMEOUT);
+ wlan_initialize_timer(&priv->CardToSleepTimer, NULL, priv, WLAN_EVENT_CARD_TO_SLEEP);
+
+ wake_lock_init(&priv->CardSleepTimerLock, WAKE_LOCK_SUSPEND, "CardSleepTimerLock");
+ wake_lock_init(&priv->MacStatusLock, WAKE_LOCK_SUSPEND, "MacStatusLock");
+ wake_lock_init(&priv->ExtIrqTimerLock, WAKE_LOCK_SUSPEND, "ExtIrqTimerLock");
+
+ return WLAN_STATUS_SUCCESS;
+}
+
+int wlan_add_card(wlan_sdio_card * card)
+{
+ struct net_device *dev = NULL;
+ wlan_private *priv = NULL;
+ int ret = -1;
+
+ /* Allocate an Ethernet device and register it */
+ dev = alloc_netdev_mq(sizeof(wlan_private), "wlan%d", ether_setup, 1);
+ ENTER();
+
+ if(!dev)
+ return ret;
+
+ priv = netdev_priv(dev);
+ card->priv = priv;
+ priv->card = card;
+ priv->netDev = dev;
+
+ dev->hard_header_len += WID_HEADER_LEN;
+ dev->watchdog_timeo = DEFAULT_WATCHDOG_TIMEOUT;
+ dev->trans_start = jiffies;
+
+#ifdef WIRELESS_EXT
+ dev->wireless_handlers = (struct iw_handler_def *)&wlan_wext_handler_def;
+#endif
+ dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+
+
+ wlan_init(priv);
+
+ priv->RxThread.priv = priv;
+ wlan_create_thread(wlan_rx_thread,
+ &priv->RxThread, "wlan_rx_thread");
+
+ priv->EventThread.priv = priv;
+ wlan_create_thread(wlan_event_thread,
+ &priv->EventThread, "EventThread");
+
+ priv->TxThread.priv = priv;
+ wlan_create_thread(wlan_tx_thread,
+ &priv->TxThread, "wlan_tx_thread");
+
+ while(priv->RxThread.pid == 0 ||
+ priv->EventThread.pid == 0 ||
+ priv->TxThread.pid == 0)
+ schedule();
+
+ return 0;
+}
+
+void wlan_release_dev(wlan_sdio_card * card)
+{
+ wlan_private * priv = (wlan_private*) card->priv;
+
+ ENTER();
+ if(!priv)
+ return;
+
+ netif_stop_queue(priv->netDev);
+ netif_carrier_off(priv->netDev);
+
+ //first remove event queue , we shold keep this befrore set CardRmoved
+ //because the event has para should be free in it event handler.
+ wlan_remove_event_queue(priv);
+
+ //release wid pending queue
+ wlan_release_wid_pending_queue(priv);
+
+ if(!(priv->CardToSleepTimer).timer_is_canceled)
+ wlan_cancel_timer(&priv->CardToSleepTimer);
+ wlan_cancel_timer(&priv->StartAssociationTimeOut);
+ wlan_cancel_timer(&priv->AssociationTimeOut);
+ wlan_cancel_timer(&priv->ReAssociationTimeOut);
+ wlan_cancel_timer(&priv->ScanResultsTimeout);
+
+ if(priv->netDev && priv->netDevRegistered)
+ unregister_netdev(priv->netDev);
+
+ priv->CardRemoved = 1;
+ //waiting rx thread terminate
+ while(priv->RxThread.pid){
+ complete(&priv->RxThread.comp);
+ wlan_sched_timeout(2);
+ }
+ //waiting event thread timeout
+ while(priv->EventThread.pid){
+ complete(&priv->EventThread.comp);
+ wlan_sched_timeout(2);
+ }
+
+ //waiting tx thread timeout
+ while(priv->TxThread.pid){
+ complete(&priv->TxThread.comp);
+ wlan_sched_timeout(2);
+ }
+
+ wlan_unit(priv);
+
+ if(priv->netDev)
+ free_netdev(priv->netDev);
+#ifdef WLAN_FORCE_SUSPEND_SUPPORT
+ unregister_pm_notifier(&priv->pm_nb);
+#endif
+
+ LEAVE();
+}
+
+void wlan_remove_tx_data_queue(wlan_private * priv)
+{
+ struct list_head *qe = NULL, *qen = NULL;
+ wlan_tx_packet_node *txNode = NULL;
+ ENTER();
+ spin_lock(&priv->TxLock);
+ if(!list_empty(&priv->TxQueue)){
+ list_for_each_safe(qe, qen, &priv->TxQueue){
+ txNode= (wlan_tx_packet_node*)qe;
+ if(txNode->Skb && (txNode->type == WLAN_DATA))
+ dev_kfree_skb(txNode->Skb);
+
+ list_del(&txNode->List);
+ kfree(txNode);
+ }
+ }
+ spin_unlock(&priv->TxLock);
+ LEAVE();
+}
+
+void wlan_remove_rx_queue(wlan_private * priv)
+{
+ struct list_head *qe = NULL, *qen = NULL;
+ wlan_rx_packet_node* rxNode = NULL;
+
+ ENTER();
+ spin_lock(&priv->RxLock);
+ if(!list_empty(&priv->RxQueue)){
+ list_for_each_safe(qe, qen, &priv->RxQueue){
+ rxNode= (wlan_rx_packet_node*)qe;
+
+ if(rxNode->Skb)
+ dev_kfree_skb(rxNode->Skb);
+
+ list_del(&rxNode->List);
+ kfree(rxNode);
+ }
+ }
+ spin_unlock(&priv->RxLock);
+ LEAVE();
+}
+
+void wlan_remove_event_queue(wlan_private * priv)
+{
+ while(1){
+ if(!list_empty(&priv->EventQueue)){
+ complete(&priv->EventThread.comp);
+ }else
+ break;
+ wlan_sched_timeout(2);
+ }
+}
+
+void wlan_unit(wlan_private * priv)
+{
+ struct bss_descriptor *iter_bss;
+ wlan_free_wid_queue(priv);
+ wlan_remove_tx_data_queue(priv);
+ wlan_remove_rx_queue(priv);
+
+ if(priv->networks){
+ list_for_each_entry(iter_bss, &priv->network_list, list) {
+ clear_bss_descriptor(iter_bss);
+ }
+ kfree(priv->networks);
+ }
+
+ priv->networks = NULL;
+
+ wlan_free_aver_rssi(priv);
+
+ wake_lock_destroy(&priv->CardSleepTimerLock);
+ wake_lock_destroy(&priv->MacStatusLock);
+ wake_lock_destroy(&priv->ExtIrqTimerLock);
+}
+
+int wlan_sleep_flags = RDA_SLEEP_ENABLE | RDA_SLEEP_PREASSO;
+int wlan_init_pm(wlan_private *priv)
+{
+ int ret = 0;
+#ifdef WLAN_POWER_MANAGER
+ wlan_sdio_card *card = (wlan_sdio_card *)priv->card;
+#endif
+
+ if(rda_combo_wifi_in_test_mode())
+ return 0;
+
+#ifdef WLAN_POWER_MANAGER
+ if (wlan_sleep_flags & RDA_SLEEP_ENABLE){
+ ret = wlan_set_pm_mode(priv, 2);
+ if(ret < 0)
+ goto err;
+ }
+ if (wlan_sleep_flags & RDA_SLEEP_PREASSO){
+ ret = wlan_set_preasso_sleep(priv, WIFI_PREASSO_SLEEP);
+ if(ret < 0)
+ goto err;
+ }
+
+ sdio_claim_host(card->func);
+ ret = wlan_write_byte(priv, IF_SDIO_FUN1_INT_TO_DEV, 1);
+ if (ret) {
+ WLAN_ERRP("write FUN1_INT_TO_DEV reg fail\n");
+ }
+ sdio_release_host(card->func);
+ priv->wlan_pm_enable = 1;
+err:
+ return ret;
+#else
+ return ret;
+#endif
+}
+
+int wlan_disable_self_cts(wlan_private *priv)
+{
+ int ret = 0;
+
+ ENTER();
+ ret = wlan_generic_set_uchar(priv, WID_PTA_MODE, 0);
+
+ if(ret < 0){
+ WLAN_ERRP("failed \n");
+ goto err;
+ }
+
+ return 0;
+
+err:
+ return ret;
+}
+
+int wlan_disable_block_bt(wlan_private *priv)
+{
+ int ret = 0;
+
+ ENTER();
+
+ ret = wlan_generic_set_uchar(priv, WID_PTA_BLOCK_BT, 0);
+ if(ret < 0){
+ WLAN_ERRP("failed \n");
+ goto err;
+ }
+
+ return 0;
+
+err:
+ return ret;
+}
+
+int wlan_card_control_init(wlan_private *priv)
+{
+ int ret = -1;
+
+ ENTER();
+ if(!rda_combo_wifi_in_test_mode()){
+ ret=wlan_sdio_init(priv);
+ if(ret<0){
+ WLAN_ERRP("wlan_sdio_init failed! \n");
+ goto err;
+ }
+
+ ret = wlan_start_card((wlan_sdio_card *)priv->card);
+ if(ret<0){
+ WLAN_ERRP("wlan_start_card failed! \n");
+ goto err;
+ }
+
+ ret = wlan_disable_self_cts(priv);
+ if(ret){
+ WLAN_ERRP("wlan_disable_self_cts failed! \n");
+ goto err;
+ }
+
+ ret = wlan_disable_block_bt(priv);
+ if(ret){
+ WLAN_ERRP("wlan_disable_block_bt failed! \n");
+ goto err;
+ }
+
+ ret = wlan_set_scan_timeout(priv);
+ if (ret) {
+ WLAN_ERRP("wlan_set_scan_timeout failed! \n");
+ goto err;
+ }
+
+ ret= wlan_set_listen_interval(priv, WIFI_LISTEN_INTERVAL);
+ if(ret){
+ WLAN_ERRP("wlan_set_listen_interval failed! \n");
+ goto err;
+ }
+
+ if (priv->version == WLAN_VERSION_90_D || priv->version == WLAN_VERSION_90_E){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_LINK_LOSS_THRESHOLD_90);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ goto err;
+ }
+ }else if(priv->version == WLAN_VERSION_91){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_LINK_LOSS_THRESHOLD_91);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ goto err;
+ }
+ ret = wlan_set_power_save(priv);
+ if(ret){
+ WLAN_ERRP("wlan_set_power_save failed! \n");
+ goto err;
+ }
+ }else if(priv->version == WLAN_VERSION_91_E){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_LINK_LOSS_THRESHOLD_91);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ goto err;
+ }
+ ret = wlan_set_power_save(priv);
+ if(ret){
+ WLAN_ERRP("wlan_set_power_save failed! \n");
+ goto err;
+ }
+
+ }else if(priv->version == WLAN_VERSION_91_F){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_LINK_LOSS_THRESHOLD_91);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ goto err;
+ }
+ ret = wlan_set_power_save(priv);
+ if(ret){
+ WLAN_ERRP("wlan_set_power_save failed! \n");
+ goto err;
+ }
+ }
+
+ // ret = wlan_generic_set_ushort(priv, WID_JOIN_TIMEOUT, 3000);
+ // if(ret)
+ // goto err;
+
+ ret = wlan_init_pm(priv);
+ if(ret){
+ WLAN_ERRP("wlan_init_pm failed! \n");
+ goto err;
+ }
+ }else{
+ ret = wlan_set_test_mode(priv);
+
+ if (register_netdev(priv->netDev)) {
+ WLAN_ERRP("register_netdev failed\n");
+ priv->netDevRegistered = FALSE;
+ goto err;
+ }else
+ priv->netDevRegistered = TRUE;
+
+ wlan_indicate_disconnected(priv);
+ }
+
+ return 0; /*success*/
+err:
+ LEAVE();
+ return -1; /*fail*/
+}
+
+
+int wlan_start_card(wlan_sdio_card * card)
+{
+ u8 mac_addr[ETH_ALEN];
+ int ret = 0;
+
+ wlan_private * priv = (wlan_private*) card->priv;
+
+ if(!priv)
+ return -1;
+
+ ENTER();
+
+#ifdef USE_MAC_DYNAMIC_ONCE
+ if(wlan_read_mac_from_file(mac_addr) != ETH_ALEN){
+#ifdef USE_MAC_FROM_RDA_NVRAM
+ ret = wlan_read_mac_from_nvram(mac_addr);
+ if (ret) {
+ WLAN_ERRP("nvram:get wifi mac addr form nvram failed, make a random mac addr instead\n");
+ random_ether_addr(mac_addr);
+ wlan_write_mac_to_nvram(mac_addr);
+ } else {
+ if (!is_valid_ether_addr(mac_addr)) {
+ mac_addr[0] &= 0xfe; /* clear multicast bit */
+ mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */
+ }
+ }
+#else
+ random_ether_addr(mac_addr);
+#endif /*USE_MAC_FROM_RDA_NVRAM*/
+ ret = wlan_write_mac_to_file(mac_addr);
+ }
+
+#else
+ mac_addr[0] = 0x00;
+ mac_addr[1] = 0xc0;
+ mac_addr[2] = 0x52;
+
+ mac_addr[3] = 0x00;
+ mac_addr[4] = 0xc0;
+ mac_addr[5] = 0x53;
+#endif
+
+ ret = wlan_set_mac_addr(priv, mac_addr);
+ if (ret){
+ goto done;
+ }
+
+ ret = wlan_get_mac_addr(priv, mac_addr);
+ if (ret) {
+ goto done;
+ }
+ memcpy(priv->netDev->dev_addr, mac_addr, ETH_ALEN);
+
+ rda5890_set_preamble(priv, G_AUTO_PREAMBLE);
+
+ if (register_netdev(priv->netDev)) {
+ WLAN_ERRP("register_netdev failed\n");
+ ret = -1;
+ priv->netDevRegistered = FALSE;
+ goto done;
+ }else
+ priv->netDevRegistered = TRUE;
+
+ wlan_indicate_disconnected(priv);
+
+done:
+ LEAVE();
+
+ return ret;
+}
+
+extern int rda_wifi_power_off(void);
+extern int rda_wifi_power_on(void);
+extern int sdio_reset_comm(struct mmc_card *card);
+extern void rda_mmc_reset_host(u32 host_id);
+
+int wlan_reset_card(wlan_private *priv)
+{
+ int ret = 0;
+ wlan_sdio_card * card = NULL;
+ struct mmc_host * host = NULL;
+ card = (wlan_sdio_card *) priv->card;
+ host = priv->mmcCard->host;
+ ENTER();
+ wlan_cancel_timer(&priv->CardToSleepTimer);
+ wlan_remove_tx_data_queue(priv);
+ wlan_release_wid_pending_queue(priv);
+ sdio_claim_host(card->func);
+ ret = sdio_release_irq(card->func);
+ if(ret){
+ WLAN_ERRP("reset_card sdio_release_irq fail, ret = %d\n", ret);
+ }
+ sdio_release_host(card->func);
+ ret = rda_wifi_power_off();
+ if(ret)
+ WLAN_ERRP("reset card power off sdio failed \n");
+
+ ret = rda_wifi_power_on();
+ if(ret){
+ WLAN_ERRP("reset card power off sdio failed \n");
+ //kevin add, otherwise ,call sdio_reset_comm will cause kernel crash
+ goto err;
+ }
+
+ //mmc_power_restore_host(host);
+rda_mci_enable_sdio_irq(priv->MmcCard->host, 0);
+
+ //rda_mmc_set_sdio_irq(1, false);
+ printk("\n\n\n\n\n\n\nkevin delete %s %d\n\n\n\n\n\n\n",__func__,__LINE__);
+ priv->sdio_irq_enable = FALSE;
+ priv->wlan_pm_enable = 0;
+
+ sdio_reset_comm(priv->mmcCard);
+
+ sdio_claim_host(card->func);
+ ret = sdio_enable_func(card->func);
+ if (ret){
+ WLAN_ERRP("reset_card sdio_enable_func fail, ret = %d\n", ret);
+ sdio_release_host(card->func);
+ goto err;
+ }
+
+ ret = sdio_claim_irq(card->func, if_sdio_interrupt);
+ if (ret){
+ WLAN_ERRP("reset_card sdio_claim_irq fail, ret = %d\n", ret);
+ sdio_release_host(card->func);
+ goto err;
+ }
+
+ //enable interrupt
+ if(wlan_write_byte(priv, IF_SDIO_FUN1_INT_MASK, 0x07)){
+ WLAN_ERRP("err_enable_int \n");
+ sdio_release_host(card->func);
+ goto err;
+ }
+
+ //re-set sdio block size
+ sdio_set_block_size(card->func, 512);
+ sdio_release_host(card->func);
+
+ ret = wlan_sdio_init(priv);
+ if(ret < 0){
+ WLAN_ERRP("wlan_sdio_init failed! \n");
+ goto err;
+ }
+
+ priv->sdio_need_reset = 2;
+
+ ret = wlan_set_mac_addr(priv, priv->netDev->dev_addr);
+ if (ret){
+ goto err;
+ }
+
+ ret = rda5890_set_preamble(priv, G_AUTO_PREAMBLE);
+ if (ret){
+ goto err;
+ }
+
+ ret = wlan_disable_self_cts(priv);
+ if(ret){
+ WLAN_ERRP("wlan_disable_self_cts failed! \n");
+ goto err;
+ }
+
+ ret = wlan_disable_block_bt(priv);
+ if(ret){
+ WLAN_ERRP("wlan_disable_block_bt failed! \n");
+ goto err;
+ }
+
+ ret = wlan_set_scan_timeout(priv);
+ if (ret) {
+ WLAN_ERRP("wlan_set_scan_timeout failed! \n");
+ goto err;
+ }
+
+ ret= wlan_set_listen_interval(priv, WIFI_LISTEN_INTERVAL);
+ if(ret){
+ WLAN_ERRP("wlan_set_listen_interval failed! \n");
+ goto err;
+ }
+
+ if (priv->version == WLAN_VERSION_90_D || priv->version == WLAN_VERSION_90_E){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_LINK_LOSS_THRESHOLD_90);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ goto err;
+ }
+ }else if(priv->version == WLAN_VERSION_91){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_LINK_LOSS_THRESHOLD_91);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ goto err;
+ }
+ ret = wlan_set_power_save(priv);
+ if(ret){
+ WLAN_ERRP("wlan_set_power_save failed! \n");
+ goto err;
+ }
+ }else if(priv->version == WLAN_VERSION_91_E){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_LINK_LOSS_THRESHOLD_91);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ goto err;
+ }
+ ret = wlan_set_power_save(priv);
+ if(ret){
+ WLAN_ERRP("wlan_set_power_save failed! \n");
+ goto err;
+ }
+
+ }else if(priv->version == WLAN_VERSION_91_F){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_LINK_LOSS_THRESHOLD_91);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ goto err;
+ }
+ ret = wlan_set_power_save(priv);
+ if(ret){
+ WLAN_ERRP("wlan_set_power_save failed! \n");
+ goto err;
+ }
+ }
+
+ ret = wlan_init_pm(priv);
+ if(ret){
+ WLAN_ERRP("wlan_init_pm failed! \n");
+ goto err;
+ }
+
+ //send a scan event after reset
+ wlan_push_event(priv, WLAN_EVENT_START_SCAN, priv, FALSE);
+
+ return 0;
+err:
+ LEAVE();
+ return -1; /*fail*/
+}
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_module.c b/drivers/net/wireless/rda/rda_wlan/wlan_module.c
new file mode 100755
index 00000000..7857564b
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_module.c
@@ -0,0 +1,992 @@
+#include "wlan_includes.h"
+#include <mach/gpio.h>
+//#include <mach/sys_config.h>
+#include <linux/gpio.h>
+///
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/pinctrl/consumer.h>
+///
+#include <mach/irqs.h>
+#include <linux/mmc/sdio.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#if 1
+#define SDIO_VENDOR_ID_RDA 0x5449
+#define SDIO_DEVICE_ID_RDA 0x0145
+
+
+int wmt_mtk6620_intr=0xf; //gpio 15
+
+extern void rda_mci_enable_sdio_irq(struct mmc_host *mmc, int enable);
+int wlan_dbg_level = WLAN_DL_DEBUG;
+
+int wlan_dbg_area = WLAN_DA_MAIN
+ | WLAN_DA_SDIO
+ | WLAN_DA_ETHER
+ | WLAN_DA_WID
+ | WLAN_DA_WEXT
+ | WLAN_DA_TXRX
+ | WLAN_DA_PM
+ ;
+/* Module parameters */
+//module_param_named(debug_level, wlan_dbg_level, int, 0644);
+//module_param_named(debug_area, wlan_dbg_area, int, 0644);
+
+static const struct sdio_device_id if_sdio_ids[] = {
+ { SDIO_DEVICE(SDIO_VENDOR_ID_RDA, SDIO_DEVICE_ID_RDA) },
+ { /* end: all zeroes */ },
+};
+MODULE_DEVICE_TABLE(sdio, if_sdio_ids);
+
+static int wlan_dev_open (struct net_device *dev)
+{
+ int ret = 0;
+ wlan_private *priv = NULL;
+
+ priv = (wlan_private *)netdev_priv(dev);
+
+ if(!priv)
+ return -EPERM;
+
+ priv->Open = TRUE;
+
+ netif_carrier_on(priv->netDev);
+ netif_wake_queue(priv->netDev);
+
+ return ret;
+}
+
+static int wlan_eth_stop(struct net_device *dev)
+{
+ int ret = 0;
+ wlan_private *priv = NULL;
+
+ priv = (wlan_private *)netdev_priv(dev);
+
+ if(!priv)
+ return -EPERM;
+
+ ENTER();
+
+ if (!netif_queue_stopped(priv->netDev)){
+ netif_stop_queue(priv->netDev);
+ }
+
+ if (netif_carrier_ok(priv->netDev)){
+ netif_carrier_off(priv->netDev);
+ }
+
+ LEAVE();
+ return ret;
+}
+
+static int wlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ int ret = 0;
+ wlan_private *priv = NULL;
+ wlan_tx_packet_node * txNode = NULL;
+ unsigned long flags = 0;
+#ifdef WLAN_RAW_DATA_DEBUG
+ u8 *printStr = NULL;
+#endif
+ int tx_queue_max_num =0;
+
+ ENTER();
+
+ if(rda_combo_wifi_in_test_mode()){
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ priv = (wlan_private *)netdev_priv(dev);
+ if(!priv || !is_sdio_init_complete()){
+ WLAN_ERRP("device is not opened \n");
+ return -EPERM;
+ }
+
+ if (priv->version == WLAN_VERSION_90_D || priv->version == WLAN_VERSION_90_E){
+ tx_queue_max_num = WLAN_TX_QUEUE_NUM_90;
+ } else if (priv->version == WLAN_VERSION_91 || priv->version == WLAN_VERSION_91_E
+ || priv->version == WLAN_VERSION_91_F) {
+ tx_queue_max_num = WLAN_TX_QUEUE_NUM_91;
+ } else {
+ tx_queue_max_num = WLAN_TX_QUEUE_NUM_90;
+ WLAN_ERRP("WLAN_TX_QUEUE_NUM doesn't set for this version\n");
+ }
+
+ if(atomic_read(&(priv->TxQuNum)) >= tx_queue_max_num || priv->CardRemoved){
+ WLAN_ERRP("queue is full, priv->TxQuNum=%d \n", atomic_read(&(priv->TxQuNum)));
+ return -ENOMEM;
+ }
+
+ txNode = (wlan_tx_packet_node*)kzalloc(sizeof(wlan_tx_packet_node), GFP_ATOMIC);
+ if(!txNode){
+ WLAN_ERRP("no memory \n");
+ return -ENOMEM;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_MAIN, WLAN_DL_DEBUG,"skb headroom: %d %d len;%d \n", skb_headroom(skb), atomic_read(&priv->netifQuStop), skb->len);
+
+#ifdef WLAN_RAW_DATA_DEBUG
+ printStr = skb->data;
+ WLAN_ERRP("%x %x %x %x %x %x %x %x\n", printStr[0], printStr[1],printStr[2],printStr[3],printStr[4],printStr[5],printStr[6],printStr[7]);
+ printStr += 8;
+ WLAN_ERRP("%x %x %x %x %x %x %x %x\n", printStr[0], printStr[1],printStr[2],printStr[3],printStr[4],printStr[5],printStr[6],printStr[7]);
+ printStr += 8;
+ WLAN_ERRP("%x %x %x %x %x %x %x %x\n", printStr[0], printStr[1],printStr[2],printStr[3],printStr[4],printStr[5],printStr[6],printStr[7]);
+#endif
+
+ txNode->type = WLAN_DATA;
+ if(IS_ALIGNED((int)skb->data - WID_HEADER_LEN, 4))
+ txNode->Skb = skb;
+ else{
+ txNode->Skb = dev_alloc_skb(skb->len + 4 + WID_HEADER_LEN);
+ if(txNode->Skb){
+ skb_align(txNode->Skb, 4);
+ skb_reserve(txNode->Skb , WID_HEADER_LEN);
+ memcpy(txNode->Skb->data, skb->data, skb->len);
+ skb_put(txNode->Skb, skb->len);
+ }
+ dev_kfree_skb(skb);
+
+ if(!txNode->Skb){
+ return -ENOMEM;
+ }
+ }
+
+ spin_lock_irqsave(&priv->TxLock, flags);
+ list_add_tail(&txNode->List, &priv->TxQueue);
+ spin_unlock_irqrestore(&priv->TxLock, flags);
+ atomic_add(1, &(priv->TxQuNum));
+
+ if(atomic_read(&(priv->TxQuNum)) >= tx_queue_max_num){
+ netif_stop_queue(dev);
+ atomic_set(&(priv->netifQuStop), 1);
+ }
+
+ dev->trans_start = jiffies;
+
+ complete(&priv->TxThread.comp);
+
+ LEAVE();
+ return ret;
+}
+
+static int wlan_set_mac_address(struct net_device *dev, void *addr)
+{
+ int ret = 0;
+ return ret;
+}
+
+static void wlan_tx_timeout (struct net_device *dev)
+{
+ ENTER();
+
+ dev->trans_start = jiffies; /* prevent tx timeout */
+ netif_wake_queue(dev);
+ dev->stats.tx_errors++;
+
+ LEAVE();
+}
+
+static struct net_device_stats *wlan_get_stats(struct net_device *dev)
+{
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+
+ return &priv->stats;
+}
+
+#define BT_COEXIST SIOCIWFIRSTPRIV + 2
+#define BT_STATE_SCO_ON 0x01
+#define BT_STATE_SCO_OFF 0x02
+#define BT_STATE_SCO_ONGOING 0x04
+#define BT_STATE_A2DP_PLAYING 0x08
+#define BT_STATE_A2DP_NO_PLAYING 0x10
+#define BT_STATE_CONNECTION_ON 0x20
+#define BT_STATE_CONNECTION_OFF 0x40
+static int wlan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ int ret = -EOPNOTSUPP;
+ static int bt_state = 0;
+ int state = 0, old_state = 0;
+ struct pta_param_s pta_param;
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+
+ ENTER();
+
+ if(priv->version < WLAN_VERSION_91_E)
+ goto out;
+
+ if(cmd == BT_COEXIST){
+ state = rq->ifr_metric;
+ ret = 0;
+
+ pta_param.prot_mode = PTA_NONE_PROTECT;
+ pta_param.mac_rate = 0x0;
+ pta_param.hw_retry = 0x7;
+ pta_param.sw_retry = 0x3;
+ pta_param.cca_bypass = TRUE;
+ pta_param.active_time = 500; /* Unit is 100us */
+ pta_param.thresh_time = 20; /* Unit is 100us */
+ pta_param.auto_prot_thresh_time = 200; /* Unit is 100us */
+ pta_param.flags = BIT0 | BIT1 | BIT5;
+
+ if(state == BT_STATE_SCO_ONGOING){
+ state = BT_STATE_SCO_ON;
+ }
+ old_state = bt_state;
+
+ if(state &(BT_STATE_SCO_ON | BT_STATE_SCO_ONGOING)){
+ bt_state |= BT_STATE_SCO_ON;
+ }
+ if(state & BT_STATE_A2DP_PLAYING){
+ bt_state |= BT_STATE_A2DP_PLAYING;
+ }
+ if(state & BT_STATE_CONNECTION_ON)
+ bt_state |= BT_STATE_CONNECTION_ON;
+
+ if(state == BT_STATE_SCO_OFF){
+ bt_state &= ~BT_STATE_SCO_ON;
+ }else if(state == BT_STATE_A2DP_NO_PLAYING){
+ bt_state &= ~BT_STATE_A2DP_PLAYING;
+ }else if(state == BT_STATE_CONNECTION_OFF)
+ bt_state &= ~BT_STATE_CONNECTION_ON;
+
+ if(old_state == bt_state)
+ goto out;
+
+ if(bt_state){
+ if(bt_state & BT_STATE_SCO_ON){
+ if(old_state) //should clear pta proc before to set a new pta protec
+ ret = wlan_set_pta(priv, &pta_param);
+ pta_param.prot_mode = PTA_PS_POLL_PROTECT;
+ pta_param.mac_rate = 0x4;
+ pta_param.hw_retry = 0x1;
+ pta_param.sw_retry = 0x1;
+ pta_param.active_time = 25;
+ pta_param.thresh_time = 5;
+ pta_param.auto_prot_thresh_time = 15;
+ pta_param.flags = BIT0 | BIT1;
+ }else if(bt_state & BT_STATE_A2DP_PLAYING){
+ if(old_state)
+ ret = wlan_set_pta(priv, &pta_param);
+ pta_param.prot_mode = PTA_NULL_DATA_PROTECT;
+ pta_param.active_time = 600;
+ pta_param.thresh_time = 20;
+ pta_param.auto_prot_thresh_time = 200;
+ }else if(bt_state & BT_STATE_CONNECTION_ON){
+ if(old_state)
+ ret = wlan_set_pta(priv, &pta_param);
+ pta_param.prot_mode = PTA_NULL_DATA_PROTECT;
+ pta_param.active_time = 600;
+ pta_param.thresh_time = 20;
+ pta_param.auto_prot_thresh_time = 200;
+ }
+ }else
+ pta_param.prot_mode = PTA_NONE_PROTECT;
+
+ ret = wlan_set_pta(priv, &pta_param);
+ //log for debug now do not delete
+ printk("***BT_COEXIST state:%x \n", bt_state);
+ }
+
+out:
+ LEAVE();
+
+ return ret;
+}
+
+static const struct net_device_ops rda_netdev_ops = {
+ .ndo_open = wlan_dev_open,
+ .ndo_stop = wlan_eth_stop,
+ .ndo_start_xmit = wlan_hard_start_xmit,
+ .ndo_set_mac_address = wlan_set_mac_address,
+ .ndo_tx_timeout = wlan_tx_timeout,
+ .ndo_get_stats = wlan_get_stats,
+ .ndo_do_ioctl = wlan_ioctl
+};
+
+#ifdef WLAN_FORCE_SUSPEND_SUPPORT
+static int rda_wlan_set_suspend(wlan_private * priv)
+{
+ int ret;
+
+ ENTER();
+
+ if (!priv) {
+ ret = -1;
+ return ret;
+ }
+
+ ret= wlan_set_listen_interval(priv, WIFI_SLEEP_LISTEN_INTERVAL);
+ if(ret){
+ WLAN_ERRP("wlan_set_listen_interval failed! \n");
+ }
+
+ if (priv->version == WLAN_VERSION_90_D || priv->version == WLAN_VERSION_90_E){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_SLEEP_LINK_LOSS_THRESHOLD_90);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ }
+ }else if(priv->version == WLAN_VERSION_91){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_SLEEP_LINK_LOSS_THRESHOLD_91);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ }
+ }else if(priv->version == WLAN_VERSION_91_E){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_SLEEP_LINK_LOSS_THRESHOLD_91);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ }
+ }else if(priv->version == WLAN_VERSION_91_F){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_SLEEP_LINK_LOSS_THRESHOLD_91);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ }
+ }
+
+ LEAVE();
+
+ return ret;
+}
+
+static int rda_wlan_set_resume(wlan_private * priv)
+{
+ int ret;
+
+ ENTER();
+
+ if (!priv) {
+ ret = -1;
+ return ret;
+ }
+
+ ret= wlan_set_listen_interval(priv, WIFI_LISTEN_INTERVAL);
+ if(ret){
+ WLAN_ERRP("wlan_set_listen_interval failed! \n");
+ }
+
+ if (priv->version == WLAN_VERSION_90_D || priv->version == WLAN_VERSION_90_E){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_LINK_LOSS_THRESHOLD_90);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ }
+ }else if(priv->version == WLAN_VERSION_91){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_LINK_LOSS_THRESHOLD_91);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ }
+ }else if(priv->version == WLAN_VERSION_91_E){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_LINK_LOSS_THRESHOLD_91);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ }
+ }else if(priv->version == WLAN_VERSION_91_F){
+ ret = wlan_set_link_loss_threshold(priv, WIFI_LINK_LOSS_THRESHOLD_91);
+ if(ret){
+ WLAN_ERRP("wlan_set_link_loss_threshold failed! \n");
+ }
+ }
+
+ LEAVE();
+ return ret;
+}
+
+static int rda_wlan_early_suspend(struct device *dev)
+{
+ ENTER();
+ LEAVE();
+ return 0;
+}
+
+static int rda_wlan_late_resume(struct device *dev)
+{
+ int ret;
+ wlan_private* priv = (wlan_private*)dev_get_drvdata(dev);
+
+ ENTER();
+
+ if (priv->CardInSuspend == TRUE) {
+ priv->CardInSuspend = FALSE;
+ ret = rda_wlan_set_resume(priv);
+ if (ret) {
+ WLAN_ERRP("rda_wlan_set_resume failed! \n");
+ }
+ }
+
+ LEAVE();
+ return 0;
+}
+
+static int rda_wlan_notify(struct notifier_block *nb,
+ unsigned long mode, void *_unused)
+{
+ int ret;
+ wlan_private * priv = NULL;
+ priv = container_of(nb, wlan_private, pm_nb);
+
+ ENTER();
+
+ switch (mode) {
+ case PM_SUSPEND_PREPARE:
+ if (priv->CardInSuspend == FALSE) {
+ ret = rda_wlan_set_suspend(priv);
+ if (ret) {
+ WLAN_ERRP("rda_wlan_set_suspend failed! \n");
+ }
+ priv->CardInSuspend = TRUE;
+ }
+ break;
+ }
+
+ LEAVE();
+
+ return 0;
+}
+#endif /*WLAN_FORCE_SUSPEND_SUPPORT*/
+#ifdef WLAN_SYS_SUSPEND
+
+static int rda_sdio_suspend(struct device *dev)
+{
+ mmc_pm_flag_t sdio_flags;
+ wlan_private * priv = NULL;
+ wlan_sdio_card * card = NULL;
+ struct sdio_func *func = dev_to_sdio_func(dev);
+ int ret = 0, ret1 = 0;
+ ENTER();
+
+ card = (wlan_sdio_card*)sdio_get_drvdata(func);
+ if(card)
+ priv = card->priv;
+ else
+ return 0;
+
+ printk("rda_sdio_suspend ***** \n");
+ netif_stop_queue(priv->netDev);
+ priv->Suspend = TRUE;
+
+ wlan_cancel_timer(&priv->StartAssociationTimeOut);
+ wlan_remove_tx_data_queue(priv);
+ wlan_release_wid_pending_queue(priv);
+
+ while(1){
+ if(!priv->CardInSleep){
+ wlan_push_event(priv, WLAN_EVENT_CARD_TO_SLEEP, priv, FALSE);
+ wlan_sched_timeout(50);
+ }else
+ break;
+ }
+ sdio_flags = sdio_get_host_pm_caps(func);
+ if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
+ printk("Host can't keep power while suspended \n");
+ ret1 = 0;
+ }
+
+ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+ if (ret) {
+ printk("set host pm flags failed \n");
+ ret1 = 0;
+ }
+ //enable wifi eint for waking up system when suspend
+ wlan_register_host_wake_irq(priv);
+ LEAVE();
+ return ret1;
+}
+
+
+static int rda_sdio_resume(struct device *dev)
+{
+ //add by LA
+ wlan_private * priv = NULL;
+ wlan_sdio_card * card = NULL;
+ struct sdio_func *func = dev_to_sdio_func(dev);
+ ENTER();
+
+ card = (wlan_sdio_card*)sdio_get_drvdata(func);
+ if(card)
+ priv = (wlan_private*)card->priv;
+ else
+ return 0;
+
+ printk("rda_sdio_resume \n");
+ netif_wake_queue(priv->netDev);
+ priv->Suspend = FALSE;
+ //disable wifi eint when system resume
+ wlan_unregister_host_wake_irq(priv);
+ LEAVE();
+ return 0;
+}
+
+static struct dev_pm_ops rda_sdio_pm_ops = {
+ .suspend = rda_sdio_suspend,
+ .resume = rda_sdio_resume,
+};
+
+#endif
+
+extern int wlan_set_rssi_91(wlan_private * priv, u8 rssi);
+
+unsigned int wlan_extern_irq_handle(int irq, void *para)
+{
+ wlan_private* priv = (wlan_private* )para;
+ disable_irq_nosync(priv->external_irq);
+ wake_lock_timeout(&priv->ExtIrqTimerLock, HZ/5);
+ return 0;
+}
+
+void if_sdio_interrupt(struct sdio_func *func)
+{
+ int ret = 0;
+ wlan_sdio_card *card = NULL;
+ wlan_private* priv = NULL;
+ u8 status;
+ unsigned long flags = 0;
+ u8 size_l = 0, size_h = 0;
+ u16 size = 0, payload_len = 0;
+ struct sk_buff *skb = NULL;
+ wlan_rx_packet_node * rx_node = NULL;
+
+ ENTER();
+ card = (wlan_sdio_card*)sdio_get_drvdata(func);
+ if(!card || !is_sdio_init_complete())
+ {
+ WLAN_ERRP("card is NULL or sdio init is not completed!\n");
+ return;
+ }
+
+ priv = card->priv;
+
+ sdio_claim_host(card->func);
+
+ ret = wlan_read_byte(priv, IF_SDIO_FUN1_INT_STAT, &status);
+ sdio_release_host(card->func);
+ if (ret){
+ WLAN_ERRP("SDIO read IF_SDIO_FUN1_INT_STAT status failed!\n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_VERB,"if_sdio_interrupt, status = 0x%02x\n", status);
+
+ if (status & IF_SDIO_INT_AHB2SDIO){
+
+ sdio_claim_host(card->func);
+ if(wlan_read_byte(priv, IF_SDIO_AHB2SDIO_PKTLEN_L, &size_l)){
+ WLAN_ERRP("SDIO read IF_SDIO_AHB2SDIO_PKTLEN_L failed!\n");
+ sdio_release_host(card->func);
+ goto out;
+ }
+
+ if(wlan_read_byte(priv, IF_SDIO_AHB2SDIO_PKTLEN_H, &size_h)){
+ WLAN_ERRP("SDIO read IF_SDIO_AHB2SDIO_PKTLEN_H failed!\n");
+ sdio_release_host(card->func);
+ goto out;
+ }
+
+ size = (size_l | ((size_h & 0x7f) << 8)) * 4;
+ if(size > SDIO_MAX_BUFSZ){
+ WLAN_ERRP("if_sdio_interrupt received buffer is too larger size %d \n", size);
+ goto out;
+ }else if(size < 4){
+ WLAN_ERRP("invalid size %d \n", size);
+ goto out;
+ }
+
+ skb = dev_alloc_skb(size + NET_IP_ALIGN + WID_HEADER_LEN + 3);
+ if(!skb){
+ WLAN_ERRP("if_sdio_interrupt alloc skb failed \n");
+ goto out;
+ }
+
+ rx_node = kzalloc(sizeof(wlan_rx_packet_node), GFP_ATOMIC);
+ if(!rx_node){
+ WLAN_ERRP("kzalloc wlan_rx_packet_node failed \n");
+ dev_kfree_skb(skb);
+ goto out;
+ }
+
+ skb_reserve(skb, NET_IP_ALIGN);
+ //4byte align
+ skb_align(skb, 4);
+ rx_node->Skb = skb;
+ if(wlan_read_bytes(priv, IF_SDIO_FUN1_FIFO_RD, skb->data, size)
+ || priv->CardRemoved){
+ WLAN_ERRP("SDIO read IF_SDIO_FUN1_FIFO_RD failed! \n");
+ sdio_release_host(card->func);
+ kfree(rx_node);
+ dev_kfree_skb(skb);
+ goto out;
+ }
+ sdio_release_host(card->func);
+
+ //put payload length in skb
+ payload_len = (u16)(skb->data[0] + ((skb->data[1]&0x0f) << 8));
+ if(payload_len > size){
+ WLAN_ERRP("SDIO read payload_len invalid! \n");
+ kfree(rx_node);
+ dev_kfree_skb(skb);
+ goto out;
+ }
+ skb_put(skb, payload_len);
+
+ spin_lock_irqsave(&priv->RxLock, flags);
+ list_add_tail(&rx_node->List, &priv->RxQueue);
+ priv->RxQuNum++;
+ spin_unlock_irqrestore(&priv->RxLock, flags);
+ complete(&priv->RxThread.comp);
+
+ }else if (status & IF_SDIO_INT_ERROR){
+ sdio_claim_host(card->func);
+ ret = wlan_write_byte(priv, IF_SDIO_FUN1_INT_PEND, IF_SDIO_INT_ERROR);
+ sdio_release_host(card->func);
+ if (ret){
+ WLAN_ERRP("write FUN1_INT_STAT reg fail \n");
+ goto out;
+ }
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_TRACE,"%s, INT_ERROR \n", __func__);
+ }
+
+out:
+ LEAVE();
+}
+
+extern unsigned int rda_wlan_version(void);
+
+static struct platform_device *platform_device = NULL;
+
+
+static ssize_t show_dbgl(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n",wlan_dbg_level);
+}
+
+static ssize_t store_dbgl(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ unsigned long dbgl;
+
+ if (strict_strtoul(buf, 0, &dbgl))
+ return -EINVAL;
+
+ wlan_dbg_level = dbgl;
+
+ return count;
+}
+
+static ssize_t show_dbga(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n",wlan_dbg_area);
+}
+
+static ssize_t store_dbga(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ unsigned long dbga;
+
+ if (strict_strtoul(buf, 0, &dbga))
+ return -EINVAL;
+
+ wlan_dbg_area = dbga;
+
+ return count;
+}
+
+static ssize_t show_wlanpm(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ wlan_private* priv = (wlan_private*)dev_get_drvdata(dev);
+ return sprintf(buf, "%d \n",priv?(u32)priv->wlan_pm_enable:0);
+}
+
+static ssize_t store_wlanpm(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ unsigned long wlanpm;
+ wlan_private* priv = (wlan_private*)dev_get_drvdata(dev);
+
+ if (strict_strtoul(buf, 0, &wlanpm))
+ return -EINVAL;
+
+ if(priv)
+ priv->wlan_pm_enable = wlanpm;
+
+ return count;
+}
+
+static ssize_t show_wlanirq(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ wlan_private* priv = (wlan_private*)dev_get_drvdata(dev);
+ return sprintf(buf, "%d \n",priv?(u32)priv->sdio_irq_enable:0);
+}
+static ssize_t store_wlanirq(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ unsigned long wlanirq;
+ wlan_private* priv = (wlan_private*)dev_get_drvdata(dev);
+ if (strict_strtoul(buf, 0, &wlanirq))
+ return -EINVAL;
+ if (wlanirq) {
+ rda_mci_enable_sdio_irq(priv->MmcCard->host, 1);
+ priv->sdio_irq_enable = TRUE;
+ } else {
+ //rda_mmc_set_sdio_irq(1, false);
+ rda_mci_enable_sdio_irq(priv->MmcCard->host, 0);
+ priv->sdio_irq_enable = FALSE;
+ }
+ return count;
+}
+static ssize_t show_wlan_earlysuspend_enabled(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ wlan_private* priv = (wlan_private*)dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",priv?(u32)priv->earlysuspend_enabled:0);
+}
+
+static ssize_t store_wlan_earlysuspend_enabled(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ int ret;
+ int set;
+ wlan_private* priv = (wlan_private*)dev_get_drvdata(dev);
+
+ ret = kstrtoint(buf, 0, &set);
+ if (ret < 0) {
+ return ret;
+ }
+
+ set = !!set;
+
+ if (priv->earlysuspend_enabled == set) {
+ return count;
+ }
+
+#ifdef WLAN_FORCE_SUSPEND_SUPPORT
+ if (set) {
+ ret = rda_wlan_late_resume(dev);
+ } else {
+ ret = rda_wlan_early_suspend(dev);
+ }
+#endif
+
+ priv->earlysuspend_enabled = set;
+
+ return count;
+}
+static DEVICE_ATTR(dbgl, S_IWUSR | S_IRUGO , show_dbgl, store_dbgl);
+static DEVICE_ATTR(dbga, S_IWUSR | S_IRUGO, show_dbga, store_dbga);
+static DEVICE_ATTR(wlanpm, S_IWUSR | S_IRUGO, show_wlanpm, store_wlanpm);
+static DEVICE_ATTR(wlanirq, S_IWUSR | S_IRUGO, show_wlanirq, store_wlanirq);
+static DEVICE_ATTR(enabled, S_IWUSR | S_IWGRP | S_IRUGO, show_wlan_earlysuspend_enabled, store_wlan_earlysuspend_enabled);
+
+static struct attribute *wlan_dbg_sysfs_entries[] = {
+ &dev_attr_dbgl.attr,
+ &dev_attr_dbga.attr,
+ &dev_attr_wlanpm.attr,
+ &dev_attr_wlanirq.attr,
+ &dev_attr_enabled.attr,
+ NULL,
+};
+
+static struct attribute_group wlan_dbg_attr_group = {
+ .attrs = wlan_dbg_sysfs_entries,
+};
+
+static int if_sdio_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ wlan_sdio_card * card = NULL;
+ wlan_private * priv = NULL;
+ int ret = -1;
+
+ ENTER();
+
+ if(func) {
+ printk("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__);
+ printk("sdio_bcmsdh: func->class=%x\n", func->class);
+ printk("sdio_vendor: 0x%04x\n", func->vendor);
+ printk("sdio_device: 0x%04x\n", func->device);
+ printk("Function#: 0x%04x\n", func->num);
+ } else {
+ printk("func is null\n");
+ }
+
+ if(id->vendor != SDIO_VENDOR_ID_RDA){
+ WLAN_ERRP("rda5890 sdio not corrent vendor:%x \n", id->vendor);
+ return -1;
+ }
+
+ card = (wlan_sdio_card*)kzalloc(sizeof(wlan_sdio_card), GFP_KERNEL);
+ if (!card){
+ ret = -ENOMEM;
+ goto err_alloc_card;
+ }
+
+ card->func = func;
+ sdio_set_drvdata(func, card);
+
+ if(wlan_add_card(card))
+ goto err_add_card;
+
+ priv = card->priv;
+ priv->MmcCard = func->card;
+ wlan_debugfs_init_all(priv);
+
+ platform_device = platform_device_alloc("rda-wlan", -1);
+ if (platform_device){
+ platform_set_drvdata(platform_device, priv);
+ if(!platform_device_add(platform_device)){
+ ret = sysfs_create_group(&platform_device->dev.kobj,
+ &wlan_dbg_attr_group);
+ }else{
+ platform_device_put(platform_device);
+ }
+ }
+
+ priv->netDev->netdev_ops = &rda_netdev_ops;
+ sdio_claim_host(func);
+ ret = sdio_enable_func(func);
+ if (ret){
+ WLAN_ERRP("sdio_enable_func fail, ret = %d\n", ret);
+ sdio_release_host(func);
+ goto err_enable_func;
+ }
+
+
+ rda_mci_enable_sdio_irq(priv->MmcCard->host, 0);
+ priv->version = rda_wlan_version();
+
+ ret = sdio_claim_irq(func, if_sdio_interrupt);
+ if (ret){
+ WLAN_ERRP("sdio_claim_irq fail, ret = %d\n", ret);
+ sdio_release_host(func);
+ goto err_claim_irq;
+ }
+
+ ret = -1;
+
+ //enable interrupt
+ if(wlan_write_byte(priv, IF_SDIO_FUN1_INT_MASK, 0x07)){
+ WLAN_ERRP("err_enable_int \n");
+ sdio_release_host(func);
+ goto err_enable_int;
+ }
+ sdio_release_host(func);
+
+ wlan_push_event(priv, WLAN_EVENT_CARD_CONTROL_INIT, priv, FALSE);
+
+#ifdef WLAN_FORCE_SUSPEND_SUPPORT
+ priv->pm_nb.notifier_call = rda_wlan_notify;
+ register_pm_notifier(&priv->pm_nb);
+#endif
+ LEAVE();
+
+ return 0;
+
+err_enable_int:
+err_claim_irq:
+err_enable_func:
+ wlan_release_dev(card);
+
+err_add_card:
+ kfree(card);
+
+err_alloc_card:
+
+ return ret;
+}
+
+
+static void if_sdio_remove(struct sdio_func *func)
+{
+ wlan_sdio_card * card = NULL;
+ wlan_private * priv = NULL;
+ ENTER();
+
+ card = (wlan_sdio_card *)sdio_get_drvdata(func);
+ if(!card)
+ return;
+
+ priv = (wlan_private*)card->priv;
+ if(!priv){
+ kfree(card);
+ return;
+ }
+
+ if(platform_device){
+ sysfs_remove_group(&platform_device->dev.kobj, &wlan_dbg_attr_group);
+ platform_device_unregister(platform_device);
+ platform_device = NULL;
+ }
+ wlan_debugfs_remove_all(priv);
+
+ sdio_claim_host(func);
+ sdio_release_irq(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+
+ rda_mci_enable_sdio_irq(priv->MmcCard->host, 0);
+ priv->sdio_irq_enable = FALSE;
+
+ wlan_unregister_host_wake_irq(priv);
+ wlan_release_dev(card);
+ kfree(card);
+ priv->MmcCard = NULL;
+ LEAVE();
+}
+
+static struct sdio_driver if_sdio_driver = {
+ .name = "rda_wlan_sdio",
+ .id_table = if_sdio_ids,
+ .probe = if_sdio_probe,
+ .remove = if_sdio_remove,
+#ifdef WLAN_SYS_SUSPEND
+ .drv.pm = &rda_sdio_pm_ops,
+#endif
+};
+
+extern void wmt_detect_sdio2(void);
+extern void force_remove_sdio2(void);
+
+static int __init wlan_init_module(void)
+{
+ int ret = 0;
+
+ printk(KERN_INFO "\nRDA5890 SDIO WIFI Driver for st_linux \n");
+ printk(KERN_INFO "Ver: %d.%d.%d\n\n",
+ WLAN_SDIOWIFI_VER_MAJ,
+ WLAN_SDIOWIFI_VER_MIN,
+ WLAN_SDIOWIFI_VER_BLD);
+ wlan_debugfs_init();
+ ret = sdio_register_driver(&if_sdio_driver);
+ wmt_detect_sdio2();
+ printk("wlan_init_module2014022801 %d \n", ret);
+ return ret;
+}
+
+static void __exit wlan_exit_module(void)
+{
+ sdio_unregister_driver(&if_sdio_driver);
+ wlan_debugfs_remove();
+ printk("wlan_exit_module \n");
+
+ force_remove_sdio2();
+
+
+}
+
+module_init(wlan_init_module);
+module_exit(wlan_exit_module);
+MODULE_DESCRIPTION("RDA SDIO WLAN Driver");
+MODULE_AUTHOR("albert");
+MODULE_LICENSE("GPL");
+
+#endif
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_nvram.c b/drivers/net/wireless/rda/rda_wlan/wlan_nvram.c
new file mode 100755
index 00000000..a48ba72b
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_nvram.c
@@ -0,0 +1,209 @@
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include "wlan_includes.h"
+
+#ifdef USE_MAC_FROM_RDA_NVRAM
+#include <plat/md_sys.h>
+#endif
+
+#define WIFI_NVRAM_FILE_NAME "/data/misc/wifi/WLANMAC"
+
+static int nvram_read(char *filename, char *buf, ssize_t len, int offset)
+{
+ struct file *fd;
+ int retLen = -1;
+
+ mm_segment_t old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ fd = filp_open(filename, O_WRONLY|O_CREAT, 0644);
+
+ if(IS_ERR(fd)){
+ printk("[wlan][nvram_read] : failed to open!!\n");
+ return -1;
+ }
+
+ do{
+ if ((fd->f_op == NULL) || (fd->f_op->read == NULL)){
+ printk("[wlan][nvram_read] : file can not be read!!\n");
+ break;
+ }
+
+ if (fd->f_pos != offset){
+ if (fd->f_op->llseek){
+ if(fd->f_op->llseek(fd, offset, 0) != offset){
+ printk("[wlan][nvram_read] : failed to seek!!\n");
+ break;
+ }
+ }else{
+ fd->f_pos = offset;
+ }
+ }
+
+ retLen = fd->f_op->read(fd, buf, len, &fd->f_pos);
+ }while(false);
+
+ filp_close(fd, NULL);
+ set_fs(old_fs);
+
+ return retLen;
+}
+
+static int nvram_write(char *filename, char *buf, ssize_t len, int offset)
+{
+ struct file *fd;
+ int retLen = -1;
+
+ mm_segment_t old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ fd = filp_open(filename, O_WRONLY|O_CREAT, 0644);
+
+ if(IS_ERR(fd)){
+ printk("[wlan][nvram_write] : failed to open!!\n");
+ return -1;
+ }
+
+ do{
+ if ((fd->f_op == NULL) || (fd->f_op->write == NULL)){
+ printk("[wlan][nvram_write] : file can not be write!!\n");
+ break;
+ }
+
+ if (fd->f_pos != offset){
+ if (fd->f_op->llseek){
+ if(fd->f_op->llseek(fd, offset, 0) != offset){
+ printk("[wlan][nvram_write] : failed to seek!!\n");
+ break;
+ }
+ }else{
+ fd->f_pos = offset;
+ }
+ }
+
+ retLen = fd->f_op->write(fd, buf, len, &fd->f_pos);
+
+ }while(false);
+
+ filp_close(fd, NULL);
+ set_fs(old_fs);
+
+ return retLen;
+}
+
+int wlan_read_mac_from_file(char* buf)
+{
+ return nvram_read(WIFI_NVRAM_FILE_NAME, buf, 6, 0);
+}
+
+int wlan_write_mac_to_file(char * buf)
+{
+ return nvram_write(WIFI_NVRAM_FILE_NAME, buf, 6, 0);
+}
+
+#ifdef USE_MAC_FROM_RDA_NVRAM
+int wlan_read_mac_from_nvram(char *buf)
+{
+ int ret;
+ struct msys_device *wlan_msys = NULL;
+ struct wlan_mac_info wlan_info;
+ struct client_cmd cmd_set;
+
+ wlan_msys = rda_msys_alloc_device();
+ if (!wlan_msys) {
+ WLAN_ERRP("nvram: can not allocate wlan_msys device\n");
+ ret = -ENOMEM;
+ goto err_handle_sys;
+ }
+
+ wlan_msys->module = SYS_GEN_MOD;
+ wlan_msys->name = "rda-wlan";
+ rda_msys_register_device(wlan_msys);
+
+ memset(&wlan_info, sizeof(wlan_info), 0);
+ cmd_set.pmsys_dev = wlan_msys;
+ cmd_set.mod_id = SYS_GEN_MOD;
+ cmd_set.mesg_id = SYS_GEN_CMD_GET_WIFI_INFO;
+ cmd_set.pdata = NULL;
+ cmd_set.data_size = 0;
+ cmd_set.pout_data = &wlan_info;
+ cmd_set.out_size = sizeof(wlan_info);
+
+ ret = rda_msys_send_cmd(&cmd_set);
+ if (ret) {
+ WLAN_ERRP("nvram:can not get wifi mac from nvram \n");
+ ret = -EBUSY;
+ goto err_handle_cmd;
+ }
+
+ if (wlan_info.activated != WIFI_MAC_ACTIVATED_FLAG) {
+ WLAN_ERRP("nvram:get invalid wifi mac address from nvram\n");
+ ret = -EINVAL;
+ goto err_invalid_mac;
+ }
+
+ memcpy(buf, wlan_info.mac_addr, ETH_ALEN);
+ WLAN_DBGLAP(WLAN_DA_MAIN, WLAN_DL_CRIT,
+ "nvram:get wifi mac address [%02x:%02x:%02x:%02x:%02x:%02x] from nvram success.\n",
+ buf[0], buf[1], buf[2],
+ buf[3], buf[4], buf[5]);
+ ret = 0; /* success*/
+
+err_invalid_mac:
+err_handle_cmd:
+ rda_msys_unregister_device(wlan_msys);
+ rda_msys_free_device(wlan_msys);
+err_handle_sys:
+ return ret;
+}
+
+int wlan_write_mac_to_nvram(const char *buf)
+{
+ int ret;
+ struct msys_device *wlan_msys = NULL;
+ struct wlan_mac_info wlan_info;
+ struct client_cmd cmd_set;
+
+ wlan_msys = rda_msys_alloc_device();
+ if (!wlan_msys) {
+ WLAN_ERRP("nvram: can not allocate wlan_msys device\n");
+ ret = -ENOMEM;
+ goto err_handle_sys;
+ }
+
+ wlan_msys->module = SYS_GEN_MOD;
+ wlan_msys->name = "rda-wlan";
+ rda_msys_register_device(wlan_msys);
+
+ memset(&wlan_info, sizeof(wlan_info), 0);
+ wlan_info.activated = WIFI_MAC_ACTIVATED_FLAG;
+ memcpy(wlan_info.mac_addr, buf, ETH_ALEN);
+
+ cmd_set.pmsys_dev = wlan_msys;
+ cmd_set.mod_id = SYS_GEN_MOD;
+ cmd_set.mesg_id = SYS_GEN_CMD_SET_WIFI_INFO;
+ cmd_set.pdata = &wlan_info;
+ cmd_set.data_size = sizeof(wlan_info);
+ cmd_set.pout_data = NULL;
+ cmd_set.out_size = 0;
+
+ ret = rda_msys_send_cmd(&cmd_set);
+ if (ret) {
+ WLAN_ERRP("nvram:can not set wifi mac to nvram \n");
+ ret = -EBUSY;
+ goto err_handle_cmd;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_MAIN, WLAN_DL_CRIT,
+ "nvram:set wifi mac address [%02x:%02x:%02x:%02x:%02x:%02x] to nvram success.\n",
+ buf[0], buf[1], buf[2],
+ buf[3], buf[4], buf[5]);
+ ret = 0; /* success*/
+
+err_handle_cmd:
+ rda_msys_unregister_device(wlan_msys);
+ rda_msys_free_device(wlan_msys);
+err_handle_sys:
+ return ret;
+}
+#endif /*USE_MAC_FROM_RDA_NVRAM*/
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_os.h b/drivers/net/wireless/rda/rda_wlan/wlan_os.h
new file mode 100755
index 00000000..72457746
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_os.h
@@ -0,0 +1,145 @@
+#ifndef __WLAN_TIMER_H_
+#define __WLAN_TIMER_H_
+
+typedef struct __WLAN_DRV_TIMER
+{
+ struct timer_list tl;
+ void (*timer_function) (void *context);
+ void *function_context;
+ u32 time_period;
+ u8 timer_is_periodic;
+ u8 timer_is_canceled;
+ u8 EventType;
+} WLAN_DRV_TIMER, *PWLAN_DRV_TIMER;
+
+extern void wlan_timer_handler(unsigned long fcontext);
+static inline void
+wlan_initialize_timer(PWLAN_DRV_TIMER timer,
+ void (*TimerFunction) (void *context),
+ void *FunctionContext, u8 eventType)
+{
+ /* first, setup the timer to trigger the wlan_timer_handler proxy */
+ init_timer(&timer->tl);
+ timer->tl.function = wlan_timer_handler;
+ timer->tl.data = (u32) timer;
+
+ /* then tell the proxy which function to call and what to pass it */
+ timer->timer_function = TimerFunction;
+ timer->function_context = FunctionContext;
+ timer->EventType = eventType;
+ timer->timer_is_canceled = TRUE;
+ timer->timer_is_periodic = FALSE;
+}
+
+static inline void
+wlan_set_timer(PWLAN_DRV_TIMER timer, u32 MillisecondPeriod)
+{
+ timer->time_period = MillisecondPeriod;
+ timer->timer_is_periodic = FALSE;
+ timer->tl.expires = jiffies + (MillisecondPeriod * HZ) / 1000;
+ add_timer(&timer->tl);
+ timer->timer_is_canceled = FALSE;
+}
+
+static inline void
+wlan_mod_timer(PWLAN_DRV_TIMER timer, u32 MillisecondPeriod)
+{
+ timer->time_period = MillisecondPeriod;
+ timer->timer_is_periodic = FALSE;
+ mod_timer(&timer->tl, jiffies + (MillisecondPeriod * HZ) / 1000);
+ timer->timer_is_canceled = FALSE;
+}
+
+static inline void
+wlan_set_periodic_timer(PWLAN_DRV_TIMER timer, u32 MillisecondPeriod)
+{
+ timer->time_period = MillisecondPeriod;
+ timer->timer_is_periodic = TRUE;
+ timer->tl.expires = jiffies + (MillisecondPeriod * HZ) / 1000;
+ add_timer(&timer->tl);
+ timer->timer_is_canceled = FALSE;
+}
+
+#define FreeTimer(x) do {} while (0)
+
+static inline void
+wlan_cancel_timer(WLAN_DRV_TIMER * timer)
+{
+ if(!timer->timer_is_canceled){
+ del_timer(&timer->tl);
+ timer->timer_is_canceled = TRUE;
+ }
+}
+
+static inline void wlan_sched_timeout(u32 millisec)
+{
+ unsigned long timeout = 0, expires = 0;
+ expires = jiffies + msecs_to_jiffies(millisec);
+ timeout = millisec;
+
+ while(timeout)
+ {
+ timeout = schedule_timeout(timeout);
+
+ if(time_after(jiffies, expires))
+ break;
+ }
+}
+
+/*
+ * OS Thread Specific
+ */
+
+#include <linux/kthread.h>
+
+typedef struct
+{
+ struct task_struct *task;
+ struct completion comp;
+ pid_t pid;
+ void *priv;
+} wlan_thread;
+
+static inline void
+wlan_activate_thread(wlan_thread * thr)
+{
+ /** Record the thread pid */
+ thr->pid = current->pid;
+ init_completion(&thr->comp);
+}
+
+static inline void
+wlan_deactivate_thread(wlan_thread * thr)
+{
+ ENTER();
+
+ /* Reset the pid */
+ thr->pid = 0;
+
+ LEAVE();
+}
+
+static inline void
+wlan_create_thread(int (*wlanfunc) (void *), wlan_thread * thr, char *name)
+{
+ thr->task = kthread_run(wlanfunc, thr, "%s", name);
+}
+
+static inline int
+wlan_terminate_thread(wlan_thread * thr)
+{
+ ENTER();
+
+ /* Check if the thread is active or not */
+ if (!thr->pid) {
+ printk(KERN_INFO "Thread does not exist\n");
+ return -1;
+ }
+ kthread_stop(thr->task);
+
+ LEAVE();
+ return 0;
+}
+
+#endif
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_rxtx.c b/drivers/net/wireless/rda/rda_wlan/wlan_rxtx.c
new file mode 100755
index 00000000..c9f13365
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_rxtx.c
@@ -0,0 +1,289 @@
+#include "wlan_includes.h"
+
+void wlan_process_rx(wlan_private *priv)
+{
+ wlan_rx_packet_node * rxNode = NULL;
+ u8 *payload = NULL, rx_type = 0, msg_type = 0;
+ u16 rx_len = 0;
+ struct sk_buff *skb = NULL;
+ unsigned long flags;
+
+ ENTER();
+
+ spin_lock_irqsave(&priv->RxLock, flags);
+ if (list_empty(&priv->RxQueue)) {
+ priv->RxQuNum=0;
+ spin_unlock_irqrestore(&priv->RxLock, flags);
+ return;
+ }
+ rxNode = list_first_entry(&priv->RxQueue, struct _wlan_rx_packet_node, List);
+ list_del(&rxNode->List);
+ if (priv->RxQuNum > 0)
+ priv->RxQuNum--;
+ spin_unlock_irqrestore(&priv->RxLock, flags);
+
+ skb = rxNode->Skb;
+ payload = skb->data;
+
+ rx_type = payload[1] & 0xf0;
+ rx_len = skb->len;
+
+ WLAN_DBGLAP(WLAN_DA_TXRX, WLAN_DL_TRACE,"payload len: %d type: %d \n", rx_len, rx_type);
+
+ switch(rx_type){
+ case HOST_MSG_CONFIGRSP:
+ {
+ msg_type = payload[2];
+
+ switch (msg_type) {
+ case 'I':
+ wlan_mac_status(priv, payload + 2, rx_len - 2);
+ break;
+
+ case 'R':
+ wlan_wid_response(priv, payload + 2, rx_len - 2);
+ break;
+
+ case 'N':
+ wlan_network_information(priv, payload + 2, rx_len - 2);
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case HOST_MSG_DATAIN:
+ {
+ skb_pull(skb, WID_HEADER_LEN);
+ skb->dev = priv->netDev;
+ skb->protocol = eth_type_trans(skb, priv->netDev);
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ {
+ struct ethhdr *eth;
+ eth = eth_hdr(skb);
+ //for wapi should verify packet length
+ if (ntohs(eth->h_proto) == 0x88b4){
+ rx_len = ((skb->data[6]) << 8) | skb->data[7];
+ skb->len = rx_len;
+ }
+ }
+
+ priv->stats.rx_packets++;
+ priv->stats.rx_bytes += skb->len;
+
+ WLAN_DBGLAP(WLAN_DA_TXRX, WLAN_DL_TRACE,
+ "DATA: %02x %02x %02x %02x ... ... %02x %02x %02x %02x\n",
+ skb->data[0], skb->data[1], skb->data[2],
+ skb->data[3], skb->data[4], skb->data[5],
+ skb->data[6], skb->data[7]);
+
+ netif_rx_ni(skb);
+ goto out_keep_skb;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+#ifdef WLAN_RAW_DATA_DEBUG
+ WLAN_ERRP("%x %x %x %x %x %x %x %x\n", payload[0], payload[1],payload[2],payload[3],payload[4],payload[5],payload[6],payload[7]);
+ payload += 8;
+ WLAN_ERRP("%x %x %x %x %x %x %x %x rx_len:%d\n", payload[0], payload[1],payload[2],payload[3],payload[4],payload[5],payload[6],payload[7], rx_len);
+#endif
+
+ dev_kfree_skb(skb);
+
+out_keep_skb:
+ kfree(rxNode);
+ LEAVE();
+ return;
+}
+
+
+int wlan_rx_thread(void *data)
+{
+ wlan_thread *thread = (wlan_thread *)data;
+ wlan_private *priv = thread->priv;
+
+ ENTER();
+
+ wlan_activate_thread(thread);
+
+ current->flags |= PF_NOFREEZE;
+
+ while(1){
+ wait_for_completion_interruptible(&thread->comp);
+
+ if (kthread_should_stop()){
+ WLAN_DBGLAP(WLAN_DA_TXRX, WLAN_DL_CRIT,"wlan_rx_thread: break from main thread \n");
+ break;
+ }
+
+ if(priv->CardRemoved)
+ break;
+ while (priv->RxQuNum)
+ wlan_process_rx(priv);
+ }
+
+ wlan_deactivate_thread(thread);
+
+ LEAVE();
+ return 0;
+}
+
+int wlan_tx_thread(void *data)
+{
+ u32 payloadLen = 0;
+ u8* payload = 0;
+ wlan_wid_packet_node * widNode = NULL;
+ wlan_tx_packet_node * txNode = NULL;
+ wlan_thread *thread = data;
+ wlan_private *priv = thread->priv;
+ unsigned long flags = 0;
+ int tx_queue_max_num =0;
+
+#ifdef WLAN_RAW_DATA_DEBUG
+ u8* printStr = NULL,
+#endif
+ ENTER();
+
+ if (priv->version == WLAN_VERSION_90_D || priv->version == WLAN_VERSION_90_E){
+ tx_queue_max_num = WLAN_TX_QUEUE_NUM_90;
+ } else if (priv->version == WLAN_VERSION_91 || priv->version == WLAN_VERSION_91_E|| priv->version == WLAN_VERSION_91_F) {
+ tx_queue_max_num = WLAN_TX_QUEUE_NUM_91;
+ } else {
+ tx_queue_max_num = WLAN_TX_QUEUE_NUM_90;
+ }
+
+ wlan_activate_thread(thread);
+
+ current->flags |= PF_NOFREEZE;
+
+ while(1) {
+
+ wait_for_completion_interruptible(&thread->comp);
+
+ if (kthread_should_stop() || priv->CardRemoved) {
+ WLAN_DBGLAP(WLAN_DA_TXRX, WLAN_DL_CRIT,"wlan_tx_thread: break from main thread \n");
+ break;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_DEBUG, "Tx Thread wakeup \n");
+
+ //wid_header_len ---data +++ data_len: whole buf_len= wid_header_len + skb->len
+ //send data
+ while(1){
+ spin_lock_irqsave(&priv->TxLock, flags);
+ if(list_empty(&priv->TxQueue)){
+ spin_unlock_irqrestore(&priv->TxLock, flags);
+ wlan_card_enter_sleep(priv);
+ break;
+ }
+ txNode = (wlan_tx_packet_node*)priv->TxQueue.next;
+ if(txNode){
+ list_del(&txNode->List);
+ spin_unlock_irqrestore(&priv->TxLock, flags);
+ }else{
+ WLAN_ERRP("should not happend!! \n");
+ spin_unlock_irqrestore(&priv->TxLock, flags);
+ break;
+ }
+
+ if(txNode->type == WLAN_DATA){
+ payloadLen = txNode->Skb->len + WID_HEADER_LEN;
+ payload = txNode->Skb->data - WID_HEADER_LEN;
+ //the first 2 byte was reserved from hard_header_len
+ payload[0] = (char)((payloadLen)&0xFF);
+ payload[1] = (char)(((payloadLen)>>8)&0x0F);
+ payload[1] |= 0x10; // for DataOut 0x1
+ }else if(txNode->type == WLAN_CMD){
+ widNode = txNode->wid_node;
+ if(!widNode->BufLen || !widNode->Buf){
+ WLAN_ERRP("WLAN_CMD widNode->BufLen is 0 or widNode->Buf is NULL! \n");
+ kfree(txNode);
+ break;
+ }
+ payloadLen = widNode->BufLen + WID_HEADER_LEN;
+ payload = widNode->Buf;
+ payload[0] = (char)((payloadLen)&0xFF);
+ payload[1] = (char)(((payloadLen)>>8)&0x0F);
+ payload[1] |= 0x40; // for WidRequest 0x40
+ if (is_sdio_init_complete())
+ init_completion(&priv->widComp);
+ } else
+ break;
+
+#ifdef WLAN_RAW_DATA_DEBUG
+ printStr = payload;
+ WLAN_ERRP("&&&send a data Packet to chip length:%d \n", payloadLen);
+ WLAN_ERRP("%x %x %x %x %x %x %x %x\n", printStr[0], printStr[1], printStr[2], printStr[3], printStr[4], printStr[5], printStr[6], printStr[7]);
+ printStr += 8;
+ WLAN_ERRP("%x %x %x %x %x %x %x %x\n", printStr[0], printStr[1], printStr[2], printStr[3], printStr[4], printStr[5], printStr[6], printStr[7]);
+ printStr += 8;
+ WLAN_ERRP("%x %x %x %x %x %x %x %x\n", printStr[0], printStr[1], printStr[2], printStr[3], printStr[4], printStr[5], printStr[6], printStr[7]);
+#endif
+
+ //for sdio must 4 bytes align
+ payloadLen = ((payloadLen + 3)/4)*4; // 4 byte align
+
+ if(wlan_write_sdio_2_ahb(priv, IF_SDIO_FUN1_FIFO_WR, payload, payloadLen)){
+ if(txNode->type == WLAN_DATA){
+ priv->stats.tx_dropped++;
+ priv->stats.tx_errors++;
+ }
+ WLAN_ERRP("wlan_write_bytes: Tx thread write data failed payload:%d \n", payloadLen);
+ }else{
+ WLAN_DBGLAP(WLAN_DA_TXRX, WLAN_DL_DEBUG,"&&& send payload:%d type:%d \n", payloadLen, txNode->type);
+
+ if(txNode->type == WLAN_DATA){
+ priv->stats.tx_packets++;
+ priv->stats.tx_bytes += txNode->Skb->len;
+ }else{
+ int left = 0;
+ if (!is_sdio_init_complete()) {
+ if (wlan_read_wid_rsp_polling(priv)) {
+ }
+ }else{
+ left = wait_for_completion_timeout(&priv->widComp, 5*HZ);
+ if(!left)
+ WLAN_ERRP("&&& wait wid cmd time out \n");
+ }
+ }
+ }
+
+ if(txNode->type == WLAN_DATA){
+ if(atomic_read(&(priv->TxQuNum)) > 0){
+ atomic_sub(1, &(priv->TxQuNum));
+ }
+ if ((atomic_read(&(priv->netifQuStop)) == 1)
+ && (atomic_read(&(priv->TxQuNum)) < tx_queue_max_num)) {
+ atomic_set(&(priv->netifQuStop), 0);
+ wlan_push_event(priv, WLAN_EVENT_START_NETIF, priv, FALSE);
+ }
+
+ }
+
+ //no matter it's send success or not we should free the skb buffer
+ if(txNode->Skb)
+ dev_kfree_skb(txNode->Skb);
+ kfree(txNode);
+ //do not send multi packet in one complete event
+ break;
+ }
+ if(priv->CardInSleep == false)
+ wlan_mod_timer(&priv->CardToSleepTimer, CARD_ENTER_SLEEP_TIMER);
+
+
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_DEBUG, "Tx Thread sleep \n");
+ }
+
+ wlan_deactivate_thread(thread);
+
+ LEAVE();
+ return 0;
+}
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_scan.c b/drivers/net/wireless/rda/rda_wlan/wlan_scan.c
new file mode 100755
index 00000000..1a76dbff
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_scan.c
@@ -0,0 +1,429 @@
+#include "wlan_includes.h"
+
+//#define SCAN_RESULT_DEBUG
+
+#ifndef FCS_LEN
+#define FCS_LEN 4
+#endif
+
+/* Element ID of various Information Elements */
+typedef enum {
+ ISSID = 0, /* Service Set Identifier */
+ ISUPRATES = 1, /* Supported Rates */
+ IFHPARMS = 2, /* FH parameter set */
+ IDSPARMS = 3, /* DS parameter set */
+ ICFPARMS = 4, /* CF parameter set */
+ ITIM = 5, /* Traffic Information Map */
+ IIBPARMS = 6, /* IBSS parameter set */
+ ICTEXT = 16, /* Challenge Text */
+ IERPINFO = 42, /* ERP Information */
+ IEXSUPRATES = 50, /* Extended Supported Rates */
+ IWAPI =68
+} ELEMENTID_T;
+
+/* Capability Information field bit assignments */
+typedef enum {
+ ESS = 0x01, /* ESS capability */
+ IBSS = 0x02, /* IBSS mode */
+ POLLABLE = 0x04, /* CF Pollable */
+ POLLREQ = 0x08, /* Request to be polled */
+ PRIVACY = 0x10, /* WEP encryption supported */
+ SHORTPREAMBLE = 0x20, /* Short Preamble is supported */
+ SHORTSLOT = 0x400, /* Short Slot is supported */
+ PBCC = 0x40, /* PBCC */
+ CHANNELAGILITY = 0x80, /* Channel Agility */
+ SPECTRUM_MGMT = 0x100, /* Spectrum Management */
+ DSSS_OFDM = 0x2000 /* DSSS-OFDM */
+} CAPABILITY_T;
+
+/* BSS type */
+typedef enum {
+ INFRASTRUCTURE = 1,
+ INDEPENDENT = 2,
+ ANY_BSS = 3
+} BSSTYPE_T;
+
+u8 *get_ie_elem(u8 * msa, ELEMENTID_T elm_id, u16 rx_len, u16 tag_param_offset)
+{
+ u16 index = 0;
+
+ /*************************************************************************/
+ /* Beacon Frame - Frame Body */
+ /* --------------------------------------------------------------------- */
+ /* |Timestamp |BeaconInt |CapInfo |SSID |SupRates |DSParSet |TIM elm | */
+ /* --------------------------------------------------------------------- */
+ /* |8 |2 |2 |2-34 |3-10 |3 |4-256 | */
+ /* --------------------------------------------------------------------- */
+ /* */
+ /*************************************************************************/
+
+ index = tag_param_offset;
+
+ /* Search for the TIM Element Field and return if the element is found */
+ while(index < (rx_len - FCS_LEN)) {
+ if(msa[index] == elm_id){
+ return(&msa[index]);
+ }else{
+ index += (2 + msa[index + 1]);
+ }
+ }
+
+ return(0);
+}
+
+/* This function extracts the 'from ds' bit from the MAC header of the input */
+/* frame. */
+/* Returns the value in the LSB of the returned value. */
+u8 get_from_ds(u8* header)
+{
+ return ((header[1] & 0x02) >> 1);
+}
+
+/* This function extracts the 'to ds' bit from the MAC header of the input */
+/* frame. */
+/* Returns the value in the LSB of the returned value. */
+u8 get_to_ds(u8* header)
+{
+ return (header[1] & 0x01);
+}
+
+/* This function extracts the MAC Address in 'address1' field of the MAC */
+/* header and updates the MAC Address in the allocated 'addr' variable. */
+void get_address1(u8* msa, u8* addr)
+{
+ memcpy(addr, msa + 4, 6);
+}
+
+/* This function extracts the MAC Address in 'address2' field of the MAC */
+/* header and updates the MAC Address in the allocated 'addr' variable. */
+void get_address2(u8* msa, u8* addr)
+{
+ memcpy(addr, msa + 10, 6);
+}
+
+/* This function extracts the MAC Address in 'address3' field of the MAC */
+/* header and updates the MAC Address in the allocated 'addr' variable. */
+void get_address3(u8* msa, u8* addr)
+{
+ memcpy(addr, msa + 16, 6);
+}
+
+/* This function extracts the BSSID from the incoming WLAN packet based on */
+/* the 'from ds' bit, and updates the MAC Address in the allocated 'addr' */
+/* variable. */
+void get_BSSID(u8* data, u8* bssid)
+{
+ if(get_from_ds(data) == 1)
+ get_address2(data, bssid);
+ else if(get_to_ds(data) == 1)
+ get_address1(data, bssid);
+ else
+ get_address3(data, bssid);
+}
+
+void wlan_network_information(wlan_private * priv, u8 * info, u16 info_len)
+{
+ struct bss_descriptor *iter_bss;
+ struct bss_descriptor *bss = NULL;
+ unsigned char *pos, *end, *p;
+ unsigned char n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
+ struct ieee_ie_country_info_set *pcountryinfo;
+
+ unsigned char* msa = &info[9];
+ unsigned short msa_len = info[6] | (info[7] << 8);
+
+#if 0
+ if(priv->scan_running == WLAN_SCAN_IDLE){
+ WLAN_ERRP("is not in scan process \n");
+ goto done;
+ }
+#endif
+
+ if((msa_len - 1 + 9 ) != info_len){
+ WLAN_ERRP("rda5890_network_information verify lengh feild failed \n");
+ }
+
+ bss = kzalloc(sizeof(struct bss_descriptor), GFP_KERNEL);
+ if (bss == NULL) {
+ WLAN_ERRP("alloc bss_descriptor memory failed \n");
+ return;
+ }
+ memset(bss, 0, sizeof (struct bss_descriptor));
+ bss->rssi = info[8];
+ msa_len -= 1; // has rssi
+
+ get_BSSID(msa, bss->bssid);
+
+ end = msa + msa_len;
+
+ //mac head
+ pos = msa + 24;
+ //time stamp
+ pos += 8;
+ //beacon
+ bss->beaconperiod = *(pos) | (*(pos + 1) << 8);
+ pos += 2 ;
+ //capability
+ bss->capability = *(pos) | (*(pos + 1) << 8);
+ pos += 2;
+
+ if (bss->capability & WLAN_CAPABILITY_IBSS)
+ bss->mode = IW_MODE_ADHOC;
+ else
+ bss->mode = IW_MODE_INFRA;
+
+ /* process variable IE */
+ while (pos + 2 <= end) {
+
+ if (pos + pos[1] > end) {
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("process_bss: error in processing IE, "
+ "bytes left < IE length\n");
+#endif
+ kfree(bss);
+ return;
+ }
+
+ switch (pos[0]) {
+ case WLAN_EID_SSID:
+ bss->ssid_len = min_t(int, IEEE80211_MAX_SSID_LEN, pos[1]);
+ memcpy(bss->ssid, pos + 2, bss->ssid_len);
+
+ if (priv->scan_ssid_len > 0) {
+ if (bss->ssid_len != priv->scan_ssid_len) {
+ kfree(bss);
+ return;
+ }
+
+ if (memcmp(bss->ssid, priv->scan_ssid, priv->scan_ssid_len)) {
+ kfree(bss);
+ return;
+ }
+ }
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got SSID IE: '%s', len %u %d\n",
+ bss->ssid, bss->ssid_len, pos[1]);
+#endif
+ break;
+
+ case WLAN_EID_SUPP_RATES:
+ n_basic_rates = min_t(uint8_t, MAX_RATES, pos[1]);
+ memcpy(bss->rates, pos + 2, n_basic_rates);
+ got_basic_rates = 1;
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got RATES IE\n");
+#endif
+ break;
+
+ case WLAN_EID_FH_PARAMS:
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got FH IE\n");
+#endif
+ break;
+
+ case WLAN_EID_DS_PARAMS:
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got DS IE\n");
+#endif
+ bss->channel = pos[2];
+ break;
+
+ case WLAN_EID_CF_PARAMS:
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got CF IE\n");
+#endif
+ break;
+
+ case WLAN_EID_IBSS_PARAMS:
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got IBSS IE\n");
+#endif
+ break;
+
+ case WLAN_EID_COUNTRY:
+ pcountryinfo = (struct ieee_ie_country_info_set *) pos;
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got COUNTRY IE\n");
+#endif
+ break;
+
+ case WLAN_EID_EXT_SUPP_RATES:
+ /* only process extended supported rate if data rate is
+ * already found. Data rate IE should come before
+ * extended supported rate IE
+ */
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got RATESEX IE\n");
+#endif
+ if (!got_basic_rates) {
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("... but ignoring it\n");
+#endif
+ break;
+ }
+
+ n_ex_rates = pos[1];
+ if (n_basic_rates + n_ex_rates > MAX_RATES)
+ n_ex_rates = MAX_RATES - n_basic_rates;
+
+ p = bss->rates + n_basic_rates;
+ memcpy(p, pos + 2, n_ex_rates);
+ break;
+
+ case WLAN_EID_GENERIC:
+ if (pos[1] >= 4 &&
+ pos[2] == 0x00 && pos[3] == 0x50 &&
+ pos[4] == 0xf2 && pos[5] == 0x01) {
+ bss->wpa_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
+ bss->wpa_ie = kzalloc(bss->wpa_ie_len, GFP_KERNEL);
+ if(bss->wpa_ie)
+ memcpy(bss->wpa_ie, pos, bss->wpa_ie_len);
+ else
+ bss->wpa_ie_len = 0;
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got WPA IE \n");
+#endif
+ }
+
+ /* huanglei add for wps */
+ else if(pos[1] >= 4 &&
+ pos[2] == 0x00 && pos[3] == 0x50 &&
+ pos[4] == 0xf2 && pos[5] == 0x04 &&
+ (priv->version == WLAN_VERSION_91_E || priv->version == WLAN_VERSION_91_F)) {
+ bss->wps_ie_len = min(pos[1] + 2, MAX_WPS_IE_LEN);
+ bss->wps_ie = kzalloc(bss->wps_ie_len, GFP_KERNEL);
+ if(bss->wps_ie)
+ memcpy(bss->wps_ie, pos, bss->wps_ie_len);
+ else
+ bss->wps_ie_len = 0;
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got WPS IE \n");
+#endif
+ }
+ else {
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got generic IE: %02x:%02x:%02x:%02x, len %d\n",
+ pos[2], pos[3], pos[4], pos[5], pos[1]);
+#endif
+ }
+ break;
+
+ case WLAN_EID_RSN:
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got RSN IE\n");
+#endif
+ bss->rsn_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
+ bss->rsn_ie = kzalloc(bss->rsn_ie_len, GFP_KERNEL);
+ if(bss->rsn_ie)
+ memcpy(bss->rsn_ie, pos, bss->rsn_ie_len);
+ else
+ bss->rsn_ie_len = 0;
+
+ break;
+
+ case IWAPI:
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("got WAPI IE\n");
+#endif
+ bss->wapi_ie_len = min(pos[1] + 2, 100);
+ bss->wapi_ie = kzalloc(bss->wapi_ie_len, GFP_KERNEL);
+ if(bss->wapi_ie)
+ memcpy(bss->wapi_ie, pos, bss->wapi_ie_len);
+ else
+ bss->wapi_ie_len = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ pos += pos[1] + 2;
+ }
+
+ bss->last_scanned = jiffies;
+
+ wlan_update_aver_rssi(priv, bss->bssid, bss->rssi);
+ /* add scaned bss into list */
+ if (1) {
+ struct bss_descriptor *found = NULL;
+ struct bss_descriptor *oldest = NULL;
+ struct bss_descriptor *unsed = NULL;
+ struct bss_descriptor *bss_lower_rssi = NULL;
+ s8 rssi = 0, lowRssi = 0;
+
+ spin_lock(&priv->ScanListLock);
+ /* Try to find this bss in the scan table */
+ list_for_each_entry(iter_bss, &priv->network_list, list) {
+ if (is_same_network(iter_bss, bss)) {
+ found = iter_bss;
+ break;
+ }
+
+ if (time_before(iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE, jiffies)) {
+ if(!oldest || (oldest->last_scanned > iter_bss->last_scanned))
+ oldest = iter_bss;
+ }
+
+ if (!iter_bss->ssid_len && unsed==NULL ) {
+ unsed=iter_bss;
+ break;
+ }
+
+ if(!is_zero_eth_addr(iter_bss->bssid)){
+ rssi = wlan_get_aver_rssi(priv, iter_bss->bssid);
+ if(bss_lower_rssi == NULL || rssi < lowRssi){
+ lowRssi = rssi;
+ bss_lower_rssi = iter_bss;
+ if(rssi == INVALID_RSSI)
+ break;
+ }
+ }
+ }
+
+ if (found) { // have in network list
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_DEBUG, "FOUND SAME %s, update\n", found->ssid);
+ /* found, clear it */
+ clear_bss_descriptor(found);
+ memcpy(found, bss, offsetof(struct bss_descriptor, list));
+ } else { //not have in network list
+ if (unsed) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_DEBUG,
+ "FOUND NEW %s, add\n", bss->ssid);
+ clear_bss_descriptor(unsed);
+ memcpy(unsed, bss, offsetof(struct bss_descriptor, list));
+ }else { // do not have space
+ if(oldest) { // have oldest
+ printk("**FOUND NEW %s, no space, replace oldest %s\n",
+ bss->ssid, oldest->ssid);
+ clear_bss_descriptor(oldest);
+ memcpy(oldest, bss, offsetof(struct bss_descriptor, list));
+ }else if (bss_lower_rssi) { // have lower rssi
+ printk("**FOUND NEW %s, no space, replace low_rssi %s\n",
+ bss->ssid, bss_lower_rssi->ssid);
+ clear_bss_descriptor(bss_lower_rssi);
+ memcpy(bss_lower_rssi, bss, offsetof(struct bss_descriptor, list));
+ }else { // don't have oldest
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_CRIT, "Networklist Oldest is NULL\n");
+ }
+ }
+ }
+ spin_unlock(&priv->ScanListLock);
+ }
+#ifdef SCAN_RESULT_DEBUG
+ WLAN_DBGP("rda5890_network_information .\n");
+#endif
+ kfree(bss);
+ return;
+}
+
+void wlan_report_scan_result(wlan_private * priv)
+{
+ union iwreq_data wrqu;
+ ENTER();
+ priv->scan_running = WLAN_SCAN_COMPLET;
+ memset(&wrqu, 0, sizeof(union iwreq_data));
+ wireless_send_event(priv->netDev, SIOCGIWSCAN, &wrqu, NULL);
+ wlan_mod_timer(&priv->CardToSleepTimer, 100);
+ LEAVE();
+}
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_sdio.c b/drivers/net/wireless/rda/rda_wlan/wlan_sdio.c
new file mode 100755
index 00000000..ff456053
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_sdio.c
@@ -0,0 +1,584 @@
+#include "wlan_includes.h"
+
+extern void rda_mci_enable_sdio_irq(struct mmc_host *mmc, int enable);
+void check_sdio_status(wlan_private * priv, int result)
+{
+#ifdef CHECK_SDIO_STAUTS
+ if (result) {
+ priv->SdioErrorCount++;
+ if ( !rda_combo_wifi_in_test_mode() && priv->SdioErrorCount > WLAN_SDIO_MAX_ERR) {
+ wlan_push_event(priv, WLAN_EVENT_CHECK_SDIO, priv, FALSE);
+ priv->SdioErrorCount = 0;
+ priv->sdio_need_reset = 1;
+ }
+ }else{
+ priv->SdioErrorCount = 0;
+ }
+#endif
+}
+
+int wlan_card_check_sdio(wlan_private * priv)
+{
+ int ret = 0;
+#ifdef WLAN_SDIO_RESET_DEBUG
+ priv->debug_count = 0;
+#endif
+ WLAN_ERRP("###################################################");
+ WLAN_ERRP("###################################################");
+ WLAN_ERRP("###################################################");
+
+ wlan_indicate_disconnected(priv);
+
+ ret = wlan_reset_card(priv);
+ if(ret < 0)
+ WLAN_ERRP("wlan sdio reset failed");
+ priv->sdio_need_reset = 0;
+ return 0;
+}
+int wlan_read_byte(wlan_private * priv, u32 addr, u8* data)
+{
+ wlan_sdio_card *card;
+ int ret = 0;
+
+ card = (wlan_sdio_card*)priv->card;
+
+ if (!card || !card->func){
+ WLAN_ERRP("wlan_read_byte(): card or function is NULL!\n");
+ return WLAN_STATUS_FAILED;
+ }
+
+ *data = sdio_readb(card->func, addr, &ret);
+ if (ret){
+ WLAN_ERRP("wlan_read_byte(): sdio_readb failed! ret=%d\n", ret);
+ //kevin add ,fix restore factory default. sdio fail too many time!
+ if(ret == -110){
+ WLAN_ERRP("sleep 100 msec\n");
+ msleep(100);
+ }
+ check_sdio_status(priv, ret);
+ }
+
+ return ret;
+}
+
+int wlan_write_byte(wlan_private * priv, u32 addr, u8 data)
+{
+ wlan_sdio_card *card;
+ int ret = 0;
+
+ card = (wlan_sdio_card*)priv->card;
+
+ if (!card || !card->func){
+ WLAN_ERRP("wlan_write_byte(): card or function is NULL!\n");
+ return WLAN_STATUS_FAILED;
+ }
+
+ sdio_writeb(card->func, data, addr, &ret);
+ if (ret){
+ WLAN_ERRP("wlan_write_byte(): sdio_writeb failed! ret=%d\n", ret);
+ check_sdio_status(priv, ret);
+ }
+
+ return ret;
+}
+
+int wlan_read_bytes(wlan_private * priv, u32 addr, u8* buf, u32 count)
+{
+ wlan_sdio_card *card;
+ int ret = 0;
+
+ card = (wlan_sdio_card*)priv->card;
+
+ if (!card || !card->func){
+ WLAN_ERRP("wlan_read_bytes(): card or function is NULL!\n");
+ return WLAN_STATUS_FAILED;
+ }
+
+ ret = sdio_readsb(card->func, buf, addr, count);
+ if (ret){
+ WLAN_ERRP("wlan_read_bytes(): sdio_readsb failed! ret=%d\n", ret);
+ check_sdio_status(priv, ret);
+ }else{
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_DEBUG, "wlan_read_bytes :len %d\n", count);
+ }
+
+ return ret;
+}
+
+int wlan_write_sdio_2_ahb(wlan_private * priv, u32 addr, u8* buf, u32 count)
+{
+ wlan_sdio_card *card;
+ int ret = 0;
+ u16 size = 0;
+ u8 size_l = 0, size_h = 0;
+ u16 bytes_left = 0, offset = 0, batch = 0;
+#ifdef RDA_ANDROID_PLATFORM
+ u32 blockSize = 4, nb = 0;
+ u8 *packet_to_send = NULL;
+ struct page *pg = NULL;
+#endif
+ card = (wlan_sdio_card*)priv->card;
+
+ if (!card || !card->func ){
+ WLAN_ERRP("wlan_read_byte(): card or function is NULL!\n");
+ return WLAN_STATUS_FAILED;
+ }
+
+ if(rda_combo_wifi_in_test_mode() && is_sdio_init_complete()){
+ return WLAN_STATUS_SUCCESS;
+ }
+
+ if (priv->version == WLAN_VERSION_90_D
+ || priv->version == WLAN_VERSION_90_E) {
+ ret = wlan_sdio_flow_ctrl_90(priv);
+ if(ret){
+ WLAN_ERRP("wlan_sdio_flow_ctrl 5990 failed! \n");
+ return ret;
+ }
+ } else if(priv->version == WLAN_VERSION_91){
+ ret = wlan_sdio_flow_ctrl_91(priv);
+ if(ret){
+ WLAN_ERRP("wlan_sdio_flow_ctrl 5991 failed! \n");
+ return ret;
+ }
+ }else if (priv->version == WLAN_VERSION_91_E) {
+ ret = wlan_sdio_flow_ctrl_91e(priv);
+ if (ret) {
+ WLAN_ERRP("wlan_sdio_flow_ctrl 5991e failed! \n");
+ return ret;
+ }
+ }else if (priv->version == WLAN_VERSION_91_F) {
+ ret = wlan_sdio_flow_ctrl_91e(priv);
+ if (ret) {
+ WLAN_ERRP("wlan_sdio_flow_ctrl 5991f failed! \n");
+ return ret;
+ }
+ } else {
+ WLAN_ERRP("wlan_sdio_flow_ctrl unkown version:%d\n",priv->version);
+ return ret;
+ }
+
+// IN rda android platform sdio should 2^n alligen
+#ifdef RDA_ANDROID_PLATFORM
+ if(count > card->func->cur_blksize){//the left bytes should be 2^n alligen
+ nb = count%(card->func->cur_blksize);
+ count -= nb;
+ while (blockSize < nb ){
+ blockSize = blockSize << 1;
+ }
+ count += blockSize;
+ blockSize = count;
+ } else {
+ while (blockSize < count){
+ blockSize = blockSize << 1;
+ }
+ }
+ size = blockSize/4;
+ count = blockSize;
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_DEBUG,"wlan_write_sdio_2_ahb size:%d %d cur_blk:%d\n",count, blockSize, card->func->cur_blksize);
+#else
+ size = count/4;
+#endif
+ size_l = size & 0xff;
+ size_h = ((size >> 8) & 0x7f) | 0x80; //0x80 flags means lenght higer bytes
+
+ sdio_claim_host(card->func);
+ ret = wlan_write_byte(priv, IF_SDIO_SDIO2AHB_PKTLEN_L, size_l);
+ if(ret){
+ WLAN_ERRP("SDIO write size_l failed! \n");
+ goto out;
+ }
+
+ ret = wlan_write_byte(priv, IF_SDIO_SDIO2AHB_PKTLEN_H, size_h);
+ if(ret){
+ WLAN_ERRP("SDIO write size_h failed! \n");
+ goto out;
+ }
+
+ bytes_left = count;
+ while(bytes_left){
+ batch = bytes_left > card->func->cur_blksize?card->func->cur_blksize:bytes_left;
+#ifdef RDA_ANDROID_PLATFORM
+ {
+ packet_to_send = buf + offset;
+
+ if (((u32)packet_to_send >> PAGE_SHIFT) !=
+ (((u32)packet_to_send + batch - 1) >> PAGE_SHIFT)){
+
+ pg = alloc_page(GFP_KERNEL);
+ if(!pg){
+ ret = -1;
+ break;
+ }
+ memcpy(page_address(pg), packet_to_send, batch);
+ packet_to_send = page_address(pg);
+
+ ret = sdio_writesb(card->func, addr, packet_to_send, batch);
+ __free_page(pg);
+ WLAN_ERRP("wlan data cross page boundary addr:%x size:%x \n", (u32)(buf + offset), batch);
+ }else
+ ret = sdio_writesb(card->func, addr, packet_to_send, batch);
+ }
+#else
+ ret = sdio_writesb(card->func, addr, buf + offset, batch);
+#endif
+ if (ret){
+ WLAN_ERRP("SDIO sdio_writesb failed! ret=%d len:%d \n", ret, size*4);
+ break;
+ }
+ offset += batch;
+ bytes_left -= batch;
+ }
+#ifdef WLAN_SDIO_RESET_DEBUG
+ priv->debug_count++;
+#endif
+out:
+ sdio_release_host(card->func);
+#ifdef WLAN_SDIO_RESET_DEBUG
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_DEBUG, "########### len %d debug_count:%d #######********\n", size * 4, priv->debug_count);
+ if(priv->debug_count > 300)
+ ret = -5;
+#endif
+ if (ret)
+ check_sdio_status(priv, ret);
+ return ret;
+}
+
+int wlan_wake_up_card(wlan_private * priv)
+{
+ int ret = 0;
+#ifdef WLAN_POWER_MANAGER
+ wlan_sdio_card *card = (wlan_sdio_card*)priv->card;
+#endif
+
+ ENTER();
+#ifdef WLAN_POWER_MANAGER
+ if (!rda_combo_wifi_in_test_mode()){
+ atomic_set(&priv->CardNeedSleep, FALSE);
+ if(priv->CardInSleep) {
+ WLAN_DBGLAP(WLAN_DA_PM, WLAN_DL_DEBUG, "wake up card \n");
+ sdio_claim_host(card->func);
+ ret = wlan_write_byte(priv, IF_SDIO_FUN1_INT_TO_DEV, 1);
+ sdio_release_host(card->func);
+ if(ret){
+ WLAN_ERRP("wakeup card failed \n");
+ }else{
+ priv->CardInSleep = FALSE;
+ WLAN_DBGLAP(WLAN_DA_PM, WLAN_DL_DEBUG,
+ "CardInSleep = FALSE \n");
+ wlan_sched_timeout(10);
+ }
+
+ if (!priv->CardSleepWakeLockOn) {
+ priv->CardSleepWakeLockOn = TRUE;
+ wake_lock(&priv->CardSleepTimerLock);
+ }
+ }
+ }
+#endif
+ LEAVE();
+ return ret;
+}
+
+void handle_card_to_sleep_cmd(wlan_private * priv)
+{
+ atomic_set(&priv->CardNeedSleep, TRUE);
+ complete(&priv->TxThread.comp);
+}
+int wlan_card_enter_sleep(wlan_private * priv)
+{
+ int ret = 0;
+#ifdef WLAN_POWER_MANAGER
+ wlan_sdio_card *card = (wlan_sdio_card *) priv->card;
+#endif
+
+ ENTER();
+
+#ifdef WLAN_POWER_MANAGER
+ if (!rda_combo_wifi_in_test_mode()
+ && priv->wlan_pm_enable
+ && (priv->scan_running != WLAN_SCAN_RUNNING)
+ && (!priv->assoc_ongoing)) {
+ if(atomic_read(&priv->CardNeedSleep)) {
+ sdio_claim_host(card->func);
+ ret = wlan_write_byte(priv, IF_SDIO_FUN1_INT_PEND, IF_SDIO_HOST_TX_FLAG);
+ sdio_release_host(card->func);
+ if (ret) {
+ WLAN_ERRP("enter sleep failed \n");
+ wlan_mod_timer(&priv->CardToSleepTimer, CARD_ENTER_SLEEP_TIMER);
+ return ret;
+ } else {
+ priv->CardInSleep = TRUE;
+ WLAN_DBGLAP(WLAN_DA_PM, WLAN_DL_DEBUG, "CardInSleep = TRUE \n");
+ atomic_set(&priv->CardNeedSleep, FALSE);
+ }
+ if (priv->CardSleepWakeLockOn) {
+ wake_unlock(&priv->CardSleepTimerLock);
+ priv->CardSleepWakeLockOn = FALSE;
+ }
+ if(!(priv->CardToSleepTimer).timer_is_canceled)
+ wlan_cancel_timer(&priv->CardToSleepTimer);
+
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_DEBUG, "card enter sleep \n");
+ } else {
+ wlan_mod_timer(&priv->CardToSleepTimer, CARD_ENTER_SLEEP_TIMER);
+ }
+ }
+
+#endif
+ LEAVE();
+ return ret;
+}
+#ifdef WLAN_FLOW_CTRL_90E
+int wlan_sdio_flow_ctrl_90(wlan_private * priv)
+{
+ int ret = 0;
+ u8 status = 0;
+ s32 int_sleep_count = 0;
+ wlan_sdio_card *card = (wlan_sdio_card *) priv->card;
+
+ ENTER();
+ wlan_wake_up_card(priv);
+ while ((!priv->CardRemoved) && is_sdio_patch_complete()) {
+ sdio_claim_host(card->func);
+ ret = wlan_read_byte(priv, IF_SDIO_FUN1_INT_PEND, &status);
+ sdio_release_host(card->func);
+ if (ret) {
+ WLAN_ERRP("wlan read IF_SDIO_FUN1_INT_PEND failed \n");
+ schedule();
+ continue;
+ }
+ if ((status & IF_SDIO_INT_SLEEP) == 0) { // If SDIO can't write
+ if (int_sleep_count >= FLOW_CTRL_INT_SLEEP_RETRY_COUNT_90){
+ WLAN_ERRP("Flow_ctrl:max int_sleep_count:%d\n",int_sleep_count);
+ complete(&priv->RxThread.comp);
+ msleep(100);
+ break;
+ } else {
+ int_sleep_count++;
+ }
+ } else {
+ if (int_sleep_count > 10)
+ WLAN_ERRP("Flow_ctrl:int_sleep_count:%d\n",int_sleep_count);
+ sdio_claim_host(card->func);
+ ret = wlan_write_byte(priv, IF_SDIO_FUN1_INT_PEND, IF_SDIO_INT_SLEEP);
+ sdio_release_host(card->func);
+ break;
+ }
+ schedule();
+ }
+ LEAVE();
+ return ret;
+}
+#else
+//return 0 success
+int wlan_sdio_flow_ctrl_90(wlan_private * priv)
+{
+ int ret = -1;
+ u8 status = 0;
+ s32 count = 0;
+ wlan_sdio_card * card = (wlan_sdio_card*)priv->card;
+
+ //first wake up card if needed
+ wlan_wake_up_card(priv);
+
+
+ ENTER();
+
+ while(!priv->CardRemoved){
+ sdio_claim_host(card->func);
+ ret = wlan_read_byte(priv,IF_SDIO_FUN1_INT_PEND, &status);
+ sdio_release_host(card->func);
+ if(status & IF_SDIO_INT_RXCMPL)
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_DEBUG, "IF_SDIO_FUN1_INT_PEND:count count %d : %x \n",count, status);
+ if(!ret){
+ if((status & IF_SDIO_INT_RXCMPL) == 0){ //flows ctrl failed
+ if(count > FLOW_CTRL_RXCMPL_RETRY_COUNT_90){
+ sdio_claim_host(card->func);
+ wlan_write_byte( priv, IF_SDIO_FUN1_INT_PEND, 0x40);
+ sdio_release_host(card->func);
+ complete(&priv->RxThread.comp);
+ msleep(100);
+ ret = 0;
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_CRIT,
+ "flows ctrl RXCMPL failed, count:%d over,return back \n",
+ FLOW_CTRL_RXCMPL_RETRY_COUNT_90);
+ break;
+ } else {
+ count ++ ;
+ }
+ }else{
+ sdio_claim_host(card->func);
+ ret = wlan_write_byte( priv, IF_SDIO_FUN1_INT_PEND, 0x40);
+ sdio_release_host(card->func);
+ if(!ret){
+ break;
+ }
+ }
+ }
+ schedule();
+ }
+
+ LEAVE();
+ return ret;
+}
+#endif
+
+//return 0 success
+int wlan_sdio_flow_ctrl_91(wlan_private * priv)
+{
+ int ret = 0;
+ u8 status = 0;
+ s32 int_sleep_count = 0;
+ wlan_sdio_card * card = (wlan_sdio_card*)priv->card;
+
+ ENTER();
+
+ //first wake up card if needed
+ wlan_wake_up_card(priv);
+
+
+
+ while ((!priv->CardRemoved) && is_sdio_patch_complete()) {
+ sdio_claim_host(card->func);
+ ret = wlan_read_byte(priv,IF_SDIO_FUN1_INT_PEND, &status);
+ sdio_release_host(card->func);
+ if(ret){
+ WLAN_ERRP("wlan read IF_SDIO_FUN1_INT_PEND failed \n");
+ schedule();
+ continue;
+ }
+
+ if ((status & IF_SDIO_INT_SLEEP) == 0) { // If SDIO can't write
+ if (int_sleep_count >= FLOW_CTRL_INT_SLEEP_RETRY_COUNT_91){
+ break;
+ } else {
+ int_sleep_count++;
+ }
+ }else{
+ sdio_claim_host(card->func);
+ ret = wlan_write_byte(priv, IF_SDIO_FUN1_INT_PEND, IF_SDIO_INT_SLEEP);
+ sdio_release_host(card->func);
+ break;
+
+ }
+ if(int_sleep_count < 20)
+ udelay(10);
+ else
+ msleep(1);
+ }
+ LEAVE();
+ return ret;
+}
+#ifndef FLOWCTRL_91E
+//return 0 success
+//int seq_num =0;
+int wlan_sdio_flow_ctrl_91e(wlan_private * priv)
+{
+ int ret = -1;
+ u8 status = 0;
+ s32 count = 0;
+ wlan_sdio_card *card = (wlan_sdio_card *) priv->card;
+
+ wlan_wake_up_card(priv);
+
+ ENTER();
+
+ while (!priv->CardRemoved) {
+ sdio_claim_host(card->func);
+ ret = wlan_read_byte(priv, IF_SDIO_FUN1_INT_PEND, &status);
+ sdio_release_host(card->func);
+ if (status & IF_SDIO_INT_RXCMPL)
+ WLAN_DBGLAP(WLAN_DA_SDIO, WLAN_DL_DEBUG, "IF_SDIO_FUN1_INT_PEND:count count %d : %x \n", count, status);
+ if (!ret) {
+ if ((status & IF_SDIO_INT_RXCMPL) == 0) { //flows ctrl failed
+ if (count > FLOW_CTRL_RXCMPL_RETRY_COUNT_91) {
+ sdio_claim_host(card->func);
+ wlan_write_byte(priv, IF_SDIO_FUN1_INT_PEND, 0x40);
+ sdio_release_host(card->func);
+ complete(&priv->RxThread.comp);
+ //msleep(100);
+ ret = 0;
+ //seq_num++;
+ //if(count>4)
+ //printk("count is %d,seq is %d,sleep_st is %d\n",count,seq_num,priv->CardInSleep);
+ break;
+ } else {
+ count++;
+ }
+ //schedule();
+ if(count < 20)
+ udelay(2);
+ else
+ msleep(1);
+ } else {
+ sdio_claim_host(card->func);
+ ret = wlan_write_byte(priv, IF_SDIO_FUN1_INT_PEND,0x40);
+ sdio_release_host(card->func);
+ //seq_num++;
+ //if(count>5)
+ //printk("count is %d,seq is %d,sleep_st is %d\n",count,seq_num,priv->CardInSleep);
+ if (!ret) {
+ break;
+ }
+ }
+ }
+ //schedule();
+
+ }
+
+ LEAVE();
+ return ret;
+}
+#else
+//int seq_num =0;
+//return 0 success
+int wlan_sdio_flow_ctrl_91e(wlan_private * priv)
+{
+ int ret = 0;
+ u8 status = 0;
+ s32 int_sleep_count = 0;
+ wlan_sdio_card *card = (wlan_sdio_card *) priv->card;
+
+ ENTER();
+
+ wlan_wake_up_card(priv);
+
+ while ((!priv->CardRemoved) && is_sdio_patch_complete()) {
+ sdio_claim_host(card->func);
+ ret = wlan_read_byte(priv, IF_SDIO_FUN1_INT_PEND, &status);
+ sdio_release_host(card->func);
+ if (ret) {
+ WLAN_ERRP("wlan read IF_SDIO_FUN1_INT_PEND failed \n");
+ schedule();
+ continue;
+ }
+
+ if ((status & IF_SDIO_INT_SLEEP) == 0) { // If SDIO can't write
+ if (int_sleep_count >= FLOW_CTRL_INT_SLEEP_RETRY_COUNT_91){
+ //seq_num++;
+ //printk("count is %d,seq is %d,sleep_st is %d\n",int_sleep_count,seq_num,priv->CardInSleep);
+ break;
+ } else {
+ int_sleep_count++;
+ }
+ } else {
+
+ //seq_num++;
+ //if(int_sleep_count > 10)
+ // printk("count is %d,seq is %d,sleep_st is %d\n",int_sleep_count,seq_num,priv->CardInSleep);
+ sdio_claim_host(card->func);
+ ret = wlan_write_byte(priv, IF_SDIO_FUN1_INT_PEND, IF_SDIO_INT_SLEEP);
+ sdio_release_host(card->func);
+ break;
+ }
+ if(int_sleep_count < 20)
+ udelay(10);
+ else
+ msleep(1);
+ }
+ LEAVE();
+ return ret;
+}
+#endif
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_sdio.h b/drivers/net/wireless/rda/rda_wlan/wlan_sdio.h
new file mode 100755
index 00000000..8306e695
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_sdio.h
@@ -0,0 +1,42 @@
+#ifndef _RDA5890_IF_SDIO_H
+#define _RDA5890_IF_SDIO_H
+#include <linux/mmc/core.h>
+
+#define IF_SDIO_SDIO2AHB_PKTLEN_L 0x00
+#define IF_SDIO_SDIO2AHB_PKTLEN_H 0x01
+
+#define IF_SDIO_AHB2SDIO_PKTLEN_L 0x02
+#define IF_SDIO_AHB2SDIO_PKTLEN_H 0x03
+
+#define IF_SDIO_FUN1_INT_MASK 0x04
+#define IF_SDIO_FUN1_INT_PEND 0x05
+#define IF_SDIO_FUN1_INT_STAT 0x06
+
+#define IF_SDIO_INT_AHB2SDIO 0x01
+#define IF_SDIO_INT_ERROR 0x04
+#define IF_SDIO_INT_SLEEP 0x10
+#define IF_SDIO_INT_AWAKE 0x20
+#define IF_SDIO_INT_RXCMPL 0x40
+#define IF_SDIO_HOST_TX_FLAG 0x80
+
+#define IF_SDIO_FUN1_FIFO_WR 0x07
+#define IF_SDIO_FUN1_FIFO_RD 0x08
+
+#define IF_SDIO_FUN1_INT_TO_DEV 0x09
+
+int wlan_card_check_sdio(wlan_private * priv);
+int wlan_read_byte(wlan_private * priv, u32 addr, u8* data);
+int wlan_write_byte(wlan_private * priv, u32 addr, u8 data);
+int wlan_read_bytes(wlan_private * priv, u32 addr, u8* buf, u32 count);
+int wlan_write_sdio_2_ahb(wlan_private * priv, u32 addr, u8* buf, u32 count);
+int wlan_wake_up_card(wlan_private * priv);
+int wlan_card_enter_sleep(wlan_private * priv);
+void handle_card_to_sleep_cmd(wlan_private * priv);
+int wlan_sdio_flow_ctrl_90(wlan_private * priv);
+int wlan_sdio_flow_ctrl_91(wlan_private * priv);
+int wlan_sdio_flow_ctrl_91e(wlan_private * priv);
+int sdio_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
+int sdio_select_card(struct mmc_host *host, struct mmc_card *card);
+int sdio_send_relative_addr(struct mmc_host *host, unsigned int *rca);
+#endif
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch.c b/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch.c
new file mode 100755
index 00000000..24842297
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch.c
@@ -0,0 +1,429 @@
+#include "wlan_includes.h"
+#include "wlan_sdio_patch_90.h"
+#include "wlan_sdio_patch_91.h"
+#include "wlan_sdio_patch_91e.h"
+#include "wlan_sdio_patch_91f.h"
+
+static u8 sdio_patch_complete = 0;
+static atomic_t sdio_init_complete = ATOMIC_INIT(0);
+
+int wlan_get_fw_version_polling(wlan_private *priv, u32* version)
+{
+ int ret = 0;
+
+ ENTER();
+
+ ret = wlan_generic_get_ulong(priv, WID_SYS_FW_VER, (u8*)version);
+ if (ret) {
+ WLAN_ERRP("get version failed \n");
+ goto out;
+ }
+
+ WLAN_ERRP("version %x \n", *version);
+
+out:
+ LEAVE();
+ return ret;
+}
+
+int wlan_write_sdio32_polling(wlan_private * priv, const u32(*data)[2],
+ u32 size)
+{
+ int count = size, index = 0;
+ int ret = 0;
+
+ ENTER();
+ //each time write five init data
+ for(index = 0; index < count/8; index ++){
+ ret = wlan_set_core_init_patch(priv, (const unsigned int (*)[2])&data[8*index][0], 8);
+ if(ret)
+ goto err;
+ WLAN_DBGLAP(WLAN_DA_PM, WLAN_DL_DEBUG, "index:%d\n", index);
+ }
+
+ if(count%8 > 0){
+ ret = wlan_set_core_init_patch(priv, (const unsigned int (*)[2])&data[8*index][0], count%8);
+ if(ret)
+ goto err;
+ }
+err:
+ LEAVE();
+ return ret;
+}
+
+int wlan_write_sdio8_polling(wlan_private *priv, const u8 (*data)[2], u32 size)
+{
+ int count = size, index = 0;
+ int ret = 0;
+
+ ENTER();
+ //each time write five init data
+ for(index = 0; index < count/8; index ++){
+ WLAN_DBGLAP(WLAN_DA_PM, WLAN_DL_DEBUG, "index:%d\n", index);
+ ret = wlan_set_core_patch(priv, (const unsigned char (*)[2])data[8*index], 8);
+ if(ret)
+ goto err;
+ }
+
+ if(count%8 > 0){
+ ret = wlan_set_core_patch(priv, (const unsigned char (*)[2])data[8*index], count%8);
+ if(ret)
+ goto err;
+ }
+
+err:
+ LEAVE();
+ return ret;
+}
+
+int wlan_sdio_patch_core_32(wlan_private *priv)
+{
+ int ret = 0;
+
+ ENTER();
+
+ if (priv->version == WLAN_VERSION_90_D) {
+ ret = wlan_write_sdio32_polling(priv, wifi_core_patch_data_32_90_D,
+ sizeof(wifi_core_patch_data_32_90_D) /
+ sizeof(wifi_core_patch_data_32_90_D[0]));
+ } else if (priv->version == WLAN_VERSION_90_E) {
+ ret = wlan_write_sdio32_polling(priv, wifi_core_patch_data_32_90_E,
+ sizeof(wifi_core_patch_data_32_90_E) /
+ sizeof(wifi_core_patch_data_32_90_E[0]));
+ } else if (priv->version == WLAN_VERSION_91) {
+ ret = wlan_write_sdio32_polling(priv, wifi_core_patch_data_32_91,
+ sizeof(wifi_core_patch_data_32_91)/
+ sizeof(wifi_core_patch_data_32_91[0]));
+
+ ret = wlan_write_sdio32_polling(priv, wifi_clock_switch_91,
+ sizeof(wifi_clock_switch_91) /
+ sizeof(wifi_clock_switch_91[0]));
+ }else if (priv->version == WLAN_VERSION_91_E) {
+ ret = wlan_write_sdio32_polling(priv, wifi_core_patch_data_32_91e,
+ sizeof(wifi_core_patch_data_32_91e)/
+ sizeof(wifi_core_patch_data_32_91e[0]));
+
+ ret = wlan_write_sdio32_polling(priv, wifi_clock_switch_91e,
+ sizeof(wifi_clock_switch_91e) /
+ sizeof(wifi_clock_switch_91e[0]));
+ }else if (priv->version == WLAN_VERSION_91_F) {
+ ret = wlan_write_sdio32_polling(priv, wifi_core_patch_data_32_91f,
+ sizeof(wifi_core_patch_data_32_91f)/
+ sizeof(wifi_core_patch_data_32_91f[0]));
+ ret = wlan_write_sdio32_polling(priv, wifi_clock_switch_91f,
+ sizeof(wifi_clock_switch_91f) /
+ sizeof(wifi_clock_switch_91f[0]));
+ }
+ LEAVE();
+ return ret;
+}
+
+int wlan_sdio_init_core_polling(wlan_private *priv)
+{
+ int ret = 0;
+
+ ENTER();
+ if(priv->version == WLAN_VERSION_90_D)
+ ret = wlan_write_sdio32_polling(priv, wifi_core_init_data_32_90_D,
+ sizeof(wifi_core_init_data_32_90_D) /
+ sizeof(wifi_core_init_data_32_90_D[0]));
+ else if(priv->version == WLAN_VERSION_90_E)
+ ret = wlan_write_sdio32_polling(priv, wifi_core_init_data_32_90_E,
+ sizeof(wifi_core_init_data_32_90_E) /
+ sizeof(wifi_core_init_data_32_90_E[0]));
+ else if(priv->version == WLAN_VERSION_91){
+ ret = wlan_write_sdio32_polling(priv, wifi_core_init_data_32_91,
+ sizeof(wifi_core_init_data_32_91) /
+ sizeof(wifi_core_init_data_32_91[0]));
+ ret = wlan_write_sdio32_polling(priv, wifi_core_AM_PM_data_32_91,
+ sizeof(wifi_core_AM_PM_data_32_91)/
+ sizeof(wifi_core_AM_PM_data_32_91[0]));
+ }else if (priv->version == WLAN_VERSION_91_E) {
+ ret = wlan_write_sdio32_polling(priv, wifi_core_init_data_32_91e,
+ sizeof(wifi_core_init_data_32_91e) /
+ sizeof(wifi_core_init_data_32_91e[0]));
+ ret = wlan_write_sdio32_polling(priv, wifi_core_AM_PM_data_32_91e,
+ sizeof(wifi_core_AM_PM_data_32_91e)/
+ sizeof(wifi_core_AM_PM_data_32_91e[0]));
+ }else if (priv->version == WLAN_VERSION_91_F) {
+ ret = wlan_write_sdio32_polling(priv, wifi_core_init_data_32_91f,
+ sizeof(wifi_core_init_data_32_91f) /
+ sizeof(wifi_core_init_data_32_91f[0]));
+ ret = wlan_write_sdio32_polling(priv, wifi_core_AM_PM_data_32_91f,
+ sizeof(wifi_core_AM_PM_data_32_91f)/
+ sizeof(wifi_core_AM_PM_data_32_91f[0]));
+ }
+ LEAVE();
+ return ret;
+}
+
+int wlan_sdio_core_wake_mode_polling(wlan_private *priv)
+{
+ int ret = 0;
+
+ if (priv->version == WLAN_VERSION_91 || priv->version == WLAN_VERSION_91_E || priv->version == WLAN_VERSION_91_F)
+ return 0;
+
+ ret = wlan_write_sdio32_polling(priv, wifi_core_data_wake,
+ sizeof(wifi_core_data_wake) /
+ sizeof(wifi_core_data_wake[0]));
+ return ret;
+}
+
+int wlan_sdio_patch_core_8_polling(wlan_private *priv)
+{
+ int ret = 0;
+ //for patch in byte mode
+
+ ENTER();
+
+ if (priv->version == WLAN_VERSION_90_D
+ || priv->version == WLAN_VERSION_90_E) {
+ ret = wlan_write_sdio8_polling(priv, wifi_core_patch_data_90_8,
+ sizeof(wifi_core_patch_data_90_8) /
+ sizeof(wifi_core_patch_data_90_8[0]));
+ if(ret)
+ goto err;
+ }else if(priv->version == WLAN_VERSION_91){
+ ret = wlan_write_sdio8_polling(priv, wifi_core_patch_data_91_8,
+ sizeof(wifi_core_patch_data_91_8)/
+ sizeof(wifi_core_patch_data_91_8[0]));
+ if (ret)
+ goto err;
+ }else if (priv->version == WLAN_VERSION_91_E) {
+ ret = wlan_write_sdio8_polling(priv, wifi_core_patch_data_91e_8,
+ sizeof(wifi_core_patch_data_91e_8)/
+ sizeof(wifi_core_patch_data_91e_8[0]));
+ if(ret)
+ goto err;
+ }else if (priv->version == WLAN_VERSION_91_F) {
+ ret = wlan_write_sdio8_polling(priv, wifi_core_patch_data_91f_8,
+ sizeof(wifi_core_patch_data_91f_8)/
+ sizeof(wifi_core_patch_data_91f_8[0]));
+ if (ret)
+ goto err;
+ }
+
+ //for patch in wake continue clock mode
+ ret = wlan_sdio_core_wake_mode_polling(priv);
+ if(ret)
+ goto err;
+
+err:
+ LEAVE();
+ return ret;
+}
+
+int wlan_sdio_set_default_notch_polling(wlan_private *priv)
+{
+ int ret = 0;
+
+ ENTER();
+
+ if (priv->version == WLAN_VERSION_91 || priv->version == WLAN_VERSION_91_E || priv->version == WLAN_VERSION_91_F)
+ return 0;
+
+ if(priv->version == WLAN_VERSION_90_D)
+ ret = wlan_write_sdio32_polling(priv, wifi_notch_data_90_D,
+ sizeof(wifi_notch_data_90_D) /
+ sizeof(wifi_notch_data_90_D[0]));
+ else if(priv->version == WLAN_VERSION_90_E)
+ ret = wlan_write_sdio32_polling(priv, wifi_notch_data_90_E,
+ sizeof(wifi_notch_data_90_E) /
+ sizeof(wifi_notch_data_90_E[0]));
+ LEAVE();
+
+ return ret;
+}
+
+extern void rda_mci_enable_sdio_irq(struct mmc_host *mmc, int enable);
+int wlan_sdio_init(wlan_private *priv)
+{
+ int ret = 0;
+
+ atomic_set(&sdio_init_complete, 0);
+ sdio_patch_complete = 0;
+
+ ret = wlan_sdio_patch_core_32(priv);
+ if(ret < 0)
+ goto err;
+
+
+ sdio_patch_complete = 1;
+ wlan_sched_timeout(10); //10ms delay
+
+ ret = wlan_sdio_init_core_polling(priv);
+ if(ret)
+ goto err;
+
+ ret = wlan_sdio_patch_core_8_polling(priv);
+ if(ret < 0)
+ goto err;
+
+ ret = wlan_sdio_set_default_notch_polling(priv);
+ if(ret < 0)
+ goto err;
+
+ atomic_set(&sdio_init_complete, 1);
+ //wlan_register_host_wake_irq(priv);
+ rda_mci_enable_sdio_irq(priv->MmcCard->host, 1);
+ priv->sdio_irq_enable = TRUE;
+
+err:
+ return ret;
+}
+
+u8 is_sdio_init_complete(void)
+{
+ return atomic_read(&sdio_init_complete);
+}
+u8 is_sdio_patch_complete(void) //after patch complete need check write flow
+{
+ return sdio_patch_complete;
+
+
+
+}
+
+int wlan_set_test_mode(wlan_private *priv)
+{
+ int ret = 0;
+ ENTER();
+ atomic_set(&sdio_init_complete, 0);
+ sdio_patch_complete = 0;
+ ret = wlan_sdio_patch_core_32(priv);
+ if(ret)
+ goto err;
+
+ sdio_patch_complete = 1;
+
+ if (priv->version == WLAN_VERSION_90_D
+ || priv->version == WLAN_VERSION_90_E) {
+ ret = wlan_write_sdio8_polling(priv, wifi_core_patch_data_90_8,
+ sizeof(wifi_core_patch_data_90_8)/
+ sizeof(wifi_core_patch_data_90_8[0]));
+ if(ret)
+ goto err;
+ }else if(priv->version == WLAN_VERSION_91){
+ ret = wlan_write_sdio32_polling(priv, wifi_core_init_data_32_91,
+ sizeof(wifi_core_init_data_32_91) /
+ sizeof(wifi_core_init_data_32_91[0]));
+ if (ret)
+ goto err;
+ ret = wlan_write_sdio32_polling(priv, wifi_core_AM_PM_data_32_91,
+ sizeof(wifi_core_AM_PM_data_32_91)/
+ sizeof(wifi_core_AM_PM_data_32_91[0]));
+ if (ret)
+ goto err;
+ ret = wlan_write_sdio8_polling(priv, wifi_core_patch_data_91_8,
+ sizeof(wifi_core_patch_data_91_8)/
+ sizeof(wifi_core_patch_data_91_8[0]));
+ if(ret)
+ goto err;
+
+ }else if (priv->version == WLAN_VERSION_91_E) {
+ ret = wlan_write_sdio32_polling(priv, wifi_core_init_data_32_91e,
+ sizeof(wifi_core_init_data_32_91e) /
+ sizeof(wifi_core_init_data_32_91e[0]));
+ if(ret)
+ goto err;
+ ret = wlan_write_sdio32_polling(priv, wifi_core_AM_PM_data_32_91e,
+ sizeof(wifi_core_AM_PM_data_32_91e)/
+ sizeof(wifi_core_AM_PM_data_32_91e[0]));
+ if(ret)
+ goto err;
+
+ ret = wlan_write_sdio8_polling(priv, wifi_core_patch_data_91e_8,
+ sizeof(wifi_core_patch_data_91e_8)/
+ sizeof(wifi_core_patch_data_91e_8[0]));
+ if(ret)
+ goto err;
+ }else if (priv->version == WLAN_VERSION_91_F) {
+ ret = wlan_write_sdio32_polling(priv, wifi_core_init_data_32_91f,
+ sizeof(wifi_core_init_data_32_91f) /
+ sizeof(wifi_core_init_data_32_91f[0]));
+ if (ret)
+ goto err;
+ ret = wlan_write_sdio32_polling(priv, wifi_core_AM_PM_data_32_91f,
+ sizeof(wifi_core_AM_PM_data_32_91f)/
+ sizeof(wifi_core_AM_PM_data_32_91f[0]));
+ if (ret)
+ goto err;
+ ret = wlan_write_sdio8_polling(priv, wifi_core_patch_data_91f_8,
+ sizeof(wifi_core_patch_data_91f_8)/
+ sizeof(wifi_core_patch_data_91f_8[0]));
+ if (ret)
+ goto err;
+ }
+ if (priv->version == WLAN_VERSION_90_D
+ || priv->version == WLAN_VERSION_90_E) {
+ ret = wlan_write_sdio32_polling(priv, wlan_test_mode_digital32_90,
+ sizeof(wlan_test_mode_digital32_90) /
+ sizeof(wlan_test_mode_digital32_90[0]));
+ if(ret)
+ goto err;
+ }
+ if (priv->version == WLAN_VERSION_90_D
+ || priv->version == WLAN_VERSION_90_E) {
+ ret = wlan_write_sdio32_polling(priv,
+ wifi_test_mode_agc_patch32_90,
+ sizeof(wifi_test_mode_agc_patch32_90) /
+ sizeof(wifi_test_mode_agc_patch32_90[0]));
+ if(ret)
+ goto err;
+ }
+
+ if (priv->version == WLAN_VERSION_90_D
+ || priv->version == WLAN_VERSION_90_E) {
+ ret = wlan_write_sdio32_polling(priv,
+ wifi_test_mode_rx_notch_32_90,
+ sizeof(wifi_test_mode_rx_notch_32_90) /
+ sizeof(wifi_test_mode_rx_notch_32_90[0]));
+ if(ret)
+ goto err;
+ }
+
+ ret = wlan_sdio_set_default_notch_polling(priv);
+ if(ret)
+ goto err;
+
+ atomic_set(&sdio_init_complete, 1);
+ rda_mci_enable_sdio_irq(priv->MmcCard->host, 1);
+ priv->sdio_irq_enable = TRUE;
+
+err:
+
+ LEAVE();
+ return ret;
+}
+int wlan_assoc_power_save(wlan_private * priv)
+{
+ int ret = 0;
+ ENTER();
+ if (priv->version == WLAN_VERSION_91){
+ ret = wlan_set_core_init_patch(priv, wifi_assoc_power_save_data_32_91,
+ sizeof(wifi_assoc_power_save_data_32_91) / sizeof(wifi_assoc_power_save_data_32_91[0]));
+ }
+
+ LEAVE();
+ return ret;
+}
+int wlan_set_phy_timeout(wlan_private * priv)
+{
+ int ret = 0;
+ if ((priv->version == WLAN_VERSION_90_D) ||
+ (priv->version == WLAN_VERSION_90_E)) {
+ ret = wlan_write_sdio32_polling(priv,
+ wifi_phy_timeout_cfg_90,
+ sizeof(wifi_phy_timeout_cfg_90) /
+ sizeof(wifi_phy_timeout_cfg_90[0]));
+ } else if ((priv->version == WLAN_VERSION_91) ||
+ (priv->version == WLAN_VERSION_91_E) || priv->version == WLAN_VERSION_91_F) {
+ ret = wlan_write_sdio32_polling(priv,
+ wifi_phy_timeout_cfg_91e,
+ sizeof(wifi_phy_timeout_cfg_91e) /
+ sizeof(wifi_phy_timeout_cfg_91e[0]));
+ }
+ return ret;
+}
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch.h b/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch.h
new file mode 100755
index 00000000..546241bf
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch.h
@@ -0,0 +1,12 @@
+#ifndef __WLAN_SDIO_PATCH_H__
+#define __WLAN_SDIO_PATCH_H__
+
+int wlan_sdio_init(wlan_private *priv);
+u8 is_sdio_init_complete(void);
+u8 is_sdio_patch_complete(void) ;
+int wlan_set_test_mode(wlan_private *priv);
+int wlan_assoc_power_save(wlan_private * priv);
+int wlan_set_phy_timeout(wlan_private * priv);
+
+#endif//__WLAN_SDIO_PATCH_H__
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_90.h b/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_90.h
new file mode 100755
index 00000000..eb4c614c
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_90.h
@@ -0,0 +1,1793 @@
+#ifndef __WLAN_SDIO_PATCH_90_H__
+#define __WLAN_SDIO_PATCH_90_H__
+
+//#define dig_access_pmu_cancel
+const u32 wifi_core_patch_data_32_90_D[][2] =
+{
+ {0x00108000, 0xEA03DF9C},
+ {0x00108004, 0xE59F101C},
+ {0x00108008, 0xE3A00040},
+ {0x0010800C, 0xE5C10038},
+ {0x00108010, 0xE1A0F00E},
+ {0x00108014, 0xEA03DF95},
+ {0x00108018, 0xE59F1008},
+ {0x0010801C, 0xE3A00040},
+ {0x00108020, 0xE5C10038},
+ {0x00108024, 0xE1A0F00E},
+ {0x00108028, 0x50300000},
+ {0x0010802C, 0xEB03D6F2},
+ {0x00108030, 0xE1A00B84},
+ {0x00108034, 0xE1B00BA0},
+ {0x00108038, 0x11A00B84},
+ {0x0010803C, 0x11A00BA0},
+ {0x00108040, 0x12600F80},
+ {0x00108044, 0x10804004},
+ {0x00108048, 0xE1A00124},
+ {0x0010804C, 0xE92D0011},
+ {0x00108050, 0xE51F4030},
+ {0x00108054, 0xE3A00020},
+ {0x00108058, 0xE5C40038},
+ {0x0010805C, 0xE8BD0011},
+ {0x00108060, 0xE1A0F00E},
+ {0x00108064, 0xEA03D3D2},
+ {0x00108068, 0xE3A00001},
+ {0x0010806C, 0xE1A0F00E},
+ {0x00108070, 0xEA03D6CD},
+ {0x00108074, 0xE3A00001},
+ {0x00108078, 0xE1A0F00E},
+ {0x0010807C, 0xEB03C786},
+ {0x00108080, 0xE51F0060},
+ {0x00108084, 0xE5D00038},
+ {0x00108088, 0xE3100080},
+ {0x0010808C, 0x1A000001},
+ {0x00108090, 0xE3A00001},
+ {0x00108094, 0xE1A0F00E},
+ {0x00108098, 0xE3A00000},
+ {0x0010809C, 0xE1A0F00E},
+ {0x001080A0, 0xEB03EADE},
+ {0x001080A4, 0xE51F0084},
+ {0x001080A8, 0xE5D00038},
+ {0x001080AC, 0xE3100080},
+ {0x001080B0, 0x1A000001},
+ {0x001080B4, 0xE3A00001},
+ {0x001080B8, 0xE1A0F00E},
+ {0x001080BC, 0xE3A00000},
+ {0x001080C0, 0xE1A0F00E},
+ {0x001080C4, 0xEB03D89D},
+ {0x001080C8, 0xE51F00A8},
+ {0x001080CC, 0xE3A01080},
+ {0x001080D0, 0xE5C01038},
+ {0x001080D4, 0xE1A0F00E},
+ {0x001080D8, 0xEB03D714},
+ {0x001080DC, 0xE51F10BC},
+ {0x001080E0, 0xE5D10038},
+ {0x001080E4, 0xE3100080},
+ {0x001080E8, 0x159F001C},
+ {0x001080EC, 0x059F0014},
+ {0x001080F0, 0xE59F100C},
+ {0x001080F4, 0xE581003C},
+ {0x001080F8, 0xE51F10D8},
+ {0x001080FC, 0xE1D101B4},
+ {0x00108100, 0xE1A0F00E},
+ {0x00108104, 0x30010000},
+ {0x00108108, 0x2E00A100},
+ {0x0010810C, 0x2E00A000},
+ {0x00108110, 0xEB03B485},
+ {0x00108114, 0x13100010},
+ {0x00108118, 0x13A00002},
+ {0x0010811C, 0x15C50067},
+ {0x00108120, 0xE1A0F00E},
+ {0x00108124, 0xEA03D804},
+ {0x00108128, 0xE51F1108},
+ {0x0010812C, 0xE5D10038},
+ {0x00108130, 0xE2000020},
+ {0x00108134, 0xE3500000},
+ {0x00108138, 0x1AFFFFFB},
+ {0x0010813C, 0xE3A01004},
+ {0x00108140, 0xE3A00B48},
+ {0x00108144, 0xE280FF45},
+ {0x00108148, 0xEA04020A},
+ {0x0010814C, 0x08BD4010},
+ {0x00108150, 0x0A000002},
+ {0x00108154, 0x13A00001},
+ {0x00108158, 0x18BD4010},
+ {0x0010815C, 0x1A000001},
+ {0x00108160, 0xE51FF004},
+ {0x00108164, 0x0000D470},
+ {0x00108168, 0xE51FF004},
+ {0x0010816C, 0x0000D2C0},
+ {0x00108170, 0xEA0402CF},
+ {0x00108174, 0xE59F600C},
+ {0x00108178, 0xE3A04000},
+ {0x0010817C, 0xE5C64000},
+ {0x00108180, 0xE59F6004},
+ {0x00108184, 0xE59FF004},
+ {0x00108188, 0x0010200B},
+ {0x0010818C, 0x0010121D},
+ {0x00108190, 0x00007634},
+ {0x00108194, 0xEAFFFFEC},
+ {0x00108198, 0xE1A00004},
+ {0x0010819C, 0xE1A00000},
+ {0x20040004, 0x0001018C},
+ {0x20040024, 0x00108000},
+ {0x20040008, 0x000101BC},
+ {0x20040028, 0x00108014},
+ {0x2004000C, 0x00012460},
+ {0x2004002C, 0x0010802C},
+ {0x20040010, 0x00013118},
+ {0x20040030, 0x00108064},
+ {0x20040014, 0x00012538},
+ {0x20040034, 0x00108070},
+ {0x20040018, 0x00016260},
+ {0x20040038, 0x0010807C},
+ {0x2004001C, 0x0000D524},
+ {0x2004003C, 0x001080A0},
+ {0x20040020, 0x00011E4C},
+ {0x20040040, 0x001080C4},
+ {0x20040100, 0x00012484},
+ {0x20040120, 0x001080D8},
+ {0x20040104, 0x0001AEF8},
+ {0x20040124, 0x00108110},
+ {0x20040108, 0x00012110},
+ {0x20040128, 0x00108124},
+ {0x2004010C, 0x0000791C},
+ {0x2004012C, 0x00108148},
+ {0x20040110, 0x00007630},
+ {0x20040130, 0x00108170},
+ {0x20040114, 0x00017158},
+ {0x20040134, 0x00108194},
+ {0x20040118, 0x00002594},
+ {0x20040138, 0x00108198},
+ {0x2004011C, 0x000172A4},
+ {0x2004013C, 0x0010819C},
+ {0x20040000, 0x0000FFFF},
+};
+
+
+
+const u32 wifi_core_patch_data_32_90_E[][2] =
+{
+#ifdef NORMAL_FIXED
+/*******************************************************************************
+* RDA5990E/F̼˵:
+* 1. ǰܽ˯ߣ
+* 2. 802.1XEAPOLݰʹСʷ͡
+* 3. ˯ߺͻMPLLԲ
+* 4. ݰPMΪ1
+* 5. ACKưPMΪ1
+* 6. (SSID)AP
+* 7. SSIDAP
+* 8. ˯ص
+* 9. ֧DSSS-OFDMPBCCChannel AgilityѡAPһΪ
+* ʾɨ裬
+* 10.鲥TKIPܷʽkey indexΪ1APһΪ֤ʽ
+* WPA/WPA2APijһʱӲ·һֱʾڻȡIPַ
+* ǻȡһʱ֮(Ҫ·)
+* 11.ŻWlanԶʿ
+* 12.ŻBT/WIFI
+*
+* ʱ:
+* 2012-11-21
+*
+******************************************************************************/
+ {0x00107FFC, 0x20121203},
+ {0x00108000, 0xEA04012F},
+ {0x00108004, 0x1A000001},
+ {0x00108008, 0xE8BD4010},
+ {0x0010800C, 0xEA000001},
+ {0x00108010, 0xE51FF004},
+ {0x00108014, 0x0000D4AC},
+ {0x00108018, 0xE51FF004},
+ {0x0010801C, 0x0000D654},
+ {0x00108020, 0xEA03EABA},
+ {0x00108024, 0xEB000003},
+ {0x00108028, 0xE3500000},
+ {0x0010802C, 0x0BFFFFF9},
+ {0x00108030, 0xE8BD4008},
+ {0x00108034, 0xE1A0F00E},
+ {0x00108038, 0xE51FF004},
+ {0x0010803C, 0x0000D6B4},
+ {0x00108040, 0x00000000},
+ {0x00108044, 0xEAFFFFEC},
+ {0x00108048, 0xEA040DFF},
+ {0x0010804C, 0xE3540000},
+ {0x00108050, 0x08BD8FF8},
+ {0x00108054, 0xE2440002},
+ {0x00108058, 0xE51FF004},
+ {0x0010805C, 0x0000484C},
+ {0x00108060, 0x00000000},
+ {0x00108064, 0x00000000},
+ {0x00108068, 0xE1A00004},
+ {0x0010806C, 0xE3A04000},
+ {0x00108070, 0x00001468},
+ {0x00108074, 0x00108070},
+ {0x00108078, 0xEA03EA36},
+ {0x0010807C, 0x0A000019},
+ {0x00108080, 0xE3E00006},
+ {0x00108084, 0xE3A015C0},
+ {0x00108088, 0xE5810000},
+ {0x0010808C, 0xE3A0000F},
+ {0x00108090, 0xEB000015},
+ {0x00108094, 0xE51F1028},
+ {0x00108098, 0xE5912000},
+ {0x0010809C, 0xE3822C80},
+ {0x001080A0, 0xE5812000},
+ {0x001080A4, 0xE1A01002},
+ {0x001080A8, 0xE3A00029},
+ {0x001080AC, 0xEB000012},
+ {0x001080B0, 0xE51F1044},
+ {0x001080B4, 0xE5912000},
+ {0x001080B8, 0xE3822CC0},
+ {0x001080BC, 0xE5812000},
+ {0x001080C0, 0xE1A01002},
+ {0x001080C4, 0xE3A00029},
+ {0x001080C8, 0xEB00000B},
+ {0x001080CC, 0xE51F1060},
+ {0x001080D0, 0xE5912000},
+ {0x001080D4, 0xE3C22CC0},
+ {0x001080D8, 0xE5812000},
+ {0x001080DC, 0xE1A01002},
+ {0x001080E0, 0xE3A00029},
+ {0x001080E4, 0xEB000004},
+ {0x001080E8, 0xE59FF014},
+ {0x001080EC, 0xE51FF004},
+ {0x001080F0, 0x00003784},
+ {0x001080F4, 0xE51FF004},
+ {0x001080F8, 0x000114B0},
+ {0x001080FC, 0xE51FF004},
+ {0x00108100, 0x0001BD58},
+ {0x00108104, 0x0000D7B0},
+ {0x00108108, 0xEA03C6DA},
+ {0x0010810C, 0x0A000019},
+ {0x00108110, 0xE3E00006},
+ {0x00108114, 0xE3A015C0},
+ {0x00108118, 0xE5810000},
+ {0x0010811C, 0xE3A0000F},
+ {0x00108120, 0xEBFFFFF1},
+ {0x00108124, 0xE51F10B8},
+ {0x00108128, 0xE5912000},
+ {0x0010812C, 0xE3822C80},
+ {0x00108130, 0xE5812000},
+ {0x00108134, 0xE1A01002},
+ {0x00108138, 0xE3A00029},
+ {0x0010813C, 0xEBFFFFEE},
+ {0x00108140, 0xE51F10D4},
+ {0x00108144, 0xE5912000},
+ {0x00108148, 0xE3822CC0},
+ {0x0010814C, 0xE5812000},
+ {0x00108150, 0xE1A01002},
+ {0x00108154, 0xE3A00029},
+ {0x00108158, 0xEBFFFFE7},
+ {0x0010815C, 0xE51F10F0},
+ {0x00108160, 0xE5912000},
+ {0x00108164, 0xE3C22CC0},
+ {0x00108168, 0xE5812000},
+ {0x0010816C, 0xE1A01002},
+ {0x00108170, 0xE3A00029},
+ {0x00108174, 0xEBFFFFE0},
+ {0x00108178, 0xE51FF004},
+ {0x0010817C, 0x000165B0},
+ {0x00108180, 0x00000000},
+ {0x00108184, 0x00000000},
+ {0x00108188, 0x00000000},
+ {0x0010818C, 0x00000000},
+ {0x00108190, 0x00000000},
+ {0x00108194, 0x00000000},
+ {0x00108198, 0x00000000},
+ {0x0010819C, 0x00000000},
+ {0x001081A0, 0x00000000},
+ {0x001081A4, 0x00108180},
+ {0x001081A8, 0xEA03D197},
+ {0x001081AC, 0xE92D40F8},
+ {0x001081B0, 0xE51F5014},
+ {0x001081B4, 0xE51FF004},
+ {0x001081B8, 0x00015730},
+ {0x001081BC, 0xEA03E13E},
+ {0x001081C0, 0xE59F0018},
+ {0x001081C4, 0xE5901038},
+ {0x001081C8, 0xE3110080},
+ {0x001081CC, 0x1A000001},
+ {0x001081D0, 0xE3A01003},
+ {0x001081D4, 0xE59FF008},
+ {0x001081D8, 0xE51FF004},
+ {0x001081DC, 0x0000FD18},
+ {0x001081E0, 0x50300000},
+ {0x001081E4, 0x0000FCC4},
+ {0x001081E8, 0xE1A00000},
+ {0x001081EC, 0x00000000},
+ {0x001081F0, 0x00000000},
+ {0x001081F4, 0x001081EC},
+ {0x001081F8, 0xEA0415B4},
+ {0x001081FC, 0xE2860018},
+ {0x00108200, 0xE3A02006},
+ {0x00108204, 0xE51F1018},
+ {0x00108208, 0xEB000003},
+ {0x0010820C, 0xE3500000},
+ {0x00108210, 0x01A07004},
+ {0x00108214, 0x0A000002},
+ {0x00108218, 0x1A000003},
+ {0x0010821C, 0xE51FF004},
+ {0x00108220, 0x00000160},
+ {0x00108224, 0xE51FF004},
+ {0x00108228, 0x00002BA0},
+ {0x0010822C, 0xE51FF004},
+ {0x00108230, 0x00002B8C},
+ {0x00108234, 0xE3A00002},
+ {0x00108238, 0x00000000},
+ {0x0010823C, 0x00108238},
+ {0x00108240, 0xEA03DFBB},
+ {0x00108244, 0xE5902834},
+ {0x00108248, 0xE51F1014},
+ {0x0010824C, 0xE5812000},
+ {0x00108250, 0xE3A01000},
+ {0x00108254, 0xE5801834},
+ {0x00108258, 0xE1A0F00E},
+ {0x0010825C, 0xEA03E040},
+ {0x00108260, 0xE51F002C},
+ {0x00108264, 0xE5900000},
+ {0x00108268, 0xE5810834},
+ {0x0010826C, 0xE1A0F00E},
+ {0x00108270, 0xE3500000},
+ {0x20040004, 0x00007B40},
+ {0x20040024, 0x00108000},
+ {0x20040008, 0x0000D534},
+ {0x20040028, 0x00108020},
+ {0x2004000C, 0x00017518},
+ {0x2004002C, 0x00108044},
+ {0x20040010, 0x00004848},
+ {0x20040030, 0x00108048},
+ {0x20040014, 0x00002520},
+ {0x20040034, 0x00108068},
+ {0x20040018, 0x00010000},
+ {0x20040038, 0x0010806C},
+ {0x2004001C, 0x0000D79C},
+ {0x2004003C, 0x00108078},
+ {0x20040020, 0x0001659C},
+ {0x20040040, 0x00108108},
+ {0x20040100, 0x00013B48},
+ {0x20040120, 0x001081A8},
+ {0x20040104, 0x0000FCC0},
+ {0x20040124, 0x001081BC},
+ {0x20040108, 0x00015090},
+ {0x20040128, 0x001081E8},
+ {0x2004010C, 0x00002B24},
+ {0x2004012C, 0x001081F8},
+ {0x20040110, 0x00001790},
+ {0x20040130, 0x00108234},
+ {0x20040114, 0x00010350},
+ {0x20040134, 0x00108240},
+ {0x20040118, 0x00010158},
+ {0x20040138, 0x0010825C},
+ {0x2004011C, 0x00004290},
+ {0x2004013C, 0x00108270},
+ {0x20040000, 0x0000FFFF},
+/*****************************************************************************/
+
+#elif defined WLAN_BIG_CURRENT_90E
+/*****************************************************************************/
+ {0x00107FFC, 0x20140312},
+ {0x00108000, 0xEA04012F},
+ {0x00108004, 0x1A000001},
+ {0x00108008, 0xE8BD4010},
+ {0x0010800C, 0xEA000001},
+ {0x00108010, 0xE51FF004},
+ {0x00108014, 0x0000D4AC},
+ {0x00108018, 0xE51FF004},
+ {0x0010801C, 0x0000D654},
+ {0x00108020, 0xEA03EABA},
+ {0x00108024, 0xEB000003},
+ {0x00108028, 0xE3500000},
+ {0x0010802C, 0x0BFFFFF9},
+ {0x00108030, 0xE8BD4008},
+ {0x00108034, 0xE1A0F00E},
+ {0x00108038, 0xE51FF004},
+ {0x0010803C, 0x0000D6B4},
+ {0x00108040, 0xE1A00004},
+ {0x00108044, 0xE3A04000},
+ {0x00108048, 0xEA03EA2A},
+ {0x0010804C, 0x0A000019},
+ {0x00108050, 0xE3E00006},
+ {0x00108054, 0xE3A015C0},
+ {0x00108058, 0xE5810000},
+ {0x0010805C, 0xE3A0000F},
+ {0x00108060, 0xEB000015},
+ {0x00108064, 0xE59F106C},
+ {0x00108068, 0xE5912000},
+ {0x0010806C, 0xE3822C80},
+ {0x00108070, 0xE5812000},
+ {0x00108074, 0xE1A01002},
+ {0x00108078, 0xE3A00029},
+ {0x0010807C, 0xEB000012},
+ {0x00108080, 0xE59F1050},
+ {0x00108084, 0xE5912000},
+ {0x00108088, 0xE3822CC0},
+ {0x0010808C, 0xE5812000},
+ {0x00108090, 0xE1A01002},
+ {0x00108094, 0xE3A00029},
+ {0x00108098, 0xEB00000B},
+ {0x0010809C, 0xE59F1034},
+ {0x001080A0, 0xE5912000},
+ {0x001080A4, 0xE3C22CC0},
+ {0x001080A8, 0xE5812000},
+ {0x001080AC, 0xE1A01002},
+ {0x001080B0, 0xE3A00029},
+ {0x001080B4, 0xEB000004},
+ {0x001080B8, 0xE59FF01C},
+ {0x001080BC, 0xE51FF004},
+ {0x001080C0, 0x00003784},
+ {0x001080C4, 0xE51FF004},
+ {0x001080C8, 0x000114B0},
+ {0x001080CC, 0xE51FF004},
+ {0x001080D0, 0x0001BD58},
+ {0x001080D4, 0x00001468},
+ {0x001080D8, 0x001080D4},
+ {0x001080DC, 0x0000D7B0},
+ {0x001080E0, 0xEA03C6D0},
+ {0x001080E4, 0x0A000019},
+ {0x001080E8, 0xE3E00006},
+ {0x001080EC, 0xE3A015C0},
+ {0x001080F0, 0xE5810000},
+ {0x001080F4, 0xE3A0000F},
+ {0x001080F8, 0xEBFFFFEF},
+ {0x001080FC, 0xE51F102C},
+ {0x00108100, 0xE5912000},
+ {0x00108104, 0xE3822C80},
+ {0x00108108, 0xE5812000},
+ {0x0010810C, 0xE1A01002},
+ {0x00108110, 0xE3A00029},
+ {0x00108114, 0xEBFFFFEC},
+ {0x00108118, 0xE51F1048},
+ {0x0010811C, 0xE5912000},
+ {0x00108120, 0xE3822CC0},
+ {0x00108124, 0xE5812000},
+ {0x00108128, 0xE1A01002},
+ {0x0010812C, 0xE3A00029},
+ {0x00108130, 0xEBFFFFE5},
+ {0x00108134, 0xE51F1064},
+ {0x00108138, 0xE5912000},
+ {0x0010813C, 0xE3C22CC0},
+ {0x00108140, 0xE5812000},
+ {0x00108144, 0xE1A01002},
+ {0x00108148, 0xE3A00029},
+ {0x0010814C, 0xEBFFFFDE},
+ {0x00108150, 0xE51FF004},
+ {0x00108154, 0x000165B0},
+ {0x00108158, 0xE1A00000},
+ {0x0010815C, 0xE1A00000},
+ {0x00108160, 0xE1A00000},
+ {0x00108164, 0xE1A00000},
+ {0x00108168, 0xE1A00000},
+ {0x0010816C, 0xE1A00000},
+ {0x00108170, 0xEA03D189},
+ {0x00108174, 0xE92D40F8},
+ {0x00108178, 0xE59F5024},
+ {0x0010817C, 0xE59FF024},
+ {0x00108180, 0x00000000},
+ {0x00108184, 0x00000000},
+ {0x00108188, 0x00000000},
+ {0x0010818C, 0x00000000},
+ {0x00108190, 0x00000000},
+ {0x00108194, 0x00000000},
+ {0x00108198, 0x00000000},
+ {0x0010819C, 0x00000000},
+ {0x001081A0, 0x00000000},
+ {0x001081A4, 0x00108180},
+ {0x001081A8, 0x00015730},
+ {0x001081AC, 0xEA03E13A},
+ {0x001081B0, 0xE59F0018},
+ {0x001081B4, 0xE5901038},
+ {0x001081B8, 0xE3110080},
+ {0x001081BC, 0x1A000001},
+ {0x001081C0, 0xE3A01003},
+ {0x001081C4, 0xE59FF008},
+ {0x001081C8, 0xE51FF004},
+ {0x001081CC, 0x0000FD18},
+ {0x001081D0, 0x50300000},
+ {0x001081D4, 0x0000FCC4},
+ {0x001081D8, 0xE1A00000},
+ {0x001081DC, 0xE1A00000},
+ {0x001081E0, 0xE1A00000},
+ {0x001081E4, 0xE1A00000},
+ {0x001081E8, 0xE1A00000},
+ {0x001081EC, 0x00000000},
+ {0x001081F0, 0x00000000},
+ {0x001081F4, 0x001081EC},
+ {0x001081F8, 0xEA0415B4},
+ {0x001081FC, 0xE2860018},
+ {0x00108200, 0xE3A02006},
+ {0x00108204, 0xE51F1018},
+ {0x00108208, 0xEB000003},
+ {0x0010820C, 0xE3500000},
+ {0x00108210, 0x01A07004},
+ {0x00108214, 0x0A000002},
+ {0x00108218, 0x1A000003},
+ {0x0010821C, 0xE51FF004},
+ {0x00108220, 0x00000160},
+ {0x00108224, 0xE51FF004},
+ {0x00108228, 0x00002BA0},
+ {0x0010822C, 0xE51FF004},
+ {0x00108230, 0x00002B8C},
+ {0x00108234, 0xE3A00002},
+ {0x00108238, 0xEA03DFB9},
+ {0x0010823C, 0xE5902834},
+ {0x00108240, 0xE59F1010},
+ {0x00108244, 0xE5812000},
+ {0x00108248, 0xE3A01000},
+ {0x0010824C, 0xE5801834},
+ {0x00108250, 0xE1A0F00E},
+ {0x00108254, 0x00000000},
+ {0x00108258, 0x00108254},
+ {0x0010825C, 0xEA03E040},
+ {0x00108260, 0xE51F0010},
+ {0x00108264, 0xE5900000},
+ {0x00108268, 0xE5810834},
+ {0x0010826C, 0xE1A0F00E},
+ {0x00108270, 0x00000000},
+ {0x00108274, 0x00108270},
+ {0x00108278, 0xEA03C6EE},
+ {0x0010827C, 0xE3500001},
+ {0x00108280, 0x1A00001A},
+ {0x00108284, 0xE92D0007},
+ {0x00108288, 0xE51F001C},
+ {0x0010828C, 0xE5901000},
+ {0x00108290, 0xE59F0050},
+ {0x00108294, 0xE5D02000},
+ {0x00108298, 0xE3520000},
+ {0x0010829C, 0x02811001},
+ {0x001082A0, 0x159F0044},
+ {0x001082A4, 0x15D02000},
+ {0x001082A8, 0x10811002},
+ {0x001082AC, 0xE51F0040},
+ {0x001082B0, 0xE3510F40},
+ {0x001082B4, 0x83A01000},
+ {0x001082B8, 0xE5801000},
+ {0x001082BC, 0x9A000007},
+ {0x001082C0, 0xE59F0020},
+ {0x001082C4, 0xE5D00000},
+ {0x001082C8, 0xE3500000},
+ {0x001082CC, 0x0A000003},
+ {0x001082D0, 0x13A00001},
+ {0x001082D4, 0xE3A01000},
+ {0x001082D8, 0xE3A02000},
+ {0x001082DC, 0xEB000005},
+ {0x001082E0, 0xE8BD0007},
+ {0x001082E4, 0xE59FF014},
+ {0x001082E8, 0x0010670D},
+ {0x001082EC, 0x00106046},
+ {0x001082F0, 0xE51FF004},
+ {0x001082F4, 0x00016770},
+ {0x001082F8, 0xE51FF004},
+ {0x001082FC, 0x00012DB0},
+ {0x00108300, 0x000166C4},
+ {0x00108304, 0xEA0401FB},
+ {0x00108308, 0xE3A00030},
+ {0x0010830C, 0xE59F100C},
+ {0x00108310, 0xEBFFFF6D},
+ {0x00108314, 0xE59F4000},
+ {0x00108318, 0xE59FF004},
+ {0x0010831C, 0x0010670C},
+ {0x00108320, 0x00000241},
+ {0x00108324, 0x00007B18},
+ {0x00108328, 0xEA03E128},
+ {0x0010832C, 0xE3A00030},
+ {0x00108330, 0xE59F100C},
+ {0x00108334, 0xEBFFFF64},
+ {0x00108338, 0xE2044001},
+ {0x0010833C, 0xE3540000},
+ {0x00108340, 0xE59FF000},
+ {0x00108344, 0x00000249},
+ {0x00108348, 0x0000FE88},
+ {0x0010834C, 0xEA03D8FA},
+ {0x00108350, 0xE3A00030},
+ {0x00108354, 0xE51F103C},
+ {0x00108358, 0xEBFFFF5B},
+ {0x0010835C, 0xE3A01003},
+ {0x00108360, 0xE51FF004},
+ {0x00108364, 0x00011F6C},
+ {0x20040004, 0x00007B40},
+ {0x20040024, 0x00108000},
+ {0x20040008, 0x0000D534},
+ {0x20040028, 0x00108020},
+ {0x2004000C, 0x00002520},
+ {0x2004002C, 0x00108040},
+ {0x20040010, 0x00010000},
+ {0x20040030, 0x00108044},
+ {0x20040014, 0x0000D79C},
+ {0x20040034, 0x00108048},
+ {0x20040018, 0x0001659C},
+ {0x20040038, 0x001080E0},
+ {0x2004001C, 0x00013B48},
+ {0x2004003C, 0x00108170},
+ {0x20040020, 0x0000FCC0},
+ {0x20040040, 0x001081AC},
+ {0x20040100, 0x00002B24},
+ {0x20040120, 0x001081F8},
+ {0x20040104, 0x00001790},
+ {0x20040124, 0x00108234},
+ {0x20040108, 0x00010350},
+ {0x20040128, 0x00108238},
+ {0x2004010C, 0x00010158},
+ {0x2004012C, 0x0010825C},
+ {0x20040110, 0x000166BC},
+ {0x20040130, 0x00108278},
+ {0x20040114, 0x00007B14},
+ {0x20040134, 0x00108304},
+ {0x20040118, 0x0000FE84},
+ {0x20040138, 0x00108328},
+ {0x2004011C, 0x00011F60},
+ {0x2004013C, 0x0010834C},
+ {0x20040000, 0x0000FFFF},
+/*****************************************************************************/
+
+#elif defined WLAN_FLOW_CTRL_90E
+/*****************************************************************************/
+ {0x00107FFC, 0x20140122},
+ {0x00108000, 0xEA04012F},
+ {0x00108004, 0x1A000001},
+ {0x00108008, 0xE8BD4010},
+ {0x0010800C, 0xEA000001},
+ {0x00108010, 0xE51FF004},
+ {0x00108014, 0x0000D4AC},
+ {0x00108018, 0xE51FF004},
+ {0x0010801C, 0x0000D654},
+ {0x00108020, 0xEA03EABA},
+ {0x00108024, 0xEB000003},
+ {0x00108028, 0xE3500000},
+ {0x0010802C, 0x0BFFFFF9},
+ {0x00108030, 0xE8BD4008},
+ {0x00108034, 0xE1A0F00E},
+ {0x00108038, 0xE51FF004},
+ {0x0010803C, 0x0000D6B4},
+ {0x00108040, 0x00000000},
+ {0x00108044, 0xEAFFFFEC},
+ {0x00108048, 0x0000484C},
+ {0x0010804C, 0x00000000},
+ {0x00108050, 0x00000000},
+ {0x00108054, 0x00000000},
+ {0x00108058, 0x00000000},
+ {0x0010805C, 0x00000000},
+ {0x00108060, 0x00000000},
+ {0x00108064, 0x00000000},
+ {0x00108068, 0xE1A00004},
+ {0x0010806C, 0xE3A04000},
+ {0x00108070, 0x00001468},
+ {0x00108074, 0x00108070},
+ {0x00108078, 0xEA03EA36},
+ {0x0010807C, 0x0A000019},
+ {0x00108080, 0xE3E00006},
+ {0x00108084, 0xE3A015C0},
+ {0x00108088, 0xE5810000},
+ {0x0010808C, 0xE3A0000F},
+ {0x00108090, 0xEB000015},
+ {0x00108094, 0xE51F1028},
+ {0x00108098, 0xE5912000},
+ {0x0010809C, 0xE3822C80},
+ {0x001080A0, 0xE5812000},
+ {0x001080A4, 0xE1A01002},
+ {0x001080A8, 0xE3A00029},
+ {0x001080AC, 0xEB000012},
+ {0x001080B0, 0xE51F1044},
+ {0x001080B4, 0xE5912000},
+ {0x001080B8, 0xE3822CC0},
+ {0x001080BC, 0xE5812000},
+ {0x001080C0, 0xE1A01002},
+ {0x001080C4, 0xE3A00029},
+ {0x001080C8, 0xEB00000B},
+ {0x001080CC, 0xE51F1060},
+ {0x001080D0, 0xE5912000},
+ {0x001080D4, 0xE3C22CC0},
+ {0x001080D8, 0xE5812000},
+ {0x001080DC, 0xE1A01002},
+ {0x001080E0, 0xE3A00029},
+ {0x001080E4, 0xEB000004},
+ {0x001080E8, 0xE59FF014},
+ {0x001080EC, 0xE51FF004},
+ {0x001080F0, 0x00003784},
+ {0x001080F4, 0xE51FF004},
+ {0x001080F8, 0x000114B0},
+ {0x001080FC, 0xE51FF004},
+ {0x00108100, 0x0001BD58},
+ {0x00108104, 0x0000D7B0},
+ {0x00108108, 0xEA03C6DA},
+ {0x0010810C, 0x0A000019},
+ {0x00108110, 0xE3E00006},
+ {0x00108114, 0xE3A015C0},
+ {0x00108118, 0xE5810000},
+ {0x0010811C, 0xE3A0000F},
+ {0x00108120, 0xEBFFFFF1},
+ {0x00108124, 0xE51F10B8},
+ {0x00108128, 0xE5912000},
+ {0x0010812C, 0xE3822C80},
+ {0x00108130, 0xE5812000},
+ {0x00108134, 0xE1A01002},
+ {0x00108138, 0xE3A00029},
+ {0x0010813C, 0xEBFFFFEE},
+ {0x00108140, 0xE51F10D4},
+ {0x00108144, 0xE5912000},
+ {0x00108148, 0xE3822CC0},
+ {0x0010814C, 0xE5812000},
+ {0x00108150, 0xE1A01002},
+ {0x00108154, 0xE3A00029},
+ {0x00108158, 0xEBFFFFE7},
+ {0x0010815C, 0xE51F10F0},
+ {0x00108160, 0xE5912000},
+ {0x00108164, 0xE3C22CC0},
+ {0x00108168, 0xE5812000},
+ {0x0010816C, 0xE1A01002},
+ {0x00108170, 0xE3A00029},
+ {0x00108174, 0xEBFFFFE0},
+ {0x00108178, 0xE51FF004},
+ {0x0010817C, 0x000165B0},
+ {0x00108180, 0x00000000},
+ {0x00108184, 0x00000000},
+ {0x00108188, 0x00000000},
+ {0x0010818C, 0x00000000},
+ {0x00108190, 0x00000000},
+ {0x00108194, 0x00000000},
+ {0x00108198, 0x00000000},
+ {0x0010819C, 0x00000000},
+ {0x001081A0, 0x00000000},
+ {0x001081A4, 0x00108180},
+ {0x001081A8, 0xEA03D197},
+ {0x001081AC, 0xE92D40F8},
+ {0x001081B0, 0xE51F5014},
+ {0x001081B4, 0xE51FF004},
+ {0x001081B8, 0x00015730},
+ {0x001081BC, 0xEA03E13E},
+ {0x001081C0, 0xE59F0018},
+ {0x001081C4, 0xE5901038},
+ {0x001081C8, 0xE3110080},
+ {0x001081CC, 0x1A000001},
+ {0x001081D0, 0xE3A01003},
+ {0x001081D4, 0xE59FF008},
+ {0x001081D8, 0xE51FF004},
+ {0x001081DC, 0x0000FD18},
+ {0x001081E0, 0x50300000},
+ {0x001081E4, 0x0000FCC4},
+ {0x001081E8, 0xE1A00000},
+ {0x001081EC, 0x00000000},
+ {0x001081F0, 0x00000000},
+ {0x001081F4, 0x001081EC},
+ {0x001081F8, 0xEA0415B4},
+ {0x001081FC, 0xE2860018},
+ {0x00108200, 0xE3A02006},
+ {0x00108204, 0xE51F1018},
+ {0x00108208, 0xEB000003},
+ {0x0010820C, 0xE3500000},
+ {0x00108210, 0x01A07004},
+ {0x00108214, 0x0A000002},
+ {0x00108218, 0x1A000003},
+ {0x0010821C, 0xE51FF004},
+ {0x00108220, 0x00000160},
+ {0x00108224, 0xE51FF004},
+ {0x00108228, 0x00002BA0},
+ {0x0010822C, 0xE51FF004},
+ {0x00108230, 0x00002B8C},
+ {0x00108234, 0xE3A00002},
+ {0x00108238, 0x00000000},
+ {0x0010823C, 0x00108238},
+ {0x00108240, 0xEA03DFBB},
+ {0x00108244, 0xE5902834},
+ {0x00108248, 0xE51F1014},
+ {0x0010824C, 0xE5812000},
+ {0x00108250, 0xE3A01000},
+ {0x00108254, 0xE5801834},
+ {0x00108258, 0xE1A0F00E},
+ {0x0010825C, 0xEA03E040},
+ {0x00108260, 0xE51F002C},
+ {0x00108264, 0xE5900000},
+ {0x00108268, 0xE5810834},
+ {0x0010826C, 0xE1A0F00E},
+ {0x00108270, 0xE3500000},
+ {0x00108274, 0xEA03E602},
+ {0x00108278, 0xE59F200C},
+ {0x0010827C, 0xE3A01010},
+ {0x00108280, 0xE5C21000},
+ {0x00108284, 0xE1A02000},
+ {0x00108288, 0xE59FF000},
+ {0x0010828C, 0x50300038},
+ {0x00108290, 0x0000EA6C},
+ {0x00108294, 0x00000000},
+ {0x00108298, 0x00108294},
+ {0x0010829C, 0xEA03C6F7},
+ {0x001082A0, 0xE3500001},
+ {0x001082A4, 0x1A00001A},
+ {0x001082A8, 0xE92D0007},
+ {0x001082AC, 0xE51F001C},
+ {0x001082B0, 0xE5901000},
+ {0x001082B4, 0xE59F0050},
+ {0x001082B8, 0xE5D02000},
+ {0x001082BC, 0xE3520000},
+ {0x001082C0, 0x02811001},
+ {0x001082C4, 0x159F0044},
+ {0x001082C8, 0x15D02000},
+ {0x001082CC, 0x10811002},
+ {0x001082D0, 0xE51F0040},
+ {0x001082D4, 0xE3510F40},
+ {0x001082D8, 0x83A01000},
+ {0x001082DC, 0xE5801000},
+ {0x001082E0, 0x9A000007},
+ {0x001082E4, 0xE59F0020},
+ {0x001082E8, 0xE5D00000},
+ {0x001082EC, 0xE3500000},
+ {0x001082F0, 0x0A000003},
+ {0x001082F4, 0x13A00001},
+ {0x001082F8, 0xE3A01000},
+ {0x001082FC, 0xE3A02000},
+ {0x00108300, 0xEB000005},
+ {0x00108304, 0xE8BD0007},
+ {0x00108308, 0xE59FF014},
+ {0x0010830C, 0x0010670D},
+ {0x00108310, 0x00106046},
+ {0x00108314, 0xE51FF004},
+ {0x00108318, 0x00016770},
+ {0x0010831C, 0xE51FF004},
+ {0x00108320, 0x00012DB0},
+ {0x00108324, 0x000166C4},
+ {0x20040004, 0x00007B40},
+ {0x20040024, 0x00108000},
+ {0x20040008, 0x0000D534},
+ {0x20040028, 0x00108020},
+ {0x2004000C, 0x00017518},
+ {0x2004002C, 0x00108044},
+ {0x20040010, 0x00002520},
+ {0x20040030, 0x00108068},
+ {0x20040014, 0x00010000},
+ {0x20040034, 0x0010806C},
+ {0x20040018, 0x0000D79C},
+ {0x20040038, 0x00108078},
+ {0x2004001C, 0x0001659C},
+ {0x2004003C, 0x00108108},
+ {0x20040020, 0x00013B48},
+ {0x20040040, 0x001081A8},
+ {0x20040100, 0x0000FCC0},
+ {0x20040120, 0x001081BC},
+ {0x20040104, 0x00015090},
+ {0x20040124, 0x001081E8},
+ {0x20040108, 0x00002B24},
+ {0x20040128, 0x001081F8},
+ {0x2004010C, 0x00001790},
+ {0x2004012C, 0x00108234},
+ {0x20040110, 0x00010350},
+ {0x20040130, 0x00108240},
+ {0x20040114, 0x00010158},
+ {0x20040134, 0x0010825C},
+ {0x20040118, 0x0000EA68},
+ {0x20040138, 0x00108274},
+ {0x2004011C, 0x000166BC},
+ {0x2004013C, 0x0010829C},
+ {0x20040000, 0x0000FFFF},
+/*****************************************************************************/
+
+#else
+/*******************************************************************************
+* RDA5990E/F̼˵:
+* 1. ǰܽ˯ߣ
+* 2. 802.1XEAPOLݰʹСʷ͡
+* 3. ˯ߺͻMPLLԲ
+* 4. ݰPMΪ1
+* 5. ACKưPMΪ1
+* 6. (SSID)AP
+* 7. SSIDAP
+* 8. ˯ص
+* 9. ֧DSSS-OFDMPBCCChannel AgilityѡAPһΪ
+* ʾɨ裬
+* 10.鲥TKIPܷʽkey indexΪ1APһΪ֤ʽ
+* WPA/WPA2APijһʱӲ·һֱʾڻȡIPַ
+* ǻȡһʱ֮(Ҫ·)
+* 11.ض·˯ߵIJһ㲻Ƽ
+* 12.ŻBT/WIFI
+*
+* ʱ:
+* 2012-11-22
+*
+******************************************************************************/
+ {0x00107FFC, 0x20121121},
+ {0x00108000, 0xEA04012F},
+ {0x00108004, 0x1A000001},
+ {0x00108008, 0xE8BD4010},
+ {0x0010800C, 0xEA000001},
+ {0x00108010, 0xE51FF004},
+ {0x00108014, 0x0000D4AC},
+ {0x00108018, 0xE51FF004},
+ {0x0010801C, 0x0000D654},
+ {0x00108020, 0xEA040142},
+ {0x00108024, 0xE3A00030},
+ {0x00108028, 0xE59F1008},
+ {0x0010802C, 0xEB000032},
+ {0x00108030, 0xE59F4004},
+ {0x00108034, 0xE59FF004},
+ {0x00108038, 0x00000241},
+ {0x0010803C, 0x0010670C},
+ {0x00108040, 0x00007B18},
+ {0x00108044, 0xEA03E06F},
+ {0x00108048, 0xE3A00030},
+ {0x0010804C, 0xE59F100C},
+ {0x00108050, 0xEB000029},
+ {0x00108054, 0xE2044001},
+ {0x00108058, 0xE3540000},
+ {0x0010805C, 0xE59FF000},
+ {0x00108060, 0x00000249},
+ {0x00108064, 0x0000FE88},
+ {0x00108068, 0xE1A00004},
+ {0x0010806C, 0xE3A04000},
+ {0x00108070, 0x00001468},
+ {0x00108074, 0x00108070},
+ {0x00108078, 0xEA03EA36},
+ {0x0010807C, 0x0A000019},
+ {0x00108080, 0xE3E00006},
+ {0x00108084, 0xE3A015C0},
+ {0x00108088, 0xE5810000},
+ {0x0010808C, 0xE3A0000F},
+ {0x00108090, 0xEB000015},
+ {0x00108094, 0xE51F1028},
+ {0x00108098, 0xE5912000},
+ {0x0010809C, 0xE3822C80},
+ {0x001080A0, 0xE5812000},
+ {0x001080A4, 0xE1A01002},
+ {0x001080A8, 0xE3A00029},
+ {0x001080AC, 0xEB000012},
+ {0x001080B0, 0xE51F1044},
+ {0x001080B4, 0xE5912000},
+ {0x001080B8, 0xE3822CC0},
+ {0x001080BC, 0xE5812000},
+ {0x001080C0, 0xE1A01002},
+ {0x001080C4, 0xE3A00029},
+ {0x001080C8, 0xEB00000B},
+ {0x001080CC, 0xE51F1060},
+ {0x001080D0, 0xE5912000},
+ {0x001080D4, 0xE3C22CC0},
+ {0x001080D8, 0xE5812000},
+ {0x001080DC, 0xE1A01002},
+ {0x001080E0, 0xE3A00029},
+ {0x001080E4, 0xEB000004},
+ {0x001080E8, 0xE59FF014},
+ {0x001080EC, 0xE51FF004},
+ {0x001080F0, 0x00003784},
+ {0x001080F4, 0xE51FF004},
+ {0x001080F8, 0x000114B0},
+ {0x001080FC, 0xE51FF004},
+ {0x00108100, 0x0001BD58},
+ {0x00108104, 0x0000D7B0},
+ {0x00108108, 0xEA03C6DA},
+ {0x0010810C, 0x0A000019},
+ {0x00108110, 0xE3E00006},
+ {0x00108114, 0xE3A015C0},
+ {0x00108118, 0xE5810000},
+ {0x0010811C, 0xE3A0000F},
+ {0x00108120, 0xEBFFFFF1},
+ {0x00108124, 0xE51F10B8},
+ {0x00108128, 0xE5912000},
+ {0x0010812C, 0xE3822C80},
+ {0x00108130, 0xE5812000},
+ {0x00108134, 0xE1A01002},
+ {0x00108138, 0xE3A00029},
+ {0x0010813C, 0xEBFFFFEE},
+ {0x00108140, 0xE51F10D4},
+ {0x00108144, 0xE5912000},
+ {0x00108148, 0xE3822CC0},
+ {0x0010814C, 0xE5812000},
+ {0x00108150, 0xE1A01002},
+ {0x00108154, 0xE3A00029},
+ {0x00108158, 0xEBFFFFE7},
+ {0x0010815C, 0xE51F10F0},
+ {0x00108160, 0xE5912000},
+ {0x00108164, 0xE3C22CC0},
+ {0x00108168, 0xE5812000},
+ {0x0010816C, 0xE1A01002},
+ {0x00108170, 0xE3A00029},
+ {0x00108174, 0xEBFFFFE0},
+ {0x00108178, 0xE51FF004},
+ {0x0010817C, 0x000165B0},
+ {0x00108180, 0x00000000},
+ {0x00108184, 0x00000000},
+ {0x00108188, 0x00000000},
+ {0x0010818C, 0x00000000},
+ {0x00108190, 0x00000000},
+ {0x00108194, 0x00000000},
+ {0x00108198, 0x00000000},
+ {0x0010819C, 0x00000000},
+ {0x001081A0, 0x00000000},
+ {0x001081A4, 0x00108180},
+ {0x001081A8, 0xEA03D197},
+ {0x001081AC, 0xE92D40F8},
+ {0x001081B0, 0xE51F5014},
+ {0x001081B4, 0xE51FF004},
+ {0x001081B8, 0x00015730},
+ {0x001081BC, 0xEA03E13E},
+ {0x001081C0, 0xE59F0018},
+ {0x001081C4, 0xE5901038},
+ {0x001081C8, 0xE3110080},
+ {0x001081CC, 0x1A000001},
+ {0x001081D0, 0xE3A01003},
+ {0x001081D4, 0xE59FF008},
+ {0x001081D8, 0xE51FF004},
+ {0x001081DC, 0x0000FD18},
+ {0x001081E0, 0x50300000},
+ {0x001081E4, 0x0000FCC4},
+ {0x001081E8, 0xE1A00000},
+ {0x001081EC, 0x00000000},
+ {0x001081F0, 0x00000000},
+ {0x001081F4, 0x001081EC},
+ {0x001081F8, 0xEA0415B4},
+ {0x001081FC, 0xE2860018},
+ {0x00108200, 0xE3A02006},
+ {0x00108204, 0xE51F1018},
+ {0x00108208, 0xEB000003},
+ {0x0010820C, 0xE3500000},
+ {0x00108210, 0x01A07004},
+ {0x00108214, 0x0A000002},
+ {0x00108218, 0x1A000003},
+ {0x0010821C, 0xE51FF004},
+ {0x00108220, 0x00000160},
+ {0x00108224, 0xE51FF004},
+ {0x00108228, 0x00002BA0},
+ {0x0010822C, 0xE51FF004},
+ {0x00108230, 0x00002B8C},
+ {0x00108234, 0xE3A00002},
+ {0x00108238, 0x00000000},
+ {0x0010823C, 0x00108238},
+ {0x00108240, 0xEA03DFBB},
+ {0x00108244, 0xE5902834},
+ {0x00108248, 0xE51F1014},
+ {0x0010824C, 0xE5812000},
+ {0x00108250, 0xE3A01000},
+ {0x00108254, 0xE5801834},
+ {0x00108258, 0xE1A0F00E},
+ {0x0010825C, 0xEA03E040},
+ {0x00108260, 0xE51F002C},
+ {0x00108264, 0xE5900000},
+ {0x00108268, 0xE5810834},
+ {0x0010826C, 0xE1A0F00E},
+ {0x00108270, 0xEAFFFFEC},
+ {0x00108274, 0xEA03D8C4},
+ {0x00108278, 0xE3A00030},
+ {0x0010827C, 0xE59F1008},
+ {0x00108280, 0xEBFFFF9D},
+ {0x00108284, 0xE3A01003},
+ {0x00108288, 0xE59FF000},
+ {0x0010828C, 0x00000241},
+ {0x00108290, 0x00011F6C},
+ {0x20040004, 0x00007B40},
+ {0x20040024, 0x00108000},
+ {0x20040008, 0x00007B14},
+ {0x20040028, 0x00108020},
+ {0x2004000C, 0x0000FE84},
+ {0x2004002C, 0x00108044},
+ {0x20040010, 0x00002520},
+ {0x20040030, 0x00108068},
+ {0x20040014, 0x00010000},
+ {0x20040034, 0x0010806C},
+ {0x20040018, 0x0000D79C},
+ {0x20040038, 0x00108078},
+ {0x2004001C, 0x0001659C},
+ {0x2004003C, 0x00108108},
+ {0x20040020, 0x00013B48},
+ {0x20040040, 0x001081A8},
+ {0x20040100, 0x0000FCC0},
+ {0x20040120, 0x001081BC},
+ {0x20040104, 0x00015090},
+ {0x20040124, 0x001081E8},
+ {0x20040108, 0x00002B24},
+ {0x20040128, 0x001081F8},
+ {0x2004010C, 0x00001790},
+ {0x2004012C, 0x00108234},
+ {0x20040110, 0x00010350},
+ {0x20040130, 0x00108240},
+ {0x20040114, 0x00010158},
+ {0x20040134, 0x0010825C},
+ {0x20040118, 0x00017518},
+ {0x20040138, 0x00108270},
+ {0x2004011C, 0x00011F60},
+ {0x2004013C, 0x00108274},
+ {0x20040000, 0x0000FFFF},
+#endif
+};
+
+const u8 wifi_core_patch_data_90_8[][2] =
+{
+ { 0x28, 0x1a} ,
+ { 0x29, 0x0d},
+ { 0x35, 0x1e},
+ { 0x4c, 0x90},
+ { 0x4d, 0x38},
+ { 0x39, 0x07},
+ { 0xe4, 0xf5},
+ { 0x21, 0x00}, //default 0
+ { 0x23, 0x10},
+ { 0x48, 0x0e},
+ { 0x25, 0x00},
+ { 0x20, 0xa8},
+ { 0x3f, 0x05},
+ { 0x41, 0x37},
+ { 0x42, 0x40},
+ { 0x5b, 0xa9},
+};
+
+//#define WF_PAT_CFG_2012_04_15
+
+
+/*if define FORCE_WF, wf is not allow of any activity, antenna switch is also forced to bt*/
+//#define FORCE_WF
+
+/*if define FORCE_WF_TX ,wf is not allow to do tx and pa is also disabled, but antenna is not forced*/
+//#define FORCE_WF_TX
+
+/*if define FORCE_WF_RX ,wf is not allow to do rx but antenna is not forced*/
+//#define FORCE_WF_RX
+
+
+/*if define FORCE_WF_RX_TX wf is not allow to do any tx and rx , pa disabled , but antenna is not forced*/
+//#define FORCE_WF_RX_TX
+
+//#define WF_PAT_CFG_2012_05_19
+#define WF_PAT_CFG_2013_04_08
+
+const u32 wifi_core_init_data_32_90_D[][2] =
+{
+#ifdef FORCE_WF_RX_TX
+ {0x50000800,0xFC003E05},
+ {0x50000804,0x00000000},
+ {0x50000808,0xA5000013}, //no pre_active protect
+ {0x5000080c,0x000001C0},
+ {0x50000810,0xFFCC0F01},
+ {0x50000814,0x00000000}, // not grant to rx and tx
+ {0x50000818,0x00FF0001},
+ {0x5000081C,0xFF000F00},
+ {0x50000820,0x00000000},
+ {0x50000824,0x0000F0FE},
+ {0x50000828,0x00100F10},
+ {0x50000838,0xFFFFFFFF},
+ {0x5000083C,0xFFFFFFFF},
+#endif
+
+#ifdef FORCE_WF_RX
+ {0x50000800,0xFC003E05},
+ {0x50000804,0x00000000},
+ {0x50000808,0xA5000013}, //no pre_active protect
+ {0x5000080c,0x000001C0},
+ {0x50000810,0xFFCC0F01},
+ {0x50000814,0xFF000F00}, //wf not grant to rx
+ {0x50000818,0x00FF0001},
+ {0x5000081C,0xFF000F00},
+ {0x50000820,0xFF000F00},
+ {0x50000824,0x0000F0FE},
+ {0x50000828,0x00100F10},
+ {0x50000838,0xFFFFFFFF},
+ {0x5000083C,0xFFFFFFFF},
+#endif
+
+#ifdef FORCE_WF_TX
+ {0x50000800,0xFC003E05},
+ {0x50000804,0x00000000},
+ {0x50000808,0xA5000013}, //no pre_active protect
+ {0x5000080c,0x000001C0},
+ {0x50000810,0xFFCC0F01},
+ {0x50000814,0x00FF0033}, //wf not grant to tx
+ {0x50000818,0x00FF0001},
+ {0x5000081C,0xFF000F00},
+ {0x50000820,0x00000000},
+ {0x50000824,0x0000F0FE},
+ {0x50000828,0x00100F10},
+ {0x50000838,0xFFFFFFFF},
+ {0x5000083C,0xFFFFFFFF},
+#endif
+
+#ifdef WF_PAT_CFG_2012_05_19
+ {0x50000800,0xFC003E05},
+ {0x50000804,0x00000000},
+ {0x50000808,0xA5000013}, //no pre_active protect
+ {0x5000080c,0x000001C0},
+ {0x50000810,0xFFCC0F01},
+ {0x50000814,0xFFFF0F03}, //0xFFFF0F33
+ {0x50000818,0x00FF0001},
+ {0x5000081C,0xFF000F00},
+ {0x50000820,0xFF000F00},
+ {0x50000824,0x0000F0FE},
+ {0x50000828,0x00100F10},
+ {0x50000838,0xFFFFFFFF},
+ {0x5000083C,0xFFFFFFFF},
+#endif
+
+#ifdef WF_PAT_CFG_2013_04_08
+ {0x50000800,0x00000000},
+ {0x50000804,0x00200000}, //ack as high
+ {0x50000838,0x00101014},
+ {0x5000083C,0x00333101},
+ {0x50000808,0x75000013},
+ {0x5000080c,0x000001C0},
+ {0x50000810,0xFFFF0111},
+ {0x50000814,0xFFFF0111},
+ {0x50000818,0x00FF0011},
+ {0x5000081C,0xFF000100},
+ {0x50000820,0xFF000100},
+ {0x50000824,0x0000FEEE},
+ {0x50000828,0x00100F10},
+ {0x50000834,0x00000000},
+#endif
+
+#ifdef FORCE_WF
+ {0x50000800,0xFC003E05},
+ {0x50000804,0x00000000},
+ {0x50000838,0xF8003f2A},
+ {0x5000083c,0x00000003},
+ {0x50000808,0xfe00001b},
+ {0x50000810,0x00000000},
+ {0x50000814,0x00000000},
+ {0x50000818,0x00000000},
+ {0x5000081C,0x00000000},
+ {0x50000820,0x00000000},
+ {0x50000824,0xffffffff},
+ {0x50000828,0x00100F10},
+#endif
+
+#ifdef WF_PAT_CFG_2012_04_15 /*pta config*/
+ {0x50000800,0xFC003E05}, //tx_pri hi bits ctrl&mgmt package
+ {0x50000804,0x00000000}, //tx_pri hi bits as hi pri
+ {0x50000808,0xA500001B}, //sig_mode and protect time
+ {0x5000080c,0x000001C0}, //sigWire mode
+ {0x50000810,0xFFCC0F01}, //Lut bt
+ {0x50000814,0xFFFF0F33}, //Lut wf
+ {0x50000818,0x00FF0001}, //antSel0 for wl_rx
+ {0x5000081C,0xFF000F00}, //antSel1 for wl_tx
+ {0x50000820,0xFF000F00}, //antSel2 for wl_pa
+ //{0x50000838,0xFFFFFFFF}, //rx_pri low bits as high pri
+ //{0x5000083C,0xFFFFFFFF}, //rx_pri high bits as high pri
+#endif
+/*end pta config*/
+ { 0x00106b6c, 0x00000002 }, // scan channel 13
+ { 0x30010004, 0x0000f77c }, //intn config
+ { 0x30010010, 0x00007dff }, //intn config
+ //item111:ver_b_wf_dig_2011_10_09
+ { 0x30010000, 0x780369AF }, //disable tports wait 100ms;
+ { 0x30000010, 0x7000FFFF },//wait 500ms;
+ { 0x50090054, 0x00000001 },//enable update
+ { 0x50090200, 0x00000000 },
+ { 0x50090204, 0x00000000 },
+ { 0x50090208, 0x00000002 },
+ { 0x5009020c, 0x00000004 },
+ { 0x50090210, 0x00000006 },
+ { 0x50090214, 0x00000008 },
+ { 0x50090218, 0x0000000a },
+ { 0x5009021c, 0x00000040 },
+ { 0x50090220, 0x00000042 },
+ { 0x50090224, 0x00000044 },
+ { 0x50090228, 0x00000046 },
+ { 0x5009022c, 0x00000048 },
+ { 0x50090230, 0x0000004a },
+ { 0x50090234, 0x00000080 },
+ { 0x50090238, 0x00000082 },
+ { 0x5009023c, 0x00000084 },
+ { 0x50090240, 0x00000086 },
+ { 0x50090244, 0x00000088 },
+ { 0x50090248, 0x0000008a },
+ { 0x5009024c, 0x000000c0 },
+ { 0x50090250, 0x000000c2 },
+ { 0x50090254, 0x000000c4 },
+ { 0x50090258, 0x000000c6 },
+ { 0x5009025c, 0x000000c8 },
+ { 0x5009025c, 0x000000c8 },
+ { 0x50090260, 0x000000ca },
+ { 0x50090264, 0x00000100 },
+ { 0x50090268, 0x00000102 },
+ { 0x5009026c, 0x00000104 },
+ { 0x50090270, 0x00000106 },
+ { 0x50090274, 0x00000108 },
+ { 0x50090278, 0x00000140 },
+ { 0x5009027c, 0x00000142 },//lna =0 end
+ { 0x50090280, 0x00000080 },
+ { 0x50090284, 0x00000082 },
+ { 0x50090288, 0x00000084 },
+ { 0x5009028c, 0x00000086 },
+ { 0x50090290, 0x00000088 },
+ { 0x50090294, 0x0000008a },
+ { 0x50090298, 0x000000c0 },
+ { 0x5009029c, 0x000000c2 },
+ { 0x500902a0, 0x000000c4 },
+ { 0x500902a4, 0x000000c6 },
+ { 0x500902a8, 0x000000c8 },
+ { 0x500902ac, 0x000000ca },
+ { 0x500902b0, 0x00000100 },
+ { 0x500902b4, 0x00000102 },
+ { 0x500902b8, 0x00000104 },
+ { 0x500902bc, 0x00000106 },
+ { 0x500902c0, 0x00000108 },
+ { 0x500902c4, 0x00000140 },
+ { 0x500902c8, 0x00000142 },
+ { 0x500902cc, 0x00000144 },
+ { 0x500902d0, 0x00000146 },
+ { 0x500902d4, 0x00000148 },
+ { 0x500902d8, 0x00000180 },
+ { 0x500902dc, 0x00000182 },
+ { 0x500902e0, 0x00000184 },
+ { 0x500902e4, 0x000001c0 },
+ { 0x500902e8, 0x000001c2 },
+ { 0x500902ec, 0x000001c4 },
+ { 0x500902f0, 0x000001c6 },
+ { 0x500902f4, 0x000001c8 },
+ { 0x500902f8, 0x000001ca },
+ { 0x500902fc, 0x000001cc },// lna = 01 end
+ { 0x50090300, 0x00000102 },
+ { 0x50090304, 0x00000104 },
+ { 0x50090308, 0x00000106 },
+ { 0x5009030c, 0x00000108 },
+ { 0x50090310, 0x00000140 },
+ { 0x50090314, 0x00000142 },
+ { 0x50090318, 0x00000144 },
+ { 0x5009031c, 0x00000146 },
+ { 0x50090320, 0x00000148 },
+ { 0x50090324, 0x00000180 },
+ { 0x50090328, 0x00000182 },
+ { 0x5009032c, 0x00000184 },
+ { 0x50090330, 0x000001c0 },
+ { 0x50090334, 0x000001c2 },
+ { 0x50090338, 0x000001c4 },
+ { 0x5009033c, 0x000001c6 },
+ { 0x50090340, 0x000001c8 },
+ { 0x50090344, 0x000001c9 },
+ { 0x50090348, 0x000001c9 },
+ { 0x5009034c, 0x000001c9 },
+ { 0x50090350, 0x000001c9 },
+ { 0x50090354, 0x000001c9 },
+ { 0x50090358, 0x000001c9 },
+ { 0x5009035c, 0x000001c9 },
+ { 0x50090360, 0x000001c9 },
+ { 0x50090364, 0x000001c9 },
+ { 0x50090368, 0x000001c9 },
+ { 0x5009036c, 0x000001c9 },
+ { 0x50090370, 0x000001c9 },
+ { 0x50090374, 0x000001c9 },
+ { 0x50090378, 0x000001c9 },
+ { 0x5009037c, 0x000001c9 },
+ { 0x50090054, 0x00000000 },//disable update
+
+ { 0x5000050c, 0x00008000 },// for association power save
+
+ //{ 0x50000808, 0x65000013 }, // disable prerx_priority;pta config
+ //{ 0x50000810, 0xFFCD0F01 }, //rx beacon priority
+
+};
+
+const u32 wifi_core_init_data_32_90_E[][2] =
+{
+#ifdef FORCE_WF_RX_TX
+ {0x50000800,0xFC003E05},
+ {0x50000804,0x00000000},
+ {0x50000808,0xA5000013}, //no pre_active protect
+ {0x5000080c,0x000001C0},
+ {0x50000810,0xFFCC0F01},
+ {0x50000814,0x00000000}, // not grant to rx and tx
+ {0x50000818,0x00FF0001},
+ {0x5000081C,0xFF000F00},
+ {0x50000820,0x00000000},
+ {0x50000824,0x0000F0FE},
+ {0x50000828,0x00100F10},
+ {0x50000838,0xFFFFFFFF},
+ {0x5000083C,0xFFFFFFFF},
+#endif
+
+#ifdef FORCE_WF_RX
+ {0x50000800,0xFC003E05},
+ {0x50000804,0x00000000},
+ {0x50000808,0xA5000013}, //no pre_active protect
+ {0x5000080c,0x000001C0},
+ {0x50000810,0xFFCC0F01},
+ {0x50000814,0xFF000F00}, //wf not grant to rx
+ {0x50000818,0x00FF0001},
+ {0x5000081C,0xFF000F00},
+ {0x50000820,0xFF000F00},
+ {0x50000824,0x0000F0FE},
+ {0x50000828,0x00100F10},
+ {0x50000838,0xFFFFFFFF},
+ {0x5000083C,0xFFFFFFFF},
+#endif
+
+#ifdef FORCE_WF_TX
+ {0x50000800,0xFC003E05},
+ {0x50000804,0x00000000},
+ {0x50000808,0xA5000013}, //no pre_active protect
+ {0x5000080c,0x000001C0},
+ {0x50000810,0xFFCC0F01},
+ {0x50000814,0x00FF0033}, //wf not grant to tx
+ {0x50000818,0x00FF0001},
+ {0x5000081C,0xFF000F00},
+ {0x50000820,0x00000000},
+ {0x50000824,0x0000F0FE},
+ {0x50000828,0x00100F10},
+ {0x50000838,0xFFFFFFFF},
+ {0x5000083C,0xFFFFFFFF},
+#endif
+
+#ifdef WF_PAT_CFG_2012_05_19
+ {0x50000800,0xFC003E05},
+ {0x50000804,0x00000000},
+ {0x50000808,0xA5000013}, //no pre_active protect
+ {0x5000080c,0x000001C0},
+ {0x50000810,0xFFCC0F01},
+ {0x50000814,0xFFFF0F03}, //0xFFFF0F33
+ {0x50000818,0x00FF0001},
+ {0x5000081C,0xFF000F00},
+ {0x50000820,0xFF000F00},
+ {0x50000824,0x0000F0FE},
+ {0x50000828,0x00100F10},
+ {0x50000838,0xFFFFFFFF},
+ {0x5000083C,0xFFFFFFFF},
+#endif
+
+#ifdef WF_PAT_CFG_2013_04_08
+ {0x50000800,0x00000000},
+ {0x50000804,0x00200000}, //ack as high
+ {0x50000838,0x00101014},
+ {0x5000083C,0x00333101},
+ {0x50000808,0x75000013},
+ {0x5000080c,0x000001C0},
+ {0x50000810,0xFFFF0111},
+ {0x50000814,0xFFFF0111},
+ {0x50000818,0x00FF0011},
+ {0x5000081C,0xFF000100},
+ {0x50000820,0xFF000100},
+ {0x50000824,0x0000FEEE},
+ {0x50000828,0x00100F10},
+ {0x50000834,0x00000000},
+#endif
+
+#ifdef FORCE_WF
+ {0x50000800,0xFC003E05},
+ {0x50000804,0x00000000},
+ {0x50000838,0xF8003f2A},
+ {0x5000083c,0x00000003},
+ {0x50000808,0xfe00001b},
+ {0x50000810,0x00000000},
+ {0x50000814,0x00000000},
+ {0x50000818,0x00000000},
+ {0x5000081C,0x00000000},
+ {0x50000820,0x00000000},
+ {0x50000824,0xffffffff},
+ {0x50000828,0x00100F10},
+#endif
+
+#ifdef WF_PAT_CFG_2012_04_15 /*pta config*/
+ {0x50000800,0xFC003E05}, //tx_pri hi bits ctrl&mgmt package
+ {0x50000804,0x00000000}, //tx_pri hi bits as hi pri
+ {0x50000808,0xA500001B}, //sig_mode and protect time
+ {0x5000080c,0x000001C0}, //sigWire mode
+ {0x50000810,0xFFCC0F01}, //Lut bt
+ {0x50000814,0xFFFF0F33}, //Lut wf
+ {0x50000818,0x00FF0001}, //antSel0 for wl_rx
+ {0x5000081C,0xFF000F00}, //antSel1 for wl_tx
+ {0x50000820,0xFF000F00}, //antSel2 for wl_pa
+ //{0x50000838,0xFFFFFFFF}, //rx_pri low bits as high pri
+ //{0x5000083C,0xFFFFFFFF}, //rx_pri high bits as high pri
+#endif
+
+ { 0x30010004, 0x0000f77c }, //intn config
+ { 0x30010010, 0x00007dff }, //intn config
+ //item111:ver_b_wf_dig_2011_10_09
+ { 0x30010000, 0x78036BAF }, //disable tports wait 100ms;
+ { 0x30000010, 0x7000FFFF },//wait 500ms;
+ { 0x5000050c, 0x00008000 },// for association power save
+};
+
+const u32 wifi_notch_data_90_D[][2] =
+{
+ //ch 1
+ {0x001008d0, 0x50090040},
+ {0x001008d4, 0x057213a2},
+ {0x001008d8, 0x50090044},
+ {0x001008dc, 0x10000000},
+ //ch 2
+ {0x00100910, 0x50090040},
+ {0x00100914, 0x10000000},
+ {0x00100918, 0x50090044},
+ {0x0010091c, 0x10000000},
+ //ch 3
+ {0x00100950, 0x50090040},
+ {0x00100954, 0x10000000},
+ {0x00100958, 0x50090044},
+ {0x0010095c, 0x10000000},
+ //ch 4
+ {0x00100990, 0x50090040},
+ {0x00100994, 0x10000000},
+ {0x00100998, 0x50090044},
+ {0x0010099c, 0x10000000},
+ //ch 5
+ {0x001009d0, 0x50090040},
+ {0x001009d4, 0x056794b4},
+ {0x001009d8, 0x50090044},
+ {0x001009dc, 0x10000000},
+ //ch 6
+ {0x00100a10, 0x50090040},
+ {0x00100a14, 0x057c71de}, //Modified Accord To xiongzhi 0x077c71de----old
+ {0x00100a18, 0x50090044},
+ {0x00100a1c, 0x10000000}, //Modified Accord To xiongzhi 0x046d242e----old
+ //ch 7
+ {0x00100a50, 0x50090040},
+ {0x00100a54, 0x057e7140},
+ {0x00100a58, 0x50090044},
+ {0x00100a5c, 0x10000000},
+ //ch 8
+ {0x00100a90, 0x50090040},
+ {0x00100a94, 0x057c7e22}, //Modified Accord To xiongzhi 0x077c7e22----old
+ {0x00100a98, 0x50090044},
+ {0x00100a9c, 0x10000000}, //Modified Accord To xiongzhi 0x046d2bd2----old
+ //ch 9
+ {0x00100ad0, 0x50090040},
+ {0x00100ad4, 0x10000000},
+ {0x00100ad8, 0x50090044},
+ {0x00100adc, 0x10000000},
+ //ch 10
+ {0x00100b10, 0x50090040},
+ {0x00100b14, 0x10000000},
+ {0x00100b18, 0x50090044},
+ {0x00100b1c, 0x10000000},
+ //ch 11
+ {0x00100b50, 0x50090040},
+ {0x00100b54, 0x10000000},
+ {0x00100b58, 0x50090044},
+ {0x00100b5c, 0x10000000},
+ //ch 12
+ {0x00100b90, 0x50090040},
+ {0x00100b94, 0x05764310},
+ {0x00100b98, 0x50090044},
+ {0x00100b9c, 0x10000000},
+ //ch 13
+ {0x00100bd0, 0x50090040},
+ {0x00100bd4, 0x056794b4},
+ {0x00100bd8, 0x50090044},
+ {0x00100bdc, 0x10000000},
+ //ch 14
+ {0x00100c10, 0x50090040},
+ {0x00100c14, 0x0579c279},
+ {0x00100c18, 0x50090044},
+ {0x00100c1c, 0x0579cd87},
+};
+
+const u32 wifi_notch_data_90_E[][2] =
+{
+ // For Verion E
+ //ch 1
+ {0x001007CC, 0x50090040},
+ {0x001007D0, 0x057213a2},
+ {0x001007D4, 0x50090044},
+ {0x001007D8, 0x10000000},
+ //ch 2
+ {0x001007FC, 0x50090040},
+ {0x00100800, 0x10000000},
+ {0x00100804, 0x50090044},
+ {0x00100808, 0x10000000},
+ //ch 3
+ {0x0010082C, 0x50090040},
+ {0x00100830, 0x10000000},
+ {0x00100834, 0x50090044},
+ {0x00100838, 0x10000000},
+ //ch 4
+ {0x0010085C, 0x50090040},
+ {0x00100860, 0x10000000},
+ {0x00100864, 0x50090044},
+ {0x00100868, 0x10000000},
+ //ch 5
+ {0x0010088C, 0x50090040},
+ {0x00100890, 0x056794b4},
+ {0x00100894, 0x50090044},
+ {0x00100898, 0x10000000},
+ //ch 6
+ {0x001008BC, 0x50090040},
+ {0x001008C0, 0x057c71de},
+ {0x001008C4, 0x50090044},
+ {0x001008C8, 0x10000000},
+ //ch 7
+ {0x001008EC, 0x50090040},
+ {0x001008F0, 0x057e7140},
+ {0x001008F4, 0x50090044},
+ {0x001008F8, 0x10000000},
+ //ch 8
+ {0x0010091C, 0x50090040},
+ {0x00100920, 0x057c7e22},
+ {0x00100924, 0x50090044},
+ {0x00100928, 0x10000000},
+ //ch 9
+ {0x0010094C, 0x50090040},
+ {0x00100950, 0x10000000},
+ {0x00100954, 0x50090044},
+ {0x00100958, 0x10000000},
+ //ch 10
+ {0x0010097C, 0x50090040},
+ {0x00100980, 0x10000000},
+ {0x00100984, 0x50090044},
+ {0x00100988, 0x10000000},
+ //ch 11
+ {0x001009AC, 0x50090040},
+ {0x001009B0, 0x10000000},
+ {0x001009B4, 0x50090044},
+ {0x001009B8, 0x10000000},
+ //ch 12
+ {0x001009DC, 0x50090040},
+ {0x001009E0, 0x05764310},
+ {0x001009E4, 0x50090044},
+ {0x001009E8, 0x10000000},
+ //ch 13
+ {0x00100A0C, 0x50090040},
+ {0x00100A10, 0x056794b4},
+ {0x00100A14, 0x50090044},
+ {0x00100A18, 0x10000000},
+ //ch 14
+ {0x00100A3C, 0x50090040},
+ {0x00100A40, 0x0579c279},
+ {0x00100A44, 0x50090044},
+ {0x00100A4c, 0x0579cd87},
+};
+
+//common sdio clock open
+const u32 wifi_core_data_wake[][2] =
+{
+ {0x3001003c, 0x2e00a000},
+};
+//sleep sdio switch
+const u32 wifi_core_data_sleep[][2] =
+{
+ {0x3001003c, 0x2e00a100},
+};
+
+const u32 wifi_phy_timeout_cfg_90[][2] =
+{
+ {0x50000634, 0x00001100},
+ {0x50000584, 0x00005BF8},
+};
+
+static const u32 wifi_test_mode_rx_notch_32_90[][2] =
+{
+ //item:notch_filter_5
+ {0x50090040,0x076794b4},//8m
+ {0x50090044,0x10000000},
+ //item:notch_filter_6
+ {0x50090040,0x057c71de},//3m
+ {0x50090044,0x10000000},//7m
+ //item:notch_filter_7
+ {0x50090040,0x077e7ec0},//2m
+ {0x50090044,0x077e7140},//-2m
+ //item:notch_filter_8
+ {0x50090040,0x057c7e22},//3m
+ {0x50090044,0x10000000},//7m
+ //item:notch_filter_c
+ {0x50090040,0x07764310},//5m
+ {0x50090044,0x10000000},
+ //item:notch_filter_e
+ {0x50090040,0x0779c279},//4m
+ {0x50090044,0x0779cd87},//-4m
+ //item:disable_notch
+ {0x50090040,0x10000000},
+ {0x50090044,0x10000000},
+};
+
+static const u32 wifi_test_mode_agc_patch32_90[][2] =
+ {
+ {0x50000600,0x0000501a},//write 1a(52) to 28h hightolow
+ {0x50000600,0x0000520d},//write 0d(26) to 29h hightomid
+ {0x50000600,0x00006a1e},//35h reg coarse2 upper window from 0d to 1a for l
+ //;50000600H,32'h00009890;//4ch reg unlock upper threshold from 70 to 90
+ {0x50000600,0x00009a38},//4dh reg unlock lower threshold from 78 to 38
+ {0x50000600,0x00007207},//39h reg change vga gain ,9 -> 7 for big signal
+ {0x50000600,0x0001c8f5},//e4h reg change hpf coeff to f5
+ {0x50000600,0x00004200},//21h reg add fine gain 0db
+ {0x50000600,0x00004610},//23h reg change maxgain index as agc table
+ {0x50000600,0x0000900e},//48h reg unlock lower threshold change from 0a to
+ {0x50000600,0x00004a00},//25h reg pecket dection threshold
+ {0x50000600,0x000040a8},//20h reg add fine itr2 98->a8
+ {0x50000600,0x00007e05},//3f reg rssi window for fine itr2 0->5
+ {0x50000600,0x00008237},//41 reg fine itr1 nextstate 4->3
+ {0x50000600,0x00008440},//42 reg fine itr2 nextstate 0->4 settle time 0->d
+ {0x50000600,0x0000b6a9},//5b reg change GreatN rssi avg count from 1 to 8
+} ;
+
+static const u32 wlan_test_mode_digital32_90[][2] =
+{
+ //item111:ver_D_wf_dig_20120208
+ {0x30010000,0x780369AF}, //disable tports
+ //wait 100ms;
+ {0x30000010,0x7000FFFF},
+ //item:agc_table_20110921
+ {0x50090054,0x00000001},//enable update
+ {0x50090200,0x00000000},
+ {0x50090204,0x00000000},
+ {0x50090208,0x00000002},
+ {0x5009020c,0x00000004},
+ {0x50090210,0x00000006},
+ {0x50090214,0x00000008},
+ {0x50090218,0x0000000a},
+ {0x5009021c,0x00000040},
+ {0x50090220,0x00000042},
+ {0x50090224,0x00000044},
+ {0x50090228,0x00000046},
+ {0x5009022c,0x00000048},
+ {0x50090230,0x0000004a},
+ {0x50090234,0x00000080},
+ {0x50090238,0x00000082},
+ {0x5009023c,0x00000084},
+ {0x50090240,0x00000086},
+ {0x50090244,0x00000088},
+ {0x50090248,0x0000008a},
+ {0x5009024c,0x000000c0},
+ {0x50090250,0x000000c2},
+ {0x50090254,0x000000c4},
+ {0x50090258,0x000000c6},
+ {0x5009025c,0x000000c8},
+ {0x50090260,0x000000ca},
+ {0x50090264,0x00000100},
+ {0x50090268,0x00000102},
+ {0x5009026c,0x00000104},
+ {0x50090270,0x00000106},
+ {0x50090274,0x00000108},
+ {0x50090278,0x00000140},
+ {0x5009027c,0x00000142},//lna =0 end
+ {0x50090280,0x00000080},
+ {0x50090284,0x00000082},
+ {0x50090288,0x00000084},
+ {0x5009028c,0x00000086},
+ {0x50090290,0x00000088},
+ {0x50090294,0x0000008a},
+ {0x50090298,0x000000c0},
+ {0x5009029c,0x000000c2},
+ {0x500902a0,0x000000c4},
+ {0x500902a4,0x000000c6},
+ {0x500902a8,0x000000c8},
+ {0x500902ac,0x000000ca},
+ {0x500902b0,0x00000100},
+ {0x500902b4,0x00000102},
+ {0x500902b8,0x00000104},
+ {0x500902bc,0x00000106},
+ {0x500902c0,0x00000108},
+ {0x500902c4,0x00000140},
+ {0x500902c8,0x00000142},
+ {0x500902cc,0x00000144},
+ {0x500902d0,0x00000146},
+ {0x500902d4,0x00000148},
+ {0x500902d8,0x00000180},
+ {0x500902dc,0x00000182},
+ {0x500902e0,0x00000184},
+ {0x500902e4,0x000001c0},
+ {0x500902e8,0x000001c2},
+ {0x500902ec,0x000001c4},
+ {0x500902f0,0x000001c6},
+ {0x500902f4,0x000001c8},
+ {0x500902f8,0x000001ca},
+ {0x500902fc,0x000001cc},// lna = 01 end
+ {0x50090300,0x00000102},
+ {0x50090304,0x00000104},
+ {0x50090308,0x00000106},
+ {0x5009030c,0x00000108},
+ {0x50090310,0x00000140},
+ {0x50090314,0x00000142},
+ {0x50090318,0x00000144},
+ {0x5009031c,0x00000146},
+ {0x50090320,0x00000148},
+ {0x50090324,0x00000180},
+ {0x50090328,0x00000182},
+ {0x5009032c,0x00000184},
+ {0x50090330,0x000001c0},
+ {0x50090334,0x000001c2},
+ {0x50090338,0x000001c4},
+ {0x5009033c,0x000001c6},
+ {0x50090340,0x000001c8},
+ {0x50090344,0x000001c9},
+ {0x50090348,0x000001c9},
+ {0x5009034c,0x000001c9},
+ {0x50090350,0x000001c9},
+ {0x50090354,0x000001c9},
+ {0x50090358,0x000001c9},
+ {0x5009035c,0x000001c9},
+ {0x50090360,0x000001c9},
+ {0x50090364,0x000001c9},
+ {0x50090368,0x000001c9},
+ {0x5009036c,0x000001c9},
+ {0x50090370,0x000001c9},
+ {0x50090374,0x000001c9},
+ {0x50090378,0x000001c9},
+ {0x5009037c,0x000001c9},
+ {0x50090054,0x00000000},//disable update
+ {0x50000808,0x65000013}, // disable prerx_prio
+ //pta config
+ {0x50000810,0xFFCD0F01}, //rx beacon priority
+};
+
+#endif
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_91.h b/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_91.h
new file mode 100755
index 00000000..d3485916
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_91.h
@@ -0,0 +1,754 @@
+#ifndef __WLAN_SDIO_PATCH_91_H__
+#define __WLAN_SDIO_PATCH_91_H__
+
+static const u32 wifi_core_patch_data_32_91[][2] = {
+ // add for pta
+ {0x50000828,0x00100FFD},
+ {0x50000810,0xFFFF0F0F},
+ {0x50000814,0xFFFF0F0F},
+ {0x50000818,0x00FF000F},
+ {0x5000081C,0xFF000F00},
+ {0x50000820,0xFF000F00},
+ {0x50000824,0x0000F0F0},
+ // add for pta
+ {0x0010FFFC, 0x20131231},
+ {0x00110000, 0xEA03ECE7},
+ {0x00110004, 0xE59D0000},
+ {0x00110008, 0xE3C01008},
+ {0x0011000C, 0xE58D1000},
+ {0x00110010, 0xE3A00030},
+ {0x00110014, 0xEB000001},
+ {0x00110018, 0xE3A0100C},
+ {0x0011001C, 0xE59FF004},
+ {0x00110020, 0xE51FF004},
+ {0x00110024, 0x0001D33C},
+ {0x00110028, 0x00014C64},
+ {0x0011002C, 0xEA03E563},
+ {0x00110030, 0xE3130008},
+ {0x00110034, 0x159F0020},
+ {0x00110038, 0x1A000002},
+ {0x0011003C, 0xE3130004},
+ {0x00110040, 0x059F000C},
+ {0x00110044, 0x159F000C},
+ {0x00110048, 0xE5840008},
+ {0x0011004C, 0xE3A00010},
+ {0x00110050, 0xE59FF008},
+ {0x00110054, 0x00010140},
+ {0x00110058, 0x00010141},
+ {0x0011005C, 0x00010142},
+ {0x00110060, 0x00016AA0},
+ {0x00110064, 0xEA03CB40},
+ {0x00110068, 0xE1A02004},
+ {0x0011006C, 0xE1A02822},
+ {0x00110070, 0xE202207F},
+ {0x00110074, 0xE3520029},
+ {0x00110078, 0x1A000010},
+ {0x0011007C, 0xE1A04804},
+ {0x00110080, 0xE1A04824},
+ {0x00110084, 0xE59F003C},
+ {0x00110088, 0xE1540000},
+ {0x0011008C, 0x059F1040},
+ {0x00110090, 0xE59F0034},
+ {0x00110094, 0xE1540000},
+ {0x00110098, 0x059F1038},
+ {0x0011009C, 0xE59F002C},
+ {0x001100A0, 0xE1540000},
+ {0x001100A4, 0x059F1030},
+ {0x001100A8, 0xE3A027C0},
+ {0x001100AC, 0xE3A04028},
+ {0x001100B0, 0xE1A04804},
+ {0x001100B4, 0xE1824004},
+ {0x001100B8, 0xE1844001},
+ {0x001100BC, 0xE59F101C},
+ {0x001100C0, 0xE5814034},
+ {0x001100C4, 0xE59FF018},
+ {0x001100C8, 0x00009468},
+ {0x001100CC, 0x0000D468},
+ {0x001100D0, 0x00001468},
+ {0x001100D4, 0x00001F20},
+ {0x001100D8, 0x00001320},
+ {0x001100DC, 0x00001320},
+ {0x001100E0, 0x50090000},
+ {0x001100E4, 0x0001D364},
+ {0x001100E8, 0xEA03D7EB},
+ {0x001100EC, 0xE59F0010},
+ {0x001100F0, 0xE3A04003},
+ {0x001100F4, 0xE5804000},
+ {0x001100F8, 0xE59F4008},
+ {0x001100FC, 0xE5940000},
+ {0x00110100, 0xE59FF004},
+ {0x00110104, 0x50000228},
+ {0x00110108, 0x00100B08},
+ {0x0011010C, 0x0001A13C},
+ {0x00110110, 0xEA03ED23},
+ {0x00110114, 0xE3510000},
+ {0x00110118, 0xE51FF004},
+ {0x0011011C, 0x00014C84},
+ {0x00110120, 0xEA03FC88},
+ {0x00110124, 0xE1C510B8},
+ {0x00110128, 0xE3510015},
+ {0x0011012C, 0xBA00001D},
+ {0x00110130, 0xE59F2074},
+ {0x00110134, 0xE3A01020},
+ {0x00110138, 0xE5C21000},
+ {0x0011013C, 0xEB000019},
+ {0x00110140, 0xE59F2068},
+ {0x00110144, 0xE5921020},
+ {0x00110148, 0xE3110A80},
+ {0x0011014C, 0x1AFFFFFC},
+ {0x00110150, 0xE1D510B8},
+ {0x00110154, 0xE1A01221},
+ {0x00110158, 0xE2811030},
+ {0x0011015C, 0xE5C21000},
+ {0x00110160, 0xE5921020},
+ {0x00110164, 0xE3110A80},
+ {0x00110168, 0x1AFFFFFC},
+ {0x0011016C, 0xE1D510B8},
+ {0x00110170, 0xE201100F},
+ {0x00110174, 0xE351000A},
+ {0x00110178, 0xA2811037},
+ {0x0011017C, 0xB2811030},
+ {0x00110180, 0xE5C21000},
+ {0x00110184, 0xE5921020},
+ {0x00110188, 0xE3110A80},
+ {0x0011018C, 0x1AFFFFFC},
+ {0x00110190, 0xE3A0100D},
+ {0x00110194, 0xE5C21000},
+ {0x00110198, 0xE5921020},
+ {0x0011019C, 0xE3110A80},
+ {0x001101A0, 0x1AFFFFFC},
+ {0x001101A4, 0xE3A0100A},
+ {0x001101A8, 0xE59FF004},
+ {0x001101AC, 0x50300038},
+ {0x001101B0, 0x50060000},
+ {0x001101B4, 0x00010F00},
+ {0x001101B8, 0xEA040A9C},
+ {0x001101BC, 0xE59F2038},
+ {0x001101C0, 0xE1D210B0},
+ {0x001101C4, 0xE3510020},
+ {0x001101C8, 0xCA000002},
+ {0x001101CC, 0xE51F2028},
+ {0x001101D0, 0xE3A01010},
+ {0x001101D4, 0xE5C21000},
+ {0x001101D8, 0xE3560000},
+ {0x001101DC, 0xE59FF01C},
+ {0x001101E0, 0xE1A00000},
+ {0x001101E4, 0xE1A00000},
+ {0x001101E8, 0xE1A00000},
+ {0x001101EC, 0xE1A00000},
+ {0x001101F0, 0xE1A00000},
+ {0x001101F4, 0xE1A00000},
+ {0x001101F8, 0xE1A00000},
+ {0x001101FC, 0x00106310},
+ {0x00110200, 0x0000D748},
+ {0x00110204, 0xEA0403F6},
+ {0x00110208, 0xE5CD0018},
+ {0x0011020C, 0xE51F0018},
+ {0x00110210, 0xE1D010B0},
+ {0x00110214, 0xE3510020},
+ {0x00110218, 0xCA000002},
+ {0x0011021C, 0xE51F0078},
+ {0x00110220, 0xE3A01010},
+ {0x00110224, 0xE5C01000},
+ {0x00110228, 0xE59FF01C},
+ {0x0011022C, 0xE1A00000},
+ {0x00110230, 0xE1A00000},
+ {0x00110234, 0xE1A00000},
+ {0x00110238, 0xE1A00000},
+ {0x0011023C, 0xE1A00000},
+ {0x00110240, 0xE1A00000},
+ {0x00110244, 0xE1A00000},
+ {0x00110248, 0x50060000},
+ {0x0011024C, 0x0000F22C},
+ {0x00110250, 0xEA03FB4F},
+ {0x00110254, 0xE59F2014},
+ {0x00110258, 0xE3500000},
+ {0x0011025C, 0x03A01000},
+ {0x00110260, 0x13A01001},
+ {0x00110264, 0xE5C21000},
+ {0x00110268, 0xE3500000},
+ {0x0011026C, 0xE59FF000},
+ {0x00110270, 0x001102C0},
+ {0x00110274, 0x00011514},
+ {0x00110278, 0xEA03ED3C},
+ {0x0011027C, 0xE59D0000},
+ {0x00110280, 0xE3C01008},
+ {0x00110284, 0xE58D1000},
+ {0x00110288, 0xE3A00030},
+ {0x0011028C, 0xEBFFFF63},
+ {0x00110290, 0xE3A0100C},
+ {0x00110294, 0xE51FF004},
+ {0x00110298, 0x00014D88},
+ {0x0011029C, 0xEA03ED77},
+ {0x001102A0, 0xE3500000},
+ {0x001102A4, 0xE59FF00C},
+ {0x001102A8, 0xE1A00000},
+ {0x001102AC, 0xE1A00000},
+ {0x001102B0, 0xE1A00000},
+ {0x001102B4, 0xE1A00000},
+ {0x001102B8, 0x00014CC0},
+ {0x001102BC, 0xEA03EDDF},
+ {0x001102C0, 0xE59D0000},
+ {0x001102C4, 0xE3C01008},
+ {0x001102C8, 0xE58D1000},
+ {0x001102CC, 0xE3A00030},
+ {0x001102D0, 0xEBFFFF52},
+ {0x001102D4, 0xE3A0100C},
+ {0x001102D8, 0xE51FF004},
+ {0x001102DC, 0x00014B40},
+ {0x001102E0, 0xEA043462},
+ {0x001102E4, 0xE1A00000},
+ {0x001102E8, 0xE1A00000},
+ {0x001102EC, 0xE51FF004},
+ {0x001102F0, 0x00003158},
+ {0x001102F4, 0xEA041567},
+ {0x001102F8, 0xE5940004},
+ {0x001102FC, 0xE3800850},
+ {0x00110300, 0xE5840004},
+ {0x00110304, 0xE3A00000},
+ {0x00110308, 0xE51FF004},
+ {0x0011030C, 0x0000AD58},
+ {0x00110310, 0xEA04300D},
+ {0x00110314, 0xE59F0028},
+ {0x00110318, 0xE5840584},
+ {0x0011031C, 0xE59F0024},
+ {0x00110320, 0xE59F1024},
+ {0x00110324, 0xE5810000},
+ {0x00110328, 0xE59F1020},
+ {0x0011032C, 0xE3A00003},
+ {0x00110330, 0xE5810000},
+ {0x00110334, 0xE59F001C},
+ {0x00110338, 0xE59F1014},
+ {0x0011033C, 0xE5810000},
+ {0x00110340, 0xE59FF014},
+ {0x00110344, 0x0000FFFB},
+ {0x00110348, 0x00000030},
+ {0x0011034C, 0x5000020C},
+ {0x00110350, 0x50000200},
+ {0x00110354, 0x30000014},
+ {0x00110358, 0x25801B0A},
+ {0x0011035C, 0x000042DC},
+ {0x00110360, 0xEA040074},
+ {0x00110364, 0xE1A00000},
+ {0x00110368, 0xE51FF004},
+ {0x0011036C, 0x000101E0},
+ {0x00110370, 0xEA03EE04},
+ {0x00110374, 0xE3510000},
+ {0x00110378, 0xE51FF004},
+ {0x0011037C, 0x00014B60},
+ {0x00110380, 0xEA03ED76},
+ {0x00110384, 0xE3510000},
+ {0x00110388, 0xE51FF004},
+ {0x0011038C, 0x00014DA8},
+ {0x00110390, 0xEA03EDFD},
+ {0x00110394, 0xE3500000},
+ {0x00110398, 0xE51FF004},
+ {0x0011039C, 0x00014B9C},
+ {0x001103A0, 0xEA03ED6F},
+ {0x001103A4, 0xE3500000},
+ {0x001103A8, 0xE51FF004},
+ {0x001103AC, 0x00014DE4},
+ {0x001103B0, 0xEA03FEA3},
+ {0x001103B4, 0xE1A00000},
+ {0x001103B8, 0xE51FF004},
+ {0x001103BC, 0x00010924},
+ {0x001103C0, 0xEA0420C9},
+ {0x001103C4, 0xE59F103C},
+ {0x001103C8, 0x03A00000},
+ {0x001103CC, 0x05810000},
+ {0x001103D0, 0x0A000007},
+ {0x001103D4, 0xE5910000},
+ {0x001103D8, 0xE2800001},
+ {0x001103DC, 0xE3500002},
+ {0x001103E0, 0x35810000},
+ {0x001103E4, 0x3A000004},
+ {0x001103E8, 0xE3A00000},
+ {0x001103EC, 0xE5810000},
+ {0x001103F0, 0xEAFFFFFF},
+ {0x001103F4, 0xE51FF004},
+ {0x001103F8, 0x0000809C},
+ {0x001103FC, 0xE51FF004},
+ {0x00110400, 0x000080E0},
+ {0x00110404, 0x00000000},
+ {0x00110408, 0x00110404},
+ {0x0011040C, 0xEA03D8AA},
+ {0x00110410, 0xE5C51000},
+ {0x00110414, 0xE1A00001},
+ {0x00110418, 0xE3A01032},
+ {0x0011041C, 0xE1500001},
+ {0x00110420, 0x3A000003},
+ {0x00110424, 0xE3A00001},
+ {0x00110428, 0xE3A02000},
+ {0x0011042C, 0xE3A01000},
+ {0x00110430, 0xE59FF004},
+ {0x00110434, 0xE51FF004},
+ {0x00110438, 0x0001A1AC},
+ {0x0011043C, 0x0001A1A4},
+ {0x00110440, 0xEA0438AC},
+ {0x00110444, 0xE1A000A0},
+ {0x00110448, 0xE51FF004},
+ {0x0011044C, 0x00002190},
+ {0x00110450, 0xEA04389C},
+ {0x00110454, 0xE3A00002},
+ {0x00110458, 0xE51FF004},
+ {0x0011045C, 0x000021E0},
+ {0x00110460, 0xEA041C47},
+ {0x00110464, 0xE3A03000},
+ {0x00110468, 0xE5D11000},
+ {0x0011046C, 0xE5802010},
+ {0x00110470, 0xE5803044},
+ {0x00110474, 0xE3510001},
+ {0x00110478, 0x13A01003},
+ {0x0011047C, 0x03A01009},
+ {0x00110480, 0xE5A01014},
+ {0x00110484, 0xE5803034},
+ {0x00110488, 0xE51FF004},
+ {0x0011048C, 0x00009364},
+ {0x20040004, 0x00014C60},
+ {0x20040024, 0x00110000},
+ {0x20040008, 0x00016A9C},
+ {0x20040028, 0x0011002C},
+ {0x2004000C, 0x0001D360},
+ {0x2004002C, 0x00110064},
+ {0x20040010, 0x0001A138},
+ {0x20040030, 0x001100E8},
+ {0x20040014, 0x00014C80},
+ {0x20040034, 0x00110110},
+ {0x20040018, 0x00010EFC},
+ {0x20040038, 0x00110120},
+ {0x2004001C, 0x0000D744},
+ {0x2004003C, 0x001101B8},
+ {0x20040020, 0x0000F228},
+ {0x20040040, 0x00110204},
+ {0x20040100, 0x00011510},
+ {0x20040120, 0x00110250},
+ {0x20040104, 0x00014D84},
+ {0x20040124, 0x00110278},
+ {0x20040108, 0x00014CBC},
+ {0x20040128, 0x0011029C},
+ {0x2004010C, 0x00014B3C},
+ {0x2004012C, 0x001102BC},
+ {0x20040110, 0x00003154},
+ {0x20040130, 0x001102E0},
+ {0x20040114, 0x0000AD54},
+ {0x20040134, 0x001102F4},
+ {0x20040118, 0x000042D8},
+ {0x20040138, 0x00110310},
+ {0x2004011C, 0x0001018C},
+ {0x2004013C, 0x00110360},
+ {0x20040140, 0x00014B5C},
+ {0x20040180, 0x00110370},
+ {0x20040144, 0x00014DA4},
+ {0x20040184, 0x00110380},
+ {0x20040148, 0x00014B98},
+ {0x20040188, 0x00110390},
+ {0x2004014C, 0x00014DE0},
+ {0x2004018C, 0x001103A0},
+ {0x20040150, 0x00010920},
+ {0x20040190, 0x001103B0},
+ {0x20040154, 0x00008098},
+ {0x20040194, 0x001103C0},
+ {0x20040158, 0x0001A160},
+ {0x20040198, 0x0011040C},
+ {0x2004015C, 0x0000218C},
+ {0x2004019C, 0x00110440},
+ {0x20040160, 0x000021DC},
+ {0x200401A0, 0x00110450},
+ {0x20040164, 0x00009340},
+ {0x200401A4, 0x00110460},
+ {0x20040000, 0x03FFFEFF},
+};
+#define SET_CHANNEL_MEM_TABLE_BASE 0x00107C98
+#define SET_CHANNEL_RF_TABLE_BASE 0x00107F38
+static const u32 wifi_clock_switch_91[][2] = {
+ //channel 1
+ {SET_CHANNEL_MEM_TABLE_BASE, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x04, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x08, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x0C, 0x2222CFCF},
+
+ //channel 2
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x30, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x34, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x38, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x3C, 0x2222CFCF},
+
+ //channel 3
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x60, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x64, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x68, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x6C, 0x2222CFCF},
+
+ //channel 4
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x90, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x94, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x98, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x9C, 0x2222CFCF},
+
+ //channel 5
+ {SET_CHANNEL_MEM_TABLE_BASE + 0xC0, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0xC4, 0x204199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0xC8, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0xCC, 0x2222CFCF},
+
+ //channel 6
+ {SET_CHANNEL_MEM_TABLE_BASE + 0xF0, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0xF4, 0x204199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0xF8, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0xFC, 0x2222CFCF},
+
+ //channel 7
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x120, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x124, 0x204199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x128, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x12C, 0x2222CFCF},
+
+ //channel 8
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x150, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x154, 0x204199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x158, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x15C, 0x2222CFCF},
+
+ //channel 9
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x180, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x184, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x188, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x18C, 0x2222CFCF},
+
+ //channel 10
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x1B0, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x1B4, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x1B8, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x1BC, 0x2222CFCF},
+
+ //channel 11
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x1E0, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x1E4, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x1E8, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x1EC, 0x2222CFCF},
+
+ //channel 12
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x210, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x214, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x218, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x21C, 0x2222CFCF},
+
+ //channel 13
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x240, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x244, 0x304199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x248, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE + 0x24C, 0x2222CFCF},
+
+ //channel 1
+ {SET_CHANNEL_RF_TABLE_BASE, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x04, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x08, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x0C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x10, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x14, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x18, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x1C, 0x00000000},
+
+ //channel 2
+ {SET_CHANNEL_RF_TABLE_BASE + 0x40, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x44, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x48, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x4C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x50, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x54, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x58, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x5C, 0x00000000},
+
+ //channel 3
+ {SET_CHANNEL_RF_TABLE_BASE + 0x80, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x84, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x88, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x8C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x90, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x94, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x98, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x9C, 0x00000000},
+
+ //channel 4
+ {SET_CHANNEL_RF_TABLE_BASE + 0xC0, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0xC4, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE + 0xC8, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE + 0xCC, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE + 0xD0, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE + 0xD4, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE + 0xD8, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0xDC, 0x00000000},
+
+ //channel 5
+ {SET_CHANNEL_RF_TABLE_BASE + 0x100, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x104, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x108, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x10C, 0x00000908},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x110, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x114, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x118, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x11C, 0x00000000},
+
+ //channel 6
+ {SET_CHANNEL_RF_TABLE_BASE + 0x140, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x144, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x148, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x14C, 0x00000908},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x150, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x154, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x158, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x15C, 0x00000000},
+
+ //channel 7
+ {SET_CHANNEL_RF_TABLE_BASE + 0x180, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x184, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x188, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x18C, 0x00000908},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x190, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x194, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x198, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x19C, 0x00000000},
+
+ //channel 8
+ {SET_CHANNEL_RF_TABLE_BASE + 0x1C0, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x1C4, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x1C8, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x1CC, 0x00000908},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x1D0, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x1D4, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x1D8, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x1DC, 0x00000000},
+
+ //channel 9
+ {SET_CHANNEL_RF_TABLE_BASE + 0x200, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x204, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x208, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x20C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x210, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x214, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x218, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x21C, 0x00000000},
+
+ //channel 10
+ {SET_CHANNEL_RF_TABLE_BASE + 0x240, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x244, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x248, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x24C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x250, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x254, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x258, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x25C, 0x00000000},
+
+ //channel 11
+ {SET_CHANNEL_RF_TABLE_BASE + 0x280, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x284, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x288, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x28C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x290, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x294, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x298, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x29C, 0x00000000},
+
+ //channel 12
+ {SET_CHANNEL_RF_TABLE_BASE + 0x2C0, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x2C4, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x2C8, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x2CC, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x2D0, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x2D4, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x2D8, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x2DC, 0x00000000},
+
+ //channel 13
+ {SET_CHANNEL_RF_TABLE_BASE + 0x300, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x304, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x308, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x30C, 0x00000B08},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x310, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x314, 0x0000AA12},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x318, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE + 0x31C, 0x00000000},
+};
+
+static const u8 wifi_core_patch_data_91_8[][2] = {
+ {0x28, 0x1a},
+ {0x29, 0x0d},
+ {0x25, 0x07},
+ {0x08, 0x43},
+ {0x26, 0x35},
+ {0x3e, 0x64},
+ {0x3f, 0x00},
+ {0x45, 0x75},
+ {0x46, 0x73},
+ {0x50, 0x58},
+
+ {0x30, 0xf6},
+
+ {0x74, 0x01},
+ {0x75, 0x40},
+
+ {0x74, 0xD4},
+ {0x75, 0x47},
+
+ {0x74, 0xff},
+ {0x75, 0x4b},
+
+ {0x74, 0x3D},
+ {0x75, 0x4c},
+
+ {0x74, 0x01},
+ {0x75, 0x50},
+
+ {0x74, 0x99},
+ {0x75, 0x57},
+
+ {0x74, 0xff},
+ {0x75, 0x5b},
+
+ {0x74, 0x33},
+ {0x75, 0x5D},
+
+ {0x74, 0xE4},
+ {0x75, 0x61},
+
+ {0x30, 0xF7},
+
+};
+
+static const u32 wifi_core_init_data_32_91[][2] = {
+ {0x500002a8, 0x00000001},
+ {0x50000080, 0x0003FEF7},
+ {0x5000050c, 0x00003900},
+ {0x30010010, 0x00007DFF},
+
+ {0x50090060, 0x000001B4},
+ {0x50090068, 0xEB3FF7FF},
+ {0x50090070, 0x1403DBFF},
+ {0x500900B0, 0x00400000},
+
+ {0x500900AC, 0x00000A00},
+ {0x50090054, 0x00000001},
+ {0x50090200, 0x00000180},
+ {0x50090204, 0x00000180},
+ {0x50090208, 0x00000180},
+ {0x5009020c, 0x00000180},
+ {0x50090210, 0x00000180},
+ {0x50090214, 0x00000180},
+ {0x50090218, 0x00000188},
+ {0x5009021c, 0x00000190},
+ {0x50090220, 0x00000200},
+ {0x50090224, 0x00000208},
+ {0x50090228, 0x00000210},
+ {0x5009022c, 0x00000280},
+ {0x50090230, 0x00000288},
+ {0x50090234, 0x00000290},
+ {0x50090238, 0x00000300},
+ {0x5009023c, 0x00000308},
+ {0x50090240, 0x00000310},
+ {0x50090244, 0x00000380},
+ {0x50090248, 0x00000388},
+ {0x5009024c, 0x00000390},
+ {0x50090250, 0x00000400},
+ {0x50090254, 0x00000408},
+ {0x50090258, 0x00000410},
+ {0x5009025c, 0x00000480},
+ {0x50090260, 0x00000488},
+ {0x50090264, 0x00000490},
+ {0x50090268, 0x00000500},
+ {0x5009026c, 0x00000508},
+ {0x50090270, 0x00000510},
+ {0x50090274, 0x00000580},
+ {0x50090278, 0x00000588},
+ {0x5009027c, 0x00000590},
+ {0x50090280, 0x00000290},
+ {0x50090284, 0x00000300},
+ {0x50090288, 0x00000308},
+ {0x5009028c, 0x00000310},
+ {0x50090290, 0x00000380},
+ {0x50090294, 0x00000388},
+ {0x50090298, 0x00000390},
+ {0x5009029c, 0x00000400},
+ {0x500902a0, 0x00000408},
+ {0x500902a4, 0x00000410},
+ {0x500902a8, 0x00000480},
+ {0x500902ac, 0x00000488},
+ {0x500902b0, 0x00000490},
+ {0x500902b4, 0x00000500},
+ {0x500902b8, 0x00000508},
+ {0x500902bc, 0x00000510},
+ {0x500902c0, 0x00000580},
+ {0x500902c4, 0x00000588},
+ {0x500902c8, 0x00000590},
+ {0x500902cc, 0x00000600},
+ {0x500902d0, 0x00000608},
+ {0x500902d4, 0x00000610},
+ {0x500902d8, 0x00000680},
+ {0x500902dc, 0x00000688},
+ {0x500902e0, 0x00000690},
+ {0x500902e4, 0x00000700},
+ {0x500902e8, 0x00000708},
+ {0x500902ec, 0x00000710},
+ {0x500902f0, 0x00000780},
+ {0x500902f4, 0x00000788},
+ {0x500902f8, 0x00000790},
+ {0x500902fc, 0x00000798},
+ {0x50090300, 0x00000500},
+ {0x50090304, 0x00000508},
+ {0x50090308, 0x00000510},
+ {0x5009030c, 0x00000580},
+ {0x50090310, 0x00000588},
+ {0x50090314, 0x00000590},
+ {0x50090318, 0x00000600},
+ {0x5009031c, 0x00000608},
+ {0x50090320, 0x00000610},
+ {0x50090324, 0x00000680},
+ {0x50090328, 0x00000688},
+ {0x5009032c, 0x00000690},
+ {0x50090330, 0x00000700},
+ {0x50090334, 0x00000708},
+ {0x50090338, 0x00000710},
+ {0x5009033c, 0x00000780},
+ {0x50090340, 0x00000780},
+ {0x50090344, 0x00000780},
+ {0x50090348, 0x00000780},
+ {0x5009034c, 0x00000780},
+ {0x50090350, 0x00000780},
+ {0x50090354, 0x00000780},
+ {0x50090358, 0x00000780},
+ {0x5009035c, 0x00000780},
+ {0x50090360, 0x00000780},
+ {0x50090364, 0x00000780},
+ {0x50090368, 0x00000780},
+ {0x5009036c, 0x00000780},
+ {0x50090370, 0x00000780},
+ {0x50090374, 0x00000780},
+ {0x50090378, 0x00000780},
+ {0x5009037c, 0x00000780},
+ {0x50090054, 0x00000000},
+};
+
+static const u32 wifi_core_AM_PM_data_32_91[][2] = {
+ {0x50090054, 0x00000000},
+ {0x50090068, 0xEB3FF7FF},
+ {0x50090070, 0x1403DBFF},
+ {0x500900B0, 0x00400000},
+ {0x50090090, 0x00000000}, //item0:theta0=7_B=0_r0=2
+ {0x50090094, 0x00A01401},
+ {0x50090098, 0x02907412},
+ {0x5009009C, 0x05D12438},
+ {0x500900A0, 0x0A522872},
+ {0x500900A4, 0xFFF380C1},
+ {0x50090078, 0x02B05400}, //item0:G0=-3.5_r0=2.5
+ {0x5009007C, 0x06D15840},
+ {0x50090080, 0x0B927885},
+ {0x50090084, 0x11A3DCD7},
+ {0x50090088, 0x1975A540},
+ {0x5009008C, 0xFFF7FDC9},
+ {0x500900A8, 0x9C4001A7},
+};
+static const u32 wifi_assoc_power_save_data_32_91[][2] = {
+ {0x5000050c, 0x00003900}// for association power save
+};
+
+
+#endif
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_91e.h b/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_91e.h
new file mode 100755
index 00000000..d55f1f55
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_91e.h
@@ -0,0 +1,675 @@
+#ifndef __WLAN_SDIO_PATCH_91_E_H__
+#define __WLAN_SDIO_PATCH_91_E_H__
+
+static const u32 wifi_core_patch_data_32_91e[][2] = {
+ // add for pta
+ {0x50000828,0x00100FFD},
+ {0x50000810,0xFFFF0F0F},
+ {0x50000814,0xFFFF0F0F},
+ {0x50000818,0x00FF000F},
+ {0x5000081C,0xFF000F00},
+ {0x50000820,0xFF000F00},
+ {0x50000824,0x0000F0F0},
+ {0x50090044,0xE6AD6CB0},//mode
+ {0x50090040,0xBA9D5EC4},//agc value
+ {0x001075EC,0x00000002},//disable ht
+ // add for pta
+#if 1
+ {0x0010FFFC, 0x20140527},
+ {0x00110000, 0xEA03FA67},
+ {0x00110004, 0xE51FF004},
+ {0x00110008, 0x000116B4},
+ {0x0011000C, 0xEA03C0BF},
+ {0x00110010, 0xE200007F},
+ {0x00110014, 0xE3500028},
+ {0x00110018, 0x1A00000B},
+ {0x0011001C, 0xE1A01801},
+ {0x00110020, 0xE1A01821},
+ {0x00110024, 0xE59F0024},
+ {0x00110028, 0xE1510000},
+ {0x0011002C, 0x059F1024},
+ {0x00110030, 0x03A00028},
+ {0x00110034, 0x059FF028},
+ {0x00110038, 0xE59F0014},
+ {0x0011003C, 0xE1510000},
+ {0x00110040, 0x059F1014},
+ {0x00110044, 0x03A00028},
+ {0x00110048, 0x059FF014},
+ {0x0011004C, 0xE59FF00C},
+ {0x00110050, 0x00001F20},
+ {0x00110054, 0x00001320},
+ {0x00110058, 0x00004F20},
+ {0x0011005C, 0x00004320},
+ {0x00110060, 0x0001FD10},
+ {0x00110064, 0x0001FD18},
+ {0x00110068, 0xEA0410ED},
+ {0x0011006C, 0xE5940004},
+ {0x00110070, 0xE3800850},
+ {0x00110074, 0xE5840004},
+ {0x00110078, 0xE3A00D44},
+ {0x0011007C, 0xE5840634},
+ {0x00110080, 0xE59F0004},
+ {0x00110084, 0xE5840584},
+ {0x00110088, 0xE59FF000},
+ {0x0011008C, 0x00007BF8},
+ {0x00110090, 0x0000BCB4},
+ {0x00110094, 0xEA040607},
+ {0x00110098, 0xE59F2020},
+ {0x0011009C, 0xE1D210B0},
+ {0x001100A0, 0xE1A00000},
+ {0x001100A4, 0xE1A00000},
+ {0x001100A8, 0xE59F200C},
+ {0x001100AC, 0xE3A01010},
+ {0x001100B0, 0xE5C21000},
+ {0x001100B4, 0xE3560000},
+ {0x001100B8, 0xE59FF004},
+ {0x001100BC, 0x50300038},
+ {0x001100C0, 0x00106B1C},
+ {0x001100C4, 0x0000E878},
+ {0x001100C8, 0xEA03FE7A},
+ {0x001100CC, 0xE5CD0018},
+ {0x001100D0, 0xE51F0018},
+ {0x001100D4, 0xE1D010B0},
+ {0x001100D8, 0xE1A00000},
+ {0x001100DC, 0xE1A00000},
+ {0x001100E0, 0xE51F002C},
+ {0x001100E4, 0xE3A01010},
+ {0x001100E8, 0xE5C01000},
+ {0x001100EC, 0xE59FF000},
+ {0x001100F0, 0x50060000},
+ {0x001100F4, 0x000106E0},
+ {0x001100F8, 0xEA042EFA},
+ {0x001100FC, 0xE59F0028},
+ {0x00110100, 0xE5840584},
+ {0x00110104, 0xE59F0024},
+ {0x00110108, 0xE59F1024},
+ {0x0011010C, 0xE5810000},
+ {0x00110110, 0xE59F1020},
+ {0x00110114, 0xE3A00003},
+ {0x00110118, 0xE5810000},
+ {0x0011011C, 0xE59F001C},
+ {0x00110120, 0xE59F1014},
+ {0x00110124, 0xE5810000},
+ {0x00110128, 0xE59FF014},
+ {0x0011012C, 0x0000FFFB},
+ {0x00110130, 0x00000030},
+ {0x00110134, 0x5000020C},
+ {0x00110138, 0x50000200},
+ {0x0011013C, 0x30000014},
+ {0x00110140, 0x25801B0A},
+ {0x00110144, 0x00004510},
+ {0x00110148, 0xEA041E5A},
+ {0x0011014C, 0xE59F103C},
+ {0x00110150, 0x03A00000},
+ {0x00110154, 0x05810000},
+ {0x00110158, 0x0A000007},
+ {0x0011015C, 0xE5910000},
+ {0x00110160, 0xE2800001},
+ {0x00110164, 0xE3500002},
+ {0x00110168, 0x35810000},
+ {0x0011016C, 0x3A000004},
+ {0x00110170, 0xE3A00000},
+ {0x00110174, 0xE5810000},
+ {0x00110178, 0xEAFFFFFF},
+ {0x0011017C, 0xE51FF004},
+ {0x00110180, 0x000087E0},
+ {0x00110184, 0xE51FF004},
+ {0x00110188, 0x00008824},
+ {0x0011018C, 0x00000000},
+ {0x00110190, 0x0011018C},
+ {0x00110194, 0xEA0437F6},
+ {0x00110198, 0xE1A000A0},
+ {0x0011019C, 0xE51FF004},
+ {0x001101A0, 0x000021BC},
+ {0x001101A4, 0xEA0437E3},
+ {0x001101A8, 0xE3A00002},
+ {0x001101AC, 0xE51FF004},
+ {0x001101B0, 0x00002218},
+ {0x001101B4, 0xEA0418DC},
+ {0x001101B8, 0xE3A03000},
+ {0x001101BC, 0xE5D11000},
+ {0x001101C0, 0xE5802010},
+ {0x001101C4, 0xE5803044},
+ {0x001101C8, 0xE3510001},
+ {0x001101CC, 0x13A01003},
+ {0x001101D0, 0x03A01009},
+ {0x001101D4, 0xE5A01014},
+ {0x001101D8, 0xE5803034},
+ {0x001101DC, 0xE51FF004},
+ {0x001101E0, 0x00009E64},
+ {0x001101E4, 0xEA03F8FC},
+ {0x001101E8, 0xE51FF004},
+ {0x001101EC, 0x00011DF4},
+ {0x001101F0, 0xEA041F1D},
+ {0x001101F4, 0xE3A015C0},
+ {0x001101F8, 0xE3E00007},
+ {0x001101FC, 0xE5810000},
+ {0x00110200, 0xE3A01001},
+ {0x00110204, 0xE3A0003F},
+ {0x00110208, 0xEB000007},
+ {0x0011020C, 0xE59F105C},
+ {0x00110210, 0xE3A00026},
+ {0x00110214, 0xEB000004},
+ {0x00110218, 0xE3A01000},
+ {0x0011021C, 0xE3A0003F},
+ {0x00110220, 0xEB000001},
+ {0x00110224, 0xE59F4008},
+ {0x00110228, 0xE59FF008},
+ {0x0011022C, 0xE51FF004},
+ {0x00110230, 0x0001FD08},
+ {0x00110234, 0x001077D4},
+ {0x00110238, 0x0000857C},
+ {0x0011023C, 0xEA042E03},
+ {0x00110240, 0xE3A01001},
+ {0x00110244, 0xE3A0003F},
+ {0x00110248, 0xEBFFFFF7},
+ {0x0011024C, 0xE59F1018},
+ {0x00110250, 0xE3A00026},
+ {0x00110254, 0xEBFFFFF4},
+ {0x00110258, 0xE3A01000},
+ {0x0011025C, 0xE3A0003F},
+ {0x00110260, 0xEBFFFFF1},
+ {0x00110264, 0xE59F0008},
+ {0x00110268, 0xE59FF008},
+ {0x0011026C, 0x0000808B},
+ {0x00110270, 0x000080BB},
+ {0x00110274, 0xFFFFFC09},
+ {0x00110278, 0x00004A30},
+ {0x0011027C, 0xEA042F4C},
+ {0x00110280, 0xE3A01001},
+ {0x00110284, 0xE3A0003F},
+ {0x00110288, 0xEBFFFFE7},
+ {0x0011028C, 0xE51F1028},
+ {0x00110290, 0xE3A00026},
+ {0x00110294, 0xEBFFFFE4},
+ {0x00110298, 0xE3A01000},
+ {0x0011029C, 0xE3A0003F},
+ {0x001102A0, 0xEBFFFFE1},
+ {0x001102A4, 0xE51F0038},
+ {0x001102A8, 0xE51FF004},
+ {0x001102AC, 0x0000454C},
+ {0x001102B0, 0xEA03EFF1},
+ {0x001102B4, 0xE3A01001},
+ {0x001102B8, 0xE3A0003F},
+ {0x001102BC, 0xEBFFFFDA},
+ {0x001102C0, 0xE51F1058},
+ {0x001102C4, 0xE3A00026},
+ {0x001102C8, 0xEBFFFFD7},
+ {0x001102CC, 0xE3A01000},
+ {0x001102D0, 0xE3A0003F},
+ {0x001102D4, 0xEBFFFFD4},
+ {0x001102D8, 0xE3A015C0},
+ {0x001102DC, 0xE3E00007},
+ {0x001102E0, 0xE5810000},
+ {0x001102E4, 0xE3A01003},
+ {0x001102E8, 0xE51FF004},
+ {0x001102EC, 0x000142EC},
+ {0x001102F0, 0xEA041316},
+ {0x001102F4, 0xE3A01002},
+ {0x001102F8, 0xE5C41000},
+ {0x001102FC, 0xE3A01001},
+ {0x00110300, 0xE51FF004},
+ {0x00110304, 0x0000B69C},
+ {0x00110308, 0xEA03F8E0},
+ {0x0011030C, 0xE5951828},
+ {0x00110310, 0xE1A01821},
+ {0x00110314, 0xE3C11CF0},
+ {0x00110318, 0xE51FF004},
+ {0x0011031C, 0x00011F88},
+ {0x00110320, 0xEA03E1E3},
+ {0x00110324, 0xE2800002},
+ {0x00110328, 0xE5D01000},
+ {0x0011032C, 0xE51FF004},
+ {0x00110330, 0x00017B94},
+ {0x20040004, 0x00011660},
+ {0x20040024, 0x00110000},
+ {0x20040008, 0x0001FD0C},
+ {0x20040028, 0x0011000C},
+ {0x2004000C, 0x0000BCB0},
+ {0x2004002C, 0x00110068},
+ {0x20040010, 0x0000E874},
+ {0x20040030, 0x00110094},
+ {0x20040014, 0x000106DC},
+ {0x20040034, 0x001100C8},
+ {0x20040018, 0x0000450C},
+ {0x20040038, 0x001100F8},
+ {0x2004001C, 0x000087DC},
+ {0x2004003C, 0x00110148},
+ {0x20040020, 0x000021B8},
+ {0x20040040, 0x00110194},
+ {0x20040100, 0x00002214},
+ {0x20040120, 0x001101A4},
+ {0x20040104, 0x00009E40},
+ {0x20040124, 0x001101B4},
+ {0x20040108, 0x00011DF0},
+ {0x20040128, 0x001101E4},
+ {0x2004010C, 0x00008578},
+ {0x2004012C, 0x001101F0},
+ {0x20040110, 0x00004A2C},
+ {0x20040130, 0x0011023C},
+ {0x20040114, 0x00004548},
+ {0x20040134, 0x0011027C},
+ {0x20040118, 0x000142E8},
+ {0x20040138, 0x001102B0},
+ {0x2004011C, 0x0000B694},
+ {0x2004013C, 0x001102F0},
+ {0x20040140, 0x00011F84},
+ {0x20040180, 0x00110308},
+ {0x20040144, 0x00017B90},
+ {0x20040184, 0x00110320},
+ {0x20040000, 0x0003FFFF},
+
+#endif
+};
+
+#define SET_CHANNEL_MEM_TABLE_BASE_91E 0x001086AC
+#define SET_CHANNEL_RF_TABLE_BASE_91E 0x0010894C
+static const u32 wifi_clock_switch_91e[][2] = {
+ //channel 1
+ {SET_CHANNEL_MEM_TABLE_BASE_91E, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x04, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x08, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x0C, 0x2222CFCF},
+
+ //channel 2
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x30, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x34, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x38, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x3C, 0x2222CFCF},
+
+ //channel 3
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x60, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x64, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x68, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x6C, 0x2222CFCF},
+
+ //channel 4
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x90, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x94, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x98, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x9C, 0x2222CFCF},
+
+ //channel 5
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0xC0, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0xC4, 0x204199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0xC8, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0xCC, 0x2222CFCF},
+
+ //channel 6
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0xF0, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0xF4, 0x204199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0xF8, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0xFC, 0x2222CFCF},
+
+ //channel 7
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x120, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x124, 0x204199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x128, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x12C, 0x2222CFCF},
+
+ //channel 8
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x150, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x154, 0x204199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x158, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x15C, 0x2222CFCF},
+
+ //channel 9
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x180, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x184, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x188, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x18C, 0x2222CFCF},
+
+ //channel 10
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x1B0, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x1B4, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x1B8, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x1BC, 0x2222CFCF},
+
+ //channel 11
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x1E0, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x1E4, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x1E8, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x1EC, 0x2222CFCF},
+
+ //channel 12
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x210, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x214, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x218, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x21C, 0x2222CFCF},
+
+ //channel 13
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x240, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x244, 0x304199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x248, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91E + 0x24C, 0x2222CFCF},
+
+ //channel 1
+ {SET_CHANNEL_RF_TABLE_BASE_91E, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x04, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x08, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x0C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x10, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x14, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x18, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x1C, 0x00000000},
+
+ //channel 2
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x40, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x44, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x48, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x4C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x50, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x54, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x58, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x5C, 0x00000000},
+
+ //channel 3
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x80, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x84, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x88, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x8C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x90, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x94, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x98, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x9C, 0x00000000},
+
+ //channel 4
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0xC0, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0xC4, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0xC8, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0xCC, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0xD0, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0xD4, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0xD8, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0xDC, 0x00000000},
+
+ //channel 5
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x100, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x104, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x108, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x10C, 0x00000908},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x110, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x114, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x118, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x11C, 0x00000000},
+
+ //channel 6
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x140, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x144, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x148, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x14C, 0x00000908},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x150, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x154, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x158, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x15C, 0x00000000},
+
+ //channel 7
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x180, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x184, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x188, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x18C, 0x00000908},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x190, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x194, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x198, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x19C, 0x00000000},
+
+ //channel 8
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x1C0, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x1C4, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x1C8, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x1CC, 0x00000908},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x1D0, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x1D4, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x1D8, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x1DC, 0x00000000},
+
+ //channel 9
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x200, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x204, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x208, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x20C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x210, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x214, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x218, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x21C, 0x00000000},
+
+ //channel 10
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x240, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x244, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x248, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x24C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x250, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x254, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x258, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x25C, 0x00000000},
+
+ //channel 11
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x280, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x284, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x288, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x28C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x290, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x294, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x298, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x29C, 0x00000000},
+
+ //channel 12
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x2C0, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x2C4, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x2C8, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x2CC, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x2D0, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x2D4, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x2D8, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x2DC, 0x00000000},
+
+ //channel 13
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x300, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x304, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x308, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x30C, 0x00000B08},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x310, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x314, 0x0000AA12},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x318, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91E + 0x31C, 0x00000000},
+};
+
+static const u8 wifi_core_patch_data_91e_8[][2] = {
+ {0x28, 0x1a},
+ {0x29, 0x0d},
+ {0x25, 0x00},
+ {0x08, 0x43},
+ //rx patch
+ {0x26, 0x35},
+ {0x3e, 0x64},
+ {0x3f, 0x00},
+ {0x45, 0x75},
+ {0x46, 0x73},
+ {0x50, 0x58},
+ {0x30, 0xf6},
+
+ {0xA0, 0x7f},
+ {0x74, 0x01},
+ {0x75, 0x40},
+
+ {0x12, 0x04},
+ {0x1C, 0x2D},
+ {0x0D, 0x59},
+ {0x17, 0x75},
+ {0x74, 0xD4},
+ {0x75, 0x47},
+
+ {0x74, 0xFF},
+ {0x75, 0x4B},
+
+ {0x74, 0x3D},
+ {0x75, 0x4C},
+
+ {0x74, 0x01},
+ {0x75, 0x50},
+
+ {0x74, 0x99},
+ {0x75, 0x57},
+
+ {0x74, 0xFF},
+ {0x75, 0x5B},
+
+ {0x74, 0x33},
+ {0x75, 0x5D},
+
+ {0x74, 0xE4},
+ {0x75, 0x61},
+
+ {0x30, 0xF7},
+};
+
+static const u32 wifi_core_init_data_32_91e[][2] = {
+ {0x500002a8, 0x00000001},
+ {0x50000080, 0x0003FEF7},
+ {0x00100018, 0x000A3243}, // flow ctrl , WPS supported, proakis
+ {0x0010001C, 0xFFFF0001},
+ {0x30010010, 0x00007DFF},
+
+ {0x50090060, 0x000001B4},
+ //item:rda5991_verE_wf_tx_pn9
+ {0x50090068, 0xEB3FF7FF},
+ {0x50090070, 0x1403DBFF},
+ {0x500900B0, 0x00400000},
+ {0x500900A8, 0x9c400180},
+ {0x5009008C, 0xFc07fdc9},
+ //PHY:phy rx timeout enable
+ {0x0010216c, 0x50000634},
+ {0x00102170, 0x00001100},
+ {0x00102174, 0x50000584},
+ {0x00102178, 0x00007bf8},
+ //new agc table 20140419
+ {0x50090054, 0x00000001},
+ {0x50090200, 0x00000100},
+ {0x50090204, 0x00000100},
+ {0x50090208, 0x00000100},
+ {0x5009020c, 0x00000100},
+ {0x50090210, 0x00000108},
+ {0x50090214, 0x00000110},
+ {0x50090218, 0x00000180},
+ {0x5009021c, 0x00000188},
+ {0x50090220, 0x00000190},
+ {0x50090224, 0x00000200},
+ {0x50090228, 0x00000208},
+ {0x5009022c, 0x00000210},
+ {0x50090230, 0x00000280},
+ {0x50090234, 0x00000288},
+ {0x50090238, 0x00000304},
+ {0x5009023c, 0x0000030C},
+ {0x50090240, 0x00000314},
+ {0x50090244, 0x00000384},
+ {0x50090248, 0x0000038C},
+ {0x5009024c, 0x00000394},
+ {0x50090250, 0x00000404},
+ {0x50090254, 0x0000040C},
+ {0x50090258, 0x00000414},
+ {0x5009025c, 0x00000484},
+ {0x50090260, 0x0000048C},
+ {0x50090264, 0x00000500},
+ {0x50090268, 0x00000508},
+ {0x5009026c, 0x00000510},
+ {0x50090270, 0x00000580},
+ {0x50090274, 0x00000588},
+ {0x50090278, 0x00000590},
+ {0x5009027c, 0x00000600},
+ {0x50090280, 0x00000288},
+ {0x50090284, 0x00000290},
+ {0x50090288, 0x00000304},
+ {0x5009028c, 0x0000030C},
+ {0x50090290, 0x00000314},
+ {0x50090294, 0x00000384},
+ {0x50090298, 0x0000038C},
+ {0x5009029c, 0x00000394},
+ {0x500902a0, 0x00000404},
+ {0x500902a4, 0x0000040C},
+ {0x500902a8, 0x00000414},
+ {0x500902ac, 0x00000484},
+ {0x500902b0, 0x0000048C},
+ {0x500902b4, 0x00000500},
+ {0x500902b8, 0x00000508},
+ {0x500902bc, 0x00000510},
+ {0x500902c0, 0x00000580},
+ {0x500902c4, 0x00000588},
+ {0x500902c8, 0x00000590},
+ {0x500902cc, 0x00000600},
+ {0x500902d0, 0x00000608},
+ {0x500902d4, 0x00000610},
+ {0x500902d8, 0x00000680},
+ {0x500902dc, 0x00000688},
+ {0x500902e0, 0x00000690},
+ {0x500902e4, 0x00000700},
+ {0x500902e8, 0x00000708},
+ {0x500902ec, 0x00000710},
+ {0x500902f0, 0x00000780},
+ {0x500902f4, 0x00000780},
+ {0x500902f8, 0x00000780},
+ {0x500902fc, 0x00000780},
+ {0x50090300, 0x00000500},
+ {0x50090304, 0x00000508},
+ {0x50090308, 0x00000510},
+ {0x5009030c, 0x00000580},
+ {0x50090310, 0x00000588},
+ {0x50090314, 0x00000590},
+ {0x50090318, 0x00000600},
+ {0x5009031c, 0x00000608},
+ {0x50090320, 0x00000610},
+ {0x50090324, 0x00000680},
+ {0x50090328, 0x00000688},
+ {0x5009032c, 0x00000690},
+ {0x50090330, 0x00000700},
+ {0x50090334, 0x00000708},
+ {0x50090338, 0x00000710},
+ {0x5009033c, 0x00000780},
+ {0x50090340, 0x00000780},
+ {0x50090344, 0x00000780},
+ {0x50090348, 0x00000780},
+ {0x5009034c, 0x00000780},
+ {0x50090350, 0x00000780},
+ {0x50090354, 0x00000780},
+ {0x50090358, 0x00000780},
+ {0x5009035c, 0x00000780},
+ {0x50090360, 0x00000780},
+ {0x50090364, 0x00000780},
+ {0x50090368, 0x00000780},
+ {0x5009036c, 0x00000780},
+ {0x50090370, 0x00000780},
+ {0x50090374, 0x00000780},
+ {0x50090378, 0x00000780},
+ {0x5009037c, 0x00000780},
+ {0x50090054, 0x00000000},
+};
+
+static const u32 wifi_core_AM_PM_data_32_91e[][2] = {
+ {0x50090054, 0x00000000},
+ {0x50090068, 0xEB3FF7FF},
+ {0x50090070, 0x1403DBFF},
+ {0x500900B0, 0x00400000},
+ //item0:theta0=7_B=0_r0=2_for_verE
+ {0x50090090, 0x00000000},
+ {0x50090094, 0x00A01401},
+ {0x50090098, 0x02907412},
+ {0x5009009C, 0x05D12438},
+ {0x500900A0, 0x0A522872},
+ {0x500900A4, 0xFFF380C1},
+ //item0:G0=-3.5_r0=2.5_for_verE
+ {0x50090078, 0x02B05400},
+ {0x5009007C, 0x06D15840},
+ {0x50090080, 0x0B927885},
+ {0x50090084, 0x11A3DCD7},
+ {0x50090088, 0x1975A540},
+ {0x5009008C, 0xFc07fdc9},
+ {0x500900A8, 0x9c400180},
+
+};
+const u32 wifi_phy_timeout_cfg_91e[][2] =
+{
+ {0x50000634, 0x00001100},
+ {0x50000584, 0x00007BF8},
+};
+
+#endif
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_91f.h b/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_91f.h
new file mode 100755
index 00000000..1c88d3e5
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_sdio_patch_91f.h
@@ -0,0 +1,583 @@
+#ifndef __WLAN_SDIO_PATCH_91_F_H__
+#define __WLAN_SDIO_PATCH_91_F_H__
+
+static const u32 wifi_core_patch_data_32_91f[][2] = {
+ // add for pta
+ {0x50000828,0x00100FFD},
+ {0x50000810,0xFFFF0F0F},
+ {0x50000814,0xFFFF0F0F},
+ {0x50000818,0x00FF000F},
+ {0x5000081C,0xFF000F00},
+ {0x50000820,0xFF000F00},
+ {0x50000824,0x0000F0F0},
+ {0x50090044,0xE6AD6CB0},//mode
+ {0x50090040,0xBA9D5EC4},//agc value
+#if 0
+ // add for pta
+ {0x0010FFFC, 0x20140304},
+ {0x00110000, 0xEA03FA67},
+ {0x00110004, 0xE51FF004},
+ {0x00110008, 0x000116B4},
+ {0x0011000C, 0xEA03C0BF},
+ {0x00110010, 0xE200007F},
+ {0x00110014, 0xE3500028},
+ {0x00110018, 0x1A00000B},
+ {0x0011001C, 0xE1A01801},
+ {0x00110020, 0xE1A01821},
+ {0x00110024, 0xE59F0024},
+ {0x00110028, 0xE1510000},
+ {0x0011002C, 0x059F1024},
+ {0x00110030, 0x03A00028},
+ {0x00110034, 0x059FF028},
+ {0x00110038, 0xE59F0014},
+ {0x0011003C, 0xE1510000},
+ {0x00110040, 0x059F1014},
+ {0x00110044, 0x03A00028},
+ {0x00110048, 0x059FF014},
+ {0x0011004C, 0xE59FF00C},
+ {0x00110050, 0x00001F20},
+ {0x00110054, 0x00001320},
+ {0x00110058, 0x00004F20},
+ {0x0011005C, 0x00004320},
+ {0x00110060, 0x0001FD10},
+ {0x00110064, 0x0001FD18},
+ {0x00110068, 0xEA0410ED},
+ {0x0011006C, 0xE5940004},
+ {0x00110070, 0xE3800850},
+ {0x00110074, 0xE5840004},
+ {0x00110078, 0xE3A00D44},
+ {0x0011007C, 0xE5840634},
+ {0x00110080, 0xE59F0004},
+ {0x00110084, 0xE5840584},
+ {0x00110088, 0xE59FF000},
+ {0x0011008C, 0x00007BF8},
+ {0x00110090, 0x0000BCB4},
+ {0x00110094, 0xEA040607},
+ {0x00110098, 0xE59F2020},
+ {0x0011009C, 0xE1D210B0},
+ {0x001100A0, 0xE1A00000},
+ {0x001100A4, 0xE1A00000},
+ {0x001100A8, 0xE59F200C},
+ {0x001100AC, 0xE3A01010},
+ {0x001100B0, 0xE5C21000},
+ {0x001100B4, 0xE3560000},
+ {0x001100B8, 0xE59FF004},
+ {0x001100BC, 0x50300038},
+ {0x001100C0, 0x00106B1C},
+ {0x001100C4, 0x0000E878},
+ {0x001100C8, 0xEA03FE7A},
+ {0x001100CC, 0xE5CD0018},
+ {0x001100D0, 0xE51F0018},
+ {0x001100D4, 0xE1D010B0},
+ {0x001100D8, 0xE1A00000},
+ {0x001100DC, 0xE1A00000},
+ {0x001100E0, 0xE51F002C},
+ {0x001100E4, 0xE3A01010},
+ {0x001100E8, 0xE5C01000},
+ {0x001100EC, 0xE59FF000},
+ {0x001100F0, 0x50060000},
+ {0x001100F4, 0x000106E0},
+ {0x001100F8, 0xEA042EFA},
+ {0x001100FC, 0xE59F0028},
+ {0x00110100, 0xE5840584},
+ {0x00110104, 0xE59F0024},
+ {0x00110108, 0xE59F1024},
+ {0x0011010C, 0xE5810000},
+ {0x00110110, 0xE59F1020},
+ {0x00110114, 0xE3A00003},
+ {0x00110118, 0xE5810000},
+ {0x0011011C, 0xE59F001C},
+ {0x00110120, 0xE59F1014},
+ {0x00110124, 0xE5810000},
+ {0x00110128, 0xE59FF014},
+ {0x0011012C, 0x0000FFFB},
+ {0x00110130, 0x00000030},
+ {0x00110134, 0x5000020C},
+ {0x00110138, 0x50000200},
+ {0x0011013C, 0x30000014},
+ {0x00110140, 0x25801B0A},
+ {0x00110144, 0x00004510},
+ {0x00110148, 0xEA041E5A},
+ {0x0011014C, 0xE59F103C},
+ {0x00110150, 0x03A00000},
+ {0x00110154, 0x05810000},
+ {0x00110158, 0x0A000007},
+ {0x0011015C, 0xE5910000},
+ {0x00110160, 0xE2800001},
+ {0x00110164, 0xE3500002},
+ {0x00110168, 0x35810000},
+ {0x0011016C, 0x3A000004},
+ {0x00110170, 0xE3A00000},
+ {0x00110174, 0xE5810000},
+ {0x00110178, 0xEAFFFFFF},
+ {0x0011017C, 0xE51FF004},
+ {0x00110180, 0x000087E0},
+ {0x00110184, 0xE51FF004},
+ {0x00110188, 0x00008824},
+ {0x0011018C, 0x00000000},
+ {0x00110190, 0x0011018C},
+ {0x00110194, 0xEA0437F6},
+ {0x00110198, 0xE1A000A0},
+ {0x0011019C, 0xE51FF004},
+ {0x001101A0, 0x000021BC},
+ {0x001101A4, 0xEA0437E3},
+ {0x001101A8, 0xE3A00002},
+ {0x001101AC, 0xE51FF004},
+ {0x001101B0, 0x00002218},
+ {0x001101B4, 0xEA0418DC},
+ {0x001101B8, 0xE3A03000},
+ {0x001101BC, 0xE5D11000},
+ {0x001101C0, 0xE5802010},
+ {0x001101C4, 0xE5803044},
+ {0x001101C8, 0xE3510001},
+ {0x001101CC, 0x13A01003},
+ {0x001101D0, 0x03A01009},
+ {0x001101D4, 0xE5A01014},
+ {0x001101D8, 0xE5803034},
+ {0x001101DC, 0xE51FF004},
+ {0x001101E0, 0x00009E64},
+ {0x001101E4, 0xEA042DED},
+ {0x001101E8, 0xE59F1010},
+ {0x001101EC, 0xE3A00007},
+ {0x001101F0, 0xEB000001},
+ {0x001101F4, 0xE3E00006},
+ {0x001101F8, 0xE59FF008},
+ {0x001101FC, 0xE59FF000},
+ {0x00110200, 0x00000E2E},
+ {0x00110204, 0x0001FD08},
+ {0x00110208, 0x00004A30},
+ {0x0011020C, 0xEA042DEC},
+ {0x00110210, 0xE59F1080},
+ {0x00110214, 0xE3A00007},
+ {0x00110218, 0xEBFFFFF7},
+ {0x0011021C, 0xE3A00007},
+ {0x00110220, 0xE59F1078},
+ {0x00110224, 0xEB00001A},
+ {0x00110228, 0xE59F1070},
+ {0x0011022C, 0xE5910000},
+ {0x00110230, 0xE3100C80},
+ {0x00110234, 0x1A000006},
+ {0x00110238, 0xE59F1068},
+ {0x0011023C, 0xE3A00000},
+ {0x00110240, 0xE5810000},
+ {0x00110244, 0xE51F104C},
+ {0x00110248, 0xE3A00007},
+ {0x0011024C, 0xEBFFFFEA},
+ {0x00110250, 0xEAFFFFEE},
+ {0x00110254, 0xE59F104C},
+ {0x00110258, 0xE5910000},
+ {0x0011025C, 0xE2800001},
+ {0x00110260, 0xE5810000},
+ {0x00110264, 0xE3500010},
+ {0x00110268, 0xBAFFFFEB},
+ {0x0011026C, 0xE59F103C},
+ {0x00110270, 0xE3A00003},
+ {0x00110274, 0xEBFFFFE0},
+ {0x00110278, 0xE59F1034},
+ {0x0011027C, 0xE3A00003},
+ {0x00110280, 0xEBFFFFDD},
+ {0x00110284, 0xE3A00000},
+ {0x00110288, 0xE5810000},
+ {0x0011028C, 0xE51F1238},
+ {0x00110290, 0xE59FF020},
+ {0x00110294, 0xE59FF010},
+ {0x00110298, 0x0000082E},
+ {0x0011029C, 0x00000000},
+ {0x001102A0, 0x0011029C},
+ {0x001102A4, 0x00000000},
+ {0x001102A8, 0x001102A4},
+ {0x001102AC, 0x00013750},
+ {0x001102B0, 0x00002627},
+ {0x001102B4, 0x00000627},
+ {0x001102B8, 0x00004A5C},
+ {0x001102BC, 0xEA042F5C},
+ {0x001102C0, 0xE51F10C8},
+ {0x001102C4, 0xE3A00007},
+ {0x001102C8, 0xEBFFFFCB},
+ {0x001102CC, 0xE3E00006},
+ {0x001102D0, 0xE51FF004},
+ {0x001102D4, 0x0000454C},
+ {0x001102D8, 0xEA042F59},
+ {0x001102DC, 0xE51F104C},
+ {0x001102E0, 0xE3A00007},
+ {0x001102E4, 0xEBFFFFC4},
+ {0x001102E8, 0xE3A00007},
+ {0x001102EC, 0xE51F1054},
+ {0x001102F0, 0xEBFFFFE7},
+ {0x001102F4, 0xE51F105C},
+ {0x001102F8, 0xE5910000},
+ {0x001102FC, 0xE3100C80},
+ {0x00110300, 0x1A000006},
+ {0x00110304, 0xE51F1064},
+ {0x00110308, 0xE3A00000},
+ {0x0011030C, 0xE5810000},
+ {0x00110310, 0xE51F1118},
+ {0x00110314, 0xE3A00007},
+ {0x00110318, 0xEBFFFFB7},
+ {0x0011031C, 0xEAFFFFEE},
+ {0x00110320, 0xE51F1080},
+ {0x00110324, 0xE5910000},
+ {0x00110328, 0xE2800001},
+ {0x0011032C, 0xE5810000},
+ {0x00110330, 0xE3500010},
+ {0x00110334, 0xBAFFFFEB},
+ {0x00110338, 0xE51F1090},
+ {0x0011033C, 0xE3A00003},
+ {0x00110340, 0xEBFFFFAD},
+ {0x00110344, 0xE51F1098},
+ {0x00110348, 0xE3A00003},
+ {0x0011034C, 0xEBFFFFAA},
+ {0x00110350, 0xE3A00000},
+ {0x00110354, 0xE5810000},
+ {0x00110358, 0xE51F1304},
+ {0x0011035C, 0xE51FF004},
+ {0x00110360, 0x00004574},
+ {0x20040004, 0x00011660},
+ {0x20040024, 0x00110000},
+ {0x20040008, 0x0001FD0C},
+ {0x20040028, 0x0011000C},
+ {0x2004000C, 0x0000BCB0},
+ {0x2004002C, 0x00110068},
+ {0x20040010, 0x0000E874},
+ {0x20040030, 0x00110094},
+ {0x20040014, 0x000106DC},
+ {0x20040034, 0x001100C8},
+ {0x20040018, 0x0000450C},
+ {0x20040038, 0x001100F8},
+ {0x2004001C, 0x000087DC},
+ {0x2004003C, 0x00110148},
+ {0x20040020, 0x000021B8},
+ {0x20040040, 0x00110194},
+ {0x20040100, 0x00002214},
+ {0x20040120, 0x001101A4},
+ {0x20040104, 0x00009E40},
+ {0x20040124, 0x001101B4},
+ {0x20040108, 0x00004A2C},
+ {0x20040128, 0x001101E4},
+ {0x2004010C, 0x00004A58},
+ {0x2004012C, 0x0011020C},
+ {0x20040110, 0x00004548},
+ {0x20040130, 0x001102BC},
+ {0x20040114, 0x00004570},
+ {0x20040134, 0x001102D8},
+ {0x20040000, 0x00003FFF},
+#endif
+};
+#define SET_CHANNEL_MEM_TABLE_BASE_91F 0x0010D7B0
+#define SET_CHANNEL_RF_TABLE_BASE_91F 0x0010DA50
+static const u32 wifi_clock_switch_91f[][2] = {
+
+ //channel 1
+ {SET_CHANNEL_MEM_TABLE_BASE_91F, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x04, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x08, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x0C, 0x2222CFCF},
+
+ //channel 2
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x30, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x34, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x38, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x3C, 0x2222CFCF},
+
+ //channel 3
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x60, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x64, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x68, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x6C, 0x2222CFCF},
+
+ //channel 4
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x90, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x94, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x98, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x9C, 0x2222CFCF},
+
+ //channel 5
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0xC0, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0xC4, 0x304199C4},//diffrent with 91e
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0xC8, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0xCC, 0x2222CFCF},
+
+ //channel 6
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0xF0, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0xF4, 0x204199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0xF8, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0xFC, 0x2222CFCF},
+
+ //channel 7
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x120, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x124, 0x204199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x128, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x12C, 0x2222CFCF},
+
+ //channel 8
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x150, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x154, 0x204199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x158, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x15C, 0x2222CFCF},
+
+ //channel 9
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x180, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x184, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x188, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x18C, 0x2222CFCF},
+
+ //channel 10
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x1B0, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x1B4, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x1B8, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x1BC, 0x2222CFCF},
+
+ //channel 11
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x1E0, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x1E4, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x1E8, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x1EC, 0x2222CFCF},
+
+ //channel 12
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x210, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x214, 0x604199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x218, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x21C, 0x2222CFCF},
+
+ //channel 13
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x240, 0x50090048},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x244, 0x304199C4},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x248, 0x50000654},
+ {SET_CHANNEL_MEM_TABLE_BASE_91F + 0x24C, 0x2222CFCF},
+
+ //channel 1
+ {SET_CHANNEL_RF_TABLE_BASE_91F, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x04, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x08, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x0C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x10, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x14, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x18, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x1C, 0x00000000},
+
+ //channel 2
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x40, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x44, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x48, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x4C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x50, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x54, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x58, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x5C, 0x00000000},
+
+ //channel 3
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x80, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x84, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x88, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x8C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x90, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x94, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x98, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x9C, 0x00000000},
+
+ //channel 4
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0xC0, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0xC4, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0xC8, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0xCC, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0xD0, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0xD4, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0xD8, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0xDC, 0x00000000},
+
+ //channel 5
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x100, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x104, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x108, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x10C, 0x00000B08},//diff with 91e
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x110, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x114, 0x0000AA12},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x118, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x11C, 0x00000000},
+
+ //channel 6
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x140, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x144, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x148, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x14C, 0x00000908},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x150, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x154, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x158, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x15C, 0x00000000},
+
+ //channel 7
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x180, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x184, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x188, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x18C, 0x00000908},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x190, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x194, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x198, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x19C, 0x00000000},
+
+ //channel 8
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x1C0, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x1C4, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x1C8, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x1CC, 0x00000908},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x1D0, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x1D4, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x1D8, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x1DC, 0x00000000},
+
+ //channel 9
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x200, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x204, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x208, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x20C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x210, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x214, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x218, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x21C, 0x00000000},
+
+ //channel 10
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x240, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x244, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x248, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x24C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x250, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x254, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x258, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x25C, 0x00000000},
+
+ //channel 11
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x280, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x284, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x288, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x28C, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x290, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x294, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x298, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x29C, 0x00000000},
+
+ //channel 12
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x2C0, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x2C4, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x2C8, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x2CC, 0x00000808},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x2D0, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x2D4, 0x0000AA00},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x2D8, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x2DC, 0x00000000},
+
+ //channel 13
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x300, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x304, 0x00000001},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x308, 0x00000038},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x30C, 0x00000B08},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x310, 0x0000003E},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x314, 0x0000AA12},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x318, 0x0000003F},
+ {SET_CHANNEL_RF_TABLE_BASE_91F + 0x31C, 0x00000000},
+
+};
+
+static const u8 wifi_core_patch_data_91f_8[][2] = {
+ {0x28, 0x1a},
+ {0x29, 0x0d},
+ {0x25, 0x00},
+ {0x08, 0x43},
+ //rx patch
+ {0x26, 0x35},
+ {0x3e, 0x64},
+ {0x3f, 0x00},
+ {0x45, 0x75},
+ {0x46, 0x73},
+ {0x50, 0x58},
+ {0x30, 0xf6},
+
+ {0xA0, 0x7f},
+ {0x74, 0x01},
+ {0x75, 0x40},
+
+ {0x12, 0x04},
+ {0x1C, 0x2D},
+ {0x0D, 0x59},
+ {0x17, 0x75},
+ {0x74, 0xD4},
+ {0x75, 0x47},
+
+ {0x74, 0xFF},
+ {0x75, 0x4B},
+
+ {0x74, 0x3D},
+ {0x75, 0x4C},
+
+ {0x74, 0x01},
+ {0x75, 0x50},
+
+ {0x74, 0x99},
+ {0x75, 0x57},
+
+ {0x74, 0xFF},
+ {0x75, 0x5B},
+
+ {0x74, 0x33},
+ {0x75, 0x5D},
+
+ {0x74, 0xE4},
+ {0x75, 0x61},
+
+ {0x30, 0xF7},
+};
+
+static const u32 wifi_core_init_data_32_91f[][2] = {
+ {0x500002a8, 0x00000001},
+ {0x50000080, 0x0003FEF7},
+#if 0
+ {0x00100018, 0x000A3243}, // flow ctrl , WPS supported, proakis
+ {0x0010001C, 0xFFFF0001},
+#endif
+ {0x30010010, 0x00007DFF},
+
+ {0x50090060, 0x000001B4},
+ //item:rda5991_verE_wf_tx_pn9
+ {0x50090068, 0xEB3FF7FF},
+ {0x50090070, 0x1403DBFF},
+ {0x500900B0, 0x00400000},
+ {0x500900A8, 0xE0400048},
+ {0x5009008C, 0xF6700000},
+ //PHY:phy rx timeout enable
+#if 0
+ {0x0010216c, 0x50000634},
+ {0x00102170, 0x00001100},
+ {0x00102174, 0x50000584},
+ {0x00102178, 0x00007bf8},
+#endif
+};
+
+static const u32 wifi_core_AM_PM_data_32_91f[][2] = {
+ {0x50090054, 0x00000000},
+ {0x50090068, 0xEB3FF7FF},
+ {0x50090070, 0x1403DBFF},
+ {0x500900B0, 0x00400000},
+ //item0:theta0=7_B=0_r0=2_for_verE
+ {0x50090090, 0x00000000},
+ {0x50090094, 0x00A01401},
+ {0x50090098, 0x02907412},
+ {0x5009009C, 0x05D12438},
+ {0x500900A0, 0x0A522872},
+ {0x500900A4, 0xFFF380C1},
+ //item0:G0=-3.5_r0=2.5_for_verE
+ {0x50090078, 0x02B05400},
+ {0x5009007C, 0x06D15840},
+ {0x50090080, 0x0B927885},
+ {0x50090084, 0x11A3DCD7},
+ {0x50090088, 0x1975A540},
+ {0x5009008C, 0xFFF7FDC9},
+ {0x500900A8, 0x9C4001A0},
+
+};
+const u32 wifi_phy_timeout_cfg_91f[][2] =
+{
+ {0x50000634, 0x00001100},
+ {0x50000584, 0x00007BF8},
+};
+
+#endif
+
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_wext.c b/drivers/net/wireless/rda/rda_wlan/wlan_wext.c
new file mode 100755
index 00000000..cd32c542
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_wext.c
@@ -0,0 +1,1870 @@
+#include "wlan_includes.h"
+
+static int wlan_get_name(struct net_device *dev, struct iw_request_info *info,
+ char *cwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ /* We could add support for 802.11n here as needed. Jean II */
+ snprintf(cwrq, IFNAMSIZ, "IEEE 802.11b/g");
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_get_freq(struct net_device *dev, struct iw_request_info *info,
+ struct iw_freq *fwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ fwrq->m = (long)2437 *100000;
+ fwrq->e = 1;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_get_wap(struct net_device *dev, struct iw_request_info *info,
+ struct sockaddr *awrq, char *extra)
+{
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ if (priv->connect_status == MAC_CONNECTED) {
+ memcpy(awrq->sa_data, priv->curbssparams.bssid, ETH_ALEN);
+ } else {
+ memset(awrq->sa_data, 0, ETH_ALEN);
+ }
+ awrq->sa_family = ARPHRD_ETHER;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_set_nick(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_get_nick(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *vwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_get_rts(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *vwrq, char *extra)
+{
+ int ret = 0;
+ u16 val = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ val = 600;
+
+ vwrq->value = val;
+ vwrq->disabled = val > WLAN_RTS_MAX_VALUE; /* min rts value is 0 */
+ vwrq->fixed = 1;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return ret;
+}
+
+static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *vwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_get_frag(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *vwrq, char *extra)
+{
+ int ret = 0;
+ u16 val = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ val = 1460;
+
+ vwrq->value = val;
+ vwrq->disabled = ((val < WLAN_FRAG_MIN_VALUE)
+ || (val > WLAN_FRAG_MAX_VALUE));
+ vwrq->fixed = 1;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return ret;
+}
+
+static int wlan_get_mode(struct net_device *dev,
+ struct iw_request_info *info, u32 * uwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ *uwrq = IW_MODE_INFRA;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_get_txpow(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ vwrq->value = 20; // in dbm
+ vwrq->fixed = 1;
+ vwrq->disabled = 0;
+ vwrq->flags = IW_TXPOW_DBM;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *vwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *vwrq, char *extra)
+{
+ int ret = 0;
+ u16 val = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ vwrq->disabled = 0;
+
+ if (vwrq->flags & IW_RETRY_LONG) {
+ val = 7;
+
+ /* Subtract 1 to convert try count to retry count */
+ vwrq->value = val - 1;
+ vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
+ } else {
+ val = 6;
+
+ /* Subtract 1 to convert try count to retry count */
+ vwrq->value = val - 1;
+ vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return ret;
+}
+
+/**
+ * 802.11b/g supported bitrates (in 500Kb/s units)
+ */
+u8 wlan_bg_rates[MAX_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18,
+ 0x24, 0x30, 0x48, 0x60, 0x6c, 0x00, 0x00
+};
+
+u16 wlan_nr_chan = 11;
+
+/**
+ * @brief Get Range Info
+ *
+ * @param dev A pointer to net_device structure
+ * @param info A pointer to iw_request_info structure
+ * @param vwrq A pointer to iw_param structure
+ * @param extra A pointer to extra data buf
+ * @return 0 --success, otherwise fail
+ */
+static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ struct iw_range *range = (struct iw_range *)extra;
+ int i;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ dwrq->length = sizeof(struct iw_range);
+ memset(range, 0, sizeof(struct iw_range));
+
+ range->min_nwid = 0;
+ range->max_nwid = 0;
+
+ range->num_bitrates = sizeof(wlan_bg_rates);
+ for (i = 0; i < range->num_bitrates; i++)
+ range->bitrate[i] = wlan_bg_rates[i] * 500000;
+ range->num_bitrates = i;
+
+ range->num_frequency = 0;
+
+ range->scan_capa = IW_SCAN_CAPA_ESSID;
+
+ for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
+ && (i < wlan_nr_chan); i++) {
+ range->freq[range->num_frequency].i = (long)(i + 1);
+ range->freq[range->num_frequency].m =
+ (long)((2412 + 5 * i) * 100000);
+ range->freq[range->num_frequency].e = 1;
+ range->num_frequency++;
+ }
+
+ range->num_channels = range->num_frequency;
+
+ /*
+ * Set an indication of the max TCP throughput in bit/s that we can
+ * expect using this interface
+ */
+ range->throughput = 5000 * 1000;
+
+ range->min_rts = WLAN_RTS_MIN_VALUE;
+ range->max_rts = WLAN_RTS_MAX_VALUE;
+ range->min_frag = WLAN_FRAG_MIN_VALUE;
+ range->max_frag = WLAN_FRAG_MAX_VALUE;
+
+ range->encoding_size[0] = 5;
+ range->encoding_size[1] = 13;
+ range->num_encoding_sizes = 2;
+ range->max_encoding_tokens = 4;
+
+ /*
+ * Right now we support only "iwconfig ethX power on|off"
+ */
+ range->pm_capa = IW_POWER_ON;
+
+ /*
+ * Minimum version we recommend
+ */
+ range->we_version_source = 15;
+
+ /*
+ * Version we are compiled with
+ */
+ range->we_version_compiled = WIRELESS_EXT;
+
+ range->retry_capa = IW_RETRY_LIMIT;
+ range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+
+ range->min_retry = 0;
+ range->max_retry = 14;
+
+ /*
+ * Set the qual, level and noise range values
+ */
+ range->max_qual.qual = 100;
+ range->max_qual.level = 0;
+ range->max_qual.noise = 0;
+ range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+
+ range->avg_qual.qual = 70;
+ /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
+ range->avg_qual.level = 0;
+ range->avg_qual.noise = 0;
+ range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+
+ range->sensitivity = 0;
+
+ /* Setup the supported power level ranges */
+ memset(range->txpower, 0, sizeof(range->txpower));
+ range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE;
+ range->txpower[0] = 0;
+ range->txpower[1] = 20;
+ range->num_txpower = 2;
+
+ range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
+ IW_EVENT_CAPA_MASK(SIOCGIWAP) |
+ IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
+ range->event_capa[1] = IW_EVENT_CAPA_K_1;
+
+ range->enc_capa = IW_ENC_CAPA_WPA
+ | IW_ENC_CAPA_WPA2
+ | IW_ENC_CAPA_CIPHER_TKIP
+ | IW_ENC_CAPA_CIPHER_CCMP;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_set_power(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *vwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_get_power(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *vwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ vwrq->value = 0;
+ vwrq->flags = 0;
+ vwrq->disabled = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_update_bss_stats(wlan_private * priv)
+{
+ int ret = -1;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ memcpy(priv->curbssparams.ssid,
+ priv->assoc_ssid, sizeof(priv->curbssparams.ssid));
+
+ if (priv->scan_running == WLAN_SCAN_RUNNING)
+ return 0;
+
+ ret = wlan_get_bssid(priv, priv->curbssparams.bssid);
+ if (ret) {
+ WLAN_ERRP("wlan_get_bssid, ret = %d\n", ret);
+ goto out;
+ }
+
+ ret = wlan_get_rssi(priv, &priv->curbssparams.rssi);
+ if (ret) {
+ WLAN_ERRP("wlan_get_rssi, ret = %d\n", ret);
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<< ch = %d rssi = %d\n",
+ __func__, priv->curbssparams.channel,
+ priv->curbssparams.rssi);
+
+out:
+ return ret;
+}
+
+static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
+{
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+ int stats_valid = 0;
+ u8 snr;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ if (priv->connect_status != MAC_CONNECTED)
+ goto out;
+
+ wlan_update_bss_stats(priv);
+
+ priv->wstats.miss.beacon = 0;
+ priv->wstats.discard.retries = 0;
+ priv->wstats.qual.level = 0x100 + (s8)priv->curbssparams.rssi;
+
+ snr = priv->wstats.qual.level - WLAN_NF_DEFAULT_SCAN_VALUE;
+ priv->wstats.qual.qual =
+ (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - snr) *
+ (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - snr))) /
+ (RSSI_DIFF * RSSI_DIFF);
+ if (priv->wstats.qual.qual > 100)
+ priv->wstats.qual.qual = 100;
+ priv->wstats.qual.noise = WLAN_NF_DEFAULT_SCAN_VALUE;
+ priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+
+ stats_valid = 1;
+
+out:
+ if (!stats_valid) {
+ priv->wstats.miss.beacon = 0;
+ priv->wstats.discard.retries = 0;
+ priv->wstats.qual.qual = 0;
+ priv->wstats.qual.level = 0;
+ priv->wstats.qual.noise = 0;
+ priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
+ priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID |
+ IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return &priv->wstats;
+}
+
+static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
+ struct iw_freq *fwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *vwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_get_rate(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *vwrq, char *extra)
+{
+ int ret = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+ vwrq->fixed = 0;
+ vwrq->value = 54*1000;
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return ret;
+}
+
+static int wlan_set_mode(struct net_device *dev,
+ struct iw_request_info *info, u32 * uwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+/**
+ * @brief Get Encryption key
+ *
+ * @param dev A pointer to net_device structure
+ * @param info A pointer to iw_request_info structure
+ * @param vwrq A pointer to iw_param structure
+ * @param extra A pointer to extra data buf
+ * @return 0 --success, otherwise fail
+ */
+static int wlan_get_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq, u8 * extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+/**
+ * @brief Set Encryption key
+ *
+ * @param dev A pointer to net_device structure
+ * @param info A pointer to iw_request_info structure
+ * @param vwrq A pointer to iw_param structure
+ * @param extra A pointer to extra data buf
+ * @return 0 --success, otherwise fail
+ */
+static int wlan_set_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+/**
+ * @brief Set Encryption key (internal)
+ *
+ * @param priv A pointer to private card structure
+ * @param key_material A pointer to key material
+ * @param key_length length of key material
+ * @param index key index to set
+ * @param set_tx_key Force set TX key (1 = yes, 0 = no)
+ * @return 0 --success, otherwise fail
+ */
+static int copy_wep_key(wlan_private * priv,
+ const char *key_material,
+ u16 key_length, u16 index, int set_tx_key)
+{
+ int ret = 0;
+ struct enc_key *pkey;
+
+ /* Paranoid validation of key index */
+ if (index > 3) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* validate max key length */
+ if (key_length > KEY_LEN_WEP_104) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (key_length == KEY_LEN_WEP_40) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "WEP40 : %02x%02x%02x%02x%02x\n",
+ key_material[0], key_material[1], key_material[2],
+ key_material[3], key_material[4]);
+ } else if (key_length == KEY_LEN_WEP_104) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "WEP104 : %02x%02x%02x%02x%02x"
+ " %02x%02x%02x%02x%02x"
+ " %02x%02x%02x\n",
+ key_material[0], key_material[1], key_material[2],
+ key_material[3], key_material[4], key_material[5],
+ key_material[6], key_material[7], key_material[8],
+ key_material[9], key_material[10], key_material[11],
+ key_material[12]);
+ } else {
+ WLAN_ERRP("Error in WEP Key length %d\n", key_length);
+ }
+
+ pkey = &priv->wep_keys[index];
+
+ if (key_length > 0) {
+ memset(pkey, 0, sizeof(struct enc_key));
+ pkey->type = KEY_TYPE_ID_WEP;
+
+ /* Standardize the key length */
+ pkey->len = (key_length > KEY_LEN_WEP_40) ?
+ KEY_LEN_WEP_104 : KEY_LEN_WEP_40;
+ memcpy(pkey->key, key_material, key_length);
+ }
+
+ if (set_tx_key) {
+ /* Ensure the chosen key is valid */
+ if (!pkey->len) {
+ WLAN_ERRP("key not set, so cannot enable it\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ priv->wep_tx_keyidx = index;
+ }
+
+ priv->secinfo.wep_enabled = 1;
+
+out:
+ return ret;
+}
+
+static int validate_key_index(u16 def_index, u16 raw_index,
+ u16 * out_index, u16 * is_default)
+{
+ if (!out_index || !is_default)
+ return -EINVAL;
+
+ /* Verify index if present, otherwise use default TX key index */
+ if (raw_index > 0) {
+ if (raw_index > 4)
+ return -EINVAL;
+ *out_index = raw_index - 1;
+ } else {
+ *out_index = def_index;
+ *is_default = 1;
+ }
+ return 0;
+}
+
+static void disable_wep(wlan_private * priv)
+{
+ int i;
+
+ /* Set Open System auth mode */
+ priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
+
+ /* Clear WEP keys and mark WEP as disabled */
+ priv->secinfo.wep_enabled = 0;
+ for (i = 0; i < 4; i++)
+ priv->wep_keys[i].len = 0;
+}
+
+static void disable_wpa(wlan_private * priv)
+{
+ memset(&priv->wpa_mcast_key, 0, sizeof(struct enc_key));
+ priv->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST;
+
+ memset(&priv->wpa_unicast_key, 0, sizeof(struct enc_key));
+ priv->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST;
+
+ priv->secinfo.WPAenabled = 0;
+ priv->secinfo.WPA2enabled = 0;
+ priv->secinfo.cipther_type = 0;
+ priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
+}
+
+/**
+ * @brief Get Extended Encryption key (WPA/802.1x and WEP)
+ *
+ * @param dev A pointer to net_device structure
+ * @param info A pointer to iw_request_info structure
+ * @param vwrq A pointer to iw_param structure
+ * @param extra A pointer to extra data buf
+ * @return 0 on success, otherwise failure
+ */
+static int wlan_get_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+ int ret = -EINVAL;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ int index, max_key_len;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ max_key_len = dwrq->length - sizeof(*ext);
+ if (max_key_len < 0)
+ goto out;
+
+ index = dwrq->flags & IW_ENCODE_INDEX;
+ if (index) {
+ if (index < 1 || index > 4)
+ goto out;
+ index--;
+ } else {
+ index = priv->wep_tx_keyidx;
+ }
+
+ if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
+ ext->alg != IW_ENCODE_ALG_WEP) {
+ if (index != 0)
+ goto out;
+ }
+
+ dwrq->flags = index + 1;
+ memset(ext, 0, sizeof(*ext));
+
+ if (!priv->secinfo.wep_enabled
+ && !priv->secinfo.WPAenabled
+ && !priv->secinfo.WPA2enabled) {
+ ext->alg = IW_ENCODE_ALG_NONE;
+ ext->key_len = 0;
+ dwrq->flags |= IW_ENCODE_DISABLED;
+ } else {
+ u8 *key = NULL;
+
+ if (priv->secinfo.wep_enabled
+ && !priv->secinfo.WPAenabled
+ && !priv->secinfo.WPA2enabled) {
+ /* WEP */
+ ext->alg = IW_ENCODE_ALG_WEP;
+ ext->key_len = priv->wep_keys[index].len;
+ key = &priv->wep_keys[index].key[0];
+ } else if (!priv->secinfo.wep_enabled
+ && (priv->secinfo.WPAenabled ||
+ priv->secinfo.WPA2enabled)) {
+ /* WPA */
+ struct enc_key *pkey = NULL;
+
+ if (priv->wpa_mcast_key.len
+ && (priv->wpa_mcast_key.
+ flags & KEY_INFO_WPA_ENABLED))
+ pkey = &priv->wpa_mcast_key;
+ else if (priv->wpa_unicast_key.len
+ && (priv->wpa_unicast_key.
+ flags & KEY_INFO_WPA_ENABLED))
+ pkey = &priv->wpa_unicast_key;
+
+ if (pkey) {
+ if (pkey->type == KEY_TYPE_ID_AES) {
+ ext->alg = IW_ENCODE_ALG_CCMP;
+ } else {
+ ext->alg = IW_ENCODE_ALG_TKIP;
+ }
+ ext->key_len = pkey->len;
+ key = &pkey->key[0];
+ } else {
+ ext->alg = IW_ENCODE_ALG_TKIP;
+ ext->key_len = 0;
+ }
+ } else {
+ goto out;
+ }
+
+ if (ext->key_len > max_key_len) {
+ ret = -E2BIG;
+ goto out;
+ }
+
+ if (ext->key_len)
+ memcpy(ext->key, key, ext->key_len);
+ else
+ dwrq->flags |= IW_ENCODE_NOKEY;
+ dwrq->flags |= IW_ENCODE_ENABLED;
+ }
+ ret = 0;
+
+out:
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+/**
+ * @brief Set Encryption key Extended (WPA/802.1x and WEP)
+ *
+ * @param dev A pointer to net_device structure
+ * @param info A pointer to iw_request_info structure
+ * @param vwrq A pointer to iw_param structure
+ * @param extra A pointer to extra data buf
+ * @return 0 --success, otherwise fail
+ */
+static int wlan_set_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+ int ret = 0;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ int alg = ext->alg;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "NO SEC\n");
+
+ if (priv->imode != 3 && priv->imode != 5)
+ disable_wep(priv);
+ disable_wpa(priv);
+ } else if (alg == IW_ENCODE_ALG_WEP) {
+ u16 is_default = 0, index, set_tx_key = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "WEP, flags = 0x%04x\n", dwrq->flags);
+
+ ret = validate_key_index(priv->wep_tx_keyidx,
+ (dwrq->flags & IW_ENCODE_INDEX),
+ &index, &is_default);
+ if (ret)
+ goto out;
+
+ /* If WEP isn't enabled, or if there is no key data but a valid
+ * index, or if the set-TX-key flag was passed, set the TX key.
+ */
+ if (!priv->secinfo.wep_enabled
+ || (dwrq->length == 0 && !is_default)
+ || (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY))
+ set_tx_key = 1;
+
+ /* Copy key to driver */
+ ret = copy_wep_key(priv, ext->key, ext->key_len, index, set_tx_key);
+ if (ret)
+ goto out;
+
+ if (dwrq->flags & IW_ENCODE_RESTRICTED) {
+ priv->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
+ } else if (dwrq->flags & IW_ENCODE_OPEN) {
+ priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
+ }
+
+ } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
+ struct enc_key *pkey;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "TKIP or CCMP, flags = 0x%04x, alg = %d\n",
+ dwrq->flags, alg);
+
+ /* validate key length */
+ if (((alg == IW_ENCODE_ALG_TKIP)
+ && (ext->key_len != KEY_LEN_WPA_TKIP))
+ || ((alg == IW_ENCODE_ALG_CCMP)
+ && (ext->key_len != KEY_LEN_WPA_AES))) {
+ WLAN_ERRP("invalid size %d for key of alg, type %d\n",
+ ext->key_len, alg);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Copy key to driver */
+ if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+ pkey = &priv->wpa_mcast_key;
+ } else {
+ pkey = &priv->wpa_unicast_key;
+ }
+
+ memset(pkey, 0, sizeof(struct enc_key));
+ memcpy(pkey->key, ext->key, ext->key_len);
+ pkey->len = ext->key_len;
+ if (pkey->len)
+ pkey->flags |= KEY_INFO_WPA_ENABLED;
+
+ /* Do this after zeroing key structure */
+ if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+ pkey->flags |= KEY_INFO_WPA_MCAST;
+ } else {
+ pkey->flags |= KEY_INFO_WPA_UNICAST;
+ }
+
+ if (alg == IW_ENCODE_ALG_TKIP) {
+ pkey->type = KEY_TYPE_ID_TKIP;
+ if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+ && !(priv->imode & (BIT6))) {
+ WLAN_ERRP("imode [0x%x] not match with cipher alg TKIP\n",
+ priv->imode);
+ }
+ } else if (alg == IW_ENCODE_ALG_CCMP) {
+ pkey->type = KEY_TYPE_ID_AES;
+ if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+ && !(priv->imode & (BIT5))) {
+ WLAN_ERRP("imode [0x%x] not match with cipher alg CCMP\n",
+ priv->imode);
+ }
+ }
+
+ /* If WPA isn't enabled yet, do that now */
+ if (priv->secinfo.WPAenabled == 0
+ && priv->secinfo.WPA2enabled == 0) {
+ priv->secinfo.WPAenabled = 1;
+ priv->secinfo.WPA2enabled = 1;
+ }
+
+ /* Set Keys to MAC */
+ if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+ /* Set GTK */
+ ret = wlan_set_gtk(priv, (dwrq->flags & IW_ENCODE_INDEX) - 1, ext->tx_seq, IW_ENCODE_SEQ_MAX_SIZE, pkey->key, pkey->len);
+ if (ret)
+ goto out;
+ } else {
+ pkey->flags |= KEY_INFO_WPA_UNICAST;
+ /* Set PTK */
+ ret = wlan_set_ptk(priv, pkey->key, pkey->len);
+ if (ret)
+ goto out;
+ }
+
+ /* Only disable wep if necessary: can't waste time here. */
+ disable_wep(priv);
+ } else if (alg == IW_ENCODE_ALG_SM4) { //wapi
+ if (ext->key_len != 32)
+ goto out;
+
+ priv->is_wapi = 1;
+
+ /* Set Keys to MAC */
+ if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+ unsigned char tmp[8];
+ /* Set GTK */
+ /*
+ *
+ * need to toggle among 1, 2, 3
+ */
+ ret = wlan_set_gtk(priv, (dwrq->flags & IW_ENCODE_INDEX) - 1, tmp, IW_ENCODE_SEQ_MAX_SIZE, ext->key, ext->key_len);
+ if (ret)
+ goto out;
+ } else {
+ /* Set PTK */
+ ret = wlan_set_ptk(priv, ext->key, ext->key_len);
+ if (ret)
+ goto out;
+ }
+ }
+
+out:
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+/**
+ * @brief PMKSA cache operation (WPA/802.1x and WEP)
+ *
+ * @param dev A pointer to net_device structure
+ * @param info A pointer to iw_request_info structure
+ * @param vwrq A pointer to iw_param structure
+ * @param extra A pointer to extra data buf
+ * @return 0 on success, otherwise failure
+ */
+static int wlan_set_pmksa(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+static int wlan_set_genie(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+ int ret = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ if(priv->version == WLAN_VERSION_91_E|| priv->version == WLAN_VERSION_91_F){
+ unsigned char ie_len;
+ //huanglei add wps
+ ie_len = extra[1] + 2;
+ wlan_generic_set_str(priv, WID_GEN_ASSOC_IE, extra ,ie_len);
+ }
+
+ if (extra[0] == 0x44) //wapi ie
+ {
+ unsigned char ie_len = extra[1] + 2;
+ wlan_generic_set_str(priv, WID_WAPI_ASSOC_IE, extra, ie_len);
+ goto out;
+ }
+
+ if (dwrq->length > MAX_WPA_IE_LEN || (dwrq->length && extra == NULL)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (dwrq->length) {
+ memcpy(&priv->wpa_ie[0], extra, dwrq->length);
+ priv->wpa_ie_len = dwrq->length;
+ } else {
+ memset(&priv->wpa_ie[0], 0, sizeof(priv->wpa_ie));
+ priv->wpa_ie_len = 0;
+ }
+
+out:
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return ret;
+}
+
+static int wlan_get_genie(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+ int ret = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ if (priv->wpa_ie_len == 0) {
+ dwrq->length = 0;
+ goto out;
+ }
+
+ if (dwrq->length < priv->wpa_ie_len) {
+ ret = -E2BIG;
+ goto out;
+ }
+
+ dwrq->length = priv->wpa_ie_len;
+ memcpy(extra, &priv->wpa_ie[0], priv->wpa_ie_len);
+
+out:
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return ret;
+}
+
+static int wlan_set_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *dwrq, char *extra)
+{
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+ int ret = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "flags = 0x%04x, value = 0x%x\n", dwrq->flags, dwrq->value);
+
+ switch (dwrq->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_CIPHER_PAIRWISE:
+ if (dwrq->value & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "WEP Selected \n");
+ priv->secinfo.wep_enabled = 1;
+ if (dwrq->value & IW_AUTH_CIPHER_WEP104)
+ priv->secinfo.cipther_type |= IW_AUTH_CIPHER_WEP104;
+ else if (dwrq->value & IW_AUTH_CIPHER_WEP40)
+ priv->secinfo.cipther_type |= IW_AUTH_CIPHER_WEP40;
+ }
+ if (dwrq->value & IW_AUTH_CIPHER_TKIP) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "IW_AUTH_CIPHER_TKIP \n");
+ priv->secinfo.cipther_type |= IW_AUTH_CIPHER_TKIP;
+ }
+ if (dwrq->value & IW_AUTH_CIPHER_CCMP) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "IW_AUTH_CIPHER_CCMP \n");
+ priv->secinfo.cipther_type |= IW_AUTH_CIPHER_CCMP;
+ }
+ if (dwrq->value & IW_AUTH_CIPHER_NONE) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "OPEN System \n");
+ priv->secinfo.cipther_type = IW_AUTH_CIPHER_NONE;
+ }
+ break;
+
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_DROP_UNENCRYPTED:
+ /*
+ * wlan does not use these parameters
+ */
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "DO NOT USE\n");
+ break;
+
+ case IW_AUTH_KEY_MGMT:
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "KEY_MGMT, val = %d\n", dwrq->value);
+ priv->secinfo.key_mgmt = dwrq->value;
+ break;
+
+ case IW_AUTH_WPA_VERSION:
+ if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "WPA_VERSION, DISABLED\n");
+ priv->secinfo.WPAenabled = 0;
+ priv->secinfo.WPA2enabled = 0;
+ disable_wpa(priv);
+ }
+ if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "WPA_VERSION, WPA\n");
+ priv->secinfo.WPAenabled = 1;
+ priv->secinfo.wep_enabled = 0;
+ priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
+ }
+ if (dwrq->value & IW_AUTH_WPA_VERSION_WPA2) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "WPA_VERSION, WPA2\n");
+ priv->secinfo.WPA2enabled = 1;
+ priv->secinfo.wep_enabled = 0;
+ priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
+ }
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ if (dwrq->value & IW_AUTH_ALG_SHARED_KEY ||
+ dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) {
+ if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "80211_AUTH_ALG, SHARED_KEY\n");
+ priv->secinfo.auth_mode |= IW_AUTH_ALG_SHARED_KEY;
+ }
+ if (dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "80211_AUTH_ALG, OPEN\n");
+ priv->secinfo.auth_mode |= IW_AUTH_ALG_OPEN_SYSTEM;
+ }
+ } else if (dwrq->value & IW_AUTH_ALG_LEAP) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "80211_AUTH_ALG, LEAP\n");
+ priv->secinfo.auth_mode = IW_AUTH_ALG_LEAP;
+ } else if (dwrq->value & IW_AUTH_ALG_WAPI) {
+ priv->secinfo.auth_mode = IW_AUTH_ALG_WAPI;
+ } else {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "80211_AUTH_ALG, unknown\n");
+ ret = -EINVAL;
+ }
+ break;
+
+ case IW_AUTH_WPA_ENABLED:
+ if (dwrq->value) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "WPA_ENABLED, value = 0x%x\n", dwrq->value);
+ if (!priv->secinfo.WPAenabled &&
+ !priv->secinfo.WPA2enabled) {
+ priv->secinfo.WPAenabled = 1;
+ priv->secinfo.WPA2enabled = 1;
+ priv->secinfo.wep_enabled = 0;
+ priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
+ }
+ } else {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "WPA_ENABLED, value = ZERO\n");
+ priv->secinfo.WPAenabled = 0;
+ priv->secinfo.WPA2enabled = 0;
+ disable_wpa(priv);
+ }
+ break;
+
+ case IW_AUTH_WAPI_ENABLED:
+ if (dwrq->value & BIT1) {
+ disable_wpa(priv);
+ disable_wep(priv);
+ priv->secinfo.auth_mode = IW_AUTH_ALG_WAPI;
+ } else if (dwrq->value & BIT2) {
+ disable_wpa(priv);
+ disable_wep(priv);
+ priv->secinfo.auth_mode = IW_AUTH_ALG_WAPI;
+ }
+ break;
+
+ default:
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "NOT SUPPORT\n");
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return ret;
+}
+
+static int wlan_get_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *dwrq, char *extra)
+{
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+ int ret = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+
+ switch (dwrq->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_KEY_MGMT:
+ dwrq->value = priv->secinfo.key_mgmt;
+ break;
+
+ case IW_AUTH_WPA_VERSION:
+ dwrq->value = 0;
+ if (priv->secinfo.WPAenabled)
+ dwrq->value |= IW_AUTH_WPA_VERSION_WPA;
+ if (priv->secinfo.WPA2enabled)
+ dwrq->value |= IW_AUTH_WPA_VERSION_WPA2;
+ if (!dwrq->value)
+ dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ dwrq->value = priv->secinfo.auth_mode;
+ break;
+
+ case IW_AUTH_WPA_ENABLED:
+ if (priv->secinfo.WPAenabled && priv->secinfo.WPA2enabled)
+ dwrq->value = 1;
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+ return ret;
+}
+
+static int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *vwrq, char *extra)
+{
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+ return 0;
+}
+
+static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+
+ memcpy(extra, priv->curbssparams.ssid, strlen(priv->curbssparams.ssid));
+ dwrq->length = strlen(priv->curbssparams.ssid);
+ extra[dwrq->length] = '\0';
+
+ /*
+ * If none, we may want to get the one that was set
+ */
+
+ dwrq->flags = 1; /* active */
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>> \n", __func__);
+ return 0;
+}
+
+void wlan_indicate_disconnected(wlan_private * priv)
+{
+ union iwreq_data wrqu;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_NORM, "%s <<<\n", __func__);
+
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(priv->netDev, SIOCGIWAP, &wrqu, NULL);
+
+ /*report disconnect to upper layer */
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_NORM, "%s >>>\n", __func__);
+}
+
+void wlan_indicate_connected(wlan_private * priv)
+{
+ union iwreq_data wrqu;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_NORM, "%s <<<\n", __func__);
+
+ memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(priv->netDev, SIOCGIWAP, &wrqu, NULL);
+
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_NORM, "%s >>> \n connect mac: %2x:%2x:%2x:%2x:%2x:%2x \n",
+ __func__, priv->curbssparams.bssid[0],
+ priv->curbssparams.bssid[1], priv->curbssparams.bssid[2],
+ priv->curbssparams.bssid[3], priv->curbssparams.bssid[4],
+ priv->curbssparams.bssid[5]);
+}
+
+struct bss_descriptor *get_bss_desc_from_scanlist(wlan_private * priv,
+ unsigned char *bssid)
+{
+ struct bss_descriptor *iter_bss;
+ struct bss_descriptor *ret_bss = NULL;
+
+ spin_lock(&priv->ScanListLock);
+ /* report all bss to upper layer */
+ list_for_each_entry(iter_bss, &priv->network_list, list) {
+ if (memcmp(iter_bss->bssid, bssid, 6) == 0) {
+ ret_bss = iter_bss;
+ break;
+ }
+ }
+ spin_unlock(&priv->ScanListLock);
+ return ret_bss;
+}
+
+static int wlan_set_essid(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+ int ret = 0;
+ u8 ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 ssid_len = 0;
+ int in_ssid_len = dwrq->length;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ /* Check the size of the string */
+ if (in_ssid_len > IW_ESSID_MAX_SIZE) {
+ ret = -E2BIG;
+ goto out;
+ }
+
+ memset(&ssid, 0, sizeof(ssid));
+
+ if (!dwrq->flags || !in_ssid_len) {
+ /* "any" SSID requested; leave SSID blank */
+ } else {
+ /* Specific SSID requested */
+ memcpy(&ssid, extra, in_ssid_len);
+ ssid[in_ssid_len] = '\0';
+ ssid_len = in_ssid_len;
+ }
+
+ if (!ssid_len) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "requested any SSID\n");
+ } else {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "requested SSID len = %d ssid:%s\n",
+ ssid_len, ssid);
+ }
+
+ if (ssid_len) {
+ memcpy(&priv->assoc_ssid[0], ssid, sizeof(ssid));
+ priv->assoc_ssid_len = ssid_len;
+#if 0
+ priv->ToggalAssociation = FALSE;
+
+ if (priv->StartAssociationTimeOut.timer_is_canceled)
+ wlan_mod_timer(&priv->StartAssociationTimeOut, 100);
+ priv->assoc_ongoing = TRUE;
+#endif
+ }
+
+out:
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return 0;
+}
+
+
+/**
+ * @brief Connect to the AP or Ad-hoc Network with specific bssid
+ *
+ * @param dev A pointer to net_device structure
+ * @param info A pointer to iw_request_info structure
+ * @param awrq A pointer to iw_param structure
+ * @param extra A pointer to extra data buf
+ * @return 0 --success, otherwise fail
+ */
+
+static int wlan_set_wap(struct net_device *dev, struct iw_request_info *info,
+ struct sockaddr *awrq, char *extra)
+{
+ unsigned char *ap_addr = NULL;
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<< \n", __func__);
+
+ ap_addr = awrq->sa_data;
+ if (!is_zero_eth_addr(ap_addr)) {
+ priv->reassoc_count = 0;
+ if (memcmp(priv->assoc_bssid, ap_addr, 6)) {
+ memcpy(priv->assoc_bssid, ap_addr, 6);
+ priv->ToggalAssociation = FALSE;
+ if (!priv->ReAssociationTimeOut.timer_is_canceled) {
+ wlan_cancel_timer(&priv->ReAssociationTimeOut);
+ }
+ if (priv->StartAssociationTimeOut.timer_is_canceled)
+ wlan_mod_timer(&priv->StartAssociationTimeOut, 100);
+ } else {
+ if (priv->ReAssociationTimeOut.timer_is_canceled) {
+ wlan_mod_timer(&priv->StartAssociationTimeOut, 100);
+ }
+ }
+ priv->assoc_ongoing = TRUE;
+ } else {
+ memcpy(priv->assoc_bssid, ap_addr, 6);
+ wlan_cancel_timer(&priv->ReAssociationTimeOut);
+ wlan_cancel_timer(&priv->StartAssociationTimeOut);
+
+ disable_wep(priv);
+ disable_wpa(priv);
+ }
+
+ WLAN_ERRP("%s <<< \n connect mac: %2x:%2x:%2x:%2x:%2x:%2x \n", __func__,
+ ap_addr[0], ap_addr[1], ap_addr[2], ap_addr[3], ap_addr[4], ap_addr[5]);
+
+ return 0;
+}
+
+unsigned char num_2_char(unsigned char num)
+{
+ if (num >= 0 && num <= 9) {
+ return '0' + num;
+ } else
+ return 'a' + (num - 0x0a);
+}
+
+void num_2_str(unsigned char num, unsigned char *str)
+{
+ *str = num_2_char((num >> 4) & 0x0f);
+ *(str + 1) = num_2_char(num & 0x0f);
+}
+
+static char *translate_scan(wlan_private * priv,
+ struct iw_request_info *info,
+ char *start, char *stop,
+ struct bss_descriptor *bss_desc)
+{
+
+ struct iw_event iwe; /* Temporary buffer */
+ u8 snr;
+ struct bss_descriptor *bss = bss_desc;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "translate_scan, ssid = %s ssi=%d ssid_len=%d \n", bss->ssid, bss->rssi, bss->ssid_len);
+
+ /* First entry *MUST* be the BSSID */
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
+
+ /* SSID */
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ iwe.u.data.length = bss->ssid_len;
+ start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
+
+ /* Mode */
+ iwe.cmd = SIOCGIWMODE;
+ iwe.u.mode = bss->mode;
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
+
+ /* Frequency */
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = (2412 + 5 * (bss->channel - 1)) * 100000;
+ iwe.u.freq.e = 1;
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
+
+ /* Add quality statistics */
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
+ iwe.u.qual.level = 0x100 + wlan_get_aver_rssi(priv, bss->bssid);
+
+ snr = iwe.u.qual.level - WLAN_NF_DEFAULT_SCAN_VALUE;
+ iwe.u.qual.qual =
+ (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - snr) *
+ (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - snr))) /
+ (RSSI_DIFF * RSSI_DIFF);
+ if (iwe.u.qual.qual > 100)
+ iwe.u.qual.qual = 100;
+ iwe.u.qual.noise = WLAN_NF_DEFAULT_SCAN_VALUE;
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
+
+ /* Add encryption capability */
+ iwe.cmd = SIOCGIWENCODE;
+ if (bss->capability & WLAN_CAPABILITY_PRIVACY) {
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ } else {
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ }
+ iwe.u.data.length = 0;
+ start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
+
+ memset(&iwe, 0, sizeof(iwe));
+ if (bss_desc->wpa_ie_len && !bss_desc->wapi_ie_len) {
+ char buf[MAX_WPA_IE_LEN];
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "translate_scan, wpa_ie, len %d\n",
+ bss_desc->wpa_ie_len);
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "%02x %02x %02x %02x ... ... %02x %02x %02x %02x\n",
+ bss_desc->wpa_ie[0], bss_desc->wpa_ie[1],
+ bss_desc->wpa_ie[2], bss_desc->wpa_ie[3],
+ bss_desc->wpa_ie[bss_desc->wpa_ie_len - 4],
+ bss_desc->wpa_ie[bss_desc->wpa_ie_len - 3],
+ bss_desc->wpa_ie[bss_desc->wpa_ie_len - 2],
+ bss_desc->wpa_ie[bss_desc->wpa_ie_len - 1]);
+
+ memcpy(buf, bss->wpa_ie, bss->wpa_ie_len);
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = bss_desc->wpa_ie_len;
+ start = iwe_stream_add_point(info, start, stop, &iwe, buf);
+ }
+
+ memset(&iwe, 0, sizeof(iwe));
+ if (bss_desc->rsn_ie_len) {
+ char buf[MAX_WPA_IE_LEN];
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "translate_scan, rsn_ie, len %d\n",
+ bss_desc->rsn_ie_len);
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "%02x %02x %02x %02x ... ... %02x %02x %02x %02x\n",
+ bss_desc->rsn_ie[0], bss_desc->rsn_ie[1],
+ bss_desc->rsn_ie[2], bss_desc->rsn_ie[3],
+ bss_desc->rsn_ie[bss_desc->rsn_ie_len - 4],
+ bss_desc->rsn_ie[bss_desc->rsn_ie_len - 3],
+ bss_desc->rsn_ie[bss_desc->rsn_ie_len - 2],
+ bss_desc->rsn_ie[bss_desc->rsn_ie_len - 1]);
+
+ memcpy(buf, bss->rsn_ie, bss->rsn_ie_len);
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = bss_desc->rsn_ie_len;
+ start = iwe_stream_add_point(info, start, stop, &iwe, buf);
+ }
+ if(priv->version == WLAN_VERSION_91_E|| priv->version == WLAN_VERSION_91_F){
+ /* huanglei add for wps */
+ memset(&iwe, 0, sizeof(iwe));
+ if (bss_desc->wps_ie_len ) {
+ char buf[MAX_WPS_IE_LEN];
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "translate_scan, wps_ie, len %d\n", bss_desc->wps_ie_len);
+
+ memcpy(buf, bss->wps_ie, bss->wps_ie_len);
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = bss_desc->wps_ie_len;
+ start = iwe_stream_add_point(info, start, stop, &iwe, buf);
+ }
+ }
+ if (bss_desc->wapi_ie_len) {
+ char buf[200];
+ unsigned char pos = 0;
+
+ memset(&iwe, 0, sizeof(iwe));
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "translate_scan, wapi_len %d\n",
+ bss_desc->wapi_ie_len);
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "%02x %02x %02x %02x ... ... %02x %02x %02x %02x\n",
+ bss_desc->wapi_ie[0], bss_desc->wapi_ie[1],
+ bss_desc->wapi_ie[2], bss_desc->wapi_ie[3],
+ bss_desc->wapi_ie[bss_desc->wapi_ie_len - 4],
+ bss_desc->wapi_ie[bss_desc->wapi_ie_len - 3],
+ bss_desc->wapi_ie[bss_desc->wapi_ie_len - 2],
+ bss_desc->wapi_ie[bss_desc->wapi_ie_len - 1]);
+
+ memcpy(buf, "wapi_ie=", 8);
+
+ while (pos < bss_desc->wapi_ie_len) {
+ //transfer hex to ascii string because wpa_supplicant need do so
+ num_2_str(bss_desc->wapi_ie[pos],
+ (unsigned char *)(buf + 8 + 2 * pos));
+ pos++;
+ }
+
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = bss_desc->wapi_ie_len * 2 + 8;
+ start = iwe_stream_add_point(info, start, stop, &iwe, buf);
+ }
+
+ return start;
+}
+
+/**
+ * @brief Handle Scan Network ioctl
+ *
+ * @param dev A pointer to net_device structure
+ * @param info A pointer to iw_request_info structure
+ * @param vwrq A pointer to iw_param structure
+ * @param extra A pointer to extra data buf
+ *
+ * @return 0 --success, otherwise fail
+ */
+int wlan_set_scan(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+ int ret = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s scan:%d assoc:%d <<< \n",
+ __func__, priv->scan_running, priv->assoc_ongoing);
+
+ if (!is_sdio_init_complete() || priv->scan_running == WLAN_SCAN_RUNNING
+ || priv->assoc_ongoing || priv->sdio_need_reset)
+ goto out;
+
+ if (wrqu->data.length == sizeof(struct iw_scan_req) &&
+ wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+ struct iw_scan_req *req = (struct iw_scan_req *)extra;
+ priv->scan_ssid_len = req->essid_len > 32 ? 32 : req->essid_len;
+ memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
+ priv->scan_ssid[priv->scan_ssid_len] = '\0';
+ } else {
+ priv->scan_ssid_len = 0;
+ memset(priv->scan_ssid, '\0', sizeof(priv->scan_ssid));
+ }
+
+ wlan_set_rssi_dirty(priv);
+ priv->scan_running = WLAN_SCAN_RUNNING;
+ ret = wlan_start_scan_enable_network_info(priv);
+ if (!ret) {
+ wlan_mod_timer(&priv->ScanResultsTimeout, 1500);
+ } else {
+ priv->scan_running = WLAN_SCAN_IDLE;
+ }
+out:
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s ret %d >>> \n", __func__, ret);
+ return 0;
+}
+
+
+void wlan_set_scan_by_driver(wlan_private *priv)
+{
+ int ret = 0;
+ priv->scan_ssid_len = 0;
+ memset(priv->scan_ssid, '\0', sizeof(priv->scan_ssid));
+ priv->scan_running = WLAN_SCAN_RUNNING;
+ ret = wlan_start_scan_enable_network_info(priv);
+ if (!ret) {
+ wlan_mod_timer(&priv->ScanResultsTimeout, 1500);
+ } else {
+ priv->scan_running = WLAN_SCAN_IDLE;
+ }
+}
+
+
+static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
+{
+ unsigned long end = jiffies;
+
+ if (end >= start)
+ return jiffies_to_msecs(end - start);
+
+ return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
+}
+
+/**
+ * @brief Handle Retrieve scan table ioctl
+ *
+ * @param dev A pointer to net_device structure
+ * @param info A pointer to iw_request_info structure
+ * @param dwrq A pointer to iw_point structure
+ * @param extra A pointer to extra data buf
+ *
+ * @return 0 --success, otherwise fail
+ */
+int wlan_get_scan(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+#define SCAN_ITEM_SIZE 128
+ wlan_private *priv = (wlan_private *) netdev_priv(dev);
+ int ret = 0;
+ struct bss_descriptor *iter_bss;
+ struct bss_descriptor *safe;
+ char *ev = extra;
+ char *stop = ev + dwrq->length;
+ u8 items = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_DEBUG, "%s >>>\n", __func__);
+
+ /* iwlist should wait until the current scan is finished */
+ if (priv->scan_running == WLAN_SCAN_RUNNING) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "Scan is Running, return AGAIN\n");
+ return -EAGAIN;
+ }
+
+ spin_lock(&priv->ScanListLock);
+ /* report all bss to upper layer */
+ list_for_each_entry_safe(iter_bss, safe, &priv->network_list, list) {
+ char *next_ev;
+ unsigned long stale_time;
+
+
+ if (stop - ev < SCAN_ITEM_SIZE) {
+ ret = -E2BIG;
+ break;
+ }
+
+ if (!iter_bss->ssid_len){
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,"No valid AP here\n");
+ continue;
+ }
+
+ /* Prune old an old scan result */
+ stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
+ if (time_before(stale_time, jiffies)) {
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "Not show %s, due to age (%ums).\n", iter_bss->ssid,
+ elapsed_jiffies_msecs(iter_bss->last_scanned));
+ clear_bss_descriptor(iter_bss);
+ continue;
+ }
+
+#ifdef WIFI_SELECT_CHANNEL
+ if (iter_bss->channel > channel_nums) {
+ clear_bss_descriptor(iter_bss);
+ continue;
+ }
+#endif
+ /* Translate to WE format this entry */
+ next_ev = translate_scan(priv, info, ev, stop, iter_bss);
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "Report BSS %s\n", iter_bss->ssid);
+
+ if (next_ev == NULL)
+ continue;
+ ev = next_ev;
+ items++;
+ }
+ spin_unlock(&priv->ScanListLock);
+ dwrq->length = (ev - extra);
+ dwrq->flags = 0;
+
+ if (priv->scan_running != WLAN_SCAN_RUNNING)
+ priv->scan_running = WLAN_SCAN_IDLE;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s ap:%d< <<\n", __func__, items);
+ return ret;
+}
+
+int wlan_set_mlme(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct iw_mlme *mlme = (struct iw_mlme *)extra;
+ wlan_private *priv = netdev_priv(dev);
+ int ret = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ switch (mlme->cmd) {
+ case IW_MLME_DEAUTH:
+ case IW_MLME_DISASSOC:
+ {
+ unsigned char null_data[6];
+ memset(null_data, 0, 6);
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "DISASSOC\n");
+
+ wlan_cancel_timer(&priv->AssociationTimeOut);
+ wlan_cancel_timer(&priv->ReAssociationTimeOut);
+ priv->assoc_ongoing = FALSE;
+
+ /* silently ignore */
+ if(priv->version >= WLAN_VERSION_91){
+ //wlan_set_bssid(priv, null_data);
+ //wlan_disconnect(priv);
+ ret = wlan_disconnect_silent(priv);
+ }
+ else
+ ret = wlan_set_ssid((wlan_private *) netdev_priv(dev), null_data, 6);
+
+ }
+ break;
+ default:
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE,
+ "Not supported cmd %d\n", mlme->cmd);
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s <<<\n", __func__);
+ return ret;
+}
+
+#define MAX_WX_STRING 80
+static int wl_iw_get_macaddr(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int error;
+ char *p = extra;
+ char buf[ETH_ALEN] = { 0 };
+ wlan_private *priv = netdev_priv(dev);
+
+ error = wlan_get_mac_addr(priv, buf);
+ p += snprintf(p, MAX_WX_STRING,
+ "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n", buf[0],
+ buf[1], buf[2], buf[3], buf[4], buf[5]);
+
+ wrqu->data.length = p - extra + 1;
+
+ return error;
+}
+
+static int wlan_set_priv(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *dwrq, char *ext)
+{
+ int ret = 0;
+ char *extra;
+
+ if (!(extra = kmalloc(dwrq->length, GFP_KERNEL)))
+ return -ENOMEM;
+
+ if (copy_from_user(extra, dwrq->pointer, dwrq->length)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+
+ if (dwrq->length && extra) {
+ if (strnicmp(extra, "MACADDR", strlen("MACADDR")) == 0) {
+ ret =
+ wl_iw_get_macaddr(dev, info,
+ (union iwreq_data *)dwrq, extra);
+ } else if (strnicmp(extra, "CSCAN", strlen("CSCAN")) == 0) {
+ }
+ }
+
+ if (extra) {
+ if (copy_to_user(dwrq->pointer, extra, dwrq->length)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+ kfree(extra);
+ }
+
+ return ret;
+}
+
+static int wlan_wext_get_wireless_stats(struct net_device *dev,
+ struct iw_request_info *info,
+ u32 * uwrq, char *extra)
+{
+ struct iw_statistics *wstats = (struct iw_statistics *)extra;
+ wlan_private *priv = netdev_priv(dev);
+ int ret = 0;
+ int stats_valid = 0;
+ u8 snr;
+
+ WLAN_DBGLAP(WLAN_DA_WEXT, WLAN_DL_TRACE, "%s >>>\n", __func__);
+
+ ret = wlan_update_bss_stats(priv);
+ if (ret)
+ goto out;
+
+ wstats->miss.beacon = 0;
+ wstats->discard.retries = 0;
+ wstats->qual.level = 0x100 + (s8)priv->curbssparams.rssi;
+
+ snr = wstats->qual.level - WLAN_NF_DEFAULT_SCAN_VALUE;
+ wstats->qual.qual =
+ (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - snr) *
+ (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - snr))) /
+ (RSSI_DIFF * RSSI_DIFF);
+ if (wstats->qual.qual > 100)
+ wstats->qual.qual = 100;
+ wstats->qual.noise = WLAN_NF_DEFAULT_SCAN_VALUE;
+ wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+
+ stats_valid = 1;
+
+out:
+ if (!stats_valid) {
+ wstats->miss.beacon = 0;
+ wstats->discard.retries = 0;
+ wstats->qual.qual = 0;
+ wstats->qual.level = 0;
+ wstats->qual.noise = 0;
+ wstats->qual.updated = IW_QUAL_ALL_UPDATED;
+ wstats->qual.updated |= IW_QUAL_NOISE_INVALID |
+ IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
+ }
+ return ret;
+}
+
+/*
+ * iwconfig settable callbacks
+ */
+static const iw_handler wlan_wext_handler[] = {
+ (iw_handler) NULL, /* SIOCSIWCOMMIT */
+ (iw_handler) wlan_get_name, /* SIOCGIWNAME */
+ (iw_handler) NULL, /* SIOCSIWNWID */
+ (iw_handler) NULL, /* SIOCGIWNWID */
+ (iw_handler) wlan_set_freq, /* SIOCSIWFREQ */
+ (iw_handler) wlan_get_freq, /* SIOCGIWFREQ */
+ (iw_handler) wlan_set_mode, /* SIOCSIWMODE */
+ (iw_handler) wlan_get_mode, /* SIOCGIWMODE */
+ (iw_handler) NULL, /* SIOCSIWSENS */
+ (iw_handler) NULL, /* SIOCGIWSENS */
+ (iw_handler) NULL, /* SIOCSIWRANGE */
+ (iw_handler) wlan_get_range, /* SIOCGIWRANGE */
+ (iw_handler) wlan_set_priv, /* SIOCSIWPRIV */
+ (iw_handler) NULL, /* SIOCGIWPRIV */
+ (iw_handler) NULL, /* SIOCSIWSTATS */
+ (iw_handler) wlan_wext_get_wireless_stats, /* SIOCGIWSTATS */
+ (iw_handler) NULL, /* SIOCSIWSPY */
+ (iw_handler) NULL, /* SIOCGIWSPY */
+ (iw_handler) NULL, /* SIOCSIWTHRSPY */
+ (iw_handler) NULL, /* SIOCGIWTHRSPY */
+ (iw_handler) wlan_set_wap, /* SIOCSIWAP */
+ (iw_handler) wlan_get_wap, /* SIOCGIWAP */
+ (iw_handler) wlan_set_mlme, /* SIOCSIWMLME */
+ (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
+ (iw_handler) wlan_set_scan, /* SIOCSIWSCAN */
+ (iw_handler) wlan_get_scan, /* SIOCGIWSCAN */
+ (iw_handler) wlan_set_essid, /* SIOCSIWESSID */
+ (iw_handler) wlan_get_essid, /* SIOCGIWESSID */
+ (iw_handler) wlan_set_nick, /* SIOCSIWNICKN */
+ (iw_handler) wlan_get_nick, /* SIOCGIWNICKN */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) wlan_set_rate, /* SIOCSIWRATE */
+ (iw_handler) wlan_get_rate, /* SIOCGIWRATE */
+ (iw_handler) wlan_set_rts, /* SIOCSIWRTS */
+ (iw_handler) wlan_get_rts, /* SIOCGIWRTS */
+ (iw_handler) wlan_set_frag, /* SIOCSIWFRAG */
+ (iw_handler) wlan_get_frag, /* SIOCGIWFRAG */
+ (iw_handler) wlan_set_txpow, /* SIOCSIWTXPOW */
+ (iw_handler) wlan_get_txpow, /* SIOCGIWTXPOW */
+ (iw_handler) wlan_set_retry, /* SIOCSIWRETRY */
+ (iw_handler) wlan_get_retry, /* SIOCGIWRETRY */
+ (iw_handler) wlan_set_encode, /* SIOCSIWENCODE */
+ (iw_handler) wlan_get_encode, /* SIOCGIWENCODE */
+ (iw_handler) wlan_set_power, /* SIOCSIWPOWER */
+ (iw_handler) wlan_get_power, /* SIOCGIWPOWER */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) wlan_set_genie, /* SIOCSIWGENIE */
+ (iw_handler) wlan_get_genie, /* SIOCGIWGENIE */
+ (iw_handler) wlan_set_auth, /* SIOCSIWAUTH */
+ (iw_handler) wlan_get_auth, /* SIOCGIWAUTH */
+ (iw_handler) wlan_set_encodeext, /* SIOCSIWENCODEEXT */
+ (iw_handler) wlan_get_encodeext, /* SIOCGIWENCODEEXT */
+ (iw_handler) wlan_set_pmksa, /* SIOCSIWPMKSA */
+};
+
+struct iw_handler_def wlan_wext_handler_def = {
+ .num_standard = ARRAY_SIZE(wlan_wext_handler),
+ .standard = (iw_handler *) wlan_wext_handler,
+ .get_wireless_stats = wlan_get_wireless_stats,
+};
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_wid.c b/drivers/net/wireless/rda/rda_wlan/wlan_wid.c
new file mode 100755
index 00000000..e653accd
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_wid.c
@@ -0,0 +1,1771 @@
+#include "wlan_includes.h"
+
+void wlan_clean_wid_node(wlan_wid_packet_node * widNode)
+{
+ if (!widNode)
+ return;
+
+ if (widNode->Buf)
+ kfree(widNode->Buf);
+
+ if (widNode->RspBuf)
+ kfree(widNode->RspBuf);
+
+ widNode->Buf = NULL;
+ widNode->BufLen = 0;
+ widNode->RspBuf = NULL;
+ widNode->RspLen = 0;
+ widNode->WidWaitOption = FALSE;
+ widNode->WidCmd = 0;
+ widNode->WidMsgId = 0;
+}
+
+wlan_wid_packet_node *wlan_get_wid_node_in_freeQ(wlan_private * priv)
+{
+ wlan_wid_packet_node *widNode = NULL;
+
+ ENTER();
+
+ if (priv->Suspend || priv->CardRemoved)
+ return NULL;
+
+ spin_lock(&priv->WidLock);
+ if (!list_empty(&priv->WidFreeQ)) {
+ widNode = (wlan_wid_packet_node *) priv->WidFreeQ.next;
+ list_del(&widNode->List);
+ }
+ spin_unlock(&priv->WidLock);
+
+ if (widNode)
+ wlan_clean_wid_node(widNode);
+ else
+ WLAN_ERRP("no free wid node \n");
+
+ LEAVE();
+ return widNode;
+}
+
+void wlan_put_wid_node_in_freeQ(wlan_private * priv,
+ wlan_wid_packet_node * widNode)
+{
+ if (!widNode || priv->CardRemoved)
+ return;
+
+ ENTER();
+ spin_lock(&priv->WidLock);
+ list_add_tail(&widNode->List, &priv->WidFreeQ);
+ spin_unlock(&priv->WidLock);
+ LEAVE();
+}
+
+int wlan_put_wid_node_in_pendingQ(wlan_private * priv,
+ wlan_wid_packet_node * widNode)
+{
+ int ret = 0;
+ wlan_tx_packet_node *txPacketNode = NULL;
+
+ if (!widNode || priv->CardRemoved)
+ return -1;
+
+ txPacketNode = (wlan_tx_packet_node *)kzalloc(sizeof(wlan_tx_packet_node), GFP_KERNEL);
+ if (!txPacketNode) {
+ WLAN_ERRP("no memory \n");
+ return -ENOMEM;
+ }
+
+ ENTER();
+
+ txPacketNode->type = WLAN_CMD;
+ txPacketNode->wid_node = widNode;
+
+ //add to pending queue
+ widNode->WidWaitOption = FALSE;
+
+ //add to pending queue
+ spin_lock(&priv->WidLock);
+ list_add_tail(&widNode->List, &priv->WidPendingQ);
+ spin_unlock(&priv->WidLock);
+
+ //add to tx queue , send to card
+ spin_lock(&priv->TxLock);
+ list_add_tail(&txPacketNode->List, &priv->TxQueue);
+ spin_unlock(&priv->TxLock);
+
+ complete(&priv->TxThread.comp);
+ ret = wait_event_timeout(widNode->WidDone, widNode->WidWaitOption, HZ * 5);
+ if (!ret) {
+ WLAN_ERRP("wait event timeout \n");
+ priv->EventErrorCount++;
+ } else if (ret == -ERESTARTSYS) {
+ WLAN_ERRP("wait event was interrupt by signal \n");
+ priv->EventErrorCount++;
+ } else {
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "wlan_put_wid_node_in_pendingQ received event success!! \n");
+ priv->EventErrorCount=0;
+ }
+
+ //delete from pending queue do not add to freeQ now because we should get wid response
+ spin_lock(&priv->WidLock);
+ widNode->BufLen = 0;
+ list_del(&widNode->List);
+ spin_unlock(&priv->WidLock);
+
+#ifdef CHECK_SDIO_STAUTS
+ if (!rda_combo_wifi_in_test_mode() && is_sdio_init_complete() && priv->EventErrorCount > WLAN_EVENT_MAX_ERR) {
+ WLAN_ERRP("Wait event timeout, push event : WLAN_EVENT_CHECK_SDIO \n");
+ wlan_push_event(priv, WLAN_EVENT_CHECK_SDIO, priv, FALSE);
+ priv->EventErrorCount = 0;
+ priv->sdio_need_reset = 1;
+ }
+#endif
+
+ if (ret > 0)
+ ret = 0;
+ else if (!ret)
+ ret = -1;
+
+ LEAVE();
+
+ return ret;
+}
+
+//do not del wid node in this, after wid complete it will be delete
+wlan_wid_packet_node *wlan_get_wid_node_in_pendingQ(wlan_private * priv)
+{
+ wlan_wid_packet_node *widNode = NULL;
+
+ if (priv->Suspend || priv->CardRemoved)
+ return NULL;
+
+ spin_lock(&priv->WidLock);
+ if (!list_empty(&priv->WidPendingQ)) {
+ widNode = (wlan_wid_packet_node *) priv->WidPendingQ.next;
+ }
+ spin_unlock(&priv->WidLock);
+ if (!widNode)
+ WLAN_ERRP("no wid pendingQ \n");
+ return widNode;
+}
+
+int wlan_alloc_wid_queue(wlan_private * priv)
+{
+ int ret = -1;
+ u32 i = 0;
+ wlan_wid_packet_node *widNode;
+
+ for (i = 0; i < WLAN_CMD_QUEUE_NUM; i++) {
+ widNode = kzalloc(sizeof(wlan_wid_packet_node), GFP_KERNEL);
+ if (widNode) {
+ init_waitqueue_head(&widNode->WidDone);
+ spin_lock(&priv->WidLock);
+ list_add_tail(&widNode->List, &priv->WidFreeQ);
+ spin_unlock(&priv->WidLock);
+ ret = 0;
+ } else {
+ WLAN_ERRP("kzalloc wlan_wid_packet_node memory failed!\n");
+ ret =-1;
+ break;
+ }
+ }
+ return ret;
+}
+
+int wlan_release_wid_pending_queue(wlan_private * priv)
+{
+ wlan_wid_packet_node *widNode;
+ struct list_head *qe, *qen;
+ ENTER();
+
+ spin_lock(&priv->WidLock);
+ if (!list_empty(&priv->WidPendingQ)) {
+ list_for_each_safe(qe, qen, &priv->WidPendingQ) {
+ widNode = (wlan_wid_packet_node *) qe;
+ list_del(&widNode->List);
+
+ wake_up(&widNode->WidDone);
+ }
+ }
+ spin_unlock(&priv->WidLock);
+ LEAVE();
+ return 0;
+}
+
+int wlan_free_wid_queue(wlan_private * priv)
+{
+ struct list_head *qe = NULL, *qen = NULL;
+ wlan_wid_packet_node *widNode;
+
+ ENTER();
+
+ spin_lock(&priv->WidLock);
+ if (!list_empty(&priv->WidFreeQ)) {
+ list_for_each_safe(qe, qen, &priv->WidFreeQ) {
+ widNode = (wlan_wid_packet_node *) qe;
+ list_del(&widNode->List);
+
+ if (widNode->Buf)
+ kfree(widNode->Buf);
+ widNode->Buf = NULL;
+
+ if (widNode->RspBuf)
+ kfree(widNode->RspBuf);
+ widNode->RspBuf = NULL;
+
+ kfree(widNode);
+ }
+ }
+ spin_unlock(&priv->WidLock);
+ LEAVE();
+ return 0;
+}
+
+int wlan_read_wid_rsp_polling(wlan_private * priv)
+{
+ u8 status;
+ int ret = 0;
+ u8 size_l = 0, size_h = 0;
+ u16 size = 0, rx_len = 0;
+ struct sk_buff *skb = NULL;
+ s16 count = 1000;
+ u8 *payload = NULL, rx_type = 0, msg_type = 0;
+ wlan_sdio_card *card = (wlan_sdio_card *) priv->card;
+
+ ENTER();
+ while (!is_sdio_init_complete() && !priv->CardRemoved && count--) {
+ sdio_claim_host(card->func);
+ ret = wlan_read_byte(priv, IF_SDIO_FUN1_INT_STAT, &status);
+ if (!ret) {
+ if (status & IF_SDIO_INT_AHB2SDIO) {
+ ret = wlan_read_byte(priv, IF_SDIO_AHB2SDIO_PKTLEN_L, &size_l);
+ if (ret) {
+ sdio_release_host(card->func);
+ break;
+ }
+
+ ret = wlan_read_byte(priv, IF_SDIO_AHB2SDIO_PKTLEN_H, &size_h);
+ if (ret) {
+ sdio_release_host(card->func);
+ break;
+ }
+
+ size = (size_l | ((size_h & 0x7f) << 8)) * 4;
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_NORM, "size = %d \n", size);
+
+ skb = dev_alloc_skb(size + NET_IP_ALIGN + 3);
+ if (!skb) {
+ sdio_release_host(card->func);
+ ret = -1;
+ break;
+ }
+
+ skb_reserve(skb, NET_IP_ALIGN);
+ skb_align(skb, 4);
+
+ if (wlan_read_bytes(priv, IF_SDIO_FUN1_FIFO_RD, skb->data, size)
+ || priv->CardRemoved) {
+ dev_kfree_skb(skb);
+ sdio_release_host(card->func);
+ ret = -1;
+ goto out;
+ }
+ sdio_release_host(card->func);
+ skb_put(skb, size);
+
+ payload = skb->data;
+
+ rx_type = payload[1] & 0xf0;
+ rx_len = (u16) (payload[0] + ((payload[1] & 0x0f) << 8));
+ if (rx_type == HOST_MSG_CONFIGRSP) {
+ msg_type = payload[2];
+ if (msg_type == 'R') {
+ wlan_wid_response(priv, payload + 2, rx_len - 2);
+ dev_kfree_skb(skb);
+ ret = 0;
+ break;
+ } else if (msg_type == 'I') {
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_NORM, "received a mac status \n");
+ }
+ }
+ dev_kfree_skb(skb);
+ } else
+ sdio_release_host(card->func);
+ } else
+ sdio_release_host(card->func);
+ udelay(10);
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_NORM, "IF_SDIO_FUN1_INT_STAT count:%d stats:0x%x\n", count, status);
+ }
+
+ if (count < 0) {
+ ret = -1;
+ WLAN_ERRP("polling wid rsp failed \n");
+ } else {
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_NORM, "polling wid rsp success \n");
+ }
+
+out:
+ LEAVE();
+ return ret;
+}
+
+//return 0 success
+int wlan_generic_get(wlan_private * priv,
+ u16 wid, u8 * val, u16 val_len, u32 * rspLen,
+ WID_TYPE_T type)
+{
+ int ret;
+ u8 wid_msg_id;
+ wlan_wid_packet_node *widNode = NULL;
+ u8 *wid_req = NULL;
+ u8 wid_req_len = 6;
+
+ ENTER();
+
+ if(priv->sdio_need_reset == 1)
+ return -ENOMEM;
+
+ widNode = wlan_get_wid_node_in_freeQ(priv);
+
+ if (!widNode)
+ return -ENOMEM;
+
+ wid_msg_id = priv->wid_msg_id++;
+
+ widNode->Buf = kmalloc(wid_req_len + WID_HEADER_LEN, GFP_KERNEL);
+ widNode->BufLen = wid_req_len;
+
+ widNode->RspBuf = kmalloc(val_len, GFP_KERNEL);
+ widNode->RspLen = val_len;
+ widNode->WidMsgId = wid_msg_id;
+ widNode->WidCmd = wid;
+ widNode->BufType = type;
+
+ wid_req = widNode->Buf + WID_HEADER_LEN;
+
+ wid_req[0] = 'Q';
+ wid_req[1] = wid_msg_id;
+
+ wid_req[2] = (char)(wid_req_len & 0x00FF);
+ wid_req[3] = (char)((wid_req_len & 0xFF00) >> 8);
+
+ wid_req[4] = (char)(wid & 0x00FF);
+ wid_req[5] = (char)((wid & 0xFF00) >> 8);
+
+ ret = wlan_put_wid_node_in_pendingQ(priv, widNode);
+
+ if (!ret) {
+ memcpy(val, widNode->RspBuf, widNode->RspLen);
+ if (rspLen)
+ *rspLen = widNode->RspLen;
+ }
+
+ wlan_put_wid_node_in_freeQ(priv, widNode);
+ LEAVE();
+ return ret;
+}
+
+int wlan_generic_get_uchar(wlan_private * priv, u16 wid, u8 * val)
+{
+ int ret;
+ ENTER();
+
+ ret = wlan_generic_get(priv, wid, val, 1, NULL, WID_CHAR);
+
+ LEAVE();
+ return ret;
+}
+
+int wlan_generic_get_ushort(wlan_private * priv, u16 wid, u8 * val)
+{
+ int ret;
+ ENTER();
+
+ ret = wlan_generic_get(priv, wid, val, 2, NULL, WID_SHORT);
+
+ LEAVE();
+ return ret;
+}
+
+int wlan_generic_get_ulong(wlan_private * priv, u16 wid, u8 * val)
+{
+ int ret;
+ ENTER();
+
+ ret = wlan_generic_get(priv, wid, (u8 *) val, 4, NULL, WID_INT);
+
+ LEAVE();
+ return ret;
+}
+
+int wlan_generic_get_str(wlan_private * priv,
+ u16 wid, u8 * val, u32 len, u32 * rspLen)
+{
+ int ret;
+ ENTER();
+
+ ret = wlan_generic_get(priv, wid, val, len, rspLen, WID_STR);
+
+ LEAVE();
+ return ret;
+}
+
+//return 0 success
+int wlan_send_wid_packet(wlan_private * priv, u8 * val, u16 val_len,
+ u8 wid_msg_id)
+{
+ int ret = 0;
+ wlan_wid_packet_node *widNode = NULL;
+ u8 *wid_req = NULL;
+ u16 wid_req_len = val_len;
+
+ ENTER();
+
+ if(priv->sdio_need_reset == 1)
+ return -ENOMEM;
+
+ widNode = wlan_get_wid_node_in_freeQ(priv);
+ if (!widNode)
+ return -ENOMEM;
+
+ widNode->Buf = kmalloc(wid_req_len + WID_HEADER_LEN, GFP_KERNEL);
+ widNode->BufLen = wid_req_len;
+
+ widNode->RspBuf = kmalloc(4, GFP_KERNEL);
+ widNode->RspLen = 4;
+ widNode->WidMsgId = wid_msg_id;
+ widNode->WidCmd = WID_STATUS;
+ widNode->BufType = WID_STR;
+
+ wid_req = widNode->Buf + WID_HEADER_LEN;
+ memcpy(wid_req, val, val_len);
+
+ ret = wlan_put_wid_node_in_pendingQ(priv, widNode);
+ //check wid status
+ if (!ret) {
+ if (widNode->RspBuf[0] != WID_STATUS_SUCCESS)
+ ret = -EINVAL;
+ }
+
+ wlan_put_wid_node_in_freeQ(priv, widNode);
+ LEAVE();
+ return ret;
+}
+
+int wlan_generic_set(wlan_private * priv,
+ u16 wid, u8 * val, u16 val_len, WID_TYPE_T type)
+{
+ int ret;
+ u8 wid_msg_id;
+ wlan_wid_packet_node *widNode = NULL;
+ u8 *wid_req = NULL;
+ u8 wid_req_len = 7 + val_len;
+
+ ENTER();
+
+ if(priv->sdio_need_reset == 1)
+ return -ENOMEM;
+
+ widNode = wlan_get_wid_node_in_freeQ(priv);
+ if (!widNode)
+ return -ENOMEM;
+
+ wid_msg_id = priv->wid_msg_id++;
+
+ if(type == WID_BIN_DATA)
+ wid_req_len += 2; //1for length feild, 1 for crc
+
+ widNode->Buf = kmalloc(wid_req_len + WID_HEADER_LEN, GFP_KERNEL);
+ widNode->BufLen = wid_req_len;
+
+ widNode->RspBuf = kmalloc(4, GFP_KERNEL);
+ widNode->RspLen = 4;
+ widNode->WidMsgId = wid_msg_id;
+ widNode->WidCmd = wid;
+ widNode->BufType = type;
+
+ wid_req = widNode->Buf + WID_HEADER_LEN;
+
+ wid_req[0] = 'W';
+ wid_req[1] = wid_msg_id;
+
+ wid_req[2] = (char)(wid_req_len & 0x00FF);
+ wid_req[3] = (char)((wid_req_len & 0xFF00) >> 8);
+
+ wid_req[4] = (char)(wid & 0x00FF);
+ wid_req[5] = (char)((wid & 0xFF00) >> 8);
+
+ if(type != WID_BIN_DATA){
+ wid_req[6] = val_len;
+ memcpy(&wid_req[7], val, val_len);
+ }else{
+ wid_req[6] = val_len & 0xff;
+ wid_req[7] = (val_len & 0xff00) >> 8;
+ memcpy(&wid_req[8], val, val_len);
+ }
+
+ ret = wlan_put_wid_node_in_pendingQ(priv, widNode);
+ //check wid status
+ if (!ret) {
+ if (widNode->RspBuf[0] != WID_STATUS_SUCCESS)
+ ret = -EINVAL;
+ }
+
+ wlan_put_wid_node_in_freeQ(priv, widNode);
+ LEAVE();
+ return ret;
+}
+
+int wlan_generic_set_uchar(wlan_private * priv, u16 wid, u8 val)
+{
+ int ret;
+ u8 tPara = val;
+ ENTER();
+
+ ret = wlan_generic_set(priv, wid, &tPara, 1, WID_CHAR);
+
+ LEAVE();
+ return ret;
+}
+
+int wlan_generic_set_ushort(wlan_private * priv, u16 wid, u16 val)
+{
+ int ret;
+ u16 tPara = val;
+ ENTER();
+
+ ret = wlan_generic_set(priv, wid, (u8 *) & tPara, 2, WID_SHORT);
+
+ LEAVE();
+ return ret;
+}
+
+int wlan_generic_set_ulong(wlan_private * priv, u16 wid, u32 val)
+{
+ int ret;
+ u32 tPara = val;
+ ENTER();
+
+ ret = wlan_generic_set(priv, wid, (u8 *) & tPara, 4, WID_INT);
+
+ LEAVE();
+ return ret;
+}
+
+int wlan_generic_set_str(wlan_private * priv, u16 wid, u8 * val, u32 val_len)
+{
+ int ret;
+ ENTER();
+
+ ret = wlan_generic_set(priv, wid, val, val_len, WID_STR);
+
+ LEAVE();
+ return ret;
+}
+
+int wlan_generic_set_bin(wlan_private * priv, u16 wid, u8 * val, u32 val_len)
+{
+ int ret;
+ ENTER();
+
+ ret = wlan_generic_set(priv, wid, val, val_len, WID_BIN_DATA);
+
+ LEAVE();
+ return ret;
+}
+
+int wlan_set_core_init_patch(wlan_private * priv, const u32(*data)[2], u8 num)
+{
+ int ret, count = 0;
+ u8 wid_msg_id;
+ wlan_wid_packet_node *widNode = NULL;
+ u8 *wid_req = NULL, *p_wid_req;
+ u8 wid_req_len = 4 + 14 * num;
+ u16 wid = WID_STATUS;
+
+ ENTER();
+
+ widNode = wlan_get_wid_node_in_freeQ(priv);
+
+ if (!widNode)
+ return -ENOMEM;
+
+ wid_msg_id = priv->wid_msg_id++;
+
+ widNode->Buf = kmalloc(wid_req_len + WID_HEADER_LEN + 4, GFP_KERNEL);
+ widNode->BufLen = wid_req_len;
+
+ widNode->RspBuf = kmalloc(4, GFP_KERNEL);
+ widNode->RspLen = 4;
+ widNode->WidMsgId = wid_msg_id;
+ widNode->WidCmd = wid;
+ widNode->BufType = WID_STR;
+ wid_req = widNode->Buf + WID_HEADER_LEN;
+
+ wid_req[0] = 'W';
+ wid_req[1] = wid_msg_id;
+
+ wid_req[2] = (char)(wid_req_len & 0x00FF);
+ wid_req[3] = (char)((wid_req_len & 0xFF00) >> 8);
+
+ p_wid_req = wid_req + 4;
+ for (count = 0; count < num; count++) {
+ wid = WID_MEMORY_ADDRESS;
+ p_wid_req[0] = (char)(wid & 0x00FF);
+ p_wid_req[1] = (char)((wid & 0xFF00) >> 8);
+
+ p_wid_req[2] = (char)4;
+ memcpy((u8 *) (p_wid_req + 3), (u8 *) (&data[count][0]), 4);
+
+ wid = WID_MEMORY_ACCESS_32BIT;
+ p_wid_req[7] = (char)(wid & 0x00FF);
+ p_wid_req[8] = (char)((wid & 0xFF00) >> 8);
+
+ p_wid_req[9] = (char)4;
+ memcpy((u8 *) (p_wid_req + 10), (u8 *) (&data[count][1]), 4);
+ p_wid_req += 14;
+ }
+ ret = wlan_put_wid_node_in_pendingQ(priv, widNode);
+ //check wid status
+ if (!ret) {
+ if (widNode->RspBuf[0] != WID_STATUS_SUCCESS)
+ ret = -EINVAL;
+ }
+
+ wlan_put_wid_node_in_freeQ(priv, widNode);
+
+ LEAVE();
+ return ret;
+}
+
+int wlan_set_core_patch(wlan_private * priv, const u8(*patch)[2], u8 num)
+{
+ int ret, count = 0;
+ u8 wid_msg_id;
+ wlan_wid_packet_node *widNode = NULL;
+ u8 *wid_req = NULL, *p_wid_req;
+ u8 wid_req_len = 4 + 8 * num;
+ u16 wid = WID_STATUS;
+
+ ENTER();
+
+ widNode = wlan_get_wid_node_in_freeQ(priv);
+
+ if (!widNode)
+ return -ENOMEM;
+
+ wid_msg_id = priv->wid_msg_id++;
+
+ widNode->Buf = kmalloc(wid_req_len + WID_HEADER_LEN + 4, GFP_KERNEL);
+ widNode->BufLen = wid_req_len;
+
+ widNode->RspBuf = kmalloc(4, GFP_KERNEL);
+ widNode->RspLen = 4;
+ widNode->WidMsgId = wid_msg_id;
+ widNode->WidCmd = wid;
+ widNode->BufType = WID_STR;
+ wid_req = widNode->Buf + WID_HEADER_LEN;
+
+ wid_req[0] = 'W';
+ wid_req[1] = wid_msg_id;
+
+ wid_req[2] = (char)(wid_req_len & 0x00FF);
+ wid_req[3] = (char)((wid_req_len & 0xFF00) >> 8);
+
+ p_wid_req = wid_req + 4;
+
+ for (count = 0; count < num; count++) {
+ wid = WID_PHY_ACTIVE_REG;
+ p_wid_req[0] = (char)(wid & 0x00FF);
+ p_wid_req[1] = (char)((wid & 0xFF00) >> 8);
+
+ p_wid_req[2] = (char)(0x01);
+ p_wid_req[3] = (char)patch[count][0];
+
+ wid = WID_PHY_ACTIVE_REG_VAL;
+ p_wid_req[4] = (char)(wid & 0x00FF);
+ p_wid_req[5] = (char)((wid & 0xFF00) >> 8);
+
+ p_wid_req[6] = (char)(0x01);
+ p_wid_req[7] = (char)patch[count][1];
+ p_wid_req += 8;
+ }
+ ret = wlan_put_wid_node_in_pendingQ(priv, widNode);
+ //check wid status
+ if (!ret) {
+ if (widNode->RspBuf[0] != WID_STATUS_SUCCESS)
+ ret = -EINVAL;
+ }
+
+ wlan_put_wid_node_in_freeQ(priv, widNode);
+
+ LEAVE();
+ return ret;
+}
+
+void wlan_wid_response(wlan_private * priv, u8 * wid_rsp, u16 wid_rsp_len)
+{
+ u16 rsp_len;
+ u16 rsp_wid;
+ u8 msg_id = 0;
+ u8 *payload = NULL, payload_len = 0;
+ struct list_head *qe, *qen;
+ wlan_wid_packet_node *widNode = NULL;
+
+ if (wid_rsp[0] != 'R') {
+ WLAN_ERRP("wid_rsp[0] != 'R'\n");
+ goto err;
+ }
+
+ if (wid_rsp_len < 4) {
+ WLAN_ERRP("wid_rsp_len < 4\n");
+ goto err;
+ }
+
+ rsp_len = wid_rsp[2] | (wid_rsp[3] << 8);
+ if (wid_rsp_len != rsp_len) {
+ WLAN_ERRP("wid_rsp_len not match, %d != %d\n", wid_rsp_len, rsp_len);
+ goto err;
+ }
+
+ if (wid_rsp_len < 7) {
+ WLAN_ERRP("wid_rsp_len < 7\n");
+ goto err;
+ }
+
+ msg_id = wid_rsp[1];
+ rsp_wid = wid_rsp[4] | (wid_rsp[5] << 8);
+ payload_len = wid_rsp[6];
+ payload = &wid_rsp[7];
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_DEBUG,"msg_id:%d rsp_wid:%d \n", msg_id, rsp_wid);
+ spin_lock(&priv->WidLock);
+ list_for_each_safe(qe, qen, &priv->WidPendingQ) {
+ widNode = (wlan_wid_packet_node *) qe;
+ //process wid write
+ if (rsp_wid == WID_STATUS) {
+ if (widNode->WidMsgId == msg_id) {
+ payload_len = widNode->RspLen > payload_len ? payload_len : widNode->RspLen;
+ memcpy(widNode->RspBuf, payload, payload_len);
+ widNode->WidWaitOption = TRUE;
+ wake_up(&widNode->WidDone);
+ if (is_sdio_init_complete())
+ complete(&priv->widComp);
+ }
+ } else { //process wid query
+ if (widNode->WidMsgId == msg_id) {
+ rsp_len = widNode->BufLen > payload_len ? payload_len : widNode->BufLen;
+ memcpy(widNode->RspBuf, payload, rsp_len);
+ widNode->WidWaitOption = TRUE;
+ widNode->RspLen = (u32) rsp_len;
+ wake_up(&widNode->WidDone);
+ if (is_sdio_init_complete())
+ complete(&priv->widComp);
+ }
+ }
+ }
+ spin_unlock(&priv->WidLock);
+
+err:
+
+ return;
+}
+
+int wlan_set_scan_timeout(wlan_private * priv)
+{
+ int ret;
+ char wid_req[24];
+ u16 wid_req_len = 19;
+ u8 wid_msg_id = priv->wid_msg_id++;
+ u16 wid = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "wlan_set_scan_timeout <<< \n");
+
+ wid = WID_SITE_SURVEY_SCAN_TIME;
+
+ wid_req[0] = 'W';
+ wid_req[1] = wid_msg_id;
+
+ wid_req[2] = (char)(wid_req_len & 0x00FF);
+ wid_req[3] = (char)((wid_req_len & 0xFF00) >> 8);
+
+ wid_req[4] = (char)(wid & 0x00FF);
+ wid_req[5] = (char)((wid & 0xFF00) >> 8);
+ wid_req[6] = 2;
+ wid_req[7] = SCAN_TIME_AT_EACH_CHANNEL; //50 ms one channel
+ wid_req[8] = 0;
+
+ wid = WID_ACTIVE_SCAN_TIME;
+ wid_req[9] = (char)(wid & 0x00FF);
+ wid_req[10] = (char)((wid & 0xFF00) >> 8);
+ wid_req[11] = 2;
+ wid_req[12] = SCAN_TIME_AT_EACH_CHANNEL; //50 ms one channel
+ wid_req[13] = 0;
+
+ wid = WID_PASSIVE_SCAN_TIME;
+ wid_req[14] = (char)(wid & 0x00FF);
+ wid_req[15] = (char)((wid & 0xFF00) >> 8);
+ wid_req[16] = 2;
+ wid_req[17] = SCAN_TIME_AT_EACH_CHANNEL; //50 ms one channel
+ wid_req[18] = 0;
+
+ ret = wlan_send_wid_packet(priv, wid_req, wid_req_len, wid_msg_id);
+
+ return ret;
+}
+
+int wlan_start_scan_enable_network_info(wlan_private * priv)
+{
+ int ret;
+ char wid_req[255], *pWid_req;
+ u16 wid_req_len = 16;
+ u16 wid;
+ u8 wid_msg_id = 0;
+ ENTER();
+
+ wid_msg_id = priv->wid_msg_id++;
+
+ wid_req[0] = 'W';
+ wid_req[1] = wid_msg_id;
+
+ wid_req[2] = (char)(wid_req_len & 0x00FF);
+ wid_req[3] = (char)((wid_req_len & 0xFF00) >> 8);
+
+ wid = WID_SITE_SURVEY;
+ wid_req[4] = (char)(wid & 0x00FF);
+ wid_req[5] = (char)((wid & 0xFF00) >> 8);
+
+ wid_req[6] = (char)(0x01);
+ wid_req[7] = (char)(0x01);
+
+ wid = WID_START_SCAN_REQ;
+ wid_req[8] = (char)(wid & 0x00FF);
+ wid_req[9] = (char)((wid & 0xFF00) >> 8);
+
+ wid_req[10] = (char)(0x01);
+ wid_req[11] = (char)(0x01);
+
+ wid = WID_NETWORK_INFO_EN;
+ wid_req[12] = (char)(wid & 0x00FF);
+ wid_req[13] = (char)((wid & 0xFF00) >> 8);
+
+ wid_req[14] = (char)(0x01);
+ wid_req[15] = (char)(0x01); // 0x01 scan network info
+
+ wid_req_len = 16;
+
+ if (priv->version == WLAN_VERSION_90_D || priv->version == WLAN_VERSION_90_E) {
+ int i = 0;
+ wid_req_len = wid_req_len;
+ pWid_req = &wid_req[wid_req_len];
+
+ while (i <= priv->scan_ssid_len) {
+ wid = WID_MEMORY_ADDRESS;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 4;
+ pWid_req[3] = 0x80 + i;
+ pWid_req[4] = 0x81;
+ pWid_req[5] = 0x10;
+ pWid_req[6] = 0x00;
+ wid_req_len += 7;
+ pWid_req += 7;
+
+ wid = WID_MEMORY_ACCESS_32BIT;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 4;
+ pWid_req[3] = priv->scan_ssid[i + 0];
+ pWid_req[4] = priv->scan_ssid[i + 1];
+ pWid_req[5] = priv->scan_ssid[i + 2];
+ pWid_req[6] = priv->scan_ssid[i + 3];
+ wid_req_len += 7;
+ pWid_req += 7;
+ i += 4;
+ }
+ } else if (priv->version == WLAN_VERSION_91 || priv->version == WLAN_VERSION_91_E|| priv->version == WLAN_VERSION_91_F) {
+ pWid_req = &wid_req[wid_req_len];
+ wid = WID_HIDE_SSID;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = priv->scan_ssid_len;
+ memcpy(pWid_req + 3, priv->scan_ssid, priv->scan_ssid_len);
+ wid_req_len += 3 + priv->scan_ssid_len;
+ pWid_req += 3 + priv->scan_ssid_len;
+ }
+
+ wid_req[2] = (char)(wid_req_len & 0x00FF);
+ wid_req[3] = (char)((wid_req_len & 0xFF00) >> 8);
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_DEBUG,
+ "wid_req_len : %d ssid_len:%d \n", wid_req_len,
+ priv->scan_ssid_len);
+
+ ret = wlan_send_wid_packet(priv, wid_req, wid_req_len, wid_msg_id);
+ if (ret) {
+ WLAN_ERRP("wlan_send_wid_packet failed!\n");
+ }
+ LEAVE();
+ return ret;
+}
+
+int wlan_start_join(wlan_private * priv)
+{
+ int ret = 0;
+ char wid_req[255];
+ u16 wid_req_len = 0;
+ u16 wid = 0;
+ u8 wid_msg_id = priv->wid_msg_id++;
+ u16 i = 0;
+ u8 key_str_len = 0;
+ u8 key_str[26 + 1], *key, *pWid_req;
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_DEBUG,
+ "%s <<< mode:0x%x authtype:%d ssid:%s\n", __func__,
+ priv->imode, priv->authtype, priv->assoc_ssid);
+
+ print_mac(priv->assoc_bssid);
+
+ pWid_req = wid_req;
+ pWid_req[0] = 'W';
+ pWid_req[1] = wid_msg_id;
+ wid_req_len = 4;
+ pWid_req += 4;
+
+ wid = WID_802_11I_MODE;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 1;
+ if(priv->imode == 0x9 && (priv->version == WLAN_VERSION_91_E|| priv->version == WLAN_VERSION_91_F)){//huanglei add for wps
+ wid_req[3] = 0x49;
+ }
+ else
+ pWid_req[3] = (priv->imode == 0x05) ? 0x07 : priv->imode; //for wep104 need set imode 0x07 firmware problem
+ wid_req_len += 4;
+ pWid_req += 4;
+
+ wid = WID_AUTH_TYPE;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 1;
+ pWid_req[3] = priv->authtype;
+ wid_req_len += 4;
+ pWid_req += 4;
+
+ wid = WID_NETWORK_INFO_EN;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 1;
+ pWid_req[3] = 0;
+ wid_req_len += 4;
+ pWid_req += 4;
+
+ wid = WID_CURRENT_TX_RATE;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 1;
+ pWid_req[3] = 1;
+ wid_req_len += 4;
+ pWid_req += 4;
+
+ if ((priv->version == WLAN_VERSION_90_D) || (priv->version == WLAN_VERSION_90_E)) {
+ // bssid
+ wid = WID_MEMORY_ADDRESS;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 4;
+ pWid_req[3] = 0xec;
+ pWid_req[4] = 0x81;
+ pWid_req[5] = 0x10;
+ pWid_req[6] = 0x00;
+ wid_req_len += 7;
+ pWid_req += 7;
+
+ wid = WID_MEMORY_ACCESS_32BIT;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 4;
+ pWid_req[3] = priv->assoc_bssid[0];
+ pWid_req[4] = priv->assoc_bssid[1];
+ pWid_req[5] = priv->assoc_bssid[2];
+ pWid_req[6] = priv->assoc_bssid[3];
+ wid_req_len += 7;
+ pWid_req += 7;
+
+ wid = WID_MEMORY_ADDRESS;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 4;
+ pWid_req[3] = 0xf0;
+ pWid_req[4] = 0x81;
+ pWid_req[5] = 0x10;
+ pWid_req[6] = 0x00;
+ wid_req_len += 7;
+ pWid_req += 7;
+
+ wid = WID_MEMORY_ACCESS_32BIT;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 4;
+ pWid_req[3] = priv->assoc_bssid[4];
+ pWid_req[4] = priv->assoc_bssid[5];
+ pWid_req[5] = 0;
+ pWid_req[6] = 0;
+ wid_req_len += 7;
+ pWid_req += 7;
+ }
+
+ if ((priv->version == WLAN_VERSION_90_D) || (priv->version == WLAN_VERSION_90_E)) {
+ //huanglei add begin
+ wid = WID_MEMORY_ADDRESS;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 4;
+ pWid_req[3] = 0x04;
+ pWid_req[4] = 0x01;
+ pWid_req[5] = 0x00;
+ pWid_req[6] = 0x50;
+ wid_req_len += 7;
+ pWid_req += 7;
+
+ wid = WID_MEMORY_ACCESS_16BIT;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 2;
+ pWid_req[3] = 0x1;//(cmax << 4) | (cmin) 00010001
+ pWid_req[4] = 0x1;
+ wid_req_len += 5;
+ pWid_req += 5;
+
+ wid = WID_MEMORY_ADDRESS;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 4;
+ pWid_req[3] = 0x08;
+ pWid_req[4] = 0x01;
+ pWid_req[5] = 0x00;
+ pWid_req[6] = 0x50;
+ wid_req_len += 7;
+ pWid_req += 7;
+
+ wid = WID_MEMORY_ACCESS_16BIT;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 2;
+ pWid_req[3] = 0x1;//(cmax << 4) | (cmin) 00010001
+ pWid_req[4] = 0x1;
+ wid_req_len += 5;
+ pWid_req += 5;
+
+ wid = WID_MEMORY_ADDRESS;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 4;
+ pWid_req[3] = 0x0C;
+ pWid_req[4] = 0x01;
+ pWid_req[5] = 0x00;
+ pWid_req[6] = 0x50;
+ wid_req_len += 7;
+ pWid_req += 7;
+
+ wid = WID_MEMORY_ACCESS_16BIT;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 2;
+ pWid_req[3] = 0x1;//(cmax << 4) | (cmin) 00010001
+ pWid_req[4] = 0x1;
+ wid_req_len += 5;
+ pWid_req += 5;
+
+ wid = WID_MEMORY_ADDRESS;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 4;
+ pWid_req[3] = 0x10;
+ pWid_req[4] = 0x01;
+ pWid_req[5] = 0x00;
+ pWid_req[6] = 0x50;
+ wid_req_len += 7;
+ pWid_req += 7;
+
+ wid = WID_MEMORY_ACCESS_16BIT;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 2;
+ pWid_req[3] = 0x1;//(cmax << 4) | (cmin) 00010001
+ pWid_req[4] = 0x1;
+ wid_req_len += 5;
+ pWid_req += 5;
+ //huanglei add end
+ }
+
+ //bssid
+ wid = WID_BSSID;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 6;
+ memcpy(&pWid_req[3], priv->assoc_bssid, 6);
+ wid_req_len += 9;
+ pWid_req += 9;
+
+ // ssid
+ wid = WID_SSID;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = priv->assoc_ssid_len;
+ memcpy(pWid_req + 3, priv->assoc_ssid, priv->assoc_ssid_len);
+ wid_req_len += 3 + priv->assoc_ssid_len;
+ pWid_req += 3 + priv->assoc_ssid_len;
+
+ wid = WID_START_SCAN_REQ;
+ pWid_req[0] = (char)(wid & 0x00FF);
+ pWid_req[1] = (char)((wid & 0xFF00) >> 8);
+ pWid_req[2] = 1;
+ pWid_req[3] = 0;
+ wid_req_len += 4;
+ pWid_req += 4;
+
+
+ wid = WID_WEP_KEY_VALUE0;
+ //write wep key
+ if (priv->imode == 3 || priv->imode == 5) {
+ for (i = 0; i < 4; i++) {
+ key = priv->wep_keys[i].key;
+
+ if (priv->wep_keys[i].len == 0)
+ continue;
+
+ if (priv->wep_keys[i].len == KEY_LEN_WEP_40) {
+ sprintf(key_str, "%02x%02x%02x%02x%02x\n",
+ key[0], key[1], key[2], key[3], key[4]);
+ key_str_len = 10;
+ key_str[key_str_len] = '\0';
+ } else if (priv->wep_keys[i].len == KEY_LEN_WEP_104) {
+ sprintf(key_str, "%02x%02x%02x%02x%02x"
+ "%02x%02x%02x%02x%02x"
+ "%02x%02x%02x\n",
+ key[0], key[1], key[2], key[3], key[4],
+ key[5], key[6], key[7], key[8], key[9],
+ key[10], key[11], key[12]);
+ key_str_len = 26;
+ key_str[key_str_len] = '\0';
+ } else
+ continue;
+
+ pWid_req[0] = (char)((wid + i) & 0x00FF);
+ pWid_req[1] = (char)(((wid + i) & 0xFF00) >> 8);
+
+ pWid_req[2] = key_str_len;
+ memcpy(pWid_req + 3, key_str, key_str_len);
+
+ pWid_req += 3 + key_str_len;
+ wid_req_len += 3 + key_str_len;
+ }
+ }
+
+
+
+ wid_req[2] = (char)(wid_req_len & 0x00FF);
+ wid_req[3] = (char)((wid_req_len & 0xFF00) >> 8);
+
+ ret = wlan_send_wid_packet(priv, wid_req, wid_req_len, wid_msg_id);
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_DEBUG,
+ "%s >>> ret = %d req len %d mod:0x%x auth_type:0x%x \n",
+ __func__, ret, wid_req_len, priv->imode, priv->authtype);
+
+ return ret;
+}
+
+int wlan_disconnect_silent(wlan_private * priv)
+{
+ int ret = 0;
+ char null_data[6];
+ char wid_req[255], *pWid_req = NULL;
+ u16 wid_req_len = 0;
+ u16 wid = 0;
+ u8 wid_msg_id = priv->wid_msg_id++;
+
+ memset(null_data, 0 , 6);
+
+ wid_req[0] = 'W';
+ wid_req[1] = wid_msg_id;
+
+ wid_req_len += 4;
+ pWid_req = wid_req + 4;
+
+ wid = WID_BSSID;
+ pWid_req[0] = (char)(wid&0x00FF);
+ pWid_req[1] = (char)((wid&0xFF00) >> 8);
+ pWid_req[2] = 6;
+ memcpy(&pWid_req[3], null_data, 6);
+ wid_req_len += 9;
+ pWid_req += 9;
+
+ wid = WID_SSID;
+ pWid_req[0] = (char)(wid&0x00FF);
+ pWid_req[1] = (char)((wid&0xFF00) >> 8);
+ pWid_req[2] = 6;
+ memcpy(&pWid_req[3], null_data, 6);
+ wid_req_len += 9;
+ pWid_req += 9;
+
+ wid_req[2] = (char)(wid_req_len&0x00FF);
+ wid_req[3] = (char)((wid_req_len&0xFF00) >> 8);
+
+ ret = wlan_send_wid_packet(priv, wid_req, wid_req_len, wid_msg_id);
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_DEBUG, "%s >>> ret = %d \n", __func__, ret);
+ return ret;
+}
+
+int wlan_set_txrate(wlan_private * priv, u8 mbps)
+{
+ int ret;
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "wlan_set_txrate <<< \n");
+ ret = wlan_generic_set_uchar(priv, WID_CURRENT_TX_RATE, mbps); //O FOR AUTO 1FOR 1MBPS
+
+ if ((priv->version == WLAN_VERSION_90_D) || (priv->version == WLAN_VERSION_90_E)) {
+ //huanglei add begin
+ ret = wlan_generic_set_ulong(priv, WID_MEMORY_ADDRESS, 0x50000104);
+ ret = wlan_generic_set_ushort(priv, WID_MEMORY_ACCESS_16BIT, 0x0101);
+ ret = wlan_generic_set_ulong(priv, WID_MEMORY_ADDRESS, 0x50000108);
+ ret = wlan_generic_set_ushort(priv, WID_MEMORY_ACCESS_16BIT, 0x0101);
+ ret = wlan_generic_set_ulong(priv, WID_MEMORY_ADDRESS, 0x5000010C);
+ ret = wlan_generic_set_ushort(priv, WID_MEMORY_ACCESS_16BIT, 0x0101);
+ ret = wlan_generic_set_ulong(priv, WID_MEMORY_ADDRESS, 0x50000110);
+ ret = wlan_generic_set_ushort(priv, WID_MEMORY_ACCESS_16BIT, 0x0101);
+ //huanglei add end
+ }
+
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "wlan_set_txrate success >>> \n");
+
+out:
+ return ret;
+}
+
+int wlan_get_fw_ver(wlan_private * priv, u32 * fw_ver)
+{
+ int ret = wlan_generic_get_ulong(priv, WID_SYS_FW_VER, (u8 *) fw_ver);
+
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "Get FW_VER 0x%04x\n", *fw_ver);
+out:
+ return ret;
+}
+
+int wlan_get_mac_addr(wlan_private * priv, u8 * mac_addr)
+{
+ int ret = wlan_generic_get_str(priv, WID_MAC_ADDR, mac_addr, ETH_ALEN, NULL);
+
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "STA MAC Address [%02x:%02x:%02x:%02x:%02x:%02x]\n",
+ mac_addr[0], mac_addr[1], mac_addr[2],
+ mac_addr[3], mac_addr[4], mac_addr[5]);
+out:
+ return ret;
+}
+
+int wlan_get_bssid(wlan_private * priv, u8 * bssid)
+{
+ int ret = 0;
+
+ memcpy(bssid, priv->curbssparams.bssid, ETH_ALEN);
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Get BSSID [%02x:%02x:%02x:%02x:%02x:%02x]\n",
+ bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
+
+ return ret;
+}
+
+int wlan_get_channel(wlan_private * priv, u8 * channel)
+{
+ int ret;
+
+ ret = wlan_generic_get_uchar(priv, WID_CURRENT_CHANNEL, channel);
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "Get Channel %d\n", *channel);
+out:
+ return ret;
+}
+
+int wlan_get_rssi(wlan_private *priv, u8 *rssi)
+{
+ int ret = 0;
+ u8 gRssi = 0;
+
+ ret = wlan_generic_get_uchar(priv, WID_RSSI, &gRssi);
+ if(!ret)
+ wlan_update_aver_rssi(priv, priv->curbssparams.bssid, gRssi);
+
+ gRssi = (u8)wlan_get_aver_rssi(priv, priv->curbssparams.bssid);
+ *rssi = gRssi;
+ return ret;
+}
+
+
+int wlan_set_mac_addr(wlan_private * priv, u8 * mac_addr)
+{
+ int ret;
+
+ ret = wlan_generic_set_str(priv, WID_MAC_ADDR, mac_addr, ETH_ALEN);
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Set STA MAC Address [%02x:%02x:%02x:%02x:%02x:%02x]\n",
+ mac_addr[0], mac_addr[1], mac_addr[2],
+ mac_addr[3], mac_addr[4], mac_addr[5]);
+out:
+ return ret;
+}
+
+int wlan_set_preamble(wlan_private * priv, u8 preamble)
+{
+ int ret;
+
+ ret = wlan_generic_set_uchar(priv, WID_PREAMBLE, preamble);
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "wlan_set_preamble \n");
+out:
+ return ret;
+}
+
+int wlan_set_scan_complete(wlan_private * priv)
+{
+ int ret;
+
+ ret = wlan_generic_set_uchar(priv, WID_NETWORK_INFO_EN, 0);
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+out:
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "wlan_set_scan_complete ret=%d \n", ret);
+ return ret;
+}
+
+int wlan_set_ssid(wlan_private * priv, u8 * ssid, u8 ssid_len)
+{
+ int ret;
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Set SSID: %s, len = %d\n", ssid, ssid_len);
+
+ ret = wlan_generic_set_str(priv, WID_SSID, ssid, ssid_len);
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "Set SSID Done\n");
+
+out:
+ return ret;
+}
+
+int wlan_get_ssid(wlan_private * priv, u8 * ssid, u8 * ssid_len)
+{
+ int ret;
+ u32 len = 0;
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "Get SSID \n");
+
+ ret = wlan_generic_get_str(priv, WID_SSID, ssid, 32, &len);
+ *ssid_len = len;
+ if (*ssid_len > 0)
+ ssid[*ssid_len] = '\0';
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Get SSID Done len:%d %s\n", *ssid_len,
+ (*ssid_len > 1) ? ssid : (u8 *) "NULL");
+
+ return ret;
+}
+
+int wlan_set_bssid(wlan_private * priv, u8 * bssid)
+{
+ int ret;
+
+ ret = wlan_generic_set_str(priv, WID_BSSID, bssid, ETH_ALEN);
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Set BSSID [%02x:%02x:%02x:%02x:%02x:%02x]\n",
+ bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
+out:
+ return ret;
+}
+
+int wlan_disconnect(wlan_private * priv)
+{
+ int ret;
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "wlan_disconnect \n");
+
+ wlan_remove_tx_data_queue(priv);
+ ret = wlan_generic_set_uchar(priv, WID_DISCONNECT, 0);
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "wlan_disconnect Done\n");
+
+out:
+ return ret;
+}
+
+int wlan_set_imode(wlan_private * priv, u8 imode)
+{
+ int ret;
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "Set IMode 0x%02x\n", imode);
+
+ ret = wlan_generic_set_uchar(priv, WID_802_11I_MODE, imode);
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "Set IMode Done\n");
+
+out:
+ return ret;
+}
+
+int wlan_set_authtype(wlan_private * priv, u8 authtype)
+{
+ int ret;
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Set AuthType 0x%02x\n", authtype);
+
+ ret = wlan_generic_set_uchar(priv, WID_AUTH_TYPE, authtype);
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "Set AuthType Done\n");
+
+out:
+ return ret;
+}
+
+int wlan_set_listen_interval(wlan_private * priv, u8 interval)
+{
+ int ret;
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Set wlan_set_listen_interval 0x%02x\n", interval);
+
+ ret = wlan_generic_set_uchar(priv, WID_LISTEN_INTERVAL, interval);
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Set wlan_set_listen_interval Done\n");
+out:
+ return ret;
+}
+
+int wlan_set_link_loss_threshold(wlan_private * priv, u8 threshold)
+{
+ int ret;
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Set wlan_set_link_loss_threshold 0x%02x\n", threshold);
+
+ ret = wlan_generic_set_uchar(priv, WID_LINK_LOSS_THRESHOLD, threshold);
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Set wlan_set_link_loss_threshold Done\n");
+
+out:
+ return ret;
+}
+
+int wlan_set_power_save(wlan_private * priv)
+{
+ int ret = 0;
+ if (priv->version == WLAN_VERSION_91 || priv->version == WLAN_VERSION_91_E|| priv->version == WLAN_VERSION_91_F) {
+ ret = wlan_generic_set_uchar(priv, WID_POWER_SAVE, 0x30);
+ if(ret){
+ WLAN_ERRP("wlan_generic_set_uchar WID_POWER_SAVE failed! \n");
+ }
+ }
+ return ret;
+
+}
+
+int wlan_set_wepkey(wlan_private * priv, u16 index, u8 * key, u8 key_len)
+{
+ int ret;
+ u8 key_str[26 + 1]; // plus 1 for debug print
+ u8 key_str_len;
+
+ if (key_len == KEY_LEN_WEP_40) {
+ sprintf(key_str, "%02x%02x%02x%02x%02x\n",
+ key[0], key[1], key[2], key[3], key[4]);
+ key_str_len = 10;
+ key_str[key_str_len] = '\0';
+ } else if (key_len == KEY_LEN_WEP_104) {
+ sprintf(key_str, "%02x%02x%02x%02x%02x"
+ "%02x%02x%02x%02x%02x"
+ "%02x%02x%02x\n",
+ key[0], key[1], key[2], key[3], key[4],
+ key[5], key[6], key[7], key[8], key[9],
+ key[10], key[11], key[12]);
+ key_str_len = 26;
+ key_str[key_str_len] = '\0';
+ } else {
+ WLAN_ERRP("Error in WEP Key length %d\n", key_len);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Set WEP KEY[%d]: %s\n", index, key_str);
+
+ ret = wlan_generic_set_str(priv,
+ (WID_WEP_KEY_VALUE0 + index), key_str,
+ key_str_len);
+ if (ret) {
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Set WEP KEY[%d] Done\n", index);
+
+out:
+ return ret;
+}
+
+static void dump_key(u8 * key, u8 key_len)
+{
+ WLAN_DBGP("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]);
+ WLAN_DBGP("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15]);
+ if (key_len > 16)
+ WLAN_DBGP("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ key[16], key[17], key[18], key[19], key[20], key[21], key[22], key[23]);
+ if (key_len > 24)
+ WLAN_DBGP("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ key[24], key[25], key[26], key[27], key[28], key[29], key[30], key[31]);
+}
+
+int wlan_set_ptk(wlan_private * priv, u8 * key, u8 key_len)
+{
+ int ret;
+ u8 key_str[32 + ETH_ALEN + 1];
+ u8 key_str_len = key_len + ETH_ALEN + 1;
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "Set PTK: len = %d\n", key_len);
+
+ if (WLAN_DBGLA(WLAN_DA_WID, WLAN_DL_VERB))
+ dump_key(key, key_len);
+
+ if (priv->connect_status != MAC_CONNECTED) {
+ WLAN_ERRP("Adding PTK while not connected\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /*----------------------------------------*/
+ /* STA Addr | KeyLength | Key */
+ /*----------------------------------------*/
+ /* 6 | 1 | KeyLength */
+ /*----------------------------------------*/
+
+ /*---------------------------------------------------------*/
+ /* key */
+ /*---------------------------------------------------------*/
+ /* Temporal Key | Rx Micheal Key | Tx Micheal Key */
+ /*---------------------------------------------------------*/
+ /* 16 bytes | 8 bytes | 8 bytes */
+ /*---------------------------------------------------------*/
+
+ memcpy(key_str, priv->curbssparams.bssid, ETH_ALEN);
+ key_str[6] = key_len;
+ memcpy(key_str + 7, key, 16);
+
+ /* swap TX MIC and RX MIC, wlan need RX MIC to be ahead */
+ if (key_len > 16) {
+ memcpy(key_str + 7 + 16, key + 24, 8);
+ memcpy(key_str + 7 + 24, key + 16, 8);
+ }
+
+ if (priv->is_wapi)
+ ret = wlan_generic_set_str(priv,
+ WID_ADD_WAPI_PTK, key_str,
+ key_str_len);
+ else
+ ret = wlan_generic_set_str(priv,
+ WID_ADD_PTK, key_str, key_str_len);
+ if (ret) {
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "Set PTK Done\n");
+
+out:
+ return ret;
+}
+
+int wlan_set_gtk(wlan_private * priv, u8 key_id,
+ u8 * key_rsc, u8 key_rsc_len, u8 * key, u8 key_len)
+{
+ int ret;
+ u8 key_str[32 + ETH_ALEN + 8 + 2];
+ u8 key_str_len = key_len + ETH_ALEN + 8 + 2;
+
+ /*---------------------------------------------------------*/
+ /* STA Addr | KeyRSC | KeyID | KeyLength | Key */
+ /*---------------------------------------------------------*/
+ /* 6 | 8 | 1 | 1 | KeyLength */
+ /*---------------------------------------------------------*/
+
+ /*-------------------------------------*/
+ /* key */
+ /*-------------------------------------*/
+ /* Temporal Key | Rx Micheal Key */
+ /*-------------------------------------*/
+ /* 16 bytes | 8 bytes */
+ /*-------------------------------------*/
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "Set GTK: len = %d\n", key_len);
+ if (WLAN_DBGLA(WLAN_DA_WID, WLAN_DL_VERB))
+ dump_key(key, key_len);
+
+ if (priv->connect_status != MAC_CONNECTED) {
+ WLAN_ERRP("Adding GTK while not connected\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ memcpy(key_str, priv->curbssparams.bssid, ETH_ALEN);
+ memcpy(key_str + 6, key_rsc, key_rsc_len);
+ key_str[14] = key_id;
+ key_str[15] = key_len;
+ memcpy(key_str + 16, key, 16);
+
+ /* swap TX MIC and RX MIC, wlan need RX MIC to be ahead */
+ if (key_len > 16) {
+ //memcpy(key_str + 16 + 16, key + 16, key_len - 16);
+ memcpy(key_str + 16 + 16, key + 24, 8);
+ memcpy(key_str + 16 + 24, key + 16, 8);
+ }
+
+ if (priv->is_wapi)
+ ret = wlan_generic_set_str(priv,
+ WID_ADD_WAPI_RX_GTK, key_str,
+ key_str_len);
+ else
+ ret = wlan_generic_set_str(priv,
+ WID_ADD_RX_GTK, key_str,
+ key_str_len);
+ if (ret) {
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "Set GTK Done\n");
+out:
+ return ret;
+}
+
+int wlan_set_pm_mode(wlan_private * priv, u8 pm_mode)
+{
+ int ret;
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Set PM Mode 0x%02x\n", pm_mode);
+
+ ret = wlan_generic_set_uchar(priv, WID_POWER_MANAGEMENT, pm_mode);
+ if (ret) {
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "Set PM Mode Done\n");
+
+out:
+ return ret;
+}
+
+int wlan_set_preasso_sleep(wlan_private * priv, u32 preasso_sleep)
+{
+ int ret;
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE,
+ "Set Preasso Sleep 0x%08x\n", preasso_sleep);
+
+ ret = wlan_generic_set_ulong(priv, WID_PREASSO_SLEEP, preasso_sleep);
+ if (ret) {
+ WLAN_ERRP("failed \n");
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "Set Preasso Sleep Done\n");
+
+out:
+ return ret;
+}
+
+int rda5890_set_preamble(wlan_private * priv, unsigned char preamble)
+{
+ int ret;
+
+ ret = wlan_generic_set_uchar(priv, WID_PREAMBLE, preamble);
+ if (ret) {
+ goto out;
+ }
+
+ WLAN_DBGLAP(WLAN_DA_WID, WLAN_DL_TRACE, "rda5890_set_preamble \n");
+out:
+ return ret;
+}
+
+int wlan_set_pta(wlan_private * priv, struct pta_param_s* param)
+{
+ int ret;
+
+ ret = wlan_generic_set_bin(priv, WID_PTA_PARAMETER, (u8*)param, sizeof(struct pta_param_s));
+ if (ret) {
+ WLAN_ERRP("set WID_PTA_PARAMETER failed \n");
+ }
+
+ return ret;
+}
diff --git a/drivers/net/wireless/rda/rda_wlan/wlan_wid.h b/drivers/net/wireless/rda/rda_wlan/wlan_wid.h
new file mode 100755
index 00000000..2a5bdf7e
--- /dev/null
+++ b/drivers/net/wireless/rda/rda_wlan/wlan_wid.h
@@ -0,0 +1,344 @@
+#ifndef __WLAN_WID_H__
+#define __WLAN_WID_H__
+
+#define MAX_STRING_LEN (256)
+#define MAX_CMD_LEN (MAX_STRING_LEN)
+#define WLAN_MAX_WID_LEN (MAX_CMD_LEN - 2)
+
+#define MAC_CONNECTED (1)
+#define MAC_DISCONNECTED (0)
+#define WID_STATUS_SUCCESS (1)
+
+#define print_mac(x) printk("%x %x %x %x %x %x \n", x[0], x[1], x[2],x[3], x[4], x[5])
+
+typedef enum
+{
+ G_SHORT_PREAMBLE = 0,
+ G_LONG_PREAMBLE = 1,
+ G_AUTO_PREAMBLE = 2
+}G_PREAMBLE_T;
+
+
+/* WID Data Types */
+typedef enum {
+ WID_CHAR = 0,
+ WID_SHORT = 1,
+ WID_INT = 2,
+ WID_STR = 3,
+ WID_BIN_DATA = 4
+} WID_TYPE_T;
+
+typedef enum{
+ HOST_MSG_DATAOUT = 0x10, /* Receive data from host */
+ HOST_MSG_DATAIN = 0x20, /* Transmit data to host */
+ HOST_MSG_CONFIGRSP = 0x30, /* Response to host */
+ HOST_MSG_CONFIGREQ = 0x40, /* Request from host */
+ HOST_MSG_ASYNCEVENT = 0x50
+}HOST_MSG_TYPE;
+
+
+/* WLAN Identifiers */
+typedef enum {
+ WID_NIL = -1,
+ WID_BSS_TYPE = 0x0000,
+ WID_CURRENT_TX_RATE = 0x0001,
+ WID_CURRENT_CHANNEL = 0x0002,
+ WID_PREAMBLE = 0x0003,
+ WID_11G_OPERATING_MODE = 0x0004,
+ WID_STATUS = 0x0005,
+ WID_11G_PROT_MECH = 0x0006,
+
+#ifdef MAC_HW_UNIT_TEST_MODE
+ WID_GOTO_SLEEP = 0x0007,
+#else /* MAC_HW_UNIT_TEST_MODE */
+ WID_SCAN_TYPE = 0x0007,
+#endif /* MAC_HW_UNIT_TEST_MODE */
+ WID_PRIVACY_INVOKED = 0x0008,
+ WID_KEY_ID = 0x0009,
+ WID_QOS_ENABLE = 0x000A,
+ WID_POWER_MANAGEMENT = 0x000B,
+ WID_802_11I_MODE = 0x000C,
+ WID_AUTH_TYPE = 0x000D,
+ WID_SITE_SURVEY = 0x000E,
+ WID_LISTEN_INTERVAL = 0x000F,
+ WID_DTIM_PERIOD = 0x0010,
+ WID_ACK_POLICY = 0x0011,
+ WID_RESET = 0x0012,
+ WID_PCF_MODE = 0x0013,
+ WID_CFP_PERIOD = 0x0014,
+ WID_BCAST_SSID = 0x0015,
+
+#ifdef MAC_HW_UNIT_TEST_MODE
+ WID_PHY_TEST_PATTERN = 0x0016,
+#else /* MAC_HW_UNIT_TEST_MODE */
+ WID_DISCONNECT = 0x0016,
+#endif /* MAC_HW_UNIT_TEST_MODE */
+
+ WID_READ_ADDR_SDRAM = 0x0017,
+ WID_TX_POWER_LEVEL_11A = 0x0018,
+ WID_REKEY_POLICY = 0x0019,
+ WID_SHORT_SLOT_ALLOWED = 0x001A,
+ WID_PHY_ACTIVE_REG = 0x001B,
+ WID_PHY_ACTIVE_REG_VAL = 0x001C,
+ WID_TX_POWER_LEVEL_11B = 0x001D,
+ WID_START_SCAN_REQ = 0x001E,
+ WID_RSSI = 0x001F,
+ WID_JOIN_REQ = 0x0020,
+ WID_ANTENNA_SELECTION = 0x0021,
+ WID_USER_CONTROL_ON_TX_POWER = 0x0027,
+ WID_MEMORY_ACCESS_8BIT = 0x0029,
+ WID_UAPSD_SUPPORT_AP = 0x002A,
+
+ WID_CURRENT_MAC_STATUS = 0x0031,
+ WID_AUTO_RX_SENSITIVITY = 0x0032,
+ WID_DATAFLOW_CONTROL = 0x0033,
+ WID_SCAN_FILTER = 0x0036,
+ WID_LINK_LOSS_THRESHOLD = 0x0037,
+ WID_AUTORATE_TYPE = 0x0038,
+ WID_CCA_THRESHOLD = 0x0039,
+
+ WID_802_11H_DFS_MODE = 0x003B,
+ WID_802_11H_TPC_MODE = 0x003C,
+
+ WID_PHY_REG_ADDR = 0x0040,
+ WID_PHY_REG_VAL = 0x0041,
+ WID_PTA_MODE = 0x0042,
+ WID_TRAP_TEST = 0x0043,
+ WID_PTA_BLOCK_BT = 0x0044,
+ WID_NETWORK_INFO_EN = 0x0045,
+ WID_RX_DATA_RATE = 0x004B,
+ WID_POWER_SAVE = 0x004C,
+
+ WID_RTS_THRESHOLD = 0x1000,
+ WID_FRAG_THRESHOLD = 0x1001,
+ WID_SHORT_RETRY_LIMIT = 0x1002,
+ WID_LONG_RETRY_LIMIT = 0x1003,
+ WID_CFP_MAX_DUR = 0x1004,
+ WID_PHY_TEST_FRAME_LEN = 0x1005,
+ WID_BEACON_INTERVAL = 0x1006,
+ WID_MEMORY_ACCESS_16BIT = 0x1008,
+
+ WID_RX_SENSE = 0x100B,
+ WID_ACTIVE_SCAN_TIME = 0x100C,
+ WID_PASSIVE_SCAN_TIME = 0x100D,
+ WID_SITE_SURVEY_SCAN_TIME = 0x100E,
+ WID_JOIN_TIMEOUT = 0x100F,
+ WID_AUTH_TIMEOUT = 0x1010,
+ WID_ASOC_TIMEOUT = 0x1011,
+ WID_11I_PROTOCOL_TIMEOUT = 0x1012,
+ WID_EAPOL_RESPONSE_TIMEOUT = 0x1013,
+ WID_CCA_BUSY_STATUS = 0x1014,
+
+ WID_FAILED_COUNT = 0x2000,
+ WID_RETRY_COUNT = 0x2001,
+ WID_MULTIPLE_RETRY_COUNT = 0x2002,
+ WID_FRAME_DUPLICATE_COUNT = 0x2003,
+ WID_ACK_FAILURE_COUNT = 0x2004,
+ WID_RECEIVED_FRAGMENT_COUNT = 0x2005,
+ WID_MULTICAST_RECEIVED_FRAME_COUNT = 0x2006,
+ WID_FCS_ERROR_COUNT = 0x2007,
+ WID_SUCCESS_FRAME_COUNT = 0x2008,
+ WID_PHY_TEST_PKT_CNT = 0x2009,
+ WID_PHY_TEST_TXD_PKT_CNT = 0x200A,
+ WID_TX_FRAGMENT_COUNT = 0x200B,
+ WID_TX_MULTICAST_FRAME_COUNT = 0x200C,
+ WID_RTS_SUCCESS_COUNT = 0x200D,
+ WID_RTS_FAILURE_COUNT = 0x200E,
+ WID_WEP_UNDECRYPTABLE_COUNT = 0x200F,
+ WID_REKEY_PERIOD = 0x2010,
+ WID_REKEY_PACKET_COUNT = 0x2011,
+#ifdef MAC_HW_UNIT_TEST_MODE
+ WID_Q_ENABLE_INFO = 0x2012,
+#else /* MAC_HW_UNIT_TEST_MODE */
+ WID_802_1X_SERV_ADDR = 0x2012,
+#endif /* MAC_HW_UNIT_TEST_MODE */
+ WID_STACK_IP_ADDR = 0x2013,
+ WID_STACK_NETMASK_ADDR = 0x2014,
+ WID_HW_RX_COUNT = 0x2015,
+ WID_MEMORY_ADDRESS = 0x201E,
+ WID_MEMORY_ACCESS_32BIT = 0x201F,
+ WID_RF_REG_VAL = 0x2021,
+ WID_FIRMWARE_INFO = 0x2023,
+
+ WID_SYS_FW_VER = 0x2801,
+ WID_SYS_DBG_LVL = 0x2802,
+ WID_SYS_DBG_AREA = 0x2803,
+ WID_UT_MODE = 0x2804,
+ WID_UT_TX_LEN = 0x2805,
+ WID_PTA_CTS_FRAME_LEN = 0x2806,
+ WID_PREASSO_SLEEP = 0x2807,
+
+ WID_SSID = 0x3000,
+ WID_FIRMWARE_VERSION = 0x3001,
+ WID_OPERATIONAL_RATE_SET = 0x3002,
+ WID_BSSID = 0x3003,
+ WID_WEP_KEY_VALUE0 = 0x3004,
+ WID_WEP_KEY_VALUE1 = 0x3005,
+ WID_WEP_KEY_VALUE2 = 0x3006,
+ WID_WEP_KEY_VALUE3 = 0x3007,
+ WID_802_11I_PSK = 0x3008,
+ WID_HCCA_ACTION_REQ = 0x3009,
+ WID_802_1X_KEY = 0x300A,
+ WID_HARDWARE_VERSION = 0x300B,
+ WID_MAC_ADDR = 0x300C,
+ WID_PHY_TEST_DEST_ADDR = 0x300D,
+ WID_PHY_TEST_STATS = 0x300E,
+ WID_PHY_VERSION = 0x300F,
+ WID_SUPP_USERNAME = 0x3010,
+ WID_SUPP_PASSWORD = 0x3011,
+ WID_SITE_SURVEY_RESULTS = 0x3012,
+ WID_RX_POWER_LEVEL = 0x3013,
+
+ WID_ADD_WEP_KEY = 0x3019,
+ WID_REMOVE_WEP_KEY = 0x301A,
+ WID_ADD_PTK = 0x301B,
+ WID_ADD_RX_GTK = 0x301C,
+ WID_ADD_TX_GTK = 0x301D,
+ WID_REMOVE_KEY = 0x301E,
+ WID_ASSOC_REQ_INFO = 0x301F,
+ WID_ASSOC_RES_INFO = 0x3020,
+ WID_UPDATE_RF_SUPPORTED_INFO = 0x3021,
+ WID_COUNTRY_IE = 0x3022,
+
+ WID_WAPI_ASSOC_IE = 0x3023,
+ WID_ADD_WAPI_PTK = 0x3024,
+ WID_ADD_WAPI_RX_GTK = 0x3025,
+ WID_ADD_WAPI_TX_GTK = 0x3026,
+ WID_HIDE_SSID = 0x3027,
+ //huanglei add for wps
+ WID_GEN_ASSOC_IE = 0x3028,
+
+ WID_CONFIG_HCCA_ACTION_REQ = 0x4000,
+ WID_UAPSD_CONFIG = 0x4001,
+ WID_UAPSD_STATUS = 0x4002,
+ WID_WMM_AP_AC_PARAMS = 0x4003,
+ WID_WMM_STA_AC_PARAMS = 0x4004,
+ WID_NEWORK_INFO = 0x4005,
+ WID_STA_JOIN_INFO = 0x4006,
+ WID_CONNECTED_STA_LIST = 0x4007,
+ WID_HUT_STATS = 0x4082,
+ WID_STATISTICS = 0x4008,
+ WID_MEMORY_DUMP = 0x4009,
+ WID_LOAD_TRAP_MAP = 0x400a,
+ WID_AGC_DGC_TBL = 0x400b,
+ // miaodefang for PTA
+ WID_PTA_PARAMETER = 0x4010,
+
+ /* NMAC Binary WID list */
+ WID_11N_AUTORATE_TABLE = 0x4080,
+
+ WID_ALL = 0x7FFE,
+ WID_MAX = 0xFFFF
+} WID_T;
+
+typedef enum
+{
+ PTA_NONE_PROTECT = 0,
+ PTA_NULL_DATA_PROTECT,
+ PTA_PS_POLL_PROTECT,
+ PTA_SELF_CTS_PROTECT,
+ PTA_AUTO_PROTECT
+
+} PTA_PROTECT_MODE_T;
+
+struct pta_param_s
+{
+ u8 prot_mode;
+ u8 mac_rate; // 0: MIN_basic rate
+ u8 hw_retry;
+ u8 sw_retry;
+ u8 cca_bypass;
+
+ u8 restore;
+
+ u16 active_time; /* Unit is 100us */
+ u16 thresh_time; /* Unit is 100us */
+
+ u16 auto_prot_thresh_time; /* Unit is 100us */
+
+ /*
+ * BIT0: Check high priority Q NULL before send PS_Poll or NULL frame
+ * BIT1: Check normal priority Q(AC_VO_Q) NULL before send PS_Poll or NULL frame
+ * BIT2: Check AC_VI_Q NULL before send PS_Poll or NULL frame
+ * BIT3: Check AC_BE_Q NULL before send PS_Poll or NULL frame
+ * BIT4: Check AC_BK_Q NULL before send PS_Poll or NULL frame
+ * BIT5: Check g_more_data_expected when send PS_Poll
+ */
+ u16 flags;
+
+} __packed;
+
+void wlan_clean_wid_node(wlan_wid_packet_node * widNode);
+wlan_wid_packet_node * wlan_get_wid_node(wlan_private * priv);
+void wlan_put_wid_node_in_freeQ(wlan_private * priv, wlan_wid_packet_node * widNode);
+wlan_wid_packet_node * wlan_get_wid_node_in_freeQ(wlan_private * priv);
+int wlan_put_wid_node_in_pendingQ(wlan_private * priv, wlan_wid_packet_node * widNode);
+wlan_wid_packet_node * wlan_get_wid_node_in_pendingQ(wlan_private * priv);
+int wlan_alloc_wid_queue(wlan_private * priv);
+int wlan_release_wid_pending_queue(wlan_private *priv);
+int wlan_free_wid_queue(wlan_private * priv);
+int wlan_read_wid_rsp_polling(wlan_private *priv);
+int wlan_generic_get(wlan_private *priv,
+ u16 wid, u8 *val, u16 val_len, u32*rspLen, WID_TYPE_T type);
+int wlan_generic_get_uchar(wlan_private *priv,
+ u16 wid, u8 *val);
+
+int wlan_generic_get_ushort(wlan_private *priv,
+ u16 wid, u8 *val);
+int wlan_generic_get_ulong(wlan_private *priv,
+ u16 wid, u8 *val);
+int wlan_generic_get_str(wlan_private *priv,
+ u16 wid, u8 *val, u32 len, u32 * rspLen);
+int wlan_send_wid_packet(wlan_private *priv, u8 *val, u16 val_len,
+ u8 wid_msg_id);
+int wlan_generic_set(wlan_private *priv,
+ u16 wid, u8 *val, u16 val_len, WID_TYPE_T type);
+int wlan_generic_set_uchar(wlan_private *priv,
+ u16 wid, u8 val);
+int wlan_generic_set_ushort(wlan_private *priv,
+ u16 wid, u16 val);
+int wlan_generic_set_ulong(wlan_private *priv,
+ u16 wid, u32 val);
+int wlan_generic_set_str(wlan_private *priv,
+ u16 wid, u8* val, u32 val_len);
+int wlan_generic_set_bin(wlan_private * priv, u16 wid, u8 * val, u32 val_len);
+int wlan_set_core_init_patch(wlan_private *priv, const u32 (*data)[2], u8 num);
+int wlan_set_core_patch(wlan_private *priv, const u8 (*patch)[2], u8 num);
+void wlan_wid_response(wlan_private *priv,
+ u8 *wid_rsp, u16 wid_rsp_len);
+int wlan_set_scan_timeout(wlan_private *priv);
+int wlan_start_scan_enable_network_info(wlan_private *priv);
+int wlan_start_join(wlan_private *priv);
+int wlan_set_txrate(wlan_private *priv, u8 mbps);
+int wlan_get_fw_ver(wlan_private *priv, u32 *fw_ver);
+int wlan_get_mac_addr(wlan_private *priv, u8 *mac_addr);
+int wlan_get_bssid(wlan_private *priv, u8 *bssid);
+int wlan_get_channel(wlan_private *priv, u8 *channel);
+int wlan_get_rssi(wlan_private *priv, u8 *rssi);
+int wlan_set_mac_addr(wlan_private *priv, u8 *mac_addr);
+int wlan_set_preamble(wlan_private *priv, u8 preamble);
+int wlan_set_scan_complete(wlan_private *priv);
+int wlan_set_ssid(wlan_private *priv,
+ u8 *ssid, u8 ssid_len);
+int wlan_get_ssid(wlan_private *priv,
+ u8 *ssid, u8 *ssid_len);
+int wlan_set_bssid(wlan_private *priv, u8 *bssid);
+int wlan_disconnect(wlan_private *priv);
+int wlan_disconnect_silent(wlan_private * priv);
+int wlan_set_imode(wlan_private *priv, u8 imode);
+int wlan_set_authtype(wlan_private *priv, u8 authtype);
+int wlan_set_listen_interval(wlan_private *priv, u8 interval);
+int wlan_set_link_loss_threshold(wlan_private *priv, u8 threshold);
+int wlan_set_power_save(wlan_private *priv);
+int wlan_set_wepkey(wlan_private *priv,
+ u16 index, u8 *key, u8 key_len);
+int wlan_set_ptk(wlan_private *priv,
+ u8 *key, u8 key_len);
+int wlan_set_gtk(wlan_private *priv, u8 key_id,
+ u8 *key_rsc, u8 key_rsc_len,
+ u8 *key, u8 key_len);
+int wlan_set_pm_mode(wlan_private *priv, u8 pm_mode);
+int wlan_set_preasso_sleep(wlan_private *priv, u32 preasso_sleep);
+int rda5890_set_preamble(wlan_private *priv, unsigned char preamble);
+int wlan_set_pta(wlan_private * priv, struct pta_param_s* param);
+#endif