(no commit message)
author罗伟 <lw@rock-chips.com>
Sat, 29 May 2010 06:08:40 +0000 (06:08 +0000)
committer黄涛 <huangtao@rock-chips.com>
Mon, 21 Jun 2010 05:35:20 +0000 (13:35 +0800)
drivers/power/rk2818_battery.c

index a7a5ba28e004e892c82831aea3ffbe498ea220b1..fac5d031b94b34cf99e57265989946143b0b369b 100644 (file)
 #include <mach/adc.h>
 #include <mach/iomux.h>
 
-#if 0
+#if 1
 #define DBG(x...)   printk(x)
 #else
 #define DBG(x...)
 #endif
 
-#if 0
-#define NUM_BAT        3
-#define NUM_ELECTRICITY        10
-
-#define BAT_CAP_1500MAH                0
-#define BAT_CAP_1200MAH                1
-#define BAT_CAP_1100MAH                2
-
-#define ELECTRICITY_1000MA     0
-#define ELECTRICITY_900MA      1
-#define ELECTRICITY_800MA      2
-#define ELECTRICITY_700MA      3
-#define ELECTRICITY_600MA      4
-#define ELECTRICITY_500MA      5
-#define ELECTRICITY_400MA      6
-#define ELECTRICITY_300MA      7
-#define ELECTRICITY_200MA      8
-#define ELECTRICITY_100MA      9
-
-#define BAT_SELECT     BAT_CAP_1200MAH
-#define ELECTRICITY_SELECT     ELECTRICITY_200MA
-
-//about 10 minutes before battery is exhaust for different bat and electricity
-static int BatMinVoltage[NUM_BAT][NUM_ELECTRICITY] = 
-{
-{3410, 3450, 3480, 3460, 3480, 3500, 3510, 3470, 3420, 3430},
-{3360, 3400, 3410, 3400, 3430, 3430, 3460, 3480, 3440, 3330},
-{3360, 3400, 3410, 3410, 3440, 3460, 3480, 3470, 3440, 3360},
-};
-
-#define BATT_MAX_VOL_VALUE     4300
-#define BATT_NOMAL_VOL_VALUE  3900
-#define        BATT_ZERO_VOL_VALUE  BatMinVoltage[BAT_SELECT][ELECTRICITY_SELECT]
-#endif
-
 /*******************ÒÔϲÎÊý¿ÉÒÔÐÞ¸Ä******************************/
 #define        TIMER_MS_COUNTS         50              //¶¨Ê±Æ÷µÄ³¤¶Èms
 #define        SLOPE_SECOND_COUNTS     120             //ͳ¼ÆµçѹбÂʵÄʱ¼ä¼ä¸ôs
 #define        TIME_UPDATE_STATUS      3000    //¸üеç³Ø״̬µÄʱ¼ä¼ä¸ôms
-#define BATT_MAX_VOL_VALUE     4200    //ÂúµçʱµÄµç³Øµçѹ      
+#define BATT_MAX_VOL_VALUE     4100    //ÂúµçʱµÄµç³Øµçѹ      
 #define        BATT_ZERO_VOL_VALUE  3400       //¹Ø»úʱµÄµç³Øµçѹ
 #define BATT_NOMAL_VOL_VALUE  3800
-#define        THRESHOLD_VOLTAGE_HIGH          3850
-#define        THRESHOLD_VOLTAGE_MID           3550
-#define        THRESHOLD_VOLTAGE_LOW           BATT_ZERO_VOL_VALUE
+#define THRESHOLD_VOLTAGE_LEVEL0          4000
+#define THRESHOLD_VOLTAGE_LEVEL1          3800
+#define THRESHOLD_VOLTAGE_LEVEL2          3600
+#define THRESHOLD_VOLTAGE_LEVEL3          BATT_ZERO_VOL_VALUE
 #define        THRESHOLD_SLOPE_HIGH            10      //бÂÊÖµ = µçѹ½µµÍµÄËÙ¶È
 #define        THRESHOLD_SLOPE_MID                     5       //<     THRESHOLD_SLOPE_HIGH    
 #define        THRESHOLD_SLOPE_LOW                     0       //< THRESHOLD_SLOPE_MID
 
