This commit is contained in:
罗伟
2010-05-26 13:15:50 +00:00
committed by 黄涛
parent 98d46e17f3
commit 5f91767112

View File

@@ -21,7 +21,12 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <mach/gpio.h>
#include <mach/adc.h>
#include <mach/iomux.h>
#if 0
#define DBG(x...) printk(x)
@@ -29,20 +34,6 @@
#define DBG(x...)
#endif
#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 BATT_NOMAL_VOL_VALUE 3900
static int gBatStatus = POWER_SUPPLY_STATUS_UNKNOWN;
static int gBatHealth = POWER_SUPPLY_HEALTH_GOOD;
static int gBatLastCapacity = 0;
static int gBatCapacity = BATT_LEVEL_EMPTY;
static int gBatPresent = BATT_PRESENT_TRUE;
static int gBatVoltage = BATT_NOMAL_VOL_VALUE;
#if 0
#define NUM_BAT 3
#define NUM_ELECTRICITY 10
@@ -73,25 +64,42 @@ static int BatMinVoltage[NUM_BAT][NUM_ELECTRICITY] =
{3360, 3400, 3410, 3410, 3440, 3460, 3480, 3470, 3440, 3360},
};
int gBatZeroVol = BatMinVoltage[BAT_SELECT][ELECTRICITY_SELECT];
int gBatMaxVol = 4300;
#else
int gBatMaxVol = 4200;
int gBatZeroVol = 3350;
#define BATT_MAX_VOL_VALUE 4300
#define BATT_NOMAL_VOL_VALUE 3900
#define BATT_ZERO_VOL_VALUE BatMinVoltage[BAT_SELECT][ELECTRICITY_SELECT]
#endif
/*******************<2A><><EFBFBD>²<EFBFBD><C2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>******************************/
#define TIMER_MS_COUNTS 50 //<2F><>ʱ<EFBFBD><CAB1><EFBFBD>ij<EFBFBD><C4B3><EFBFBD>ms
#define SLOPE_SECOND_COUNTS 60 //ͳ<>Ƶ<EFBFBD>ѹб<D1B9>ʵ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>s
#define SLOPE_SECOND_COUNTS 120 //ͳ<>Ƶ<EFBFBD>ѹб<D1B9>ʵ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>s
#define TIME_UPDATE_STATUS 3000 //<2F><><EFBFBD>µ<EFBFBD><C2B5><EFBFBD>״̬<D7B4><CCAC>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ms
#define BATT_MAX_VOL_VALUE 4200 //<2F><><EFBFBD><EFBFBD>ʱ<EFBFBD>ĵ<EFBFBD><C4B5>ص<EFBFBD>ѹ
#define BATT_ZERO_VOL_VALUE 3400 //<2F>ػ<EFBFBD>ʱ<EFBFBD>ĵ<EFBFBD><C4B5>ص<EFBFBD>ѹ
#define BATT_NOMAL_VOL_VALUE 3800
#define THRESHOLD_VOLTAGE_HIGH 3850
#define THRESHOLD_VOLTAGE_MID 3450
#define THRESHOLD_VOLTAGE_LOW gBatZeroVol
#define THRESHOLD_SLOPE_HIGH 8 //<EFBFBD><EFBFBD>ʵб<EFBFBD><EFBFBD>ֵ
#define THRESHOLD_SLOPE_MID 3
#define THRESHOLD_SLOPE_LOW 0
#define THRESHOLD_VOLTAGE_MID 3550
#define THRESHOLD_VOLTAGE_LOW BATT_ZERO_VOL_VALUE
#define THRESHOLD_SLOPE_HIGH 10 //б<><D0B1>ֵ = <20><>ѹ<EFBFBD><D1B9><EFBFBD>͵<EFBFBD><CDB5>ٶ<EFBFBD>
#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 LODER_CHARGE_LEVEL 0 //<2F><><EFBFBD><EFBFBD>״̬<D7B4>ȼ<EFBFBD>
@@ -127,6 +135,7 @@ extern int dwc_vbus_status(void);
struct rk2818_battery_data {
int irq;
spinlock_t lock;
struct work_struct timer_work;
struct timer_list timer;
struct power_supply battery;
struct power_supply usb;
@@ -161,14 +170,26 @@ typedef enum {
static int rk2818_get_charge_status(void)
{
//return dwc_vbus_status();
#if 0
return dwc_vbus_status();
#else
//DBG("gAdcValue[CHN_USB_ADC]=%d\n",gAdcValue[CHN_USB_ADC]);
if(gAdcValue[CHN_USB_ADC] > 100)
return 1;
else
return 0;
#endif
}
static void rk2818_get_bat_status(struct rk2818_battery_data *bat)
{
if(rk2818_get_charge_status() == 1)
gBatStatus = POWER_SUPPLY_STATUS_CHARGING;
{
if(gpio_get_value (KEY_CHARGEOK_PIN) == 1) //CHG_OK ==0
gBatStatus = POWER_SUPPLY_STATUS_FULL;
else
gBatStatus = POWER_SUPPLY_STATUS_CHARGING;
}
else
gBatStatus = POWER_SUPPLY_STATUS_NOT_CHARGING;
}
@@ -192,7 +213,7 @@ 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];
gBatVoltage = (value * 1422 * 2)/gAdcValue[3]; // channel 3 is about 1.42v,need modified
gBatVoltage = (value * BAT_1V2_VALUE * 2)/gAdcValue[3]; // channel 3 is about 1.42v,need modified
*pSamples = gBatVoltage;
if((++pSamples - pStart) > NUM_VOLTAGE_SAMPLE)
{
@@ -247,7 +268,7 @@ static void rk2818_get_bat_voltage(struct rk2818_battery_data *bat)
|| ((gBatVoltageLevel == VOLTAGE_HIGH_LEVEL) && ((gBatSlopeLevel == SLOPE_HIGH_LEVEL) || (gBatSlopeLevel == SLOPE_MID_LEVEL))))
{
gBatLoaderLevel = LODER_HIGH_LEVEL;
DBG("gBatLoaderLevel = LODER_HIGH_LEVEL\n");
//DBG("gBatLoaderLevel = LODER_HIGH_LEVEL\n");
}
/*<2A><>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>л<EFBFBD><D0BB>͡<EFBFBD><CDA1><EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>б<EFBFBD>ʵ͡<CAB5> <20><>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>б<EFBFBD>ʵ<EFBFBD>*/
@@ -255,7 +276,7 @@ static void rk2818_get_bat_voltage(struct rk2818_battery_data *bat)
|| ((gBatVoltageLevel == VOLTAGE_MID_LEVEL) && (gBatSlopeLevel == SLOPE_MID_LEVEL)))
{
gBatLoaderLevel = LODER_MID_LEVEL;
DBG("gBatLoaderLevel = LODER_MID_LEVEL\n");
//DBG("gBatLoaderLevel = LODER_MID_LEVEL\n");
}
/*<2A><>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>б<EFBFBD>ʸ߻<CAB8><DFBB>С<EFBFBD> <20><>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>*/
@@ -263,7 +284,7 @@ static void rk2818_get_bat_voltage(struct rk2818_battery_data *bat)
|| (gBatVoltageLevel == VOLTAGE_RELEASE_LEVEL))
{
gBatLoaderLevel = LOADER_RELEASE_LEVEL; //<2F><><EFBFBD><EFBFBD><EFBFBD>Ѻľ<D1BA>
DBG("gBatLoaderLevel = LOADER_RELEASE_LEVEL\n");
//DBG("gBatLoaderLevel = LOADER_RELEASE_LEVEL\n");
}
}
@@ -287,6 +308,10 @@ static void rk2818_get_bat_capacity(struct rk2818_battery_data *bat)
|| ((gBatLoaderLevel > gBatLastLoaderLevel)&&(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;
gBatLastLoaderLevel = gBatLoaderLevel;
}
@@ -295,14 +320,16 @@ static void rk2818_get_bat_capacity(struct rk2818_battery_data *bat)
else
{
gBatCapacity = ((gBatVoltage - bat->bat_min) * 100) / (bat->bat_max - bat->bat_min);
if(gBatCapacity >= 100)
gBatCapacity = 100;
else if(gBatCapacity < 0)
gBatCapacity = 0;
}
}
static void rk2818_batscan_timer(unsigned long data)
{
gBatteryData->timer.expires = jiffies + msecs_to_jiffies(TIMER_MS_COUNTS);
add_timer(&gBatteryData->timer);
static void rk2818_battery_timer_work(struct work_struct *work)
{
rk2818_get_bat_status(gBatteryData);
rk2818_get_bat_health(gBatteryData);
rk2818_get_bat_present(gBatteryData);
@@ -312,15 +339,51 @@ static void rk2818_batscan_timer(unsigned long data)
if(++gNumSamples > TIME_UPDATE_STATUS/TIMER_MS_COUNTS)
{
gNumSamples = 0;
if(gBatVoltage != 0) //update battery parameter after adc
if(gFlagLoop == 1) //update battery parameter after adc
{
power_supply_changed(&gBatteryData->battery);
DBG("voltage has changed\n");
if(!( strstr(saved_command_line,"nfsroot=") ) )
{
power_supply_changed(&gBatteryData->battery);
power_supply_changed(&gBatteryData->usb);
power_supply_changed(&gBatteryData->ac);
}
else
{
DBG("voltage has changed\n");
DBG("gBatStatus=%d,gBatHealth=%d,gBatPresent=%d\n",gBatStatus,gBatHealth,gBatPresent);
if(gBatVoltageValue[1] == 0)
DBG("gBatVoltage=%d\n",gBatVoltage);
else
DBG("gBatVoltage=%d\n",gBatVoltageValue[1]);
if(gBatLastCapacity == 0)
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 void rk2818_batscan_timer(unsigned long data)
{
gBatteryData->timer.expires = jiffies + msecs_to_jiffies(TIMER_MS_COUNTS);
add_timer(&gBatteryData->timer);
schedule_work(&gBatteryData->timer_work);
}
static int rk2818_usb_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -361,7 +424,6 @@ static int rk2818_ac_get_property(struct power_supply *psy,
val->intval = (charger == CHARGER_USB ? 1 : 0);
else
val->intval = 0;
//val->intval = RK2818_BATTERY_READ(data, BATTERY_AC_ONLINE);
break;
default:
ret = -EINVAL;
@@ -406,7 +468,7 @@ static int rk2818_battery_get_property(struct power_supply *psy,
val->intval = gBatCapacity;
else
val->intval = gBatLastCapacity;
DBG("gBatCapacity=%d%\n",val->intval);
DBG("gBatCapacity=%d%%\n",val->intval);
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
val->intval = data->bat_max;
@@ -469,16 +531,28 @@ static irqreturn_t rk2818_battery_interrupt(int irq, void *dev_id)
static int rk2818_battery_probe(struct platform_device *pdev)
{
int ret;
//struct resource *r;
struct rk2818_battery_data *data;
ret = gpio_request(KEY_CHARGEOK_PIN, NULL);
if (ret) {
printk("failed to request charge_ok key gpio\n");
goto err_free_gpio;
}
gpio_pull_updown(KEY_CHARGEOK_PIN, GPIOPullUp);//important
ret = gpio_direction_input(KEY_CHARGEOK_PIN);
if (ret) {
printk("failed to set gpio charge_ok input\n");
goto err_free_gpio;
}
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL) {
ret = -ENOMEM;
goto err_data_alloc_failed;
}
spin_lock_init(&data->lock);
memset(gBatVoltageSamples, 0, sizeof(gBatVoltageSamples));
data->battery.properties = rk2818_battery_props;
@@ -487,10 +561,10 @@ static int rk2818_battery_probe(struct platform_device *pdev)
data->battery.name = "battery";
data->battery.type = POWER_SUPPLY_TYPE_BATTERY;
data->adc_bat_divider = 414;
data->bat_max = gBatMaxVol;
data->bat_min = gBatZeroVol;
data->bat_max = BATT_MAX_VOL_VALUE;
data->bat_min = BATT_ZERO_VOL_VALUE;
DBG("bat_min = %d\n",data->bat_min);
data->usb.properties = rk2818_usb_props;
data->usb.num_properties = ARRAY_SIZE(rk2818_ac_props);
data->usb.get_property = rk2818_usb_get_property;
@@ -503,42 +577,33 @@ static int rk2818_battery_probe(struct platform_device *pdev)
data->ac.name = "ac";
data->ac.type = POWER_SUPPLY_TYPE_MAINS;
#if 0
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) {
printk(KERN_ERR "%s: platform_get_resource failed\n", pdev->name);
ret = -ENODEV;
goto err_no_io_base;
}
data->irq = platform_get_irq(pdev, 0);
if (data->irq < 0) {
printk(KERN_ERR "%s: platform_get_irq failed\n", pdev->name);
ret = -ENODEV;
goto err_no_irq;
}
ret = request_irq(data->irq, rk2818_battery_interrupt, IRQF_SHARED, pdev->name, data);
if (ret)
goto err_request_irq_failed;
#endif
ret = power_supply_register(&pdev->dev, &data->ac);
if (ret)
{
printk(KERN_INFO "fail to power_supply_register\n");
goto err_ac_failed;
}
ret = power_supply_register(&pdev->dev, &data->usb);
if (ret)
{
printk(KERN_INFO "fail to power_supply_register\n");
goto err_usb_failed;
}
ret = power_supply_register(&pdev->dev, &data->battery);
if (ret)
{
printk(KERN_INFO "fail to power_supply_register\n");
goto err_battery_failed;
}
platform_set_drvdata(pdev, data);
gBatteryData = data;
INIT_WORK(&data->timer_work, rk2818_battery_timer_work);
gBatteryData = data;
setup_timer(&data->timer, rk2818_batscan_timer, (unsigned long)data);
data->timer.expires = jiffies+500;
data->timer.expires = jiffies+100;
add_timer(&data->timer);
printk(KERN_INFO "rk2818_battery: driver initialized\n");
@@ -549,12 +614,10 @@ err_battery_failed:
err_usb_failed:
power_supply_unregister(&data->ac);
err_ac_failed:
//free_irq(data->irq, data);
//err_request_irq_failed:
//err_no_irq:
//err_no_io_base:
kfree(data);
err_data_alloc_failed:
err_free_gpio:
gpio_free(KEY_CHARGEOK_PIN);
return ret;
}
@@ -564,7 +627,7 @@ static int rk2818_battery_remove(struct platform_device *pdev)
power_supply_unregister(&data->battery);
power_supply_unregister(&data->ac);
gpio_free(KEY_CHARGEOK_PIN);
free_irq(data->irq, data);
kfree(data);
gBatteryData = NULL;