当前位置:操作系统 > 安卓/Android >>

android2.3电池驱动优化

android2.3内核版本2.6.35.7,内核中已经自带了电池驱动,做项目是不能用的,下面是我修改过后的驱动源码:
 
/* 
* linux/drivers/power/s3c_fake_battery.c 
* 
* Battery measurement code for S3C platform. 
* 
* based on palmtx_battery.c 
* 
* Copyright (C) 2009 Samsung Electronics. 
* 
* This program is free software; you can redistribute it and/or modify 
* it under the terms of the GNU General Public License version 2 as 
* published by the Free Software Foundation. 
* 
*/  
  
#include <linux/kernel.h>  
#include <linux/device.h>  
#include <linux/module.h>  
#include <linux/power_supply.h>  
#include <linux/delay.h>  
#include <linux/spinlock.h>  
#include <linux/interrupt.h>  
#include <linux/gpio.h>  
#include <linux/platform_device.h>  
#include <linux/timer.h>  
#include <linux/jiffies.h>  
#include <linux/irq.h>  
#include <linux/wakelock.h>  
#include <asm/mach-types.h>  
#include <mach/hardware.h>  
#include <plat/gpio-cfg.h>  
  
#define DRIVER_NAME        "sec-fake-battery"  
  
#include <linux/clk.h>  
#include <linux/miscdevice.h>  
#include <mach/regs-clock.h>  
#include <mach/regs-adc.h>  
#include <mach/regs-gpio.h>  
#include <plat/regs-timer.h>  
  
#include <asm/io.h>  
#include <asm/irq.h>  
#include <asm/uaccess.h>  
static void __iomem *base_addr;  
  
typedef struct {  
        wait_queue_head_t wait;  
        int channel;  
        int prescale;  
} ADC_DEV;  
  
static int __ADC_locked = 0;  
  
static ADC_DEV adcdev;  
static volatile int ev_adc = 0;  
static int adc_data;  
  
static struct clk        *adc_clock;  
  
  
static int old_flag = 0;  
#define __ADCREG(name)        (*(volatile unsigned long *)(base_addr + name))  
#define ADCCON                        __ADCREG(S3C_ADCCON)        // ADC control  
#define ADCTSC                        __ADCREG(S3C_ADCTSC)        // ADC touch screen control  
#define ADCDLY                        __ADCREG(S3C_ADCDLY)        // ADC start or Interval Delay  
#define ADCDAT0                        __ADCREG(S3C_ADCDAT0)        // ADC conversion data 0  
#define ADCDAT1                        __ADCREG(S3C_ADCDAT1)        // ADC conversion data 1  
#define ADCUPDN                        __ADCREG(S3C_ADCUPDN)        // Stylus Up/Down interrupt status  
  
#define PRESCALE_DIS                (0 << 14)  
#define PRESCALE_EN                        (1 << 14)  
#define PRSCVL(x)                        ((x) << 6)  
#define ADC_INPUT(x)                ((x) << 3)  
#define ADC_START                        (1 << 0)  
#define ADC_ENDCVT                        (1 << 15)  
  
#define START_ADC_AIN(ch, prescale) \  
        do { \  
                ADCCON = PRESCALE_EN | PRSCVL(prescale) | ADC_INPUT((ch)) ; \  
                ADCCON |= ADC_START; \  
        } while (0)  
  
#include <linux/workqueue.h>  
struct delayed_work monitor_work;  
struct workqueue_struct *monitor_wqueue;  
  
struct delayed_work ad_work;  
struct workqueue_struct *ad_wqueue;  
static int ad_value=0;  
static int times = 0;  
#define ACIRQ                                IRQ_EINT(0)  
  
#define ACIRQSTA                        S5PV210_GPH0(0)  
  
static irqreturn_t adcdone_int_handler(int irq, void *dev_id)  
{  
#if        1  
        if (__ADC_locked) {  
                adc_data = ADCDAT0 & 0x3ff;  
  
                ev_adc = 1;  
                wake_up_interruptible(&adcdev.wait);  
  
                /* clear interrupt */  
                __raw_writel(0x0, base_addr + S3C_ADCCLRINT);  
        }  
#endif  
  
        return IRQ_HANDLED;  
}  
  
static struct wake_lock vbus_wake_lock;  
  
/* Prototypes */  
extern int s3c_adc_get_adc_data(int channel);  
  