-
+/*************************************************************/
 #define CHN_BAT_ADC    0
 #define CHN_USB_ADC    2
 #define BATT_LEVEL_EMPTY       0
 #define BATT_PRESENT_TRUE       1
 #define BATT_PRESENT_FALSE  0
-#define BAT_1V2_VALUE  1422
-#define KEY_CHARGEOK_PIN       RK2818_PIN_PH6
-
-static int gBatStatus =  POWER_SUPPLY_STATUS_UNKNOWN;
-static int gBatHealth = POWER_SUPPLY_HEALTH_GOOD;
-static int gBatLastCapacity = 0;
-static int gBatPresent = BATT_PRESENT_TRUE;
-static int gBatVoltage =  BATT_NOMAL_VOL_VALUE;
-static int gBatCapacity = ((BATT_NOMAL_VOL_VALUE-BATT_ZERO_VOL_VALUE)*100/(BATT_MAX_VOL_VALUE-BATT_ZERO_VOL_VALUE));
-
+#define BAT_1V2_VALUE  1418
+#define CHARGEOK_PIN   RK2818_PIN_PH6
 
-
-/*************************************************************/
-#define LODER_CHARGE_LEVEL             0       //¸ººÉ״̬µÈ¼¶
-#define        LODER_HIGH_LEVEL                1
-#define        LODER_MID_LEVEL                 2
-#define        LOADER_RELEASE_LEVEL    3       //µç³Ø¼´½«ºÄ¾¡×´Ì¬
+#define BAT_LOADER_STATUS              0       //Óõç״̬
+#define BAT_CHANGE_STATUS              1       //²¨¶¯×´Ì¬
+#define BAT_CHARGE_STATUS              2       //³äµç״̬
+#define        BAT_RELEASE_STATUS              3       //µç³ØºÄ¾¡×´Ì¬
 
 #define        SLOPE_HIGH_LEVEL                0       //µçѹ±ä»¯Ð±Âʵȼ¶
 #define        SLOPE_MID_LEVEL                 1
