diff options
Diffstat (limited to 'drivers/net/wireless/rda/rda_combo_power_ctrl')
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"); |