rk3188:pmu_rt5025:updata rt5025 drivers,modify some bug
author张晴 <zhangqing@rock-chips.com>
Sat, 10 Aug 2013 02:28:23 +0000 (10:28 +0800)
committer张晴 <zhangqing@rock-chips.com>
Sat, 10 Aug 2013 02:28:23 +0000 (10:28 +0800)
20 files changed:
arch/arm/mach-rk30/board-pmu-rt5025.c
drivers/mfd/ricoh619.c [changed mode: 0644->0755]
drivers/mfd/rt5025-core.c
drivers/mfd/rt5025-debug.c
drivers/mfd/rt5025-irq.c
drivers/mfd/rt5025-misc.c [changed mode: 0755->0644]
drivers/power/Makefile [changed mode: 0755->0644]
drivers/power/rt5025-battery.c [new file with mode: 0755]
drivers/power/rt5025-gauge.c [deleted file]
drivers/power/rt5025-power.c
drivers/power/rt5025-swjeita.c [new file with mode: 0755]
drivers/regulator/rt5025-regulator.c
include/linux/mfd/rt5025-irq.h [changed mode: 0755->0644]
include/linux/mfd/rt5025.h [changed mode: 0755->0644]
include/linux/power/rockchip-6200ma-bat.h [new file with mode: 0755]
include/linux/power/rt5025-battery.h [new file with mode: 0755]
include/linux/power/rt5025-gauge.h [deleted file]
include/linux/power/rt5025-power.h
include/linux/power/rt5025-swjeita.h [new file with mode: 0755]
include/linux/regulator/rt5025-regulator.h [changed mode: 0755->0644]

index 4cb462ba30023e5c65110efe22279bee69f94695..17b99fa43dbd01bd6056f821108d816fafa3a35f 100644 (file)
@@ -303,7 +303,7 @@ static struct rt5025_power_data rt5025_power_data = {
                        .BATD_EN = 0,
                },
        },
-       .fcc = 6200, //6200 mAh
+//     .fcc = 6200, //6200 mAh
 };
 
 static struct rt5025_gpio_data rt5025_gpio_data = {
@@ -379,7 +379,7 @@ static struct rt5025_irq_data rt5025_irq_data = {
                        .TIMEOUT_PC = 1,
                        .CHVSREGI = 0,
                        .CHTREGI = 0,
-                       .CHRCHGI = 0,
+                       .CHRCHGI = 1,
                },
        },
        .irq_enable4 = {
@@ -407,6 +407,27 @@ static struct rt5025_irq_data rt5025_irq_data = {
        },
 };
 
+//temp unit: 'c*10 degree
+static int jeita_temp[4] = { 0, 150, 500, 600};
+static u8 jeita_scalar[4] = { 0x2d,  0x25, 0x12, 0x0e};
+//cc unit: xxx mA
+static int jeita_temp_cc[][5] = {{ 500,  500,  500,  500, 500},    // not plugin
+                                {   0 , 250,  500,  250,   0},    // normal USB
+                                {   0,  500, 1000,  500,   0},    // USB charger
+                                {   0,  500, 1000,  500,   0}};   // AC Adapter
+//cv unit: xxx mV
+static int jeita_temp_cv[][5] = {{ 4200, 4200, 4200, 4200, 4200},  // not plugin
+                                { 4200, 4200, 4200, 4200, 4200},  // normal USB
+                                { 4200, 4200, 4200, 4200, 4200},  // USB charger
+                                { 4200, 4200, 4200, 4200, 4200}}; // AC Adapter
+
+static struct rt5025_jeita_data rt5025_jeita_data = {
+       .temp = jeita_temp,
+       .temp_scalar = jeita_scalar,
+       .temp_cc = jeita_temp_cc,
+       .temp_cv = jeita_temp_cv,
+};
+
 static void rt5025_charger_event_callback(uint32_t detected)
 {
        RTINFO("event detected = 0x%08x\n", detected);
@@ -449,6 +470,7 @@ static struct rt5025_platform_data rt5025_data = {
        .gpio_data = &rt5025_gpio_data,
        .misc_data = &rt5025_misc_data,
        .irq_data = &rt5025_irq_data,
+       .jeita_data = &rt5025_jeita_data,
        .cb = &rt5025_event_callback,
        .intr_pin = 81, //GPIO81
 };
old mode 100644 (file)
new mode 100755 (executable)
index d5b8162..bdceb2c
@@ -715,7 +715,7 @@ static int ricoh619_i2c_probe(struct i2c_client *client,
        mutex_init(&ricoh619->io_lock);
 
        ret = ricoh619_read(ricoh619->dev, 0x36, &control);
-       if ((control < 0) || (control == 0xff)) {
+       if ((control < 0) || (control == 0xff) || (control == 0)) {
                printk(KERN_INFO "The device is not ricoh619\n");
                return 0;
        }
index 164f193cc6946cc325d4bd043580d60ddb07d7ed..245c1c0c9f635bc3e93c3c8c0eb327232f6233a1 100644 (file)
@@ -47,6 +47,16 @@ static struct mfd_cell power_devs[] = {
        .id = -1,
        .num_resources = 0,
 },
+{
+       .name = RT5025_DEVICE_NAME "-swjeita",
+       .id = -1,
+       .num_resources = 0,
+},
+{
+       .name = RT5025_DEVICE_NAME "-battery",
+       .id = -1,
+       .num_resources = 0,
+},
 };
 #endif /* CONFIG_POWER_RT5025 */
 
@@ -95,7 +105,6 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
        int ret = 0;
 
        RTINFO("Start to initialize all device\n");
-       printk("%s,line=%d\n", __func__,__LINE__);
 
        #ifdef CONFIG_REGULATOR_RT5025
        if (pdata && pdata->regulator[0]) {
@@ -117,7 +126,7 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
        #endif /* CONFIG_REGULATOR_RT5025 */
 
        #ifdef CONFIG_POWER_RT5025
-       if (pdata && pdata->power_data) {
+       if (pdata && pdata->power_data && pdata->jeita_data) {
            RTINFO("mfd add power dev\n");
                #if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
                ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
@@ -155,7 +164,7 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
                }
        }
        #endif /* CONFIG_GPIO_RT5025 */
-\
+
        #ifdef CONFIG_MFD_RT5025_MISC
        if (pdata && pdata->misc_data) {
                RTINFO("mfd add misc dev\n");
@@ -193,10 +202,9 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
                }
        }
        #endif /* CONFIG_MFD_RT5025_IRQ */
-#if 1
+
        #ifdef CONFIG_MFD_RT5025_DEBUG
        RTINFO("mfd add debug dev\n");
-       printk("%s,line=%d\n", __func__,__LINE__);
        #if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
        ret = mfd_add_devices(chip->dev, 0, &debug_devs[0],
                              ARRAY_SIZE(debug_devs),
@@ -211,8 +219,7 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
                goto out_dev;
        }
        #endif /* CONFIG_MFD_RT5025_DEBUG */
-#endif
-       
+
        RTINFO("Initialize all device successfully\n");
        return ret;
 out_dev:
index 71dce8ad7f9f569935f906f36de4924359e09f97..b50c70990d5345294ce75397940e57844d9aaa8c 100644 (file)
@@ -31,8 +31,9 @@ static struct i2c_client *client;
 static struct dentry *debugfs_rt_dent;
 static struct dentry *debugfs_peek;
 static struct dentry *debugfs_poke;
+static struct dentry *debugfs_regs;
 
-static unsigned char read_data;
+static unsigned char read_data[10];
 
 static int reg_debug_open(struct inode *inode, struct file *file)
 {
@@ -65,12 +66,23 @@ static int get_parameters(char *buf, long int *param1, int num_of_par)
        return 0;
 }
 
+#define LOG_FORMAT "0x%02x\n0x%02x\n0x%02x\n0x%02x\n0x%02x\n"
+
 static ssize_t reg_debug_read(struct file *filp, char __user *ubuf,
                                size_t count, loff_t *ppos)
 {
-       char lbuf[8];
-       
-       snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
+       char *access_str = filp->private_data;
+       char lbuf[150];
+       if (!strcmp(access_str, "regs"))
+       {
+               RTINFO("read regs file\n");
+               /* read regs */
+               snprintf(lbuf, sizeof(lbuf), LOG_FORMAT LOG_FORMAT, read_data[0], \
+               read_data[1], read_data[2], read_data[3], read_data[4], read_data[5], \
+               read_data[6], read_data[7], read_data[8], read_data[9]);
+       }
+       else
+               snprintf(lbuf, sizeof(lbuf), "0x%02x\n", read_data[0]);
        return simple_read_from_buffer(ubuf, count, ppos, lbuf, strlen(lbuf));
 }
 
@@ -105,7 +117,26 @@ static ssize_t reg_debug_write(struct file *filp,
                rc = get_parameters(lbuf, param, 1);
                if ((param[0] <= 0xFF) && (rc == 0))
                {
-                       read_data = rt5025_reg_read(client, param[0]);
+                       read_data[0] = rt5025_reg_read(client, param[0]);
+               }
+               else
+                       rc = -EINVAL;
+       } else if (!strcmp(access_str, "regs")) {
+               /* read */
+               rc = get_parameters(lbuf, param, 1);
+               if ((param[0] <= 0xFF) && (rc == 0))
+               {
+                       rt5025_reg_block_read(client, param[0], 10, read_data);
+                       RTINFO("regs 0 = 0x%02x\n", read_data[0]);
+                       RTINFO("regs 1 = 0x%02x\n", read_data[1]);
+                       RTINFO("regs 2 = 0x%02x\n", read_data[2]);
+                       RTINFO("regs 3 = 0x%02x\n", read_data[3]);
+                       RTINFO("regs 4 = 0x%02x\n", read_data[4]);
+                       RTINFO("regs 5 = 0x%02x\n", read_data[5]);
+                       RTINFO("regs 6 = 0x%02x\n", read_data[6]);
+                       RTINFO("regs 7 = 0x%02x\n", read_data[7]);
+                       RTINFO("regs 8 = 0x%02x\n", read_data[8]);
+                       RTINFO("regs 9 = 0x%02x\n", read_data[9]);
                }
                else
                        rc = -EINVAL;
@@ -145,6 +176,10 @@ static int __devinit rt5025_debug_probe(struct platform_device *pdev)
                debugfs_poke = debugfs_create_file("poke",
                S_IFREG | S_IRUGO, debugfs_rt_dent,
                (void *) "poke", &reg_debug_ops);
+
+               debugfs_regs = debugfs_create_file("regs",
+               S_IFREG | S_IRUGO, debugfs_rt_dent,
+               (void *) "regs", &reg_debug_ops);
        }
 
        platform_set_drvdata(pdev, di);
index 1c1198705c1d284afcf9970de5d12bcfb4a900fb..dcb15ecaf4de086a3b68abfc2fab06d84c12198e 100644 (file)
@@ -40,33 +40,40 @@ static void rt5025_work_func(struct work_struct *work)
 {
        struct delayed_work *delayed_work = (struct delayed_work *)container_of(work, struct delayed_work, work);
        struct rt5025_irq_info *ii = (struct rt5025_irq_info *)container_of(delayed_work, struct rt5025_irq_info, delayed_work);
-       unsigned char irq_stat[10] = {0};
+       unsigned char irq_stat[6] = {0};
        uint32_t chg_event = 0, pwr_event = 0;
 
        #ifdef CONFIG_POWER_RT5025
-       if (!ii->chip->power_info)
+       if (!ii->chip->power_info || !ii->chip->jeita_info || !ii->chip->battery_info)
        {
                queue_delayed_work(ii->wq, &ii->delayed_work, msecs_to_jiffies(1));
                return;
        }
        #endif
 
-       //if (rt5025_reg_block_read(ii->i2c, RT5025_REG_IRQEN1, 10, irq_stat) >= 0)
+       #if 0
+       if (rt5025_reg_block_read(ii->i2c, RT5025_REG_IRQEN1, 10, irq_stat) >= 0)
        {
-               irq_stat[1] = rt5025_reg_read(ii->i2c, 0x31);
-               irq_stat[3] = rt5025_reg_read(ii->i2c, 0x33);
-               irq_stat[5] = rt5025_reg_read(ii->i2c, 0x35);
-               irq_stat[7] = rt5025_reg_read(ii->i2c, 0x37);
-               irq_stat[9] = rt5025_reg_read(ii->i2c, 0x39);
-               RTINFO("irq1->%02x, irq2->%02x, irq3->%02x\n", irq_stat[1], irq_stat[3], irq_stat[5]);
-               RTINFO("irq4->%02x, irq5->%02x\n", irq_stat[7], irq_stat[9]);
+       #endif
+               irq_stat[0] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS1);
+               irq_stat[1] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS2);
+               irq_stat[2] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS3);
+               irq_stat[3] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS4);
+               irq_stat[4] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQSTATUS5);
+               irq_stat[5] = rt5025_reg_read(ii->i2c, RT5025_REG_GAUGEIRQFLG);
+               RTINFO("irq1->0x%02x, irq2->0x%02x, irq3->0x%02x\n", irq_stat[0], irq_stat[1], irq_stat[2]);
+               RTINFO("irq4->0x%02x, irq5->0x%02x, irq6->0x%02x\n", irq_stat[3], irq_stat[4], irq_stat[5]);
                RTINFO("stat value = %02x\n", rt5025_reg_read(ii->i2c, RT5025_REG_CHGSTAT));
 
-               chg_event = irq_stat[1]<<16 | irq_stat[3]<<8 | irq_stat[5];
-               pwr_event = irq_stat[7]<<8 | irq_stat[9];
+               chg_event = irq_stat[0]<<16 | irq_stat[1]<<8 | irq_stat[2];
+               pwr_event = irq_stat[3]<<8 | irq_stat[4];
                #ifdef CONFIG_POWER_RT5025
                if (chg_event & CHARGER_DETECT_MASK)
+               {
+                       if (chg_event & CHG_EVENT_CHTERMI)
+                               ii->chip->power_info->chg_term++;
                        rt5025_power_charge_detect(ii->chip->power_info);
+               }
                #endif /* CONFIG_POWER_RT5025 */
                if (ii->event_cb)
                {
@@ -75,15 +82,18 @@ static void rt5025_work_func(struct work_struct *work)
                        if (pwr_event)
                                ii->event_cb->power_event_callkback(pwr_event);
                }
-       }
        #if 0
+       }
        else
                dev_err(ii->dev, "read irq stat io fail\n");
        #endif
        
 
        #ifdef CONFIG_POWER_RT5025
-       rt5025_power_passirq_to_gauge(ii->chip->power_info);
+       if (irq_stat[5] & RT5025_FLG_TEMP)
+               rt5025_swjeita_irq_handler(ii->chip->jeita_info, irq_stat[5] & RT5025_FLG_TEMP);
+       if (irq_stat[5] & RT5025_FLG_VOLT)
+               rt5025_gauge_irq_handler(ii->chip->battery_info, irq_stat[5] & RT5025_FLG_VOLT);
        #endif /* CONFIG_POWER_RT5025 */
 
        //enable_irq(ii->irq);
@@ -170,7 +180,6 @@ static int __devinit rt5025_irq_probe(struct platform_device *pdev)
        struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct rt5025_platform_data *pdata = chip->dev->platform_data;
        struct rt5025_irq_info *ii;
-       printk("%s,line=%d\n", __func__,__LINE__);      
 
        RTINFO("\n");
        ii = kzalloc(sizeof(*ii), GFP_KERNEL);
@@ -201,6 +210,20 @@ static int __devexit rt5025_irq_remove(struct platform_device *pdev)
        return 0;
 }
 
+static void rt5025_irq_shutdown(struct platform_device *pdev)
+{
+       struct rt5025_irq_info *ii = platform_get_drvdata(pdev);
+
+       if (ii->irq)
+               free_irq(ii->irq, ii);
+
+       if (ii->wq)
+       {
+               cancel_delayed_work_sync(&ii->delayed_work);
+               flush_workqueue(ii->wq);
+       }
+}
+
 static struct platform_driver rt5025_irq_driver = 
 {
        .driver = {
@@ -209,6 +232,7 @@ static struct platform_driver rt5025_irq_driver =
        },
        .probe = rt5025_irq_probe,
        .remove = __devexit_p(rt5025_irq_remove),
+       .shutdown = rt5025_irq_shutdown,
 };
 
 static int __init rt5025_irq_init(void)
old mode 100755 (executable)
new mode 100644 (file)
index 83be67c..e47b1d6
@@ -49,7 +49,6 @@ static int __devinit rt5025_misc_probe(struct platform_device *pdev)
        struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct rt5025_platform_data *pdata = chip->dev->platform_data;
        struct rt5025_misc_info *mi;
-       printk("%s,line=%d\n", __func__,__LINE__);      
 
        mi = kzalloc(sizeof(*mi), GFP_KERNEL);
        if (!mi)
old mode 100755 (executable)
new mode 100644 (file)
index 2513b80..8ab4962
@@ -49,4 +49,4 @@ obj-$(CONFIG_PLAT_RK)         += rk29_charger_display.o
 obj-$(CONFIG_BATTERY_RK30_ADC_FAC)  += rk30_factory_adc_battery.o
 obj-$(CONFIG_CW2015_BATTERY)  += cw2015_battery.o
 obj-$(CONFIG_BATTERY_RICOH619) += ricoh619-battery.o
