summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rda/rda_combo_power_ctrl
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rda/rda_combo_power_ctrl')
-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
7 files changed, 5056 insertions, 0 deletions
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");