@@ -117,17 +73,29 @@ static int gBatCapacity = ((BATT_NOMAL_VOL_VALUE-BATT_ZERO_VOL_VALUE)*100/(BATT_
 #define        VOLTAGE_RELEASE_LEVEL   3
 
 #define        NUM_VOLTAGE_SAMPLE      ((1000*SLOPE_SECOND_COUNTS) / TIMER_MS_COUNTS)  //´æ´¢µÄ²ÉÑùµã¸öÊý
+
+int gBatStatus =  POWER_SUPPLY_STATUS_UNKNOWN;
+int gBatHealth = POWER_SUPPLY_HEALTH_GOOD;
+int gBatLastCapacity = 0;
+int gBatPresent = BATT_PRESENT_TRUE;
+int gBatVoltage =  BATT_NOMAL_VOL_VALUE;
+int gBatCapacity = ((BATT_NOMAL_VOL_VALUE-BATT_ZERO_VOL_VALUE)*100/(BATT_MAX_VOL_VALUE-BATT_ZERO_VOL_VALUE));
+
 int gBatVoltageSamples[NUM_VOLTAGE_SAMPLE];
 int gBatSlopeValue = 0;
-int    gBatVoltageValue[2]={0,0};
+int gBatVoltageValue[2]={0,0};
 int *pSamples = &gBatVoltageSamples[0];                //²ÉÑùµãÖ¸Õë
 int gFlagLoop = 0;             //²ÉÑù×ã¹»±êÖ¾
 int gNumSamples = 0;
+int gNumCharge = 0;
+int gMaxCharge = 0;
+int gNumLoader = 0;
+int gMaxLoader = 0;
 
 int gBatSlopeLevel = SLOPE_LOW_LEVEL;
 int gBatVoltageLevel = VOLTAGE_MID_LEVEL;
-int gBatLastLoaderLevel = LODER_MID_LEVEL;
-int gBatLoaderLevel = LODER_MID_LEVEL; 
+int gBatUseStatus = BAT_LOADER_STATUS; 
+
 
 
 extern int dwc_vbus_status(void);
@@ -174,7 +142,7 @@ static int rk2818_get_charge_status(void)
        return dwc_vbus_status();
 #else
        //DBG("gAdcValue[CHN_USB_ADC]=%d\n",gAdcValue[CHN_USB_ADC]);
-       if(gAdcValue[CHN_USB_ADC] > 100)
+       if(gAdcValue[CHN_USB_ADC] > 50)
        return 1;
        else
        return 0;
@@ -185,7 +153,7 @@ static void rk2818_get_bat_status(struct rk2818_battery_data *bat)
 {
        if(rk2818_get_charge_status() == 1)
        {
-               if(gpio_get_value (KEY_CHARGEOK_PIN) == 1) //CHG_OK ==0 
+               if(gpio_get_value (CHARGEOK_PIN) == 1) //CHG_OK ==0 
                gBatStatus = POWER_SUPPLY_STATUS_FULL;
                else
                gBatStatus = POWER_SUPPLY_STATUS_CHARGING;              
@@ -213,7 +181,14 @@ static void rk2818_get_bat_voltage(struct rk2818_battery_data *bat)
        int i,*pSamp,*pStart = &gBatVoltageSamples[0];
        int temp[2] = {0,0};
        value = gAdcValue[CHN_BAT_ADC];
+       if(0 != gAdcValue[3])
        gBatVoltage = (value * BAT_1V2_VALUE * 2)/gAdcValue[3]; // channel 3 is about 1.42v,need modified
+       /*Ïû³ýë´Ìµçѹ*/
+       if(gBatVoltage >= BATT_MAX_VOL_VALUE + 10)
+               gBatVoltage = BATT_MAX_VOL_VALUE + 10;
+       else if(gBatVoltage <= BATT_ZERO_VOL_VALUE - 10)
+               gBatVoltage = BATT_ZERO_VOL_VALUE - 10;
+       
        *pSamples = gBatVoltage;
        if((++pSamples - pStart) > NUM_VOLTAGE_SAMPLE)
        {
@@ -242,58 +217,64 @@ static void rk2818_get_bat_voltage(struct rk2818_battery_data *bat)
                
                gBatVoltageValue[1] = temp[1] / (NUM_VOLTAGE_SAMPLE >> 1);
 
-               gBatSlopeValue = gBatVoltageValue[0] - gBatVoltageValue[1];     
+               gBatSlopeValue = gBatVoltageValue[0] - gBatVoltageValue[1];
                //DBG("gBatSlopeValue=%d,gBatVoltageValue[1]=%d\n",gBatSlopeValue,gBatVoltageValue[1]);
-               if(gBatSlopeValue >= 0) //Óõç״̬
-               {
 
-                       if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_HIGH)
-                       gBatVoltageLevel =      VOLTAGE_HIGH_LEVEL;     
-                       else if((gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_MID) && (gBatVoltageValue[1] < THRESHOLD_VOLTAGE_HIGH))
-                       gBatVoltageLevel =      VOLTAGE_MID_LEVEL;
-                       else if((gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LOW) && (gBatVoltageValue[1] < THRESHOLD_VOLTAGE_MID))
-                       gBatVoltageLevel = VOLTAGE_LOW_LEVEL;
-                       else
-                       gBatVoltageLevel = VOLTAGE_RELEASE_LEVEL;
-
-                       if(gBatSlopeValue >= THRESHOLD_SLOPE_HIGH)
-                       gBatSlopeLevel = SLOPE_HIGH_LEVEL;      
-                       else if((gBatSlopeValue >= THRESHOLD_SLOPE_MID) && (gBatSlopeValue < THRESHOLD_SLOPE_HIGH))
-                       gBatSlopeLevel = SLOPE_MID_LEVEL;       
-                       else if(gBatSlopeValue >= THRESHOLD_SLOPE_LOW)
-                       gBatSlopeLevel = SLOPE_LOW_LEVEL;
-                       
-                       /*µçѹÖÐÇÒбÂʸߡ¢ µçѹ¸ßÇÒбÂʸ߻òÖÐ*/
-                       if(((gBatVoltageLevel == VOLTAGE_MID_LEVEL) && (gBatSlopeLevel == SLOPE_HIGH_LEVEL)) \
-                               || ((gBatVoltageLevel == VOLTAGE_HIGH_LEVEL) && ((gBatSlopeLevel == SLOPE_HIGH_LEVEL) || (gBatSlopeLevel == SLOPE_MID_LEVEL))))
-                       {
-                               gBatLoaderLevel = LODER_HIGH_LEVEL;
-                               //DBG("gBatLoaderLevel = LODER_HIGH_LEVEL\n");
-                       }
-                       
-                       /*µçѹÖÐÇÒбÂÊÖлòµÍ¡¢µçѹ¸ßÇÒбÂʵ͡¢ µçѹµÍÇÒбÂʵÍ*/
-                       else if(((gBatVoltageLevel != VOLTAGE_RELEASE_LEVEL) && (gBatSlopeLevel == SLOPE_LOW_LEVEL)) \
-                               || ((gBatVoltageLevel == VOLTAGE_MID_LEVEL) && (gBatSlopeLevel == SLOPE_MID_LEVEL)))
+               if(gBatVoltageValue[1] < BATT_ZERO_VOL_VALUE)
+               {
+                       gBatUseStatus = BAT_RELEASE_STATUS;             //µç³ØºÄ¾¡×´Ì¬
+               }
+               else
+               {
+                       if(gBatSlopeValue < 0)
                        {
-                               gBatLoaderLevel = LODER_MID_LEVEL;
-                               //DBG("gBatLoaderLevel = LODER_MID_LEVEL\n");
+                               gNumLoader = 0;
+                                       
+                               //Á¬Ðø¶à´Îµçѹ½µµÍÂÊΪ¸º±íʾ³äµç״̬
+                               if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL0)
+                               gMaxCharge = 6;
+                               else if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL1)
+                               gMaxCharge = 8;
+                               else if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL2)
+                               gMaxCharge = 8;         
+                               else if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL3)
+                               gMaxCharge = 6; 
+                               if(++gNumCharge >= gMaxCharge)
+                               {
+                                       gBatUseStatus = BAT_CHARGE_STATUS;              //³äµç״̬
+                                       gNumCharge = gMaxCharge - 2;
+                               }
+                               else
+                               {
+                                       gBatUseStatus = BAT_CHANGE_STATUS;      //²¨¶¯×´Ì¬
+                               }
+                               
                        }
-                       
-                       /*µçѹµÍÇÒбÂʸ߻òÖС¢ µçѹ³¬µÍ*/
-                       else if(((gBatVoltageLevel == VOLTAGE_LOW_LEVEL) && ((gBatSlopeLevel == SLOPE_MID_LEVEL) || (gBatSlopeLevel == SLOPE_MID_LEVEL))) \
-                               || (gBatVoltageLevel == VOLTAGE_RELEASE_LEVEL))
+                       else
                        {
-                               gBatLoaderLevel = LOADER_RELEASE_LEVEL; //µç³ØÒѺľ¡
-                               //DBG("gBatLoaderLevel = LOADER_RELEASE_LEVEL\n");
-                       }
+                               gNumCharge = 0;
+                               //Á¬Ðø¶à´Îµçѹ½µµÍÂÊΪÕý±íʾÓõç״̬
+                               if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL0)
+                               gMaxCharge = 4;
+                               else if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL1)
+                               gMaxCharge = 6;
+                               else if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL2)
+                               gMaxCharge = 6;         
+                               else if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL3)
+                               gMaxLoader = 4; 
+                               
+                               if(++gNumLoader >= gMaxLoader)
+                               {               
+                                       gBatUseStatus = BAT_LOADER_STATUS;
+                                       gNumLoader = gMaxLoader - 2;
+                               }
+                               else
+                               {
+                                       gBatUseStatus = BAT_CHANGE_STATUS;      //²¨¶¯×´Ì¬
+                               }
 