-obj-$(CONFIG_POWER_RT5025)     += rt5025-power.o rt5025-gauge.o
\ No newline at end of file
+obj-$(CONFIG_POWER_RT5025)     += rt5025-power.o rt5025-battery.o rt5025-swjeita.o
diff --git a/drivers/power/rt5025-battery.c b/drivers/power/rt5025-battery.c
new file mode 100755 (executable)
index 0000000..83b458a
--- /dev/null
@@ -0,0 +1,1658 @@
+/* drivers/power/rt5025-battery.c
+ * I2C Driver for Richtek RT5025 PMIC
+ * Multi function device - multi functional baseband PMIC Battery part
+ *
+ * Copyright (C) 2013
+ * Author: Nick Hung <nick_hung@richtek.com>
+ *
+ * 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/module.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/wakelock.h>
+#include <linux/workqueue.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <linux/android_alarm.h>
+#include <linux/mfd/rt5025.h>
+#include <linux/power/rt5025-battery.h>
+
+#define VOLTAGE_ALERT 1
+#define TEMPERATURE_ALERT 0
+
+#define RT5025_CSV 0
+#define RT5025_B 1
+#define RT5025_TEST_WAKE_LOCK 1
+
+u8 irq_thres[LAST_TYPE];
+
+void rt5025_gauge_set_status(struct rt5025_battery_info *bi, int status)
+{
+  bi->status = status;
+  if (status == POWER_SUPPLY_STATUS_FULL)
+       bi->tp_flag = true;
+}
+EXPORT_SYMBOL(rt5025_gauge_set_status);
+
+void rt5025_gauge_set_online(struct rt5025_battery_info *bi, bool present)
+{
+  bi->online = present;
+}
+EXPORT_SYMBOL(rt5025_gauge_set_online);
+
+static int rt5025_read_reg(struct i2c_client *client,
+                               u8 reg, u8 *data, u8 len)
+{
+       #if 1
+       return rt5025_reg_block_read(client, reg, len, data);
+       #else
+       struct i2c_adapter *adap = client->adapter;
+       struct i2c_msg msgs[2];
+       int ret;
+       
+       msgs[0].addr = client->addr;
+       msgs[0].flags = client->flags;
+       msgs[0].len = 1;
+       msgs[0].buf = &reg;
+
+       msgs[1].addr = client->addr;
+       msgs[1].flags = client->flags | I2C_M_RD;
+       msgs[1].len = len;
+       msgs[1].buf = data;
+       
+       ret = i2c_transfer(adap, msgs, 2);
+        
+       return (ret == 2)? len : ret;
+       #endif
+}
+
+static int rt5025_write_reg(struct i2c_client *client,
+                               u8 reg, u8 *data, u8 len)
+{
+       #if 1
+       return rt5025_reg_block_write(client, reg, len, data);
+       #else
+       struct i2c_adapter *adap = client->adapter;
+       struct i2c_msg msg;
+       int ret;
+       char *tx_buf = (char *)kmalloc(len + 1, GFP_KERNEL);
+       
+       if(!tx_buf)
+               return -ENOMEM;
+       tx_buf[0] = reg;
+       memcpy(tx_buf+1, data, len);
+       
+       msg.addr = client->addr;
+       msg.flags = client->flags;
+       msg.len = len + 1;
+       msg.buf = (char *)tx_buf;
+
+       ret = i2c_transfer(adap, &msg, 1);
+       kfree(tx_buf);
+       return (ret == 1) ? len : ret;
+       #endif
+}
+
+static void rt5025_gauge_alarm(struct alarm *alarm)
+{
+       struct rt5025_battery_info *bi = (struct rt5025_battery_info *)container_of(alarm, struct rt5025_battery_info, wakeup_alarm);
+
+       wake_lock(&bi->monitor_wake_lock);
+       schedule_delayed_work(&bi->monitor_work, 0);
+}
+
+static void rt5025_program_alarm(struct rt5025_battery_info *bi)
+{
+       ktime_t low_interval = ktime_set(bi->update_time, 0);
+       ktime_t slack = ktime_set(20, 0);
+       ktime_t next;
+
+       next = ktime_add(bi->last_poll, low_interval);
+       alarm_start_range(&bi->wakeup_alarm, next, ktime_add(next, slack));
+}
+
+#if 0
+static void rt5025_run_time(struct rt5025_battery_info *bi)
+{
+       if(bi->curr <= 0)
+       {
+               bi->time_to_empty = bi->rm / (bi->curr*(-1));
+       }
+       else
+       {
+               bi->time_to_full = (bi->fcc * 3600 - bi->rm) / bi->curr;
+       }
+       RTINFO("RTTF = %d\n",bi->time_to_full);
+       RTINFO("RTTE = %d\n",bi->time_to_empty);
+}
+#endif
+
+static int rt5025_get_property(struct power_supply *psy,
+                           enum power_supply_property psp,
+                           union power_supply_propval *val)
+{
+  struct rt5025_battery_info *bi = dev_get_drvdata(psy->dev->parent);
+
+  switch (psp) {
+    case POWER_SUPPLY_PROP_STATUS:
+      val->intval = bi->status;
+      //val->intval = POWER_SUPPLY_STATUS_CHARGING;
+      break;
+    case POWER_SUPPLY_PROP_HEALTH:
+      val->intval = bi->health;
+      break;
+    case POWER_SUPPLY_PROP_PRESENT:
+      val->intval = bi->present;
+      break;
+    case POWER_SUPPLY_PROP_TEMP:
+      val->intval = bi->ext_temp;
+      break;
+    case POWER_SUPPLY_PROP_ONLINE:
+      val->intval = bi->online;
+      break;
+    case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+      val->intval = bi->vcell * 1000; //uV
+      break;
+    case POWER_SUPPLY_PROP_CURRENT_NOW:
+      val->intval = bi->curr * 1000; //uA
+      break;
+    case POWER_SUPPLY_PROP_CAPACITY:
+      val->intval = bi->soc;
+                       //val->intval = 50;
+      if (val->intval > 100)
+                               val->intval = 100;
+      break;
+    case POWER_SUPPLY_PROP_TECHNOLOGY:
+      val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+      break;
+    #if 0
+    case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
+                       val->intval = bi->time_to_empty;
+    break;
+    case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
+                       val->intval = bi->time_to_full;
+    #endif
+    break;
+    default:
+      return -EINVAL;
+  }
+  return 0;
+}
+
+static void rt5025_get_vcell(struct rt5025_battery_info *bi)
+{
+  u8 data[2];
+       
+  if (rt5025_read_reg(bi->client, RT5025_REG_VCELL_MSB, data, 2) < 0){
+    printk(KERN_ERR "%s: Failed to read Voltage\n", __func__);
+  }
+
+  if (bi->avg_flag)
+    bi->vcell = ((data[0] << 8) + data[1]) * 61 / 100;
+  else 
+         bi->vcell = (bi->vcell + ((data[0] << 8) + data[1]) * 61 / 100) / 2;
+#if RT5025_B
+       bi->curr_offset = (15444 * bi->vcell - 27444000) / 10000;
+#else 
+  if (37 * bi->vcell > 92000)
+               bi->curr_offset = (37 * bi->vcell - 92000) / 1000;
+       else
+               bi->curr_offset = 0;
+#endif
+               
+#if RT5025_CSV
+ // if (!bi->avg_flag)
+  //  pr_info("%d,%d,", bi->vcell, bi->curr_offset);
+#else  
+  if (bi->avg_flag)
+               RTINFO("vcell_pre: %d, offset: %d\n", bi->vcell, bi->curr_offset);
+  else
+               RTINFO("vcell_avg: %d, offset: %d\n", bi->vcell, bi->curr_offset);
+#endif
+}
+
+static void rt5025_get_current(struct rt5025_battery_info *bi)
+{
+  u8 data[2];
+  s32 temp;
+  int sign = 0;
+
+  if (rt5025_read_reg(bi->client, RT5025_REG_CURRENT_MSB, data, 2) < 0) {
+    printk(KERN_ERR "%s: Failed to read CURRENT\n", __func__);
+  }
+#if RT5025_B
+  temp = (data[0]<<8) | data[1];
+  bi->curr_raw = ((temp & 0x7FFF) * 3125) / 10000;
+    
+  if (data[0] & (1 << 7)) {
+    sign = 1;
+    temp = (((temp & 0x7FFF) * 3125) / 10 + bi->curr_offset) / 1000;
+  }else{
+               if ((temp * 3125) / 10 > bi->curr_offset)
+                       temp = ((temp * 3125) / 10 - bi->curr_offset) / 1000;
+       }
+       
+  if (temp < DEADBAND)
+               temp = 0;
+  
+  if (sign){
+    temp *= -1;
+    bi->curr_raw *= -1;
+       }
+#else
+  temp = (data[0]<<8) | data[1];
+  if (data[0] & (1 << 7)) {
+    sign = 1;
+    temp = temp & 0x7FFF;
+    if(temp > bi->curr_offset)
+                       temp = temp - bi->curr_offset;
+  }else {
+    temp = temp + bi->curr_offset;
+       }
+
+  temp = (temp * 37375) / 100000; //Unit: 0.3125mA
+  if (temp < DEADBAND)
+               temp = 0;
+  
+  if (sign)
+    temp *= -1;
+#endif
+
+  if (bi->avg_flag) 
+    bi->curr = temp;
+  else
+         bi->curr = (bi->curr + temp) / 2;
+
+  if(bi->curr > 0)
+    bi->internal_status = POWER_SUPPLY_STATUS_CHARGING;
+  else
+    bi->internal_status = POWER_SUPPLY_STATUS_DISCHARGING;
+  RTINFO("current=%d, internal_status=%d\n", bi->curr, bi->internal_status);
+
+#if RT5025_CSV
+ // if (!bi->avg_flag)
+  //  pr_info("%d,",bi->curr);
+#else
+  if (bi->avg_flag)
+               RTINFO("current_pre: %d\n", bi->curr);
+  else  
+               RTINFO("current_avg: %d\n", bi->curr);
+#endif
+}
+
+static void rt5025_get_external_temp(struct rt5025_battery_info *bi)
+{
+  u8 data[2];
+  s32 temp;
+
+  if (rt5025_read_reg(bi->client, RT5025_REG_EXT_TEMPERATUE_MSB, data, 2) < 0) {
+    printk(KERN_ERR "%s: Failed to read TEMPERATURE\n", __func__);
+  }
+  bi->ain_volt = (data[0] * 256 + data[1]) * 61 / 100;
+  if(bi->ain_volt < 1150) 
+  {
+       bi->present = 1;
+  }
+  else
+  {
+       bi->present = 0;  
+  }
+  
+  temp =  (bi->ain_volt * (-91738) + 81521000) / 100000;
+  bi->ext_temp = (int)temp;
+       //test
+       //bi->ext_temp = 250;
+       
+       if (bi->ext_temp >= HIGH_TEMP_THRES) {
+               if (bi->health != POWER_SUPPLY_HEALTH_OVERHEAT)
+                       bi->temp_high_cnt++;
+       } else if (bi->ext_temp <= HIGH_TEMP_RECOVER && bi->ext_temp >= LOW_TEMP_RECOVER) {
+               if (bi->health == POWER_SUPPLY_HEALTH_OVERHEAT ||
+                   bi->health == POWER_SUPPLY_HEALTH_COLD)
+                       bi->temp_recover_cnt++;
+       } else if (bi->ext_temp <= LOW_TEMP_THRES) {
+               if (bi->health != POWER_SUPPLY_HEALTH_COLD)
+                       bi->temp_low_cnt++;
+       }else {
+               bi->temp_high_cnt = 0;
+               bi->temp_low_cnt = 0;
+               bi->temp_recover_cnt = 0;
+       }
+       
+       if (bi->temp_high_cnt >= TEMP_ABNORMAL_COUNT) {
+        bi->health = POWER_SUPPLY_HEALTH_OVERHEAT;
+        bi->temp_high_cnt = 0;
+       } else if (bi->temp_low_cnt >= TEMP_ABNORMAL_COUNT) {
+        bi->health = POWER_SUPPLY_HEALTH_COLD;
+        bi->temp_low_cnt = 0;
+       } else if (bi->temp_recover_cnt >= TEMP_ABNORMAL_COUNT) {
+        bi->health = POWER_SUPPLY_HEALTH_GOOD;
+        bi->temp_recover_cnt = 0;
+       }
+       //RTINFO("external temperature: %d\n", bi->ext_temp);
+}
+
+static void rt5025_clear_cc(struct rt5025_battery_info *bi, operation_mode mode)
+{  
+  u8 data[2];
+       
+  if (rt5025_read_reg(bi->client, RT5025_REG_CHANNEL_MSB, data, 2) < 0){
+    pr_err("%s: failed to read channel\n", __func__);
+  }
+
+  if (mode == CHG)
+               data[0] = data[0] | CHANNEL_H_BIT_CLRQCHG;
+       else
+               data[0] = data[0] | CHANNEL_H_BIT_CLRQDCHG;
+               
+  if (rt5025_write_reg(bi->client, RT5025_REG_CHANNEL_MSB, data, 2) < 0){
+    pr_err("%s: failed to write channel\n", __func__);
+  }
+}
+
+static void rt5025_get_chg_cc(struct rt5025_battery_info *bi)
+{
+  u8 data[4];
+  u32 qh_old,ql_old,qh_new,ql_new;
+  u32 cc_masec,offset;
+  
+  if (rt5025_read_reg(bi->client, RT5025_REG_QCHGH_MSB, data, 4) < 0){
+    pr_err("%s: Failed to read QCHG\n", __func__);
+  }
+  qh_old = (data[0]<<8) + data[1];
+  ql_old = (data[2]<<8) + data[3];
+  
+  if (rt5025_read_reg(bi->client, RT5025_REG_QCHGH_MSB, data, 4) < 0){
+    pr_err("%s: Failed to read QCHG\n", __func__);
+  }
+  qh_new = (data[0]<<8) + data[1];
+  ql_new = (data[2]<<8) + data[3];
+
+#if RT5025_B
+  if (qh_new > qh_old){
+     cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
+  }else if (qh_new == qh_old){
+    if (ql_new >= ql_old){
+      cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
+    }else {  
+      cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
+               }
+  }    
+  
+       offset = bi->curr_offset * bi->time_interval;
+                         
+  if (cc_masec > offset){
+               cc_masec = (cc_masec - offset) / 1000;
+       }
+#else          
+  if (qh_new > qh_old){
+     cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000;
+  }else if (qh_new == qh_old){
+    if (ql_new >= ql_old){
+      cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000;
+    }else {  
+      cc_masec = (((qh_old<<16) + ql_old) * 5996) / 1000;
+               }
+  }    
+  
+       offset = (bi->curr_offset * bi->time_interval * 37375) / 100000;
+                         
+  if (cc_masec != 0){
+               cc_masec = cc_masec - offset;
+       }
+#endif
+       if (cc_masec < (DEADBAND * bi->time_interval))
+               cc_masec = 0;
+
+#if RT5025_CSV
+  //pr_info("%d,\n", cc_masec);
+#else
+       RTINFO("chg_cc_mAsec: %d\n", cc_masec);
+#endif
+
+       bi->chg_cc = cc_masec;
+       //bi->chg_cc = (cc_masec + bi->chg_cc_unuse) / 3600;
+  //bi->chg_cc_unuse = (cc_masec + bi->chg_cc_unuse) % 3600;
+  rt5025_clear_cc(bi, CHG);
+}
+
+static void rt5025_get_dchg_cc(struct rt5025_battery_info *bi)
+{
+  u8 data[4];
+  u32 qh_old,ql_old,qh_new,ql_new;
+  u32 cc_masec,offset;
+  
+  if (rt5025_read_reg(bi->client, RT5025_REG_QDCHGH_MSB, data, 4) < 0){
+    printk(KERN_ERR "%s: Failed to read QDCHG\n", __func__);
+  }
+  qh_old = (data[0]<<8) + data[1];
+  ql_old = (data[2]<<8) + data[3];
+  
+  if (rt5025_read_reg(bi->client, RT5025_REG_QDCHGH_MSB, data, 4) < 0){
+    printk(KERN_ERR "%s: Failed to read QDCHG\n", __func__);
+  }
+  qh_new = (data[0]<<8) + data[1];
+  ql_new = (data[2]<<8) + data[3];
+  
+#if RT5025_B
+  if (qh_new > qh_old){
+     cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
+  }else if (qh_new == qh_old){
+    if (ql_new >= ql_old){
+      cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
+    }else {  
+      cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
+               }
+  }    
+  
+       offset = bi->curr_offset * bi->time_interval;
+                         
+  if (cc_masec != 0){
+               cc_masec = (cc_masec + offset) / 1000;
+       }
+#else  
+  if (qh_new > qh_old){
+     cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000;
+  }else if (qh_new == qh_old){
+    if (ql_new >= ql_old){
+      cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000;
+    }else {  
+      cc_masec = (((qh_old<<16) + ql_old) * 5996) / 1000;
+               }
+  }
+  
+       offset = (bi->curr_offset * bi->time_interval * 37375) / 100000;
+                         
+  if (cc_masec > offset){
+               cc_masec = cc_masec - offset;
+       }
+#endif
+       if (cc_masec < (DEADBAND * bi->time_interval))
+               cc_masec = 0;
+               
+#if RT5025_CSV
+  //pr_info("%d,", cc_masec);
+#else
+       RTINFO("dchg_cc_mAsec: %d\n", cc_masec);
+#endif
+       bi->dchg_cc = cc_masec;
+       //bi->dchg_cc = (cc_masec + bi->dchg_cc_unuse) / 3600;
+  //bi->dchg_cc_unuse = (cc_masec + bi->dchg_cc_unuse) % 3600;
+       rt5025_clear_cc(bi, DCHG);
+       
+}
+
+static void rt5025_cycle_count(struct rt5025_battery_info *bi)
+{
+       bi->acc_dchg_cap +=  bi->dchg_cc;
+       if(bi->acc_dchg_cap >= (bi->dc * 3600)){
+               bi->cycle_cnt++;
+               bi->acc_dchg_cap -= (bi->dc * 3600);
+       }
+}
+
+static void rt5025_get_irq_flag(struct rt5025_battery_info *bi, u8 flag)
+{
+#if 0
+  u8 data[1];
+
+  if (rt5025_read_reg(bi->client, RT5025_REG_IRQ_FLAG, data, 1) < 0){
+    pr_err("%s: Failed to read irq_flag\n", __func__);
+  }
+#endif
+               
+  bi->irq_flag = flag;
+       //RTINFO("IRQ_FLG 0x%x\n", bi->irq_flag);
+}
+
+static void rt5025_get_timer(struct rt5025_battery_info *bi)
+{
+  u8 data[2];
+  //frankie
+       //u16 gauge_timer;
+       
+  if (rt5025_read_reg(bi->client, RT5025_REG_TIMER, data, 2) < 0){
+       pr_err("%s: Failed to read Timer\n", __func__);
+  }
+               
+  bi->gauge_timer = (data[0] << 8) + data[1];
+  if (!bi->device_suspend){
+    if (bi->gauge_timer > bi->pre_gauge_timer)
+                 bi->time_interval = bi->gauge_timer - bi->pre_gauge_timer;
+         else  
+                 bi->time_interval = 65536 - bi->pre_gauge_timer + bi->gauge_timer;
+  }
+    
+  bi->pre_gauge_timer = bi->gauge_timer;
+#if RT5025_CSV
+ // pr_info("%d,%d,", bi->gauge_timer,bi->time_interval);
+#else
+       RTINFO("timer %d , interval %d\n", bi->gauge_timer,bi->time_interval);
+#endif
+}
+
+static void rt5025_alert_setting(struct rt5025_battery_info *bi, alert_type type, bool enable)
+{
+       u8 data[1];
+       
+       if (rt5025_read_reg(bi->client, RT5025_REG_IRQ_CTL, data, 1) < 0){
+               printk(KERN_ERR "%s: Failed to read CONFIG\n", __func__);
+       }
+
+       if(enable){
+               switch(type){
+                       case MAXTEMP:
+                               data[0] |= IRQ_CTL_BIT_TMX; //Enable max temperature alert
+                               bi->max_temp_irq = true;
+                               //RTDBG("Enable min temperature alert");
+                               break;
+                       case MINTEMP:
+                               data[0] |= IRQ_CTL_BIT_TMN; //Enable min temperature alert
+                               bi->min_temp_irq = true;  
+                               //RTDBG("Enable max temperature alert");
+                               break;
+                       case MAXVOLT:
+                               data[0] |= IRQ_CTL_BIT_VMX; //Enable max voltage alert
+                               bi->max_volt_irq = true;
+                               //RTDBG("Enable max voltage alert");
+                               break;
+                       case MINVOLT1:
+                               data[0] |= IRQ_CTL_BIT_VMN1; //Enable min1 voltage alert        
+                               bi->min_volt1_irq = true;
+                               //RTDBG("Enable min1 voltage alert");
+                               break;
+                       case MINVOLT2:
+                               data[0] |= IRQ_CTL_BIT_VMN2; //Enable min2 voltage alert
+                               bi->min_volt2_irq = true;
+                               //RTDBG("Enable min2 voltage alert");
+                               break;
+                       default:
+                               break;
+               }
+       }else{
+               switch(type){
+                       case MAXTEMP:
+                               data[0] = data[0] &~ IRQ_CTL_BIT_TMX; //Disable max temperature alert
+                               bi->max_temp_irq = false;
+                               //RTDBG("Disable min temperature alert");
+                               break;
+                       case MINTEMP:
+                               data[0] = data[0] &~ IRQ_CTL_BIT_TMN; //Disable min temperature alert
+                               bi->min_temp_irq = false;
+                               //RTDBG("Disable max temperature alert");
+                               break;
+                       case MAXVOLT:
+                               data[0] = data[0] &~ IRQ_CTL_BIT_VMX; //Disable max voltage alert
+                               bi->max_volt_irq = false;
+                               //RTDBG("Disable max voltage alert");
+                               break;
+                       case MINVOLT1:
+                               data[0] = data[0] &~ IRQ_CTL_BIT_VMN1; //Disable min1 voltage alert     
+                               bi->min_volt1_irq = false;
+                               //RTDBG("Disable min1 voltage alert");
+                               break;
+                       case MINVOLT2:
+                               data[0] = data[0] &~ IRQ_CTL_BIT_VMN2; //Disable min2 voltage alert
+                               bi->min_volt2_irq = false;
+                               //RTDBG("Disable min2 voltage alert");
+                               break;
+                       default:
+                               break;
+               }
+       }
+       if (rt5025_write_reg(bi->client, RT5025_REG_IRQ_CTL, data, 1) < 0)
+               pr_err("%s: failed to write IRQ control\n", __func__);
+}
+
+static void rt5025_alert_threshold_init(struct i2c_client *client)
+{
+       u8 data[1];
+
+       #if 0 //change the operating right to jeita driver
+       /* TALRT MAX threshold setting */
+       data[0] = irq_thres[MAXTEMP];
+       if (rt5025_write_reg(client, RT5025_REG_TALRT_MAXTH, data, 1) < 0)
+               printk(KERN_ERR "%s: failed to write TALRT MAX threshold\n", __func__); 
+       /* TALRT MIN threshold setting */
+       data[0] = irq_thres[MINTEMP];
+       if (rt5025_write_reg(client, RT5025_REG_TALRT_MINTH, data, 1) < 0)
+               printk(KERN_ERR "%s: failed to write TALRT MIN threshold\n", __func__); 
+       #endif
+       /* VALRT MAX threshold setting */
+       data[0] = irq_thres[MAXVOLT];
+       if (rt5025_write_reg(client, RT5025_REG_VALRT_MAXTH, data, 1) < 0)
+               printk(KERN_ERR "%s: failed to write VALRT MAX threshold\n", __func__); 
+       /* VALRT MIN1 threshold setting */
+       data[0] = irq_thres[MINVOLT1];
+       if (rt5025_write_reg(client, RT5025_REG_VALRT_MIN1TH, data, 1) < 0)
+               printk(KERN_ERR "%s: failed to write VALRT MIN1 threshold\n", __func__);        
+       /* VALRT MIN2 threshold setting */
+       data[0] = irq_thres[MINVOLT2];
+       if (rt5025_write_reg(client, RT5025_REG_VALRT_MIN2TH, data, 1) < 0)
+               printk(KERN_ERR "%s: failed to write VALRT MIN2 threshold\n", __func__);        
+}
+
+static void rt5025_alert_init(struct rt5025_battery_info *bi)
+{
+
+       /* Set RT5025 gauge alert configuration */
+       rt5025_alert_threshold_init(bi->client);
+       /* Enable gauge alert function */
+       rt5025_alert_setting(bi, MINVOLT2,VOLTAGE_ALERT);       
+}
+
+void rt5025_gauge_irq_handler(struct rt5025_battery_info *bi, u8 irq_flag)
+{
+  rt5025_get_irq_flag(bi, irq_flag);
+
+  if ((bi->irq_flag) & IRQ_FLG_BIT_TMX){       
+               //printk(KERN_INFO "[RT5025]: Min temperature IRQ received\n");
+               rt5025_alert_setting(bi,MAXTEMP,false);
+               bi->max_temp_irq = false;
+       }
+  if ((bi->irq_flag) & IRQ_FLG_BIT_TMN){
+               //printk(KERN_INFO "[RT5025]: Max temperature IRQ received\n");
+               rt5025_alert_setting(bi,MINTEMP,false);
+               bi->min_temp_irq = false; 
+       }
+  if ((bi->irq_flag) & IRQ_FLG_BIT_VMX){
+               //printk(KERN_INFO "[RT5025]: Max voltage IRQ received\n");
+               rt5025_alert_setting(bi,MAXVOLT,false);
+               bi->max_volt_irq = false;
+       }
+  if ((bi->irq_flag) & IRQ_FLG_BIT_VMN1){
+               //printk(KERN_INFO "[RT5025]: Min voltage1 IRQ received\n");
+               rt5025_alert_setting(bi,MINVOLT1,false);
+               bi->min_volt1_irq = false;
+       }
+  if ((bi->irq_flag) & IRQ_FLG_BIT_VMN2){
+               //printk(KERN_INFO "[RT5025]: Min voltage2 IRQ received\n");
+               rt5025_alert_setting(bi,MINVOLT2,false);
+               bi->min_volt2_irq = false;
+               bi->min_volt2_alert = true;
+               wake_lock_timeout(&bi->low_battery_wake_lock, msecs_to_jiffies(LOW_BAT_WAKE_LOK_TIME*MSEC_PER_SEC));
+       }
+       
+       wake_lock(&bi->monitor_wake_lock);
+       schedule_delayed_work(&bi->monitor_work, 0);
+}
+EXPORT_SYMBOL(rt5025_gauge_irq_handler);
+
+static void rt5025_convert_masec_to_permille(struct rt5025_battery_info *bi)
+{
+  bi->permille = bi->rm / 3600 * 1000 / bi->fcc;
+  RTINFO("permille=%d\n", bi->permille);
+  return;
+}
+
+static void rt5025_convert_permille_to_masec(struct rt5025_battery_info *bi)
+{ 
+  bi->rm = bi->permille * bi->fcc / 1000 * 3600;
+  return;
+}
+
+static void rt5025_init_capacity(struct rt5025_battery_info *bi)
+{
+  int i = 1;
+  int size;
+  int slope, const_term;
+  int delta_y, delta_x;
+
+  size = ARRAY_SIZE(rt5025_battery_param1);
+  while((bi->vcell < rt5025_battery_param1[i].x) &&
+                               (i < (size - 1))){
+    i++;
+  }
+
+  delta_x = rt5025_battery_param1[i-1].x - rt5025_battery_param1[i].x;
+  delta_y = (rt5025_battery_param1[i-1].y - rt5025_battery_param1[i].y);
+
+  slope = delta_y  * 1000 / delta_x;
+
+  const_term = (rt5025_battery_param1[i].y) - ((rt5025_battery_param1[i].x * slope) / 1000);
+
+  if (bi->vcell >= rt5025_battery_param1[0].x)
+    bi->permille = rt5025_battery_param1[0].y; 
+  else if (bi->vcell <= rt5025_battery_param1[size-1].x)
+    bi->permille = rt5025_battery_param1[size-1].y;
+  else
+    bi->permille = (bi->vcell * slope) / 1000 + const_term;
+  rt5025_convert_permille_to_masec(bi);
+  bi->soc = bi->rm /36/bi->fcc_aging;
+       bi->init_cap = false;
+
+  //pr_err("[rt5025] i=%d, delta_x=%d, delta_y=%d, slope=%d, const_term=%d\n", i, delta_x, delta_y, slope, const_term);
+       RTINFO("voltage=%d, permille=%d, soc=%d, rm=%d\n", bi->vcell, bi->permille, bi->soc, bi->rm);
+  return;              
+}
+
+static void rt5025_smooth_soc(struct rt5025_battery_info *bi)
+{
+       if ((bi->internal_status == POWER_SUPPLY_STATUS_CHARGING) &&
+           (bi->soc < 100)){
+               bi->soc++;
+       }else if ((bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) &&
+                 (bi->soc > 0)){
+               bi->soc--;
+       }else{
+         bi->smooth_flag = false;
+         bi->update_time = NORMAL_POLL;
+  }
+}
+
+
+static void rt5025_soc_irreversible(struct rt5025_battery_info *bi)
+{
+       // Prevent inverse
+       //if (!bi->init_cap){
+       if (!bi->init_once){
+               if (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING){
+                       if (bi->soc < bi->pre_soc)
+                               bi->soc = bi->pre_soc;
+               }else if (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING){
+                       if (bi->soc > bi->pre_soc)
+                               bi->soc = bi->pre_soc;          
+               }
+       }
+       else
+               bi->init_once = false;
+
+       bi->pre_soc = bi->soc; 
+}
+
+static void rt5025_soc_lock(struct rt5025_battery_info *bi)
+{
+        // lock 99%
+  RTINFO("internal status=%d, tp_flag=%d, soc=%d\n", bi->internal_status, bi->tp_flag, bi->soc);
+  if ((bi->soc >= 99) && (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING))
+  {
+       if (bi->tp_flag)
+               bi->soc = 100;
+       else
+       {
+               if (bi->status == POWER_SUPPLY_STATUS_FULL)
+                       bi->soc = 100;
+               else
+                       bi->soc = 99;
+       }
+  }
+  else if ((bi->soc < 99) && (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING) && \
+          (bi->tp_flag))
+  {
+       bi->update_time = SMOOTH_POLL;
+       bi->smooth_flag = true;
+       rt5025_smooth_soc(bi);
+  }else
+  {
+       bi->tp_flag = false;
+  }
+
+  // lock 1%   
+  if ((bi->soc <= 1) &&
+      (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING)){
+    if (bi->edv_flag)
+      bi->soc = 0;
+    else
+      bi->soc = 1;
+       }else if ((bi->soc > 1) &&
+            (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) &&
+            (bi->edv_flag)){
+               bi->update_time = SMOOTH_POLL;
+               bi->smooth_flag = true;
+               rt5025_smooth_soc(bi);
+       }else{
+               bi->edv_flag = false;
+       }
+}
+
+static void rt5025_get_soc(struct rt5025_battery_info *bi)
+{
+  if (bi->smooth_flag){
+    bi->smooth_flag = false;
+    bi->update_time = NORMAL_POLL;
+  }
+       RTINFO("before rm=%d\n", bi->rm);
+       if ((!bi->tp_flag) &&
+                       (!bi->edv_flag)){
+               bi->rm = (bi->rm + bi->chg_cc) > bi->dchg_cc ? 
+                           bi->rm + bi->chg_cc - bi->dchg_cc : 0;
+               if (bi->rm > (bi->fcc * 3600))
+                                       bi->rm = bi->fcc * 3600;
+               rt5025_convert_masec_to_permille(bi);
+               bi->soc = DIV_ROUND_UP(bi->permille, 10);
+#if RT5025_CSV
+    bi->temp_soc = bi->soc;
+    //pr_info("%d", bi->soc);
+#else
+       RTINFO("after rm=%d\n", bi->rm);
+               RTINFO("temp_soc=%d\n", bi->soc);
+#endif
+  }
+#if RT5025_CSV
+ // pr_info("%d,%d,%d,%d,%d", bi->soc,bi->permille,bi->rm,bi->fcc,bi->smooth_flag);
+#else  
+       RTINFO("soc=%d, permille=%d, rm=%d, fcc=%d, smooth_flag=%d\n", bi->soc,bi->permille,bi->rm,bi->fcc,bi->smooth_flag);
+#endif
+  return;
+}
+
+static void rt5025_soc_relearn_check(struct rt5025_battery_info *bi)
+{
+  // TP relearn
+/*  if ((bi->vcell >= TP_VOLT) &&
+                       (bi->curr <= TP_CURR) &&
+                       (bi->status == POWER_SUPPLY_STATUS_CHARGING) &&
+                       (!bi->tp_flag)){
+               bi->tp_cnt++;
+               bi->update_time = TP_POLL;
+       }else {
+               bi->tp_cnt = 0;
+               bi->update_time = NORMAL_POLL;
+       }
+   
+  if (bi->tp_cnt == TP_TOTAL_COUNT){
+               bi->tp_cnt = 0;
+               bi->tp_flag = true;
+               bi->rm = bi->fcc * 3600;
+               rt5025_convert_masec_to_permille();
+               bi->update_time = NORMAL_POLL;
+       }*/
+       
+       // if EOC happened, the tp_flag should be set 1.
+       if(bi->tp_flag == true)
+       {
+               bi->rm = bi->fcc * 3600;
+               rt5025_convert_masec_to_permille(bi);
+               bi->update_time = NORMAL_POLL;
+       }
+       
+       if(rt5025_battery_param2[4].x < bi->vcell && bi->vcell <= rt5025_battery_param2[4].x+300)
+       {
+               bi->update_time = EDV_POLL;
+               bi->edv_detection = true;
+       }
+       else if((bi->vcell >= rt5025_battery_param2[4].x + 300 +EDV_HYS) && (bi->edv_detection == true))
+       {
+                bi->update_time = NORMAL_POLL;
+                bi->edv_detection = false;              
+       }
+       else if((bi->vcell <= rt5025_battery_param2[4].x) && (bi->min_volt2_alert == true))
+       {
+               bi->edv_flag = true;
+               bi->rm = 0;
+               rt5025_convert_masec_to_permille(bi);
+               bi->edv_detection = false;
+               bi->update_time = NORMAL_POLL;
+       }
+       else if((bi->vcell > rt5025_battery_param2[4].x + EDV_HYS) && (bi->min_volt2_alert == true))
+       {
+               bi->min_volt2_alert = false;
+       }
+       
+       /*// EDV relearn
+  if (bi->vcell <= EDV_VOLT){
+               if ((bi->curr <= EDV_CURR) ||
+                               (bi->vcell <= rt5025_battery_param2[4].x))
+                       bi->edv_cnt++;
+               else
+               {
+                       bi->edv_cnt = 0;        
+               }
+               bi->edv_detection = true;
+               bi->update_time = EDV_POLL;
+       }else if ((bi->vcell > (EDV_VOLT + EDV_HYS)) &&
+                 (bi->edv_detection)) {
+               bi->edv_cnt = 0;
+               bi->edv_detection = false;
+               bi->edv_flag = false;
+               bi->update_time = NORMAL_POLL;
+       }
+       else
+       {
+               bi->edv_cnt = 0;
+       }
+   
+  if (bi->edv_cnt == EDV_TOTAL_COUNT){
+               bi->edv_cnt = 0;
+               bi->edv_flag = true;
+               bi->rm = 0;
+               rt5025_convert_masec_to_permille();
+               bi->edv_detection = false;
+               bi->update_time = NORMAL_POLL;
+       }
+  if(bi->edv_detection)
+  {
+       bi->update_time = EDV_POLL;
+  }*/
+  if (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING) 
+         bi->edv_flag = false;
+  else if (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING)
+    bi->tp_flag = false;
+
+#if RT5025_CSV
+  //pr_err("%d,%d,%d,%d,%d", 
+   // bi->tp_cnt,bi->tp_flag,bi->edv_detection,bi->edv_cnt,bi->edv_flag);
+#else  
+       RTINFO("tp_cnt=%d, tp_flag=%d, edv_detection=%d, edv_cnt=%d, edv_flag=%d\n", 
+    bi->tp_cnt,bi->tp_flag,bi->edv_detection,bi->edv_cnt,bi->edv_flag);
+#endif
+
+  return;
+}
+
+static void rt5025_channel_cc(struct rt5025_battery_info *bi, bool enable)
+{
+  u8 data[1];
+       
+  if (rt5025_read_reg(bi->client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
+    printk(KERN_INFO "%s: failed to read channel\n", __func__);
+  }
+
+  if (enable){
+    data[0] = data[0] | 0x80;
+  }else { 
+    data[0] = data[0] & 0x7F;
+  }
+    
+  if (rt5025_write_reg(bi->client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
+    printk(KERN_INFO "%s: failed to write channel\n", __func__);
+  }
+}
+
+#if 0
+static void rt5025_pretrim(struct rt5025_battery_info *bi)
+{
+       u8 data0[2];
+       u8 data1[1];
+       
+       data0[0] = 0x55;
+       data0[1] = 0xAA;
+  if (rt5025_write_reg(bi->client, 0xF0, data0, 2) < 0){
+    printk(KERN_ERR "%s: failed to write channel\n", __func__);
+  }
+       data0[0] = 0x07;
+  if (rt5025_write_reg(bi->client, 0xF1, data0, 1) < 0){
+    printk(KERN_ERR "%s: failed to write channel\n", __func__);
+  }
+  // write trim data D0
+       data0[0] = 0xDE;
+  if (rt5025_write_reg(bi->client, 0xD0, data0, 1) < 0){
+    printk(KERN_ERR "%s: failed to write channel\n", __func__);
+  }
+  // Read back to verify
+  if (rt5025_read_reg(bi->client, 0xD0, data1, 1) < 0){
+    printk(KERN_ERR "%s: failed to read channel\n", __func__);
+  }
+  if (data1[0] != data0[0])
+               printk(KERN_ERR "%s: 0xD0 write fail\n", __func__);
+       // write trim data D1
+       data0[0] = 0x01;
+  if (rt5025_write_reg(bi->client, 0xD1, data0, 1) < 0){
+    printk(KERN_ERR "%s: failed to write channel\n", __func__);
+  }
+  // Read back to verify
+  if (rt5025_read_reg(bi->client, 0xD1, data1, 1) < 0){
+    printk(KERN_ERR "%s: failed to read channel\n", __func__);
+  }
+  if (data1[0] != data0[0])
+               printk(KERN_ERR "%s: 0xD1 write fail\n", __func__);
+  // write trim data D2
+       data0[0] = 0x10;
+  if (rt5025_write_reg(bi->client, 0xD2, data0, 1) < 0){
+    printk(KERN_ERR "%s: failed to write channel\n", __func__);
+  }
+  // Read back to verify
+  if (rt5025_read_reg(bi->client, 0xD2, data1, 1) < 0){
+    printk(KERN_ERR "%s: failed to read channel\n", __func__);
+  }
+  if(data1[0] != data0[0])
+               printk(KERN_ERR "%s: 0xD2 write fail\n", __func__);
+  // write trim data D3
+       data0[0] = 0x89;
+  if (rt5025_write_reg(bi->client, 0xD3, data0, 1) < 0){
+    printk(KERN_ERR "%s: failed to write channel\n", __func__);
+  }
+  // Read back to verify
+  if (rt5025_read_reg(bi->client, 0xD3, data1, 1) < 0){
+    printk(KERN_ERR "%s: failed to read channel\n", __func__);
+  }
+  if(data1[0] != data0[0])
+               printk(KERN_ERR "%s: 0xD3 write fail\n", __func__);
+  // write trim data D4
+       data0[0] = 0xF2;
+  if (rt5025_write_reg(bi->client, 0xD4, data0, 1) < 0){
+    printk(KERN_ERR "%s: failed to write channel\n", __func__);
+  }
+  // Read back to verify
+  if (rt5025_read_reg(bi->client, 0xD4, data1, 1) < 0){
+    printk(KERN_ERR "%s: failed to read channel\n", __func__);
+  }
+  if (data1[0] != data0[0])
+               printk(KERN_ERR "%s: 0xD4 write fail\n", __func__);                             
+                        
+       data0[0] = 0x55;
+       data0[1] = 0x55;
+  if (rt5025_write_reg(bi->client, 0xF0, data0, 2) < 0){
+    printk(KERN_ERR "%s: failed to write channel\n", __func__);
+  }
+}
+#endif
+
+static int rt5025_battery_parameter_backup(struct rt5025_battery_info *bi)
+{
+       u8 data[4];
+       RTINFO("\n");
+       //backup fcc_aging, rm, cycle_count, acc_dchg_cap
+       //fcc_aging
+       data[0] = (bi->fcc_aging>>8)&0xff;
+       data[1] = (bi->fcc_aging)&0xff;
+       rt5025_write_reg(bi->client, 0x21, data, 2);
+       //rm
+       data[0] = (bi->rm>>24)&0xff;
+       data[1] = (bi->rm>>16)&0xff;
+       data[2] = (bi->rm>>8)&0xff;
+       data[3] = (bi->rm)&0xff;
+       rt5025_write_reg(bi->client, 0x23, data, 4);
+       //acc_dchg_cap
+       data[0] = (bi->acc_dchg_cap>>24)&0xff;
+       data[1] = (bi->acc_dchg_cap>>16)&0xff;
+       data[2] = (bi->acc_dchg_cap>>8)&0xff;
+       data[3] = (bi->acc_dchg_cap)&0xff;
+       rt5025_write_reg(bi->client, 0x27, data, 4);
+       //cycle_count
+       data[0] = (bi->cycle_cnt)&0xff;
+       rt5025_write_reg(bi->client, 0x2B, data, 1);
+       return 0;
+}
+
+static int rt5025_battery_parameter_restore(struct rt5025_battery_info *bi)
+{
+       u8 data[4];
+       RTINFO("\n");
+       //restore fcc_aging, rm ,cycle_count, acc_dchg_cap
+       //fcc_aging
+       rt5025_read_reg(bi->client, 0x21, data, 2);
+       bi->fcc = bi->fcc_aging = data[0]<<8 | data[1];
+       //rm
+       rt5025_read_reg(bi->client, 0x23, data, 4);
+       bi->rm = data[0]<<24 | data[1]<<16 | data[2]<<8 | data[3];
+       //acc_dchg_cap
+       rt5025_read_reg(bi->client, 0x27, data, 4);
+       bi->acc_dchg_cap = data[0]<<24 | data[1]<<16 | data[2]<<8 | data[3];
+       //cycle_count
+       rt5025_read_reg(bi->client, 0x2B, data, 1);
+       bi->cycle_cnt = data[0];
+       
+       return 0;
+}
+
+
+// return value; 1-> initialized, 0-> no initial value
+static int rt5025_battery_parameter_initcheck(struct rt5025_battery_info *bi)
+{
+       u8 data[2];
+       u16 value;
+       int ret = 0;
+
+       if (rt5025_read_reg(bi->client, 0x21, data, 2) < 0)
+       {
+               pr_err("%s: check initial value error\n", __func__);
+       }
+       else
+       {
+               value = data[1]<<8 | data[0];
+               if (value)
+                       ret = 1;
+       }
+       RTINFO("initial check = %d\n", ret);
+
+       return ret;
+}
+
+static void rt5025_register_init(struct rt5025_battery_info *bi)
+{  
+       u8 data[1];
+       
+       /* enable the channel of current,qc,ain,vbat and vadc */
+       if (rt5025_read_reg(bi->client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
+               pr_err("%s: failed to read channel\n", __func__);
+       }
+       data[0] = data[0] | CHANNEL_L_BIT_CADC_EN | CHANNEL_L_BIT_AINCH | \
+               CHANNEL_L_BIT_VBATSCH | CHANNEL_L_BIT_VADC_EN;
+       if (rt5025_write_reg(bi->client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
+               pr_err("%s: failed to write channel\n", __func__);
+       }
+       /* set the alert threshold value */
+       irq_thres[MINVOLT2] = VALRTMIN2_VALUE;
+       irq_thres[VOLT_RLS] = VRLS_VALUE;
+
+       bi->chg_cc_unuse = 0;
+       bi->dchg_cc_unuse = 0;
+       bi->pre_gauge_timer = 0;
+       bi->online = 1;
+       bi->status = bi->internal_status = POWER_SUPPLY_STATUS_DISCHARGING;
+       bi->health = POWER_SUPPLY_HEALTH_GOOD;
+       
+       bi->init_cap = true;
+       bi->avg_flag = true;
+
+       bi->fcc_aging = rt5025_battery_param2[4].y;
+       bi->fcc = rt5025_battery_param2[4].y;
+       bi->dc = rt5025_battery_param2[4].y;
+       bi->rm = 0;
+
+       bi->edv_cnt = 0;
+       bi->edv_flag = false;
+       bi->edv_detection = false;
+       bi->init_once = true;
+
+       bi->tp_cnt = 0;
+       bi->tp_flag = false;
+  
+       bi->acc_dchg_cap = 0;
+       bi->cycle_cnt = 0;
+
+       // if has initial data, rewrite to the stored data
+       if (rt5025_battery_parameter_initcheck(bi))
+       {
+               bi->init_cap = false;
+               rt5025_battery_parameter_restore(bi);
+               bi->soc = bi->rm/36/bi->fcc_aging;
+       }
+  
+       bi->update_time = NORMAL_POLL;
+       bi->device_suspend = false;
+       RTINFO("register initialized\n");
+}
+
+static void rt5025_soc_aging(struct rt5025_battery_info *bi)
+{
+       if (bi->cycle_cnt >= rt5025_battery_param2[3].x)
+       {
+               bi->fcc_aging = bi->fcc_aging*(1000-rt5025_battery_param2[3].y)/1000;
+               bi->rm = bi->rm*(1000-rt5025_battery_param2[3].y)/1000;
+               bi->cycle_cnt -= rt5025_battery_param2[3].x;
+       }
+       RTINFO("fcc_aging=%d, rm=%d, cycle_cnt=%d\n", bi->fcc_aging, bi->rm, bi->cycle_cnt);
+}
+
+static void rt5025_temp_comp(struct rt5025_battery_info *bi)
+{
+       int i = 1;
+  int size;
+  int slope, const_term;
+  int delta_y, delta_x;        
+  
+  size = 3;
+  while((bi->ext_temp < rt5025_battery_param2[i].x) &&
+                               (i < (size - 1))){
+    i++;
+  }
+
+  delta_x = rt5025_battery_param2[i-1].x - rt5025_battery_param2[i].x;
+  delta_y = (rt5025_battery_param2[i-1].y - rt5025_battery_param2[i].y);
+
+  slope = delta_y  * 1000 / delta_x;
+
+  const_term = (rt5025_battery_param2[i].y) - ((rt5025_battery_param2[i].x * slope) / 1000);
+
+  if (bi->ext_temp >= rt5025_battery_param2[0].x)
+    bi->tempcmp = rt5025_battery_param2[0].y; 
+  else if (bi->ext_temp <= rt5025_battery_param2[size-1].x)
+    bi->tempcmp = rt5025_battery_param2[size-1].y;
+  else
+    bi->tempcmp = (bi->ext_temp * slope) / 1000 + const_term;
+       
+  bi->fcc = bi->fcc_aging + bi->fcc_aging * bi->tempcmp /1000;
+  if (bi->fcc >= (bi->dc*3>>1))
+       bi->fcc = bi->dc*3>>1;
+  if (bi->fcc <= (bi->dc>>1))
+       bi->fcc = bi->dc>>1;
+  bi->rm = bi->fcc * bi->soc * 36;
+  //pr_err("[rt5025] i=%d, delta_x=%d, delta_y=%d, slope=%d, const_term=%d\n", i, delta_x, delta_y, slope, const_term);
+  RTINFO("tempcmp=%d, ext_temp=%d, fcc=%d, rm=%d\n", bi->tempcmp, bi->ext_temp, bi->fcc, bi->rm);
+  return;              
+}
+
+static void rt5025_soc_temp_comp(struct rt5025_battery_info *bi)
+{
+  RTINFO("soc->%d++\n", bi->soc);
+  bi->temp_range_0_5 = false;
+  bi->temp_range_5_10 = false;
+  bi->temp_range_10_15 = false;
+  bi->temp_range_15_20 = false;
+  bi->temp_range_20_30 = false; 
+  bi->temp_range_30_35 = false;
+  bi->temp_range_35_40 = false;
+  bi->temp_range_40_45 = false;
+  bi->temp_range_45_50 = false;
+  
+  if (bi->ext_temp < 50)
+       bi->temp_range_0_5 = true;
+  else if (50 <= bi->ext_temp && bi->ext_temp < 100)
+       bi->temp_range_5_10 = true;
+  else if (100 <= bi->ext_temp && bi->ext_temp < 150)
+       bi->temp_range_10_15 = true;
+  else if (150 <= bi->ext_temp && bi->ext_temp < 200)
+               bi->temp_range_15_20 = true;
+  else if (200 <= bi->ext_temp && bi->ext_temp <= 300)
+       bi->temp_range_20_30 = true;
+  else if (300 < bi->ext_temp && bi->ext_temp <= 350)
+       bi->temp_range_30_35 = true;
+  else if (350 < bi->ext_temp && bi->ext_temp <= 400)
+       bi->temp_range_35_40 = true;
+  else if (400 < bi->ext_temp && bi->ext_temp <= 450)
+       bi->temp_range_40_45 = true;
+  else if (450 < bi->ext_temp)
+       bi->temp_range_45_50 = true;
+       
+  if((bi->temp_range_0_5 == true) && (bi->range_0_5_done == false))    
+  {
+       rt5025_temp_comp(bi);
+       bi->range_0_5_done = true;
+       bi->range_5_10_done = false;
+       bi->range_10_15_done = false;
+       bi->range_15_20_done = false;
+       bi->range_20_30_done = false;
+       bi->range_30_35_done = false;
+       bi->range_35_40_done = false;
+       bi->range_40_45_done = false;
+       bi->range_45_50_done = false;
+  }
+       else if((bi->temp_range_5_10 == true) && (bi->range_5_10_done == false))        
+  {
+       rt5025_temp_comp(bi);
+       bi->range_0_5_done = false;
+       bi->range_5_10_done = true;
+       bi->range_10_15_done = false;
+       bi->range_15_20_done = false;
+       bi->range_20_30_done = false;
+       bi->range_30_35_done = false;
+       bi->range_35_40_done = false;
+       bi->range_40_45_done = false;
+       bi->range_45_50_done = false;
+  }
+  else if((bi->temp_range_10_15 == true) && (bi->range_10_15_done == false))   
+  {
+    rt5025_temp_comp(bi);
+    bi->range_0_5_done = false;
+       bi->range_5_10_done = false;
+       bi->range_10_15_done = true;
+       bi->range_15_20_done = false;
+       bi->range_20_30_done = false;
+       bi->range_30_35_done = false;
+       bi->range_35_40_done = false;
+       bi->range_40_45_done = false;
+       bi->range_45_50_done = false;
+  }
+  else if((bi->temp_range_15_20 == true) && (bi->range_15_20_done == false))   
+  {
+       rt5025_temp_comp(bi);
+       bi->range_0_5_done = false;
+       bi->range_5_10_done = false;
+       bi->range_10_15_done = false;
+       bi->range_15_20_done = true;
+       bi->range_20_30_done = false;
+       bi->range_30_35_done = false;
+       bi->range_35_40_done = false;
+       bi->range_40_45_done = false;
+       bi->range_45_50_done = false;
+  }
+  else if((bi->temp_range_20_30 == true) && (bi->range_20_30_done == false))   
+  {
+       bi->fcc = bi->fcc_aging;
+       bi->rm = bi->fcc*bi->soc*36;
+       bi->range_0_5_done = false;
+       bi->range_5_10_done = false;
+       bi->range_10_15_done = false;
+       bi->range_15_20_done = false;
+       bi->range_20_30_done = true;
+       bi->range_30_35_done = false;
+       bi->range_35_40_done = false;
+       bi->range_40_45_done = false;
+       bi->range_45_50_done = false;
+  }  
+  else if((bi->temp_range_30_35 == true) && (bi->range_30_35_done == false))   
+  {
+       rt5025_temp_comp(bi);
+       bi->range_0_5_done = false;
+       bi->range_5_10_done = false;
+       bi->range_10_15_done = false;
+       bi->range_15_20_done = false;
+       bi->range_20_30_done = false;
+       bi->range_30_35_done = true;
+       bi->range_35_40_done = false;
+       bi->range_40_45_done = false;
+       bi->range_45_50_done = false;
+  }  
+  else if((bi->temp_range_35_40 == true) && (bi->range_35_40_done == false))   
+  {
+       rt5025_temp_comp(bi);
+       bi->range_0_5_done = false;
+       bi->range_5_10_done = false;
+       bi->range_10_15_done = false;
+       bi->range_15_20_done = false;
+       bi->range_20_30_done = false;
+       bi->range_30_35_done = false;
+       bi->range_35_40_done = true;
+       bi->range_40_45_done = false;
+       bi->range_45_50_done = false;
+  }  
+  else if((bi->temp_range_40_45 == true) && (bi->range_40_45_done == false))   
+  {
+       rt5025_temp_comp(bi);
+       bi->range_0_5_done = false;
+       bi->range_5_10_done = false;
+       bi->range_10_15_done = false;
+       bi->range_15_20_done = false;
+       bi->range_20_30_done = false;
+       bi->range_30_35_done = false;
+       bi->range_35_40_done = false;
+       bi->range_40_45_done = true;
+       bi->range_45_50_done = false;
+  }  
+  else if((bi->temp_range_45_50 == true) && (bi->range_45_50_done == false))   
+  {
+       rt5025_temp_comp(bi);
+       bi->range_0_5_done = false;
+       bi->range_5_10_done = false;
+       bi->range_10_15_done = false;
+       bi->range_15_20_done = false;
+       bi->range_20_30_done = false;
+       bi->range_30_35_done = false;
+       bi->range_35_40_done = false;
+       bi->range_40_45_done = false;
+       bi->range_45_50_done = true;
+  } 
+  RTINFO("soc->%d--\n", bi->soc);
+}
+
+static void rt5025_update(struct rt5025_battery_info *bi)
+{
+  /* Update voltage */
+  rt5025_get_vcell(bi);
+  /* Update current */
+  rt5025_get_current(bi);
+       
+  /* Update external temperature */
+  rt5025_get_external_temp(bi);
+  /* Read timer */
+  rt5025_get_timer(bi);
+  /* Update chg cc */
+  rt5025_get_chg_cc(bi);
+  /* Update dchg cc */
+  rt5025_get_dchg_cc(bi);
+  /* Update cycle count check */
+  rt5025_cycle_count(bi);
+  /* Calculate cycle count */
+  rt5025_soc_aging(bi);
+  /* calculate initial soc */
+  if (bi->init_cap){  
+    rt5025_init_capacity(bi);
+#if RT5025_CSV
+    pr_info("vcell,offset,current,timer,interval,QCHG,QDCHG,tp_cnt,tp_flag,edv_det,edv_cnt,edv_flag,soc,permille,RM,FCC,smooth_flag,acc_QD,cycle,update_time\n");
+#endif
+  }
+
+       /* Relearn SOC */
+       rt5025_soc_relearn_check(bi);
+       /* SOC_Temp_Comp*/
+       rt5025_soc_temp_comp(bi);
+  /* Update SOC */
+  rt5025_get_soc(bi);
+  
+  /* SOC Control Process */
+  rt5025_soc_lock(bi);
+  rt5025_soc_irreversible(bi);
+  
+  /* Update RTTF or RTTE */
+  //rt5025_run_time(bi);
+       
+#if TEMPERATURE_ALERT 
+  if ((bi->max_temp_irq == false) &&
+                 (((irq_thres[MAXTEMP] * IRQ_THRES_UNIT) / 100 - bi->ain_volt) > irq_thres[TEMP_RLS])){
+               rt5025_alert_setting(bi,MAXTEMP,true);
+       }else if ((bi->min_temp_irq == false) &&
+                                         ((bi->ain_volt - (irq_thres[MINTEMP] * IRQ_THRES_UNIT) / 100) > irq_thres[TEMP_RLS])){
+               rt5025_alert_setting(bi,MINTEMP,true);
+  }
+#endif  
+#if 0          
+       }else if ((bi->min_volt1_irq == false) &&
+                                       ((bi->vcell - ((irq_thres[MINVOLT1] * IRQ_THRES_UNIT) / 100)) > irq_thres[VOLT_RLS])){
+               rt5025_alert_setting(bi,MINVOLT1,true);                         
+       }else if ((bi->min_volt2_irq == false) &&
+                                       ((bi->vcell - ((irq_thres[MINVOLT2] * IRQ_THRES_UNIT) / 100)) > irq_thres[VOLT_RLS])){
+               rt5025_alert_setting(bi,MINVOLT2,true);                                         
+       }
+#endif
+       
+#if VOLTAGE_ALERT
+       if ((bi->min_volt2_irq == false) &&
+                               (bi->vcell > (rt5025_battery_param2[4].x + EDV_HYS))){  
+               rt5025_alert_setting(bi,MINVOLT2,true);                                         
+       }
+#endif
+#if RT5025_CSV
+  printk(KERN_INFO "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",bi->vcell,bi->curr_offset,bi->curr,bi->gauge_timer,bi->time_interval,bi->chg_cc,
+               bi->dchg_cc,bi->tp_cnt,bi->tp_flag,bi->edv_detection,bi->edv_cnt,bi->edv_flag,bi->soc,
+               bi->permille,bi->rm,bi->fcc,bi->smooth_flag,bi->acc_dchg_cap,bi->cycle_cnt,bi->update_time);
+#else
+  pr_info("[RT5025] update_time=%d\n",bi->update_time);
+  pr_info("\n");
+#endif
+}
+
+static void rt5025_update_work(struct work_struct *work)
+{
+       struct delayed_work *delayed_work = (struct delayed_work *)container_of(work, struct delayed_work, work);
+       struct rt5025_battery_info *bi = (struct rt5025_battery_info *)container_of(delayed_work, struct rt5025_battery_info, monitor_work);
+       unsigned long flags;
+       
+  rt5025_update(bi);
+  
+       /* prevent suspend before starting the alarm */
+       local_irq_save(flags);
+       bi->last_poll = alarm_get_elapsed_realtime();
+       rt5025_program_alarm(bi);
+       local_irq_restore(flags);
+
+       wake_unlock(&bi->monitor_wake_lock);
+}
+
+static enum power_supply_property rt5025_battery_props[] = {
+  POWER_SUPPLY_PROP_STATUS,
+  POWER_SUPPLY_PROP_HEALTH,
+  POWER_SUPPLY_PROP_PRESENT,
+  POWER_SUPPLY_PROP_TEMP,
+  POWER_SUPPLY_PROP_ONLINE,
+  POWER_SUPPLY_PROP_VOLTAGE_NOW,
+  POWER_SUPPLY_PROP_CURRENT_NOW,
+  POWER_SUPPLY_PROP_CAPACITY,
+  POWER_SUPPLY_PROP_TECHNOLOGY,
+  #if 0
+  POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+  POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+  #endif
+};
+
+static int rt5025_battery_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct rt5025_battery_info *bi = platform_get_drvdata(pdev);
+       //bi->last_event = ktime_get();
+       bi->last_event = current_kernel_time();
+
+       //cy add for battery parameter backup
+       rt5025_battery_parameter_backup(bi);
+
+       rt5025_channel_cc(bi, false);
+       cancel_delayed_work(&bi->monitor_work);
+       rt5025_get_timer(bi);
+       bi->device_suspend = true;
+       //bi->update_time = SUSPEND_POLL;
+       RTINFO("RM=%d\n",bi->rm);
+       return 0;
+}
+
+static int rt5025_battery_resume(struct platform_device *pdev)
+{
+       struct rt5025_battery_info *bi = platform_get_drvdata(pdev);
+       //ktime_t now;
+       //struct timespec now = current_kernel_time();
+       //struct timeval tv;
+       //long time_interval;
+
+       //now = ktime_get();
+       //tv = ktime_to_timeval(ktime_sub(now, bi->last_event));
+       //RTINFO("Sleep time = %d\n",(u32)tv.tv_sec);
+       //bi->rm = bi->rm - ((u32)tv.tv_sec * SLEEP_CURRENT);
+
+       //time_interval = now.tv_sec - bi->last_event.tv_sec;
+       //bi->rm = bi->rm - (time_interval * SLEEP_CURRENT);
+       //RTINFO("Sleep time=%d, RM=%d",(int)time_interval,bi->rm);  
+
+       rt5025_channel_cc(bi, true);
+       wake_lock(&bi->monitor_wake_lock);
+       schedule_delayed_work(&bi->monitor_work, 0);
+       bi->device_suspend = false;
+       //RTINFO("\n");
+       return 0;
+}
+
+static int rt5025_battery_remove(struct platform_device *pdev)
+{
+       struct rt5025_battery_info *bi = platform_get_drvdata(pdev);
+
+       power_supply_unregister(&bi->battery);
+       cancel_delayed_work(&bi->monitor_work);
+       wake_lock_destroy(&bi->monitor_wake_lock);
+       kfree(bi);
+       return 0;
+}
+
+static int rt5025_battery_probe(struct platform_device *pdev)
+{
+       struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
+       struct rt5025_battery_info *bi;
+       int ret;
+
+       bi = kzalloc(sizeof(*bi), GFP_KERNEL);
+       if (!bi)
+               return -ENOMEM;
+   
+       bi->client = chip->i2c;
+       bi->chip = chip;
+
+
+       bi->last_poll = alarm_get_elapsed_realtime();
+       alarm_init(&bi->wakeup_alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
+               rt5025_gauge_alarm);
+
+       INIT_DELAYED_WORK(&bi->monitor_work, rt5025_update_work);
+       
+       wake_lock_init(&bi->monitor_wake_lock, WAKE_LOCK_SUSPEND, "rt-battery-monitor");
+       wake_lock_init(&bi->low_battery_wake_lock, WAKE_LOCK_SUSPEND, "low_battery_wake_lock");
+#if RT5025_TEST_WAKE_LOCK
+       wake_lock_init(&bi->test_wake_lock, WAKE_LOCK_SUSPEND, "rt-test");
+#endif
+       /* Write trimed data */
+       //rt5025_pretrim(client);
+       /* enable channel */
+       rt5025_register_init(bi);
+       /* enable gauge IRQ */
+       rt5025_alert_init(bi);
+  
+       /* register callback functions */
+       /*
+       chip->cb.rt5025_gauge_irq_handler = rt5025_irq_handler;
+       chip->cb.rt5025_gauge_set_status = rt5025_set_status;
+       chip->cb.rt5025_gauge_set_online = rt5025_set_online;
+       chip->cb.rt5025_gauge_suspend = rt5025_gauge_suspend;
+       chip->cb.rt5025_gauge_resume = rt5025_gauge_resume;
+       chip->cb.rt5025_gauge_remove = rt5025_gauge_remove;
+       
+       rt5025_register_gauge_callbacks(&chip->cb);
+       */
+
+       platform_set_drvdata(pdev, bi);
+
+       bi->battery.name = "rt5025-battery";
+       bi->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+       bi->battery.get_property = rt5025_get_property;
+       bi->battery.properties = rt5025_battery_props;
+       bi->battery.num_properties = ARRAY_SIZE(rt5025_battery_props);
+  
+       ret = power_supply_register(&pdev->dev, &bi->battery);
+       if (ret) {
+               printk(KERN_ERR "[RT5025] power supply register failed\n");
+               goto err_wake_lock;
+       }
+  
+
+       wake_lock(&bi->monitor_wake_lock);
+#if RT5025_TEST_WAKE_LOCK
+       wake_lock(&bi->test_wake_lock);
+#endif
+       schedule_delayed_work(&bi->monitor_work, msecs_to_jiffies(INIT_POLL*MSEC_PER_SEC));
+       chip->battery_info = bi;
+
+       pr_info("rt5025-battery driver is successfully loaded\n");
+       
+  return 0;
+
+err_wake_lock:
+       wake_lock_destroy(&bi->monitor_wake_lock);
+       kfree(bi);
+
+       return ret;
+}
+
+static void rt5025_battery_shutdown(struct platform_device *pdev)
+{
+       struct rt5025_battery_info *bi = platform_get_drvdata(pdev);
+
+       RTINFO("\n");
+       rt5025_battery_parameter_backup(bi);
+}
+
+static struct platform_driver rt5025_battery_driver = 
+{
+       .driver = {
+               .name = RT5025_DEVICE_NAME "-battery",
+               .owner = THIS_MODULE,
+       },
+       .probe = rt5025_battery_probe,
+       .remove = __devexit_p(rt5025_battery_remove),
+       .shutdown = rt5025_battery_shutdown,
+       .suspend = rt5025_battery_suspend,
+       .resume = rt5025_battery_resume,
+};
+
+static int __init rt5025_battery_init(void)
+{
+       return platform_driver_register(&rt5025_battery_driver);
+}
+module_init(rt5025_battery_init);
+
+static void __exit rt5025_battery_exit(void)
+{
+       platform_driver_unregister(&rt5025_battery_driver);
+}
+module_exit(rt5025_battery_exit);
+
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Nick Hung <nick_hung@richtek.com");
+MODULE_DESCRIPTION("battery gauge driver for RT5025");
+MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-battery");
diff --git a/drivers/power/rt5025-gauge.c b/drivers/power/rt5025-gauge.c
deleted file mode 100644 (file)
index e4dd00d..0000000
+++ /dev/null
@@ -1,1070 +0,0 @@
-/*
- *  rt5025_gauge.c
- *  fuel-gauge driver
- *  revision 0.1
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/power_supply.h>
-#include <linux/slab.h>
-#include <linux/wakelock.h>
-#include <linux/workqueue.h>
-#include <linux/jiffies.h>
-#include <linux/timer.h>
-#include <linux/android_alarm.h>
-#include <linux/mfd/rt5025.h>
-#include <linux/power/rt5025-gauge.h>
-
-#define RT5025_REG_IRQ_CTL                                             0x50
-#define RT5025_REG_IRQ_FLAG                                            0x51
-#define RT5025_REG_VALRT_MAXTH                         0x53
-#define RT5025_REG_VALRT_MIN1TH                                0x54
-#define RT5025_REG_VALRT_MIN2TH                                0x55
-#define RT5025_REG_TALRT_MAXTH                         0x56
-#define RT5025_REG_TALRT_MINTH                         0x57
-#define RT5025_REG_VCELL_MSB                                   0x58
-#define RT5025_REG_VCELL_LSB                                   0x59
-#define RT5025_REG_INT_TEMPERATUE_MSB  0x5B
-#define RT5025_REG_INT_TEMPERATUE_LSB 0x5C
-#define RT5025_REG_EXT_TEMPERATUE_MSB  0x5E
-#define RT5025_REG_EXT_TEMPERATUE_LSB  0x5F
-#define RT5025_REG_TIMER                                                       0x60
-#define RT5025_REG_CHANNEL_MSB         0x62
-#define RT5025_REG_CHANNEL_LSB         0x63
-#define RT5025_REG_CURRENT_MSB                         0x76
-#define RT5025_REG_CURRENT_LSB                         0x77
-#define RT5025_REG_QCHGH_MSB          0x78
-#define RT5025_REG_QCHGH_LSB          0x79
-#define RT5025_REG_QCHGL_MSB          0x7A
-#define RT5025_REG_QCHGL_LSB          0x7B
-#define RT5025_REG_QDCHGH_MSB                                  0x7C
-#define RT5025_REG_QDCHGH_LSB                                  0x7D
-#define RT5025_REG_QDCHGL_MSB                                  0x7E
-#define RT5025_REG_QDCHGL_LSB                                  0x7F
-
-#define IRQ_CTL_BIT_TMX  (1 << 5)
-#define IRQ_CTL_BIT_TMN  (1 << 4)
-#define IRQ_CTL_BIT_VMX  (1 << 2)
-#define IRQ_CTL_BIT_VMN1 (1 << 1)
-#define IRQ_CTL_BIT_VMN2 (1 << 0)
-
-#define IRQ_FLG_BIT_TMX  (1 << 5)
-#define IRQ_FLG_BIT_TMN  (1 << 4)
-#define IRQ_FLG_BIT_VMX  (1 << 2)
-#define IRQ_FLG_BIT_VMN1 (1 << 1)
-#define IRQ_FLG_BIT_VMN2 (1 << 0)
-
-#define CHANNEL_H_BIT_CLRQDCHG  (1 << 7)
-#define CHANNEL_H_BIT_CLRQCHG   (1 << 6)
-
-#define CHANNEL_L_BIT_CADC_EN   (1 << 7)
-#define CHANNEL_L_BIT_INTEMPCH  (1 << 6)
-#define CHANNEL_L_BIT_AINCH     (1 << 2)
-#define CHANNEL_L_BIT_VBATSCH   (1 << 1)
-#define CHANNEL_L_BIT_VADC_EN   (1 << 0)
-
-#define NORMAL_POLL 10  /* 10 sec */
-#define SUSPEND_POLL (30*60) /* 30 min */
-
-#define HIGH_TEMP_THRES        650
-#define HIGH_TEMP_RECOVER      430
-#define LOW_TEMP_THRES (-30)
-#define LOW_TEMP_RECOVER 0
-#define TEMP_ABNORMAL_COUNT    3
-
-#define TALRTMAX_VALUE  0x38 //65.39'C 0x9
-#define TALRTMIN_VALUE  0x11 //-18.75'C 0x17
-#define VALRTMAX_VALUE  0xDC //4297mV
-#define VALRTMIN1_VALUE 0xB8 //3600mV
-#define VALRTMIN2_VALUE 0x99 //3000mV
-#define TRLS_VALUE      55   //5'C
-#define VRLS_VALUE      100  //100mV
-
-#define IRQ_THRES_UNIT 1953
-
-struct rt5025_gauge_chip {
-  struct i2c_client *client;
-  struct rt5025_power_info *info;
-  struct rt5025_gauge_callbacks cb;
-
-       struct power_supply     battery;
-       
-       struct delayed_work monitor_work;
-       struct wake_lock monitor_wake_lock;
-       struct alarm wakeup_alarm;
-       
-       bool    suspend_poll;
-       ktime_t last_poll;
-       
-  /* battery voltage */
-  u16 vcell;
-  /* battery current */
-  s16 curr;
-  /* battery current offset */
-  u8 curr_offset;
-  /* AIN voltage */
-  u16 ain_volt;
-  /* battery external temperature */
-  s16 ext_temp;
-  /* charge coulomb counter */
-  u32 chg_cc;
-  u32 chg_cc_unuse;
-  //u32 chg_cc_raw; // JY: May not necessary
-  /* discharge coulomb counter */
-  u32 dchg_cc;
-  u32 dchg_cc_unuse;
-  //u32 dchg_cc_raw; // JY: May not necessary
-
-  // JY add variable
-  bool soc_init;
-  u32 rm;
-  u32 rm_old;
-  u8 soc_old;
-  // ---------------
-
-  u32 fcc;
-  /* battery capacity */
-  u8 soc;
-  u32 soc_precise;
-  u16 time_interval;
-  u16 pre_gauge_timer;
-    
-  u8 online;
-  u8 status;
-  u8 health;
-
-  /* IRQ flag */
-  u8 irq_flag;
-   
-  /* max voltage IRQ flag */
-  bool max_volt_irq;
-  /* min voltage1 IRQ flag */
-  bool min_volt1_irq;  
-  /* min voltage2 IRQ flag */
-  bool min_volt2_irq;
-  /* max temperature IRQ flag */
-  bool max_temp_irq;
-  /* min temperature IRQ flag */
-  bool min_temp_irq;
-  
-       u8 temp_high_cnt;
-       u8 temp_low_cnt;
-       u8 temp_recover_cnt;
-};
-
-static u32 battery_vcell_table[] = {3000, 3418, 3598, 3650, 3679, 3722, 3766, 3790, 3826, 3914, 3973, 4046, 4130, 4190};
-static u32 battery_soc_table[] = {0, 2, 5, 7, 14, 24, 40, 49, 58, 71, 80, 89, 98, 100};
-
-struct rt5025_gauge_chip *chip;
-u8 irq_thres[LAST_TYPE];
-
-void rt5025_set_status(int status)
-{
-  chip->status = status; 
-}
-
-static int get_vcell_segment_index(u32* pX, size_t size, u32 x)
-{
-       unsigned int i;
-       if (x <= *pX)
-               return 0;
-       for (i=0; i<size; i++)
-       {
-               if (x<=*(pX+i))
-                       break;
-       }
-       #if 0 // for linear interpolation
-       #else
-       if (i>=(size-2))
-               return size-3;
-       #endif
-       return i;
-}
-
-static u32 rt5025_vcell2soc(u32* pX, u32* pY, size_t size, u32 _x)
-{
-       #if 0 // Linear interpolation
-       int index;
-       int x1, x2;
-       int y, y1, y2;
-       index = get_vcell_segment_index(pX, size, _x);
-       if (_x<*pX)
-               return 0;
-       if (_x>=*(pX+size-1))
-               return 100;
-       if (_x == *(pX+index))
-               return *(pY+index);
-       x1 = *(pX+index-1);
-       x2 = *(pX+index);
-       y1 = *(pY+index-1);
-       y2 = *(pY+index);
-
-       y = (_x-x1)*(y2-y1)*100/(x2-x1);
-       y /= 100;
-       y += y1;
-       
-       return y;
-       #else  // Lagrange interpolation
-       int index;
-       int32_t x1, x2, x3;
-       int32_t y1, y2, y3;
-       int32_t a1, a2, a3, b1, b2, b3;
-       int32_t x = _x;
-       if (_x<*pX)
-               return 0;
-       if (_x>=*(pX+size-1))
-               return 100;
-       index = get_vcell_segment_index(pX, size, _x);
-       pX+=index;
-       pY+=index;
-       x1 = *pX;
-       x2 = *(pX+1);
-       x3 = *(pX+2);
-       y1 = *pY;
-       y2 = *(pY+1);
-       y3 = *(pY+2);
-       if (x == x1)
-               return y1;
-       if (x == x2)
-               return y2;
-       if (x == x3)
-               return y3;
-       a1 = y1*(x-x2)*(x-x3);
-       a2 = y2*(x-x1)*(x-x3);
-       a3 = y3*(x-x1)*(x-x2);
-       b1 = (x1-x2)*(x1-x3);
-       b2 = (x2-x1)*(x2-x3);
-       b3 = (x3-x1)*(x3-x2);
-       
-       return (100*a1/b1+100*a2/b2+100*a3/b3)/100;
-       #endif
-}
-
-static int rt5025_read_reg(struct i2c_client *client,
-                               u8 reg, u8 *data, u8 len)
-{
-       #if 1
-       int ret;
-
-       ret = rt5025_reg_block_read(client, reg, len, data);
-       #else
-       struct i2c_adapter *adap = client->adapter;
-       struct i2c_msg msgs[2];
-       int ret;
-
-       msgs[0].addr = client->addr;
-       msgs[0].flags = client->flags;
-       msgs[0].len = 1;
-       msgs[0].buf = &reg;
-       msgs[0].scl_rate = 200*1000;
-
-       msgs[1].addr = client->addr;
-       msgs[1].flags = client->flags | I2C_M_RD;
-       msgs[1].len = len;
-       msgs[1].buf = data;
-       msgs[1].scl_rate = 200*1000;
-
-       ret = i2c_transfer(adap, msgs, 2);
-       #endif
-       return (ret == 2)? len : ret;  
-}
-
-static int rt5025_write_reg(struct i2c_client *client,
-                               u8 reg, u8 *data, u8 len)
-{
-       #if 1
-       int ret;
-
-       ret = rt5025_reg_block_write(client, reg, len, data);
-       #else
-       struct i2c_adapter *adap = client->adapter;
-       struct i2c_msg msg;
-
-       int ret;
-       char* tx_buf = (char *)kmalloc(len + 1, GFP_KERNEL);
-
-       if (!tx_buf)
-               return -ENOMEM;
-       tx_buf[0] = reg;
-       memcpy(tx_buf+1, data, len);
-
-       msg.addr = client->addr;
-       msg.flags = client->flags;
-       msg.len = len + 1;
-       msg.buf = (char *)tx_buf;
-       msg.scl_rate = 200*1000;
-       ret = i2c_transfer(adap, &msg, 1);
-       kfree(tx_buf);
-
-       #endif
-       return (ret == 1) ? len : ret; 
-}
-
-static void rt5025_gauge_alarm(struct alarm *alarm)
-{
-       pr_info("%s: alarmed \n", __func__);
-       wake_lock(&chip->monitor_wake_lock);
-       schedule_delayed_work(&chip->monitor_work, 0);
-}
-
-static void rt5025_program_alarm(int seconds)
-{
-       ktime_t low_interval = ktime_set(seconds, 0);
-       ktime_t slack = ktime_set(20, 0);
-       ktime_t next;
-
-       next = ktime_add(chip->last_poll, low_interval);
-       alarm_start_range(&chip->wakeup_alarm, next, ktime_add(next, slack));
-}
-
-static int rt5025_get_property(struct power_supply *psy,
-                           enum power_supply_property psp,
-                           union power_supply_propval *val)
-{
-  switch (psp) {
-    case POWER_SUPPLY_PROP_STATUS:
-      val->intval = chip->status;
-      break;
-    case POWER_SUPPLY_PROP_HEALTH:
-      val->intval = chip->health;
-      break;
-    case POWER_SUPPLY_PROP_PRESENT:
-      val->intval = chip->online;
-      break;
-    case POWER_SUPPLY_PROP_TEMP:
-      val->intval = chip->ext_temp;
-      break;
-    case POWER_SUPPLY_PROP_ONLINE:
-      val->intval = 1;
-      break;
-    case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-      val->intval = chip->vcell * 1000; //uV
-      break;
-    case POWER_SUPPLY_PROP_CURRENT_NOW:
-      val->intval = chip->curr * 1000; //uA
-      break;
-    case POWER_SUPPLY_PROP_CAPACITY:
-      val->intval = chip->soc;
-      if (val->intval > 100)
-                               val->intval = 100;
-      break;
-    case POWER_SUPPLY_PROP_TECHNOLOGY:
-      val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
-      break;
-    default:
-      return -EINVAL;
-  }
-  return 0;
-}
-
-static void rt5025_get_vcell(struct i2c_client *client)
-{
-  u8 data[2];
-       
-  if (rt5025_read_reg(client, RT5025_REG_VCELL_MSB, data, 2) < 0){
-    printk(KERN_ERR "%s: Failed to read Voltage\n", __func__);
-  }
-               
-  chip->vcell = ((data[0] << 8) + data[1]) * 61 / 100;
-       chip->curr_offset = (15444 * chip->vcell - 27444000) / 10000;
-               
-  RTINFO("[RT5025] vcell: %d, offset: %d\n", chip->vcell, chip->curr_offset);
-}
-
-static void rt5025_get_current(struct i2c_client *client)
-{
-  u8 data[2];
-  u16 temp;
-  int sign = 0;
-
-  if (rt5025_read_reg(client, RT5025_REG_CURRENT_MSB, data, 2) < 0) {
-    printk(KERN_ERR "%s: Failed to read CURRENT\n", __func__);
-  }
-
-  temp = (data[0]<<8) | data[1];
-  if (data[0] & (1 << 7)) {
-    sign = 1;
-    temp = (((temp & 0x7FFF) * 3125) / 10 + chip->curr_offset) / 1000;
-  }else
-               temp = ((temp * 3125) / 10 - chip->curr_offset) / 1000;
-
-  if (sign)
-    temp *= -1;
-
-       chip->curr = temp;
-  RTINFO("[RT5025] current: %d\n", chip->curr);
-}
-
-static void rt5025_get_external_temp(struct i2c_client *client)
-{
-  u8 data[2];
-  long int temp;
-
-  if (rt5025_read_reg(client, RT5025_REG_EXT_TEMPERATUE_MSB, data, 2) < 0) {
-    printk(KERN_ERR "%s: Failed to read TEMPERATURE\n", __func__);
-  }
-  chip->ain_volt = (data[0] * 256 + data[1]) * 61 / 100;
-  /// Check battery present
-       if (chip->ain_volt < 1150)
-               chip->online = true;
-       else
-               chip->online = false;
-  temp =  (chip->ain_volt * (-91738) + 81521000) / 100000;
-  chip->ext_temp = (int)temp;
-       
-       if (chip->ext_temp >= HIGH_TEMP_THRES) {
-               if (chip->health != POWER_SUPPLY_HEALTH_OVERHEAT)
-                       chip->temp_high_cnt++;
-       } else if (chip->ext_temp <= HIGH_TEMP_RECOVER && chip->ext_temp >= LOW_TEMP_RECOVER) {
-               if (chip->health == POWER_SUPPLY_HEALTH_OVERHEAT ||
-                   chip->health == POWER_SUPPLY_HEALTH_COLD)
-                       chip->temp_recover_cnt++;
-       } else if (chip->ext_temp <= LOW_TEMP_THRES) {
-               if (chip->health != POWER_SUPPLY_HEALTH_COLD)
-                       chip->temp_low_cnt++;
-       } else {
-               chip->temp_high_cnt = 0;
-               chip->temp_low_cnt = 0;
-               chip->temp_recover_cnt = 0;
-       }
-       
-       if (chip->temp_high_cnt >= TEMP_ABNORMAL_COUNT) {
-        chip->health = POWER_SUPPLY_HEALTH_OVERHEAT;
-        chip->temp_high_cnt = 0;
-       } else if (chip->temp_low_cnt >= TEMP_ABNORMAL_COUNT) {
-        chip->health = POWER_SUPPLY_HEALTH_COLD;
-        chip->temp_low_cnt = 0;
-       } else if (chip->temp_recover_cnt >= TEMP_ABNORMAL_COUNT) {
-        chip->health = POWER_SUPPLY_HEALTH_GOOD;
-        chip->temp_recover_cnt = 0;
-       }
-  RTINFO("[RT5025] external temperature: %d\n", chip->ext_temp);
-}
-
-static void rt5025_clear_cc(operation_mode mode)
-{  
-  u8 data[2];
-       
-  if (rt5025_read_reg(chip->client, RT5025_REG_CHANNEL_MSB, data, 2) < 0){
-    printk(KERN_ERR "%s: failed to read channel\n", __func__);
-  }
-
-  if (mode == CHG)
-               data[0] = data[0] | CHANNEL_H_BIT_CLRQCHG;
-       else
-               data[0] = data[0] | CHANNEL_H_BIT_CLRQDCHG;
-               
-  if (rt5025_write_reg(chip->client, RT5025_REG_CHANNEL_MSB, data, 2) < 0){
-    printk(KERN_ERR "%s: failed to write channel\n", __func__);
-  }
-}
-
-static void rt5025_get_chg_cc(struct i2c_client *client)
-{
-  u8 data[4];
-  u32 qh_old,ql_old,qh_new,ql_new;
-  u32 cc_masec,offset;
-  
-  if (rt5025_read_reg(client, RT5025_REG_QCHGH_MSB, data, 4) < 0){
-    printk(KERN_ERR "%s: Failed to read QCHG\n", __func__);
-  }
-  qh_old = (data[0]<<8) + data[1];
-  ql_old = (data[2]<<8) + data[3];
-  //pr_info("%s qh_old %04x ql_old %04x\n", __func__, qh_old, ql_old);
-  
-  if (rt5025_read_reg(client, RT5025_REG_QCHGH_MSB, data, 4) < 0){
-    printk(KERN_ERR "%s: Failed to read QCHG\n", __func__);
-  }
-  qh_new = (data[0]<<8) + data[1];
-  ql_new = (data[2]<<8) + data[3];
-  //pr_info("%s qh_new %04x ql_new %04x\n", __func__, qh_new, ql_new);
-   
-  #if 0
-  if (qh_new > qh_old){
-     cc_masec = qh_new*91266 + ((ql_new*22)>>4);
-  }else if (qh_new == qh_old){
-    if (ql_new >= ql_old){
-      cc_masec = qh_new*91266 + ((ql_new*22)>>4);
-    }else {  
-      cc_masec = qh_old*91266 + ((ql_old*22)>>4);
-               }
-  }
-  #else        
-  if (qh_new > qh_old){
-     cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
-  }else if (qh_new == qh_old){
-    if (ql_new >= ql_old){
-      cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
-    }else {  
-      cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
-               }
-  }
-  #endif       
-  
-       offset = chip->curr_offset * chip->time_interval;
-                         
-  if (cc_masec != 0){
-               #if 0
-               cc_masec /= 1000;
-               #else
-               cc_masec = (cc_masec - offset) / 1000;
-               #endif
-       }
-
-  RTINFO("[RT5025] chg_cc_mAsec: %d\n", cc_masec);
-
-       #if 0
-       chip->chg_cc = cc_masec;
-       chip->chg_cc_unuse = 0;
-       #else
-       chip->chg_cc = (cc_masec + chip->chg_cc_unuse) / 3600;
-  chip->chg_cc_unuse = (cc_masec + chip->chg_cc_unuse) % 3600;
-       #endif
-  RTINFO("[RT5025] chg_cc_mAH: %d\n", chip->chg_cc);
-  rt5025_clear_cc(CHG);
-}
-
-static void rt5025_get_dchg_cc(struct i2c_client *client)
-{
-  u8 data[4];
-  u32 qh_old,ql_old,qh_new,ql_new;
-  u32 cc_masec,offset;
-  
-  if (rt5025_read_reg(client, RT5025_REG_QDCHGH_MSB, data, 4) < 0){
-    printk(KERN_ERR "%s: Failed to read QDCHG\n", __func__);
-  }
-  qh_old = (data[0]<<8) + data[1];
-  ql_old = (data[2]<<8) + data[3];
-  //pr_info("%s qh_old %04x ql_old %04x\n", __func__, qh_old, ql_old);
-  
-  if (rt5025_read_reg(client, RT5025_REG_QDCHGH_MSB, data, 4) < 0){
-    printk(KERN_ERR "%s: Failed to read QDCHG\n", __func__);
-  }
-  qh_new = (data[0]<<8) + data[1];
-  ql_new = (data[2]<<8) + data[3];
- // pr_info("%s qh_new %04x ql_new %04x\n", __func__, qh_new, ql_new);
-
-#if 0
-  if (qh_new > qh_old){
-     cc_masec =  qh_new*91266 + ((ql_new*22)>>4);
-  }else if (qh_new == qh_old){
-    if (ql_new >= ql_old){
-      cc_masec = qh_new*91266 + ((ql_new*22)>>4);
-    }else {  
-      cc_masec = qh_old*91266 + ((ql_old*22)>>4);
-               }
-  }
-#else
-  if (qh_new > qh_old){
-     cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
-  }else if (qh_new == qh_old){
-    if (ql_new >= ql_old){
-      cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
-    }else {  
-      cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
-               }
-  }
-#endif 
-  
-       offset = chip->curr_offset * chip->time_interval;
-                         
-  if (cc_masec != 0){
-               #if 0
-               cc_masec /= 1000;
-               #else
-               cc_masec = (cc_masec - offset) / 1000;
-               #endif
-       }
-
-  RTINFO("[RT5025] dchg_cc_mAsec: %d\n", cc_masec);
-
-       #if 0
-       chip->dchg_cc = cc_masec;
-       chip->dchg_cc_unuse = 0;
-       #else
-       chip->dchg_cc = (cc_masec + chip->dchg_cc_unuse) / 3600;
-  chip->dchg_cc_unuse = (cc_masec + chip->dchg_cc_unuse) % 3600;
-       #endif
-  RTINFO("[RT5025] dchg_cc_mAH: %d\n", chip->dchg_cc);
-       rt5025_clear_cc(DCHG);
-}
-
-static void rt5025_get_irq_flag(struct i2c_client *client)
-{
-  u8 data[1];
-
-  if (rt5025_read_reg(client, RT5025_REG_IRQ_FLAG, data, 1) < 0){
-    printk(KERN_ERR "%s: Failed to read irq_flag\n", __func__);
-  }
-               
-  chip->irq_flag = data[0];
-  RTINFO("[RT5025] IRQ_FLG 0x%x\n", chip->irq_flag);
-}
-
-static void rt5025_get_timer(struct i2c_client *client)
-{
-  u8 data[2];
-       u16 gauge_timer;
-       
-  if (rt5025_read_reg(client, RT5025_REG_TIMER, data, 2) < 0){
-    printk(KERN_ERR "%s: Failed to read Timer\n", __func__);
-  }
-               
-  gauge_timer = (data[0] << 8) + data[1];
-  if (gauge_timer > chip->pre_gauge_timer)
-               chip->time_interval = gauge_timer - chip->pre_gauge_timer;
-       else    
-               chip->time_interval = 65536 - chip->pre_gauge_timer + gauge_timer;
-               
-  chip->pre_gauge_timer = gauge_timer;
-  RTINFO("[RT5025] timer %d , interval %d\n", gauge_timer,chip->time_interval);
-}
-
-static void rt5025_gauge_init_soc(struct i2c_client *client)
-{
-       /* Update voltage */
-       rt5025_get_vcell(client);
-       /* Update current */
-       rt5025_get_current(client);
-       /* Update external temperature */
-       rt5025_get_external_temp(client);
-       // JY add 
-       if (chip->soc_init)
-       {
-               chip->soc = chip->soc_old;
-               chip->rm = chip->rm_old;
-       }
-       else
-       {
-               chip->soc = rt5025_vcell2soc(battery_vcell_table, battery_soc_table, ARRAY_SIZE(battery_vcell_table), chip->vcell);
-               chip->soc_precise = (u32)(chip->soc);
-               chip->soc_init = true;
-               chip->soc_old = chip->soc;
-               chip->rm = (chip->soc *chip->fcc)/100;
-               chip->rm_old = chip->rm;
-       }
-       // ----------------
-       /*
-       chip->soc = rt5025_vcell2soc(battery_vcell_table, battery_soc_table, ARRAY_SIZE(battery_vcell_table), chip->vcell);
-       chip->soc_precise = (u32)(chip->soc);
-       */
-       pr_info("%s: vcell = %d, soc = %d\n", __func__, chip->vcell, chip->soc);
-       /* upsampling (extend more 12 bits)*/
-}
-
-static void rt5025_get_soc(struct i2c_client *client)
-{
-       //fcc = full charged capacity (battery capacity)
-       int chg_cc = chip->chg_cc;
-       int dchg_cc = chip->dchg_cc;
-
-       // JY new implement
-       chip->rm = chip->rm_old + (chg_cc - dchg_cc);
-       if (chip->rm  < 0)
-       {
-               chip->rm = 0;
-               chip->chg_cc = 0;
-               chip->dchg_cc = 0;
-       }
-       else if (chip->rm > chip->fcc)
-       {
-               chip->rm = chip->fcc;
-               chip->chg_cc = chip->fcc;
-               chip->dchg_cc = 0;
-       }
-
-       chip->soc_precise = (chip->rm *100)/chip->fcc;
-
-       chip->soc = (chip->soc_precise);
-
-       if (chip->soc > chip->soc_old+1)
-       {
-               chip->soc = chip->soc_old + 1;
-       }
-       else if (chip->soc < chip->soc_old-1)
-       {
-               chip->soc = chip->soc_old -1;
-       }
-
-       if (chip->soc < 0)
-               chip->soc = 0;
-       else if (chip->soc > 100)
-               chip->soc = 100;
-
-       chip->rm_old = chip->rm;
-       chip->soc_old = chip->soc;
-       // --------------------
-
-       /* JY mark it
-
-       chip->soc_precise = chip->soc_precise + ((chg_cc-dchg_cc)*100)/chip->fcc;
-       
-       pr_info("%s chg_cc = %d\n", __func__, chg_cc);
-       pr_info("%s dchg_cc = %d\n", __func__, dchg_cc);
-       pr_info("%s soc_precise = %d\n", __func__, chip->soc_precise);
-       chip->soc = (chip->soc_precise);
-       if (chip->soc < 0)
-               chip->soc = 0;
-       else if (chip->soc > 100)
-               chip->soc = 100;
-       */
-  //chip->soc = 50;
-}
-
-static void rt5025_channel_cc(bool enable)
-{
-  u8 data[1];
-       
-  if (rt5025_read_reg(chip->client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
-    printk(KERN_ERR "%s: failed to read channel\n", __func__);
-  }
-
-  if (enable){
-    data[0] = data[0] | 0x80;
-  }else { 
-    data[0] = data[0] & 0x7F;
-  }
-    
-  if (rt5025_write_reg(chip->client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
-    printk(KERN_ERR "%s: failed to write channel\n", __func__);
-  }
-}
-
-static void rt5025_register_init(struct i2c_client *client)
-{  
-  u8 data[1];
-       
-  /* enable the channel of current,qc,ain,vbat and vadc */
-  if (rt5025_read_reg(client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
-    printk("%s: failed to read channel\n", __func__);
-  }
-  data[0] = data[0] |
-                                               CHANNEL_L_BIT_CADC_EN |
-                                               CHANNEL_L_BIT_AINCH |
-                                               CHANNEL_L_BIT_VBATSCH |
-                                               CHANNEL_L_BIT_VADC_EN;
-  if (rt5025_write_reg(client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
-    printk("%s: failed to write channel\n", __func__);
-  }
-       /* set the alert threshold value */
-       irq_thres[MAXTEMP]  = TALRTMAX_VALUE;
-       irq_thres[MINTEMP]  = TALRTMIN_VALUE;
-       irq_thres[MAXVOLT]  = VALRTMAX_VALUE;
-       irq_thres[MINVOLT1] = VALRTMIN1_VALUE;
-       irq_thres[MINVOLT2] = VALRTMIN2_VALUE;
-       irq_thres[TEMP_RLS] = TRLS_VALUE;
-       irq_thres[VOLT_RLS] = VRLS_VALUE;
-
-       chip->chg_cc_unuse = 0;
-       chip->dchg_cc_unuse = 0;
-       chip->pre_gauge_timer = 0;
-       chip->online = 1;
-       chip->status = POWER_SUPPLY_STATUS_DISCHARGING;
-       chip->health = POWER_SUPPLY_HEALTH_GOOD;
-  RTINFO("[RT5025] register initialized\n");
-}
-
-static void rt5025_alert_setting(alert_type type, bool enable)
-{
-       u8 data[1];
-       
-  if (rt5025_read_reg(chip->client, RT5025_REG_IRQ_CTL, data, 1) < 0){
-    printk(KERN_ERR "%s: Failed to read CONFIG\n", __func__);
-  }
-
-  if(enable){
-               switch(type){
-                       case MAXTEMP:
-                               data[0] |= IRQ_CTL_BIT_TMX; //Enable max temperature alert
-                               chip->max_temp_irq = true;
-                               RTINFO("Enable min temperature alert");
-                               break;
-                       case MINTEMP:
-                               data[0] |= IRQ_CTL_BIT_TMN; //Enable min temperature alert
-                               chip->min_temp_irq = true;  
-                               RTINFO("Enable max temperature alert");
-                               break;
-                       case MAXVOLT:
-                               data[0] |= IRQ_CTL_BIT_VMX; //Enable max voltage alert
-                               chip->max_volt_irq = true;
-                               RTINFO("Enable max voltage alert");
-                               break;
-                       case MINVOLT1:
-                               data[0] |= IRQ_CTL_BIT_VMN1; //Enable min1 voltage alert        
-                               chip->min_volt1_irq = true;
-                               RTINFO("Enable min1 voltage alert");
-                               break;
-                       case MINVOLT2:
-                               data[0] |= IRQ_CTL_BIT_VMN2; //Enable min2 voltage alert
-                               chip->min_volt2_irq = true;
-                               RTINFO("Enable min2 voltage alert");
-                               break;
-                       default:
-                               break;
-               }
-       }else{
-               switch(type){
-                       case MAXTEMP:
-                               data[0] = data[0] &~ IRQ_CTL_BIT_TMX; //Disable max temperature alert
-                               chip->max_temp_irq = false;
-                               RTINFO("Disable min temperature alert");
-                               break;
-                       case MINTEMP:
-                               data[0] = data[0] &~ IRQ_CTL_BIT_TMN; //Disable min temperature alert
-                               chip->min_temp_irq = false;
-                               RTINFO("Disable max temperature alert");
-                               break;
-                       case MAXVOLT:
-                               data[0] = data[0] &~ IRQ_CTL_BIT_VMX; //Disable max voltage alert
-                               chip->max_volt_irq = false;
-                               RTINFO("Disable max voltage alert");
-                               break;
-                       case MINVOLT1:
-                               data[0] = data[0] &~ IRQ_CTL_BIT_VMN1; //Disable min1 voltage alert     
-                               chip->min_volt1_irq = false;
-                               RTINFO("Disable min1 voltage alert");
-                               break;
-                       case MINVOLT2:
-                               data[0] = data[0] &~ IRQ_CTL_BIT_VMN2; //Disable min2 voltage alert
-                               chip->min_volt2_irq = false;
-                               RTINFO("Disable min2 voltage alert");
-                               break;
-                       default:
-                               break;
-               }
-       }
-  if (rt5025_write_reg(chip->client, RT5025_REG_IRQ_CTL, data, 1) < 0)
-               printk(KERN_ERR "%s: failed to write IRQ control\n", __func__);
-}      
-static void rt5025_alert_threshold_init(struct i2c_client *client)
-{
-  u8 data[1];
-
-  /* TALRT MAX threshold setting */
-  data[0] = irq_thres[MAXTEMP];
-  if (rt5025_write_reg(client, RT5025_REG_TALRT_MAXTH, data, 1) < 0)
-               printk(KERN_ERR "%s: failed to write TALRT MAX threshold\n", __func__); 
-  /* TALRT MIN threshold setting */
-  data[0] = irq_thres[MINTEMP];
-  if (rt5025_write_reg(client, RT5025_REG_TALRT_MINTH, data, 1) < 0)
-               printk(KERN_ERR "%s: failed to write TALRT MIN threshold\n", __func__); 
-  /* VALRT MAX threshold setting */
-  data[0] = irq_thres[MAXVOLT];
-  if (rt5025_write_reg(client, RT5025_REG_VALRT_MAXTH, data, 1) < 0)
-               printk(KERN_ERR "%s: failed to write VALRT MAX threshold\n", __func__); 
-  /* VALRT MIN1 threshold setting */
-  data[0] = irq_thres[MINVOLT1];
-  if (rt5025_write_reg(client, RT5025_REG_VALRT_MIN1TH, data, 1) < 0)
-               printk(KERN_ERR "%s: failed to write VALRT MIN1 threshold\n", __func__);        
-  /* VALRT MIN2 threshold setting */
-  data[0] = irq_thres[MINVOLT2];
-  if (rt5025_write_reg(client, RT5025_REG_VALRT_MIN2TH, data, 1) < 0)
-               printk(KERN_ERR "%s: failed to write VALRT MIN2 threshold\n", __func__);        
-}
-
-static void rt5025_alert_init(struct i2c_client *client)
-{
-  /* Set RT5025 gauge alert configuration */
-  rt5025_alert_threshold_init(client);
-       /* Enable gauge alert function */
-       rt5025_alert_setting(MAXTEMP,true);
-       rt5025_alert_setting(MINTEMP,true);
-       rt5025_alert_setting(MAXVOLT,true);
-       rt5025_alert_setting(MINVOLT1,true);
-       rt5025_alert_setting(MINVOLT2,true);    
-}
-
-void rt5025_irq_handler(void)
-{
-  rt5025_get_irq_flag(chip->client);
-
-  if ((chip->irq_flag) & IRQ_FLG_BIT_TMX){     
-               printk(KERN_INFO "[RT5025]: Min temperature IRQ received\n");
-               rt5025_alert_setting(MAXTEMP,false);
-               chip->max_temp_irq = false;
-       }
-  if ((chip->irq_flag) & IRQ_FLG_BIT_TMN){
-               printk(KERN_INFO "[RT5025]: Max temperature IRQ received\n");
-               rt5025_alert_setting(MINTEMP,false);
-               chip->min_temp_irq = false; 
-       }
-  if ((chip->irq_flag) & IRQ_FLG_BIT_VMX){
-               printk(KERN_INFO "[RT5025]: Max voltage IRQ received\n");
-               rt5025_alert_setting(MAXVOLT,false);
-               chip->max_volt_irq = false;
-       }
-  if ((chip->irq_flag) & IRQ_FLG_BIT_VMN1){
-               printk(KERN_INFO "[RT5025]: Min voltage1 IRQ received\n");
-               rt5025_alert_setting(MINVOLT1,false);
-               chip->min_volt1_irq = false;
-       }
-  if ((chip->irq_flag) & IRQ_FLG_BIT_VMN2){
-               printk(KERN_INFO "[RT5025]: Min voltage2 IRQ received\n");
-               rt5025_alert_setting(MINVOLT2,false);
-               chip->min_volt2_irq = false;
-       }
-       
-       wake_lock(&chip->monitor_wake_lock);
-       schedule_delayed_work(&chip->monitor_work, 0);
-}
-
-static void rt5025_update(struct i2c_client *client)
-{
-  /* Update voltage */
-  rt5025_get_vcell(client);
-  /* Update current */
-  rt5025_get_current(client);
-  /* Update external temperature */
-  rt5025_get_external_temp(client);
-  /* Read timer */
-  rt5025_get_timer(client);
-  /* Update chg cc */
-  rt5025_get_chg_cc(client);
-  /* Update dchg cc */
-  rt5025_get_dchg_cc(client);
-  /* Update SOC */
-  rt5025_get_soc(client);
-
-  if ((chip->max_temp_irq == false) &&
-                (((irq_thres[MAXTEMP] * IRQ_THRES_UNIT) / 100 - chip->ain_volt) > irq_thres[TEMP_RLS])){
-               rt5025_alert_setting(MAXTEMP,true);
-       }else if ((chip->min_temp_irq == false) &&
-                                         ((chip->ain_volt - (irq_thres[MINTEMP] * IRQ_THRES_UNIT) / 100) > irq_thres[TEMP_RLS])){
-               rt5025_alert_setting(MINTEMP,true);
-       }else if ((chip->max_volt_irq == false) &&
-                                       ((((irq_thres[MAXVOLT] * IRQ_THRES_UNIT) / 100) - chip->vcell) > irq_thres[VOLT_RLS])){
-               rt5025_alert_setting(MAXVOLT,true);
-       }else if ((chip->min_volt1_irq == false) &&
-                                       ((chip->vcell - ((irq_thres[MINVOLT1] * IRQ_THRES_UNIT) / 100)) > irq_thres[VOLT_RLS])){
-               rt5025_alert_setting(MINVOLT1,true);                            
-       }else if ((chip->min_volt2_irq == false) &&
-                                       ((chip->vcell - ((irq_thres[MINVOLT2] * IRQ_THRES_UNIT) / 100)) > irq_thres[VOLT_RLS])){
-               rt5025_alert_setting(MINVOLT2,true);                                            
-       }
-}
-
-static void rt5025_update_work(struct work_struct *work)
-{
-       unsigned long flags;
-       
-  rt5025_update(chip->client);
-
-  /* Update data to framework */
-  power_supply_changed(&chip->battery);
-  
-       /* prevent suspend before starting the alarm */
-       local_irq_save(flags);
-       chip->last_poll = alarm_get_elapsed_realtime();
-       rt5025_program_alarm(NORMAL_POLL);
-       local_irq_restore(flags);
-
-       wake_unlock(&chip->monitor_wake_lock);
-}
-
-static enum power_supply_property rt5025_battery_props[] = {
-  POWER_SUPPLY_PROP_STATUS,
-  POWER_SUPPLY_PROP_HEALTH,
-  POWER_SUPPLY_PROP_PRESENT,
-  POWER_SUPPLY_PROP_TEMP,
-  POWER_SUPPLY_PROP_ONLINE,
-  POWER_SUPPLY_PROP_VOLTAGE_NOW,
-  POWER_SUPPLY_PROP_CURRENT_NOW,
-  POWER_SUPPLY_PROP_CAPACITY,
-  POWER_SUPPLY_PROP_TECHNOLOGY,
-};
-
-void rt5025_gauge_suspend(void)
-{
-       rt5025_channel_cc(false);
-       cancel_delayed_work(&chip->monitor_work);
-
-  RTINFO("\n");
-}
-
-void rt5025_gauge_resume(void)
-{
-       rt5025_channel_cc(true);
-       wake_lock(&chip->monitor_wake_lock);
-       schedule_delayed_work(&chip->monitor_work, 0);
-  RTINFO("\n");
-}
-
-void rt5025_gauge_remove(void)
-{
-       chip->info->event_callback = NULL;
-       power_supply_unregister(&chip->battery);
-       cancel_delayed_work(&chip->monitor_work);
-       wake_lock_destroy(&chip->monitor_wake_lock);
-       kfree(chip);
-}
-
-int rt5025_gauge_init(struct rt5025_power_info *info)
-{
-       int ret;
-  chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-  if (!chip)
-    return -ENOMEM;
-
-  chip->client = info->i2c;
-  chip->fcc = info->fcc;
-  chip->info = info;  
-  // JY add
-  chip->soc_init = false;
-  chip->rm = chip->fcc/2;
-  chip->rm_old = chip->rm;
-  // ------------
-  chip->battery.name = "rt5025-battery";
-  chip->battery.type = POWER_SUPPLY_TYPE_BATTERY;
-  chip->battery.get_property = rt5025_get_property;
-  chip->battery.properties = rt5025_battery_props;
-  chip->battery.num_properties = ARRAY_SIZE(rt5025_battery_props);
-
-  ret = power_supply_register(info->dev, &chip->battery);
-  if (ret) {
-    printk(KERN_ERR "[RT5025] power supply register failed\n");
-               goto err_wake_lock;
-  }
-
-  chip->last_poll = alarm_get_elapsed_realtime();
-       alarm_init(&chip->wakeup_alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
-               rt5025_gauge_alarm);
-
-       INIT_DELAYED_WORK(&chip->monitor_work, rt5025_update_work);
-       
-       wake_lock_init(&chip->monitor_wake_lock, WAKE_LOCK_SUSPEND,
-                       "rt-battery-monitor");
-  /* enable channel */
-  rt5025_register_init(info->i2c);
-  rt5025_gauge_init_soc(info->i2c);
-
-       /* enable gauge IRQ */
-  rt5025_alert_init(info->i2c);
-
-       /* register callback functions */
-       chip->cb.rt5025_gauge_irq_handler = rt5025_irq_handler;
-       chip->cb.rt5025_gauge_set_status = rt5025_set_status;
-       chip->cb.rt5025_gauge_suspend = rt5025_gauge_suspend;
-       chip->cb.rt5025_gauge_resume = rt5025_gauge_resume;
-       chip->cb.rt5025_gauge_remove = rt5025_gauge_remove;
-       info->event_callback=&chip->cb;
-
-       //rt_register_gauge_callbacks(info->i2c, &chip->cb);
-       
-       wake_lock(&chip->monitor_wake_lock);
-       schedule_delayed_work(&chip->monitor_work, msecs_to_jiffies(1000));
-
-  return 0;
-
-err_wake_lock:
-       wake_lock_destroy(&chip->monitor_wake_lock);
-       kfree(chip);
-
-       return ret;
-}
index b99a79d32fc7d920e022aa85ceade5725dd862e5..037be178ecca8a471a1a33c3b4bc840bc75f3815 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/workqueue.h>
 #include <linux/mfd/rt5025.h>
 #include <linux/power/rt5025-power.h>
-#include <linux/power/rt5025-gauge.h>
 #include <linux/delay.h>
 
 
@@ -34,6 +33,7 @@ static char *rt5025_supply_list[] = {
        "rt5025-battery",
 };
 
+
 #if 0
 static int rt5025_set_charging_current_switch (struct i2c_client *i2c, int onoff)
 {
@@ -62,6 +62,7 @@ static int rt5025_set_charging_current(struct i2c_client *i2c, int cur_value)
        u8 data = 0;
 
        //ICC Setting
+       #if 0
        if (cur_value > 2000)
                data |= 0x0f<<3;
        else if (cur_value >= 500 && cur_value <= 2000)
@@ -69,7 +70,7 @@ static int rt5025_set_charging_current(struct i2c_client *i2c, int cur_value)
                data = (cur_value-500)/100;
                data<<=3;
        }
-       
+       #endif
 
        //AICR Setting
        if (cur_value > 1000)
@@ -79,7 +80,7 @@ static int rt5025_set_charging_current(struct i2c_client *i2c, int cur_value)
        else if (cur_value > 100 && cur_value >= 500)
                data |= 0x01<<1;
 
-       rt5025_assign_bits(i2c, RT5025_REG_CHGCTL4, RT5025_CHGCC_MASK, data);
+       rt5025_assign_bits(i2c, RT5025_REG_CHGCTL4, RT5025_CHGAICR_MASK, data);
        return ret;
 }
 
@@ -94,22 +95,52 @@ static int rt5025_chgstat_changed(struct rt5025_power_info *info, unsigned new_v
                        rt5025_set_charging_buck(info->i2c, 1);
                        #endif
                        info->chg_stat = 0x00;
+                       #if 1
+                       if (info->chip->battery_info)
+                       {
+                               if (info->chg_term == 0)
+                                       rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_DISCHARGING);
+                               else if (info->chg_term > 0)
+                               {
+                                       rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_FULL);
+                                       info->chg_term = 0;
+                               }
+                               
+                       }
+                       #else
                        if (info->event_callback)
                                info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_CHARGING);
+                       #endif
                        break;
                case 0x01:
                        //rt5025_set_charging_current_switch(info->i2c, 1);
                        info->chg_stat = 0x01;
+                       #if 1
+                       if (info->chip->battery_info)
+                       {
+                               rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_CHARGING);
+                               info->chg_term = 0;
+                       }
+                       #else
                        if (info->event_callback)
                                info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_CHARGING);
+                       #endif
                        break;
                case 0x02:
                        #if 0
                        rt5025_set_charging_current_switch(info->i2c, 0);
                        #endif
                        info->chg_stat = 0x02;
+                       #if 1
+                       if (info->chip->battery_info)
+                       {
+                               rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_FULL);
+                               info->chg_term = 0;
+                       }
+                       #else
                        if (info->event_callback)
                                info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_FULL);
