#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
#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);
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;
{
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;
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)
{
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;
- }
-
}
}
{
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
{
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=") ) )
{
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");
}
}
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);
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;
}
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;
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,