From: 许盛飞 Date: Wed, 17 Oct 2012 01:50:42 +0000 (+0800) Subject: rk30:add interface for rk30_adc_battery X-Git-Tag: firefly_0821_release~8399 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=249086bfe6194924c0d7960b23370af0a6df05b9;p=firefly-linux-kernel-4.4.55.git rk30:add interface for rk30_adc_battery --- diff --git a/arch/arm/mach-rk30/include/mach/board.h b/arch/arm/mach-rk30/include/mach/board.h index cbf02d079490..058145e90a9f 100755 --- a/arch/arm/mach-rk30/include/mach/board.h +++ b/arch/arm/mach-rk30/include/mach/board.h @@ -11,23 +11,48 @@ #include #include #include - /* adc battery */ struct rk30_adc_battery_platform_data { - int (*io_init)(void); - int (*io_deinit)(void); + int (*io_init)(void); + int (*io_deinit)(void); + int (*is_dc_charging)(void); + int (*charging_ok)(void); + + int (*is_usb_charging)(void); + int spport_usb_charging ; + + int dc_det_pin; + int batt_low_pin; + int charge_ok_pin; + int charge_set_pin; + + int dc_det_level; + int batt_low_level; + int charge_ok_level; + int charge_set_level; + + int adc_channel; + + int dc_det_pin_pull; //pull up/down enable/disbale + int batt_low_pin_pull; + int charge_ok_pin_pull; + int charge_set_pin_pull; + + int low_voltage_protection; // low voltage protection + + int charging_sleep; // don't have lock,if chargeing_sleep = 0;else have lock + + + int save_capacity; //save capacity to /data/bat_last_capacity.dat, suggested use + + int reference_voltage; // the rK2928 is 3300;RK3066 and rk29 are 2500;rk3066B is 1800; + int pull_up_res; //divider resistance , pull-up resistor + int pull_down_res; //divider resistance , pull-down resistor - int dc_det_pin; - int batt_low_pin; - int charge_ok_pin; - int charge_set_pin; + int time_down_discharge; //the time of capactiy drop 1% --discharge + int time_up_charge; //the time of capacity up 1% ---charging -// int adc_channel; - int dc_det_level; - int batt_low_level; - int charge_ok_level; - int charge_set_level; }; #ifndef _LINUX_WLAN_PLAT_H_ diff --git a/drivers/power/rk30_adc_battery.c b/drivers/power/rk30_adc_battery.c index 7a4b4460f5cf..9cc477577a44 100644 --- a/drivers/power/rk30_adc_battery.c +++ b/drivers/power/rk30_adc_battery.c @@ -71,9 +71,14 @@ module_param_named(dbg_level, rk30_battery_dbg_level, int, 0644); #define NUM_CHARGE_FULL_DELAY_TIMES ((CHARGE_FULL_DELAY_TIMES * 1000) / TIMER_MS_COUNTS) //³äµçÂú״̬³ÖÐøʱ¼ä³¤¶È #define NUM_USBCHARGE_IDENTIFY_TIMES ((USBCHARGE_IDENTIFY_TIMES * 1000) / TIMER_MS_COUNTS) //³äµçÂú״̬³ÖÐøʱ¼ä³¤¶È +#define CHARGE_IS_OK 1 +#define INVALID_CHARGE_CHECK -1 + #if defined(CONFIG_ARCH_RK3066B) #define BAT_DEFINE_VALUE 1800 +#elif defined(CONFIG_ARCH_RK2928) +#define BAT_DEFINE_VALUE 3300 #else #define BAT_DEFINE_VALUE 2500 @@ -275,39 +280,48 @@ static int rk30_adc_battery_get_charge_level(struct rk30_adc_battery_data *bat) charge_on = 1; } } + else{ + if(pdata->is_dc_charging) + charge_on =pdata->is_dc_charging(); + } + + #endif +#if 1 + if (pdata->spport_usb_charging) //is usb charging + if(pdata->is_usb_charging) + charge_on = pdata->is_usb_charging(); -#if defined (CONFIG_BATTERY_RK30_USB_CHARGE) - if (charge_on == 0){ - if (suspend_flag) - return; - if (1 == dwc_vbus_status()) { //¼ì²âµ½USB²åÈ룬µ«ÊÇÎÞ·¨Ê¶±ðÊÇ·ñÊdzäµçÆ÷ - //ͨ¹ýÑÓʱ¼ì²âPCʶ±ð±êÖ¾£¬Èç¹û³¬Ê±¼ì²â²»µ½£¬ËµÃ÷Êdzäµç - if (0 == get_msc_connect_flag()){ //²åÈë³äµçÆ÷ʱ¼ä´óÓÚÒ»¶¨Ê±¼äÖ®ºó£¬¿ªÊ¼½øÈë³äµç״̬ - if (++gBatUsbChargeCnt >= NUM_USBCHARGE_IDENTIFY_TIMES){ - gBatUsbChargeCnt = NUM_USBCHARGE_IDENTIFY_TIMES + 1; - charge_on = 1; - } - } //·ñÔò£¬²»½øÈë³äµçģʽ - } - else{ - gBatUsbChargeCnt = 0; - if (2 == dwc_vbus_status()) { - charge_on = 1; - } - } - } #endif return charge_on; } +static int is_charge_ok(struct rk30_adc_battery_data *bat) +{ + int charge_is_ok = 0; + struct rk30_adc_battery_platform_data *pdata = bat->pdata; + + if((pdata->charge_ok_pin == INVALID_GPIO)&& ( pdata->charging_ok == NULL)) + return -1; + + if (pdata->charge_ok_pin != INVALID_GPIO){ + if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level) + { + charge_is_ok =1; + } + }else if( pdata->charging_ok) + { + charge_is_ok = pdata->charging_ok(); + } + return charge_is_ok; + + +} //int old_charge_level; static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat) { int charge_level; - - struct rk30_adc_battery_platform_data *pdata = bat->pdata; - +// struct rk30_adc_battery_platform_data *pdata = bat->pdata; charge_level = rk30_adc_battery_get_charge_level(bat); //¼ì²â³äµç״̬±ä»¯Çé¿ö @@ -330,8 +344,9 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat) bat->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING; } else{ - //CHARGE - if (pdata->charge_ok_pin == INVALID_GPIO){ //no charge_ok_pin + //CHARGE + if( is_charge_ok(bat) == INVALID_CHARGE_CHECK){ + //if (pdata->charge_ok_pin == INVALID_GPIO){ //no charge_ok_pin if (bat->bat_capacity == 100){ if (bat->bat_status != POWER_SUPPLY_STATUS_FULL){ @@ -344,7 +359,7 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat) } } else{ // pin of charge_ok_pin - if (gpio_get_value(pdata->charge_ok_pin) != pdata->charge_ok_level){ + if (is_charge_ok(bat) != CHARGE_IS_OK ){ bat->full_times = 0; bat->bat_status = POWER_SUPPLY_STATUS_CHARGING; @@ -357,7 +372,7 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat) bat->full_times = NUM_CHARGE_FULL_DELAY_TIMES + 1; } - if ((bat->full_times >= NUM_CHARGE_FULL_DELAY_TIMES) && (bat->bat_capacity >= 99)){ + if ((bat->full_times >= NUM_CHARGE_FULL_DELAY_TIMES) && (bat->bat_capacity >= 95)){ if (bat->bat_status != POWER_SUPPLY_STATUS_FULL){ bat->bat_status = POWER_SUPPLY_STATUS_FULL; bat->bat_capacity = 100; @@ -373,6 +388,32 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat) return charge_level; } +//#define adc_to_voltage(adc_val) ((adc_val * BAT_DEFINE_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R)) + +static int rk_adc_voltage(int value) +{ + int voltage; + + int ref_voltage; //reference_voltage + int pullup_res; + int pulldown_res; + + ref_voltage = gBatteryData ->pdata->reference_voltage; + pullup_res = gBatteryData ->pdata->pull_up_res; + pulldown_res = gBatteryData ->pdata->pull_down_res; + + if(ref_voltage && pullup_res && pulldown_res){ + + voltage = ((value * ref_voltage * (pullup_res + pulldown_res)) / (1024 * pulldown_res)); + + }else{ + voltage = adc_to_voltage(value); + } + + + return voltage; + +} static int *pSamples; static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat) @@ -385,7 +426,7 @@ static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat) value = bat->adc_val; adc_async_read(bat->client); - *pSamples++ = adc_to_voltage(value); + *pSamples++ = rk_adc_voltage(value); bat->bat_status_cnt++; if (bat->bat_status_cnt > NUM_VOLTAGE_SAMPLE) bat->bat_status_cnt = NUM_VOLTAGE_SAMPLE + 1; @@ -430,7 +471,7 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba if (rk30_adc_battery_get_charge_level(bat)){ //charge if(BatVoltage >= (p[BATT_NUM - 1].charge_vol)){ - capacity = 100; + capacity = 99; } else{ if(BatVoltage <= (p[0].charge_vol)){ @@ -470,12 +511,15 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba } return capacity; -} + } + static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat) { int capacity = 0; - struct rk30_adc_battery_platform_data *pdata = bat->pdata; +// struct rk30_adc_battery_platform_data *pdata = bat->pdata; + int timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE; + int timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE; //³ä·Åµç״̬±ä»¯ºó£¬BufferÌîÂú֮ǰ£¬²»¸üРif (bat->bat_status_cnt < NUM_VOLTAGE_SAMPLE) { @@ -488,8 +532,14 @@ static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat) if (rk30_adc_battery_get_charge_level(bat)){ if (capacity > bat->bat_capacity){ + if(capacity > bat->bat_capacity + 10 ) + timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE -10; //5s + else if(capacity > bat->bat_capacity + 7 ) + timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE -5; //10s + else if(capacity > bat->bat_capacity + 3 ) + timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE - 2; // 13 //ʵ¼Ê²ÉÑùµ½µÄÈÝÁ¿±ÈÏÔʾµÄÈÝÁ¿´ó£¬Öð¼¶ÉÏÉý - if (++(bat->gBatCapacityDisChargeCnt) >= NUM_CHARGE_MIN_SAMPLE){ + if (++(bat->gBatCapacityDisChargeCnt) >= timer_of_charge_sample){ bat->gBatCapacityDisChargeCnt = 0; if (bat->bat_capacity < 99){ bat->bat_capacity++; @@ -501,11 +551,19 @@ static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat) else{ // ʵ¼ÊµÄÈÝÁ¿±È²ÉÑù±È ÏÔʾµÄÈÝÁ¿Ð¡ bat->gBatCapacityDisChargeCnt = 0; (bat->gBatCapacityChargeCnt)++; - - if (pdata->charge_ok_pin != INVALID_GPIO){ - if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level){ + pr_bat("------------- is_charge_ok(bat)=%d\n", is_charge_ok(bat)); + if( is_charge_ok(bat) != INVALID_CHARGE_CHECK){ + //if (pdata->charge_ok_pin != INVALID_GPIO){ + //if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level){ + if( is_charge_ok(bat) == CHARGE_IS_OK){ + if(capacity > bat->bat_capacity + 10 ) + timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE -13; // 2s + else if(capacity > bat->bat_capacity + 7 ) + timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE -10; //10s + else if(capacity > bat->bat_capacity + 2 ) + timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE -8; //7s //¼ì²âµ½µç³Ø³äÂú±êÖ¾£¬Í¬Ê±³¤Ê±¼äÄÚ³äµçµçѹÎޱ仯£¬¿ªÊ¼Æô¶¯¼Æʱ³äµç£¬¿ìËÙÉÏÉýÈÝÁ¿ - if (bat->gBatCapacityChargeCnt >= NUM_CHARGE_MIN_SAMPLE){ + if (bat->gBatCapacityChargeCnt >= timer_of_charge_sample){ bat->gBatCapacityChargeCnt = 0; if (bat->bat_capacity < 99){ bat->bat_capacity++; @@ -559,7 +617,7 @@ static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat) if ((bat->bat_capacity >= 85) &&(bat->gBatCapacityChargeCnt > NUM_CHARGE_MAX_SAMPLE)){ bat->gBatCapacityChargeCnt = (NUM_CHARGE_MAX_SAMPLE - NUM_CHARGE_MID_SAMPLE); - if (bat->bat_capacity < 99){ + if (bat->bat_capacity <= 99){ bat->bat_capacity++; bat->bat_change = 1; } @@ -573,7 +631,14 @@ static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat) else{ //·Åµçʱ,Ö»ÔÊÐíµçѹϽµ if (capacity < bat->bat_capacity){ - if (++(bat->gBatCapacityDisChargeCnt) >= NUM_DISCHARGE_MIN_SAMPLE){ + if(capacity + 10 > bat->bat_capacity ) + timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -10; //5s + else if(capacity + 7 > bat->bat_capacity ) + timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -5; //10s + else if(capacity + 3> bat->bat_capacity ) + timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 2; // 13 + + if (++(bat->gBatCapacityDisChargeCnt) >= timer_of_discharge_sample){ bat->gBatCapacityDisChargeCnt = 0; if (bat->bat_capacity > 0){ bat->bat_capacity-- ; @@ -597,6 +662,8 @@ static void rk30_adc_battery_poweron_capacity_check(void) new_capacity = gBatteryData->bat_capacity; old_capacity = rk30_adc_battery_load_capacity(); + + pr_bat("------------old_capacity---%d\n",old_capacity); if ((old_capacity <= 0) || (old_capacity >= 100)){ old_capacity = new_capacity; } @@ -623,7 +690,7 @@ static void rk30_adc_battery_poweron_capacity_check(void) } - //printk("capacity = %d, new_capacity = %d, old_capacity = %d\n",gBatteryData->bat_capacity, new_capacity, old_capacity); + pr_bat("capacity = %d, new_capacity = %d, old_capacity = %d\n",gBatteryData->bat_capacity, new_capacity, old_capacity); gBatteryData->bat_change = 1; } @@ -639,7 +706,11 @@ static int rk30_adc_battery_get_usb_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_ONLINE: if (psy->type == POWER_SUPPLY_TYPE_USB) - val->intval = get_msc_connect_flag(); + // val->intval = get_msc_connect_flag(); + if (gBatteryData->pdata->spport_usb_charging) //is usb charging + if(gBatteryData->pdata->is_usb_charging) + val->intval = gBatteryData ->pdata->is_usb_charging(); + printk("%s:%d\n",__FUNCTION__,val->intval); break; @@ -928,8 +999,7 @@ static void rk30_adc_battery_timer_work(struct work_struct *work) gBatteryData->resume = false; } #endif - - + rk30_adc_battery_status_samples(gBatteryData); if (gBatteryData->poweron_check){ @@ -940,18 +1010,20 @@ static void rk30_adc_battery_timer_work(struct work_struct *work) rk30_adc_battery_voltage_samples(gBatteryData); rk30_adc_battery_capacity_samples(gBatteryData); - if( 1 == rk30_adc_battery_get_charge_level(gBatteryData)){ // charge - if(0 == gBatteryData->status_lock ){ - wake_lock(&batt_wake_lock); //lock - gBatteryData->status_lock = 1; - } - } - else{ - if(1 == gBatteryData->status_lock ){ - wake_unlock(&batt_wake_lock); //unlock - gBatteryData->status_lock = 0; + if( 0 == gBatteryData ->pdata ->charging_sleep){ + if( 1 == rk30_adc_battery_get_charge_level(gBatteryData)){ // charge + if(0 == gBatteryData->status_lock ){ + wake_lock(&batt_wake_lock); //lock + gBatteryData->status_lock = 1; + } } + else{ + if(1 == gBatteryData->status_lock ){ + wake_unlock(&batt_wake_lock); //unlock + gBatteryData->status_lock = 0; + } + } } @@ -960,6 +1032,11 @@ static void rk30_adc_battery_timer_work(struct work_struct *work) gBatteryData->bat_change = 0; rk30_adc_battery_put_capacity(gBatteryData->bat_capacity); power_supply_changed(&rk30_battery_supply); +#if defined (CONFIG_BATTERY_RK30_AC_CHARGE) + if (gBatteryData->pdata->dc_det_pin == INVALID_GPIO){ + power_supply_changed(&rk30_ac_supply); + } +#endif } if (rk30_battery_dbg_level){ @@ -967,8 +1044,8 @@ static void rk30_adc_battery_timer_work(struct work_struct *work) { AdcTestCnt = 0; - printk("Status = %d, RealAdcVal = %d, RealVol = %d,gBatVol = %d, gBatCap = %d, RealCapacity = %d, dischargecnt = %d, chargecnt = %d\n", - gBatteryData->bat_status, gBatteryData->adc_val, adc_to_voltage(gBatteryData->adc_val), + pr_bat("Status = %d, RealAdcVal = %d, RealVol = %d,gBatVol = %d, gBatCap = %d, RealCapacity = %d, dischargecnt = %d, chargecnt = %d\n", + gBatteryData->bat_status, gBatteryData->adc_val, rk_adc_voltage(gBatteryData->adc_val), gBatteryData->bat_voltage, gBatteryData->bat_capacity, gBatteryData->capacitytmp, gBatteryData->gBatCapacityDisChargeCnt,gBatteryData-> gBatCapacityChargeCnt); } @@ -984,6 +1061,7 @@ static int rk30_adc_battery_io_init(struct rk30_adc_battery_platform_data *pdata if (pdata->io_init) { pdata->io_init(); + return 0; } //charge control pin @@ -1048,7 +1126,7 @@ error: return -1; } -//extern void kernel_power_off(void); +extern void kernel_power_off(void); static void rk30_adc_battery_check(struct rk30_adc_battery_data *bat) { int i; @@ -1094,14 +1172,14 @@ static void rk30_adc_battery_check(struct rk30_adc_battery_data *bat) } - +#if 0 #if 1 rk30_adc_battery_poweron_capacity_check(); #else gBatteryData->poweron_check = 1; #endif gBatteryData->poweron_check = 0; - +#endif /******************************************* //¿ª»ú²ÉÑùµ½µÄµçѹºÍÉϴιػú±£´æµçѹÏà²î½Ï´ó£¬Ôõô´¦Àí£¿ if (bat->bat_capacity > old_capacity) @@ -1122,11 +1200,12 @@ if ((old_capacity > bat->bat_capacity) > 20) if (bat->bat_capacity == 0) bat->bat_capacity = 1; -#if 0 - if ((bat->bat_voltage <= batt_table[0].dis_charge_vol+ 50)&&(bat->bat_status != POWER_SUPPLY_STATUS_CHARGING)){ - kernel_power_off(); - } -#endif + if(1==gBatteryData -> pdata->low_voltage_protection) + + if ((bat->bat_voltage <= batt_table[0].dis_charge_vol+ 50)&&(bat->bat_status != POWER_SUPPLY_STATUS_CHARGING)){ + kernel_power_off(); + } + } static void rk30_adc_battery_callback(struct adc_client *client, void *param, int result) @@ -1184,8 +1263,9 @@ static int rk30_adc_battery_probe(struct platform_device *pdev) ret = -ENOMEM; goto err_data_alloc_failed; } + + memset(data, 0, sizeof(struct rk30_adc_battery_data)); gBatteryData = data; - platform_set_drvdata(pdev, data); data->pdata = pdata; @@ -1198,7 +1278,10 @@ static int rk30_adc_battery_probe(struct platform_device *pdev) memset(data->adc_samples, 0, sizeof(int)*(NUM_VOLTAGE_SAMPLE + 2)); //register adc for battery sample - client = adc_register(0, rk30_adc_battery_callback, NULL); //pdata->adc_channel = ani0 + if(0 == pdata->adc_channel) + client = adc_register(0, rk30_adc_battery_callback, NULL); //pdata->adc_channel = ani0 + else + client = adc_register(pdata->adc_channel, rk30_adc_battery_callback, NULL); if(!client) goto err_adc_register_failed; @@ -1224,9 +1307,16 @@ static int rk30_adc_battery_probe(struct platform_device *pdev) data->wq = create_singlethread_workqueue("adc_battd"); INIT_DELAYED_WORK(&data->delay_work, rk30_adc_battery_timer_work); + //Power on Battery detect rk30_adc_battery_check(data); - queue_delayed_work(data->wq, &data->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS)); + if(1 == pdata->save_capacity ){ + queue_delayed_work(data->wq, &data->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS*10)); + gBatteryData->poweron_check = 1; + }else{ + queue_delayed_work(data->wq, &data->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS)); + gBatteryData->poweron_check = 0; + } #if defined (CONFIG_BATTERY_RK30_AC_CHARGE) ret = power_supply_register(&pdev->dev, &rk30_ac_supply); @@ -1342,7 +1432,9 @@ static void __exit rk30_adc_battery_exit(void) platform_driver_unregister(&rk30_adc_battery_driver); } -subsys_initcall(rk30_adc_battery_init);//subsys_initcall(rk30_adc_battery_init); +//subsys_initcall(rk30_adc_battery_init);//subsys_initcall(rk30_adc_battery_init); +module_init(rk30_adc_battery_init);//subsys_initcall(rk30_adc_battery_init); + module_exit(rk30_adc_battery_exit); MODULE_DESCRIPTION("Battery detect driver for the rk30");