+                       #endif
                        break;
                case 0x03:
                        #if 0
@@ -117,8 +148,21 @@ static int rt5025_chgstat_changed(struct rt5025_power_info *info, unsigned new_v
                        rt5025_set_charging_current_switch(info->i2c, 0);
                        #endif
                        info->chg_stat = 0x03;
+                       #if 1
+                       if (info->chip->battery_info)
+                       {
+                               if (info->chg_term == 0)
+                                       rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_CHARGING);
+                               else if (info->chg_term > 1)
+                               {
+                                       rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_FULL);
+                                       info->chg_term = 0;
+                               }
+                       }
+                       #else
                        if (info->event_callback)
                                info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_DISCHARGING);
+                       #endif
                        break;
                default:
                        break;
@@ -126,6 +170,7 @@ static int rt5025_chgstat_changed(struct rt5025_power_info *info, unsigned new_v
        return ret;
 }
 
+#if 0
 int rt5025_power_passirq_to_gauge(struct rt5025_power_info *info)
 {
        if (info->event_callback)
@@ -133,6 +178,7 @@ int rt5025_power_passirq_to_gauge(struct rt5025_power_info *info)
        return 0;
 }
 EXPORT_SYMBOL(rt5025_power_passirq_to_gauge);
+#endif
 
 int rt5025_power_charge_detect(struct rt5025_power_info *info)
 {
@@ -169,6 +215,7 @@ int rt5025_power_charge_detect(struct rt5025_power_info *info)
                schedule_delayed_work(&info->usb_detect_work, 0); //no delay
 
        new_chgval = (chgstatval&RT5025_CHGSTAT_MASK)>>RT5025_CHGSTAT_SHIFT;
+       
        if (new_acval || new_usbval)
        {
                if (old_chgval != new_chgval)
@@ -183,8 +230,15 @@ int rt5025_power_charge_detect(struct rt5025_power_info *info)
                rt5025_set_charging_current_switch(info->i2c, 0);
                #endif
                info->chg_stat = RT5025_CHGSTAT_UNKNOWN;
+               if (info->chip->jeita_info)
+                       rt5025_notify_charging_cable(info->chip->jeita_info, JEITA_NO_CHARGE);
+               #if 1
+               if (info->chip->battery_info)
+                       rt5025_gauge_set_status(info->chip->battery_info, POWER_SUPPLY_STATUS_NOT_CHARGING);
+               #else
                if (info->event_callback)
                        info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_NOT_CHARGING);
+               #endif
        }
 
        return ret;
