luowei modify battery driver on 100521

This commit is contained in:
罗伟
2010-05-21 07:20:28 +00:00
committed by 黄涛
parent f18ecaa18b
commit dc799500f1
4 changed files with 247 additions and 58 deletions

View File

@@ -29,12 +29,17 @@
* and stores information such as the necessary functions to callback when
* action is required.
*/
#if 1
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
struct rk28_adc_client {
struct platform_device *pdev;
struct list_head pend;
wait_queue_head_t *wait;
unsigned int nr_samples;
int result;
unsigned char is_ts;
@@ -47,18 +52,22 @@ struct rk28_adc_client {
};
struct adc_device {
struct semaphore lock;
struct platform_device *pdev;
struct platform_device *owner;
struct clk *clk;
struct rk28_adc_client *client;
struct rk28_adc_client *cur;
struct rk28_adc_client *ts_pend;
void __iomem *regs;
struct timer_list timer;
unsigned int pre_con;
int irq;
};
static struct adc_device *pAdcDev;
volatile int gAdcChanel = 0;
volatile int gAdcValue[4]={0, 0, 0, 0}; //0->ch0 1->ch1 2->ch2 3->ch3
static LIST_HEAD(adc_pending);
@@ -278,6 +287,34 @@ void rk28_adc_release(struct rk28_adc_client *client)
}
EXPORT_SYMBOL_GPL(rk28_adc_release);
//read four ADC chanel
static int rk28_read_adc(struct adc_device *adc)
{
int ret = 0,i;
ret = down_interruptible(&adc->lock);
if (ret < 0)
return ret;
for(i=0; i<4; i++)
{
gAdcValue[i] = rk28_adc_read(adc->client, i);
//DBG("gAdcValue[%d]=%d\n",i,gAdcValue[i]);
}
up(&adc->lock);
return ret;
}
static void rk28_adcscan_timer(unsigned long data)
{
pAdcDev->timer.expires = jiffies + msecs_to_jiffies(30);
add_timer(&pAdcDev->timer);
rk28_read_adc(pAdcDev);
}
static irqreturn_t rk28_adc_irq(int irq, void *pw)
{
struct adc_device *adc = pw;
@@ -373,9 +410,23 @@ static int rk28_adc_probe(struct platform_device *pdev)
dev_info(dev, "attached adc driver\n");
platform_set_drvdata(pdev, adc);
init_MUTEX(&adc->lock);
/* Register with the core ADC driver. */
adc->client = rk28_adc_register(pdev, NULL, NULL, 0);
if (IS_ERR(adc->client)) {
dev_err(dev, "cannot register adc\n");
ret = PTR_ERR(adc->client);
goto err_clk;
}
rk28_adc_int_disable(adc);
pAdcDev = adc;
setup_timer(&adc->timer, rk28_adcscan_timer, (unsigned long)adc);
adc->timer.expires = jiffies + 50;
add_timer(&adc->timer);
printk(KERN_INFO "rk2818 adc: driver initialized\n");
return 0;
@@ -394,6 +445,7 @@ static int rk28_adc_remove(struct platform_device *pdev)
{
struct adc_device *adc = platform_get_drvdata(pdev);
rk28_adc_power_down(adc);
rk28_adc_release(adc->client);
iounmap(adc->regs);
free_irq(adc->irq, adc);
clk_disable(adc->clk);

View File

@@ -26,7 +26,7 @@
#include <mach/gpio.h>
#include <mach/adc.h>
#if 1
#if 0
#define DBG(x...) printk(x)
#else
#define DBG(x...)
@@ -56,8 +56,6 @@
#define KEY_PHYS_NAME "rk2818_adckey/input0"
volatile int gADSampleTimes = 0;
volatile int gAdcChanel = 0;
volatile int gAdcValue[4]={0, 0, 0, 0}; //0->ch0 1->ch1 2->ch2 3->ch3
volatile int gStatePlaykey = 0;
volatile unsigned int gCodeCount = 0;
@@ -161,24 +159,6 @@ static int rk28_adckey_resume(struct platform_device *pdev)
#define rk28_adckey_suspend NULL
#define rk28_adckey_resume NULL
#endif
//read four ADC chanel
static int rk28_read_adc(struct rk28_adckey *adckey)
{
int ret;
ret = down_interruptible(&adckey->lock);
if (ret < 0)
return ret;
if(gAdcChanel > 3)
gAdcChanel = 0;
gAdcValue[gAdcChanel] = rk28_adc_read(adckey->client, gAdcChanel);
//DBG("Enter::%s,LINE=%d,gAdcValue[%d]=%d\n",__FUNCTION__,__LINE__,gAdcChanel,gAdcValue[gAdcChanel]);
gAdcChanel++;
up(&adckey->lock);
return ret;
}
static void rk28_adkeyscan_timer(unsigned long data)
{
unsigned int adcvalue = -1, code;
@@ -194,7 +174,7 @@ static void rk28_adkeyscan_timer(unsigned long data)
gADSampleTimes = 0;
rk28_read_adc(pRk28AdcKey);
//rk28_read_adc(pRk28AdcKey);
adcvalue = gAdcValue[ADKEYCH];
if((adcvalue > ADEmpty) || (adcvalue < ADInvalid))
{
@@ -297,21 +277,11 @@ static int __devinit rk28_adckey_probe(struct platform_device *pdev)
adckey->input_dev = input_dev;
input_set_drvdata(input_dev, adckey);
input_dev->evbit[0] = BIT_MASK(EV_KEY) ;
input_dev->evbit[0] = BIT_MASK(EV_KEY);
// rk28_adckey_build_keycode(adckey);
platform_set_drvdata(pdev, adckey);
init_MUTEX(&adckey->lock);
/* Register with the core ADC driver. */
adckey->client = rk28_adc_register(pdev, NULL, NULL, 0);
if (IS_ERR(adckey->client)) {
dev_err(&pdev->dev, "cannot register adc\n");
error = PTR_ERR(adckey->client);
goto failed_free;
}
pRk28AdcKey = adckey;
/* Register the input device */
@@ -360,7 +330,6 @@ static int __devexit rk28_adckey_remove(struct platform_device *pdev)
input_unregister_device(adckey->input_dev);
input_free_device(adckey->input_dev);
platform_set_drvdata(pdev, NULL);
rk28_adc_release(adckey->client);
kfree(adckey);
free_irq(gpio_to_irq(KEY_PLAYON_PIN),NULL);
gpio_free(KEY_PLAYON_PIN);

View File

@@ -112,7 +112,7 @@ config CHARGER_PCF50633
config BATTERY_RK2818
tristate "RK2818 battery"
depends on KEYBOARD_RK28ADC
depends on RK28_ADC
help
Say Y to enable support for the battery on the RK2818.
endif # POWER_SUPPLY

View File

@@ -1,9 +1,6 @@
/* drivers/power/rk2818_battery.c
*
* Power supply driver for the rk2818 emulator
*
* Copyright (C) 2008 Google, Inc.
* Author: Mike Lockwood <lockwood@android.com>
* battery detect driver for the rk2818
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -26,13 +23,13 @@
#include <asm/io.h>
#include <mach/adc.h>
#if 1
#if 0
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
#define CHN_BAT_ADC 0
#define CHN_BAT_ADC 3
#define CHN_USB_ADC 2
#define BATT_LEVEL_EMPTY 0
#define BATT_PRESENT_TRUE 1
@@ -44,6 +41,85 @@ static int gBatHealth = POWER_SUPPLY_HEALTH_GOOD;
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
#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},
};
int gBatZeroVol = BatMinVoltage[BAT_SELECT][ELECTRICITY_SELECT];
int gBatMaxVol = 4300;
#else
int gBatMaxVol = 4300;
int gBatZeroVol = 3400;
#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 TIME_UPDATE_STATUS 3000 //<2F><><EFBFBD>µ<EFBFBD><C2B5><EFBFBD>״̬<D7B4><CCAC>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ms
#define THRESHOLD_VOLTAGE_HIGH 3900
#define THRESHOLD_VOLTAGE_MID 3550
#define THRESHOLD_VOLTAGE_LOW gBatZeroVol
#define THRESHOLD_SLOPE_HIGH 8 //<2F><>ʵб<CAB5><D0B1>ֵ
#define THRESHOLD_SLOPE_MID 3
#define THRESHOLD_SLOPE_LOW 0
/*************************************************************/
#define LODER_HIGH_LEVEL 0 //<2F><><EFBFBD><EFBFBD>״̬<D7B4>ȼ<EFBFBD>
#define LODER_MID_LEVEL 1
#define LODER_LOW_LEVEL 2
#define LOADER_RELEASE_LEVEL 3 //<2F><><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD>ľ<EFBFBD>״̬
#define SLOPE_HIGH_LEVEL 0 //<2F><>ѹ<EFBFBD>б<E4BBAF>ʵȼ<CAB5>
#define SLOPE_MID_LEVEL 1
#define SLOPE_LOW_LEVEL 2
#define VOLTAGE_HIGH_LEVEL 0 //<2F><>ѹ<EFBFBD>ߵ͵ȼ<CDB5>
#define VOLTAGE_MID_LEVEL 1
#define VOLTAGE_LOW_LEVEL 2
#define VOLTAGE_RELEASE_LEVEL 3
#define NUM_VOLTAGE_SAMPLE ((1000*SLOPE_SECOND_COUNTS) / TIMER_MS_COUNTS) //<2F><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int gBatVoltageSamples[NUM_VOLTAGE_SAMPLE];
int gBatSlopeValue = 0;
int gBatVoltageValue[2];
int *pSamples = &gBatVoltageSamples[0]; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
int gFlagLoop = 0; //ѭ<><D1AD><EFBFBD><EFBFBD>־
int gNumSamples = 0;
int gBatSlopeLevel = SLOPE_LOW_LEVEL;
int gBatVoltageLevel = VOLTAGE_MID_LEVEL;
int gBatLoaderLevel = LODER_MID_LEVEL;
extern int dwc_vbus_status(void);
struct rk2818_battery_data {
@@ -59,8 +135,6 @@ struct rk2818_battery_data {
int bat_min;
};
#define RK2818_BATTERY_WRITE(data, addr, x) (writel(x, data->reg_base + addr))
/* temporary variable used between rk2818_battery_probe() and rk2818_battery_open() */
static struct rk2818_battery_data *gBatteryData;
@@ -113,19 +187,106 @@ static void rk2818_get_bat_present(struct rk2818_battery_data *bat)
static void rk2818_get_bat_voltage(struct rk2818_battery_data *bat)
{
unsigned long value;
int i,*pSamp,*pStart = &gBatVoltageSamples[0];
int temp[2] = {0,0};
value = gAdcValue[CHN_BAT_ADC];
gBatVoltage = value * 1000000 / bat->adc_bat_divider;
gBatVoltage = (value * 5000)>>10; // 3.3v to 5v
*pSamples = gBatVoltage;
if((++pSamples - pStart) > NUM_VOLTAGE_SAMPLE)
{
pSamples = pStart;
gFlagLoop = 1;
}
//compute the average voltage after samples-count is larger than NUM_VOLTAGE_SAMPLE
if(gFlagLoop)
{
pSamp = pSamples;
for(i=0; i<(NUM_VOLTAGE_SAMPLE >> 1); i++)
{
temp[0] += *pSamp;
if((++pSamp - pStart) > NUM_VOLTAGE_SAMPLE)
pSamp = pStart;
}
gBatVoltageValue[0] = temp[0] / (NUM_VOLTAGE_SAMPLE >> 1);
for(i=0; i<(NUM_VOLTAGE_SAMPLE >> 1); i++)
{
temp[1] += *pSamp;
if((++pSamp - pStart) > NUM_VOLTAGE_SAMPLE)
pSamp = pStart;
}
gBatVoltageValue[1] = temp[1] / (NUM_VOLTAGE_SAMPLE >> 1);
//DBG("gBatVoltageValue[0]=%d,gBatVoltageValue[1]=%d\n",gBatVoltageValue[0],gBatVoltageValue[1]);
gBatSlopeValue = gBatVoltageValue[0] - gBatVoltageValue[1];
if(gBatSlopeValue >= 0) //<2F>õ<EFBFBD>״̬
{
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;
/*<2A><>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>б<EFBFBD>ʸߡ<CAB8> <20><>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>б<EFBFBD>ʸ߻<CAB8><DFBB><EFBFBD>*/
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");
}
/*<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>*/
else if(((gBatVoltageLevel != VOLTAGE_RELEASE_LEVEL) && (gBatSlopeLevel == SLOPE_LOW_LEVEL)) \
|| ((gBatVoltageLevel == VOLTAGE_MID_LEVEL) && (gBatSlopeLevel == SLOPE_MID_LEVEL)))
{
gBatLoaderLevel = LODER_MID_LEVEL;
DBG("gBatLoaderLevel = LODER_MID_LEVEL\n");
}
/*<2A><>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>б<EFBFBD>ʸ߻<CAB8><DFBB>С<EFBFBD> <20><>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD>*/
else if(((gBatVoltageLevel == VOLTAGE_LOW_LEVEL) && ((gBatSlopeLevel == SLOPE_MID_LEVEL) || (gBatSlopeLevel == SLOPE_MID_LEVEL))) \
|| (gBatVoltageLevel == VOLTAGE_RELEASE_LEVEL))
{
gBatLoaderLevel = LOADER_RELEASE_LEVEL; //<2F><><EFBFBD><EFBFBD><EFBFBD>Ѻľ<D1BA>
DBG("gBatLoaderLevel = LOADER_RELEASE_LEVEL\n");
}
}
else //<2F><><EFBFBD><EFBFBD>״̬
{
//to do
}
}
}
static void rk2818_get_bat_capacity(struct rk2818_battery_data *bat)
{
gBatCapacity = (gBatVoltage * 100) / bat->bat_max;
if(gFlagLoop)
gBatCapacity = ((gBatVoltageValue[1] - bat->bat_min) * 100) / (bat->bat_max - bat->bat_min);
else
gBatCapacity = ((gBatVoltage - bat->bat_min) * 100) / (bat->bat_max - bat->bat_min);
}
static void rk2818_batscan_timer(unsigned long data)
{
gBatteryData->timer.expires = jiffies + msecs_to_jiffies(20);
gBatteryData->timer.expires = jiffies + msecs_to_jiffies(TIMER_MS_COUNTS);
add_timer(&gBatteryData->timer);
rk2818_get_bat_status(gBatteryData);
rk2818_get_bat_health(gBatteryData);
@@ -133,6 +294,15 @@ static void rk2818_batscan_timer(unsigned long data)
rk2818_get_bat_voltage(gBatteryData);
rk2818_get_bat_capacity(gBatteryData);
if(++gNumSamples > TIME_UPDATE_STATUS/TIMER_MS_COUNTS)
{
gNumSamples = 0;
if(gBatSlopeValue != 0) //if voltage has changed
{
power_supply_changed(&gBatteryData->battery);
DBG("voltage has changed\n");
}
}
}
@@ -141,7 +311,6 @@ static int rk2818_usb_get_property(struct power_supply *psy,
union power_supply_propval *val)
{
charger_type_t charger;
//todo
charger = CHARGER_USB;
switch (psp) {
@@ -168,7 +337,6 @@ static int rk2818_ac_get_property(struct power_supply *psy,
// struct rk2818_battery_data, ac);
int ret = 0;
charger_type_t charger;
//todo
charger = CHARGER_USB;
switch (psp) {
case POWER_SUPPLY_PROP_ONLINE:
@@ -217,7 +385,7 @@ static int rk2818_battery_get_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = gBatCapacity;
DBG("gBatCapacity=0x%x\n",val->intval);
DBG("gBatCapacity=%d%\n",val->intval);
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
val->intval = data->bat_max;
@@ -290,16 +458,17 @@ static int rk2818_battery_probe(struct platform_device *pdev)
}
spin_lock_init(&data->lock);
memset(gBatVoltageSamples, 0, sizeof(gBatVoltageSamples));
data->battery.properties = rk2818_battery_props;
data->battery.num_properties = ARRAY_SIZE(rk2818_battery_props);
data->battery.get_property = rk2818_battery_get_property;
data->battery.name = "battery";
data->battery.type = POWER_SUPPLY_TYPE_BATTERY;
//data->adc_bat_divider = gAdcValue[3];
data->adc_bat_divider = 414;
DBG("adc_bat_divider=%d\n",data->adc_bat_divider);
data->bat_max = 4310000;
data->bat_min = 1551 * 1000000 / 414;
data->bat_max = gBatMaxVol;
data->bat_min = gBatZeroVol;
DBG("bat_min = %d\n",data->bat_min);
data->usb.properties = rk2818_usb_props;
data->usb.num_properties = ARRAY_SIZE(rk2818_ac_props);
@@ -351,7 +520,6 @@ static int rk2818_battery_probe(struct platform_device *pdev)
data->timer.expires = jiffies+50;
add_timer(&data->timer);
printk(KERN_INFO "rk2818_battery: driver initialized\n");
//RK2818_BATTERY_WRITE(data, BATTERY_INT_ENABLE, BATTERY_INT_MASK);
return 0;
@@ -404,7 +572,7 @@ static void __exit rk2818_battery_exit(void)
module_init(rk2818_battery_init);
module_exit(rk2818_battery_exit);
MODULE_AUTHOR("Mike Lockwood lockwood@android.com");
MODULE_DESCRIPTION("Battery detect driver for the rk2818");
MODULE_AUTHOR("luowei lw@rock-chips.com");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Battery driver for the Goldfish emulator");