mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
add battery module on 100520
This commit is contained in:
3
.config
3
.config
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.32.9
|
||||
# Tue May 18 22:11:51 2010
|
||||
# Wed May 19 19:32:08 2010
|
||||
#
|
||||
CONFIG_ARM=y
|
||||
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
|
||||
@@ -819,6 +819,7 @@ CONFIG_POWER_SUPPLY=y
|
||||
# CONFIG_BATTERY_DS2782 is not set
|
||||
# CONFIG_BATTERY_BQ27x00 is not set
|
||||
# CONFIG_BATTERY_MAX17040 is not set
|
||||
CONFIG_BATTERY_RK2818=y
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_THERMAL is not set
|
||||
# CONFIG_WATCHDOG is not set
|
||||
|
||||
@@ -376,7 +376,7 @@ static int rk28_adc_probe(struct platform_device *pdev)
|
||||
|
||||
rk28_adc_int_disable(adc);
|
||||
pAdcDev = adc;
|
||||
printk("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
|
||||
printk(KERN_INFO "rk2818 adc: driver initialized\n");
|
||||
return 0;
|
||||
|
||||
err_clk:
|
||||
@@ -452,7 +452,6 @@ static int __init adc_init(void)
|
||||
ret = platform_driver_register(&rk28_adc_driver);
|
||||
if (ret)
|
||||
printk(KERN_ERR "%s: failed to add adc driver\n", __func__);
|
||||
printk("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -291,6 +291,7 @@ static struct platform_device *devices[] __initdata = {
|
||||
&rk2818_device_pmem,
|
||||
&rk2818_device_adc,
|
||||
&rk2818_device_adckey,
|
||||
&rk2818_device_battery,
|
||||
&rk2818_device_fb,
|
||||
&rk2818_device_backlight,
|
||||
&rk2818_device_dsp,
|
||||
|
||||
@@ -279,6 +279,11 @@ struct platform_device rk2818_device_adckey = {
|
||||
.dev.parent = &rk2818_device_adc.dev,
|
||||
};
|
||||
|
||||
struct platform_device rk2818_device_battery = {
|
||||
.name = "rk2818-battery",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* rk2818 dsp device
|
||||
|
||||
@@ -30,6 +30,7 @@ extern struct platform_device rk2818_device_pmem;
|
||||
extern struct platform_device rk2818_device_fb;
|
||||
extern struct platform_device rk2818_device_adc;
|
||||
extern struct platform_device rk2818_device_adckey;
|
||||
extern struct platform_device rk2818_device_battery;
|
||||
extern struct platform_device rk2818_device_backlight;
|
||||
extern struct platform_device rk2818_device_dsp;
|
||||
#endif
|
||||
|
||||
@@ -424,7 +424,7 @@ config KEYBOARD_W90P910
|
||||
module will be called w90p910_keypad.
|
||||
config KEYBOARD_RK28ADC
|
||||
tristate "RK2818 ADC Keypad support"
|
||||
depends on ARCH_RK2818
|
||||
depends on RK28_ADC
|
||||
default y
|
||||
help
|
||||
Say Y here to enable the adc keypad on SDK board
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/adc.h>
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
#define DBG(x...) printk(x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
@@ -34,14 +34,16 @@
|
||||
|
||||
//ROCKCHIP AD KEY CODE ,for demo board
|
||||
// key ---> EV
|
||||
#define AD2KEY1 114 ///VOLUME_DOWN
|
||||
#define AD2KEY2 115 ///VOLUME_UP
|
||||
#define AD2KEY3 59 ///MENU
|
||||
#define AD2KEY4 102 ///HOME
|
||||
#define AD2KEY5 158 ///BACK
|
||||
#define AD2KEY6 61 ///CALL
|
||||
#define AD2KEY1 114 ///VOLUME_DOWN
|
||||
#define AD2KEY2 115 ///VOLUME_UP
|
||||
#define AD2KEY3 59 ///MENU
|
||||
#define AD2KEY4 102 ///HOME
|
||||
#define AD2KEY5 158 ///BACK
|
||||
#define AD2KEY6 61 ///CALL
|
||||
|
||||
#define KEYMENU AD2KEY6
|
||||
#define KEYSTART 28 //ENTER
|
||||
#define KEYMENU AD2KEY6 ///CALL
|
||||
#define KEY_PLAYON_PIN RK2818_PIN_PE1
|
||||
#define ENDCALL 62
|
||||
|
||||
#define Valuedrift 50
|
||||
@@ -56,6 +58,7 @@
|
||||
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;
|
||||
volatile unsigned int gThisCode = 0;
|
||||
@@ -94,7 +97,6 @@ struct rk28_adckey
|
||||
struct input_dev *input_dev;
|
||||
struct timer_list timer;
|
||||
unsigned char keycodes[ADKEYNUM];
|
||||
struct clk *clk;
|
||||
void __iomem *mmio_base;
|
||||
};
|
||||
|
||||
@@ -112,6 +114,17 @@ unsigned int rk28_get_keycode(unsigned int advalue,pADC_keyst ptab)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t rk2818_playkey_irq(int irq, void *handle)
|
||||
{
|
||||
input_report_key(pRk28AdcKey->input_dev,KEYSTART,1);
|
||||
input_sync(pRk28AdcKey->input_dev);
|
||||
input_report_key(pRk28AdcKey->input_dev,KEYSTART,0);
|
||||
input_sync(pRk28AdcKey->input_dev);
|
||||
printk("Enter::%s,LINE=%d,KEYSTART=%d,0\n",__FUNCTION__,__LINE__,KEYSTART);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rk28_adckey_open(struct input_dev *dev)
|
||||
{
|
||||
//struct rk28_adckey *adckey = input_get_drvdata(dev);
|
||||
@@ -128,26 +141,20 @@ static void rk28_adckey_close(struct input_dev *dev)
|
||||
#ifdef CONFIG_PM
|
||||
static int rk28_adckey_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct rk28_adckey *adckey = platform_get_drvdata(pdev);
|
||||
//struct rk28_adckey *adckey = platform_get_drvdata(pdev);
|
||||
|
||||
clk_disable(adckey->clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk28_adckey_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct rk28_adckey *adckey = platform_get_drvdata(pdev);
|
||||
struct input_dev *input_dev = adckey->input_dev;
|
||||
|
||||
//struct rk28_adckey *adckey = platform_get_drvdata(pdev);
|
||||
//struct input_dev *input_dev = adckey->input_dev;
|
||||
#if 0
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users) {
|
||||
/* Enable unit clock */
|
||||
clk_enable(adckey->clk);
|
||||
}
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
@@ -267,7 +274,7 @@ static int __devinit rk28_adckey_probe(struct platform_device *pdev)
|
||||
if (!input_dev) {
|
||||
dev_err(&pdev->dev, "failed to allocate input device\n");
|
||||
error = -ENOMEM;
|
||||
goto failed_put_clk;
|
||||
goto failed_free;
|
||||
}
|
||||
|
||||
input_dev->name = pdev->name;
|
||||
@@ -314,17 +321,33 @@ static int __devinit rk28_adckey_probe(struct platform_device *pdev)
|
||||
goto failed_free_dev;
|
||||
}
|
||||
|
||||
error = gpio_request(KEY_PLAYON_PIN, "play key gpio");
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to request play key gpio\n");
|
||||
goto free_gpio;
|
||||
}
|
||||
|
||||
gpio_pull_updown(KEY_PLAYON_PIN,GPIOPullUp);
|
||||
error = request_irq(gpio_to_irq(KEY_PLAYON_PIN),rk2818_playkey_irq,IRQF_TRIGGER_FALLING,NULL,NULL);
|
||||
if(error)
|
||||
{
|
||||
printk("unable to request play key irq\n");
|
||||
goto free_gpio_irq;
|
||||
}
|
||||
|
||||
setup_timer(&adckey->timer, rk28_adkeyscan_timer, (unsigned long)adckey);
|
||||
adckey->timer.expires = jiffies+50;
|
||||
add_timer(&adckey->timer);
|
||||
DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
|
||||
printk(KERN_INFO "rk2818_adckey: driver initialized\n");
|
||||
return 0;
|
||||
|
||||
|
||||
free_gpio_irq:
|
||||
free_irq(gpio_to_irq(KEY_PLAYON_PIN),NULL);
|
||||
free_gpio:
|
||||
gpio_free(KEY_PLAYON_PIN);
|
||||
failed_free_dev:
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
input_free_device(input_dev);
|
||||
failed_put_clk:
|
||||
//clk_put(adckey->clk);
|
||||
failed_free:
|
||||
kfree(adckey);
|
||||
return error;
|
||||
@@ -339,6 +362,9 @@ static int __devexit rk28_adckey_remove(struct platform_device *pdev)
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -356,7 +382,6 @@ static struct platform_driver rk28_adckey_driver =
|
||||
|
||||
int __init rk28_adckey_init(void)
|
||||
{
|
||||
DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
|
||||
return platform_driver_register(&rk28_adckey_driver);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,4 +110,9 @@ config CHARGER_PCF50633
|
||||
help
|
||||
Say Y to include support for NXP PCF50633 Main Battery Charger.
|
||||
|
||||
config BATTERY_RK2818
|
||||
tristate "RK2818 battery"
|
||||
depends on KEYBOARD_RK28ADC
|
||||
help
|
||||
Say Y to enable support for the battery on the RK2818.
|
||||
endif # POWER_SUPPLY
|
||||
|
||||
@@ -29,3 +29,4 @@ obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
|
||||
obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
|
||||
obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
|
||||
obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
|
||||
obj-$(CONFIG_BATTERY_RK2818) += rk2818_battery.o
|
||||
|
||||
410
drivers/power/rk2818_battery.c
Normal file
410
drivers/power/rk2818_battery.c
Normal file
@@ -0,0 +1,410 @@
|
||||
/* drivers/power/rk2818_battery.c
|
||||
*
|
||||
* Power supply driver for the rk2818 emulator
|
||||
*
|
||||
* Copyright (C) 2008 Google, Inc.
|
||||
* Author: Mike Lockwood <lockwood@android.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/io.h>
|
||||
#include <mach/adc.h>
|
||||
|
||||
#if 1
|
||||
#define DBG(x...) printk(x)
|
||||
#else
|
||||
#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 4000
|
||||
|
||||
static int gBatStatus = POWER_SUPPLY_STATUS_UNKNOWN;
|
||||
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;
|
||||
extern int dwc_vbus_status(void);
|
||||
|
||||
struct rk2818_battery_data {
|
||||
int irq;
|
||||
spinlock_t lock;
|
||||
struct timer_list timer;
|
||||
struct power_supply battery;
|
||||
struct power_supply usb;
|
||||
struct power_supply ac;
|
||||
|
||||
int adc_bat_divider;
|
||||
int bat_max;
|
||||
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;
|
||||
|
||||
enum {
|
||||
BATTERY_STATUS = 0,
|
||||
BATTERY_HEALTH = 1,
|
||||
BATTERY_PRESENT = 2,
|
||||
BATTERY_CAPACITY = 3,
|
||||
BATTERY_AC_ONLINE = 4,
|
||||
BATTERY_STATUS_CHANGED = 5,
|
||||
AC_STATUS_CHANGED = 6,
|
||||
BATTERY_INT_STATUS = 7,
|
||||
BATTERY_INT_ENABLE = 8,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CHARGER_BATTERY = 0,
|
||||
CHARGER_USB,
|
||||
CHARGER_AC
|
||||
} charger_type_t;
|
||||
|
||||
static int rk2818_get_charge_status(void)
|
||||
{
|
||||
//return dwc_vbus_status();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void rk2818_get_bat_status(struct rk2818_battery_data *bat)
|
||||
{
|
||||
if(rk2818_get_charge_status() == 1)
|
||||
gBatStatus = POWER_SUPPLY_STATUS_CHARGING;
|
||||
else
|
||||
gBatStatus = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
||||
}
|
||||
|
||||
static void rk2818_get_bat_health(struct rk2818_battery_data *bat)
|
||||
{
|
||||
gBatHealth = POWER_SUPPLY_HEALTH_GOOD;
|
||||
}
|
||||
|
||||
static void rk2818_get_bat_present(struct rk2818_battery_data *bat)
|
||||
{
|
||||
if(gBatVoltage < bat->bat_min)
|
||||
gBatPresent = 0;
|
||||
else
|
||||
gBatPresent = 1;
|
||||
}
|
||||
|
||||
static void rk2818_get_bat_voltage(struct rk2818_battery_data *bat)
|
||||
{
|
||||
unsigned long value;
|
||||
value = gAdcValue[CHN_BAT_ADC];
|
||||
gBatVoltage = value * 1000000 / bat->adc_bat_divider;
|
||||
}
|
||||
|
||||
static void rk2818_get_bat_capacity(struct rk2818_battery_data *bat)
|
||||
{
|
||||
gBatCapacity = (gBatVoltage * 100) / bat->bat_max;
|
||||
}
|
||||
|
||||
|
||||
static void rk2818_batscan_timer(unsigned long data)
|
||||
{
|
||||
gBatteryData->timer.expires = jiffies + msecs_to_jiffies(20);
|
||||
add_timer(&gBatteryData->timer);
|
||||
rk2818_get_bat_status(gBatteryData);
|
||||
rk2818_get_bat_health(gBatteryData);
|
||||
rk2818_get_bat_present(gBatteryData);
|
||||
rk2818_get_bat_voltage(gBatteryData);
|
||||
rk2818_get_bat_capacity(gBatteryData);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int rk2818_usb_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
charger_type_t charger;
|
||||
//todo
|
||||
charger = CHARGER_USB;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
if (psy->type == POWER_SUPPLY_TYPE_USB)
|
||||
val->intval = (charger == CHARGER_AC ? 1 : 0);
|
||||
else
|
||||
val->intval = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int rk2818_ac_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
// struct rk2818_battery_data *data = container_of(psy,
|
||||
// struct rk2818_battery_data, ac);
|
||||
int ret = 0;
|
||||
charger_type_t charger;
|
||||
//todo
|
||||
charger = CHARGER_USB;
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
if (psy->type == POWER_SUPPLY_TYPE_MAINS)
|
||||
val->intval = (charger == CHARGER_AC ? 1 : 0);
|
||||
else if (psy->type == POWER_SUPPLY_TYPE_USB)
|
||||
val->intval = (charger == CHARGER_USB ? 1 : 0);
|
||||
else
|
||||
val->intval = 0;
|
||||
//val->intval = RK2818_BATTERY_READ(data, BATTERY_AC_ONLINE);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk2818_battery_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct rk2818_battery_data *data = container_of(psy,
|
||||
struct rk2818_battery_data, battery);
|
||||
int ret = 0;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
val->intval = gBatStatus;
|
||||
DBG("gBatStatus=0x%x\n",val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
val->intval = gBatHealth;
|
||||
DBG("gBatHealth=0x%x\n",val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
val->intval = gBatPresent;
|
||||
DBG("gBatPresent=0x%x\n",val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
val ->intval = gBatVoltage;
|
||||
DBG("gBatVoltage=0x%x\n",val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TECHNOLOGY:
|
||||
val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CAPACITY:
|
||||
val->intval = gBatCapacity;
|
||||
DBG("gBatCapacity=0x%x\n",val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
|
||||
val->intval = data->bat_max;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
|
||||
val->intval = data->bat_min;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum power_supply_property rk2818_battery_props[] = {
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_TECHNOLOGY,
|
||||
POWER_SUPPLY_PROP_CAPACITY,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
|
||||
};
|
||||
|
||||
static enum power_supply_property rk2818_usb_props[] = {
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int rk2818_battery_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
//struct resource *r;
|
||||
struct rk2818_battery_data *data;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (data == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err_data_alloc_failed;
|
||||
}
|
||||
spin_lock_init(&data->lock);
|
||||
|
||||
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->usb.properties = rk2818_usb_props;
|
||||
data->usb.num_properties = ARRAY_SIZE(rk2818_ac_props);
|
||||
data->usb.get_property = rk2818_usb_get_property;
|
||||
data->usb.name = "usb";
|
||||
data->usb.type = POWER_SUPPLY_TYPE_USB;
|
||||
|
||||
data->ac.properties = rk2818_ac_props;
|
||||
data->ac.num_properties = ARRAY_SIZE(rk2818_ac_props);
|
||||
data->ac.get_property = rk2818_ac_get_property;
|
||||
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)
|
||||
goto err_ac_failed;
|
||||
|
||||
ret = power_supply_register(&pdev->dev, &data->usb);
|
||||
if (ret)
|
||||
goto err_usb_failed;
|
||||
|
||||
ret = power_supply_register(&pdev->dev, &data->battery);
|
||||
if (ret)
|
||||
goto err_battery_failed;
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
gBatteryData = data;
|
||||
|
||||
setup_timer(&data->timer, rk2818_batscan_timer, (unsigned long)data);
|
||||
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;
|
||||
|
||||
err_battery_failed:
|
||||
power_supply_unregister(&data->usb);
|
||||
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:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk2818_battery_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rk2818_battery_data *data = platform_get_drvdata(pdev);
|
||||
|
||||
power_supply_unregister(&data->battery);
|
||||
power_supply_unregister(&data->ac);
|
||||
|
||||
free_irq(data->irq, data);
|
||||
kfree(data);
|
||||
gBatteryData = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rk2818_battery_device = {
|
||||
.probe = rk2818_battery_probe,
|
||||
.remove = rk2818_battery_remove,
|
||||
.driver = {
|
||||
.name = "rk2818-battery",
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init rk2818_battery_init(void)
|
||||
{
|
||||
return platform_driver_register(&rk2818_battery_device);
|
||||
}
|
||||
|
||||
static void __exit rk2818_battery_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rk2818_battery_device);
|
||||
}
|
||||
|
||||
module_init(rk2818_battery_init);
|
||||
module_exit(rk2818_battery_exit);
|
||||
|
||||
MODULE_AUTHOR("Mike Lockwood lockwood@android.com");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Battery driver for the Goldfish emulator");
|
||||
|
||||
Reference in New Issue
Block a user