@@ -212,8 +266,10 @@ static int rt5025_adap_get_props(struct power_supply *psy,
        return 0;
 }
 
+
 extern int dwc_vbus_status(void);
 
+
 static void usb_detect_work_func(struct work_struct *work)
 {
        struct delayed_work *delayed_work = (struct delayed_work *)container_of(work, struct delayed_work, work);
@@ -225,6 +281,7 @@ static void usb_detect_work_func(struct work_struct *work)
        if (pi->ac_online)
        {
                rt5025_set_charging_current(pi->i2c, 1000);
+               rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_AC_ADAPTER);
                pi->usb_cnt = 0;
        }
        else if (pi->usb_online)
@@ -234,11 +291,13 @@ static void usb_detect_work_func(struct work_struct *work)
                {
                        case 2: // USB Wall charger
                                rt5025_set_charging_current(pi->i2c, 1000);
+                               rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_USB_TA);
                                pr_info("rt5025: detect usb wall charger\n");
                                break;
                        case 1: //normal USB
                        default:
                                rt5025_set_charging_current(pi->i2c, 500);
+                               rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_NORMAL_USB);
                                pr_info("rt5025: detect normal usb\n");
                                break;
                }
@@ -249,6 +308,7 @@ static void usb_detect_work_func(struct work_struct *work)
        {
                //default to prevent over current charging
                rt5025_set_charging_current(pi->i2c, 500);
+               rt5025_notify_charging_cable(pi->chip->jeita_info, JEITA_NO_CHARGE);
                //reset usb_cnt;
                pi->usb_cnt = 0;
        }