static ssize_t s3c_bat_show_property(struct device *dev,  
                                      struct device_attribute *attr,  
                                      char *buf);  
static ssize_t s3c_bat_store(struct device *dev,  
                         struct device_attribute *attr,  
                         const char *buf, size_t count);  
  
#define FAKE_BAT_LEVEL        80  
  
static struct device *dev;  
static int s3c_battery_initial;  
static int force_update;  
  
static char *status_text[] = {  
        [POWER_SUPPLY_STATUS_UNKNOWN] =                "Unknown",  
        [POWER_SUPPLY_STATUS_CHARGING] =        "Charging",  
        [POWER_SUPPLY_STATUS_DISCHARGING] =        "Discharging",  
        [POWER_SUPPLY_STATUS_NOT_CHARGING] =        "Not Charging",  
        [POWER_SUPPLY_STATUS_FULL] =                "Full",  
};  
  
typedef enum {  
        CHARGER_BATTERY = 0,  
        CHARGER_USB,  
        CHARGER_AC,  
        CHARGER_DISCHARGE  
} charger_type_t;  
  
struct battery_info {  
        u32 batt_id;                /* Battery ID from ADC */  
        u32 batt_vol;                /* Battery voltage from ADC */  
        u32 batt_vol_adc;        /* Battery ADC value */  
        u32 batt_vol_adc_cal;        /* Battery ADC value (calibrated)*/  
        u32 batt_temp;                /* Battery Temperature (C) from ADC */  
        u32 batt_temp_adc;        /* Battery Temperature ADC value */  
        u32 batt_temp_adc_cal;        /* Battery Temperature ADC value (calibrated) */  
        u32 batt_current;        /* Battery current from ADC */  
        u32 level;                /* formula */  
        u32 charging_source;        /* 0: no cable, 1:usb, 2:AC */  
        u32 charging_enabled;        /* 0: Disable, 1: Enable */  
        u32 batt_health;        /* Battery Health (Authority) */  
        u32 batt_is_full; /* 0 : Not full 1: Full */  
};  
  
/* lock to protect the battery info */  
static DEFINE_MUTEX(work_lock);  
  
struct s3c_battery_info {  
        int present;  
        int polling;  
        unsigned long polling_interval;  
  
        struct battery_info bat_info;  
};  
static struct s3c_battery_info s3c_bat_info;  
  
static int s3c_adc_read(void)  
{  
        int value;  
        __ADC_locked = 1;  
  
        START_ADC_AIN(adcdev.channel, adcdev.prescale);  
  
        wait_event_interruptible(adcdev.wait, ev_adc);  
        ev_adc = 0;  
        value = adc_data;  
        __ADC_locked = 0;  
        return value;  
}  
  
static int s3c_get_bat_level(struct power_supply *bat_ps)  
{  
        int level;  
        int voltage;  
        //level = s3c_adc_read();  
        //printk("times is %d\n",times);  
        level = ad_value / times;  
        ad_value = 0;  
        times = 0;  
        //printk("read ad is +++++++++++++++++++++++++ %d\n",level);  
  
        voltage = (level * 3300) / 10230;  
        //printk("voltage is +++++++++++++++++++++++++ %d\n",voltage);  
        if(voltage < 185)  
                level = 0;  
        else if(voltage > 210)  
                level = 100;  
        else  
                level = (voltage - 185) * 4;  
        //printk("report level is %d\n",level);  
        return level;  
}  
  
static int s3c_get_bat_vol(struct power_supply *bat_ps)  
{  
        int bat_vol = 0;  
  
        return bat_vol;  
}  
  
static u32 s3c_get_bat_health(void)  
{  
        return s3c_bat_info.bat_info.batt_health;  
}  
  
static int s3c_get_bat_temp(struct power_supply *bat_ps)  
{  
        int temp = 0;  
  
        return temp;  
}  
  
static int s3c_bat_get_charging_status(void)  
{  
        charger_type_t charger = CHARGER_BATTERY;  
        int ret = 0;  
          
        charger = s3c_bat_info.bat_info.charging_source;  
          
        switch (charger) {  
        case CHARGER_BATTERY:  
                ret = POWER_SUPPLY_STATUS_NOT_CHARGING;  
                break;  
        case CHARGER_USB:  
        case CHARGER_AC:  
       
补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,