+                       }
                }
-               else    //³äµç״̬
-               {
-                       //to do
-                       gBatLoaderLevel = LODER_CHARGE_LEVEL;
-               }
-               
        }
        
 }
@@ -302,20 +283,36 @@ static void rk2818_get_bat_capacity(struct rk2818_battery_data *bat)
 {
        if(gFlagLoop)
        {
-               //³öÏÖ¸ºÔرäСʱÈÝÁ¿±ä´óµÄÇé¿öʱ£¬²»¸üÐÂÈÝÁ¿Öµ
-               if((gBatLastCapacity ==0) \
-                       || (gBatLoaderLevel <= gBatLastLoaderLevel) \
-                       || ((gBatLoaderLevel > gBatLastLoaderLevel)&&(gBatCapacity <= gBatLastCapacity)))       
+               if(gBatUseStatus == BAT_LOADER_STATUS)
                {
-                       gBatCapacity = ((gBatVoltageValue[1] - bat->bat_min) * 100) / (bat->bat_max - bat->bat_min);
-                       if(gBatCapacity >= 100)
-                       gBatCapacity = 100;
-                       else if(gBatCapacity < 0)
-                       gBatCapacity = 0;
-                       gBatLastCapacity = gBatCapacity;
-                       gBatLastLoaderLevel = gBatLoaderLevel;
+                       //Óõç״̬ϳöÏÖ¸ºÔرäСÈÝÁ¿±ä´óʱ£¬²»¸üÐÂÈÝÁ¿Öµ
+                       if((gBatLastCapacity ==0) || (gBatCapacity <= gBatLastCapacity))
+                       {
+                               gBatCapacity = ((gBatVoltageValue[1] - bat->bat_min) * 100) / (bat->bat_max - bat->bat_min);
+                               if(gBatCapacity >= 100)
+                               gBatCapacity = 100;
+                               else if(gBatCapacity < 0)
+                               gBatCapacity = 0;
+                               gBatLastCapacity = gBatCapacity;
+                       }
+       
+               }
+               else if(gBatUseStatus == BAT_CHARGE_STATUS)
+               {
+                       //³äµç״̬ÏÂÈÝÁ¿½µµÍʱ£¬²»¸üÐÂÈÝÁ¿Öµ
+                       if((gBatCapacity >= gBatLastCapacity) || (gBatLastCapacity ==0))
+                       {
+                               gBatCapacity = ((gBatVoltageValue[1] - bat->bat_min) * 100) / (bat->bat_max - bat->bat_min);
+                               if(gBatCapacity >= 100)
+                               gBatCapacity = 100;
+                               else if(gBatCapacity < 0)
+                               gBatCapacity = 0;
+                               gBatLastCapacity = gBatCapacity;
+                       }
+
                }
 
+               //±ä»¯×´Ì¬²»¸üÐÂÈÝÁ¿
        }
        else
        {
@@ -339,7 +336,7 @@ static void rk2818_battery_timer_work(struct work_struct *work)
        if(++gNumSamples > TIME_UPDATE_STATUS/TIMER_MS_COUNTS)
        {
                gNumSamples = 0;
-               if(gFlagLoop == 1)      //update battery parameter after adc
+               if(gBatVoltage != 0)    //update battery parameter after adc
                {
                        if(!( strstr(saved_command_line,"nfsroot=") ) )
                        {
@@ -359,15 +356,6 @@ static void rk2818_battery_timer_work(struct work_struct *work)
                                DBG("gBatCapacity=%d%%\n",gBatCapacity);
                                else
                                DBG("gBatCapacity=%d%%\n",gBatLastCapacity);
-                               DBG("gBatSlopeValue == %d\n",gBatSlopeValue);
-                               if(gBatLoaderLevel == LODER_CHARGE_LEVEL)
-                               DBG("gBatLoaderLevel == LODER_CHARGE_LEVEL\n");
-                               else if(gBatLoaderLevel == LODER_HIGH_LEVEL)
-                               DBG("gBatLoaderLevel == LODER_HIGH_LEVEL\n");   
-                               else if(gBatLoaderLevel == LODER_MID_LEVEL)
-                               DBG("gBatLoaderLevel == LODER_MID_LEVEL\n");    
-                               else if(gBatLoaderLevel == LOADER_RELEASE_LEVEL)
-                               DBG("gBatLoaderLevel == LOADER_RELEASE_LEVEL\n");       
                        }
 
                }
@@ -503,47 +491,44 @@ static enum power_supply_property rk2818_usb_props[] = {
 static enum power_supply_property rk2818_ac_props[] = {
        POWER_SUPPLY_PROP_ONLINE,
 };
-#if 0
-static irqreturn_t rk2818_battery_interrupt(int irq, void *dev_id)
-{
-
-       unsigned long irq_flags;
-       struct rk2818_battery_data *data = dev_id;
-       uint32_t status;
 
-       spin_lock_irqsave(&data->lock, irq_flags);
-       /* read status flags, which will clear the interrupt */
-       //status = RK2818_BATTERY_READ(data, BATTERY_INT_STATUS);
-       status &= BATTERY_INT_MASK;
 
-       if (status & BATTERY_STATUS_CHANGED)
-               power_supply_changed(&data->battery);
-       if (status & AC_STATUS_CHANGED)
-               power_supply_changed(&data->ac);
-
-       spin_unlock_irqrestore(&data->lock, irq_flags);
-       return status ? IRQ_HANDLED : IRQ_NONE;
+#ifdef CONFIG_PM
+static int rk2818_battery_suspend(struct platform_device *dev, pm_message_t state)
+{
+       /* flush all pending status updates */
+       flush_scheduled_work();
+       return 0;
+}
 
-       return IRQ_HANDLED;
+static int rk2818_battery_resume(struct platform_device *dev)
+{
+       /* things may have changed while we were away */
+       schedule_work(&gBatteryData->timer_work);
+       return 0;
 }
+#else
+#define tosa_bat_suspend NULL
+#define tosa_bat_resume NULL
 #endif
 
+
 static int rk2818_battery_probe(struct platform_device *pdev)
 {
        int ret;
        struct rk2818_battery_data *data;
 
-       ret = gpio_request(KEY_CHARGEOK_PIN, NULL);
+       ret = gpio_request(CHARGEOK_PIN, NULL);
        if (ret) {
-               printk("failed to request charge_ok key gpio\n");
-               goto err_free_gpio;
+               printk("failed to request charge_ok gpio\n");
+               goto err_free_gpio1;
        }
        
-       gpio_pull_updown(KEY_CHARGEOK_PIN, GPIOPullUp);//important
-       ret = gpio_direction_input(KEY_CHARGEOK_PIN);
+       gpio_pull_updown(CHARGEOK_PIN, GPIOPullUp);//important
+       ret = gpio_direction_input(CHARGEOK_PIN);
        if (ret) {
                printk("failed to set gpio charge_ok input\n");
-               goto err_free_gpio;
+               goto err_free_gpio1;
        }
        
        data = kzalloc(sizeof(*data), GFP_KERNEL);
@@ -616,8 +601,9 @@ err_usb_failed:
 err_ac_failed:
        kfree(data);
 err_data_alloc_failed:
-err_free_gpio:
-       gpio_free(KEY_CHARGEOK_PIN);
+
+err_free_gpio1:
+       gpio_free(CHARGEOK_PIN);
        return ret;
 }
 
@@ -626,8 +612,9 @@ static int rk2818_battery_remove(struct platform_device *pdev)
        struct rk2818_battery_data *data = platform_get_drvdata(pdev);
 
        power_supply_unregister(&data->battery);
+       power_supply_unregister(&data->usb);
        power_supply_unregister(&data->ac);
-       gpio_free(KEY_CHARGEOK_PIN);
+       gpio_free(CHARGEOK_PIN);
        free_irq(data->irq, data);
        kfree(data);
        gBatteryData = NULL;
@@ -637,6 +624,8 @@ static int rk2818_battery_remove(struct platform_device *pdev)
 static struct platform_driver rk2818_battery_device = {
        .probe          = rk2818_battery_probe,
        .remove         = rk2818_battery_remove,
+       .suspend        = rk2818_battery_suspend,
+       .resume         = rk2818_battery_resume,
        .driver = {
                .name = "rk2818-battery",
                .owner  = THIS_MODULE,