@@ -259,13 +319,14 @@ static void usb_detect_work_func(struct work_struct *work)
 
 static int __devinit rt5025_init_charger(struct rt5025_power_info *info, struct rt5025_power_data* pd)
 {
-       RTINFO("++\n");
        info->ac_online = 0;
        info->usb_online =0;
        //init charger buckck & charger current en to disable stat
        info->chg_stat = RT5025_CHGSTAT_UNKNOWN;
+       #if 0
        if (info->event_callback)
                info->event_callback->rt5025_gauge_set_status(POWER_SUPPLY_STATUS_DISCHARGING);
+       #endif
        rt5025_set_bits(info->i2c, RT5025_REG_CHGCTL4, RT5025_CHGRST_MASK);
        udelay(200);
        //init register setting
@@ -278,7 +339,6 @@ static int __devinit rt5025_init_charger(struct rt5025_power_info *info, struct
        
        rt5025_power_charge_detect(info);
 
-       RTINFO("--\n");
        return 0;
 }
 
@@ -288,25 +348,26 @@ static int __devinit rt5025_power_probe(struct platform_device *pdev)
        struct rt5025_platform_data *pdata = chip->dev->platform_data;
        struct rt5025_power_info *pi;
        int ret = 0;
-       printk("%s,line=%d\n", __func__,__LINE__);      
-
+       
        pi = kzalloc(sizeof(*pi), GFP_KERNEL);
        if (!pi)
                return -ENOMEM;
 
        pi->i2c = chip->i2c;
        pi->dev = &pdev->dev;
-       pi->fcc = pdata->power_data->fcc;
+       pi->chip = chip;
        mutex_init(&pi->var_lock);
        INIT_DELAYED_WORK(&pi->usb_detect_work, usb_detect_work_func);
 
+       #if 0
        ret = rt5025_gauge_init(pi);
        if (ret)
                goto out;
+       #endif
 
        platform_set_drvdata(pdev, pi);
 
-       pi->ac.name = "rt5025-ac";
+       pi->ac.name = "rt5025-dc";
        pi->ac.type = POWER_SUPPLY_TYPE_MAINS;
        pi->ac.supplied_to = rt5025_supply_list;
        pi->ac.properties = rt5025_adap_props;
@@ -340,18 +401,23 @@ out:
 
 static int rt5025_power_suspend(struct platform_device *pdev, pm_message_t state)
 {
+       #if 0
        struct rt5025_power_info *pi = platform_get_drvdata(pdev);
 
        if (pi->event_callback)
                pi->event_callback->rt5025_gauge_suspend();
+       #endif
        return 0;
 }
 
 static int rt5025_power_resume(struct platform_device *pdev)
 {
+       #if 0
        struct rt5025_power_info *pi = platform_get_drvdata(pdev);
+
        if (pi->event_callback)
                pi->event_callback->rt5025_gauge_resume();
+       #endif
        return 0;
 }
 
@@ -360,8 +426,10 @@ static int __devexit rt5025_power_remove(struct platform_device *pdev)
        struct rt5025_power_info *pi = platform_get_drvdata(pdev);
        struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
 
+       #if 0
        if (pi->event_callback)
                pi->event_callback->rt5025_gauge_remove();
+       #endif
        power_supply_unregister(&pi->usb);
        power_supply_unregister(&pi->ac);
        chip->power_info = NULL;
diff --git a/drivers/power/rt5025-swjeita.c b/drivers/power/rt5025-swjeita.c
new file mode 100755 (executable)
index 0000000..5df1a36
--- /dev/null
@@ -0,0 +1,397 @@
+/* drivers/power/rt5025-swjeita.c
+ * swjeita Driver for Richtek RT5025 PMIC
+ * Multi function device - multi functional baseband PMIC swjeita part
+ *
+ * Copyright (C) 2013
+ * Author: CY Huang <cy_huang@richtek.com>
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <linux/mfd/rt5025.h>
+#include <linux/power/rt5025-swjeita.h>
+
+#define TEMP_TOLERANCE 10  // 'c*10 gap for tolerance
+
+static int rt5025_set_charging_cc_switch (struct i2c_client *i2c, int onoff)
+{
+       int ret;
+       RTINFO("onoff = %d\n", onoff);
+       if (onoff)
+               ret = rt5025_set_bits(i2c, RT5025_REG_CHGCTL7, RT5025_CHGCCEN_MASK);
+       else
+               ret = rt5025_clr_bits(i2c, RT5025_REG_CHGCTL7, RT5025_CHGCCEN_MASK);
+       return ret;
+}
+
+static int rt5025_set_charging_cc(struct i2c_client *i2c, int cur_value)
+{
+       int ret;
+       u8 data;
+
+       RTINFO("current value = %d\n", cur_value);
+       if (cur_value < 500)
+               data = 0;
+       else if (cur_value > 2000)
+               data = 0xf<<RT5025_CHGICC_SHIFT;
+       else
+               data = ((cur_value-500)/100)<<RT5025_CHGICC_SHIFT;
+
+       ret = rt5025_assign_bits(i2c, RT5025_REG_CHGCTL4, RT5025_CHGICC_MASK, data);
+
+       if (cur_value == 0)
+               rt5025_set_charging_cc_switch(i2c, 0);
+       else
+               rt5025_set_charging_cc_switch(i2c, 1);
+
+       return ret;
+}
+
+static int rt5025_set_charging_cv(struct i2c_client *i2c, int voltage)
+{
+       int ret;
+       u8 data;
+
+       RTINFO("voltage = %d\n", voltage);
+       if (voltage < 3500)
+               data = 0;
+       else if (voltage > 4440)
+               data = 0x2f<<RT5025_CHGCV_SHIFT;
+       else
+               data = ((voltage-3500)/20)<<RT5025_CHGCV_SHIFT;
+
+       ret = rt5025_assign_bits(i2c, RT5025_REG_CHGCTL3, RT5025_CHGCV_MASK, data);
+       return ret;
+}
+
+static int rt5025_sel_external_temp_index(struct rt5025_swjeita_info *swji)
+{
+       int temp = swji->cur_temp;
+       int sect_index;
+
+       RTINFO("\n");
+       if (temp < swji->temp[0])
+               sect_index = 0;
+       else if (temp >= swji->temp[0] && temp < swji->temp[1])
+               sect_index = 1;
+       else if (temp >= swji->temp[1] && temp < swji->temp[2])
+               sect_index = 2;
+       else if (temp >= swji->temp[2] && temp < swji->temp[3])
+               sect_index = 3;
+       else if (temp >= swji->temp[3])
+               sect_index = 4;
+
+       RTINFO("sect_index = %d\n", sect_index);
+       return sect_index;
+}
+
+static int rt5025_get_external_temp_index(struct rt5025_swjeita_info *swji)
+{
+       u8 data[2];
+       long int temp;
+       int sect_index;
+       
+       RTINFO("\n");
+       if (rt5025_reg_block_read(swji->i2c, RT5025_REG_AINH, 2, data) < 0)
+               pr_err("%s: failed to read ext_temp register\n", __func__);
+
+       temp = (data[0]*256+data[1])*61/100;
+       temp = (temp * (-91738) +81521000)/100000;
+
+       swji->cur_temp = temp;
+
+       RTINFO("cur_section = %d, cur_temp = %d\n", swji->cur_section, swji->cur_temp);
+
+       switch (swji->cur_section)
+       {
+               case 0:
+                       if (temp < swji->temp[0]+TEMP_TOLERANCE)
+                               sect_index = rt5025_sel_external_temp_index(swji);
+                       else
+                               sect_index = swji->cur_section;
+                       break;
+               case 1:
+                       if (temp <= swji->temp[0]-TEMP_TOLERANCE || temp >= swji->temp[1]+TEMP_TOLERANCE)
+                               sect_index = rt5025_sel_external_temp_index(swji);
+                       else
+                               sect_index = swji->cur_section;
+                       break;
+               case 2:
+                       if (temp <= swji->temp[1]-TEMP_TOLERANCE || temp >= swji->temp[2]+TEMP_TOLERANCE)
+                               sect_index = rt5025_sel_external_temp_index(swji);
+                       else
+                               sect_index = swji->cur_section;
+                       break;
+               case 3:
+                       if (temp <= swji->temp[2]-TEMP_TOLERANCE || temp >= swji->temp[3]+TEMP_TOLERANCE)
+                               sect_index = rt5025_sel_external_temp_index(swji);
+                       else
+                               sect_index = swji->cur_section;
+                       break;
+               case 4:
+                       if (temp <= swji->temp[3]-TEMP_TOLERANCE)
+                               sect_index = rt5025_sel_external_temp_index(swji);
+                       else
+                               sect_index = swji->cur_section;
+                       break;
+               default:
+                               sect_index = swji->cur_section;
+                       break;
+       }
+       RTINFO("sect_index = %d\n", sect_index);
+       return sect_index;
+}
+
+static inline int rt5025_set_ainadc_onoff(struct rt5025_swjeita_info *swji, int enable)
+{
+       int ret;
+
+       RTINFO("enable = %d\n", enable);
+       if (enable)
+               ret = rt5025_set_bits(swji->i2c, RT5025_REG_CHANNELL, RT5025_AINEN_MASK);
+       else
+               ret = rt5025_clr_bits(swji->i2c, RT5025_REG_CHANNELL, RT5025_AINEN_MASK);
+
+       return ret;
+}
+
+static int rt5025_set_exttemp_alert(struct rt5025_swjeita_info *swji, int index)
+{
+       int ret = 0;
+
+       RTINFO("index = %d\n", index);
+
+       switch (index)
+       {
+               case 0:
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[0]);
+                       break;
+               case 1:
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[0]);
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[1]);
+                       break;
+               case 2:
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[1]);
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[2]);
+                       break;
+               case 3:
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[2]);
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[3]);
+                       break;
+               case 4:
+                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[3]);
+                       break;
+       }
+
+       return ret;
+}
+
+static int rt5025_exttemp_alert_switch(struct rt5025_swjeita_info *swji, int onoff)
+{
+       if (!onoff)
+       {
+               rt5025_clr_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
+               rt5025_clr_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
+       }
+       else
+       {
+               switch (swji->cur_section)
+               {
+                       case 0:
+                               rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
+                               break;
+                       case 1:
+                               rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
+                               rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
+                               break;
+                       case 2:
+                               rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
+                               rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
+                               break;
+                       case 3:
+                               rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
+                               rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
+                               break;
+                       case 4:
+                               rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
+                               break;
+               }
+       }
+
+       RTINFO("index=%d, onoff=%d\n", swji->cur_section, onoff);
+       return 0;               
+}
+
+int rt5025_notify_charging_cable(struct rt5025_swjeita_info *swji, int cable_type)
+{
+       int sect_index;
+       int ret = 0;
+
+       RTINFO("cable_type = %d\n", cable_type);
+
+       rt5025_exttemp_alert_switch(swji, 0);
+
+       sect_index = rt5025_get_external_temp_index(swji);
+       if (swji->cur_section != sect_index || swji->init_once == 0)
+       {
+               rt5025_set_exttemp_alert(swji, sect_index);
+               swji->cur_section = sect_index;
+               swji->init_once = 1;
+       }
+
+       switch (cable_type)
+       {
+               case JEITA_NORMAL_USB:
+                       rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]);
+                       rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
+                       break;
+               case JEITA_USB_TA:
+                       rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]);
+                       rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
+                       break;
+               case JEITA_AC_ADAPTER:
+                       rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]);
+                       rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
+                       break;
+               case JEITA_NO_CHARGE:
+                       rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]);
+                       rt5025_set_charging_cv(swji->i2c, swji->temp_cv[cable_type][swji->cur_section]);
+                       break;
+       }
+       swji->cur_cable = cable_type;
+
+       rt5025_exttemp_alert_switch(swji, 1);
+
+       return ret;
+}
+EXPORT_SYMBOL(rt5025_notify_charging_cable);
+
+int rt5025_swjeita_irq_handler(struct rt5025_swjeita_info *swji, unsigned char event)
+{
+       int ret = 0;
+       RTINFO("event = 0x%02x\n", event);
+
+       if (event&(RT5025_TMXEN_MASK|RT5025_TMNEN_MASK))
+               rt5025_notify_charging_cable(swji, swji->cur_cable);
+
+       return ret;
+}
+EXPORT_SYMBOL(rt5025_swjeita_irq_handler);
+
+static int __devinit rt5025_swjeita_probe(struct platform_device *pdev)
+{
+       struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
+       struct rt5025_platform_data *pdata = chip->dev->platform_data; 
+       struct rt5025_swjeita_info *swji;
+       int ret = 0;
+
+       swji = kzalloc(sizeof(*swji), GFP_KERNEL);
+       if (!swji)
+               return -ENOMEM;
+
+       #if 0 // for debug pdata->jeita_data
+       for (ret=0; ret<4; ret++)
+               RTINFO("jeita temp value %d\n", pdata->jeita_data->temp[ret]);
+       for (ret=0; ret<4; ret++)
+       {
+               RTINFO("jeita temp_cc value %d, %d, %d, %d, %d\n", pdata->jeita_data->temp_cc[ret][0], \
+               pdata->jeita_data->temp_cc[ret][1], pdata->jeita_data->temp_cc[ret][2], \
+               pdata->jeita_data->temp_cc[ret][3], pdata->jeita_data->temp_cc[ret][4]);
+       }
+       for (ret=0; ret<4; ret++)
+       {
+               RTINFO("jeita temp_cv value %d, %d, %d, %d, %d\n", pdata->jeita_data->temp_cv[ret][0], \
+               pdata->jeita_data->temp_cv[ret][1], pdata->jeita_data->temp_cv[ret][2], \
+               pdata->jeita_data->temp_cv[ret][3], pdata->jeita_data->temp_cv[ret][4]);
+       }
+       for (ret=0; ret<4; ret++)
+       {
+               RTINFO("temp_scalar[%d] = 0x%02x\n", ret, pdata->jeita_data->temp_scalar[ret]);
+       }
+       ret = 0;
+       #endif /* #if 0 */
+
+       swji->i2c = chip->i2c;
+       swji->chip = chip;
+       swji->cur_section = 2; //initial as the normal temperature
+       swji->cur_cable = JEITA_NO_CHARGE;
+       swji->temp = pdata->jeita_data->temp;
+       swji->temp_scalar = pdata->jeita_data->temp_scalar;
+       swji->temp_cc = pdata->jeita_data->temp_cc;
+       swji->temp_cv = pdata->jeita_data->temp_cv;
+       platform_set_drvdata(pdev, swji);
+
+       rt5025_set_ainadc_onoff(swji, 1);
+       mdelay(100);
+       rt5025_notify_charging_cable(swji, swji->cur_cable);
+
+       chip->jeita_info = swji;
+       RTINFO("rt5025-swjeita driver is successfully loaded\n");
+       return ret;
+}
+
+static int __devexit rt5025_swjeita_remove(struct platform_device *pdev)
+{
+       struct rt5025_swjeita_info *swji = platform_get_drvdata(pdev);
+
+       swji->chip->jeita_info = NULL;
+       kfree(swji);
+       return 0;
+}
+
+static int rt5025_swjeita_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct rt5025_swjeita_info *swji = platform_get_drvdata(pdev);
+       
+       swji->suspend = 1;
+       return 0;
+}
+
+static int rt5025_swjeita_resume(struct platform_device *pdev)
+{
+       struct rt5025_swjeita_info *swji = platform_get_drvdata(pdev);
+
+       swji->suspend = 0;
+       return 0;
+}
+
+static struct platform_driver rt5025_swjeita_driver = 
+{
+       .driver = {
+               .name = RT5025_DEVICE_NAME "-swjeita",
+               .owner = THIS_MODULE,
+       },
+       .probe = rt5025_swjeita_probe,
+       .remove = __devexit_p(rt5025_swjeita_remove),
+       .suspend = rt5025_swjeita_suspend,
+       .resume = rt5025_swjeita_resume,
+};
+
+static int __init rt5025_swjeita_init(void)
+{
+       return platform_driver_register(&rt5025_swjeita_driver);
+}
+module_init(rt5025_swjeita_init);
+
+static void __exit rt5025_swjeita_exit(void)
+{
+       platform_driver_unregister(&rt5025_swjeita_driver);
+}
+module_exit(rt5025_swjeita_exit);
+
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
+MODULE_DESCRIPTION("Swjeita driver for RT5025");
+MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-swjeita");
index e9192a6183559a16a6997755c3f7c988b84b5615..98b0d1b98c5ec4f8f49734fe3a0fe670023741a2 100755 (executable)
@@ -35,6 +35,8 @@ struct rt5025_regulator_info {
        int     vol_mask;
        int     enable_bit;
        int     enable_reg;
+       int     mode_bit;
+       int     mode_reg;
 };
 
 //for DCDC1
