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 ,