#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 <linux/adc.h>
-#include <mach/iomux.h>
-#include <mach/board.h>
#include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/init.h>
-#include <linux/earlysuspend.h>
#include <linux/suspend.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/power/rockchip-adc-battery.h>
+#include <linux/rk_keys.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+#include <linux/iio/consumer.h>
+
#ifdef CONFIG_EARLYSUSPEND
/* kernel/power/earlysuspend.c */
extern suspend_state_t get_suspend_state(void);
#endif
-static int rk30_battery_dbg_level = 0;
+static int rk30_battery_dbg_level;
module_param_named(dbg_level, rk30_battery_dbg_level, int, 0644);
#define DBG( args...) \
- do { \
- if (rk30_battery_dbg_level) { \
- pr_info(args); \
- } \
- } while (0)
+do {\
+ if (rk30_battery_dbg_level) {\
+ pr_info(args);\
+ } \
+} while (0)
#define TIMER_MS_COUNTS 1000
#define SLOPE_SECOND_COUNTS 15
-#define DISCHARGE_MIN_SECOND 45
+#define DISCHARGE_MIN_SECOND 30
#define CHARGE_MIN_SECOND 45
#define CHARGE_MID_SECOND 90
#define CHARGE_MAX_SECOND 250
#define CHARGE_FULL_DELAY_TIMES 10
-#define USBCHARGE_IDENTIFY_TIMES 5
+#define USBCHARGE_IDENTIFY_TIMES 2
#define NUM_VOLTAGE_SAMPLE ((SLOPE_SECOND_COUNTS * 1000) / TIMER_MS_COUNTS)
#define NUM_DISCHARGE_MIN_SAMPLE ((DISCHARGE_MIN_SECOND * 1000) / TIMER_MS_COUNTS)
#elif defined(CONFIG_ARCH_RK2928)
#define BAT_DEFINE_VALUE 3300
#else
-#define BAT_DEFINE_VALUE 2500
+#define BAT_DEFINE_VALUE 3300 /*2500*/
#endif
+#define RK30_GPIO_LOW 0
+#define RK30_GPIO_HIGH 1
+
+
-#define BATT_FILENAME "/data/bat_last_capacity.dat"
+//#define BATT_FILENAME "/data/bat_last_capacity.dat"
#define BATTERY_APK
int gVoltageCnt = 3400;
int gDoubleVoltageCnt = 6800;
unsigned long gSecondsCnt = 0;
-char gDischargeFlag[3] = {"on "};
+char gDischargeFlag[4] = {"on "};
+static int g_old_cap = -1;
+static int g_uboot_incre = 0;
-
-#ifdef CONFIG_BATTERY_RK30_VOL3V8
-#define BATT_MAX_VOL_VALUE 4120 //Full charge volate
-#define BATT_ZERO_VOL_VALUE 3500 //power down voltage
+#if 1
+#define BATT_MAX_VOL_VALUE 4250/*Full charge volatge*/
+#define BATT_ZERO_VOL_VALUE 3500/*power down voltage*/
#define BATT_NOMAL_VOL_VALUE 3800
static int batt_table[2*BATT_NUM+6] =
#define adc_to_voltage(adc_val) ((adc_val * BAT_DEFINE_VALUE * (batt_table[4] +batt_table[5])) / (1024 *batt_table[5]))
#else
#define BATT_MAX_VOL_VALUE 8284 //Full charge voltage
-#define BATT_ZERO_VOL_VALUE 6800 // power down voltage
+#define BATT_ZERO_VOL_VALUE 6900 // power down voltage
#define BATT_NOMAL_VOL_VALUE 7600
//struct timer_list timer;
struct workqueue_struct *wq;
struct delayed_work delay_work;
- struct delayed_work check_work;
+ struct delayed_work check_work;
struct work_struct dcwakeup_work;
struct work_struct lowerpower_work;
bool resume;
int start_voltage_status;
int charge_up_proprotion;
int charge_down_proportion;
+ int voltage_to_local;
unsigned long suspend_time;
unsigned long resume_time;
+ int adc_value;
int full_times;
int charge_full_flag;
int stop_check;
+ struct notifier_block battery_nb;
+ int lower_power_flag;
+ int time_to_full;
};
static struct rk30_adc_battery_data *gBatteryData;
static struct wake_lock batt_wake_lock;
+static struct wake_lock batt_wake_lock_detect_lowpower;
static struct wake_lock charge_display_lock;
int system_lowerpower = 0;
-
+extern void kernel_power_off(void);
extern int dwc_vbus_status(void);
extern int get_gadget_connect_flag(void);
extern int dwc_otg_check_dpdm(void);
static int is_charge_ok(struct rk30_adc_battery_data *bat);
static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat);
-
-
+static bool batt_gpio_is_valid(int number)
+{
+ return number > 0 && number < 256;
+}
#ifdef BATTERY_APK
//#define BAT_ADC_TABLE_LEN 11
static ssize_t bat_param_read(struct device *dev,struct device_attribute *attr, char *buf)
printk("i=%d batt_table=%d\n",i+17,batt_table[i+17]);
return 0;
}
-DEVICE_ATTR(batparam, 0664, bat_param_read,NULL);
+DEVICE_ATTR(batparam, 0444, bat_param_read, NULL);
static ssize_t rkbatt_show_debug_attrs(struct device *dev,
}
return size;
}
+
+static int __init adc_bootloader_setup(char *str)
+{
+
+ if(str) {
+ printk("adc.incre is %s\n", str);
+ sscanf(str, "%d", &g_uboot_incre);
+ }
+ return 0;
+}
+early_param("adc.incre", adc_bootloader_setup);
+
+static ssize_t rkbatt_show_oldcap_attrs(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", g_old_cap);
+}
+
+static ssize_t rkbatt_restore_oldcap_attrs(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ int old_cap;
+
+ sscanf(buf, "%d", &old_cap);
+
+ if(old_cap >= 0 && old_cap <= 100)
+ {
+ g_old_cap = old_cap;
+ }
+ else
+ {
+ dev_err(dev, "rk29adc_restore_oldcap_attrs err\n");
+ }
+ return size;
+}
+
+
static struct device_attribute rkbatt_attrs[] = {
__ATTR(state, 0664, rkbatt_show_state_attrs, rkbatt_restore_state_attrs),
__ATTR(debug, 0664, rkbatt_show_debug_attrs, rkbatt_restore_debug_attrs),
- __ATTR(value, 0666, rkbatt_show_value_attrs, rkbatt_restore_value_attrs),
- __ATTR(flag, 0666, rkbatt_show_flag_attrs, rkbatt_restore_flag_attrs),
+ __ATTR(value, 0555, rkbatt_show_value_attrs, rkbatt_restore_value_attrs),
+ __ATTR(flag, 0555, rkbatt_show_flag_attrs, rkbatt_restore_flag_attrs),
+ __ATTR(oldcap, 0664, rkbatt_show_oldcap_attrs, rkbatt_restore_oldcap_attrs),
};
+static int rk_adc_battery_iio_read(struct rk30_adc_battery_platform_data *data)
+{
+ struct iio_channel *channel = data->chan;
+ int val, ret;
+
+ ret = iio_read_channel_raw(channel, &val);
+ if (ret < 0) {
+ pr_err("read channel() error: %d\n", ret);
+ return ret;
+ }
+ return val;
+}
+
+
static int create_sysfs_interfaces(struct device *dev)
{
int liTmep;
#endif
-
+#if 0
static int rk30_adc_battery_load_capacity(void)
{
char value[4];
sys_write(fd, (const char __user *)value, 4);
sys_close(fd);
}
+#endif
+static BLOCKING_NOTIFIER_HEAD(adc_battery_chain_head);
+
+int register_adc_battery_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&adc_battery_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(register_adc_battery_notifier);
+
+int unregister_adc_battery_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&adc_battery_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_adc_battery_notifier);
+
+int adc_battery_notifier_call_chain(unsigned long val)
+{
+ return (blocking_notifier_call_chain(&adc_battery_chain_head, val, NULL)
+ == NOTIFY_BAD) ? -EINVAL : 0;
+}
+EXPORT_SYMBOL_GPL(adc_battery_notifier_call_chain);
static void rk_start_charge(struct rk30_adc_battery_data *bat)
{
struct rk30_adc_battery_platform_data *pdata = bat->pdata;
-
- if (pdata->charge_set_pin != INVALID_GPIO){
+ if (batt_gpio_is_valid(pdata->charge_set_pin))
gpio_direction_output(pdata->charge_set_pin, pdata->charge_set_level);
- }
}
static void rk_stop_charge(struct rk30_adc_battery_data *bat)
{
struct rk30_adc_battery_platform_data *pdata = bat->pdata;
- if (pdata->charge_set_pin != INVALID_GPIO){
+
+ if (batt_gpio_is_valid(pdata->charge_set_pin))
gpio_direction_output(pdata->charge_set_pin, 1 - pdata->charge_set_level);
- }
}
static int get_ac_status(struct rk30_adc_battery_data *bat){
struct rk30_adc_battery_platform_data *pdata = bat->pdata;
int status = 0;
- if (pdata->dc_det_pin != INVALID_GPIO){
+ if (batt_gpio_is_valid(pdata->dc_det_pin)) {
if (gpio_get_value (pdata->dc_det_pin) == pdata->dc_det_level){
status = 1;
}else{
return status;
}
-// state of charge --- charge-display
-static int get_usb_status1(struct rk30_adc_battery_data *bat){
+#if defined CONFIG_BATTERY_RK30_USB_CHARGE
-}
//state of charge ----running
static int get_usb_status2(struct rk30_adc_battery_data *bat){
// struct rk30_adc_battery_platform_data *pdata = bat->pdata;
int usb_status = 0; // 0--dischage ,1 ---usb charge, 2 ---ac charge
+ int vbus_status = dwc_vbus_status();
- if (1 == dwc_vbus_status()) {
+ if (1 == vbus_status) {
if (0 == get_gadget_connect_flag()){
if (++bat->gBatUsbChargeCnt >= NUM_USBCHARGE_IDENTIFY_TIMES){
bat->gBatUsbChargeCnt = NUM_USBCHARGE_IDENTIFY_TIMES + 1;
usb_status = 2; // non-standard AC charger
if(bat ->pdata ->control_usb_charging)
bat ->pdata ->control_usb_charging(1);
+ }else{
+ usb_status = 1; // connect to pc
+ if(bat ->pdata ->control_usb_charging)
+ bat ->pdata ->control_usb_charging(0);
}
}else{
}else{
bat->gBatUsbChargeCnt = 0;
- if (2 == dwc_vbus_status()) {
+ if (2 == vbus_status) {
usb_status = 2; //standard AC charger
if(bat ->pdata ->control_usb_charging)
return usb_status;
}
-
+#endif
static int rk_battery_get_status(struct rk30_adc_battery_data *bat)
{
int charge_on = 0;
- struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+/* struct rk30_adc_battery_platform_data *pdata = bat->pdata;*/
int ac_ac_charging = 0, usb_ac_charging = 0;
int i=0;
-#if defined (CONFIG_BATTERY_RK30_AC_CHARGE)
ac_ac_charging = get_ac_status(bat);
if(1 == ac_ac_charging)
charge_on = 1;
-#endif
#if defined (CONFIG_BATTERY_RK30_USB_CHARGE)
if (strstr(saved_command_line,"charger")){
wake_lock(&charge_display_lock); //lock
- if( bat->pdata->usb_det_pin != INVALID_GPIO ){
+ if (batt_gpio_is_valid(bat->pdata->usb_det_pin)) {
if( gpio_get_value(bat->pdata->usb_det_pin)== bat->pdata->usb_det_level){
if(( 1 == usb_ac_charging )||( 1 == ac_ac_charging ))
bat -> ac_charging = 1;
if( 1 != bat->charge_level)
return -1;
- if((pdata->charge_ok_pin == INVALID_GPIO)&& ( pdata->charging_ok == NULL))
+ if ((!(batt_gpio_is_valid(pdata->charge_ok_pin))) && (
+ pdata->charging_ok == NULL))
return -1;
- if (pdata->charge_ok_pin != INVALID_GPIO){
+ if (batt_gpio_is_valid(pdata->charge_ok_pin)) {
if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level){
charge_is_ok =1;
}
return charge_is_ok;
-
}
//discharge
bat->charge_full_flag = 0;
bat->full_times = 0;
+ bat->time_to_full = 0;
bat->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
}else{
//charging
}
}else{
bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+ if((bat->bat_capacity == 99)&&(bat->time_to_full == 0)){
+ bat->time_to_full = get_seconds();
+ }else if(bat->bat_capacity == 99)
+ {
+ if(get_seconds() - bat->time_to_full > 1800){
+ bat->bat_capacity = 100;
+ bat->time_to_full = 0;
+ }
+
+ }
+
if(bat->pdata->ctrl_charge_led != NULL)
bat->pdata->ctrl_charge_led(0);
}
bat->full_times = 0;
bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+
+ if((bat->bat_capacity == 99)&&(bat->time_to_full == 0)){
+ bat->time_to_full = get_seconds();
+ }else if(bat->bat_capacity == 99)
+ {
+ if(get_seconds() - bat->time_to_full > 1800){
+ bat->bat_capacity = 100;
+ bat->time_to_full = 0;
+ }
+
+ }
+
+
}else{
bat->full_times++;
return charge_level;
}
+
+static int rk_adc_battery_iio_read_refvol(struct rk30_adc_battery_platform_data *data)
+{
+ struct iio_channel *channel = data->ref_voltage_chan;
+ int val, ret;
+
+ ret = iio_read_channel_raw(channel, &val);
+ if (ret < 0) {
+ pr_err("read channel() error: %d\n", ret);
+ return ret;
+ }
+ return val;
+}
+
+static int get_ref_voltage(struct rk30_adc_battery_data *bat)
+{
+ int data_value;
+ struct regulator *logic;
+ int voltage, ref_voltage;
+
+ logic = regulator_get(NULL, "vdd_arm");
+ voltage = regulator_get_voltage(logic);
+ data_value = rk_adc_battery_iio_read_refvol(bat->pdata);
+ ref_voltage = voltage*1024/data_value/1000;
+
+ return ref_voltage;
+}
static int rk_adc_voltage(struct rk30_adc_battery_data *bat, int value)
{
int voltage;
-
- int ref_voltage; //reference_voltage
- int pullup_res;
- int pulldown_res;
+ int ref_voltage;
ref_voltage = bat ->pdata->reference_voltage;
- pullup_res = bat ->pdata->pull_up_res;
- pulldown_res = bat ->pdata->pull_down_res;
- if(ref_voltage && pullup_res && pulldown_res){
-
- voltage = ((value * ref_voltage * (pullup_res + pulldown_res)) / (1024 * pulldown_res));
+ if (ref_voltage) {
+ if (bat->pdata->auto_calibration == 1)
+ ref_voltage = get_ref_voltage(bat);
+ voltage = (value * ref_voltage * (batt_table[4] + batt_table[5])) / (1024 * batt_table[5]);
+ DBG("ref_voltage =%d, voltage=%d\n", ref_voltage, voltage);
}else{
- voltage = adc_to_voltage(value);
+ voltage = adc_to_voltage(value);
}
-
-
+ DBG("ref_voltage =%d, voltage=%d\n", ref_voltage, voltage);
return voltage;
}
value = bat->adc_val;
- adc_async_read(bat->client);
+ bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
*(bat->pSamples++) = rk_adc_voltage(bat,value);
if((get_seconds() - gSecondsCnt) > 30){
gSecondsCnt = get_seconds();
if((gVoltageCnt - bat->bat_voltage) > 15){
- strncpy(gDischargeFlag, "off" ,3);
+ strncpy(gDischargeFlag, "off" ,4);
}
gVoltageCnt = bat->bat_voltage;
if((get_seconds() - gSecondsCnt) > 30){
gSecondsCnt = get_seconds();
if((gDoubleVoltageCnt - bat->bat_voltage) > 30){
- strncpy(gDischargeFlag, "off" ,3);
+ strncpy(gDischargeFlag, "off" ,4);
}
gDoubleVoltageCnt =bat->bat_voltage;
}
int capacity = 0;
int *p;
+
if (bat->pdata->use_board_table)
- p = bat->pdata->board_batt_table;
+ p = bat->pdata->board_batt_table;
+ else if (bat->pdata->dts_batt_table)
+ p = bat->pdata->dts_batt_table;
else
p = batt_table;
+
if (1 == bat->charge_level){ //charge
if(0 == bat->start_voltage_status ){
if(BatVoltage >= (p[2*BATT_NUM +5])){
DBG("start_voltage=%d,start_capacity =%d\n", bat->charge_start_voltage, bat->charge_start_capacity);
DBG("charge_down_proportion =%d,charge_up_proprotion=%d\n",bat ->charge_down_proportion,bat ->charge_up_proprotion);
+ for(i = BATT_NUM +6; i <2*BATT_NUM +5; i++)
+ if(((p[i]) <= bat->charge_start_voltage) && (bat->charge_start_voltage < (p[i+1])))
+ bat->voltage_to_local = i;
if(BatVoltage >= (p[2*BATT_NUM +5])){
capacity = 100;
}else{
for(i = BATT_NUM +6; i <2*BATT_NUM +5; i++)
if(((p[i]) <= BatVoltage) && (BatVoltage < (p[i+1]))){
if( p[i+1] < bat->charge_start_voltage ){
- capacity =(i-(BATT_NUM +6))*(bat ->charge_down_proportion) + ((BatVoltage - p[i]) * bat ->charge_down_proportion)/ (p[i+1]- p[i]);
+ capacity =bat->charge_start_capacity - ((p[i+1] -BatVoltage) * bat->charge_start_capacity/(bat->voltage_to_local -17+1))/ (p[i+1]- p[i]) - (bat->voltage_to_local- (i ))*bat->charge_start_capacity/(bat->voltage_to_local -17+1);
+ DBG("1<<<<<<< %d bat->voltage_to_local =%d capacity = %d BatVoltage =%d p[i] = %d,p[i+1] = %d \n", i, bat->voltage_to_local,capacity,BatVoltage,p[i], p[i+1]);
+
}
else {
- capacity = (i-(BATT_NUM +6))*(bat ->charge_down_proportion) + ((BatVoltage - p[i]) * bat ->charge_down_proportion)/ (bat->charge_start_voltage - p[i]);
+ capacity =bat->charge_start_capacity - ((bat->charge_start_voltage -BatVoltage) * bat->charge_start_capacity/(bat->voltage_to_local -17+1) )/ (bat->charge_start_voltage - p[i]);
+ DBG("2<<<<<< %d capacity = %d BatVoltage =%d p[i] = %d,p[i+1] = %d \n", i,capacity,BatVoltage,p[i], p[i+1]);
}
break;
}
for(i = BATT_NUM +6; i <2*BATT_NUM +5; i++)
if(((p[i]) <= BatVoltage) && (BatVoltage < (p[i+1]))){
if( p[i] > bat->charge_start_voltage ){
- capacity = bat->charge_start_capacity + (i - (BATT_NUM +6)-bat->charge_start_capacity/10)*(bat ->charge_up_proprotion) + ((BatVoltage - p[i]) * bat ->charge_up_proprotion)/ (p[i+1]- p[i]);
+ capacity = bat->charge_start_capacity + (i +1- (bat->voltage_to_local))*(100- bat->charge_start_capacity )/( 10 - (bat->voltage_to_local - 17)) + (BatVoltage - p[i]) * (100- bat->charge_start_capacity )/( 10 - (bat->voltage_to_local -17))/ (p[i+1]- p[i]);
+ DBG("3<<<<<<<< %d bat->voltage_to_local =%d capacity = %d BatVoltage =%d p[i] = %d,p[i+1] = %d \n", i, bat->voltage_to_local,capacity,BatVoltage,p[i], p[i+1]);
}
else {
- capacity = bat->charge_start_capacity + (i - (BATT_NUM +6)-bat->charge_start_capacity/10)*(bat ->charge_up_proprotion) + ((BatVoltage - p[i]) * bat ->charge_up_proprotion)/ (p[i+1] - bat->charge_start_voltage );
- }
+ capacity = bat->charge_start_capacity + (BatVoltage - bat->charge_start_voltage) * (100- bat->charge_start_capacity )/( 10 - (bat->voltage_to_local-17 )) /(p[i+1] - bat->charge_start_voltage );
+ DBG(" 4<<<<<<<<<%d bat->voltage_to_local =%d capacity = %d BatVoltage =%d p[i] = %d,p[i+1] = %d \n", i,bat->voltage_to_local,capacity,BatVoltage,p[i], p[i+1]);
+ }
break;
}
}
DBG("real_voltage_to_capacity =%d\n" ,capacity);
+
return capacity;
}
+#if defined CONFIG_BATTERY_RK30_USB_CHARGE
static void rk_usb_charger(struct rk30_adc_battery_data *bat)
{
-
int capacity = 0;
-// struct rk30_adc_battery_platform_data *pdata = bat->pdata;
int timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE;
int timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE;
bat ->charge_start_voltage = bat ->bat_voltage;
bat ->start_voltage_status = 1;
bat ->charge_start_capacity = bat ->bat_capacity;
- bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10+1;
- bat ->charge_down_proportion = bat ->charge_start_capacity/10+1;
+ if(bat ->charge_start_capacity%10 != 0){
+ bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10+1;
+ bat ->charge_down_proportion = bat ->charge_start_capacity/10+1;
+ }else{
+ bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10;
+ bat ->charge_down_proportion = bat ->charge_start_capacity/10;
+
+
+ }
}
capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage);
timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE - 2; // 13
if (++(bat->gBatCapacityusbChargeCnt) >= timer_of_charge_sample){
bat->gBatCapacityusbChargeCnt = 0;
- if (bat->bat_capacity <= 99){
+ if (bat->bat_capacity < 99){
bat->bat_capacity++;
bat->bat_change = 1;
}
bat->capacitytmp = capacity;
}
+#endif
static void rk_ac_charger(struct rk30_adc_battery_data *bat)
{
int capacity = 0;
bat->charge_start_voltage = bat->bat_voltage;
bat->start_voltage_status = 1;
bat->charge_start_capacity = bat->bat_capacity;
- bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10+1;
- bat ->charge_down_proportion = bat ->charge_start_capacity/10+1;
+ if(bat ->charge_start_capacity%10 != 0){
+ bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10+1;
+ bat ->charge_down_proportion = bat ->charge_start_capacity/10+1;
+ }else{
+ bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10;
+ bat ->charge_down_proportion = bat ->charge_start_capacity/10;
+
+
+ }
}
capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage);
if (capacity > bat->bat_capacity){
timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE - 2; // 13
if (++(bat->gBatCapacityacChargeCnt) >= timer_of_charge_sample){
bat->gBatCapacityacChargeCnt = 0;
- if (bat->bat_capacity <= 99){
+ if (bat->bat_capacity < 99){
bat->bat_capacity++;
bat->bat_change = 1;
}
{
int capacity = 0;
- int timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE;
+ int timer_of_discharge_sample = DISCHARGE_MIN_SECOND;
capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage);
if (capacity < bat->bat_capacity){
+ #if 0
if(capacity <10){
timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 40; // 13
- }else if(capacity < 20){
+ }else
+ #endif
+ if(capacity < 20){
if(capacity + 3 > bat->bat_capacity )
- timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -5; //5s
+ timer_of_discharge_sample = DISCHARGE_MIN_SECOND -5; //5s
else if(capacity + 7 > bat->bat_capacity )
- timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -10; //10s
+ timer_of_discharge_sample = DISCHARGE_MIN_SECOND -10; //10s
else if(capacity + 10> bat->bat_capacity )
- timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -25; // 13
+ timer_of_discharge_sample = DISCHARGE_MIN_SECOND -25; // 13
else
- timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 35; // 13
+ timer_of_discharge_sample = DISCHARGE_MIN_SECOND - 35; // 13
}else{
if(capacity + 3 > bat->bat_capacity )
- timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -5; //5s
+ timer_of_discharge_sample = DISCHARGE_MIN_SECOND -5; //5s
else if(capacity + 7 > bat->bat_capacity )
- timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -10; //10s
+ timer_of_discharge_sample = DISCHARGE_MIN_SECOND -10; //10s
else if(capacity + 10> bat->bat_capacity )
- timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 15; // 13
+ timer_of_discharge_sample = DISCHARGE_MIN_SECOND - 15; // 13
else
- timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 20; // 13
+ timer_of_discharge_sample = DISCHARGE_MIN_SECOND - 20; // 13
}
if (++(bat->gBatCapacityDisChargeCnt) >= timer_of_discharge_sample){
{
// int capacity = 0;
// int timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE;
- int timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE;
+// int timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE;
if (bat->bat_status_cnt < NUM_VOLTAGE_SAMPLE) {
bat->gBatCapacityDisChargeCnt = 0;
int cnt = 50 ;
new_capacity = bat ->bat_capacity;
-//#if defined (CONFIG_BATTERY_RK30_USB_CHARGE)
-// if(dwc_vbus_status() != 0)
-// bat ->bat_status = POWER_SUPPLY_STATUS_CHARGING; // add for charging.
-//#endif
while( cnt -- ){
- old_capacity = rk30_adc_battery_load_capacity();
- if( old_capacity >= 0 ){
+ g_old_cap = g_old_cap + g_uboot_incre;
+ if(g_old_cap > 100)
+ g_old_cap = 100;
+ old_capacity = g_old_cap; // rk30_adc_battery_load_capacity();
+ if( old_capacity != -1 ){
break ;
}
msleep(100);
}
+ printk("func:%s; line:%d; old_capacity = %d; new_capacity = %d; g_uboot_incre = %d\n", __func__, __LINE__, old_capacity, new_capacity,g_uboot_incre);
if ((old_capacity < 0) || (old_capacity > 100)){
old_capacity = new_capacity;
}
else if (bat ->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING){
//chargeing state
-
- if( bat ->pdata->is_reboot_charging == 1)
- bat ->bat_capacity = (old_capacity < 10) ?(old_capacity+2):old_capacity;
- else
- bat ->bat_capacity = (new_capacity > old_capacity) ? new_capacity : old_capacity;
+ bat->bat_capacity = (old_capacity < 10) ? (old_capacity + 2) : old_capacity;
}else{
- if(new_capacity > old_capacity + 50 )
- bat ->bat_capacity = new_capacity;
- else
- bat ->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity; //avoid the value of capacity increase
+ bat ->bat_capacity = old_capacity;
+ if(bat->bat_capacity == 100)
+ bat->bat_capacity = 99;
+ if(bat->bat_capacity == 0)
+ bat->bat_capacity =1;
}
-
+ DBG("oldcapacity %d,newcapacity %d,capacity %d\n", old_capacity
+ , new_capacity, bat->bat_capacity);
bat ->bat_change = 1;
}
+#if defined CONFIG_BATTERY_RK30_USB_CHARGE
#define to_battery_usb_device_info(x) container_of((x), \
struct rk30_adc_battery_data, usb);
case POWER_SUPPLY_PROP_ONLINE:
if (psy->type == POWER_SUPPLY_TYPE_USB){
val->intval = bat ->usb_charging;
- if( 1 == bat->charge_full_flag)
- val->intval = 0;
-
+ if (strstr(saved_command_line,"charger") == NULL){
+ if( 1 == bat->charge_full_flag)
+ val->intval = 0;
+ }
}
break;
.properties = rk30_adc_battery_usb_props,
.num_properties = ARRAY_SIZE(rk30_adc_battery_usb_props),
};
-
+#endif
static irqreturn_t rk30_adc_battery_dc_wakeup(int irq, void *dev_id)
{
disable_irq_nosync(irq);
struct rk30_adc_battery_data *bat = container_of((work), \
struct rk30_adc_battery_data, dcwakeup_work);
- rk28_send_wakeup_key(); // wake up the system
-
-
pdata = bat->pdata;
irq = gpio_to_irq(pdata->dc_det_pin);
free_irq(irq, NULL);
}
power_supply_changed(&bat ->ac);
+ rk_send_wakeup_key();
bat ->bat_status_cnt = 0; //the state of battery is change
union power_supply_propval *val)
{
int ret = 0;
+ int voltage;
struct rk30_adc_battery_data *bat = container_of((psy), \
struct rk30_adc_battery_data, bat);
switch (psp) {
DBG("gBatPresent=%d\n",val->intval);
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- val ->intval = rk30_adc_battery_get_voltage(bat);
+ // val ->intval = rk30_adc_battery_get_voltage(bat);
+ voltage = rk30_adc_battery_get_voltage(bat);
+ val->intval = voltage*1000;
DBG("gBatVoltage=%d\n",val->intval);
break;
case POWER_SUPPLY_PROP_CAPACITY:
bat ->old_charge_level = -1;
bat ->pSamples = bat->adc_samples;
- adc_sync_read(bat->client); //start adc sample
+ bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
+
level = oldlevel = rk_battery_get_status(bat);//rk30_adc_battery_status_samples(bat);//init charge status
for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++) { //0.3 s
//if (bat->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING){
if( 1 == level ){
//chargeing state
- bat->bat_capacity = (new_capacity > old_capacity) ? new_capacity : old_capacity;
+ bat->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity;
}
else{
bat->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity; // aviod the value of capacity increase dicharge
}
+ if (batt_gpio_is_valid(bat->pdata->batt_low_pin)) {
+ if (gpio_get_value(bat ->pdata->batt_low_pin) == bat ->pdata->batt_low_level)
+ bat->bat_capacity = 0;
+
+ }
+ return;
}
static int rk30_adc_battery_suspend(struct platform_device *dev, pm_message_t state)
data ->suspend_time = get_seconds();
cancel_delayed_work(&data ->delay_work);
- if( data ->pdata->batt_low_pin != INVALID_GPIO){
+ if (batt_gpio_is_valid(data->pdata->batt_low_pin)) {
irq = gpio_to_irq(data ->pdata->batt_low_pin);
enable_irq(irq);
{
int irq;
struct rk30_adc_battery_data *data = platform_get_drvdata(dev);
+ if( data->bat_capacity < 10 ){
+ wake_lock_timeout(&batt_wake_lock_detect_lowpower,15*HZ);
+ data->bat_change = 1;
+ }
data ->resume_time = get_seconds();
data ->resume = true;
queue_delayed_work(data->wq, &data ->delay_work, msecs_to_jiffies(100));
- if( data ->pdata->batt_low_pin != INVALID_GPIO){
+ if (batt_gpio_is_valid(data->pdata->batt_low_pin)) {
irq = gpio_to_irq(data ->pdata ->batt_low_pin);
disable_irq_wake(irq);
unsigned long AdcTestCnt = 0;
static void rk30_adc_battery_timer_work(struct work_struct *work)
{
-struct rk30_adc_battery_data *bat = container_of((work), \
- struct rk30_adc_battery_data, delay_work);
+ struct rk30_adc_battery_data *bat = container_of((work), struct
+ rk30_adc_battery_data, delay_work.work);
#ifdef CONFIG_PM
if (bat ->resume) {
}
#endif
bat->stop_check = 1;
+ if( 1 == bat ->lower_power_flag ){
+ bat ->bat_capacity = 0;
+ bat ->bat_change =1;
+ }
if (bat ->poweron_check){
bat ->poweron_check = 0;
rk30_adc_battery_poweron_capacity_check(bat);
}
bat ->charge_level = rk_battery_get_status(bat);
+ DBG("bat ->charge_level =%d\n", bat ->charge_level);
rk30_adc_battery_status_samples(bat);
rk30_adc_battery_voltage_samples(bat);
rk30_adc_battery_capacity_samples(bat);
/*update battery parameter after adc and capacity has been changed*/
if(bat ->bat_change){
bat ->bat_change= 0;
- if(0 == bat ->bat_capacity){
- bat ->ac_charging = 0;
- bat ->usb_charging = 0;
+ if (strstr(saved_command_line,"charger") == NULL){ //when low charging-current,not in charging-displays
+ if(0 == bat ->bat_capacity){
+ bat ->ac_charging = 0;
+ bat ->usb_charging = 0;
+ }
}
- rk30_adc_battery_put_capacity(bat ->bat_capacity);
+ // rk30_adc_battery_put_capacity(bat ->bat_capacity);
power_supply_changed(&bat ->bat);
power_supply_changed(&bat ->ac);
#if defined (CONFIG_BATTERY_RK30_USB_CHARGE)
static int rk30_adc_battery_io_init(struct rk30_adc_battery_platform_data *pdata)
{
int ret = 0;
-
- if (pdata->io_init) {
- pdata->io_init();
- return 0;
- }
-
- //charge control pin
- if (pdata->charge_set_pin != INVALID_GPIO){
- ret = gpio_request(pdata->charge_set_pin, NULL);
- if (ret) {
- printk("failed to request dc_det gpio\n");
- goto error;
- }
- gpio_direction_output(pdata->charge_set_pin, 1 - pdata->charge_set_level);
- }
-
- //dc charge detect pin
- if (pdata->dc_det_pin != INVALID_GPIO){
+
+ if (batt_gpio_is_valid(pdata->dc_det_pin)) {
ret = gpio_request(pdata->dc_det_pin, NULL);
if (ret) {
- printk("failed to request dc_det gpio\n");
+ pr_info("failed to request dc_det gpio\n");
goto error;
}
- gpio_pull_updown(pdata->dc_det_pin, GPIOPullUp);//important
ret = gpio_direction_input(pdata->dc_det_pin);
if (ret) {
- printk("failed to set gpio dc_det input\n");
+ pr_info("failed to set gpio dc_det input\n");
goto error;
}
}
//charge ok detect
- if (pdata->charge_ok_pin != INVALID_GPIO){
+ if (batt_gpio_is_valid(pdata->charge_ok_pin)) {
ret = gpio_request(pdata->charge_ok_pin, NULL);
if (ret) {
- printk("failed to request charge_ok gpio\n");
+ pr_err("failed to request charge_ok gpio\n");
goto error;
}
- gpio_pull_updown(pdata->charge_ok_pin, GPIOPullUp);//important
ret = gpio_direction_input(pdata->charge_ok_pin);
if (ret) {
- printk("failed to set gpio charge_ok input\n");
+ pr_err("failed to set gpio charge_ok input\n");
goto error;
}
}
//batt low pin
- if( pdata->batt_low_pin != INVALID_GPIO){
+ if (batt_gpio_is_valid(pdata->batt_low_pin)) {
ret = gpio_request(pdata->batt_low_pin, NULL);
if (ret) {
- printk("failed to request batt_low_pin gpio\n");
+ pr_err("failed to request batt_low_pin gpio\n");
goto error;
}
- gpio_pull_updown(pdata->batt_low_pin, GPIOPullUp);
ret = gpio_direction_input(pdata->batt_low_pin);
if (ret) {
- printk("failed to set gpio batt_low_pin input\n");
+ pr_err("failed to set gpio batt_low_pin input\n");
goto error;
}
}
int get_battery_status(void)
{
return system_lowerpower;
+}
+static int rk_adc_battery_poweron_status(struct rk30_adc_battery_data *bat)
+{
+ int status;
+#if defined CONFIG_BATTERY_RK30_USB_CHARGE
+ int otg_status = 0;
+#endif
+
+// struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+
+ if (get_ac_status(bat) ){
+ bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+ bat -> ac_charging = 1;
+ if (is_charge_ok(bat) == 1){
+ bat->bat_status = POWER_SUPPLY_STATUS_FULL;
+ bat->bat_capacity = 100;
+ }
+ power_supply_changed(&bat ->ac);
+
+ }
+#if defined (CONFIG_BATTERY_RK30_USB_CHARGE)
+ otg_status = dwc_otg_check_dpdm();
+ if( 0 != otg_status ){
+ bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+ if (is_charge_ok(bat) == 1){
+ bat->bat_status = POWER_SUPPLY_STATUS_FULL;
+ bat->bat_capacity = 100;
+ }
+ }
+
+ if(otg_status == 1){
+ bat->usb_charging = 1;
+ if(bat -> pdata ->control_usb_charging)
+ bat -> pdata ->control_usb_charging(0);
+ }else if(otg_status == 2){
+ bat->usb_charging = 0;
+ bat -> ac_charging = 1;
+ if(bat -> pdata ->control_usb_charging)
+ bat -> pdata ->control_usb_charging(1);
+ }else{
+ bat->usb_charging = 0;
+ }
+ printk("charge_status = %d\n",otg_status);
+#endif
+ power_supply_changed(&bat ->ac);
+#if defined (CONFIG_BATTERY_RK30_USB_CHARGE)
+ power_supply_changed(&bat ->usb);
+#endif
+ if((bat -> ac_charging == 1)||(bat->usb_charging == 1)){
+ bat ->old_charge_level =1;
+ bat->charge_level = 1;
+ status =1;
+ }else{
+ bat ->old_charge_level =0;
+ bat->charge_level = 0;
+ status =0;
+ }
+ return status;
+
+
}
static void rk30_adc_battery_check(struct rk30_adc_battery_data *bat)
{
int i;
int level,oldlevel;
- struct rk30_adc_battery_platform_data *pdata = bat->pdata;
-
+// struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+ int check_data[NUM_VOLTAGE_SAMPLE];
+ //bat ->old_charge_level
// pSamples = bat->adc_samples;
- adc_sync_read(bat->client); //start adc sample
- level = oldlevel = rk_battery_get_status(bat);// rk30_adc_battery_status_samples(bat);//init charge status
+
+ bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
+
+ DBG("first_adc_value is %d\n", bat->adc_val);
+ level = oldlevel = rk_adc_battery_poweron_status(bat);// rk30_adc_battery_status_samples(bat);//init charge status
for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++){ //0.3 s
mdelay(1);
rk30_adc_battery_voltage_samples(bat); //get voltage
//level = rk30_adc_battery_status_samples(bat); //check charge status
- level = rk_battery_get_status(bat);
+#if 0
+ level = rk_adc_battery_poweron_status(bat);
if (oldlevel != level){
oldlevel = level; //if charge status changed, reset sample
i = 0;
- }
- bat->charge_level = level;
+ }
+#endif
}
-
-
+ for(i=0; i< NUM_VOLTAGE_SAMPLE; i++){
+ mdelay(10);
+ check_data[i] = bat->adc_val;
+
+ bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
+ bat->adc_value += check_data[i];
+ }
+ bat->adc_value /= NUM_VOLTAGE_SAMPLE;
+
bat->bat_capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage); //init bat_capacity
-
+ bat->capacitytmp = bat->bat_capacity;
+ level = rk_adc_battery_poweron_status(bat);
if((1 == level)&&(0 == bat->start_voltage_status )){
bat->charge_start_voltage = bat->bat_voltage;
bat->start_voltage_status = 1;
bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10+1;
bat ->charge_down_proportion = bat ->charge_start_capacity/10+1;
}
-
- if (get_ac_status(bat) || dwc_otg_check_dpdm() ){
+#if 0
+ if (get_ac_status(bat) ){
+ bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+ bat -> ac_charging = 1;
+ if (is_charge_ok(bat) == 1){
+ bat->bat_status = POWER_SUPPLY_STATUS_FULL;
+ bat->bat_capacity = 100;
+ }
+ }
+#if defined (CONFIG_BATTERY_RK30_USB_CHARGE)
+ if( 0 != dwc_otg_check_dpdm() ){
+ bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
if (is_charge_ok(bat) == 1){
bat->bat_status = POWER_SUPPLY_STATUS_FULL;
bat->bat_capacity = 100;
}
-#if defined (CONFIG_BATTERY_RK30_USB_CHARGE)
- if( 0 != dwc_otg_check_dpdm() )
- bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
- if(dwc_otg_check_dpdm() == 0){
- bat->usb_charging = 0;
- }else if(dwc_otg_check_dpdm() == 1){
- bat->usb_charging = 1;
- if(bat -> pdata ->control_usb_charging)
- bat -> pdata ->control_usb_charging(0);
- }else if(dwc_otg_check_dpdm() == 2){
- bat->usb_charging = 0;
- bat -> ac_charging = 1;
- if(bat -> pdata ->control_usb_charging)
- bat -> pdata ->control_usb_charging(1);
- }
+ }
+
+ if(dwc_otg_check_dpdm() == 1){
+ bat->usb_charging = 1;
+ if(bat -> pdata ->control_usb_charging)
+ bat -> pdata ->control_usb_charging(0);
+ }else if(dwc_otg_check_dpdm() == 2){
+ bat->usb_charging = 0;
+ bat -> ac_charging = 1;
+ if(bat -> pdata ->control_usb_charging)
+ bat -> pdata ->control_usb_charging(1);
+ }else{
+ bat->usb_charging = 0;
+ }
#endif
- if(1 == get_ac_status(bat)){
- bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
- bat -> ac_charging = 1;
- }
- power_supply_changed(&bat ->ac);
+ power_supply_changed(&bat ->ac);
#if defined (CONFIG_BATTERY_RK30_USB_CHARGE)
- power_supply_changed(&bat ->usb);
+ power_supply_changed(&bat ->usb);
#endif
-
+ if((bat -> ac_charging == 1)||(bat->usb_charging == 1)){
+ bat ->old_charge_level =1;
+ bat->charge_level = 1;
}
+
+#endif
#if 0
if (bat->bat_capacity == 0) {
bat->bat_capacity = 1;
system_lowerpower = 1;
}
#endif
+
if(0 !=bat ->pdata->low_voltage_protection ){
- if((bat->bat_voltage <= bat ->pdata->low_voltage_protection)&&(bat->bat_status != POWER_SUPPLY_STATUS_CHARGING))
+ if (bat->bat_voltage <= bat->pdata->low_voltage_protection) {
system_lowerpower = 1;
+ printk("protection lower power .....\n");
+ }
}else{
- if((bat->bat_voltage <= BATT_ZERO_VOL_VALUE)&&(bat->bat_status != POWER_SUPPLY_STATUS_CHARGING))
+ if (bat->bat_voltage <= BATT_ZERO_VOL_VALUE) {
system_lowerpower = 1;
-
+ pr_info("lower power bat->bat_voltage = %d\n"
+ , bat->bat_voltage);
+ }
}
-#if 1
+
+#if 0
if ((bat->bat_voltage <= BATT_ZERO_VOL_VALUE)&&(bat->bat_status != POWER_SUPPLY_STATUS_CHARGING)){
kernel_power_off();
}
}
-static void rk30_adc_battery_callback(struct adc_client *client, void *param, int result)
-{
- struct rk30_adc_battery_data *bat = container_of((client), \
- struct rk30_adc_battery_data, client);
-
- if (result < 0){
- DBG("adc_battery_callback resule < 0 , the value ");
- return;
- }else{
- gBatteryData->adc_val = result;
- DBG("result = %d, gBatteryData->adc_val = %d\n", result, gBatteryData->adc_val );
- }
- return;
-}
-
static void rk30_adc_battery_lowerpower_delaywork(struct work_struct *work)
{
int irq;
struct rk30_adc_battery_data *bat = container_of((work), \
struct rk30_adc_battery_data, lowerpower_work);
- if( bat->pdata->batt_low_pin != INVALID_GPIO){
+ if (batt_gpio_is_valid(bat->pdata->batt_low_pin)) {
irq = gpio_to_irq(bat ->pdata ->batt_low_pin);
disable_irq(irq);
}
printk("lowerpower\n");
- rk28_send_wakeup_key(); // wake up the system
return;
}
queue_work(gBatteryData->wq, &gBatteryData->lowerpower_work);
return IRQ_HANDLED;
}
+static void rk_lowerpower_check(struct rk30_adc_battery_data *bat)
+{
+ int adc_val;
+ int i;
+ int check_data[NUM_VOLTAGE_SAMPLE];
+
+ for(i=0; i< NUM_VOLTAGE_SAMPLE; i++){
+ mdelay(10);
+ bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
+ check_data[i] = bat->adc_val;
+
+ adc_val += check_data[i];
+ }
+ adc_val /=NUM_VOLTAGE_SAMPLE;
+
+ DBG(">>>>>>>>>>>one>>>%d, two<<<<<%d<<<<\n",bat->adc_value,adc_val);
+ DBG(">>>>>>>>>>>firset-value>>>%d, second-value<<<<<%d<<<<\n",rk_adc_voltage(bat, bat->adc_value),rk_adc_voltage(bat, adc_val));
+ if((adc_val >= bat->adc_value+5) &&(bat->bat_status == POWER_SUPPLY_STATUS_NOT_CHARGING ) )//
+ {
+ printk("%d,%d\n",adc_val,bat->adc_value);
+ printk("lower-power shutdown");
+ kernel_power_off();
+ }
+
+}
static void rk_adc_battery_check_work(struct work_struct *work)
{
- struct rk30_adc_battery_data *bat = container_of((work), \
- struct rk30_adc_battery_data, check_work);
+ struct rk30_adc_battery_data *bat =
+ container_of((work), struct
+ rk30_adc_battery_data, check_work.work);
if(1 == get_ac_status(bat)){
bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
queue_delayed_work(bat ->wq, &bat ->check_work, msecs_to_jiffies(TIMER_MS_COUNTS));
}
+static void poweron_lowerpoer_handle(struct rk30_adc_battery_data *bat)
+{
+#ifdef CONFIG_LOGO_LOWERPOWER_WARNING
+ if((1 == get_battery_status())&&(bat->bat_status == POWER_SUPPLY_STATUS_NOT_CHARGING )){
+ mdelay (1500);
+ kernel_power_off();
+ }
+#endif
+
+}
+static int battery_notifier_call(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct rk30_adc_battery_data *bat=
+ container_of(nb, struct rk30_adc_battery_data, battery_nb);
+
+ switch (event) {
+ case 1:
+ rk_lowerpower_check(bat);
+ break;
+
+ case 2:
+ poweron_lowerpoer_handle(bat);
+ break;
+ default:
+ return NOTIFY_OK;
+ }
+ return NOTIFY_OK;
+}
+
+#ifdef CONFIG_OF
+static int rk31_adcbat_parse_dt(struct platform_device *pdev, struct
+rk30_adc_battery_platform_data *data)
+{
+ struct device_node *node = pdev->dev.of_node;
+ enum of_gpio_flags flags;
+ struct property *prop;
+ int length;
+ u32 value;
+ int ret;
+ int i;
+ size_t size;
+
+ struct iio_channel *channels;
+ int num = 0;
+
+ channels = iio_channel_get_all(&pdev->dev);
+ if (IS_ERR(channels))
+ pr_err("get adc channels fails\n");
+ while (channels[num].indio_dev)
+ num++;
+ data->chan = &channels[0];
+ if (num > 1)
+ data->ref_voltage_chan = &channels[1];
+ ret = of_property_read_u32(node, "auto_calibration", &value);
+ if (ret < 0) {
+ pr_info("%s:unsupport auto_calibration\n", __func__);
+ value = 0;
+ }
+ data->auto_calibration = value;
+
+ ret = of_property_read_u32(node, "ref_voltage", &value);
+ if (ret < 0) {
+ pr_info("%s:unsupport ref_voltage\n", __func__);
+ value = 0;
+ }
+ data->reference_voltage = value;
+
+ /* determine the number of config info */
+ prop = of_find_property(node, "bat_table", &length);
+ if (!prop)
+ return -EINVAL;
+
+ length /= sizeof(u32);
+
+ if (length > 0) {
+ size = (sizeof(*data->dts_batt_table)) * length;
+ data->dts_batt_table =
+ devm_kzalloc(&(pdev->dev), size, GFP_KERNEL);
+ if (!data->dts_batt_table)
+ return -ENOMEM;
+
+ ret = of_property_read_u32_array(node
+ , "bat_table", data->dts_batt_table, length);
+ if (ret < 0)
+ return ret;
+ }
+
+ for (i = 4; i < length; i++) {
+ batt_table[i] = data->dts_batt_table[i];
+
+ pr_info("data->dts_batt_table[ %d ] %d %d\n", i
+ , data->dts_batt_table[i], batt_table[i]);
+ }
+ data->dc_det_pin = of_get_named_gpio_flags(node
+ , "dc_det_gpio", 0, &flags);
+ if (data->dc_det_pin == -EPROBE_DEFER)
+ pr_info("%s dc_det_gpio error\n", __func__);
+
+ if (batt_gpio_is_valid(data->dc_det_pin))
+ data->dc_det_level = (flags & OF_GPIO_ACTIVE_LOW)
+ ? RK30_GPIO_LOW : RK30_GPIO_HIGH;
+
+ data->batt_low_pin = of_get_named_gpio_flags(node
+ , "bat_low_gpio", 0, &flags);
+ if (data->batt_low_pin == -EPROBE_DEFER)
+ pr_info("%s bat_low_gpio error\n", __func__);
+
+ if (batt_gpio_is_valid(data->batt_low_pin))
+ data->batt_low_level = (flags & OF_GPIO_ACTIVE_LOW)
+ ? RK30_GPIO_LOW : RK30_GPIO_HIGH;
+
+ data->charge_ok_pin = of_get_named_gpio_flags(node
+ , "chg_ok_gpio", 0, &flags);
+ if (data->charge_ok_pin == -EPROBE_DEFER)
+ pr_info("%s chg_ok_gpio error\n", __func__);
+
+ if (batt_gpio_is_valid(data->charge_ok_pin))
+ data->charge_ok_level = (flags & OF_GPIO_ACTIVE_LOW)
+ ? RK30_GPIO_LOW : RK30_GPIO_HIGH;
+
+ ret = of_property_read_u32(node, "is_dc_charge", &value);
+ if (ret < 0) {
+ pr_info("%s:hardware unsupport dc charge\n", __func__);
+ value = 0;
+ }
+ data->is_dc_charge = value;
+
+ ret = of_property_read_u32(node, "is_usb_charge"
+ , &value);
+ if (ret < 0) {
+ pr_err("%s:hardware unsupport usb charge\n", __func__);
+ value = 0;
+ }
+ data->is_usb_charge = value;
+
+ pr_info("rk30 battery:support %s %s charger\n",
+ data->is_dc_charge ? "DC" : ""
+ , data->is_usb_charge ? "USB" : "");
+
+ return 0;
+}
+#else
+static int rk31_adcbat_parse_dt(struct platform_device
+*dev, struct rk30_adc_battery_platform_data *data)
+{
+ return -ENODEV;
+}
+#endif
+
+
static int rk30_adc_battery_probe(struct platform_device *pdev)
{
+
int ret;
int irq;
int irq_flag;
- struct adc_client *client;
struct rk30_adc_battery_data *data;
- struct rk30_adc_battery_platform_data *pdata = pdev->dev.platform_data;
+ struct rk30_adc_battery_platform_data *pdata;
+#ifdef CONFIG_MACH_RK_FAC
+ int i;
+ for(i=0;i<BATT_NUM;i++)
+ {
+ batt_table[6+i]=pdata->chargeArray[i];
+ batt_table[BATT_NUM+6+i]=pdata->chargeArray[i];
+ }
+#endif
gSecondsCnt = get_seconds();
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (data == NULL) {
+ /*data = kzalloc(sizeof(*data), GFP_KERNEL);*/
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
ret = -ENOMEM;
- goto err_data_alloc_failed;
- }
+
+ /*pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);*/
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (pdata == NULL)
+ ret = -ENOMEM;
+
memset(data, 0, sizeof(struct rk30_adc_battery_data));
gBatteryData = data;
-
platform_set_drvdata(pdev, data);
data->pdata = pdata;
data->start_voltage_status = 0;
data->charge_full_flag =0;
data->pSamples = data->adc_samples;
+ data->lower_power_flag = 0;
+ data->capacitytmp = 0;
+ data->time_to_full = 0;
data->stop_check = 0;
+ data->voltage_to_local = 0;
data->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
wake_lock_init(&batt_wake_lock, WAKE_LOCK_SUSPEND, "batt_lock");
wake_lock_init(&charge_display_lock, WAKE_LOCK_SUSPEND, "charge_display_lock"); //charge_display_lock
-
- ret = rk30_adc_battery_io_init(pdata);
+ wake_lock_init(&batt_wake_lock_detect_lowpower
+ , WAKE_LOCK_SUSPEND, "lowpower_lock");
+
+ ret = rk31_adcbat_parse_dt(pdev, data->pdata);
+ /*ret = rk31_adcbat_parse_dt(pdev, pdata);*/
+ if (ret < 0) {
+ pr_err("failed to find rk30 adc battery platform data\n");
+ goto err_io_init;
+ }
+
+ ret = rk30_adc_battery_io_init(data->pdata);
if (ret) {
ret = -EINVAL;
goto err_io_init;
memset(data->adc_samples, 0, sizeof(int)*(NUM_VOLTAGE_SAMPLE + 2));
//register adc for battery sample
- if(0 == pdata->adc_channel)
- client = adc_register(0, rk30_adc_battery_callback, NULL); //pdata->adc_channel = ani0
- else
- client = adc_register(pdata->adc_channel, rk30_adc_battery_callback, NULL);
- if(!client){
- ret = -EINVAL;
- goto err_adc_register_failed;
- }
-
+ data->wq = create_singlethread_workqueue("adc_battd");
//variable init
- data->client = client;
- data->adc_val = adc_sync_read(client);
+ /*data->client = client;*/
+ data->adc_val = rk_adc_battery_iio_read(data->pdata);
data ->bat = rk30_battery_supply;
ret = power_supply_register(&pdev->dev,&data ->bat);
goto err_ac_failed;
}
-#if defined (CONFIG_BATTERY_RK30_AC_CHARGE)
//init dc dectet irq & delay work
- if (pdata->dc_det_pin != INVALID_GPIO){
+ if (batt_gpio_is_valid(data->pdata->dc_det_pin)) {
INIT_WORK(&data->dcwakeup_work, rk30_adc_battery_dcdet_delaywork);
- irq = gpio_to_irq(pdata->dc_det_pin);
- irq_flag = gpio_get_value (pdata->dc_det_pin) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
+ irq = gpio_to_irq(data->pdata->dc_det_pin);
+ irq_flag = gpio_get_value(data->pdata->dc_det_pin)
+ ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
ret = request_irq(irq, rk30_adc_battery_dc_wakeup, irq_flag, "ac_charge_irq", NULL);
if (ret) {
ret = -EINVAL;
enable_irq_wake(irq);
}
-#endif
#ifdef BATTERY_APK
ret = device_create_file(&pdev->dev,&dev_attr_batparam);
//Power on Battery detect
rk30_adc_battery_check(data);
- data->wq = create_singlethread_workqueue("adc_battd");
+// data->wq = create_singlethread_workqueue("adc_battd");
INIT_DELAYED_WORK(&data->delay_work, rk30_adc_battery_timer_work);
- if(1 == pdata->save_capacity ){
+ //if (1 == data->pdata->save_capacity) {
+ if (1) {
queue_delayed_work(data->wq, &data->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS*10));
data ->poweron_check = 1;
}else{
}
INIT_DELAYED_WORK(&data->check_work, rk_adc_battery_check_work);
queue_delayed_work(data ->wq, &data ->check_work, msecs_to_jiffies(TIMER_MS_COUNTS));
- if( pdata->batt_low_pin != INVALID_GPIO){
-
- if (gpio_get_value(pdata->batt_low_pin) ==0){
- mdelay(20);
- if (gpio_get_value(pdata->batt_low_pin) ==0){
+ if (batt_gpio_is_valid(data->pdata->batt_low_pin)) {
+ if (0 == gpio_get_value(data->pdata->batt_low_pin)) {
+ mdelay(20);
+ if (gpio_get_value(data->pdata->batt_low_pin) == 0) {
printk("lower power\n");
kernel_power_off();
}
}
INIT_WORK(&data->lowerpower_work, rk30_adc_battery_lowerpower_delaywork);
- irq = gpio_to_irq(pdata->batt_low_pin);
+ irq = gpio_to_irq(data->pdata->batt_low_pin);
ret = request_irq(irq, rk30_adc_battery_low_wakeup, IRQF_TRIGGER_LOW, "batt_low_irq", NULL);
if (ret) {
ret = -EINVAL;
disable_irq(irq);
}
+ data->battery_nb.notifier_call = battery_notifier_call;
+ register_adc_battery_notifier(&data->battery_nb);
printk(KERN_INFO "rk30_adc_battery: driver initialized\n");
return 0;
err_sysfs:
-err_usb_failed:
power_supply_unregister(&data ->usb);
err_ac_failed:
power_supply_unregister(&data ->ac);
+err_usb_failed:
err_battery_failed:
power_supply_unregister(&data ->bat);
err_dcirq_failed:
- free_irq(gpio_to_irq(pdata->dc_det_pin), data);
+ if (batt_gpio_is_valid(data->pdata->dc_det_pin))
+ free_irq(gpio_to_irq(data->pdata->dc_det_pin), data);
#if 1
err_lowpowerirq_failed:
- free_irq(gpio_to_irq(pdata->batt_low_pin), data);
-#endif
-err_adc_register_failed:
-err_io_init:
-err_data_alloc_failed:
- kfree(data);
+ if (batt_gpio_is_valid(data->pdata->batt_low_pin))
+ free_irq(gpio_to_irq(data->pdata->batt_low_pin), data);
+#endif
+err_io_init:
printk("rk30_adc_battery: error!\n");
return ret;
static int rk30_adc_battery_remove(struct platform_device *pdev)
{
struct rk30_adc_battery_data *data = platform_get_drvdata(pdev);
- struct rk30_adc_battery_platform_data *pdata = pdev->dev.platform_data;
+ struct rk30_adc_battery_platform_data *pdata = data->pdata;
- cancel_delayed_work(&data->delay_work);
-#if defined (CONFIG_BATTERY_RK30_AC_CHARGE)
- if (pdata->dc_det_pin != INVALID_GPIO)
- cancel_delayed_work_sync(&data->dcwakeup_work);
-#endif
+ cancel_delayed_work_sync(&data->delay_work);
+ if (batt_gpio_is_valid(pdata->dc_det_pin))
+ cancel_work_sync(&data->dcwakeup_work);
cancel_delayed_work_sync(&data->check_work);
- if( pdata->batt_low_pin != INVALID_GPIO)
- cancel_delayed_work_sync(&data->lowerpower_work);
+ if (batt_gpio_is_valid(pdata->batt_low_pin))
+ cancel_work_sync(&data->lowerpower_work);
#if defined (CONFIG_BATTERY_RK30_USB_CHARGE)
power_supply_unregister(&data ->usb);
#endif
power_supply_unregister(&data ->ac);
power_supply_unregister(&data ->bat);
-
- free_irq(gpio_to_irq(pdata->dc_det_pin), data);
-
- kfree(data);
+ if (batt_gpio_is_valid(pdata->dc_det_pin))
+ free_irq(gpio_to_irq(pdata->dc_det_pin), data);
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id rk30_adc_battery_dt_match[] = {
+ { .compatible = "rk30-adc-battery",},
+ {},
+};
+MODULE_DEVICE_TABLE(of, rk30_adc_battery_dt_match);
+#endif
+
+
static struct platform_driver rk30_adc_battery_driver = {
.probe = rk30_adc_battery_probe,
.remove = rk30_adc_battery_remove,
.suspend = rk30_adc_battery_suspend,
.resume = rk30_adc_battery_resume,
.driver = {
- .name = "rk30-battery",
+ .name = "rk30-adc-battery",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(rk30_adc_battery_dt_match),
}
};
//fs_initcall(rk30_adc_battery_init);
module_exit(rk30_adc_battery_exit);
+
+
MODULE_DESCRIPTION("Battery detect driver for the rk30");
MODULE_AUTHOR("luowei lw@rock-chips.com");
MODULE_LICENSE("GPL");