@@ -121,10 +123,10 @@ static int rt5025_list_voltage(struct regulator_dev *rdev, unsigned index)
 
        return (index>=info->vol_output_size)? \
                 -EINVAL: \
-               info->vol_output_list[index ];
+               info->vol_output_list[index];
 }
 
-//#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38))
+#if 0 //(LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38))
 static int rt5025_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
 {
        struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
@@ -147,7 +149,7 @@ static int rt5025_get_voltage_sel(struct regulator_dev *rdev)
                return ret;
        return (ret & info->vol_mask)  >> info->vol_shift;
 }
-//#else
+#else
 static int rt5025_find_voltage(struct regulator_dev *rdev,
                               int min_uV, int max_uV)
 {
@@ -169,6 +171,7 @@ static int rt5025_set_voltage(struct regulator_dev *rdev,
 {
        struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
        unsigned char data;
+
        if (check_range(info, min_uV, max_uV)) {
                dev_err(info->chip->dev, "invalid voltage range (%d, %d) uV\n",
                        min_uV, max_uV);
@@ -176,20 +179,22 @@ static int rt5025_set_voltage(struct regulator_dev *rdev,
        }
        data = rt5025_find_voltage(rdev,min_uV,max_uV);
        data <<= info->vol_shift;
+
        return rt5025_assign_bits(info->i2c, info->vol_reg, info->vol_mask, data);
 }
 
 
 static int rt5025_get_voltage(struct regulator_dev *rdev)
 {
+       struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
        int ret;
-       ret = rt5025_get_voltage_sel(rdev);
+       ret = rt5025_reg_read(info->i2c, info->vol_reg);
        if (ret < 0)
                return ret;
-       return rt5025_list_voltage(rdev, ret );
-
+       ret =  (ret & info->vol_mask)  >> info->vol_shift;
+       return rt5025_list_voltage(rdev, ret);
 }
-//#endif /* LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38) */
+#endif /* LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38) */
 
 static int rt5025_enable(struct regulator_dev *rdev)
 {
@@ -218,102 +223,61 @@ static int rt5025_is_enabled(struct regulator_dev *rdev)
 
        return (ret & (info->enable_bit))?1:0;
 }
-static int rt5025_dcdc_get_mode(struct regulator_dev *rdev)
+
+static int rt5025_set_mode(struct regulator_dev *rdev, unsigned int mode)
 {
        struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
-       int buck = rdev_get_id(rdev) - 0;
        int ret;
-       uint8_t control;
-       
-       ret = rt5025_reg_read(info->i2c, 0x0c);
-        if (ret < 0) {
-                return ret;
-        }
-       if (buck ==0){
-       control =(ret & 0x80)>>7;
-       }
-       else if (buck ==1){
-       control =(ret & 0x40)>>6;
-       }
-       else if (buck ==2){
-       control =(ret & 0x20)>>5;
-       }
-       else{
-       return -1;
-       }
-       switch (control) {
-       case 0:
-               return REGULATOR_MODE_FAST;
-       case 1:
-               return REGULATOR_MODE_NORMAL;
-       default:
-               return -1;
+       if (!info->mode_bit)
+               ret = 0;
+       else
+       {
+               switch (mode)
+               {
+                       case REGULATOR_MODE_NORMAL:
+                               ret = rt5025_set_bits(info->i2c, info->mode_reg, info->mode_bit);
+                               break;
+                       case REGULATOR_MODE_FAST:
+                               ret = rt5025_clr_bits(info->i2c, info->mode_reg, info->mode_bit);
+                               break;
+                       default:
+                               ret = -EINVAL;
+                               break;
+               }
        }
-       
+       return ret;
 }
-static int rt5025_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
+
+static unsigned int rt5025_get_mode(struct regulator_dev *rdev)
 {
        struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
-       int buck = rdev_get_id(rdev) - 0;
-       int ret;
-       uint8_t control;
-       
-       ret = rt5025_reg_read(info->i2c, 0x0c);
-       if (buck ==0){
-       control =ret &(~ (1 <<7));
-       }
-       else if (buck ==1){
-       control =ret &(~ (1 <<6));
-       }
-       else if (buck ==2){
-       control =ret &(~ (1 <<5));
-       }
-       else{
-       return -1;
-       }
-       
-       switch(mode)
+       unsigned int mode;
+       int data;
+
+       if (!info->mode_bit)
+               mode = REGULATOR_MODE_NORMAL;
+       else
        {
-       case REGULATOR_MODE_FAST:
-               return  rt5025_reg_write(info->i2c, 0x0c,control);
-       case REGULATOR_MODE_NORMAL:
-                return rt5025_reg_write(info->i2c, 0x0c,(control | (1 <<(7-buck))));
-       default:
-               printk("error:pmu_rt5025 only powersave pwm & auto mode\n");
-               return -EINVAL;
+               data = rt5025_reg_read(info->i2c, info->mode_reg);
+               mode = (data & info->mode_bit)?REGULATOR_MODE_NORMAL:REGULATOR_MODE_FAST;
        }
-}
-static int rt5025_dcdc_set_voltage_time_sel(struct regulator_dev *rdev,   unsigned int old_selector,
-                                    unsigned int new_selector)
-{
-       int old_volt, new_volt;
-       
-       old_volt = rt5025_list_voltage(rdev, old_selector);
-       if (old_volt < 0)
-               return old_volt;
-       
-       new_volt = rt5025_list_voltage(rdev, new_selector);
-       if (new_volt < 0)
-               return new_volt;
-
-       return DIV_ROUND_UP(abs(old_volt - new_volt), 25000);
+       return mode;
 }
 
 static struct regulator_ops rt5025_regulator_ops = {
        .list_voltage           = rt5025_list_voltage,
-//#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38))
-//     .get_voltage_sel        = rt5025_get_voltage_sel,
-//     .set_voltage_sel        = rt5025_set_voltage_sel,
-//#else
+#if 0 //(LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38))
+       .get_voltage_sel        = rt5025_get_voltage_sel,
+       .set_voltage_sel        = rt5025_set_voltage_sel,
+#else
        .set_voltage            = rt5025_set_voltage,
        .get_voltage            = rt5025_get_voltage,
-//#endif /* LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38) */
+#endif /* LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38) */
        .enable                 = rt5025_enable,
        .disable                = rt5025_disable,
        .is_enabled             = rt5025_is_enabled,
-       .get_mode = rt5025_dcdc_get_mode,
-       .set_mode = rt5025_dcdc_set_mode,
-       .set_voltage_time_sel = rt5025_dcdc_set_voltage_time_sel,
+       .set_mode               = rt5025_set_mode,
+       .get_mode               = rt5025_get_mode,
 };
 
 #define RT5025_DCDCVOUT_LIST1 rt5025_vol_output_list1
@@ -358,6 +322,8 @@ static struct regulator_ops rt5025_regulator_ops = {
        .vol_mask       = RT5025_DCDCVOUT_MASK##_id,            \
        .enable_reg     = RT5025_DCDC_OUTPUT_EN,                \
        .enable_bit     = RT5025_DCDCEN_MASK##_id,              \
+       .mode_reg       = RT5025_REG_DCDCVRC,                   \
+       .mode_bit       = RT5025_DCDCMODE_MASK##_id             \
 }
 
 #define RT5025_LDO(_id, min, max)                              \
@@ -379,6 +345,8 @@ static struct regulator_ops rt5025_regulator_ops = {
        .vol_mask       = RT5025_LDOVOUT_MASK##_id,             \
        .enable_reg     = RT5025_LDO_OUTPUT_EN,                 \
        .enable_bit     = RT5025_LDOEN_MASK##_id,               \
+       .mode_reg       = RT5025_REG_LDOVRC,                    \
+       .mode_bit       = RT5025_LDOMODE_MASK##_id,             \
 }
 
 static struct rt5025_regulator_info rt5025_regulator_info[] = 
old mode 100755 (executable)
new mode 100644 (file)
index 96efd61..2355d8c
 #define RT5025_REG_CHGSTAT     0x01
 
 #define RT5025_REG_IRQEN1      0x30
+#define RT5025_REG_IRQSTATUS1  0x31
 #define RT5025_REG_IRQEN2      0x32
+#define RT5025_REG_IRQSTATUS2  0x33
 #define RT5025_REG_IRQEN3      0x34
+#define RT5025_REG_IRQSTATUS3  0x35
 #define RT5025_REG_IRQEN4      0x36
+#define RT5025_REG_IRQSTATUS4  0x37
 #define RT5025_REG_IRQEN5      0x38
+#define RT5025_REG_IRQSTATUS5  0x39
+
+#define RT5025_REG_GAUGEIRQFLG 0x51
+#define RT5025_FLG_TEMP                0x30
+#define RT5025_FLG_VOLT                0x07
 
 #endif /* #ifndef __LINUX_RT5025_IRQ_H */
old mode 100755 (executable)
new mode 100644 (file)
index e83c60d..d3b790b
@@ -14,6 +14,7 @@
 #define __LINUX_MFD_RT5025_H
 
 #include <linux/power_supply.h>
+#include <linux/android_alarm.h>
 
 #define RT5025_DEVICE_NAME "RT5025"
 
@@ -215,7 +216,6 @@ struct rt5025_power_data {
                }bitfield;
                unsigned char val;
        }CHGControl7;
-       u32 fcc;
 };
 
 struct rt5025_gpio_data {
@@ -337,6 +337,21 @@ struct rt5025_irq_data {
        }irq_enable5;
 };
 
+enum {
+       JEITA_NO_CHARGE,
+       JEITA_NORMAL_USB,
+       JEITA_USB_TA,
+       JEITA_AC_ADAPTER,
+       JEITA_CHARGER_MAX,
+};
+
+struct rt5025_jeita_data {
+       int* temp;
+       u8* temp_scalar;
+       int (*temp_cc)[5];
+       int (*temp_cv)[5];
+};
+
 #define CHG_EVENT_INACOVP      (0x80<<16)
 #define CHG_EVENT_INAC_PLUGIN  (0x40<<16)
 #define CHG_EVENT_INUSBOVP     (0x10<<16)
@@ -360,7 +375,9 @@ struct rt5025_irq_data {
 
 #define CHARGER_DETECT_MASK    (CHG_EVENT_INAC_PLUGIN | CHG_EVENT_INUSB_PLUGIN | \
                                 CHG_EVENT_CHSLPI_INAC | CHG_EVENT_CHSLPI_INUSB | \
-                                CHG_EVENT_CHBADI_INAC | CHG_EVENT_CHBADI_INUSB)
+                                CHG_EVENT_CHBADI_INAC | CHG_EVENT_CHBADI_INUSB | \
+                                CHG_EVENT_CHTERMI | CHG_EVENT_CHRCHGI)
 
 #define PWR_EVENT_OTIQ         (0x80<<8)
 #define PWR_EVENT_DCDC1LV      (0x40<<8)
@@ -374,7 +391,7 @@ struct rt5025_irq_data {
 #define PWR_EVENT_KPSHDN       (0x80<<0)
 #define PWR_EVNET_PWRONR       (0x40<<0)
 #define PWR_EVENT_PWRONF       (0x20<<0)
-#define        PWR_EVENT_RESETB        (0x10<<0)
+#define PWR_EVENT_RESETB       (0x10<<0)
 #define PWR_EVENT_GPIO2IE      (0x08<<0)
 #define PWR_EVENT_GPIO1IE      (0x04<<0)
 #define PWR_EVENT_GPIO0IE      (0x02<<0)
@@ -393,53 +410,209 @@ struct rt5025_event_callback {
        #endif
 };
 
+struct rt5025_platform_data {
+       struct regulator_init_data* regulator[RT5025_MAX_REGULATOR];
+       struct rt5025_power_data* power_data;
+       struct rt5025_gpio_data* gpio_data;
+       struct rt5025_misc_data* misc_data;
+       struct rt5025_irq_data* irq_data;
+       struct rt5025_jeita_data* jeita_data;
+       struct rt5025_event_callback *cb;
+       int (*pre_init)(struct rt5025_chip *rt5025_chip);
+       /** Called after subdevices are set up */
+       int (*post_init)(void);
+       int intr_pin;
+};
+
 struct rt5025_power_info {
        struct i2c_client       *i2c;
        struct device           *dev;
-       struct rt5025_gauge_callbacks *event_callback;
+       struct rt5025_chip      *chip;
+       //struct rt5025_gauge_callbacks *event_callback;
        struct power_supply     ac;
        struct power_supply     usb;
        struct mutex    var_lock;
        struct delayed_work usb_detect_work;
        int usb_cnt;
-       u32     fcc;
+       int chg_term;
        unsigned                ac_online:1;
        unsigned                usb_online:1;
        unsigned                chg_stat:3;
 };
 
+struct rt5025_swjeita_info {
+       struct i2c_client *i2c;
+       struct rt5025_chip *chip;
+       int *temp;
+       u8 *temp_scalar;
+       int (*temp_cc)[5];
+       int (*temp_cv)[5];
+       int cur_section;
+       int cur_cable;
+       int cur_temp;
+       int init_once;
+       int suspend;
+};
+
+struct rt5025_battery_info {
+       struct i2c_client *client;
+       struct rt5025_chip *chip;
+       //struct rt5025_gauge_callbacks cb;
+
+       struct power_supply     battery;
+       
+       struct delayed_work monitor_work;
+       struct wake_lock monitor_wake_lock;
+       struct wake_lock low_battery_wake_lock;
+//#if RT5025_TEST_WAKE_LOCK
+       struct wake_lock test_wake_lock;
+//#endif
+       struct alarm wakeup_alarm;
+       
+       bool temp_range_0_5;
+       bool temp_range_5_10;
+       bool temp_range_10_15;
+       bool temp_range_15_20;
+       bool temp_range_20_30;
+       bool temp_range_30_35;
+       bool temp_range_35_40;
+       bool temp_range_40_45;
+       bool temp_range_45_50;
+       
+       bool range_0_5_done;
+       bool range_5_10_done;
+       bool range_10_15_done;
+       bool range_15_20_done;
+       bool range_20_30_done;
+       bool range_30_35_done;
+       bool range_35_40_done;
+       bool range_40_45_done;
+       bool range_45_50_done;
+       
+       
+       
+       bool    suspend_poll;
+       ktime_t last_poll;
+//     ktime_t last_event;
+  struct timespec last_event;
+
+  u16 update_time;
+  
+  /* previous battery voltage */
+  u16 pre_vcell;
+  /* previous battery current */
+  s16 pre_curr;        
+  /* battery voltage */
+  u16 vcell;
+  /* battery current */
+  s16 curr;
+  /* battery current offset */
+  u16 curr_offset;
+  /* AIN voltage */
+  u16 ain_volt;
+  /* battery external temperature */
+  s16 ext_temp;
+  /* charge coulomb counter */
+  u32 chg_cc;
+  u32 chg_cc_unuse;
+  /* discharge coulomb counter */
+  u32 dchg_cc;
+  u32 dchg_cc_unuse;
+  /* battery capacity */
+  u16 soc;
+  u16 temp_soc;
+  u16 pre_soc;
+  
+  u16 time_interval;
+  u16 pre_gauge_timer;
+    
+  u8 online;
+  u8 status;
+  u8 internal_status;
+  u8 health;
+  u8 present;
+
+  /* IRQ flag */
+  u8 irq_flag;
+   
+  /* max voltage IRQ flag */
+  bool max_volt_irq;
+  /* min voltage1 IRQ flag */
+  bool min_volt1_irq;  
+  /* min voltage2 IRQ flag */
+  bool min_volt2_irq;
+  /* max temperature IRQ flag */
+  bool max_temp_irq;
+  /* min temperature IRQ flag */
+  bool min_temp_irq;
+
+  bool min_volt2_alert;
+
+       u8 temp_high_cnt;
+       u8 temp_low_cnt;
+       u8 temp_recover_cnt;
+       
+       bool init_cap;
+       bool avg_flag;
+       
+  /* remain capacity */
+  u32 rm;
+  /* SOC permille  */
+  u16 permille;
+  /* full capccity */
+  u16 fcc_aging;
+  u16 fcc;
+  u16  dc;
+  s16 tempcmp;
+  #if 0
+  u32 time_to_empty;
+  u32 time_to_full;
+  #endif
+  
+  bool edv_flag;
+  bool edv_detection;
+  u8 edv_cnt;
+  
+  bool tp_flag;
+  u8 tp_cnt;
+  
+  u8 cycle_cnt;
+  u32 acc_dchg_cap;
+
+  bool smooth_flag;
+  
+  u16 gauge_timer;
+  s16 curr_raw;
+
+  bool init_once;
+  bool device_suspend;
+  u8 test_temp;
+};
+
 struct rt5025_chip {
        struct i2c_client *i2c;
        struct workqueue_struct *wq;
        struct device *dev;
        struct rt5025_power_info *power_info;
+       struct rt5025_swjeita_info *jeita_info;
+       struct rt5025_battery_info *battery_info;
        int suspend;
        int irq;
        struct delayed_work delayed_work;
        struct mutex io_lock;
 };
 
-struct rt5025_platform_data {
-       struct regulator_init_data* regulator[RT5025_MAX_REGULATOR];
-       struct rt5025_power_data* power_data;
-       struct rt5025_gpio_data* gpio_data;
-       struct rt5025_misc_data* misc_data;
-       struct rt5025_irq_data* irq_data;
-       struct rt5025_event_callback *cb;
-       int (*pre_init)(struct rt5025_chip *rt5025_chip);
-       /** Called after subdevices are set up */
-       int (*post_init)(void);
-       int intr_pin;
-};
-
 #ifdef CONFIG_MFD_RT5025_MISC
 extern void rt5025_power_off(void);
 #endif /* CONFIG_MFD_RT5025_MISC */
 
 #ifdef CONFIG_POWER_RT5025
-extern int rt5025_gauge_init(struct rt5025_power_info *);
-extern int rt5025_power_passirq_to_gauge(struct rt5025_power_info *);
+extern void rt5025_gauge_set_status(struct rt5025_battery_info *, int);
+extern void rt5025_gauge_set_online(struct rt5025_battery_info *, bool);
+extern void rt5025_gauge_irq_handler(struct rt5025_battery_info *, u8);
 extern int rt5025_power_charge_detect(struct rt5025_power_info *);
+extern int rt5025_notify_charging_cable(struct rt5025_swjeita_info *, int);
+extern int rt5025_swjeita_irq_handler(struct rt5025_swjeita_info *, unsigned char);
 #endif /* CONFIG_POEWR_RT5025 */
 
 extern int rt5025_reg_block_read(struct i2c_client *, int, int, void *);
diff --git a/include/linux/power/rockchip-6200ma-bat.h b/include/linux/power/rockchip-6200ma-bat.h
new file mode 100755 (executable)
index 0000000..8cfc32a
--- /dev/null
@@ -0,0 +1,26 @@
+battery_graph_prop rt5025_battery_param1[] =
+{
+  {4190, 1000},
+  {4153, 980},
+  {4067, 890},
+  {3991, 800},
+  {3931, 710},
+  {3845, 580},
+  {3799, 490},
+  {3776, 400},
+  {3743, 240},
+  {3695, 140},
+  {3660, 70},
+  {3642, 50},
+  {3509, 20},
+  {3300, 0},   
+};
+
+battery_graph_prop rt5025_battery_param2[] =
+{
+  {450,30},
+  {250,  0},
+  {50,-90},
+  {50,  10},
+  {3400, 6900},
+};
diff --git a/include/linux/power/rt5025-battery.h b/include/linux/power/rt5025-battery.h
new file mode 100755 (executable)
index 0000000..cbb92ac
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ *  include/linux/power/rt5025-battery.h
+ *  Include header file for Richtek RT5025 battery Driver
+ *
+ *  Copyright (C) 2013 Richtek Electronics
+ *  cy_huang <cy_huang@richtek.com>
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_RT5025_BATTERY_H
+#define __LINUX_RT5025_BATTERY_H
+
+#define ROCKCHIP_BATTERY_6200MAH
+#undef ROCKCHIP_BATTERY_2100MAH
+
+#define RT5025_REG_IRQ_CTL             0x50
+#define RT5025_REG_IRQ_FLAG            0x51
+#define RT5025_REG_VALRT_MAXTH         0x53
+#define RT5025_REG_VALRT_MIN1TH        0x54
+#define RT5025_REG_VALRT_MIN2TH        0x55
+#define RT5025_REG_TALRT_MAXTH         0x56
+#define RT5025_REG_TALRT_MINTH         0x57
+#define RT5025_REG_VCELL_MSB           0x58
+#define RT5025_REG_VCELL_LSB           0x59
+#define RT5025_REG_INT_TEMPERATUE_MSB  0x5B
+#define RT5025_REG_INT_TEMPERATUE_LSB  0x5C
+#define RT5025_REG_EXT_TEMPERATUE_MSB  0x5E
+#define RT5025_REG_EXT_TEMPERATUE_LSB  0x5F
+#define RT5025_REG_TIMER               0x60
+#define RT5025_REG_CHANNEL_MSB         0x62
+#define RT5025_REG_CHANNEL_LSB         0x63
+#define RT5025_REG_CURRENT_MSB         0x76
+#define RT5025_REG_CURRENT_LSB         0x77
+#define RT5025_REG_QCHGH_MSB           0x78
+#define RT5025_REG_QCHGH_LSB           0x79
+#define RT5025_REG_QCHGL_MSB           0x7A
+#define RT5025_REG_QCHGL_LSB           0x7B
+#define RT5025_REG_QDCHGH_MSB          0x7C
+#define RT5025_REG_QDCHGH_LSB          0x7D
+#define RT5025_REG_QDCHGL_MSB          0x7E
+#define RT5025_REG_QDCHGL_LSB          0x7F
+
+#define IRQ_CTL_BIT_TMX  (1 << 5)
+#define IRQ_CTL_BIT_TMN  (1 << 4)
+#define IRQ_CTL_BIT_VMX  (1 << 2)
+#define IRQ_CTL_BIT_VMN1 (1 << 1)
+#define IRQ_CTL_BIT_VMN2 (1 << 0)
+
+#define IRQ_FLG_BIT_TMX  (1 << 5)
+#define IRQ_FLG_BIT_TMN  (1 << 4)
+#define IRQ_FLG_BIT_VMX  (1 << 2)
+#define IRQ_FLG_BIT_VMN1 (1 << 1)
+#define IRQ_FLG_BIT_VMN2 (1 << 0)
+
+#define CHANNEL_H_BIT_CLRQDCHG  (1 << 7)
+#define CHANNEL_H_BIT_CLRQCHG   (1 << 6)
+
+#define CHANNEL_L_BIT_CADC_EN   (1 << 7)
+#define CHANNEL_L_BIT_INTEMPCH  (1 << 6)
+#define CHANNEL_L_BIT_AINCH     (1 << 2)
+#define CHANNEL_L_BIT_VBATSCH   (1 << 1)
+#define CHANNEL_L_BIT_VADC_EN   (1 << 0)
+
+#define NORMAL_POLL  30       /* 30 sec */
+#define TP_POLL      5       /* 5 sec */
+#define EDV_POLL     1       /* 1 sec */
+#define SMOOTH_POLL  5      /* 5 sec */
+#define SUSPEND_POLL (30*60) /* 30 min */
+#define INIT_POLL    1
+#define LOW_BAT_WAKE_LOK_TIME 120
+
+#define HIGH_TEMP_THRES        650
+#define HIGH_TEMP_RECOVER 430
+#define LOW_TEMP_THRES (-30)
+#define LOW_TEMP_RECOVER 0
+#define TEMP_ABNORMAL_COUNT    3
+
+#define EDV_HYS      100
+#define IRQ_THRES_UNIT 1953
+
+#define TALRTMAX_VALUE  0x38 //65.39'C
+#define TALRTMIN_VALUE  0x9 //-18.75'C
+#define TRLS_VALUE      55   //5'C ; unit:mV
+#define VRLS_VALUE      100  //100mV
+
+
+#define DEADBAND   10
+
+//#define SLEEP_CURRENT 3 //mA
+
+typedef enum{
+       CHG,
+       DCHG
+}operation_mode;
+
+typedef struct{
+       int x;
+       int y;
+}battery_graph_prop;
+
+typedef enum {
+       MAXTEMP,
+       MINTEMP,
+       MAXVOLT,
+       MINVOLT1,
+       MINVOLT2,
+       TEMP_RLS,
+       VOLT_RLS,
+       LAST_TYPE,
+}alert_type;
+
+#if defined(ROCKCHIP_BATTERY_6200MAH)
+#include <linux/power/rockchip-6200ma-bat.h>
+#elif defined(ROCKCHIP_BATTERY_2100MAH)
+#include <linux/power/rockchip-2100ma-bat.h>
+#else
+#include <linux/power/rockchip-general-bat.h>
+#endif
+
+#define VALRTMIN2_VALUE (rt5025_battery_param2[4].x * 100 / IRQ_THRES_UNIT + 1) //EDV0 voltage
+
+#endif /* #ifndef __LINUX_RT5025_BATTERY_H */
diff --git a/include/linux/power/rt5025-gauge.h b/include/linux/power/rt5025-gauge.h
deleted file mode 100755 (executable)
index 4ca38cb..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  rt5025_gauge.h
- *  fuel-gauge driver
- *  revision 0.1
- */
-
-#ifndef __LINUX_RT5025_GAUGE_H_
-#define __LINUX_RT5025_GAUGE_H_
-
-#define GPIO_GAUGE_ALERT 4
-
-struct rt5025_gauge_callbacks {
-       void (*rt5025_gauge_irq_handler)(void);
-       void (*rt5025_gauge_set_status)(int status);
-       void (*rt5025_gauge_suspend)(void);
-       void (*rt5025_gauge_resume)(void);
-       void (*rt5025_gauge_remove)(void);
-};
-
-
-typedef enum{
-       CHG,
-       DCHG
-}operation_mode;
-
-typedef enum{
-       MAXTEMP,
-       MINTEMP,
-       MAXVOLT,
-       MINVOLT1,
-       MINVOLT2,
-       TEMP_RLS,
-       VOLT_RLS,
-       LAST_TYPE
-}alert_type;   
-
-#endif  /* #ifndef __LINUX_RT5025_GAUGE_H_ */
index 3f700c6bbf66580e01ae3d5241f2172fc6479c21..0f6d2470e2dc38643f689670828ba77adf127e52 100755 (executable)
@@ -25,7 +25,7 @@
 
 #define RT5025_CHGBUCKEN_MASK 0x02
 #define RT5025_CHGCEN_MASK    0x10
-#define RT5025_CHGCC_MASK     0x7E
+#define RT5025_CHGAICR_MASK   0x06
 
 #define RT5025_CHGSTAT_MASK  0x30
 #define RT5025_CHGSTAT_SHIFT 4
diff --git a/include/linux/power/rt5025-swjeita.h b/include/linux/power/rt5025-swjeita.h
new file mode 100755 (executable)
index 0000000..e2e432c
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  include/linux/power/rt5025-swjeita.h
+ *  Include header file for Richtek RT5025 Core Jeita Driver
+ *
+ *  Copyright (C) 2013 Richtek Electronics
+ *  cy_huang <cy_huang@richtek.com>
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_RT5025_SWJEITA_H
+#define __LINUX_RT5025_SWJEITA_H
+
+#define RT5025_REG_CHGCTL3     0x03
+#define RT5025_REG_CHGCTL4     0x04
+#define RT5025_REG_CHGCTL7     0x07
+#define RT5025_REG_AINH                0x5E
+#define RT5025_REG_CHANNELL    0x63
+#define RT5025_REG_IRQCTL      0x50
+#define RT5025_REG_TALRTMAX    0x56
+#define RT5025_REG_TALRTMIN    0x57
+
+#define RT5025_CHGCCEN_MASK    0x10
+#define RT5025_CHGICC_SHIFT    3
+#define RT5025_CHGICC_MASK     0x78
+#define RT5025_CHGCV_SHIFT     2
+#define RT5025_CHGCV_MASK      0xFC
+#define RT5025_AINEN_MASK      0x04
+#define RT5025_TMXEN_MASK      0x20
+#define RT5025_TMNEN_MASK      0x10
+
+
+#endif /* #ifndef __LINUX_RT5025_SWJEITA_H */
old mode 100755 (executable)
new mode 100644 (file)
index 317e3f6..f946783
@@ -25,6 +25,8 @@
 #define RT5025_REG_LDOCTRL6  0x12
 #define RT5025_REG_DCDCEN    0x17
 #define RT5025_REG_LDOEN     0x18
+#define RT5025_REG_DCDCVRC   0x0B
+#define RT5025_REG_LDOVRC    0x00
 
 #define RT5025_DCDCVOUT1     RT5025_REG_DCDCCTRL1
 #define RT5025_DCDCVOUT2     RT5025_REG_DCDCCTRL2
 #define RT5025_LDOEN_MASK5        0x10
 #define RT5025_LDOEN_MASK6        0x20
 
+#define RT5025_DCDCMODE_MASK1    0x40
+#define RT5025_DCDCMODE_MASK2    0x20
+#define RT5025_DCDCMODE_MASK3    0x10
+#define RT5025_DCDCMODE_MASK4    0x00
+#define RT5025_LDOMODE_MASK1     0x00
+#define RT5025_LDOMODE_MASK2     0x00
+#define RT5025_LDOMODE_MASK3     0x00
+#define RT5025_LDOMODE_MASK4     0x00
+#define RT5025_LDOMODE_MASK5     0x00
+#define RT5025_LDOMODE_MASK6     0x00
+
 #endif  /* __LINUX_RT5025_REGULATOR_H */